@k2b/ui 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/browser/content/Calendar.js +12 -5
  2. package/dist/browser/content/Calendar.js.map +1 -1
  3. package/dist/browser/content/DataTable.js +25 -10
  4. package/dist/browser/content/DataTable.js.map +1 -1
  5. package/dist/browser/content/PdfPreview.js +170 -72
  6. package/dist/browser/content/PdfPreview.js.map +1 -1
  7. package/dist/browser/feedback/dialog-core.js +2 -1
  8. package/dist/browser/feedback/dialog-core.js.map +1 -1
  9. package/dist/browser/feedback/prompts.js +20 -6
  10. package/dist/browser/feedback/prompts.js.map +1 -1
  11. package/dist/browser/feedback/toast.js +4 -2
  12. package/dist/browser/feedback/toast.js.map +1 -1
  13. package/dist/browser/inputs/MultiSelectInput.js +258 -174
  14. package/dist/browser/inputs/MultiSelectInput.js.map +1 -1
  15. package/dist/browser/inputs/choice.js +27 -0
  16. package/dist/browser/inputs/choice.js.map +1 -1
  17. package/dist/browser/intl/messages.js +54 -2
  18. package/dist/browser/intl/messages.js.map +1 -1
  19. package/dist/browser/layout/Navigation.js +8 -5
  20. package/dist/browser/layout/Navigation.js.map +1 -1
  21. package/dist/browser/layout/SettingsModal.js +32 -10
  22. package/dist/browser/layout/SettingsModal.js.map +1 -1
  23. package/dist/browser/layout/navigation-model.js +1 -0
  24. package/dist/browser/layout/navigation-model.js.map +1 -1
  25. package/dist/browser/surfaces/Placeholder.js +3 -0
  26. package/dist/browser/surfaces/Placeholder.js.map +1 -1
  27. package/dist/ssr/content/Calendar.js +13 -6
  28. package/dist/ssr/content/Calendar.js.map +1 -1
  29. package/dist/ssr/content/DataTable.js +25 -10
  30. package/dist/ssr/content/DataTable.js.map +1 -1
  31. package/dist/ssr/content/PdfPreview.js +79 -22
  32. package/dist/ssr/content/PdfPreview.js.map +1 -1
  33. package/dist/ssr/feedback/dialog-core.js +2 -1
  34. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  35. package/dist/ssr/feedback/prompts.js +19 -5
  36. package/dist/ssr/feedback/prompts.js.map +1 -1
  37. package/dist/ssr/feedback/toast.js +4 -2
  38. package/dist/ssr/feedback/toast.js.map +1 -1
  39. package/dist/ssr/inputs/MultiSelectInput.js +87 -42
  40. package/dist/ssr/inputs/MultiSelectInput.js.map +1 -1
  41. package/dist/ssr/inputs/choice.js +27 -0
  42. package/dist/ssr/inputs/choice.js.map +1 -1
  43. package/dist/ssr/intl/messages.js +54 -2
  44. package/dist/ssr/intl/messages.js.map +1 -1
  45. package/dist/ssr/layout/Navigation.js +8 -5
  46. package/dist/ssr/layout/Navigation.js.map +1 -1
  47. package/dist/ssr/layout/SettingsModal.js +30 -5
  48. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  49. package/dist/ssr/layout/navigation-model.js +1 -0
  50. package/dist/ssr/layout/navigation-model.js.map +1 -1
  51. package/dist/ssr/surfaces/Placeholder.js +3 -0
  52. package/dist/ssr/surfaces/Placeholder.js.map +1 -1
  53. package/dist/styles.css +1 -1
  54. package/dist/types/content/PdfPreview.d.ts +8 -0
  55. package/dist/types/inputs/choice.d.ts +12 -0
  56. package/dist/types/intl/messages.d.ts +26 -0
  57. package/dist/types/layout/navigation-model.d.ts +5 -0
  58. package/dist/types/surfaces/Placeholder.d.ts +2 -1
  59. package/package.json +2 -1
@@ -1,17 +1,20 @@
1
+ import { memo as _$memo } from "solid-js/web";
1
2
  import { ssr as _$ssr } from "solid-js/web";
2
3
  import { createComponent as _$createComponent } from "solid-js/web";
3
4
  import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
4
5
  import { escape as _$escape } from "solid-js/web";
5
6
  var _tmpl$ = ["<button", " type=\"button\" role=\"tab\"", ">", "<span>", "</span></button>"],
6
7
  _tmpl$2 = ["<i", " aria-hidden=\"true\"></i>"],
7
- _tmpl$3 = ["<button type=\"button\" class=\"k2b-settings__close k2b-icon-button\"", "><i class=\"ti ti-x\" aria-hidden=\"true\"></i></button>"],
8
- _tmpl$4 = ["<div class=\"", "\" role=\"region\"", ">", "<aside class=\"k2b-settings__rail\"><nav class=\"k2b-settings__tabs\"", " role=\"tablist\">", "</nav></aside><div class=\"k2b-settings__content\">", "", "</div></div>"],
8
+ _tmpl$3 = "<i class=\"ti ti-x\" aria-hidden=\"true\"></i>",
9
+ _tmpl$4 = ["<div class=\"", "\" role=\"region\"", ">", "<aside class=\"k2b-settings__rail\"><nav class=\"k2b-settings__tabs\"", " role=\"tablist\" data-scroll-fade-mode=\"both\" data-scroll-fade-axis=\"horizontal\">", "</nav></aside><div class=\"k2b-settings__content\">", "", "</div></div>"],
9
10
  _tmpl$5 = ["<div class=\"k2b-settings__tab-group\" role=\"presentation\"><span class=\"k2b-settings__tab-group-label\" aria-hidden=\"true\">", "</span>", "</div>"],
10
11
  _tmpl$6 = ["<section", " class=\"k2b-settings__body\" role=\"tabpanel\"", " tabindex=\"0\"", "><div class=\"k2b-settings__section\"><div class=\"k2b-settings__section-heading\"><h2>", "</h2>", "</div>", "</div></section>"],
11
12
  _tmpl$7 = ["<p>", "</p>"],
12
13
  _tmpl$8 = ["<footer class=\"k2b-settings__footer\">", "</footer>"];
13
- import { children, createMemo, createSignal, createUniqueId, For, Show } from "solid-js";
14
+ import { children, createEffect, createMemo, createSignal, createUniqueId, For, Show } from "solid-js";
15
+ import { IconButton } from "../actions/Button";
14
16
  import { useUiMessages } from "../intl/messages";
17
+ import { createScrollFade } from "./scroll-fade";
15
18
  import { assertUniqueStableUiIds } from "./stable-id";
16
19
  const SETTINGS_MODAL_TAB = Symbol("SettingsModal.Tab");
17
20
  const SETTINGS_MODAL_GROUP = Symbol("SettingsModal.Group");
@@ -76,10 +79,21 @@ const SettingsModal = props => {
76
79
  });
77
80
  const instanceId = `k2b-settings-${createUniqueId()}`;
78
81
  const tabRefs = new Map();
82
+ let tabList;
83
+ // Narrow surfaces show the categories as one scrolling row; the fade tells that more follow.
84
+ createScrollFade(() => tabList, () => true);
79
85
  const firstTabId = () => tabs()[0]?.props.id ?? "";
80
86
  const [localActiveTab, setLocalActiveTab] = createSignal(props.defaultTab ?? firstTabId());
81
87
  const requestedActiveTabId = () => props.activeTab ?? (localActiveTab() || firstTabId());
82
- const resolvedActiveTabId = () => tabs().some(tab => tab.props.id === requestedActiveTabId()) ? requestedActiveTabId() : firstTabId();
88
+ const resolvedActiveTabId = createMemo(() => tabs().some(tab => tab.props.id === requestedActiveTabId()) ? requestedActiveTabId() : firstTabId());
89
+ // `defaultTab`, `activeTab` and clicks can select a category past the edge of the scrolling row or rail.
90
+ createEffect(() => {
91
+ const id = resolvedActiveTabId();
92
+ queueMicrotask(() => tabRefs.get(id)?.scrollIntoView?.({
93
+ block: "nearest",
94
+ inline: "nearest"
95
+ }));
96
+ });
83
97
  const activeTab = () => tabs().find(tab => tab.props.id === resolvedActiveTabId()) ?? null;
84
98
  const resolvedPanelChildren = children(() => activeTab()?.props.children);
85
99
  const panelChildren = createMemo(() => splitPanelChildren(resolvedPanelChildren()));
@@ -118,7 +132,18 @@ const SettingsModal = props => {
118
132
  return props.onClose;
119
133
  },
120
134
  get children() {
121
- return _$ssr(_tmpl$3, _$ssrAttribute("aria-label", _$escape(props.closeLabel ?? messages().close, true), false));
135
+ return _$createComponent(IconButton, {
136
+ "class": "k2b-settings__close",
137
+ get label() {
138
+ return props.closeLabel ?? messages().close;
139
+ },
140
+ get onClick() {
141
+ return props.onClose;
142
+ },
143
+ get children() {
144
+ return _$ssr(_tmpl$3);
145
+ }
146
+ });
122
147
  }
123
148
  })), _$ssrAttribute("aria-label", _$escape(messages().sectionsLabel({
124
149
  title: props.title
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["layout/SettingsModal.tsx"],"sourcesContent":["import { children, createMemo, createSignal, createUniqueId, For, type JSX, Show } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { assertUniqueStableUiIds } from \"./stable-id\";\n\nconst SETTINGS_MODAL_TAB = Symbol(\"SettingsModal.Tab\");\nconst SETTINGS_MODAL_GROUP = Symbol(\"SettingsModal.Group\");\nconst SETTINGS_MODAL_FOOTER = Symbol(\"SettingsModal.Footer\");\n\nexport type SettingsModalTabTone = \"default\" | \"danger\";\n\nexport type SettingsModalTabProps = {\n id: string;\n title: string;\n description?: string;\n icon?: string;\n tone?: SettingsModalTabTone;\n children: JSX.Element;\n};\n\nexport type SettingsModalGroupProps = {\n title: string;\n children: JSX.Element;\n};\n\nexport type SettingsModalFooterProps = {\n children: JSX.Element;\n};\n\ntype SettingsModalTabDefinition = {\n readonly kind: typeof SETTINGS_MODAL_TAB;\n readonly props: SettingsModalTabProps;\n};\n\ntype SettingsModalGroupDefinition = {\n readonly kind: typeof SETTINGS_MODAL_GROUP;\n readonly props: SettingsModalGroupProps;\n};\n\ntype SettingsModalFooterDefinition = {\n readonly kind: typeof SETTINGS_MODAL_FOOTER;\n readonly props: SettingsModalFooterProps;\n};\n\nexport type SettingsModalProps = {\n /** Accessible name for the settings surface. */\n title: string;\n /** @deprecated Retained for source compatibility; tab descriptions carry the visible context. */\n subtitle?: string;\n /** @deprecated Retained for source compatibility; tab icons identify the rail entries. */\n icon?: string;\n defaultTab?: string;\n activeTab?: string;\n onTabChange?: (id: string) => void;\n onClose?: () => void;\n closeLabel?: string;\n class?: string;\n children: JSX.Element;\n};\n\ntype SettingsModalComponent = ((props: SettingsModalProps) => JSX.Element) & {\n Tab: (props: SettingsModalTabProps) => JSX.Element;\n Group: (props: SettingsModalGroupProps) => JSX.Element;\n Footer: (props: SettingsModalFooterProps) => JSX.Element;\n};\n\nconst isTabDefinition = (value: unknown): value is SettingsModalTabDefinition =>\n !!value && typeof value === \"object\" && (value as { kind?: unknown }).kind === SETTINGS_MODAL_TAB;\n\nconst isGroupDefinition = (value: unknown): value is SettingsModalGroupDefinition =>\n !!value && typeof value === \"object\" && (value as { kind?: unknown }).kind === SETTINGS_MODAL_GROUP;\n\nconst isFooterDefinition = (value: unknown): value is SettingsModalFooterDefinition =>\n !!value && typeof value === \"object\" && (value as { kind?: unknown }).kind === SETTINGS_MODAL_FOOTER;\n\nconst collectTabs = (value: unknown): SettingsModalTabDefinition[] => {\n if (Array.isArray(value)) return value.flatMap(collectTabs);\n if (isGroupDefinition(value)) return collectTabs(value.props.children);\n return isTabDefinition(value) ? [value] : [];\n};\n\nconst collectRailEntries = (value: unknown): (SettingsModalGroupDefinition | SettingsModalTabDefinition)[] => {\n if (Array.isArray(value)) return value.flatMap(collectRailEntries);\n if (isGroupDefinition(value) || isTabDefinition(value)) return [value];\n return [];\n};\n\nconst splitPanelChildren = (value: unknown): { content: JSX.Element[]; footer?: SettingsModalFooterDefinition } => {\n if (Array.isArray(value)) {\n return value.reduce<{ content: JSX.Element[]; footer?: SettingsModalFooterDefinition }>(\n (result, entry) => {\n const next = splitPanelChildren(entry);\n result.content.push(...next.content);\n if (next.footer) result.footer = next.footer;\n return result;\n },\n { content: [] },\n );\n }\n return isFooterDefinition(value) ? { content: [], footer: value } : { content: [value as JSX.Element] };\n};\n\nfunction SettingsModalTab(props: SettingsModalTabProps): JSX.Element {\n return { kind: SETTINGS_MODAL_TAB, props } satisfies SettingsModalTabDefinition as unknown as JSX.Element;\n}\n\nfunction SettingsModalGroup(props: SettingsModalGroupProps): JSX.Element {\n return { kind: SETTINGS_MODAL_GROUP, props } satisfies SettingsModalGroupDefinition as unknown as JSX.Element;\n}\n\nfunction SettingsModalFooter(props: SettingsModalFooterProps): JSX.Element {\n return { kind: SETTINGS_MODAL_FOOTER, props } satisfies SettingsModalFooterDefinition as unknown as JSX.Element;\n}\n\nconst SettingsModal = ((props: SettingsModalProps): JSX.Element => {\n const messages = useUiMessages();\n const resolved = children(() => props.children);\n const railEntries = createMemo(() => collectRailEntries(resolved()));\n const tabs = createMemo(() => {\n const collected = collectTabs(resolved());\n assertUniqueStableUiIds(\n collected.map((tab) => tab.props.id),\n \"SettingsModal.Tab id\",\n );\n return collected;\n });\n const instanceId = `k2b-settings-${createUniqueId()}`;\n const tabRefs = new Map<string, HTMLButtonElement>();\n const firstTabId = () => tabs()[0]?.props.id ?? \"\";\n const [localActiveTab, setLocalActiveTab] = createSignal(props.defaultTab ?? firstTabId());\n const requestedActiveTabId = () => props.activeTab ?? (localActiveTab() || firstTabId());\n const resolvedActiveTabId = () => (tabs().some((tab) => tab.props.id === requestedActiveTabId()) ? requestedActiveTabId() : firstTabId());\n const activeTab = () => tabs().find((tab) => tab.props.id === resolvedActiveTabId()) ?? null;\n const resolvedPanelChildren = children(() => activeTab()?.props.children);\n const panelChildren = createMemo(() => splitPanelChildren(resolvedPanelChildren()));\n\n const selectTab = (id: string) => {\n if (props.activeTab === undefined) setLocalActiveTab(id);\n props.onTabChange?.(id);\n };\n\n const moveTabFocus = (event: KeyboardEvent, currentId: string) => {\n const currentIndex = tabs().findIndex((tab) => tab.props.id === currentId);\n if (currentIndex < 0 || tabs().length === 0) return;\n let nextIndex: number | null = null;\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") nextIndex = (currentIndex + 1) % tabs().length;\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") nextIndex = (currentIndex - 1 + tabs().length) % tabs().length;\n if (event.key === \"Home\") nextIndex = 0;\n if (event.key === \"End\") nextIndex = tabs().length - 1;\n if (nextIndex === null) return;\n event.preventDefault();\n const nextTab = tabs()[nextIndex];\n if (!nextTab) return;\n selectTab(nextTab.props.id);\n tabRefs.get(nextTab.props.id)?.focus();\n };\n\n const tabId = (id: string) => `${instanceId}-tab-${id}`;\n const panelId = (id: string) => `${instanceId}-panel-${id}`;\n\n const TabButton = (tab: SettingsModalTabDefinition): JSX.Element => {\n const active = () => resolvedActiveTabId() === tab.props.id;\n return (\n <button\n ref={(element) => tabRefs.set(tab.props.id, element)}\n id={tabId(tab.props.id)}\n type=\"button\"\n role=\"tab\"\n aria-selected={active()}\n aria-controls={active() ? panelId(tab.props.id) : undefined}\n tabIndex={active() ? 0 : -1}\n data-state={active() ? \"active\" : \"idle\"}\n data-active={active() ? \"true\" : undefined}\n data-tone={tab.props.tone ?? \"default\"}\n onClick={() => selectTab(tab.props.id)}\n onKeyDown={(event) => moveTabFocus(event, tab.props.id)}\n >\n <Show when={tab.props.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>\n <span>{tab.props.title}</span>\n </button>\n );\n };\n\n return (\n <div class={`k2b-settings ${props.class ?? \"\"}`} role=\"region\" aria-label={props.title}>\n <Show when={props.onClose}>\n <button\n type=\"button\"\n class=\"k2b-settings__close k2b-icon-button\"\n aria-label={props.closeLabel ?? messages().close}\n onClick={props.onClose}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n <aside class=\"k2b-settings__rail\">\n <nav class=\"k2b-settings__tabs\" aria-label={messages().sectionsLabel({ title: props.title })} role=\"tablist\">\n <For each={railEntries()}>\n {(entry) =>\n isGroupDefinition(entry) ? (\n <div class=\"k2b-settings__tab-group\" role=\"presentation\">\n <span class=\"k2b-settings__tab-group-label\" aria-hidden=\"true\">\n {entry.props.title}\n </span>\n <For each={collectTabs(entry.props.children)}>{(tab) => TabButton(tab)}</For>\n </div>\n ) : (\n TabButton(entry)\n )\n }\n </For>\n </nav>\n </aside>\n <div class=\"k2b-settings__content\">\n <Show when={activeTab()}>\n {(tab) => (\n <section\n id={panelId(tab().props.id)}\n class=\"k2b-settings__body\"\n role=\"tabpanel\"\n aria-labelledby={tabId(tab().props.id)}\n tabIndex={0}\n data-tone={tab().props.tone ?? \"default\"}\n >\n <div class=\"k2b-settings__section\">\n <div class=\"k2b-settings__section-heading\">\n <h2>{tab().props.title}</h2>\n <Show when={tab().props.description}>{(description) => <p>{description()}</p>}</Show>\n </div>\n {panelChildren().content}\n </div>\n </section>\n )}\n </Show>\n <Show when={panelChildren().footer}>{(footer) => <footer class=\"k2b-settings__footer\">{footer().props.children}</footer>}</Show>\n </div>\n </div>\n );\n}) as SettingsModalComponent;\n\nSettingsModal.Tab = SettingsModalTab;\nSettingsModal.Group = SettingsModalGroup;\nSettingsModal.Footer = SettingsModalFooter;\n\nexport default SettingsModal;\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,EAAY,IAAI,QAAQ,UAAU;AAClG,SAAS,aAAa,QAAQ,kBAAkB;AAChD,SAAS,uBAAuB,QAAQ,aAAa;AAErD,MAAM,kBAAkB,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACtD,MAAM,oBAAoB,GAAG,MAAM,CAAC,qBAAqB,CAAC;AAC1D,MAAM,qBAAqB,GAAG,MAAM,CAAC,sBAAsB,CAAC;AA2D5D,MAAM,eAAe,GAAI,KAAc,IACrC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAK,CAAwB,IAAI,KAAK,kBAAkB;AAEnG,MAAM,iBAAiB,GAAI,KAAc,IACvC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAK,CAAwB,IAAI,KAAK,oBAAoB;AAErG,MAAM,kBAAkB,GAAI,KAAc,IACxC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,KAAK,CAAwB,IAAI,KAAK,qBAAqB;AAEtG,MAAM,WAAW,GAAI,KAAc,IAAmC;EACpE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;EAC3D,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;EACtE,OAAO,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE;AAC9C,CAAC;AAED,MAAM,kBAAkB,GAAI,KAAc,IAAoE;EAC5G,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC;EAClE,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC;EACtE,OAAO,EAAE;AACX,CAAC;AAED,MAAM,kBAAkB,GAAI,KAAc,IAAyE;EACjH,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;IACxB,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,MAAM,EAAE,KAAK,KAAK;MACjB,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC;MACtC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;MACpC,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;MAC5C,OAAO,MAAM;IACf,CAAC,EACD;MAAE,OAAO,EAAE;IAAG,CAChB,CAAC;EACH;EACA,OAAO,kBAAkB,CAAC,KAAK,CAAC,GAAG;IAAE,OAAO,EAAE,EAAE;IAAE,MAAM,EAAE;EAAM,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,KAAK;EAAiB,CAAC;AACzG,CAAC;AAED,SAAS,gBAAgB,CAAC,KAA4B,EAAe;EACnE,OAAO;IAAE,IAAI,EAAE,kBAAkB;IAAE;EAAM,CAAC;AAC5C;AAEA,SAAS,kBAAkB,CAAC,KAA8B,EAAe;EACvE,OAAO;IAAE,IAAI,EAAE,oBAAoB;IAAE;EAAM,CAAC;AAC9C;AAEA,SAAS,mBAAmB,CAAC,KAA+B,EAAe;EACzE,OAAO;IAAE,IAAI,EAAE,qBAAqB;IAAE;EAAM,CAAC;AAC/C;AAEA,MAAM,aAAa,GAAK,KAAyB,IAAkB;EACjE,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC;EAC/C,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;EACpE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM;IAC5B,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzC,uBAAuB,CACrB,SAAS,CAAC,GAAG,CAAE,GAAG,IAAK,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EACpC,sBACF,CAAC;IACD,OAAO,SAAS;EAClB,CAAC,CAAC;EACF,MAAM,UAAU,GAAG,gBAAgB,cAAc,CAAC,CAAC,EAAE;EACrD,MAAM,OAAO,GAAG,IAAI,GAAG,CAA4B,CAAC;EACpD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE;EAClD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC,CAAC;EAC1F,MAAM,oBAAoB,GAAG,MAAM,KAAK,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC;EACxF,MAAM,mBAAmB,GAAG,MAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAE,GAAG,IAAK,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,oBAAoB,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,GAAG,UAAU,CAAC,CAAE;EACzI,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAE,GAAG,IAAK,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,mBAAmB,CAAC,CAAC,CAAC,IAAI,IAAI;EAC5F,MAAM,qBAAqB,GAAG,QAAQ,CAAC,MAAM,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;EACzE,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,kBAAkB,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;EAEnF,MAAM,SAAS,GAAI,EAAU,IAAK;IAChC,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,iBAAiB,CAAC,EAAE,CAAC;IACxD,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC;EACzB,CAAC;EAED,MAAM,YAAY,GAAG,CAAC,KAAoB,EAAE,SAAiB,KAAK;IAChE,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAE,GAAG,IAAK,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC;IAC1E,IAAI,YAAY,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;IAC7C,IAAI,SAAwB,GAAG,IAAI;IACnC,IAAI,KAAK,CAAC,GAAG,KAAK,YAAY,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE,SAAS,GAAG,CAAC,YAAY,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM;IAC3G,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM;IACxH,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC;IACvC,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;IACtD,IAAI,SAAS,KAAK,IAAI,EAAE;IACxB,KAAK,CAAC,cAAc,CAAC,CAAC;IACtB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACjC,IAAI,CAAC,OAAO,EAAE;IACd,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;EACxC,CAAC;EAED,MAAM,KAAK,GAAI,EAAU,IAAK,GAAG,UAAU,QAAQ,EAAE,EAAE;EACvD,MAAM,OAAO,GAAI,EAAU,IAAK,GAAG,UAAU,UAAU,EAAE,EAAE;EAE3D,MAAM,SAAS,GAAI,GAA+B,IAAkB;IAClE,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,EAAE;IAC3D,mDAGQ,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,0DAGR,MAAM,CAAC,CAAC,kDACR,MAAM,CAAC,CAAC,YAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,mBAAG,SAAS,6CACjD,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,wCACf,MAAM,CAAC,CAAC,GAAG,QAAQ,GAAG,MAAM,yCAC3B,MAAM,CAAC,CAAC,GAAG,MAAM,YAAG,SAAS,uDAC/B,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,4CAIrC,IAAI;MAAA,IAAC,IAAI;QAAA,OAAE,GAAG,CAAC,KAAK,CAAC,IAAI;MAAA;MAAA,UAAI,IAAI,oDAAe,IAAI,CAAC,CAAC;IAAuB,cACvE,GAAG,CAAC,KAAK,CAAC,KAAK;EAG5B,CAAC;EAED,sBACc,yBAAgB,KAAK,CAAC,KAAK,IAAI,EAAE,SAAE,wCAA4B,KAAK,CAAC,KAAK,4CACnF,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,KAAK,CAAC,OAAO;IAAA;IAAA;MAAA,4DAIT,KAAK,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK;IAAA;EAAA,2CAON,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;EAAM,CAAC,CAAC,4CACzF,GAAG;IAAA,IAAC,IAAI;MAAA,OAAE,WAAW,CAAC,CAAC;IAAA;IAAA,UACpB,KAAK,IACL,iBAAiB,CAAC,KAAK,CAAC,2BAGjB,KAAK,CAAC,KAAK,CAAC,KAAK,8BAEnB,GAAG;MAAA,IAAC,IAAI;QAAA,OAAE,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;MAAA;MAAA,UAAI,GAAG,IAAK,SAAS,CAAC,GAAG;IAAC,OAGxE,SAAS,CAAC,KAAK;EAChB,gCAMN,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,SAAS,CAAC,CAAC;IAAA;IAAA,UACnB,GAAG,iDAEG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,4DAGV,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,sDAE3B,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,0BAI/B,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,8BACrB,IAAI;MAAA,IAAC,IAAI;QAAA,OAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW;MAAA;MAAA,UAAI,WAAW,4BAAS,WAAW,CAAC,CAAC;IAAK,cAE9E,aAAa,CAAC,CAAC,CAAC,OAAO;EAG7B,gCAEF,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,aAAa,CAAC,CAAC,CAAC,MAAM;IAAA;IAAA,UAAI,MAAM,4BAA2C,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ;EAAU;AAIhI,CAA4B;AAE5B,aAAa,CAAC,GAAG,GAAG,gBAAgB;AACpC,aAAa,CAAC,KAAK,GAAG,kBAAkB;AACxC,aAAa,CAAC,MAAM,GAAG,mBAAmB;AAE1C,eAAe,aAAa","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["layout/SettingsModal.tsx"],"sourcesContent":["import { children, createEffect, createMemo, createSignal, createUniqueId, For, type JSX, Show } from \"solid-js\";\nimport { IconButton } from \"../actions/Button\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { createScrollFade } from \"./scroll-fade\";\nimport { assertUniqueStableUiIds } from \"./stable-id\";\n\nconst SETTINGS_MODAL_TAB = Symbol(\"SettingsModal.Tab\");\nconst SETTINGS_MODAL_GROUP = Symbol(\"SettingsModal.Group\");\nconst SETTINGS_MODAL_FOOTER = Symbol(\"SettingsModal.Footer\");\n\nexport type SettingsModalTabTone = \"default\" | \"danger\";\n\nexport type SettingsModalTabProps = {\n id: string;\n title: string;\n description?: string;\n icon?: string;\n tone?: SettingsModalTabTone;\n children: JSX.Element;\n};\n\nexport type SettingsModalGroupProps = {\n title: string;\n children: JSX.Element;\n};\n\nexport type SettingsModalFooterProps = {\n children: JSX.Element;\n};\n\ntype SettingsModalTabDefinition = {\n readonly kind: typeof SETTINGS_MODAL_TAB;\n readonly props: SettingsModalTabProps;\n};\n\ntype SettingsModalGroupDefinition = {\n readonly kind: typeof SETTINGS_MODAL_GROUP;\n readonly props: SettingsModalGroupProps;\n};\n\ntype SettingsModalFooterDefinition = {\n readonly kind: typeof SETTINGS_MODAL_FOOTER;\n readonly props: SettingsModalFooterProps;\n};\n\nexport type SettingsModalProps = {\n /** Accessible name for the settings surface. */\n title: string;\n /** @deprecated Retained for source compatibility; tab descriptions carry the visible context. */\n subtitle?: string;\n /** @deprecated Retained for source compatibility; tab icons identify the rail entries. */\n icon?: string;\n defaultTab?: string;\n activeTab?: string;\n onTabChange?: (id: string) => void;\n onClose?: () => void;\n closeLabel?: string;\n class?: string;\n children: JSX.Element;\n};\n\ntype SettingsModalComponent = ((props: SettingsModalProps) => JSX.Element) & {\n Tab: (props: SettingsModalTabProps) => JSX.Element;\n Group: (props: SettingsModalGroupProps) => JSX.Element;\n Footer: (props: SettingsModalFooterProps) => JSX.Element;\n};\n\nconst isTabDefinition = (value: unknown): value is SettingsModalTabDefinition =>\n !!value && typeof value === \"object\" && (value as { kind?: unknown }).kind === SETTINGS_MODAL_TAB;\n\nconst isGroupDefinition = (value: unknown): value is SettingsModalGroupDefinition =>\n !!value && typeof value === \"object\" && (value as { kind?: unknown }).kind === SETTINGS_MODAL_GROUP;\n\nconst isFooterDefinition = (value: unknown): value is SettingsModalFooterDefinition =>\n !!value && typeof value === \"object\" && (value as { kind?: unknown }).kind === SETTINGS_MODAL_FOOTER;\n\nconst collectTabs = (value: unknown): SettingsModalTabDefinition[] => {\n if (Array.isArray(value)) return value.flatMap(collectTabs);\n if (isGroupDefinition(value)) return collectTabs(value.props.children);\n return isTabDefinition(value) ? [value] : [];\n};\n\nconst collectRailEntries = (value: unknown): (SettingsModalGroupDefinition | SettingsModalTabDefinition)[] => {\n if (Array.isArray(value)) return value.flatMap(collectRailEntries);\n if (isGroupDefinition(value) || isTabDefinition(value)) return [value];\n return [];\n};\n\nconst splitPanelChildren = (value: unknown): { content: JSX.Element[]; footer?: SettingsModalFooterDefinition } => {\n if (Array.isArray(value)) {\n return value.reduce<{ content: JSX.Element[]; footer?: SettingsModalFooterDefinition }>(\n (result, entry) => {\n const next = splitPanelChildren(entry);\n result.content.push(...next.content);\n if (next.footer) result.footer = next.footer;\n return result;\n },\n { content: [] },\n );\n }\n return isFooterDefinition(value) ? { content: [], footer: value } : { content: [value as JSX.Element] };\n};\n\nfunction SettingsModalTab(props: SettingsModalTabProps): JSX.Element {\n return { kind: SETTINGS_MODAL_TAB, props } satisfies SettingsModalTabDefinition as unknown as JSX.Element;\n}\n\nfunction SettingsModalGroup(props: SettingsModalGroupProps): JSX.Element {\n return { kind: SETTINGS_MODAL_GROUP, props } satisfies SettingsModalGroupDefinition as unknown as JSX.Element;\n}\n\nfunction SettingsModalFooter(props: SettingsModalFooterProps): JSX.Element {\n return { kind: SETTINGS_MODAL_FOOTER, props } satisfies SettingsModalFooterDefinition as unknown as JSX.Element;\n}\n\nconst SettingsModal = ((props: SettingsModalProps): JSX.Element => {\n const messages = useUiMessages();\n const resolved = children(() => props.children);\n const railEntries = createMemo(() => collectRailEntries(resolved()));\n const tabs = createMemo(() => {\n const collected = collectTabs(resolved());\n assertUniqueStableUiIds(\n collected.map((tab) => tab.props.id),\n \"SettingsModal.Tab id\",\n );\n return collected;\n });\n const instanceId = `k2b-settings-${createUniqueId()}`;\n const tabRefs = new Map<string, HTMLButtonElement>();\n let tabList: HTMLElement | undefined;\n // Narrow surfaces show the categories as one scrolling row; the fade tells that more follow.\n createScrollFade(\n () => tabList,\n () => true,\n );\n const firstTabId = () => tabs()[0]?.props.id ?? \"\";\n const [localActiveTab, setLocalActiveTab] = createSignal(props.defaultTab ?? firstTabId());\n const requestedActiveTabId = () => props.activeTab ?? (localActiveTab() || firstTabId());\n const resolvedActiveTabId = createMemo(() =>\n tabs().some((tab) => tab.props.id === requestedActiveTabId()) ? requestedActiveTabId() : firstTabId(),\n );\n // `defaultTab`, `activeTab` and clicks can select a category past the edge of the scrolling row or rail.\n createEffect(() => {\n const id = resolvedActiveTabId();\n queueMicrotask(() => tabRefs.get(id)?.scrollIntoView?.({ block: \"nearest\", inline: \"nearest\" }));\n });\n const activeTab = () => tabs().find((tab) => tab.props.id === resolvedActiveTabId()) ?? null;\n const resolvedPanelChildren = children(() => activeTab()?.props.children);\n const panelChildren = createMemo(() => splitPanelChildren(resolvedPanelChildren()));\n\n const selectTab = (id: string) => {\n if (props.activeTab === undefined) setLocalActiveTab(id);\n props.onTabChange?.(id);\n };\n\n const moveTabFocus = (event: KeyboardEvent, currentId: string) => {\n const currentIndex = tabs().findIndex((tab) => tab.props.id === currentId);\n if (currentIndex < 0 || tabs().length === 0) return;\n let nextIndex: number | null = null;\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") nextIndex = (currentIndex + 1) % tabs().length;\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") nextIndex = (currentIndex - 1 + tabs().length) % tabs().length;\n if (event.key === \"Home\") nextIndex = 0;\n if (event.key === \"End\") nextIndex = tabs().length - 1;\n if (nextIndex === null) return;\n event.preventDefault();\n const nextTab = tabs()[nextIndex];\n if (!nextTab) return;\n selectTab(nextTab.props.id);\n tabRefs.get(nextTab.props.id)?.focus();\n };\n\n const tabId = (id: string) => `${instanceId}-tab-${id}`;\n const panelId = (id: string) => `${instanceId}-panel-${id}`;\n\n const TabButton = (tab: SettingsModalTabDefinition): JSX.Element => {\n const active = () => resolvedActiveTabId() === tab.props.id;\n return (\n <button\n ref={(element) => tabRefs.set(tab.props.id, element)}\n id={tabId(tab.props.id)}\n type=\"button\"\n role=\"tab\"\n aria-selected={active()}\n aria-controls={active() ? panelId(tab.props.id) : undefined}\n tabIndex={active() ? 0 : -1}\n data-state={active() ? \"active\" : \"idle\"}\n data-active={active() ? \"true\" : undefined}\n data-tone={tab.props.tone ?? \"default\"}\n onClick={() => selectTab(tab.props.id)}\n onKeyDown={(event) => moveTabFocus(event, tab.props.id)}\n >\n <Show when={tab.props.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>\n <span>{tab.props.title}</span>\n </button>\n );\n };\n\n return (\n <div class={`k2b-settings ${props.class ?? \"\"}`} role=\"region\" aria-label={props.title}>\n <Show when={props.onClose}>\n <IconButton class=\"k2b-settings__close\" label={props.closeLabel ?? messages().close} onClick={props.onClose}>\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </IconButton>\n </Show>\n <aside class=\"k2b-settings__rail\">\n <nav\n ref={tabList}\n class=\"k2b-settings__tabs\"\n aria-label={messages().sectionsLabel({ title: props.title })}\n role=\"tablist\"\n data-scroll-fade-mode=\"both\"\n data-scroll-fade-axis=\"horizontal\"\n >\n <For each={railEntries()}>\n {(entry) =>\n isGroupDefinition(entry) ? (\n <div class=\"k2b-settings__tab-group\" role=\"presentation\">\n <span class=\"k2b-settings__tab-group-label\" aria-hidden=\"true\">\n {entry.props.title}\n </span>\n <For each={collectTabs(entry.props.children)}>{(tab) => TabButton(tab)}</For>\n </div>\n ) : (\n TabButton(entry)\n )\n }\n </For>\n </nav>\n </aside>\n <div class=\"k2b-settings__content\">\n <Show when={activeTab()}>\n {(tab) => (\n <section\n id={panelId(tab().props.id)}\n class=\"k2b-settings__body\"\n role=\"tabpanel\"\n aria-labelledby={tabId(tab().props.id)}\n tabIndex={0}\n data-tone={tab().props.tone ?? \"default\"}\n >\n <div class=\"k2b-settings__section\">\n <div class=\"k2b-settings__section-heading\">\n <h2>{tab().props.title}</h2>\n <Show when={tab().props.description}>{(description) => <p>{description()}</p>}</Show>\n </div>\n {panelChildren().content}\n </div>\n </section>\n )}\n </Show>\n <Show when={panelChildren().footer}>{(footer) => <footer class=\"k2b-settings__footer\">{footer().props.children}</footer>}</Show>\n </div>\n </div>\n );\n}) as SettingsModalComponent;\n\nSettingsModal.Tab = SettingsModalTab;\nSettingsModal.Group = SettingsModalGroup;\nSettingsModal.Footer = SettingsModalFooter;\n\nexport default SettingsModal;\n"],"mappings":"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","ignoreList":[]}
@@ -14,6 +14,7 @@ export function createNavigation(options) {
14
14
  return {
15
15
  items: options.items,
16
16
  onNavigate: options.onNavigate,
17
+ onExpandedChange: options.onExpandedChange,
17
18
  async activate(id) {
18
19
  const item = findNavigationItem(options.items(), id);
19
20
  if (item?.action) await options.onAction?.(item.action);
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["layout/navigation-model.ts"],"sourcesContent":["import type { LinkNavigateEvent, NavigationScrollMode } from \"@k2b/ssr/nav\";\nimport type { Accessor } from \"solid-js\";\n\ntype NavigationEntry = {\n id: string;\n label: string;\n icon?: string;\n badge?: string | number;\n description?: string;\n active?: boolean;\n disabled?: boolean;\n color?: string;\n children?: readonly NavigationItem[];\n /** Initial disclosure state; subsequent toggles remain local to the renderer. */\n defaultExpanded?: boolean;\n actions?: readonly NavigationItem[];\n};\n\n/** Serializable presentation. Functions stay with the controller's owning island. */\nexport type NavigationItem = NavigationEntry &\n (\n | { href: string; action?: string; navigation?: \"document\" | \"enhanced\"; scroll?: NavigationScrollMode }\n | { action: string; href?: never; navigation?: never; scroll?: never }\n | { href?: never; action?: never; navigation?: never; scroll?: never; children: readonly NavigationItem[] }\n );\n\nexport type NavigationOptions = {\n items: Accessor<readonly NavigationItem[]>;\n onAction?: (action: string) => void | Promise<void>;\n onNavigate?: (event: LinkNavigateEvent) => void | Promise<void>;\n};\n\nexport function findNavigationItem(items: readonly NavigationItem[], id: string): NavigationItem | undefined {\n for (const item of items) {\n if (item.disabled) continue;\n if (item.id === id) return item;\n const found = findNavigationItem(item.children ?? [], id) ?? findNavigationItem(item.actions ?? [], id);\n if (found) return found;\n }\n}\n\n/** One live source for renderers; no router, registry, fetching or persisted state. */\nexport function createNavigation(options: NavigationOptions) {\n return {\n items: options.items,\n onNavigate: options.onNavigate,\n async activate(id: string) {\n const item = findNavigationItem(options.items(), id);\n if (item?.action) await options.onAction?.(item.action);\n },\n };\n}\n\nexport type NavigationController = ReturnType<typeof createNavigation>;\n"],"mappings":"AAkBA;;AAcA,OAAO,SAAS,kBAAkB,CAAC,KAAgC,EAAE,EAAU,EAA8B;EAC3G,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;IACxB,IAAI,IAAI,CAAC,QAAQ,EAAE;IACnB,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,IAAI;IAC/B,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,EAAE,CAAC;IACvG,IAAI,KAAK,EAAE,OAAO,KAAK;EACzB;AACF;;AAEA;AACA,OAAO,SAAS,gBAAgB,CAAC,OAA0B,EAAE;EAC3D,OAAO;IACL,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,UAAU,EAAE,OAAO,CAAC,UAAU;IAC9B,MAAM,QAAQ,CAAC,EAAU,EAAE;MACzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;MACpD,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;IACzD;EACF,CAAC;AACH","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["layout/navigation-model.ts"],"sourcesContent":["import type { LinkNavigateEvent, NavigationScrollMode } from \"@k2b/ssr/nav\";\nimport type { Accessor } from \"solid-js\";\n\ntype NavigationEntry = {\n id: string;\n label: string;\n icon?: string;\n badge?: string | number;\n description?: string;\n active?: boolean;\n disabled?: boolean;\n color?: string;\n children?: readonly NavigationItem[];\n /** Initial disclosure state; subsequent toggles remain local to the renderer. */\n defaultExpanded?: boolean;\n /** Owner-held disclosure state. The renderer shows it and reports toggles through `onExpandedChange`. */\n expanded?: boolean;\n actions?: readonly NavigationItem[];\n};\n\n/** Serializable presentation. Functions stay with the controller's owning island. */\nexport type NavigationItem = NavigationEntry &\n (\n | { href: string; action?: string; navigation?: \"document\" | \"enhanced\"; scroll?: NavigationScrollMode }\n | { action: string; href?: never; navigation?: never; scroll?: never }\n | { href?: never; action?: never; navigation?: never; scroll?: never; children: readonly NavigationItem[] }\n );\n\nexport type NavigationOptions = {\n items: Accessor<readonly NavigationItem[]>;\n onAction?: (action: string) => void | Promise<void>;\n onNavigate?: (event: LinkNavigateEvent) => void | Promise<void>;\n /** Receives disclosure toggles of items that carry `expanded`; the owner decides the next state. */\n onExpandedChange?: (id: string, expanded: boolean) => void;\n};\n\nexport function findNavigationItem(items: readonly NavigationItem[], id: string): NavigationItem | undefined {\n for (const item of items) {\n if (item.disabled) continue;\n if (item.id === id) return item;\n const found = findNavigationItem(item.children ?? [], id) ?? findNavigationItem(item.actions ?? [], id);\n if (found) return found;\n }\n}\n\n/** One live source for renderers; no router, registry, fetching or persisted state. */\nexport function createNavigation(options: NavigationOptions) {\n return {\n items: options.items,\n onNavigate: options.onNavigate,\n onExpandedChange: options.onExpandedChange,\n async activate(id: string) {\n const item = findNavigationItem(options.items(), id);\n if (item?.action) await options.onAction?.(item.action);\n },\n };\n}\n\nexport type NavigationController = ReturnType<typeof createNavigation>;\n"],"mappings":"AAoBA;;AAgBA,OAAO,SAAS,kBAAkB,CAAC,KAAgC,EAAE,EAAU,EAA8B;EAC3G,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;IACxB,IAAI,IAAI,CAAC,QAAQ,EAAE;IACnB,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,IAAI;IAC/B,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,EAAE,CAAC;IACvG,IAAI,KAAK,EAAE,OAAO,KAAK;EACzB;AACF;;AAEA;AACA,OAAO,SAAS,gBAAgB,CAAC,OAA0B,EAAE;EAC3D,OAAO;IACL,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,UAAU,EAAE,OAAO,CAAC,UAAU;IAC9B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;IAC1C,MAAM,QAAQ,CAAC,EAAU,EAAE;MACzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;MACpD,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;IACzD;EACF,CAAC;AACH","ignoreList":[]}
@@ -10,6 +10,9 @@ var _tmpl$ = ["<p class=\"k2b-placeholder__title\">", "</p>"],
10
10
  import { Show } from "solid-js";
11
11
  import { Dynamic } from "solid-js/web";
12
12
  import { Paper } from "./Paper";
13
+
14
+ /** `compact` stacks inside a section, `inline` is one row in a list or sidebar, `panel` fills a work area. */
15
+
13
16
  export default function Placeholder(props) {
14
17
  const align = () => props.align ?? "center";
15
18
  const state = () => props.state ?? "empty";
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["surfaces/Placeholder.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport { Paper } from \"./Paper\";\n\nexport type PlaceholderAlign = \"center\" | \"left\";\nexport type PlaceholderSurface = \"none\" | \"paper\";\nexport type PlaceholderState = \"empty\" | \"loading\" | \"error\";\nexport type PlaceholderVariant = \"compact\" | \"panel\";\n\nexport type PlaceholderProps = {\n title?: JSX.Element;\n description?: JSX.Element;\n icon?: string;\n action?: JSX.Element;\n align?: PlaceholderAlign;\n surface?: PlaceholderSurface;\n state?: PlaceholderState;\n variant?: PlaceholderVariant;\n class?: string;\n};\n\nexport default function Placeholder(props: PlaceholderProps): JSX.Element {\n const align = () => props.align ?? \"center\";\n const state = () => props.state ?? \"empty\";\n const variant = () => props.variant ?? \"compact\";\n const icon = () => props.icon ?? (state() === \"loading\" ? \"ti ti-loader-2\" : state() === \"error\" ? \"ti ti-alert-circle\" : undefined);\n\n return (\n <Dynamic\n component={props.surface === \"paper\" ? Paper : \"div\"}\n class={`k2b-placeholder ${props.class ?? \"\"}`}\n data-align={align()}\n data-state={state()}\n data-surface={props.surface ?? \"none\"}\n data-variant={variant()}\n role={state() === \"error\" ? \"alert\" : state() === \"loading\" ? \"status\" : undefined}\n aria-live={state() === \"loading\" ? \"polite\" : undefined}\n aria-busy={state() === \"loading\" ? \"true\" : undefined}\n >\n <Show when={icon()}>\n {(iconClass) => (\n <span class=\"k2b-placeholder__icon\">\n <i class={iconClass()} aria-hidden=\"true\" />\n </span>\n )}\n </Show>\n <Show when={props.title}>\n <p class=\"k2b-placeholder__title\">{props.title}</p>\n </Show>\n <Show when={props.description}>\n <div class=\"k2b-placeholder__description\">{props.description}</div>\n </Show>\n <Show when={props.action}>\n <div class=\"k2b-placeholder__action\">{props.action}</div>\n </Show>\n </Dynamic>\n );\n}\n"],"mappings":";;;;;;;;;AAAA,SAAmB,IAAI,QAAQ,UAAU;AACzC,SAAS,OAAO,QAAQ,cAAc;AACtC,SAAS,KAAK,QAAQ,SAAS;AAmB/B,eAAe,SAAS,WAAW,CAAC,KAAuB,EAAe;EACxE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,IAAI,QAAQ;EAC3C,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,IAAI,OAAO;EAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,IAAI,SAAS;EAChD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,gBAAgB,GAAG,KAAK,CAAC,CAAC,KAAK,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAAC;EAEpI,yBACG,OAAO;IAAA,IACN,SAAS;MAAA,OAAE,KAAK,CAAC,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,KAAK;IAAA;IAAA;MAAA,OAC7C,mBAAmB,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE;IAAA;IAAA;MAAA,OACjC,KAAK,CAAC,CAAC;IAAA;IAAA;MAAA,OACP,KAAK,CAAC,CAAC;IAAA;IAAA;MAAA,OACL,KAAK,CAAC,OAAO,IAAI,MAAM;IAAA;IAAA;MAAA,OACvB,OAAO,CAAC,CAAC;IAAA;IAAA,IACvB,IAAI;MAAA,OAAE,kBAAK,CAAC,CAAC,KAAK,OAAO,MAAG,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS;IAAA;IAAA;MAAA,OACvE,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS;IAAA;IAAA;MAAA,OAC5C,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,MAAM,GAAG,SAAS;IAAA;IAAA;MAAA,0BAEpD,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,IAAI,CAAC,CAAC;QAAA;QAAA,UACd,SAAS,oDAEG,SAAS,CAAC,CAAC;MAExB,sBAEF,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,KAAK;QAAA;QAAA;UAAA,8BACc,KAAK,CAAC,KAAK;QAAA;MAAA,sBAE/C,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,WAAW;QAAA;QAAA;UAAA,+BACgB,KAAK,CAAC,WAAW;QAAA;MAAA,sBAE7D,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,MAAM;QAAA;QAAA;UAAA,+BACgB,KAAK,CAAC,MAAM;QAAA;MAAA;IAAA;EAAA;AAI1D","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["surfaces/Placeholder.tsx"],"sourcesContent":["import { type JSX, Show } from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport { Paper } from \"./Paper\";\n\nexport type PlaceholderAlign = \"center\" | \"left\";\nexport type PlaceholderSurface = \"none\" | \"paper\";\nexport type PlaceholderState = \"empty\" | \"loading\" | \"error\";\n/** `compact` stacks inside a section, `inline` is one row in a list or sidebar, `panel` fills a work area. */\nexport type PlaceholderVariant = \"compact\" | \"inline\" | \"panel\";\n\nexport type PlaceholderProps = {\n title?: JSX.Element;\n description?: JSX.Element;\n icon?: string;\n action?: JSX.Element;\n align?: PlaceholderAlign;\n surface?: PlaceholderSurface;\n state?: PlaceholderState;\n variant?: PlaceholderVariant;\n class?: string;\n};\n\nexport default function Placeholder(props: PlaceholderProps): JSX.Element {\n const align = () => props.align ?? \"center\";\n const state = () => props.state ?? \"empty\";\n const variant = () => props.variant ?? \"compact\";\n const icon = () => props.icon ?? (state() === \"loading\" ? \"ti ti-loader-2\" : state() === \"error\" ? \"ti ti-alert-circle\" : undefined);\n\n return (\n <Dynamic\n component={props.surface === \"paper\" ? Paper : \"div\"}\n class={`k2b-placeholder ${props.class ?? \"\"}`}\n data-align={align()}\n data-state={state()}\n data-surface={props.surface ?? \"none\"}\n data-variant={variant()}\n role={state() === \"error\" ? \"alert\" : state() === \"loading\" ? \"status\" : undefined}\n aria-live={state() === \"loading\" ? \"polite\" : undefined}\n aria-busy={state() === \"loading\" ? \"true\" : undefined}\n >\n <Show when={icon()}>\n {(iconClass) => (\n <span class=\"k2b-placeholder__icon\">\n <i class={iconClass()} aria-hidden=\"true\" />\n </span>\n )}\n </Show>\n <Show when={props.title}>\n <p class=\"k2b-placeholder__title\">{props.title}</p>\n </Show>\n <Show when={props.description}>\n <div class=\"k2b-placeholder__description\">{props.description}</div>\n </Show>\n <Show when={props.action}>\n <div class=\"k2b-placeholder__action\">{props.action}</div>\n </Show>\n </Dynamic>\n );\n}\n"],"mappings":";;;;;;;;;AAAA,SAAmB,IAAI,QAAQ,UAAU;AACzC,SAAS,OAAO,QAAQ,cAAc;AACtC,SAAS,KAAK,QAAQ,SAAS;;AAK/B;;AAeA,eAAe,SAAS,WAAW,CAAC,KAAuB,EAAe;EACxE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,IAAI,QAAQ;EAC3C,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,IAAI,OAAO;EAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,IAAI,SAAS;EAChD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,gBAAgB,GAAG,KAAK,CAAC,CAAC,KAAK,OAAO,GAAG,oBAAoB,GAAG,SAAS,CAAC;EAEpI,yBACG,OAAO;IAAA,IACN,SAAS;MAAA,OAAE,KAAK,CAAC,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,KAAK;IAAA;IAAA;MAAA,OAC7C,mBAAmB,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE;IAAA;IAAA;MAAA,OACjC,KAAK,CAAC,CAAC;IAAA;IAAA;MAAA,OACP,KAAK,CAAC,CAAC;IAAA;IAAA;MAAA,OACL,KAAK,CAAC,OAAO,IAAI,MAAM;IAAA;IAAA;MAAA,OACvB,OAAO,CAAC,CAAC;IAAA;IAAA,IACvB,IAAI;MAAA,OAAE,kBAAK,CAAC,CAAC,KAAK,OAAO,MAAG,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS;IAAA;IAAA;MAAA,OACvE,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,QAAQ,GAAG,SAAS;IAAA;IAAA;MAAA,OAC5C,KAAK,CAAC,CAAC,KAAK,SAAS,GAAG,MAAM,GAAG,SAAS;IAAA;IAAA;MAAA,0BAEpD,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,IAAI,CAAC,CAAC;QAAA;QAAA,UACd,SAAS,oDAEG,SAAS,CAAC,CAAC;MAExB,sBAEF,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,KAAK;QAAA;QAAA;UAAA,8BACc,KAAK,CAAC,KAAK;QAAA;MAAA,sBAE/C,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,WAAW;QAAA;QAAA;UAAA,+BACgB,KAAK,CAAC,WAAW;QAAA;MAAA,sBAE7D,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,MAAM;QAAA;QAAA;UAAA,+BACgB,KAAK,CAAC,MAAM;QAAA;MAAA;IAAA;EAAA;AAI1D","ignoreList":[]}