@keboola/design 11.6.1 → 11.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +16 -1
- package/CHANGELOG.md +86 -0
- package/COMPONENT-API.md +47 -46
- package/README.md +1 -1
- package/dist/{AIKit-CQxVwyAk.js → AIKit-ELIsegJz.js} +550 -103
- package/dist/AIKit-ELIsegJz.js.map +1 -0
- package/dist/{Alert-C4Y9IwMI.js → Alert-BsIM_oFK.js} +2 -2
- package/dist/{Alert-C4Y9IwMI.js.map → Alert-BsIM_oFK.js.map} +1 -1
- package/dist/{BrandEditor-CS9P4r2p.js → BrandEditor-BsTBM3s6.js} +4 -4
- package/dist/{BrandEditor-CS9P4r2p.js.map → BrandEditor-BsTBM3s6.js.map} +1 -1
- package/dist/{Breadcrumb-D1id7YXd.js → Breadcrumb-xqEUxfwn.js} +2 -2
- package/dist/{Breadcrumb-D1id7YXd.js.map → Breadcrumb-xqEUxfwn.js.map} +1 -1
- package/dist/{Checkbox-Bqr6zXcW.js → Checkbox-Dq5fPNrO.js} +2 -2
- package/dist/{Checkbox-Bqr6zXcW.js.map → Checkbox-Dq5fPNrO.js.map} +1 -1
- package/dist/{Clipboard-C2YBRfD8.js → Clipboard-BZitKiSA.js} +2 -2
- package/dist/{Clipboard-C2YBRfD8.js.map → Clipboard-BZitKiSA.js.map} +1 -1
- package/dist/{ClipboardButton-CrljClL1.js → ClipboardButton-KHQnPEh_.js} +2 -2
- package/dist/{ClipboardButton-CrljClL1.js.map → ClipboardButton-KHQnPEh_.js.map} +1 -1
- package/dist/{CodeEditor-C9AS8Ch0.js → CodeEditor-BJKJXA0c.js} +4 -4
- package/dist/{CodeEditor-C9AS8Ch0.js.map → CodeEditor-BJKJXA0c.js.map} +1 -1
- package/dist/{ColorInput-Dg87lKcR.js → ColorInput-Bj3dfPFA.js} +3 -3
- package/dist/{ColorInput-Dg87lKcR.js.map → ColorInput-Bj3dfPFA.js.map} +1 -1
- package/dist/{ColorModeSwitch-CsWLiTBX.js → ColorModeSwitch-CWt-DZGC.js} +2 -2
- package/dist/{ColorModeSwitch-CsWLiTBX.js.map → ColorModeSwitch-CWt-DZGC.js.map} +1 -1
- package/dist/{Combobox-BfanUAqY.js → Combobox-D8PrEqTG.js} +3 -3
- package/dist/{Combobox-BfanUAqY.js.map → Combobox-D8PrEqTG.js.map} +1 -1
- package/dist/{Command-CqxoI_De.js → Command-BDU3C1gg.js} +2 -2
- package/dist/{Command-CqxoI_De.js.map → Command-BDU3C1gg.js.map} +1 -1
- package/dist/{CopyField-Rx9HPTbJ.js → CopyField-BHRQUyuF.js} +2 -2
- package/dist/{CopyField-Rx9HPTbJ.js.map → CopyField-BHRQUyuF.js.map} +1 -1
- package/dist/{DateInput-DpifECUQ.js → DateInput-B6N8g0ra.js} +3 -3
- package/dist/{DateInput-DpifECUQ.js.map → DateInput-B6N8g0ra.js.map} +1 -1
- package/dist/{DateRangeInput-9MIw7P6L.js → DateRangeInput-7M9Z4cVO.js} +3 -3
- package/dist/{DateRangeInput-9MIw7P6L.js.map → DateRangeInput-7M9Z4cVO.js.map} +1 -1
- package/dist/{DropdownMenu-CASr-jgl.js → DropdownMenu-CgVwhDvl.js} +9 -4
- package/dist/DropdownMenu-CgVwhDvl.js.map +1 -0
- package/dist/{FieldItem-DtPTzNef.js → FieldItem-DZGIdiXE.js} +3 -3
- package/dist/{FieldItem-DtPTzNef.js.map → FieldItem-DZGIdiXE.js.map} +1 -1
- package/dist/{Form-DAaatlBk.js → Form-CcK7dRrC.js} +5 -5
- package/dist/{Form-DAaatlBk.js.map → Form-CcK7dRrC.js.map} +1 -1
- package/dist/{FormGroup-Bl8JmnzJ.js → FormGroup-DR_gZ25-.js} +3 -3
- package/dist/{FormGroup-Bl8JmnzJ.js.map → FormGroup-DR_gZ25-.js.map} +1 -1
- package/dist/{InputGroup-DcZRlVnN.js → InputGroup-Do8K2hvD.js} +2 -1
- package/dist/InputGroup-Do8K2hvD.js.map +1 -0
- package/dist/{Kbd-D1Azcc4g.js → Kbd-LCFMumoq.js} +2 -2
- package/dist/{Kbd-D1Azcc4g.js.map → Kbd-LCFMumoq.js.map} +1 -1
- package/dist/{MermaidDiagram-CujFxVzk.js → MermaidDiagram-ZG0iiDV_.js} +2 -2
- package/dist/{MermaidDiagram-CujFxVzk.js.map → MermaidDiagram-ZG0iiDV_.js.map} +1 -1
- package/dist/{Modal-Coj-H02o.js → Modal-I3VWk2oo.js} +2 -2
- package/dist/{Modal-Coj-H02o.js.map → Modal-I3VWk2oo.js.map} +1 -1
- package/dist/{ModalTitle-C76ke2eo.js → ModalTitle-CeLM_mX9.js} +2 -2
- package/dist/ModalTitle-CeLM_mX9.js.map +1 -0
- package/dist/{MultiActionButtonGroup-CNNoBQbv.js → MultiActionButtonGroup-CYZ8IgSf.js} +2 -2
- package/dist/{MultiActionButtonGroup-CNNoBQbv.js.map → MultiActionButtonGroup-CYZ8IgSf.js.map} +1 -1
- package/dist/{RadioGroup-CUBsuP7r.js → RadioGroup-Byc2mym4.js} +2 -2
- package/dist/{RadioGroup-CUBsuP7r.js.map → RadioGroup-Byc2mym4.js.map} +1 -1
- package/dist/{Search-DVpJuzr9.js → Search-Dhig_hPD.js} +2 -2
- package/dist/{Search-DVpJuzr9.js.map → Search-Dhig_hPD.js.map} +1 -1
- package/dist/{SearchInput-Q85p8Ews.js → SearchInput-92r2bkA7.js} +3 -3
- package/dist/{SearchInput-Q85p8Ews.js.map → SearchInput-92r2bkA7.js.map} +1 -1
- package/dist/{SectionNav-mpmSM3OC.js → SectionNav-CNLJsiVG.js} +3 -3
- package/dist/{SectionNav-mpmSM3OC.js.map → SectionNav-CNLJsiVG.js.map} +1 -1
- package/dist/{Sheet-Chf0kX1E.js → Sheet-OparjIi-.js} +2 -2
- package/dist/{Sheet-Chf0kX1E.js.map → Sheet-OparjIi-.js.map} +1 -1
- package/dist/{Sidebar-CTWsHZhF.js → Sidebar-CLEbBtNY.js} +190 -25
- package/dist/Sidebar-CLEbBtNY.js.map +1 -0
- package/dist/{Slider-Bv0B6lI0.js → Slider-DLclvRws.js} +2 -2
- package/dist/{Slider-Bv0B6lI0.js.map → Slider-DLclvRws.js.map} +1 -1
- package/dist/{TextInput-DiEMxVF6.js → TextInput-CFTf4Cz1.js} +5 -4
- package/dist/TextInput-CFTf4Cz1.js.map +1 -0
- package/dist/{ThemeProvider-BI6JWBdJ.js → ThemeProvider-DAmNn9Sd.js} +2 -2
- package/dist/{ThemeProvider-BI6JWBdJ.js.map → ThemeProvider-DAmNn9Sd.js.map} +1 -1
- package/dist/{Timeline-BG5Xogxh.js → Timeline-C8-wnRRr.js} +2 -2
- package/dist/{Timeline-BG5Xogxh.js.map → Timeline-C8-wnRRr.js.map} +1 -1
- package/dist/{ZoomableSvg-U_VH3QRO.js → ZoomableSvg-BZlk3PFJ.js} +3 -3
- package/dist/{ZoomableSvg-U_VH3QRO.js.map → ZoomableSvg-BZlk3PFJ.js.map} +1 -1
- package/dist/editors.js +2 -2
- package/dist/flint.js +1 -1
- package/dist/index.d.ts +900 -561
- package/dist/index.js +36 -34
- package/dist/internal/blocks/AIKit.js +2 -2
- package/dist/internal/blocks/BrandEditor.js +1 -1
- package/dist/internal/blocks/ChipEditor.js +137 -0
- package/dist/internal/blocks/ChipEditor.js.map +1 -0
- package/dist/internal/blocks/ClipboardButton.js +1 -1
- package/dist/internal/blocks/ColorInput.js +1 -1
- package/dist/internal/blocks/ColorModeSwitch.js +1 -1
- package/dist/internal/blocks/Command.js +1 -1
- package/dist/internal/blocks/CopyField.js +1 -1
- package/dist/internal/blocks/DateInput.js +1 -1
- package/dist/internal/blocks/DateRangeInput.js +1 -1
- package/dist/internal/blocks/ExportMenu.js +2 -2
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
- package/dist/internal/blocks/Form.js +1 -1
- package/dist/internal/blocks/FormGroup.js +1 -1
- package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
- package/dist/internal/blocks/MultiCombobox.js +18 -28
- package/dist/internal/blocks/MultiCombobox.js.map +1 -1
- package/dist/internal/blocks/NumberInput.js +1 -1
- package/dist/internal/blocks/PasswordInput.js +2 -2
- package/dist/internal/blocks/SearchInput.js +1 -1
- package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
- package/dist/internal/blocks/SectionNav.js +1 -1
- package/dist/internal/blocks/SplitButton.js +1 -1
- package/dist/internal/blocks/TextInput.js +1 -1
- package/dist/internal/blocks/Textarea.js +1 -1
- package/dist/internal/blocks/TimeInput.js +2 -2
- package/dist/internal/components/Alert.js +1 -1
- package/dist/internal/components/Avatar.js +1 -1
- package/dist/internal/components/Breadcrumb.js +1 -1
- package/dist/internal/components/Checkbox.js +1 -1
- package/dist/internal/components/Clipboard.js +1 -1
- package/dist/internal/components/CollapsiblePanel.js +1 -1
- package/dist/internal/components/Combobox.js +1 -1
- package/dist/internal/components/DropdownMenu.js +1 -1
- package/dist/internal/components/InputGroup.js +1 -1
- package/dist/internal/components/Kbd.js +1 -1
- package/dist/internal/components/Modal.js +1 -1
- package/dist/internal/components/RadioGroup.js +1 -1
- package/dist/internal/components/Search.js +1 -1
- package/dist/internal/components/Sheet.js +1 -1
- package/dist/internal/components/Sidebar.js +1 -1
- package/dist/internal/components/Slider.js +1 -1
- package/dist/internal/components/StatusDot.js +67 -0
- package/dist/internal/components/StatusDot.js.map +1 -0
- package/dist/internal/components/ThemeProvider.js +1 -1
- package/dist/internal/components/Timeline.js +1 -1
- package/dist/internal/components/Tooltip.js +2 -2
- package/dist/internal/components/Truncated.js +1 -1
- package/dist/internal/components/ZoomableSvg.js +1 -1
- package/dist/internal/hooks/useScrollbarPosition.js +1 -1
- package/dist/internal/utils/mergeRefs.js +27 -9
- package/dist/internal/utils/mergeRefs.js.map +1 -1
- package/dist/internal/utils.js +2 -2
- package/dist/markdown-editor.js +5 -5
- package/dist/mermaid.js +1 -1
- package/dist/rjsf.js +9 -9
- package/dist/styles.css +1 -1
- package/dist/testing.js +1 -1
- package/dist/useElement-BK3AAiIf.js +24 -0
- package/dist/useElement-BK3AAiIf.js.map +1 -0
- package/dist/{utils-DnkrFYqY.js → utils-BW4AE8VP.js} +31 -3
- package/dist/utils-BW4AE8VP.js.map +1 -0
- package/package.json +2 -1
- package/dist/AIKit-CQxVwyAk.js.map +0 -1
- package/dist/DropdownMenu-CASr-jgl.js.map +0 -1
- package/dist/InputGroup-DcZRlVnN.js.map +0 -1
- package/dist/ModalTitle-C76ke2eo.js.map +0 -1
- package/dist/Sidebar-CTWsHZhF.js.map +0 -1
- package/dist/TextInput-DiEMxVF6.js.map +0 -1
- package/dist/useElement-DkF6esWL.js +0 -15
- package/dist/useElement-DkF6esWL.js.map +0 -1
- package/dist/utils-DnkrFYqY.js.map +0 -1
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { cn } from "./classNames-BzrkDnOD.js";
|
|
2
|
-
import { Tooltip, TooltipProvider } from "./utils-
|
|
2
|
+
import { Tooltip, TooltipProvider } from "./utils-BW4AE8VP.js";
|
|
3
3
|
import { mergeRefs } from "./internal/utils/mergeRefs.js";
|
|
4
4
|
import { ChevronDown, Search } from "./icons-Cek151jC.js";
|
|
5
|
-
import { DropdownMenu } from "./DropdownMenu-
|
|
5
|
+
import { DropdownMenu } from "./DropdownMenu-CgVwhDvl.js";
|
|
6
6
|
import { ScrollArea } from "./internal/components/ScrollArea.js";
|
|
7
7
|
import { Separator } from "./internal/components/Separator.js";
|
|
8
|
+
import { Sheet } from "./Sheet-OparjIi-.js";
|
|
8
9
|
import { HoverCard } from "./HoverCard-B9ZMJxjn.js";
|
|
9
10
|
import { Collapsible } from "./Collapsible-BQXWEOBC.js";
|
|
11
|
+
import { useThemeScopeContainer } from "./ThemeProvider-DAmNn9Sd.js";
|
|
10
12
|
import { BrandLogo } from "./BrandLogo-CoKBk4MI.js";
|
|
11
|
-
import { useElement } from "./useElement-
|
|
13
|
+
import { useElement } from "./useElement-BK3AAiIf.js";
|
|
12
14
|
import { useScrollbarPosition } from "./internal/hooks/useScrollbarPosition.js";
|
|
13
15
|
import { Root, Slot, Slottable } from "@radix-ui/react-slot";
|
|
14
|
-
import { createContext, use, useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
16
|
+
import { createContext, use, useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
15
17
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
18
|
//#region src/components/Sidebar/SidebarProvider/useTransitionPresence.ts
|
|
17
19
|
const FALLBACK_TIMEOUT_MS = 500;
|
|
@@ -79,20 +81,47 @@ const SidebarContent = ({ ref, className, children, contentRef }) => {
|
|
|
79
81
|
});
|
|
80
82
|
};
|
|
81
83
|
//#endregion
|
|
84
|
+
//#region src/hooks/useMediaQuery.ts
|
|
85
|
+
/**
|
|
86
|
+
* Whether a CSS media query currently matches, re-rendering when it flips.
|
|
87
|
+
*
|
|
88
|
+
* - `false` wherever `matchMedia` is absent (SSR, a stubbed test environment), so the
|
|
89
|
+
* caller renders its desktop branch rather than crashing.
|
|
90
|
+
* - The subscription is the query's own `change` event — no resize listener, no polling.
|
|
91
|
+
*/
|
|
92
|
+
const useMediaQuery = (query) => {
|
|
93
|
+
const subscribe = useCallback((onStoreChange) => {
|
|
94
|
+
const list = globalThis.matchMedia?.(query);
|
|
95
|
+
list?.addEventListener?.("change", onStoreChange);
|
|
96
|
+
return () => list?.removeEventListener?.("change", onStoreChange);
|
|
97
|
+
}, [query]);
|
|
98
|
+
const getSnapshot = useCallback(() => globalThis.matchMedia?.(query).matches ?? false, [query]);
|
|
99
|
+
return useSyncExternalStore(subscribe, getSnapshot, () => false);
|
|
100
|
+
};
|
|
101
|
+
//#endregion
|
|
82
102
|
//#region src/components/Sidebar/utils.ts
|
|
83
103
|
const SidebarWidthInPx = {
|
|
84
104
|
MIN_DEFAULT: 256,
|
|
85
105
|
COLLAPSED_ICON: 52,
|
|
86
106
|
FLOATING_VARIANT_PADDING: 8
|
|
87
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* The query a rail watches to know whether it is a sheet.
|
|
110
|
+
*
|
|
111
|
+
* - `max-width`, so it is exclusive of the breakpoint itself — the width passed in is the
|
|
112
|
+
* first one at which the rail is a column again.
|
|
113
|
+
* - Per side, because the width at which a rail stops fitting is the rail's own: a 320px
|
|
114
|
+
* panel beside a capped reading column runs out of room long before a navigation rail does.
|
|
115
|
+
*/
|
|
116
|
+
const sidebarMobileMediaQuery = (breakpointPx) => `(max-width: ${breakpointPx - .02}px)`;
|
|
88
117
|
const floatingSideCount = {
|
|
89
118
|
"sided-floating": 1,
|
|
90
119
|
floating: 2,
|
|
91
120
|
inset: 0,
|
|
92
121
|
none: 0
|
|
93
122
|
};
|
|
94
|
-
const calcEffectiveWidths = ({ variant, width: customWidth, collapsible, state, mode }) => {
|
|
95
|
-
if (variant === "none") return {
|
|
123
|
+
const calcEffectiveWidths = ({ variant, width: customWidth, collapsible, state, mode, isMobile = false }) => {
|
|
124
|
+
if (variant === "none" || isMobile) return {
|
|
96
125
|
sidebar: 0,
|
|
97
126
|
gap: 0,
|
|
98
127
|
fill: 0
|
|
@@ -140,14 +169,16 @@ const useSidebar = (side = "left") => {
|
|
|
140
169
|
//#region src/components/Sidebar/SidebarProvider/useHoverTracking.ts
|
|
141
170
|
const PORTAL_OPEN_SELECTORS_STRING = ["[aria-haspopup=\"menu\"][aria-expanded=true]", "[aria-haspopup=\"dialog\"][aria-expanded=true]"].join(",");
|
|
142
171
|
const useHoverTracking = (sidebarElement) => {
|
|
143
|
-
const [
|
|
172
|
+
const [hoveredElement, setHoveredElement] = useState(null);
|
|
144
173
|
const isLockedRef = useRef(false);
|
|
174
|
+
if (hoveredElement !== null && hoveredElement !== sidebarElement) setHoveredElement(null);
|
|
175
|
+
const isHovered = hoveredElement !== null;
|
|
145
176
|
useEffect(() => {
|
|
146
177
|
if (!sidebarElement) return;
|
|
147
|
-
const handleMouseEnter = () =>
|
|
178
|
+
const handleMouseEnter = () => setHoveredElement(sidebarElement);
|
|
148
179
|
const handleMouseLeave = () => {
|
|
149
180
|
if (isLockedRef.current) return;
|
|
150
|
-
|
|
181
|
+
setHoveredElement(null);
|
|
151
182
|
};
|
|
152
183
|
sidebarElement.addEventListener("mouseenter", handleMouseEnter);
|
|
153
184
|
sidebarElement.addEventListener("mouseleave", handleMouseLeave);
|
|
@@ -164,7 +195,7 @@ const useHoverTracking = (sidebarElement) => {
|
|
|
164
195
|
isLockedRef.current = hasOpenPortal;
|
|
165
196
|
if (hasOpenPortal) return;
|
|
166
197
|
animationFrameId = requestAnimationFrame(() => {
|
|
167
|
-
|
|
198
|
+
setHoveredElement(sidebarElement.matches(":hover") ? sidebarElement : null);
|
|
168
199
|
});
|
|
169
200
|
});
|
|
170
201
|
isLockedRef.current = sidebarElement.querySelector(PORTAL_OPEN_SELECTORS_STRING) !== null;
|
|
@@ -221,14 +252,31 @@ const useSidebarState = ({ defaultMode, mode: modeProp, onModeChange }) => {
|
|
|
221
252
|
const DEFAULT_SIDEBAR_VARIANT = "none";
|
|
222
253
|
const DEFAULT_SIDEBAR_MODE = "expanded";
|
|
223
254
|
const DEFAULT_SIDEBAR_COLLAPSIBLE = "off-canvas";
|
|
224
|
-
|
|
255
|
+
/**
|
|
256
|
+
* What `setMode` becomes for a rail that is currently a sheet.
|
|
257
|
+
*
|
|
258
|
+
* - The collapse axis has nothing to act on there, and the call site's own `mode` prop is a
|
|
259
|
+
* stored desktop preference — `Sidebar.SearchInput` expands the rail on focus, which would
|
|
260
|
+
* otherwise overwrite a stored `collapsed` the first time someone searches on a phone.
|
|
261
|
+
*/
|
|
262
|
+
const ignoreModeChange = () => {};
|
|
263
|
+
/** The width a side watches: its own when it named one, the default when it just opted in. */
|
|
264
|
+
const mobileBreakpointOf = (mobileSheet) => typeof mobileSheet === "number" ? mobileSheet : 768;
|
|
265
|
+
const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, leftMode, onLeftModeChange, defaultRightMode = DEFAULT_SIDEBAR_MODE, rightMode, onRightModeChange, leftMobileSheet = false, rightMobileSheet = false, leftCollapsible = DEFAULT_SIDEBAR_COLLAPSIBLE, leftVariant = DEFAULT_SIDEBAR_VARIANT, leftWidth, rightCollapsible = DEFAULT_SIDEBAR_COLLAPSIBLE, rightVariant = DEFAULT_SIDEBAR_VARIANT, rightWidth, onLeftWidthChange, onRightWidthChange, defaultFilledSide = null }) => {
|
|
266
|
+
const isLeftNarrow = useMediaQuery(sidebarMobileMediaQuery(mobileBreakpointOf(leftMobileSheet)));
|
|
267
|
+
const isRightNarrow = useMediaQuery(sidebarMobileMediaQuery(mobileBreakpointOf(rightMobileSheet)));
|
|
268
|
+
const isLeftMobile = isLeftNarrow && leftMobileSheet !== false && leftVariant !== "none";
|
|
269
|
+
const isRightMobile = isRightNarrow && rightMobileSheet !== false && rightVariant !== "none";
|
|
225
270
|
const [filledSide, setFilledSide] = useState(defaultFilledSide);
|
|
271
|
+
const [openMobileSide, setOpenMobileSide] = useState(null);
|
|
226
272
|
const [isLeftDragging, setIsLeftDragging] = useState(false);
|
|
227
273
|
const [isRightDragging, setIsRightDragging] = useState(false);
|
|
228
274
|
const [leftDragWidth, setLeftDragWidth] = useState(null);
|
|
229
275
|
const [rightDragWidth, setRightDragWidth] = useState(null);
|
|
230
276
|
if (leftDragWidth !== null && leftWidth === leftDragWidth) setLeftDragWidth(null);
|
|
231
277
|
if (rightDragWidth !== null && rightWidth === rightDragWidth) setRightDragWidth(null);
|
|
278
|
+
if (openMobileSide === "left" && !isLeftMobile) setOpenMobileSide(null);
|
|
279
|
+
if (openMobileSide === "right" && !isRightMobile) setOpenMobileSide(null);
|
|
232
280
|
const leftState = useSidebarState({
|
|
233
281
|
defaultMode: defaultLeftMode,
|
|
234
282
|
mode: leftMode,
|
|
@@ -239,6 +287,10 @@ const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, lef
|
|
|
239
287
|
mode: rightMode,
|
|
240
288
|
onModeChange: onRightModeChange
|
|
241
289
|
});
|
|
290
|
+
const toggleLeftMobile = useCallback(() => setOpenMobileSide((prev) => prev === "left" ? null : "left"), []);
|
|
291
|
+
const toggleRightMobile = useCallback(() => setOpenMobileSide((prev) => prev === "right" ? null : "right"), []);
|
|
292
|
+
const setLeftMobileOpen = useCallback((open) => setOpenMobileSide((prev) => open ? "left" : prev === "left" ? null : prev), []);
|
|
293
|
+
const setRightMobileOpen = useCallback((open) => setOpenMobileSide((prev) => open ? "right" : prev === "right" ? null : prev), []);
|
|
242
294
|
const toggleLeftFill = useCallback(() => setFilledSide((prev) => prev === "left" ? null : "left"), []);
|
|
243
295
|
const toggleRightFill = useCallback(() => setFilledSide((prev) => prev === "right" ? null : "right"), []);
|
|
244
296
|
const setLeftFill = useCallback((fill) => setFilledSide((prev) => fill ? "left" : prev === "left" ? null : prev), []);
|
|
@@ -246,6 +298,15 @@ const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, lef
|
|
|
246
298
|
const value = useMemo(() => ({
|
|
247
299
|
left: {
|
|
248
300
|
...leftState,
|
|
301
|
+
...isLeftMobile ? {
|
|
302
|
+
mode: "expanded",
|
|
303
|
+
state: "expanded",
|
|
304
|
+
toggle: toggleLeftMobile,
|
|
305
|
+
setMode: ignoreModeChange
|
|
306
|
+
} : null,
|
|
307
|
+
isMobile: isLeftMobile,
|
|
308
|
+
isMobileOpen: openMobileSide === "left",
|
|
309
|
+
setMobileOpen: setLeftMobileOpen,
|
|
249
310
|
isFill: filledSide === "left",
|
|
250
311
|
toggleFill: toggleLeftFill,
|
|
251
312
|
setFill: setLeftFill,
|
|
@@ -254,7 +315,8 @@ const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, lef
|
|
|
254
315
|
width: leftDragWidth ?? leftWidth,
|
|
255
316
|
collapsible: leftCollapsible,
|
|
256
317
|
state: leftState.state,
|
|
257
|
-
mode: leftState.mode
|
|
318
|
+
mode: leftState.mode,
|
|
319
|
+
isMobile: isLeftMobile
|
|
258
320
|
}),
|
|
259
321
|
collapsible: leftCollapsible,
|
|
260
322
|
variant: leftVariant,
|
|
@@ -266,6 +328,15 @@ const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, lef
|
|
|
266
328
|
},
|
|
267
329
|
right: {
|
|
268
330
|
...rightState,
|
|
331
|
+
...isRightMobile ? {
|
|
332
|
+
mode: "expanded",
|
|
333
|
+
state: "expanded",
|
|
334
|
+
toggle: toggleRightMobile,
|
|
335
|
+
setMode: ignoreModeChange
|
|
336
|
+
} : null,
|
|
337
|
+
isMobile: isRightMobile,
|
|
338
|
+
isMobileOpen: openMobileSide === "right",
|
|
339
|
+
setMobileOpen: setRightMobileOpen,
|
|
269
340
|
isFill: filledSide === "right",
|
|
270
341
|
toggleFill: toggleRightFill,
|
|
271
342
|
setFill: setRightFill,
|
|
@@ -274,7 +345,8 @@ const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, lef
|
|
|
274
345
|
width: rightDragWidth ?? rightWidth,
|
|
275
346
|
collapsible: rightCollapsible,
|
|
276
347
|
state: rightState.state,
|
|
277
|
-
mode: rightState.mode
|
|
348
|
+
mode: rightState.mode,
|
|
349
|
+
isMobile: isRightMobile
|
|
278
350
|
}),
|
|
279
351
|
collapsible: rightCollapsible,
|
|
280
352
|
variant: rightVariant,
|
|
@@ -285,6 +357,13 @@ const SidebarProvider = ({ children, defaultLeftMode = DEFAULT_SIDEBAR_MODE, lef
|
|
|
285
357
|
setIsDragging: setIsRightDragging
|
|
286
358
|
}
|
|
287
359
|
}), [
|
|
360
|
+
isLeftMobile,
|
|
361
|
+
isRightMobile,
|
|
362
|
+
openMobileSide,
|
|
363
|
+
toggleLeftMobile,
|
|
364
|
+
setLeftMobileOpen,
|
|
365
|
+
toggleRightMobile,
|
|
366
|
+
setRightMobileOpen,
|
|
288
367
|
leftState,
|
|
289
368
|
filledSide,
|
|
290
369
|
toggleLeftFill,
|
|
@@ -407,12 +486,39 @@ const SidebarMenuIcon = ({ ref, className, children, ...rest }) => /* @__PURE__
|
|
|
407
486
|
children
|
|
408
487
|
});
|
|
409
488
|
//#endregion
|
|
489
|
+
//#region src/components/Sidebar/SidebarMenu/useDestinationDismiss.ts
|
|
490
|
+
/**
|
|
491
|
+
* The click handler a sidebar menu item runs: the caller's own, then the sheet's dismissal.
|
|
492
|
+
*
|
|
493
|
+
* - On a phone the rail is a sheet over the page, so a chosen destination has to dismiss it —
|
|
494
|
+
* otherwise the page it navigated to sits behind the overlay.
|
|
495
|
+
* - Two kinds of click are not a destination:
|
|
496
|
+
* - Opening a popup. `DropdownMenu.Trigger` and `Sidebar.SubMenu` both hand their child an
|
|
497
|
+
* `aria-haspopup` / `aria-expanded`, and closing the sheet under their popup would take
|
|
498
|
+
* the popup with it.
|
|
499
|
+
* - Acting on the rail itself. `Sidebar.Trigger` marks its child `data-sidebar-trigger`; its
|
|
500
|
+
* own `toggle` runs after this handler, so dismissing here would hand `toggle` a closed
|
|
501
|
+
* sheet and it would open it straight back up.
|
|
502
|
+
* - Above the breakpoint the caller's `onClick` is all that runs.
|
|
503
|
+
*/
|
|
504
|
+
const useDestinationDismiss = (props, onClick) => {
|
|
505
|
+
const { side } = useSidebarInstance();
|
|
506
|
+
const { isMobile, setMobileOpen } = useSidebar(side);
|
|
507
|
+
const isDestination = props["aria-haspopup"] === void 0 && props["aria-expanded"] === void 0 && props["data-sidebar-trigger"] === void 0;
|
|
508
|
+
return (event) => {
|
|
509
|
+
onClick?.(event);
|
|
510
|
+
if (isMobile && isDestination) setMobileOpen(false);
|
|
511
|
+
};
|
|
512
|
+
};
|
|
513
|
+
//#endregion
|
|
410
514
|
//#region src/components/Sidebar/SidebarMenu/SidebarMenuButton.tsx
|
|
411
|
-
const SidebarMenuButton = ({ ref, "aria-selected": selected, className, children, asChild = false, icon, tooltip, ...props }) => {
|
|
515
|
+
const SidebarMenuButton = ({ ref, "aria-selected": selected, className, children, asChild = false, icon, tooltip, onClick, ...props }) => {
|
|
412
516
|
const Component = asChild ? Root : "button";
|
|
413
517
|
const { state, mode, side } = useSidebarInstance();
|
|
518
|
+
const handleClick = useDestinationDismiss(props, onClick);
|
|
414
519
|
const button = /* @__PURE__ */ jsxs(Component, {
|
|
415
520
|
...props,
|
|
521
|
+
onClick: handleClick,
|
|
416
522
|
ref,
|
|
417
523
|
"data-slot": "sidebar-menu-button",
|
|
418
524
|
...asChild ? {} : { type: "button" },
|
|
@@ -605,8 +711,9 @@ const SidebarMenuSub = ({ children, icon, isActive = false, label, defaultOpen =
|
|
|
605
711
|
};
|
|
606
712
|
//#endregion
|
|
607
713
|
//#region src/components/Sidebar/SidebarMenu/SidebarMenuSubItem.tsx
|
|
608
|
-
const SidebarMenuSubItem = ({ ref, className, asChild = false, children, disabled, "aria-current": ariaCurrent, ...props }) => {
|
|
714
|
+
const SidebarMenuSubItem = ({ ref, className, asChild = false, children, disabled, onClick, "aria-current": ariaCurrent, ...props }) => {
|
|
609
715
|
const { mode } = useSidebarInstance();
|
|
716
|
+
const handleClick = useDestinationDismiss(props, onClick);
|
|
610
717
|
if (mode === "collapsed" || mode === "expand-on-hover") return /* @__PURE__ */ jsx(DropdownMenu.Item, {
|
|
611
718
|
"aria-current": ariaCurrent,
|
|
612
719
|
asChild,
|
|
@@ -618,6 +725,7 @@ const SidebarMenuSubItem = ({ ref, className, asChild = false, children, disable
|
|
|
618
725
|
className: "tw:group/sidebar-menu-sub-item tw:relative",
|
|
619
726
|
children: /* @__PURE__ */ jsx(asChild ? Root : "button", {
|
|
620
727
|
...props,
|
|
728
|
+
onClick: handleClick,
|
|
621
729
|
ref,
|
|
622
730
|
"aria-current": ariaCurrent,
|
|
623
731
|
"data-slot": "sidebar-menu-sub-button",
|
|
@@ -725,22 +833,26 @@ const SidebarSeparator = ({ className, ...props }) => /* @__PURE__ */ jsx(Separa
|
|
|
725
833
|
//#endregion
|
|
726
834
|
//#region src/components/Sidebar/SidebarTrigger.tsx
|
|
727
835
|
const SidebarTrigger = ({ side = "left", onClick, hideWhenCollapsed = false, className, ...rest }) => {
|
|
728
|
-
const { toggle } = useSidebar(side);
|
|
836
|
+
const { toggle, state, isMobile, isMobileOpen } = useSidebar(side);
|
|
729
837
|
const handleOnClick = (event) => {
|
|
730
838
|
toggle();
|
|
731
839
|
onClick?.(event);
|
|
732
840
|
};
|
|
733
841
|
return /* @__PURE__ */ jsx(Slot, {
|
|
734
842
|
...rest,
|
|
843
|
+
"aria-expanded": isMobile ? isMobileOpen : state === "expanded",
|
|
844
|
+
...isMobile ? { "aria-haspopup": "dialog" } : null,
|
|
845
|
+
"data-sidebar-trigger": "",
|
|
735
846
|
onClick: handleOnClick,
|
|
736
847
|
className: cn({ "tw:group-data-[state=collapsed]/sidebar:hidden": hideWhenCollapsed }, className)
|
|
737
848
|
});
|
|
738
849
|
};
|
|
739
850
|
//#endregion
|
|
740
851
|
//#region src/components/Sidebar/Sidebar.tsx
|
|
741
|
-
const Sidebar = ({ children, className, id, side = "left", style, container = false, keepMounted, mountAfterEnter, resizable = false, ...rest }) => {
|
|
852
|
+
const Sidebar = ({ children, className, id, side = "left", style, container = false, keepMounted, mountAfterEnter, resizable = false, mobileTitle, ...rest }) => {
|
|
742
853
|
const oppositeSide = side === "left" ? "right" : "left";
|
|
743
|
-
const { setSidebarElement, state, mode, isFill, widths, collapsible, variant, isDragging } = useSidebar(side);
|
|
854
|
+
const { setSidebarElement, state, mode, isFill, widths, collapsible, variant, isDragging, isMobile, isMobileOpen, setMobileOpen } = useSidebar(side);
|
|
855
|
+
const themeScopeContainer = useThemeScopeContainer();
|
|
744
856
|
const { isMounted, completeUnmount } = useTransitionPresence({
|
|
745
857
|
mounted: collapsible !== "off-canvas" || mode !== "collapsed",
|
|
746
858
|
keepMounted,
|
|
@@ -756,6 +868,23 @@ const Sidebar = ({ children, className, id, side = "left", style, container = fa
|
|
|
756
868
|
mode,
|
|
757
869
|
side
|
|
758
870
|
]);
|
|
871
|
+
const focusOriginRef = useRef(null);
|
|
872
|
+
useEffect(() => {
|
|
873
|
+
if (!isMobile || isMobileOpen) return;
|
|
874
|
+
const remember = (event) => {
|
|
875
|
+
if (event.target instanceof HTMLElement) focusOriginRef.current = event.target;
|
|
876
|
+
};
|
|
877
|
+
document.addEventListener("focusin", remember);
|
|
878
|
+
return () => document.removeEventListener("focusin", remember);
|
|
879
|
+
}, [isMobile, isMobileOpen]);
|
|
880
|
+
const wasSheetUpRef = useRef(false);
|
|
881
|
+
useEffect(() => {
|
|
882
|
+
const wasSheetUp = wasSheetUpRef.current;
|
|
883
|
+
wasSheetUpRef.current = isMobile && isMobileOpen;
|
|
884
|
+
if (!wasSheetUp || isMobile) return;
|
|
885
|
+
const origin = focusOriginRef.current;
|
|
886
|
+
if (origin?.isConnected) origin.focus();
|
|
887
|
+
}, [isMobile, isMobileOpen]);
|
|
759
888
|
const handleTransitionEnd = (event) => {
|
|
760
889
|
if (event.target !== event.currentTarget) return;
|
|
761
890
|
completeUnmount();
|
|
@@ -768,18 +897,54 @@ const Sidebar = ({ children, className, id, side = "left", style, container = fa
|
|
|
768
897
|
"--opposite-sidebar-width": `${oppositeWidths.fill}px`
|
|
769
898
|
};
|
|
770
899
|
if (variant === "none") return null;
|
|
900
|
+
const railAttributes = {
|
|
901
|
+
"data-state": state,
|
|
902
|
+
"data-side": side,
|
|
903
|
+
"data-mode": mode,
|
|
904
|
+
"data-collapsible": collapsible,
|
|
905
|
+
"data-variant": variant,
|
|
906
|
+
"data-fill": isFill
|
|
907
|
+
};
|
|
908
|
+
if (isMobile) return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(SidebarInstanceContext, {
|
|
909
|
+
value: sidebarInstanceContextValue,
|
|
910
|
+
children: /* @__PURE__ */ jsx(Sheet, {
|
|
911
|
+
open: isMobileOpen,
|
|
912
|
+
onOpenChange: setMobileOpen,
|
|
913
|
+
children: /* @__PURE__ */ jsxs(Sheet.Content, {
|
|
914
|
+
side,
|
|
915
|
+
container: themeScopeContainer ?? void 0,
|
|
916
|
+
className: "tw:w-[min(20rem,85vw)] tw:bg-sidebar tw:text-sidebar-foreground tw:p-0",
|
|
917
|
+
onCloseAutoFocus: (event) => {
|
|
918
|
+
const origin = focusOriginRef.current;
|
|
919
|
+
if (!origin?.isConnected) return;
|
|
920
|
+
event.preventDefault();
|
|
921
|
+
origin.focus();
|
|
922
|
+
},
|
|
923
|
+
children: [/* @__PURE__ */ jsx(Sheet.Title, {
|
|
924
|
+
visuallyHidden: true,
|
|
925
|
+
children: mobileTitle ?? (side === "left" ? "Navigation" : "Side panel")
|
|
926
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
927
|
+
...rest,
|
|
928
|
+
...railAttributes,
|
|
929
|
+
id,
|
|
930
|
+
style,
|
|
931
|
+
className: cn("tw:flex tw:min-h-0 tw:flex-1 tw:flex-col", { "tw:group/sidebar tw:peer/sidebar": !container }, className),
|
|
932
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
933
|
+
"data-slot": "sidebar",
|
|
934
|
+
className: cn("tw:bg-sidebar", "tw:relative", "tw:flex", "tw:flex-col", "tw:size-full", "tw:overflow-hidden", "tw:border-sidebar-border", "tw:group-[]/sidebar:pt-2"),
|
|
935
|
+
children
|
|
936
|
+
})
|
|
937
|
+
})]
|
|
938
|
+
})
|
|
939
|
+
})
|
|
940
|
+
}) });
|
|
771
941
|
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(SidebarInstanceContext, {
|
|
772
942
|
value: sidebarInstanceContextValue,
|
|
773
943
|
children: /* @__PURE__ */ jsxs("div", {
|
|
774
944
|
...rest,
|
|
945
|
+
...railAttributes,
|
|
775
946
|
id,
|
|
776
947
|
ref: setSidebarElement,
|
|
777
|
-
"data-state": state,
|
|
778
|
-
"data-side": side,
|
|
779
|
-
"data-mode": mode,
|
|
780
|
-
"data-collapsible": collapsible,
|
|
781
|
-
"data-variant": variant,
|
|
782
|
-
"data-fill": isFill,
|
|
783
948
|
style: styles,
|
|
784
949
|
className: cn("tailwindcss-preflight", "tw:flex", "tw:relative", mode === "expand-on-hover" ? "tw:z-[51]" : "tw:z-50", { "tw:group/sidebar tw:peer/sidebar": !container }, "tw:[&>[data-slot=gap]]:w-(--sidebar-width-gap)", "tw:[&[data-side=right]>[data-slot=gap]]:rotate-180", "tw:[&>[data-slot=sidebar-wrapper]]:w-(--sidebar-width)", "tw:[&[data-side=left]>[data-slot=sidebar-wrapper]]:left-0", "tw:[&[data-side=right]>[data-slot=sidebar-wrapper]]:right-0", "tw:[&[data-state=collapsed][data-collapsible=off-canvas][data-side=left]>[data-slot=sidebar-wrapper]]:-translate-x-full", "tw:[&[data-state=collapsed][data-collapsible=off-canvas][data-side=right]>[data-slot=sidebar-wrapper]]:translate-x-full", "tw:[&[data-variant=sided-floating]>[data-slot=sidebar-wrapper]]:pt-(--sidebar-floating-padding)", "tw:[&[data-variant=sided-floating][data-side=left]>[data-slot=sidebar-wrapper]]:pr-(--sidebar-floating-padding)", "tw:[&[data-variant=sided-floating][data-side=right]>[data-slot=sidebar-wrapper]]:pl-(--sidebar-floating-padding)", "tw:[&[data-variant=floating]>[data-slot=sidebar-wrapper]]:p-(--sidebar-floating-padding)", "tw:[&[data-fill=true]>[data-slot=sidebar-wrapper]]:!w-[calc(100svw-var(--opposite-sidebar-width))]", "tw:[&[data-fill=true][data-variant=floating]>[data-slot=sidebar-wrapper]]:!p-(--sidebar-floating-padding)", "tw:[&[data-fill=true][data-variant=sided-floating][data-side=left]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:!rounded-tr-xl", "tw:[&[data-fill=true][data-variant=sided-floating][data-side=right]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:!rounded-tl-xl", "tw:[&[data-variant=inset][data-side=left]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:border-r", "tw:[&[data-variant=inset][data-side=right]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:border-l", "tw:[&[data-variant=floating]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:shadow", "tw:[&[data-variant=floating]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:rounded-xl", "tw:[&[data-variant=sided-floating]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:shadow", "tw:[&[data-variant=sided-floating][data-side=left]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:rounded-tr-xl", "tw:[&[data-variant=sided-floating][data-side=right]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:rounded-tl-xl", "tw:[&[data-variant=sided-floating][data-side=left]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:border-r", "tw:[&[data-variant=sided-floating][data-side=right]>[data-slot=sidebar-wrapper]>[data-slot=sidebar]]:border-l", isDragging ? "tw:transition-none" : "tw:transition-[width,translate,transform] tw:duration-(--sidebar-motion-duration) tw:ease-(--sidebar-motion-easing) tw:motion-reduce:transition-none"),
|
|
785
950
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -822,4 +987,4 @@ Sidebar.SubItem = SidebarMenuSubItem;
|
|
|
822
987
|
//#endregion
|
|
823
988
|
export { Sidebar, SidebarProvider, useOptionalSidebar, useSidebar };
|
|
824
989
|
|
|
825
|
-
//# sourceMappingURL=Sidebar-
|
|
990
|
+
//# sourceMappingURL=Sidebar-CLEbBtNY.js.map
|