@kerfjs/ui 5.0.0-beta.17 → 5.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -81
- package/ai/application-ui-diagnostic-ids-v1.json +92 -0
- package/ai/application-ui-profile-sync.cjs +529 -0
- package/ai/application-ui-profile.d.mts +1 -0
- package/ai/application-ui-profile.d.ts +102 -0
- package/ai/application-ui-profile.defaults.json +41 -0
- package/ai/application-ui-profile.mjs +626 -0
- package/ai/application-ui-profile.schema.json +130 -0
- package/ai/catalog-authoring.json +25 -0
- package/ai/catalog-authoring.schema.json +61 -0
- package/ai/compile-time-contracts-v1.json +101 -0
- package/ai/compile-time-contracts-v1.schema.json +49 -0
- package/ai/component-catalog-extension-v2.d.ts +7 -0
- package/ai/component-catalog-extension-v2.schema.json +7 -0
- package/ai/component-catalog-extension.schema.json +79 -0
- package/ai/component-catalog-v2-overrides.json +326 -0
- package/ai/component-catalog-v2.d.ts +67 -0
- package/ai/component-catalog-v2.json +4441 -0
- package/ai/component-catalog-v2.schema.json +246 -0
- package/ai/component-catalog.json +649 -6
- package/ai/component-catalog.schema.json +15 -0
- package/ai/public-api-signatures-v1.md +357 -91
- package/ai/skill.md +95 -50
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/cli.mjs +46 -0
- package/analyzer/index.d.mts +45 -0
- package/analyzer/index.mjs +743 -0
- package/analyzer/report.schema.json +66 -0
- package/dist/app-tab.d.ts +1 -1
- package/dist/app-tab.js +1 -1
- package/dist/browser/pane.js +3 -0
- package/dist/browser/sunken-panel.js +3 -0
- package/dist/catalog-resources.d.ts +34 -0
- package/dist/catalog-resources.js +22 -0
- package/dist/catalog-resources.js.map +1 -0
- package/dist/catalog.d.ts +29 -4
- package/dist/catalog.js +302 -84
- package/dist/catalog.js.map +1 -1
- package/dist/chunk-5VTB2BKP.js +35 -0
- package/dist/chunk-5VTB2BKP.js.map +1 -0
- package/dist/chunk-6WTETUZ6.js +21 -0
- package/dist/chunk-6WTETUZ6.js.map +1 -0
- package/dist/chunk-7KEUJIIC.js +218 -0
- package/dist/chunk-7KEUJIIC.js.map +1 -0
- package/dist/chunk-7L6EHUMV.js +31 -0
- package/dist/chunk-7L6EHUMV.js.map +1 -0
- package/dist/{chunk-XXMOARTH.js → chunk-AASLYRGE.js} +57 -16
- package/dist/chunk-AASLYRGE.js.map +1 -0
- package/dist/chunk-BBRXX6PF.js +108 -0
- package/dist/chunk-BBRXX6PF.js.map +1 -0
- package/dist/{chunk-6NLRBSVX.js → chunk-CN2XNTAM.js} +129 -72
- package/dist/chunk-CN2XNTAM.js.map +1 -0
- package/dist/chunk-DPDBVKNA.js +113 -0
- package/dist/chunk-DPDBVKNA.js.map +1 -0
- package/dist/chunk-DSNIYOZ3.js +114 -0
- package/dist/chunk-DSNIYOZ3.js.map +1 -0
- package/dist/chunk-ELSJX4W7.js +68 -0
- package/dist/chunk-ELSJX4W7.js.map +1 -0
- package/dist/{chunk-AHQI52QO.js → chunk-FEY65TBV.js} +6 -2
- package/dist/chunk-FEY65TBV.js.map +1 -0
- package/dist/chunk-JRKSK2HX.js +79 -0
- package/dist/chunk-JRKSK2HX.js.map +1 -0
- package/dist/chunk-K57KRAOV.js +117 -0
- package/dist/chunk-K57KRAOV.js.map +1 -0
- package/dist/chunk-LPOMRC4C.js +25 -0
- package/dist/chunk-LPOMRC4C.js.map +1 -0
- package/dist/chunk-M7JBER5U.js +41 -0
- package/dist/chunk-M7JBER5U.js.map +1 -0
- package/dist/chunk-NENBUYX5.js +79 -0
- package/dist/chunk-NENBUYX5.js.map +1 -0
- package/dist/chunk-OHU6CI22.js +83 -0
- package/dist/chunk-OHU6CI22.js.map +1 -0
- package/dist/{chunk-YGN7OMLT.js → chunk-OZWU5ZPZ.js} +2 -2
- package/dist/chunk-OZWU5ZPZ.js.map +1 -0
- package/dist/chunk-PIDTEQ3U.js +105 -0
- package/dist/chunk-PIDTEQ3U.js.map +1 -0
- package/dist/chunk-PX3YSS5C.js +32 -0
- package/dist/chunk-PX3YSS5C.js.map +1 -0
- package/dist/chunk-PZQVSDLH.js +61 -0
- package/dist/chunk-PZQVSDLH.js.map +1 -0
- package/dist/chunk-QO55FN2Y.js +20 -0
- package/dist/chunk-QO55FN2Y.js.map +1 -0
- package/dist/chunk-QQFJMRIB.js +45 -0
- package/dist/chunk-QQFJMRIB.js.map +1 -0
- package/dist/chunk-RYRIFZCT.js +58 -0
- package/dist/chunk-RYRIFZCT.js.map +1 -0
- package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
- package/dist/chunk-SRSJO5QE.js.map +1 -0
- package/dist/chunk-VLYV65LK.js +38 -0
- package/dist/chunk-VLYV65LK.js.map +1 -0
- package/dist/chunk-W4CXQYSG.js +23 -0
- package/dist/chunk-W4CXQYSG.js.map +1 -0
- package/dist/{chunk-WXMGNX2Y.js → chunk-W7YD6E4N.js} +2 -2
- package/dist/chunk-W7YD6E4N.js.map +1 -0
- package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
- package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
- package/dist/collapsible-panel.d.ts +2 -2
- package/dist/collapsible-panel.js +47 -6
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/device-class.js +33 -5
- package/dist/device-class.js.map +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.d.ts +1 -1
- package/dist/empty-state.js +1 -1
- package/dist/floating-toolbar.d.ts +1 -1
- package/dist/floating-toolbar.js +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +27 -25
- package/dist/list-action-row.d.ts +1 -1
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.d.ts +30 -9
- package/dist/list-header.js +1 -1
- package/dist/list-inset-control.d.ts +1 -1
- package/dist/list-inset-control.js +1 -1
- package/dist/list-inset-text.d.ts +1 -1
- package/dist/list-inset-text.js +1 -1
- package/dist/list-item.d.ts +1 -1
- package/dist/list-item.js +1 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/nav-stack.d.ts +1 -1
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +49 -0
- package/dist/pane.js +4 -0
- package/dist/pane.js.map +1 -0
- package/dist/panel-header.d.ts +10 -4
- package/dist/panel-header.js +1 -1
- package/dist/resizable-region.d.ts +1 -1
- package/dist/resizable-region.js +1 -1
- package/dist/segmented-control.d.ts +6 -6
- package/dist/segmented-control.js +1 -1
- package/dist/select.d.ts +11 -5
- package/dist/select.js +1 -1
- package/dist/skeleton.d.ts +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/split-view.d.ts +1 -1
- package/dist/split-view.js +70 -10
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +4 -3
- package/dist/state-banner.js +1 -1
- package/dist/styles/catalog.css +32 -6
- package/dist/styles/layout.css +2 -20
- package/dist/styles/pane.css +62 -0
- package/dist/styles/segmented-control.css +3 -7
- package/dist/styles/sunken-panel.css +18 -0
- package/dist/sunken-panel.d.ts +16 -0
- package/dist/sunken-panel.js +3 -0
- package/dist/sunken-panel.js.map +1 -0
- package/dist/tab-bar.d.ts +4 -3
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +6 -6
- package/dist/tab-scaffold.js +43 -8
- package/dist/tab-scaffold.js.map +1 -1
- package/dist/token-search-field.d.ts +25 -9
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.d.ts +10 -6
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +10 -11
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +1 -1
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +2 -2
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.d.ts +31 -2
- package/dist/wire-catalog.js +203 -8
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-nav-stack.js +22 -7
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-resizable-regions.d.ts +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.js +52 -41
- package/dist/wire-sidebar.js.map +1 -1
- package/dist/wire-tab-bars.d.ts +5 -2
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-scaffold.js +9 -4
- package/dist/wire-tab-scaffold.js.map +1 -1
- package/dist/wire-token-search-fields.d.ts +12 -7
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +1 -1
- package/dist/workbench.js +56 -9
- package/dist/workbench.js.map +1 -1
- package/docs/app-layouts.md +7 -7
- package/docs/catalog.md +249 -46
- package/docs/collapsible-panel.md +38 -11
- package/docs/component-contract.md +132 -7
- package/docs/component-selection.md +79 -67
- package/docs/design/templates.md +1 -1
- package/docs/design-philosophy.md +7 -9
- package/docs/device-class.md +8 -8
- package/docs/examples/application-ui-profile.json +60 -0
- package/docs/examples/command-palette-adapter.tsx +67 -17
- package/docs/examples/component-catalog-extension-v2.json +81 -0
- package/docs/examples/component-catalog-extension.json +45 -0
- package/docs/layout.md +51 -32
- package/docs/nav-stack.md +15 -6
- package/docs/recipes.md +4 -4
- package/docs/split-view.md +3 -3
- package/docs/sunken-panel.md +43 -0
- package/docs/tab-scaffold.md +16 -7
- package/docs/type-contracts.md +99 -0
- package/docs/ui-analyzer.md +81 -0
- package/docs/ui-doctor.md +77 -0
- package/docs/ui-evaluator.md +122 -0
- package/docs/webawesome-theme.md +8 -8
- package/docs/workbench.md +18 -5
- package/doctor/cli.mjs +115 -0
- package/doctor/config.schema.json +68 -0
- package/doctor/index.d.mts +116 -0
- package/doctor/index.mjs +1256 -0
- package/doctor/report.schema.json +118 -0
- package/evaluator/cli.mjs +89 -0
- package/evaluator/index.d.mts +90 -0
- package/evaluator/index.mjs +1138 -0
- package/evaluator/report.schema.json +152 -0
- package/llms.txt +58 -15
- package/package.json +70 -10
- package/ux-demo/recipes/app-shell.tsx +206 -10
- package/ux-demo/recipes/collapsible-sidebar.tsx +167 -44
- package/ux-demo/recipes/compact-toolbar.tsx +114 -12
- package/ux-demo/recipes/composer-form.tsx +106 -18
- package/ux-demo/recipes/list-detail-dialog.tsx +144 -8
- package/ux-demo/recipes/list-workspace-states.tsx +165 -8
- package/ux-demo/recipes/loaders.ts +5 -2
- package/ux-demo/recipes/loading-inspector.tsx +124 -41
- package/ux-demo/recipes/mount-recipe.ts +27 -6
- package/ux-demo/recipes/navigation-sidebar.tsx +120 -9
- package/ux-demo/recipes/navigation-stack.tsx +61 -19
- package/ux-demo/recipes/types.ts +3 -1
- package/ux-demo/recipes/workspace-header.tsx +57 -2
- package/dist/chunk-2Z5TWHKQ.js +0 -34
- package/dist/chunk-2Z5TWHKQ.js.map +0 -1
- package/dist/chunk-37T3VNIZ.js +0 -19
- package/dist/chunk-37T3VNIZ.js.map +0 -1
- package/dist/chunk-55DATV3A.js +0 -10
- package/dist/chunk-55DATV3A.js.map +0 -1
- package/dist/chunk-5ATCDSQS.js +0 -42
- package/dist/chunk-5ATCDSQS.js.map +0 -1
- package/dist/chunk-5E2HVJ33.js +0 -10
- package/dist/chunk-5E2HVJ33.js.map +0 -1
- package/dist/chunk-6NLRBSVX.js.map +0 -1
- package/dist/chunk-7BR3DO2A.js.map +0 -1
- package/dist/chunk-7JB7VPRI.js +0 -34
- package/dist/chunk-7JB7VPRI.js.map +0 -1
- package/dist/chunk-7LDCTU7D.js +0 -134
- package/dist/chunk-7LDCTU7D.js.map +0 -1
- package/dist/chunk-AHQI52QO.js.map +0 -1
- package/dist/chunk-AQNKJRFH.js +0 -79
- package/dist/chunk-AQNKJRFH.js.map +0 -1
- package/dist/chunk-AVZHJN6C.js +0 -14
- package/dist/chunk-AVZHJN6C.js.map +0 -1
- package/dist/chunk-B24C4A6T.js +0 -22
- package/dist/chunk-B24C4A6T.js.map +0 -1
- package/dist/chunk-CH4SQ6H5.js +0 -39
- package/dist/chunk-CH4SQ6H5.js.map +0 -1
- package/dist/chunk-DAFFDO33.js +0 -14
- package/dist/chunk-DAFFDO33.js.map +0 -1
- package/dist/chunk-I7INRJO4.js +0 -17
- package/dist/chunk-I7INRJO4.js.map +0 -1
- package/dist/chunk-L4OKFDJY.js +0 -24
- package/dist/chunk-L4OKFDJY.js.map +0 -1
- package/dist/chunk-M5JRI6MN.js +0 -27
- package/dist/chunk-M5JRI6MN.js.map +0 -1
- package/dist/chunk-RNPGFQ33.js +0 -10
- package/dist/chunk-RNPGFQ33.js.map +0 -1
- package/dist/chunk-VPCTCUED.js +0 -10
- package/dist/chunk-VPCTCUED.js.map +0 -1
- package/dist/chunk-WRTAQ7BZ.js +0 -23
- package/dist/chunk-WRTAQ7BZ.js.map +0 -1
- package/dist/chunk-WVPYVDXY.js +0 -15
- package/dist/chunk-WVPYVDXY.js.map +0 -1
- package/dist/chunk-WXMGNX2Y.js.map +0 -1
- package/dist/chunk-XXMOARTH.js.map +0 -1
- package/dist/chunk-YGN7OMLT.js.map +0 -1
- package/dist/chunk-ZQQ6P4SV.js +0 -20
- package/dist/chunk-ZQQ6P4SV.js.map +0 -1
|
@@ -14,7 +14,9 @@ import { Columns3, FileText, Inbox, List } from 'lucide';
|
|
|
14
14
|
|
|
15
15
|
import type { RecipeFactory } from './types.js';
|
|
16
16
|
|
|
17
|
-
const icon = (node: Parameters<typeof LucideIcon>[0]['icon'], name: string) =>
|
|
17
|
+
const icon = (node: Parameters<typeof LucideIcon>[0]['icon'], name: string) => (
|
|
18
|
+
<LucideIcon icon={node} name={name} />
|
|
19
|
+
);
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* A record inspector whose per-record values load asynchronously. Every
|
|
@@ -27,47 +29,128 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
27
29
|
const loading = signal(true);
|
|
28
30
|
const render = () => {
|
|
29
31
|
const p = loading.value;
|
|
30
|
-
return
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
32
|
+
return (
|
|
33
|
+
<section
|
|
34
|
+
class="kui-recipe recipe-inspector kui-recipe__surface kui-pane"
|
|
35
|
+
data-recipe="recipe-loading-inspector"
|
|
36
|
+
data-inspector-loading={String(p)}
|
|
37
|
+
>
|
|
38
|
+
<PanelHeader
|
|
39
|
+
title="Ticket · KF-2048"
|
|
40
|
+
titleId="recipe-inspector-title"
|
|
41
|
+
summary="Restore keyboard focus after a dialog closes"
|
|
42
|
+
summaryId="recipe-inspector-summary"
|
|
43
|
+
icon={icon(FileText, 'file-text')}
|
|
44
|
+
placeholder={p}
|
|
45
|
+
actions={
|
|
46
|
+
<button
|
|
47
|
+
class="kui-recipe__button"
|
|
48
|
+
data-primary="true"
|
|
49
|
+
type="button"
|
|
50
|
+
data-action="recipe-action"
|
|
51
|
+
data-recipe-command="toggle"
|
|
52
|
+
>
|
|
53
|
+
{p ? 'Show loaded' : 'Show loading'}
|
|
54
|
+
</button>
|
|
55
|
+
}
|
|
56
|
+
/>
|
|
57
|
+
<div class="recipe-inspector__body kui-pane__content kui-content">
|
|
58
|
+
<section>
|
|
59
|
+
<ValueTable label="Ticket details">
|
|
60
|
+
<ValueTableRow
|
|
61
|
+
label="Status"
|
|
62
|
+
value="In review"
|
|
63
|
+
icon={icon(Inbox, 'inbox')}
|
|
64
|
+
placeholder={p}
|
|
65
|
+
/>
|
|
66
|
+
<ValueTableRow label="Owner" value="Mara Lopez" placeholder={p} />
|
|
67
|
+
<ValueTableRow label="Priority" value="High" placeholder={p} />
|
|
68
|
+
<ValueTableRow
|
|
69
|
+
label="Updated"
|
|
70
|
+
value="2 hours ago"
|
|
71
|
+
placeholder={p}
|
|
72
|
+
/>
|
|
73
|
+
</ValueTable>
|
|
74
|
+
</section>
|
|
75
|
+
<div class="recipe-inspector__controls">
|
|
76
|
+
<Select
|
|
77
|
+
name="recipe-inspector-status"
|
|
78
|
+
value="review"
|
|
79
|
+
label="Status"
|
|
80
|
+
placeholder={p}
|
|
81
|
+
choices={[
|
|
82
|
+
{ value: 'review', label: 'In review' },
|
|
83
|
+
{ value: 'ready', label: 'Ready' },
|
|
84
|
+
{ value: 'done', label: 'Done' },
|
|
85
|
+
]}
|
|
86
|
+
/>
|
|
87
|
+
<SegmentedControl
|
|
88
|
+
id="recipe-inspector-view"
|
|
89
|
+
label="Inspector view"
|
|
90
|
+
value="details"
|
|
91
|
+
appearance="toolbar"
|
|
92
|
+
shape="pill"
|
|
93
|
+
size="small"
|
|
94
|
+
placeholder={p}
|
|
95
|
+
choices={[
|
|
96
|
+
{
|
|
97
|
+
value: 'details',
|
|
98
|
+
label: 'Details',
|
|
99
|
+
content: icon(List, 'list'),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
value: 'activity',
|
|
103
|
+
label: 'Activity',
|
|
104
|
+
content: icon(Columns3, 'columns-3'),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
value: 'files',
|
|
108
|
+
label: 'Files',
|
|
109
|
+
content: icon(FileText, 'file-text'),
|
|
110
|
+
},
|
|
111
|
+
]}
|
|
112
|
+
/>
|
|
113
|
+
</div>
|
|
114
|
+
<section>
|
|
115
|
+
<ListItem
|
|
116
|
+
action="recipe-action"
|
|
117
|
+
itemId="reassign"
|
|
118
|
+
label="Reassign ticket"
|
|
119
|
+
icon={icon(Inbox, 'inbox')}
|
|
120
|
+
placeholder={p}
|
|
121
|
+
/>
|
|
122
|
+
<ListItem
|
|
123
|
+
action="recipe-action"
|
|
124
|
+
itemId="watch"
|
|
125
|
+
label="Watch for changes"
|
|
126
|
+
placeholder={p}
|
|
127
|
+
/>
|
|
128
|
+
</section>
|
|
129
|
+
{p ? (
|
|
130
|
+
<StateBanner
|
|
131
|
+
tone="info"
|
|
132
|
+
title=""
|
|
133
|
+
detail=""
|
|
134
|
+
icon={icon(FileText, 'file-text')}
|
|
135
|
+
placeholder
|
|
136
|
+
/>
|
|
137
|
+
) : (
|
|
138
|
+
<StateBanner
|
|
139
|
+
tone="success"
|
|
140
|
+
title="Up to date"
|
|
141
|
+
detail="All checks passed on the latest revision."
|
|
142
|
+
icon={icon(FileText, 'file-text')}
|
|
143
|
+
/>
|
|
144
|
+
)}
|
|
145
|
+
<p class="kui-recipe__ownership kui-content-item">
|
|
146
|
+
Each value-bearing component's <code>placeholder</code> prop renders
|
|
147
|
+
skeletons in its value slots while loading, so the recipe composes a
|
|
148
|
+
faithful loading inspector from real chrome. The app owns the
|
|
149
|
+
loading lifecycle and which values are still unknown.
|
|
150
|
+
</p>
|
|
60
151
|
</div>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<ListItem action="recipe-action" itemId="watch" label="Watch for changes" placeholder={p} />
|
|
64
|
-
</section>
|
|
65
|
-
{p
|
|
66
|
-
? <StateBanner tone="info" title="" detail="" icon={icon(FileText, 'file-text')} placeholder />
|
|
67
|
-
: <StateBanner tone="success" title="Up to date" detail="All checks passed on the latest revision." icon={icon(FileText, 'file-text')} />}
|
|
68
|
-
<p class="kui-recipe__ownership kui-content-item">Each value-bearing component's <code>placeholder</code> prop renders skeletons in its value slots while loading, so the recipe composes a faithful loading inspector from real chrome. The app owns the loading lifecycle and which values are still unknown.</p>
|
|
69
|
-
</div>
|
|
70
|
-
</section>;
|
|
152
|
+
</section>
|
|
153
|
+
);
|
|
71
154
|
};
|
|
72
155
|
return {
|
|
73
156
|
render,
|
|
@@ -9,7 +9,10 @@ import type { RecipeController } from './types.js';
|
|
|
9
9
|
* Copyable application boundary for a recipe. The caller owns one stable root
|
|
10
10
|
* and retains the returned disposer for that root's lifetime.
|
|
11
11
|
*/
|
|
12
|
-
export function mountRecipe(
|
|
12
|
+
export function mountRecipe(
|
|
13
|
+
root: HTMLElement,
|
|
14
|
+
controller: RecipeController,
|
|
15
|
+
): () => void {
|
|
13
16
|
const stopMount = mount(root, controller.render);
|
|
14
17
|
const stopActions = delegateActions(root, 'click', {
|
|
15
18
|
'recipe-action': (_event, element) => {
|
|
@@ -17,14 +20,32 @@ export function mountRecipe(root: HTMLElement, controller: RecipeController): ()
|
|
|
17
20
|
controller.action(target.dataset.recipeCommand ?? '', target);
|
|
18
21
|
},
|
|
19
22
|
});
|
|
20
|
-
const dispatchChange = (_event: Event, element: Element) =>
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
23
|
+
const dispatchChange = (_event: Event, element: Element) =>
|
|
24
|
+
controller.change?.(element as HTMLElement);
|
|
25
|
+
const stopChanges = delegate(
|
|
26
|
+
root,
|
|
27
|
+
'change',
|
|
28
|
+
'wa-select, wa-input, wa-textarea',
|
|
29
|
+
dispatchChange,
|
|
30
|
+
);
|
|
31
|
+
const stopInputs = delegate(
|
|
32
|
+
root,
|
|
33
|
+
'input',
|
|
34
|
+
'wa-input, wa-textarea',
|
|
35
|
+
dispatchChange,
|
|
36
|
+
);
|
|
37
|
+
const stopDialogs = delegate(
|
|
38
|
+
root,
|
|
39
|
+
'wa-after-hide',
|
|
40
|
+
'wa-dialog',
|
|
41
|
+
(_event, element) => controller.afterHide?.(element as HTMLElement),
|
|
42
|
+
);
|
|
24
43
|
const stopResize = wireResizableRegions(root, {
|
|
25
44
|
onCommit: ({ id, size }) => controller.resize?.(id, size),
|
|
26
45
|
});
|
|
27
|
-
const stopNav = wireNavStack(root, {
|
|
46
|
+
const stopNav = wireNavStack(root, {
|
|
47
|
+
onBack: () => controller.action('nav-back', root),
|
|
48
|
+
});
|
|
28
49
|
const stopWire = controller.wire?.(root);
|
|
29
50
|
|
|
30
51
|
let disposed = false;
|
|
@@ -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 = () =>
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
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:
|
|
32
|
-
<
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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:
|
|
44
|
-
<div class="kui-content
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
80
|
+
),
|
|
50
81
|
});
|
|
51
82
|
|
|
52
83
|
const views = signal<NavStackView[]>([listView()]);
|
|
53
84
|
|
|
54
|
-
const render = () =>
|
|
55
|
-
<
|
|
56
|
-
|
|
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,
|
package/ux-demo/recipes/types.ts
CHANGED
|
@@ -14,4 +14,6 @@ export interface RecipeController {
|
|
|
14
14
|
wire?(root: HTMLElement): () => void;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export type RecipeFactory = (
|
|
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: () =>
|
|
11
|
-
|
|
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
|
});
|
package/dist/chunk-2Z5TWHKQ.js
DELETED
|
@@ -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":"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","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"]}
|
package/dist/chunk-37T3VNIZ.js
DELETED
|
@@ -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"]}
|
package/dist/chunk-55DATV3A.js
DELETED
|
@@ -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"]}
|