@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.
- package/THEMING.md +5 -1
- package/dist/components/_internal/box-layout.js +1 -1
- package/dist/components/_internal/classes.js.map +1 -1
- package/dist/components/_internal/jsx.js.map +1 -1
- package/dist/components/_internal/layout.js +2 -7
- package/dist/components/_internal/layout.js.map +1 -1
- package/dist/components/_internal/style.js +25 -1
- package/dist/components/_internal/style.js.map +1 -1
- package/dist/components/aspect-ratio/aspect-ratio.js +1 -1
- package/dist/components/block/block.js.map +1 -1
- package/dist/components/container/container.js.map +1 -1
- package/dist/components/flex/flex.js.map +1 -1
- package/dist/components/nav/nav.js.map +1 -1
- package/dist/components/navbar/navbar-panel.js +10 -16
- package/dist/components/navbar/navbar-panel.js.map +1 -1
- package/dist/components/navbar/navbar.js +23 -12
- package/dist/components/navbar/navbar.js.map +1 -1
- package/dist/components/section/section.js.map +1 -1
- package/dist/components/shell/shell-responsive.js +51 -20
- package/dist/components/shell/shell-responsive.js.map +1 -1
- package/dist/components/sidebar/sidebar-panel.js +14 -24
- package/dist/components/sidebar/sidebar-panel.js.map +1 -1
- package/dist/components/sidebar/sidebar.js +38 -24
- package/dist/components/sidebar/sidebar.js.map +1 -1
- package/dist/components/spacer/spacer.js +1 -1
- package/dist/components/spacer/spacer.js.map +1 -1
- package/dist/components/theme/theme.js +55 -13
- package/dist/components/theme/theme.js.map +1 -1
- package/dist/themes/default/index.css +35 -3
- package/package.json +11 -10
- package/src/components/_internal/jsx.ts +18 -6
- package/src/components/_internal/layout.ts +3 -12
- package/src/components/_internal/style.ts +42 -4
- package/src/components/navbar/navbar-panel.tsx +11 -16
- package/src/components/navbar/navbar.tsx +32 -17
- package/src/components/shell/shell-responsive.tsx +79 -29
- package/src/components/sidebar/sidebar-panel.tsx +15 -24
- package/src/components/sidebar/sidebar.tsx +52 -34
- package/src/components/theme/theme.tsx +88 -16
- package/src/themes/default/styles/actions/button.css +16 -0
- package/src/themes/default/styles/display/avatar.css +7 -1
- package/src/themes/default/styles/display/badge.css +2 -1
- package/src/themes/default/styles/display/table.css +2 -0
- package/src/themes/default/styles/forms/select.css +6 -0
- package/src/themes/default/styles/shell/navbar.css +2 -1
- package/templates/theme/styles/actions/button.css +16 -0
- package/templates/theme/styles/display/avatar.css +7 -1
- package/templates/theme/styles/display/badge.css +2 -1
- package/templates/theme/styles/display/table.css +2 -0
- package/templates/theme/styles/forms/select.css +6 -0
- 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
|
|
28
|
-
|
|
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
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
...
|
|
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) =>
|
|
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
|
|
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
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
|
|
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
|
|
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
|
|
105
|
-
const
|
|
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:
|
|
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,
|
|
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,
|
|
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, {
|
|
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:
|
|
128
|
+
value: currentTheme,
|
|
107
129
|
onChange: (event) => {
|
|
108
|
-
const target = event
|
|
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:
|
|
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: { ...
|
|
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
|
-
|
|
225
|
+
const storedTheme = window.localStorage.getItem(storageKey);
|
|
226
|
+
return storedTheme ? storedTheme : void 0;
|
|
185
227
|
} catch {
|
|
186
228
|
return;
|
|
187
229
|
}
|