{
  "element": "nve-viewport",
  "entrypoint": "@nvidia-elements/core/viewport/viewport.examples.json",
  "items": [
    {
      "id": "viewport",
      "name": "Default",
      "template": "<nve-viewport autofit fit-inset=\"24\" behavior-pan behavior-zoom style=\"height: 420px\">\n  <nve-viewport-gridlines></nve-viewport-gridlines>\n  <svg role=\"img\" aria-label=\"Three geometric forms in a spatial field\" width=\"900\" height=\"600\" viewBox=\"0 0 900 600\" style=\"position: absolute; left: 0; top: 0\">\n    <circle cx=\"200\" cy=\"400\" r=\"100\" fill=\"var(--nve-ref-color-green-jade-600)\"></circle>\n    <rect x=\"350\" y=\"100\" width=\"200\" height=\"200\" rx=\"50\" fill=\"var(--nve-ref-color-blue-cobalt-600)\"></rect>\n    <path d=\"M 700 290 L 810 400 L 700 510 L 590 400 Z\" fill=\"var(--nve-ref-color-purple-lavender-600)\"></path>\n    <rect x=\"1\" y=\"1\" width=\"898\" height=\"598\" rx=\"24\" fill=\"none\" stroke=\"var(--nve-ref-border-color-emphasis)\" stroke-width=\"2\" stroke-dasharray=\"32 20\" vector-effect=\"non-scaling-stroke\"></rect>\n  </svg>\n  <nve-viewport-minimap></nve-viewport-minimap>\n</nve-viewport>\n",
      "summary": "Auto-fit a bounded SVG with direct pan and zoom; the minimap represents its single content root as one rectangle.",
      "description": "",
      "composition": false,
      "tags": []
    },
    {
      "id": "viewport-minimap",
      "name": "Minimap",
      "template": "<nve-viewport autofit fit-inset=\"24\" behavior-pan behavior-zoom style=\"height: 420px\">\n  <nve-viewport-gridlines></nve-viewport-gridlines>\n  <svg role=\"img\" aria-label=\"Three geometric forms in a spatial field\" width=\"900\" height=\"600\" viewBox=\"0 0 900 600\" style=\"position: absolute; left: 0; top: 0\">\n    <circle cx=\"200\" cy=\"400\" r=\"100\" fill=\"var(--nve-ref-color-green-jade-600)\"></circle>\n    <rect x=\"350\" y=\"100\" width=\"200\" height=\"200\" rx=\"50\" fill=\"var(--nve-ref-color-blue-cobalt-600)\"></rect>\n    <path d=\"M 700 290 L 810 400 L 700 510 L 590 400 Z\" fill=\"var(--nve-ref-color-purple-lavender-600)\"></path>\n    <rect x=\"1\" y=\"1\" width=\"898\" height=\"598\" rx=\"24\" fill=\"none\" stroke=\"var(--nve-ref-border-color-emphasis)\" stroke-width=\"2\" stroke-dasharray=\"32 20\" vector-effect=\"non-scaling-stroke\"></rect>\n  </svg>\n  <nve-viewport-minimap>\n    <svg slot=\"preview\" width=\"900\" height=\"600\" viewBox=\"0 0 900 600\" style=\"position: absolute; left: 0; top: 0\">\n      <circle cx=\"200\" cy=\"400\" r=\"100\" fill=\"var(--nve-ref-color-green-jade-600)\"></circle>\n      <rect x=\"350\" y=\"100\" width=\"200\" height=\"200\" rx=\"50\" fill=\"var(--nve-ref-color-blue-cobalt-600)\"></rect>\n      <path d=\"M 700 290 L 810 400 L 700 510 L 590 400 Z\" fill=\"var(--nve-ref-color-purple-lavender-600)\"></path>\n    </svg>\n  </nve-viewport-minimap>\n</nve-viewport>\n",
      "summary": "Provide custom minimap content to replace the automatic bounding boxes with a simplified representation of the viewport content.",
      "description": "",
      "composition": false,
      "tags": []
    },
    {
      "id": "viewport-background",
      "name": "Background",
      "template": "<nve-viewport autofit fit-inset=\"24\" behavior-pan behavior-zoom style=\"height: 420px\">\n  <svg slot=\"background\" aria-hidden=\"true\" width=\"20480\" height=\"20480\" viewBox=\"-10240 -10240 20480 20480\" style=\"position: absolute; left: -10240px; top: -10240px\">\n    <defs>\n      <pattern id=\"viewport-background-dots\" width=\"100\" height=\"100\" patternUnits=\"userSpaceOnUse\">\n        <circle cx=\"2\" cy=\"2\" r=\"2\" fill=\"var(--nve-ref-border-color-emphasis)\"></circle>\n      </pattern>\n    </defs>\n    <rect x=\"-10240\" y=\"-10240\" width=\"20480\" height=\"20480\" fill=\"url(#viewport-background-dots)\"></rect>\n  </svg>\n  <svg role=\"img\" aria-label=\"Three geometric forms in a spatial field\" width=\"900\" height=\"600\" viewBox=\"0 0 900 600\" style=\"position: absolute; left: 0; top: 0\">\n    <circle cx=\"200\" cy=\"400\" r=\"100\" fill=\"var(--nve-ref-color-green-jade-600)\"></circle>\n    <rect x=\"350\" y=\"100\" width=\"200\" height=\"200\" rx=\"50\" fill=\"var(--nve-ref-color-blue-cobalt-600)\"></rect>\n    <path d=\"M 700 290 L 810 400 L 700 510 L 590 400 Z\" fill=\"var(--nve-ref-color-purple-lavender-600)\"></path>\n    <rect x=\"1\" y=\"1\" width=\"898\" height=\"598\" rx=\"24\" fill=\"none\" stroke=\"var(--nve-ref-border-color-emphasis)\" stroke-width=\"2\" stroke-dasharray=\"32 20\" vector-effect=\"non-scaling-stroke\"></rect>\n  </svg>\n</nve-viewport>\n",
      "summary": "Place custom content in the background slot to provide a spatial reference without affecting content fitting.",
      "description": "",
      "composition": false,
      "tags": []
    },
    {
      "id": "viewport-interactive-content",
      "name": "InteractiveContent",
      "template": "<nve-viewport x=\"-20\" y=\"-20\" scale=\"0.9\" behavior-pan behavior-zoom style=\"height: 420px\">\n  <nve-viewport-gridlines step=\"20\" target-spacing=\"72\"></nve-viewport-gridlines>\n  <nve-card style=\"position: absolute; left: 280px; top: 110px; width: 300px\">\n    <nve-card-header>\n      <h2 nve-text=\"heading sm bold\">Viewport content</h2>\n    </nve-card-header>\n    <nve-card-content>\n      <nve-input>\n        <label>Label</label>\n        <input value=\"Editable value\" />\n      </nve-input>\n    </nve-card-content>\n  </nve-card>\n</nve-viewport>\n",
      "summary": "Place native and Elements controls inside a viewport without losing their standard interactions.",
      "description": "",
      "composition": true,
      "tags": []
    },
    {
      "id": "viewport-pan-with-space",
      "name": "PanWithSpace",
      "template": "<style>\n  #viewport-space-pan-card {\n    cursor: var(--drag-cursor, auto);\n  }\n  #viewport-space-pan-card:hover {\n    --drag-cursor: grab;\n  }\n  #viewport-space-pan-card[data-dragging] {\n    --background: var(--nve-sys-layer-overlay-background);\n    --box-shadow: var(--nve-ref-shadow-300);\n    --drag-cursor: grabbing;\n  }\n</style>\n<div nve-layout=\"column align:horizontal-stretch\" style=\"height: 420px\">\n  <nve-alert-group status=\"accent\">\n    <nve-alert>\n      <p nve-text=\"body sm medium\">Pan the viewport with <kbd nve-text=\"code\">Space</kbd>, or using the middle mouse button.</p>\n    </nve-alert>\n  </nve-alert-group>\n  <nve-viewport id=\"viewport-space-pan-demo\" behavior-pan=\"space\" behavior-zoom style=\"flex: 1; --min-height: 0\">\n    <nve-viewport-gridlines step=\"20\"></nve-viewport-gridlines>\n    <nve-card id=\"viewport-space-pan-card\" data-draggable-card data-card-drag-handle style=\"position: absolute; left: 290px; top: 120px; width: 300px\">\n      <nve-card-header>\n        <h2 nve-text=\"heading sm bold\">Drag this card</h2>\n      </nve-card-header>\n      <nve-card-content>\n        <p nve-text=\"body relaxed\" nve-layout=\"pad:md\" style=\"text-align: center\">Application-defined dragging remains independent in this mode.</p>\n      </nve-card-content>\n    </nve-card>\n  </nve-viewport>\n</div>\n<script type=\"module\">\n  const viewport = document.querySelector(\"#viewport-space-pan-demo\");\n  const handles = viewport.querySelectorAll(\"[data-card-drag-handle]\");\n  handles.forEach((handle) => {\n    const card = handle.closest(\"[data-draggable-card]\");\n    let pointerId;\n    let startClientX;\n    let startClientY;\n    let startLeft;\n    let startTop;\n    const finishDrag = (event) => {\n      if (event.pointerId !== pointerId) return;\n      pointerId = undefined;\n      card.removeAttribute(\"data-dragging\");\n    };\n    handle.addEventListener(\"pointerdown\", (event) => {\n      if ((event.pointerType !== \"mouse\" && event.pointerType !== \"pen\") || event.button !== 0 || event.defaultPrevented) {\n        return;\n      }\n      event.preventDefault();\n      event.stopPropagation();\n      pointerId = event.pointerId;\n      startClientX = event.clientX;\n      startClientY = event.clientY;\n      startLeft = Number.parseFloat(card.style.left);\n      startTop = Number.parseFloat(card.style.top);\n      card.setAttribute(\"data-dragging\", \"\");\n      handle.setPointerCapture(pointerId);\n    });\n    handle.addEventListener(\"pointermove\", (event) => {\n      if (event.pointerId !== pointerId) return;\n      card.style.left = startLeft + (event.clientX - startClientX) / viewport.scale + \"px\";\n      card.style.top = startTop + (event.clientY - startClientY) / viewport.scale + \"px\";\n      event.preventDefault();\n    });\n    handle.addEventListener(\"pointerup\", finishDrag);\n    handle.addEventListener(\"pointercancel\", finishDrag);\n    handle.addEventListener(\"lostpointercapture\", finishDrag);\n  });\n</script>\n",
      "summary": "Configure panning to require Space when application content needs to handle its own drag interactions.",
      "description": "",
      "composition": true,
      "tags": []
    },
    {
      "id": "viewport-commands",
      "name": "Commands",
      "template": "<div nve-layout=\"column align:horizontal-stretch\" style=\"height: 420px\">\n  <nve-toolbar aria-label=\"Viewport navigation controls\">\n    <nve-button commandfor=\"viewport-command-demo\" command=\"--pan-left\" aria-label=\"Pan left\">←</nve-button>\n    <nve-button commandfor=\"viewport-command-demo\" command=\"--pan-up\" aria-label=\"Pan up\">↑</nve-button>\n    <nve-button commandfor=\"viewport-command-demo\" command=\"--pan-down\" aria-label=\"Pan down\">↓</nve-button>\n    <nve-button commandfor=\"viewport-command-demo\" command=\"--pan-right\" aria-label=\"Pan right\">→</nve-button>\n    <nve-button slot=\"suffix\" commandfor=\"viewport-command-demo\" command=\"--zoom-out\" aria-label=\"Zoom out\">−</nve-button>\n    <nve-button slot=\"suffix\" commandfor=\"viewport-command-demo\" command=\"--zoom-reset\">100%</nve-button>\n    <nve-button slot=\"suffix\" commandfor=\"viewport-command-demo\" command=\"--zoom-in\" aria-label=\"Zoom in\">+</nve-button>\n    <nve-button slot=\"suffix\" commandfor=\"viewport-command-demo\" command=\"--zoom-to-fit\">Fit</nve-button>\n  </nve-toolbar>\n  <nve-viewport id=\"viewport-command-demo\" autofit fit-inset=\"24\" behavior-pan behavior-zoom style=\"flex: 1; --min-height: 0\">\n    <nve-viewport-gridlines></nve-viewport-gridlines>\n    <svg role=\"img\" aria-label=\"Three geometric forms in a spatial field\" width=\"900\" height=\"600\" viewBox=\"0 0 900 600\" style=\"position: absolute; left: 0; top: 0\">\n      <circle cx=\"200\" cy=\"400\" r=\"100\" fill=\"var(--nve-ref-color-green-jade-600)\"></circle>\n      <rect x=\"350\" y=\"100\" width=\"200\" height=\"200\" rx=\"50\" fill=\"var(--nve-ref-color-blue-cobalt-600)\"></rect>\n      <path d=\"M 700 290 L 810 400 L 700 510 L 590 400 Z\" fill=\"var(--nve-ref-color-purple-lavender-600)\"></path>\n      <rect x=\"1\" y=\"1\" width=\"898\" height=\"598\" rx=\"24\" fill=\"none\" stroke=\"var(--nve-ref-border-color-emphasis)\" stroke-width=\"2\" stroke-dasharray=\"32 20\" vector-effect=\"non-scaling-stroke\"></rect>\n    </svg>\n  </nve-viewport>\n</div>\n",
      "summary": "Use external controls with `commandfor` to invoke viewport pan, zoom, reset, and fit commands.",
      "description": "",
      "composition": true,
      "tags": []
    },
    {
      "id": "viewport-programmatic-navigation",
      "name": "ProgrammaticNavigation",
      "template": "<div nve-layout=\"column gap:sm align:horizontal-stretch\" style=\"height: 420px\">\n  <div nve-layout=\"row align:center\">\n    <nve-button-group container=\"rounded\" behavior-select=\"single\" aria-label=\"Navigate to workflow region\">\n      <nve-button data-viewport-region=\"viewport-region-ingest\">Ingest</nve-button>\n      <nve-button data-viewport-region=\"viewport-region-train\">Train</nve-button>\n      <nve-button data-viewport-region=\"viewport-region-deploy\">Deploy</nve-button>\n    </nve-button-group>\n  </div>\n  <nve-viewport id=\"viewport-reveal-demo\" autofit fit-inset=\"24\" style=\"flex: 1; --min-height: 0\">\n    <nve-viewport-gridlines step=\"40\"></nve-viewport-gridlines>\n    <svg aria-hidden=\"true\" width=\"500\" height=\"320\" viewBox=\"0 0 500 320\" style=\"position: absolute; left: 380px; top: 144px\">\n      <path d=\"M 0 0 C 50 0 50 160 100 160 M 400 160 C 450 160 450 320 500 320\" fill=\"none\" stroke=\"var(--nve-ref-border-color-emphasis)\" stroke-width=\"4\"></path>\n    </svg>\n    <nve-card id=\"viewport-region-ingest\" style=\"position: absolute; left: 80px; top: 80px; width: 320px\">\n      <nve-card-header><h2 nve-text=\"heading sm bold\">Ingest</h2></nve-card-header>\n      <nve-card-content>\n        <p nve-text=\"body\" nve-layout=\"pad:md\" style=\"text-align: center\">Validate and prepare the dataset.</p>\n      </nve-card-content>\n    </nve-card>\n    <nve-card id=\"viewport-region-train\" style=\"position: absolute; left: 480px; top: 240px; width: 320px\">\n      <nve-card-header><h2 nve-text=\"heading sm bold\">Train</h2></nve-card-header>\n      <nve-card-content>\n        <p nve-text=\"body\" nve-layout=\"pad:md\" style=\"text-align: center\">Run and compare model experiments.</p>\n      </nve-card-content>\n    </nve-card>\n    <nve-card id=\"viewport-region-deploy\" style=\"position: absolute; left: 880px; top: 400px; width: 320px\">\n      <nve-card-header><h2 nve-text=\"heading sm bold\">Deploy</h2></nve-card-header>\n      <nve-card-content>\n        <p nve-text=\"body\" nve-layout=\"pad:md\" style=\"text-align: center\">Promote the selected model.</p>\n      </nve-card-content>\n    </nve-card>\n  </nve-viewport>\n</div>\n<script type=\"module\">\n  const viewport = document.querySelector(\"#viewport-reveal-demo\");\n  const buttons = Array.from(document.querySelectorAll(\"[data-viewport-region]\"));\n  const framing = 80;\n  buttons.forEach((button) => {\n    button.addEventListener(\"click\", () => {\n      const region = viewport.querySelector(\"#\" + button.dataset.viewportRegion);\n      viewport.reveal(\n        {\n          x: region.offsetLeft - framing,\n          y: region.offsetTop - framing,\n          width: region.offsetWidth + framing * 2,\n          height: region.offsetHeight + framing * 2,\n        },\n        { animated: true, duration: 500 },\n      );\n    });\n  });\n</script>\n",
      "summary": "Viewport navigation helpers let application logic animate specific content regions into view.",
      "description": "",
      "composition": true,
      "tags": []
    }
  ]
}