@kerfjs/ui 5.0.0-beta.6 → 5.0.0-beta.8

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 (90) hide show
  1. package/README.md +1 -0
  2. package/ai/component-catalog.json +84 -11
  3. package/ai/public-api-signatures-v1.md +74 -11
  4. package/ai/skill.md +1 -0
  5. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  6. package/dist/app-tab.d.ts +3 -1
  7. package/dist/app-tab.js +2 -1
  8. package/dist/browser/app-tab.js +1 -0
  9. package/dist/browser/menu-action-row.js +1 -0
  10. package/dist/browser/menu-header.js +1 -0
  11. package/dist/browser/menu-item.js +1 -0
  12. package/dist/browser/panel-header.js +1 -0
  13. package/dist/browser/segmented-control.js +1 -0
  14. package/dist/browser/select.js +1 -0
  15. package/dist/browser/skeleton.js +3 -0
  16. package/dist/browser/state-banner.js +1 -0
  17. package/dist/browser/toolbar-text.js +1 -0
  18. package/dist/browser/value-table.js +1 -0
  19. package/dist/{chunk-XZXRLY5Q.js → chunk-2Z5TWHKQ.js} +7 -6
  20. package/dist/chunk-2Z5TWHKQ.js.map +1 -0
  21. package/dist/{chunk-EGHL5S4P.js → chunk-3YD6ZNRA.js} +8 -7
  22. package/dist/chunk-3YD6ZNRA.js.map +1 -0
  23. package/dist/chunk-B24C4A6T.js +22 -0
  24. package/dist/chunk-B24C4A6T.js.map +1 -0
  25. package/dist/{chunk-RBTVBGRD.js → chunk-BLK3UEEI.js} +2 -2
  26. package/dist/{chunk-RBTVBGRD.js.map → chunk-BLK3UEEI.js.map} +1 -1
  27. package/dist/{chunk-KZKSBUKC.js → chunk-BNQ2YDV4.js} +8 -7
  28. package/dist/chunk-BNQ2YDV4.js.map +1 -0
  29. package/dist/{chunk-NPPD2A6O.js → chunk-H6URQGJI.js} +8 -6
  30. package/dist/chunk-H6URQGJI.js.map +1 -0
  31. package/dist/chunk-I7INRJO4.js +17 -0
  32. package/dist/chunk-I7INRJO4.js.map +1 -0
  33. package/dist/{chunk-CTQKI2XL.js → chunk-LC3YSAZC.js} +14 -3
  34. package/dist/chunk-LC3YSAZC.js.map +1 -0
  35. package/dist/{chunk-R6JHHBKQ.js → chunk-PONXLV5U.js} +5 -5
  36. package/dist/chunk-PONXLV5U.js.map +1 -0
  37. package/dist/chunk-RUNWEPR4.js +10 -0
  38. package/dist/chunk-RUNWEPR4.js.map +1 -0
  39. package/dist/{chunk-TRNBHPNW.js → chunk-YGN7OMLT.js} +11 -8
  40. package/dist/chunk-YGN7OMLT.js.map +1 -0
  41. package/dist/chunk-YKUUZPED.js +24 -0
  42. package/dist/chunk-YKUUZPED.js.map +1 -0
  43. package/dist/index.d.ts +2 -1
  44. package/dist/index.js +12 -11
  45. package/dist/menu-action-row.d.ts +3 -1
  46. package/dist/menu-action-row.js +2 -1
  47. package/dist/menu-header.d.ts +3 -1
  48. package/dist/menu-header.js +2 -1
  49. package/dist/menu-item.d.ts +3 -1
  50. package/dist/menu-item.js +2 -1
  51. package/dist/nav-stack.js +2 -1
  52. package/dist/panel-header.d.ts +11 -1
  53. package/dist/panel-header.js +2 -1
  54. package/dist/segmented-control.d.ts +3 -1
  55. package/dist/segmented-control.js +2 -1
  56. package/dist/select.d.ts +5 -2
  57. package/dist/select.js +2 -1
  58. package/dist/skeleton.d.ts +24 -0
  59. package/dist/skeleton.js +3 -0
  60. package/dist/skeleton.js.map +1 -0
  61. package/dist/split-view.js +2 -1
  62. package/dist/split-view.js.map +1 -1
  63. package/dist/state-banner.d.ts +3 -1
  64. package/dist/state-banner.js +2 -1
  65. package/dist/styles/panel-header.css +5 -0
  66. package/dist/styles/select.css +42 -0
  67. package/dist/styles/skeleton.css +31 -0
  68. package/dist/styles/styles.css +1 -0
  69. package/dist/toolbar-text.d.ts +12 -2
  70. package/dist/toolbar-text.js +2 -1
  71. package/dist/value-table.d.ts +3 -1
  72. package/dist/value-table.js +2 -1
  73. package/docs/accessibility.md +10 -5
  74. package/docs/component-contract.md +12 -0
  75. package/docs/component-selection.md +3 -2
  76. package/llms.txt +10 -1
  77. package/package.json +7 -1
  78. package/dist/chunk-24Z2XE6C.js +0 -10
  79. package/dist/chunk-24Z2XE6C.js.map +0 -1
  80. package/dist/chunk-CTQKI2XL.js.map +0 -1
  81. package/dist/chunk-EGHL5S4P.js.map +0 -1
  82. package/dist/chunk-KZKSBUKC.js.map +0 -1
  83. package/dist/chunk-NPPD2A6O.js.map +0 -1
  84. package/dist/chunk-R6JHHBKQ.js.map +0 -1
  85. package/dist/chunk-S3TPM2LP.js +0 -23
  86. package/dist/chunk-S3TPM2LP.js.map +0 -1
  87. package/dist/chunk-TRNBHPNW.js.map +0 -1
  88. package/dist/chunk-VHW5YNIB.js +0 -17
  89. package/dist/chunk-VHW5YNIB.js.map +0 -1
  90. package/dist/chunk-XZXRLY5Q.js.map +0 -1
package/dist/select.d.ts CHANGED
@@ -18,11 +18,14 @@ interface SelectProps<Value extends string = string> {
18
18
  ariaLabel?: string;
19
19
  choices: readonly SelectChoice<Value>[];
20
20
  className?: string;
21
- placeholder?: string;
21
+ /** Empty-value hint text shown in the closed control (the native select placeholder). */
22
+ placeholderText?: string;
22
23
  disabled?: boolean;
23
24
  fitMenu?: boolean;
24
25
  renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;
26
+ /** Render as an unanimated loading skeleton: the label above a static, empty control box. */
27
+ placeholder?: boolean;
25
28
  }
26
- declare function Select<Value extends string>({ name, value, label, ariaLabel, choices, className, placeholder, disabled, fitMenu, renderSelected }: SelectProps<Value>): SafeHtml;
29
+ declare function Select<Value extends string>({ name, value, label, ariaLabel, choices, className, placeholderText, disabled, fitMenu, renderSelected, placeholder }: SelectProps<Value>): SafeHtml;
27
30
 
28
31
  export { Select, type SelectChoice, type SelectProps };
package/dist/select.js CHANGED
@@ -1,4 +1,5 @@
1
- export { Select } from './chunk-CTQKI2XL.js';
1
+ export { Select } from './chunk-LC3YSAZC.js';
2
+
2
3
 
3
4
 
4
5
  //# sourceMappingURL=select.js.map
@@ -0,0 +1,24 @@
1
+ import * as kerfjs from 'kerfjs';
2
+
3
+ interface SkeletonProps {
4
+ /** Width as any CSS length (e.g. `remify(120px)`, `60%`). Defaults to filling its slot. */
5
+ width?: string;
6
+ /** Height as any CSS length. Defaults to a single text line. */
7
+ height?: string;
8
+ /** Corner radius override (a CSS length). Defaults to the small radius token. */
9
+ radius?: string;
10
+ /** Render this many stacked lines (the last one shorter), for multi-line text. */
11
+ lines?: number;
12
+ /** Accessible label. Omit to keep the block decorative (`aria-hidden`). */
13
+ label?: string;
14
+ className?: string;
15
+ }
16
+ /**
17
+ * A subtle, deliberately **unanimated** loading placeholder block. Use it for a
18
+ * value slot whose content is not yet known, on its own or via a component's
19
+ * `placeholder` prop. Decorative by default (`aria-hidden`); pass `label` to
20
+ * announce it. Sizes to its slot unless `width`/`height` are given.
21
+ */
22
+ declare function Skeleton({ width, height, radius, lines, label, className }: SkeletonProps): kerfjs.SafeHtml;
23
+
24
+ export { Skeleton, type SkeletonProps };
@@ -0,0 +1,3 @@
1
+ export { Skeleton } from './chunk-B24C4A6T.js';
2
+
3
+ //# sourceMappingURL=skeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"skeleton.js"}
@@ -1,6 +1,7 @@
1
- import { NavStack } from './chunk-RBTVBGRD.js';
1
+ import { NavStack } from './chunk-BLK3UEEI.js';
2
2
 
3
3
  import { ResizableRegion } from './chunk-M5JRI6MN.js';
4
+
4
5
  import { jsx, jsxs } from 'kerfjs/jsx-runtime';
5
6
 
6
7
  function SplitView({ id, label, list, detail, compact = false, detailActive = false, listTitle = "", detailTitle = "", backLabel = "Back", resizable, className = "" }) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/split-view.tsx"],"names":[],"mappings":";;;;;AA4CO,SAAS,UAAU,EAAE,EAAA,EAAI,OAAO,IAAA,EAAM,MAAA,EAAQ,UAAU,KAAA,EAAO,YAAA,GAAe,OAAO,SAAA,GAAY,EAAA,EAAI,cAAc,EAAA,EAAI,SAAA,GAAY,QAAQ,SAAA,EAAW,SAAA,GAAY,IAAG,EAAmB;AAC7L,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,KAAA,GAAQ,YAAA,GACV,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAK,EAAG,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,CAAA,GACzG,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAM,CAAA;AACrD,IAAA,uBAAO,GAAA,CAAC,SAAI,KAAA,EAAO,CAAA,uCAAA,EAA0C,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,YAAA,EAAa,mBAAgB,SAAA,EACnI,QAAA,kBAAA,GAAA,CAAC,YAAS,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,KAAA,EAAc,KAAA,EAAc,SAAA,EAAsB,CAAA,EACjF,CAAA;AAAA,EACF;AACA,EAAA,MAAM,QAAA,GAAW,SAAA,mBACb,GAAA,CAAC,eAAA,EAAA,EAAgB,IAAI,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,EAAS,KAAA,EAAO,aAAa,MAAA,EAAQ,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,KAAK,SAAA,CAAU,GAAA,EAAK,GAAA,EAAK,SAAA,CAAU,KACtH,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,mBAAe,IAAA,EAAE,QAAA,EAAA,IAAA,EAAK,CAAA,EACnE,CAAA,uBACC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,iBAAA,EAAe,MAAE,QAAA,EAAA,IAAA,EAAK,CAAA;AACrE,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,YAAA,EAAa,iBAAA,EAAgB,OAAA,EAAQ,cAAY,KAAA,EAC9H,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA,CAAC,SAAI,KAAA,EAAM,iCAAA,EAAkC,qBAAiB,IAAA,EAAC,YAAA,EAAY,WAAA,IAAe,MAAA,EAAY,QAAA,EAAA,MAAA,EAAO;AAAA,GAAA,EAC/G,CAAA;AACF","file":"split-view.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { NavStack } from './nav-stack.js';\nimport { ResizableRegion } from './resizable-region.js';\n\nexport interface SplitViewResizable {\n size: number;\n min: number;\n max: number;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: SafeHtml;\n /** The detail (secondary) pane. */\n detail: SafeHtml;\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 /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n className?: string;\n}\n\n/**\n * A list-detail (master-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({ id, label, list, detail, compact = false, detailActive = false, listTitle = '', detailTitle = '', backLabel = 'Back', resizable, className = '' }: SplitViewProps) {\n if (compact) {\n const views = detailActive\n ? [{ key: 'list', title: listTitle, content: list }, { key: 'detail', title: detailTitle, content: detail }]\n : [{ key: 'list', title: listTitle, content: list }];\n return <div class={`kui-split-view kui-split-view--compact ${className}`.trim()} id={id} data-component=\"split-view\" data-split-mode=\"compact\">\n <NavStack id={`${id}-stack`} label={label} views={views} backLabel={backLabel} />\n </div>;\n }\n const listPane = resizable\n ? <ResizableRegion id={`${id}-list`} label={listTitle || 'List'} size={resizable.size} min={resizable.min} max={resizable.max}>\n <div class=\"kui-split-view__list kui-pane\" data-split-list>{list}</div>\n </ResizableRegion>\n : <div class=\"kui-split-view__list kui-pane\" data-split-list>{list}</div>;\n return <div class={`kui-split-view ${className}`.trim()} id={id} data-component=\"split-view\" data-split-mode=\"split\" aria-label={label}>\n {listPane}\n <div class=\"kui-split-view__detail kui-pane\" data-split-detail aria-label={detailTitle || undefined}>{detail}</div>\n </div>;\n}\n"]}
1
+ {"version":3,"sources":["../src/split-view.tsx"],"names":[],"mappings":";;;;;;AA4CO,SAAS,UAAU,EAAE,EAAA,EAAI,OAAO,IAAA,EAAM,MAAA,EAAQ,UAAU,KAAA,EAAO,YAAA,GAAe,OAAO,SAAA,GAAY,EAAA,EAAI,cAAc,EAAA,EAAI,SAAA,GAAY,QAAQ,SAAA,EAAW,SAAA,GAAY,IAAG,EAAmB;AAC7L,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,KAAA,GAAQ,YAAA,GACV,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAK,EAAG,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,CAAA,GACzG,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAM,CAAA;AACrD,IAAA,uBAAO,GAAA,CAAC,SAAI,KAAA,EAAO,CAAA,uCAAA,EAA0C,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,YAAA,EAAa,mBAAgB,SAAA,EACnI,QAAA,kBAAA,GAAA,CAAC,YAAS,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,KAAA,EAAc,KAAA,EAAc,SAAA,EAAsB,CAAA,EACjF,CAAA;AAAA,EACF;AACA,EAAA,MAAM,QAAA,GAAW,SAAA,mBACb,GAAA,CAAC,eAAA,EAAA,EAAgB,IAAI,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,EAAS,KAAA,EAAO,aAAa,MAAA,EAAQ,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,KAAK,SAAA,CAAU,GAAA,EAAK,GAAA,EAAK,SAAA,CAAU,KACtH,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,mBAAe,IAAA,EAAE,QAAA,EAAA,IAAA,EAAK,CAAA,EACnE,CAAA,uBACC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,iBAAA,EAAe,MAAE,QAAA,EAAA,IAAA,EAAK,CAAA;AACrE,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,YAAA,EAAa,iBAAA,EAAgB,OAAA,EAAQ,cAAY,KAAA,EAC9H,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA,CAAC,SAAI,KAAA,EAAM,iCAAA,EAAkC,qBAAiB,IAAA,EAAC,YAAA,EAAY,WAAA,IAAe,MAAA,EAAY,QAAA,EAAA,MAAA,EAAO;AAAA,GAAA,EAC/G,CAAA;AACF","file":"split-view.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { NavStack } from './nav-stack.js';\nimport { ResizableRegion } from './resizable-region.js';\n\nexport interface SplitViewResizable {\n size: number;\n min: number;\n max: number;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: SafeHtml;\n /** The detail (secondary) pane. */\n detail: SafeHtml;\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 /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n className?: string;\n}\n\n/**\n * A list-detail (master-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({ id, label, list, detail, compact = false, detailActive = false, listTitle = '', detailTitle = '', backLabel = 'Back', resizable, className = '' }: SplitViewProps) {\n if (compact) {\n const views = detailActive\n ? [{ key: 'list', title: listTitle, content: list }, { key: 'detail', title: detailTitle, content: detail }]\n : [{ key: 'list', title: listTitle, content: list }];\n return <div class={`kui-split-view kui-split-view--compact ${className}`.trim()} id={id} data-component=\"split-view\" data-split-mode=\"compact\">\n <NavStack id={`${id}-stack`} label={label} views={views} backLabel={backLabel} />\n </div>;\n }\n const listPane = resizable\n ? <ResizableRegion id={`${id}-list`} label={listTitle || 'List'} size={resizable.size} min={resizable.min} max={resizable.max}>\n <div class=\"kui-split-view__list kui-pane\" data-split-list>{list}</div>\n </ResizableRegion>\n : <div class=\"kui-split-view__list kui-pane\" data-split-list>{list}</div>;\n return <div class={`kui-split-view ${className}`.trim()} id={id} data-component=\"split-view\" data-split-mode=\"split\" aria-label={label}>\n {listPane}\n <div class=\"kui-split-view__detail kui-pane\" data-split-detail aria-label={detailTitle || undefined}>{detail}</div>\n </div>;\n}\n"]}
@@ -9,7 +9,9 @@ interface StateBannerProps {
9
9
  tone?: StateBannerTone;
10
10
  urgency?: 'status' | 'alert';
11
11
  className?: string;
12
+ /** Render the title and detail as unanimated loading skeletons, keeping the icon and tone. */
13
+ placeholder?: boolean;
12
14
  }
13
- declare function StateBanner({ title, detail, icon, action, tone, urgency, className }: StateBannerProps): SafeHtml;
15
+ declare function StateBanner({ title, detail, icon, action, tone, urgency, className, placeholder }: StateBannerProps): SafeHtml;
14
16
 
15
17
  export { StateBanner, type StateBannerProps, type StateBannerTone };
@@ -1,3 +1,4 @@
1
- export { StateBanner } from './chunk-VHW5YNIB.js';
1
+ export { StateBanner } from './chunk-I7INRJO4.js';
2
+
2
3
 
3
4
  //# sourceMappingURL=state-banner.js.map
@@ -22,9 +22,14 @@
22
22
  --kui-panel-header-icon-foreground,
23
23
  var(--kui-color-brand-on-quiet)
24
24
  );
25
+ /* The icon is a raw svg child (not a button), so the group's default
26
+ flex-start alignment would pin it to the left of the filled tile. Center it
27
+ on both axes inside the circle. */
28
+ justify-content: center;
25
29
  }
26
30
 
27
31
  .kui-panel-header__icon svg {
32
+ display: block;
28
33
  width: 1.375rem;
29
34
  height: 1.375rem;
30
35
  }
@@ -94,3 +94,45 @@
94
94
  letter-spacing: 0.04em;
95
95
  text-transform: uppercase;
96
96
  }
97
+
98
+ /* Loading placeholder: a static box that mirrors the closed combobox (label
99
+ above, a value skeleton and a dormant chevron inside a 44px control box).
100
+ Rendered instead of the interactive wa-select, so it needs no registration. */
101
+ .kui-select--placeholder {
102
+ display: block;
103
+ width: 100%;
104
+ }
105
+ .kui-select__placeholder-label {
106
+ display: block;
107
+ margin-block-end: 0.25rem;
108
+ color: var(--kui-color-text);
109
+ font-size: var(--kui-font-s);
110
+ line-height: 1.4;
111
+ }
112
+ .kui-select__placeholder-box {
113
+ display: flex;
114
+ min-height: 2.75rem;
115
+ align-items: center;
116
+ justify-content: space-between;
117
+ gap: 0.5rem;
118
+ padding-inline: var(--kui-layout-item-padding, 0.5rem);
119
+ border: 1px solid var(--kui-color-border);
120
+ border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
121
+ background: var(--kui-color-surface);
122
+ }
123
+ .kui-select__placeholder-box .kui-skeleton {
124
+ max-width: 10rem;
125
+ }
126
+ .kui-select__placeholder-chevron {
127
+ display: inline-flex;
128
+ width: 1rem;
129
+ height: 1rem;
130
+ flex: none;
131
+ color: var(--kui-color-text-quiet);
132
+ transform: scale(var(--kui-disclosure-icon-scale, 0.85));
133
+ }
134
+ .kui-select__placeholder-chevron svg {
135
+ display: block;
136
+ width: 100%;
137
+ height: 100%;
138
+ }
@@ -0,0 +1,31 @@
1
+ .kui-skeleton {
2
+ --kui-skeleton-radius: var(--kui-radius-s);
3
+
4
+ display: inline-block;
5
+ width: 100%;
6
+ max-width: 100%;
7
+ height: 1em;
8
+ min-width: 1.5rem;
9
+ border-radius: var(--kui-skeleton-radius);
10
+ /* Deliberately unanimated: a flat, subtle fill that reads as "not yet loaded"
11
+ without drawing the eye or implying progress. */
12
+ background: color-mix(in srgb, var(--kui-color-text) 12%, transparent);
13
+ vertical-align: middle;
14
+ }
15
+
16
+ .kui-skeleton-lines {
17
+ display: flex;
18
+ width: 100%;
19
+ flex-direction: column;
20
+ gap: var(--kui-space-2xs);
21
+ }
22
+
23
+ .kui-skeleton-lines .kui-skeleton {
24
+ height: 0.8em;
25
+ }
26
+
27
+ @media (forced-colors: active) {
28
+ .kui-skeleton {
29
+ background: GrayText;
30
+ }
31
+ }
@@ -12,6 +12,7 @@
12
12
  @import "./app-tab.css";
13
13
  @import "./tab-bar.css";
14
14
  @import "./loading-spinner.css";
15
+ @import "./skeleton.css";
15
16
  @import "./select.css";
16
17
  @import "./segmented-control.css";
17
18
  @import "./token-search-field.css";
@@ -1,13 +1,23 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
 
3
3
  type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small';
4
+ /** ARIA heading level for a title exposed as a heading landmark. */
5
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
4
6
  interface ToolbarTextProps {
5
7
  text: string;
6
8
  size?: ToolbarTextSize;
7
9
  className?: string;
8
10
  /** Optional id, e.g. so a dialog can reference the title via aria-labelledby. */
9
11
  id?: string;
12
+ /**
13
+ * Expose heading semantics (`role="heading"` + `aria-level`) so the text acts as
14
+ * a heading landmark — e.g. a page's primary title. Omit to keep the plain span
15
+ * (the default), which suits a dialog title referenced via `aria-labelledby`.
16
+ */
17
+ headingLevel?: HeadingLevel;
18
+ /** Render the text as an unanimated loading skeleton instead of its value. */
19
+ placeholder?: boolean;
10
20
  }
11
- declare function ToolbarText({ text, size, className, id }: ToolbarTextProps): kerfjs.SafeHtml;
21
+ declare function ToolbarText({ text, size, className, id, headingLevel, placeholder }: ToolbarTextProps): kerfjs.SafeHtml;
12
22
 
13
- export { ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
23
+ export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
@@ -1,3 +1,4 @@
1
- export { ToolbarText } from './chunk-24Z2XE6C.js';
1
+ export { ToolbarText } from './chunk-RUNWEPR4.js';
2
+
2
3
 
3
4
  //# sourceMappingURL=toolbar-text.js.map
@@ -5,8 +5,10 @@ interface ValueTableRowProps {
5
5
  value: string | SafeHtml;
6
6
  icon?: SafeHtml;
7
7
  className?: string;
8
+ /** Render the value as an unanimated loading skeleton, keeping the field label. */
9
+ placeholder?: boolean;
8
10
  }
9
- declare function ValueTableRow({ label, value, icon, className }: ValueTableRowProps): SafeHtml;
11
+ declare function ValueTableRow({ label, value, icon, className, placeholder }: ValueTableRowProps): SafeHtml;
10
12
 
11
13
  interface ValueTableProps {
12
14
  label: string;
@@ -1,3 +1,4 @@
1
- export { ValueTable, ValueTableRow } from './chunk-R6JHHBKQ.js';
1
+ export { ValueTable, ValueTableRow } from './chunk-PONXLV5U.js';
2
+
2
3
 
3
4
  //# sourceMappingURL=value-table.js.map
@@ -46,11 +46,16 @@ The application owns persistence and collapsed/expanded policy. Keep the last ex
46
46
  `PanelHeader` is a plain `Toolbar` heading. Its leading zone holds an optional
47
47
  icon (a normal bordered `ToolbarControlGroup`) and the title as extra-large
48
48
  `ToolbarText`, and the app's trailing controls go straight into the trailing
49
- zone. The title carries no native heading role, so the application connects
50
- `titleId` and an optional `summaryId` to the owning dialog or panel through
51
- `aria-labelledby` and `aria-describedby` (and provides a document heading
52
- separately when one is required). Pass the trailing controls as a labeled
53
- `ToolbarControlGroup` when that group needs an accessible name.
49
+ zone. By default the title carries no native heading role, so for a **dialog or
50
+ panel** the application connects `titleId` and an optional `summaryId` to the
51
+ owning host through `aria-labelledby` and `aria-describedby`. For a **page or
52
+ view** title, pass `headingLevel` (usually `1`): the title then exposes
53
+ `role="heading"` with a matching `aria-level`, giving the view a heading landmark
54
+ so screen-reader heading navigation and "main heading" semantics work — the same
55
+ role/level pair `ToolbarText` exposes when it is given `headingLevel` directly.
56
+ Keep the levels meaningful and non-skipping within a view. Pass the trailing
57
+ controls as a labeled `ToolbarControlGroup` when that group needs an accessible
58
+ name.
54
59
 
55
60
  ## Tabs
56
61
 
@@ -182,6 +182,18 @@ CSS, the generated wrappers that make it
182
182
  reachable, and the registration module are the package's only declared side
183
183
  effects.
184
184
 
185
+ A value-bearing component's `placeholder` prop is a first-class loading mode: the
186
+ component renders its own real chrome (labels, icon and action affordances,
187
+ container geometry) while replacing each **value** slot with a subtle, deliberately
188
+ unanimated `Skeleton` block and disabling its own interactive controls
189
+ (`aria-busy`, dropped `data-action`, disabled buttons). Sizes and shapes stay
190
+ identical to the populated component, so a parent composes a faithful loading view —
191
+ an inspector, a detail pane — from placeholder children without hand-rebuilding
192
+ markup. The application still owns the loading lifecycle (when to pass `placeholder`)
193
+ and which slots are unknown; the standalone `Skeleton` covers custom slots. It is a
194
+ placeholder, not progress: use `LoadingSpinner` for known busy activity, and never
195
+ animate the skeleton.
196
+
185
197
  Package source styles express root-scaled geometry with `remify(<px>)`; the
186
198
  build converts it against the 16px authoring baseline and exposes only ordinary
187
199
  `rem` CSS. Literal pixels remain for intentional hairlines, and `em` remains
@@ -62,7 +62,7 @@ an upstream component or recipe request.
62
62
  | Disclosure indicator — `DisclosureArrow` | A control needs one animated 18px root-scaled visual for open and closed state, including configurable directions or a replacement icon. | Do not use it as the interactive control or accessible name; place it inside the button or control that exposes expanded state. | Pass the controlled `open` state, render it inside the owning control, author replacement icon content facing right before transforms, and override `--kui-disclosure-arrow-size` only when another visual size is required. Direction changes use the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. | Open state, interaction, accessible name, size override, replacement glyph, direction choices, and shortest-path rotation. | `@kerfjs/ui/disclosure-arrow` | [Component ownership](./component-contract.md#ownership-boundaries) |
63
63
  | Application toolbar — `Toolbar` | Leading identity, optional centered content, and trailing controls form one horizontal app bar. | Do not use it for a page, panel, or dialog heading; use `PanelHeader`. | Compose `ToolbarText` and `ToolbarControlGroup` where their contracts fit. | Actions, command availability, responsive relocation, and state. | `@kerfjs/ui/toolbar` | [Toolbar composition](../README.md#component-subpaths) |
64
64
  | Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained, borderless, pressed, or single-control treatment. | Do not use it merely to align unrelated buttons; use toolbar slots or ordinary layout. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; use `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
65
- | Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Do not substitute it for document heading semantics; use `PanelHeader` or native headings. | None. | Text and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
65
+ | Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel` (or prefer `PanelHeader`, which forwards it). | Optional `headingLevel` for `role="heading"` + `aria-level`. | Text, heading level, and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
66
66
  | Navigation row — `MenuItem` | A pane or navigation area needs a selectable, disabled, dormant-trailing, or multiline action row. | Do not put a control in `trailing`; use `MenuActionRow` when the trailing region must be independently interactive. Use an `<a>` for navigation that must retain link behavior, a native `<button>` for an ordinary action, or implement the complete ARIA menu widget. | Delegate its `data-action`; compose inside a `.kui-content` section. Put domain event/drop metadata in `rootAttributes` rather than adding wrapper markup. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/menu-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
67
67
  | Navigation row with trailing action — `MenuActionRow` | A full-width row needs a selectable primary action and an independently focusable trailing action. | Use `MenuItem` when trailing content is dormant metadata. Do not put controls inside the row's `label`, `icon`, or `trailingActionIcon` SafeHtml slots. Do not use `AppTab` outside tablist semantics or `ToolbarControlGroup` outside a toolbar. | Delegate both action strings; update controlled selection and any popover/context-menu state in the app. | Routing, selection, both action policies, domain metadata, and popover/context-menu behavior. | `@kerfjs/ui/menu-action-row` | [Accessibility](./accessibility.md#menuactionrow) |
68
68
  | Navigation section heading — `MenuHeader` | A menu section needs a full-width label, semantic count, non-count badge, logical-end action, or real disclosure state. | Do not concatenate counts into `label` or put numeric content in `badge`; use `count` with the localized full phrase in `countLabel`. Do not add a disclosure arrow to navigation that reveals nothing. Do not shrink its 44px action target to the 18px visual. Do not use it as a page, panel, or dialog title; use `PanelHeader`. | Delegate its optional action; the app controls expanded state and revealed content. Toggle mode supplies `DisclosureArrow` unless `actionIcon` replaces it. Use `triggerAttributes` only for domain `data-*` or a native popover relationship. | Section organization, valid count and localized count label, disclosure state and content, non-count badge content, popover target behavior, and policy. | `@kerfjs/ui/menu-header` | [Pane geometry](../README.md#pane-and-content-geometry) |
@@ -71,9 +71,10 @@ an upstream component or recipe request.
71
71
  | Resizable application pane — `ResizableRegion`, `clampRegionSize`, `resizeRegionFromPointer` | A controlled split pane needs the Kerf separator, collapse state, pointer plus keyboard resizing, or a product-specific decorative grip. | Do not use it for a static two-column layout; use CSS grid. Prefer it over Web Awesome `wa-split-panel` unless that component's distinct API is required. Keep `handleIcon` noninteractive. | Call `wireResizableRegions` from `@kerfjs/ui/wire-resizable-regions` once and retain its disposer. | Size signal, min/max policy, collapse policy, persistence, and optional decorative handle icon. | `@kerfjs/ui/resizable-region` | [ResizableRegion contract](./accessibility.md#resizableregion) |
72
72
  | One application tab — `AppTab` | A controlled app tab needs selection, close, drag, leading/trailing anatomy, safe domain metadata, or a product-specific close glyph. | Do not render it alone or use it for a small settings choice; compose in `TabBar`, or use `SegmentedControl`. Keep `closeIcon` noninteractive. | Compose in `TabBar`; let `wireTabBars` manage interaction. Put only domain `data-*` values in `rootAttributes`. | Tab identity, order, selection, close policy, content, and domain metadata values. | `@kerfjs/ui/app-tab` | [Tabs contract](./accessibility.md#tabs) |
73
73
  | Application tab strip — `TabBar`, `wireTabBars`, `reorderTabs` | Tabs switch page regions and may overflow, close, or reorder. | Do not use it for a compact local view toggle; use `SegmentedControl`. Do not use it for a long choice list; use `Select`. Prefer it over Web Awesome `wa-tab-group`, `wa-tab`, and `wa-tab-panel` for Kerf app tabs. | Call `wireTabBars` once, retain the disposer, and apply `onReorder` synchronously; `reorderTabs` is the default array helper. | Ordered tabs, selection, panels, routing, closing, and persistence. | `@kerfjs/ui/tab-bar` plus `@kerfjs/ui/wire-tab-bars` | [Tabs contract](./accessibility.md#tabs) |
74
- | Panel, dialog, or page heading — `PanelHeader` | A panel, dialog, or page needs a heading with an extra-large title, an optional icon and subtitle, and trailing actions. | Do not use it as persistent app chrome; use `Toolbar`. It supplies header structure, not modal behavior; use an application overlay or Web Awesome `wa-dialog` for that behavior. | Connect the title id and any provided summary id to the dialog or panel host, pass the trailing controls (typically a `ToolbarControlGroup`), and delegate their actions. | Open state, focus lifecycle, dismissal, the trailing controls, labels, and copy. | `@kerfjs/ui/panel-header` | [Header ownership](./component-contract.md#extracted-versus-application-specific) |
74
+ | Panel, dialog, or page heading — `PanelHeader` | A panel, dialog, or page needs a heading with an extra-large title, an optional icon and subtitle, and trailing actions. | Do not use it as persistent app chrome; use `Toolbar`. It supplies header structure, not modal behavior; use an application overlay or Web Awesome `wa-dialog` for that behavior. | Connect the title id and any provided summary id to the dialog or panel host, pass the trailing controls (typically a `ToolbarControlGroup`), and delegate their actions. **For a page or view title set `headingLevel` (usually `1`)** so the title is a real heading landmark (`role="heading"` + `aria-level`) for screen-reader heading navigation; omit it for a dialog title, which is referenced via `aria-labelledby` to `titleId` and needs no heading. | Open state, focus lifecycle, dismissal, the trailing controls, labels, copy, and the heading level for page use. | `@kerfjs/ui/panel-header` | [Header ownership](./component-contract.md#extracted-versus-application-specific) |
75
75
  | Key/value facts — `ValueTable`, `ValueTableRow` | Read-only labels and values form a semantic definition list, optionally with a leading icon. | Do not use it for editable form fields or a row/column data grid; use native form or table semantics. | Compose typed `ValueTableRow` entries; pass `icon` when a 24px leading icon adds useful context. | Values, formatting, icon meaning, and empty/loading policy. | `@kerfjs/ui/value-table` | [Component ownership](./component-contract.md#ownership-boundaries) |
76
76
  | Indeterminate activity — `LoadingSpinner` | A Kerf surface needs compact, labeled or decorative indeterminate progress. | Do not use it for known progress; use Web Awesome `wa-progress-bar` or `wa-progress-ring`. Direct Web Awesome UI may use `wa-spinner`; do not mix spinner systems within one surface. | None; pass a label when the spinner conveys status. | Loading lifecycle and adjacent status copy. | `@kerfjs/ui/loading-spinner` | [Accessibility](./accessibility.md#shared-rules) |
77
+ | Loading placeholder — `Skeleton` + a component's `placeholder` prop | A value or a whole component is still loading and should hold its space as a subtle, unanimated block, keeping the layout stable — an inspector or detail view rendering its real chrome with per-record values absent. | Do not use it for known progress (use `LoadingSpinner`), do not animate it, and do not hand-rebuild a component's empty state — set `placeholder` on the component instead. Prefer it over `wa-skeleton`, which the pure-Kerf primitives avoid to stay Web-Awesome-free. | Set `placeholder` on a value-bearing component (`Select`, `MenuHeader`, `MenuItem`, `ValueTableRow`, `PanelHeader`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `MenuActionRow`) to render skeletons in its value slots with interactivity disabled; use the standalone `Skeleton` for a custom slot. | Loading lifecycle, which slots are unknown, and announcing the loading region. | `@kerfjs/ui/skeleton` | [Accessibility](./accessibility.md#shared-rules) |
77
78
  | Value selection — `Select` | A controlled form value comes from a moderate or long choice list, possibly grouped or icon-bearing. | Do not use it for commands; use a real action menu. Do not use it for a small visible choice set; use `SegmentedControl`. Prefer it over direct `wa-select`, `wa-option`, or value-like `wa-dropdown`/`wa-dropdown-item` composition. | Import `@kerfjs/ui/select/register` once; listen for standard input/change events. | Controlled value, validation, choices, and domain mapping. | `@kerfjs/ui/select` | [Web Awesome integration](../README.md#web-awesome-theme) |
78
79
  | Small exclusive choice — `SegmentedControl` | A few visible choices switch a compact view or setting, with toolbar, rounded, or pill presentation. | Do not use it for tabpanel semantics; use `TabBar`. Do not use it for many choices; use `Select`. Prefer it over `wa-button-group` when the controls select one value. | Delegate its action, read `data-segment-value`, update `value`, and rerender. | Controlled value, labels, action, and persistence. | `@kerfjs/ui/segmented-control` | [SegmentedControl contract](./accessibility.md#segmentedcontrol) |
79
80
  | Structured search editor — `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`, `wireTokenSearchFields` | Free text and ordered, editable, removable filter tokens share one searchbox; enable `collapsible` when an empty, unfocused field should reduce to one iconic action, standalone or in a toolbar group. | Do not use it for ordinary text entry; use a native input or Web Awesome `wa-input`. Do not use it when filters belong in separate form controls. | Read DOM-owned text on input, empty `textContent` on clear, and use `placeTokenSearchCaret` after explicit controlled focus changes. Call `wireTokenSearchFields` from `@kerfjs/ui/wire-token-search-fields` once so Enter submits without adding a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. In `collapsible` mode it also manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse); bind the field's `expanded` to the signal on the returned handle (`handle.expanded(id)`) or adopt your own via `collapsible.signals`, and opt out per behavior only when the app must own it. | Parsing, suggestions, tokens, query execution, results, announcements, and — only if overriding the default — the collapsible `expanded` signal. | `@kerfjs/ui/token-search-field` | [TokenSearchField contract](./accessibility.md#tokensearchfield) |
package/llms.txt CHANGED
@@ -81,6 +81,15 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
81
81
  via `collapsible.signals`. Do not hand-roll open/collapse/focus that helper
82
82
  provides; but do keep a plain disclosure toggle (a one-line boolean the app already
83
83
  renders from) in the app.
84
+ - **Placeholder loading state, don't rebuild it.** For a value or component that is
85
+ still loading, set `placeholder` on the component (`Select`, `MenuHeader`,
86
+ `MenuItem`, `ValueTableRow`, `PanelHeader`, `SegmentedControl`, `StateBanner`,
87
+ `AppTab`, `ToolbarText`, `MenuActionRow`): it renders its real chrome with value
88
+ slots as subtle **unanimated** skeleton blocks and interactivity disabled, so a
89
+ parent composes a faithful loading view (e.g. an inspector) without hand-rebuilding
90
+ markup. Use the standalone `Skeleton` for a custom slot. Prefer it over `wa-skeleton`
91
+ (the pure-Kerf primitives avoid Web Awesome), and never animate it — use
92
+ `LoadingSpinner` for known busy activity instead.
84
93
 
85
94
  ## Public exports
86
95
 
@@ -89,7 +98,7 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
89
98
  `Select`, `TokenSearchField` (+ `readTokenSearchField`, `placeTokenSearchCaret`,
90
99
  `wireTokenSearchFields`), `AppTab`, `TabBar` (+ `wireTabBars`, `reorderTabs`),
91
100
  `ResizableRegion` (+ `wireResizableRegions`), `StateBanner`, `EmptyState`,
92
- `LoadingSpinner`, `ValueTable`, `ValueTableRow`. Whole-screen layouts (opt-in,
101
+ `LoadingSpinner`, `Skeleton`, `ValueTable`, `ValueTableRow`. Whole-screen layouts (opt-in,
93
102
  tree-shakeable, declarative with `wire…` helpers, each with a companion CSS import):
94
103
  `NavStack`, `SplitView`, `Workbench`, `TabScaffold`, driven by `deviceClass()` from
95
104
  `@kerfjs/ui/device-class`. `@kerfjs/ui/webawesome` is a type-only boundary for
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kerfjs/ui",
3
- "version": "5.0.0-beta.6",
3
+ "version": "5.0.0-beta.8",
4
4
  "description": "Accessible, composable UI primitives for kerf applications.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -140,6 +140,11 @@
140
140
  "browser": "./dist/browser/select.js",
141
141
  "import": "./dist/select.js"
142
142
  },
143
+ "./skeleton": {
144
+ "types": "./dist/skeleton.d.ts",
145
+ "browser": "./dist/browser/skeleton.js",
146
+ "import": "./dist/skeleton.js"
147
+ },
143
148
  "./segmented-control": {
144
149
  "types": "./dist/segmented-control.d.ts",
145
150
  "browser": "./dist/browser/segmented-control.js",
@@ -207,6 +212,7 @@
207
212
  "./tab-scaffold.css": "./dist/styles/tab-scaffold.css",
208
213
  "./loading-spinner.css": "./dist/styles/loading-spinner.css",
209
214
  "./select.css": "./dist/styles/select.css",
215
+ "./skeleton.css": "./dist/styles/skeleton.css",
210
216
  "./segmented-control.css": "./dist/styles/segmented-control.css",
211
217
  "./token-search-field.css": "./dist/styles/token-search-field.css",
212
218
  "./state-banner.css": "./dist/styles/state-banner.css",
@@ -1,10 +0,0 @@
1
- import { jsx } from 'kerfjs/jsx-runtime';
2
-
3
- // src/toolbar-text.tsx
4
- function ToolbarText({ text, size = "default", className = "", id }) {
5
- return /* @__PURE__ */ jsx("span", { class: `kui-toolbar-text ${className}`.trim(), "data-component": "toolbar-text", "data-size": size, id, children: text });
6
- }
7
-
8
- export { ToolbarText };
9
-
10
- //# sourceMappingURL=chunk-24Z2XE6C.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/toolbar-text.tsx"],"names":[],"mappings":";;;AAUO,SAAS,WAAA,CAAY,EAAE,IAAA,EAAM,IAAA,GAAO,WAAW,SAAA,GAAY,EAAA,EAAI,IAAG,EAAqB;AAC5F,EAAA,uBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,cAAA,EAAe,WAAA,EAAW,IAAA,EAAM,IAAS,QAAA,EAAA,IAAA,EAAK,CAAA;AAC3H","file":"chunk-24Z2XE6C.js","sourcesContent":["export type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small';\n\nexport interface ToolbarTextProps {\n text: string;\n size?: ToolbarTextSize;\n className?: string;\n /** Optional id, e.g. so a dialog can reference the title via aria-labelledby. */\n id?: string;\n}\n\nexport function ToolbarText({ text, size = 'default', className = '', id }: ToolbarTextProps) {\n return <span class={`kui-toolbar-text ${className}`.trim()} data-component=\"toolbar-text\" data-size={size} id={id}>{text}</span>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/select.tsx"],"names":[],"mappings":"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","file":"chunk-CTQKI2XL.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { LucideIcon, type LucideNode } from './lucide-icon.js';\n\nexport interface SelectChoice<Value extends string = string> {\n value: Value;\n label: string;\n icon?: LucideNode;\n iconName?: string;\n color?: string;\n group?: string;\n separatorBefore?: boolean;\n}\n\nexport interface SelectProps<Value extends string = string> {\n name: string;\n value: Value;\n label?: string;\n ariaLabel?: string;\n choices: readonly SelectChoice<Value>[];\n className?: string;\n placeholder?: string;\n disabled?: boolean;\n fitMenu?: boolean;\n renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;\n}\n\nexport function Select<Value extends string>({ name, value, label, ariaLabel, choices, className = '', placeholder, disabled = false, fitMenu = false, renderSelected }: SelectProps<Value>) {\n const selected = choices.find((choice) => choice.value === value);\n const icon = (choice: SelectChoice<Value>, selectedIcon = false) => <span data-key={`${name}:${choice.value}:${selectedIcon ? 'selected' : 'option'}`} data-morph-skip slot=\"start\" class={`kui-select__icon${selectedIcon ? ' kui-select__icon--selected' : ''}`} style={choice.color ? `color:${choice.color}` : undefined}>{choice.icon ? <LucideIcon icon={choice.icon} name={choice.iconName ?? choice.label.toLowerCase().replaceAll(' ', '-')} /> : null}</span>;\n const option = (choice: SelectChoice<Value>) => <>{choice.separatorBefore && <wa-divider></wa-divider>}<wa-option value={choice.value}>{choice.icon ? icon(choice) : null}{choice.label}</wa-option></>;\n const groups = [...new Set(choices.map((choice) => choice.group).filter((group): group is string => Boolean(group)))];\n const ungrouped = choices.filter((choice) => !choice.group);\n return <wa-select class={`kui-select${renderSelected ? ' kui-select--custom-selected' : ''}${fitMenu ? ' kui-select--fit-menu' : ''} ${className}`.trim()} data-component=\"select\" name={name} label={label} aria-label={ariaLabel} value={value} placeholder={placeholder} disabled={disabled}>\n {selected && (renderSelected ? <span data-key={`${name}:${value}:custom-selected`} slot=\"start\" class=\"kui-select__custom-selected\">{renderSelected(selected)}</span> : selected.icon ? icon(selected, true) : null)}\n {ungrouped.map(option)}\n {groups.map((group, index) => <div class={`kui-select__group${index > 0 || ungrouped.length > 0 ? ' kui-select__group--separated' : ''}`} role=\"group\" aria-label={group}><span class=\"kui-select__group-title\">{group}</span>{choices.filter((choice) => choice.group === group).map(option)}</div>)}\n </wa-select>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/menu-action-row.tsx"],"names":[],"mappings":";;;AAIA,IAAM,8BAAA,uBAAqC,GAAA,CAAI;AAAA,EAC7C,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAC,CAAA;AACD,IAAM,kCAAA,uBAAyC,GAAA,CAAI;AAAA,EACjD,gBAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAC,CAAA;AAsDM,SAAS,aAAA,CAAc,EAAE,KAAA,EAAO,IAAA,EAAM,QAAQ,MAAA,EAAQ,QAAA,GAAW,KAAA,EAAO,OAAA,EAAS,eAAA,EAAiB,KAAA,EAAO,SAAA,GAAY,KAAA,EAAO,OAAO,QAAA,GAAW,KAAA,EAAO,QAAA,EAAU,cAAA,EAAgB,mBAAA,EAAqB,kBAAA,EAAoB,sBAAA,GAAyB,KAAA,EAAO,qBAAqB,SAAA,GAAY,EAAA,EAAI,KAAA,EAAO,cAAA,GAAiB,EAAC,EAAG,wBAAA,GAA2B,IAAG,EAAuB;AACnX,EAAA,MAAM,uBAAA,GAA0B,oBAAA,CAAqB,cAAA,EAAgB,8BAA8B,CAAA;AACnG,EAAA,MAAM,2BAAA,GAA8B,uBAAA,CAAwB,wBAAA,EAA0B,kCAAkC,CAAA;AAExH,EAAA,4BAAQ,KAAA,EAAA,EAAK,GAAG,uBAAA,EAAyB,KAAA,EAAO,uBAAuB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,OAAc,gBAAA,EAAe,iBAAA,EAAkB,cAAA,EAAc,MAAA,EAAQ,iBAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,GAAG,gBAAA,EAAgB,SAAA,GAAY,MAAA,GAAS,MAAA,EAAW,cAAY,KAAA,EAAO,eAAA,EAAe,MAAA,CAAO,QAAQ,GAAG,cAAA,EAAc,OAAA,KAAY,SAAY,MAAA,GAAY,MAAA,CAAO,OAAO,CAAA,EACxW,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,KAAA,EAAM,8BAAA,EAA+B,OAAc,QAAA,EAAoB,QAAA,EAAU,QAAA,EAAU,aAAA,EAAa,MAAA,EAAQ,cAAA,EAAc,QAAQ,YAAA,EAAY,eAAA,EAAiB,cAAA,EAAc,QAAA,GAAW,MAAA,GAAS,MAAA,EAAW,cAAA,EAAc,OAAA,KAAY,MAAA,GAAY,MAAA,GAAY,MAAA,CAAO,OAAO,CAAA,EACnS,QAAA,EAAA;AAAA,MAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,2BAAA,EAA6B,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,sBACvD,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,4BAAA,EAA8B,QAAA,EAAA,KAAA,EAAM;AAAA,KAAA,EAClD,CAAA;AAAA,oBACA,GAAA,CAAC,YAAQ,GAAG,2BAAA,EAA6B,MAAK,QAAA,EAAS,KAAA,EAAM,wCAAuC,aAAA,EAAa,cAAA,EAAgB,gBAAc,MAAA,EAAQ,YAAA,EAAY,qBAAqB,KAAA,EAAO,mBAAA,IAAuB,qBAAqB,QAAA,EAAU,sBAAA,IAA0B,QAAY,QAAA,EAAA,kBAAA,EAAmB;AAAA,GAAA,EAChT,CAAA;AACF","file":"chunk-EGHL5S4P.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { filterControlAttributes, filterDataAttributes } from './extension-attributes.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-has-icon',\n 'data-multiline',\n 'data-state',\n 'data-selected',\n 'data-pressed',\n]);\nconst PROTECTED_TRAILING_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n]);\n\ntype MenuActionRowRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-has-icon'?: never;\n 'data-multiline'?: never;\n 'data-state'?: never;\n 'data-selected'?: never;\n 'data-pressed'?: never;\n }\n>;\n\ntype MenuActionRowTrailingAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n popoverTarget?: string;\n popoverTargetAction?: 'toggle' | 'show' | 'hide';\n 'aria-controls'?: string;\n 'aria-haspopup'?: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | 'true';\n }\n>;\n\nexport interface MenuActionRowProps {\n /** Visible dormant content for the primary button. Must not contain interactive descendants. */\n label: string | SafeHtml;\n /** Decorative dormant content for the primary button. Must not contain interactive descendants. */\n icon?: SafeHtml;\n action: string;\n itemId?: string;\n selected?: boolean;\n pressed?: boolean;\n accessibleLabel?: string;\n title?: string;\n multiline?: boolean;\n state?: string;\n disabled?: boolean;\n tabIndex?: number;\n trailingAction: string;\n trailingActionLabel: string;\n /** Decorative dormant content for the trailing button. Must not contain interactive descendants. */\n trailingActionIcon: SafeHtml;\n trailingActionDisabled?: boolean;\n trailingActionTitle?: string;\n className?: string;\n style?: string;\n rootAttributes?: MenuActionRowRootAttributes;\n trailingActionAttributes?: MenuActionRowTrailingAttributes;\n}\n\nexport function MenuActionRow({ label, icon, action, itemId, selected = false, pressed, accessibleLabel, title, multiline = false, state, disabled = false, tabIndex, trailingAction, trailingActionLabel, trailingActionIcon, trailingActionDisabled = false, trailingActionTitle, className = '', style, rootAttributes = {}, trailingActionAttributes = {} }: MenuActionRowProps) {\n const extensionRootAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);\n const extensionTrailingAttributes = filterControlAttributes(trailingActionAttributes, PROTECTED_TRAILING_DATA_ATTRIBUTES);\n\n return <div {...extensionRootAttributes} class={`kui-menu-action-row ${className}`.trim()} style={style} data-component=\"menu-action-row\" data-item-id={itemId} data-has-icon={String(Boolean(icon))} data-multiline={multiline ? 'true' : undefined} data-state={state} data-selected={String(selected)} data-pressed={pressed === undefined ? undefined : String(pressed)}>\n <button type=\"button\" class=\"kui-menu-action-row__primary\" title={title} disabled={disabled} tabindex={tabIndex} data-action={action} data-item-id={itemId} aria-label={accessibleLabel} aria-current={selected ? 'page' : undefined} aria-pressed={pressed === undefined ? undefined : String(pressed)}>\n {icon && <span class=\"kui-menu-action-row__icon\">{icon}</span>}\n <span class=\"kui-menu-action-row__label\">{label}</span>\n </button>\n <button {...extensionTrailingAttributes} type=\"button\" class=\"kui-menu-action-row__trailing-action\" data-action={trailingAction} data-item-id={itemId} aria-label={trailingActionLabel} title={trailingActionTitle ?? trailingActionLabel} disabled={trailingActionDisabled || undefined}>{trailingActionIcon}</button>\n </div>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/panel-header.tsx"],"names":[],"mappings":";;;;;AA4BO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,WAAW,IAAA,EAAM,aAAA,GAAgB,EAAA,EAAI,OAAA,EAAQ,EAAqB;AACvH,EAAA,MAAM,2BAAW,IAAA,CAAA,QAAA,EAAA,EACd,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAM,IAAA,EAAC,SAAA,EAAW,0BAA0B,aAAa,CAAA,CAAA,CAAG,IAAA,EAAK,EAAI,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACxG,GAAA,CAAC,eAAY,IAAA,EAAM,KAAA,EAAO,MAAK,QAAA,EAAS,EAAA,EAAI,OAAA,EAAS,SAAA,EAAU,yBAAA,EAA0B;AAAA,GAAA,EAC3F,CAAA;AAEA,EAAA,uBAAO,IAAA,CAAC,SAAI,KAAA,EAAM,kBAAA,EAAmB,kBAAe,cAAA,EAAe,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,GAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,oBAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAC5L,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAQ,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,OAAA,EAAS,SAAS,KAAA,EAAO,CAAA;AAAA,IAC9D,2BAAW,GAAA,CAAC,GAAA,EAAA,EAAE,OAAM,2BAAA,EAA4B,EAAA,EAAI,WAAY,QAAA,EAAA,OAAA,EAAQ;AAAA,GAAA,EAC3E,CAAA;AACF","file":"chunk-KZKSBUKC.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Toolbar } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\nimport { ToolbarText } from './toolbar-text.js';\n\nexport interface PanelHeaderProps {\n title: string;\n titleId: string;\n summary?: string;\n summaryId?: string;\n icon?: SafeHtml;\n iconClassName?: string;\n actions?: SafeHtml;\n}\n\n/**\n * The heading of a panel, dialog, or page: a plain `Toolbar` whose leading zone\n * holds an optional icon control group and the title as extra-large `ToolbarText`,\n * whose trailing zone holds the app's action controls, and with an optional\n * subtitle on its own row, left-aligned with the title.\n *\n * PanelHeader overrides no Toolbar styles — it is just a Toolbar with an xl title.\n * The only styling it adds is the icon group's fill/border color and the subtitle.\n * When no icon is provided, the icon group is omitted entirely. The `actions` slot\n * is passed straight into the toolbar's trailing zone; the app supplies whatever\n * trailing controls it needs (typically a `ToolbarControlGroup`).\n */\nexport function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName = '', actions }: PanelHeaderProps) {\n const identity = <>\n {icon && <ToolbarControlGroup single className={`kui-panel-header__icon ${iconClassName}`.trim()}>{icon}</ToolbarControlGroup>}\n <ToolbarText text={title} size=\"xlarge\" id={titleId} className=\"kui-panel-header__title\" />\n </>;\n\n return <div class=\"kui-panel-header\" data-component=\"panel-header\" data-has-icon={String(Boolean(icon))} data-has-actions={String(Boolean(actions))} data-has-summary={String(Boolean(summary))}>\n <Toolbar leading={identity} trailing={actions} divider={false} />\n {summary && <p class=\"kui-panel-header__summary\" id={summaryId}>{summary}</p>}\n </div>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/menu-header.tsx"],"names":[],"mappings":"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","file":"chunk-NPPD2A6O.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { DisclosureArrow } from './disclosure-arrow.js';\nimport { filterControlAttributes, filterDataAttributes } from './extension-attributes.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-has-badge',\n 'data-has-count',\n 'data-toggle',\n]);\nconst PROTECTED_TRIGGER_DATA_ATTRIBUTES = new Set(['data-action']);\n\ntype MenuHeaderRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-has-badge'?: never;\n 'data-has-count'?: never;\n 'data-toggle'?: never;\n }\n>;\n\ntype MenuHeaderTriggerAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-action'?: never;\n popoverTarget?: string;\n popoverTargetAction?: 'toggle' | 'show' | 'hide';\n 'aria-controls'?: string;\n 'aria-haspopup'?: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | 'true';\n }\n>;\n\ninterface MenuHeaderBaseProps {\n label: string;\n action?: string;\n actionLabel?: string;\n actionIcon?: SafeHtml;\n actionDisabled?: boolean;\n disabledReason?: string;\n expanded?: boolean;\n toggle?: boolean;\n rootAttributes?: MenuHeaderRootAttributes;\n triggerAttributes?: MenuHeaderTriggerAttributes;\n}\n\ntype MenuHeaderIndicatorProps =\n | { count: number; countLabel: string; badge?: never }\n | { count?: never; countLabel?: never; badge?: SafeHtml };\n\nexport type MenuHeaderProps = MenuHeaderBaseProps & MenuHeaderIndicatorProps;\n\nexport function MenuHeader({ label, count, countLabel, badge, action, actionLabel, actionIcon, actionDisabled = false, disabledReason, expanded, toggle = false, rootAttributes = {}, triggerAttributes = {} }: MenuHeaderProps) {\n const extensionRootAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);\n const extensionTriggerAttributes = filterControlAttributes(triggerAttributes, PROTECTED_TRIGGER_DATA_ATTRIBUTES);\n const normalizedCount = typeof count === 'number' && Number.isSafeInteger(count) && count >= 0 ? count : undefined;\n const normalizedCountLabel = normalizedCount === undefined\n ? undefined\n : typeof countLabel === 'string' && countLabel.trim() ? countLabel : String(normalizedCount);\n const renderedBadge = normalizedCount === undefined ? badge : undefined;\n const renderedActionIcon = actionIcon ?? (toggle ? <DisclosureArrow open={Boolean(expanded)} /> : undefined);\n const accessibleLabel = normalizedCount === undefined ? undefined : `${label}, ${normalizedCountLabel}`;\n const indicator = normalizedCount === undefined\n ? renderedBadge && <span class=\"kui-menu-header__badge\">{renderedBadge}</span>\n : <span class=\"kui-menu-header__count\" aria-hidden=\"true\">{normalizedCount}</span>;\n if (toggle) {\n return <header {...extensionRootAttributes} class=\"kui-menu-header\" data-component=\"menu-header\" data-has-badge={String(Boolean(renderedBadge))} data-has-count={String(normalizedCount !== undefined)} data-toggle=\"true\"><button {...extensionTriggerAttributes} type=\"button\" class=\"kui-menu-header__title kui-menu-header__toggle\" data-action={action} aria-label={accessibleLabel} aria-expanded={String(Boolean(expanded))}><span class=\"kui-menu-header__label\">{label}</span>{indicator}{renderedActionIcon && <span class=\"kui-menu-header__action-layer\">{renderedActionIcon}</span>}</button></header>;\n }\n return <header {...extensionRootAttributes} class=\"kui-menu-header\" data-component=\"menu-header\" data-has-badge={String(Boolean(renderedBadge))} data-has-count={String(normalizedCount !== undefined)} data-toggle=\"false\"><div class=\"kui-menu-header__title\"><h2 class=\"kui-menu-header__label\" aria-label={accessibleLabel}>{label}</h2>{indicator}</div>{action && <button {...extensionTriggerAttributes} type=\"button\" class=\"kui-menu-header__action\" data-action={action} aria-label={actionLabel} title={actionDisabled ? disabledReason : actionLabel} disabled={actionDisabled || undefined}>{renderedActionIcon}</button>}</header>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/value-table-row.tsx","../src/value-table.tsx"],"names":["jsx"],"mappings":";;;AASO,SAAS,cAAc,EAAE,KAAA,EAAO,OAAO,IAAA,EAAM,SAAA,GAAY,IAAG,EAAuB;AACxF,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,qBAAA,EAAwB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EAChG,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,IAAA,EAAA,EACE,QAAA,EAAA;AAAA,MAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,uBAAA,EAAyB,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,sBACnD,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,wBAAA,EAA0B,QAAA,EAAA,KAAA,EAAM;AAAA,KAAA,EAC9C,CAAA;AAAA,oBACA,GAAA,CAAC,QAAI,QAAA,EAAA,KAAA,EAAM;AAAA,GAAA,EACb,CAAA;AACF;ACPO,SAAS,WAAW,EAAE,KAAA,EAAO,SAAA,GAAY,EAAA,EAAI,UAAS,EAAoB;AAC/E,EAAA,uBAAOA,GAAAA,CAAC,IAAA,EAAA,EAAG,KAAA,EAAO,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,aAAA,EAAc,YAAA,EAAY,OAAQ,QAAA,EAAS,CAAA;AACrH","file":"chunk-R6JHHBKQ.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface ValueTableRowProps {\n label: string | SafeHtml;\n value: string | SafeHtml;\n icon?: SafeHtml;\n className?: string;\n}\n\nexport function ValueTableRow({ label, value, icon, className = '' }: ValueTableRowProps) {\n return <div class={`kui-value-table__row ${className}`.trim()} data-has-icon={String(Boolean(icon))}>\n <dt>\n {icon && <span class=\"kui-value-table__icon\">{icon}</span>}\n <span class=\"kui-value-table__label\">{label}</span>\n </dt>\n <dd>{value}</dd>\n </div>;\n}\n","import type { SafeHtml } from 'kerfjs';\n\nexport { ValueTableRow, type ValueTableRowProps } from './value-table-row.js';\n\nexport interface ValueTableProps {\n label: string;\n className?: string;\n children: SafeHtml | readonly SafeHtml[];\n}\n\nexport function ValueTable({ label, className = '', children }: ValueTableProps) {\n return <dl class={`kui-value-table ${className}`.trim()} data-component=\"value-table\" aria-label={label}>{children}</dl>;\n}\n"]}
@@ -1,23 +0,0 @@
1
- import { filterDataAttributes } from './chunk-7BR3DO2A.js';
2
- import { jsxs, jsx } from 'kerfjs/jsx-runtime';
3
-
4
- var PROTECTED_ROOT_DATA_ATTRIBUTES = /* @__PURE__ */ new Set([
5
- "data-component",
6
- "data-action",
7
- "data-item-id",
8
- "data-has-icon",
9
- "data-multiline",
10
- "data-state"
11
- ]);
12
- function MenuItem({ label, icon, trailing, selected = false, action, itemId, className = "", style, pressed, accessibleLabel, title, multiline = false, state, disabled = false, tabIndex, rootAttributes = {} }) {
13
- const extensionAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);
14
- return /* @__PURE__ */ jsxs("button", { ...extensionAttributes, type: "button", class: `kui-menu-item ${className}`.trim(), style, title, disabled, tabindex: tabIndex, "data-component": "menu-item", "data-action": action, "data-item-id": itemId, "data-has-icon": String(Boolean(icon)), "data-multiline": multiline ? "true" : void 0, "data-state": state, "aria-label": accessibleLabel, "aria-current": selected ? "page" : void 0, "aria-pressed": pressed === void 0 ? void 0 : String(pressed), children: [
15
- icon && /* @__PURE__ */ jsx("span", { class: "kui-menu-item__icon", children: icon }),
16
- /* @__PURE__ */ jsx("span", { class: "kui-menu-item__label", children: label }),
17
- trailing && /* @__PURE__ */ jsx("span", { class: "kui-menu-item__trailing", children: trailing })
18
- ] });
19
- }
20
-
21
- export { MenuItem };
22
-
23
- //# sourceMappingURL=chunk-S3TPM2LP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/menu-item.tsx"],"names":[],"mappings":";;;AAIA,IAAM,8BAAA,uBAAqC,GAAA,CAAI;AAAA,EAC7C,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAgCM,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,WAAW,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,SAAA,GAAY,EAAA,EAAI,KAAA,EAAO,SAAS,eAAA,EAAiB,KAAA,EAAO,SAAA,GAAY,KAAA,EAAO,KAAA,EAAO,QAAA,GAAW,OAAO,QAAA,EAAU,cAAA,GAAiB,EAAC,EAAE,EAAkB;AACtO,EAAA,MAAM,mBAAA,GAAsB,oBAAA,CAAqB,cAAA,EAAgB,8BAA8B,CAAA;AAC/F,EAAA,uBAAO,IAAA,CAAC,YAAQ,GAAG,mBAAA,EAAqB,MAAK,QAAA,EAAS,KAAA,EAAO,iBAAiB,SAAS,CAAA,CAAA,CAAG,MAAK,EAAG,KAAA,EAAc,OAAc,QAAA,EAAoB,QAAA,EAAU,UAAU,gBAAA,EAAe,WAAA,EAAY,aAAA,EAAa,MAAA,EAAQ,cAAA,EAAc,MAAA,EAAQ,iBAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EAAG,kBAAgB,SAAA,GAAY,MAAA,GAAS,MAAA,EAAW,YAAA,EAAY,KAAA,EAAO,YAAA,EAAY,iBAAiB,cAAA,EAAc,QAAA,GAAW,SAAS,MAAA,EAAW,cAAA,EAAc,YAAY,MAAA,GAAY,MAAA,GAAY,MAAA,CAAO,OAAO,CAAA,EAC5d,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,qBAAA,EAAuB,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACjD,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,sBAAA,EAAwB,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IACzC,QAAA,oBAAY,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,2BAA2B,QAAA,EAAA,QAAA,EAAS;AAAA,GAAA,EAC/D,CAAA;AACF","file":"chunk-S3TPM2LP.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { filterDataAttributes } from './extension-attributes.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-has-icon',\n 'data-multiline',\n 'data-state',\n]);\n\ntype MenuItemRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-has-icon'?: never;\n 'data-multiline'?: never;\n 'data-state'?: never;\n }\n>;\n\nexport interface MenuItemProps {\n label: string | SafeHtml;\n icon?: SafeHtml;\n trailing?: SafeHtml;\n selected?: boolean;\n action: string;\n itemId?: string;\n className?: string;\n style?: string;\n pressed?: boolean;\n accessibleLabel?: string;\n title?: string;\n multiline?: boolean;\n state?: string;\n disabled?: boolean;\n tabIndex?: number;\n rootAttributes?: MenuItemRootAttributes;\n}\n\nexport function MenuItem({ label, icon, trailing, selected = false, action, itemId, className = '', style, pressed, accessibleLabel, title, multiline = false, state, disabled = false, tabIndex, rootAttributes = {} }: MenuItemProps) {\n const extensionAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);\n return <button {...extensionAttributes} type=\"button\" class={`kui-menu-item ${className}`.trim()} style={style} title={title} disabled={disabled} tabindex={tabIndex} data-component=\"menu-item\" data-action={action} data-item-id={itemId} data-has-icon={String(Boolean(icon))} data-multiline={multiline ? 'true' : undefined} data-state={state} aria-label={accessibleLabel} aria-current={selected ? 'page' : undefined} aria-pressed={pressed === undefined ? undefined : String(pressed)}>\n {icon && <span class=\"kui-menu-item__icon\">{icon}</span>}\n <span class=\"kui-menu-item__label\">{label}</span>\n {trailing && <span class=\"kui-menu-item__trailing\">{trailing}</span>}\n </button>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/segmented-control.tsx"],"names":[],"mappings":";;;AA4BO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,EAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA,GAAS,gBAAA;AAAA,EACT,UAAA,GAAa,QAAA;AAAA,EACb,KAAA,GAAQ,SAAA;AAAA,EACR,IAAA,GAAO,SAAA;AAAA,EACP,MAAA,GAAS,SAAA;AAAA,EACT,SAAA,GAAY;AACd,CAAA,EAA0B;AACxB,EAAA,uBAAO,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACN,KAAA,EAAO,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MACjD,gBAAA,EAAe,mBAAA;AAAA,MACf,2BAAA,EAA2B,EAAA;AAAA,MAC3B,YAAA,EAAY,KAAA;AAAA,MACZ,iBAAA,EAAiB,UAAA;AAAA,MACjB,YAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAa,MAAA;AAAA,MACb,IAAA,EAAK,OAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MAEX,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AACvB,QAAA,MAAM,QAAA,GAAW,OAAO,KAAA,KAAU,KAAA;AAClC,QAAA,uBAAO,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACN,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,6BAAA;AAAA,YACN,aAAA,EAAa,MAAA;AAAA,YACb,sBAAoB,MAAA,CAAO,KAAA;AAAA,YAC3B,eAAA,EAAe,OAAO,QAAQ,CAAA;AAAA,YAC9B,cAAY,MAAA,CAAO,KAAA;AAAA,YACnB,cAAA,EAAc,OAAO,QAAQ,CAAA;AAAA,YAC7B,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,UAAU,MAAA,CAAO,QAAA;AAAA,YACjB,QAAA,EAAS,GAAA;AAAA,YACT,QAAA,EAAA,MAAA,CAAO,OAAA,oBAAW,GAAA,CAAC,MAAA,EAAA,EAAM,iBAAO,KAAA,EAAM;AAAA;AAAA,SAAQ;AAAA,MAClD,CAAC;AAAA;AAAA,GACH;AACF","file":"chunk-TRNBHPNW.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport type SegmentedControlAppearance = 'filled' | 'outlined' | 'toolbar';\nexport type SegmentedControlShape = 'rounded' | 'pill';\nexport type SegmentedControlSize = 'small' | 'default';\nexport type SegmentedControlLayout = 'content' | 'equal';\n\nexport interface SegmentedControlChoice {\n value: string;\n label: string;\n content?: SafeHtml;\n title?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps {\n id: string;\n label: string;\n value: string;\n choices: readonly SegmentedControlChoice[];\n action?: string;\n appearance?: SegmentedControlAppearance;\n shape?: SegmentedControlShape;\n size?: SegmentedControlSize;\n layout?: SegmentedControlLayout;\n className?: string;\n}\n\nexport function SegmentedControl({\n id,\n label,\n value,\n choices,\n action = 'select-segment',\n appearance = 'filled',\n shape = 'rounded',\n size = 'default',\n layout = 'content',\n className = '',\n}: SegmentedControlProps) {\n return <div\n class={`kui-segmented-control ${className}`.trim()}\n data-component=\"segmented-control\"\n data-segmented-control-id={id}\n data-value={value}\n data-appearance={appearance}\n data-shape={shape}\n data-size={size}\n data-layout={layout}\n role=\"group\"\n aria-label={label}\n >\n {choices.map((choice) => {\n const selected = choice.value === value;\n return <button\n type=\"button\"\n class=\"kui-segmented-control__item\"\n data-action={action}\n data-segment-value={choice.value}\n data-selected={String(selected)}\n aria-label={choice.label}\n aria-pressed={String(selected)}\n title={choice.title}\n disabled={choice.disabled}\n tabindex=\"0\"\n >{choice.content ?? <span>{choice.label}</span>}</button>;\n })}\n </div>;\n}\n"]}
@@ -1,17 +0,0 @@
1
- import { jsxs, jsx } from 'kerfjs/jsx-runtime';
2
-
3
- // src/state-banner.tsx
4
- function StateBanner({ title, detail, icon, action, tone = "info", urgency = "status", className = "" }) {
5
- return /* @__PURE__ */ jsxs("section", { class: `kui-state-banner ${className}`.trim(), "data-component": "state-banner", "data-tone": tone, role: urgency, "aria-live": urgency === "alert" ? "assertive" : "polite", children: [
6
- icon && /* @__PURE__ */ jsx("span", { class: "kui-state-banner__icon", children: icon }),
7
- /* @__PURE__ */ jsxs("div", { class: "kui-state-banner__copy", children: [
8
- /* @__PURE__ */ jsx("strong", { children: title }),
9
- detail && /* @__PURE__ */ jsx("span", { children: detail })
10
- ] }),
11
- action && /* @__PURE__ */ jsx("div", { class: "kui-state-banner__action", children: action })
12
- ] });
13
- }
14
-
15
- export { StateBanner };
16
-
17
- //# sourceMappingURL=chunk-VHW5YNIB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/state-banner.tsx"],"names":[],"mappings":";;;AAcO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,IAAA,GAAO,MAAA,EAAQ,OAAA,GAAU,QAAA,EAAU,SAAA,GAAY,EAAA,EAAG,EAAqB;AAChI,EAAA,4BAAQ,SAAA,EAAA,EAAQ,KAAA,EAAO,oBAAoB,SAAS,CAAA,CAAA,CAAG,MAAK,EAAG,gBAAA,EAAe,cAAA,EAAe,WAAA,EAAW,MAAM,IAAA,EAAM,OAAA,EAAS,aAAW,OAAA,KAAY,OAAA,GAAU,cAAc,QAAA,EACzK,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,wBAAA,EAA0B,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACpD,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,wBAAA,EAAyB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,YAAQ,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MAAU,MAAA,oBAAU,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,MAAA,EAAO;AAAA,KAAA,EAAQ,CAAA;AAAA,IAC5F,MAAA,oBAAU,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,4BAA4B,QAAA,EAAA,MAAA,EAAO;AAAA,GAAA,EAC3D,CAAA;AACF","file":"chunk-VHW5YNIB.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport type StateBannerTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n\nexport interface StateBannerProps {\n title: string;\n detail?: string;\n icon?: SafeHtml;\n action?: SafeHtml;\n tone?: StateBannerTone;\n urgency?: 'status' | 'alert';\n className?: string;\n}\n\nexport function StateBanner({ title, detail, icon, action, tone = 'info', urgency = 'status', className = '' }: StateBannerProps) {\n return <section class={`kui-state-banner ${className}`.trim()} data-component=\"state-banner\" data-tone={tone} role={urgency} aria-live={urgency === 'alert' ? 'assertive' : 'polite'}>\n {icon && <span class=\"kui-state-banner__icon\">{icon}</span>}\n <div class=\"kui-state-banner__copy\"><strong>{title}</strong>{detail && <span>{detail}</span>}</div>\n {action && <div class=\"kui-state-banner__action\">{action}</div>}\n </section>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/app-tab.tsx"],"names":[],"mappings":";;;AAIA,IAAM,8BAAA,uBAAqC,GAAA,CAAI;AAAA,EAC7C,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAC,CAAA;AA6BD,SAAS,SAAA,GAAY;AACnB,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,aAAA,EAAY,MAAA,EAAO,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,cAAA,EAAa,MAAA,EAAO,kBAAe,OAAA,EAAQ,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,YAAA,EAAa,CAAA;AAAA,oBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,YAAA,EAAa;AAAA,GAAA,EAAO,CAAA;AAC1L;AAEO,SAAS,MAAA,CAAO,EAAE,EAAA,EAAI,IAAA,EAAM,WAAW,KAAA,EAAO,QAAA,GAAW,IAAA,EAAM,SAAA,GAAY,KAAA,EAAO,OAAA,EAAS,UAAU,SAAA,EAAW,YAAA,GAAe,cAAc,WAAA,GAAc,WAAA,EAAa,YAAY,EAAA,EAAI,cAAA,GAAiB,EAAC,EAAE,EAAgB;AACjO,EAAA,MAAM,YAAA,GAAe,CAAC,QAAA,GAAW,kBAAA,GAAqB,EAAA,EAAI,SAAA,GAAY,0CAAA,GAA6C,EAAE,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAC/I,EAAA,MAAM,mBAAA,GAAsB,oBAAA,CAAqB,cAAA,EAAgB,8BAA8B,CAAA;AAC/F,EAAA,uBAAO,IAAA,CAAC,SAAK,GAAG,mBAAA,EAAqB,OAAO,CAAA,YAAA,EAAe,SAAS,GAAG,IAAA,EAAK,EAAG,kBAAe,SAAA,EAAU,aAAA,EAAa,IAAI,eAAA,EAAe,MAAA,CAAO,QAAQ,CAAA,EAAG,SAAA,EAAW,SAAA,GAAY,MAAA,GAAS,OAAA,EACvL,QAAA,EAAA;AAAA,IAAA,QAAA,oBAAY,GAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,QAAA,EAAS,IAAA,EAAK,KAAA,EAAM,oBAAA,EAAqB,aAAA,EAAa,WAAA,EAAa,aAAA,EAAa,EAAA,EAAI,cAAY,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,EAAI,KAAA,EAAO,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,EAAI,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,yBAAA,EAA0B,aAAA,EAAY,MAAA,EAAQ,QAAA,EAAA,SAAA,oBAAa,GAAA,CAAC,SAAA,EAAA,EAAU,GAAG,CAAA,EAAO,CAAA;AAAA,oBACxQ,IAAA,CAAC,YAAO,IAAA,EAAK,QAAA,EAAS,OAAM,qBAAA,EAAsB,IAAA,EAAK,KAAA,EAAM,eAAA,EAAe,MAAA,CAAO,QAAQ,GAAG,mBAAA,EAAmB,YAAA,IAAgB,QAAW,aAAA,EAAa,YAAA,EAAc,eAAa,EAAA,EAAI,QAAA,EAAU,QAAA,GAAW,GAAA,GAAM,IAAA,EAChN,QAAA,EAAA;AAAA,MAAA,OAAA;AAAA,sBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,mBAAA,EAAqB,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,MAAQ,YAAY,QAAA,mBAAW,GAAA,CAAC,UAAK,KAAA,EAAM,uBAAA,EAAyB,oBAAS,CAAA,GAAU;AAAA,KAAA,EACxI;AAAA,GAAA,EACF,CAAA;AACF","file":"chunk-XZXRLY5Q.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { filterDataAttributes } from './extension-attributes.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-tab-id',\n 'data-selected',\n 'data-tab-dragging',\n 'data-tab-drop-position',\n]);\n\ntype AppTabRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-tab-id'?: never;\n 'data-selected'?: never;\n 'data-tab-dragging'?: never;\n 'data-tab-drop-position'?: never;\n }\n>;\n\nexport interface AppTabProps {\n id: string;\n name: string;\n selected?: boolean;\n closable?: boolean;\n draggable?: boolean;\n leading?: SafeHtml;\n trailing?: SafeHtml;\n /** Decorative dormant content for the close button. Must not contain interactive descendants. */\n closeIcon?: SafeHtml;\n selectAction?: string;\n closeAction?: string;\n className?: string;\n rootAttributes?: AppTabRootAttributes;\n}\n\nfunction CloseIcon() {\n return <svg aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\"><path d=\"m7 7 10 10\"></path><path d=\"M17 7 7 17\"></path></svg>;\n}\n\nexport function AppTab({ id, name, selected = false, closable = true, draggable = false, leading, trailing, closeIcon, selectAction = 'select-tab', closeAction = 'close-tab', className = '', rootAttributes = {} }: AppTabProps) {\n const keyshortcuts = [closable ? 'Delete Backspace' : '', draggable ? 'Alt+Shift+ArrowLeft Alt+Shift+ArrowRight' : ''].filter(Boolean).join(' ');\n const extensionAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);\n return <div {...extensionAttributes} class={`kui-app-tab ${className}`.trim()} data-component=\"app-tab\" data-tab-id={id} data-selected={String(selected)} draggable={draggable ? 'true' : 'false'}>\n {closable && <button type=\"button\" tabindex=\"-1\" class=\"kui-app-tab__close\" data-action={closeAction} data-tab-id={id} aria-label={`Close ${name}`} title={`Close ${name}`}><span class=\"kui-app-tab__close-icon\" aria-hidden=\"true\">{closeIcon ?? <CloseIcon />}</span></button>}\n <button type=\"button\" class=\"kui-app-tab__select\" role=\"tab\" aria-selected={String(selected)} aria-keyshortcuts={keyshortcuts || undefined} data-action={selectAction} data-tab-id={id} tabindex={selected ? '0' : '-1'}>\n {leading}<span class=\"kui-app-tab__name\">{name}</span>{closable || trailing ? <span class=\"kui-app-tab__trailing\">{trailing}</span> : undefined}\n </button>\n </div>;\n}\n"]}