@nvidia-elements/core 2.8.1 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +3 -7
- package/dist/accordion/accordion.d.ts +4 -4
- package/dist/accordion/accordion2.js +4 -4
- package/dist/alert/alert-group.d.ts +1 -1
- package/dist/alert/alert-group2.js +1 -1
- package/dist/alert/alert.d.ts +1 -1
- package/dist/alert/alert2.js +1 -1
- package/dist/avatar/avatar-group.d.ts +1 -1
- package/dist/avatar/avatar-group2.js +1 -1
- package/dist/avatar/avatar.d.ts +1 -1
- package/dist/avatar/avatar2.js +1 -1
- package/dist/badge/badge.d.ts +1 -1
- package/dist/badge/badge2.js +1 -1
- package/dist/breadcrumb/breadcrumb.d.ts +2 -1
- package/dist/breadcrumb/breadcrumb2.js +1 -1
- package/dist/breadcrumb/breadcrumb2.js.map +1 -1
- package/dist/bundle.d.ts +2 -0
- package/dist/bundles/index.d.ts +212 -1
- package/dist/bundles/index.js +6 -6
- package/dist/button/button.d.ts +1 -1
- package/dist/button/button2.js +1 -1
- package/dist/button-group/button-group.d.ts +1 -1
- package/dist/button-group/button-group2.js +1 -1
- package/dist/card/card.d.ts +4 -4
- package/dist/card/card2.js +4 -4
- package/dist/chat-message/chat-message.d.ts +1 -1
- package/dist/chat-message/chat-message2.js +1 -1
- package/dist/checkbox/checkbox-group2.js +1 -1
- package/dist/checkbox/checkbox2.js +1 -1
- package/dist/color/color.d.ts +1 -1
- package/dist/color/color2.js +1 -1
- package/dist/combobox/combobox.d.ts +2 -2
- package/dist/combobox/combobox2.js +1 -1
- package/dist/copy-button/copy-button.d.ts +1 -1
- package/dist/copy-button/copy-button2.js +1 -1
- package/dist/custom-elements-jsx.d.ts +125 -16
- package/dist/custom-elements-vue.d.ts +123 -16
- package/dist/custom-elements.json +3827 -1126
- package/dist/data.html.json +98 -4
- package/dist/date/date.d.ts +1 -1
- package/dist/date/date2.js +1 -1
- package/dist/datetime/datetime.d.ts +1 -1
- package/dist/datetime/datetime2.js +1 -1
- package/dist/dialog/dialog-footer.d.ts +1 -1
- package/dist/dialog/dialog-footer2.js +1 -1
- package/dist/dialog/dialog-header.d.ts +1 -1
- package/dist/dialog/dialog-header2.js +1 -1
- package/dist/dialog/dialog.d.ts +1 -1
- package/dist/dialog/dialog2.js +1 -1
- package/dist/divider/divider.d.ts +1 -1
- package/dist/divider/divider2.js +1 -1
- package/dist/dot/dot.d.ts +1 -1
- package/dist/dot/dot2.js +1 -1
- package/dist/drawer/drawer-content.d.ts +1 -1
- package/dist/drawer/drawer-content2.js +1 -1
- package/dist/drawer/drawer-footer.d.ts +1 -1
- package/dist/drawer/drawer-footer2.js +1 -1
- package/dist/drawer/drawer-header.d.ts +1 -1
- package/dist/drawer/drawer-header2.js +1 -1
- package/dist/drawer/drawer.d.ts +1 -1
- package/dist/drawer/drawer2.js +1 -1
- package/dist/dropdown/dropdown-footer.d.ts +1 -1
- package/dist/dropdown/dropdown-footer2.js +1 -1
- package/dist/dropdown/dropdown-header.d.ts +1 -1
- package/dist/dropdown/dropdown-header2.js +1 -1
- package/dist/dropdown/dropdown.d.ts +1 -1
- package/dist/dropdown/dropdown2.js +1 -1
- package/dist/dropdown-group/dropdown-group.d.ts +1 -1
- package/dist/dropdown-group/dropdown-group.js +1 -1
- package/dist/dropzone/dropzone.d.ts +1 -1
- package/dist/dropzone/dropzone2.js +1 -1
- package/dist/file/file2.js +1 -1
- package/dist/format-bytes/format-bytes.d.ts +1 -1
- package/dist/format-bytes/format-bytes2.js +1 -1
- package/dist/format-datetime/format-datetime.d.ts +1 -1
- package/dist/format-datetime/format-datetime2.js +1 -1
- package/dist/format-number/format-number.d.ts +1 -1
- package/dist/format-number/format-number2.js +1 -1
- package/dist/format-relative-time/format-relative-time.d.ts +1 -1
- package/dist/format-relative-time/format-relative-time2.js +1 -1
- package/dist/format-truncate/format-truncate2.js +1 -1
- package/dist/forms/control/control2.js +1 -1
- package/dist/forms/control-group/control-group.d.ts +3 -1
- package/dist/forms/control-group/control-group2.js +1 -1
- package/dist/forms/control-group/control-group2.js.map +1 -1
- package/dist/forms/control-message/control-message.d.ts +1 -1
- package/dist/forms/control-message/control-message2.js +1 -1
- package/dist/gauge/gauge.d.ts +1 -1
- package/dist/gauge/gauge2.js +1 -1
- package/dist/grid/cell/cell.d.ts +1 -1
- package/dist/grid/cell/cell2.js +1 -1
- package/dist/grid/column/column.d.ts +1 -1
- package/dist/grid/column/column2.js +1 -1
- package/dist/grid/footer/footer.d.ts +1 -1
- package/dist/grid/footer/footer2.js +1 -1
- package/dist/grid/grid.d.ts +3 -1
- package/dist/grid/grid2.js +1 -1
- package/dist/grid/grid2.js.map +1 -1
- package/dist/grid/header/header.d.ts +1 -1
- package/dist/grid/header/header2.js +1 -1
- package/dist/grid/placeholder/placeholder.d.ts +1 -1
- package/dist/grid/placeholder/placeholder2.js +1 -1
- package/dist/grid/row/row.d.ts +1 -1
- package/dist/grid/row/row2.js +1 -1
- package/dist/icon/icon.d.ts +1 -1
- package/dist/icon/icon2.js +2 -2
- package/dist/icon-button/icon-button.d.ts +1 -1
- package/dist/icon-button/icon-button2.js +1 -1
- package/dist/index.js +1 -1
- package/dist/input/input-group2.js +1 -1
- package/dist/input/input2.js +1 -1
- package/dist/internal/controllers/gesture.controller.d.ts +122 -42
- package/dist/internal/controllers/gesture.controller.examples.js.map +1 -1
- package/dist/internal/controllers/gesture.controller.examples.json +2 -2
- package/dist/internal/controllers/gesture.controller.js +300 -159
- package/dist/internal/controllers/gesture.controller.js.map +1 -1
- package/dist/internal/controllers/key-state.controller.d.ts +18 -0
- package/dist/internal/controllers/key-state.controller.js +84 -0
- package/dist/internal/controllers/key-state.controller.js.map +1 -0
- package/dist/internal/controllers/keynav-list.controller.js.map +1 -1
- package/dist/internal/controllers/keynav-spatial.controller.d.ts +4 -1
- package/dist/internal/controllers/keynav-spatial.controller.js +7 -6
- package/dist/internal/controllers/keynav-spatial.controller.js.map +1 -1
- package/dist/internal/index.d.ts +2 -0
- package/dist/internal/index.js +29 -27
- package/dist/internal/services/global.service.js +1 -1
- package/dist/internal/utils/dom.d.ts +4 -1
- package/dist/internal/utils/dom.js +42 -38
- package/dist/internal/utils/dom.js.map +1 -1
- package/dist/internal/utils/focus.d.ts +2 -0
- package/dist/internal/utils/focus.js +14 -7
- package/dist/internal/utils/focus.js.map +1 -1
- package/dist/internal/utils/numeric.d.ts +3 -0
- package/dist/internal/utils/numeric.js +14 -0
- package/dist/internal/utils/numeric.js.map +1 -0
- package/dist/logo/logo.d.ts +1 -1
- package/dist/logo/logo2.js +1 -1
- package/dist/menu/menu-item.d.ts +1 -1
- package/dist/menu/menu-item2.js +1 -1
- package/dist/menu/menu.d.ts +1 -1
- package/dist/menu/menu2.js +1 -1
- package/dist/month/month.d.ts +1 -1
- package/dist/month/month2.js +1 -1
- package/dist/notification/notification-group.d.ts +1 -1
- package/dist/notification/notification-group2.js +1 -1
- package/dist/notification/notification.d.ts +1 -1
- package/dist/notification/notification2.js +1 -1
- package/dist/page/page-panel/page-panel-content.d.ts +1 -1
- package/dist/page/page-panel/page-panel-content2.js +1 -1
- package/dist/page/page-panel/page-panel-footer.d.ts +1 -1
- package/dist/page/page-panel/page-panel-footer2.js +1 -1
- package/dist/page/page-panel/page-panel-header.d.ts +1 -1
- package/dist/page/page-panel/page-panel-header2.js +1 -1
- package/dist/page/page-panel/page-panel.d.ts +1 -1
- package/dist/page/page-panel/page-panel2.js +1 -1
- package/dist/page/page.d.ts +1 -1
- package/dist/page/page2.js +1 -1
- package/dist/page-header/page-header.d.ts +1 -1
- package/dist/page-header/page-header2.js +1 -1
- package/dist/page-loader/page-loader.d.ts +1 -1
- package/dist/page-loader/page-loader2.js +1 -1
- package/dist/pagination/pagination.d.ts +1 -1
- package/dist/pagination/pagination2.js +1 -1
- package/dist/panel/panel.d.ts +4 -4
- package/dist/panel/panel2.js +4 -4
- package/dist/password/password.d.ts +1 -1
- package/dist/password/password2.js +1 -1
- package/dist/preferences-input/preferences-input.d.ts +1 -1
- package/dist/preferences-input/preferences-input2.js +1 -1
- package/dist/progress-bar/progress-bar.d.ts +1 -1
- package/dist/progress-bar/progress-bar2.js +1 -1
- package/dist/progress-ring/progress-ring.d.ts +1 -1
- package/dist/progress-ring/progress-ring2.js +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip.d.ts +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
- package/dist/pulse/pulse.d.ts +1 -1
- package/dist/pulse/pulse2.js +1 -1
- package/dist/radio/radio-group2.js +1 -1
- package/dist/radio/radio2.js +1 -1
- package/dist/range/range.d.ts +1 -1
- package/dist/range/range2.js +1 -1
- package/dist/resize-handle/resize-handle.d.ts +1 -1
- package/dist/resize-handle/resize-handle2.js +6 -10
- package/dist/resize-handle/resize-handle2.js.map +1 -1
- package/dist/search/search.d.ts +1 -1
- package/dist/search/search2.js +1 -1
- package/dist/select/select.d.ts +2 -2
- package/dist/select/select2.js +1 -1
- package/dist/skeleton/skeleton.d.ts +1 -1
- package/dist/skeleton/skeleton2.js +1 -1
- package/dist/sort-button/sort-button.d.ts +1 -1
- package/dist/sort-button/sort-button2.js +1 -1
- package/dist/sparkline/sparkline.d.ts +1 -1
- package/dist/sparkline/sparkline2.js +1 -1
- package/dist/star-rating/star-rating.d.ts +1 -1
- package/dist/star-rating/star-rating2.js +1 -1
- package/dist/steps/steps.d.ts +2 -2
- package/dist/steps/steps2.js +2 -2
- package/dist/switch/switch-group2.js +1 -1
- package/dist/switch/switch2.js +1 -1
- package/dist/tabs/tabs-group.d.ts +1 -1
- package/dist/tabs/tabs-group2.js +1 -1
- package/dist/tabs/tabs.d.ts +2 -2
- package/dist/tabs/tabs2.js +2 -2
- package/dist/tag/tag.d.ts +1 -1
- package/dist/tag/tag2.js +1 -1
- package/dist/textarea/textarea.d.ts +2 -2
- package/dist/textarea/textarea2.js +1 -1
- package/dist/time/time.d.ts +1 -1
- package/dist/time/time2.js +1 -1
- package/dist/toast/toast.d.ts +1 -1
- package/dist/toast/toast2.js +1 -1
- package/dist/toggletip/toggletip-footer.d.ts +1 -1
- package/dist/toggletip/toggletip-footer2.js +1 -1
- package/dist/toggletip/toggletip-header.d.ts +1 -1
- package/dist/toggletip/toggletip-header2.js +1 -1
- package/dist/toggletip/toggletip.d.ts +1 -1
- package/dist/toggletip/toggletip2.js +1 -1
- package/dist/toolbar/toolbar.d.ts +1 -1
- package/dist/toolbar/toolbar2.js +1 -1
- package/dist/tooltip/tooltip.d.ts +1 -1
- package/dist/tooltip/tooltip2.js +1 -1
- package/dist/tree/tree-node.d.ts +2 -2
- package/dist/tree/tree-node2.js +1 -1
- package/dist/tree/tree-node2.js.map +1 -1
- package/dist/tree/tree.d.ts +2 -1
- package/dist/tree/tree2.js +1 -1
- package/dist/tree/tree2.js.map +1 -1
- package/dist/viewport/define.d.ts +7 -0
- package/dist/viewport/define.js +7 -0
- package/dist/viewport/define.js.map +1 -0
- package/dist/viewport/index.d.ts +3 -0
- package/dist/viewport/index.js +3 -0
- package/dist/viewport/viewport-animation.controller.d.ts +21 -0
- package/dist/viewport/viewport-animation.controller.js +93 -0
- package/dist/viewport/viewport-animation.controller.js.map +1 -0
- package/dist/viewport/viewport-autofit.controller.d.ts +18 -0
- package/dist/viewport/viewport-autofit.controller.js +105 -0
- package/dist/viewport/viewport-autofit.controller.js.map +1 -0
- package/dist/viewport/viewport-fitting.utils.d.ts +36 -0
- package/dist/viewport/viewport-fitting.utils.js +35 -0
- package/dist/viewport/viewport-fitting.utils.js.map +1 -0
- package/dist/viewport/viewport-gesture-navigation.controller.d.ts +29 -0
- package/dist/viewport/viewport-gesture-navigation.controller.js +311 -0
- package/dist/viewport/viewport-gesture-navigation.controller.js.map +1 -0
- package/dist/viewport/viewport-gridlines.d.ts +38 -0
- package/dist/viewport/viewport-gridlines.js +6 -0
- package/dist/viewport/viewport-gridlines.js.map +1 -0
- package/dist/viewport/viewport-gridlines.utils.d.ts +11 -0
- package/dist/viewport/viewport-gridlines.utils.js +54 -0
- package/dist/viewport/viewport-gridlines.utils.js.map +1 -0
- package/dist/viewport/viewport-gridlines2.js +154 -0
- package/dist/viewport/viewport-gridlines2.js.map +1 -0
- package/dist/viewport/viewport-navigation.controller.d.ts +27 -0
- package/dist/viewport/viewport-navigation.controller.js +142 -0
- package/dist/viewport/viewport-navigation.controller.js.map +1 -0
- package/dist/viewport/viewport-navigation.types.d.ts +9 -0
- package/dist/viewport/viewport-projection.utils.d.ts +7 -0
- package/dist/viewport/viewport-projection.utils.js +25 -0
- package/dist/viewport/viewport-projection.utils.js.map +1 -0
- package/dist/viewport/viewport.d.ts +92 -0
- package/dist/viewport/viewport.examples.js +6 -0
- package/dist/viewport/viewport.examples.js.map +1 -0
- package/dist/viewport/viewport.examples.json +60 -0
- package/dist/viewport/viewport.js +6 -0
- package/dist/viewport/viewport.js.map +1 -0
- package/dist/viewport/viewport.types.d.ts +66 -0
- package/dist/viewport/viewport2.js +375 -0
- package/dist/viewport/viewport2.js.map +1 -0
- package/dist/week/week.d.ts +1 -1
- package/dist/week/week2.js +1 -1
- package/package.json +19 -4
package/dist/tree/tree-node2.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-node2.js","names":[],"sources":["../../src/tree/tree-node.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { LitElement, html, nothing } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { state } from 'lit/decorators/state.js';\nimport { queryAssignedElements } from 'lit/decorators/query-assigned-elements.js';\nimport {\n I18nController,\n TypeExpandableController,\n TypeSelectableController,\n attachInternals,\n audit,\n getFlattenedFocusableItems,\n hostAttr,\n scopedRegistry,\n stateExpanded,\n stateHighlighted,\n stateSelected,\n typeAnchor,\n typeSSR,\n useStyles\n} from '@nvidia-elements/core/internal';\nimport { IconButton } from '@nvidia-elements/core/icon-button';\nimport { Icon } from '@nvidia-elements/core/icon';\nimport { Checkbox } from '@nvidia-elements/core/checkbox';\nimport type { Tree } from './tree.js';\nimport styles from './tree-node.css?inline';\nimport { updateNodeSelection } from './utils.js';\n\n/**\n * @element nve-tree-node\n * @description A tree view widget presents a hierarchical list. Any item in the hierarchy may have child items, and items that have children can expand or collapse to show or hide the children.\n * @documentation https://nvidia.github.io/elements/docs/elements/tree/\n * @since 1.2.0\n * @entrypoint \\@nvidia-elements/core/tree\n * @event open - Dispatched when the node opens.\n * @event close - Dispatched when the node closes.\n * @event select - Dispatched when the node selection state changes.\n * @command --select - use to select the node\n * @command --deselect - use to deselect the node\n * @command --toggle-select - use to toggle the node selection state\n * @command --open - use to open the node\n * @command --close - use to close the node\n * @command --toggle - use to toggle open / closed state of the node\n * @slot - Use default slot for basic text content or nested <nve-tree-node> elements.\n * @slot content - Use only for extended long form content containing interactive elements or form inputs.\n * @cssprop --color\n * @cssprop --border-radius\n * @cssprop --font-size\n * @cssprop --min-height\n * @cssprop --text-wrap\n * @cssprop --font-weight\n * @cssprop --width\n\n * @csspart icon-button - The icon button element\n * @csspart icon - The icon element\n * @csspart checkbox - The checkbox element\n\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/treeview/\n *\n */\n@audit()\n@typeSSR({ log: false }) // warning about ssr mismatch disabled as tree node will never be a 1:1 match in ssr due to performance constraints and slot complexity\n@typeAnchor()\n@stateSelected()\n@stateExpanded()\n@scopedRegistry()\n@stateHighlighted()\nexport class TreeNode extends LitElement {\n /**\n * Determines if node is in an expanded state.\n */\n @property({ type: Boolean, reflect: true }) expanded = false;\n\n /**\n * Determines whether if node is in a selected state.\n */\n @property({ type: Boolean, reflect: true }) selected = false;\n\n /**\n * Determines whether a node can be expandable. Expandable by default if slotted nodes exist.\n */\n @property({ type: Boolean }) expandable = false;\n\n /**\n * Determines whether a node can be in a selected state. Nodes can be in a single or multi select state.\n */\n @property({ type: String }) selectable: 'single' | 'multi';\n\n /**\n * Determines the highlighted state of the element. Highlighted states serve non-interactive selections where nodes may relate to other selected portions of the UI.\n */\n @property({ type: Boolean }) highlighted = false;\n\n #i18nController: I18nController<this> = new I18nController<this>(this);\n\n /**\n * Updates internal string values for internationalization.\n */\n @property({ type: Object }) i18n = this.#i18nController.i18n;\n\n /** @private */\n @hostAttr() slot = 'nodes';\n\n get #tree() {\n return this.closest<Tree>('nve-tree');\n }\n\n /**\n * Returns list of child nodes\n */\n @queryAssignedElements({ slot: 'nodes' }) readonly nodes!: TreeNode[];\n\n /** @private */\n @state() indeterminate = false;\n\n /** @private */\n @state() behaviorExpand = false;\n\n /** @private */\n @state() behaviorSelect = false;\n\n #typeExpandableController = new TypeExpandableController(this);\n\n #typeSelectableController = new TypeSelectableController(this);\n\n get #isExpandable() {\n return this.expandable || this.expanded || !!this.nodes?.length;\n }\n\n static metadata = {\n tag: 'nve-tree-node',\n version: '0.0.0',\n parents: ['nve-tree', 'nve-tree-node']\n };\n\n static elementDefinitions = {\n [IconButton.metadata.tag]: IconButton,\n [Icon.metadata.tag]: Icon,\n [Checkbox.metadata.tag]: Checkbox\n };\n\n static styles = useStyles([styles]);\n\n declare _internals: ElementInternals;\n\n /* eslint-disable @nvidia-elements/lint/no-missing-control-label */\n render() {\n return html`\n <div internal-host @slotchange=${this.#nodeUpdate}>\n <div part=\"_node\">\n ${\n this.#isExpandable\n ? html`\n <nve-icon-button part=\"icon-button\" exportparts=\"icon:icon-button-icon\" @pointerup=${this.#toggleExpand} role=\"presentation\" tabindex=\"-1\" size=\"sm\" container=\"inline\" nofocus>\n <nve-icon part=\"icon\" name=\"caret\" direction=${this.expanded ? 'down' : 'right'} size=\"sm\"></nve-icon>\n </nve-icon-button>`\n : nothing\n }\n ${\n this.selectable === 'multi'\n ? html`\n <nve-checkbox part=\"checkbox\" nofocus>\n <input type=\"checkbox\" @change=${this.#toggleMultiSelection} .checked=${this.selected} .indeterminate=${this.indeterminate} .ariaLabel=${this.i18n.expand} tabindex=\"-1\" />\n </nve-checkbox>`\n : nothing\n }\n <div tabindex=\"0\" part=\"_node-header\">\n <slot class=\"node-title\" @click=${this.#nodeHeaderClick}></slot>\n <slot name=\"content\" part=\"_content\"></slot>\n </div>\n </div>\n <div role=\"group\" part=\"_nodes\"><slot name=\"nodes\"></slot></div>\n </div>\n `;\n }\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n this._internals.role = 'treeitem';\n this.addEventListener('keydown', this.#onKeydown);\n this.addEventListener('keyup', this.#onKeyup);\n this.#nodeUpdate();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this.#onKeydown);\n this.removeEventListener('keyup', this.#onKeyup);\n }\n\n /** opens and sets the expanded state automatically if behaviorExpand is true */\n open() {\n this.#typeExpandableController.open();\n }\n\n /** closes and sets the expanded state automatically if behaviorExpand is true */\n close() {\n this.#typeExpandableController.close();\n }\n\n #nodeUpdate() {\n this.requestUpdate();\n this.#toggleExpandableState();\n }\n\n #toggleExpandableState() {\n this.#isExpandable ? this._internals.states.add('is-expandable') : this._internals.states.delete('is-expandable');\n }\n\n #onKeydown = (e: KeyboardEvent) => {\n const isSelectionKey = this.selectable && e.code === 'Space';\n const isExpansionKey = this.#isExpandable && (e.code === 'ArrowLeft' || e.code === 'ArrowRight');\n\n if (e.target === this && (isSelectionKey || isExpansionKey)) {\n e.preventDefault();\n }\n };\n\n #onKeyup = (e: KeyboardEvent) => {\n if (this.#isExpandable && e.code === 'ArrowLeft' && e.target === this) {\n this.close();\n }\n\n if (this.#isExpandable && e.code === 'ArrowRight' && e.target === this) {\n this.open();\n }\n\n if (e.code === 'Space' && e.target === this && this.selectable) {\n this.#toggleSelection();\n }\n };\n\n #nodeHeaderClick(e: Event) {\n const hasFocusableElements = getFlattenedFocusableItems(e.currentTarget as HTMLElement).length;\n if (this.#isExpandable && !this.selectable && !hasFocusableElements) {\n this.#toggleExpand();\n }\n\n if (this.selectable && (!hasFocusableElements || (e.target as HTMLElement).localName === 'a')) {\n this.#toggleSelection();\n }\n }\n\n #toggleExpand() {\n this.#typeExpandableController.toggle();\n }\n\n #toggleSelection() {\n if (this.selectable === 'single') {\n this.#toggleSingleSelection();\n }\n\n if (this.selectable === 'multi') {\n this.#toggleMultiSelection();\n }\n }\n\n #toggleSingleSelection() {\n this.#typeSelectableController.toggle();\n if (this.behaviorSelect) {\n this.#tree!.nodes.filter(n => n !== this).forEach(n => (n.selected = false));\n }\n }\n\n #toggleMultiSelection() {\n this.#typeSelectableController.toggle();\n\n if (this.behaviorSelect) {\n this.nodes.forEach(n => {\n n.selected = this.selected;\n n.indeterminate = false;\n });\n this.#tree!.nodes.forEach(node => updateNodeSelection(node));\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree-node2.js","names":[],"sources":["../../src/tree/tree-node.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { LitElement, html, nothing } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport { state } from 'lit/decorators/state.js';\nimport { queryAssignedElements } from 'lit/decorators/query-assigned-elements.js';\nimport {\n I18nController,\n TypeExpandableController,\n TypeSelectableController,\n attachInternals,\n audit,\n getFlattenedFocusableItems,\n hostAttr,\n scopedRegistry,\n stateExpanded,\n stateHighlighted,\n stateSelected,\n typeAnchor,\n typeSSR,\n useStyles\n} from '@nvidia-elements/core/internal';\nimport { IconButton } from '@nvidia-elements/core/icon-button';\nimport { Icon } from '@nvidia-elements/core/icon';\nimport { Checkbox } from '@nvidia-elements/core/checkbox';\nimport type { Tree } from './tree.js';\nimport styles from './tree-node.css?inline';\nimport { updateNodeSelection } from './utils.js';\n\n/**\n * @element nve-tree-node\n * @description A tree view widget presents a hierarchical list. Any item in the hierarchy may have child items, and items that have children can expand or collapse to show or hide the children.\n * @documentation https://nvidia.github.io/elements/docs/elements/tree/\n * @since 1.2.0\n * @entrypoint \\@nvidia-elements/core/tree\n * @event open - Dispatched when the node opens.\n * @event close - Dispatched when the node closes.\n * @event select - Dispatched when the node selection state changes.\n * @command --select - use to select the node\n * @command --deselect - use to deselect the node\n * @command --toggle-select - use to toggle the node selection state\n * @command --open - use to open the node\n * @command --close - use to close the node\n * @command --toggle - use to toggle open / closed state of the node\n * @slot - Use default slot for basic text content or nested <nve-tree-node> elements.\n * @slot content - Use only for extended long form content containing interactive elements or form inputs.\n * @cssprop --color\n * @cssprop --border-radius\n * @cssprop --font-size\n * @cssprop --min-height\n * @cssprop --text-wrap\n * @cssprop --font-weight\n * @cssprop --width\n\n * @csspart icon-button - The icon button element\n * @csspart icon - The icon element\n * @csspart checkbox - The checkbox element\n\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/treeview/\n *\n */\n@audit()\n@typeSSR({ log: false }) // warning about ssr mismatch disabled as tree node will never be a 1:1 match in ssr due to performance constraints and slot complexity\n@typeAnchor()\n@stateSelected()\n@stateExpanded()\n@scopedRegistry()\n@stateHighlighted()\nexport class TreeNode extends LitElement {\n /**\n * Determines if node is in an expanded state.\n */\n @property({ type: Boolean, reflect: true }) expanded = false;\n\n /**\n * Determines whether if node is in a selected state.\n */\n @property({ type: Boolean, reflect: true }) selected = false;\n\n /**\n * Determines whether a node can be expandable. Expandable by default if slotted nodes exist.\n */\n @property({ type: Boolean }) expandable = false;\n\n /**\n * Determines whether a node can be in a selected state. Nodes can be in a single or multi select state.\n */\n @property({ type: String }) selectable: 'single' | 'multi';\n\n /**\n * Determines the highlighted state of the element. Highlighted states serve non-interactive selections where nodes may relate to other selected portions of the UI.\n */\n @property({ type: Boolean }) highlighted = false;\n\n #i18nController: I18nController<this> = new I18nController<this>(this);\n\n /**\n * Updates internal string values for internationalization.\n */\n @property({ type: Object }) i18n = this.#i18nController.i18n;\n\n /** @private */\n @hostAttr() slot = 'nodes';\n\n get #tree() {\n return this.closest<Tree>('nve-tree');\n }\n\n /**\n * Returns the slotted child tree nodes.\n */\n @queryAssignedElements({ slot: 'nodes' }) readonly nodes!: TreeNode[];\n\n /** @private */\n @state() indeterminate = false;\n\n /** @private */\n @state() behaviorExpand = false;\n\n /** @private */\n @state() behaviorSelect = false;\n\n #typeExpandableController = new TypeExpandableController(this);\n\n #typeSelectableController = new TypeSelectableController(this);\n\n get #isExpandable() {\n return this.expandable || this.expanded || !!this.nodes?.length;\n }\n\n static metadata = {\n tag: 'nve-tree-node',\n version: '0.0.0',\n parents: ['nve-tree', 'nve-tree-node']\n };\n\n static elementDefinitions = {\n [IconButton.metadata.tag]: IconButton,\n [Icon.metadata.tag]: Icon,\n [Checkbox.metadata.tag]: Checkbox\n };\n\n static styles = useStyles([styles]);\n\n declare _internals: ElementInternals;\n\n /* eslint-disable @nvidia-elements/lint/no-missing-control-label */\n render() {\n return html`\n <div internal-host @slotchange=${this.#nodeUpdate}>\n <div part=\"_node\">\n ${\n this.#isExpandable\n ? html`\n <nve-icon-button part=\"icon-button\" exportparts=\"icon:icon-button-icon\" @pointerup=${this.#toggleExpand} role=\"presentation\" tabindex=\"-1\" size=\"sm\" container=\"inline\" nofocus>\n <nve-icon part=\"icon\" name=\"caret\" direction=${this.expanded ? 'down' : 'right'} size=\"sm\"></nve-icon>\n </nve-icon-button>`\n : nothing\n }\n ${\n this.selectable === 'multi'\n ? html`\n <nve-checkbox part=\"checkbox\" nofocus>\n <input type=\"checkbox\" @change=${this.#toggleMultiSelection} .checked=${this.selected} .indeterminate=${this.indeterminate} .ariaLabel=${this.i18n.expand} tabindex=\"-1\" />\n </nve-checkbox>`\n : nothing\n }\n <div tabindex=\"0\" part=\"_node-header\">\n <slot class=\"node-title\" @click=${this.#nodeHeaderClick}></slot>\n <slot name=\"content\" part=\"_content\"></slot>\n </div>\n </div>\n <div role=\"group\" part=\"_nodes\"><slot name=\"nodes\"></slot></div>\n </div>\n `;\n }\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n this._internals.role = 'treeitem';\n this.addEventListener('keydown', this.#onKeydown);\n this.addEventListener('keyup', this.#onKeyup);\n this.#nodeUpdate();\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this.#onKeydown);\n this.removeEventListener('keyup', this.#onKeyup);\n }\n\n /** opens and sets the expanded state automatically if behaviorExpand is true */\n open() {\n this.#typeExpandableController.open();\n }\n\n /** closes and sets the expanded state automatically if behaviorExpand is true */\n close() {\n this.#typeExpandableController.close();\n }\n\n #nodeUpdate() {\n this.requestUpdate();\n this.#toggleExpandableState();\n }\n\n #toggleExpandableState() {\n this.#isExpandable ? this._internals.states.add('is-expandable') : this._internals.states.delete('is-expandable');\n }\n\n #onKeydown = (e: KeyboardEvent) => {\n const isSelectionKey = this.selectable && e.code === 'Space';\n const isExpansionKey = this.#isExpandable && (e.code === 'ArrowLeft' || e.code === 'ArrowRight');\n\n if (e.target === this && (isSelectionKey || isExpansionKey)) {\n e.preventDefault();\n }\n };\n\n #onKeyup = (e: KeyboardEvent) => {\n if (this.#isExpandable && e.code === 'ArrowLeft' && e.target === this) {\n this.close();\n }\n\n if (this.#isExpandable && e.code === 'ArrowRight' && e.target === this) {\n this.open();\n }\n\n if (e.code === 'Space' && e.target === this && this.selectable) {\n this.#toggleSelection();\n }\n };\n\n #nodeHeaderClick(e: Event) {\n const hasFocusableElements = getFlattenedFocusableItems(e.currentTarget as HTMLElement).length;\n if (this.#isExpandable && !this.selectable && !hasFocusableElements) {\n this.#toggleExpand();\n }\n\n if (this.selectable && (!hasFocusableElements || (e.target as HTMLElement).localName === 'a')) {\n this.#toggleSelection();\n }\n }\n\n #toggleExpand() {\n this.#typeExpandableController.toggle();\n }\n\n #toggleSelection() {\n if (this.selectable === 'single') {\n this.#toggleSingleSelection();\n }\n\n if (this.selectable === 'multi') {\n this.#toggleMultiSelection();\n }\n }\n\n #toggleSingleSelection() {\n this.#typeSelectableController.toggle();\n if (this.behaviorSelect) {\n this.#tree!.nodes.filter(n => n !== this).forEach(n => (n.selected = false));\n }\n }\n\n #toggleMultiSelection() {\n this.#typeSelectableController.toggle();\n\n if (this.behaviorSelect) {\n this.nodes.forEach(n => {\n n.selected = this.selected;\n n.indeterminate = false;\n });\n this.#tree!.nodes.forEach(node => updateNodeSelection(node));\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/tree/tree.d.ts
CHANGED
|
@@ -42,12 +42,13 @@ export declare class Tree extends LitElement {
|
|
|
42
42
|
children: string[];
|
|
43
43
|
};
|
|
44
44
|
_internals: ElementInternals;
|
|
45
|
+
/** Returns the tree nodes in document order. */
|
|
45
46
|
get nodes(): TreeNode[];
|
|
46
47
|
/** @private */
|
|
47
48
|
get keynavListConfig(): KeynavListConfig;
|
|
48
49
|
/** @private */
|
|
49
50
|
get openNodes(): TreeNode[];
|
|
50
|
-
render(): import("lit").TemplateResult<1>;
|
|
51
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
51
52
|
connectedCallback(): void;
|
|
52
53
|
disconnectedCallback(): void;
|
|
53
54
|
updated(props: PropertyValues<this>): Promise<void>;
|
package/dist/tree/tree2.js
CHANGED
package/dist/tree/tree2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree2.js","names":[],"sources":["../../src/tree/tree.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { PropertyValues } from 'lit';\nimport { html, LitElement } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport type { KeynavListConfig } from '@nvidia-elements/core/internal';\nimport {\n appendRootNodeStyle,\n attachInternals,\n audit,\n keyNavigationList,\n onChildListMutation,\n useStyles\n} from '@nvidia-elements/core/internal';\nimport { updateNodeSelection } from './utils.js';\nimport { TreeNode } from './tree-node.js';\nimport styles from './tree.css?inline';\nimport globalStyles from './tree.global.css?inline';\n\n/**\n * @element nve-tree\n * @description A tree view widget presents a hierarchical list. Any item in the hierarchy may have child items, and items that have children can expand or collapse to show or hide the children.\n * @documentation https://nvidia.github.io/elements/docs/elements/tree/\n * @since 1.2.0\n * @entrypoint \\@nvidia-elements/core/tree\n * @slot - tree nodes\n * @cssprop --max-width\n * @cssprop --node-border - Border style for tree node depth indicator\n * @event open - Dispatched from a child nve-tree-node when opened.\n * @event close - Dispatched from a child nve-tree-node when closed.\n * @event select - Dispatched from a child nve-tree-node when its selection state changes.\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/treeview/\n *\n */\n@audit()\n@keyNavigationList<Tree>()\nexport class Tree extends LitElement {\n /**\n * Determines whether all nodes can be in a selected state. Nodes can be in a single or multi select state.\n */\n @property({ type: String }) selectable: 'single' | 'multi';\n\n /**\n * Determines whether the tree nodes should handle auto-expanding behavior.\n */\n @property({ type: Boolean, attribute: 'behavior-expand' }) behaviorExpand = false;\n\n /**\n * Determines whether the tree nodes should handle auto-select behavior.\n */\n @property({ type: Boolean, attribute: 'behavior-select' }) behaviorSelect = false;\n\n /**\n * Determines if the node depth border renders.\n */\n @property({ type: Boolean, reflect: true }) border = false;\n\n static styles = useStyles([styles]);\n\n static readonly metadata = {\n tag: 'nve-tree',\n version: '0.0.0',\n children: ['nve-tree-node']\n };\n\n _internals: ElementInternals;\n\n get nodes() {\n return Array.from(this.querySelectorAll<TreeNode>(TreeNode.metadata.tag));\n }\n\n /** @private */\n get keynavListConfig(): KeynavListConfig {\n return {\n items: this.openNodes\n .map(node => node.shadowRoot!.querySelector('[part=\"_node-header\"]'))\n .filter((el): el is HTMLElement => el !== null),\n layout: 'vertical'\n };\n }\n\n /** @private */\n get openNodes(): TreeNode[] {\n return this.nodes.filter(\n node => node.expanded || (node.parentNode as TreeNode).expanded || (node.parentNode as Tree) === this\n );\n }\n\n render() {\n return html`\n <div internal-host>\n <slot name=\"nodes\"></slot>\n </div>\n `;\n }\n\n #observers: MutationObserver[] = [];\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n appendRootNodeStyle(this, globalStyles);\n this._internals.role = 'tree';\n\n this.#observers.push(\n onChildListMutation(\n this,\n () => {\n this.#syncNodes();\n },\n { subtree: true }\n )\n );\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#observers.forEach(o => o.disconnect());\n }\n\n async updated(props: PropertyValues<this>) {\n super.updated(props);\n await this.updateComplete;\n this.#syncNodes();\n }\n\n #syncNodes() {\n this.#syncNodeOptions();\n this.#syncNodeSelections();\n }\n\n #syncNodeOptions() {\n this.nodes.forEach(node => {\n node.selectable = this.selectable;\n node.behaviorExpand = this.behaviorExpand;\n node.behaviorSelect = this.behaviorSelect;\n });\n }\n\n #syncNodeSelections() {\n if (this.behaviorSelect && this.selectable === 'multi') {\n this.nodes.forEach(node => updateNodeSelection(node));\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAqCO,IAAM,IAAN,cAAmB,EAAW;;
|
|
1
|
+
{"version":3,"file":"tree2.js","names":[],"sources":["../../src/tree/tree.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { PropertyValues } from 'lit';\nimport { html, LitElement } from 'lit';\nimport { property } from 'lit/decorators/property.js';\nimport type { KeynavListConfig } from '@nvidia-elements/core/internal';\nimport {\n appendRootNodeStyle,\n attachInternals,\n audit,\n keyNavigationList,\n onChildListMutation,\n useStyles\n} from '@nvidia-elements/core/internal';\nimport { updateNodeSelection } from './utils.js';\nimport { TreeNode } from './tree-node.js';\nimport styles from './tree.css?inline';\nimport globalStyles from './tree.global.css?inline';\n\n/**\n * @element nve-tree\n * @description A tree view widget presents a hierarchical list. Any item in the hierarchy may have child items, and items that have children can expand or collapse to show or hide the children.\n * @documentation https://nvidia.github.io/elements/docs/elements/tree/\n * @since 1.2.0\n * @entrypoint \\@nvidia-elements/core/tree\n * @slot - tree nodes\n * @cssprop --max-width\n * @cssprop --node-border - Border style for tree node depth indicator\n * @event open - Dispatched from a child nve-tree-node when opened.\n * @event close - Dispatched from a child nve-tree-node when closed.\n * @event select - Dispatched from a child nve-tree-node when its selection state changes.\n * @aria https://www.w3.org/WAI/ARIA/apg/patterns/treeview/\n *\n */\n@audit()\n@keyNavigationList<Tree>()\nexport class Tree extends LitElement {\n /**\n * Determines whether all nodes can be in a selected state. Nodes can be in a single or multi select state.\n */\n @property({ type: String }) selectable: 'single' | 'multi';\n\n /**\n * Determines whether the tree nodes should handle auto-expanding behavior.\n */\n @property({ type: Boolean, attribute: 'behavior-expand' }) behaviorExpand = false;\n\n /**\n * Determines whether the tree nodes should handle auto-select behavior.\n */\n @property({ type: Boolean, attribute: 'behavior-select' }) behaviorSelect = false;\n\n /**\n * Determines if the node depth border renders.\n */\n @property({ type: Boolean, reflect: true }) border = false;\n\n static styles = useStyles([styles]);\n\n static readonly metadata = {\n tag: 'nve-tree',\n version: '0.0.0',\n children: ['nve-tree-node']\n };\n\n _internals: ElementInternals;\n\n /** Returns the tree nodes in document order. */\n get nodes() {\n return Array.from(this.querySelectorAll<TreeNode>(TreeNode.metadata.tag));\n }\n\n /** @private */\n get keynavListConfig(): KeynavListConfig {\n return {\n items: this.openNodes\n .map(node => node.shadowRoot!.querySelector('[part=\"_node-header\"]'))\n .filter((el): el is HTMLElement => el !== null),\n layout: 'vertical'\n };\n }\n\n /** @private */\n get openNodes(): TreeNode[] {\n return this.nodes.filter(\n node => node.expanded || (node.parentNode as TreeNode).expanded || (node.parentNode as Tree) === this\n );\n }\n\n render() {\n return html`\n <div internal-host>\n <slot name=\"nodes\"></slot>\n </div>\n `;\n }\n\n #observers: MutationObserver[] = [];\n\n connectedCallback() {\n super.connectedCallback();\n attachInternals(this);\n appendRootNodeStyle(this, globalStyles);\n this._internals.role = 'tree';\n\n this.#observers.push(\n onChildListMutation(\n this,\n () => {\n this.#syncNodes();\n },\n { subtree: true }\n )\n );\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.#observers.forEach(o => o.disconnect());\n }\n\n async updated(props: PropertyValues<this>) {\n super.updated(props);\n await this.updateComplete;\n this.#syncNodes();\n }\n\n #syncNodes() {\n this.#syncNodeOptions();\n this.#syncNodeSelections();\n }\n\n #syncNodeOptions() {\n this.nodes.forEach(node => {\n node.selectable = this.selectable;\n node.behaviorExpand = this.behaviorExpand;\n node.behaviorSelect = this.behaviorSelect;\n });\n }\n\n #syncNodeSelections() {\n if (this.behaviorSelect && this.selectable === 'multi') {\n this.nodes.forEach(node => updateNodeSelection(node));\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAqCO,IAAM,IAAN,cAAmB,EAAW;;EA6DF,aApD2C,KAAA,iBAAA,IAKA,KAAA,iBAAA,IAKvB,KAAA,SAAA,IA0CpB,KAAA,KAAA,CAAC;;;EAxClB,KAAA,SAAA,EAAU,CAAC,CAAM,CAAC;;;EAEP,KAAA,WAAA;GACzB,KAAK;GACL,SAAS;GACT,UAAU,CAAC,eAAe;EAC5B;;CAKA,IAAI,QAAQ;EACV,OAAO,MAAM,KAAK,KAAK,iBAA2B,EAAS,SAAS,GAAG,CAAC;CAC1E;CAGA,IAAI,mBAAqC;EACvC,OAAO;GACL,OAAO,KAAK,UACT,KAAI,MAAQ,EAAK,WAAY,cAAc,yBAAuB,CAAC,CAAC,CACpE,QAAQ,MAA0B,MAAO,IAAI;GAChD,QAAQ;EACV;CACF;CAGA,IAAI,YAAwB;EAC1B,OAAO,KAAK,MAAM,QAChB,MAAQ,EAAK,YAAa,EAAK,WAAwB,YAAa,EAAK,eAAwB,IACnG;CACF;CAEA,SAAS;EACP,OAAO,CAAI;CAKb;CAEA;CAEA,oBAAoB;EAMlB,AALA,MAAM,kBAAkB,GACxB,EAAgB,IAAI,GACpB,EAAoB,MAAM,CAAY,GACtC,KAAK,WAAW,OAAO,QAEvB,KAAK,GAAW,KACd,EACE,YACM;GACJ,KAAK,GAAW;EAClB,GACA,EAAE,SAAS,GAAK,CAClB,CACF;CACF;CAEA,uBAAuB;EAErB,AADA,MAAM,qBAAqB,GAC3B,KAAK,GAAW,SAAQ,MAAK,EAAE,WAAW,CAAC;CAC7C;CAEA,MAAM,QAAQ,GAA6B;EAGzC,AAFA,MAAM,QAAQ,CAAK,GACnB,MAAM,KAAK,gBACX,KAAK,GAAW;CAClB;CAEA,KAAa;EAEX,AADA,KAAK,GAAiB,GACtB,KAAK,GAAoB;CAC3B;CAEA,KAAmB;EACjB,KAAK,MAAM,SAAQ,MAAQ;GAGzB,AAFA,EAAK,aAAa,KAAK,YACvB,EAAK,iBAAiB,KAAK,gBAC3B,EAAK,iBAAiB,KAAK;EAC7B,CAAC;CACH;CAEA,KAAsB;EACpB,AAAI,KAAK,kBAAkB,KAAK,eAAe,WAC7C,KAAK,MAAM,SAAQ,MAAQ,EAAoB,CAAI,CAAC;CAExD;AACF;AAzGG,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GAKzB,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,WAAW;AAAkB,CAAC,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAKxD,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,WAAW;AAAkB,CAAC,CAAA,GAAA,EAAA,WAAA,kBAAA,KAAA,CAAA,GAKxD,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,UAAA,KAAA,CAAA,GArB3C,IAAA,EAAA,CAAA,EAAM,GACN,EAAwB,CAAA,GAAA,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","names":[],"sources":["../../src/viewport/define.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { define } from '@nvidia-elements/core/internal';\nimport { Viewport, ViewportGridlines } from '@nvidia-elements/core/viewport';\n\ndefine(Viewport);\ndefine(ViewportGridlines);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nve-viewport': Viewport;\n 'nve-viewport-gridlines': ViewportGridlines;\n }\n}\n"],"mappings":";;;AAMA,EAAO,CAAQ,GACf,EAAO,CAAiB"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export * from './viewport.js';
|
|
2
|
+
export * from './viewport-gridlines.js';
|
|
3
|
+
export type { ViewportAnimationOptions, ViewportDiscretePanDetail, ViewportPanBehavior, ViewportPanDetail, ViewportPanEndDetail, ViewportPanEndReason, ViewportPoint, ViewportPointerPanDetail, ViewportRect, ViewportRevealOptions, ViewportTransform, ViewportWheelPanDetail, ViewportZoomDetail } from './viewport.types.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import type { ViewportAnimationOptions, ViewportTransform } from './viewport.types.js';
|
|
3
|
+
interface ViewportSize {
|
|
4
|
+
readonly width: number;
|
|
5
|
+
readonly height: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ViewportAnimationDelegate {
|
|
8
|
+
readonly commitTransform: (transform: ViewportTransform) => void;
|
|
9
|
+
readonly clampScale: (value: number) => number;
|
|
10
|
+
readonly getTransform: () => ViewportTransform;
|
|
11
|
+
readonly getViewportSize: () => ViewportSize;
|
|
12
|
+
}
|
|
13
|
+
export declare class ViewportAnimationController implements ReactiveController {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(reactiveHost: ReactiveControllerHost, delegate: ViewportAnimationDelegate);
|
|
16
|
+
get destinationScale(): number | undefined;
|
|
17
|
+
animateTo(target: Partial<ViewportTransform>, options?: ViewportAnimationOptions): void;
|
|
18
|
+
cancel(): void;
|
|
19
|
+
hostDisconnected(): void;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { finiteOr as e, nonnegativeFiniteOr as t } from "../internal/utils/numeric.js";
|
|
2
|
+
//#region src/viewport/viewport-animation.controller.ts
|
|
3
|
+
var n = class {
|
|
4
|
+
#e;
|
|
5
|
+
#t;
|
|
6
|
+
constructor(e, t) {
|
|
7
|
+
this.#e = t, e.addController(this);
|
|
8
|
+
}
|
|
9
|
+
get destinationScale() {
|
|
10
|
+
return this.#t?.target.scale;
|
|
11
|
+
}
|
|
12
|
+
animateTo(n, i = {}) {
|
|
13
|
+
let o = this.#e.getTransform(), l = {
|
|
14
|
+
x: e(n.x, o.x),
|
|
15
|
+
y: e(n.y, o.y),
|
|
16
|
+
scale: this.#e.clampScale(n.scale ?? o.scale)
|
|
17
|
+
};
|
|
18
|
+
if (this.cancel(), s(o, l)) return;
|
|
19
|
+
let u = t(i.duration, r(o.scale, l.scale));
|
|
20
|
+
if (u === 0 || a()) {
|
|
21
|
+
this.#e.commitTransform(l);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
let d = {
|
|
25
|
+
duration: u,
|
|
26
|
+
frame: 0,
|
|
27
|
+
start: o,
|
|
28
|
+
startCenter: c(o, this.#e.getViewportSize()),
|
|
29
|
+
target: l
|
|
30
|
+
};
|
|
31
|
+
this.#t = d, d.frame = requestAnimationFrame(this.#n);
|
|
32
|
+
}
|
|
33
|
+
cancel() {
|
|
34
|
+
let e = this.#t;
|
|
35
|
+
e && (cancelAnimationFrame(e.frame), this.#t = void 0);
|
|
36
|
+
}
|
|
37
|
+
hostDisconnected() {
|
|
38
|
+
this.cancel();
|
|
39
|
+
}
|
|
40
|
+
#n = (e) => {
|
|
41
|
+
let t = this.#t;
|
|
42
|
+
if (!t) return;
|
|
43
|
+
if (t.startTime === void 0) return this.#r(t, e);
|
|
44
|
+
let n = Math.min(1, Math.max(0, (e - t.startTime) / t.duration)), r = o(n), a = this.#e.getViewportSize(), s = c(t.target, a), l = 1 / i(1 / t.start.scale, 1 / t.target.scale, r), u = i(t.startCenter.x, s.x, r), d = i(t.startCenter.y, s.y, r);
|
|
45
|
+
this.#e.commitTransform({
|
|
46
|
+
scale: l,
|
|
47
|
+
x: u - a.width / (2 * l),
|
|
48
|
+
y: d - a.height / (2 * l)
|
|
49
|
+
}), n >= 1 ? (this.#t = void 0, this.#e.commitTransform(t.target)) : t.frame = requestAnimationFrame(this.#n);
|
|
50
|
+
};
|
|
51
|
+
#r(e, t) {
|
|
52
|
+
e.startTime = t, e.frame = requestAnimationFrame(this.#n);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function r(e, t) {
|
|
56
|
+
return Math.min(400, Math.max(150, 150 + Math.abs(Math.log2(t / e)) * 100));
|
|
57
|
+
}
|
|
58
|
+
function i(e, t, n) {
|
|
59
|
+
return e + (t - e) * n;
|
|
60
|
+
}
|
|
61
|
+
function a() {
|
|
62
|
+
return typeof matchMedia == "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
63
|
+
}
|
|
64
|
+
function o(e) {
|
|
65
|
+
let t = e;
|
|
66
|
+
for (let n = 0; n < 6; n += 1) {
|
|
67
|
+
let n = l(t, .4, .2) - e, r = u(t, .4, .2);
|
|
68
|
+
if (Math.abs(r) < 1e-7) break;
|
|
69
|
+
t = Math.min(1, Math.max(0, t - n / r));
|
|
70
|
+
}
|
|
71
|
+
return l(t, 0, 1);
|
|
72
|
+
}
|
|
73
|
+
function s(e, t) {
|
|
74
|
+
return e.x === t.x && e.y === t.y && e.scale === t.scale;
|
|
75
|
+
}
|
|
76
|
+
function c(e, t) {
|
|
77
|
+
return {
|
|
78
|
+
x: e.x + t.width / (2 * e.scale),
|
|
79
|
+
y: e.y + t.height / (2 * e.scale)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function l(e, t, n) {
|
|
83
|
+
let r = 1 - e;
|
|
84
|
+
return 3 * r ** 2 * e * t + 3 * r * e ** 2 * n + e ** 3;
|
|
85
|
+
}
|
|
86
|
+
function u(e, t, n) {
|
|
87
|
+
let r = 1 - e;
|
|
88
|
+
return 3 * r ** 2 * t + 6 * r * e * (n - t) + 3 * e ** 2 * (1 - n);
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { n as ViewportAnimationController };
|
|
92
|
+
|
|
93
|
+
//# sourceMappingURL=viewport-animation.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-animation.controller.js","names":[],"sources":["../../src/viewport/viewport-animation.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveControllerHost } from 'lit';\nimport { finiteOr, nonnegativeFiniteOr } from '@nvidia-elements/core/internal';\nimport type { ViewportAnimationOptions, ViewportPoint, ViewportTransform } from './viewport.types.js';\n\ninterface ViewportAnimation {\n frame: number;\n readonly start: ViewportTransform;\n readonly target: ViewportTransform;\n readonly startCenter: ViewportPoint;\n startTime?: number;\n readonly duration: number;\n}\n\ninterface ViewportSize {\n readonly width: number;\n readonly height: number;\n}\n\nexport interface ViewportAnimationDelegate {\n readonly commitTransform: (transform: ViewportTransform) => void;\n readonly clampScale: (value: number) => number;\n readonly getTransform: () => ViewportTransform;\n readonly getViewportSize: () => ViewportSize;\n}\n\nexport class ViewportAnimationController implements ReactiveController {\n readonly #delegate: ViewportAnimationDelegate;\n #animation?: ViewportAnimation;\n\n constructor(reactiveHost: ReactiveControllerHost, delegate: ViewportAnimationDelegate) {\n this.#delegate = delegate;\n reactiveHost.addController(this);\n }\n\n get destinationScale(): number | undefined {\n return this.#animation?.target.scale;\n }\n\n animateTo(target: Partial<ViewportTransform>, options: ViewportAnimationOptions = {}): void {\n const start = this.#delegate.getTransform();\n const next: ViewportTransform = {\n x: finiteOr(target.x, start.x),\n y: finiteOr(target.y, start.y),\n scale: this.#delegate.clampScale(target.scale ?? start.scale)\n };\n this.cancel();\n if (transformsEqual(start, next)) return;\n const duration = nonnegativeFiniteOr(options.duration, defaultAnimationDuration(start.scale, next.scale));\n if (duration === 0 || prefersReducedMotion()) {\n this.#delegate.commitTransform(next);\n return;\n }\n const viewport = this.#delegate.getViewportSize();\n const animation: ViewportAnimation = {\n duration,\n frame: 0,\n start,\n startCenter: viewportCenter(start, viewport),\n target: next\n };\n this.#animation = animation;\n animation.frame = requestAnimationFrame(this.#animateFrame);\n }\n\n cancel(): void {\n const animation = this.#animation;\n if (!animation) return;\n cancelAnimationFrame(animation.frame);\n this.#animation = undefined;\n }\n\n hostDisconnected(): void {\n this.cancel();\n }\n\n #animateFrame = (time: number): void => {\n const animation = this.#animation;\n if (!animation) return;\n if (animation.startTime === undefined) return this.#startAnimation(animation, time);\n const progress = Math.min(1, Math.max(0, (time - animation.startTime) / animation.duration));\n const eased = standardEasing(progress);\n const viewport = this.#delegate.getViewportSize();\n const targetCenter = viewportCenter(animation.target, viewport);\n const scale = 1 / lerp(1 / animation.start.scale, 1 / animation.target.scale, eased);\n const centerX = lerp(animation.startCenter.x, targetCenter.x, eased);\n const centerY = lerp(animation.startCenter.y, targetCenter.y, eased);\n this.#delegate.commitTransform({\n scale,\n x: centerX - viewport.width / (2 * scale),\n y: centerY - viewport.height / (2 * scale)\n });\n if (progress >= 1) {\n this.#animation = undefined;\n this.#delegate.commitTransform(animation.target);\n } else {\n animation.frame = requestAnimationFrame(this.#animateFrame);\n }\n };\n\n #startAnimation(animation: ViewportAnimation, time: number): void {\n animation.startTime = time;\n animation.frame = requestAnimationFrame(this.#animateFrame);\n }\n}\n\nfunction defaultAnimationDuration(startScale: number, targetScale: number): number {\n return Math.min(400, Math.max(150, 150 + Math.abs(Math.log2(targetScale / startScale)) * 100));\n}\n\nfunction lerp(start: number, end: number, progress: number): number {\n return start + (end - start) * progress;\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\nfunction standardEasing(progress: number): number {\n let parameter = progress;\n for (let iteration = 0; iteration < 6; iteration += 1) {\n const x = cubicBezier(parameter, 0.4, 0.2) - progress;\n const slope = cubicBezierSlope(parameter, 0.4, 0.2);\n if (Math.abs(slope) < 1e-7) break;\n parameter = Math.min(1, Math.max(0, parameter - x / slope));\n }\n return cubicBezier(parameter, 0, 1);\n}\n\nfunction transformsEqual(first: ViewportTransform, second: ViewportTransform): boolean {\n return first.x === second.x && first.y === second.y && first.scale === second.scale;\n}\n\nfunction viewportCenter(transform: ViewportTransform, viewport: ViewportSize): ViewportPoint {\n return {\n x: transform.x + viewport.width / (2 * transform.scale),\n y: transform.y + viewport.height / (2 * transform.scale)\n };\n}\n\nfunction cubicBezier(parameter: number, firstControl: number, secondControl: number): number {\n const inverse = 1 - parameter;\n return 3 * inverse ** 2 * parameter * firstControl + 3 * inverse * parameter ** 2 * secondControl + parameter ** 3;\n}\n\nfunction cubicBezierSlope(parameter: number, firstControl: number, secondControl: number): number {\n const inverse = 1 - parameter;\n return (\n 3 * inverse ** 2 * firstControl +\n 6 * inverse * parameter * (secondControl - firstControl) +\n 3 * parameter ** 2 * (1 - secondControl)\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import type { ViewportClientRect } from './viewport-fitting.utils.js';
|
|
3
|
+
interface ViewportAutoFitHost extends ReactiveControllerHost, HTMLElement {
|
|
4
|
+
readonly autoFit: boolean;
|
|
5
|
+
readonly hasUpdated: boolean;
|
|
6
|
+
}
|
|
7
|
+
type ApplyInitialFit = (clientRects: readonly ViewportClientRect[]) => void;
|
|
8
|
+
/** Coordinates one initial fit once default-slot children have definitions and measurable layout. */
|
|
9
|
+
export declare class ViewportAutoFitController implements ReactiveController {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(host: ViewportAutoFitHost, applyInitialFit: ApplyInitialFit);
|
|
12
|
+
hostConnected(): void;
|
|
13
|
+
hostDisconnected(): void;
|
|
14
|
+
hostUpdated(): void;
|
|
15
|
+
contentChanged: (event: Event) => void;
|
|
16
|
+
consume(): void;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { getChildren as e, getCustomElementRegistry as t } from "../internal/utils/dom.js";
|
|
2
|
+
//#region src/viewport/viewport-autofit.controller.ts
|
|
3
|
+
var n = class {
|
|
4
|
+
#e;
|
|
5
|
+
#t;
|
|
6
|
+
#n;
|
|
7
|
+
#r;
|
|
8
|
+
#i;
|
|
9
|
+
#a;
|
|
10
|
+
#o;
|
|
11
|
+
constructor(e, t) {
|
|
12
|
+
this.#r = !1, this.#a = 0, this.contentChanged = (e) => {
|
|
13
|
+
e.target instanceof HTMLSlotElement && this.#c(e.target);
|
|
14
|
+
}, this.#t = e, this.#e = t, e.addController(this);
|
|
15
|
+
}
|
|
16
|
+
hostConnected() {
|
|
17
|
+
this.#t.hasUpdated && this.#c();
|
|
18
|
+
}
|
|
19
|
+
hostDisconnected() {
|
|
20
|
+
this.#s();
|
|
21
|
+
}
|
|
22
|
+
hostUpdated() {
|
|
23
|
+
this.#t.autoFit ? this.#c() : this.#s();
|
|
24
|
+
}
|
|
25
|
+
consume() {
|
|
26
|
+
!this.#t.autoFit || this.#r || (this.#r = !0, this.#n = void 0, this.#a += 1, this.#i !== void 0 && cancelAnimationFrame(this.#i), this.#i = void 0, this.#o?.disconnect(), this.#o = void 0);
|
|
27
|
+
}
|
|
28
|
+
#s() {
|
|
29
|
+
this.#a += 1, this.#n = void 0, this.#i !== void 0 && cancelAnimationFrame(this.#i), this.#i = void 0, this.#o?.disconnect(), this.#o = void 0;
|
|
30
|
+
}
|
|
31
|
+
#c(t) {
|
|
32
|
+
if (!this.#t.autoFit || this.#r || this.#n || !this.#t.isConnected) return;
|
|
33
|
+
let n = (t ? e(t) : Array.from(this.#t.children).filter((e) => !e.slot)).filter((e) => !(e instanceof HTMLElement && e.hidden));
|
|
34
|
+
this.#n = n;
|
|
35
|
+
let r = ++this.#a;
|
|
36
|
+
this.#l(n).then(() => this.#u(r));
|
|
37
|
+
}
|
|
38
|
+
async #l(e) {
|
|
39
|
+
let n = /* @__PURE__ */ new Map();
|
|
40
|
+
for (let r of e) for (let e of [r, ...r.querySelectorAll(":not(:defined)")]) {
|
|
41
|
+
if (e.namespaceURI !== "http://www.w3.org/1999/xhtml" || !e.localName.includes("-") || i(e, r)) continue;
|
|
42
|
+
let a = t(e);
|
|
43
|
+
if (!a) continue;
|
|
44
|
+
let o = n.get(a) ?? /* @__PURE__ */ new Set();
|
|
45
|
+
o.add(e.localName), n.set(a, o);
|
|
46
|
+
}
|
|
47
|
+
await Promise.all(Array.from(n, ([e, t]) => Promise.all(Array.from(t, (t) => r(e, t)))));
|
|
48
|
+
}
|
|
49
|
+
#u(e) {
|
|
50
|
+
if (this.#m(e)) {
|
|
51
|
+
if (typeof ResizeObserver > "u") {
|
|
52
|
+
queueMicrotask(() => this.#f(e));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.#o?.disconnect(), this.#o = new ResizeObserver(() => this.#d(e)), this.#o.observe(this.#t);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
#d(e) {
|
|
59
|
+
!this.#m(e) || this.#t.clientWidth <= 0 || this.#t.clientHeight <= 0 || (this.#o?.disconnect(), this.#o = void 0, this.#i = requestAnimationFrame(() => {
|
|
60
|
+
this.#i = void 0, this.#f(e);
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
#f(e) {
|
|
64
|
+
if (!this.#m(e) || this.#t.clientWidth <= 0 || this.#t.clientHeight <= 0) return;
|
|
65
|
+
let t = this.#n;
|
|
66
|
+
if (!t) return;
|
|
67
|
+
let n = this.#p(t);
|
|
68
|
+
this.consume(), n.length && this.#e(n);
|
|
69
|
+
}
|
|
70
|
+
#p(e) {
|
|
71
|
+
let t = new Set(Array.from(this.#t.children).filter((e) => !e.slot)), n = [];
|
|
72
|
+
for (let r of e) {
|
|
73
|
+
if (!t.has(r) || r instanceof HTMLElement && r.hidden) continue;
|
|
74
|
+
let e = r.getBoundingClientRect();
|
|
75
|
+
e.width > 0 && e.height > 0 && n.push({
|
|
76
|
+
height: e.height,
|
|
77
|
+
left: e.left,
|
|
78
|
+
top: e.top,
|
|
79
|
+
width: e.width
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return n;
|
|
83
|
+
}
|
|
84
|
+
#m(e) {
|
|
85
|
+
return e === this.#a && this.#t.autoFit && !this.#r && this.#n !== void 0 && this.#t.isConnected;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
async function r(e, t) {
|
|
89
|
+
try {
|
|
90
|
+
await e.whenDefined(t);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
if (!(e instanceof DOMException) || e.name !== "SyntaxError") throw e;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function i(e, t) {
|
|
96
|
+
for (let n = e; n; n = n.parentElement) {
|
|
97
|
+
if (n instanceof HTMLElement && n.hidden) return !0;
|
|
98
|
+
if (n === t) return !1;
|
|
99
|
+
}
|
|
100
|
+
return !1;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { n as ViewportAutoFitController };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=viewport-autofit.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-autofit.controller.js","names":[],"sources":["../../src/viewport/viewport-autofit.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { ReactiveController, ReactiveControllerHost } from 'lit';\nimport { getChildren, getCustomElementRegistry } from '@nvidia-elements/core/internal';\nimport type { ViewportClientRect } from './viewport-fitting.utils.js';\n\ninterface ViewportAutoFitHost extends ReactiveControllerHost, HTMLElement {\n readonly autoFit: boolean;\n readonly hasUpdated: boolean;\n}\n\ntype ApplyInitialFit = (clientRects: readonly ViewportClientRect[]) => void;\n\n/** Coordinates one initial fit once default-slot children have definitions and measurable layout. */\nexport class ViewportAutoFitController implements ReactiveController {\n readonly #applyInitialFit: ApplyInitialFit;\n readonly #host: ViewportAutoFitHost;\n #children?: readonly Element[];\n #consumed = false;\n #frame?: number;\n #generation = 0;\n #observer?: ResizeObserver;\n\n constructor(host: ViewportAutoFitHost, applyInitialFit: ApplyInitialFit) {\n this.#host = host;\n this.#applyInitialFit = applyInitialFit;\n host.addController(this);\n }\n\n hostConnected(): void {\n if (this.#host.hasUpdated) this.#start();\n }\n\n hostDisconnected(): void {\n this.#cancelPending();\n }\n\n hostUpdated(): void {\n if (this.#host.autoFit) {\n this.#start();\n } else {\n this.#cancelPending();\n }\n }\n\n contentChanged = (event: Event): void => {\n if (!(event.target instanceof HTMLSlotElement)) return;\n this.#start(event.target);\n };\n\n consume(): void {\n if (!this.#host.autoFit || this.#consumed) return;\n this.#consumed = true;\n this.#children = undefined;\n this.#generation += 1;\n if (this.#frame !== undefined) cancelAnimationFrame(this.#frame);\n this.#frame = undefined;\n this.#observer?.disconnect();\n this.#observer = undefined;\n }\n\n #cancelPending(): void {\n this.#generation += 1;\n this.#children = undefined;\n if (this.#frame !== undefined) cancelAnimationFrame(this.#frame);\n this.#frame = undefined;\n this.#observer?.disconnect();\n this.#observer = undefined;\n }\n\n #start(slot?: HTMLSlotElement): void {\n if (!this.#host.autoFit || this.#consumed || this.#children || !this.#host.isConnected) return;\n const children = (slot ? getChildren(slot) : Array.from(this.#host.children).filter(child => !child.slot)).filter(\n child => !(child instanceof HTMLElement && child.hidden)\n );\n this.#children = children;\n const generation = ++this.#generation;\n void this.#waitForDefinitions(children).then(() => this.#waitForLayout(generation));\n }\n\n async #waitForDefinitions(children: readonly Element[]): Promise<void> {\n const definitions = new Map<CustomElementRegistry, Set<string>>();\n for (const child of children) {\n for (const element of [child, ...child.querySelectorAll(':not(:defined)')]) {\n if (\n element.namespaceURI !== 'http://www.w3.org/1999/xhtml' ||\n !element.localName.includes('-') ||\n isExplicitlyHidden(element, child)\n ) {\n continue;\n }\n const registry = getCustomElementRegistry(element);\n if (!registry) continue;\n const names = definitions.get(registry) ?? new Set<string>();\n names.add(element.localName);\n definitions.set(registry, names);\n }\n }\n await Promise.all(\n Array.from(definitions, ([registry, names]) =>\n Promise.all(Array.from(names, name => whenDefined(registry, name)))\n )\n );\n }\n\n #waitForLayout(generation: number): void {\n if (!this.#isCurrent(generation)) return;\n if (typeof ResizeObserver === 'undefined') {\n queueMicrotask(() => this.#fit(generation));\n return;\n }\n this.#observer?.disconnect();\n this.#observer = new ResizeObserver(() => this.#scheduleFit(generation));\n this.#observer.observe(this.#host);\n }\n\n #scheduleFit(generation: number): void {\n if (!this.#isCurrent(generation) || this.#host.clientWidth <= 0 || this.#host.clientHeight <= 0) return;\n this.#observer?.disconnect();\n this.#observer = undefined;\n this.#frame = requestAnimationFrame(() => {\n this.#frame = undefined;\n this.#fit(generation);\n });\n }\n\n #fit(generation: number): void {\n if (!this.#isCurrent(generation) || this.#host.clientWidth <= 0 || this.#host.clientHeight <= 0) return;\n const children = this.#children;\n if (!children) return;\n const measurableBounds = this.#measurableClientRects(children);\n this.consume();\n if (measurableBounds.length) this.#applyInitialFit(measurableBounds);\n }\n\n #measurableClientRects(children: readonly Element[]): ViewportClientRect[] {\n const assigned = new Set(Array.from(this.#host.children).filter(child => !child.slot));\n const measurableBounds: ViewportClientRect[] = [];\n for (const child of children) {\n if (!assigned.has(child) || (child instanceof HTMLElement && child.hidden)) continue;\n const bounds = child.getBoundingClientRect();\n if (bounds.width > 0 && bounds.height > 0) {\n measurableBounds.push({ height: bounds.height, left: bounds.left, top: bounds.top, width: bounds.width });\n }\n }\n return measurableBounds;\n }\n\n #isCurrent(generation: number): boolean {\n return (\n generation === this.#generation &&\n this.#host.autoFit &&\n !this.#consumed &&\n this.#children !== undefined &&\n this.#host.isConnected\n );\n }\n}\n\nasync function whenDefined(registry: CustomElementRegistry, name: string): Promise<void> {\n try {\n await registry.whenDefined(name);\n } catch (error) {\n if (!(error instanceof DOMException) || error.name !== 'SyntaxError') throw error;\n }\n}\n\nfunction isExplicitlyHidden(element: Element, child: Element): boolean {\n for (let current: Element | null = element; current; current = current.parentElement) {\n if (current instanceof HTMLElement && current.hidden) return true;\n if (current === child) return false;\n }\n return false;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ViewportRect, ViewportTransform } from './viewport.types.js';
|
|
2
|
+
export interface ViewportClientRect {
|
|
3
|
+
readonly height: number;
|
|
4
|
+
readonly left: number;
|
|
5
|
+
readonly top: number;
|
|
6
|
+
readonly width: number;
|
|
7
|
+
}
|
|
8
|
+
interface ViewportClientFrame {
|
|
9
|
+
readonly left: number;
|
|
10
|
+
readonly top: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ViewportFitOptions {
|
|
13
|
+
readonly inset?: number;
|
|
14
|
+
readonly scale?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Converts measurable client-space rectangles into their single content-space union. */
|
|
17
|
+
export declare function contentBoundsFromClientRects(clientRects: Iterable<ViewportClientRect>, viewportFrame: ViewportClientFrame, transform: ViewportTransform): ViewportRect | undefined;
|
|
18
|
+
/** Calculates the viewport transform that centers or fits a content-space region. */
|
|
19
|
+
export declare function revealTarget(region: {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
width?: number;
|
|
23
|
+
height?: number;
|
|
24
|
+
}, configuration: {
|
|
25
|
+
options: ViewportFitOptions;
|
|
26
|
+
scaleRange: {
|
|
27
|
+
min: number;
|
|
28
|
+
max: number;
|
|
29
|
+
};
|
|
30
|
+
transform: ViewportTransform;
|
|
31
|
+
viewport: {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
};
|
|
35
|
+
}): ViewportTransform;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { finiteOr as e, nonnegativeFiniteOr as t, positiveFiniteOr as n } from "../internal/utils/numeric.js";
|
|
2
|
+
//#region src/viewport/viewport-fitting.utils.ts
|
|
3
|
+
function r(e, t, n) {
|
|
4
|
+
let r = Infinity, a = Infinity, o = -Infinity, s = -Infinity;
|
|
5
|
+
for (let c of e) {
|
|
6
|
+
let e = i(c, t, n);
|
|
7
|
+
e && (r = Math.min(r, e.x), a = Math.min(a, e.y), o = Math.max(o, e.x + e.width), s = Math.max(s, e.y + e.height));
|
|
8
|
+
}
|
|
9
|
+
if (!(!Number.isFinite(r) || !Number.isFinite(a) || !Number.isFinite(o) || !Number.isFinite(s))) return {
|
|
10
|
+
height: s - a,
|
|
11
|
+
width: o - r,
|
|
12
|
+
x: r,
|
|
13
|
+
y: a
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function i(e, t, n) {
|
|
17
|
+
if (!(!(e.width > 0) || !(e.height > 0))) return {
|
|
18
|
+
height: e.height / n.scale,
|
|
19
|
+
width: e.width / n.scale,
|
|
20
|
+
x: n.x + (e.left - t.left) / n.scale,
|
|
21
|
+
y: n.y + (e.top - t.top) / n.scale
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function a(r, i) {
|
|
25
|
+
let { options: a, scaleRange: o, transform: s, viewport: c } = i, l = t(a.inset, 0), u = n(r.width, 0), d = n(r.height, 0), f = u > 0 && d > 0, p = Math.max(0, c.width - l * 2), m = Math.max(0, c.height - l * 2), h = a.scale ?? (f && p > 0 && m > 0 ? Math.min(p / u, m / d) : s.scale), g = Math.min(o.max, Math.max(o.min, n(h, o.min))), _ = e(r.x, 0) + (f ? u / 2 : 0), v = e(r.y, 0) + (f ? d / 2 : 0);
|
|
26
|
+
return {
|
|
27
|
+
scale: g,
|
|
28
|
+
x: _ - c.width / (2 * g),
|
|
29
|
+
y: v - c.height / (2 * g)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { r as contentBoundsFromClientRects, a as revealTarget };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=viewport-fitting.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-fitting.utils.js","names":[],"sources":["../../src/viewport/viewport-fitting.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { finiteOr, nonnegativeFiniteOr, positiveFiniteOr } from '@nvidia-elements/core/internal';\nimport type { ViewportRect, ViewportTransform } from './viewport.types.js';\n\nexport interface ViewportClientRect {\n readonly height: number;\n readonly left: number;\n readonly top: number;\n readonly width: number;\n}\n\ninterface ViewportClientFrame {\n readonly left: number;\n readonly top: number;\n}\n\nexport interface ViewportFitOptions {\n readonly inset?: number;\n readonly scale?: number;\n}\n\n/** Converts measurable client-space rectangles into their single content-space union. */\nexport function contentBoundsFromClientRects(\n clientRects: Iterable<ViewportClientRect>,\n viewportFrame: ViewportClientFrame,\n transform: ViewportTransform\n): ViewportRect | undefined {\n let left = Number.POSITIVE_INFINITY;\n let top = Number.POSITIVE_INFINITY;\n let right = Number.NEGATIVE_INFINITY;\n let bottom = Number.NEGATIVE_INFINITY;\n for (const clientRect of clientRects) {\n const contentRect = contentRectFromClientRect(clientRect, viewportFrame, transform);\n if (!contentRect) continue;\n left = Math.min(left, contentRect.x);\n top = Math.min(top, contentRect.y);\n right = Math.max(right, contentRect.x + contentRect.width);\n bottom = Math.max(bottom, contentRect.y + contentRect.height);\n }\n if (!Number.isFinite(left) || !Number.isFinite(top) || !Number.isFinite(right) || !Number.isFinite(bottom)) {\n return undefined;\n }\n return { height: bottom - top, width: right - left, x: left, y: top };\n}\n\nfunction contentRectFromClientRect(\n clientRect: ViewportClientRect,\n viewportFrame: ViewportClientFrame,\n transform: ViewportTransform\n): ViewportRect | undefined {\n if (!(clientRect.width > 0) || !(clientRect.height > 0)) return undefined;\n return {\n height: clientRect.height / transform.scale,\n width: clientRect.width / transform.scale,\n x: transform.x + (clientRect.left - viewportFrame.left) / transform.scale,\n y: transform.y + (clientRect.top - viewportFrame.top) / transform.scale\n };\n}\n\n/** Calculates the viewport transform that centers or fits a content-space region. */\nexport function revealTarget(\n region: { x: number; y: number; width?: number; height?: number },\n configuration: {\n options: ViewportFitOptions;\n scaleRange: { min: number; max: number };\n transform: ViewportTransform;\n viewport: { width: number; height: number };\n }\n): ViewportTransform {\n const { options, scaleRange, transform, viewport } = configuration;\n const inset = nonnegativeFiniteOr(options.inset, 0);\n const width = positiveFiniteOr(region.width, 0);\n const height = positiveFiniteOr(region.height, 0);\n const isRect = width > 0 && height > 0;\n const availableWidth = Math.max(0, viewport.width - inset * 2);\n const availableHeight = Math.max(0, viewport.height - inset * 2);\n const requestedScale =\n options.scale ??\n (isRect && availableWidth > 0 && availableHeight > 0\n ? Math.min(availableWidth / width, availableHeight / height)\n : transform.scale);\n const scale = Math.min(scaleRange.max, Math.max(scaleRange.min, positiveFiniteOr(requestedScale, scaleRange.min)));\n const centerX = finiteOr(region.x, 0) + (isRect ? width / 2 : 0);\n const centerY = finiteOr(region.y, 0) + (isRect ? height / 2 : 0);\n return {\n scale,\n x: centerX - viewport.width / (2 * scale),\n y: centerY - viewport.height / (2 * scale)\n };\n}\n"],"mappings":";;AAwBA,SAAgB,EACd,GACA,GACA,GAC0B;CAC1B,IAAI,IAAO,UACP,IAAM,UACN,IAAQ,WACR,IAAS;CACb,KAAK,IAAM,KAAc,GAAa;EACpC,IAAM,IAAc,EAA0B,GAAY,GAAe,CAAS;EAC7E,MACL,IAAO,KAAK,IAAI,GAAM,EAAY,CAAC,GACnC,IAAM,KAAK,IAAI,GAAK,EAAY,CAAC,GACjC,IAAQ,KAAK,IAAI,GAAO,EAAY,IAAI,EAAY,KAAK,GACzD,IAAS,KAAK,IAAI,GAAQ,EAAY,IAAI,EAAY,MAAM;CAC9D;CACI,OAAC,OAAO,SAAS,CAAI,KAAK,CAAC,OAAO,SAAS,CAAG,KAAK,CAAC,OAAO,SAAS,CAAK,KAAK,CAAC,OAAO,SAAS,CAAM,IAGzG,OAAO;EAAE,QAAQ,IAAS;EAAK,OAAO,IAAQ;EAAM,GAAG;EAAM,GAAG;CAAI;AACtE;AAEA,SAAS,EACP,GACA,GACA,GAC0B;CACtB,QAAE,EAAW,QAAQ,MAAM,EAAE,EAAW,SAAS,KACrD,OAAO;EACL,QAAQ,EAAW,SAAS,EAAU;EACtC,OAAO,EAAW,QAAQ,EAAU;EACpC,GAAG,EAAU,KAAK,EAAW,OAAO,EAAc,QAAQ,EAAU;EACpE,GAAG,EAAU,KAAK,EAAW,MAAM,EAAc,OAAO,EAAU;CACpE;AACF;AAGA,SAAgB,EACd,GACA,GAMmB;CACnB,IAAM,EAAE,YAAS,eAAY,cAAW,gBAAa,GAC/C,IAAQ,EAAoB,EAAQ,OAAO,CAAC,GAC5C,IAAQ,EAAiB,EAAO,OAAO,CAAC,GACxC,IAAS,EAAiB,EAAO,QAAQ,CAAC,GAC1C,IAAS,IAAQ,KAAK,IAAS,GAC/B,IAAiB,KAAK,IAAI,GAAG,EAAS,QAAQ,IAAQ,CAAC,GACvD,IAAkB,KAAK,IAAI,GAAG,EAAS,SAAS,IAAQ,CAAC,GACzD,IACJ,EAAQ,UACP,KAAU,IAAiB,KAAK,IAAkB,IAC/C,KAAK,IAAI,IAAiB,GAAO,IAAkB,CAAM,IACzD,EAAU,QACV,IAAQ,KAAK,IAAI,EAAW,KAAK,KAAK,IAAI,EAAW,KAAK,EAAiB,GAAgB,EAAW,GAAG,CAAC,CAAC,GAC3G,IAAU,EAAS,EAAO,GAAG,CAAC,KAAK,IAAS,IAAQ,IAAI,IACxD,IAAU,EAAS,EAAO,GAAG,CAAC,KAAK,IAAS,IAAS,IAAI;CAC/D,OAAO;EACL;EACA,GAAG,IAAU,EAAS,SAAS,IAAI;EACnC,GAAG,IAAU,EAAS,UAAU,IAAI;CACtC;AACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import type { ViewportPanBehavior, ViewportPoint, ViewportTransform } from './viewport.types.js';
|
|
3
|
+
import type { ViewportNavigationEventDelegate } from './viewport-navigation.types.js';
|
|
4
|
+
type ViewportGestureNavigationHost = HTMLElement & ReactiveControllerHost & {
|
|
5
|
+
readonly _internals: ElementInternals;
|
|
6
|
+
readonly behaviorPan: ViewportPanBehavior;
|
|
7
|
+
readonly behaviorZoom: boolean;
|
|
8
|
+
readonly dragThreshold: number;
|
|
9
|
+
};
|
|
10
|
+
export interface ViewportGestureNavigationDelegate {
|
|
11
|
+
readonly commitTransform: (next: ViewportTransform) => boolean;
|
|
12
|
+
readonly cancelAnimation: () => void;
|
|
13
|
+
readonly clampScale: (value: number) => number;
|
|
14
|
+
readonly clientToViewport: (clientX: number, clientY: number) => ViewportPoint;
|
|
15
|
+
readonly consumeAutoFit: () => void;
|
|
16
|
+
readonly events: ViewportNavigationEventDelegate;
|
|
17
|
+
readonly getTransform: () => ViewportTransform;
|
|
18
|
+
}
|
|
19
|
+
/** Coordinates the viewport's opt-in pointer, touch, pinch, and wheel navigation behavior. */
|
|
20
|
+
export declare class ViewportGestureNavigationController implements ReactiveController {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(host: ViewportGestureNavigationHost, delegate: ViewportGestureNavigationDelegate);
|
|
23
|
+
hostConnected(): void;
|
|
24
|
+
hostDisconnected(): void;
|
|
25
|
+
hostUpdated(): void;
|
|
26
|
+
/** Rebase in-progress pointer math synchronously after an independent transform change. */
|
|
27
|
+
rebasePointerSessions(): void;
|
|
28
|
+
}
|
|
29
|
+
export {};
|