@kerfjs/ui 5.0.0-beta.4 → 5.0.0-beta.7
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 +9 -8
- package/ai/component-catalog.json +379 -174
- package/ai/public-api-signatures-v1.md +387 -33
- package/ai/skill.md +15 -7
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/app-tab.d.ts +3 -1
- package/dist/app-tab.js +2 -1
- package/dist/browser/app-tab.js +1 -0
- package/dist/browser/menu-action-row.js +1 -0
- package/dist/browser/menu-header.js +1 -0
- package/dist/browser/menu-item.js +1 -0
- package/dist/browser/panel-header.js +7 -0
- package/dist/browser/segmented-control.js +1 -0
- package/dist/browser/select.js +1 -0
- package/dist/browser/skeleton.js +3 -0
- package/dist/browser/state-banner.js +1 -0
- package/dist/browser/toolbar-text.js +1 -0
- package/dist/browser/value-table.js +1 -0
- package/dist/chunk-2RJBFNB6.js +172 -0
- package/dist/chunk-2RJBFNB6.js.map +1 -0
- package/dist/{chunk-XZXRLY5Q.js → chunk-2Z5TWHKQ.js} +7 -6
- package/dist/chunk-2Z5TWHKQ.js.map +1 -0
- package/dist/{chunk-EGHL5S4P.js → chunk-3YD6ZNRA.js} +8 -7
- package/dist/chunk-3YD6ZNRA.js.map +1 -0
- package/dist/chunk-B24C4A6T.js +22 -0
- package/dist/chunk-B24C4A6T.js.map +1 -0
- package/dist/{chunk-NPPD2A6O.js → chunk-H6URQGJI.js} +8 -6
- package/dist/chunk-H6URQGJI.js.map +1 -0
- package/dist/chunk-I7INRJO4.js +17 -0
- package/dist/chunk-I7INRJO4.js.map +1 -0
- package/dist/chunk-KJYXOTG3.js +10 -0
- package/dist/chunk-KJYXOTG3.js.map +1 -0
- package/dist/{chunk-CTQKI2XL.js → chunk-LC3YSAZC.js} +14 -3
- package/dist/chunk-LC3YSAZC.js.map +1 -0
- package/dist/chunk-N3SUXLLS.js +23 -0
- package/dist/chunk-N3SUXLLS.js.map +1 -0
- package/dist/{chunk-R6JHHBKQ.js → chunk-PONXLV5U.js} +5 -5
- package/dist/chunk-PONXLV5U.js.map +1 -0
- package/dist/chunk-TZNCCM5H.js +20 -0
- package/dist/chunk-TZNCCM5H.js.map +1 -0
- package/dist/{chunk-TRNBHPNW.js → chunk-YGN7OMLT.js} +11 -8
- package/dist/chunk-YGN7OMLT.js.map +1 -0
- package/dist/chunk-YKUUZPED.js +24 -0
- package/dist/chunk-YKUUZPED.js.map +1 -0
- package/dist/device-class.d.ts +62 -0
- package/dist/device-class.js +75 -0
- package/dist/device-class.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +15 -15
- package/dist/menu-action-row.d.ts +3 -1
- package/dist/menu-action-row.js +2 -1
- package/dist/menu-header.d.ts +3 -1
- package/dist/menu-header.js +2 -1
- package/dist/menu-item.d.ts +3 -1
- package/dist/menu-item.js +2 -1
- package/dist/nav-stack.d.ts +38 -0
- package/dist/nav-stack.js +5 -0
- package/dist/nav-stack.js.map +1 -0
- package/dist/panel-header.d.ts +28 -0
- package/dist/panel-header.js +7 -0
- package/dist/panel-header.js.map +1 -0
- package/dist/segmented-control.d.ts +3 -1
- package/dist/segmented-control.js +2 -1
- package/dist/select.d.ts +5 -2
- package/dist/select.js +2 -1
- package/dist/skeleton.d.ts +24 -0
- package/dist/skeleton.js +3 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/split-view.d.ts +42 -0
- package/dist/split-view.js +21 -0
- package/dist/split-view.js.map +1 -0
- package/dist/state-banner.d.ts +3 -1
- package/dist/state-banner.js +2 -1
- package/dist/styles/foundation.css +21 -0
- package/dist/styles/menu-header.css +19 -2
- package/dist/styles/nav-stack.css +112 -0
- package/dist/styles/panel-header.css +64 -0
- package/dist/styles/select.css +42 -0
- package/dist/styles/skeleton.css +31 -0
- package/dist/styles/split-view.css +35 -0
- package/dist/styles/styles.css +2 -2
- package/dist/styles/tab-scaffold.css +84 -0
- package/dist/styles/toolbar-control-group.css +52 -2
- package/dist/styles/toolbar-text.css +11 -0
- package/dist/styles/toolbar.css +9 -0
- package/dist/styles/workbench.css +94 -0
- package/dist/tab-scaffold.d.ts +30 -0
- package/dist/tab-scaffold.js +16 -0
- package/dist/tab-scaffold.js.map +1 -0
- package/dist/toolbar-text.d.ts +6 -2
- package/dist/toolbar-text.js +2 -1
- package/dist/value-table.d.ts +3 -1
- package/dist/value-table.js +2 -1
- package/dist/wire-nav-stack.d.ts +15 -0
- package/dist/wire-nav-stack.js +88 -0
- package/dist/wire-nav-stack.js.map +1 -0
- package/dist/wire-tab-scaffold.d.ts +11 -0
- package/dist/wire-tab-scaffold.js +16 -0
- package/dist/wire-tab-scaffold.js.map +1 -0
- package/dist/wire-token-search-fields.d.ts +46 -4
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +33 -0
- package/dist/workbench.js +17 -0
- package/dist/workbench.js.map +1 -0
- package/docs/accessibility.md +10 -10
- package/docs/app-layouts.md +57 -0
- package/docs/component-contract.md +46 -9
- package/docs/component-selection.md +57 -7
- package/docs/design-philosophy.md +23 -1
- package/docs/device-class.md +54 -0
- package/docs/layout.md +33 -8
- package/docs/nav-stack.md +47 -0
- package/docs/recipes.md +17 -5
- package/docs/split-view.md +49 -0
- package/docs/tab-scaffold.md +41 -0
- package/docs/ux-demo.md +3 -3
- package/docs/workbench.md +47 -0
- package/llms.txt +116 -43
- package/package.json +43 -11
- package/ux-demo/recipes/app-shell.tsx +3 -3
- package/ux-demo/recipes/composer-form.tsx +2 -2
- package/ux-demo/recipes/list-workspace-states.tsx +2 -2
- package/ux-demo/recipes/loaders.ts +2 -0
- package/ux-demo/recipes/master-detail-dialog.tsx +2 -2
- package/ux-demo/recipes/mount-recipe.ts +3 -0
- package/ux-demo/recipes/navigation-stack.tsx +76 -0
- package/ux-demo/recipes/recipes.css +19 -8
- package/ux-demo/recipes/workspace-header.tsx +2 -2
- package/dist/browser/dialog-header.js +0 -5
- package/dist/browser/page-header.js +0 -3
- package/dist/chunk-2PES33HS.js +0 -13
- package/dist/chunk-2PES33HS.js.map +0 -1
- package/dist/chunk-CTQKI2XL.js.map +0 -1
- package/dist/chunk-EGHL5S4P.js.map +0 -1
- package/dist/chunk-GY5WH7TO.js +0 -10
- package/dist/chunk-GY5WH7TO.js.map +0 -1
- package/dist/chunk-H5AGGVU5.js +0 -75
- package/dist/chunk-H5AGGVU5.js.map +0 -1
- package/dist/chunk-K3G72I6D.js +0 -24
- package/dist/chunk-K3G72I6D.js.map +0 -1
- package/dist/chunk-NPPD2A6O.js.map +0 -1
- package/dist/chunk-R6JHHBKQ.js.map +0 -1
- package/dist/chunk-S3TPM2LP.js +0 -23
- package/dist/chunk-S3TPM2LP.js.map +0 -1
- package/dist/chunk-TRNBHPNW.js.map +0 -1
- package/dist/chunk-VHW5YNIB.js +0 -17
- package/dist/chunk-VHW5YNIB.js.map +0 -1
- package/dist/chunk-XZXRLY5Q.js.map +0 -1
- package/dist/dialog-header.d.ts +0 -15
- package/dist/dialog-header.js +0 -5
- package/dist/dialog-header.js.map +0 -1
- package/dist/page-header.d.ts +0 -9
- package/dist/page-header.js +0 -3
- package/dist/page-header.js.map +0 -1
- package/dist/styles/dialog-header.css +0 -87
- package/dist/styles/page-header.css +0 -33
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ToolbarText } from './chunk-KJYXOTG3.js';
|
|
2
|
+
import { jsxs, jsx } from 'kerfjs/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
function NavStack({ id, label, views, backLabel = "Back", hideToolbar = false, bottomToolbar, className = "" }) {
|
|
5
|
+
const topIndex = views.length - 1;
|
|
6
|
+
const top = views[topIndex];
|
|
7
|
+
const canPop = views.length > 1;
|
|
8
|
+
return /* @__PURE__ */ jsxs("section", { class: `kui-nav-stack ${className}`.trim(), id, "data-component": "nav-stack", "data-nav-stack-id": id, "data-depth": String(views.length), "aria-label": label, children: [
|
|
9
|
+
!hideToolbar && /* @__PURE__ */ jsxs("header", { class: "kui-nav-stack__chrome", "data-nav-stack-chrome": true, children: [
|
|
10
|
+
/* @__PURE__ */ jsxs("div", { class: "kui-nav-stack__lead", children: [
|
|
11
|
+
canPop && /* @__PURE__ */ jsx("button", { type: "button", class: "kui-nav-stack__back", "data-nav-back": true, "aria-label": backLabel, children: /* @__PURE__ */ jsx("svg", { class: "kui-nav-stack__back-icon", viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
12
|
+
/* @__PURE__ */ jsx(ToolbarText, { text: top?.title ?? "", size: "large", className: "kui-nav-stack__title" })
|
|
13
|
+
] }),
|
|
14
|
+
top?.toolbar && /* @__PURE__ */ jsx("div", { class: "kui-nav-stack__actions", children: top.toolbar })
|
|
15
|
+
] }),
|
|
16
|
+
/* @__PURE__ */ jsx("div", { class: "kui-nav-stack__viewport", "data-nav-stack-viewport": true, children: views.map((view, index) => /* @__PURE__ */ jsx("article", { class: "kui-nav-stack__view", "data-key": view.key, "data-nav-key": view.key, "data-nav-active": String(index === topIndex), "aria-hidden": String(index !== topIndex), children: view.content })) }),
|
|
17
|
+
bottomToolbar && /* @__PURE__ */ jsx("footer", { class: "kui-nav-stack__bottom", "data-nav-stack-bottom": true, children: bottomToolbar })
|
|
18
|
+
] });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { NavStack };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=chunk-N3SUXLLS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/nav-stack.tsx"],"names":[],"mappings":";;;AAuCO,SAAS,QAAA,CAAS,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,SAAA,GAAY,MAAA,EAAQ,WAAA,GAAc,KAAA,EAAO,aAAA,EAAe,SAAA,GAAY,EAAA,EAAG,EAAkB;AACpI,EAAA,MAAM,QAAA,GAAW,MAAM,MAAA,GAAS,CAAA;AAChC,EAAA,MAAM,GAAA,GAAM,MAAM,QAAQ,CAAA;AAC1B,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,GAAS,CAAA;AAC9B,EAAA,4BAAQ,SAAA,EAAA,EAAQ,KAAA,EAAO,iBAAiB,SAAS,CAAA,CAAA,CAAG,MAAK,EAAG,EAAA,EAAQ,kBAAe,WAAA,EAAY,mBAAA,EAAmB,IAAI,YAAA,EAAY,MAAA,CAAO,MAAM,MAAM,CAAA,EAAG,cAAY,KAAA,EACjK,QAAA,EAAA;AAAA,IAAA,CAAC,+BAAe,IAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAM,uBAAA,EAAwB,yBAAqB,IAAA,EAC1E,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,OAAM,qBAAA,EACR,QAAA,EAAA;AAAA,QAAA,MAAA,wBAAW,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,KAAA,EAAM,uBAAsB,eAAA,EAAa,IAAA,EAAC,YAAA,EAAY,SAAA,EACrF,8BAAC,KAAA,EAAA,EAAI,KAAA,EAAM,0BAAA,EAA2B,OAAA,EAAQ,aAAY,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,eAAY,MAAA,EAAO,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,gBAAe,cAAA,EAAa,GAAA,EAAI,gBAAA,EAAe,OAAA,EAAQ,mBAAgB,OAAA,EAAQ,QAAA,kBAAA,GAAA,CAAC,UAAK,CAAA,EAAE,gBAAA,EAAiB,GAAE,CAAA,EACnO,CAAA;AAAA,wBACA,GAAA,CAAC,eAAY,IAAA,EAAM,GAAA,EAAK,SAAS,EAAA,EAAI,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAU,sBAAA,EAAuB;AAAA,OAAA,EACrF,CAAA;AAAA,MACC,KAAK,OAAA,oBAAW,GAAA,CAAC,SAAI,KAAA,EAAM,wBAAA,EAA0B,cAAI,OAAA,EAAQ;AAAA,KAAA,EACpE,CAAA;AAAA,oBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAA,EAA0B,2BAAuB,IAAA,EACzD,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,MAAM,KAAA,qBAAU,GAAA,CAAC,SAAA,EAAA,EAAQ,KAAA,EAAM,uBAAsB,UAAA,EAAU,IAAA,CAAK,GAAA,EAAK,cAAA,EAAc,IAAA,CAAK,GAAA,EAAK,iBAAA,EAAiB,MAAA,CAAO,UAAU,QAAQ,CAAA,EAAG,aAAA,EAAa,MAAA,CAAO,UAAU,QAAQ,CAAA,EAAI,QAAA,EAAA,IAAA,CAAK,OAAA,EAAQ,CAAU,CAAA,EAC7N,CAAA;AAAA,IACC,iCAAiB,GAAA,CAAC,QAAA,EAAA,EAAO,OAAM,uBAAA,EAAwB,uBAAA,EAAqB,MAAE,QAAA,EAAA,aAAA,EAAc;AAAA,GAAA,EAC/F,CAAA;AACF","file":"chunk-N3SUXLLS.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { ToolbarText } from './toolbar-text.js';\n\n/**\n * One entry in a {@link NavStack}. The app owns the stack as an array (usually a\n * signal); `NavStack` renders it and `wireNavStack` animates the transitions.\n */\nexport interface NavStackView {\n /** Stable identity for keyed reconcile and transition direction. */\n key: string;\n content: SafeHtml;\n /** Title shown in the top toolbar for this view. */\n title?: string;\n /** Trailing actions for this view's top toolbar. */\n toolbar?: SafeHtml;\n}\n\nexport interface NavStackProps {\n id: string;\n /** Accessible name for the stack region. */\n label: string;\n /** The stack, root first; the last entry is the active top view. */\n views: NavStackView[];\n /** Accessible label for the back control (default \"Back\"). */\n backLabel?: string;\n /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */\n hideToolbar?: boolean;\n /** Optional persistent bottom toolbar. */\n bottomToolbar?: SafeHtml;\n className?: string;\n}\n\n/**\n * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last\n * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and\n * cross-fades the chrome across a change. A single-pane layout is a `NavStack`\n * with one entry. See `docs/23-app-layouts.md` §3.1.\n */\nexport function NavStack({ id, label, views, backLabel = 'Back', hideToolbar = false, bottomToolbar, className = '' }: NavStackProps) {\n const topIndex = views.length - 1;\n const top = views[topIndex];\n const canPop = views.length > 1;\n return <section class={`kui-nav-stack ${className}`.trim()} id={id} data-component=\"nav-stack\" data-nav-stack-id={id} data-depth={String(views.length)} aria-label={label}>\n {!hideToolbar && <header class=\"kui-nav-stack__chrome\" data-nav-stack-chrome>\n <div class=\"kui-nav-stack__lead\">\n {canPop && <button type=\"button\" class=\"kui-nav-stack__back\" data-nav-back aria-label={backLabel}>\n <svg class=\"kui-nav-stack__back-icon\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m15 18-6-6 6-6\" /></svg>\n </button>}\n <ToolbarText text={top?.title ?? ''} size=\"large\" className=\"kui-nav-stack__title\" />\n </div>\n {top?.toolbar && <div class=\"kui-nav-stack__actions\">{top.toolbar}</div>}\n </header>}\n <div class=\"kui-nav-stack__viewport\" data-nav-stack-viewport>\n {views.map((view, index) => <article class=\"kui-nav-stack__view\" data-key={view.key} data-nav-key={view.key} data-nav-active={String(index === topIndex)} aria-hidden={String(index !== topIndex)}>{view.content}</article>)}\n </div>\n {bottomToolbar && <footer class=\"kui-nav-stack__bottom\" data-nav-stack-bottom>{bottomToolbar}</footer>}\n </section>;\n}\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { Skeleton } from './chunk-B24C4A6T.js';
|
|
1
2
|
import { jsxs, jsx } from 'kerfjs/jsx-runtime';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return /* @__PURE__ */ jsxs("div", { class: `kui-value-table__row ${className}`.trim(), "data-has-icon": String(Boolean(icon)), children: [
|
|
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
6
|
/* @__PURE__ */ jsxs("dt", { children: [
|
|
7
7
|
icon && /* @__PURE__ */ jsx("span", { class: "kui-value-table__icon", children: icon }),
|
|
8
8
|
/* @__PURE__ */ jsx("span", { class: "kui-value-table__label", children: label })
|
|
9
9
|
] }),
|
|
10
|
-
/* @__PURE__ */ jsx("dd", { children: value })
|
|
10
|
+
/* @__PURE__ */ jsx("dd", { children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "10em" }) : value })
|
|
11
11
|
] });
|
|
12
12
|
}
|
|
13
13
|
function ValueTable({ label, className = "", children }) {
|
|
@@ -16,4 +16,4 @@ function ValueTable({ label, className = "", children }) {
|
|
|
16
16
|
|
|
17
17
|
export { ValueTable, ValueTableRow };
|
|
18
18
|
|
|
19
|
-
//# sourceMappingURL=chunk-
|
|
19
|
+
//# sourceMappingURL=chunk-PONXLV5U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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;ACPO,SAAS,WAAW,EAAE,KAAA,EAAO,SAAA,GAAY,EAAA,EAAI,UAAS,EAAoB;AAC/E,EAAA,uBAAOA,GAAAA,CAAC,IAAA,EAAA,EAAG,KAAA,EAAO,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,gBAAA,EAAe,aAAA,EAAc,YAAA,EAAY,OAAQ,QAAA,EAAS,CAAA;AACrH","file":"chunk-PONXLV5U.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\n// Import (not just re-export) so the browser-entry CSS scanner follows the row to\n// its Skeleton dependency, keeping placeholder styles reachable from this subpath.\nimport { ValueTableRow, type ValueTableRowProps } from './value-table-row.js';\n\nexport { ValueTableRow, type ValueTableRowProps };\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"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Toolbar } from './chunk-DAFFDO33.js';
|
|
2
|
+
import { ToolbarControlGroup } from './chunk-MFKMHK5W.js';
|
|
3
|
+
import { ToolbarText } from './chunk-KJYXOTG3.js';
|
|
4
|
+
import { Skeleton } from './chunk-B24C4A6T.js';
|
|
5
|
+
import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName = "", actions, placeholder = false }) {
|
|
8
|
+
const identity = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9
|
+
icon && /* @__PURE__ */ jsx(ToolbarControlGroup, { single: true, className: `kui-panel-header__icon ${iconClassName}`.trim(), children: icon }),
|
|
10
|
+
/* @__PURE__ */ jsx(ToolbarText, { text: title, size: "xlarge", id: titleId, className: "kui-panel-header__title", placeholder })
|
|
11
|
+
] });
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", { class: "kui-panel-header", "data-component": "panel-header", "data-has-icon": String(Boolean(icon)), "data-has-actions": String(Boolean(actions)), "data-has-summary": String(Boolean(summary)), "data-placeholder": placeholder ? "true" : void 0, children: [
|
|
13
|
+
/* @__PURE__ */ jsx(Toolbar, { leading: identity, trailing: actions, divider: false }),
|
|
14
|
+
summary && /* @__PURE__ */ jsx("p", { class: "kui-panel-header__summary", id: summaryId, children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "18em" }) : summary })
|
|
15
|
+
] });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { PanelHeader };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=chunk-TZNCCM5H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/panel-header.tsx"],"names":[],"mappings":";;;;;;AA+BO,SAAS,WAAA,CAAY,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,aAAA,GAAgB,EAAA,EAAI,OAAA,EAAS,WAAA,GAAc,KAAA,EAAM,EAAqB;AAC5I,EAAA,MAAM,2BAAW,IAAA,CAAA,QAAA,EAAA,EACd,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAM,IAAA,EAAC,SAAA,EAAW,0BAA0B,aAAa,CAAA,CAAA,CAAG,IAAA,EAAK,EAAI,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBACxG,GAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK,UAAS,EAAA,EAAI,OAAA,EAAS,SAAA,EAAU,yBAAA,EAA0B,WAAA,EAA0B;AAAA,GAAA,EACrH,CAAA;AAEA,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,kBAAA,EAAmB,gBAAA,EAAe,cAAA,EAAe,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,kBAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA,EAAG,kBAAA,EAAkB,WAAA,GAAc,MAAA,GAAS,MAAA,EACxO,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAQ,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,OAAA,EAAS,SAAS,KAAA,EAAO,CAAA;AAAA,IAC9D,OAAA,oBAAW,GAAA,CAAC,GAAA,EAAA,EAAE,KAAA,EAAM,2BAAA,EAA4B,EAAA,EAAI,SAAA,EAAY,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,MAAA,EAAO,IAAK,OAAA,EAAQ;AAAA,GAAA,EACrH,CAAA;AACF","file":"chunk-TZNCCM5H.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Skeleton } from './skeleton.js';\nimport { Toolbar } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\nimport { ToolbarText } from './toolbar-text.js';\n\nexport interface PanelHeaderProps {\n title: string;\n titleId: string;\n summary?: string;\n summaryId?: string;\n icon?: SafeHtml;\n iconClassName?: string;\n actions?: SafeHtml;\n /** Render the title and summary as unanimated loading skeletons, keeping the icon and actions. */\n placeholder?: boolean;\n}\n\n/**\n * The heading of a panel, dialog, or page: a plain `Toolbar` whose leading zone\n * holds an optional icon control group and the title as extra-large `ToolbarText`,\n * whose trailing zone holds the app's action controls, and with an optional\n * subtitle on its own row, left-aligned with the title.\n *\n * PanelHeader overrides no Toolbar styles — it is just a Toolbar with an xl title.\n * The only styling it adds is the icon group's fill/border color and the subtitle.\n * When no icon is provided, the icon group is omitted entirely. The `actions` slot\n * is passed straight into the toolbar's trailing zone; the app supplies whatever\n * trailing controls it needs (typically a `ToolbarControlGroup`).\n */\nexport function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName = '', actions, placeholder = false }: PanelHeaderProps) {\n const identity = <>\n {icon && <ToolbarControlGroup single className={`kui-panel-header__icon ${iconClassName}`.trim()}>{icon}</ToolbarControlGroup>}\n <ToolbarText text={title} size=\"xlarge\" id={titleId} className=\"kui-panel-header__title\" placeholder={placeholder} />\n </>;\n\n return <div class=\"kui-panel-header\" data-component=\"panel-header\" data-has-icon={String(Boolean(icon))} data-has-actions={String(Boolean(actions))} data-has-summary={String(Boolean(summary))} data-placeholder={placeholder ? 'true' : undefined}>\n <Toolbar leading={identity} trailing={actions} divider={false} />\n {summary && <p class=\"kui-panel-header__summary\" id={summaryId}>{placeholder ? <Skeleton width=\"18em\" /> : summary}</p>}\n </div>;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { Skeleton } from './chunk-B24C4A6T.js';
|
|
1
2
|
import { jsx } from 'kerfjs/jsx-runtime';
|
|
2
3
|
|
|
3
|
-
// src/segmented-control.tsx
|
|
4
4
|
function SegmentedControl({
|
|
5
5
|
id,
|
|
6
6
|
label,
|
|
@@ -11,7 +11,8 @@ function SegmentedControl({
|
|
|
11
11
|
shape = "rounded",
|
|
12
12
|
size = "default",
|
|
13
13
|
layout = "content",
|
|
14
|
-
className = ""
|
|
14
|
+
className = "",
|
|
15
|
+
placeholder = false
|
|
15
16
|
}) {
|
|
16
17
|
return /* @__PURE__ */ jsx(
|
|
17
18
|
"div",
|
|
@@ -24,8 +25,10 @@ function SegmentedControl({
|
|
|
24
25
|
"data-shape": shape,
|
|
25
26
|
"data-size": size,
|
|
26
27
|
"data-layout": layout,
|
|
28
|
+
"data-placeholder": placeholder ? "true" : void 0,
|
|
27
29
|
role: "group",
|
|
28
30
|
"aria-label": label,
|
|
31
|
+
"aria-busy": placeholder ? "true" : void 0,
|
|
29
32
|
children: choices.map((choice) => {
|
|
30
33
|
const selected = choice.value === value;
|
|
31
34
|
return /* @__PURE__ */ jsx(
|
|
@@ -33,15 +36,15 @@ function SegmentedControl({
|
|
|
33
36
|
{
|
|
34
37
|
type: "button",
|
|
35
38
|
class: "kui-segmented-control__item",
|
|
36
|
-
"data-action": action,
|
|
39
|
+
"data-action": placeholder ? void 0 : action,
|
|
37
40
|
"data-segment-value": choice.value,
|
|
38
41
|
"data-selected": String(selected),
|
|
39
42
|
"aria-label": choice.label,
|
|
40
43
|
"aria-pressed": String(selected),
|
|
41
|
-
title: choice.title,
|
|
42
|
-
disabled: choice.disabled,
|
|
43
|
-
tabindex: "0",
|
|
44
|
-
children: choice.content ?? /* @__PURE__ */ jsx("span", { children: choice.label })
|
|
44
|
+
title: placeholder ? void 0 : choice.title,
|
|
45
|
+
disabled: choice.disabled || placeholder,
|
|
46
|
+
tabindex: placeholder ? "-1" : "0",
|
|
47
|
+
children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "4em" }) : choice.content ?? /* @__PURE__ */ jsx("span", { children: choice.label })
|
|
45
48
|
}
|
|
46
49
|
);
|
|
47
50
|
})
|
|
@@ -51,4 +54,4 @@ function SegmentedControl({
|
|
|
51
54
|
|
|
52
55
|
export { SegmentedControl };
|
|
53
56
|
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-YGN7OMLT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/segmented-control.tsx"],"names":[],"mappings":";;;AAgCO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,EAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA,GAAS,gBAAA;AAAA,EACT,UAAA,GAAa,QAAA;AAAA,EACb,KAAA,GAAQ,SAAA;AAAA,EACR,IAAA,GAAO,SAAA;AAAA,EACP,MAAA,GAAS,SAAA;AAAA,EACT,SAAA,GAAY,EAAA;AAAA,EACZ,WAAA,GAAc;AAChB,CAAA,EAA0B;AACxB,EAAA,uBAAO,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACN,KAAA,EAAO,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MACjD,gBAAA,EAAe,mBAAA;AAAA,MACf,2BAAA,EAA2B,EAAA;AAAA,MAC3B,YAAA,EAAY,KAAA;AAAA,MACZ,iBAAA,EAAiB,UAAA;AAAA,MACjB,YAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAa,MAAA;AAAA,MACb,kBAAA,EAAkB,cAAc,MAAA,GAAS,MAAA;AAAA,MACzC,IAAA,EAAK,OAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAW,cAAc,MAAA,GAAS,MAAA;AAAA,MAEjC,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AACvB,QAAA,MAAM,QAAA,GAAW,OAAO,KAAA,KAAU,KAAA;AAClC,QAAA,uBAAO,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACN,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,6BAAA;AAAA,YACN,aAAA,EAAa,cAAc,MAAA,GAAY,MAAA;AAAA,YACvC,sBAAoB,MAAA,CAAO,KAAA;AAAA,YAC3B,eAAA,EAAe,OAAO,QAAQ,CAAA;AAAA,YAC9B,cAAY,MAAA,CAAO,KAAA;AAAA,YACnB,cAAA,EAAc,OAAO,QAAQ,CAAA;AAAA,YAC7B,KAAA,EAAO,WAAA,GAAc,MAAA,GAAY,MAAA,CAAO,KAAA;AAAA,YACxC,QAAA,EAAU,OAAO,QAAA,IAAY,WAAA;AAAA,YAC7B,QAAA,EAAU,cAAc,IAAA,GAAO,GAAA;AAAA,YAC/B,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,KAAA,EAAM,CAAA,GAAK,MAAA,CAAO,OAAA,oBAAW,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM;AAAA;AAAA,SAAQ;AAAA,MAC3F,CAAC;AAAA;AAAA,GACH;AACF","file":"chunk-YGN7OMLT.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Skeleton } from './skeleton.js';\n\nexport type SegmentedControlAppearance = 'filled' | 'outlined' | 'toolbar';\nexport type SegmentedControlShape = 'rounded' | 'pill';\nexport type SegmentedControlSize = 'small' | 'default';\nexport type SegmentedControlLayout = 'content' | 'equal';\n\nexport interface SegmentedControlChoice {\n value: string;\n label: string;\n content?: SafeHtml;\n title?: string;\n disabled?: boolean;\n}\n\nexport interface SegmentedControlProps {\n id: string;\n label: string;\n value: string;\n choices: readonly SegmentedControlChoice[];\n action?: string;\n appearance?: SegmentedControlAppearance;\n shape?: SegmentedControlShape;\n size?: SegmentedControlSize;\n layout?: SegmentedControlLayout;\n className?: string;\n /** Render as an unanimated loading skeleton, disabling every segment. */\n placeholder?: boolean;\n}\n\nexport function SegmentedControl({\n id,\n label,\n value,\n choices,\n action = 'select-segment',\n appearance = 'filled',\n shape = 'rounded',\n size = 'default',\n layout = 'content',\n className = '',\n placeholder = false,\n}: SegmentedControlProps) {\n return <div\n class={`kui-segmented-control ${className}`.trim()}\n data-component=\"segmented-control\"\n data-segmented-control-id={id}\n data-value={value}\n data-appearance={appearance}\n data-shape={shape}\n data-size={size}\n data-layout={layout}\n data-placeholder={placeholder ? 'true' : undefined}\n role=\"group\"\n aria-label={label}\n aria-busy={placeholder ? 'true' : undefined}\n >\n {choices.map((choice) => {\n const selected = choice.value === value;\n return <button\n type=\"button\"\n class=\"kui-segmented-control__item\"\n data-action={placeholder ? undefined : action}\n data-segment-value={choice.value}\n data-selected={String(selected)}\n aria-label={choice.label}\n aria-pressed={String(selected)}\n title={placeholder ? undefined : choice.title}\n disabled={choice.disabled || placeholder}\n tabindex={placeholder ? '-1' : '0'}\n >{placeholder ? <Skeleton width=\"4em\" /> : choice.content ?? <span>{choice.label}</span>}</button>;\n })}\n </div>;\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
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-item-id",
|
|
9
|
+
"data-has-icon",
|
|
10
|
+
"data-multiline",
|
|
11
|
+
"data-state"
|
|
12
|
+
]);
|
|
13
|
+
function MenuItem({ label, icon, trailing, selected = false, action, itemId, className = "", style, pressed, accessibleLabel, title, multiline = false, state, disabled = false, tabIndex, placeholder = false, rootAttributes = {} }) {
|
|
14
|
+
const extensionAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);
|
|
15
|
+
return /* @__PURE__ */ jsxs("button", { ...extensionAttributes, type: "button", class: `kui-menu-item ${className}`.trim(), style, title: placeholder ? void 0 : title, disabled: disabled || placeholder, tabindex: placeholder ? -1 : tabIndex, "data-component": "menu-item", "data-action": placeholder ? void 0 : action, "data-item-id": itemId, "data-has-icon": String(Boolean(icon)), "data-multiline": multiline ? "true" : void 0, "data-state": state, "data-placeholder": placeholder ? "true" : void 0, "aria-label": accessibleLabel, "aria-current": selected ? "page" : void 0, "aria-pressed": pressed === void 0 ? void 0 : String(pressed), "aria-busy": placeholder ? "true" : void 0, children: [
|
|
16
|
+
icon && /* @__PURE__ */ jsx("span", { class: "kui-menu-item__icon", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "1em", height: "1em" }) : icon }),
|
|
17
|
+
/* @__PURE__ */ jsx("span", { class: "kui-menu-item__label", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "9em" }) : label }),
|
|
18
|
+
trailing && /* @__PURE__ */ jsx("span", { class: "kui-menu-item__trailing", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: "2.5em" }) : trailing })
|
|
19
|
+
] });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { MenuItem };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=chunk-YKUUZPED.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/menu-item.tsx"],"names":[],"mappings":";;;;AAKA,IAAM,8BAAA,uBAAqC,GAAA,CAAI;AAAA,EAC7C,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAkCM,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,QAAA,GAAW,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,SAAA,GAAY,EAAA,EAAI,KAAA,EAAO,OAAA,EAAS,iBAAiB,KAAA,EAAO,SAAA,GAAY,KAAA,EAAO,KAAA,EAAO,QAAA,GAAW,KAAA,EAAO,QAAA,EAAU,WAAA,GAAc,KAAA,EAAO,cAAA,GAAiB,EAAC,EAAE,EAAkB;AAC3P,EAAA,MAAM,mBAAA,GAAsB,oBAAA,CAAqB,cAAA,EAAgB,8BAA8B,CAAA;AAC/F,EAAA,uBAAO,IAAA,CAAC,QAAA,EAAA,EAAQ,GAAG,mBAAA,EAAqB,IAAA,EAAK,QAAA,EAAS,KAAA,EAAO,CAAA,cAAA,EAAiB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,OAAc,KAAA,EAAO,WAAA,GAAc,MAAA,GAAY,KAAA,EAAO,QAAA,EAAU,QAAA,IAAY,WAAA,EAAa,QAAA,EAAU,WAAA,GAAc,EAAA,GAAK,QAAA,EAAU,gBAAA,EAAe,WAAA,EAAY,aAAA,EAAa,WAAA,GAAc,MAAA,GAAY,QAAQ,cAAA,EAAc,MAAA,EAAQ,eAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA,EAAG,gBAAA,EAAgB,SAAA,GAAY,MAAA,GAAS,MAAA,EAAW,YAAA,EAAY,KAAA,EAAO,kBAAA,EAAkB,WAAA,GAAc,SAAS,MAAA,EAAW,YAAA,EAAY,eAAA,EAAiB,cAAA,EAAc,QAAA,GAAW,MAAA,GAAS,MAAA,EAAW,cAAA,EAAc,OAAA,KAAY,MAAA,GAAY,MAAA,GAAY,MAAA,CAAO,OAAO,CAAA,EAAG,WAAA,EAAW,WAAA,GAAc,SAAS,MAAA,EAC3oB,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,qBAAA,EAAuB,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,KAAA,EAAM,MAAA,EAAO,KAAA,EAAM,CAAA,GAAK,IAAA,EAAK,CAAA;AAAA,oBACvG,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,sBAAA,EAAwB,QAAA,EAAA,WAAA,uBAAe,QAAA,EAAA,EAAS,KAAA,EAAM,KAAA,EAAM,CAAA,GAAK,KAAA,EAAM,CAAA;AAAA,IAClF,QAAA,oBAAY,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,yBAAA,EAA2B,QAAA,EAAA,WAAA,mBAAc,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,OAAA,EAAQ,CAAA,GAAK,QAAA,EAAS;AAAA,GAAA,EAC1G,CAAA;AACF","file":"chunk-YKUUZPED.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-item-id',\n 'data-has-icon',\n 'data-multiline',\n 'data-state',\n]);\n\ntype MenuItemRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-has-icon'?: never;\n 'data-multiline'?: never;\n 'data-state'?: never;\n }\n>;\n\nexport interface MenuItemProps {\n label: string | SafeHtml;\n icon?: SafeHtml;\n trailing?: SafeHtml;\n selected?: boolean;\n action: string;\n itemId?: string;\n className?: string;\n style?: string;\n pressed?: boolean;\n accessibleLabel?: string;\n title?: string;\n multiline?: boolean;\n state?: string;\n disabled?: boolean;\n tabIndex?: number;\n /** Render the row as an unanimated loading skeleton, disabling its action. */\n placeholder?: boolean;\n rootAttributes?: MenuItemRootAttributes;\n}\n\nexport function MenuItem({ label, icon, trailing, selected = false, action, itemId, className = '', style, pressed, accessibleLabel, title, multiline = false, state, disabled = false, tabIndex, placeholder = false, rootAttributes = {} }: MenuItemProps) {\n const extensionAttributes = filterDataAttributes(rootAttributes, PROTECTED_ROOT_DATA_ATTRIBUTES);\n return <button {...extensionAttributes} type=\"button\" class={`kui-menu-item ${className}`.trim()} style={style} title={placeholder ? undefined : title} disabled={disabled || placeholder} tabindex={placeholder ? -1 : tabIndex} data-component=\"menu-item\" data-action={placeholder ? undefined : action} data-item-id={itemId} data-has-icon={String(Boolean(icon))} data-multiline={multiline ? 'true' : undefined} data-state={state} data-placeholder={placeholder ? 'true' : undefined} aria-label={accessibleLabel} aria-current={selected ? 'page' : undefined} aria-pressed={pressed === undefined ? undefined : String(pressed)} aria-busy={placeholder ? 'true' : undefined}>\n {icon && <span class=\"kui-menu-item__icon\">{placeholder ? <Skeleton width=\"1em\" height=\"1em\" /> : icon}</span>}\n <span class=\"kui-menu-item__label\">{placeholder ? <Skeleton width=\"9em\" /> : label}</span>\n {trailing && <span class=\"kui-menu-item__trailing\">{placeholder ? <Skeleton width=\"2.5em\" /> : trailing}</span>}\n </button>;\n}\n"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ReadonlySignal } from 'kerfjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Reactive device-class detection for `@kerfjs/ui` (see `docs/23-app-layouts.md`
|
|
5
|
+
* §2). `deviceClass()` returns a `ReadonlySignal<DeviceClass>` describing the
|
|
6
|
+
* current viewport as a size bucket × orientation × viewport-segment count, so a
|
|
7
|
+
* layout can pick its presentation reactively instead of hand-wiring `matchMedia`.
|
|
8
|
+
*
|
|
9
|
+
* One shared viewport source backs every reader; the pure `classifyViewport`
|
|
10
|
+
* core is DOM-free and directly unit-tested.
|
|
11
|
+
*/
|
|
12
|
+
type DeviceSize = 'xs-mobile' | 'mobile' | 'tablet' | 'desktop' | 'xl-desktop';
|
|
13
|
+
type DeviceOrientation = 'portrait' | 'landscape';
|
|
14
|
+
/** Minimum widths (px) at which each larger bucket begins. `xs-mobile` is 0. */
|
|
15
|
+
interface DeviceBreakpoints {
|
|
16
|
+
mobile: number;
|
|
17
|
+
tablet: number;
|
|
18
|
+
desktop: number;
|
|
19
|
+
'xl-desktop': number;
|
|
20
|
+
}
|
|
21
|
+
interface DeviceClass {
|
|
22
|
+
size: DeviceSize;
|
|
23
|
+
orientation: DeviceOrientation;
|
|
24
|
+
/** Horizontal viewport segments (foldables / dual-screen); 1 on ordinary devices. */
|
|
25
|
+
segments: number;
|
|
26
|
+
/** Vertical viewport segments; 1 on ordinary devices. */
|
|
27
|
+
verticalSegments: number;
|
|
28
|
+
/** Small phones — `xs-mobile` or `mobile`. */
|
|
29
|
+
handset: boolean;
|
|
30
|
+
/** "One pane at a time" — a handset or a portrait tablet. */
|
|
31
|
+
compact: boolean;
|
|
32
|
+
/** True when the current size is `size` or larger, e.g. `atLeast('tablet')`. */
|
|
33
|
+
atLeast(size: DeviceSize): boolean;
|
|
34
|
+
}
|
|
35
|
+
/** A raw viewport snapshot, before breakpoints are applied. */
|
|
36
|
+
interface Viewport {
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
segments: number;
|
|
40
|
+
verticalSegments: number;
|
|
41
|
+
}
|
|
42
|
+
interface DeviceClassOptions {
|
|
43
|
+
/** Override any of the default bucket thresholds. */
|
|
44
|
+
breakpoints?: Partial<DeviceBreakpoints>;
|
|
45
|
+
/** The viewport assumed when there is no DOM (SSR). Defaults to 1024×768, one segment. */
|
|
46
|
+
ssr?: Partial<Viewport>;
|
|
47
|
+
}
|
|
48
|
+
declare const DEFAULT_BREAKPOINTS: DeviceBreakpoints;
|
|
49
|
+
/**
|
|
50
|
+
* Classify a raw viewport into a {@link DeviceClass}. Pure and DOM-free — the
|
|
51
|
+
* single source of truth for the bucketing rules.
|
|
52
|
+
*/
|
|
53
|
+
declare function classifyViewport(width: number, orientation: DeviceOrientation, segments?: number, verticalSegments?: number, breakpoints?: DeviceBreakpoints): DeviceClass;
|
|
54
|
+
/**
|
|
55
|
+
* A reactive signal of the current {@link DeviceClass}. Reading it inside an
|
|
56
|
+
* `effect`/`computed` re-runs when the viewport crosses a breakpoint, rotates,
|
|
57
|
+
* or changes its segment count. Without a DOM it resolves to `options.ssr`
|
|
58
|
+
* (default 1024×768, landscape, one segment).
|
|
59
|
+
*/
|
|
60
|
+
declare function deviceClass(options?: DeviceClassOptions): ReadonlySignal<DeviceClass>;
|
|
61
|
+
|
|
62
|
+
export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type DeviceClassOptions, type DeviceOrientation, type DeviceSize, type Viewport, classifyViewport, deviceClass };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { computed, signal } from 'kerfjs';
|
|
2
|
+
|
|
3
|
+
// src/device-class.ts
|
|
4
|
+
var DEFAULT_BREAKPOINTS = {
|
|
5
|
+
mobile: 360,
|
|
6
|
+
tablet: 720,
|
|
7
|
+
desktop: 1024,
|
|
8
|
+
"xl-desktop": 1440
|
|
9
|
+
};
|
|
10
|
+
var SIZE_ORDER = ["xs-mobile", "mobile", "tablet", "desktop", "xl-desktop"];
|
|
11
|
+
var SSR_VIEWPORT = { width: 1024, height: 768, segments: 1, verticalSegments: 1 };
|
|
12
|
+
function classifyViewport(width, orientation, segments = 1, verticalSegments = 1, breakpoints = DEFAULT_BREAKPOINTS) {
|
|
13
|
+
const size = width >= breakpoints["xl-desktop"] ? "xl-desktop" : width >= breakpoints.desktop ? "desktop" : width >= breakpoints.tablet ? "tablet" : width >= breakpoints.mobile ? "mobile" : "xs-mobile";
|
|
14
|
+
const rank = SIZE_ORDER.indexOf(size);
|
|
15
|
+
return {
|
|
16
|
+
size,
|
|
17
|
+
orientation,
|
|
18
|
+
segments,
|
|
19
|
+
verticalSegments,
|
|
20
|
+
handset: rank <= 1,
|
|
21
|
+
compact: rank <= 1 || size === "tablet" && orientation === "portrait",
|
|
22
|
+
atLeast: (target) => rank >= SIZE_ORDER.indexOf(target)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function countSegments(axis, view) {
|
|
26
|
+
const mq = view.matchMedia;
|
|
27
|
+
if (typeof mq !== "function") return 1;
|
|
28
|
+
for (let n = 4; n >= 2; n--) {
|
|
29
|
+
if (mq.call(view, `(${axis}-viewport-segments: ${n})`).matches) return n;
|
|
30
|
+
}
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
function readViewport(view) {
|
|
34
|
+
return {
|
|
35
|
+
width: view.innerWidth,
|
|
36
|
+
height: view.innerHeight,
|
|
37
|
+
segments: countSegments("horizontal", view),
|
|
38
|
+
verticalSegments: countSegments("vertical", view)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function browserWindow() {
|
|
42
|
+
return typeof window === "undefined" ? void 0 : window;
|
|
43
|
+
}
|
|
44
|
+
var sharedSource;
|
|
45
|
+
function viewportSource(view) {
|
|
46
|
+
if (sharedSource) return sharedSource;
|
|
47
|
+
const source = signal(readViewport(view));
|
|
48
|
+
sharedSource = source;
|
|
49
|
+
const update = () => {
|
|
50
|
+
source.value = readViewport(view);
|
|
51
|
+
};
|
|
52
|
+
view.addEventListener("resize", update);
|
|
53
|
+
view.addEventListener("orientationchange", update);
|
|
54
|
+
return source;
|
|
55
|
+
}
|
|
56
|
+
function orientationOf(view) {
|
|
57
|
+
return view.height > view.width ? "portrait" : "landscape";
|
|
58
|
+
}
|
|
59
|
+
function deviceClass(options = {}) {
|
|
60
|
+
const breakpoints = { ...DEFAULT_BREAKPOINTS, ...options.breakpoints };
|
|
61
|
+
const view = browserWindow();
|
|
62
|
+
if (!view) {
|
|
63
|
+
const snapshot = { ...SSR_VIEWPORT, ...options.ssr };
|
|
64
|
+
return computed(() => classifyViewport(snapshot.width, orientationOf(snapshot), snapshot.segments, snapshot.verticalSegments, breakpoints));
|
|
65
|
+
}
|
|
66
|
+
const source = viewportSource(view);
|
|
67
|
+
return computed(() => {
|
|
68
|
+
const v = source.value;
|
|
69
|
+
return classifyViewport(v.width, orientationOf(v), v.segments, v.verticalSegments, breakpoints);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { DEFAULT_BREAKPOINTS, classifyViewport, deviceClass };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=device-class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/device-class.ts"],"names":[],"mappings":"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","file":"device-class.js","sourcesContent":["import { computed, type ReadonlySignal, signal } from 'kerfjs';\n\n/**\n * Reactive device-class detection for `@kerfjs/ui` (see `docs/23-app-layouts.md`\n * §2). `deviceClass()` returns a `ReadonlySignal<DeviceClass>` describing the\n * current viewport as a size bucket × orientation × viewport-segment count, so a\n * layout can pick its presentation reactively instead of hand-wiring `matchMedia`.\n *\n * One shared viewport source backs every reader; the pure `classifyViewport`\n * core is DOM-free and directly unit-tested.\n */\n\nexport type DeviceSize = 'xs-mobile' | 'mobile' | 'tablet' | 'desktop' | 'xl-desktop';\nexport type DeviceOrientation = 'portrait' | 'landscape';\n\n/** Minimum widths (px) at which each larger bucket begins. `xs-mobile` is 0. */\nexport interface DeviceBreakpoints {\n mobile: number;\n tablet: number;\n desktop: number;\n 'xl-desktop': number;\n}\n\nexport interface DeviceClass {\n size: DeviceSize;\n orientation: DeviceOrientation;\n /** Horizontal viewport segments (foldables / dual-screen); 1 on ordinary devices. */\n segments: number;\n /** Vertical viewport segments; 1 on ordinary devices. */\n verticalSegments: number;\n /** Small phones — `xs-mobile` or `mobile`. */\n handset: boolean;\n /** \"One pane at a time\" — a handset or a portrait tablet. */\n compact: boolean;\n /** True when the current size is `size` or larger, e.g. `atLeast('tablet')`. */\n atLeast(size: DeviceSize): boolean;\n}\n\n/** A raw viewport snapshot, before breakpoints are applied. */\nexport interface Viewport {\n width: number;\n height: number;\n segments: number;\n verticalSegments: number;\n}\n\nexport interface DeviceClassOptions {\n /** Override any of the default bucket thresholds. */\n breakpoints?: Partial<DeviceBreakpoints>;\n /** The viewport assumed when there is no DOM (SSR). Defaults to 1024×768, one segment. */\n ssr?: Partial<Viewport>;\n}\n\nexport const DEFAULT_BREAKPOINTS: DeviceBreakpoints = {\n mobile: 360,\n tablet: 720,\n desktop: 1024,\n 'xl-desktop': 1440,\n};\n\nconst SIZE_ORDER: readonly DeviceSize[] = ['xs-mobile', 'mobile', 'tablet', 'desktop', 'xl-desktop'];\n\nconst SSR_VIEWPORT: Viewport = { width: 1024, height: 768, segments: 1, verticalSegments: 1 };\n\n/**\n * Classify a raw viewport into a {@link DeviceClass}. Pure and DOM-free — the\n * single source of truth for the bucketing rules.\n */\nexport function classifyViewport(\n width: number,\n orientation: DeviceOrientation,\n segments = 1,\n verticalSegments = 1,\n breakpoints: DeviceBreakpoints = DEFAULT_BREAKPOINTS,\n): DeviceClass {\n const size: DeviceSize =\n width >= breakpoints['xl-desktop']\n ? 'xl-desktop'\n : width >= breakpoints.desktop\n ? 'desktop'\n : width >= breakpoints.tablet\n ? 'tablet'\n : width >= breakpoints.mobile\n ? 'mobile'\n : 'xs-mobile';\n const rank = SIZE_ORDER.indexOf(size);\n return {\n size,\n orientation,\n segments,\n verticalSegments,\n handset: rank <= 1,\n compact: rank <= 1 || (size === 'tablet' && orientation === 'portrait'),\n atLeast: (target) => rank >= SIZE_ORDER.indexOf(target),\n };\n}\n\n/** Count viewport segments along one axis, feature-detecting the media query. */\nfunction countSegments(axis: 'horizontal' | 'vertical', view: Window): number {\n const mq = view.matchMedia;\n if (typeof mq !== 'function') return 1;\n for (let n = 4; n >= 2; n--) {\n if (mq.call(view, `(${axis}-viewport-segments: ${n})`).matches) return n;\n }\n return 1;\n}\n\n/** Read the current viewport from a browser window. */\nfunction readViewport(view: Window): Viewport {\n return {\n width: view.innerWidth,\n height: view.innerHeight,\n segments: countSegments('horizontal', view),\n verticalSegments: countSegments('vertical', view),\n };\n}\n\n/** The browser window, or `undefined` when running without a DOM (SSR). */\nfunction browserWindow(): Window | undefined {\n return typeof window === 'undefined' ? undefined : window;\n}\n\nlet sharedSource: ReturnType<typeof signal<Viewport>> | undefined;\n\n/**\n * The shared reactive viewport source. Installed lazily on first read and kept\n * for the life of the page — there is only ever one viewport, so a single\n * listener set backs every `deviceClass()` reader.\n */\nfunction viewportSource(view: Window): ReturnType<typeof signal<Viewport>> {\n if (sharedSource) return sharedSource;\n const source = signal(readViewport(view));\n sharedSource = source;\n const update = (): void => {\n source.value = readViewport(view);\n };\n view.addEventListener('resize', update);\n view.addEventListener('orientationchange', update);\n return source;\n}\n\nfunction orientationOf(view: Viewport): DeviceOrientation {\n return view.height > view.width ? 'portrait' : 'landscape';\n}\n\n/**\n * A reactive signal of the current {@link DeviceClass}. Reading it inside an\n * `effect`/`computed` re-runs when the viewport crosses a breakpoint, rotates,\n * or changes its segment count. Without a DOM it resolves to `options.ssr`\n * (default 1024×768, landscape, one segment).\n */\nexport function deviceClass(options: DeviceClassOptions = {}): ReadonlySignal<DeviceClass> {\n const breakpoints: DeviceBreakpoints = { ...DEFAULT_BREAKPOINTS, ...options.breakpoints };\n const view = browserWindow();\n if (!view) {\n const snapshot: Viewport = { ...SSR_VIEWPORT, ...options.ssr };\n return computed(() => classifyViewport(snapshot.width, orientationOf(snapshot), snapshot.segments, snapshot.verticalSegments, breakpoints));\n }\n const source = viewportSource(view);\n return computed(() => {\n const v = source.value;\n return classifyViewport(v.width, orientationOf(v), v.segments, v.verticalSegments, breakpoints);\n });\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { AppTab, AppTabProps } from './app-tab.js';
|
|
2
|
-
export { DialogHeader, DialogHeaderProps } from './dialog-header.js';
|
|
3
2
|
export { DisclosureArrow, DisclosureArrowProps, DisclosureDirection } from './disclosure-arrow.js';
|
|
4
3
|
export { EmptyState, EmptyStateProps } from './empty-state.js';
|
|
5
4
|
export { LoadingSpinner, LoadingSpinnerProps } from './loading-spinner.js';
|
|
@@ -7,10 +6,11 @@ export { LucideIcon, LucideIconProps, LucideNode } from './lucide-icon.js';
|
|
|
7
6
|
export { MenuActionRow, MenuActionRowProps } from './menu-action-row.js';
|
|
8
7
|
export { MenuHeader, MenuHeaderProps } from './menu-header.js';
|
|
9
8
|
export { MenuItem, MenuItemProps } from './menu-item.js';
|
|
10
|
-
export {
|
|
9
|
+
export { PanelHeader, PanelHeaderProps } from './panel-header.js';
|
|
11
10
|
export { ResizableRegion, ResizableRegionAxis, ResizableRegionEdge, ResizableRegionProps, clampRegionSize, resizeRegionFromPointer } from './resizable-region.js';
|
|
12
11
|
export { SegmentedControl, SegmentedControlAppearance, SegmentedControlChoice, SegmentedControlLayout, SegmentedControlProps, SegmentedControlShape, SegmentedControlSize } from './segmented-control.js';
|
|
13
12
|
export { Select, SelectChoice, SelectProps } from './select.js';
|
|
13
|
+
export { Skeleton, SkeletonProps } from './skeleton.js';
|
|
14
14
|
export { StateBanner, StateBannerProps, StateBannerTone } from './state-banner.js';
|
|
15
15
|
export { TabBar, TabBarProps } from './tab-bar.js';
|
|
16
16
|
export { TokenSearchField, TokenSearchFieldProps, TokenSearchFieldValue, TokenSearchToken, placeTokenSearchCaret, readTokenSearchField } from './token-search-field.js';
|
|
@@ -20,6 +20,6 @@ export { ToolbarText, ToolbarTextProps, ToolbarTextSize } from './toolbar-text.j
|
|
|
20
20
|
export { ValueTable, ValueTableProps, ValueTableRow, ValueTableRowProps } from './value-table.js';
|
|
21
21
|
export { ResizeCommit, WireResizableRegionsOptions, wireResizableRegions } from './wire-resizable-regions.js';
|
|
22
22
|
export { TabDropPosition, TabReorder, TabReorderSource, WireTabBarsOptions, reorderTabs, wireTabBars } from './wire-tab-bars.js';
|
|
23
|
-
export { TokenSearchSubmit, WireTokenSearchFieldsOptions, wireTokenSearchFields } from './wire-token-search-fields.js';
|
|
23
|
+
export { TokenSearchCollapsibleOptions, TokenSearchFieldsHandle, TokenSearchSubmit, WireTokenSearchFieldsOptions, wireTokenSearchFields } from './wire-token-search-fields.js';
|
|
24
24
|
import 'kerfjs';
|
|
25
25
|
import 'lucide';
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
+
export { ValueTable, ValueTableRow } from './chunk-PONXLV5U.js';
|
|
2
|
+
export { wireResizableRegions } from './chunk-AQNKJRFH.js';
|
|
1
3
|
export { reorderTabs, wireTabBars } from './chunk-MQIZAD4A.js';
|
|
2
|
-
export { wireTokenSearchFields } from './chunk-
|
|
4
|
+
export { wireTokenSearchFields } from './chunk-2RJBFNB6.js';
|
|
5
|
+
export { StateBanner } from './chunk-I7INRJO4.js';
|
|
3
6
|
export { TabBar } from './chunk-MBR3TYNL.js';
|
|
4
7
|
export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-7LDCTU7D.js';
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export { MenuHeader } from './chunk-NPPD2A6O.js';
|
|
9
|
-
export { MenuItem } from './chunk-S3TPM2LP.js';
|
|
10
|
-
export { PageHeader } from './chunk-2PES33HS.js';
|
|
11
|
-
export { ResizableRegion, clampRegionSize, resizeRegionFromPointer } from './chunk-M5JRI6MN.js';
|
|
12
|
-
export { SegmentedControl } from './chunk-TRNBHPNW.js';
|
|
13
|
-
export { Select } from './chunk-CTQKI2XL.js';
|
|
14
|
-
export { StateBanner } from './chunk-VHW5YNIB.js';
|
|
15
|
-
export { AppTab } from './chunk-XZXRLY5Q.js';
|
|
16
|
-
export { DialogHeader } from './chunk-K3G72I6D.js';
|
|
17
|
-
export { ToolbarControlGroup } from './chunk-MFKMHK5W.js';
|
|
8
|
+
export { MenuHeader } from './chunk-H6URQGJI.js';
|
|
9
|
+
export { MenuItem } from './chunk-YKUUZPED.js';
|
|
10
|
+
export { PanelHeader } from './chunk-TZNCCM5H.js';
|
|
18
11
|
export { Toolbar } from './chunk-DAFFDO33.js';
|
|
12
|
+
export { ToolbarControlGroup } from './chunk-MFKMHK5W.js';
|
|
13
|
+
export { ToolbarText } from './chunk-KJYXOTG3.js';
|
|
14
|
+
export { ResizableRegion, clampRegionSize, resizeRegionFromPointer } from './chunk-M5JRI6MN.js';
|
|
15
|
+
export { SegmentedControl } from './chunk-YGN7OMLT.js';
|
|
16
|
+
export { Select } from './chunk-LC3YSAZC.js';
|
|
17
|
+
export { AppTab } from './chunk-2Z5TWHKQ.js';
|
|
19
18
|
export { DisclosureArrow } from './chunk-56RJXPHG.js';
|
|
20
19
|
export { EmptyState } from './chunk-WVPYVDXY.js';
|
|
21
20
|
export { LoadingSpinner } from './chunk-55DATV3A.js';
|
|
22
21
|
export { LucideIcon } from './chunk-W2FK7ZNY.js';
|
|
23
|
-
export { MenuActionRow } from './chunk-
|
|
22
|
+
export { MenuActionRow } from './chunk-3YD6ZNRA.js';
|
|
24
23
|
|
|
24
|
+
export { Skeleton } from './chunk-B24C4A6T.js';
|
|
25
25
|
|
|
26
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -34,6 +34,8 @@ interface MenuActionRowProps {
|
|
|
34
34
|
state?: string;
|
|
35
35
|
disabled?: boolean;
|
|
36
36
|
tabIndex?: number;
|
|
37
|
+
/** Render as an unanimated loading skeleton, disabling both actions. */
|
|
38
|
+
placeholder?: boolean;
|
|
37
39
|
trailingAction: string;
|
|
38
40
|
trailingActionLabel: string;
|
|
39
41
|
/** Decorative dormant content for the trailing button. Must not contain interactive descendants. */
|
|
@@ -45,6 +47,6 @@ interface MenuActionRowProps {
|
|
|
45
47
|
rootAttributes?: MenuActionRowRootAttributes;
|
|
46
48
|
trailingActionAttributes?: MenuActionRowTrailingAttributes;
|
|
47
49
|
}
|
|
48
|
-
declare function MenuActionRow({ label, icon, action, itemId, selected, pressed, accessibleLabel, title, multiline, state, disabled, tabIndex, trailingAction, trailingActionLabel, trailingActionIcon, trailingActionDisabled, trailingActionTitle, className, style, rootAttributes, trailingActionAttributes }: MenuActionRowProps): SafeHtml;
|
|
50
|
+
declare function MenuActionRow({ label, icon, action, itemId, selected, pressed, accessibleLabel, title, multiline, state, disabled, tabIndex, placeholder, trailingAction, trailingActionLabel, trailingActionIcon, trailingActionDisabled, trailingActionTitle, className, style, rootAttributes, trailingActionAttributes }: MenuActionRowProps): SafeHtml;
|
|
49
51
|
|
|
50
52
|
export { MenuActionRow, type MenuActionRowProps };
|
package/dist/menu-action-row.js
CHANGED
package/dist/menu-header.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ interface MenuHeaderBaseProps {
|
|
|
23
23
|
disabledReason?: string;
|
|
24
24
|
expanded?: boolean;
|
|
25
25
|
toggle?: boolean;
|
|
26
|
+
/** Render as an unanimated loading skeleton: keep the label and action affordance, disable interaction. */
|
|
27
|
+
placeholder?: boolean;
|
|
26
28
|
rootAttributes?: MenuHeaderRootAttributes;
|
|
27
29
|
triggerAttributes?: MenuHeaderTriggerAttributes;
|
|
28
30
|
}
|
|
@@ -36,6 +38,6 @@ type MenuHeaderIndicatorProps = {
|
|
|
36
38
|
badge?: SafeHtml;
|
|
37
39
|
};
|
|
38
40
|
type MenuHeaderProps = MenuHeaderBaseProps & MenuHeaderIndicatorProps;
|
|
39
|
-
declare function MenuHeader({ label, count, countLabel, badge, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, rootAttributes, triggerAttributes }: MenuHeaderProps): SafeHtml;
|
|
41
|
+
declare function MenuHeader({ label, count, countLabel, badge, action, actionLabel, actionIcon, actionDisabled, disabledReason, expanded, toggle, placeholder, rootAttributes, triggerAttributes }: MenuHeaderProps): SafeHtml;
|
|
40
42
|
|
|
41
43
|
export { MenuHeader, type MenuHeaderProps };
|
package/dist/menu-header.js
CHANGED
package/dist/menu-item.d.ts
CHANGED
|
@@ -24,8 +24,10 @@ interface MenuItemProps {
|
|
|
24
24
|
state?: string;
|
|
25
25
|
disabled?: boolean;
|
|
26
26
|
tabIndex?: number;
|
|
27
|
+
/** Render the row as an unanimated loading skeleton, disabling its action. */
|
|
28
|
+
placeholder?: boolean;
|
|
27
29
|
rootAttributes?: MenuItemRootAttributes;
|
|
28
30
|
}
|
|
29
|
-
declare function MenuItem({ label, icon, trailing, selected, action, itemId, className, style, pressed, accessibleLabel, title, multiline, state, disabled, tabIndex, rootAttributes }: MenuItemProps): SafeHtml;
|
|
31
|
+
declare function MenuItem({ label, icon, trailing, selected, action, itemId, className, style, pressed, accessibleLabel, title, multiline, state, disabled, tabIndex, placeholder, rootAttributes }: MenuItemProps): SafeHtml;
|
|
30
32
|
|
|
31
33
|
export { MenuItem, type MenuItemProps };
|
package/dist/menu-item.js
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SafeHtml } from 'kerfjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One entry in a {@link NavStack}. The app owns the stack as an array (usually a
|
|
5
|
+
* signal); `NavStack` renders it and `wireNavStack` animates the transitions.
|
|
6
|
+
*/
|
|
7
|
+
interface NavStackView {
|
|
8
|
+
/** Stable identity for keyed reconcile and transition direction. */
|
|
9
|
+
key: string;
|
|
10
|
+
content: SafeHtml;
|
|
11
|
+
/** Title shown in the top toolbar for this view. */
|
|
12
|
+
title?: string;
|
|
13
|
+
/** Trailing actions for this view's top toolbar. */
|
|
14
|
+
toolbar?: SafeHtml;
|
|
15
|
+
}
|
|
16
|
+
interface NavStackProps {
|
|
17
|
+
id: string;
|
|
18
|
+
/** Accessible name for the stack region. */
|
|
19
|
+
label: string;
|
|
20
|
+
/** The stack, root first; the last entry is the active top view. */
|
|
21
|
+
views: NavStackView[];
|
|
22
|
+
/** Accessible label for the back control (default "Back"). */
|
|
23
|
+
backLabel?: string;
|
|
24
|
+
/** Hide the top toolbar entirely (rare — a fully custom-chrome view). */
|
|
25
|
+
hideToolbar?: boolean;
|
|
26
|
+
/** Optional persistent bottom toolbar. */
|
|
27
|
+
bottomToolbar?: SafeHtml;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A navigation stack (iOS-style push/pop). Renders every entry stacked, the last
|
|
32
|
+
* one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and
|
|
33
|
+
* cross-fades the chrome across a change. A single-pane layout is a `NavStack`
|
|
34
|
+
* with one entry. See `docs/23-app-layouts.md` §3.1.
|
|
35
|
+
*/
|
|
36
|
+
declare function NavStack({ id, label, views, backLabel, hideToolbar, bottomToolbar, className }: NavStackProps): SafeHtml;
|
|
37
|
+
|
|
38
|
+
export { NavStack, type NavStackProps, type NavStackView };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"nav-stack.js"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SafeHtml } from 'kerfjs';
|
|
2
|
+
|
|
3
|
+
interface PanelHeaderProps {
|
|
4
|
+
title: string;
|
|
5
|
+
titleId: string;
|
|
6
|
+
summary?: string;
|
|
7
|
+
summaryId?: string;
|
|
8
|
+
icon?: SafeHtml;
|
|
9
|
+
iconClassName?: string;
|
|
10
|
+
actions?: SafeHtml;
|
|
11
|
+
/** Render the title and summary as unanimated loading skeletons, keeping the icon and actions. */
|
|
12
|
+
placeholder?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The heading of a panel, dialog, or page: a plain `Toolbar` whose leading zone
|
|
16
|
+
* holds an optional icon control group and the title as extra-large `ToolbarText`,
|
|
17
|
+
* whose trailing zone holds the app's action controls, and with an optional
|
|
18
|
+
* subtitle on its own row, left-aligned with the title.
|
|
19
|
+
*
|
|
20
|
+
* PanelHeader overrides no Toolbar styles — it is just a Toolbar with an xl title.
|
|
21
|
+
* The only styling it adds is the icon group's fill/border color and the subtitle.
|
|
22
|
+
* When no icon is provided, the icon group is omitted entirely. The `actions` slot
|
|
23
|
+
* is passed straight into the toolbar's trailing zone; the app supplies whatever
|
|
24
|
+
* trailing controls it needs (typically a `ToolbarControlGroup`).
|
|
25
|
+
*/
|
|
26
|
+
declare function PanelHeader({ title, titleId, summary, summaryId, icon, iconClassName, actions, placeholder }: PanelHeaderProps): SafeHtml;
|
|
27
|
+
|
|
28
|
+
export { PanelHeader, type PanelHeaderProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"panel-header.js"}
|
|
@@ -22,7 +22,9 @@ interface SegmentedControlProps {
|
|
|
22
22
|
size?: SegmentedControlSize;
|
|
23
23
|
layout?: SegmentedControlLayout;
|
|
24
24
|
className?: string;
|
|
25
|
+
/** Render as an unanimated loading skeleton, disabling every segment. */
|
|
26
|
+
placeholder?: boolean;
|
|
25
27
|
}
|
|
26
|
-
declare function SegmentedControl({ id, label, value, choices, action, appearance, shape, size, layout, className, }: SegmentedControlProps): SafeHtml;
|
|
28
|
+
declare function SegmentedControl({ id, label, value, choices, action, appearance, shape, size, layout, className, placeholder, }: SegmentedControlProps): SafeHtml;
|
|
27
29
|
|
|
28
30
|
export { SegmentedControl, type SegmentedControlAppearance, type SegmentedControlChoice, type SegmentedControlLayout, type SegmentedControlProps, type SegmentedControlShape, type SegmentedControlSize };
|