@kerfjs/ui 5.0.0-beta.17 → 5.0.0-beta.18

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 (213) hide show
  1. package/README.md +108 -79
  2. package/ai/component-catalog-extension.schema.json +79 -0
  3. package/ai/component-catalog.json +499 -0
  4. package/ai/component-catalog.schema.json +15 -0
  5. package/ai/public-api-signatures-v1.md +67 -31
  6. package/ai/skill.md +58 -49
  7. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  8. package/dist/app-tab.d.ts +1 -1
  9. package/dist/app-tab.js +1 -1
  10. package/dist/catalog.d.ts +10 -3
  11. package/dist/catalog.js +279 -90
  12. package/dist/catalog.js.map +1 -1
  13. package/dist/chunk-43FUQH35.js +83 -0
  14. package/dist/chunk-43FUQH35.js.map +1 -0
  15. package/dist/{chunk-YGN7OMLT.js → chunk-4TRDV6RL.js} +2 -2
  16. package/dist/chunk-4TRDV6RL.js.map +1 -0
  17. package/dist/chunk-6ETZKKAE.js +38 -0
  18. package/dist/chunk-6ETZKKAE.js.map +1 -0
  19. package/dist/chunk-6WTETUZ6.js +21 -0
  20. package/dist/chunk-6WTETUZ6.js.map +1 -0
  21. package/dist/chunk-7L6EHUMV.js +31 -0
  22. package/dist/chunk-7L6EHUMV.js.map +1 -0
  23. package/dist/chunk-BBRXX6PF.js +108 -0
  24. package/dist/chunk-BBRXX6PF.js.map +1 -0
  25. package/dist/chunk-DPDBVKNA.js +113 -0
  26. package/dist/chunk-DPDBVKNA.js.map +1 -0
  27. package/dist/chunk-ELSJX4W7.js +68 -0
  28. package/dist/chunk-ELSJX4W7.js.map +1 -0
  29. package/dist/{chunk-6NLRBSVX.js → chunk-ENVTNLYC.js} +125 -68
  30. package/dist/chunk-ENVTNLYC.js.map +1 -0
  31. package/dist/{chunk-AHQI52QO.js → chunk-FEY65TBV.js} +6 -2
  32. package/dist/chunk-FEY65TBV.js.map +1 -0
  33. package/dist/chunk-JTHUXDN2.js +58 -0
  34. package/dist/chunk-JTHUXDN2.js.map +1 -0
  35. package/dist/chunk-LPOMRC4C.js +25 -0
  36. package/dist/chunk-LPOMRC4C.js.map +1 -0
  37. package/dist/chunk-NENBUYX5.js +79 -0
  38. package/dist/chunk-NENBUYX5.js.map +1 -0
  39. package/dist/{chunk-XXMOARTH.js → chunk-NVWXKU37.js} +57 -16
  40. package/dist/chunk-NVWXKU37.js.map +1 -0
  41. package/dist/chunk-PIDTEQ3U.js +105 -0
  42. package/dist/chunk-PIDTEQ3U.js.map +1 -0
  43. package/dist/chunk-PX3YSS5C.js +32 -0
  44. package/dist/chunk-PX3YSS5C.js.map +1 -0
  45. package/dist/chunk-PZQVSDLH.js +61 -0
  46. package/dist/chunk-PZQVSDLH.js.map +1 -0
  47. package/dist/chunk-QIRXYKCE.js +113 -0
  48. package/dist/chunk-QIRXYKCE.js.map +1 -0
  49. package/dist/chunk-QO55FN2Y.js +20 -0
  50. package/dist/chunk-QO55FN2Y.js.map +1 -0
  51. package/dist/chunk-QQFJMRIB.js +45 -0
  52. package/dist/chunk-QQFJMRIB.js.map +1 -0
  53. package/dist/chunk-S3HKPI7I.js +218 -0
  54. package/dist/chunk-S3HKPI7I.js.map +1 -0
  55. package/dist/{chunk-WXMGNX2Y.js → chunk-S3PCZ7NV.js} +2 -2
  56. package/dist/chunk-S3PCZ7NV.js.map +1 -0
  57. package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
  58. package/dist/chunk-SRSJO5QE.js.map +1 -0
  59. package/dist/chunk-U5IFGQCD.js +117 -0
  60. package/dist/chunk-U5IFGQCD.js.map +1 -0
  61. package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
  62. package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
  63. package/dist/chunk-ZK2G3VR5.js +35 -0
  64. package/dist/chunk-ZK2G3VR5.js.map +1 -0
  65. package/dist/chunk-ZVI5YST2.js +41 -0
  66. package/dist/chunk-ZVI5YST2.js.map +1 -0
  67. package/dist/collapsible-panel.d.ts +2 -2
  68. package/dist/collapsible-panel.js +47 -6
  69. package/dist/collapsible-panel.js.map +1 -1
  70. package/dist/device-class.js +33 -5
  71. package/dist/device-class.js.map +1 -1
  72. package/dist/disclosure-arrow.js +1 -1
  73. package/dist/empty-state.d.ts +1 -1
  74. package/dist/empty-state.js +1 -1
  75. package/dist/floating-toolbar.d.ts +1 -1
  76. package/dist/floating-toolbar.js +1 -1
  77. package/dist/index.js +25 -25
  78. package/dist/list-action-row.d.ts +1 -1
  79. package/dist/list-action-row.js +1 -1
  80. package/dist/list-header.d.ts +1 -1
  81. package/dist/list-header.js +1 -1
  82. package/dist/list-inset-control.d.ts +1 -1
  83. package/dist/list-inset-control.js +1 -1
  84. package/dist/list-inset-text.d.ts +1 -1
  85. package/dist/list-inset-text.js +1 -1
  86. package/dist/list-item.d.ts +1 -1
  87. package/dist/list-item.js +1 -1
  88. package/dist/loading-spinner.js +1 -1
  89. package/dist/nav-stack.d.ts +1 -1
  90. package/dist/nav-stack.js +1 -1
  91. package/dist/panel-header.d.ts +1 -1
  92. package/dist/panel-header.js +1 -1
  93. package/dist/resizable-region.d.ts +1 -1
  94. package/dist/resizable-region.js +1 -1
  95. package/dist/segmented-control.js +1 -1
  96. package/dist/select.d.ts +1 -1
  97. package/dist/select.js +1 -1
  98. package/dist/skeleton.d.ts +1 -1
  99. package/dist/skeleton.js +1 -1
  100. package/dist/split-view.d.ts +1 -1
  101. package/dist/split-view.js +70 -10
  102. package/dist/split-view.js.map +1 -1
  103. package/dist/state-banner.d.ts +1 -1
  104. package/dist/state-banner.js +1 -1
  105. package/dist/styles/catalog.css +26 -0
  106. package/dist/tab-bar.d.ts +1 -1
  107. package/dist/tab-bar.js +1 -1
  108. package/dist/tab-scaffold.d.ts +1 -1
  109. package/dist/tab-scaffold.js +43 -8
  110. package/dist/tab-scaffold.js.map +1 -1
  111. package/dist/token-search-field.js +1 -1
  112. package/dist/toolbar-control-group.d.ts +1 -1
  113. package/dist/toolbar-control-group.js +1 -1
  114. package/dist/toolbar-text.js +1 -1
  115. package/dist/toolbar.d.ts +1 -1
  116. package/dist/toolbar.js +1 -1
  117. package/dist/value-table.d.ts +2 -2
  118. package/dist/value-table.js +1 -1
  119. package/dist/wire-catalog.d.ts +31 -2
  120. package/dist/wire-catalog.js +203 -8
  121. package/dist/wire-catalog.js.map +1 -1
  122. package/dist/wire-nav-stack.js +22 -7
  123. package/dist/wire-nav-stack.js.map +1 -1
  124. package/dist/wire-resizable-regions.d.ts +1 -1
  125. package/dist/wire-resizable-regions.js +1 -1
  126. package/dist/wire-sidebar.js +52 -41
  127. package/dist/wire-sidebar.js.map +1 -1
  128. package/dist/wire-tab-bars.js +1 -1
  129. package/dist/wire-tab-scaffold.js +9 -4
  130. package/dist/wire-tab-scaffold.js.map +1 -1
  131. package/dist/wire-token-search-fields.d.ts +1 -1
  132. package/dist/wire-token-search-fields.js +1 -1
  133. package/dist/workbench.d.ts +1 -1
  134. package/dist/workbench.js +56 -9
  135. package/dist/workbench.js.map +1 -1
  136. package/docs/app-layouts.md +7 -7
  137. package/docs/catalog.md +108 -24
  138. package/docs/collapsible-panel.md +38 -11
  139. package/docs/component-contract.md +30 -2
  140. package/docs/component-selection.md +71 -63
  141. package/docs/design/templates.md +1 -1
  142. package/docs/design-philosophy.md +5 -5
  143. package/docs/device-class.md +8 -8
  144. package/docs/examples/command-palette-adapter.tsx +67 -17
  145. package/docs/examples/component-catalog-extension.json +45 -0
  146. package/docs/layout.md +19 -19
  147. package/docs/nav-stack.md +15 -6
  148. package/docs/recipes.md +4 -4
  149. package/docs/split-view.md +3 -3
  150. package/docs/tab-scaffold.md +16 -7
  151. package/docs/webawesome-theme.md +8 -8
  152. package/docs/workbench.md +18 -5
  153. package/llms.txt +20 -14
  154. package/package.json +6 -4
  155. package/ux-demo/recipes/app-shell.tsx +206 -10
  156. package/ux-demo/recipes/collapsible-sidebar.tsx +167 -44
  157. package/ux-demo/recipes/compact-toolbar.tsx +114 -12
  158. package/ux-demo/recipes/composer-form.tsx +106 -18
  159. package/ux-demo/recipes/list-detail-dialog.tsx +144 -8
  160. package/ux-demo/recipes/list-workspace-states.tsx +165 -8
  161. package/ux-demo/recipes/loaders.ts +5 -2
  162. package/ux-demo/recipes/loading-inspector.tsx +124 -41
  163. package/ux-demo/recipes/mount-recipe.ts +27 -6
  164. package/ux-demo/recipes/navigation-sidebar.tsx +120 -9
  165. package/ux-demo/recipes/navigation-stack.tsx +61 -19
  166. package/ux-demo/recipes/types.ts +3 -1
  167. package/ux-demo/recipes/workspace-header.tsx +57 -2
  168. package/dist/chunk-2Z5TWHKQ.js +0 -34
  169. package/dist/chunk-2Z5TWHKQ.js.map +0 -1
  170. package/dist/chunk-37T3VNIZ.js +0 -19
  171. package/dist/chunk-37T3VNIZ.js.map +0 -1
  172. package/dist/chunk-55DATV3A.js +0 -10
  173. package/dist/chunk-55DATV3A.js.map +0 -1
  174. package/dist/chunk-5ATCDSQS.js +0 -42
  175. package/dist/chunk-5ATCDSQS.js.map +0 -1
  176. package/dist/chunk-5E2HVJ33.js +0 -10
  177. package/dist/chunk-5E2HVJ33.js.map +0 -1
  178. package/dist/chunk-6NLRBSVX.js.map +0 -1
  179. package/dist/chunk-7BR3DO2A.js.map +0 -1
  180. package/dist/chunk-7JB7VPRI.js +0 -34
  181. package/dist/chunk-7JB7VPRI.js.map +0 -1
  182. package/dist/chunk-7LDCTU7D.js +0 -134
  183. package/dist/chunk-7LDCTU7D.js.map +0 -1
  184. package/dist/chunk-AHQI52QO.js.map +0 -1
  185. package/dist/chunk-AQNKJRFH.js +0 -79
  186. package/dist/chunk-AQNKJRFH.js.map +0 -1
  187. package/dist/chunk-AVZHJN6C.js +0 -14
  188. package/dist/chunk-AVZHJN6C.js.map +0 -1
  189. package/dist/chunk-B24C4A6T.js +0 -22
  190. package/dist/chunk-B24C4A6T.js.map +0 -1
  191. package/dist/chunk-CH4SQ6H5.js +0 -39
  192. package/dist/chunk-CH4SQ6H5.js.map +0 -1
  193. package/dist/chunk-DAFFDO33.js +0 -14
  194. package/dist/chunk-DAFFDO33.js.map +0 -1
  195. package/dist/chunk-I7INRJO4.js +0 -17
  196. package/dist/chunk-I7INRJO4.js.map +0 -1
  197. package/dist/chunk-L4OKFDJY.js +0 -24
  198. package/dist/chunk-L4OKFDJY.js.map +0 -1
  199. package/dist/chunk-M5JRI6MN.js +0 -27
  200. package/dist/chunk-M5JRI6MN.js.map +0 -1
  201. package/dist/chunk-RNPGFQ33.js +0 -10
  202. package/dist/chunk-RNPGFQ33.js.map +0 -1
  203. package/dist/chunk-VPCTCUED.js +0 -10
  204. package/dist/chunk-VPCTCUED.js.map +0 -1
  205. package/dist/chunk-WRTAQ7BZ.js +0 -23
  206. package/dist/chunk-WRTAQ7BZ.js.map +0 -1
  207. package/dist/chunk-WVPYVDXY.js +0 -15
  208. package/dist/chunk-WVPYVDXY.js.map +0 -1
  209. package/dist/chunk-WXMGNX2Y.js.map +0 -1
  210. package/dist/chunk-XXMOARTH.js.map +0 -1
  211. package/dist/chunk-YGN7OMLT.js.map +0 -1
  212. package/dist/chunk-ZQQ6P4SV.js +0 -20
  213. package/dist/chunk-ZQQ6P4SV.js.map +0 -1
@@ -14,13 +14,124 @@ import type { RecipeFactory } from './types.js';
14
14
  export const createRecipe: RecipeFactory = (announce) => {
15
15
  const selected = signal('inbox');
16
16
  const expanded = signal(true);
17
- const render = () => <aside class="kui-recipe recipe-sidebar kui-recipe__surface kui-pane" data-recipe="recipe-navigation-sidebar">
18
- <div class="recipe-sidebar__body kui-pane__content kui-content">
19
- <section><ListHeader label="Workspace" count={3} countLabel="3 workspaces" action="recipe-action" actionLabel="Add workspace item" actionIcon={<LucideIcon icon={Plus} name="plus" />} /><ListItem action="recipe-action" itemId="inbox" label="Inbox" icon={<LucideIcon icon={Inbox} name="inbox" />} trailing={<span>12</span>} selected={selected.value === 'inbox'} /><ListItem action="recipe-action" itemId="shared" label="Shared with me" icon={<LucideIcon icon={Users} name="users" />} selected={selected.value === 'shared'} /><ListItem action="recipe-action" itemId="drafts" label="Drafts without an icon" selected={selected.value === 'drafts'} /></section>
20
- <section><ListHeader label="Projects" toggle action="recipe-action" expanded={expanded.value} />{expanded.value && <><ListItem action="recipe-action" itemId="design" label="Design system rollout across desktop and tablet" icon={<LucideIcon icon={Folder} name="folder" />} selected={selected.value === 'design'} multiline /><ListItem action="recipe-action" itemId="archive" label="Archived" disabled title="Available to administrators" /><div class="kui-content-item"><strong>Quarterly goal</strong><p class="kui-recipe__muted">Ship accessible navigation patterns to every workspace.</p></div></>}</section>
21
- <p class="kui-recipe__ownership kui-content-item">The recipe owns pane, content-item, and toolbar geometry. The app owns routes, permissions, labels, and disclosure state.</p>
22
- </div>
23
- <footer class="recipe-sidebar__footer kui-pane__footer"><Toolbar label="Sidebar actions" divider={false} leading={<ToolbarControlGroup appearance="borderless" single><button type="button" aria-label="Add project" data-action="recipe-action" data-recipe-command="add"><LucideIcon icon={Plus} name="plus" /></button></ToolbarControlGroup>} trailing={<ToolbarControlGroup appearance="borderless" single><button type="button" aria-label="Workspace settings" data-action="recipe-action" data-recipe-command="settings"><LucideIcon icon={Settings} name="settings" /></button></ToolbarControlGroup>} /></footer>
24
- </aside>;
25
- return { render, action(command, element) { if (element.matches('.kui-list-header__toggle')) { expanded.value = !expanded.value; announce(expanded.value ? 'Projects expanded' : 'Projects collapsed'); return; } const id = element.dataset.itemId; if (id) selected.value = id; announce(id ? `Selected ${id}` : `${command} requested`); } };
17
+ const render = () => (
18
+ <aside
19
+ class="kui-recipe recipe-sidebar kui-recipe__surface kui-pane"
20
+ data-recipe="recipe-navigation-sidebar"
21
+ >
22
+ <div class="recipe-sidebar__body kui-pane__content kui-content">
23
+ <section>
24
+ <ListHeader
25
+ label="Workspace"
26
+ count={3}
27
+ countLabel="3 workspaces"
28
+ action="recipe-action"
29
+ actionLabel="Add workspace item"
30
+ actionIcon={<LucideIcon icon={Plus} name="plus" />}
31
+ />
32
+ <ListItem
33
+ action="recipe-action"
34
+ itemId="inbox"
35
+ label="Inbox"
36
+ icon={<LucideIcon icon={Inbox} name="inbox" />}
37
+ trailing={<span>12</span>}
38
+ selected={selected.value === 'inbox'}
39
+ />
40
+ <ListItem
41
+ action="recipe-action"
42
+ itemId="shared"
43
+ label="Shared with me"
44
+ icon={<LucideIcon icon={Users} name="users" />}
45
+ selected={selected.value === 'shared'}
46
+ />
47
+ <ListItem
48
+ action="recipe-action"
49
+ itemId="drafts"
50
+ label="Drafts without an icon"
51
+ selected={selected.value === 'drafts'}
52
+ />
53
+ </section>
54
+ <section>
55
+ <ListHeader
56
+ label="Projects"
57
+ toggle
58
+ action="recipe-action"
59
+ expanded={expanded.value}
60
+ />
61
+ {expanded.value && (
62
+ <>
63
+ <ListItem
64
+ action="recipe-action"
65
+ itemId="design"
66
+ label="Design system rollout across desktop and tablet"
67
+ icon={<LucideIcon icon={Folder} name="folder" />}
68
+ selected={selected.value === 'design'}
69
+ multiline
70
+ />
71
+ <ListItem
72
+ action="recipe-action"
73
+ itemId="archive"
74
+ label="Archived"
75
+ disabled
76
+ title="Available to administrators"
77
+ />
78
+ <div class="kui-content-item">
79
+ <strong>Quarterly goal</strong>
80
+ <p class="kui-recipe__muted">
81
+ Ship accessible navigation patterns to every workspace.
82
+ </p>
83
+ </div>
84
+ </>
85
+ )}
86
+ </section>
87
+ <p class="kui-recipe__ownership kui-content-item">
88
+ The recipe owns pane, content-item, and toolbar geometry. The app owns
89
+ routes, permissions, labels, and disclosure state.
90
+ </p>
91
+ </div>
92
+ <footer class="recipe-sidebar__footer kui-pane__footer">
93
+ <Toolbar
94
+ label="Sidebar actions"
95
+ divider={false}
96
+ leading={
97
+ <ToolbarControlGroup appearance="borderless" single>
98
+ <button
99
+ type="button"
100
+ aria-label="Add project"
101
+ data-action="recipe-action"
102
+ data-recipe-command="add"
103
+ >
104
+ <LucideIcon icon={Plus} name="plus" />
105
+ </button>
106
+ </ToolbarControlGroup>
107
+ }
108
+ trailing={
109
+ <ToolbarControlGroup appearance="borderless" single>
110
+ <button
111
+ type="button"
112
+ aria-label="Workspace settings"
113
+ data-action="recipe-action"
114
+ data-recipe-command="settings"
115
+ >
116
+ <LucideIcon icon={Settings} name="settings" />
117
+ </button>
118
+ </ToolbarControlGroup>
119
+ }
120
+ />
121
+ </footer>
122
+ </aside>
123
+ );
124
+ return {
125
+ render,
126
+ action(command, element) {
127
+ if (element.matches('.kui-list-header__toggle')) {
128
+ expanded.value = !expanded.value;
129
+ announce(expanded.value ? 'Projects expanded' : 'Projects collapsed');
130
+ return;
131
+ }
132
+ const id = element.dataset.itemId;
133
+ if (id) selected.value = id;
134
+ announce(id ? `Selected ${id}` : `${command} requested`);
135
+ },
136
+ };
26
137
  };
@@ -19,41 +19,83 @@ interface LibraryItem {
19
19
  }
20
20
 
21
21
  const ITEMS: LibraryItem[] = [
22
- { id: 'tokens', label: 'Design tokens', detail: 'Semantic color, spacing, and radius scales shared across every surface.' },
23
- { id: 'controls', label: 'Toolbar controls', detail: 'Control groups and segmented controls with their hover and pressed contracts.' },
24
- { id: 'layouts', label: 'App layouts', detail: 'Navigation stacks, split views, workbench, and bottom-tab scaffolds.' },
22
+ {
23
+ id: 'tokens',
24
+ label: 'Design tokens',
25
+ detail:
26
+ 'Semantic color, spacing, and radius scales shared across every surface.',
27
+ },
28
+ {
29
+ id: 'controls',
30
+ label: 'Toolbar controls',
31
+ detail:
32
+ 'Control groups and segmented controls with their hover and pressed contracts.',
33
+ },
34
+ {
35
+ id: 'layouts',
36
+ label: 'App layouts',
37
+ detail:
38
+ 'Navigation stacks, split views, workbench, and bottom-tab scaffolds.',
39
+ },
25
40
  ];
26
41
 
27
42
  export const createRecipe: RecipeFactory = (announce) => {
28
43
  const listView = (): NavStackView => ({
29
44
  key: 'library',
30
45
  title: 'Library',
31
- content: <div class="recipe-navstack__view kui-pane__content kui-content">
32
- <section>
33
- <ListHeader label="Components" />
34
- {ITEMS.map((item) => <ListItem action="recipe-action" itemId={item.id} label={item.label} icon={<LucideIcon icon={Folder} name="folder" />} trailing={<LucideIcon icon={ChevronRight} name="chevron-right" />} />)}
35
- </section>
36
- <p class="kui-recipe__ownership kui-content-item">The recipe owns the stack as a signal of views and pushes/pops it; `NavStack` renders the stack and `wireNavStack` slides the content and settles the chrome. The app owns selection, data, and routing.</p>
37
- </div>,
46
+ content: (
47
+ <div class="recipe-navstack__view kui-pane__content kui-content">
48
+ <section>
49
+ <ListHeader label="Components" />
50
+ {ITEMS.map((item) => (
51
+ <ListItem
52
+ action="recipe-action"
53
+ itemId={item.id}
54
+ label={item.label}
55
+ icon={<LucideIcon icon={Folder} name="folder" />}
56
+ trailing={<LucideIcon icon={ChevronRight} name="chevron-right" />}
57
+ />
58
+ ))}
59
+ </section>
60
+ <p class="kui-recipe__ownership kui-content-item">
61
+ The recipe owns the stack as a signal of views and pushes/pops it;
62
+ `NavStack` renders the stack and `wireNavStack` slides the content and
63
+ settles the chrome. The app owns selection, data, and routing.
64
+ </p>
65
+ </div>
66
+ ),
38
67
  });
39
68
 
40
69
  const detailView = (item: LibraryItem): NavStackView => ({
41
70
  key: item.id,
42
71
  title: item.label,
43
- content: <div class="recipe-navstack__view kui-pane__content kui-content">
44
- <div class="kui-content-item">
45
- <LucideIcon icon={FileText} name="file-text" />
46
- <strong>{item.label}</strong>
47
- <p class="kui-recipe__muted">{item.detail}</p>
72
+ content: (
73
+ <div class="recipe-navstack__view kui-pane__content kui-content">
74
+ <div class="kui-content-item">
75
+ <LucideIcon icon={FileText} name="file-text" />
76
+ <strong>{item.label}</strong>
77
+ <p class="kui-recipe__muted">{item.detail}</p>
78
+ </div>
48
79
  </div>
49
- </div>,
80
+ ),
50
81
  });
51
82
 
52
83
  const views = signal<NavStackView[]>([listView()]);
53
84
 
54
- const render = () => <section class="kui-recipe recipe-navstack kui-recipe__surface" data-recipe="recipe-navigation-stack">
55
- <div class="recipe-navstack__stage"><NavStack id="recipe-nav" label="Component library" views={views.value} /></div>
56
- </section>;
85
+ const render = () => (
86
+ <section
87
+ class="kui-recipe recipe-navstack kui-recipe__surface"
88
+ data-recipe="recipe-navigation-stack"
89
+ >
90
+ <div class="recipe-navstack__stage">
91
+ <NavStack
92
+ id="recipe-nav"
93
+ label="Component library"
94
+ views={views.value}
95
+ />
96
+ </div>
97
+ </section>
98
+ );
57
99
 
58
100
  return {
59
101
  render,
@@ -14,4 +14,6 @@ export interface RecipeController {
14
14
  wire?(root: HTMLElement): () => void;
15
15
  }
16
16
 
17
- export type RecipeFactory = (announce: (message: string) => void) => RecipeController;
17
+ export type RecipeFactory = (
18
+ announce: (message: string) => void,
19
+ ) => RecipeController;
@@ -7,6 +7,61 @@ import { StateBanner } from '@kerfjs/ui/state-banner';
7
7
  import type { RecipeFactory } from './types.js';
8
8
 
9
9
  export const createRecipe: RecipeFactory = (announce) => ({
10
- render: () => <section class="kui-recipe recipe-header kui-recipe__surface kui-content" data-recipe="recipe-workspace-header"><p class="recipe-header__context kui-inline-metadata kui-content-item"><span>Northstar workspace</span><span>·</span><span>Product planning</span></p><PanelHeader title="Accessibility readiness and responsive navigation rollout" titleId="recipe-workspace-title" actions={<div class="kui-control-cluster"><button class="kui-recipe__button" type="button" data-action="recipe-action" data-recipe-command="share">Share</button><button class="kui-recipe__button" type="button" data-action="recipe-action" data-recipe-command="more">More actions</button><button class="kui-recipe__button" data-primary="true" type="button" data-action="recipe-action" data-recipe-command="publish">Publish update</button></div>} /><StateBanner title="Ready for review" detail="All required checks passed 18 minutes ago." tone="success" /><p class="kui-recipe__ownership kui-content-item">The recipe owns page hierarchy and action relocation. The app owns authorization, command behavior, breadcrumbs, and product copy.</p></section>,
11
- action(command) { announce(`${command} requested`); },
10
+ render: () => (
11
+ <section
12
+ class="kui-recipe recipe-header kui-recipe__surface kui-content"
13
+ data-recipe="recipe-workspace-header"
14
+ >
15
+ <p class="recipe-header__context kui-inline-metadata kui-content-item">
16
+ <span>Northstar workspace</span>
17
+ <span>·</span>
18
+ <span>Product planning</span>
19
+ </p>
20
+ <PanelHeader
21
+ title="Accessibility readiness and responsive navigation rollout"
22
+ titleId="recipe-workspace-title"
23
+ actions={
24
+ <div class="kui-control-cluster">
25
+ <button
26
+ class="kui-recipe__button"
27
+ type="button"
28
+ data-action="recipe-action"
29
+ data-recipe-command="share"
30
+ >
31
+ Share
32
+ </button>
33
+ <button
34
+ class="kui-recipe__button"
35
+ type="button"
36
+ data-action="recipe-action"
37
+ data-recipe-command="more"
38
+ >
39
+ More actions
40
+ </button>
41
+ <button
42
+ class="kui-recipe__button"
43
+ data-primary="true"
44
+ type="button"
45
+ data-action="recipe-action"
46
+ data-recipe-command="publish"
47
+ >
48
+ Publish update
49
+ </button>
50
+ </div>
51
+ }
52
+ />
53
+ <StateBanner
54
+ title="Ready for review"
55
+ detail="All required checks passed 18 minutes ago."
56
+ tone="success"
57
+ />
58
+ <p class="kui-recipe__ownership kui-content-item">
59
+ The recipe owns page hierarchy and action relocation. The app owns
60
+ authorization, command behavior, breadcrumbs, and product copy.
61
+ </p>
62
+ </section>
63
+ ),
64
+ action(command) {
65
+ announce(`${command} requested`);
66
+ },
12
67
  });
@@ -1,34 +0,0 @@
1
- import { filterDataAttributes } from './chunk-7BR3DO2A.js';
2
- import { Skeleton } from './chunk-B24C4A6T.js';
3
- import { jsxs, jsx } from 'kerfjs/jsx-runtime';
4
-
5
- var PROTECTED_ROOT_DATA_ATTRIBUTES = /* @__PURE__ */ new Set([
6
- "data-component",
7
- "data-action",
8
- "data-tab-id",
9
- "data-selected",
10
- "data-tab-dragging",
11
- "data-tab-drop-position"
12
- ]);
13
- function CloseIcon() {
14
- return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2.25", "stroke-linecap": "round", children: [
15
- /* @__PURE__ */ jsx("path", { d: "m7 7 10 10" }),
16
- /* @__PURE__ */ jsx("path", { d: "M17 7 7 17" })
17
- ] });
18
- }
19
- function AppTab({ id, name, selected = false, closable = true, draggable = false, leading, trailing, closeIcon, selectAction = "select-tab", closeAction = "close-tab", className = "", placeholder = false, rootAttributes = {} }) {
20
- const keyshortcuts = [closable ? "Delete Backspace" : "", draggable ? "Alt+Shift+ArrowLeft Alt+Shift+ArrowRight" : ""].filter(Boolean).join(" ");
21
- const extensionAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);
22
- return /* @__PURE__ */ jsxs("div", { ...extensionAttributes, class: `kui-app-tab ${className}`.trim(), "data-component": "app-tab", "data-tab-id": id, "data-selected": String(selected), "data-placeholder": placeholder ? "true" : void 0, draggable: placeholder ? "false" : draggable ? "true" : "false", "aria-busy": placeholder ? "true" : void 0, children: [
23
- closable && /* @__PURE__ */ jsx("button", { type: "button", tabindex: "-1", class: "kui-app-tab__close", "data-action": placeholder ? void 0 : closeAction, "data-tab-id": id, disabled: placeholder || void 0, "aria-label": `Close ${name}`, title: `Close ${name}`, children: /* @__PURE__ */ jsx("span", { class: "kui-app-tab__close-icon", "aria-hidden": "true", children: closeIcon ?? /* @__PURE__ */ jsx(CloseIcon, {}) }) }),
24
- /* @__PURE__ */ jsxs("button", { type: "button", class: "kui-app-tab__select", role: "tab", "aria-selected": String(selected), "aria-keyshortcuts": placeholder ? void 0 : keyshortcuts || void 0, "data-action": placeholder ? void 0 : selectAction, "data-tab-id": id, disabled: placeholder || void 0, tabindex: placeholder ? "-1" : selected ? "0" : "-1", children: [
25
- leading,
26
- /* @__PURE__ */ jsx("span", { class: "kui-app-tab__name", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "7em" }) : name }),
27
- closable || trailing ? /* @__PURE__ */ jsx("span", { class: "kui-app-tab__trailing", children: trailing }) : void 0
28
- ] })
29
- ] });
30
- }
31
-
32
- export { AppTab };
33
-
34
- //# sourceMappingURL=chunk-2Z5TWHKQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/app-tab.tsx"],"names":[],"mappings":";;;;AAKA,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;AA+BD,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,QAAA,GAAW,OAAO,QAAA,GAAW,IAAA,EAAM,SAAA,GAAY,KAAA,EAAO,OAAA,EAAS,QAAA,EAAU,WAAW,YAAA,GAAe,YAAA,EAAc,WAAA,GAAc,WAAA,EAAa,SAAA,GAAY,EAAA,EAAI,cAAc,KAAA,EAAO,cAAA,GAAiB,EAAC,EAAE,EAAgB;AACtP,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,KAAA,EAAA,EAAK,GAAG,mBAAA,EAAqB,KAAA,EAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,SAAA,EAAU,eAAa,EAAA,EAAI,eAAA,EAAe,MAAA,CAAO,QAAQ,CAAA,EAAG,kBAAA,EAAkB,WAAA,GAAc,MAAA,GAAS,QAAW,SAAA,EAAW,WAAA,GAAc,OAAA,GAAU,SAAA,GAAY,MAAA,GAAS,OAAA,EAAS,WAAA,EAAW,WAAA,GAAc,SAAS,MAAA,EAC9S,QAAA,EAAA;AAAA,IAAA,QAAA,oBAAY,GAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,UAAS,IAAA,EAAK,KAAA,EAAM,oBAAA,EAAqB,aAAA,EAAa,cAAc,MAAA,GAAY,WAAA,EAAa,aAAA,EAAa,EAAA,EAAI,UAAU,WAAA,IAAe,MAAA,EAAW,YAAA,EAAY,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA,EAAI,KAAA,EAAO,CAAA,MAAA,EAAS,IAAI,IAAI,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,yBAAA,EAA0B,eAAY,MAAA,EAAQ,QAAA,EAAA,SAAA,oBAAa,GAAA,CAAC,SAAA,EAAA,EAAU,GAAG,CAAA,EAAO,CAAA;AAAA,oBACtU,IAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,KAAA,EAAM,qBAAA,EAAsB,IAAA,EAAK,KAAA,EAAM,eAAA,EAAe,MAAA,CAAO,QAAQ,CAAA,EAAG,qBAAmB,WAAA,GAAc,MAAA,GAAY,YAAA,IAAgB,MAAA,EAAW,aAAA,EAAa,WAAA,GAAc,MAAA,GAAY,YAAA,EAAc,eAAa,EAAA,EAAI,QAAA,EAAU,WAAA,IAAe,MAAA,EAAW,QAAA,EAAU,WAAA,GAAc,IAAA,GAAO,QAAA,GAAW,MAAM,IAAA,EAC7T,QAAA,EAAA;AAAA,MAAA,OAAA;AAAA,sBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,mBAAA,EAAqB,QAAA,EAAA,WAAA,uBAAe,QAAA,EAAA,EAAS,KAAA,EAAM,KAAA,EAAM,CAAA,GAAK,IAAA,EAAK,CAAA;AAAA,MAAQ,YAAY,QAAA,mBAAW,GAAA,CAAC,UAAK,KAAA,EAAM,uBAAA,EAAyB,oBAAS,CAAA,GAAU;AAAA,KAAA,EACjL;AAAA,GAAA,EACF,CAAA;AACF","file":"chunk-2Z5TWHKQ.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { filterDataAttributes } from './extension-attributes.js';\nimport { Skeleton } from './skeleton.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 /** Render as an unanimated loading skeleton, disabling select/close and dragging. */\n placeholder?: boolean;\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 = '', placeholder = false, 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)} data-placeholder={placeholder ? 'true' : undefined} draggable={placeholder ? 'false' : draggable ? 'true' : 'false'} aria-busy={placeholder ? 'true' : undefined}>\n {closable && <button type=\"button\" tabindex=\"-1\" class=\"kui-app-tab__close\" data-action={placeholder ? undefined : closeAction} data-tab-id={id} disabled={placeholder || undefined} 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={placeholder ? undefined : keyshortcuts || undefined} data-action={placeholder ? undefined : selectAction} data-tab-id={id} disabled={placeholder || undefined} tabindex={placeholder ? '-1' : selected ? '0' : '-1'}>\n {leading}<span class=\"kui-app-tab__name\">{placeholder ? <Skeleton width=\"7em\" /> : name}</span>{closable || trailing ? <span class=\"kui-app-tab__trailing\">{trailing}</span> : undefined}\n </button>\n </div>;\n}\n"]}
@@ -1,19 +0,0 @@
1
- import { Skeleton } from './chunk-B24C4A6T.js';
2
- import { jsxs, jsx } from 'kerfjs/jsx-runtime';
3
-
4
- function ValueTableRow({ label, value, icon, className = "", placeholder = false }) {
5
- return /* @__PURE__ */ jsxs("div", { class: `kui-value-table__row ${className}`.trim(), "data-has-icon": String(Boolean(icon)), "data-placeholder": placeholder ? "true" : void 0, children: [
6
- /* @__PURE__ */ jsxs("dt", { children: [
7
- icon && /* @__PURE__ */ jsx("span", { class: "kui-value-table__icon", children: icon }),
8
- /* @__PURE__ */ jsx("span", { class: "kui-value-table__label", children: label })
9
- ] }),
10
- /* @__PURE__ */ jsx("dd", { children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "10em" }) : value })
11
- ] });
12
- }
13
- function ValueTable({ label, className = "", children }) {
14
- return /* @__PURE__ */ jsx("dl", { class: `kui-value-table ${className}`.trim(), "data-component": "value-table", "aria-label": label, children });
15
- }
16
-
17
- export { ValueTable, ValueTableRow };
18
-
19
- //# sourceMappingURL=chunk-37T3VNIZ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/value-table-row.tsx","../src/value-table.tsx"],"names":["jsx"],"mappings":";;;AAaO,SAAS,aAAA,CAAc,EAAE,KAAA,EAAO,KAAA,EAAO,MAAM,SAAA,GAAY,EAAA,EAAI,WAAA,GAAc,KAAA,EAAM,EAAuB;AAC7G,EAAA,4BAAQ,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,qBAAA,EAAwB,SAAS,GAAG,IAAA,EAAK,EAAG,eAAA,EAAe,MAAA,CAAO,QAAQ,IAAI,CAAC,GAAG,kBAAA,EAAkB,WAAA,GAAc,SAAS,MAAA,EAC5I,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,WAAA,mBAAc,GAAA,CAAC,YAAS,KAAA,EAAM,MAAA,EAAO,IAAK,KAAA,EAAM;AAAA,GAAA,EACvD,CAAA;AACF;ACXO,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-37T3VNIZ.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Skeleton } from './skeleton.js';\n\nexport interface ValueTableRowProps {\n label: string | SafeHtml;\n value: string | SafeHtml;\n icon?: SafeHtml;\n className?: string;\n /** Render the value as an unanimated loading skeleton, keeping the field label. */\n placeholder?: boolean;\n}\n\nexport function ValueTableRow({ label, value, icon, className = '', placeholder = false }: ValueTableRowProps) {\n return <div class={`kui-value-table__row ${className}`.trim()} data-has-icon={String(Boolean(icon))} data-placeholder={placeholder ? 'true' : undefined}>\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>{placeholder ? <Skeleton width=\"10em\" /> : 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,10 +0,0 @@
1
- import { jsx } from 'kerfjs/jsx-runtime';
2
-
3
- // src/loading-spinner.tsx
4
- function LoadingSpinner({ className = "", label }) {
5
- return /* @__PURE__ */ jsx("svg", { class: `kui-loading-spinner ${className}`.trim(), "data-component": "loading-spinner", viewBox: "0 0 24 24", role: label ? "img" : void 0, "aria-label": label, "aria-hidden": label ? void 0 : "true", children: /* @__PURE__ */ jsx("path", { d: "M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z" }) });
6
- }
7
-
8
- export { LoadingSpinner };
9
-
10
- //# sourceMappingURL=chunk-55DATV3A.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/loading-spinner.tsx"],"names":[],"mappings":";;;AAMO,SAAS,cAAA,CAAe,EAAE,SAAA,GAAY,EAAA,EAAI,OAAM,EAAwB;AAC7E,EAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,iBAAA,EAAkB,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAM,QAAQ,KAAA,GAAQ,MAAA,EAAW,YAAA,EAAY,KAAA,EAAO,aAAA,EAAa,KAAA,GAAQ,MAAA,GAAY,MAAA,EAAQ,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,kKAAA,EAAmK,CAAA,EAAO,CAAA;AACpY","file":"chunk-55DATV3A.js","sourcesContent":["export interface LoadingSpinnerProps {\n className?: string;\n label?: string;\n}\n\n/** Stable viewBox-centered progress ring based on svg-spinners' MIT-licensed 180-ring. */\nexport function LoadingSpinner({ className = '', label }: LoadingSpinnerProps) {\n return <svg class={`kui-loading-spinner ${className}`.trim()} data-component=\"loading-spinner\" viewBox=\"0 0 24 24\" role={label ? 'img' : undefined} aria-label={label} aria-hidden={label ? undefined : 'true'}><path d=\"M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z\"></path></svg>;\n}\n"]}
@@ -1,42 +0,0 @@
1
- import { filterDataAttributes, filterControlAttributes } from './chunk-7BR3DO2A.js';
2
- import { Skeleton } from './chunk-B24C4A6T.js';
3
- import { DisclosureArrow } from './chunk-56RJXPHG.js';
4
- import { jsx, jsxs } from 'kerfjs/jsx-runtime';
5
-
6
- var PROTECTED_ROOT_DATA_ATTRIBUTES = /* @__PURE__ */ new Set([
7
- "data-component",
8
- "data-action",
9
- "data-has-badge",
10
- "data-has-count",
11
- "data-toggle"
12
- ]);
13
- var PROTECTED_TRIGGER_DATA_ATTRIBUTES = /* @__PURE__ */ new Set(["data-action"]);
14
- function ListHeader({ label, count, countLabel, badge, action, actionLabel, actionIcon, actionDisabled = false, disabledReason, expanded, toggle = false, placeholder = false, rootAttributes = {}, triggerAttributes = {} }) {
15
- const extensionRootAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);
16
- const extensionTriggerAttributes = filterControlAttributes(triggerAttributes, PROTECTED_TRIGGER_DATA_ATTRIBUTES);
17
- const normalizedCount = typeof count === "number" && Number.isSafeInteger(count) && count >= 0 ? count : void 0;
18
- const normalizedCountLabel = normalizedCount === void 0 ? void 0 : typeof countLabel === "string" && countLabel.trim() ? countLabel : String(normalizedCount);
19
- const renderedBadge = normalizedCount === void 0 ? badge : void 0;
20
- const renderedActionIcon = actionIcon ?? (toggle ? /* @__PURE__ */ jsx(DisclosureArrow, { open: Boolean(expanded) }) : void 0);
21
- const accessibleLabel = normalizedCount === void 0 ? void 0 : `${label}, ${normalizedCountLabel}`;
22
- const indicator = placeholder ? (normalizedCount !== void 0 || renderedBadge) && /* @__PURE__ */ jsx("span", { class: "kui-list-header__badge", children: /* @__PURE__ */ jsx(Skeleton, { width: "1.75em" }) }) : normalizedCount === void 0 ? renderedBadge && /* @__PURE__ */ jsx("span", { class: "kui-list-header__badge", children: renderedBadge }) : /* @__PURE__ */ jsx("span", { class: "kui-list-header__count", "aria-hidden": "true", children: normalizedCount });
23
- const busy = placeholder ? "true" : void 0;
24
- if (toggle) {
25
- return /* @__PURE__ */ jsx("header", { ...extensionRootAttributes, class: "kui-list-header", "data-component": "list-header", "data-has-badge": String(Boolean(renderedBadge)), "data-has-count": String(normalizedCount !== void 0), "data-toggle": "true", "data-placeholder": placeholder ? "true" : void 0, "aria-busy": busy, children: /* @__PURE__ */ jsxs("button", { ...extensionTriggerAttributes, type: "button", class: "kui-list-header__title kui-list-header__toggle", "data-action": placeholder ? void 0 : action, disabled: placeholder || void 0, "aria-label": accessibleLabel, "aria-expanded": String(Boolean(expanded)), children: [
26
- /* @__PURE__ */ jsx("span", { class: "kui-list-header__label", children: label }),
27
- indicator,
28
- renderedActionIcon && /* @__PURE__ */ jsx("span", { class: "kui-list-header__action-layer", children: renderedActionIcon })
29
- ] }) });
30
- }
31
- return /* @__PURE__ */ jsxs("header", { ...extensionRootAttributes, class: "kui-list-header", "data-component": "list-header", "data-has-badge": String(Boolean(renderedBadge)), "data-has-count": String(normalizedCount !== void 0), "data-toggle": "false", "data-placeholder": placeholder ? "true" : void 0, "aria-busy": busy, children: [
32
- /* @__PURE__ */ jsxs("div", { class: "kui-list-header__title", children: [
33
- /* @__PURE__ */ jsx("h2", { class: "kui-list-header__label", "aria-label": accessibleLabel, children: label }),
34
- indicator
35
- ] }),
36
- action && /* @__PURE__ */ jsx("button", { ...extensionTriggerAttributes, type: "button", class: "kui-list-header__action", "data-action": placeholder ? void 0 : action, "aria-label": actionLabel, title: actionDisabled ? disabledReason : actionLabel, disabled: actionDisabled || placeholder || void 0, children: renderedActionIcon })
37
- ] });
38
- }
39
-
40
- export { ListHeader };
41
-
42
- //# sourceMappingURL=chunk-5ATCDSQS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/list-header.tsx"],"names":[],"mappings":"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","file":"chunk-5ATCDSQS.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { DisclosureArrow } from './disclosure-arrow.js';\nimport { filterControlAttributes, filterDataAttributes } from './extension-attributes.js';\nimport { Skeleton } from './skeleton.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 ListHeaderRootAttributes = 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 ListHeaderTriggerAttributes = 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 ListHeaderBaseProps {\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 /** Render as an unanimated loading skeleton: keep the label and action affordance, disable interaction. */\n placeholder?: boolean;\n rootAttributes?: ListHeaderRootAttributes;\n triggerAttributes?: ListHeaderTriggerAttributes;\n}\n\ntype ListHeaderIndicatorProps =\n | { count: number; countLabel: string; badge?: never }\n | { count?: never; countLabel?: never; badge?: SafeHtml };\n\nexport type ListHeaderProps = ListHeaderBaseProps & ListHeaderIndicatorProps;\n\nexport function ListHeader({ label, count, countLabel, badge, action, actionLabel, actionIcon, actionDisabled = false, disabledReason, expanded, toggle = false, placeholder = false, rootAttributes = {}, triggerAttributes = {} }: ListHeaderProps) {\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 = placeholder\n ? ((normalizedCount !== undefined || renderedBadge) && <span class=\"kui-list-header__badge\"><Skeleton width=\"1.75em\" /></span>)\n : normalizedCount === undefined\n ? renderedBadge && <span class=\"kui-list-header__badge\">{renderedBadge}</span>\n : <span class=\"kui-list-header__count\" aria-hidden=\"true\">{normalizedCount}</span>;\n const busy = placeholder ? ('true' as const) : undefined;\n if (toggle) {\n return <header {...extensionRootAttributes} class=\"kui-list-header\" data-component=\"list-header\" data-has-badge={String(Boolean(renderedBadge))} data-has-count={String(normalizedCount !== undefined)} data-toggle=\"true\" data-placeholder={placeholder ? 'true' : undefined} aria-busy={busy}><button {...extensionTriggerAttributes} type=\"button\" class=\"kui-list-header__title kui-list-header__toggle\" data-action={placeholder ? undefined : action} disabled={placeholder || undefined} aria-label={accessibleLabel} aria-expanded={String(Boolean(expanded))}><span class=\"kui-list-header__label\">{label}</span>{indicator}{renderedActionIcon && <span class=\"kui-list-header__action-layer\">{renderedActionIcon}</span>}</button></header>;\n }\n return <header {...extensionRootAttributes} class=\"kui-list-header\" data-component=\"list-header\" data-has-badge={String(Boolean(renderedBadge))} data-has-count={String(normalizedCount !== undefined)} data-toggle=\"false\" data-placeholder={placeholder ? 'true' : undefined} aria-busy={busy}><div class=\"kui-list-header__title\"><h2 class=\"kui-list-header__label\" aria-label={accessibleLabel}>{label}</h2>{indicator}</div>{action && <button {...extensionTriggerAttributes} type=\"button\" class=\"kui-list-header__action\" data-action={placeholder ? undefined : action} aria-label={actionLabel} title={actionDisabled ? disabledReason : actionLabel} disabled={actionDisabled || placeholder || undefined}>{renderedActionIcon}</button>}</header>;\n}\n"]}
@@ -1,10 +0,0 @@
1
- import { jsx } from 'kerfjs/jsx-runtime';
2
-
3
- // src/floating-toolbar.tsx
4
- function FloatingToolbar({ children, label, position = "bottom-end", className = "" }) {
5
- return /* @__PURE__ */ jsx("div", { class: `kui-floating-toolbar ${className}`.trim(), "data-component": "floating-toolbar", "data-position": position, role: "toolbar", "aria-label": label, children });
6
- }
7
-
8
- export { FloatingToolbar };
9
-
10
- //# sourceMappingURL=chunk-5E2HVJ33.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/floating-toolbar.tsx"],"names":[],"mappings":";;;AAiCO,SAAS,eAAA,CAAgB,EAAE,QAAA,EAAU,KAAA,EAAO,WAAW,YAAA,EAAc,SAAA,GAAY,IAAG,EAAyB;AAClH,EAAA,2BAAQ,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,qBAAA,EAAwB,SAAS,GAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,kBAAA,EAAmB,iBAAe,QAAA,EAAU,IAAA,EAAK,SAAA,EAAU,YAAA,EAAY,OAAQ,QAAA,EAAS,CAAA;AACxK","file":"chunk-5E2HVJ33.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\n/** Where a {@link FloatingToolbar} floats within its positioned container. */\nexport type FloatingToolbarPosition =\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'top'\n | 'top-start'\n | 'top-end';\n\nexport interface FloatingToolbarProps {\n /** Toolbar contents — normally one or more `ToolbarControlGroup`s. */\n children: SafeHtml | SafeHtml[];\n /** Accessible name for the toolbar (required — it exposes `role=\"toolbar\"`). */\n label: string;\n /**\n * Corner or edge it floats to inside its nearest positioned ancestor.\n * Default: `'bottom-end'`.\n */\n position?: FloatingToolbarPosition;\n className?: string;\n}\n\n/**\n * A toolbar that floats above the main content of its nearest positioned\n * ancestor — a transparent, forced-dark cluster of controls (e.g. a drawer\n * restore button) that sits over the content but NOT over dialogs or overlays\n * (it is not in the top layer). It is inset from the container edges by\n * `--kui-floating-toolbar-inset` (default `--kui-space-m`, i.e. 8px more than a\n * top toolbar's own inset); override that token to move it. The app owns the\n * controls and their behavior — wire them with `delegate()` as usual.\n */\nexport function FloatingToolbar({ children, label, position = 'bottom-end', className = '' }: FloatingToolbarProps) {\n return <div class={`kui-floating-toolbar ${className}`.trim()} data-component=\"floating-toolbar\" data-position={position} role=\"toolbar\" aria-label={label}>{children}</div>;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/wire-token-search-fields.ts"],"names":["block"],"mappings":"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","file":"chunk-6NLRBSVX.js","sourcesContent":["import { delegate, type Signal,signal } from 'kerfjs';\n\nimport { placeTokenSearchCaret, readTokenSearchField } from './token-search-field.js';\n\nexport interface TokenSearchSubmit {\n id: string;\n editor: HTMLElement;\n}\n\n/** Reported to {@link WireTokenSearchFieldsOptions.onEdit} on every editor input. */\nexport interface TokenSearchEdit extends TokenSearchSubmit {\n /**\n * The `InputEvent` that mutated the editor — read `event.inputType` / `event.data`\n * to gate commit behavior (e.g. only parse a chip on whitespace-terminated input)\n * without keeping a separate `input` listener.\n */\n event: InputEvent;\n}\n\n/** Reported when adjacent-token keyboard deletion asks the app to drop a chip. */\nexport interface TokenSearchTokenRemoval {\n id: string;\n /** The `data-token-value` of the token the app should remove from its state. */\n value: string;\n editor: HTMLElement;\n /** `'backward'` = the token before the caret (Backspace); `'forward'` = after (Delete). */\n direction: 'backward' | 'forward';\n}\n\n/**\n * Opt-in keyboard behavior for the atomic token chips. Off unless `keyboard` is\n * set; each piece defaults on once opted in. The helper never mutates app state:\n * a removal is reported through {@link TokenSearchKeyboardOptions.onRemoveToken}\n * for the caller to apply, while caret movement past a chip is a pure ephemeral\n * mechanic the helper performs itself.\n */\nexport interface TokenSearchKeyboardOptions {\n /**\n * From a collapsed caret with no selection, Backspace removes the token\n * immediately before it and Delete the token immediately after — reported via\n * `onRemoveToken` — instead of deleting a character. Default: true.\n */\n removeAdjacentToken?: boolean;\n /**\n * ArrowRight moves the caret past a trailing atomic token so text typed next\n * lands after the chip. Default: true.\n */\n moveCaretPastToken?: boolean;\n /** Apply the reported removal to your controlled state, then re-render. */\n onRemoveToken?: (removal: TokenSearchTokenRemoval) => void;\n}\n\n/**\n * Managed collapsible behavior for the iconic TokenSearchField. Every piece is on\n * by default; disable a specific one to own it in the app. Provide `signals` to\n * drive app-owned `expanded` signals per field id instead of helper-created ones.\n */\nexport interface TokenSearchCollapsibleOptions {\n /** Expand the field and focus its editor when the iconic trigger is activated. Default: true. */\n expandOnActivate?: boolean;\n /** Collapse the field when focus leaves it while it is empty. Default: true. */\n collapseOnEmptyBlur?: boolean;\n /** Collapse an empty field on Escape and restore focus to its trigger. Default: true. */\n collapseOnEscape?: boolean;\n /** Focus the editor on expand and the trigger on Escape-collapse. Default: true. */\n manageFocus?: boolean;\n /**\n * Keep an empty field expanded when focus moves to a caller-owned surface\n * rendered outside the field — a suggestions dropdown, date picker, or help\n * popover shown beside it. Return true for any focus target that must NOT\n * trigger collapse-on-empty-blur. An element carrying `data-token-search-keep-open`\n * (or any node inside one) is always exempt, so this predicate is only needed\n * for surfaces you cannot mark declaratively.\n */\n keepOpenOn?: (target: Node | null) => boolean;\n /** App-owned `expanded` signals keyed by field id; adopted instead of helper-created. */\n signals?: Readonly<Record<string, Signal<boolean>>>;\n}\n\nexport interface WireTokenSearchFieldsOptions {\n onSubmit?: (submission: TokenSearchSubmit) => void;\n /** Fired on every editor `input`, after the browser mutates it, so a caller can drop its own `input` listener. */\n onEdit?: (edit: TokenSearchEdit) => void;\n /** Managed collapsible transient behavior. `true`/omitted = on with defaults; `false` = fully off. */\n collapsible?: boolean | TokenSearchCollapsibleOptions;\n /** Opt-in atomic-chip keyboard behavior (off by default). `true` = on with defaults. */\n keyboard?: boolean | TokenSearchKeyboardOptions;\n}\n\n/**\n * The value returned from {@link wireTokenSearchFields}: call it (or `dispose()`) to\n * tear down. When collapsible behavior is managed, it also exposes the transient\n * `expanded` state per field id so the app can read it in render, hand in its own\n * signal, or drive it imperatively.\n */\nexport interface TokenSearchFieldsHandle {\n (): void;\n dispose(): void;\n /** The managed `expanded` signal for a field id (adopted or helper-created); undefined when unmanaged. */\n expanded(id: string): Signal<boolean> | undefined;\n /** Expand the field (and, when focus is managed, focus its editor). */\n open(id: string): void;\n /** Collapse the field (and, when focus is managed, restore focus to its trigger). */\n close(id: string): void;\n}\n\ninterface PendingTokenDeletion {\n id: string;\n offset: number;\n tokenCount: number;\n selectedAll: boolean;\n}\n\nfunction editorFromEvent(root: HTMLElement, event: Event): HTMLElement | undefined {\n const target = event.target;\n if (!(target instanceof Element)) return;\n const editor = target.closest<HTMLElement>('[data-token-search-editor]');\n return editor && root.contains(editor) ? editor : undefined;\n}\n\nfunction caretQueryOffset(editor: HTMLElement): number | undefined {\n const selection = editor.ownerDocument.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n const selectionRange = selection.getRangeAt(0);\n if (!editor.contains(selectionRange.startContainer)) return;\n const prefixRange = editor.ownerDocument.createRange();\n prefixRange.selectNodeContents(editor);\n prefixRange.setEnd(selectionRange.startContainer, selectionRange.startOffset);\n const prefix = editor.ownerDocument.createElement('div');\n prefix.append(prefixRange.cloneContents());\n return readTokenSearchField(prefix).query.length;\n}\n\nfunction replacementEditor(root: HTMLElement, id: string): HTMLElement | undefined {\n return [...root.querySelectorAll<HTMLElement>('[data-token-search-editor]')]\n .find((editor) => editor.dataset.tokenSearchEditor === id);\n}\n\nfunction editorIsEmpty(editor: HTMLElement): boolean {\n const value = readTokenSearchField(editor);\n return value.query.length === 0 && value.tokens.length === 0;\n}\n\n/** Whether the active selection covers every child of the editing host. */\nfunction selectionCoversEditor(editor: HTMLElement): boolean {\n // onBeforeInput calls this only after caretQueryOffset verified a live range.\n const selected = editor.ownerDocument.getSelection()!.getRangeAt(0);\n if (selected.collapsed || !editor.contains(selected.commonAncestorContainer)) return false;\n const contents = editor.ownerDocument.createRange();\n contents.selectNodeContents(editor);\n const RangeCtor = editor.ownerDocument.defaultView!.Range;\n return selected.compareBoundaryPoints(RangeCtor.START_TO_START, contents) <= 0\n && selected.compareBoundaryPoints(RangeCtor.END_TO_END, contents) >= 0;\n}\n\nconst TOKEN_SELECTOR = '[data-component=\"token-search-token\"]';\nconst TEXT_SELECTOR = '[data-token-search-text]';\nconst stripZwsp = (text: string): string => text.replaceAll('​', '');\n\n/**\n * A `contenteditable` host emptied by select-all + Delete (or Backspace) leaves a\n * bogus `<br>` in every engine: it renders as a stray newline and `readTokenSearchField`\n * reads it back as a space. Strip those line breaks after a delete, and when the field\n * is otherwise empty (no chips, no visible text) restore the canonical empty text span\n * and place the caret in it so typing resumes cleanly. Called only after the browser has\n * applied the delete, so an ordinary partial delete is never touched.\n */\nfunction normalizeEmptiedEditor(editor: HTMLElement, selectedAll = false): void {\n const lineBreaks = editor.querySelectorAll('br');\n if (lineBreaks.length === 0 && !selectedAll) return;\n for (const lineBreak of lineBreaks) lineBreak.remove();\n if (!selectedAll && editor.querySelector(TOKEN_SELECTOR)) return;\n if (!selectedAll && stripZwsp(editor.textContent ?? '') !== '') return;\n const doc = editor.ownerDocument;\n const span = doc.createElement('span');\n span.setAttribute('data-token-search-text', '');\n span.setAttribute('data-empty', 'true');\n editor.replaceChildren(span);\n if (doc.activeElement !== editor) return;\n // The editor is the focused, connected editing host, so a selection exists.\n const selection = doc.getSelection()!;\n const range = doc.createRange();\n range.setStart(span, 0);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n}\n\n/** The collapsed, in-editor caret range, or undefined when there is a selection or none. */\nfunction collapsedCaret(editor: HTMLElement): Range | undefined {\n const selection = editor.ownerDocument.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n const range = selection.getRangeAt(0);\n if (!range.collapsed || !editor.contains(range.startContainer)) return;\n return range;\n}\n\n/** The direct child of `editor` that contains `node` (or `node` itself), else null. */\nfunction topBlock(editor: HTMLElement, node: Node): Node | null {\n let current: Node = node;\n while (current.parentNode && current.parentNode !== editor) current = current.parentNode;\n return current.parentNode === editor ? current : null;\n}\n\n/** A text node or text span holding no visible character (only zero-width spacers). */\nfunction isBlankText(node: Node): boolean {\n if (node.nodeType === Node.TEXT_NODE) return stripZwsp((node as CharacterData).data) === '';\n return node instanceof Element && node.matches(TEXT_SELECTOR) && stripZwsp(node.textContent ?? '') === '';\n}\n\n/** The nearest sibling block on `direction`, skipping blank text spacers. */\nfunction meaningfulSibling(block: Node, direction: 'backward' | 'forward'): Node | null {\n let sibling = direction === 'backward' ? block.previousSibling : block.nextSibling;\n while (sibling && isBlankText(sibling)) sibling = direction === 'backward' ? sibling.previousSibling : sibling.nextSibling;\n return sibling;\n}\n\n/** The node immediately on `direction` of the caret, only when no visible character separates them. */\nfunction caretSideNode(editor: HTMLElement, range: Range, direction: 'backward' | 'forward'): Node | null {\n const { startContainer: container, startOffset: offset } = range;\n if (container.nodeType === Node.TEXT_NODE) {\n const text = (container as CharacterData).data;\n const side = direction === 'backward' ? text.slice(0, offset) : text.slice(offset);\n if (stripZwsp(side).length > 0) return null;\n // An in-editor text node always has a top block (itself or its wrapping span).\n return meaningfulSibling(topBlock(editor, container)!, direction);\n }\n const child = container.childNodes[direction === 'backward' ? offset - 1 : offset] as Node | undefined;\n if (child) {\n // `child` is a descendant of the in-editor caret container, so it has a top block.\n const block = topBlock(editor, child)!;\n return isBlankText(child) ? meaningfulSibling(block, direction) : block;\n }\n const block = topBlock(editor, container);\n return block ? meaningfulSibling(block, direction) : null;\n}\n\n/** The atomic token chip adjacent to a collapsed caret on `direction`, if any. */\nfunction adjacentToken(editor: HTMLElement, direction: 'backward' | 'forward'): HTMLElement | undefined {\n const range = collapsedCaret(editor);\n if (!range) return;\n const node = caretSideNode(editor, range, direction);\n if (!node) return;\n const base = node instanceof Element ? node : node.parentElement;\n const chip = base?.closest<HTMLElement>(TOKEN_SELECTOR) ?? null;\n return chip && editor.contains(chip) ? chip : undefined;\n}\n\n/** Move the caret to just after an atomic token chip so typed text lands after it.\n * Only reached after {@link collapsedCaret} already found a live selection, and the\n * chip is a direct block of the editor. */\nfunction placeCaretAfterToken(editor: HTMLElement, chip: HTMLElement): void {\n const selection = editor.ownerDocument.getSelection()!;\n const range = editor.ownerDocument.createRange();\n range.setStartAfter(topBlock(editor, chip)!);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n editor.focus({ preventScroll: true });\n}\n\n/**\n * Wire every TokenSearchField under `root`: submit on Enter, preserve the caret across\n * controlled token deletion, and (by default) manage the collapsible field's transient\n * expand/collapse/focus. Returns a {@link TokenSearchFieldsHandle} — a disposer that also\n * exposes the managed `expanded` state per field id.\n */\nexport function wireTokenSearchFields(\n root: HTMLElement,\n { onSubmit, onEdit, collapsible = true, keyboard = false }: WireTokenSearchFieldsOptions = {},\n): TokenSearchFieldsHandle {\n const managed = collapsible !== false;\n const config = typeof collapsible === 'object' ? collapsible : {};\n const expandOnActivate = managed && (config.expandOnActivate ?? true);\n const collapseOnEmptyBlur = managed && (config.collapseOnEmptyBlur ?? true);\n const collapseOnEscape = managed && (config.collapseOnEscape ?? true);\n const manageFocus = managed && (config.manageFocus ?? true);\n const keepOpenOn = config.keepOpenOn;\n const keyboardOn = keyboard !== false;\n const keyboardConfig = typeof keyboard === 'object' ? keyboard : {};\n const removeAdjacentToken = keyboardOn && (keyboardConfig.removeAdjacentToken ?? true);\n const moveCaretPastToken = keyboardOn && (keyboardConfig.moveCaretPastToken ?? true);\n const onRemoveToken = keyboardConfig.onRemoveToken;\n const adopted = config.signals ?? {};\n const created = new Map<string, Signal<boolean>>();\n\n /** True when focus moving to `element` should keep an empty field expanded. */\n const isExemptTarget = (element: Element | null): boolean => {\n if (!element) return false;\n if (element.closest('[data-token-search-keep-open]')) return true;\n return keepOpenOn ? keepOpenOn(element) : false;\n };\n\n const signalFor = (id: string): Signal<boolean> => {\n const own = adopted[id];\n if (own) return own;\n let field = created.get(id);\n if (!field) {\n field = signal(false);\n created.set(id, field);\n }\n return field;\n };\n const setExpanded = (id: string, next: boolean) => {\n const state = signalFor(id);\n if (state.value !== next) state.value = next;\n };\n const view = () => root.ownerDocument.defaultView!;\n const focusAfterRender = (id: string, selector: string) => {\n view().requestAnimationFrame(() => {\n const target = root.querySelector<HTMLElement>(\n `[data-component=\"token-search-field\"][data-token-search-id=\"${CSS.escape(id)}\"] ${selector}`,\n );\n if (!target) return;\n if (target.matches('[data-token-search-editor]')) placeTokenSearchCaret(target);\n else target.focus();\n });\n };\n const openField = (id: string) => {\n setExpanded(id, true);\n if (manageFocus) focusAfterRender(id, '[data-token-search-editor]');\n };\n const closeField = (id: string) => {\n setExpanded(id, false);\n if (manageFocus) focusAfterRender(id, '.kui-token-search__expand');\n };\n\n const pending = new WeakMap<HTMLElement, PendingTokenDeletion>();\n const onBeforeInput = (event: Event) => {\n const inputEvent = event as InputEvent;\n const editor = editorFromEvent(root, event);\n if (!editor || !inputEvent.inputType.startsWith('delete') || editor.ownerDocument.activeElement !== editor) return;\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n const offset = caretQueryOffset(editor);\n if (!id || offset === undefined || field?.dataset.disabled === 'true') return;\n pending.set(editor, {\n id,\n offset,\n tokenCount: editor.querySelectorAll('[data-component=\"token-search-token\"]').length,\n selectedAll: selectionCoversEditor(editor),\n });\n };\n const onInput = (event: Event) => {\n const editor = editorFromEvent(root, event);\n if (!editor) return;\n const deletion = pending.get(editor);\n if ((event as InputEvent).inputType?.startsWith('delete')) normalizeEmptiedEditor(editor, deletion?.selectedAll);\n if (onEdit) {\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (id && field?.dataset.disabled !== 'true') onEdit({ id, editor, event: event as InputEvent });\n }\n pending.delete(editor);\n if (!deletion || editor.querySelectorAll('[data-component=\"token-search-token\"]').length >= deletion.tokenCount) return;\n editor.ownerDocument.defaultView!.requestAnimationFrame(() => {\n const replacement = replacementEditor(root, deletion.id);\n if (!replacement) return;\n const active = replacement.ownerDocument.activeElement;\n if (active !== editor && active !== replacement && active !== replacement.ownerDocument.body) return;\n placeTokenSearchCaret(replacement, deletion.offset);\n });\n };\n root.addEventListener('beforeinput', onBeforeInput, true);\n root.addEventListener('input', onInput, true);\n\n const disposers: Array<() => void> = [\n () => root.removeEventListener('beforeinput', onBeforeInput, true),\n () => root.removeEventListener('input', onInput, true),\n ];\n\n disposers.push(\n delegate(root, 'keydown', '[data-token-search-editor]', (event, element) => {\n const keyboardEvent = event as KeyboardEvent;\n const editor = element as HTMLElement;\n if (keyboardEvent.isComposing) return;\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (!id || field?.dataset.disabled === 'true') return;\n if (keyboardEvent.key === 'Enter') {\n keyboardEvent.preventDefault();\n onSubmit?.({ id, editor });\n return;\n }\n if (removeAdjacentToken && (keyboardEvent.key === 'Backspace' || keyboardEvent.key === 'Delete')) {\n const direction = keyboardEvent.key === 'Backspace' ? 'backward' : 'forward';\n const chip = adjacentToken(editor, direction);\n if (chip) {\n keyboardEvent.preventDefault();\n onRemoveToken?.({ id, value: chip.dataset.tokenValue ?? '', editor, direction });\n return;\n }\n }\n if (moveCaretPastToken && keyboardEvent.key === 'ArrowRight') {\n const chip = adjacentToken(editor, 'forward');\n if (chip) {\n keyboardEvent.preventDefault();\n placeCaretAfterToken(editor, chip);\n return;\n }\n }\n if (collapseOnEscape && keyboardEvent.key === 'Escape' && field?.dataset.collapsible === 'true' && editorIsEmpty(editor)) {\n keyboardEvent.preventDefault();\n closeField(id);\n }\n }),\n );\n\n if (expandOnActivate) {\n disposers.push(\n delegate(root, 'click', '.kui-token-search__expand', (_event, element) => {\n // The selector guarantees a collapsible field ancestor; only skip a disabled one.\n const field = (element as HTMLElement).closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (id && field?.dataset.disabled !== 'true') openField(id);\n }),\n );\n }\n\n if (collapseOnEmptyBlur) {\n // Pressing an in-field control (clear, trailing, token, or the trigger) must not\n // blur the editor — otherwise the transient blur would collapse the field before\n // the control's own handler runs. Keeping focus also keeps the click firing.\n disposers.push(\n delegate(root, 'mousedown', '[data-component=\"token-search-field\"][data-collapsible=\"true\"] button', (event) => {\n event.preventDefault();\n }),\n );\n disposers.push(\n delegate(root, 'focusout', '[data-token-search-editor]', (event, element) => {\n const editor = element as HTMLElement;\n const field = editor.closest<HTMLElement>('[data-component=\"token-search-field\"]');\n const id = field?.dataset.tokenSearchId;\n if (!id || field?.dataset.collapsible !== 'true' || field.dataset.disabled === 'true') return;\n const next = (event as FocusEvent).relatedTarget;\n if (next instanceof Node && field.contains(next)) return;\n if (isExemptTarget(next instanceof Element ? next : null)) return;\n if (!editorIsEmpty(editor)) return;\n view().queueMicrotask(() => {\n const active = field.ownerDocument.activeElement;\n if (!field.contains(active) && !isExemptTarget(active)) setExpanded(id, false);\n });\n }),\n );\n }\n\n const dispose = () => {\n for (const stop of disposers.splice(0)) stop();\n };\n const handle = (() => dispose()) as TokenSearchFieldsHandle;\n handle.dispose = dispose;\n handle.expanded = (id) => (managed ? signalFor(id) : undefined);\n handle.open = (id) => {\n if (managed) openField(id);\n };\n handle.close = (id) => {\n if (managed) closeField(id);\n };\n return handle;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/extension-attributes.ts"],"names":[],"mappings":";AAEA,IAAM,mBAAA,GAAsB,sBAAA;AAC5B,IAAM,yCAAyB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM,CAAC,CAAA;AACjE,IAAM,oBAAA,mBAAuB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,QAAQ,SAAA,EAAW,MAAA,EAAQ,MAAA,EAAQ,MAAM,CAAC,CAAA;AAEnF,SAAS,oBAAA,CACd,YACA,cAAA,EACwB;AACxB,EAAA,MAAM,WAAmC,EAAC;AAE1C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAA0B,CAAA,EAAG;AACtE,IAAA,MAAM,cAAA,GAAiB,KAAK,WAAA,EAAY;AACxC,IAAA,IACE,OAAO,KAAA,KAAU,QAAA,IACd,mBAAA,CAAoB,IAAA,CAAK,cAAc,CAAA,IACvC,CAAC,cAAA,CAAe,GAAA,CAAI,cAAc,CAAA,EACrC;AACA,MAAA,QAAA,CAAS,cAAc,CAAA,GAAI,KAAA;AAAA,IAC7B;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAEO,SAAS,uBAAA,CACd,YACA,kBAAA,EACwB;AACxB,EAAA,MAAM,MAAA,GAAS,UAAA;AACf,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,UAAA,EAAY,kBAAkB,CAAA;AAEpE,EAAA,IAAI,OAAO,MAAA,CAAO,aAAA,KAAkB,QAAA,EAAU,QAAA,CAAS,gBAAgB,MAAA,CAAO,aAAA;AAC9E,EAAA,IAAI,sBAAA,CAAuB,GAAA,CAAI,MAAA,CAAO,mBAA6B,CAAA,EAAG;AACpE,IAAA,QAAA,CAAS,sBAAsB,MAAA,CAAO,mBAAA;AAAA,EACxC;AACA,EAAA,IAAI,OAAO,OAAO,eAAe,CAAA,KAAM,UAAU,QAAA,CAAS,eAAe,CAAA,GAAI,MAAA,CAAO,eAAe,CAAA;AACnG,EAAA,IAAI,oBAAA,CAAqB,GAAA,CAAI,MAAA,CAAO,eAAe,CAAW,CAAA,EAAG;AAC/D,IAAA,QAAA,CAAS,eAAe,CAAA,GAAI,MAAA,CAAO,eAAe,CAAA;AAAA,EACpD;AAEA,EAAA,OAAO,QAAA;AACT","file":"chunk-7BR3DO2A.js","sourcesContent":["type AttributeBag = Readonly<Record<string, unknown>>;\n\nconst DATA_ATTRIBUTE_NAME = /^data-[a-z0-9_.:-]+$/;\nconst POPOVER_TARGET_ACTIONS = new Set(['toggle', 'show', 'hide']);\nconst ARIA_HASPOPUP_VALUES = new Set(['dialog', 'menu', 'listbox', 'tree', 'grid', 'true']);\n\nexport function filterDataAttributes(\n attributes: object,\n protectedNames: ReadonlySet<string>,\n): Record<string, string> {\n const filtered: Record<string, string> = {};\n\n for (const [name, value] of Object.entries(attributes as AttributeBag)) {\n const normalizedName = name.toLowerCase();\n if (\n typeof value === 'string'\n && DATA_ATTRIBUTE_NAME.test(normalizedName)\n && !protectedNames.has(normalizedName)\n ) {\n filtered[normalizedName] = value;\n }\n }\n\n return filtered;\n}\n\nexport function filterControlAttributes(\n attributes: object,\n protectedDataNames: ReadonlySet<string>,\n): Record<string, string> {\n const source = attributes as AttributeBag;\n const filtered = filterDataAttributes(attributes, protectedDataNames);\n\n if (typeof source.popoverTarget === 'string') filtered.popoverTarget = source.popoverTarget;\n if (POPOVER_TARGET_ACTIONS.has(source.popoverTargetAction as string)) {\n filtered.popoverTargetAction = source.popoverTargetAction as string;\n }\n if (typeof source['aria-controls'] === 'string') filtered['aria-controls'] = source['aria-controls'];\n if (ARIA_HASPOPUP_VALUES.has(source['aria-haspopup'] as string)) {\n filtered['aria-haspopup'] = source['aria-haspopup'] as string;\n }\n\n return filtered;\n}\n"]}