@kerfjs/ui 5.0.0-beta.107 → 5.0.0-beta.108

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.
Files changed (118) hide show
  1. package/ai/component-catalog.json +24 -12
  2. package/ai/component-composition.json +8 -2
  3. package/ai/components/button.md +5 -5
  4. package/ai/components/chip.md +1 -0
  5. package/ai/components/foundation.md +1 -1
  6. package/ai/components/list.md +1 -1
  7. package/ai/components/segmented-control.md +1 -0
  8. package/ai/components/surface-scaffold.md +1 -0
  9. package/ai/components/text-field.md +3 -1
  10. package/ai/components/toolbar-control-group.md +1 -0
  11. package/ai/components/toolbar.md +1 -1
  12. package/ai/public-api-signatures-v1.md +64 -13
  13. package/ai/skill.md +12 -6
  14. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  15. package/dist/button.d.ts +3 -3
  16. package/dist/button.js +1 -1
  17. package/dist/catalog.js +4 -4
  18. package/dist/chip.d.ts +20 -2
  19. package/dist/chip.js +2 -1
  20. package/dist/{chunk-23PPPNH6.js → chunk-4OV272LF.js} +2 -2
  21. package/dist/{chunk-23PPPNH6.js.map → chunk-4OV272LF.js.map} +1 -1
  22. package/dist/{chunk-2PXZBFEC.js → chunk-5J6Z4BWY.js} +1 -1
  23. package/dist/{chunk-2PXZBFEC.js.map → chunk-5J6Z4BWY.js.map} +1 -1
  24. package/dist/{chunk-G4DRH4A5.js → chunk-6CDILXF4.js} +3 -1
  25. package/dist/chunk-6CDILXF4.js.map +1 -0
  26. package/dist/{chunk-NLMEDZRM.js → chunk-CPSGUGAY.js} +5 -5
  27. package/dist/{chunk-NLMEDZRM.js.map → chunk-CPSGUGAY.js.map} +1 -1
  28. package/dist/{chunk-TXRKCGT3.js → chunk-KPINJHIC.js} +1 -1
  29. package/dist/chunk-KPINJHIC.js.map +1 -0
  30. package/dist/{chunk-N7MBGONH.js → chunk-LMHN2TJL.js} +22 -2
  31. package/dist/chunk-LMHN2TJL.js.map +1 -0
  32. package/dist/{chunk-NS2TBYM4.js → chunk-LZUUUHNH.js} +7 -3
  33. package/dist/chunk-LZUUUHNH.js.map +1 -0
  34. package/dist/{chunk-OY2MXIBB.js → chunk-NB6POCFH.js} +3 -1
  35. package/dist/chunk-NB6POCFH.js.map +1 -0
  36. package/dist/{chunk-AZ3WT77F.js → chunk-P7EJ4CAD.js} +2 -2
  37. package/dist/{chunk-AZ3WT77F.js.map → chunk-P7EJ4CAD.js.map} +1 -1
  38. package/dist/{chunk-Z4DS77U2.js → chunk-SOFPUW3O.js} +4 -4
  39. package/dist/{chunk-Z4DS77U2.js.map → chunk-SOFPUW3O.js.map} +1 -1
  40. package/dist/{chunk-QLA25V2K.js → chunk-WPNIKZMJ.js} +15 -1
  41. package/dist/chunk-WPNIKZMJ.js.map +1 -0
  42. package/dist/{chunk-DNWWF6UN.js → chunk-WSEJ2FDE.js} +4 -4
  43. package/dist/{chunk-DNWWF6UN.js.map → chunk-WSEJ2FDE.js.map} +1 -1
  44. package/dist/{chunk-WU57BYYM.js → chunk-YVZCKXR3.js} +8 -2
  45. package/dist/chunk-YVZCKXR3.js.map +1 -0
  46. package/dist/{chunk-CMLPFIC5.js → chunk-ZN7KUMPY.js} +3 -1
  47. package/dist/chunk-ZN7KUMPY.js.map +1 -0
  48. package/dist/collapsible-panel.js +2 -2
  49. package/dist/index.js +9 -9
  50. package/dist/list-detail-dialog.js +4 -4
  51. package/dist/list.d.ts +7 -1
  52. package/dist/list.js +1 -1
  53. package/dist/message-composer.js +1 -1
  54. package/dist/nav-stack.js +1 -1
  55. package/dist/segmented-control.d.ts +3 -1
  56. package/dist/segmented-control.js +1 -1
  57. package/dist/split-view.js +1 -1
  58. package/dist/styles/button.css +28 -2
  59. package/dist/styles/components/actions/button/button.css +28 -2
  60. package/dist/styles/components/actions/toolbar/toolbar.css +9 -0
  61. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +29 -1
  62. package/dist/styles/components/collections/framed-list/framed-list.css +2 -0
  63. package/dist/styles/components/layout/pane/pane.css +15 -0
  64. package/dist/styles/components/navigation/nav-stack/nav-stack.css +13 -0
  65. package/dist/styles/components/navigation/tab-bar/tab-bar.css +6 -0
  66. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +16 -0
  67. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +2 -0
  68. package/dist/styles/foundation.css +63 -19
  69. package/dist/styles/framed-list.css +2 -0
  70. package/dist/styles/nav-stack.css +13 -0
  71. package/dist/styles/pane.css +15 -0
  72. package/dist/styles/surface-scaffold.css +2 -0
  73. package/dist/styles/tab-bar.css +6 -0
  74. package/dist/styles/tab-navigator.css +16 -0
  75. package/dist/styles/toolbar-control-group.css +29 -1
  76. package/dist/styles/toolbar.css +9 -0
  77. package/dist/styles/webawesome.css +11 -3
  78. package/dist/surface-scaffold.d.ts +9 -1
  79. package/dist/surface-scaffold.js +1 -1
  80. package/dist/text-field.d.ts +7 -1
  81. package/dist/text-field.js +1 -1
  82. package/dist/toolbar-control-group.d.ts +8 -2
  83. package/dist/toolbar-control-group.js +1 -1
  84. package/dist/toolbar.d.ts +6 -1
  85. package/dist/toolbar.js +1 -1
  86. package/dist/wire-catalog.js +1 -1
  87. package/dist/wire-workbench.js +1 -1
  88. package/dist/workbench-dialog.js +3 -3
  89. package/dist/workbench.js +1 -1
  90. package/docs/accessibility.md +25 -9
  91. package/docs/component-contract.md +19 -6
  92. package/docs/component-selection.md +38 -12
  93. package/docs/design/templates/button/tones-dark.svg +1 -1
  94. package/docs/design/templates/button/tones.svg +1 -1
  95. package/docs/design/templates/button-dark.svg +1 -1
  96. package/docs/design/templates/button.svg +1 -1
  97. package/docs/design/templates/split-button/states-dark.svg +1 -1
  98. package/docs/design/templates/split-button/states.svg +1 -1
  99. package/docs/design/templates/split-button-dark.svg +1 -1
  100. package/docs/design/templates/split-button.svg +1 -1
  101. package/docs/design/templates/text-field/number-dark.svg +1 -0
  102. package/docs/design/templates/text-field/number.svg +1 -0
  103. package/docs/design/templates/text-field-dark.svg +1 -1
  104. package/docs/design/templates/text-field.svg +1 -1
  105. package/docs/layout.md +16 -5
  106. package/docs/webawesome-migration.md +2 -0
  107. package/docs/webawesome-theme.md +8 -2
  108. package/docs/workbench.md +7 -1
  109. package/llms.txt +17 -5
  110. package/package.json +1 -1
  111. package/dist/chunk-CMLPFIC5.js.map +0 -1
  112. package/dist/chunk-G4DRH4A5.js.map +0 -1
  113. package/dist/chunk-N7MBGONH.js.map +0 -1
  114. package/dist/chunk-NS2TBYM4.js.map +0 -1
  115. package/dist/chunk-OY2MXIBB.js.map +0 -1
  116. package/dist/chunk-QLA25V2K.js.map +0 -1
  117. package/dist/chunk-TXRKCGT3.js.map +0 -1
  118. package/dist/chunk-WU57BYYM.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/layout/split-view/split-view.tsx"],"names":[],"mappings":"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","file":"chunk-AZ3WT77F.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { pct, remify } from '../../../shared/styles/css-values.js';\nimport {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from '../../navigation/nav-stack/nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from '../resizable-region/resizable-region.js';\n\n/**\n * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /\n * `max` limits, plus the region configuration that forwards unchanged\n * (`separator`, `handleIcon`, `contentOverflow`, and collapse:\n * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,\n * `restorePosition`). Omitted options keep the region's defaults.\n */\nexport interface SplitViewResizable extends Pick<\n ResizableRegionProps,\n | 'separator'\n | 'handleIcon'\n | 'contentOverflow'\n | 'collapsed'\n | 'transitioning'\n | 'collapseMotion'\n | 'restoreControl'\n | 'restorePosition'\n> {\n size: number;\n min: number;\n max: number;\n}\n\n/**\n * One compact view's top- and bottom-toolbar content and pinned footer (see\n * `NavStackView`).\n */\nexport type SplitViewCompactViewToolbars = Pick<\n NavStackView,\n 'toolbar' | 'bottomToolbar' | 'footer'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, chrome dividers, and chrome and\n * bottom-toolbar presentations forward to the stack, and `list` / `detail`\n * give each view its own toolbar groups.\n */\nexport interface SplitViewCompactStack extends Pick<\n NavStackProps,\n | 'toolbarConfig'\n | 'backIcon'\n | 'backText'\n | 'hideToolbar'\n | 'bottomToolbar'\n | 'chromeDividers'\n | 'chromePresentation'\n | 'bottomToolbarPresentation'\n> {\n /** Toolbar content for the list (root) view. */\n list?: SplitViewCompactViewToolbars;\n /** Toolbar content for the pushed detail view. */\n detail?: SplitViewCompactViewToolbars;\n}\n\n/**\n * The fixed list column's width: a size in CSS pixels, or that size capped\n * at a fraction of the SplitView's own width so a narrow container (a\n * dialog, a small window) always leaves the detail in view.\n */\nexport type SplitViewListWidth =\n | number\n | {\n /** Preferred width in CSS pixels. */\n size: number;\n /** Largest share of the SplitView's width, greater than 0 and at most 1. */\n maxFraction?: number;\n };\n\n/** The list-width custom property value for a fixed split. */\nfunction listWidthValue(listWidth: SplitViewListWidth): string {\n const { size, maxFraction } =\n typeof listWidth === 'number'\n ? { size: listWidth, maxFraction: undefined }\n : listWidth;\n if (!Number.isFinite(size) || size <= 0)\n throw new RangeError(\n 'SplitView listWidth size must be a positive number of pixels',\n );\n if (\n maxFraction !== undefined &&\n (!Number.isFinite(maxFraction) || maxFraction <= 0 || maxFraction > 1)\n )\n throw new RangeError(\n 'SplitView listWidth maxFraction must be greater than 0 and at most 1',\n );\n const preferred = remify(size);\n return maxFraction === undefined\n ? preferred\n : `min(${preferred}, ${pct(maxFraction * 100)})`;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: KerfUiContent;\n /** The detail (secondary) pane. */\n detail: KerfUiContent;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** Compact NavStack configuration and per-view toolbars. */\n compactStack?: SplitViewCompactStack;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n /**\n * The fixed split's list column width (default 320px). A number is CSS\n * pixels; `{ size, maxFraction }` caps it at that share of the SplitView's\n * width. A resizable split sizes its list with `resizable` instead.\n */\n listWidth?: SplitViewListWidth;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n compactStack = {},\n resizable,\n listWidth,\n className = '',\n slot,\n}: SplitViewProps) {\n if (listWidth !== undefined && resizable)\n throw new RangeError(\n 'SplitView listWidth applies to a fixed split; size a resizable list with resizable.size, min, and max',\n );\n const listWidthStyle =\n listWidth === undefined\n ? undefined\n : `--kui-split-view-list-width:${listWidthValue(listWidth)}`;\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n toolbar: { ...compactStack.list?.toolbar, title: listTitle },\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n toolbar: { ...compactStack.detail?.toolbar, title: detailTitle },\n content: detail,\n },\n ]\n : [listView];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n slot={slot}\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n backIcon={compactStack.backIcon}\n backText={compactStack.backText}\n toolbarConfig={compactStack.toolbarConfig}\n hideToolbar={compactStack.hideToolbar}\n bottomToolbar={compactStack.bottomToolbar}\n chromeDividers={compactStack.chromeDividers}\n chromePresentation={compactStack.chromePresentation}\n bottomToolbarPresentation={compactStack.bottomToolbarPresentation}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n separator={resizable.separator}\n handleIcon={resizable.handleIcon}\n contentOverflow={resizable.contentOverflow}\n collapsed={resizable.collapsed}\n transitioning={resizable.transitioning}\n collapseMotion={resizable.collapseMotion}\n restoreControl={resizable.restoreControl}\n restorePosition={resizable.restorePosition}\n >\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"true\"\n >\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"false\"\n >\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n style={listWidthStyle}\n slot={slot}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/layout/split-view/split-view.tsx"],"names":[],"mappings":"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","file":"chunk-P7EJ4CAD.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { pct, remify } from '../../../shared/styles/css-values.js';\nimport {\n NavStack,\n type NavStackProps,\n type NavStackView,\n} from '../../navigation/nav-stack/nav-stack.js';\nimport {\n ResizableRegion,\n type ResizableRegionProps,\n} from '../resizable-region/resizable-region.js';\n\n/**\n * The roomy list pane's `ResizableRegion`: its committed `size` and `min` /\n * `max` limits, plus the region configuration that forwards unchanged\n * (`separator`, `handleIcon`, `contentOverflow`, and collapse:\n * `collapsed`, `transitioning`, `collapseMotion`, `restoreControl`,\n * `restorePosition`). Omitted options keep the region's defaults.\n */\nexport interface SplitViewResizable extends Pick<\n ResizableRegionProps,\n | 'separator'\n | 'handleIcon'\n | 'contentOverflow'\n | 'collapsed'\n | 'transitioning'\n | 'collapseMotion'\n | 'restoreControl'\n | 'restorePosition'\n> {\n size: number;\n min: number;\n max: number;\n}\n\n/**\n * One compact view's top- and bottom-toolbar content and pinned footer (see\n * `NavStackView`).\n */\nexport type SplitViewCompactViewToolbars = Pick<\n NavStackView,\n 'toolbar' | 'bottomToolbar' | 'footer'\n>;\n\n/**\n * The compact `NavStack`'s configuration: its toolbar configuration, back\n * control, persistent bottom toolbar, chrome dividers, and chrome and\n * bottom-toolbar presentations forward to the stack, and `list` / `detail`\n * give each view its own toolbar groups.\n */\nexport interface SplitViewCompactStack extends Pick<\n NavStackProps,\n | 'toolbarConfig'\n | 'backIcon'\n | 'backText'\n | 'hideToolbar'\n | 'bottomToolbar'\n | 'chromeDividers'\n | 'chromePresentation'\n | 'bottomToolbarPresentation'\n> {\n /** Toolbar content for the list (root) view. */\n list?: SplitViewCompactViewToolbars;\n /** Toolbar content for the pushed detail view. */\n detail?: SplitViewCompactViewToolbars;\n}\n\n/**\n * The fixed list column's width: a size in CSS pixels, or that size capped\n * at a fraction of the SplitView's own width so a narrow container (a\n * dialog, a small window) always leaves the detail in view.\n */\nexport type SplitViewListWidth =\n | number\n | {\n /** Preferred width in CSS pixels. */\n size: number;\n /** Largest share of the SplitView's width, greater than 0 and at most 1. */\n maxFraction?: number;\n };\n\n/** The list-width custom property value for a fixed split. */\nfunction listWidthValue(listWidth: SplitViewListWidth): string {\n const { size, maxFraction } =\n typeof listWidth === 'number'\n ? { size: listWidth, maxFraction: undefined }\n : listWidth;\n if (!Number.isFinite(size) || size <= 0)\n throw new RangeError(\n 'SplitView listWidth size must be a positive number of pixels',\n );\n if (\n maxFraction !== undefined &&\n (!Number.isFinite(maxFraction) || maxFraction <= 0 || maxFraction > 1)\n )\n throw new RangeError(\n 'SplitView listWidth maxFraction must be greater than 0 and at most 1',\n );\n const preferred = remify(size);\n return maxFraction === undefined\n ? preferred\n : `min(${preferred}, ${pct(maxFraction * 100)})`;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: KerfUiContent;\n /** The detail (secondary) pane. */\n detail: KerfUiContent;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** Compact NavStack configuration and per-view toolbars. */\n compactStack?: SplitViewCompactStack;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n /**\n * The fixed split's list column width (default 320px). A number is CSS\n * pixels; `{ size, maxFraction }` caps it at that share of the SplitView's\n * width. A resizable split sizes its list with `resizable` instead.\n */\n listWidth?: SplitViewListWidth;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n compactStack = {},\n resizable,\n listWidth,\n className = '',\n slot,\n}: SplitViewProps) {\n if (listWidth !== undefined && resizable)\n throw new RangeError(\n 'SplitView listWidth applies to a fixed split; size a resizable list with resizable.size, min, and max',\n );\n const listWidthStyle =\n listWidth === undefined\n ? undefined\n : `--kui-split-view-list-width:${listWidthValue(listWidth)}`;\n if (compact) {\n const listView: NavStackView = {\n ...compactStack.list,\n key: 'list',\n toolbar: { ...compactStack.list?.toolbar, title: listTitle },\n content: list,\n };\n const views: NavStackView[] = detailActive\n ? [\n listView,\n {\n ...compactStack.detail,\n key: 'detail',\n toolbar: { ...compactStack.detail?.toolbar, title: detailTitle },\n content: detail,\n },\n ]\n : [listView];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n slot={slot}\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n backIcon={compactStack.backIcon}\n backText={compactStack.backText}\n toolbarConfig={compactStack.toolbarConfig}\n hideToolbar={compactStack.hideToolbar}\n bottomToolbar={compactStack.bottomToolbar}\n chromeDividers={compactStack.chromeDividers}\n chromePresentation={compactStack.chromePresentation}\n bottomToolbarPresentation={compactStack.bottomToolbarPresentation}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n separator={resizable.separator}\n handleIcon={resizable.handleIcon}\n contentOverflow={resizable.contentOverflow}\n collapsed={resizable.collapsed}\n transitioning={resizable.transitioning}\n collapseMotion={resizable.collapseMotion}\n restoreControl={resizable.restoreControl}\n restorePosition={resizable.restorePosition}\n >\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"true\"\n >\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div\n class=\"kui-split-view__list kui-pane\"\n data-split-list\n data-resizable=\"false\"\n >\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n style={listWidthStyle}\n slot={slot}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  import { ToolbarText } from './chunk-EKHDLBRP.js';
2
2
  import { paneConfigProps } from './chunk-CTQUDCY5.js';
3
- import { ToolbarControlGroup } from './chunk-2PXZBFEC.js';
4
- import { Toolbar } from './chunk-CMLPFIC5.js';
3
+ import { ToolbarControlGroup } from './chunk-5J6Z4BWY.js';
4
+ import { Toolbar } from './chunk-ZN7KUMPY.js';
5
5
  import { Pane } from './chunk-HQZG3OFL.js';
6
6
  import { surfaceTintAttributes, joinStyles, scrollEdgeAttributes } from './chunk-SQ5DH66U.js';
7
- import { List } from './chunk-OY2MXIBB.js';
7
+ import { List } from './chunk-NB6POCFH.js';
8
8
  import { LucideIcon } from './chunk-HJXVVFBT.js';
9
9
  import { ChevronLeft } from 'lucide';
10
10
  import { jsx, jsxs, Fragment } from 'kerfjs/jsx-runtime';
@@ -193,4 +193,4 @@ function NavStack({
193
193
 
194
194
  export { NavStack };
195
195
 
196
- //# sourceMappingURL=chunk-Z4DS77U2.js.map
196
+ //# sourceMappingURL=chunk-SOFPUW3O.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/navigation/nav-stack/nav-stack.tsx"],"names":[],"mappings":"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","file":"chunk-Z4DS77U2.js","sourcesContent":["import { ChevronLeft } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport {\n type ScrollEdge,\n scrollEdgeAttributes,\n} from '../../../shared/layout/scroll-edge.js';\nimport type { NavPane } from '../../../shared/panels/nav-pane.js';\nimport type { PanelBottomToolbar } from '../../../shared/panels/panel-toolbar.js';\nimport type { CssColor } from '../../../shared/styles/css-values.js';\nimport {\n joinStyles,\n type SurfaceTint,\n surfaceTintAttributes,\n} from '../../../shared/styles/surface-tint.js';\nimport { Toolbar, type ToolbarConfig } from '../../actions/toolbar/toolbar.js';\nimport { ToolbarControlGroup } from '../../actions/toolbar-control-group/toolbar-control-group.js';\nimport {\n type HeadingLevel,\n ToolbarText,\n type ToolbarTextSize,\n} from '../../actions/toolbar-text/toolbar-text.js';\nimport { List, type ListConfig } from '../../collections/list/list.js';\nimport { paneConfigProps } from '../../layout/pane/internal/pane-config-props.js';\nimport { Pane } from '../../layout/pane/pane.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\n\n/**\n * One entry in a {@link NavStack}. The app owns the stack as an array (usually a\n * signal); `NavStack` renders it and `wireNavStack` animates the transitions.\n */\nexport interface NavStackView extends NavPane<\n NavStackViewToolbar,\n PanelBottomToolbar\n> {\n /** Stable identity for keyed reconcile and transition direction. */\n key: string;\n}\n\n/** Per-view top toolbar. The stack supplies its back control before `leading`. */\nexport interface NavStackViewToolbar extends NavStackToolbarConfig {\n title?: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n}\n\n/** A view's structured bottom toolbar; it cross-fades on navigation. */\nexport type NavStackViewBottomToolbar = PanelBottomToolbar;\n\n/**\n * The top toolbar's configuration. Its `ToolbarConfig` forwards to the real\n * `Toolbar` the stack renders; by default that toolbar draws no divider and\n * claims the top and side safe-area edges the stack still touches.\n */\nexport interface NavStackToolbarConfig extends ToolbarConfig {\n /** Accessible name of the top toolbar (default: none). */\n label?: string;\n /**\n * Size of the view title's `ToolbarText`. Default `xlarge` at the root,\n * where the title is the page heading, and `large` once a back control\n * shares the bar.\n */\n titleSize?: ToolbarTextSize;\n /** Expose the view title as a heading at this level (default: a plain span). */\n headingLevel?: HeadingLevel;\n}\n\n/**\n * How a {@link NavStack}'s top chrome relates to the active view: `docked`\n * above it, or `overlay` laid over its top edge on the translucent chrome\n * material, so the view's content scrolls visibly beneath it.\n * `clear` lays it over\n * the same edge fully transparent, for chrome over imagery: legibility comes\n * from glass control groups or a scrim, and with `scrollEdge=\"material\"` the\n * chrome material fades in once content scrolls beneath it.\n */\nexport type NavStackChromePresentation = 'docked' | 'overlay' | 'clear';\n\n/**\n * How a {@link NavStack}'s bottom toolbar relates to the active view:\n * `docked` below it, or `overlay` laid over its bottom edge on the\n * translucent chrome material, so the view's content scrolls visibly beneath\n * it.\n * `clear` lays it over\n * the same edge fully transparent, for chrome over imagery: legibility comes\n * from glass control groups or a scrim, and with `scrollEdge=\"material\"` the\n * chrome material fades in once content scrolls beneath\n * it, until the view scrolls to its end.\n */\nexport type NavStackBottomToolbarPresentation = 'docked' | 'overlay' | 'clear';\n\nexport interface NavStackProps {\n id: string;\n /** Accessible name for the stack region. */\n label: string;\n /** The stack, root first; the last entry is the active top view. */\n views: NavStackView[];\n /** Accessible label for the icon-only back control (default \"Back\"). */\n backLabel?: string;\n /** The back control's icon (default a chevron-left `LucideIcon`). */\n backIcon?: KerfUiContent;\n /**\n * Visible text beside the back icon, such as the previous view's title\n * (default: icon only). When set, the text names the control and\n * `backLabel` is not used.\n */\n backText?: string;\n /** The top toolbar's configuration, forwarded to its `Toolbar`. */\n toolbarConfig?: NavStackToolbarConfig;\n /** Persistent last group in every view's top toolbar, supplied by a hosting panel. */\n panelToggle?: KerfUiContent;\n /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */\n hideToolbar?: boolean;\n /** Optional persistent bottom toolbar used when the active view does not provide one. */\n bottomToolbar?: NavStackViewBottomToolbar;\n /**\n * Stack chrome separator. `auto` (default) draws both available edges\n * against a sunken active Pane and otherwise follows `chromeDividers`;\n * `hidden` suppresses the stack-owned edges.\n */\n separator?: 'auto' | 'hidden';\n /**\n * The line under the top chrome and over the bottom toolbar, where they\n * meet the active view. `scroll` (default) shows the chrome's line only\n * while the view's content is scrolled beneath it, and the bottom\n * toolbar's only while more content lies below — never when the content\n * fits — once `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is\n * wired above the stack; unwired, neither shows. `always` shows both\n * without the wiring; `none` neither, even when wired. The line is drawn\n * inside the chrome, so no state moves the chrome or the content. A\n * A sunken active Pane still draws the separator unless\n * `separator=\"hidden\"`. A `toolbarConfig.dividerSides` edge is the Toolbar's\n * own and is unaffected.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n /**\n * `docked` (default) gives the top chrome its own band above the active\n * view. `overlay` lays the chrome over the view's top edge on the\n * translucent chrome material (`--kui-chrome-material`, opaque under\n * `prefers-reduced-transparency`, `prefers-contrast: more`, forced colors,\n * or without `backdrop-filter`), so content scrolls visibly beneath it, as\n * an iOS navigation bar does. `wireNavStack` measures the live chrome and\n * hands its height (top safe area included) to the viewport as the\n * block-start `--kui-edge-inset-*` context, so every view clears it with no\n * prop: a plain view, a sole `Pane`'s content (or header), and a nested\n * layout all pad and `scroll-padding` by it, so the first item, and anything\n * focused or scrolled into view, rests clear of the bar. Until then, and\n * with `hideToolbar`, the chrome stays docked. An untoned `ToolbarText` in\n * the chrome lifts its title and description to AA over the content passing\n * beneath it; keep any other quiet copy in the view. With `clear`, the\n * stack's own back control sits in a glass control group\n * (`material=\"glass\"`), so it stays legible over imagery.\n */\n chromePresentation?: NavStackChromePresentation;\n /**\n * `docked` (default) gives the bottom toolbar its own band below the\n * active view. `overlay` lays it over the view's bottom edge on the\n * translucent chrome material (opaque under the same preferences as\n * `chromePresentation`), so content scrolls visibly beneath it, as under\n * an iOS toolbar. `wireNavStack` measures the live bottom toolbar (never a\n * cross-fading copy) and hands its height (bottom safe area included) to\n * the viewport as the block-end `--kui-edge-inset-*` context, so a plain\n * view, a sole `Pane`'s content (or footer), and a nested layout rest their\n * last item, and anything focused or scrolled into view, clear of it. Until\n * then, and while no bottom toolbar is shown, it stays docked. Independent\n * of `chromePresentation`, which governs only the top chrome. An untoned\n * `ToolbarText` in the toolbar lifts to AA over the content beneath it.\n */\n bottomToolbarPresentation?: NavStackBottomToolbarPresentation;\n /**\n * For `clear` chrome or bottom toolbar, `material` fades the chrome\n * material in while the active view's content lies beneath it (default\n * `none`).\n */\n scrollEdge?: ScrollEdge;\n /**\n * The scroll distance, in CSS pixels, over which the scroll edge fades in\n * (default 60).\n */\n scrollEdgeDistance?: number;\n /**\n * Paint the stack, its docked chrome and bottom toolbar, and every view in\n * an app-chosen color (a `@kerfjs/ui/css-values` color builder) instead of\n * the surface. Overlay chrome keeps the chrome material; one view's own\n * color goes in its `pane: { background }`. Forced colors paint `Canvas`.\n */\n background?: CssColor;\n /**\n * A scoped tint (`{ color, scheme }`) for the stack, its chrome, bottom toolbar, and views: its surfaces and every\n * descendant re-derive their surface and text tokens from the app's color\n * in the declared scheme, with lightness clamped to keep text at WCAG AA.\n */\n tint?: SurfaceTint;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nconst DEFAULT_SAFE_AREA_EDGES = [\n 'block-start',\n 'inline-start',\n 'inline-end',\n] as const;\n\nconst DEFAULT_BOTTOM_SAFE_AREA_EDGES = [\n 'block-end',\n 'inline-start',\n 'inline-end',\n] as const;\n\nfunction chromeList(content: KerfUiContent, config?: ListConfig) {\n return (\n <List\n dividerSides={config?.dividerSides}\n gap={config?.gap}\n hAlign={config?.hAlign}\n vAlign={config?.vAlign}\n textInsets={config?.textInsets}\n controlInsets={config?.controlInsets}\n >\n {content}\n </List>\n );\n}\n\n/**\n * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last\n * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and\n * cross-fades the chrome across a change. Its top chrome is a real `Toolbar`: the\n * back control and title lead, the active view's `toolbar` fills the zones,\n * and `toolbarConfig` supplies defaults. A single-pane\n * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.\n */\nexport function NavStack({\n id,\n label,\n views,\n backLabel = 'Back',\n backIcon,\n backText,\n toolbarConfig = {},\n panelToggle,\n hideToolbar = false,\n bottomToolbar,\n separator = 'auto',\n chromeDividers = 'scroll',\n chromePresentation = 'docked',\n bottomToolbarPresentation = 'docked',\n scrollEdge = 'none',\n scrollEdgeDistance,\n background,\n tint,\n className = '',\n slot,\n}: NavStackProps) {\n const tinted = surfaceTintAttributes(tint);\n const topIndex = views.length - 1;\n const top = views[topIndex];\n const topToolbar = top?.toolbar;\n const bottom = top?.bottomToolbar ?? bottomToolbar;\n const canPop = views.length > 1;\n const topDensity = topToolbar?.density ?? toolbarConfig.density;\n // With a back control, the title centers on the bar (iOS-style) unless the\n // view owns the center zone; at the root it leads and fills, left-aligned.\n const centerTitle = canPop && topToolbar?.center === undefined;\n const title = (\n <ToolbarText\n text={topToolbar?.title ?? ''}\n size={\n topToolbar?.titleSize ??\n toolbarConfig.titleSize ??\n (canPop ? 'large' : 'xlarge')\n }\n headingLevel={topToolbar?.headingLevel ?? toolbarConfig.headingLevel}\n fill={!centerTitle}\n />\n );\n return (\n <section\n class={`kui-nav-stack ${tinted.className} ${className}`\n .replace(/\\s+/g, ' ')\n .trim()}\n id={id}\n data-component=\"nav-stack\"\n data-nav-stack-id={id}\n data-depth={String(views.length)}\n data-separator={separator}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n data-chrome-presentation={\n chromePresentation !== 'docked' && !hideToolbar ? 'overlay' : undefined\n }\n data-chrome-material={\n chromePresentation === 'clear' && !hideToolbar ? 'clear' : undefined\n }\n data-bottom-toolbar-presentation={\n bottomToolbarPresentation !== 'docked' ? 'overlay' : undefined\n }\n data-bottom-toolbar-material={\n bottomToolbarPresentation === 'clear' ? 'clear' : undefined\n }\n {...scrollEdgeAttributes(\n scrollEdge,\n scrollEdgeDistance,\n (chromePresentation === 'clear' && !hideToolbar) ||\n bottomToolbarPresentation === 'clear',\n )}\n data-background={background === undefined ? undefined : ''}\n data-kui-tint={tinted['data-kui-tint']}\n data-kui-tint-accent={tinted['data-kui-tint-accent']}\n style={joinStyles(\n background === undefined\n ? undefined\n : `--_kui-nav-stack-background:${background}`,\n tinted.style,\n )}\n aria-label={label}\n slot={slot}\n >\n {!hideToolbar && (\n <div class=\"kui-nav-stack__chrome\" data-nav-stack-chrome>\n <Toolbar\n label={topToolbar?.label ?? toolbarConfig.label}\n density={topDensity}\n dividerSides={\n topToolbar?.dividerSides ?? toolbarConfig.dividerSides\n }\n centerAlign={\n centerTitle\n ? 'balanced'\n : (topToolbar?.centerAlign ?? toolbarConfig.centerAlign)\n }\n responsive={topToolbar?.responsive ?? toolbarConfig.responsive}\n responsiveAt={\n topToolbar?.responsiveAt ?? toolbarConfig.responsiveAt\n }\n safeAreaEdges={\n topToolbar?.safeAreaEdges ??\n toolbarConfig.safeAreaEdges ??\n DEFAULT_SAFE_AREA_EDGES\n }\n leading={\n <>\n {canPop && (\n <ToolbarControlGroup\n content={backText ? 'mixed' : 'icon'}\n size={topDensity === 'compact' ? 'compact' : 'default'}\n material={\n chromePresentation === 'clear' ? 'glass' : undefined\n }\n single\n >\n <button\n type=\"button\"\n class=\"kui-nav-stack__back\"\n data-nav-back\n aria-label={backText ? undefined : backLabel}\n >\n {backIcon ?? (\n <LucideIcon\n icon={ChevronLeft}\n name=\"chevron-left\"\n className=\"kui-nav-stack__back-icon\"\n />\n )}\n {backText ? <span>{backText}</span> : null}\n </button>\n </ToolbarControlGroup>\n )}\n {topToolbar?.leading}\n {centerTitle ? null : title}\n </>\n }\n center={centerTitle ? title : topToolbar?.center}\n trailing={\n <>\n {topToolbar?.trailing}\n {panelToggle}\n </>\n }\n />\n </div>\n )}\n <div class=\"kui-nav-stack__viewport\" data-nav-stack-viewport>\n {views.map((view, index) => (\n <article\n class=\"kui-nav-stack__view\"\n data-key={view.key}\n data-nav-key={view.key}\n data-nav-active={String(index === topIndex)}\n aria-hidden={String(index !== topIndex)}\n >\n {view.pane ||\n view.header !== undefined ||\n view.footer !== undefined ? (\n <Pane\n {...paneConfigProps(view.pane)}\n header={\n view.header === undefined ? undefined : (\n <div data-nav-stack-header>\n {chromeList(view.header, view.headerList)}\n </div>\n )\n }\n footer={\n view.footer === undefined ? undefined : (\n <div data-nav-stack-footer>\n {chromeList(view.footer, view.footerList)}\n </div>\n )\n }\n >\n {view.content}\n </Pane>\n ) : (\n view.content\n )}\n </article>\n ))}\n </div>\n {bottom && (\n <footer class=\"kui-nav-stack__bottom\" data-nav-stack-bottom>\n <Toolbar\n position=\"footer\"\n label={bottom.label}\n density={bottom.density}\n dividerSides={bottom.dividerSides}\n centerAlign={bottom.centerAlign}\n responsive={bottom.responsive}\n responsiveAt={bottom.responsiveAt}\n safeAreaEdges={\n bottom.safeAreaEdges ?? DEFAULT_BOTTOM_SAFE_AREA_EDGES\n }\n leading={bottom.leading}\n center={bottom.center}\n trailing={bottom.trailing}\n />\n </footer>\n )}\n </section>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/navigation/nav-stack/nav-stack.tsx"],"names":[],"mappings":";;;;;;;;;;;AAuMA,IAAM,uBAAA,GAA0B;AAAA,EAC9B,aAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEA,IAAM,8BAAA,GAAiC;AAAA,EACrC,WAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,UAAA,CAAW,SAAwB,MAAA,EAAqB;AAC/D,EAAA,uBACE,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,cAAc,MAAA,EAAQ,YAAA;AAAA,MACtB,KAAK,MAAA,EAAQ,GAAA;AAAA,MACb,QAAQ,MAAA,EAAQ,MAAA;AAAA,MAChB,QAAQ,MAAA,EAAQ,MAAA;AAAA,MAChB,YAAY,MAAA,EAAQ,UAAA;AAAA,MACpB,eAAe,MAAA,EAAQ,aAAA;AAAA,MAEtB,QAAA,EAAA;AAAA;AAAA,GACH;AAEJ;AAUO,SAAS,QAAA,CAAS;AAAA,EACvB,EAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA,GAAY,MAAA;AAAA,EACZ,QAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAgB,EAAC;AAAA,EACjB,WAAA;AAAA,EACA,WAAA,GAAc,KAAA;AAAA,EACd,aAAA;AAAA,EACA,SAAA,GAAY,MAAA;AAAA,EACZ,cAAA,GAAiB,QAAA;AAAA,EACjB,kBAAA,GAAqB,QAAA;AAAA,EACrB,yBAAA,GAA4B,QAAA;AAAA,EAC5B,UAAA,GAAa,MAAA;AAAA,EACb,kBAAA;AAAA,EACA,UAAA;AAAA,EACA,IAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ;AACF,CAAA,EAAkB;AAChB,EAAA,MAAM,MAAA,GAAS,sBAAsB,IAAI,CAAA;AACzC,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,GAAS,CAAA;AAChC,EAAA,MAAM,GAAA,GAAM,MAAM,QAAQ,CAAA;AAC1B,EAAA,MAAM,aAAa,GAAA,EAAK,OAAA;AACxB,EAAA,MAAM,MAAA,GAAS,KAAK,aAAA,IAAiB,aAAA;AACrC,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,GAAS,CAAA;AAC9B,EAAA,MAAM,UAAA,GAAa,UAAA,EAAY,OAAA,IAAW,aAAA,CAAc,OAAA;AAGxD,EAAA,MAAM,WAAA,GAAc,MAAA,IAAU,UAAA,EAAY,MAAA,KAAW,MAAA;AACrD,EAAA,MAAM,KAAA,mBACJ,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,YAAY,KAAA,IAAS,EAAA;AAAA,MAC3B,MACE,UAAA,EAAY,SAAA,IACZ,aAAA,CAAc,SAAA,KACb,SAAS,OAAA,GAAU,QAAA,CAAA;AAAA,MAEtB,YAAA,EAAc,UAAA,EAAY,YAAA,IAAgB,aAAA,CAAc,YAAA;AAAA,MACxD,MAAM,CAAC;AAAA;AAAA,GACT;AAEF,EAAA,uBACE,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,cAAA,EAAiB,MAAA,CAAO,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,CAClD,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,CACnB,IAAA,EAAK;AAAA,MACR,EAAA;AAAA,MACA,gBAAA,EAAe,WAAA;AAAA,MACf,mBAAA,EAAmB,EAAA;AAAA,MACnB,YAAA,EAAY,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA;AAAA,MAC/B,gBAAA,EAAgB,SAAA;AAAA,MAChB,sBAAA,EACE,cAAA,KAAmB,QAAA,IAAY,cAAA,KAAmB,SAC9C,cAAA,GACA,MAAA;AAAA,MAEN,0BAAA,EACE,kBAAA,KAAuB,QAAA,IAAY,CAAC,cAAc,SAAA,GAAY,MAAA;AAAA,MAEhE,sBAAA,EACE,kBAAA,KAAuB,OAAA,IAAW,CAAC,cAAc,OAAA,GAAU,MAAA;AAAA,MAE7D,kCAAA,EACE,yBAAA,KAA8B,QAAA,GAAW,SAAA,GAAY,MAAA;AAAA,MAEvD,8BAAA,EACE,yBAAA,KAA8B,OAAA,GAAU,OAAA,GAAU,MAAA;AAAA,MAEnD,GAAG,oBAAA;AAAA,QACF,UAAA;AAAA,QACA,kBAAA;AAAA,QACC,kBAAA,KAAuB,OAAA,IAAW,CAAC,WAAA,IAClC,yBAAA,KAA8B;AAAA,OAClC;AAAA,MACA,iBAAA,EAAiB,UAAA,KAAe,MAAA,GAAY,MAAA,GAAY,EAAA;AAAA,MACxD,eAAA,EAAe,OAAO,eAAe,CAAA;AAAA,MACrC,sBAAA,EAAsB,OAAO,sBAAsB,CAAA;AAAA,MACnD,KAAA,EAAO,UAAA;AAAA,QACL,UAAA,KAAe,MAAA,GACX,MAAA,GACA,CAAA,4BAAA,EAA+B,UAAU,CAAA,CAAA;AAAA,QAC7C,MAAA,CAAO;AAAA,OACT;AAAA,MACA,YAAA,EAAY,KAAA;AAAA,MACZ,IAAA;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,CAAC,+BACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAwB,yBAAqB,IAAA,EACtD,QAAA,kBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO,UAAA,EAAY,KAAA,IAAS,aAAA,CAAc,KAAA;AAAA,YAC1C,OAAA,EAAS,UAAA;AAAA,YACT,YAAA,EACE,UAAA,EAAY,YAAA,IAAgB,aAAA,CAAc,YAAA;AAAA,YAE5C,WAAA,EACE,WAAA,GACI,UAAA,GACC,UAAA,EAAY,eAAe,aAAA,CAAc,WAAA;AAAA,YAEhD,UAAA,EAAY,UAAA,EAAY,UAAA,IAAc,aAAA,CAAc,UAAA;AAAA,YACpD,YAAA,EACE,UAAA,EAAY,YAAA,IAAgB,aAAA,CAAc,YAAA;AAAA,YAE5C,aAAA,EACE,UAAA,EAAY,aAAA,IACZ,aAAA,CAAc,aAAA,IACd,uBAAA;AAAA,YAEF,yBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,cAAA,MAAA,oBACC,GAAA;AAAA,gBAAC,mBAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAS,WAAW,OAAA,GAAU,MAAA;AAAA,kBAC9B,IAAA,EAAM,UAAA,KAAe,SAAA,GAAY,SAAA,GAAY,SAAA;AAAA,kBAC7C,QAAA,EACE,kBAAA,KAAuB,OAAA,GAAU,OAAA,GAAU,MAAA;AAAA,kBAE7C,MAAA,EAAM,IAAA;AAAA,kBAEN,QAAA,kBAAA,IAAA;AAAA,oBAAC,QAAA;AAAA,oBAAA;AAAA,sBACC,IAAA,EAAK,QAAA;AAAA,sBACL,KAAA,EAAM,qBAAA;AAAA,sBACN,eAAA,EAAa,IAAA;AAAA,sBACb,YAAA,EAAY,WAAW,MAAA,GAAY,SAAA;AAAA,sBAElC,QAAA,EAAA;AAAA,wBAAA,QAAA,oBACC,GAAA;AAAA,0BAAC,UAAA;AAAA,0BAAA;AAAA,4BACC,IAAA,EAAM,WAAA;AAAA,4BACN,IAAA,EAAK,cAAA;AAAA,4BACL,SAAA,EAAU;AAAA;AAAA,yBACZ;AAAA,wBAED,QAAA,mBAAW,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,QAAA,EAAS,CAAA,GAAU;AAAA;AAAA;AAAA;AACxC;AAAA,eACF;AAAA,cAED,UAAA,EAAY,OAAA;AAAA,cACZ,cAAc,IAAA,GAAO;AAAA,aAAA,EACxB,CAAA;AAAA,YAEF,MAAA,EAAQ,WAAA,GAAc,KAAA,GAAQ,UAAA,EAAY,MAAA;AAAA,YAC1C,0BACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,cAAA,UAAA,EAAY,QAAA;AAAA,cACZ;AAAA,aAAA,EACH;AAAA;AAAA,SAEJ,EACF,CAAA;AAAA,wBAEF,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAA,EAA0B,yBAAA,EAAuB,MACzD,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,KAAA,qBAChB,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,qBAAA;AAAA,YACN,YAAU,IAAA,CAAK,GAAA;AAAA,YACf,gBAAc,IAAA,CAAK,GAAA;AAAA,YACnB,iBAAA,EAAiB,MAAA,CAAO,KAAA,KAAU,QAAQ,CAAA;AAAA,YAC1C,aAAA,EAAa,MAAA,CAAO,KAAA,KAAU,QAAQ,CAAA;AAAA,YAErC,eAAK,IAAA,IACN,IAAA,CAAK,WAAW,MAAA,IAChB,IAAA,CAAK,WAAW,MAAA,mBACd,GAAA;AAAA,cAAC,IAAA;AAAA,cAAA;AAAA,gBACE,GAAG,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA;AAAA,gBAC7B,MAAA,EACE,IAAA,CAAK,MAAA,KAAW,MAAA,GAAY,yBAC1B,GAAA,CAAC,KAAA,EAAA,EAAI,uBAAA,EAAqB,IAAA,EACvB,QAAA,EAAA,UAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,UAAU,CAAA,EAC1C,CAAA;AAAA,gBAGJ,MAAA,EACE,IAAA,CAAK,MAAA,KAAW,MAAA,GAAY,yBAC1B,GAAA,CAAC,KAAA,EAAA,EAAI,uBAAA,EAAqB,IAAA,EACvB,QAAA,EAAA,UAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,UAAU,CAAA,EAC1C,CAAA;AAAA,gBAIH,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,gBAGR,IAAA,CAAK;AAAA;AAAA,SAGV,CAAA,EACH,CAAA;AAAA,QACC,0BACC,GAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,uBAAA,EAAwB,yBAAqB,IAAA,EACzD,QAAA,kBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,QAAA,EAAS,QAAA;AAAA,YACT,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,cAAc,MAAA,CAAO,YAAA;AAAA,YACrB,aAAa,MAAA,CAAO,WAAA;AAAA,YACpB,YAAY,MAAA,CAAO,UAAA;AAAA,YACnB,cAAc,MAAA,CAAO,YAAA;AAAA,YACrB,aAAA,EACE,OAAO,aAAA,IAAiB,8BAAA;AAAA,YAE1B,SAAS,MAAA,CAAO,OAAA;AAAA,YAChB,QAAQ,MAAA,CAAO,MAAA;AAAA,YACf,UAAU,MAAA,CAAO;AAAA;AAAA,SACnB,EACF;AAAA;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-SOFPUW3O.js","sourcesContent":["import { ChevronLeft } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport {\n type ScrollEdge,\n scrollEdgeAttributes,\n} from '../../../shared/layout/scroll-edge.js';\nimport type { NavPane } from '../../../shared/panels/nav-pane.js';\nimport type { PanelBottomToolbar } from '../../../shared/panels/panel-toolbar.js';\nimport type { CssColor } from '../../../shared/styles/css-values.js';\nimport {\n joinStyles,\n type SurfaceTint,\n surfaceTintAttributes,\n} from '../../../shared/styles/surface-tint.js';\nimport { Toolbar, type ToolbarConfig } from '../../actions/toolbar/toolbar.js';\nimport { ToolbarControlGroup } from '../../actions/toolbar-control-group/toolbar-control-group.js';\nimport {\n type HeadingLevel,\n ToolbarText,\n type ToolbarTextSize,\n} from '../../actions/toolbar-text/toolbar-text.js';\nimport { List, type ListConfig } from '../../collections/list/list.js';\nimport { paneConfigProps } from '../../layout/pane/internal/pane-config-props.js';\nimport { Pane } from '../../layout/pane/pane.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\n\n/**\n * One entry in a {@link NavStack}. The app owns the stack as an array (usually a\n * signal); `NavStack` renders it and `wireNavStack` animates the transitions.\n */\nexport interface NavStackView extends NavPane<\n NavStackViewToolbar,\n PanelBottomToolbar\n> {\n /** Stable identity for keyed reconcile and transition direction. */\n key: string;\n}\n\n/** Per-view top toolbar. The stack supplies its back control before `leading`. */\nexport interface NavStackViewToolbar extends NavStackToolbarConfig {\n title?: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n}\n\n/** A view's structured bottom toolbar; it cross-fades on navigation. */\nexport type NavStackViewBottomToolbar = PanelBottomToolbar;\n\n/**\n * The top toolbar's configuration. Its `ToolbarConfig` forwards to the real\n * `Toolbar` the stack renders; by default that toolbar draws no divider and\n * claims the top and side safe-area edges the stack still touches.\n */\nexport interface NavStackToolbarConfig extends ToolbarConfig {\n /** Accessible name of the top toolbar (default: none). */\n label?: string;\n /**\n * Size of the view title's `ToolbarText`. Default `xlarge` at the root,\n * where the title is the page heading, and `large` once a back control\n * shares the bar.\n */\n titleSize?: ToolbarTextSize;\n /** Expose the view title as a heading at this level (default: a plain span). */\n headingLevel?: HeadingLevel;\n}\n\n/**\n * How a {@link NavStack}'s top chrome relates to the active view: `docked`\n * above it, or `overlay` laid over its top edge on the translucent chrome\n * material, so the view's content scrolls visibly beneath it.\n * `clear` lays it over\n * the same edge fully transparent, for chrome over imagery: legibility comes\n * from glass control groups or a scrim, and with `scrollEdge=\"material\"` the\n * chrome material fades in once content scrolls beneath it.\n */\nexport type NavStackChromePresentation = 'docked' | 'overlay' | 'clear';\n\n/**\n * How a {@link NavStack}'s bottom toolbar relates to the active view:\n * `docked` below it, or `overlay` laid over its bottom edge on the\n * translucent chrome material, so the view's content scrolls visibly beneath\n * it.\n * `clear` lays it over\n * the same edge fully transparent, for chrome over imagery: legibility comes\n * from glass control groups or a scrim, and with `scrollEdge=\"material\"` the\n * chrome material fades in once content scrolls beneath\n * it, until the view scrolls to its end.\n */\nexport type NavStackBottomToolbarPresentation = 'docked' | 'overlay' | 'clear';\n\nexport interface NavStackProps {\n id: string;\n /** Accessible name for the stack region. */\n label: string;\n /** The stack, root first; the last entry is the active top view. */\n views: NavStackView[];\n /** Accessible label for the icon-only back control (default \"Back\"). */\n backLabel?: string;\n /** The back control's icon (default a chevron-left `LucideIcon`). */\n backIcon?: KerfUiContent;\n /**\n * Visible text beside the back icon, such as the previous view's title\n * (default: icon only). When set, the text names the control and\n * `backLabel` is not used.\n */\n backText?: string;\n /** The top toolbar's configuration, forwarded to its `Toolbar`. */\n toolbarConfig?: NavStackToolbarConfig;\n /** Persistent last group in every view's top toolbar, supplied by a hosting panel. */\n panelToggle?: KerfUiContent;\n /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */\n hideToolbar?: boolean;\n /** Optional persistent bottom toolbar used when the active view does not provide one. */\n bottomToolbar?: NavStackViewBottomToolbar;\n /**\n * Stack chrome separator. `auto` (default) draws both available edges\n * against a sunken active Pane and otherwise follows `chromeDividers`;\n * `hidden` suppresses the stack-owned edges.\n */\n separator?: 'auto' | 'hidden';\n /**\n * The line under the top chrome and over the bottom toolbar, where they\n * meet the active view. `scroll` (default) shows the chrome's line only\n * while the view's content is scrolled beneath it, and the bottom\n * toolbar's only while more content lies below — never when the content\n * fits — once `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is\n * wired above the stack; unwired, neither shows. `always` shows both\n * without the wiring; `none` neither, even when wired. The line is drawn\n * inside the chrome, so no state moves the chrome or the content. A\n * A sunken active Pane still draws the separator unless\n * `separator=\"hidden\"`. A `toolbarConfig.dividerSides` edge is the Toolbar's\n * own and is unaffected.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n /**\n * `docked` (default) gives the top chrome its own band above the active\n * view. `overlay` lays the chrome over the view's top edge on the\n * translucent chrome material (`--kui-chrome-material`, opaque under\n * `prefers-reduced-transparency`, `prefers-contrast: more`, forced colors,\n * or without `backdrop-filter`), so content scrolls visibly beneath it, as\n * an iOS navigation bar does. `wireNavStack` measures the live chrome and\n * hands its height (top safe area included) to the viewport as the\n * block-start `--kui-edge-inset-*` context, so every view clears it with no\n * prop: a plain view, a sole `Pane`'s content (or header), and a nested\n * layout all pad and `scroll-padding` by it, so the first item, and anything\n * focused or scrolled into view, rests clear of the bar. Until then, and\n * with `hideToolbar`, the chrome stays docked. An untoned `ToolbarText` in\n * the chrome lifts its title and description to AA over the content passing\n * beneath it; keep any other quiet copy in the view. With `clear`, the\n * stack's own back control sits in a glass control group\n * (`material=\"glass\"`), so it stays legible over imagery.\n */\n chromePresentation?: NavStackChromePresentation;\n /**\n * `docked` (default) gives the bottom toolbar its own band below the\n * active view. `overlay` lays it over the view's bottom edge on the\n * translucent chrome material (opaque under the same preferences as\n * `chromePresentation`), so content scrolls visibly beneath it, as under\n * an iOS toolbar. `wireNavStack` measures the live bottom toolbar (never a\n * cross-fading copy) and hands its height (bottom safe area included) to\n * the viewport as the block-end `--kui-edge-inset-*` context, so a plain\n * view, a sole `Pane`'s content (or footer), and a nested layout rest their\n * last item, and anything focused or scrolled into view, clear of it. Until\n * then, and while no bottom toolbar is shown, it stays docked. Independent\n * of `chromePresentation`, which governs only the top chrome. An untoned\n * `ToolbarText` in the toolbar lifts to AA over the content beneath it.\n */\n bottomToolbarPresentation?: NavStackBottomToolbarPresentation;\n /**\n * For `clear` chrome or bottom toolbar, `material` fades the chrome\n * material in while the active view's content lies beneath it (default\n * `none`).\n */\n scrollEdge?: ScrollEdge;\n /**\n * The scroll distance, in CSS pixels, over which the scroll edge fades in\n * (default 60).\n */\n scrollEdgeDistance?: number;\n /**\n * Paint the stack, its docked chrome and bottom toolbar, and every view in\n * an app-chosen color (a `@kerfjs/ui/css-values` color builder) instead of\n * the surface. Overlay chrome keeps the chrome material; one view's own\n * color goes in its `pane: { background }`. Forced colors paint `Canvas`.\n */\n background?: CssColor;\n /**\n * A scoped tint (`{ color, scheme }`) for the stack, its chrome, bottom toolbar, and views: its surfaces and every\n * descendant re-derive their surface and text tokens from the app's color\n * in the declared scheme, with lightness clamped to keep text at WCAG AA.\n */\n tint?: SurfaceTint;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nconst DEFAULT_SAFE_AREA_EDGES = [\n 'block-start',\n 'inline-start',\n 'inline-end',\n] as const;\n\nconst DEFAULT_BOTTOM_SAFE_AREA_EDGES = [\n 'block-end',\n 'inline-start',\n 'inline-end',\n] as const;\n\nfunction chromeList(content: KerfUiContent, config?: ListConfig) {\n return (\n <List\n dividerSides={config?.dividerSides}\n gap={config?.gap}\n hAlign={config?.hAlign}\n vAlign={config?.vAlign}\n textInsets={config?.textInsets}\n controlInsets={config?.controlInsets}\n >\n {content}\n </List>\n );\n}\n\n/**\n * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last\n * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and\n * cross-fades the chrome across a change. Its top chrome is a real `Toolbar`: the\n * back control and title lead, the active view's `toolbar` fills the zones,\n * and `toolbarConfig` supplies defaults. A single-pane\n * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.\n */\nexport function NavStack({\n id,\n label,\n views,\n backLabel = 'Back',\n backIcon,\n backText,\n toolbarConfig = {},\n panelToggle,\n hideToolbar = false,\n bottomToolbar,\n separator = 'auto',\n chromeDividers = 'scroll',\n chromePresentation = 'docked',\n bottomToolbarPresentation = 'docked',\n scrollEdge = 'none',\n scrollEdgeDistance,\n background,\n tint,\n className = '',\n slot,\n}: NavStackProps) {\n const tinted = surfaceTintAttributes(tint);\n const topIndex = views.length - 1;\n const top = views[topIndex];\n const topToolbar = top?.toolbar;\n const bottom = top?.bottomToolbar ?? bottomToolbar;\n const canPop = views.length > 1;\n const topDensity = topToolbar?.density ?? toolbarConfig.density;\n // With a back control, the title centers on the bar (iOS-style) unless the\n // view owns the center zone; at the root it leads and fills, left-aligned.\n const centerTitle = canPop && topToolbar?.center === undefined;\n const title = (\n <ToolbarText\n text={topToolbar?.title ?? ''}\n size={\n topToolbar?.titleSize ??\n toolbarConfig.titleSize ??\n (canPop ? 'large' : 'xlarge')\n }\n headingLevel={topToolbar?.headingLevel ?? toolbarConfig.headingLevel}\n fill={!centerTitle}\n />\n );\n return (\n <section\n class={`kui-nav-stack ${tinted.className} ${className}`\n .replace(/\\s+/g, ' ')\n .trim()}\n id={id}\n data-component=\"nav-stack\"\n data-nav-stack-id={id}\n data-depth={String(views.length)}\n data-separator={separator}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n data-chrome-presentation={\n chromePresentation !== 'docked' && !hideToolbar ? 'overlay' : undefined\n }\n data-chrome-material={\n chromePresentation === 'clear' && !hideToolbar ? 'clear' : undefined\n }\n data-bottom-toolbar-presentation={\n bottomToolbarPresentation !== 'docked' ? 'overlay' : undefined\n }\n data-bottom-toolbar-material={\n bottomToolbarPresentation === 'clear' ? 'clear' : undefined\n }\n {...scrollEdgeAttributes(\n scrollEdge,\n scrollEdgeDistance,\n (chromePresentation === 'clear' && !hideToolbar) ||\n bottomToolbarPresentation === 'clear',\n )}\n data-background={background === undefined ? undefined : ''}\n data-kui-tint={tinted['data-kui-tint']}\n data-kui-tint-accent={tinted['data-kui-tint-accent']}\n style={joinStyles(\n background === undefined\n ? undefined\n : `--_kui-nav-stack-background:${background}`,\n tinted.style,\n )}\n aria-label={label}\n slot={slot}\n >\n {!hideToolbar && (\n <div class=\"kui-nav-stack__chrome\" data-nav-stack-chrome>\n <Toolbar\n label={topToolbar?.label ?? toolbarConfig.label}\n density={topDensity}\n dividerSides={\n topToolbar?.dividerSides ?? toolbarConfig.dividerSides\n }\n centerAlign={\n centerTitle\n ? 'balanced'\n : (topToolbar?.centerAlign ?? toolbarConfig.centerAlign)\n }\n responsive={topToolbar?.responsive ?? toolbarConfig.responsive}\n responsiveAt={\n topToolbar?.responsiveAt ?? toolbarConfig.responsiveAt\n }\n safeAreaEdges={\n topToolbar?.safeAreaEdges ??\n toolbarConfig.safeAreaEdges ??\n DEFAULT_SAFE_AREA_EDGES\n }\n leading={\n <>\n {canPop && (\n <ToolbarControlGroup\n content={backText ? 'mixed' : 'icon'}\n size={topDensity === 'compact' ? 'compact' : 'default'}\n material={\n chromePresentation === 'clear' ? 'glass' : undefined\n }\n single\n >\n <button\n type=\"button\"\n class=\"kui-nav-stack__back\"\n data-nav-back\n aria-label={backText ? undefined : backLabel}\n >\n {backIcon ?? (\n <LucideIcon\n icon={ChevronLeft}\n name=\"chevron-left\"\n className=\"kui-nav-stack__back-icon\"\n />\n )}\n {backText ? <span>{backText}</span> : null}\n </button>\n </ToolbarControlGroup>\n )}\n {topToolbar?.leading}\n {centerTitle ? null : title}\n </>\n }\n center={centerTitle ? title : topToolbar?.center}\n trailing={\n <>\n {topToolbar?.trailing}\n {panelToggle}\n </>\n }\n />\n </div>\n )}\n <div class=\"kui-nav-stack__viewport\" data-nav-stack-viewport>\n {views.map((view, index) => (\n <article\n class=\"kui-nav-stack__view\"\n data-key={view.key}\n data-nav-key={view.key}\n data-nav-active={String(index === topIndex)}\n aria-hidden={String(index !== topIndex)}\n >\n {view.pane ||\n view.header !== undefined ||\n view.footer !== undefined ? (\n <Pane\n {...paneConfigProps(view.pane)}\n header={\n view.header === undefined ? undefined : (\n <div data-nav-stack-header>\n {chromeList(view.header, view.headerList)}\n </div>\n )\n }\n footer={\n view.footer === undefined ? undefined : (\n <div data-nav-stack-footer>\n {chromeList(view.footer, view.footerList)}\n </div>\n )\n }\n >\n {view.content}\n </Pane>\n ) : (\n view.content\n )}\n </article>\n ))}\n </div>\n {bottom && (\n <footer class=\"kui-nav-stack__bottom\" data-nav-stack-bottom>\n <Toolbar\n position=\"footer\"\n label={bottom.label}\n density={bottom.density}\n dividerSides={bottom.dividerSides}\n centerAlign={bottom.centerAlign}\n responsive={bottom.responsive}\n responsiveAt={bottom.responsiveAt}\n safeAreaEdges={\n bottom.safeAreaEdges ?? DEFAULT_BOTTOM_SAFE_AREA_EDGES\n }\n leading={bottom.leading}\n center={bottom.center}\n trailing={bottom.trailing}\n />\n </footer>\n )}\n </section>\n );\n}\n"]}
@@ -262,6 +262,20 @@ function wireWorkbenchOverlays(root, findWorkbench, panels, exclusive = false) {
262
262
  if (other !== panel) other.collapsed.value = true;
263
263
  }
264
264
  (focusables(element)[0] ?? element).focus({ preventScroll: true });
265
+ const opener = openers.get(panel);
266
+ const focusIn = (frames) => {
267
+ const current = panelElement(panel);
268
+ const focused = ownerDocument.activeElement;
269
+ if (panel.collapsed.peek() || !current || current.contains(focused) || !overlaid(current) || focused !== null && focused !== ownerDocument.body && focused !== opener)
270
+ return;
271
+ focusables(current)[0]?.focus({ preventScroll: true });
272
+ if (current.contains(ownerDocument.activeElement)) return;
273
+ if (frames > 0)
274
+ globalThis.requestAnimationFrame(() => focusIn(frames - 1));
275
+ else current.focus({ preventScroll: true });
276
+ };
277
+ if (!element.contains(ownerDocument.activeElement))
278
+ globalThis.requestAnimationFrame(() => focusIn(8));
265
279
  })
266
280
  );
267
281
  }
@@ -490,4 +504,4 @@ function wireWorkbench(root, {
490
504
 
491
505
  export { wireWorkbench };
492
506
 
493
- //# sourceMappingURL=chunk-QLA25V2K.js.map
507
+ //# sourceMappingURL=chunk-WPNIKZMJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/workbench/internal/workbench-overlays.ts","../src/components/layout/workbench/wiring/wire-workbench.ts"],"names":["active","element","panel","inside","effect","selector"],"mappings":"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","file":"chunk-WPNIKZMJ.js","sourcesContent":["// The transient-overlay behavior `wireWorkbench` gives Workbench panels that\n// present as overlays: a responsive overlay starts collapsed when its\n// breakpoint begins to apply, an open overlay takes focus and keeps Tab inside\n// it, and it closes on Escape or a press outside it. It mirrors `wireSidebar`'s\n// compact overlay (the ARIA dialog pattern). Internal.\n\nimport { effect, type Signal } from 'kerfjs';\n\nimport type { WorkbenchPanelKey } from './workbench-resize.js';\n\n/** A Workbench panel whose app-owned `collapsed` signal the wiring may write. */\nexport interface WorkbenchOverlayPanel {\n key: WorkbenchPanelKey;\n collapsed: Signal<boolean>;\n keepOpenOn?: (target: Node) => boolean;\n}\n\n/** Each panel's own element, never a nested Workbench's. */\nconst PANEL_SELECTORS: Record<WorkbenchPanelKey, string> = {\n leftRail: ':scope > [data-workbench-rail=\"left\"]',\n rightRail: ':scope > [data-workbench-rail=\"right\"]',\n bottomDrawer: ':scope > .kui-workbench__center > [data-workbench-drawer]',\n};\n\n/** Any Workbench panel element: a rail or the bottom drawer. */\nconst PANEL_ELEMENT = '[data-workbench-rail], [data-workbench-drawer]';\n\nconst RESTORE_PANELS: Record<WorkbenchPanelKey, string> = {\n leftRail: 'left',\n rightRail: 'right',\n bottomDrawer: 'bottom',\n};\n\nconst FOCUSABLE =\n 'a[href],area[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * The panel's focusable controls, in tab order. Only an open panel is ever\n * asked. The selector drops disabled controls and `tabindex=\"-1\"`; a\n * rendered control the CSS hides (the separator of a panel whose responsive\n * overlay breakpoint applies is `display: none`) is dropped too, or Tab would\n * wrap from a control focus can never reach. Where `checkVisibility` is\n * missing, every matched control counts.\n */\nconst focusables = (element: HTMLElement): HTMLElement[] =>\n [...element.querySelectorAll<HTMLElement>(FOCUSABLE)].filter(\n (control) =>\n typeof control.checkVisibility !== 'function' ||\n control.checkVisibility(),\n );\n\n/**\n * Wire transient overlay behavior for the given panels of the Workbench that\n * `findWorkbench` returns (looked up on use, so the Workbench may render after\n * wire-up). The app still owns each `collapsed` signal; this wiring only\n * writes it:\n *\n * - When a panel's `responsiveOverlayAt` breakpoint begins to apply (at\n * wire-up, on first render, or on a crossing), its inline collapsed state is\n * remembered and the panel collapses, so no overlay covers the work area\n * until the user opens it. When the breakpoint stops applying (or on\n * disposal) the remembered state comes back. These presentation changes\n * skip the collapse motion.\n * - A panel that opens while it presents as an overlay takes focus: its\n * first focusable control (else the panel itself) is focused, without\n * scrolling its sliding content. While an overlay is open, Tab and\n * Shift+Tab cycle through the controls of the overlay that holds focus\n * (else the most recently opened one) and never reach the work area it\n * covers — the ARIA dialog pattern `wireSidebar`'s compact overlay follows.\n * Inline panels are left alone.\n * - Escape closes the open overlay panel that holds focus, else the most\n * recently opened one; a press that starts and ends outside an open overlay\n * panel closes it. Static `presentation: \"overlay\"` panels are included.\n * - Focus stranded in a panel that closes — however it closed, including\n * through the app's own control inside it — returns to the control that\n * had it when the panel opened, else to the panel's restore control, else\n * to a control outside it whose `aria-controls` names the panel (or an\n * element inside it). The last covers a panel that was already open at\n * wire-up, which has no recorded opener. Focus a press inside the panel\n * dropped to the body counts as stranded too: Safari and macOS WebKit\n * never focus a clicked button, so pressing the panel's own close control\n * blurs the focused control before the click closes the panel. Focus the\n * user has since moved to any element is left where it is.\n * - With `exclusive`, a panel that opens while it presents as an overlay\n * closes every other open overlay panel, so overlays never cover each\n * other's controls. Inline panels are never closed by it.\n *\n * Returns a disposer.\n */\nexport function wireWorkbenchOverlays(\n root: HTMLElement,\n findWorkbench: () => HTMLElement | null,\n panels: readonly WorkbenchOverlayPanel[],\n exclusive = false,\n): () => void {\n const ownerDocument = root.ownerDocument;\n const disposers: Array<() => void> = [];\n // Open panels, most recently opened last, and each one's opener: the\n // control that had focus when it opened.\n const openOrder: WorkbenchOverlayPanel[] = [];\n const openers = new Map<WorkbenchOverlayPanel, HTMLElement>();\n // The open panel the latest press started in while focus was inside it,\n // until focus next lands anywhere. Safari and macOS WebKit never focus a\n // clicked button, so pressing a panel's own close control blurs the focused\n // control to the body before the click closes the panel; this is how the\n // close still counts as leaving focus stranded in it.\n let pressedFocus: WorkbenchOverlayPanel | undefined;\n /**\n * The `aria-controls` control a click just activated, kept for a couple of\n * frames: the toggle a panel opens or closes from, even once the app's\n * render has removed it.\n */\n let activated: HTMLElement | undefined;\n\n const panelElement = (panel: WorkbenchOverlayPanel): HTMLElement | null =>\n findWorkbench()?.querySelector<HTMLElement>(PANEL_SELECTORS[panel.key]) ??\n null;\n /**\n * Each panel element's computed \"out of flow\" state, so a mutation or a\n * press does not force a document-wide style recalculation to read it. Its\n * inputs are the Workbench's inline size (the container queries), the root\n * font size (rem breakpoints), and the panel's own presentation attributes:\n * a ResizeObserver callback clears every entry, and a presentation attribute\n * change, whoever writes it, clears that panel's entry. A re-rendered panel\n * is a new element and is measured afresh. Without a ResizeObserver to\n * report a breakpoint crossing, nothing is cached.\n */\n let outOfFlow = new WeakMap<HTMLElement, boolean>();\n /** Whether the panel's responsive overlay breakpoint currently applies. */\n const responsive = (element: HTMLElement): boolean => {\n if (\n element.dataset.presentation !== 'inline' ||\n !element.hasAttribute('data-responsive-overlay-at')\n )\n return false;\n const cached = outOfFlow.get(element);\n if (cached !== undefined) return cached;\n const absolute =\n globalThis.getComputedStyle(element).position === 'absolute';\n if (resizeObserver) outOfFlow.set(element, absolute);\n return absolute;\n };\n const overlaid = (element: HTMLElement): boolean =>\n element.dataset.presentation === 'overlay' || responsive(element);\n\n /** Where focus goes when a panel it was in closes. */\n const restoreTarget = (\n panel: WorkbenchOverlayPanel,\n element: HTMLElement | null,\n ): HTMLElement | undefined => {\n const opener = openers.get(panel);\n // An opener inside another panel that has closed since (an exclusive\n // overlay closes the one it was opened from) would strand focus there too.\n if (\n opener?.isConnected &&\n !element?.contains(opener) &&\n !panels.some(\n (other) =>\n other.collapsed.peek() && panelElement(other)?.contains(opener),\n )\n )\n return opener;\n const side = RESTORE_PANELS[panel.key];\n const restore = findWorkbench()\n ?.querySelector<HTMLElement>(\n `.kui-workbench__restore[data-panel=\"${side}\"]`,\n )\n ?.querySelector<HTMLElement>(FOCUSABLE);\n return restore ?? (element ? controller(element) : undefined);\n };\n /**\n * A control outside the panel that names it, or an element inside it, in\n * its `aria-controls`: the app's toggle for a panel with no opener.\n */\n const controller = (element: HTMLElement): HTMLElement | undefined => {\n const ids = new Set(\n [element, ...element.querySelectorAll('[id]')].map((node) => node.id),\n );\n ids.delete('');\n return [\n ...ownerDocument.querySelectorAll<HTMLElement>('[aria-controls]'),\n ].find(\n (control) =>\n !element.contains(control) &&\n control.matches(FOCUSABLE) &&\n control\n .getAttribute('aria-controls')!\n .split(/\\s+/)\n .some((id) => ids.has(id)),\n );\n };\n /** Whether a control's `aria-controls` (always present) names panel `id`. */\n const namesPanel = (control: Element, id: string): boolean =>\n control.getAttribute('aria-controls')!.split(/\\s+/).includes(id);\n /** The panel's own control for itself: its toggle inside it. */\n const controlInside = (element: HTMLElement): HTMLElement | undefined =>\n [...element.querySelectorAll<HTMLElement>('[aria-controls]')].find(\n (control) =>\n control.matches(FOCUSABLE) && namesPanel(control, element.id),\n );\n const rescueFocus = (panel: WorkbenchOverlayPanel): void => {\n const element = panelElement(panel);\n const target = restoreTarget(panel, element);\n if (target) {\n target.focus();\n return;\n }\n // An app that renders its restore control after this write has not\n // produced it yet; look again once the current batch settles.\n globalThis.queueMicrotask(() => {\n if (!panel.collapsed.peek()) return;\n const later = restoreTarget(panel, panelElement(panel));\n const active = ownerDocument.activeElement;\n if (later) later.focus();\n else if (active instanceof HTMLElement && element?.contains(active))\n active.blur();\n });\n };\n\n /**\n * A presentation-driven write: no collapse motion, because nothing the user\n * did moved the panel. The app's render has normally applied the new state\n * by the time the write returns, so the content's transition is suspended\n * across one style flush.\n */\n const adapt = (\n panel: WorkbenchOverlayPanel,\n element: HTMLElement,\n collapsed: boolean,\n ): void => {\n if (panel.collapsed.peek() === collapsed) return;\n const stranded = collapsed && element.contains(ownerDocument.activeElement);\n panel.collapsed.value = collapsed;\n // Every Workbench panel renders its content wrapper, and never with a\n // style of its own, so the attribute goes again once the flush is done.\n const content = element.querySelector<HTMLElement>(\n ':scope > .kui-workbench__panel-content',\n )!;\n content.style.transition = 'none';\n void globalThis.getComputedStyle(content).transform;\n content.removeAttribute('style');\n // The collapse effect has normally returned the focus already; on\n // disposal, after the effects are gone, this is what returns it.\n if (stranded && element.contains(ownerDocument.activeElement))\n rescueFocus(panel);\n };\n\n // The inline collapsed state of each panel whose responsive overlay\n // currently applies, restored when it stops applying.\n const inlineState = new Map<WorkbenchOverlayPanel, boolean>();\n // The Workbench's measured width, for numeric thresholds; cleared with the\n // presentation cache, and when the Workbench element changes.\n let measuredWidth: { workbench: HTMLElement; width: number } | undefined;\n const workbenchWidth = (workbench: HTMLElement): number => {\n if (measuredWidth?.workbench === workbench) return measuredWidth.width;\n const width = workbench.getBoundingClientRect().width;\n if (resizeObserver) measuredWidth = { workbench, width };\n return width;\n };\n const sync = (): void => {\n const workbench = findWorkbench();\n let width: number | undefined;\n for (const panel of panels) {\n const element = panelElement(panel);\n if (!element) continue;\n // CSS container queries cannot take a runtime pixel value. For a\n // numeric threshold the same measured Workbench width drives the CSS\n // presentation hook and the collapsed-state transition below.\n const at = Number(element.dataset.responsiveOverlayAt);\n const customActive =\n element.dataset.responsiveOverlayAt !== undefined &&\n Number.isFinite(at) &&\n at > 0 &&\n element.dataset.presentation === 'inline' &&\n (width ??= workbenchWidth(workbench!)) <= at;\n if (customActive) {\n if (element.dataset.responsiveOverlayActive !== 'true') {\n element.dataset.responsiveOverlayActive = 'true';\n outOfFlow.delete(element);\n }\n } else if (element.hasAttribute('data-responsive-overlay-active')) {\n element.removeAttribute('data-responsive-overlay-active');\n outOfFlow.delete(element);\n }\n const active = responsive(element);\n if (active && !inlineState.has(panel)) {\n inlineState.set(panel, panel.collapsed.peek());\n adapt(panel, element, true);\n } else if (!active && inlineState.has(panel)) {\n const remembered = inlineState.get(panel)!;\n inlineState.delete(panel);\n adapt(panel, element, remembered);\n }\n // A signal write can patch or replace the panel synchronously. Preserve\n // the measured presentation marker on the rendered element too.\n const rendered = panelElement(panel);\n if (\n rendered &&\n customActive &&\n rendered.dataset.responsiveOverlayActive !== 'true'\n ) {\n rendered.dataset.responsiveOverlayActive = 'true';\n outOfFlow.delete(rendered);\n }\n }\n if (!workbench) return;\n // A direct root attribute limits style invalidation to overlay changes.\n // Descendant :has() selectors on the Workbench caused every ordinary\n // work-area mutation to restyle the entire center subtree.\n const active = (key: WorkbenchPanelKey): HTMLElement | null => {\n const element = workbench.querySelector<HTMLElement>(\n PANEL_SELECTORS[key],\n );\n return element?.dataset.responsiveOverlayActive === 'true'\n ? element\n : null;\n };\n const left = active('leftRail');\n const right = active('rightRail');\n const drawer = active('bottomDrawer');\n const railOpen = [left, right].some(\n (element) => element && element.dataset.collapsed !== 'true',\n );\n const markers = [\n left && 'left',\n right && 'right',\n drawer && 'drawer',\n railOpen && 'rail-open',\n (railOpen || (drawer && drawer.dataset.collapsed !== 'true')) && 'open',\n ]\n .filter(Boolean)\n .join(' ');\n if (markers) {\n if (workbench.dataset.numericOverlays !== markers)\n workbench.dataset.numericOverlays = markers;\n } else if (workbench.hasAttribute('data-numeric-overlays'))\n workbench.removeAttribute('data-numeric-overlays');\n };\n\n // The Workbench is its own breakpoint container, so its size is what moves a\n // panel across the breakpoint. It may render after wire-up or be replaced,\n // and the app may change a presentation, so both are observed too.\n let observed: HTMLElement | null = null;\n const resizeObserver =\n typeof globalThis.ResizeObserver === 'function'\n ? new globalThis.ResizeObserver(() => {\n outOfFlow = new WeakMap();\n measuredWidth = undefined;\n sync();\n })\n : undefined;\n /** Observe the current Workbench; whether it changed. */\n const track = (): boolean => {\n const workbench = findWorkbench();\n if (workbench === observed) return false;\n if (observed) resizeObserver?.unobserve(observed);\n observed = workbench;\n if (workbench) resizeObserver?.observe(workbench);\n return true;\n };\n // Only a mutation that can change a panel's presentation re-syncs: a new\n // Workbench, a panel element added or removed, or a presentation attribute\n // change on a panel. Other renders below root (a CollapsiblePanel's\n // `data-collapsed`, a list's rows) are skipped, so they never force style.\n const isPanel = (node: Node): boolean =>\n node instanceof HTMLElement && node.matches(PANEL_ELEMENT);\n const hasPanel = (nodes: NodeList): boolean => {\n for (const node of nodes) if (isPanel(node)) return true;\n return false;\n };\n const mutationObserver = new MutationObserver((records) => {\n let relevant = track();\n for (const record of records) {\n if (record.type === 'attributes') {\n if (!isPanel(record.target)) continue;\n if (record.attributeName !== 'data-collapsed')\n outOfFlow.delete(record.target as HTMLElement);\n relevant = true;\n } else if (\n !relevant &&\n (hasPanel(record.addedNodes) || hasPanel(record.removedNodes))\n )\n relevant = true;\n }\n if (relevant) sync();\n });\n mutationObserver.observe(root, {\n attributes: true,\n attributeFilter: [\n 'data-presentation',\n 'data-responsive-overlay-at',\n 'data-responsive-overlay-active',\n 'data-collapsed',\n ],\n childList: true,\n subtree: true,\n });\n // The breakpoints are in rem, so a root font-size change (a text-size\n // setting applied after load) moves a panel across them without resizing\n // the Workbench. A 1rem probe outside the app's tree reports that change.\n const remProbe = ownerDocument.createElement('div');\n remProbe.setAttribute('aria-hidden', 'true');\n remProbe.style.cssText =\n 'position:absolute;width:1rem;height:0;overflow:hidden;visibility:hidden;pointer-events:none';\n if (resizeObserver) {\n ownerDocument.body.append(remProbe);\n resizeObserver.observe(remProbe);\n }\n disposers.push(() => {\n mutationObserver.disconnect();\n resizeObserver?.disconnect();\n remProbe.remove();\n });\n track();\n sync();\n\n for (const panel of panels) {\n let previous = panel.collapsed.peek();\n if (!previous) openOrder.push(panel);\n disposers.push(\n effect(() => {\n const collapsed = panel.collapsed.value;\n if (collapsed === previous) return;\n previous = collapsed;\n const index = openOrder.indexOf(panel);\n if (index >= 0) openOrder.splice(index, 1);\n if (collapsed) {\n // Whatever closed the panel — Escape, an outside press, a\n // breakpoint, or the app's own control inside it — focus left in\n // it would be stranded in a hidden panel. So would focus that a\n // press inside it dropped to the body (see `pressedFocus`).\n const active = ownerDocument.activeElement;\n const element = panelElement(panel);\n if (\n element?.contains(active) ||\n // The panel's own control closed it (focused or not), so hand\n // focus to the control that reopens it.\n (activated !== undefined && element?.contains(activated)) ||\n (pressedFocus === panel &&\n (active === null || active === ownerDocument.body))\n )\n rescueFocus(panel);\n return;\n }\n openOrder.push(panel);\n const element = panelElement(panel);\n const active = ownerDocument.activeElement;\n if (\n active instanceof HTMLElement &&\n active !== ownerDocument.body &&\n !element?.contains(active)\n )\n openers.set(panel, active);\n else openers.delete(panel);\n // A focused toggle the app's render removes as the panel opens — a\n // Workbench toolbar toggle leaves the work-area toolbar for the\n // panel's own — would drop focus to the body. Hand it to the panel's\n // own control for it, so a keyboard user keeps their place. The\n // render may land before this effect (the toggle is gone already, so\n // the activated control stands in for the opener) or after it, in a\n // microtask or a later frame.\n const toggle =\n openers.get(panel) ??\n (activated && element && namesPanel(activated, element.id)\n ? activated\n : undefined);\n if (toggle) {\n const handOff = (frames: number): void => {\n const focused = ownerDocument.activeElement;\n if (panel.collapsed.peek()) return;\n if (toggle.isConnected) {\n if (toggle === focused && frames > 0)\n globalThis.requestAnimationFrame(() => handOff(frames - 1));\n return;\n }\n if (focused !== null && focused !== ownerDocument.body) return;\n const current = panelElement(panel);\n if (current) controlInside(current)?.focus({ preventScroll: true });\n };\n globalThis.queueMicrotask(() => handOff(5));\n }\n if (!element || !overlaid(element)) return;\n // Opening an overlay closes the others. Their collapse effects run\n // after this one, by which time focus has moved into this panel, so\n // none of them hands it back to an opener.\n if (exclusive)\n for (const [other] of openOverlays())\n if (other !== panel) other.collapsed.value = true;\n // An overlay covers the work area, so focus moves in with it rather\n // than staying on a control it may cover. Without preventScroll the\n // browser scrolls the panel's clipped, still-sliding content to reveal\n // the target, which then unwinds as the slide finishes.\n (focusables(element)[0] ?? element).focus({ preventScroll: true });\n // The app's render may show the panel after this effect (its render\n // effect runs later, or in a later frame), so the focus above can\n // land on a still-hidden panel and do nothing. The Workbench's own\n // toggle recovers through the hand-off once it is removed; a\n // persistent toggle outside the Workbench never is, so retry for a\n // few frames until the overlay can take focus. Only focus left on\n // the opener or the body is moved, never focus the person moved.\n const opener = openers.get(panel);\n const focusIn = (frames: number): void => {\n const current = panelElement(panel);\n const focused = ownerDocument.activeElement;\n if (\n panel.collapsed.peek() ||\n !current ||\n current.contains(focused) ||\n !overlaid(current) ||\n (focused !== null &&\n focused !== ownerDocument.body &&\n focused !== opener)\n )\n return;\n focusables(current)[0]?.focus({ preventScroll: true });\n if (current.contains(ownerDocument.activeElement)) return;\n if (frames > 0)\n globalThis.requestAnimationFrame(() => focusIn(frames - 1));\n else current.focus({ preventScroll: true });\n };\n if (!element.contains(ownerDocument.activeElement))\n globalThis.requestAnimationFrame(() => focusIn(8));\n }),\n );\n }\n\n /** The open overlay panels with their elements, most recent last. */\n const openOverlays = (): Array<[WorkbenchOverlayPanel, HTMLElement]> =>\n openOrder.flatMap((panel): Array<[WorkbenchOverlayPanel, HTMLElement]> => {\n const element = panelElement(panel);\n return !panel.collapsed.peek() && element && overlaid(element)\n ? [[panel, element]]\n : [];\n });\n\n const inAllowedPortal = (\n panel: WorkbenchOverlayPanel,\n path: EventTarget[],\n ): boolean => {\n const keepOpenOn = panel.keepOpenOn;\n return Boolean(\n keepOpenOn &&\n path.some((target) => target instanceof Node && keepOpenOn(target)),\n );\n };\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (\n (event.key !== 'Escape' && event.key !== 'Tab') ||\n event.defaultPrevented\n )\n return;\n const open = openOverlays();\n if (open.length === 0) return;\n // A dialog or menu launched from a panel owns its own keyboard handling.\n if (open.some(([panel]) => inAllowedPortal(panel, event.composedPath())))\n return;\n const active = ownerDocument.activeElement;\n const [panel, element] =\n open.find(([, candidate]) => candidate.contains(active)) ??\n open[open.length - 1]!;\n if (event.key === 'Escape') {\n event.preventDefault();\n // The collapse effect returns focus stranded inside it.\n panel.collapsed.value = true;\n return;\n }\n // Tab stays inside the open overlay: it wraps at either end, and focus\n // that is somewhere else (the app moved it, or the panel had no control\n // to take it when it opened) comes back in.\n const items = focusables(element);\n if (items.length === 0) return;\n const first = items[0]!;\n const last = items[items.length - 1]!;\n const inside = element.contains(active);\n if (event.shiftKey && (!inside || active === first)) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && (!inside || active === last)) {\n event.preventDefault();\n first.focus();\n }\n };\n\n // An outside press closes an open overlay when it both starts and ends\n // outside it. Deciding at the click lets an app toggle that closes the panel\n // run first, and a press that opens a panel never closes it.\n let pressed: WorkbenchOverlayPanel[] = [];\n const inside = (\n panel: WorkbenchOverlayPanel,\n element: HTMLElement,\n path: EventTarget[],\n ): boolean => path.includes(element) || inAllowedPortal(panel, path);\n const onPointerdown = (event: PointerEvent): void => {\n const path = event.composedPath();\n pressed = openOverlays()\n .filter(([panel, element]) => !inside(panel, element, path))\n .map(([panel]) => panel);\n // Before the press's default action moves focus: the open panel it\n // started in, when focus was inside that panel too.\n const active = ownerDocument.activeElement;\n pressedFocus = panels.find((panel) => {\n if (panel.collapsed.peek()) return false;\n const element = panelElement(panel);\n return !!element && path.includes(element) && element.contains(active);\n });\n };\n // Focus landing anywhere is a deliberate move the rescue must not undo.\n const onFocusin = (): void => {\n pressedFocus = undefined;\n };\n const onClick = (event: MouseEvent): void => {\n const candidates = pressed;\n pressed = [];\n const path = event.composedPath();\n for (const [panel, element] of openOverlays())\n if (candidates.includes(panel) && !inside(panel, element, path))\n panel.collapsed.value = true;\n };\n const onActivate = (event: MouseEvent): void => {\n const target = event.target;\n const control =\n target instanceof Element\n ? target.closest<HTMLElement>('[aria-controls]')\n : null;\n // Recorded whether or not it took focus: Safari and macOS WebKit never\n // focus a clicked button.\n if (!control) return;\n activated = control;\n // The collapse effect may run after the click's dispatch (the app can\n // batch its write), so keep the control for a couple of frames.\n globalThis.requestAnimationFrame(() =>\n globalThis.requestAnimationFrame(() => {\n if (activated === control) activated = undefined;\n }),\n );\n };\n ownerDocument.addEventListener('keydown', onKeydown);\n ownerDocument.addEventListener('pointerdown', onPointerdown, true);\n ownerDocument.addEventListener('click', onActivate, true);\n ownerDocument.addEventListener('click', onClick);\n ownerDocument.addEventListener('focusin', onFocusin, true);\n disposers.push(() => {\n ownerDocument.removeEventListener('keydown', onKeydown);\n ownerDocument.removeEventListener('pointerdown', onPointerdown, true);\n ownerDocument.removeEventListener('click', onActivate, true);\n ownerDocument.removeEventListener('click', onClick);\n ownerDocument.removeEventListener('focusin', onFocusin, true);\n });\n\n return () => {\n for (const dispose of disposers.splice(0)) dispose();\n for (const panel of panels)\n panelElement(panel)?.removeAttribute('data-responsive-overlay-active');\n // After every observer and effect is gone, so handing the inline state\n // back cannot re-enter the wiring.\n for (const [panel, remembered] of inlineState) {\n const element = panelElement(panel);\n if (element) adapt(panel, element, remembered);\n else panel.collapsed.value = remembered;\n }\n inlineState.clear();\n };\n}\n","import { effect, type ReadonlySignal, type Signal } from 'kerfjs';\n\nimport type { DeviceClass } from '../../../../shared/environment/device-class.js';\nimport {\n type ResizeLimit,\n wireResizeHandles,\n} from '../../resizable-region/internal/resize-wiring.js';\nimport {\n wireWorkbenchOverlays,\n type WorkbenchOverlayPanel,\n} from '../internal/workbench-overlays.js';\nimport {\n type WorkbenchPanelKey,\n workbenchRegionId,\n} from '../internal/workbench-resize.js';\n\nexport type { WorkbenchPanelKey };\n\n/** Minimal `localStorage`-shaped store, so the persistence hook is testable. */\nexport interface WorkbenchStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\n/** One Workbench panel's app-owned state. */\nexport interface WireWorkbenchPanel {\n /**\n * The app-owned size signal a `resizable` panel renders as its `size`.\n * `wireWorkbench` writes each committed resize here; collapsing never\n * touches it, so an expanded panel returns at the size it had. Omit it for\n * a panel that is not resizable.\n */\n size?: Signal<number>;\n /**\n * When set with `size`, the size is loaded from and saved to `storage`\n * under this key, so the panel remembers the user's size.\n */\n storageKey?: string;\n /**\n * The app-owned signal the panel renders as its `collapsed`. With it (and\n * `dismissOverlays`, on by default) `wireWorkbench` treats the panel as a\n * transient overlay while it presents as one: it collapses when its\n * `responsiveOverlayAt` breakpoint begins to apply and gets its inline state\n * back when the breakpoint stops applying, an open overlay takes focus and\n * keeps Tab inside it, and it closes on Escape or a press outside it.\n */\n collapsed?: Signal<boolean>;\n /**\n * Treat presses in a portal surface launched by this panel (for example a\n * body-level menu or dialog) as inside it. The predicate receives each Node\n * in the press's composed path; return true for the portal root. Ordinary\n * presses outside the panel and its allowed surfaces still dismiss it.\n */\n keepOpenOn?: (target: Node) => boolean;\n}\n\n/** A resize the user made, after `wireWorkbench` wrote it to the size signal. */\nexport interface WorkbenchResize {\n panel: WorkbenchPanelKey;\n size: number;\n source: 'keyboard' | 'pointer';\n}\n\nexport interface WireWorkbenchOptions {\n /** The `id` the `Workbench` was rendered with. */\n id: string;\n /**\n * The wired panels, keyed like the `Workbench` props. Render a panel given\n * a `size` with `resizable` and `size={panel.size.value}`, and one given a\n * `collapsed` signal with `collapsed={panel.collapsed.value}`.\n */\n panels: Partial<Record<WorkbenchPanelKey, WireWorkbenchPanel>>;\n /**\n * When provided, resizing is suspended while `deviceClass.compact` is true —\n * the classes where rails become overlay drawers or are replaced.\n */\n deviceClass?: ReadonlySignal<DeviceClass>;\n /** Persistence store (default `globalThis.localStorage`, if present). */\n storage?: WorkbenchStorage;\n /** Keyboard step in px (default 16). */\n step?: number;\n /** Shift+arrow step in px (default 64). */\n largeStep?: number;\n /** Called after each committed resize. */\n onResize?: (change: WorkbenchResize) => void;\n /**\n * Treat the panels given a `collapsed` signal as transient overlays while\n * they present as overlays (default `true`), like `wireSidebar`'s compact\n * overlay: a panel whose `responsiveOverlayAt` breakpoint begins to apply\n * starts collapsed, with no collapse motion, and gets its inline collapsed\n * state back when the breakpoint stops applying (and on disposal); an open\n * overlay panel, responsive or `presentation: \"overlay\"`, closes on Escape\n * or a press that starts and ends outside it. A panel that opens as an\n * overlay takes focus on its first focusable control, and while it is open\n * Tab and Shift+Tab cycle through its controls instead of reaching the\n * work area it covers (the ARIA dialog pattern of `wireSidebar`'s compact\n * overlay); inline panels never move focus. Focus stranded in a closing\n * panel — however it closed, the app's own control inside it included —\n * returns to the control that had it when the panel opened, else to the\n * panel's restore control, else to a control outside the panel whose\n * `aria-controls` names it (each panel's `id` is its region id, e.g.\n * `studio-left-rail`) — the fallback for a panel already open at wire-up.\n * An opener inside a panel that has closed since is skipped. `false` leaves\n * every `collapsed` write and all focus handling to the app.\n */\n dismissOverlays?: boolean;\n /**\n * Keep overlays exclusive (default `true`), like `wireSidebar`'s\n * `exclusiveCompact`: when a panel opens while it presents as an overlay,\n * every other open overlay panel — rails and the bottom drawer alike —\n * closes, so one overlay never covers another's controls. Panels presenting\n * inline are never closed by it. Applies only with `dismissOverlays`.\n */\n exclusiveOverlays?: boolean;\n}\n\nfunction defaultStorage(): WorkbenchStorage | undefined {\n try {\n return globalThis.localStorage ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/** A stored size, or undefined when the stored text is not a usable size. */\nfunction storedSize(text: string | null) {\n if (text === null) return undefined;\n const size = Number(text);\n return Number.isFinite(size) && size > 0 ? Math.round(size) : undefined;\n}\n\n/** A double-quoted CSS attribute-selector value. */\nconst quoted = (value: string) =>\n `\"${value.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')}\"`;\n\nconst px = (value: string) => Number.parseFloat(value) || 0;\n\n/**\n * The largest size a resizable panel may take while the work area keeps its\n * minimum: for a rail, its minimum width (the Workbench's `mainMinSize`,\n * rendered as `data-main-min-size`) — the Workbench width, less that minimum,\n * the other in-flow rails as shown, and the rail's own safe-area extent and\n * border; for the bottom drawer, its minimum height (`mainMinHeight`, rendered\n * as `data-main-min-height`) — the work-area column's height, less that\n * minimum and the drawer's own safe-area extent and border. A panel the\n * container has already squeezed is held at the size it shows, so it can\n * shrink but not grow. Without layout (no box yet) or a minimum, the panel's\n * own maximum stands.\n */\nconst mainRoomLimit: ResizeLimit = (region, { max }) => {\n const horizontal = region.dataset.axis === 'horizontal';\n // A rail's parent is the Workbench; the drawer's is the work-area column.\n const container = region.parentElement;\n const workbench = horizontal ? container : container?.parentElement;\n const mainMin = Number(\n horizontal\n ? workbench?.dataset.mainMinSize\n : workbench?.dataset.mainMinHeight,\n );\n if (!container || !(mainMin > 0)) return max;\n const box = container.getBoundingClientRect();\n const room = horizontal ? box.width : box.height;\n if (room <= 0) return max;\n let others = 0;\n if (horizontal)\n for (const rail of container.children) {\n if (\n rail === region ||\n !rail.matches('.kui-workbench__rail') ||\n globalThis.getComputedStyle(rail).position === 'absolute'\n )\n continue;\n others += rail.getBoundingClientRect().width;\n }\n const style = globalThis.getComputedStyle(region);\n const size = px(region.style.getPropertyValue('--kui-resizable-region-size'));\n const border =\n style.boxSizing === 'border-box'\n ? 0\n : horizontal\n ? px(style.borderInlineStartWidth) + px(style.borderInlineEndWidth)\n : px(style.borderBlockStartWidth) + px(style.borderBlockEndWidth);\n // The track is the size plus the panel's safe-area extent (its flex basis).\n const extent = px(style.flexBasis) - size + border;\n return Math.floor(room - Math.min(mainMin, room) - others - extent);\n};\n\n/**\n * Wire a `Workbench`'s panels. For `resizable` panels given a `size` signal:\n * pointer drags and arrow / Shift+arrow / Home / End on each panel's\n * separator, clamped to the panel's limits and to the room that leaves the\n * work area its minimum width and height, committed to the app-owned size signals.\n * Optional persistence loads and saves each size; optional `deviceClass`\n * suspends resizing on compact classes. Collapse stays the app's `collapsed`\n * flag and never changes a size. For panels given a `collapsed` signal,\n * overlays are transient (`dismissOverlays`): a responsive overlay starts\n * collapsed, an open overlay takes focus and keeps Tab inside it, it closes\n * on Escape or an outside press, and\n * opening one overlay closes the others (`exclusiveOverlays`). Returns a disposer. See `docs/23-app-layouts.md` §3.3.\n */\nexport function wireWorkbench(\n root: HTMLElement,\n {\n id,\n panels,\n deviceClass,\n storage = defaultStorage(),\n step,\n largeStep,\n onResize,\n dismissOverlays = true,\n exclusiveOverlays = true,\n }: WireWorkbenchOptions,\n): () => void {\n const keys = Object.keys(panels) as WorkbenchPanelKey[];\n const entries = keys.flatMap((key) => {\n const size = panels[key]?.size;\n return size\n ? [\n {\n key,\n size,\n storageKey: panels[key]!.storageKey,\n regionId: workbenchRegionId(id, key),\n },\n ]\n : [];\n });\n const byRegion = new Map(entries.map((entry) => [entry.regionId, entry]));\n const disposers: Array<() => void> = [];\n\n // Seed from storage before any effect runs, so the first render after\n // wire-up already has the remembered size; then mirror every size change.\n for (const { size, storageKey } of entries) {\n if (!storageKey || !storage) continue;\n const seed = storedSize(storage.getItem(storageKey));\n if (seed !== undefined) size.value = seed;\n disposers.push(\n effect(() => {\n storage.setItem(storageKey, String(size.value));\n }),\n );\n }\n\n // Each panel is matched by its own region id, so this wiring never drives a\n // ResizableRegion or another Workbench below the same root.\n const selector = entries\n .map(\n ({ regionId }) =>\n `[data-resizable=\"true\"][data-region-id=${quoted(regionId)}]`,\n )\n .join(', ');\n const start = () =>\n wireResizeHandles(\n root,\n {\n step,\n largeStep,\n onCommit: ({ id: regionId, size, source }) => {\n // The selector only matches configured panels.\n const entry = byRegion.get(regionId)!;\n entry.size.value = size;\n onResize?.({ panel: entry.key, size, source });\n },\n },\n selector,\n mainRoomLimit,\n );\n\n let stopResize: (() => void) | undefined;\n if (selector) {\n if (deviceClass) {\n disposers.push(\n effect(() => {\n const compact = deviceClass.value.compact;\n stopResize?.();\n stopResize = compact ? undefined : start();\n }),\n );\n } else {\n stopResize = start();\n }\n }\n\n const overlayPanels = keys.flatMap((key): WorkbenchOverlayPanel[] => {\n const collapsed = panels[key]?.collapsed;\n return collapsed\n ? [{ key, collapsed, keepOpenOn: panels[key]?.keepOpenOn }]\n : [];\n });\n if (dismissOverlays && overlayPanels.length > 0) {\n const selector = `[data-component=\"workbench\"][id=${quoted(id)}]`;\n disposers.push(\n wireWorkbenchOverlays(\n root,\n () =>\n root.matches(selector)\n ? root\n : root.querySelector<HTMLElement>(selector),\n overlayPanels,\n exclusiveOverlays,\n ),\n );\n }\n\n return () => {\n stopResize?.();\n stopResize = undefined;\n for (const dispose of disposers.splice(0)) dispose();\n };\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { paneConfigProps } from './chunk-CTQUDCY5.js';
2
- import { ToolbarControlGroup, isRelocatableGroup } from './chunk-2PXZBFEC.js';
3
- import { Toolbar } from './chunk-CMLPFIC5.js';
2
+ import { ToolbarControlGroup, isRelocatableGroup } from './chunk-5J6Z4BWY.js';
3
+ import { Toolbar } from './chunk-ZN7KUMPY.js';
4
4
  import { Pane } from './chunk-HQZG3OFL.js';
5
- import { List } from './chunk-OY2MXIBB.js';
5
+ import { List } from './chunk-NB6POCFH.js';
6
6
  import { LucideIcon } from './chunk-HJXVVFBT.js';
7
7
  import { PanelLeftOpen, PanelLeftClose, PanelRightOpen, PanelRightClose, PanelBottomOpen, PanelBottomClose } from 'lucide';
8
8
  import { jsx, jsxs, Fragment } from 'kerfjs/jsx-runtime';
@@ -159,4 +159,4 @@ function relocatedPanelGroups(toolbar, side, collapsed, attributes, size = "defa
159
159
 
160
160
  export { collapsiblePanelToggleIcon, composedPanelBody, groupSizeFor, panelToggleGroup, relocatedPanelGroups };
161
161
 
162
- //# sourceMappingURL=chunk-DNWWF6UN.js.map
162
+ //# sourceMappingURL=chunk-WSEJ2FDE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/panels/panel-toolbar.tsx"],"names":[],"mappings":"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","file":"chunk-DNWWF6UN.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport {\n PanelBottomClose,\n PanelBottomOpen,\n PanelLeftClose,\n PanelLeftOpen,\n PanelRightClose,\n PanelRightOpen,\n} from 'lucide';\n\nimport {\n Toolbar,\n type ToolbarConfig,\n} from '../../components/actions/toolbar/toolbar.js';\nimport {\n ToolbarControlGroup,\n type ToolbarControlGroupSize,\n} from '../../components/actions/toolbar-control-group/toolbar-control-group.js';\nimport {\n List,\n type ListConfig,\n} from '../../components/collections/list/list.js';\nimport { paneConfigProps } from '../../components/layout/pane/internal/pane-config-props.js';\nimport { Pane, type PaneConfig } from '../../components/layout/pane/pane.js';\nimport { LucideIcon } from '../../components/media/lucide-icon/lucide-icon.js';\nimport type { KerfUiContent } from '../content/semantic-content.js';\nimport { isRelocatableGroup } from './panel-toolbar-group.js';\n\n/** Which edge a collapsible panel docks to. */\nexport type PanelSide = 'left' | 'right' | 'bottom';\n\n/**\n * The standard collapse/expand icon for a panel `side` and `collapsed` state,\n * so every app's sidebars and drawers use one recognizable convention:\n * `PanelLeft*` for a left rail, `PanelRight*` for a right rail, `PanelBottom*`\n * for a bottom drawer — the `Close` glyph while open, the `Open` glyph while\n * collapsed. Exposed so an app can render its own toggle affordance.\n */\nexport function collapsiblePanelToggleIcon(\n side: PanelSide,\n collapsed: boolean,\n): { icon: Parameters<typeof LucideIcon>[0]['icon']; name: string } {\n if (side === 'left')\n return collapsed\n ? { icon: PanelLeftOpen, name: 'panel-left-open' }\n : { icon: PanelLeftClose, name: 'panel-left-close' };\n if (side === 'right')\n return collapsed\n ? { icon: PanelRightOpen, name: 'panel-right-open' }\n : { icon: PanelRightClose, name: 'panel-right-close' };\n return collapsed\n ? { icon: PanelBottomOpen, name: 'panel-bottom-open' }\n : { icon: PanelBottomClose, name: 'panel-bottom-close' };\n}\n\n/**\n * The standard collapse toggle a panel toolbar renders. The app handles the\n * button's `data-action` and flips its own `collapsed` flag.\n */\nexport interface PanelToggle {\n /** The `data-action` the toggle button carries. */\n action: string;\n /**\n * The panel's short title-style name (\"Navigator\", \"Build Output\"). It is\n * the toggle group's accessible name and completes the default \"Show …\" /\n * \"Hide …\" label (\"Show Navigator\"), so it follows the title-style rule in\n * `docs/writing.md`; it is never recapitalized.\n */\n name: string;\n /** Accessible label while the panel is collapsed. Defaults to `Show {name}`. */\n showLabel?: string;\n /** Accessible label while the panel is open. Defaults to `Hide {name}`. */\n hideLabel?: string;\n}\n\n/**\n * A collapsible panel's top toolbar, composed so its groups follow the\n * panel's open state.\n *\n * - `title` precedes the `leading` zone. Groups may appear in any of the\n * `leading`, `center`, and `trailing` zones while the panel is open.\n * - Groups marked `relocateOnCollapse` move to the work area's toolbar while\n * the panel is collapsed, preserving their order across the three zones.\n * - `toggle` is always the last group: in the panel's toolbar while it is\n * open, and right after the relocated groups in the work area's toolbar\n * while it is collapsed.\n *\n * Relocated content renders in both places while the panel is collapsed (the\n * panel's copy is inert), so give it no `id`s. Pass groups directly or in\n * arrays so their render-time annotation remains available to the panel.\n *\n * The toolbar's configuration (`dividerSides`, `centerAlign`, `responsive`,\n * `responsiveAt`, `safeAreaEdges`) forwards to its `Toolbar`. It draws no\n * divider of its own: the panel's `Pane` draws the line under it while the\n * content is scrolled (its `chromeDividers`, wired by `wireScrollDividers`).\n */\nexport interface PanelToolbar extends ToolbarConfig {\n /** Accessible name of the panel's toolbar. */\n label: string;\n title?: KerfUiContent;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n toggle?: PanelToggle;\n}\n\n/** A panel's fixed bottom toolbar, below its optional footer content. */\nexport interface PanelBottomToolbar extends ToolbarConfig {\n label: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n}\n\n/** Whether panel chrome stays fixed, scrolls, or follows Pane's auto rule. */\nexport type PanelChromePlacement = 'fixed' | 'scroll' | 'auto';\n\nfunction panelChromeList(content: KerfUiContent, config?: ListConfig) {\n return (\n <List\n dividerSides={config?.dividerSides}\n gap={config?.gap}\n hAlign={config?.hAlign}\n vAlign={config?.vAlign}\n textInsets={config?.textInsets}\n controlInsets={config?.controlInsets}\n >\n {content}\n </List>\n );\n}\n\n/** Owner-specific attributes a toggle button carries (its wiring hooks). */\nexport type PanelToggleAttributes = Readonly<Record<string, string>>;\n\n/** The group size that fits a toolbar of this density. */\nexport function groupSizeFor(\n density: ToolbarConfig['density'],\n): ToolbarControlGroupSize {\n return density === 'compact' ? 'compact' : 'default';\n}\n\n/** The standard toggle, alone in a borderless group. */\nexport function panelToggleGroup(\n side: PanelSide,\n toggle: PanelToggle,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): SafeHtml {\n const glyph = collapsiblePanelToggleIcon(side, collapsed);\n return (\n <ToolbarControlGroup\n label={toggle.name}\n appearance=\"borderless\"\n size={size}\n single\n >\n <button\n type=\"button\"\n {...attributes}\n data-action={toggle.action}\n aria-expanded={String(!collapsed)}\n aria-label={\n collapsed\n ? (toggle.showLabel ?? `Show ${toggle.name}`)\n : (toggle.hideLabel ?? `Hide ${toggle.name}`)\n }\n >\n <LucideIcon icon={glyph.icon} name={glyph.name} />\n </button>\n </ToolbarControlGroup>\n );\n}\n\n/**\n * The panel's own toolbar: content keeps its chosen zones and the toggle trails.\n */\nexport function composedPanelToolbar(\n toolbar: PanelToolbar,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n): SafeHtml {\n return (\n <Toolbar\n label={toolbar.label}\n density={toolbar.density}\n dividerSides={toolbar.dividerSides}\n centerAlign={toolbar.centerAlign}\n responsive={toolbar.responsive}\n responsiveAt={toolbar.responsiveAt}\n safeAreaEdges={toolbar.safeAreaEdges}\n center={toolbar.center}\n leading={\n <>\n {toolbar.title}\n {toolbar.leading}\n </>\n }\n trailing={\n <>\n {toolbar.trailing}\n {toolbar.toggle\n ? panelToggleGroup(\n side,\n toolbar.toggle,\n collapsed,\n attributes,\n groupSizeFor(toolbar.density),\n )\n : null}\n </>\n }\n />\n );\n}\n\n/**\n * A toolbar panel's body: its content in a `Pane` under its composed toolbar,\n * with its optional `footer` below. The panel's `pane` configuration forwards\n * to that `Pane`; an omitted or `undefined` field keeps the `Pane` default.\n */\nexport function composedPanelBody({\n toolbar,\n side,\n collapsed,\n attributes,\n pane,\n header,\n headerList,\n headerPlacement = 'fixed',\n footer,\n footerList,\n bottomToolbar,\n footerPlacement = 'fixed',\n content,\n}: {\n toolbar: PanelToolbar;\n side: PanelSide;\n collapsed: boolean;\n attributes: PanelToggleAttributes;\n pane: PaneConfig | undefined;\n header?: KerfUiContent;\n headerList?: ListConfig;\n headerPlacement?: PanelChromePlacement;\n footer?: KerfUiContent;\n footerList?: ListConfig;\n bottomToolbar?: PanelBottomToolbar;\n footerPlacement?: PanelChromePlacement;\n content: KerfUiContent;\n}): SafeHtml {\n const panelHeader = (\n <>\n {composedPanelToolbar(toolbar, side, collapsed, attributes)}\n {header ? panelChromeList(header, headerList) : null}\n </>\n );\n const panelFooter =\n footer || bottomToolbar ? (\n <>\n {footer ? panelChromeList(footer, footerList) : null}\n {bottomToolbar ? (\n <Toolbar\n position=\"footer\"\n label={bottomToolbar.label}\n density={bottomToolbar.density}\n dividerSides={bottomToolbar.dividerSides}\n centerAlign={bottomToolbar.centerAlign}\n responsive={bottomToolbar.responsive}\n responsiveAt={bottomToolbar.responsiveAt}\n safeAreaEdges={bottomToolbar.safeAreaEdges}\n leading={bottomToolbar.leading}\n center={bottomToolbar.center}\n trailing={bottomToolbar.trailing}\n />\n ) : null}\n </>\n ) : undefined;\n const scrollHeader = headerPlacement === 'scroll';\n const scrollFooter = footerPlacement === 'scroll';\n return (\n <Pane\n header={scrollHeader ? undefined : panelHeader}\n footer={scrollFooter ? undefined : panelFooter}\n chromePlacement={\n headerPlacement === 'auto' || footerPlacement === 'auto'\n ? 'auto'\n : 'fixed'\n }\n {...paneConfigProps(pane)}\n >\n {scrollHeader ? panelHeader : null}\n {content}\n {scrollFooter ? panelFooter : null}\n </Pane>\n );\n}\n\n/**\n * The groups a collapsed panel hands to the work area, in zone order, then its\n * toggle. Empty while the panel is open or has no toolbar.\n */\nexport function relocatedPanelGroups(\n toolbar: PanelToolbar | undefined,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): KerfUiContent[] {\n if (!collapsed || !toolbar) return [];\n const groups: KerfUiContent[] = [];\n const collect = (content: KerfUiContent): void => {\n if (Array.isArray(content)) {\n for (const item of content) collect(item);\n } else if (isRelocatableGroup(content)) {\n groups.push(content);\n }\n };\n collect(toolbar.leading);\n collect(toolbar.center);\n collect(toolbar.trailing);\n return [\n ...groups,\n toolbar.toggle\n ? panelToggleGroup(side, toolbar.toggle, true, attributes, size)\n : null,\n ].filter((group) => group !== undefined && group !== null && group !== false);\n}\n"]}
1
+ {"version":3,"sources":["../src/shared/panels/panel-toolbar.tsx"],"names":[],"mappings":"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","file":"chunk-WSEJ2FDE.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\nimport {\n PanelBottomClose,\n PanelBottomOpen,\n PanelLeftClose,\n PanelLeftOpen,\n PanelRightClose,\n PanelRightOpen,\n} from 'lucide';\n\nimport {\n Toolbar,\n type ToolbarConfig,\n} from '../../components/actions/toolbar/toolbar.js';\nimport {\n ToolbarControlGroup,\n type ToolbarControlGroupSize,\n} from '../../components/actions/toolbar-control-group/toolbar-control-group.js';\nimport {\n List,\n type ListConfig,\n} from '../../components/collections/list/list.js';\nimport { paneConfigProps } from '../../components/layout/pane/internal/pane-config-props.js';\nimport { Pane, type PaneConfig } from '../../components/layout/pane/pane.js';\nimport { LucideIcon } from '../../components/media/lucide-icon/lucide-icon.js';\nimport type { KerfUiContent } from '../content/semantic-content.js';\nimport { isRelocatableGroup } from './panel-toolbar-group.js';\n\n/** Which edge a collapsible panel docks to. */\nexport type PanelSide = 'left' | 'right' | 'bottom';\n\n/**\n * The standard collapse/expand icon for a panel `side` and `collapsed` state,\n * so every app's sidebars and drawers use one recognizable convention:\n * `PanelLeft*` for a left rail, `PanelRight*` for a right rail, `PanelBottom*`\n * for a bottom drawer — the `Close` glyph while open, the `Open` glyph while\n * collapsed. Exposed so an app can render its own toggle affordance.\n */\nexport function collapsiblePanelToggleIcon(\n side: PanelSide,\n collapsed: boolean,\n): { icon: Parameters<typeof LucideIcon>[0]['icon']; name: string } {\n if (side === 'left')\n return collapsed\n ? { icon: PanelLeftOpen, name: 'panel-left-open' }\n : { icon: PanelLeftClose, name: 'panel-left-close' };\n if (side === 'right')\n return collapsed\n ? { icon: PanelRightOpen, name: 'panel-right-open' }\n : { icon: PanelRightClose, name: 'panel-right-close' };\n return collapsed\n ? { icon: PanelBottomOpen, name: 'panel-bottom-open' }\n : { icon: PanelBottomClose, name: 'panel-bottom-close' };\n}\n\n/**\n * The standard collapse toggle a panel toolbar renders. The app handles the\n * button's `data-action` and flips its own `collapsed` flag.\n */\nexport interface PanelToggle {\n /** The `data-action` the toggle button carries. */\n action: string;\n /**\n * The panel's short title-style name (\"Navigator\", \"Build Output\"). It is\n * the toggle group's accessible name and completes the default \"Show …\" /\n * \"Hide …\" label (\"Show Navigator\"), so it follows the title-style rule in\n * `docs/writing.md`; it is never recapitalized.\n */\n name: string;\n /** Accessible label while the panel is collapsed. Defaults to `Show {name}`. */\n showLabel?: string;\n /** Accessible label while the panel is open. Defaults to `Hide {name}`. */\n hideLabel?: string;\n}\n\n/**\n * A collapsible panel's top toolbar, composed so its groups follow the\n * panel's open state.\n *\n * - `title` precedes the `leading` zone. Groups may appear in any of the\n * `leading`, `center`, and `trailing` zones while the panel is open.\n * - Groups marked `relocateOnCollapse` move to the work area's toolbar while\n * the panel is collapsed, preserving their order across the three zones.\n * - `toggle` is always the last group: in the panel's toolbar while it is\n * open, and right after the relocated groups in the work area's toolbar\n * while it is collapsed.\n *\n * Relocated content renders in both places while the panel is collapsed (the\n * panel's copy is inert), so give it no `id`s. Pass groups directly or in\n * arrays so their render-time annotation remains available to the panel.\n *\n * The toolbar's configuration (`dividerSides`, `centerAlign`, `responsive`,\n * `responsiveAt`, `safeAreaEdges`) forwards to its `Toolbar`. It draws no\n * divider of its own: the panel's `Pane` draws the line under it while the\n * content is scrolled (its `chromeDividers`, wired by `wireScrollDividers`).\n */\nexport interface PanelToolbar extends ToolbarConfig {\n /** Accessible name of the panel's toolbar. */\n label: string;\n title?: KerfUiContent;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n toggle?: PanelToggle;\n}\n\n/** A panel's fixed bottom toolbar, below its optional footer content. */\nexport interface PanelBottomToolbar extends ToolbarConfig {\n label: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n}\n\n/** Whether panel chrome stays fixed, scrolls, or follows Pane's auto rule. */\nexport type PanelChromePlacement = 'fixed' | 'scroll' | 'auto';\n\nfunction panelChromeList(content: KerfUiContent, config?: ListConfig) {\n return (\n <List\n dividerSides={config?.dividerSides}\n gap={config?.gap}\n hAlign={config?.hAlign}\n vAlign={config?.vAlign}\n textInsets={config?.textInsets}\n controlInsets={config?.controlInsets}\n >\n {content}\n </List>\n );\n}\n\n/** Owner-specific attributes a toggle button carries (its wiring hooks). */\nexport type PanelToggleAttributes = Readonly<Record<string, string>>;\n\n/** The group size that fits a toolbar of this density. */\nexport function groupSizeFor(\n density: ToolbarConfig['density'],\n): ToolbarControlGroupSize {\n return density === 'compact' ? 'compact' : 'default';\n}\n\n/** The standard toggle, alone in a borderless group. */\nexport function panelToggleGroup(\n side: PanelSide,\n toggle: PanelToggle,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): SafeHtml {\n const glyph = collapsiblePanelToggleIcon(side, collapsed);\n return (\n <ToolbarControlGroup\n label={toggle.name}\n appearance=\"borderless\"\n size={size}\n single\n >\n <button\n type=\"button\"\n {...attributes}\n data-action={toggle.action}\n aria-expanded={String(!collapsed)}\n aria-label={\n collapsed\n ? (toggle.showLabel ?? `Show ${toggle.name}`)\n : (toggle.hideLabel ?? `Hide ${toggle.name}`)\n }\n >\n <LucideIcon icon={glyph.icon} name={glyph.name} />\n </button>\n </ToolbarControlGroup>\n );\n}\n\n/**\n * The panel's own toolbar: content keeps its chosen zones and the toggle trails.\n */\nexport function composedPanelToolbar(\n toolbar: PanelToolbar,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n): SafeHtml {\n return (\n <Toolbar\n label={toolbar.label}\n density={toolbar.density}\n dividerSides={toolbar.dividerSides}\n centerAlign={toolbar.centerAlign}\n responsive={toolbar.responsive}\n responsiveAt={toolbar.responsiveAt}\n safeAreaEdges={toolbar.safeAreaEdges}\n center={toolbar.center}\n leading={\n <>\n {toolbar.title}\n {toolbar.leading}\n </>\n }\n trailing={\n <>\n {toolbar.trailing}\n {toolbar.toggle\n ? panelToggleGroup(\n side,\n toolbar.toggle,\n collapsed,\n attributes,\n groupSizeFor(toolbar.density),\n )\n : null}\n </>\n }\n />\n );\n}\n\n/**\n * A toolbar panel's body: its content in a `Pane` under its composed toolbar,\n * with its optional `footer` below. The panel's `pane` configuration forwards\n * to that `Pane`; an omitted or `undefined` field keeps the `Pane` default.\n */\nexport function composedPanelBody({\n toolbar,\n side,\n collapsed,\n attributes,\n pane,\n header,\n headerList,\n headerPlacement = 'fixed',\n footer,\n footerList,\n bottomToolbar,\n footerPlacement = 'fixed',\n content,\n}: {\n toolbar: PanelToolbar;\n side: PanelSide;\n collapsed: boolean;\n attributes: PanelToggleAttributes;\n pane: PaneConfig | undefined;\n header?: KerfUiContent;\n headerList?: ListConfig;\n headerPlacement?: PanelChromePlacement;\n footer?: KerfUiContent;\n footerList?: ListConfig;\n bottomToolbar?: PanelBottomToolbar;\n footerPlacement?: PanelChromePlacement;\n content: KerfUiContent;\n}): SafeHtml {\n const panelHeader = (\n <>\n {composedPanelToolbar(toolbar, side, collapsed, attributes)}\n {header ? panelChromeList(header, headerList) : null}\n </>\n );\n const panelFooter =\n footer || bottomToolbar ? (\n <>\n {footer ? panelChromeList(footer, footerList) : null}\n {bottomToolbar ? (\n <Toolbar\n position=\"footer\"\n label={bottomToolbar.label}\n density={bottomToolbar.density}\n dividerSides={bottomToolbar.dividerSides}\n centerAlign={bottomToolbar.centerAlign}\n responsive={bottomToolbar.responsive}\n responsiveAt={bottomToolbar.responsiveAt}\n safeAreaEdges={bottomToolbar.safeAreaEdges}\n leading={bottomToolbar.leading}\n center={bottomToolbar.center}\n trailing={bottomToolbar.trailing}\n />\n ) : null}\n </>\n ) : undefined;\n const scrollHeader = headerPlacement === 'scroll';\n const scrollFooter = footerPlacement === 'scroll';\n return (\n <Pane\n header={scrollHeader ? undefined : panelHeader}\n footer={scrollFooter ? undefined : panelFooter}\n chromePlacement={\n headerPlacement === 'auto' || footerPlacement === 'auto'\n ? 'auto'\n : 'fixed'\n }\n {...paneConfigProps(pane)}\n >\n {scrollHeader ? panelHeader : null}\n {content}\n {scrollFooter ? panelFooter : null}\n </Pane>\n );\n}\n\n/**\n * The groups a collapsed panel hands to the work area, in zone order, then its\n * toggle. Empty while the panel is open or has no toolbar.\n */\nexport function relocatedPanelGroups(\n toolbar: PanelToolbar | undefined,\n side: PanelSide,\n collapsed: boolean,\n attributes: PanelToggleAttributes,\n size: ToolbarControlGroupSize = 'default',\n): KerfUiContent[] {\n if (!collapsed || !toolbar) return [];\n const groups: KerfUiContent[] = [];\n const collect = (content: KerfUiContent): void => {\n if (Array.isArray(content)) {\n for (const item of content) collect(item);\n } else if (isRelocatableGroup(content)) {\n groups.push(content);\n }\n };\n collect(toolbar.leading);\n collect(toolbar.center);\n collect(toolbar.trailing);\n return [\n ...groups,\n toolbar.toggle\n ? panelToggleGroup(side, toolbar.toggle, true, attributes, size)\n : null,\n ].filter((group) => group !== undefined && group !== null && group !== false);\n}\n"]}
@@ -24,6 +24,9 @@ function TextField({
24
24
  maxLength,
25
25
  showCount = false,
26
26
  type = "text",
27
+ min,
28
+ max,
29
+ step,
27
30
  multiline = false,
28
31
  rows = 3,
29
32
  maxRows,
@@ -85,7 +88,10 @@ function TextField({
85
88
  ...shared,
86
89
  class: "kui-text-field__input",
87
90
  type,
88
- value
91
+ value,
92
+ min: type === "number" ? min : void 0,
93
+ max: type === "number" ? max : void 0,
94
+ step: type === "number" ? step : void 0
89
95
  }
90
96
  ),
91
97
  clearable && !multiline ? /* @__PURE__ */ jsx(
@@ -112,4 +118,4 @@ function TextField({
112
118
 
113
119
  export { TextField };
114
120
 
115
- //# sourceMappingURL=chunk-WU57BYYM.js.map
121
+ //# sourceMappingURL=chunk-YVZCKXR3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/forms/text-field/text-field.tsx"],"names":[],"mappings":"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","file":"chunk-YVZCKXR3.js","sourcesContent":["import { CircleX } from 'lucide';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { filterDataAttributes } from '../../../shared/dom/extension-attributes.js';\nimport { LucideIcon } from '../../media/lucide-icon/lucide-icon.js';\n\n/** `default` is the 44px control height; `compact` is 33px with smaller text. */\nexport type TextFieldSize = 'default' | 'compact';\n\n/** The kinds of single-line value a TextField takes. */\nexport type TextFieldType =\n 'text' | 'email' | 'password' | 'search' | 'url' | 'tel' | 'number';\n\nconst TEXT_FIELD_PROTECTED = new Set([\n 'data-component',\n 'data-size',\n 'data-invalid',\n 'data-multiline',\n]);\n\n/** Application `data-*` metadata; the TextField's own markers stay protected. */\nexport type TextFieldRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined>\n>;\n\n/**\n * The field's accessible name: a visible `label`, or `ariaLabel` when the\n * surrounding content already names it.\n */\nexport type TextFieldName =\n { label: string; ariaLabel?: never } | { label?: never; ariaLabel: string };\n\nexport type TextFieldProps = TextFieldName & TextFieldOptions;\n\nexport interface TextFieldOptions {\n /** The controlled value. */\n value?: string;\n name?: string;\n placeholder?: string;\n /** Supporting text below the field, also its accessible description. */\n hint?: string;\n /**\n * A validation message: shown below the field in the danger color, added\n * to its description, and marking it `aria-invalid`.\n */\n error?: string;\n size?: TextFieldSize;\n /** A leading decorative icon, such as a `LucideIcon` (single-line only). */\n icon?: KerfUiContent;\n /**\n * A clear button while the field has a value (single-line only). Needs\n * `wireTextFields(root)`, which clears the field and announces `input`.\n */\n clearable?: boolean;\n /** The clear button's accessible name (default `Clear`). */\n clearLabel?: string;\n /** The most characters the field accepts (native `maxlength`). */\n maxLength?: number;\n /**\n * Show a live `count / maxLength` below the field. Needs `maxLength` and\n * `wireTextFields(root)`, which updates it as people type.\n */\n showCount?: boolean;\n /** Single-line value kind (default `text`). */\n type?: TextFieldType;\n /** Native lower bound for `type=\"number\"` (number or numeric string). */\n min?: number | string;\n /** Native upper bound for `type=\"number\"` (number or numeric string). */\n max?: number | string;\n /** Native number increment (number, numeric string, or `\"any\"`). */\n step?: number | string;\n /** A multi-line field: a `<textarea>`. */\n multiline?: boolean;\n /** A multi-line field's height in lines (default 3). */\n rows?: number;\n /**\n * Grow a multi-line field with its content from `rows` up to this many\n * lines, then scroll.\n */\n maxRows?: number;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n autocomplete?: string;\n /** The input's id, for an external label or form. */\n id?: string;\n className?: string;\n /** Safe `data-*` metadata (a `data-key`). */\n rootAttributes?: TextFieldRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A text input with its label above, an optional leading icon and clear\n * button, and supporting or error text below, at the 44px control height or\n * compact. `multiline` makes it a textarea that can grow with its content.\n * The whole field is one `<label>`, so clicking anywhere on it focuses the\n * input; the input is named by `label` (or `ariaLabel`) directly.\n */\nexport function TextField({\n label,\n ariaLabel,\n value,\n name,\n placeholder,\n hint,\n error,\n size = 'default',\n icon,\n clearable = false,\n clearLabel = 'Clear',\n maxLength,\n showCount = false,\n type = 'text',\n min,\n max,\n step,\n multiline = false,\n rows = 3,\n maxRows,\n disabled = false,\n readOnly = false,\n required = false,\n autocomplete,\n id,\n className = '',\n rootAttributes = {},\n slot,\n}: TextFieldProps) {\n const description = [hint, error].filter(Boolean).join(' ') || undefined;\n const shared = {\n id,\n name,\n // A clearable field always has a placeholder, so CSS can hide its clear\n // button while the field is empty (`:placeholder-shown`); a blank one\n // shows nothing.\n placeholder: clearable && !multiline ? (placeholder ?? ' ') : placeholder,\n disabled,\n readonly: readOnly,\n required,\n autocomplete,\n maxlength: maxLength,\n // The label element also wraps the clear button and the count, so the\n // input takes its name explicitly rather than from the label's text.\n 'aria-label': label ?? ariaLabel,\n 'aria-description': description,\n 'aria-invalid': error ? 'true' : undefined,\n } as const;\n const hintText =\n hint === undefined ? null : (\n <span class=\"kui-text-field__hint\" aria-hidden=\"true\">\n {hint}\n </span>\n );\n const count =\n showCount && maxLength !== undefined\n ? `${String((value ?? '').length)} / ${String(maxLength)}`\n : undefined;\n const style = [\n multiline ? `--_kui-text-field-rows:${String(rows)}` : '',\n multiline && maxRows !== undefined\n ? `--_kui-text-field-max-rows:${String(Math.max(rows, maxRows))}`\n : '',\n ]\n .filter(Boolean)\n .join(';');\n return (\n <label\n {...filterDataAttributes(rootAttributes, TEXT_FIELD_PROTECTED)}\n class={`kui-text-field ${className}`.trim()}\n data-component=\"text-field\"\n data-size={size}\n data-invalid={error ? '' : undefined}\n data-multiline={\n multiline ? (maxRows === undefined ? '' : 'grow') : undefined\n }\n style={style || undefined}\n slot={slot}\n >\n {label === undefined ? null : (\n <span class=\"kui-text-field__label\" aria-hidden=\"true\">\n {label}\n {required ? (\n <span class=\"kui-text-field__required\" aria-hidden=\"true\">\n *\n </span>\n ) : null}\n </span>\n )}\n <span class=\"kui-text-field__box\">\n {icon === undefined || multiline ? null : (\n <span class=\"kui-text-field__icon\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n {multiline ? (\n <textarea {...shared} class=\"kui-text-field__input\" rows={rows}>\n {value ?? ''}\n </textarea>\n ) : (\n <input\n {...shared}\n class=\"kui-text-field__input\"\n type={type}\n value={value}\n min={type === 'number' ? min : undefined}\n max={type === 'number' ? max : undefined}\n step={type === 'number' ? step : undefined}\n />\n )}\n {clearable && !multiline ? (\n <button\n type=\"button\"\n class=\"kui-text-field__clear\"\n aria-label={clearLabel}\n data-text-field-clear=\"\"\n disabled={disabled || readOnly}\n >\n <LucideIcon icon={CircleX} name=\"circle-x\" />\n </button>\n ) : null}\n </span>\n {count === undefined ? (\n hintText\n ) : (\n <span class=\"kui-text-field__footer\">\n {hintText}\n <span class=\"kui-text-field__count\" data-text-field-count=\"\">\n {count}\n </span>\n </span>\n )}\n {error === undefined ? null : (\n <span class=\"kui-text-field__error\" aria-hidden=\"true\">\n {error}\n </span>\n )}\n </label>\n );\n}\n"]}
@@ -3,6 +3,7 @@ import { jsx, jsxs, Fragment } from 'kerfjs/jsx-runtime';
3
3
  // src/components/actions/toolbar/toolbar.tsx
4
4
  var claim = (edges, side) => edges?.includes(side) ? "true" : void 0;
5
5
  function Toolbar({
6
+ id,
6
7
  leading,
7
8
  center,
8
9
  trailing,
@@ -18,6 +19,7 @@ function Toolbar({
18
19
  slot
19
20
  }) {
20
21
  const attributes = {
22
+ id,
21
23
  class: `kui-toolbar ${className}`.trim(),
22
24
  "data-component": "toolbar",
23
25
  "data-density": density === "compact" ? "compact" : void 0,
@@ -43,4 +45,4 @@ function Toolbar({
43
45
 
44
46
  export { Toolbar };
45
47
 
46
- //# sourceMappingURL=chunk-CMLPFIC5.js.map
48
+ //# sourceMappingURL=chunk-ZN7KUMPY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/actions/toolbar/toolbar.tsx"],"names":[],"mappings":";;;AAyFA,IAAM,KAAA,GAAQ,CACZ,KAAA,EACA,IAAA,KACI,OAAO,QAAA,CAAS,IAAI,IAAI,MAAA,GAAS,MAAA;AAEhC,SAAS,OAAA,CAAQ;AAAA,EACtB,EAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA,GAAW,QAAA;AAAA,EACX,OAAA,GAAU,SAAA;AAAA,EACV,YAAA,GAAe,EAAA;AAAA,EACf,WAAA,GAAc,QAAA;AAAA,EACd,UAAA,GAAa,MAAA;AAAA,EACb,YAAA,GAAe,QAAA;AAAA,EACf,aAAA;AAAA,EACA,SAAA,GAAY,EAAA;AAAA,EACZ;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,EAAA;AAAA,IACA,KAAA,EAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,IACvC,gBAAA,EAAkB,SAAA;AAAA,IAClB,cAAA,EAAgB,OAAA,KAAY,SAAA,GAAY,SAAA,GAAY,MAAA;AAAA,IACpD,iBAAiB,YAAA,IAAgB,MAAA;AAAA,IACjC,iBAAA,EAAmB,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AAAA,IACzC,mBAAA,EAAqB,WAAA;AAAA,IACrB,iBAAA,EAAmB,UAAA;AAAA,IACnB,oBAAA,EAAsB,YAAA;AAAA,IACtB,4BAAA,EAA8B,KAAA,CAAM,aAAA,EAAe,aAAa,CAAA;AAAA,IAChE,0BAAA,EAA4B,KAAA,CAAM,aAAA,EAAe,WAAW,CAAA;AAAA,IAC5D,6BAAA,EAA+B,KAAA,CAAM,aAAA,EAAe,cAAc,CAAA;AAAA,IAClE,2BAAA,EAA6B,KAAA,CAAM,aAAA,EAAe,YAAY,CAAA;AAAA,IAC9D,YAAA,EAAc,KAAA;AAAA,IACd;AAAA,GACF;AACA,EAAA,MAAM,wBACJ,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,sBAAA,EAAwB,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,oBAC3C,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,qBAAA,EAAuB,QAAA,EAAA,MAAA,EAAO,CAAA;AAAA,oBACzC,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAyB,QAAA,EAAA,QAAA,EAAS;AAAA,GAAA,EAC/C,CAAA;AAEF,EAAA,OAAO,QAAA,KAAa,QAAA,mBAClB,GAAA,CAAC,QAAA,EAAA,EAAQ,GAAG,UAAA,EAAa,QAAA,EAAA,KAAA,EAAM,CAAA,mBAE/B,GAAA,CAAC,QAAA,EAAA,EAAQ,GAAG,UAAA,EAAa,QAAA,EAAA,KAAA,EAAM,CAAA;AAEnC","file":"chunk-ZN7KUMPY.js","sourcesContent":["import type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport type { Sides } from '../../../shared/layout/sides.js';\nimport type { PaneSeparatorSide } from '../../layout/pane/pane.js';\n\nexport type ToolbarPosition = 'header' | 'footer';\n/** Control-band density: `default` (60px with 44px groups) or `compact`. */\nexport type ToolbarDensity = 'default' | 'compact';\n\nexport interface ToolbarProps {\n /**\n * The toolbar's id, so app code can address it: name it as a scrolling\n * List's chrome in `wireScrollDividers({ targets })`, or find it in tests.\n */\n id?: string;\n leading?: KerfUiContent;\n center?: KerfUiContent;\n trailing?: KerfUiContent;\n label?: string;\n /** Use footer semantics for a bottom toolbar; defaults to header. */\n position?: ToolbarPosition;\n /**\n * `compact` sizes the toolbar to a 34px control band with 3px block\n * insets — 40px tall — for a header embedded in a panel or card. Fill it\n * with `ToolbarControlGroup size=\"compact\"` groups; inline insets and the\n * gap between zones are unchanged. Composites that render a Toolbar from a\n * `ToolbarConfig` (Workbench, CollapsiblePanel, NavStack, SplitView) forward\n * it and size the groups they compose to match. Defaults to `default`.\n */\n density?: ToolbarDensity;\n /**\n * Physical divider edges in canonical top/right/bottom/left order, drawn\n * always. Defaults to none: a toolbar pinned over or under scrolling content\n * gets its divider from the scroll state instead — a `Pane` draws the line\n * between its chrome and content while content is scrolled away beneath it,\n * and `wireScrollDividers` `targets` can name a toolbar as chrome, which\n * then draws its facing side the same way.\n */\n dividerSides?: Sides;\n /** `balanced` gives both side zones equal tracks, centering the middle zone on the toolbar even if only one side has controls. */\n centerAlign?: 'center' | 'stretch' | 'balanced';\n /**\n * Component-owned responsive layout; applications choose the policy rather\n * than restyling toolbar internals. Under every policy the trailing zone\n * wraps its groups instead of clipping an action, and the center zone keeps\n * its whole content width: when the zones do not fit one row, the leading\n * title truncates with an ellipsis rather than the center overlapping it.\n * - `none` keeps one row; the leading identity truncates first.\n * - `stack` stacks the zones at `responsiveAt`, wrapping stacked control\n * groups onto further rows.\n * - `wrap` keeps one row while every zone fits at its natural width, and\n * otherwise moves the trailing zone below a whole leading identity.\n * - `center-priority` gives an expanded center control the full row.\n * - `trailing-priority` moves an expanded trailing control to a full row\n * below the leading identity at `responsiveAt`.\n */\n responsive?:\n 'none' | 'stack' | 'wrap' | 'center-priority' | 'trailing-priority';\n /** Container width at which `stack` or `trailing-priority` activates. */\n responsiveAt?: 'compact' | 'narrow';\n /**\n * Screen edges this toolbar claims for device safe-area compensation, for an\n * app bar or bottom bar that sits directly at a screen edge rather than in a\n * Pane header or footer. Each listed side pads by the inset its surrounding\n * layout reports through `--kui-edge-inset-*`, or the full device inset when\n * nothing routes that edge, while the toolbar's box and dividers paint\n * through. Omitted, the toolbar pads only the inline edges an owner such as\n * a Pane header hands it, and never a block edge.\n */\n safeAreaEdges?: readonly PaneSeparatorSide[];\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A toolbar's configuration, apart from its content: the props a composite\n * that renders a `Toolbar` for the app (a Workbench or CollapsiblePanel\n * toolbar) forwards, so the app configures that toolbar instead of styling it.\n */\nexport type ToolbarConfig = Pick<\n ToolbarProps,\n | 'density'\n | 'dividerSides'\n | 'centerAlign'\n | 'responsive'\n | 'responsiveAt'\n | 'safeAreaEdges'\n>;\n\nconst claim = (\n edges: readonly PaneSeparatorSide[] | undefined,\n side: PaneSeparatorSide,\n) => (edges?.includes(side) ? 'true' : undefined);\n\nexport function Toolbar({\n id,\n leading,\n center,\n trailing,\n label,\n position = 'header',\n density = 'default',\n dividerSides = '',\n centerAlign = 'center',\n responsive = 'none',\n responsiveAt = 'narrow',\n safeAreaEdges,\n className = '',\n slot,\n}: ToolbarProps) {\n const attributes = {\n id,\n class: `kui-toolbar ${className}`.trim(),\n 'data-component': 'toolbar',\n 'data-density': density === 'compact' ? 'compact' : undefined,\n 'divider-sides': dividerSides || undefined,\n 'data-has-center': String(Boolean(center)),\n 'data-center-align': centerAlign,\n 'data-responsive': responsive,\n 'data-responsive-at': responsiveAt,\n 'data-safe-area-block-start': claim(safeAreaEdges, 'block-start'),\n 'data-safe-area-block-end': claim(safeAreaEdges, 'block-end'),\n 'data-safe-area-inline-start': claim(safeAreaEdges, 'inline-start'),\n 'data-safe-area-inline-end': claim(safeAreaEdges, 'inline-end'),\n 'aria-label': label,\n slot,\n };\n const zones = (\n <>\n <div class=\"kui-toolbar__leading\">{leading}</div>\n <div class=\"kui-toolbar__center\">{center}</div>\n <div class=\"kui-toolbar__trailing\">{trailing}</div>\n </>\n );\n return position === 'footer' ? (\n <footer {...attributes}>{zones}</footer>\n ) : (\n <header {...attributes}>{zones}</header>\n );\n}\n\nexport type { Sides } from '../../../shared/layout/sides.js';\n"]}
@@ -1,5 +1,5 @@
1
- import { collapsiblePanelToggleIcon, composedPanelBody, relocatedPanelGroups, groupSizeFor } from './chunk-DNWWF6UN.js';
2
- export { collapsiblePanelToggleIcon } from './chunk-DNWWF6UN.js';
1
+ import { collapsiblePanelToggleIcon, composedPanelBody, relocatedPanelGroups, groupSizeFor } from './chunk-WSEJ2FDE.js';
2
+ export { collapsiblePanelToggleIcon } from './chunk-WSEJ2FDE.js';
3
3
 
4
4
 
5
5