@ds-mo/ui 12.3.0 → 12.4.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/dist/.build-stamp +1 -1
- package/dist/agent-patterns.json +89 -11
- package/dist/agent.json +543 -9
- package/dist/angular/ds-shell-app.d.ts +13 -2
- package/dist/angular/ds-shell-app.js +9 -5
- package/dist/angular/ds-shell-mobile-bar.d.ts +18 -0
- package/dist/angular/ds-shell-mobile-bar.js +46 -0
- package/dist/angular/ds-shell-mobile-nav.d.ts +23 -0
- package/dist/angular/ds-shell-mobile-nav.js +51 -0
- package/dist/angular/ds-shell-mobile-section-nav.d.ts +18 -0
- package/dist/angular/ds-shell-mobile-section-nav.js +42 -0
- package/dist/angular/ds-shell-tools.d.ts +42 -0
- package/dist/angular/ds-shell-tools.js +52 -0
- package/dist/angular/index.d.ts +1 -1
- package/dist/angular/index.js +4 -0
- package/dist/angular/proxies.d.ts +4 -0
- package/dist/angular/proxies.js +4 -0
- package/dist/components/ds-agent-response.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-title.js +1 -1
- package/dist/components/ds-bar-workflow.js +1 -1
- package/dist/components/ds-chart-donut.js +1 -1
- package/dist/components/ds-code-block.js +1 -1
- package/dist/components/ds-conversation-list-item.js +1 -1
- package/dist/components/ds-conversation-list-item.js.map +1 -1
- package/dist/components/ds-markdown.js +1 -1
- package/dist/components/ds-menu.js +1 -1
- package/dist/components/ds-message-composer.js +1 -1
- package/dist/components/ds-message-scroller.js +1 -1
- package/dist/components/ds-modal.js +1 -1
- package/dist/components/ds-modal.js.map +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-nav.js.map +1 -1
- package/dist/components/ds-panel-tool-header.js +1 -1
- package/dist/components/ds-panel-tool-search.js +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-panel-tools.js.map +1 -1
- package/dist/components/ds-select-multi.js +1 -1
- package/dist/components/ds-select-multi.js.map +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-select.js.map +1 -1
- package/dist/components/ds-shell-app.js +1 -1
- package/dist/components/ds-shell-app.js.map +1 -1
- package/dist/components/ds-shell-gradient-picker.js +1 -1
- package/dist/components/ds-shell-gradient-picker.js.map +1 -1
- package/dist/components/ds-shell-gradient-swatch.js +1 -1
- package/dist/components/ds-shell-mobile-bar.d.ts +11 -0
- package/dist/components/ds-shell-mobile-bar.js +2 -0
- package/dist/components/ds-shell-mobile-bar.js.map +1 -0
- package/dist/components/ds-shell-mobile-nav.d.ts +11 -0
- package/dist/components/ds-shell-mobile-nav.js +2 -0
- package/dist/components/ds-shell-mobile-nav.js.map +1 -0
- package/dist/components/ds-shell-mobile-section-nav.d.ts +11 -0
- package/dist/components/ds-shell-mobile-section-nav.js +2 -0
- package/dist/components/ds-shell-mobile-section-nav.js.map +1 -0
- package/dist/components/ds-shell-page.js +1 -1
- package/dist/components/ds-shell-page.js.map +1 -1
- package/dist/components/ds-shell-tools.d.ts +11 -0
- package/dist/components/ds-shell-tools.js +2 -0
- package/dist/components/ds-shell-tools.js.map +1 -0
- package/dist/components/ds-swatch-picker.js +1 -1
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-tab-group.js.map +1 -1
- package/dist/components/ds-toast.js +1 -1
- package/dist/components/ds-toast.js.map +1 -1
- package/dist/components/ds-tooltip-data-viz.js +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/ds-typing-indicator.js +1 -1
- package/dist/components/p-B6Vuayt6.js +2 -0
- package/dist/components/p-B6Vuayt6.js.map +1 -0
- package/dist/components/p-BPS9VExm.js +2 -0
- package/dist/components/{p-D3DYxbC5.js.map → p-BPS9VExm.js.map} +1 -1
- package/dist/components/{p-Bi_bxbih.js → p-Biz6xo-z.js} +2 -2
- package/dist/components/p-BrusnEYP.js +2 -0
- package/dist/components/p-BrusnEYP.js.map +1 -0
- package/dist/components/p-C_0Q8Cnp.js +2 -0
- package/dist/components/{p-Dg3xLna0.js.map → p-C_0Q8Cnp.js.map} +1 -1
- package/dist/components/p-CgHTNfC1.js +2 -0
- package/dist/components/p-CgHTNfC1.js.map +1 -0
- package/dist/components/p-Co8hD3P-.js +2 -0
- package/dist/components/{p-DC7yOUQx.js.map → p-Co8hD3P-.js.map} +1 -1
- package/dist/components/{p-Cuw2Lo2g.js → p-CtD24EyI.js} +2 -2
- package/dist/components/{p-C0NPJ0h2.js → p-DXnFhmZF.js} +2 -2
- package/dist/components/p-NUNsefU1.js +2 -0
- package/dist/components/{p-CWlh7HAg.js.map → p-NUNsefU1.js.map} +1 -1
- package/dist/components/p-PZ6R_nGI.js +2 -0
- package/dist/components/p-PZ6R_nGI.js.map +1 -0
- package/dist/components/{p-J6xK6Ihq.js → p-g40DTeV8.js} +2 -2
- package/dist/components/p-yhj1lIPx.js +2 -0
- package/dist/components/p-yhj1lIPx.js.map +1 -0
- package/dist/docs/components.json +2143 -115
- package/dist/lib/components/BarNav/bar-nav-types.d.ts +2 -0
- package/dist/lib/components/PanelNav/panel-nav-types.d.ts +29 -0
- package/dist/lib/components/PanelTools/panel-tools-types.d.ts +40 -0
- package/dist/lib/components/TabGroup/tab-item-utils.d.ts +31 -0
- package/dist/lib/shell/index.d.ts +5 -0
- package/dist/lib/shell/index.js +36 -0
- package/dist/lib/shell/index.js.map +3 -3
- package/dist/lib/shell/shell-responsive.d.ts +13 -0
- package/dist/mcp-data/registry/conversation-list-item.json +1 -1
- package/dist/mcp-data/registry/modal.json +1 -1
- package/dist/mcp-data/registry/registry.json +554 -8
- package/dist/mcp-data/registry/shell-app.json +71 -11
- package/dist/mcp-data/registry/shell-mobile-bar.json +314 -0
- package/dist/mcp-data/registry/shell-mobile-nav.json +348 -0
- package/dist/mcp-data/registry/shell-mobile-section-nav.json +267 -0
- package/dist/mcp-data/registry/shell-page.json +1 -1
- package/dist/mcp-data/registry/shell-tools.json +450 -0
- package/dist/react/components.d.ts +4 -0
- package/dist/react/components.js +4 -0
- package/dist/react/ds-shell-app.d.ts +7 -2
- package/dist/react/ds-shell-app.js +1 -1
- package/dist/react/ds-shell-mobile-bar.d.ts +13 -0
- package/dist/react/ds-shell-mobile-bar.js +15 -0
- package/dist/react/ds-shell-mobile-nav.d.ts +15 -0
- package/dist/react/ds-shell-mobile-nav.js +17 -0
- package/dist/react/ds-shell-mobile-section-nav.d.ts +12 -0
- package/dist/react/ds-shell-mobile-section-nav.js +12 -0
- package/dist/react/ds-shell-tools.d.ts +25 -0
- package/dist/react/ds-shell-tools.js +17 -0
- package/dist/types/components/ShellApp/ShellApp.d.ts +16 -0
- package/dist/types/components/ShellMobileBar/ShellMobileBar.d.ts +25 -0
- package/dist/types/components/ShellMobileBar/index.d.ts +4 -0
- package/dist/types/components/ShellMobileBar/shell-mobile-bar-types.d.ts +5 -0
- package/dist/types/components/ShellMobileNav/ShellMobileNav.d.ts +32 -0
- package/dist/types/components/ShellMobileNav/index.d.ts +2 -0
- package/dist/types/components/ShellMobileNav/shell-mobile-nav-types.d.ts +6 -0
- package/dist/types/components/ShellMobileSectionNav/ShellMobileSectionNav.d.ts +30 -0
- package/dist/types/components/ShellMobileSectionNav/index.d.ts +2 -0
- package/dist/types/components/ShellTools/ShellTools.d.ts +61 -0
- package/dist/types/components/ShellTools/index.d.ts +3 -0
- package/dist/types/components.d.ts +607 -2
- package/dist/types/shell/index.d.ts +5 -0
- package/dist/types/shell/shell-responsive.d.ts +14 -0
- package/package.json +1 -1
- package/dist/components/p-CWlh7HAg.js +0 -2
- package/dist/components/p-D3DYxbC5.js +0 -2
- package/dist/components/p-DC7yOUQx.js +0 -2
- package/dist/components/p-Dg3xLna0.js +0 -2
- /package/dist/components/{p-Bi_bxbih.js.map → p-Biz6xo-z.js.map} +0 -0
- /package/dist/components/{p-Cuw2Lo2g.js.map → p-CtD24EyI.js.map} +0 -0
- /package/dist/components/{p-C0NPJ0h2.js.map → p-DXnFhmZF.js.map} +0 -0
- /package/dist/components/{p-J6xK6Ihq.js.map → p-g40DTeV8.js.map} +0 -0
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
},
|
|
205
205
|
{
|
|
206
206
|
"path": "src/wc/components/ShellPage/ShellPage.tsx",
|
|
207
|
-
"content": "import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';\nimport { resolveCssLengthPx } from '../../utils/resolve-css-length-px';\nimport type { BarTitleVariant } from '../BarTitle/bar-title-types';\nimport { resolveShellPageHeaderVariant } from './shell-page-responsive';\nimport type {\n ShellPageCapacity,\n ShellPageContentInset,\n ShellPageHeaderPresentation,\n} from './shell-page-types';\n\ntype BarTitleElement = HTMLElement & { variant: BarTitleVariant };\n\n@Component({\n tag: 'ds-shell-page',\n styleUrl: 'ShellPage.css',\n scoped: true,\n})\nexport class ShellPage {\n private static readonly MAX_HEADER_REVEAL_FRAMES = 12;\n private static readonly MAX_HEADER_GEOMETRY_FRAMES = 12;\n\n @Element() el!: HTMLElement;\n\n /** Automatic capacity/scroll behavior, or an explicit header variant override. */\n @Prop() headerPresentation: ShellPageHeaderPresentation = 'auto';\n\n /** Available page-header capacity supplied by the owning application shell. */\n @Prop() headerCapacity?: ShellPageCapacity;\n\n /** Standard page gutters, or no inset for full-bleed page content. */\n @Prop() contentInset: ShellPageContentInset = 'default';\n\n @State() private pageTopVisible = true;\n\n private sentinelEl: HTMLElement | null = null;\n private spacerEl: HTMLElement | null = null;\n private stickyHeaderEl: HTMLElement | null = null;\n private headerEl: BarTitleElement | null = null;\n private expandedHeaderHeight = 0;\n private headerTravel = 0;\n private expandedGeometryFrozen = false;\n private headerResizeObserver: ResizeObserver | null = null;\n private headerMutationObserver: MutationObserver | null = null;\n private headerRevealFrame: number | null = null;\n private headerGeometryFrame: number | null = null;\n private scrollRoot: HTMLElement | Window | null = null;\n\n @Watch('headerCapacity')\n @Watch('headerPresentation')\n handleHeaderContractChange() {\n this.syncHeaderVariant(true);\n }\n\n componentDidLoad() {\n this.observeHeader(this.findHeader());\n this.connectScrollRoot();\n }\n\n componentDidRender() {\n this.syncHeaderVariant();\n }\n\n disconnectedCallback() {\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = null;\n }\n\n private get effectiveVariant(): BarTitleVariant {\n return resolveShellPageHeaderVariant(\n this.headerPresentation,\n this.headerCapacity ?? 'roomy',\n this.pageTopVisible\n );\n }\n\n private get headerContractResolved(): boolean {\n return this.headerPresentation !== 'auto' || this.headerCapacity !== undefined;\n }\n\n private get isScrollCompacted(): boolean {\n return (\n this.headerPresentation === 'auto' && this.headerCapacity === 'roomy' && !this.pageTopVisible\n );\n }\n\n private composedParent(element: Element): Element | null {\n return (element as HTMLElement).assignedSlot?.parentElement ?? element.parentElement;\n }\n\n private findScrollRoot(): HTMLElement | Window {\n let ancestor = this.composedParent(this.el);\n while (ancestor && ancestor !== document.documentElement) {\n const overflow = getComputedStyle(ancestor).overflowY;\n if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') {\n return ancestor as HTMLElement;\n }\n ancestor = this.composedParent(ancestor);\n }\n return window;\n }\n\n private connectScrollRoot() {\n const next = this.findScrollRoot();\n if (next === this.scrollRoot) return;\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = next;\n this.scrollRoot.addEventListener('scroll', this.handleScroll, { passive: true });\n this.handleScroll();\n }\n\n private handleScroll = () => {\n if (!this.sentinelEl || !this.scrollRoot) return;\n const rootTop =\n this.scrollRoot === window ? 0 : (this.scrollRoot as HTMLElement).getBoundingClientRect().top;\n const nextPageTopVisible = this.sentinelEl.getBoundingClientRect().top >= rootTop;\n if (\n !nextPageTopVisible &&\n this.pageTopVisible &&\n this.headerEl?.classList.contains(this.variantClass('expanded'))\n ) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n this.expandedGeometryFrozen = true;\n }\n if (\n nextPageTopVisible &&\n this.expandedGeometryFrozen &&\n this.el.getBoundingClientRect().top >= rootTop\n ) {\n this.expandedGeometryFrozen = false;\n if (this.headerEl?.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n }\n }\n this.pageTopVisible = nextPageTopVisible;\n };\n\n private findHeader(): BarTitleElement | null {\n return this.el.querySelector<BarTitleElement>('ds-bar-title');\n }\n\n private get compactHeaderHeight(): number {\n return resolveCssLengthPx('--dimension-size-600', 0);\n }\n\n private setHeaderTravel(distance: number) {\n const next = Math.max(0, distance);\n if (Math.abs(next - this.headerTravel) < 0.5) return;\n this.headerTravel = next;\n this.el.style.setProperty('--ds-shell-page-header-travel', `${next}px`);\n this.handleScroll();\n }\n\n private measureHeaderTravel(header: BarTitleElement) {\n const anchor = header.querySelector<HTMLElement>('[data-shell-page-header-anchor]');\n const compactHeight = this.compactHeaderHeight;\n if (!anchor || compactHeight <= 0) return;\n\n const headerRect = header.getBoundingClientRect();\n const anchorRect = anchor.getBoundingClientRect();\n if (headerRect.height <= 0 || anchorRect.height <= 0) return;\n\n const expandedAnchorTop = anchorRect.top - headerRect.top;\n const compactAnchorTop = Math.max(0, (compactHeight - anchorRect.height) / 2);\n this.setHeaderTravel(expandedAnchorTop - compactAnchorTop);\n }\n\n private captureExpandedHeaderGeometry(header: BarTitleElement) {\n this.expandedHeaderHeight = header.getBoundingClientRect().height;\n this.measureHeaderTravel(header);\n }\n\n private setSpacerHeight(height: number) {\n if (!this.spacerEl) return;\n this.spacerEl.style.setProperty('--ds-shell-page-flow-spacer', `${Math.max(0, height)}px`);\n }\n\n private variantClass(variant: BarTitleVariant): string {\n return `bar-title-host--${variant}`;\n }\n\n private setStickyHeaderOffset(renderedVariant: BarTitleVariant) {\n this.stickyHeaderEl?.style.setProperty(\n '--ds-shell-page-sticky-offset',\n renderedVariant === 'expanded' &&\n this.headerPresentation === 'auto' &&\n this.headerCapacity === 'roomy'\n ? `${-this.headerTravel}px`\n : '0px'\n );\n }\n\n private syncRenderedHeaderGeometry(header: BarTitleElement) {\n const renderedVariant = this.effectiveVariant;\n if (!header.classList.contains(this.variantClass(renderedVariant))) return;\n\n // Update both flow-preservation pieces before reading layout. Otherwise a\n // reverse compact → expanded render can briefly contain the tall header and\n // the compact spacer together, giving browser scroll anchoring a transient\n // height change to compensate.\n this.setSpacerHeight(\n this.isScrollCompacted ? this.expandedHeaderHeight - this.compactHeaderHeight : 0\n );\n this.setStickyHeaderOffset(renderedVariant);\n\n if (renderedVariant === 'expanded' && !this.expandedGeometryFrozen) {\n this.captureExpandedHeaderGeometry(header);\n this.setStickyHeaderOffset(renderedVariant);\n }\n }\n\n private cancelHeaderGeometrySync() {\n if (this.headerGeometryFrame !== null) cancelAnimationFrame(this.headerGeometryFrame);\n this.headerGeometryFrame = null;\n }\n\n private scheduleHeaderGeometrySync(header: BarTitleElement) {\n this.cancelHeaderGeometrySync();\n let framesRemaining = ShellPage.MAX_HEADER_GEOMETRY_FRAMES;\n let framesElapsed = 0;\n const sync = () => {\n if (this.headerEl !== header) return;\n framesRemaining -= 1;\n framesElapsed += 1;\n // In WebKit a child's componentDidLoad can precede its assignment into\n // the parent's rendered slot. Revalidate after ShellApp has had a frame\n // to expose the actual content scroller.\n this.connectScrollRoot();\n this.syncRenderedHeaderGeometry(header);\n const geometryReady =\n this.effectiveVariant !== 'expanded' ||\n (this.expandedHeaderHeight > 0 && this.headerTravel > 0);\n if ((geometryReady && framesElapsed >= 2) || framesRemaining <= 0) {\n this.headerGeometryFrame = null;\n return;\n }\n this.headerGeometryFrame = requestAnimationFrame(sync);\n };\n this.headerGeometryFrame = requestAnimationFrame(sync);\n }\n\n private cancelHeaderReveal() {\n if (this.headerRevealFrame !== null) cancelAnimationFrame(this.headerRevealFrame);\n this.headerRevealFrame = null;\n this.headerEl?.removeAttribute('data-shell-page-syncing');\n }\n\n private revealHeaderWhenSynced(header: BarTitleElement, variant: BarTitleVariant) {\n // Stencil normally re-renders within a frame or two of a prop change. Stop\n // polling at the cap, but fail closed: a stale variant must never paint.\n let framesRemaining = ShellPage.MAX_HEADER_REVEAL_FRAMES;\n const reveal = () => {\n if (this.headerEl !== header) {\n header.removeAttribute('data-shell-page-syncing');\n return;\n }\n framesRemaining -= 1;\n if (header.classList.contains(this.variantClass(variant))) {\n header.removeAttribute('data-shell-page-syncing');\n this.headerRevealFrame = null;\n return;\n }\n if (framesRemaining <= 0) {\n this.headerRevealFrame = null;\n return;\n }\n this.headerRevealFrame = requestAnimationFrame(reveal);\n };\n this.headerRevealFrame = requestAnimationFrame(reveal);\n }\n\n private syncHeaderVariant(concealUntilSynced = false) {\n const header = this.headerEl;\n if (!header) return;\n\n if (!this.headerContractResolved) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n return;\n }\n\n const next = this.effectiveVariant;\n const renderedVariantIsStale = !header.classList.contains(this.variantClass(next));\n if (!renderedVariantIsStale) this.syncRenderedHeaderGeometry(header);\n if (concealUntilSynced) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n }\n if (header.variant !== next) header.variant = next;\n if (concealUntilSynced) {\n this.revealHeaderWhenSynced(header, next);\n }\n }\n\n private observeHeader(header: BarTitleElement | null) {\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.headerEl = header;\n this.expandedHeaderHeight = 0;\n this.expandedGeometryFrozen = false;\n this.setHeaderTravel(0);\n this.setSpacerHeight(0);\n this.stickyHeaderEl?.style.setProperty('--ds-shell-page-sticky-offset', '0px');\n\n if (!header) return;\n if (header.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(header);\n }\n if (typeof ResizeObserver !== 'undefined') {\n this.headerResizeObserver = new ResizeObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerResizeObserver.observe(header);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.headerMutationObserver = new MutationObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerMutationObserver.observe(header, {\n attributes: true,\n attributeFilter: ['class'],\n });\n }\n this.syncHeaderVariant(true);\n this.scheduleHeaderGeometrySync(header);\n }\n\n private handleHeaderSlotChange = (event: Event) => {\n const slot = event.target as HTMLSlotElement;\n const header = slot\n .assignedElements({ flatten: true })\n .find(element => element.tagName.toLowerCase() === 'ds-bar-title');\n this.observeHeader((header as BarTitleElement | undefined) ?? null);\n };\n\n render() {\n return (\n <Host\n role=\"main\"\n class={{\n 'shell-page-host--inset-default': this.contentInset === 'default',\n 'shell-page-host--inset-none': this.contentInset === 'none',\n [`shell-page-host--header-${this.effectiveVariant}`]: true,\n }}\n >\n <div\n ref={el => {\n this.sentinelEl = el ?? null;\n }}\n class=\"shell-page__scroll-sentinel\"\n aria-hidden=\"true\"\n />\n <div\n ref={el => {\n this.stickyHeaderEl = el ?? null;\n }}\n class=\"shell-page__sticky-header\"\n >\n <slot name=\"header\" onSlotchange={this.handleHeaderSlotChange} />\n </div>\n <div\n ref={el => {\n this.spacerEl = el ?? null;\n }}\n class=\"shell-page__flow-spacer\"\n aria-hidden=\"true\"\n />\n <div class=\"shell-page__content\">\n <slot />\n </div>\n </Host>\n );\n }\n}\n",
|
|
207
|
+
"content": "import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';\nimport { resolveCssLengthPx } from '../../utils/resolve-css-length-px';\nimport type { BarTitleVariant } from '../BarTitle/bar-title-types';\nimport { resolveShellPageHeaderVariant } from './shell-page-responsive';\nimport type {\n ShellPageCapacity,\n ShellPageContentInset,\n ShellPageHeaderPresentation,\n} from './shell-page-types';\n\ntype BarTitleElement = HTMLElement & { variant: BarTitleVariant };\n\n@Component({\n tag: 'ds-shell-page',\n styleUrl: 'ShellPage.css',\n scoped: true,\n})\nexport class ShellPage {\n private static readonly MAX_HEADER_REVEAL_FRAMES = 12;\n private static readonly MAX_HEADER_GEOMETRY_FRAMES = 12;\n\n @Element() el!: HTMLElement;\n\n /** Automatic capacity/scroll behavior, or an explicit header variant override. */\n @Prop() headerPresentation: ShellPageHeaderPresentation = 'auto';\n\n /** Available page-header capacity supplied by the owning application shell. */\n @Prop() headerCapacity?: ShellPageCapacity;\n\n /** Standard page gutters, or no inset for full-bleed page content. */\n @Prop() contentInset: ShellPageContentInset = 'default';\n\n @State() private pageTopVisible = true;\n\n private sentinelEl: HTMLElement | null = null;\n private spacerEl: HTMLElement | null = null;\n private stickyHeaderEl: HTMLElement | null = null;\n private headerEl: BarTitleElement | null = null;\n private expandedHeaderHeight = 0;\n private headerTravel = 0;\n private expandedGeometryFrozen = false;\n private headerResizeObserver: ResizeObserver | null = null;\n private headerMutationObserver: MutationObserver | null = null;\n private headerRevealFrame: number | null = null;\n private headerGeometryFrame: number | null = null;\n private scrollRoot: HTMLElement | Window | null = null;\n\n @Watch('headerCapacity')\n @Watch('headerPresentation')\n handleHeaderContractChange() {\n this.syncHeaderVariant(true);\n }\n\n componentDidLoad() {\n this.observeHeader(this.findHeader());\n this.connectScrollRoot();\n }\n\n componentDidRender() {\n this.syncHeaderVariant();\n }\n\n disconnectedCallback() {\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = null;\n }\n\n private get effectiveVariant(): BarTitleVariant {\n return resolveShellPageHeaderVariant(\n this.headerPresentation,\n this.headerCapacity ?? 'roomy',\n this.pageTopVisible\n );\n }\n\n private get headerContractResolved(): boolean {\n return this.headerPresentation !== 'auto' || this.headerCapacity !== undefined;\n }\n\n private get isScrollCompacted(): boolean {\n return (\n this.headerPresentation === 'auto' && this.headerCapacity === 'roomy' && !this.pageTopVisible\n );\n }\n\n private composedParent(element: Element): Element | null {\n return (element as HTMLElement).assignedSlot?.parentElement ?? element.parentElement;\n }\n\n private findScrollRoot(): HTMLElement | Window {\n let ancestor = this.composedParent(this.el);\n while (ancestor && ancestor !== document.documentElement) {\n const overflow = getComputedStyle(ancestor).overflowY;\n if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') {\n return ancestor as HTMLElement;\n }\n ancestor = this.composedParent(ancestor);\n }\n return window;\n }\n\n private connectScrollRoot() {\n const next = this.findScrollRoot();\n if (next === this.scrollRoot) return;\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = next;\n this.scrollRoot.addEventListener('scroll', this.handleScroll, { passive: true });\n this.handleScroll();\n }\n\n private handleScroll = () => {\n if (!this.sentinelEl || !this.scrollRoot) return;\n const rootTop =\n this.scrollRoot === window ? 0 : (this.scrollRoot as HTMLElement).getBoundingClientRect().top;\n const nextPageTopVisible = this.sentinelEl.getBoundingClientRect().top >= rootTop;\n if (\n !nextPageTopVisible &&\n this.pageTopVisible &&\n this.headerEl?.classList.contains(this.variantClass('expanded'))\n ) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n this.expandedGeometryFrozen = true;\n }\n if (\n nextPageTopVisible &&\n this.expandedGeometryFrozen &&\n this.el.getBoundingClientRect().top >= rootTop\n ) {\n this.expandedGeometryFrozen = false;\n if (this.headerEl?.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n }\n }\n this.pageTopVisible = nextPageTopVisible;\n };\n\n private findHeader(): BarTitleElement | null {\n return this.el.querySelector<BarTitleElement>('ds-bar-title');\n }\n\n private get compactHeaderHeight(): number {\n return resolveCssLengthPx('--dimension-size-600', 0);\n }\n\n private setHeaderTravel(distance: number) {\n const next = Math.max(0, distance);\n if (Math.abs(next - this.headerTravel) < 0.5) return;\n this.headerTravel = next;\n this.el.style.setProperty('--ds-shell-page-header-travel', `${next}px`);\n this.handleScroll();\n }\n\n private measureHeaderTravel(header: BarTitleElement) {\n const anchor = header.querySelector<HTMLElement>('[data-shell-page-header-anchor]');\n const compactHeight = this.compactHeaderHeight;\n if (!anchor || compactHeight <= 0) return;\n\n const headerRect = header.getBoundingClientRect();\n const anchorRect = anchor.getBoundingClientRect();\n if (headerRect.height <= 0 || anchorRect.height <= 0) return;\n\n const expandedAnchorTop = anchorRect.top - headerRect.top;\n const compactAnchorTop = Math.max(0, (compactHeight - anchorRect.height) / 2);\n this.setHeaderTravel(expandedAnchorTop - compactAnchorTop);\n }\n\n private captureExpandedHeaderGeometry(header: BarTitleElement) {\n this.expandedHeaderHeight = header.getBoundingClientRect().height;\n this.measureHeaderTravel(header);\n }\n\n private setSpacerHeight(height: number) {\n if (!this.spacerEl) return;\n this.spacerEl.style.setProperty('--ds-shell-page-flow-spacer', `${Math.max(0, height)}px`);\n }\n\n private variantClass(variant: BarTitleVariant): string {\n return `bar-title-host--${variant}`;\n }\n\n private setStickyHeaderOffset(renderedVariant: BarTitleVariant) {\n this.stickyHeaderEl?.style.setProperty(\n '--ds-shell-page-sticky-offset',\n renderedVariant === 'expanded' &&\n this.headerPresentation === 'auto' &&\n this.headerCapacity === 'roomy'\n ? `${-this.headerTravel}px`\n : '0px'\n );\n }\n\n private syncRenderedHeaderGeometry(header: BarTitleElement) {\n const renderedVariant = this.effectiveVariant;\n if (!header.classList.contains(this.variantClass(renderedVariant))) return;\n\n // Update both flow-preservation pieces before reading layout. Otherwise a\n // reverse compact → expanded render can briefly contain the tall header and\n // the compact spacer together, giving browser scroll anchoring a transient\n // height change to compensate.\n this.setSpacerHeight(\n this.isScrollCompacted ? this.expandedHeaderHeight - this.compactHeaderHeight : 0\n );\n this.setStickyHeaderOffset(renderedVariant);\n\n if (renderedVariant === 'expanded' && !this.expandedGeometryFrozen) {\n this.captureExpandedHeaderGeometry(header);\n this.setStickyHeaderOffset(renderedVariant);\n }\n }\n\n private cancelHeaderGeometrySync() {\n if (this.headerGeometryFrame !== null) cancelAnimationFrame(this.headerGeometryFrame);\n this.headerGeometryFrame = null;\n }\n\n private scheduleHeaderGeometrySync(header: BarTitleElement) {\n this.cancelHeaderGeometrySync();\n let framesRemaining = ShellPage.MAX_HEADER_GEOMETRY_FRAMES;\n let framesElapsed = 0;\n const sync = () => {\n if (this.headerEl !== header) return;\n framesRemaining -= 1;\n framesElapsed += 1;\n // In WebKit a child's componentDidLoad can precede its assignment into\n // the parent's rendered slot. Revalidate after ShellApp has had a frame\n // to expose the actual content scroller.\n this.connectScrollRoot();\n this.syncRenderedHeaderGeometry(header);\n const geometryReady =\n this.effectiveVariant !== 'expanded' ||\n (this.expandedHeaderHeight > 0 && this.headerTravel > 0);\n if ((geometryReady && framesElapsed >= 2) || framesRemaining <= 0) {\n this.headerGeometryFrame = null;\n return;\n }\n this.headerGeometryFrame = requestAnimationFrame(sync);\n };\n this.headerGeometryFrame = requestAnimationFrame(sync);\n }\n\n private cancelHeaderReveal() {\n if (this.headerRevealFrame !== null) cancelAnimationFrame(this.headerRevealFrame);\n this.headerRevealFrame = null;\n this.headerEl?.removeAttribute('data-shell-page-syncing');\n }\n\n private revealHeaderWhenSynced(header: BarTitleElement, variant: BarTitleVariant) {\n // Stencil normally re-renders within a frame or two of a prop change. Stop\n // polling at the cap, but fail closed: a stale variant must never paint.\n let framesRemaining = ShellPage.MAX_HEADER_REVEAL_FRAMES;\n const reveal = () => {\n if (this.headerEl !== header) {\n header.removeAttribute('data-shell-page-syncing');\n return;\n }\n framesRemaining -= 1;\n if (header.classList.contains(this.variantClass(variant))) {\n header.removeAttribute('data-shell-page-syncing');\n this.headerRevealFrame = null;\n return;\n }\n if (framesRemaining <= 0) {\n this.headerRevealFrame = null;\n return;\n }\n this.headerRevealFrame = requestAnimationFrame(reveal);\n };\n this.headerRevealFrame = requestAnimationFrame(reveal);\n }\n\n private syncHeaderVariant(concealUntilSynced = false) {\n const header = this.headerEl;\n if (!header) return;\n\n if (!this.headerContractResolved) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n return;\n }\n\n const next = this.effectiveVariant;\n const renderedVariantIsStale = !header.classList.contains(this.variantClass(next));\n if (!renderedVariantIsStale) this.syncRenderedHeaderGeometry(header);\n if (concealUntilSynced) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n }\n if (header.variant !== next) header.variant = next;\n if (concealUntilSynced) {\n this.revealHeaderWhenSynced(header, next);\n }\n }\n\n private observeHeader(header: BarTitleElement | null) {\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.headerEl = header;\n this.expandedHeaderHeight = 0;\n this.expandedGeometryFrozen = false;\n this.setHeaderTravel(0);\n this.setSpacerHeight(0);\n this.stickyHeaderEl?.style.setProperty('--ds-shell-page-sticky-offset', '0px');\n\n if (!header) return;\n if (header.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(header);\n }\n if (typeof ResizeObserver !== 'undefined') {\n this.headerResizeObserver = new ResizeObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerResizeObserver.observe(header);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.headerMutationObserver = new MutationObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerMutationObserver.observe(header, {\n attributes: true,\n attributeFilter: ['class'],\n });\n }\n this.syncHeaderVariant(true);\n this.scheduleHeaderGeometrySync(header);\n }\n\n private handleHeaderSlotChange = (event: Event) => {\n const slot = event.target as HTMLSlotElement;\n const header = slot\n .assignedElements()\n .find(element => element.tagName.toLowerCase() === 'ds-bar-title');\n this.observeHeader((header as BarTitleElement | undefined) ?? null);\n };\n\n render() {\n return (\n <Host\n role=\"main\"\n class={{\n 'shell-page-host--inset-default': this.contentInset === 'default',\n 'shell-page-host--inset-none': this.contentInset === 'none',\n [`shell-page-host--header-${this.effectiveVariant}`]: true,\n }}\n >\n <div\n ref={el => {\n this.sentinelEl = el ?? null;\n }}\n class=\"shell-page__scroll-sentinel\"\n aria-hidden=\"true\"\n />\n <div\n ref={el => {\n this.stickyHeaderEl = el ?? null;\n }}\n class=\"shell-page__sticky-header\"\n >\n <slot name=\"header\" onSlotchange={this.handleHeaderSlotChange} />\n </div>\n <div\n ref={el => {\n this.spacerEl = el ?? null;\n }}\n class=\"shell-page__flow-spacer\"\n aria-hidden=\"true\"\n />\n <div class=\"shell-page__content\">\n <slot />\n </div>\n </Host>\n );\n }\n}\n",
|
|
208
208
|
"type": "registry:ui"
|
|
209
209
|
},
|
|
210
210
|
{
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "shell-tools",
|
|
4
|
+
"title": "ShellTools",
|
|
5
|
+
"description": "Responsive persistent host for shell tools, adapting PanelTools rail and drawer chrome to full-stage mobile Search, Agents, and Inbox surfaces.",
|
|
6
|
+
"type": "registry:ui",
|
|
7
|
+
"meta": {
|
|
8
|
+
"library": "@ds-mo/ui",
|
|
9
|
+
"distribution": "npm",
|
|
10
|
+
"storybook": "https://zainadeel.github.io/compomo/?path=/story/shell-tools",
|
|
11
|
+
"source": "src/wc/components/ShellTools/ShellTools.tsx",
|
|
12
|
+
"intentStatus": "complete",
|
|
13
|
+
"intent": {
|
|
14
|
+
"audience": "specialized",
|
|
15
|
+
"status": "experimental",
|
|
16
|
+
"summary": "Responsive persistent host for shell tools, adapting PanelTools rail and drawer chrome to full-stage mobile Search, Agents, and Inbox surfaces.",
|
|
17
|
+
"useWhen": [
|
|
18
|
+
"A ShellApp must preserve the same Search, Agents, Messages, Stacks, Activity, and Help product owners across desktop, tablet, and mobile."
|
|
19
|
+
],
|
|
20
|
+
"avoidWhen": [
|
|
21
|
+
"The tools exist only in desktop and tablet chrome; PanelTools remains supported for that case.",
|
|
22
|
+
"The content is a routed primary application area."
|
|
23
|
+
],
|
|
24
|
+
"alternatives": [
|
|
25
|
+
{
|
|
26
|
+
"when": "Only legacy rail and drawer behavior is required.",
|
|
27
|
+
"component": "component:ds-panel-tools",
|
|
28
|
+
"reason": "PanelTools remains the backward-compatible desktop and tablet primitive."
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"commonlyComposedWith": [
|
|
32
|
+
"component:ds-shell-app",
|
|
33
|
+
"component:ds-panel-tool-header",
|
|
34
|
+
"component:ds-shell-mobile-bar"
|
|
35
|
+
],
|
|
36
|
+
"patterns": [
|
|
37
|
+
"pattern:application-shell"
|
|
38
|
+
],
|
|
39
|
+
"accessibility": [
|
|
40
|
+
"Only the active mobile tool view participates in focus or the accessibility tree.",
|
|
41
|
+
"Header Back and application-owned header actions preserve the PanelTools event contract.",
|
|
42
|
+
"Inbox uses TabGroup semantics for Messages, Stacks, and Activity."
|
|
43
|
+
],
|
|
44
|
+
"states": [
|
|
45
|
+
"The application owns open and activeTool and replaces headers when tool depth changes.",
|
|
46
|
+
"Messages, Stacks, and Activity map to one mobile Inbox destination while retaining the actual active tool id.",
|
|
47
|
+
"Switching responsive mode must not recreate application-owned slotted product elements."
|
|
48
|
+
],
|
|
49
|
+
"responsiveBehavior": [
|
|
50
|
+
"Desktop and tablet compose PanelTools-compatible rail and drawer chrome.",
|
|
51
|
+
"Mobile renders the active tool across the shell stage and groups available inbox tools in a segmented control."
|
|
52
|
+
],
|
|
53
|
+
"frameworkCaveats": {
|
|
54
|
+
"customElements": [
|
|
55
|
+
"Assign items and headers as JavaScript properties and place each persistent owner in its named *-view slot."
|
|
56
|
+
],
|
|
57
|
+
"react": [
|
|
58
|
+
"Keep stable keyed product owner elements in the generated wrapper's named slots."
|
|
59
|
+
],
|
|
60
|
+
"angular": [
|
|
61
|
+
"Bind structured items and headers as properties and keep each tool owner mounted under a named *-view slot."
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"references": [
|
|
65
|
+
{
|
|
66
|
+
"label": "Storybook",
|
|
67
|
+
"path": "src/wc/components/ShellTools/ShellTools.stories.ts"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"label": "PanelTools contract",
|
|
71
|
+
"path": "src/wc/components/PanelTools/PanelTools.agent.json"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"api": {
|
|
76
|
+
"props": {
|
|
77
|
+
"activeTool": {
|
|
78
|
+
"type": "PanelToolsToolId | ''",
|
|
79
|
+
"resolvedType": "\"\" | \"activity\" | \"agents\" | \"help\" | \"messages\" | \"search\" | \"stacks\"",
|
|
80
|
+
"attribute": "active-tool",
|
|
81
|
+
"default": "''",
|
|
82
|
+
"required": false,
|
|
83
|
+
"mutable": true
|
|
84
|
+
},
|
|
85
|
+
"fullscreenHeaderMode": {
|
|
86
|
+
"type": "'shared' | 'split'",
|
|
87
|
+
"resolvedType": "\"shared\" | \"split\"",
|
|
88
|
+
"attribute": "fullscreen-header-mode",
|
|
89
|
+
"default": "'shared'",
|
|
90
|
+
"required": false,
|
|
91
|
+
"mutable": false
|
|
92
|
+
},
|
|
93
|
+
"headers": {
|
|
94
|
+
"type": "PanelToolsHeaders",
|
|
95
|
+
"resolvedType": "\"activity\" | \"agents\" | \"help\" | \"messages\" | \"search\" | \"stacks\" | PanelToolsHeaderConfig",
|
|
96
|
+
"default": "{}",
|
|
97
|
+
"required": false,
|
|
98
|
+
"mutable": false
|
|
99
|
+
},
|
|
100
|
+
"headersJson": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"resolvedType": "string",
|
|
103
|
+
"attribute": "headers-json",
|
|
104
|
+
"default": "''",
|
|
105
|
+
"required": false,
|
|
106
|
+
"mutable": false
|
|
107
|
+
},
|
|
108
|
+
"inboxLabel": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"resolvedType": "string",
|
|
111
|
+
"attribute": "inbox-label",
|
|
112
|
+
"default": "'Inbox'",
|
|
113
|
+
"required": false,
|
|
114
|
+
"mutable": false
|
|
115
|
+
},
|
|
116
|
+
"inboxNavigationLabel": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"resolvedType": "string",
|
|
119
|
+
"attribute": "inbox-navigation-label",
|
|
120
|
+
"default": "'Inbox sections'",
|
|
121
|
+
"required": false,
|
|
122
|
+
"mutable": false
|
|
123
|
+
},
|
|
124
|
+
"items": {
|
|
125
|
+
"type": "PanelToolsItem[]",
|
|
126
|
+
"resolvedType": "PanelToolsItem[]",
|
|
127
|
+
"default": "[]",
|
|
128
|
+
"required": false,
|
|
129
|
+
"mutable": false
|
|
130
|
+
},
|
|
131
|
+
"itemsJson": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"resolvedType": "string",
|
|
134
|
+
"attribute": "items-json",
|
|
135
|
+
"default": "''",
|
|
136
|
+
"required": false,
|
|
137
|
+
"mutable": false
|
|
138
|
+
},
|
|
139
|
+
"open": {
|
|
140
|
+
"type": "boolean",
|
|
141
|
+
"resolvedType": "boolean",
|
|
142
|
+
"attribute": "open",
|
|
143
|
+
"default": "false",
|
|
144
|
+
"required": false,
|
|
145
|
+
"mutable": true
|
|
146
|
+
},
|
|
147
|
+
"presentation": {
|
|
148
|
+
"type": "'drawer' | 'fullscreen'",
|
|
149
|
+
"resolvedType": "\"drawer\" | \"fullscreen\"",
|
|
150
|
+
"attribute": "presentation",
|
|
151
|
+
"default": "'drawer'",
|
|
152
|
+
"required": false,
|
|
153
|
+
"mutable": true
|
|
154
|
+
},
|
|
155
|
+
"responsiveMode": {
|
|
156
|
+
"type": "ShellResponsiveMode",
|
|
157
|
+
"resolvedType": "\"desktop\" | \"mobile\" | \"tablet\"",
|
|
158
|
+
"attribute": "responsive-mode",
|
|
159
|
+
"default": "'desktop'",
|
|
160
|
+
"required": false,
|
|
161
|
+
"mutable": false,
|
|
162
|
+
"description": "Resolved by ShellApp; mobile uses a full-stage tool presentation."
|
|
163
|
+
},
|
|
164
|
+
"storageKey": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"resolvedType": "string",
|
|
167
|
+
"attribute": "storage-key",
|
|
168
|
+
"default": "''",
|
|
169
|
+
"required": false,
|
|
170
|
+
"mutable": false
|
|
171
|
+
},
|
|
172
|
+
"toolShortcutsLabel": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"resolvedType": "string",
|
|
175
|
+
"attribute": "tool-shortcuts-label",
|
|
176
|
+
"default": "'Tool shortcuts'",
|
|
177
|
+
"required": false,
|
|
178
|
+
"mutable": false
|
|
179
|
+
},
|
|
180
|
+
"toolsLabel": {
|
|
181
|
+
"type": "string",
|
|
182
|
+
"resolvedType": "string",
|
|
183
|
+
"attribute": "tools-label",
|
|
184
|
+
"default": "'Tools'",
|
|
185
|
+
"required": false,
|
|
186
|
+
"mutable": false
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"events": [
|
|
190
|
+
{
|
|
191
|
+
"name": "dsHeaderAction",
|
|
192
|
+
"detail": "{\n tool: PanelToolsToolId;\n id: string;\n }",
|
|
193
|
+
"bubbles": true,
|
|
194
|
+
"cancelable": true,
|
|
195
|
+
"composed": true
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"name": "dsHeaderBack",
|
|
199
|
+
"detail": "{\n tool: PanelToolsToolId;\n }",
|
|
200
|
+
"bubbles": true,
|
|
201
|
+
"cancelable": true,
|
|
202
|
+
"composed": true
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"name": "dsPresentationChange",
|
|
206
|
+
"detail": "{\n presentation: 'drawer' | 'fullscreen';\n }",
|
|
207
|
+
"bubbles": true,
|
|
208
|
+
"cancelable": true,
|
|
209
|
+
"composed": true
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"name": "dsToolChange",
|
|
213
|
+
"detail": "{\n id: PanelToolsToolId;\n selected: boolean;\n }",
|
|
214
|
+
"bubbles": true,
|
|
215
|
+
"cancelable": true,
|
|
216
|
+
"composed": true
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"methods": [
|
|
220
|
+
{
|
|
221
|
+
"name": "activateTool",
|
|
222
|
+
"signature": "activateTool(id: PanelToolsToolId) => Promise<void>",
|
|
223
|
+
"description": "Match PanelTools' imperative activation contract in every responsive mode."
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "closeDrawer",
|
|
227
|
+
"signature": "closeDrawer() => Promise<void>",
|
|
228
|
+
"description": "Close the active global tool surface."
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"name": "focusHeaderAction",
|
|
232
|
+
"signature": "focusHeaderAction(id: string) => Promise<void>",
|
|
233
|
+
"description": "Focus an application-owned action in the visible shared tool header."
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
"slots": []
|
|
237
|
+
},
|
|
238
|
+
"props": {
|
|
239
|
+
"activeTool": {
|
|
240
|
+
"type": "PanelToolsToolId | ''",
|
|
241
|
+
"resolvedType": "\"\" | \"activity\" | \"agents\" | \"help\" | \"messages\" | \"search\" | \"stacks\"",
|
|
242
|
+
"attribute": "active-tool",
|
|
243
|
+
"default": "''",
|
|
244
|
+
"required": false,
|
|
245
|
+
"mutable": true
|
|
246
|
+
},
|
|
247
|
+
"fullscreenHeaderMode": {
|
|
248
|
+
"type": "'shared' | 'split'",
|
|
249
|
+
"resolvedType": "\"shared\" | \"split\"",
|
|
250
|
+
"attribute": "fullscreen-header-mode",
|
|
251
|
+
"default": "'shared'",
|
|
252
|
+
"required": false,
|
|
253
|
+
"mutable": false
|
|
254
|
+
},
|
|
255
|
+
"headers": {
|
|
256
|
+
"type": "PanelToolsHeaders",
|
|
257
|
+
"resolvedType": "\"activity\" | \"agents\" | \"help\" | \"messages\" | \"search\" | \"stacks\" | PanelToolsHeaderConfig",
|
|
258
|
+
"default": "{}",
|
|
259
|
+
"required": false,
|
|
260
|
+
"mutable": false
|
|
261
|
+
},
|
|
262
|
+
"headersJson": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"resolvedType": "string",
|
|
265
|
+
"attribute": "headers-json",
|
|
266
|
+
"default": "''",
|
|
267
|
+
"required": false,
|
|
268
|
+
"mutable": false
|
|
269
|
+
},
|
|
270
|
+
"inboxLabel": {
|
|
271
|
+
"type": "string",
|
|
272
|
+
"resolvedType": "string",
|
|
273
|
+
"attribute": "inbox-label",
|
|
274
|
+
"default": "'Inbox'",
|
|
275
|
+
"required": false,
|
|
276
|
+
"mutable": false
|
|
277
|
+
},
|
|
278
|
+
"inboxNavigationLabel": {
|
|
279
|
+
"type": "string",
|
|
280
|
+
"resolvedType": "string",
|
|
281
|
+
"attribute": "inbox-navigation-label",
|
|
282
|
+
"default": "'Inbox sections'",
|
|
283
|
+
"required": false,
|
|
284
|
+
"mutable": false
|
|
285
|
+
},
|
|
286
|
+
"items": {
|
|
287
|
+
"type": "PanelToolsItem[]",
|
|
288
|
+
"resolvedType": "PanelToolsItem[]",
|
|
289
|
+
"default": "[]",
|
|
290
|
+
"required": false,
|
|
291
|
+
"mutable": false
|
|
292
|
+
},
|
|
293
|
+
"itemsJson": {
|
|
294
|
+
"type": "string",
|
|
295
|
+
"resolvedType": "string",
|
|
296
|
+
"attribute": "items-json",
|
|
297
|
+
"default": "''",
|
|
298
|
+
"required": false,
|
|
299
|
+
"mutable": false
|
|
300
|
+
},
|
|
301
|
+
"open": {
|
|
302
|
+
"type": "boolean",
|
|
303
|
+
"resolvedType": "boolean",
|
|
304
|
+
"attribute": "open",
|
|
305
|
+
"default": "false",
|
|
306
|
+
"required": false,
|
|
307
|
+
"mutable": true
|
|
308
|
+
},
|
|
309
|
+
"presentation": {
|
|
310
|
+
"type": "'drawer' | 'fullscreen'",
|
|
311
|
+
"resolvedType": "\"drawer\" | \"fullscreen\"",
|
|
312
|
+
"attribute": "presentation",
|
|
313
|
+
"default": "'drawer'",
|
|
314
|
+
"required": false,
|
|
315
|
+
"mutable": true
|
|
316
|
+
},
|
|
317
|
+
"responsiveMode": {
|
|
318
|
+
"type": "ShellResponsiveMode",
|
|
319
|
+
"resolvedType": "\"desktop\" | \"mobile\" | \"tablet\"",
|
|
320
|
+
"attribute": "responsive-mode",
|
|
321
|
+
"default": "'desktop'",
|
|
322
|
+
"required": false,
|
|
323
|
+
"mutable": false,
|
|
324
|
+
"description": "Resolved by ShellApp; mobile uses a full-stage tool presentation."
|
|
325
|
+
},
|
|
326
|
+
"storageKey": {
|
|
327
|
+
"type": "string",
|
|
328
|
+
"resolvedType": "string",
|
|
329
|
+
"attribute": "storage-key",
|
|
330
|
+
"default": "''",
|
|
331
|
+
"required": false,
|
|
332
|
+
"mutable": false
|
|
333
|
+
},
|
|
334
|
+
"toolShortcutsLabel": {
|
|
335
|
+
"type": "string",
|
|
336
|
+
"resolvedType": "string",
|
|
337
|
+
"attribute": "tool-shortcuts-label",
|
|
338
|
+
"default": "'Tool shortcuts'",
|
|
339
|
+
"required": false,
|
|
340
|
+
"mutable": false
|
|
341
|
+
},
|
|
342
|
+
"toolsLabel": {
|
|
343
|
+
"type": "string",
|
|
344
|
+
"resolvedType": "string",
|
|
345
|
+
"attribute": "tools-label",
|
|
346
|
+
"default": "'Tools'",
|
|
347
|
+
"required": false,
|
|
348
|
+
"mutable": false
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
"events": [
|
|
352
|
+
{
|
|
353
|
+
"name": "dsHeaderAction",
|
|
354
|
+
"detail": "{\n tool: PanelToolsToolId;\n id: string;\n }",
|
|
355
|
+
"bubbles": true,
|
|
356
|
+
"cancelable": true,
|
|
357
|
+
"composed": true
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"name": "dsHeaderBack",
|
|
361
|
+
"detail": "{\n tool: PanelToolsToolId;\n }",
|
|
362
|
+
"bubbles": true,
|
|
363
|
+
"cancelable": true,
|
|
364
|
+
"composed": true
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"name": "dsPresentationChange",
|
|
368
|
+
"detail": "{\n presentation: 'drawer' | 'fullscreen';\n }",
|
|
369
|
+
"bubbles": true,
|
|
370
|
+
"cancelable": true,
|
|
371
|
+
"composed": true
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"name": "dsToolChange",
|
|
375
|
+
"detail": "{\n id: PanelToolsToolId;\n selected: boolean;\n }",
|
|
376
|
+
"bubbles": true,
|
|
377
|
+
"cancelable": true,
|
|
378
|
+
"composed": true
|
|
379
|
+
}
|
|
380
|
+
],
|
|
381
|
+
"methods": [
|
|
382
|
+
{
|
|
383
|
+
"name": "activateTool",
|
|
384
|
+
"signature": "activateTool(id: PanelToolsToolId) => Promise<void>",
|
|
385
|
+
"description": "Match PanelTools' imperative activation contract in every responsive mode."
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"name": "closeDrawer",
|
|
389
|
+
"signature": "closeDrawer() => Promise<void>",
|
|
390
|
+
"description": "Close the active global tool surface."
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"name": "focusHeaderAction",
|
|
394
|
+
"signature": "focusHeaderAction(id: string) => Promise<void>",
|
|
395
|
+
"description": "Focus an application-owned action in the visible shared tool header."
|
|
396
|
+
}
|
|
397
|
+
],
|
|
398
|
+
"slots": [],
|
|
399
|
+
"exports": {
|
|
400
|
+
"customElement": "ds-shell-tools",
|
|
401
|
+
"react": "DsShellTools",
|
|
402
|
+
"angular": "DsShellTools"
|
|
403
|
+
},
|
|
404
|
+
"consumption": {
|
|
405
|
+
"install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
|
|
406
|
+
"cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
|
|
407
|
+
"customElements": {
|
|
408
|
+
"import": "import '@ds-mo/ui/dist/components/ds-shell-tools.js';",
|
|
409
|
+
"example": "<ds-shell-tools></ds-shell-tools>"
|
|
410
|
+
},
|
|
411
|
+
"react": {
|
|
412
|
+
"import": "import { DsShellTools } from '@ds-mo/ui/react';",
|
|
413
|
+
"example": "<DsShellTools />"
|
|
414
|
+
},
|
|
415
|
+
"angular": {
|
|
416
|
+
"import": "import { DsShellTools } from '@ds-mo/ui/angular/ds-shell-tools';",
|
|
417
|
+
"example": "<ds-shell-tools></ds-shell-tools>"
|
|
418
|
+
},
|
|
419
|
+
"complexPropertyNote": "Assign these non-primitive values as JavaScript properties: headers, items.",
|
|
420
|
+
"peerDependencies": {
|
|
421
|
+
"required": [
|
|
422
|
+
"@ds-mo/tokens ^3.1.1",
|
|
423
|
+
"@ds-mo/icons ^6.4.0"
|
|
424
|
+
],
|
|
425
|
+
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
"dependencies": [
|
|
430
|
+
"@ds-mo/ui",
|
|
431
|
+
"@ds-mo/tokens"
|
|
432
|
+
],
|
|
433
|
+
"registryDependencies": [
|
|
434
|
+
"panel-tool-header",
|
|
435
|
+
"panel-tools",
|
|
436
|
+
"tab-group"
|
|
437
|
+
],
|
|
438
|
+
"files": [
|
|
439
|
+
{
|
|
440
|
+
"path": "src/wc/components/ShellTools/ShellTools.css",
|
|
441
|
+
"content": ":host {\n display: block;\n min-width: 0;\n min-height: 0;\n height: 100%;\n background: var(--color-background-primary);\n}\n\n.shell-tools__desktop,\n.shell-tools__desktop ds-panel-tools,\n.shell-tools__mobile {\n display: block;\n min-width: 0;\n min-height: 0;\n height: 100%;\n}\n\n.shell-tools__mobile {\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n background: var(--color-background-primary);\n}\n\n.shell-tools__inbox-nav {\n padding: var(--dimension-space-100);\n border-bottom: var(--dimension-stroke-width-012) solid var(--color-border-tertiary);\n background: var(--color-background-primary);\n}\n\n.shell-tools__mobile-body,\n.shell-tools__view {\n min-width: 0;\n min-height: 0;\n height: 100%;\n}\n\n.shell-tools__mobile-body {\n overflow: hidden;\n}\n\n.shell-tools__view {\n overflow: auto;\n overscroll-behavior: contain;\n}\n\n.shell-tools__view[hidden] {\n display: none;\n}\n\n.shell-tools__view ::slotted(*) {\n min-height: 0;\n}\n",
|
|
442
|
+
"type": "registry:ui"
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
"path": "src/wc/components/ShellTools/ShellTools.tsx",
|
|
446
|
+
"content": "import {\n Component,\n Element,\n Event,\n EventEmitter,\n h,\n Host,\n Method,\n Prop,\n Watch,\n} from '@stencil/core';\nimport {\n PANEL_TOOLS_LABELS,\n PANEL_TOOLS_TOOL_IDS,\n type PanelToolsHeaderAction,\n type PanelToolsHeaderConfig,\n type PanelToolsHeaders,\n type PanelToolsItem,\n type PanelToolsToolId,\n} from '../PanelTools/panel-tools-types';\nimport {\n parsePanelToolsItems,\n reconcilePanelToolsAvailability,\n resolvePanelToolActivation,\n} from '../PanelTools/panel-tools-utils';\nimport {\n isShellInboxTool,\n resolveAvailableInboxTool,\n type ShellInboxToolId,\n type ShellResponsiveMode,\n} from '../../shell/shell-responsive';\n\nconst MOBILE_VIEW_ORDER: PanelToolsToolId[] = [\n 'search',\n 'agents',\n 'messages',\n 'stacks',\n 'activity',\n 'help',\n];\n\n@Component({\n tag: 'ds-shell-tools',\n styleUrl: 'ShellTools.css',\n scoped: true,\n})\nexport class ShellTools {\n @Element() el!: HTMLElement;\n\n /** Resolved by ShellApp; mobile uses a full-stage tool presentation. */\n @Prop({ attribute: 'responsive-mode', reflect: true })\n responsiveMode: ShellResponsiveMode = 'desktop';\n @Prop({ mutable: true, reflect: true }) open: boolean = false;\n @Prop({ mutable: true, attribute: 'active-tool', reflect: true })\n activeTool: PanelToolsToolId | '' = '';\n @Prop({ mutable: true, reflect: true }) presentation: 'drawer' | 'fullscreen' = 'drawer';\n @Prop({ attribute: 'fullscreen-header-mode', reflect: true })\n fullscreenHeaderMode: 'shared' | 'split' = 'shared';\n @Prop() items: PanelToolsItem[] = [];\n @Prop({ attribute: 'items-json' }) itemsJson: string = '';\n @Prop() headers: PanelToolsHeaders = {};\n @Prop({ attribute: 'headers-json' }) headersJson: string = '';\n @Prop({ attribute: 'storage-key' }) storageKey: string = '';\n @Prop() toolsLabel: string = 'Tools';\n @Prop() toolShortcutsLabel: string = 'Tool shortcuts';\n @Prop() inboxLabel: string = 'Inbox';\n @Prop() inboxNavigationLabel: string = 'Inbox sections';\n\n @Event({ bubbles: true, composed: true }) dsToolChange!: EventEmitter<{\n id: PanelToolsToolId;\n selected: boolean;\n }>;\n @Event({ bubbles: true, composed: true }) dsPresentationChange!: EventEmitter<{\n presentation: 'drawer' | 'fullscreen';\n }>;\n @Event({ bubbles: true, composed: true }) dsHeaderBack!: EventEmitter<{\n tool: PanelToolsToolId;\n }>;\n @Event({ bubbles: true, composed: true }) dsHeaderAction!: EventEmitter<{\n tool: PanelToolsToolId;\n id: string;\n }>;\n\n private panelToolsEl: HTMLDsPanelToolsElement | null = null;\n\n private get resolvedItems(): PanelToolsItem[] {\n return parsePanelToolsItems(this.items, this.itemsJson);\n }\n\n private get availableInboxTools(): ShellInboxToolId[] {\n return this.resolvedItems\n .filter(item => !item.isInactive && isShellInboxTool(item.id))\n .map(item => item.id as ShellInboxToolId);\n }\n\n private get mobileActiveTool(): PanelToolsToolId | '' {\n if (!isShellInboxTool(this.activeTool)) return this.activeTool;\n return resolveAvailableInboxTool(this.activeTool, this.availableInboxTools);\n }\n\n componentWillLoad() {\n this.reconcileAvailability();\n }\n\n @Watch('items')\n @Watch('itemsJson')\n handleItemsChange() {\n this.reconcileAvailability();\n }\n\n private reconcileAvailability() {\n const next = reconcilePanelToolsAvailability(this.resolvedItems, this.open, this.activeTool);\n this.open = next.open;\n this.activeTool = next.activeTool;\n }\n\n private resolvedHeaders(): PanelToolsHeaders {\n if (Object.keys(this.headers).length) return this.headers;\n if (!this.headersJson.trim()) return {};\n try {\n const parsed = JSON.parse(this.headersJson);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as PanelToolsHeaders)\n : {};\n } catch {\n return {};\n }\n }\n\n private activeHeader(tool: PanelToolsToolId): PanelToolsHeaderConfig {\n return this.resolvedHeaders()[tool] ?? {};\n }\n\n private activateMobileTool(id: PanelToolsToolId) {\n const item = this.resolvedItems.find(entry => entry.id === id);\n if (!item || item.isInactive) return;\n const next = resolvePanelToolActivation(this.open, this.activeTool, id);\n this.open = next.open;\n this.activeTool = next.activeTool;\n this.dsToolChange.emit({ id, selected: next.selected });\n }\n\n private selectInboxTool = (event: CustomEvent<string>) => {\n const id = event.detail;\n if (!isShellInboxTool(id) || id === this.mobileActiveTool) return;\n this.open = true;\n this.activeTool = id;\n this.dsToolChange.emit({ id, selected: true });\n };\n\n private handlePanelToolChange = (\n event: CustomEvent<{ id: PanelToolsToolId; selected: boolean }>\n ) => {\n this.activeTool = event.detail.id;\n this.open = event.detail.selected;\n };\n\n private handlePanelPresentationChange = (\n event: CustomEvent<{ presentation: 'drawer' | 'fullscreen' }>\n ) => {\n this.presentation = event.detail.presentation;\n };\n\n private handleMobileHeaderAction = (\n tool: PanelToolsToolId,\n event: CustomEvent<{ id: string }>\n ) => {\n event.stopPropagation();\n this.dsHeaderAction.emit({ tool, id: event.detail.id });\n };\n\n /** Match PanelTools' imperative activation contract in every responsive mode. */\n @Method()\n async activateTool(id: PanelToolsToolId) {\n if (this.responsiveMode !== 'mobile') {\n await this.panelToolsEl?.activateTool(id);\n return;\n }\n this.activateMobileTool(id);\n }\n\n /** Close the active global tool surface. */\n @Method()\n async closeDrawer() {\n if (this.responsiveMode !== 'mobile') {\n await this.panelToolsEl?.closeDrawer();\n return;\n }\n if (!this.open) return;\n const id = this.activeTool;\n this.open = false;\n if (id) this.dsToolChange.emit({ id, selected: false });\n }\n\n /** Focus an application-owned action in the visible shared tool header. */\n @Method()\n async focusHeaderAction(id: string) {\n if (this.responsiveMode !== 'mobile') {\n await this.panelToolsEl?.focusHeaderAction(id);\n return;\n }\n const action = this.el.querySelector(`[data-header-action-id=\"${CSS.escape(id)}\"]`) as\n | (HTMLElement & { setFocus?: () => Promise<void> })\n | null;\n await action?.setFocus?.();\n }\n\n private renderForwardedSlots() {\n return PANEL_TOOLS_TOOL_IDS.flatMap(id => [\n <slot name={id} slot={id} />,\n <slot name={`${id}-view`} slot={`${id}-view`} />,\n ]);\n }\n\n private renderDesktop() {\n return (\n <div class=\"shell-tools__desktop\">\n <ds-panel-tools\n open={this.open}\n activeTool={this.activeTool}\n presentation={this.presentation}\n fullscreenHeaderMode={this.fullscreenHeaderMode}\n items={this.resolvedItems}\n headers={this.resolvedHeaders()}\n storageKey={this.storageKey}\n toolsLabel={this.toolsLabel}\n toolShortcutsLabel={this.toolShortcutsLabel}\n ref={element => {\n this.panelToolsEl = element as HTMLDsPanelToolsElement | null;\n }}\n onDsToolChange={this.handlePanelToolChange}\n onDsPresentationChange={this.handlePanelPresentationChange}\n >\n {this.renderForwardedSlots()}\n </ds-panel-tools>\n </div>\n );\n }\n\n private renderMobileHeader(tool: PanelToolsToolId) {\n const header = this.activeHeader(tool);\n const configuredTitle = header.title?.trim();\n const title = isShellInboxTool(tool)\n ? header.showBack && configuredTitle\n ? configuredTitle\n : this.inboxLabel\n : configuredTitle || PANEL_TOOLS_LABELS[tool];\n const actions = header.actions ?? [];\n\n return (\n <ds-panel-tool-header\n class=\"shell-tools__mobile-header\"\n heading={title}\n showBack={header.showBack ?? false}\n backIcon={header.backIcon || 'ChevronLeft'}\n backAriaLabel={header.backAriaLabel || 'Back'}\n showMenu={false}\n ref={element => {\n const toolHeader = element as\n | (HTMLDsPanelToolHeaderElement & { actions: PanelToolsHeaderAction[] })\n | undefined;\n if (toolHeader) toolHeader.actions = actions;\n }}\n onDsBack={() => this.dsHeaderBack.emit({ tool })}\n onDsAction={(event: CustomEvent<{ id: string }>) =>\n this.handleMobileHeaderAction(tool, event)}\n />\n );\n }\n\n private renderMobile() {\n const tool = this.mobileActiveTool;\n const inboxTabs = this.availableInboxTools.map(id => ({\n id,\n label: PANEL_TOOLS_LABELS[id],\n }));\n\n return (\n <div\n class=\"shell-tools__mobile\"\n aria-hidden={this.open && tool ? undefined : 'true'}\n inert={this.open && tool ? undefined : true}\n >\n {tool ? this.renderMobileHeader(tool) : null}\n {tool && isShellInboxTool(tool) && inboxTabs.length ? (\n <div class=\"shell-tools__inbox-nav\">\n <ds-tab-group\n tabs={inboxTabs}\n value={tool}\n aria-label={this.inboxNavigationLabel}\n onDsChange={this.selectInboxTool}\n />\n </div>\n ) : null}\n <div class=\"shell-tools__mobile-body\">\n {MOBILE_VIEW_ORDER.map(id => {\n const active = this.open && id === tool;\n return (\n <div\n class={{\n 'shell-tools__view': true,\n 'shell-tools__view--active': active,\n }}\n hidden={!active}\n aria-hidden={active ? undefined : 'true'}\n inert={active ? undefined : true}\n >\n <slot name={`${id}-view`}>\n <slot name={id} />\n </slot>\n </div>\n );\n })}\n </div>\n </div>\n );\n }\n\n render() {\n return (\n <Host\n role={this.presentation === 'fullscreen' ? 'dialog' : 'complementary'}\n aria-modal={this.presentation === 'fullscreen' ? 'true' : undefined}\n aria-label={this.toolsLabel}\n >\n {this.responsiveMode === 'mobile' ? this.renderMobile() : this.renderDesktop()}\n </Host>\n );\n }\n}\n",
|
|
447
|
+
"type": "registry:ui"
|
|
448
|
+
}
|
|
449
|
+
]
|
|
450
|
+
}
|
|
@@ -56,7 +56,11 @@ export { DsSelect } from "./ds-select.js";
|
|
|
56
56
|
export { DsShellApp } from "./ds-shell-app.js";
|
|
57
57
|
export { DsShellGradientPicker } from "./ds-shell-gradient-picker.js";
|
|
58
58
|
export { DsShellGradientSwatch } from "./ds-shell-gradient-swatch.js";
|
|
59
|
+
export { DsShellMobileBar } from "./ds-shell-mobile-bar.js";
|
|
60
|
+
export { DsShellMobileNav } from "./ds-shell-mobile-nav.js";
|
|
61
|
+
export { DsShellMobileSectionNav } from "./ds-shell-mobile-section-nav.js";
|
|
59
62
|
export { DsShellPage } from "./ds-shell-page.js";
|
|
63
|
+
export { DsShellTools } from "./ds-shell-tools.js";
|
|
60
64
|
export { DsSkeleton } from "./ds-skeleton.js";
|
|
61
65
|
export { DsSlider } from "./ds-slider.js";
|
|
62
66
|
export { DsSwatchPicker } from "./ds-swatch-picker.js";
|
package/dist/react/components.js
CHANGED
|
@@ -57,7 +57,11 @@ export { DsSelect } from "./ds-select.js";
|
|
|
57
57
|
export { DsShellApp } from "./ds-shell-app.js";
|
|
58
58
|
export { DsShellGradientPicker } from "./ds-shell-gradient-picker.js";
|
|
59
59
|
export { DsShellGradientSwatch } from "./ds-shell-gradient-swatch.js";
|
|
60
|
+
export { DsShellMobileBar } from "./ds-shell-mobile-bar.js";
|
|
61
|
+
export { DsShellMobileNav } from "./ds-shell-mobile-nav.js";
|
|
62
|
+
export { DsShellMobileSectionNav } from "./ds-shell-mobile-section-nav.js";
|
|
60
63
|
export { DsShellPage } from "./ds-shell-page.js";
|
|
64
|
+
export { DsShellTools } from "./ds-shell-tools.js";
|
|
61
65
|
export { DsSkeleton } from "./ds-skeleton.js";
|
|
62
66
|
export { DsSlider } from "./ds-slider.js";
|
|
63
67
|
export { DsSwatchPicker } from "./ds-swatch-picker.js";
|
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
* This file was automatically generated by the Stencil React Output Target.
|
|
3
3
|
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
4
|
*/
|
|
5
|
-
import type { StencilReactComponent } from '@stencil/react-output-target/runtime';
|
|
5
|
+
import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
|
|
6
|
+
import { type DsShellAppCustomEvent, type ShellResponsiveMode } from "@ds-mo/ui";
|
|
6
7
|
import type { Components } from "@ds-mo/ui/dist/components";
|
|
7
8
|
import { DsShellApp as DsShellAppElement } from "@ds-mo/ui/dist/components/ds-shell-app.js";
|
|
8
|
-
export type DsShellAppEvents =
|
|
9
|
+
export type DsShellAppEvents = {
|
|
10
|
+
onDsResponsiveModeChange: EventName<DsShellAppCustomEvent<{
|
|
11
|
+
mode: ShellResponsiveMode;
|
|
12
|
+
}>>;
|
|
13
|
+
};
|
|
9
14
|
export declare const DsShellApp: StencilReactComponent<DsShellAppElement, DsShellAppEvents, Components.DsShellApp>;
|
|
@@ -7,6 +7,6 @@ export const DsShellApp = /*@__PURE__*/ createComponent({
|
|
|
7
7
|
elementClass: DsShellAppElement,
|
|
8
8
|
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
|
|
9
9
|
react: React,
|
|
10
|
-
events: {},
|
|
10
|
+
events: { onDsResponsiveModeChange: 'dsResponsiveModeChange' },
|
|
11
11
|
defineCustomElement: defineDsShellApp
|
|
12
12
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by the Stencil React Output Target.
|
|
3
|
+
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
|
+
*/
|
|
5
|
+
import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
|
|
6
|
+
import { type DsShellMobileBarCustomEvent, type ShellMobileBarDestinationDetail } from "@ds-mo/ui";
|
|
7
|
+
import type { Components } from "@ds-mo/ui/dist/components";
|
|
8
|
+
import { DsShellMobileBar as DsShellMobileBarElement } from "@ds-mo/ui/dist/components/ds-shell-mobile-bar.js";
|
|
9
|
+
export type DsShellMobileBarEvents = {
|
|
10
|
+
onDsNavigationToggle: EventName<DsShellMobileBarCustomEvent<boolean>>;
|
|
11
|
+
onDsDestinationChange: EventName<DsShellMobileBarCustomEvent<ShellMobileBarDestinationDetail>>;
|
|
12
|
+
};
|
|
13
|
+
export declare const DsShellMobileBar: StencilReactComponent<DsShellMobileBarElement, DsShellMobileBarEvents, Components.DsShellMobileBar>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createComponent } from '@stencil/react-output-target/runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { DsShellMobileBar as DsShellMobileBarElement, defineCustomElement as defineDsShellMobileBar } from "@ds-mo/ui/dist/components/ds-shell-mobile-bar.js";
|
|
5
|
+
export const DsShellMobileBar = /*@__PURE__*/ createComponent({
|
|
6
|
+
tagName: 'ds-shell-mobile-bar',
|
|
7
|
+
elementClass: DsShellMobileBarElement,
|
|
8
|
+
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
|
|
9
|
+
react: React,
|
|
10
|
+
events: {
|
|
11
|
+
onDsNavigationToggle: 'dsNavigationToggle',
|
|
12
|
+
onDsDestinationChange: 'dsDestinationChange'
|
|
13
|
+
},
|
|
14
|
+
defineCustomElement: defineDsShellMobileBar
|
|
15
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by the Stencil React Output Target.
|
|
3
|
+
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
|
|
4
|
+
*/
|
|
5
|
+
import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
|
|
6
|
+
import { type DsShellMobileNavCustomEvent, type NavChromeStyle, type ShellMobileNavAuxiliaryDetail } from "@ds-mo/ui";
|
|
7
|
+
import type { Components } from "@ds-mo/ui/dist/components";
|
|
8
|
+
import { DsShellMobileNav as DsShellMobileNavElement } from "@ds-mo/ui/dist/components/ds-shell-mobile-nav.js";
|
|
9
|
+
export type DsShellMobileNavEvents = {
|
|
10
|
+
onDsAreaSelect: EventName<DsShellMobileNavCustomEvent<string>>;
|
|
11
|
+
onDsBrowseContextChange: EventName<DsShellMobileNavCustomEvent<NavChromeStyle>>;
|
|
12
|
+
onDsAuxiliarySelect: EventName<DsShellMobileNavCustomEvent<ShellMobileNavAuxiliaryDetail>>;
|
|
13
|
+
onDsClose: EventName<DsShellMobileNavCustomEvent<void>>;
|
|
14
|
+
};
|
|
15
|
+
export declare const DsShellMobileNav: StencilReactComponent<DsShellMobileNavElement, DsShellMobileNavEvents, Components.DsShellMobileNav>;
|