@askrjs/themes 0.0.7 → 0.0.9

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 (51) hide show
  1. package/THEMING.md +5 -1
  2. package/dist/components/_internal/box-layout.js +1 -1
  3. package/dist/components/_internal/classes.js.map +1 -1
  4. package/dist/components/_internal/jsx.js.map +1 -1
  5. package/dist/components/_internal/layout.js +2 -7
  6. package/dist/components/_internal/layout.js.map +1 -1
  7. package/dist/components/_internal/style.js +25 -1
  8. package/dist/components/_internal/style.js.map +1 -1
  9. package/dist/components/aspect-ratio/aspect-ratio.js +1 -1
  10. package/dist/components/block/block.js.map +1 -1
  11. package/dist/components/container/container.js.map +1 -1
  12. package/dist/components/flex/flex.js.map +1 -1
  13. package/dist/components/nav/nav.js.map +1 -1
  14. package/dist/components/navbar/navbar-panel.js +10 -16
  15. package/dist/components/navbar/navbar-panel.js.map +1 -1
  16. package/dist/components/navbar/navbar.js +23 -12
  17. package/dist/components/navbar/navbar.js.map +1 -1
  18. package/dist/components/section/section.js.map +1 -1
  19. package/dist/components/shell/shell-responsive.js +51 -20
  20. package/dist/components/shell/shell-responsive.js.map +1 -1
  21. package/dist/components/sidebar/sidebar-panel.js +14 -24
  22. package/dist/components/sidebar/sidebar-panel.js.map +1 -1
  23. package/dist/components/sidebar/sidebar.js +38 -24
  24. package/dist/components/sidebar/sidebar.js.map +1 -1
  25. package/dist/components/spacer/spacer.js +1 -1
  26. package/dist/components/spacer/spacer.js.map +1 -1
  27. package/dist/components/theme/theme.js +55 -13
  28. package/dist/components/theme/theme.js.map +1 -1
  29. package/dist/themes/default/index.css +35 -3
  30. package/package.json +11 -10
  31. package/src/components/_internal/jsx.ts +18 -6
  32. package/src/components/_internal/layout.ts +3 -12
  33. package/src/components/_internal/style.ts +42 -4
  34. package/src/components/navbar/navbar-panel.tsx +11 -16
  35. package/src/components/navbar/navbar.tsx +32 -17
  36. package/src/components/shell/shell-responsive.tsx +79 -29
  37. package/src/components/sidebar/sidebar-panel.tsx +15 -24
  38. package/src/components/sidebar/sidebar.tsx +52 -34
  39. package/src/components/theme/theme.tsx +88 -16
  40. package/src/themes/default/styles/actions/button.css +16 -0
  41. package/src/themes/default/styles/display/avatar.css +7 -1
  42. package/src/themes/default/styles/display/badge.css +2 -1
  43. package/src/themes/default/styles/display/table.css +2 -0
  44. package/src/themes/default/styles/forms/select.css +6 -0
  45. package/src/themes/default/styles/shell/navbar.css +2 -1
  46. package/templates/theme/styles/actions/button.css +16 -0
  47. package/templates/theme/styles/display/avatar.css +7 -1
  48. package/templates/theme/styles/display/badge.css +2 -1
  49. package/templates/theme/styles/display/table.css +2 -0
  50. package/templates/theme/styles/forms/select.css +6 -0
  51. package/templates/theme/styles/shell/navbar.css +2 -1
@@ -24,39 +24,70 @@ function releaseShellScrollLock() {
24
24
  function isShellPanelChild(child, panelComponent) {
25
25
  return isJsxElement(child) && child.type === panelComponent;
26
26
  }
27
- function renderKeyedShellChildren(children, keyPrefix) {
28
- const keyedChildren = toChildArray(children).map((child, index) => {
29
- if (!isJsxElement(child) || child.key != null) return child;
30
- return {
31
- ...child,
32
- key: `${keyPrefix}-${index}`
33
- };
34
- });
35
- return /* @__PURE__ */ jsx(For, {
36
- each: () => keyedChildren,
37
- by: (child, index) => isJsxElement(child) && child.key != null ? String(child.key) : `${keyPrefix}-${index}`,
38
- children: (child) => child
39
- });
27
+ function renderShellChildKey(child, index, keyPrefix) {
28
+ return isJsxElement(child) && child.key != null ? String(child.key) : `${keyPrefix}-${index}`;
40
29
  }
41
- function renderKeyedShellPanelChildren(children, keyPrefix, panelProps) {
42
- const keyedChildren = toChildArray(children).map((child, index) => {
43
- if (!isJsxElement(child)) return child;
44
- return {
30
+ function keyMissingShellChildren(children, keyPrefix) {
31
+ let keyedChildren;
32
+ for (let index = 0; index < children.length; index += 1) {
33
+ const child = children[index];
34
+ if (isJsxElement(child) && child.key == null) {
35
+ keyedChildren ??= children.slice(0, index);
36
+ keyedChildren.push({
37
+ ...child,
38
+ key: `${keyPrefix}-${index}`
39
+ });
40
+ continue;
41
+ }
42
+ keyedChildren?.push(child);
43
+ }
44
+ return keyedChildren ?? children;
45
+ }
46
+ function hasPanelProps(props, panelProps) {
47
+ return props?.active === panelProps.active && props?.collapseLabel === panelProps.collapseLabel && props?.onClose === panelProps.onClose && props?.open === panelProps.open && props?.panelId === panelProps.panelId;
48
+ }
49
+ function applyShellPanelProps(children, keyPrefix, panelProps) {
50
+ let panelChildren;
51
+ for (let index = 0; index < children.length; index += 1) {
52
+ const child = children[index];
53
+ if (!isJsxElement(child)) {
54
+ panelChildren?.push(child);
55
+ continue;
56
+ }
57
+ const props = child.props;
58
+ if (hasPanelProps(props, panelProps)) {
59
+ panelChildren?.push(child);
60
+ continue;
61
+ }
62
+ panelChildren ??= children.slice(0, index);
63
+ panelChildren.push({
45
64
  ...child,
46
65
  key: child.key != null ? child.key : `${keyPrefix}-${index}`,
47
66
  props: {
48
- ...child.props,
67
+ ...props,
49
68
  active: panelProps.active,
50
69
  collapseLabel: panelProps.collapseLabel,
51
70
  onClose: panelProps.onClose,
52
71
  open: panelProps.open,
53
72
  panelId: panelProps.panelId
54
73
  }
55
- };
74
+ });
75
+ }
76
+ return panelChildren ?? children;
77
+ }
78
+ function renderKeyedShellChildren(children, keyPrefix) {
79
+ const keyedChildren = keyMissingShellChildren(toChildArray(children), keyPrefix);
80
+ return /* @__PURE__ */ jsx(For, {
81
+ each: () => keyedChildren,
82
+ by: (child, index) => renderShellChildKey(child, index, keyPrefix),
83
+ children: (child) => child
56
84
  });
85
+ }
86
+ function renderKeyedShellPanelChildren(children, keyPrefix, panelProps) {
87
+ const keyedChildren = applyShellPanelProps(toChildArray(children), keyPrefix, panelProps);
57
88
  return /* @__PURE__ */ jsx(For, {
58
89
  each: () => keyedChildren,
59
- by: (child, index) => isJsxElement(child) && child.key != null ? String(child.key) : `${keyPrefix}-${index}`,
90
+ by: (child, index) => renderShellChildKey(child, index, keyPrefix),
60
91
  children: (child) => child
61
92
  });
62
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shell-responsive.js","names":[],"sources":["../../../src/components/shell/shell-responsive.tsx"],"sourcesContent":["import { For } from \"@askrjs/askr/control\";\nimport { resource } from \"@askrjs/askr/resources\";\nimport type { JSXElement } from \"@askrjs/askr/foundations\";\nimport { isJsxElement, toChildArray } from \"../_internal/jsx\";\n\nexport type ShellResponsivePanelProps = {\n active: boolean;\n collapseLabel: string;\n onClose: () => void;\n open: boolean;\n panelId?: string;\n};\n\nlet shellScrollLockCount = 0;\nlet shellScrollLockPreviousValue: string | null = null;\n\nfunction acquireShellScrollLock(): void {\n if (typeof document === \"undefined\") return;\n\n const body = document.body;\n if (shellScrollLockCount === 0) {\n shellScrollLockPreviousValue = body.getAttribute(\"data-shell-scroll-lock\");\n }\n\n shellScrollLockCount += 1;\n body.setAttribute(\"data-shell-scroll-lock\", \"true\");\n}\n\nfunction releaseShellScrollLock(): void {\n if (typeof document === \"undefined\" || shellScrollLockCount === 0) return;\n\n shellScrollLockCount -= 1;\n if (shellScrollLockCount > 0) return;\n\n const body = document.body;\n if (shellScrollLockPreviousValue === null) {\n body.removeAttribute(\"data-shell-scroll-lock\");\n } else {\n body.setAttribute(\"data-shell-scroll-lock\", shellScrollLockPreviousValue);\n }\n\n shellScrollLockPreviousValue = null;\n}\n\nexport function isShellPanelChild(child: unknown, panelComponent: unknown): child is JSXElement {\n return isJsxElement(child) && child.type === panelComponent;\n}\n\nexport function renderKeyedShellChildren(children: unknown, keyPrefix: string): JSX.Element {\n const keyedChildren = toChildArray(children).map((child, index) => {\n if (!isJsxElement(child) || child.key != null) {\n return child;\n }\n\n return {\n ...child,\n key: `${keyPrefix}-${index}`,\n };\n });\n\n return (\n <For\n each={() => keyedChildren}\n by={(child, index) =>\n isJsxElement(child) && child.key != null ? String(child.key) : `${keyPrefix}-${index}`\n }\n >\n {(child) => child as never}\n </For>\n );\n}\n\nexport function renderKeyedShellPanelChildren(\n children: unknown,\n keyPrefix: string,\n panelProps: ShellResponsivePanelProps,\n): JSX.Element {\n const keyedChildren = toChildArray(children).map((child, index) => {\n if (!isJsxElement(child)) {\n return child;\n }\n\n return {\n ...child,\n key: child.key != null ? child.key : `${keyPrefix}-${index}`,\n props: {\n ...child.props,\n active: panelProps.active,\n collapseLabel: panelProps.collapseLabel,\n onClose: panelProps.onClose,\n open: panelProps.open,\n panelId: panelProps.panelId,\n },\n };\n });\n\n return (\n <For\n each={() => keyedChildren}\n by={(child, index) =>\n isJsxElement(child) && child.key != null ? String(child.key) : `${keyPrefix}-${index}`\n }\n >\n {(child) => child as never}\n </For>\n );\n}\n\nexport function ShellResponsiveWatcher<TBreakpoint extends string>(props: {\n breakpoint: TBreakpoint;\n isCollapsed: (breakpoint: TBreakpoint) => boolean;\n onExpand: () => void;\n onResize: (nextCollapsed: boolean) => void;\n}): JSX.Element | null {\n const { breakpoint, isCollapsed, onExpand, onResize } = props;\n\n resource(\n ({ signal }: { signal: AbortSignal }) => {\n const updateCollapsedState = () => {\n const nextCollapsed = isCollapsed(breakpoint);\n onResize(nextCollapsed);\n\n if (!nextCollapsed) {\n onExpand();\n }\n };\n\n updateCollapsedState();\n\n if (typeof window === \"undefined\") {\n return null;\n }\n\n window.addEventListener(\"resize\", updateCollapsedState);\n signal.addEventListener(\n \"abort\",\n () => {\n window.removeEventListener(\"resize\", updateCollapsedState);\n },\n { once: true },\n );\n\n return null;\n },\n [breakpoint],\n );\n\n return null;\n}\n\nexport function ShellPanelWatcher(props: {\n contentId?: string;\n onClose: () => void;\n open: boolean;\n panelSlot: string;\n}): JSX.Element | null {\n const { contentId, onClose, open, panelSlot } = props;\n\n resource(\n ({ signal }: { signal: AbortSignal }) => {\n if (!open || typeof window === \"undefined\") {\n releaseShellScrollLock();\n return null;\n }\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") {\n return;\n }\n\n event.preventDefault();\n onClose();\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n\n const focusFrame =\n typeof window.requestAnimationFrame === \"function\"\n ? window.requestAnimationFrame(() => {\n const content =\n (typeof contentId === \"string\" ? document.getElementById(contentId) : null) ??\n document.querySelector<HTMLElement>(\n `[data-slot=\"${panelSlot}\"][data-state=\"open\"]`,\n );\n\n content?.focus({ preventScroll: true });\n })\n : undefined;\n\n acquireShellScrollLock();\n\n signal.addEventListener(\n \"abort\",\n () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n\n if (focusFrame !== undefined && typeof window.cancelAnimationFrame === \"function\") {\n window.cancelAnimationFrame(focusFrame);\n }\n\n releaseShellScrollLock();\n },\n { once: true },\n );\n\n return null;\n },\n [open],\n );\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shell-responsive.js","names":[],"sources":["../../../src/components/shell/shell-responsive.tsx"],"sourcesContent":["import { For } from \"@askrjs/askr/control\";\nimport { resource } from \"@askrjs/askr/resources\";\nimport type { JSXElement } from \"@askrjs/askr/foundations\";\nimport { isJsxElement, toChildArray } from \"../_internal/jsx\";\n\nexport type ShellResponsivePanelProps = {\n active: boolean;\n collapseLabel: string;\n onClose: () => void;\n open: boolean;\n panelId?: string;\n};\n\nlet shellScrollLockCount = 0;\nlet shellScrollLockPreviousValue: string | null = null;\n\nfunction acquireShellScrollLock(): void {\n if (typeof document === \"undefined\") return;\n\n const body = document.body;\n if (shellScrollLockCount === 0) {\n shellScrollLockPreviousValue = body.getAttribute(\"data-shell-scroll-lock\");\n }\n\n shellScrollLockCount += 1;\n body.setAttribute(\"data-shell-scroll-lock\", \"true\");\n}\n\nfunction releaseShellScrollLock(): void {\n if (typeof document === \"undefined\" || shellScrollLockCount === 0) return;\n\n shellScrollLockCount -= 1;\n if (shellScrollLockCount > 0) return;\n\n const body = document.body;\n if (shellScrollLockPreviousValue === null) {\n body.removeAttribute(\"data-shell-scroll-lock\");\n } else {\n body.setAttribute(\"data-shell-scroll-lock\", shellScrollLockPreviousValue);\n }\n\n shellScrollLockPreviousValue = null;\n}\n\nexport function isShellPanelChild(child: unknown, panelComponent: unknown): child is JSXElement {\n return isJsxElement(child) && child.type === panelComponent;\n}\n\nfunction renderShellChildKey(child: unknown, index: number, keyPrefix: string): string {\n return isJsxElement(child) && child.key != null ? String(child.key) : `${keyPrefix}-${index}`;\n}\n\nfunction keyMissingShellChildren(children: unknown[], keyPrefix: string): unknown[] {\n let keyedChildren: unknown[] | undefined;\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index];\n\n if (isJsxElement(child) && child.key == null) {\n keyedChildren ??= children.slice(0, index);\n keyedChildren.push({\n ...child,\n key: `${keyPrefix}-${index}`,\n });\n continue;\n }\n\n keyedChildren?.push(child);\n }\n\n return keyedChildren ?? children;\n}\n\nfunction hasPanelProps(\n props: Record<string, unknown> | undefined,\n panelProps: ShellResponsivePanelProps,\n): boolean {\n return (\n props?.active === panelProps.active &&\n props?.collapseLabel === panelProps.collapseLabel &&\n props?.onClose === panelProps.onClose &&\n props?.open === panelProps.open &&\n props?.panelId === panelProps.panelId\n );\n}\n\nfunction applyShellPanelProps(\n children: unknown[],\n keyPrefix: string,\n panelProps: ShellResponsivePanelProps,\n): unknown[] {\n let panelChildren: unknown[] | undefined;\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index];\n\n if (!isJsxElement(child)) {\n panelChildren?.push(child);\n continue;\n }\n\n const props = child.props as Record<string, unknown> | undefined;\n\n if (hasPanelProps(props, panelProps)) {\n panelChildren?.push(child);\n continue;\n }\n\n panelChildren ??= children.slice(0, index);\n panelChildren.push({\n ...child,\n key: child.key != null ? child.key : `${keyPrefix}-${index}`,\n props: {\n ...props,\n active: panelProps.active,\n collapseLabel: panelProps.collapseLabel,\n onClose: panelProps.onClose,\n open: panelProps.open,\n panelId: panelProps.panelId,\n },\n });\n }\n\n return panelChildren ?? children;\n}\n\nexport function renderKeyedShellChildren(children: unknown, keyPrefix: string): JSX.Element {\n const childList = toChildArray(children);\n const keyedChildren = keyMissingShellChildren(childList, keyPrefix);\n\n return (\n <For\n each={() => keyedChildren}\n by={(child, index) => renderShellChildKey(child, index, keyPrefix)}\n >\n {(child) => child as never}\n </For>\n );\n}\n\nexport function renderKeyedShellPanelChildren(\n children: unknown,\n keyPrefix: string,\n panelProps: ShellResponsivePanelProps,\n): JSX.Element {\n const childList = toChildArray(children);\n const keyedChildren = applyShellPanelProps(childList, keyPrefix, panelProps);\n\n return (\n <For\n each={() => keyedChildren}\n by={(child, index) => renderShellChildKey(child, index, keyPrefix)}\n >\n {(child) => child as never}\n </For>\n );\n}\n\nexport function ShellResponsiveWatcher<TBreakpoint extends string>(props: {\n breakpoint: TBreakpoint;\n isCollapsed: (breakpoint: TBreakpoint) => boolean;\n onExpand: () => void;\n onResize: (nextCollapsed: boolean) => void;\n}): JSX.Element | null {\n const { breakpoint, isCollapsed, onExpand, onResize } = props;\n\n resource(\n ({ signal }: { signal: AbortSignal }) => {\n const updateCollapsedState = () => {\n const nextCollapsed = isCollapsed(breakpoint);\n onResize(nextCollapsed);\n\n if (!nextCollapsed) {\n onExpand();\n }\n };\n\n updateCollapsedState();\n\n if (typeof window === \"undefined\") {\n return null;\n }\n\n window.addEventListener(\"resize\", updateCollapsedState);\n signal.addEventListener(\n \"abort\",\n () => {\n window.removeEventListener(\"resize\", updateCollapsedState);\n },\n { once: true },\n );\n\n return null;\n },\n [breakpoint],\n );\n\n return null;\n}\n\nexport function ShellPanelWatcher(props: {\n contentId?: string;\n onClose: () => void;\n open: boolean;\n panelSlot: string;\n}): JSX.Element | null {\n const { contentId, onClose, open, panelSlot } = props;\n\n resource(\n ({ signal }: { signal: AbortSignal }) => {\n if (!open || typeof window === \"undefined\") {\n releaseShellScrollLock();\n return null;\n }\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") {\n return;\n }\n\n event.preventDefault();\n onClose();\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n\n const focusFrame =\n typeof window.requestAnimationFrame === \"function\"\n ? window.requestAnimationFrame(() => {\n const content =\n (typeof contentId === \"string\" ? document.getElementById(contentId) : null) ??\n document.querySelector<HTMLElement>(\n `[data-slot=\"${panelSlot}\"][data-state=\"open\"]`,\n );\n\n content?.focus({ preventScroll: true });\n })\n : undefined;\n\n acquireShellScrollLock();\n\n signal.addEventListener(\n \"abort\",\n () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n\n if (focusFrame !== undefined && typeof window.cancelAnimationFrame === \"function\") {\n window.cancelAnimationFrame(focusFrame);\n }\n\n releaseShellScrollLock();\n },\n { once: true },\n );\n\n return null;\n },\n [open],\n );\n\n return null;\n}\n"],"mappings":"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"}
@@ -2,37 +2,27 @@ import { renderShellPanel } from "../shell/shell-panel.js";
2
2
  import { SidebarResponsiveContext } from "./sidebar.context.js";
3
3
  import { readContext } from "@askrjs/askr";
4
4
  //#region src/components/sidebar/sidebar-panel.tsx
5
+ const DEFAULT_SIDEBAR_RESPONSIVE_CONTEXT = {
6
+ active: () => false,
7
+ collapseLabel: () => "Menu",
8
+ closePanel: () => void 0,
9
+ iconCollapsed: () => false,
10
+ isRailCollapsible: () => false,
11
+ orientation: () => "vertical",
12
+ panelId: () => void 0,
13
+ panelOpen: () => false,
14
+ togglePanel: () => void 0,
15
+ toggleRail: () => void 0
16
+ };
5
17
  function SidebarPanel(props) {
6
18
  const { active: activeProp, brand, children, class: className, collapseLabel: collapseLabelProp, onClose, open: openProp, panelId: panelIdProp, ref, ...rest } = props;
7
19
  const responsive = activeProp === void 0 || collapseLabelProp === void 0 || onClose === void 0 || openProp === void 0 || panelIdProp === void 0 ? (() => {
8
20
  try {
9
21
  return readContext(SidebarResponsiveContext);
10
22
  } catch {
11
- return {
12
- active: () => false,
13
- collapseLabel: () => "Menu",
14
- closePanel: () => void 0,
15
- iconCollapsed: () => false,
16
- isRailCollapsible: () => false,
17
- orientation: () => "vertical",
18
- panelId: () => void 0,
19
- panelOpen: () => false,
20
- togglePanel: () => void 0,
21
- toggleRail: () => void 0
22
- };
23
+ return DEFAULT_SIDEBAR_RESPONSIVE_CONTEXT;
23
24
  }
24
- })() : {
25
- active: () => false,
26
- collapseLabel: () => "Menu",
27
- closePanel: () => void 0,
28
- iconCollapsed: () => false,
29
- isRailCollapsible: () => false,
30
- orientation: () => "vertical",
31
- panelId: () => void 0,
32
- panelOpen: () => false,
33
- togglePanel: () => void 0,
34
- toggleRail: () => void 0
35
- };
25
+ })() : DEFAULT_SIDEBAR_RESPONSIVE_CONTEXT;
36
26
  const active = activeProp ?? responsive.active();
37
27
  const open = openProp ?? responsive.panelOpen();
38
28
  const panelId = panelIdProp ?? responsive.panelId();
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-panel.js","names":[],"sources":["../../../src/components/sidebar/sidebar-panel.tsx"],"sourcesContent":["import { readContext } from \"@askrjs/askr\";\nimport { renderShellPanel } from \"../shell/shell-panel\";\nimport { SidebarResponsiveContext } from \"./sidebar.context\";\nimport type { SidebarPanelProps } from \"./sidebar.types\";\n\nexport function SidebarPanel(props: SidebarPanelProps): JSX.Element | null {\n const {\n active: activeProp,\n brand,\n children,\n class: className,\n collapseLabel: collapseLabelProp,\n onClose,\n open: openProp,\n panelId: panelIdProp,\n ref,\n ...rest\n } = props;\n const needsResponsiveContext =\n activeProp === undefined ||\n collapseLabelProp === undefined ||\n onClose === undefined ||\n openProp === undefined ||\n panelIdProp === undefined;\n const responsive = needsResponsiveContext\n ? (() => {\n try {\n return readContext(SidebarResponsiveContext);\n } catch {\n return {\n active: () => false,\n collapseLabel: () => \"Menu\",\n closePanel: () => undefined,\n iconCollapsed: () => false,\n isRailCollapsible: () => false,\n orientation: () => \"vertical\" as const,\n panelId: () => undefined,\n panelOpen: () => false,\n togglePanel: () => undefined,\n toggleRail: () => undefined,\n };\n }\n })()\n : {\n active: () => false,\n collapseLabel: () => \"Menu\",\n closePanel: () => undefined,\n iconCollapsed: () => false,\n isRailCollapsible: () => false,\n orientation: () => \"vertical\" as const,\n panelId: () => undefined,\n panelOpen: () => false,\n togglePanel: () => undefined,\n toggleRail: () => undefined,\n };\n const active = activeProp ?? responsive.active();\n const open = openProp ?? responsive.panelOpen();\n const panelId = panelIdProp ?? responsive.panelId();\n const collapseLabel = collapseLabelProp ?? responsive.collapseLabel();\n const closePanel = onClose ?? responsive.closePanel;\n\n return renderShellPanel({\n active,\n brand,\n children,\n className,\n collapseLabel,\n dataOrientation: responsive.orientation(),\n onClose: closePanel,\n open,\n panelId,\n prefix: \"sidebar\",\n ref,\n rest,\n });\n}\n"],"mappings":";;;;AAKA,SAAgB,aAAa,OAA8C;CACzE,MAAM,EACJ,QAAQ,YACR,OACA,UACA,OAAO,WACP,eAAe,mBACf,SACA,MAAM,UACN,SAAS,aACT,KACA,GAAG,SACD;CAOJ,MAAM,aALJ,eAAe,KAAA,KACf,sBAAsB,KAAA,KACtB,YAAY,KAAA,KACZ,aAAa,KAAA,KACb,gBAAgB,KAAA,WAEP;EACL,IAAI;GACF,OAAO,YAAY,wBAAwB;EAC7C,QAAQ;GACN,OAAO;IACL,cAAc;IACd,qBAAqB;IACrB,kBAAkB,KAAA;IAClB,qBAAqB;IACrB,yBAAyB;IACzB,mBAAmB;IACnB,eAAe,KAAA;IACf,iBAAiB;IACjB,mBAAmB,KAAA;IACnB,kBAAkB,KAAA;GACpB;EACF;CACF,GAAG,IACH;EACE,cAAc;EACd,qBAAqB;EACrB,kBAAkB,KAAA;EAClB,qBAAqB;EACrB,yBAAyB;EACzB,mBAAmB;EACnB,eAAe,KAAA;EACf,iBAAiB;EACjB,mBAAmB,KAAA;EACnB,kBAAkB,KAAA;CACpB;CACJ,MAAM,SAAS,cAAc,WAAW,OAAO;CAC/C,MAAM,OAAO,YAAY,WAAW,UAAU;CAC9C,MAAM,UAAU,eAAe,WAAW,QAAQ;CAClD,MAAM,gBAAgB,qBAAqB,WAAW,cAAc;CACpE,MAAM,aAAa,WAAW,WAAW;CAEzC,OAAO,iBAAiB;EACtB;EACA;EACA;EACA;EACA;EACA,iBAAiB,WAAW,YAAY;EACxC,SAAS;EACT;EACA;EACA,QAAQ;EACR;EACA;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"sidebar-panel.js","names":[],"sources":["../../../src/components/sidebar/sidebar-panel.tsx"],"sourcesContent":["import { readContext } from \"@askrjs/askr\";\nimport { renderShellPanel } from \"../shell/shell-panel\";\nimport { SidebarResponsiveContext } from \"./sidebar.context\";\nimport type { SidebarPanelProps } from \"./sidebar.types\";\n\nconst DEFAULT_SIDEBAR_RESPONSIVE_CONTEXT = {\n active: () => false,\n collapseLabel: () => \"Menu\",\n closePanel: () => undefined,\n iconCollapsed: () => false,\n isRailCollapsible: () => false,\n orientation: () => \"vertical\" as const,\n panelId: () => undefined,\n panelOpen: () => false,\n togglePanel: () => undefined,\n toggleRail: () => undefined,\n};\n\nexport function SidebarPanel(props: SidebarPanelProps): JSX.Element | null {\n const {\n active: activeProp,\n brand,\n children,\n class: className,\n collapseLabel: collapseLabelProp,\n onClose,\n open: openProp,\n panelId: panelIdProp,\n ref,\n ...rest\n } = props;\n const needsResponsiveContext =\n activeProp === undefined ||\n collapseLabelProp === undefined ||\n onClose === undefined ||\n openProp === undefined ||\n panelIdProp === undefined;\n const responsive = needsResponsiveContext\n ? (() => {\n try {\n return readContext(SidebarResponsiveContext);\n } catch {\n return DEFAULT_SIDEBAR_RESPONSIVE_CONTEXT;\n }\n })()\n : DEFAULT_SIDEBAR_RESPONSIVE_CONTEXT;\n const active = activeProp ?? responsive.active();\n const open = openProp ?? responsive.panelOpen();\n const panelId = panelIdProp ?? responsive.panelId();\n const collapseLabel = collapseLabelProp ?? responsive.collapseLabel();\n const closePanel = onClose ?? responsive.closePanel;\n\n return renderShellPanel({\n active,\n brand,\n children,\n className,\n collapseLabel,\n dataOrientation: responsive.orientation(),\n onClose: closePanel,\n open,\n panelId,\n prefix: \"sidebar\",\n ref,\n rest,\n });\n}\n"],"mappings":";;;;AAKA,MAAM,qCAAqC;CACzC,cAAc;CACd,qBAAqB;CACrB,kBAAkB,KAAA;CAClB,qBAAqB;CACrB,yBAAyB;CACzB,mBAAmB;CACnB,eAAe,KAAA;CACf,iBAAiB;CACjB,mBAAmB,KAAA;CACnB,kBAAkB,KAAA;AACpB;AAEA,SAAgB,aAAa,OAA8C;CACzE,MAAM,EACJ,QAAQ,YACR,OACA,UACA,OAAO,WACP,eAAe,mBACf,SACA,MAAM,UACN,SAAS,aACT,KACA,GAAG,SACD;CAOJ,MAAM,aALJ,eAAe,KAAA,KACf,sBAAsB,KAAA,KACtB,YAAY,KAAA,KACZ,aAAa,KAAA,KACb,gBAAgB,KAAA,WAEP;EACL,IAAI;GACF,OAAO,YAAY,wBAAwB;EAC7C,QAAQ;GACN,OAAO;EACT;CACF,EAAA,CAAG,IACH;CACJ,MAAM,SAAS,cAAc,WAAW,OAAO;CAC/C,MAAM,OAAO,YAAY,WAAW,UAAU;CAC9C,MAAM,UAAU,eAAe,WAAW,QAAQ;CAClD,MAAM,gBAAgB,qBAAqB,WAAW,cAAc;CACpE,MAAM,aAAa,WAAW,WAAW;CAEzC,OAAO,iBAAiB;EACtB;EACA;EACA;EACA;EACA;EACA,iBAAiB,WAAW,YAAY;EACxC,SAAS;EACT;EACA;EACA,QAAQ;EACR;EACA;CACF,CAAC;AACH"}
@@ -10,24 +10,42 @@ import { isSidebarCollapsed, resolveSidebarCollapsible } from "./sidebar.shared.
10
10
  import { Fragment, jsx, jsxs } from "@askrjs/askr/jsx-runtime";
11
11
  import { state } from "@askrjs/askr";
12
12
  //#region src/components/sidebar/sidebar.tsx
13
- function splitSidebarChildren(children) {
14
- const brandIndex = children.findIndex((child) => isJsxElement(child) && child.type === NavBrand);
15
- if (brandIndex === -1) return { items: children };
16
- return {
17
- brand: children[brandIndex],
18
- items: children.filter((_, index) => index !== brandIndex)
19
- };
20
- }
21
13
  function isSidebarToggleChild(child) {
22
14
  return isJsxElement(child) && child.type === SidebarToggle;
23
15
  }
24
- function splitSidebarToggle(children) {
25
- const toggleIndex = children.findIndex((child) => isSidebarToggleChild(child));
26
- if (toggleIndex === -1) return { items: children };
27
- const toggleChild = children[toggleIndex];
16
+ function splitSidebarChildren(children) {
17
+ const explicitPanelItems = [];
18
+ const drawerSourceItems = [];
19
+ let drawerItems;
20
+ let brand;
21
+ let hasBrand = false;
22
+ let hasToggle = false;
23
+ let toggle;
24
+ for (const child of children) {
25
+ if (isShellPanelChild(child, SidebarPanel)) {
26
+ explicitPanelItems.push(child);
27
+ continue;
28
+ }
29
+ if (!hasToggle && isSidebarToggleChild(child)) {
30
+ hasToggle = true;
31
+ toggle = child?.props;
32
+ continue;
33
+ }
34
+ drawerSourceItems.push(child);
35
+ if (!hasBrand && isJsxElement(child) && child.type === NavBrand) {
36
+ brand = child;
37
+ hasBrand = true;
38
+ drawerItems ??= drawerSourceItems.slice(0, drawerSourceItems.length - 1);
39
+ continue;
40
+ }
41
+ drawerItems?.push(child);
42
+ }
28
43
  return {
29
- items: children.filter((_, index) => index !== toggleIndex),
30
- toggle: toggleChild?.props
44
+ brand: hasBrand ? brand : void 0,
45
+ drawerItems: drawerItems ?? drawerSourceItems,
46
+ drawerSourceItems,
47
+ explicitPanelItems,
48
+ toggle
31
49
  };
32
50
  }
33
51
  function renderSidebarMenuContents(label, icon, iconPlacement) {
@@ -67,9 +85,7 @@ function renderSidebarRailContents(label, collapsed, toggle) {
67
85
  function Sidebar(props) {
68
86
  const { children, collapsed: controlledCollapsed, breakpoint, collapseIcon, collapseIconPlacement = "start", collapseLabel, collapsible, defaultCollapsed = false, id, "aria-label": ariaLabel, onCollapsedChange, class: className, ref, ...rest } = props;
69
87
  const effectiveCollapseLabel = collapseLabel ?? (typeof ariaLabel === "string" ? ariaLabel : void 0) ?? "Menu";
70
- const childItems = toChildArray(children);
71
- const explicitPanelItems = childItems.filter((child) => isShellPanelChild(child, SidebarPanel));
72
- const contentItems = childItems.filter((child) => !isShellPanelChild(child, SidebarPanel));
88
+ const sidebarChildren = splitSidebarChildren(toChildArray(children));
73
89
  const isResponsive = breakpoint !== void 0;
74
90
  const responsiveCollapsedState = state(isResponsive ? isSidebarCollapsed(breakpoint) : false);
75
91
  const drawerOpenState = state(false);
@@ -101,10 +117,8 @@ function Sidebar(props) {
101
117
  if (!isRailCollapsible) return;
102
118
  setRailCollapsed(!isRailCollapsed);
103
119
  };
104
- const { items: drawerSourceItems, toggle: railToggleConfig } = splitSidebarToggle(contentItems);
105
- const { brand: drawerBrand, items: drawerItems } = splitSidebarChildren(drawerSourceItems);
106
- const desktopChildren = renderKeyedShellChildren(drawerSourceItems, "sidebar-desktop");
107
- const drawerChildren = renderKeyedShellChildren(drawerItems, "sidebar-drawer");
120
+ const desktopChildren = renderKeyedShellChildren(sidebarChildren.drawerSourceItems, "sidebar-desktop");
121
+ const drawerChildren = renderKeyedShellChildren(sidebarChildren.drawerItems, "sidebar-drawer");
108
122
  const contextValue = {
109
123
  active: () => isResponsive,
110
124
  collapseLabel: () => effectiveCollapseLabel,
@@ -124,9 +138,9 @@ function Sidebar(props) {
124
138
  open: isDrawerOpen,
125
139
  panelId
126
140
  };
127
- const panels = explicitPanelItems.length > 0 ? renderKeyedShellPanelChildren(explicitPanelItems, "sidebar-panel", panelContext) : isResponsive ? /* @__PURE__ */ jsx(SidebarPanel, {
141
+ const panels = sidebarChildren.explicitPanelItems.length > 0 ? renderKeyedShellPanelChildren(sidebarChildren.explicitPanelItems, "sidebar-panel", panelContext) : isResponsive ? /* @__PURE__ */ jsx(SidebarPanel, {
128
142
  active: isResponsive,
129
- brand: drawerBrand,
143
+ brand: sidebarChildren.brand,
130
144
  collapseLabel: effectiveCollapseLabel,
131
145
  onClose: closeDrawer,
132
146
  onClick: closeDrawerOnNavActivation,
@@ -185,7 +199,7 @@ function Sidebar(props) {
185
199
  "data-state": isRailCollapsed ? "collapsed" : "expanded",
186
200
  type: "button",
187
201
  onClick: toggleRail,
188
- children: renderSidebarRailContents(effectiveCollapseLabel, isRailCollapsed, railToggleConfig)
202
+ children: renderSidebarRailContents(effectiveCollapseLabel, isRailCollapsed, sidebarChildren.toggle)
189
203
  })
190
204
  }) : null, desktopChildren]
191
205
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.js","names":[],"sources":["../../../src/components/sidebar/sidebar.tsx"],"sourcesContent":["import { state } from \"@askrjs/askr\";\nimport { classes } from \"../_internal/classes\";\nimport { isJsxElement, toChildArray } from \"../_internal/jsx\";\nimport { mergeProps } from \"../_internal/merge-props\";\nimport { NavBrand } from \"../navbar/navbar\";\nimport {\n isShellPanelChild,\n renderKeyedShellChildren,\n renderKeyedShellPanelChildren,\n ShellPanelWatcher,\n ShellResponsiveWatcher,\n} from \"../shell/shell-responsive\";\nimport { SidebarContext, SidebarResponsiveContext } from \"./sidebar.context\";\nimport { SidebarPanel } from \"./sidebar-panel\";\nimport { SidebarToggle } from \"./sidebar-toggle\";\nimport { isSidebarCollapsed, resolveSidebarCollapsible } from \"./sidebar.shared\";\nimport type { SidebarProps } from \"./sidebar.types\";\nimport type { CollapseIconPlacement } from \"../shell/shell-nav.types\";\n\ntype SidebarChildren = {\n brand?: unknown;\n items: unknown[];\n};\n\ntype SidebarToggleConfig = {\n collapsedIcon?: unknown;\n expandedIcon?: unknown;\n};\n\nfunction splitSidebarChildren(children: unknown[]): SidebarChildren {\n const brandIndex = children.findIndex((child) => isJsxElement(child) && child.type === NavBrand);\n\n if (brandIndex === -1) {\n return { items: children };\n }\n\n return {\n brand: children[brandIndex],\n items: children.filter((_, index) => index !== brandIndex),\n };\n}\n\nfunction isSidebarToggleChild(child: unknown): boolean {\n return isJsxElement(child) && child.type === SidebarToggle;\n}\n\nfunction splitSidebarToggle(children: unknown[]): {\n items: unknown[];\n toggle?: SidebarToggleConfig;\n} {\n const toggleIndex = children.findIndex((child) => isSidebarToggleChild(child));\n\n if (toggleIndex === -1) {\n return { items: children };\n }\n\n const toggleChild = children[toggleIndex] as { props?: SidebarToggleConfig } | undefined;\n\n return {\n items: children.filter((_, index) => index !== toggleIndex),\n toggle: toggleChild?.props,\n };\n}\n\nfunction renderSidebarMenuContents(\n label: string,\n icon: unknown,\n iconPlacement: CollapseIconPlacement,\n): JSX.Element {\n const renderedIcon = (\n <span class=\"sidebar-toggle-icon\" data-slot=\"sidebar-toggle-icon\" aria-hidden=\"true\">\n {icon ?? (\n <span class=\"sidebar-toggle-glyph sidebar-toggle-glyph--menu\">\n <span />\n <span />\n <span />\n </span>\n )}\n </span>\n );\n const renderedLabel = (\n <span class=\"sidebar-toggle-label\" data-slot=\"sidebar-toggle-label\">\n {label}\n </span>\n );\n\n if (iconPlacement === \"end\") {\n return (\n <>\n {renderedLabel}\n {renderedIcon}\n </>\n );\n }\n\n return (\n <>\n {renderedIcon}\n {renderedLabel}\n </>\n );\n}\n\nfunction renderSidebarRailContents(\n label: string,\n collapsed: boolean,\n toggle: SidebarToggleConfig | undefined,\n): JSX.Element {\n const icon = collapsed ? toggle?.collapsedIcon : toggle?.expandedIcon;\n\n return (\n <>\n <span\n class=\"sidebar-rail-toggle-icon\"\n data-slot=\"sidebar-rail-toggle-icon\"\n aria-hidden=\"true\"\n >\n {icon ?? (\n <span\n class={classes(\n \"sidebar-toggle-glyph\",\n \"sidebar-toggle-glyph--rail\",\n collapsed ? \"is-collapsed\" : \"is-expanded\",\n )}\n />\n )}\n </span>\n <span class=\"sidebar-rail-toggle-label\" data-slot=\"sidebar-rail-toggle-label\">\n {label}\n </span>\n </>\n );\n}\n\nexport function Sidebar(props: SidebarProps): JSX.Element {\n const {\n children,\n collapsed: controlledCollapsed,\n breakpoint,\n collapseIcon,\n collapseIconPlacement = \"start\",\n collapseLabel,\n collapsible,\n defaultCollapsed = false,\n id,\n \"aria-label\": ariaLabel,\n onCollapsedChange,\n class: className,\n ref,\n ...rest\n } = props;\n const effectiveCollapseLabel =\n collapseLabel ?? (typeof ariaLabel === \"string\" ? ariaLabel : undefined) ?? \"Menu\";\n const childItems = toChildArray(children);\n const explicitPanelItems = childItems.filter((child) => isShellPanelChild(child, SidebarPanel));\n const contentItems = childItems.filter((child) => !isShellPanelChild(child, SidebarPanel));\n const isResponsive = breakpoint !== undefined;\n const responsiveCollapsedState = state(isResponsive ? isSidebarCollapsed(breakpoint) : false);\n const drawerOpenState = state(false);\n const panelId = typeof id === \"string\" ? `${id}-panel` : undefined;\n const collapseBehavior = resolveSidebarCollapsible(collapsible);\n const isRailCollapsible = collapseBehavior === \"icon\";\n const railCollapsedState = state(defaultCollapsed);\n const responsiveCollapsed = responsiveCollapsedState();\n const drawerOpen = drawerOpenState();\n const internalRailCollapsed = railCollapsedState();\n const isMobile = isResponsive ? responsiveCollapsed : false;\n const isDrawerOpen = isResponsive && isMobile && drawerOpen;\n const isRailCollapsed = isRailCollapsible\n ? (controlledCollapsed ?? internalRailCollapsed ?? false)\n : false;\n const closeDrawer = () => drawerOpenState.set(false);\n const closeDrawerOnNavActivation = (event: MouseEvent) => {\n const target = event.target;\n\n if (!(target instanceof Element)) {\n return;\n }\n\n if (target.closest('a[data-slot=\"nav-link\"], a[data-slot=\"nav-item\"], a.navbar-item')) {\n closeDrawer();\n }\n };\n const toggleDrawer = () => {\n drawerOpenState.set(!drawerOpenState());\n };\n const setRailCollapsed = (nextCollapsed: boolean) => {\n if (!isRailCollapsible) {\n return;\n }\n\n if (controlledCollapsed === undefined) {\n railCollapsedState.set(nextCollapsed);\n }\n\n onCollapsedChange?.(nextCollapsed);\n };\n const toggleRail = () => {\n if (!isRailCollapsible) {\n return;\n }\n\n setRailCollapsed(!isRailCollapsed);\n };\n const { items: drawerSourceItems, toggle: railToggleConfig } = splitSidebarToggle(contentItems);\n const { brand: drawerBrand, items: drawerItems } = splitSidebarChildren(drawerSourceItems);\n const desktopChildren = renderKeyedShellChildren(drawerSourceItems, \"sidebar-desktop\");\n const drawerChildren = renderKeyedShellChildren(drawerItems, \"sidebar-drawer\");\n\n const contextValue = {\n active: () => isResponsive,\n collapseLabel: () => effectiveCollapseLabel,\n closePanel: closeDrawer,\n iconCollapsed: () => isRailCollapsed,\n isRailCollapsible: () => isRailCollapsible,\n orientation: () => \"vertical\" as const,\n panelId: () => panelId,\n panelOpen: () => isDrawerOpen,\n togglePanel: toggleDrawer,\n toggleRail,\n };\n const panelContext = {\n active: isResponsive,\n collapseLabel: effectiveCollapseLabel,\n onClose: closeDrawer,\n open: isDrawerOpen,\n panelId,\n };\n const panels =\n explicitPanelItems.length > 0 ? (\n renderKeyedShellPanelChildren(explicitPanelItems, \"sidebar-panel\", panelContext)\n ) : isResponsive ? (\n <SidebarPanel\n active={isResponsive}\n brand={drawerBrand}\n collapseLabel={effectiveCollapseLabel}\n onClose={closeDrawer}\n onClick={closeDrawerOnNavActivation}\n open={isDrawerOpen}\n panelId={panelId}\n >\n {drawerChildren}\n </SidebarPanel>\n ) : null;\n\n const finalProps = mergeProps(rest, {\n ref,\n \"aria-label\": ariaLabel,\n class: classes(\"sidebar\", className),\n \"data-collapse-below\": breakpoint,\n \"data-collapsible\": collapseBehavior === \"none\" ? undefined : collapseBehavior,\n \"data-icon-collapsed\": isRailCollapsible ? (isRailCollapsed ? \"true\" : \"false\") : undefined,\n \"data-mobile-open\": isResponsive ? (drawerOpen ? \"true\" : \"false\") : undefined,\n \"data-orientation\": \"vertical\",\n \"data-responsive-collapsed\": isMobile ? \"true\" : \"false\",\n \"data-slot\": \"sidebar\",\n });\n\n return (\n <SidebarContext.Scope value={{ orientation: () => \"vertical\" as const }}>\n <SidebarResponsiveContext.Scope value={contextValue}>\n <nav {...finalProps}>\n {isResponsive ? (\n <div class=\"sidebar-mobile\" data-slot=\"sidebar-mobile\">\n <button\n aria-controls={panelId}\n aria-expanded={isDrawerOpen ? \"true\" : \"false\"}\n aria-label={effectiveCollapseLabel}\n class=\"sidebar-toggle\"\n data-slot=\"sidebar-toggle\"\n data-state={isDrawerOpen ? \"open\" : \"closed\"}\n data-variant=\"mobile\"\n type=\"button\"\n onClick={toggleDrawer}\n >\n {renderSidebarMenuContents(\n effectiveCollapseLabel,\n collapseIcon,\n collapseIconPlacement,\n )}\n </button>\n </div>\n ) : null}\n\n <div class=\"sidebar-shell\" data-orientation=\"vertical\" data-slot=\"sidebar-shell\">\n {isRailCollapsible && !isMobile ? (\n <div\n class=\"sidebar-rail\"\n data-slot=\"sidebar-rail\"\n data-state={isRailCollapsed ? \"collapsed\" : \"expanded\"}\n >\n <button\n aria-expanded={isRailCollapsed ? \"false\" : \"true\"}\n aria-label={\n isRailCollapsed\n ? `Expand ${effectiveCollapseLabel}`\n : `Collapse ${effectiveCollapseLabel}`\n }\n class=\"sidebar-rail-toggle\"\n data-slot=\"sidebar-rail-toggle\"\n data-state={isRailCollapsed ? \"collapsed\" : \"expanded\"}\n type=\"button\"\n onClick={toggleRail}\n >\n {renderSidebarRailContents(\n effectiveCollapseLabel,\n isRailCollapsed,\n railToggleConfig,\n )}\n </button>\n </div>\n ) : null}\n {desktopChildren}\n </div>\n\n {panels}\n\n {isResponsive && isDrawerOpen ? (\n <button\n aria-label={`Close ${effectiveCollapseLabel}`}\n class=\"sidebar-backdrop\"\n data-slot=\"sidebar-backdrop\"\n data-state=\"open\"\n tabIndex={-1}\n type=\"button\"\n onClick={closeDrawer}\n />\n ) : null}\n\n {isResponsive ? (\n <ShellResponsiveWatcher\n breakpoint={breakpoint}\n isCollapsed={isSidebarCollapsed}\n onResize={(nextCollapsed) => {\n responsiveCollapsedState.set(nextCollapsed);\n }}\n onExpand={() => {\n drawerOpenState.set(false);\n }}\n />\n ) : null}\n\n <ShellPanelWatcher\n contentId={panelId}\n open={isDrawerOpen}\n panelSlot=\"sidebar-panel\"\n onClose={() => {\n closeDrawer();\n }}\n />\n </nav>\n </SidebarResponsiveContext.Scope>\n </SidebarContext.Scope>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sidebar.js","names":[],"sources":["../../../src/components/sidebar/sidebar.tsx"],"sourcesContent":["import { state } from \"@askrjs/askr\";\nimport { classes } from \"../_internal/classes\";\nimport { isJsxElement, toChildArray } from \"../_internal/jsx\";\nimport { mergeProps } from \"../_internal/merge-props\";\nimport { NavBrand } from \"../navbar/navbar\";\nimport {\n isShellPanelChild,\n renderKeyedShellChildren,\n renderKeyedShellPanelChildren,\n ShellPanelWatcher,\n ShellResponsiveWatcher,\n} from \"../shell/shell-responsive\";\nimport { SidebarContext, SidebarResponsiveContext } from \"./sidebar.context\";\nimport { SidebarPanel } from \"./sidebar-panel\";\nimport { SidebarToggle } from \"./sidebar-toggle\";\nimport { isSidebarCollapsed, resolveSidebarCollapsible } from \"./sidebar.shared\";\nimport type { SidebarProps } from \"./sidebar.types\";\nimport type { CollapseIconPlacement } from \"../shell/shell-nav.types\";\n\ntype SidebarChildren = {\n brand?: unknown;\n drawerItems: unknown[];\n drawerSourceItems: unknown[];\n explicitPanelItems: unknown[];\n toggle?: SidebarToggleConfig;\n};\n\ntype SidebarToggleConfig = {\n collapsedIcon?: unknown;\n expandedIcon?: unknown;\n};\n\nfunction isSidebarToggleChild(child: unknown): boolean {\n return isJsxElement(child) && child.type === SidebarToggle;\n}\n\nfunction splitSidebarChildren(children: unknown[]): SidebarChildren {\n const explicitPanelItems: unknown[] = [];\n const drawerSourceItems: unknown[] = [];\n let drawerItems: unknown[] | undefined;\n let brand: unknown;\n let hasBrand = false;\n let hasToggle = false;\n let toggle: SidebarToggleConfig | undefined;\n\n for (const child of children) {\n if (isShellPanelChild(child, SidebarPanel)) {\n explicitPanelItems.push(child);\n continue;\n }\n\n if (!hasToggle && isSidebarToggleChild(child)) {\n hasToggle = true;\n toggle = (child as { props?: SidebarToggleConfig } | undefined)?.props;\n continue;\n }\n\n drawerSourceItems.push(child);\n\n if (!hasBrand && isJsxElement(child) && child.type === NavBrand) {\n brand = child;\n hasBrand = true;\n drawerItems ??= drawerSourceItems.slice(0, drawerSourceItems.length - 1);\n continue;\n }\n\n drawerItems?.push(child);\n }\n\n return {\n brand: hasBrand ? brand : undefined,\n drawerItems: drawerItems ?? drawerSourceItems,\n drawerSourceItems,\n explicitPanelItems,\n toggle,\n };\n}\n\nfunction renderSidebarMenuContents(\n label: string,\n icon: unknown,\n iconPlacement: CollapseIconPlacement,\n): JSX.Element {\n const renderedIcon = (\n <span class=\"sidebar-toggle-icon\" data-slot=\"sidebar-toggle-icon\" aria-hidden=\"true\">\n {icon ?? (\n <span class=\"sidebar-toggle-glyph sidebar-toggle-glyph--menu\">\n <span />\n <span />\n <span />\n </span>\n )}\n </span>\n );\n const renderedLabel = (\n <span class=\"sidebar-toggle-label\" data-slot=\"sidebar-toggle-label\">\n {label}\n </span>\n );\n\n if (iconPlacement === \"end\") {\n return (\n <>\n {renderedLabel}\n {renderedIcon}\n </>\n );\n }\n\n return (\n <>\n {renderedIcon}\n {renderedLabel}\n </>\n );\n}\n\nfunction renderSidebarRailContents(\n label: string,\n collapsed: boolean,\n toggle: SidebarToggleConfig | undefined,\n): JSX.Element {\n const icon = collapsed ? toggle?.collapsedIcon : toggle?.expandedIcon;\n\n return (\n <>\n <span\n class=\"sidebar-rail-toggle-icon\"\n data-slot=\"sidebar-rail-toggle-icon\"\n aria-hidden=\"true\"\n >\n {icon ?? (\n <span\n class={classes(\n \"sidebar-toggle-glyph\",\n \"sidebar-toggle-glyph--rail\",\n collapsed ? \"is-collapsed\" : \"is-expanded\",\n )}\n />\n )}\n </span>\n <span class=\"sidebar-rail-toggle-label\" data-slot=\"sidebar-rail-toggle-label\">\n {label}\n </span>\n </>\n );\n}\n\nexport function Sidebar(props: SidebarProps): JSX.Element {\n const {\n children,\n collapsed: controlledCollapsed,\n breakpoint,\n collapseIcon,\n collapseIconPlacement = \"start\",\n collapseLabel,\n collapsible,\n defaultCollapsed = false,\n id,\n \"aria-label\": ariaLabel,\n onCollapsedChange,\n class: className,\n ref,\n ...rest\n } = props;\n const effectiveCollapseLabel =\n collapseLabel ?? (typeof ariaLabel === \"string\" ? ariaLabel : undefined) ?? \"Menu\";\n const childItems = toChildArray(children);\n const sidebarChildren = splitSidebarChildren(childItems);\n const isResponsive = breakpoint !== undefined;\n const responsiveCollapsedState = state(isResponsive ? isSidebarCollapsed(breakpoint) : false);\n const drawerOpenState = state(false);\n const panelId = typeof id === \"string\" ? `${id}-panel` : undefined;\n const collapseBehavior = resolveSidebarCollapsible(collapsible);\n const isRailCollapsible = collapseBehavior === \"icon\";\n const railCollapsedState = state(defaultCollapsed);\n const responsiveCollapsed = responsiveCollapsedState();\n const drawerOpen = drawerOpenState();\n const internalRailCollapsed = railCollapsedState();\n const isMobile = isResponsive ? responsiveCollapsed : false;\n const isDrawerOpen = isResponsive && isMobile && drawerOpen;\n const isRailCollapsed = isRailCollapsible\n ? (controlledCollapsed ?? internalRailCollapsed ?? false)\n : false;\n const closeDrawer = () => drawerOpenState.set(false);\n const closeDrawerOnNavActivation = (event: MouseEvent) => {\n const target = event.target;\n\n if (!(target instanceof Element)) {\n return;\n }\n\n if (target.closest('a[data-slot=\"nav-link\"], a[data-slot=\"nav-item\"], a.navbar-item')) {\n closeDrawer();\n }\n };\n const toggleDrawer = () => {\n drawerOpenState.set(!drawerOpenState());\n };\n const setRailCollapsed = (nextCollapsed: boolean) => {\n if (!isRailCollapsible) {\n return;\n }\n\n if (controlledCollapsed === undefined) {\n railCollapsedState.set(nextCollapsed);\n }\n\n onCollapsedChange?.(nextCollapsed);\n };\n const toggleRail = () => {\n if (!isRailCollapsible) {\n return;\n }\n\n setRailCollapsed(!isRailCollapsed);\n };\n const desktopChildren = renderKeyedShellChildren(\n sidebarChildren.drawerSourceItems,\n \"sidebar-desktop\",\n );\n const drawerChildren = renderKeyedShellChildren(sidebarChildren.drawerItems, \"sidebar-drawer\");\n\n const contextValue = {\n active: () => isResponsive,\n collapseLabel: () => effectiveCollapseLabel,\n closePanel: closeDrawer,\n iconCollapsed: () => isRailCollapsed,\n isRailCollapsible: () => isRailCollapsible,\n orientation: () => \"vertical\" as const,\n panelId: () => panelId,\n panelOpen: () => isDrawerOpen,\n togglePanel: toggleDrawer,\n toggleRail,\n };\n const panelContext = {\n active: isResponsive,\n collapseLabel: effectiveCollapseLabel,\n onClose: closeDrawer,\n open: isDrawerOpen,\n panelId,\n };\n const panels =\n sidebarChildren.explicitPanelItems.length > 0 ? (\n renderKeyedShellPanelChildren(\n sidebarChildren.explicitPanelItems,\n \"sidebar-panel\",\n panelContext,\n )\n ) : isResponsive ? (\n <SidebarPanel\n active={isResponsive}\n brand={sidebarChildren.brand}\n collapseLabel={effectiveCollapseLabel}\n onClose={closeDrawer}\n onClick={closeDrawerOnNavActivation}\n open={isDrawerOpen}\n panelId={panelId}\n >\n {drawerChildren}\n </SidebarPanel>\n ) : null;\n\n const finalProps = mergeProps(rest, {\n ref,\n \"aria-label\": ariaLabel,\n class: classes(\"sidebar\", className),\n \"data-collapse-below\": breakpoint,\n \"data-collapsible\": collapseBehavior === \"none\" ? undefined : collapseBehavior,\n \"data-icon-collapsed\": isRailCollapsible ? (isRailCollapsed ? \"true\" : \"false\") : undefined,\n \"data-mobile-open\": isResponsive ? (drawerOpen ? \"true\" : \"false\") : undefined,\n \"data-orientation\": \"vertical\",\n \"data-responsive-collapsed\": isMobile ? \"true\" : \"false\",\n \"data-slot\": \"sidebar\",\n });\n\n return (\n <SidebarContext.Scope value={{ orientation: () => \"vertical\" as const }}>\n <SidebarResponsiveContext.Scope value={contextValue}>\n <nav {...finalProps}>\n {isResponsive ? (\n <div class=\"sidebar-mobile\" data-slot=\"sidebar-mobile\">\n <button\n aria-controls={panelId}\n aria-expanded={isDrawerOpen ? \"true\" : \"false\"}\n aria-label={effectiveCollapseLabel}\n class=\"sidebar-toggle\"\n data-slot=\"sidebar-toggle\"\n data-state={isDrawerOpen ? \"open\" : \"closed\"}\n data-variant=\"mobile\"\n type=\"button\"\n onClick={toggleDrawer}\n >\n {renderSidebarMenuContents(\n effectiveCollapseLabel,\n collapseIcon,\n collapseIconPlacement,\n )}\n </button>\n </div>\n ) : null}\n\n <div class=\"sidebar-shell\" data-orientation=\"vertical\" data-slot=\"sidebar-shell\">\n {isRailCollapsible && !isMobile ? (\n <div\n class=\"sidebar-rail\"\n data-slot=\"sidebar-rail\"\n data-state={isRailCollapsed ? \"collapsed\" : \"expanded\"}\n >\n <button\n aria-expanded={isRailCollapsed ? \"false\" : \"true\"}\n aria-label={\n isRailCollapsed\n ? `Expand ${effectiveCollapseLabel}`\n : `Collapse ${effectiveCollapseLabel}`\n }\n class=\"sidebar-rail-toggle\"\n data-slot=\"sidebar-rail-toggle\"\n data-state={isRailCollapsed ? \"collapsed\" : \"expanded\"}\n type=\"button\"\n onClick={toggleRail}\n >\n {renderSidebarRailContents(\n effectiveCollapseLabel,\n isRailCollapsed,\n sidebarChildren.toggle,\n )}\n </button>\n </div>\n ) : null}\n {desktopChildren}\n </div>\n\n {panels}\n\n {isResponsive && isDrawerOpen ? (\n <button\n aria-label={`Close ${effectiveCollapseLabel}`}\n class=\"sidebar-backdrop\"\n data-slot=\"sidebar-backdrop\"\n data-state=\"open\"\n tabIndex={-1}\n type=\"button\"\n onClick={closeDrawer}\n />\n ) : null}\n\n {isResponsive ? (\n <ShellResponsiveWatcher\n breakpoint={breakpoint}\n isCollapsed={isSidebarCollapsed}\n onResize={(nextCollapsed) => {\n responsiveCollapsedState.set(nextCollapsed);\n }}\n onExpand={() => {\n drawerOpenState.set(false);\n }}\n />\n ) : null}\n\n <ShellPanelWatcher\n contentId={panelId}\n open={isDrawerOpen}\n panelSlot=\"sidebar-panel\"\n onClose={() => {\n closeDrawer();\n }}\n />\n </nav>\n </SidebarResponsiveContext.Scope>\n </SidebarContext.Scope>\n );\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { mergeProps } from "../_internal/merge-props.js";
2
- import { isCssLength, mergeLayoutStyles } from "../_internal/layout.js";
3
2
  import { styleDeclarationsToClass } from "../_internal/style.js";
3
+ import { isCssLength, mergeLayoutStyles } from "../_internal/layout.js";
4
4
  import { isJsxElement, toChildArray } from "../_internal/jsx.js";
5
5
  import { jsx } from "@askrjs/askr/jsx-runtime";
6
6
  import { Slot } from "@askrjs/askr/foundations";
@@ -1 +1 @@
1
- {"version":3,"file":"spacer.js","names":[],"sources":["../../../src/components/spacer/spacer.tsx"],"sourcesContent":["import { Slot } from \"@askrjs/askr/foundations\";\nimport { mergeProps } from \"../_internal/merge-props\";\nimport { isCssLength, mergeLayoutStyles } from \"../_internal/layout\";\nimport { styleDeclarationsToClass } from \"../_internal/style\";\nimport { isJsxElement, toChildArray } from \"../_internal/jsx\";\nimport type { SpacerAsChildProps, SpacerNativeProps } from \"./spacer.types\";\n\nexport function Spacer(props: SpacerNativeProps): JSX.Element;\nexport function Spacer(props: SpacerAsChildProps): JSX.Element;\nexport function Spacer(props: SpacerNativeProps | SpacerAsChildProps) {\n const { asChild, children, grow, shrink, basis, axis, ref, style: userStyle, ...rest } = props;\n\n const layoutStyle: Record<string, string | number> = {};\n\n if (axis === \"inline\") {\n if (shrink !== undefined && shrink !== 0) {\n layoutStyle.flexShrink = shrink;\n }\n if (isCssLength(basis)) layoutStyle.width = basis!;\n } else if (axis === \"block\") {\n if (shrink !== undefined && shrink !== 0) {\n layoutStyle.flexShrink = shrink;\n }\n if (isCssLength(basis)) layoutStyle.height = basis!;\n } else {\n if (grow !== undefined && grow !== 1) {\n layoutStyle.flexGrow = grow;\n }\n if (shrink !== undefined && shrink !== 1) {\n layoutStyle.flexShrink = shrink;\n }\n if (isCssLength(basis)) {\n layoutStyle.flexBasis = basis!;\n }\n }\n\n const layoutClass = styleDeclarationsToClass(mergeLayoutStyles(layoutStyle, userStyle));\n\n const finalProps = mergeProps(rest, {\n ref,\n \"data-slot\": \"spacer\",\n \"data-axis\": axis,\n ...(layoutClass ? { class: layoutClass } : {}),\n });\n const keyedChildren = toChildArray(children).map((child, index) => {\n if (!isJsxElement(child) || child.key != null) {\n return child;\n }\n\n return {\n ...child,\n key: `spacer-${index}`,\n };\n });\n\n if (asChild) {\n return <Slot asChild {...finalProps} children={children} />;\n }\n\n return <div {...finalProps}>{keyedChildren}</div>;\n}\n"],"mappings":";;;;;;;AASA,SAAgB,OAAO,OAA+C;CACpE,MAAM,EAAE,SAAS,UAAU,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,WAAW,GAAG,SAAS;CAEzF,MAAM,cAA+C,CAAC;CAEtD,IAAI,SAAS,UAAU;EACrB,IAAI,WAAW,KAAA,KAAa,WAAW,GACrC,YAAY,aAAa;EAE3B,IAAI,YAAY,KAAK,GAAG,YAAY,QAAQ;CAC9C,OAAO,IAAI,SAAS,SAAS;EAC3B,IAAI,WAAW,KAAA,KAAa,WAAW,GACrC,YAAY,aAAa;EAE3B,IAAI,YAAY,KAAK,GAAG,YAAY,SAAS;CAC/C,OAAO;EACL,IAAI,SAAS,KAAA,KAAa,SAAS,GACjC,YAAY,WAAW;EAEzB,IAAI,WAAW,KAAA,KAAa,WAAW,GACrC,YAAY,aAAa;EAE3B,IAAI,YAAY,KAAK,GACnB,YAAY,YAAY;CAE5B;CAEA,MAAM,cAAc,yBAAyB,kBAAkB,aAAa,SAAS,CAAC;CAEtF,MAAM,aAAa,WAAW,MAAM;EAClC;EACA,aAAa;EACb,aAAa;EACb,GAAI,cAAc,EAAE,OAAO,YAAY,IAAI,CAAC;CAC9C,CAAC;CACD,MAAM,gBAAgB,aAAa,QAAQ,EAAE,KAAK,OAAO,UAAU;EACjE,IAAI,CAAC,aAAa,KAAK,KAAK,MAAM,OAAO,MACvC,OAAO;EAGT,OAAO;GACL,GAAG;GACH,KAAK,UAAU;EACjB;CACF,CAAC;CAED,IAAI,SACF,OAAO,oBAAC,MAAD;EAAM,SAAA;EAAQ,GAAI;EAAsB;CAAW,CAAA;CAG5D,OAAO,oBAAC,OAAD;EAAK,GAAI;YAAa;CAAmB,CAAA;AAClD"}
1
+ {"version":3,"file":"spacer.js","names":[],"sources":["../../../src/components/spacer/spacer.tsx"],"sourcesContent":["import { Slot } from \"@askrjs/askr/foundations\";\nimport { mergeProps } from \"../_internal/merge-props\";\nimport { isCssLength, mergeLayoutStyles } from \"../_internal/layout\";\nimport { styleDeclarationsToClass } from \"../_internal/style\";\nimport { isJsxElement, toChildArray } from \"../_internal/jsx\";\nimport type { SpacerAsChildProps, SpacerNativeProps } from \"./spacer.types\";\n\nexport function Spacer(props: SpacerNativeProps): JSX.Element;\nexport function Spacer(props: SpacerAsChildProps): JSX.Element;\nexport function Spacer(props: SpacerNativeProps | SpacerAsChildProps) {\n const { asChild, children, grow, shrink, basis, axis, ref, style: userStyle, ...rest } = props;\n\n const layoutStyle: Record<string, string | number> = {};\n\n if (axis === \"inline\") {\n if (shrink !== undefined && shrink !== 0) {\n layoutStyle.flexShrink = shrink;\n }\n if (isCssLength(basis)) layoutStyle.width = basis!;\n } else if (axis === \"block\") {\n if (shrink !== undefined && shrink !== 0) {\n layoutStyle.flexShrink = shrink;\n }\n if (isCssLength(basis)) layoutStyle.height = basis!;\n } else {\n if (grow !== undefined && grow !== 1) {\n layoutStyle.flexGrow = grow;\n }\n if (shrink !== undefined && shrink !== 1) {\n layoutStyle.flexShrink = shrink;\n }\n if (isCssLength(basis)) {\n layoutStyle.flexBasis = basis!;\n }\n }\n\n const layoutClass = styleDeclarationsToClass(mergeLayoutStyles(layoutStyle, userStyle));\n\n const finalProps = mergeProps(rest, {\n ref,\n \"data-slot\": \"spacer\",\n \"data-axis\": axis,\n ...(layoutClass ? { class: layoutClass } : {}),\n });\n const keyedChildren = toChildArray(children).map((child, index) => {\n if (!isJsxElement(child) || child.key != null) {\n return child;\n }\n\n return {\n ...child,\n key: `spacer-${index}`,\n };\n });\n\n if (asChild) {\n return <Slot asChild {...finalProps} children={children} />;\n }\n\n return <div {...finalProps}>{keyedChildren}</div>;\n}\n"],"mappings":";;;;;;;AASA,SAAgB,OAAO,OAA+C;CACpE,MAAM,EAAE,SAAS,UAAU,MAAM,QAAQ,OAAO,MAAM,KAAK,OAAO,WAAW,GAAG,SAAS;CAEzF,MAAM,cAA+C,CAAC;CAEtD,IAAI,SAAS,UAAU;EACrB,IAAI,WAAW,KAAA,KAAa,WAAW,GACrC,YAAY,aAAa;EAE3B,IAAI,YAAY,KAAK,GAAG,YAAY,QAAQ;CAC9C,OAAO,IAAI,SAAS,SAAS;EAC3B,IAAI,WAAW,KAAA,KAAa,WAAW,GACrC,YAAY,aAAa;EAE3B,IAAI,YAAY,KAAK,GAAG,YAAY,SAAS;CAC/C,OAAO;EACL,IAAI,SAAS,KAAA,KAAa,SAAS,GACjC,YAAY,WAAW;EAEzB,IAAI,WAAW,KAAA,KAAa,WAAW,GACrC,YAAY,aAAa;EAE3B,IAAI,YAAY,KAAK,GACnB,YAAY,YAAY;CAE5B;CAEA,MAAM,cAAc,yBAAyB,kBAAkB,aAAa,SAAS,CAAC;CAEtF,MAAM,aAAa,WAAW,MAAM;EAClC;EACA,aAAa;EACb,aAAa;EACb,GAAI,cAAc,EAAE,OAAO,YAAY,IAAI,CAAC;CAC9C,CAAC;CACD,MAAM,gBAAgB,aAAa,QAAQ,CAAC,CAAC,KAAK,OAAO,UAAU;EACjE,IAAI,CAAC,aAAa,KAAK,KAAK,MAAM,OAAO,MACvC,OAAO;EAGT,OAAO;GACL,GAAG;GACH,KAAK,UAAU;EACjB;CACF,CAAC;CAED,IAAI,SACF,OAAO,oBAAC,MAAD;EAAM,SAAA;EAAQ,GAAI;EAAsB;CAAW,CAAA;CAG5D,OAAO,oBAAC,OAAD;EAAK,GAAI;YAAa;CAAmB,CAAA;AAClD"}
@@ -1,6 +1,6 @@
1
1
  import { Button } from "@askrjs/ui";
2
2
  import { jsx, jsxs } from "@askrjs/askr/jsx-runtime";
3
- import { defineContext, readContext, state } from "@askrjs/askr";
3
+ import { defineContext, getSignal, readContext, state } from "@askrjs/askr";
4
4
  import { resource } from "@askrjs/askr/resources";
5
5
  //#region src/components/theme/theme.tsx
6
6
  const CAT_THEME_NAMES = [
@@ -47,6 +47,9 @@ const CAT_THEME_OPTIONS = [
47
47
  }
48
48
  ];
49
49
  const DEFAULT_STORAGE_KEY = "askr-theme";
50
+ let rootThemeRevision = 0;
51
+ let explicitRootThemeOwner;
52
+ const registeredProviderSignals = /* @__PURE__ */ new WeakSet();
50
53
  const ThemeContext = defineContext({
51
54
  theme: () => "system",
52
55
  setTheme: () => void 0,
@@ -58,10 +61,21 @@ function useTheme() {
58
61
  }
59
62
  function ThemeProvider(props) {
60
63
  const { children, defaultTheme = "system", themes = DEFAULT_THEME_OPTIONS, storageKey = DEFAULT_STORAGE_KEY } = props;
64
+ const providerId = state(Symbol("ThemeProvider"))();
65
+ const providerSignal = getSignal();
61
66
  const themeState = state(readStoredTheme(storageKey) ?? defaultTheme);
67
+ const currentTheme = themeState();
68
+ if (!registeredProviderSignals.has(providerSignal)) {
69
+ registeredProviderSignals.add(providerSignal);
70
+ providerSignal.addEventListener("abort", () => {
71
+ if (explicitRootThemeOwner === providerId) explicitRootThemeOwner = void 0;
72
+ }, { once: true });
73
+ }
62
74
  const setTheme = (nextTheme) => {
63
75
  themeState.set(nextTheme);
64
76
  writeStoredTheme(storageKey, nextTheme);
77
+ explicitRootThemeOwner = providerId;
78
+ rootThemeRevision += 1;
65
79
  syncThemeRoot(nextTheme);
66
80
  };
67
81
  const value = {
@@ -70,24 +84,31 @@ function ThemeProvider(props) {
70
84
  themes,
71
85
  storageKey
72
86
  };
73
- const currentTheme = themeState();
74
87
  return /* @__PURE__ */ jsxs(ThemeContext.Scope, {
75
88
  value,
76
- children: [/* @__PURE__ */ jsx(ThemeRootSync, { theme: currentTheme }), /* @__PURE__ */ jsx("div", {
89
+ children: [/* @__PURE__ */ jsx(ThemeRootSync, {
90
+ providerId,
91
+ theme: currentTheme
92
+ }), /* @__PURE__ */ jsx("div", {
77
93
  "data-slot": "theme-provider",
78
94
  children
79
95
  })]
80
96
  });
81
97
  }
82
98
  function ThemeRootSync(props) {
83
- const { theme } = props;
99
+ const { providerId, theme } = props;
100
+ const expectedRootThemeRevision = rootThemeRevision;
84
101
  resource(({ signal }) => {
85
102
  if (typeof window === "undefined") {
86
103
  syncThemeRoot(theme);
87
104
  return null;
88
105
  }
89
106
  const timeoutId = window.setTimeout(() => {
90
- if (!signal.aborted) syncThemeRoot(theme);
107
+ if (!signal.aborted) syncThemeRoot(theme, {
108
+ expectedRevision: expectedRootThemeRevision,
109
+ passive: true,
110
+ providerId
111
+ });
91
112
  }, 0);
92
113
  signal.addEventListener("abort", () => {
93
114
  window.clearTimeout(timeoutId);
@@ -99,21 +120,34 @@ function ThemeRootSync(props) {
99
120
  function ThemePicker(props) {
100
121
  const theme = useTheme();
101
122
  const { themes = theme.themes, label = "Theme", ...rest } = props;
123
+ const currentTheme = theme.theme();
102
124
  return /* @__PURE__ */ jsx("select", {
103
125
  ...rest,
104
126
  "aria-label": rest["aria-label"] ?? label,
105
127
  "data-slot": "theme-picker",
106
- value: theme.theme(),
128
+ value: currentTheme,
107
129
  onChange: (event) => {
108
- const target = event.currentTarget;
109
- theme.setTheme(target.value);
130
+ const target = getThemePickerTarget(event);
131
+ if (target) theme.setTheme(target.value);
110
132
  },
111
133
  children: themes.map((option) => /* @__PURE__ */ jsx("option", {
112
134
  value: option.value,
135
+ selected: option.value === currentTheme,
113
136
  children: option.label
114
137
  }, option.value))
115
138
  });
116
139
  }
140
+ function getThemePickerTarget(event) {
141
+ if (typeof HTMLSelectElement === "undefined") return null;
142
+ const path = typeof event.composedPath === "function" ? event.composedPath() : [];
143
+ const candidates = [
144
+ event.target,
145
+ event.currentTarget,
146
+ ...path
147
+ ];
148
+ for (const candidate of candidates) if (candidate instanceof HTMLSelectElement) return candidate;
149
+ return null;
150
+ }
117
151
  function ThemeToggle(props) {
118
152
  const theme = useTheme();
119
153
  const { children, lightIcon, darkIcon, systemIcon, themes = ["light", "dark"], onPress, ...rest } = props;
@@ -138,9 +172,12 @@ function ThemeToggle(props) {
138
172
  "data-next-theme": nextTheme,
139
173
  onPress: (event) => {
140
174
  onPress?.(event);
141
- if (!event.defaultPrevented) theme.setTheme(nextTheme);
175
+ if (!event.defaultPrevented && !Object.is(nextTheme, currentTheme)) theme.setTheme(nextTheme);
142
176
  },
143
- children: content
177
+ children: /* @__PURE__ */ jsx("span", {
178
+ "data-slot": "theme-toggle-content",
179
+ children: content
180
+ })
144
181
  });
145
182
  }
146
183
  function getNextTheme(currentTheme, themes) {
@@ -161,14 +198,18 @@ function isJSXElement(value) {
161
198
  }
162
199
  function cloneThemeToggleIcon(icon) {
163
200
  if (!isJSXElement(icon)) return icon;
201
+ const props = icon.props;
202
+ if (!props || Object.keys(props).length === 0) return icon;
164
203
  return {
165
204
  ...icon,
166
- props: { ...icon.props }
205
+ props: { ...props }
167
206
  };
168
207
  }
169
- function syncThemeRoot(themeChoice) {
208
+ function syncThemeRoot(themeChoice, options) {
170
209
  if (typeof document === "undefined") return;
171
210
  const html = document.documentElement;
211
+ if (options?.passive && options.expectedRevision !== void 0 && options.expectedRevision !== rootThemeRevision) return;
212
+ if (options?.passive && explicitRootThemeOwner !== void 0 && explicitRootThemeOwner !== options.providerId) return;
172
213
  if (themeChoice == null) {
173
214
  html.removeAttribute("data-theme");
174
215
  html.removeAttribute("data-theme-choice");
@@ -181,7 +222,8 @@ function syncThemeRoot(themeChoice) {
181
222
  function readStoredTheme(storageKey) {
182
223
  if (typeof window === "undefined") return void 0;
183
224
  try {
184
- return window.localStorage.getItem(storageKey) ?? void 0;
225
+ const storedTheme = window.localStorage.getItem(storageKey);
226
+ return storedTheme ? storedTheme : void 0;
185
227
  } catch {
186
228
  return;
187
229
  }