@k2b/ui 0.8.0 → 0.9.1

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 (48) 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/MarkdownView.js +8 -1
  4. package/dist/browser/content/MarkdownView.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/intl/messages.js +48 -2
  14. package/dist/browser/intl/messages.js.map +1 -1
  15. package/dist/browser/layout/Navigation.js +8 -5
  16. package/dist/browser/layout/Navigation.js.map +1 -1
  17. package/dist/browser/layout/SettingsModal.js +32 -10
  18. package/dist/browser/layout/SettingsModal.js.map +1 -1
  19. package/dist/browser/layout/navigation-model.js +1 -0
  20. package/dist/browser/layout/navigation-model.js.map +1 -1
  21. package/dist/ssr/content/Calendar.js +13 -6
  22. package/dist/ssr/content/Calendar.js.map +1 -1
  23. package/dist/ssr/content/MarkdownView.js +8 -1
  24. package/dist/ssr/content/MarkdownView.js.map +1 -1
  25. package/dist/ssr/content/PdfPreview.js +79 -22
  26. package/dist/ssr/content/PdfPreview.js.map +1 -1
  27. package/dist/ssr/feedback/dialog-core.js +2 -1
  28. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  29. package/dist/ssr/feedback/prompts.js +19 -5
  30. package/dist/ssr/feedback/prompts.js.map +1 -1
  31. package/dist/ssr/feedback/toast.js +4 -2
  32. package/dist/ssr/feedback/toast.js.map +1 -1
  33. package/dist/ssr/intl/messages.js +48 -2
  34. package/dist/ssr/intl/messages.js.map +1 -1
  35. package/dist/ssr/layout/Navigation.js +8 -5
  36. package/dist/ssr/layout/Navigation.js.map +1 -1
  37. package/dist/ssr/layout/SettingsModal.js +30 -5
  38. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  39. package/dist/ssr/layout/navigation-model.js +1 -0
  40. package/dist/ssr/layout/navigation-model.js.map +1 -1
  41. package/dist/styles.css +1 -1
  42. package/dist/tabler-icons-15sezdfp.woff2 +0 -0
  43. package/dist/tabler.css +2 -2
  44. package/dist/types/content/PdfPreview.d.ts +8 -0
  45. package/dist/types/intl/messages.d.ts +23 -0
  46. package/dist/types/layout/navigation-model.d.ts +5 -0
  47. package/package.json +7 -6
  48. package/dist/tabler-icons-q30jt7jk.woff2 +0 -0
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["layout/Navigation.tsx"],"sourcesContent":["import { documentNavigate, Link } from \"@k2b/ssr/nav\";\nimport { createSignal, For, Show } from \"solid-js\";\nimport { Dropdown } from \"../actions/Dropdown\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { NavigationController, NavigationItem } from \"./navigation-model\";\n\nexport type NavigationProps = {\n navigation: NavigationController;\n label: string;\n /** A host can finish dismissing its menu before the selected operation runs. */\n beforeSelect?: () => boolean | void | Promise<boolean | void>;\n};\n\nexport default function Navigation(props: NavigationProps) {\n const messages = useUiMessages();\n const [expanded, setExpanded] = createSignal<Record<string, boolean>>({});\n const ready = async () => (await props.beforeSelect?.()) !== false;\n const activate = async (id: string) => {\n if (await ready()) await props.navigation.activate(id);\n };\n const Rows = (rows: { items: readonly NavigationItem[]; disabled?: boolean }) => (\n <ul class=\"k2b-navigation__list\">\n <For each={rows.items.map((item) => item.id)}>\n {(id) => {\n const item = () => rows.items.find((entry) => entry.id === id)!;\n const disabled = () => rows.disabled || item().disabled;\n const open = () => expanded()[id] ?? item().defaultExpanded ?? true;\n const toggle = () => setExpanded((current) => ({ ...current, [id]: !open() }));\n const content = () => (\n <>\n <Show when={item().icon}>\n <i class={item().icon} aria-hidden=\"true\" />\n </Show>\n <span class=\"k2b-navigation__copy\">\n <span>{item().label}</span>\n <Show when={item().description}>\n <small>{item().description}</small>\n </Show>\n </span>\n <Show when={item().color}>\n <span class=\"k2b-navigation__color\" style={{ \"background-color\": item().color }} />\n </Show>\n <Show when={item().badge !== undefined}>\n <span class=\"k2b-navigation__badge\">{item().badge}</span>\n </Show>\n </>\n );\n return (\n <li>\n <div class=\"k2b-navigation__row\" data-active={item().active || undefined}>\n <Show\n when={item().href}\n fallback={\n <button\n type=\"button\"\n class=\"k2b-navigation__control\"\n disabled={disabled()}\n aria-expanded={!item().action ? open() : undefined}\n onClick={() => (item().action ? void activate(id) : toggle())}\n >\n {content()}\n <Show when={!item().action && item().children?.length}>\n <i class={open() ? \"ti ti-chevron-down\" : \"ti ti-chevron-right\"} aria-hidden=\"true\" />\n </Show>\n </button>\n }\n >\n {(href) => (\n <Link\n class=\"k2b-navigation__control\"\n href={href()}\n aria-current={item().active ? \"page\" : undefined}\n aria-disabled={disabled() || undefined}\n tabIndex={disabled() ? -1 : undefined}\n scroll={item().scroll}\n onNavigate={async (event) => {\n if (!(await ready())) return;\n if (item().navigation === \"enhanced\" && props.navigation.onNavigate) await props.navigation.onNavigate(event);\n else event.fallback();\n }}\n onClick={(event) => {\n if (disabled()) {\n event.preventDefault();\n return;\n }\n if (!item().action || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)\n return;\n // Local opening can fetch before committing navigation, outside a view transition.\n event.preventDefault();\n void activate(id);\n }}\n >\n {content()}\n </Link>\n )}\n </Show>\n <Show when={(item().href || item().action) && item().children?.length}>\n <button\n type=\"button\"\n class=\"k2b-navigation__disclosure\"\n aria-label={item().label}\n aria-expanded={open()}\n disabled={disabled()}\n onClick={toggle}\n >\n <i class={open() ? \"ti ti-chevron-down\" : \"ti ti-chevron-right\"} aria-hidden=\"true\" />\n </button>\n </Show>\n <Show when={item().actions?.length}>\n <Dropdown.Root\n items={(item().actions ?? []).map((action) => ({\n label: action.label,\n icon: action.icon,\n disabled: disabled() || action.disabled,\n action: () => {\n if (action.href)\n void ready().then((allowed) => {\n if (allowed) documentNavigate(action.href!);\n });\n else void activate(action.id);\n },\n }))}\n >\n <Dropdown.Trigger iconOnly label={`${item().label}: ${messages().rowAction}`} variant=\"ghost\">\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n <Show when={item().children?.length}>\n <div hidden={!open()}>\n <Rows items={item().children ?? []} disabled={disabled()} />\n </div>\n </Show>\n </li>\n );\n }}\n </For>\n </ul>\n );\n return (\n <nav class=\"k2b-navigation\" aria-label={props.label}>\n <Rows items={props.navigation.items()} />\n </nav>\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["layout/Navigation.tsx"],"sourcesContent":["import { documentNavigate, Link } from \"@k2b/ssr/nav\";\nimport { createSignal, For, Show } from \"solid-js\";\nimport { Dropdown } from \"../actions/Dropdown\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { NavigationController, NavigationItem } from \"./navigation-model\";\n\nexport type NavigationProps = {\n navigation: NavigationController;\n label: string;\n /** A host can finish dismissing its menu before the selected operation runs. */\n beforeSelect?: () => boolean | void | Promise<boolean | void>;\n};\n\nexport default function Navigation(props: NavigationProps) {\n const messages = useUiMessages();\n const [expanded, setExpanded] = createSignal<Record<string, boolean>>({});\n const ready = async () => (await props.beforeSelect?.()) !== false;\n const activate = async (id: string) => {\n if (await ready()) await props.navigation.activate(id);\n };\n const Rows = (rows: { items: readonly NavigationItem[]; disabled?: boolean }) => (\n <ul class=\"k2b-navigation__list\">\n <For each={rows.items.map((item) => item.id)}>\n {(id) => {\n const item = () => rows.items.find((entry) => entry.id === id)!;\n const disabled = () => rows.disabled || item().disabled;\n // `expanded` hands disclosure to the item's owner; every other toggle stays local to this renderer.\n const open = () => item().expanded ?? expanded()[id] ?? item().defaultExpanded ?? true;\n const toggle = () => {\n if (item().expanded !== undefined) props.navigation.onExpandedChange?.(id, !open());\n else setExpanded((current) => ({ ...current, [id]: !open() }));\n };\n const content = () => (\n <>\n <Show when={item().icon}>\n <i class={item().icon} aria-hidden=\"true\" />\n </Show>\n <span class=\"k2b-navigation__copy\">\n <span>{item().label}</span>\n <Show when={item().description}>\n <small>{item().description}</small>\n </Show>\n </span>\n <Show when={item().color}>\n <span class=\"k2b-navigation__color\" style={{ \"background-color\": item().color }} />\n </Show>\n <Show when={item().badge !== undefined}>\n <span class=\"k2b-navigation__badge\">{item().badge}</span>\n </Show>\n </>\n );\n return (\n <li>\n <div class=\"k2b-navigation__row\" data-active={item().active || undefined}>\n <Show\n when={item().href}\n fallback={\n <button\n type=\"button\"\n class=\"k2b-navigation__control\"\n disabled={disabled()}\n aria-expanded={!item().action ? open() : undefined}\n onClick={() => (item().action ? void activate(id) : toggle())}\n >\n {content()}\n <Show when={!item().action && item().children?.length}>\n <i class={open() ? \"ti ti-chevron-down\" : \"ti ti-chevron-right\"} aria-hidden=\"true\" />\n </Show>\n </button>\n }\n >\n {(href) => (\n <Link\n class=\"k2b-navigation__control\"\n href={href()}\n aria-current={item().active ? \"page\" : undefined}\n aria-disabled={disabled() || undefined}\n tabIndex={disabled() ? -1 : undefined}\n scroll={item().scroll}\n onNavigate={async (event) => {\n if (!(await ready())) return;\n if (item().navigation === \"enhanced\" && props.navigation.onNavigate) await props.navigation.onNavigate(event);\n else event.fallback();\n }}\n onClick={(event) => {\n if (disabled()) {\n event.preventDefault();\n return;\n }\n if (!item().action || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)\n return;\n // Local opening can fetch before committing navigation, outside a view transition.\n event.preventDefault();\n void activate(id);\n }}\n >\n {content()}\n </Link>\n )}\n </Show>\n <Show when={(item().href || item().action) && item().children?.length}>\n <button\n type=\"button\"\n class=\"k2b-navigation__disclosure\"\n aria-label={item().label}\n aria-expanded={open()}\n disabled={disabled()}\n onClick={toggle}\n >\n <i class={open() ? \"ti ti-chevron-down\" : \"ti ti-chevron-right\"} aria-hidden=\"true\" />\n </button>\n </Show>\n <Show when={item().actions?.length}>\n <Dropdown.Root\n items={(item().actions ?? []).map((action) => ({\n label: action.label,\n icon: action.icon,\n disabled: disabled() || action.disabled,\n action: () => {\n if (action.href)\n void ready().then((allowed) => {\n if (allowed) documentNavigate(action.href!);\n });\n else void activate(action.id);\n },\n }))}\n >\n <Dropdown.Trigger iconOnly label={`${item().label}: ${messages().rowAction}`} variant=\"ghost\">\n <i class=\"ti ti-dots\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n <Show when={item().children?.length}>\n <div hidden={!open()}>\n <Rows items={item().children ?? []} disabled={disabled()} />\n </div>\n </Show>\n </li>\n );\n }}\n </For>\n </ul>\n );\n return (\n <nav class=\"k2b-navigation\" aria-label={props.label}>\n <Rows items={props.navigation.items()} />\n </nav>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB,EAAE,IAAI,QAAQ,cAAc;AACrD,SAAS,YAAY,EAAE,GAAG,EAAE,IAAI,QAAQ,UAAU;AAClD,SAAS,QAAQ,QAAQ,qBAAqB;AAC9C,SAAS,aAAa,QAAQ,kBAAkB;AAUhD,eAAe,SAAS,UAAU,CAAC,KAAsB,EAAE;EACzD,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,YAAY,CAA0B,CAAC,CAAC,CAAC;EACzE,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,KAAK,CAAC,YAAY,GAAG,CAAC,MAAM,KAAK;EAClE,MAAM,QAAQ,GAAG,MAAO,EAAU,IAAK;IACrC,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;EACxD,CAAC;EACD,MAAM,IAAI,GAAI,IAA8D;IAAA;IAAA,iCAEvE,GAAG;MAAA,IAAC,IAAI;QAAA,OAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAE,IAAI,IAAK,IAAI,CAAC,EAAE,CAAC;MAAA;MAAA,UACxC,EAAE,IAAK;QACP,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAE,KAAK,IAAK,KAAK,CAAC,EAAE,KAAK,EAAE,CAAE;QAC/D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ;QACvD;QACA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,eAAe,IAAI,IAAI;QACtF,MAAM,MAAM,GAAG,MAAM;UACnB,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAC/E,WAAW,CAAE,OAAO,KAAM;YAAE,GAAG,OAAO;YAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC;UAAE,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,OAAO,GAAG,yBAEX,IAAI;UAAA,IAAC,IAAI;YAAA,OAAE,IAAI,CAAC,CAAC,CAAC,IAAI;UAAA;UAAA;YAAA;YAAA,kCACX,IAAI,CAAC,CAAC,CAAC,IAAI;YAAA;UAAA;QAAA;UAAA;YAAA;YAAA;YAAA;UAAA,sBAGd,IAAI,CAAC,CAAC,CAAC,KAAK;UAAA,kCAClB,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,IAAI,CAAC,CAAC,CAAC,WAAW;YAAA;YAAA;cAAA;cAAA,sBACpB,IAAI,CAAC,CAAC,CAAC,WAAW;cAAA;YAAA;UAAA;UAAA;QAAA,wBAG7B,IAAI;UAAA,IAAC,IAAI;YAAA,OAAE,IAAI,CAAC,CAAC,CAAC,KAAK;UAAA;UAAA;YAAA;YAAA,8DAC2C,IAAI,CAAC,CAAC,CAAC,KAAK;YAAA;UAAA;QAAA,sBAE9E,IAAI;UAAA,IAAC,IAAI;YAAA,OAAE,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS;UAAA;UAAA;YAAA;YAAA,sBACC,IAAI,CAAC,CAAC,CAAC,KAAK;YAAA;UAAA;QAAA,GAGtD;QACD;UAAA;YAAA;YAAA;YAAA;YAAA;YAAA;YAAA;YAAA;YAAA;YAAA;UAAA,kCAGO,IAAI;YAAA,IACH,IAAI;cAAA,OAAE,IAAI,CAAC,CAAC,CAAC,IAAI;YAAA;YAAA,IACjB,QAAQ;cAAA;gBAAA;kBAAA;kBAAA;kBAAA;kBAAA;gBAAA,iBAMK,MAAO,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,QAAQ,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAE;gBAAA,iBAE5D,OAAO;gBAAA,mCACP,IAAI;kBAAA,IAAC,IAAI;oBAAA,OAAE,gBAAC,IAAI,CAAC,CAAC,CAAC,MAAM,OAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM;kBAAA;kBAAA;oBAAA;oBAAA,mCACzC,IAAI,CAAC,CAAC,GAAG,oBAAoB,GAAG,qBAAqB;oBAAA;kBAAA;gBAAA;gBAAA;kBAAA,WANvD,QAAQ,CAAC,CAAC;oBAAA,OACL,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS;kBAAA;kBAAA;kBAAA;gBAAA;kBAAA;kBAAA;gBAAA;gBAAA;gBAAA;cAAA;YAAA;YAAA,UAUpD,IAAI,sBACH,IAAI;cAAA;cAAA,IAEH,IAAI;gBAAA,OAAE,IAAI,CAAC,CAAC;cAAA;cAAA;gBAAA,OACE,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS;cAAA;cAAA;gBAAA,OACjC,QAAQ,CAAC,CAAC,IAAI,SAAS;cAAA;cAAA,IACtC,QAAQ;gBAAA,OAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS;cAAA;cAAA,IACrC,MAAM;gBAAA,OAAE,IAAI,CAAC,CAAC,CAAC,MAAM;cAAA;cACrB,UAAU,EAAE,MAAO,KAAK,IAAK;gBAC3B,IAAI,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE;gBACtB,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KACzG,KAAK,CAAC,QAAQ,CAAC,CAAC;cACvB,CAAC;cACD,OAAO,EAAG,KAAK,IAAK;gBAClB,IAAI,QAAQ,CAAC,CAAC,EAAE;kBACd,KAAK,CAAC,cAAc,CAAC,CAAC;kBACtB;gBACF;gBACA,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,EAC1G;gBACF;gBACA,KAAK,CAAC,cAAc,CAAC,CAAC;gBACtB,KAAK,QAAQ,CAAC,EAAE,CAAC;cACnB,CAAC;cAAA;gBAAA,OAEA,OAAO,CAAC,CAAC;cAAA;YAAA;UAEb;UAAA,kCAEF,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,gBAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,QAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM;YAAA;YAAA;cAAA;gBAAA;cAAA,iBAOxD,MAAM;cAAA;gBAAA,UAHH,IAAI,CAAC,CAAC,CAAC,KAAK;kBAAA,OACT,IAAI,CAAC,CAAC;kBAAA,OACX,QAAQ,CAAC,CAAC;kBAAA,OAGV,IAAI,CAAC,CAAC,GAAG,oBAAoB,GAAG,qBAAqB;gBAAA;gBAAA;gBAAA;gBAAA;gBAAA;cAAA;gBAAA;gBAAA;gBAAA;gBAAA;cAAA;cAAA;cAAA;YAAA;UAAA;UAAA,kCAGlE,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM;YAAA;YAAA;cAAA,yBAC/B,QAAQ,CAAC,IAAI;gBAAA,IACZ,KAAK;kBAAA,OAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,GAAG,CAAE,MAAM,KAAM;oBAC7C,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,QAAQ,EAAE,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ;oBACvC,MAAM,EAAE,MAAM;sBACZ,IAAI,MAAM,CAAC,IAAI,EACb,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAE,OAAO,IAAK;wBAC7B,IAAI,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,IAAK,CAAC;sBAC7C,CAAC,CAAC,CAAC,KACA,KAAK,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC/B;kBACF,CAAC,CAAC,CAAC;gBAAA;gBAAA;kBAAA,yBAEF,QAAQ,CAAC,OAAO;oBAAC,QAAQ;oBAAA,IAAC,KAAK;sBAAA,OAAE,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE;oBAAA;oBAAE,OAAO;oBAAA;sBAAA;oBAAA;kBAAA;gBAAA;cAAA;YAAA;UAAA;UAAA,kCAM1F,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM;YAAA;YAAA;cAAA;cAAA,mCAE9B,IAAI;gBAAA,IAAC,KAAK;kBAAA,OAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE;gBAAA;gBAAA,IAAE,QAAQ;kBAAA,OAAE,QAAQ,CAAC,CAAC;gBAAA;cAAA;cAAA,+CAD7C,CAAC,IAAI,CAAC,CAAC;cAAA;YAAA;UAAA;UAAA,oDAjFwB,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,SAAS;UAAA;QAAA;MAuF9E;IAAC;IAAA;EAAA,IAGN;EACD;IAAA;IAAA,mCAEK,IAAI;MAAA,IAAC,KAAK;QAAA,OAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;MAAA;IAAA;IAAA,oDADC,KAAK,CAAC,KAAK;IAAA;EAAA;AAIvD;AAAC","ignoreList":[]}
@@ -1,6 +1,6 @@
1
1
  import { template as _$template } from "solid-js/web";
2
2
  import { delegateEvents as _$delegateEvents } from "solid-js/web";
3
- import { addEventListener as _$addEventListener } from "solid-js/web";
3
+ import { memo as _$memo } from "solid-js/web";
4
4
  import { className as _$className } from "solid-js/web";
5
5
  import { setAttribute as _$setAttribute } from "solid-js/web";
6
6
  import { effect as _$effect } from "solid-js/web";
@@ -12,14 +12,16 @@ import { createComponent as _$createComponent } from "solid-js/web";
12
12
  import { use as _$use } from "solid-js/web";
13
13
  var _tmpl$ = /*#__PURE__*/_$template(`<button type=button role=tab><!$><!/><span>`),
14
14
  _tmpl$2 = /*#__PURE__*/_$template(`<i aria-hidden=true>`),
15
- _tmpl$3 = /*#__PURE__*/_$template(`<button type=button class="k2b-settings__close k2b-icon-button"><i class="ti ti-x"aria-hidden=true>`),
16
- _tmpl$4 = /*#__PURE__*/_$template(`<div role=region><!$><!/><aside class=k2b-settings__rail><nav class=k2b-settings__tabs role=tablist></nav></aside><div class=k2b-settings__content><!$><!/><!$><!/>`),
15
+ _tmpl$3 = /*#__PURE__*/_$template(`<i class="ti ti-x"aria-hidden=true>`),
16
+ _tmpl$4 = /*#__PURE__*/_$template(`<div 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><!$><!/><!$><!/>`),
17
17
  _tmpl$5 = /*#__PURE__*/_$template(`<div class=k2b-settings__tab-group role=presentation><span class=k2b-settings__tab-group-label aria-hidden=true></span><!$><!/>`),
18
18
  _tmpl$6 = /*#__PURE__*/_$template(`<section class=k2b-settings__body role=tabpanel tabindex=0><div class=k2b-settings__section><div class=k2b-settings__section-heading><h2></h2><!$><!/></div><!$><!/>`),
19
19
  _tmpl$7 = /*#__PURE__*/_$template(`<p>`),
20
20
  _tmpl$8 = /*#__PURE__*/_$template(`<footer class=k2b-settings__footer>`);
21
- import { children, createMemo, createSignal, createUniqueId, For, Show } from "solid-js";
21
+ import { children, createEffect, createMemo, createSignal, createUniqueId, For, Show } from "solid-js";
22
+ import { IconButton } from "../actions/Button";
22
23
  import { useUiMessages } from "../intl/messages";
24
+ import { createScrollFade } from "./scroll-fade";
23
25
  import { assertUniqueStableUiIds } from "./stable-id";
24
26
  const SETTINGS_MODAL_TAB = Symbol("SettingsModal.Tab");
25
27
  const SETTINGS_MODAL_GROUP = Symbol("SettingsModal.Group");
@@ -84,10 +86,21 @@ const SettingsModal = props => {
84
86
  });
85
87
  const instanceId = `k2b-settings-${createUniqueId()}`;
86
88
  const tabRefs = new Map();
89
+ let tabList;
90
+ // Narrow surfaces show the categories as one scrolling row; the fade tells that more follow.
91
+ createScrollFade(() => tabList, () => true);
87
92
  const firstTabId = () => tabs()[0]?.props.id ?? "";
88
93
  const [localActiveTab, setLocalActiveTab] = createSignal(props.defaultTab ?? firstTabId());
89
94
  const requestedActiveTabId = () => props.activeTab ?? (localActiveTab() || firstTabId());
90
- const resolvedActiveTabId = () => tabs().some(tab => tab.props.id === requestedActiveTabId()) ? requestedActiveTabId() : firstTabId();
95
+ const resolvedActiveTabId = createMemo(() => tabs().some(tab => tab.props.id === requestedActiveTabId()) ? requestedActiveTabId() : firstTabId());
96
+ // `defaultTab`, `activeTab` and clicks can select a category past the edge of the scrolling row or rail.
97
+ createEffect(() => {
98
+ const id = resolvedActiveTabId();
99
+ queueMicrotask(() => tabRefs.get(id)?.scrollIntoView?.({
100
+ block: "nearest",
101
+ inline: "nearest"
102
+ }));
103
+ });
91
104
  const activeTab = () => tabs().find(tab => tab.props.id === resolvedActiveTabId()) ?? null;
92
105
  const resolvedPanelChildren = children(() => activeTab()?.props.children);
93
106
  const panelChildren = createMemo(() => splitPanelChildren(resolvedPanelChildren()));
@@ -178,13 +191,22 @@ const SettingsModal = props => {
178
191
  return props.onClose;
179
192
  },
180
193
  get children() {
181
- var _el$7 = _$getNextElement(_tmpl$3);
182
- _$addEventListener(_el$7, "click", props.onClose, true);
183
- _$effect(() => _$setAttribute(_el$7, "aria-label", props.closeLabel ?? messages().close));
184
- _$runHydrationEvents();
185
- return _el$7;
194
+ return _$createComponent(IconButton, {
195
+ "class": "k2b-settings__close",
196
+ get label() {
197
+ return props.closeLabel ?? messages().close;
198
+ },
199
+ get onClick() {
200
+ return props.onClose;
201
+ },
202
+ get children() {
203
+ return _$getNextElement(_tmpl$3);
204
+ }
205
+ });
186
206
  }
187
207
  }), _el$14, _co$4);
208
+ var _ref$ = tabList;
209
+ typeof _ref$ === "function" ? _$use(_ref$, _el$9) : tabList = _el$9;
188
210
  _$insert(_el$9, _$createComponent(For, {
189
211
  get each() {
190
212
  return railEntries();
@@ -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":"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","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,9 +10,9 @@ import { escape as _$escape } from "solid-js/web";
10
10
  var _tmpl$ = ["<span class=\"k2b-calendar-event__title\">", "</span>"],
11
11
  _tmpl$2 = ["<span class=\"k2b-calendar-event__meta\">", "</span>"],
12
12
  _tmpl$3 = ["<span class=\"k2b-calendar-event__description\">", "</span>"],
13
- _tmpl$4 = ["<a", " class=\"k2b-calendar-event\" data-calendar-event", " style=\"", "\"", " aria-label=\"", "\">", "</a>"],
14
- _tmpl$5 = ["<button type=\"button\" class=\"k2b-calendar-event\" data-calendar-event", " data-interactive=\"true\"", " style=\"", "\" aria-label=\"", "\">", "</button>"],
15
- _tmpl$6 = ["<div class=\"k2b-calendar-event\" role=\"group\" data-calendar-event", " style=\"", "\" aria-label=\"", "\">", "</div>"],
13
+ _tmpl$4 = ["<a", " class=\"k2b-calendar-event\" data-calendar-event", " style=\"", "\"", ">", "</a>"],
14
+ _tmpl$5 = ["<button type=\"button\" class=\"k2b-calendar-event\" data-calendar-event", " data-interactive=\"true\"", " style=\"", "\"", ">", "</button>"],
15
+ _tmpl$6 = ["<div class=\"k2b-calendar-event\" role=\"group\" data-calendar-event", " style=\"", "\"", ">", "</div>"],
16
16
  _tmpl$7 = ["<div role=\"radiogroup\"", " aria-orientation=\"horizontal\" class=\"k2b-segmented-control k2b-calendar-view-switcher\">", "</div>"],
17
17
  _tmpl$8 = ["<i class=\"", "\"></i>"],
18
18
  _tmpl$9 = ["<button type=\"button\"", " class=\"k2b-calendar-header__nav-button\"><i class=\"", "\"></i></button>"],
@@ -214,6 +214,7 @@ const timedEventLayouts = events => {
214
214
  }));
215
215
  };
216
216
  const EventChip = props => {
217
+ const messages = useUiMessages();
217
218
  const dateConfig = createMemo(() => ownerDateConfig(props.owner));
218
219
  const color = () => props.event.color ?? "blue";
219
220
  const selected = () => Boolean(props.owner.selectedEventId) && props.owner.selectedEventId === props.event.id;
@@ -227,6 +228,11 @@ const EventChip = props => {
227
228
  const showLocation = () => Boolean(props.event.location && !props.compact && durationHours() >= 1.25);
228
229
  const showDescription = () => Boolean(props.event.description?.trim() && props.fill && !props.event.allDay && !props.compact && durationHours() >= 1.5);
229
230
  const timeLabel = () => `${formatTime(props.event.startDate, dateConfig())} - ${formatTime(props.event.endDate, dateConfig())}`;
231
+ const ariaLabel = () => props.event.allDay ? props.event.title : messages().calendarEventTime({
232
+ title: props.event.title,
233
+ start: formatTime(props.event.startDate, dateConfig()),
234
+ end: formatTime(props.event.endDate, dateConfig())
235
+ });
230
236
  const renderedEvent = () => props.owner.renderEvent?.(props.event, {
231
237
  compact: props.compact ?? false,
232
238
  fill: props.fill ?? false,
@@ -290,7 +296,7 @@ const EventChip = props => {
290
296
  suppressClickUntil = performance.now() + 400;
291
297
  });
292
298
  };
293
- return props.href ? _$ssr(_tmpl$4, _$ssrAttribute("href", _$escape(props.href, true), false), _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-interactive", isInteractive() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-display", _$escape(props.event.display, true), false) + _$ssrAttribute("data-space-item-id", _$escape(props.event.dataSpaceItemId, true), false), _$ssrStyle(style()), _$ssrAttribute("draggable", props.onMovePointerDown ? _$escape(false, true) : _$escape(undefined, true), false), `${_$escape(props.event.title, true)}${props.event.allDay ? "" : `, ${_$escape(formatTime(props.event.startDate, dateConfig()), true)} to ${_$escape(formatTime(props.event.endDate, dateConfig()), true)}`}`, _$escape(content())) : isActionable() ? _$ssr(_tmpl$5, _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-display", _$escape(props.event.display, true), false), _$ssrStyle(style()), `${_$escape(props.event.title, true)}${props.event.allDay ? "" : `, ${_$escape(formatTime(props.event.startDate, dateConfig()), true)} to ${_$escape(formatTime(props.event.endDate, dateConfig()), true)}`}`, _$escape(content())) : _$ssr(_tmpl$6, _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-interactive", _$escape(undefined, true), false) + _$ssrAttribute("data-display", _$escape(props.event.display, true), false), _$ssrStyle(style()), `${_$escape(props.event.title, true)}${props.event.allDay ? "" : `, ${_$escape(formatTime(props.event.startDate, dateConfig()), true)} to ${_$escape(formatTime(props.event.endDate, dateConfig()), true)}`}`, _$escape(content()));
299
+ return props.href ? _$ssr(_tmpl$4, _$ssrAttribute("href", _$escape(props.href, true), false), _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-interactive", isInteractive() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-display", _$escape(props.event.display, true), false) + _$ssrAttribute("data-space-item-id", _$escape(props.event.dataSpaceItemId, true), false), _$ssrStyle(style()), _$ssrAttribute("draggable", props.onMovePointerDown ? _$escape(false, true) : _$escape(undefined, true), false) + _$ssrAttribute("aria-label", _$escape(ariaLabel(), true), false), _$escape(content())) : isActionable() ? _$ssr(_tmpl$5, _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-display", _$escape(props.event.display, true), false), _$ssrStyle(style()), _$ssrAttribute("aria-label", _$escape(ariaLabel(), true), false), _$escape(content())) : _$ssr(_tmpl$6, _$ssrAttribute("data-color", props.event.colorHex ? _$escape(undefined, true) : _$escape(color(), true), false) + _$ssrAttribute("data-selected", selected() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-compact", props.compact ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-fill", props.fill ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-short", short() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-moving", props.moving ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-interactive", _$escape(undefined, true), false) + _$ssrAttribute("data-display", _$escape(props.event.display, true), false), _$ssrStyle(style()), _$ssrAttribute("aria-label", _$escape(ariaLabel(), true), false), _$escape(content()));
294
300
  };
295
301
  const slotInteractionProps = (owner, slot, suppressed, nativeControl = false) => {
296
302
  const isSlotChild = event => {
@@ -613,7 +619,7 @@ const MonthView = props => {
613
619
  });
614
620
  };
615
621
  onCleanup(() => cancelInteraction?.());
616
- return _$ssr(_tmpl$12, _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, minmax(5rem, 1fr))`), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
622
+ return _$ssr(_tmpl$12, _$ssrStyleProperty("grid-template-rows:", `auto repeat(${_$escape(weeks().length, true)}, ${props.compact ? "minmax(2.75rem, auto)" : "minmax(5rem, 1fr)"})`), _$ssrAttribute("data-week-numbers", props.owner.withWeekNumbers ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
617
623
  get when() {
618
624
  return props.owner.withWeekNumbers;
619
625
  },
@@ -1348,7 +1354,8 @@ const MobileMonthView = props => {
1348
1354
  },
1349
1355
  get labels() {
1350
1356
  return props.labels;
1351
- }
1357
+ },
1358
+ compact: true
1352
1359
  })), _$escape(props.selectedDate.toLocaleDateString(dateConfig().locale ?? "en", {
1353
1360
  weekday: "long",
1354
1361
  month: "long",