@kerfjs/ui 5.0.0-beta.54 → 5.0.0-beta.55

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 (109) hide show
  1. package/README.md +3 -2
  2. package/ai/component-catalog-v2.json +58 -1
  3. package/ai/component-catalog.json +105 -8
  4. package/ai/public-api-signatures-v1.md +265 -28
  5. package/ai/skill.md +6 -4
  6. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  7. package/dist/browser/popup-menu.js +3 -0
  8. package/dist/catalog-resources.d.ts +1 -1
  9. package/dist/catalog.d.ts +10 -4
  10. package/dist/catalog.js +243 -300
  11. package/dist/catalog.js.map +1 -1
  12. package/dist/{chunk-7IUSV4XG.js → chunk-24PHKUR3.js} +2 -2
  13. package/dist/chunk-24PHKUR3.js.map +1 -0
  14. package/dist/chunk-4BIMLITI.js +92 -0
  15. package/dist/chunk-4BIMLITI.js.map +1 -0
  16. package/dist/{chunk-ZK5EGVFP.js → chunk-5OLVUEND.js} +12 -2
  17. package/dist/chunk-5OLVUEND.js.map +1 -0
  18. package/dist/{chunk-CMUIXJZM.js → chunk-BSKEH3UC.js} +2 -2
  19. package/dist/{chunk-CMUIXJZM.js.map → chunk-BSKEH3UC.js.map} +1 -1
  20. package/dist/chunk-EAX2GSS4.js +384 -0
  21. package/dist/chunk-EAX2GSS4.js.map +1 -0
  22. package/dist/chunk-KH6VUGHU.js +399 -0
  23. package/dist/chunk-KH6VUGHU.js.map +1 -0
  24. package/dist/{chunk-BJJKFVWW.js → chunk-LZXQVUGN.js} +2 -2
  25. package/dist/chunk-LZXQVUGN.js.map +1 -0
  26. package/dist/chunk-N7FHFNT6.js +55 -0
  27. package/dist/chunk-N7FHFNT6.js.map +1 -0
  28. package/dist/{chunk-KPNTVB7A.js → chunk-R754MHXX.js} +3 -3
  29. package/dist/{chunk-KPNTVB7A.js.map → chunk-R754MHXX.js.map} +1 -1
  30. package/dist/{chunk-HJKRCKDR.js → chunk-RNRUVPJ3.js} +4 -2
  31. package/dist/chunk-RNRUVPJ3.js.map +1 -0
  32. package/dist/collapsible-panel.d.ts +40 -13
  33. package/dist/collapsible-panel.js +41 -10
  34. package/dist/collapsible-panel.js.map +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +17 -16
  37. package/dist/list-header.js +1 -1
  38. package/dist/list-inset-text.d.ts +7 -1
  39. package/dist/list-inset-text.js +2 -1
  40. package/dist/panel-toolbar-BFQxFITu.d.ts +52 -0
  41. package/dist/popup-menu-register.d.ts +9 -0
  42. package/dist/popup-menu-register.js +30 -0
  43. package/dist/popup-menu-register.js.map +1 -0
  44. package/dist/popup-menu.d.ts +71 -0
  45. package/dist/popup-menu.js +3 -0
  46. package/dist/popup-menu.js.map +1 -0
  47. package/dist/state-banner.js +1 -1
  48. package/dist/styles/catalog/components/catalog-example.css +0 -16
  49. package/dist/styles/catalog/components/catalog-stage.css +8 -13
  50. package/dist/styles/catalog/components/catalog.css +8 -18
  51. package/dist/styles/catalog.css +0 -5
  52. package/dist/styles/popup-menu.css +12 -0
  53. package/dist/styles/state-banner.css +13 -4
  54. package/dist/styles/styles.css +1 -0
  55. package/dist/styles/tab-bar.css +31 -3
  56. package/dist/styles/toolbar-control-group.css +13 -0
  57. package/dist/styles/toolbar.css +43 -2
  58. package/dist/styles/workbench.css +31 -0
  59. package/dist/text.js +1 -1
  60. package/dist/token-search-field.d.ts +10 -1
  61. package/dist/token-search-field.js +1 -1
  62. package/dist/{types-CEsieBZi.d.ts → types-D6vzj-VT.d.ts} +15 -0
  63. package/dist/wire-catalog.d.ts +13 -1
  64. package/dist/wire-catalog.js +18 -3
  65. package/dist/wire-catalog.js.map +1 -1
  66. package/dist/wire-sidebar.js +6 -3
  67. package/dist/wire-sidebar.js.map +1 -1
  68. package/dist/wire-token-search-fields.js +1 -1
  69. package/dist/wire-workbench.js +1 -350
  70. package/dist/wire-workbench.js.map +1 -1
  71. package/dist/workbench.d.ts +107 -6
  72. package/dist/workbench.js +11 -208
  73. package/dist/workbench.js.map +1 -1
  74. package/docs/accessibility.md +12 -1
  75. package/docs/catalog.md +27 -9
  76. package/docs/collapsible-panel.md +55 -0
  77. package/docs/component-contract.md +2 -2
  78. package/docs/component-selection.md +25 -17
  79. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  80. package/docs/design/templates/state-banner/danger.svg +1 -1
  81. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  82. package/docs/design/templates/state-banner/info.svg +1 -1
  83. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  84. package/docs/design/templates/state-banner/success.svg +1 -1
  85. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  86. package/docs/design/templates/state-banner/warning.svg +1 -1
  87. package/docs/design/templates/state-banner-dark.svg +1 -1
  88. package/docs/design/templates/state-banner.svg +1 -1
  89. package/docs/layout.md +5 -0
  90. package/docs/recipes.md +44 -37
  91. package/docs/surface-scaffold.md +1 -1
  92. package/docs/ux-demo.md +6 -2
  93. package/docs/workbench.md +92 -7
  94. package/llms.txt +6 -5
  95. package/package.json +13 -2
  96. package/ux-demo/recipes/app-shell.tsx +141 -223
  97. package/ux-demo/recipes/collapsible-sidebar.tsx +44 -75
  98. package/ux-demo/recipes/list-detail-dialog.tsx +150 -54
  99. package/ux-demo/recipes/mount-recipe.ts +0 -5
  100. package/ux-demo/recipes/types.ts +0 -1
  101. package/dist/chunk-7IUSV4XG.js.map +0 -1
  102. package/dist/chunk-BJJKFVWW.js.map +0 -1
  103. package/dist/chunk-HJKRCKDR.js.map +0 -1
  104. package/dist/chunk-ZK5EGVFP.js.map +0 -1
  105. package/dist/styles/catalog/components/catalog-detail.css +0 -35
  106. package/dist/styles/catalog/components/catalog-resource-footer.css +0 -37
  107. package/dist/styles/catalog/components/catalog-secondary-sections.css +0 -38
  108. package/dist/styles/catalog/components/catalog-section-list.css +0 -22
  109. package/dist/styles/catalog/components/catalog-sidebar.css +0 -82
@@ -7,15 +7,19 @@ import '@awesome.me/webawesome/dist/components/dialog/dialog.js';
7
7
 
8
8
  import { deviceClass } from '@kerfjs/ui/device-class';
9
9
  import { List } from '@kerfjs/ui/list';
10
- import { ListHeader } from '@kerfjs/ui/list-header';
11
10
  import { ListItem } from '@kerfjs/ui/list-item';
12
11
  import { LucideIcon } from '@kerfjs/ui/lucide-icon';
12
+ import { Pane } from '@kerfjs/ui/pane';
13
13
  import { Row } from '@kerfjs/ui/row';
14
+ import { Spacer } from '@kerfjs/ui/spacer';
14
15
  import { SplitView } from '@kerfjs/ui/split-view';
15
16
  import { DialogSurface } from '@kerfjs/ui/surface-scaffold';
17
+ import { Toolbar } from '@kerfjs/ui/toolbar';
18
+ import { ToolbarControlGroup } from '@kerfjs/ui/toolbar-control-group';
19
+ import { ToolbarText } from '@kerfjs/ui/toolbar-text';
16
20
  import { ValueTable, ValueTableRow } from '@kerfjs/ui/value-table';
17
21
  import { signal } from 'kerfjs';
18
- import { ChevronRight, FileText } from 'lucide';
22
+ import { ChevronRight, FileText, X } from 'lucide';
19
23
 
20
24
  import type { RecipeFactory, RecipePresentation } from './types.js';
21
25
 
@@ -48,7 +52,7 @@ interface RecipeDialogElement extends HTMLElement {
48
52
 
49
53
  export const presentation: RecipePresentation = {
50
54
  viewport: { layout: 'grid', width: 'full' },
51
- note: 'Web Awesome owns modal focus, Escape, and the close control; DialogSurface owns dialog geometry; SplitView owns the list-detail panes and their compact drill-down. The app owns open state, selection, and record actions.',
55
+ note: 'On roomy devices the dialog body is a workbench: a full-height list sidebar with its own toolbar beside a full-height detail column that carries the primary title, close control, and record actions. Compact devices get a full-screen sheet that drills from the list into the detail. Web Awesome owns modal focus and Escape; DialogSurface owns dialog geometry; SplitView owns the panes and the compact drill-down. The app owns open state, selection, and record actions.',
52
56
  };
53
57
 
54
58
  export const createRecipe: RecipeFactory = (announce) => {
@@ -59,35 +63,109 @@ export const createRecipe: RecipeFactory = (announce) => {
59
63
  const open = { value: false };
60
64
  const device = deviceClass();
61
65
 
62
- const projectList = (compact: boolean) => (
63
- <List>
64
- {compact ? null : <ListHeader label="Recent projects" />}
65
- <section aria-label="Projects">
66
- {Object.entries(records).map(([id, record]) => (
67
- <ListItem
68
- action="recipe-action"
69
- itemId={id}
70
- label={record.name}
71
- description={`${record.owner} · ${record.state}`}
72
- icon={<LucideIcon icon={FileText} name="file-text" />}
66
+ const projectRows = (compact: boolean) => (
67
+ <section aria-label="Projects">
68
+ {Object.entries(records).map(([id, record]) => (
69
+ <ListItem
70
+ action="recipe-action"
71
+ itemId={id}
72
+ label={record.name}
73
+ description={`${record.owner} · ${record.state}`}
74
+ icon={<LucideIcon icon={FileText} name="file-text" />}
75
+ trailing={
76
+ compact ? (
77
+ <LucideIcon icon={ChevronRight} name="chevron-right" />
78
+ ) : undefined
79
+ }
80
+ selected={!compact && selected.value === id}
81
+ multiline
82
+ />
83
+ ))}
84
+ </section>
85
+ );
86
+
87
+ const recordActions = () => (
88
+ <Row gap="xs" wrap controlInsets="trbl">
89
+ <Spacer flex />
90
+ <wa-button
91
+ appearance="outlined"
92
+ data-action="recipe-action"
93
+ data-recipe-command="archive"
94
+ >
95
+ Archive
96
+ </wa-button>
97
+ <wa-button
98
+ variant="brand"
99
+ appearance="accent"
100
+ data-action="recipe-action"
101
+ data-recipe-command="open-record"
102
+ >
103
+ Open project
104
+ </wa-button>
105
+ </Row>
106
+ );
107
+
108
+ // Roomy: a workbench. The list is a full-height sidebar with its own top
109
+ // toolbar; the detail column carries the dialog's primary title, the close
110
+ // control, and the record actions, and runs the full dialog height too.
111
+ const sidebar = () => (
112
+ <Pane
113
+ label="Recent projects"
114
+ header={
115
+ <Toolbar
116
+ label="Recent projects"
117
+ dividerSides=""
118
+ leading={<ToolbarText text="Recent projects" />}
119
+ />
120
+ }
121
+ >
122
+ <List controlInsets="tb">{projectRows(false)}</List>
123
+ </Pane>
124
+ );
125
+
126
+ const detailColumn = () => {
127
+ const record = records[selected.value];
128
+ return (
129
+ <Pane
130
+ label={record.name}
131
+ header={
132
+ <Toolbar
133
+ label="Project details"
134
+ dividerSides=""
135
+ leading={
136
+ <ToolbarText
137
+ text={record.name}
138
+ size="xlarge"
139
+ id="recipe-project-title"
140
+ headingLevel={2}
141
+ />
142
+ }
73
143
  trailing={
74
- compact ? (
75
- <LucideIcon icon={ChevronRight} name="chevron-right" />
76
- ) : undefined
144
+ <ToolbarControlGroup appearance="borderless" single>
145
+ <button type="button" aria-label="Close" data-dialog="close">
146
+ <LucideIcon icon={X} name="x" />
147
+ </button>
148
+ </ToolbarControlGroup>
77
149
  }
78
- selected={!compact && selected.value === id}
79
- multiline
80
150
  />
81
- ))}
82
- </section>
83
- </List>
84
- );
151
+ }
152
+ footer={recordActions()}
153
+ >
154
+ <List controlInsets="tb">
155
+ <ValueTable label="Project details">
156
+ <ValueTableRow label="Owner" value={record.owner} />
157
+ <ValueTableRow label="Status" value={record.state} />
158
+ <ValueTableRow label="Updated" value={record.updated} />
159
+ </ValueTable>
160
+ </List>
161
+ </Pane>
162
+ );
163
+ };
85
164
 
86
- const projectDetail = (compact: boolean) => {
165
+ const compactDetail = () => {
87
166
  const record = records[selected.value];
88
167
  return (
89
168
  <List>
90
- {compact ? null : <ListHeader label={record.name} />}
91
169
  <ValueTable label="Project details">
92
170
  <ValueTableRow label="Owner" value={record.owner} />
93
171
  <ValueTableRow label="Status" value={record.state} />
@@ -119,36 +197,54 @@ export const createRecipe: RecipeFactory = (announce) => {
119
197
  >
120
198
  Open project details
121
199
  </wa-button>
122
- <wa-dialog label="Project details" open={open.value} with-footer>
123
- <SplitView
124
- id="recipe-projects"
125
- label="Projects"
126
- compact={compact}
127
- detailActive={compact && detailOpen.value}
128
- listTitle="Recent projects"
129
- detailTitle={records[selected.value].name}
130
- backLabel="Back to projects"
131
- list={projectList(compact)}
132
- detail={projectDetail(compact)}
133
- />
134
- <wa-button
135
- slot="footer"
136
- appearance="outlined"
137
- data-action="recipe-action"
138
- data-recipe-command="archive"
139
- >
140
- Archive
141
- </wa-button>
142
- <wa-button
143
- slot="footer"
144
- variant="brand"
145
- appearance="accent"
146
- data-action="recipe-action"
147
- data-recipe-command="open-record"
200
+ {compact ? (
201
+ <wa-dialog label="Project details" open={open.value} with-footer>
202
+ <SplitView
203
+ id="recipe-projects"
204
+ label="Projects"
205
+ compact
206
+ detailActive={detailOpen.value}
207
+ listTitle="Recent projects"
208
+ detailTitle={records[selected.value].name}
209
+ backLabel="Back to projects"
210
+ list={<List>{projectRows(true)}</List>}
211
+ detail={compactDetail()}
212
+ />
213
+ <wa-button
214
+ slot="footer"
215
+ appearance="outlined"
216
+ data-action="recipe-action"
217
+ data-recipe-command="archive"
218
+ >
219
+ Archive
220
+ </wa-button>
221
+ <wa-button
222
+ slot="footer"
223
+ variant="brand"
224
+ appearance="accent"
225
+ data-action="recipe-action"
226
+ data-recipe-command="open-record"
227
+ >
228
+ Open project
229
+ </wa-button>
230
+ </wa-dialog>
231
+ ) : (
232
+ <wa-dialog
233
+ label="Project details"
234
+ open={open.value}
235
+ without-header
148
236
  >
149
- Open project
150
- </wa-button>
151
- </wa-dialog>
237
+ <SplitView
238
+ id="recipe-projects"
239
+ label="Projects"
240
+ compact={false}
241
+ listTitle="Recent projects"
242
+ detailTitle={records[selected.value].name}
243
+ list={sidebar()}
244
+ detail={detailColumn()}
245
+ />
246
+ </wa-dialog>
247
+ )}
152
248
  </DialogSurface>
153
249
  </Row>
154
250
  </section>
@@ -1,5 +1,4 @@
1
1
  import { wireNavStack } from '@kerfjs/ui/wire-nav-stack';
2
- import { wireResizableRegions } from '@kerfjs/ui/wire-resizable-regions';
3
2
  import { delegate, mount } from 'kerfjs';
4
3
  import { delegateActions } from 'kerfjs/actions';
5
4
 
@@ -40,9 +39,6 @@ export function mountRecipe(
40
39
  'wa-dialog',
41
40
  (_event, element) => controller.afterHide?.(element as HTMLElement),
42
41
  );
43
- const stopResize = wireResizableRegions(root, {
44
- onCommit: ({ id, size }) => controller.resize?.(id, size),
45
- });
46
42
  const stopNav = wireNavStack(root, {
47
43
  onBack: () => controller.action('nav-back', root),
48
44
  });
@@ -54,7 +50,6 @@ export function mountRecipe(
54
50
  disposed = true;
55
51
  stopWire?.();
56
52
  stopNav();
57
- stopResize();
58
53
  stopDialogs();
59
54
  stopInputs();
60
55
  stopChanges();
@@ -6,7 +6,6 @@ export interface RecipeController {
6
6
  action(command: string, element: HTMLElement): void;
7
7
  change?(element: HTMLElement): void;
8
8
  afterHide?(element: HTMLElement): void;
9
- resize?(id: string, size: number): void;
10
9
  /**
11
10
  * Install any imperative wiring the recipe owns on its mounted root (e.g.
12
11
  * `wireSidebar` for a collapsible rail/drawer), returning a disposer. The
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/text.tsx"],"names":[],"mappings":";;;AAsCO,SAAS,IAAA,CAAK;AAAA,EACnB,SAAS,OAAA,GAAU,GAAA;AAAA,EACnB,IAAA,GAAO,SAAA;AAAA,EACP,IAAA,GAAO,SAAA;AAAA,EACP,IAAA,GAAO,SAAA;AAAA,EACP,MAAA,GAAS,aAAA;AAAA,EACT,QAAA;AAAA,EACA,OAAO,UAAA,GAAa,EAAA;AAAA,EACpB,SAAA,GAAY,EAAA;AAAA,EACZ,GAAG;AACL,CAAA,EAAc;AACZ,EAAA,MAAM,UAAU,CAAA,SAAA,EAAY,UAAU,CAAA,CAAA,EAAI,SAAS,GAAG,IAAA,EAAK;AAC3D,EAAA,uBACE,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACE,GAAG,UAAA;AAAA,MACJ,KAAA,EAAO,OAAA;AAAA,MACP,gBAAA,EAAe,MAAA;AAAA,MACf,WAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAa,MAAA;AAAA,MAEZ;AAAA;AAAA,GACH;AAEJ","file":"chunk-7IUSV4XG.js","sourcesContent":["import type { KerfBaseAttrs } from 'kerfjs/jsx-runtime';\n\nimport type { KerfUiContent } from './semantic-content.js';\n\nexport type TextVariant =\n 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span';\nexport type TextTone = 'default' | 'quiet' | 'danger';\nexport type TextSize = 'default' | 'compact';\nexport type TextFont = 'default' | 'monospace';\nexport type TextBorder = 'transparent' | 'none';\n\nexport type TextContent =\n KerfUiContent | string | number | readonly TextContent[];\n\nexport type TextProps = Omit<\n KerfBaseAttrs,\n 'children' | 'class' | 'className'\n> & {\n /** Native heading, paragraph, or inline span element to render. Defaults to `p`. */\n variant?: TextVariant;\n /** Semantic foreground treatment. Defaults to the inherited foreground. */\n tone?: TextTone;\n /** Text sizing independent of the native semantic element. */\n size?: TextSize;\n /** Font family independent of the native semantic element. */\n font?: TextFont;\n /** Transparent alignment border or no border when embedded in owner chrome. */\n border?: TextBorder;\n children: TextContent;\n class?: string;\n className?: string;\n};\n\n/**\n * Semantic heading, paragraph, or inline text. Block variants use the standard\n * content-item padding; `span` adds no box geometry.\n * All ordinary native heading/paragraph attributes pass through to the element.\n */\nexport function Text({\n variant: Variant = 'p',\n tone = 'default',\n size = 'default',\n font = 'default',\n border = 'transparent',\n children,\n class: classValue = '',\n className = '',\n ...attributes\n}: TextProps) {\n const classes = `kui-text ${classValue} ${className}`.trim();\n return (\n <Variant\n {...attributes}\n class={classes}\n data-component=\"text\"\n data-tone={tone}\n data-size={size}\n data-font={font}\n data-border={border}\n >\n {children}\n </Variant>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/state-banner.tsx"],"names":[],"mappings":";;;;;AA2BO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA,GAAO,MAAA;AAAA,EACP,OAAA,GAAU,QAAA;AAAA,EACV,SAAA,GAAY,EAAA;AAAA,EACZ,WAAA,GAAc,KAAA;AAAA,EACd;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,SAAA,GAAY,IAAA,KAAS,MAAA,GAAS,OAAA,GAAU,IAAA;AAC9C,EAAA,uBACE,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC5C,gBAAA,EAAe,cAAA;AAAA,MACf,WAAA,EAAW,IAAA;AAAA,MACX,kBAAA,EAAkB,cAAc,MAAA,GAAS,MAAA;AAAA,MACzC,IAAA,EAAM,OAAA;AAAA,MACN,WAAA,EAAW,OAAA,KAAY,OAAA,GAAU,WAAA,GAAc,QAAA;AAAA,MAC/C,WAAA,EAAW,cAAc,MAAA,GAAS,MAAA;AAAA,MAClC,IAAA;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,wBAAA,EAA0B,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,wBACpD,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,wBAAA,EACT,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,QAAA,EAAA,EAAQ,wCAAc,GAAA,CAAC,QAAA,EAAA,EAAS,OAAO,EAAA,CAAG,EAAE,CAAA,EAAG,CAAA,GAAK,KAAA,EAAM,CAAA;AAAA,UAC1D,KAAA,oBACC,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,UAAA,EAAW,OAAA;AAAA,cACX,IAAA,EAAK,SAAA;AAAA,cACL,IAAA,EAAM,SAAA;AAAA,cACN,SAAA,EAAU,yBAAA;AAAA,cAET,wCAAc,GAAA,CAAC,QAAA,EAAA,EAAS,OAAO,EAAA,CAAG,IAAI,GAAG,CAAA,GAAK;AAAA;AAAA,WACjD;AAAA,UAED,MAAA,oBACC,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,0BAAA,EACT,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAO,EAAA,CAAG,EAAE,CAAA,EAAG,IAAK,MAAA,EAC/C;AAAA,SAAA,EAEJ,CAAA;AAAA,QACC,MAAA,oBAAU,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,4BAA4B,QAAA,EAAA,MAAA,EAAO;AAAA;AAAA;AAAA,GAC3D;AAEJ","file":"chunk-BJJKFVWW.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Badge } from './badge.js';\nimport { em } from './css-values.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport { Skeleton } from './skeleton.js';\n\nexport type StateBannerTone =\n 'neutral' | 'info' | 'pop' | 'success' | 'warning' | 'danger';\nexport type StateBannerUrgency = 'status' | 'alert';\n\nexport interface StateBannerProps {\n title: string;\n detail?: string;\n /** Optional compact status or count shown beside the title. */\n badge?: string;\n icon?: SafeHtml;\n action?: KerfUiContent;\n tone?: StateBannerTone;\n urgency?: StateBannerUrgency;\n className?: string;\n /** Render the title, badge, and detail as unanimated loading skeletons, keeping the icon and tone. The detail line appears only when `detail` is set, as in the live banner. */\n placeholder?: boolean;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nexport function StateBanner({\n title,\n detail,\n badge,\n icon,\n action,\n tone = 'info',\n urgency = 'status',\n className = '',\n placeholder = false,\n slot,\n}: StateBannerProps) {\n const badgeTone = tone === 'info' ? 'brand' : tone;\n return (\n <section\n class={`kui-state-banner ${className}`.trim()}\n data-component=\"state-banner\"\n data-tone={tone}\n data-placeholder={placeholder ? 'true' : undefined}\n role={urgency}\n aria-live={urgency === 'alert' ? 'assertive' : 'polite'}\n aria-busy={placeholder ? 'true' : undefined}\n slot={slot}\n >\n {icon && <span class=\"kui-state-banner__icon\">{icon}</span>}\n <div class=\"kui-state-banner__copy\">\n <strong>{placeholder ? <Skeleton width={em(10)} /> : title}</strong>\n {badge && (\n <Badge\n appearance=\"solid\"\n size=\"compact\"\n tone={badgeTone}\n className=\"kui-state-banner__badge\"\n >\n {placeholder ? <Skeleton width={em(1.75)} /> : badge}\n </Badge>\n )}\n {detail && (\n <span class=\"kui-state-banner__detail\">\n {placeholder ? <Skeleton width={em(16)} /> : detail}\n </span>\n )}\n </div>\n {action && <div class=\"kui-state-banner__action\">{action}</div>}\n </section>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/token-search-field.tsx"],"names":[],"mappings":"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","file":"chunk-HJKRCKDR.js","sourcesContent":["import { Search, X } from 'lucide';\n\nimport { LucideIcon } from './lucide-icon.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\nexport interface TokenSearchToken {\n value: string;\n label: string;\n offset?: number;\n accessibleLabel?: string;\n}\n\nexport type TokenSearchEditorAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-key'?: never;\n 'data-morph-skip'?: never;\n 'data-token-search-editor'?: never;\n 'data-token-count'?: never;\n 'data-placeholder'?: never;\n }\n>;\n\ninterface TokenSearchFieldBaseProps {\n id: string;\n label: string;\n query?: string;\n tokens?: readonly TokenSearchToken[];\n placeholder?: string;\n tokenPlaceholder?: string;\n disabled?: boolean;\n autofocus?: boolean;\n leading?: KerfUiContent;\n trailing?: KerfUiContent;\n /** Standalone field chrome or the inset visual layer of a configured toolbar group. */\n presentation?: 'standalone' | 'toolbar-group';\n editAction?: string;\n removeAction?: string;\n clearAction?: string;\n clearLabel?: string;\n className?: string;\n editorAttributes?: TokenSearchEditorAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\ntype TokenSearchCollapsibleProps =\n | {\n /** Allow an empty field to render as one iconic action. */\n collapsible: true;\n /** Keep an empty collapsible field open while the application owns focus. */\n expanded?: boolean;\n expandAction?: string;\n expandLabel?: string;\n }\n | {\n collapsible?: false;\n expanded?: never;\n expandAction?: never;\n expandLabel?: never;\n };\n\nexport type TokenSearchFieldProps = TokenSearchFieldBaseProps &\n TokenSearchCollapsibleProps;\n\nexport interface TokenSearchFieldValue {\n query: string;\n tokens: TokenSearchToken[];\n}\n\ntype TokenSearchPart =\n { kind: 'text'; value: string } | { kind: 'token'; token: TokenSearchToken };\n\nfunction orderedParts(\n query: string,\n tokens: readonly TokenSearchToken[],\n): TokenSearchPart[] {\n const ordered = tokens\n .map((token, index) => ({\n token,\n index,\n offset: Math.max(0, Math.min(query.length, token.offset ?? query.length)),\n }))\n .sort(\n (left, right) => left.offset - right.offset || left.index - right.index,\n );\n const parts: TokenSearchPart[] = [];\n let cursor = 0;\n for (const { token, offset } of ordered) {\n parts.push({ kind: 'text', value: query.slice(cursor, offset) });\n parts.push({ kind: 'token', token: { ...token, offset } });\n cursor = offset;\n }\n parts.push({ kind: 'text', value: query.slice(cursor) });\n return parts;\n}\n\nfunction CloseIcon() {\n return <LucideIcon icon={X} name=\"x\" />;\n}\n\nexport function TokenSearchField({\n id,\n label,\n query = '',\n tokens = [],\n placeholder = 'Search',\n tokenPlaceholder = 'Add search…',\n disabled = false,\n autofocus = false,\n collapsible = false,\n expanded = false,\n expandAction = 'expand-token-search',\n expandLabel,\n leading,\n trailing,\n presentation = 'standalone',\n editAction = 'edit-search-token',\n removeAction = 'remove-search-token',\n clearAction = 'clear-token-search',\n clearLabel = 'Clear search',\n className = '',\n editorAttributes = {},\n slot,\n}: TokenSearchFieldProps) {\n const parts = orderedParts(query, tokens);\n const key = `${id}:${tokens.map((token) => token.value).join('|')}`;\n const resolvedExpanded =\n !collapsible || expanded || query.length > 0 || tokens.length > 0;\n return (\n <div\n class={`kui-token-search ${className}`.trim()}\n data-component=\"token-search-field\"\n data-token-search-id={id}\n data-disabled={String(disabled)}\n data-collapsible={String(collapsible)}\n data-expanded={String(resolvedExpanded)}\n data-has-trailing={String(Boolean(trailing))}\n data-presentation={presentation}\n slot={slot}\n >\n {!resolvedExpanded ? (\n <button\n type=\"button\"\n class=\"kui-token-search__expand\"\n data-action={expandAction}\n aria-label={expandLabel ?? label}\n title={expandLabel ?? label}\n disabled={disabled}\n >\n <LucideIcon icon={Search} name=\"search\" />\n </button>\n ) : (\n <>\n <span class=\"kui-token-search__leading\" aria-hidden=\"true\">\n {leading ?? <LucideIcon icon={Search} name=\"search\" />}\n </span>\n <div\n {...editorAttributes}\n class=\"kui-token-search__editor\"\n data-key={key}\n data-morph-skip\n data-token-search-editor={id}\n data-token-count={tokens.length}\n data-placeholder={tokens.length ? tokenPlaceholder : placeholder}\n role=\"searchbox\"\n aria-label={label}\n aria-disabled={disabled ? 'true' : undefined}\n contenteditable={disabled ? 'false' : 'true'}\n spellcheck=\"false\"\n autofocus={autofocus}\n >\n {parts.map((part) =>\n part.kind === 'text' ? (\n <span\n data-token-search-text\n data-empty={String(part.value.length === 0)}\n >\n {part.value || (tokens.length ? '\\u200b' : '')}\n </span>\n ) : (\n <span\n class=\"kui-token-search__token\"\n contenteditable=\"false\"\n data-component=\"token-search-token\"\n data-token-value={part.token.value}\n >\n <button\n type=\"button\"\n class=\"kui-token-search__token-edit\"\n data-action={editAction}\n data-token-value={part.token.value}\n aria-label={`Edit ${part.token.accessibleLabel ?? part.token.label}`}\n disabled={disabled}\n >\n {part.token.label}\n </button>\n <button\n type=\"button\"\n class=\"kui-token-search__token-remove\"\n data-action={removeAction}\n data-token-value={part.token.value}\n aria-label={`Remove ${part.token.accessibleLabel ?? part.token.label}`}\n disabled={disabled}\n >\n <CloseIcon />\n </button>\n </span>\n ),\n )}\n </div>\n {(query || tokens.length > 0) && (\n <button\n type=\"button\"\n class=\"kui-token-search__clear\"\n data-action={clearAction}\n aria-label={clearLabel}\n title={clearLabel}\n disabled={disabled}\n >\n <CloseIcon />\n </button>\n )}\n {trailing && (\n <span class=\"kui-token-search__trailing\">{trailing}</span>\n )}\n </>\n )}\n </div>\n );\n}\n\n/** Read editable text and ordered token offsets from a rendered TokenSearchField editor. */\nexport function readTokenSearchField(\n editor: HTMLElement,\n knownTokens: readonly TokenSearchToken[] = [],\n): TokenSearchFieldValue {\n let query = '';\n const tokens: TokenSearchToken[] = [];\n const visit = (node: Node): void => {\n if (node.nodeType === Node.TEXT_NODE) {\n query += (node.textContent ?? '')\n .replaceAll('\\u00a0', ' ')\n .replaceAll('\\u200b', '');\n return;\n }\n if (!(node instanceof HTMLElement)) return;\n if (node.matches('[data-component=\"token-search-token\"]')) {\n const value = node.dataset.tokenValue;\n const known = knownTokens.find((token) => token.value === value);\n if (known) tokens.push({ ...known, offset: query.length });\n else if (value)\n tokens.push({ value, label: value, offset: query.length });\n return;\n }\n if (node.tagName === 'BR') {\n query += ' ';\n return;\n }\n for (const child of node.childNodes) visit(child);\n };\n for (const child of editor.childNodes) visit(child);\n return { query, tokens };\n}\n\n/** Focus an editor and place its caret at a text offset, skipping atomic token chips. */\nexport function placeTokenSearchCaret(\n editor: HTMLElement,\n offset?: number,\n): void {\n editor.focus({ preventScroll: true });\n const selection = globalThis.getSelection();\n if (!selection) return;\n const range = document.createRange();\n if (offset === undefined) {\n range.selectNodeContents(editor);\n range.collapse(false);\n } else {\n let remaining = Math.max(0, offset);\n let found = false;\n const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, {\n acceptNode: (node) =>\n node.parentElement?.closest('[data-component=\"token-search-token\"]')\n ? NodeFilter.FILTER_REJECT\n : NodeFilter.FILTER_ACCEPT,\n });\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n const source = node.textContent ?? '';\n const length = source.replaceAll('\\u200b', '').length;\n if (remaining <= length) {\n range.setStart(\n node,\n source === '\\u200b' ? 0 : Math.min(remaining, source.length),\n );\n range.collapse(true);\n found = true;\n break;\n }\n remaining -= length;\n }\n if (!found) {\n range.selectNodeContents(editor);\n range.collapse(false);\n }\n }\n selection.removeAllRanges();\n selection.addRange(range);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/list-inset-text.tsx"],"names":[],"mappings":";;;AA4BO,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,KAAA;AAAA,EACA,cAAA,GAAiB,KAAA;AAAA,EACjB,SAAA,GAAY,EAAA;AAAA,EACZ;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,aAAA,GAAgB,KAAA,KAAU,cAAA,GAAiB,IAAA,GAAO,MAAA,CAAA;AACxD,EAAA,MAAM,GAAA,GACJ,sBAAsB,cAAA,GAAiB,kCAAA,GAAqC,EAAE,CAAA,CAAA,EAAI,SAAS,GAAG,IAAA,EAAK;AACrG,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,GAAA;AAAA,MACP,gBAAA,EAAe,iBAAA;AAAA,MACf,YAAA,EAAY,aAAA;AAAA,MACZ,IAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ","file":"chunk-ZK5EGVFP.js","sourcesContent":["import type { Sides } from './divider-sides.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\nexport interface ListInsetTextProps {\n /** Text (or inline content) that carries no margin, border, or padding of its own. */\n children: KerfUiContent | string;\n /** Physical inset sides in canonical top/right/bottom/left order. Defaults to all sides. */\n sides?: Sides;\n /**\n * @deprecated Pass `sides=\"rl\"` instead. Keep only the horizontal geometry (inline margin, left/right border, and\n * left/right padding) and drop the vertical margin, border, and padding. Use it\n * when the text edge must still align with bordered items but the line should not\n * add its own vertical box space — tight text layout inside a content region.\n */\n horizontalOnly?: boolean;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * Gives bare text the content-item geometry — an 8px inline margin, a 1px\n * transparent border, and 8px padding — so a plain string lines up with\n * bordered `.kui-content` items (its text edge lands at the same 17px inset).\n * Use it for text elements that have no margin, border, or padding of their own.\n * Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box\n * space for tight text layout.\n */\nexport function ListInsetText({\n children,\n sides,\n horizontalOnly = false,\n className = '',\n slot,\n}: ListInsetTextProps) {\n const resolvedSides = sides ?? (horizontalOnly ? 'rl' : 'trbl');\n const cls =\n `kui-list-inset-text${horizontalOnly ? ' kui-list-inset-text--horizontal' : ''} ${className}`.trim();\n return (\n <div\n class={cls}\n data-component=\"list-inset-text\"\n data-sides={resolvedSides}\n slot={slot}\n >\n {children}\n </div>\n );\n}\n\nexport type { Sides } from './divider-sides.js';\n"]}
@@ -1,35 +0,0 @@
1
- .kui-catalog__detail {
2
- display: grid;
3
- min-width: 0;
4
- min-height: 0;
5
- height: 100%;
6
- grid-column: 2;
7
- }
8
-
9
- .kui-catalog__header {
10
- border-block-end: 1px solid var(--kui-color-border);
11
- background: var(--kui-color-surface);
12
- }
13
-
14
- .kui-catalog__description {
15
- max-width: var(--kui-catalog-content-measure, 70rem);
16
- margin-block: 0;
17
- background: transparent;
18
- }
19
-
20
- /* css-ownership: allow-root kui-catalog__detail-preview -- CatalogDetail assigns this class to its Pane content scroll owner. */
21
- .kui-catalog__detail-preview {
22
- background-color: var(--kui-color-surface-lowered);
23
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%238e8e93' fill-opacity='.12' d='M0 0h12v12H0zM12 12h12v12H12z'/%3E%3C/svg%3E");
24
- background-position: 0 0;
25
- background-repeat: repeat;
26
- background-size: 1.5rem 1.5rem;
27
- }
28
-
29
- @media (max-width: 52rem) {
30
- .kui-catalog__detail {
31
- height: auto;
32
- min-height: auto;
33
- grid-column: 1;
34
- }
35
- }
@@ -1,37 +0,0 @@
1
- .kui-catalog__footer {
2
- border-block-start: 1px solid var(--kui-color-border);
3
- background: color-mix(
4
- in srgb,
5
- var(--kui-color-surface-lowered) 72%,
6
- var(--kui-color-surface)
7
- );
8
- }
9
-
10
- .kui-catalog__status {
11
- display: flex;
12
- min-height: 1.625rem;
13
- padding: 0.375rem 0.75rem 0;
14
- color: var(--kui-color-text-quiet);
15
- align-items: center;
16
- justify-content: space-between;
17
- gap: var(--kui-layout-control-gap);
18
- font-size: var(--kui-font-xs);
19
- }
20
-
21
- .kui-catalog__related-heading {
22
- display: block;
23
- padding: 0.25rem var(--kui-wa-control-inset, 0.5rem) 0;
24
- color: var(--kui-color-text-quiet);
25
- font-size: var(--kui-font-xs);
26
- font-weight: 600;
27
- text-transform: uppercase;
28
- letter-spacing: 0.04em;
29
- }
30
-
31
- @media (max-width: 52rem) {
32
- .kui-catalog__status {
33
- align-items: flex-start;
34
- flex-direction: column;
35
- gap: 0.25rem;
36
- }
37
- }
@@ -1,38 +0,0 @@
1
- .kui-catalog__group--secondary {
2
- margin-block-start: var(--kui-space-m);
3
- padding-block-start: var(--kui-space-s);
4
- border-block-start: 1px solid var(--kui-color-border-quiet);
5
- }
6
-
7
- .kui-catalog__secondary {
8
- display: grid;
9
- padding-block: var(--kui-space-xs);
10
- gap: var(--kui-space-s);
11
- }
12
-
13
- .kui-catalog__secondary-group {
14
- display: grid;
15
- min-width: 0;
16
- gap: var(--kui-space-2xs);
17
- }
18
-
19
- .kui-catalog__secondary-heading {
20
- margin: 0 0.5rem;
21
- padding: 0.1rem 0.55rem;
22
- color: var(--kui-color-text-quiet);
23
- font-size: var(--kui-font-2xs);
24
- font-weight: 650;
25
- letter-spacing: 0.04em;
26
- text-transform: uppercase;
27
- }
28
-
29
- .kui-catalog__secondary-items {
30
- min-width: 0;
31
- }
32
-
33
- @media (max-width: 52rem) {
34
- .kui-catalog__group--secondary {
35
- min-width: 0;
36
- margin-block-start: 0;
37
- }
38
- }
@@ -1,22 +0,0 @@
1
- .kui-catalog__group {
2
- margin-block-start: var(--kui-space-m);
3
- }
4
-
5
- .kui-catalog__group:first-child {
6
- margin-block-start: var(--kui-space-2xs);
7
- }
8
-
9
- .kui-catalog__items {
10
- min-width: 0;
11
- }
12
-
13
- @media (max-width: 52rem) {
14
- .kui-catalog__group,
15
- .kui-catalog__group:first-child {
16
- min-width: 0;
17
- margin: 0;
18
- }
19
- }
20
- .kui-catalog__sections {
21
- display: contents;
22
- }
@@ -1,82 +0,0 @@
1
- .kui-catalog__sidebar {
2
- display: grid;
3
- width: var(--kui-catalog-sidebar-width);
4
- min-width: var(--kui-catalog-sidebar-width);
5
- height: 100%;
6
- padding: 0;
7
- overflow: hidden;
8
- justify-self: start;
9
- box-sizing: border-box;
10
- border: 0 solid var(--kui-pane-separator-color, var(--kui-color-border));
11
- border-inline-end-width: var(--kui-pane-separator-width, 1px);
12
- background: var(--kui-color-surface);
13
- transition:
14
- transform 200ms ease,
15
- visibility 0s linear 0s;
16
- }
17
-
18
- .kui-catalog__brand {
19
- display: flex;
20
- min-width: 0;
21
- flex-direction: column;
22
- }
23
-
24
- .kui-catalog__sidebar[data-collapsed="true"] {
25
- transform: translateX(-100%);
26
- visibility: hidden;
27
- transition:
28
- transform 200ms ease,
29
- visibility 0s linear 200ms;
30
- }
31
-
32
- .kui-catalog__mark {
33
- display: block;
34
- width: 2.125rem;
35
- height: 2.125rem;
36
- flex: 0 0 auto;
37
- }
38
-
39
- .kui-catalog__subtitle {
40
- margin: 0;
41
- padding: var(--kui-layout-item-padding, 0.5rem);
42
- box-sizing: border-box;
43
- border: 1px solid transparent;
44
- color: var(--kui-color-text-quiet);
45
- font-size: var(--kui-font-xs);
46
- }
47
-
48
- .kui-catalog__navigation {
49
- display: flex;
50
- min-width: 0;
51
- flex-direction: column;
52
- gap: var(--kui-layout-content-gap, 1.5rem);
53
- }
54
-
55
- @media (max-width: 52rem) {
56
- .kui-catalog__sidebar[data-collapsed="true"] {
57
- display: none;
58
- }
59
-
60
- .kui-catalog__sidebar {
61
- width: 100%;
62
- min-width: 0;
63
- height: auto;
64
- justify-self: stretch;
65
- border-block-end-width: var(--kui-pane-separator-width, 1px);
66
- border-inline-end-width: 0;
67
- transform: none;
68
- }
69
-
70
- .kui-catalog__navigation {
71
- display: grid;
72
- grid-template-columns: repeat(2, minmax(0, 1fr));
73
- align-items: start;
74
- gap: 0.5rem 1rem;
75
- }
76
- }
77
-
78
- @media (prefers-reduced-motion: reduce) {
79
- .kui-catalog__sidebar {
80
- transition-duration: 0s;
81
- }
82
- }