@bizapps/design-system-testing 1.10.0 → 1.11.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/dist/main.cjs +1050 -17
- package/dist/main.cjs.map +1 -1
- package/dist/main.css +1 -1
- package/dist/main.d.cts +209 -3
- package/dist/main.d.ts +209 -3
- package/dist/main.js +1051 -19
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -2243,10 +2243,10 @@ function createStore() {
|
|
|
2243
2243
|
listeners: [],
|
|
2244
2244
|
add(item, id) {
|
|
2245
2245
|
const toastId = id ?? Math.random().toString(36).slice(2);
|
|
2246
|
-
const exists = store.toasts.find((
|
|
2246
|
+
const exists = store.toasts.find((t2) => t2.id === toastId);
|
|
2247
2247
|
if (exists) {
|
|
2248
2248
|
store.toasts = store.toasts.map(
|
|
2249
|
-
(
|
|
2249
|
+
(t2) => t2.id === toastId ? { ...t2, ...item, id: toastId } : t2
|
|
2250
2250
|
);
|
|
2251
2251
|
} else {
|
|
2252
2252
|
store.toasts = [{ id: toastId, ...item }, ...store.toasts].slice(0, MAX_TOASTS);
|
|
@@ -2261,7 +2261,7 @@ function createStore() {
|
|
|
2261
2261
|
remove(id) {
|
|
2262
2262
|
clearTimeout(timers.get(id));
|
|
2263
2263
|
timers.delete(id);
|
|
2264
|
-
store.toasts = store.toasts.filter((
|
|
2264
|
+
store.toasts = store.toasts.filter((t2) => t2.id !== id);
|
|
2265
2265
|
store.listeners.forEach((l) => l([...store.toasts]));
|
|
2266
2266
|
},
|
|
2267
2267
|
subscribe(listener) {
|
|
@@ -2405,7 +2405,7 @@ function Toaster({ position = "bottom-right", children }) {
|
|
|
2405
2405
|
"pointer-events-none fixed z-[100] flex flex-col gap-2",
|
|
2406
2406
|
positionStyles[position]
|
|
2407
2407
|
),
|
|
2408
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { mode: "sync", initial: false, children: toasts.map((
|
|
2408
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { mode: "sync", initial: false, children: toasts.map((t2) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsxRuntime.jsx(ToastCard, { ...t2 }) }, t2.id)) })
|
|
2409
2409
|
}
|
|
2410
2410
|
)
|
|
2411
2411
|
] });
|
|
@@ -5186,13 +5186,11 @@ function AbilityProvider({ children, permissions }) {
|
|
|
5186
5186
|
setImperativelyResolved(true);
|
|
5187
5187
|
}, []);
|
|
5188
5188
|
const permissionKey = permissions === void 0 ? null : [...permissions].sort().join("|");
|
|
5189
|
-
const syncedKey = react.
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
if (permissionKey === syncedKey.current) return;
|
|
5193
|
-
syncedKey.current = permissionKey;
|
|
5189
|
+
const [syncedKey, setSyncedKey] = react.useState(permissionKey);
|
|
5190
|
+
if (permissionKey !== null && permissionKey !== syncedKey) {
|
|
5191
|
+
setSyncedKey(permissionKey);
|
|
5194
5192
|
setPermissionSet(new Set(permissions));
|
|
5195
|
-
}
|
|
5193
|
+
}
|
|
5196
5194
|
const value = react.useMemo(
|
|
5197
5195
|
() => ({ can: can2, setAbilities, clearAbilities, status }),
|
|
5198
5196
|
[can2, setAbilities, clearAbilities, status]
|
|
@@ -5206,6 +5204,9 @@ function useAbility() {
|
|
|
5206
5204
|
}
|
|
5207
5205
|
return context;
|
|
5208
5206
|
}
|
|
5207
|
+
function useOptionalAbility() {
|
|
5208
|
+
return react.useContext(AbilityContext);
|
|
5209
|
+
}
|
|
5209
5210
|
function useCan(permissions, mode = "any") {
|
|
5210
5211
|
const { can: can2 } = useAbility();
|
|
5211
5212
|
return can2(permissions, mode);
|
|
@@ -9200,6 +9201,1034 @@ function BottomNavTabsList({ items, className }) {
|
|
|
9200
9201
|
}
|
|
9201
9202
|
);
|
|
9202
9203
|
}
|
|
9204
|
+
var DEFAULT_LABELS = {
|
|
9205
|
+
navigation: "Modules navigation",
|
|
9206
|
+
title: "Modules",
|
|
9207
|
+
collapse: "Collapse menu",
|
|
9208
|
+
expand: "Expand menu",
|
|
9209
|
+
openMenu: "Open menu",
|
|
9210
|
+
currentPageSuffix: " (contains the current page)",
|
|
9211
|
+
searchPlaceholder: () => "Filter links\u2026",
|
|
9212
|
+
searchLabel: (moduleLabel) => `Filter links of ${moduleLabel}`,
|
|
9213
|
+
clearSearch: "Clear search",
|
|
9214
|
+
noMatchesTitle: "No matches",
|
|
9215
|
+
noMatches: (moduleLabel, query) => `No links in ${moduleLabel} match \u201C${query}\u201D.`,
|
|
9216
|
+
flyoutNoMatches: (query) => `No links match \u201C${query}\u201D.`,
|
|
9217
|
+
emptyModule: "No links in this module yet.",
|
|
9218
|
+
addFavorite: (itemLabel) => `Add to favorites: ${itemLabel}`,
|
|
9219
|
+
removeFavorite: (itemLabel) => `Remove from favorites: ${itemLabel}`
|
|
9220
|
+
};
|
|
9221
|
+
var EASE = "cubic-bezier(.2,.8,.2,1)";
|
|
9222
|
+
var MOTION_MS = 240;
|
|
9223
|
+
var FADE_MS = MOTION_MS / 2;
|
|
9224
|
+
var BOUNCE_KEYFRAMES = [
|
|
9225
|
+
{ transform: "translateY(0) scale(1)" },
|
|
9226
|
+
{ transform: "translateY(-3px) scale(1.06)", offset: 0.35 },
|
|
9227
|
+
{ transform: "translateY(0) scale(0.97)", offset: 0.65 },
|
|
9228
|
+
{ transform: "translateY(0) scale(1)" }
|
|
9229
|
+
];
|
|
9230
|
+
var BOUNCE_MS = 420;
|
|
9231
|
+
var SUBTLE_SCROLLBAR = "[scrollbar-color:var(--floating-sidebar-scrollbar-thumb)_var(--floating-sidebar-scrollbar-track)]! [&::-webkit-scrollbar]:w-2.5! [&::-webkit-scrollbar-track]:bg-floating-sidebar-scrollbar-track! [&::-webkit-scrollbar-thumb]:rounded-full! [&::-webkit-scrollbar-thumb]:border-2! [&::-webkit-scrollbar-thumb]:border-solid! [&::-webkit-scrollbar-thumb]:border-floating-sidebar-scrollbar-track! [&::-webkit-scrollbar-thumb]:bg-floating-sidebar-scrollbar-thumb! [&::-webkit-scrollbar-thumb:hover]:bg-floating-sidebar-scrollbar-thumb-hover!";
|
|
9232
|
+
var DEFAULT_WIDTH = 276;
|
|
9233
|
+
var DEFAULT_COLLAPSED_WIDTH = 48;
|
|
9234
|
+
var MIN_COLLAPSED_WIDTH = 40;
|
|
9235
|
+
var t = (prop, ms = 300, delay = 0) => `${prop} ${ms}ms ${EASE} ${delay}ms`;
|
|
9236
|
+
function transition2(reduced, ...parts) {
|
|
9237
|
+
const kept = reduced ? parts.filter((part) => /^(opacity|visibility|background|color|box-shadow)/.test(part)) : parts;
|
|
9238
|
+
return kept.join(", ") || "none";
|
|
9239
|
+
}
|
|
9240
|
+
function useControllableState2(value, defaultValue, onChange) {
|
|
9241
|
+
const [internal, setInternal] = react.useState(defaultValue);
|
|
9242
|
+
const isControlled = value !== void 0;
|
|
9243
|
+
const current = isControlled ? value : internal;
|
|
9244
|
+
const setValue = react.useCallback(
|
|
9245
|
+
(next) => {
|
|
9246
|
+
if (!isControlled) setInternal(next);
|
|
9247
|
+
onChange?.(next);
|
|
9248
|
+
},
|
|
9249
|
+
[isControlled, onChange]
|
|
9250
|
+
);
|
|
9251
|
+
return [current, setValue];
|
|
9252
|
+
}
|
|
9253
|
+
var normalize = (value) => value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
|
|
9254
|
+
function filterItems(items, query) {
|
|
9255
|
+
const needle = normalize(query.trim());
|
|
9256
|
+
return needle ? items.filter((item) => normalize(item.label).includes(needle)) : items;
|
|
9257
|
+
}
|
|
9258
|
+
var lastUsedSidebar = null;
|
|
9259
|
+
var SHORTCUT_SIDEBAR = '[data-slot="floating-sidebar"][data-shortcut]';
|
|
9260
|
+
function isEditableTarget(target) {
|
|
9261
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
9262
|
+
if (target.closest('[data-slot="floating-sidebar-search"]')) return false;
|
|
9263
|
+
return target.closest('[contenteditable]:not([contenteditable="false"])') !== null || target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT";
|
|
9264
|
+
}
|
|
9265
|
+
function SidebarIcon({
|
|
9266
|
+
icon,
|
|
9267
|
+
resolveIcon,
|
|
9268
|
+
small = false
|
|
9269
|
+
}) {
|
|
9270
|
+
const resolved = typeof icon === "string" ? resolveIcon?.(icon) : icon;
|
|
9271
|
+
if (resolved === void 0 || resolved === null) {
|
|
9272
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": "floating-sidebar-fallback-icon", className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9273
|
+
lucideReact.CircleDashed,
|
|
9274
|
+
{
|
|
9275
|
+
"aria-hidden": "true",
|
|
9276
|
+
className: small ? "size-[18px]" : "size-5",
|
|
9277
|
+
strokeWidth: 1.5
|
|
9278
|
+
}
|
|
9279
|
+
) });
|
|
9280
|
+
}
|
|
9281
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9282
|
+
"span",
|
|
9283
|
+
{
|
|
9284
|
+
"data-slot": "floating-sidebar-icon",
|
|
9285
|
+
className: cn(
|
|
9286
|
+
"flex",
|
|
9287
|
+
"[&>svg]:stroke-[1.5]",
|
|
9288
|
+
small ? "[&>svg]:size-[18px]" : "[&>svg]:size-5"
|
|
9289
|
+
),
|
|
9290
|
+
children: resolved
|
|
9291
|
+
}
|
|
9292
|
+
);
|
|
9293
|
+
}
|
|
9294
|
+
function FloatingSidebar({
|
|
9295
|
+
modules,
|
|
9296
|
+
resolveIcon,
|
|
9297
|
+
renderLink,
|
|
9298
|
+
open: openProp,
|
|
9299
|
+
defaultOpen = true,
|
|
9300
|
+
onOpenChange,
|
|
9301
|
+
side = "left",
|
|
9302
|
+
width = DEFAULT_WIDTH,
|
|
9303
|
+
collapsedWidth = DEFAULT_COLLAPSED_WIDTH,
|
|
9304
|
+
type = "single",
|
|
9305
|
+
openModuleIds: openModulesProp,
|
|
9306
|
+
defaultOpenModuleIds = [],
|
|
9307
|
+
onOpenModulesChange,
|
|
9308
|
+
hideEmptyModules = true,
|
|
9309
|
+
activeItemId: activeItemProp,
|
|
9310
|
+
defaultActiveItemId = null,
|
|
9311
|
+
onItemSelect,
|
|
9312
|
+
favoriteIds: favoritesProp,
|
|
9313
|
+
defaultFavoriteIds = [],
|
|
9314
|
+
onFavoritesChange,
|
|
9315
|
+
showFavorites = true,
|
|
9316
|
+
loading = false,
|
|
9317
|
+
emptyState,
|
|
9318
|
+
mobileOpen: mobileOpenProp,
|
|
9319
|
+
defaultMobileOpen = false,
|
|
9320
|
+
onMobileOpenChange,
|
|
9321
|
+
shortcut = true,
|
|
9322
|
+
labels: labelsProp,
|
|
9323
|
+
className,
|
|
9324
|
+
ref,
|
|
9325
|
+
style,
|
|
9326
|
+
onPointerDownCapture,
|
|
9327
|
+
onFocusCapture,
|
|
9328
|
+
...navProps
|
|
9329
|
+
}) {
|
|
9330
|
+
const labels = { ...DEFAULT_LABELS, ...labelsProp };
|
|
9331
|
+
const reduced = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
9332
|
+
const isMobile = useIsMobile();
|
|
9333
|
+
const baseId = react.useId();
|
|
9334
|
+
const [open, setOpen] = useControllableState2(openProp, defaultOpen, onOpenChange);
|
|
9335
|
+
const [rawOpenModuleIds, setOpenModuleIds] = useControllableState2(
|
|
9336
|
+
openModulesProp,
|
|
9337
|
+
defaultOpenModuleIds,
|
|
9338
|
+
onOpenModulesChange
|
|
9339
|
+
);
|
|
9340
|
+
const railWidth = Math.max(MIN_COLLAPSED_WIDTH, collapsedWidth);
|
|
9341
|
+
const [activeItemId, setActiveItemId] = useControllableState2(
|
|
9342
|
+
activeItemProp,
|
|
9343
|
+
defaultActiveItemId
|
|
9344
|
+
);
|
|
9345
|
+
const [favoriteIds, setFavoriteIds] = useControllableState2(
|
|
9346
|
+
favoritesProp,
|
|
9347
|
+
defaultFavoriteIds,
|
|
9348
|
+
onFavoritesChange
|
|
9349
|
+
);
|
|
9350
|
+
const [mobileOpen, setMobileOpen] = useControllableState2(
|
|
9351
|
+
mobileOpenProp,
|
|
9352
|
+
defaultMobileOpen,
|
|
9353
|
+
onMobileOpenChange
|
|
9354
|
+
);
|
|
9355
|
+
const [queries, setQueries] = react.useState({});
|
|
9356
|
+
const [flyoutId, setFlyoutId] = react.useState(null);
|
|
9357
|
+
const [hoverId, setHoverId] = react.useState(null);
|
|
9358
|
+
const collapsed = !isMobile && !open;
|
|
9359
|
+
const [prevCollapsed, setPrevCollapsed] = react.useState(collapsed);
|
|
9360
|
+
const [settling, setSettling] = react.useState(false);
|
|
9361
|
+
if (prevCollapsed !== collapsed) {
|
|
9362
|
+
setPrevCollapsed(collapsed);
|
|
9363
|
+
setSettling(collapsed);
|
|
9364
|
+
setFlyoutId(null);
|
|
9365
|
+
setHoverId(null);
|
|
9366
|
+
}
|
|
9367
|
+
react.useEffect(() => {
|
|
9368
|
+
if (!settling) return;
|
|
9369
|
+
const timer = setTimeout(() => setSettling(false), MOTION_MS);
|
|
9370
|
+
return () => clearTimeout(timer);
|
|
9371
|
+
}, [settling]);
|
|
9372
|
+
const toggle = react.useCallback(() => setOpen(!open), [open, setOpen]);
|
|
9373
|
+
const navRef = react.useRef(null);
|
|
9374
|
+
react.useEffect(() => {
|
|
9375
|
+
if (!shortcut) return;
|
|
9376
|
+
const onKeyDown = (event) => {
|
|
9377
|
+
if (event.defaultPrevented || isEditableTarget(event.target)) return;
|
|
9378
|
+
if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey && event.key.toLowerCase() === "b") {
|
|
9379
|
+
const owner = event.target instanceof Element ? event.target.closest(SHORTCUT_SIDEBAR) : null;
|
|
9380
|
+
const nav2 = navRef.current;
|
|
9381
|
+
if (owner && owner !== nav2) return;
|
|
9382
|
+
if (!owner) {
|
|
9383
|
+
const fallback = lastUsedSidebar?.isConnected && lastUsedSidebar.matches(SHORTCUT_SIDEBAR) ? lastUsedSidebar : document.querySelector(SHORTCUT_SIDEBAR);
|
|
9384
|
+
if (fallback && fallback !== nav2) return;
|
|
9385
|
+
}
|
|
9386
|
+
event.preventDefault();
|
|
9387
|
+
if (isMobile) setMobileOpen(!mobileOpen);
|
|
9388
|
+
else toggle();
|
|
9389
|
+
}
|
|
9390
|
+
};
|
|
9391
|
+
document.addEventListener("keydown", onKeyDown);
|
|
9392
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
9393
|
+
}, [shortcut, toggle, isMobile, mobileOpen, setMobileOpen]);
|
|
9394
|
+
const selectItem = (item, module, navigates) => {
|
|
9395
|
+
if (navigates) setActiveItemId(item.id);
|
|
9396
|
+
setFlyoutId(null);
|
|
9397
|
+
if (isMobile) setMobileOpen(false);
|
|
9398
|
+
onItemSelect?.(item, module);
|
|
9399
|
+
};
|
|
9400
|
+
const toggleFavorite = (itemId) => setFavoriteIds(
|
|
9401
|
+
favoriteIds.includes(itemId) ? favoriteIds.filter((id) => id !== itemId) : [...favoriteIds, itemId]
|
|
9402
|
+
);
|
|
9403
|
+
const list = {
|
|
9404
|
+
activeItemId,
|
|
9405
|
+
favoriteIds: showFavorites ? favoriteIds : null,
|
|
9406
|
+
reduced,
|
|
9407
|
+
labels,
|
|
9408
|
+
resolveIcon,
|
|
9409
|
+
renderLink,
|
|
9410
|
+
onToggleFavorite: toggleFavorite
|
|
9411
|
+
};
|
|
9412
|
+
const toggleLabel = collapsed ? labels.expand : labels.collapse;
|
|
9413
|
+
const ability = useOptionalAbility();
|
|
9414
|
+
const usesPermissions = modules.some(
|
|
9415
|
+
(module) => module.permission || module.items.some((item) => item.permission)
|
|
9416
|
+
);
|
|
9417
|
+
const permissionsPending = usesPermissions && ability?.status === "loading";
|
|
9418
|
+
const isAllowed = (entry) => !entry.permission || ability?.status === "ready" && ability.can(entry.permission, entry.permissionMode);
|
|
9419
|
+
const authorizedModules = usesPermissions ? modules.filter(isAllowed).flatMap((module) => {
|
|
9420
|
+
const items = module.items.filter(isAllowed);
|
|
9421
|
+
return items.length > 0 || module.items.length === 0 ? [{ ...module, items }] : [];
|
|
9422
|
+
}) : modules;
|
|
9423
|
+
const showSkeletons = loading || permissionsPending;
|
|
9424
|
+
const visibleModules = hideEmptyModules ? authorizedModules.filter((module) => module.items.length > 0) : authorizedModules;
|
|
9425
|
+
const visibleModuleIds = new Set(visibleModules.map((module) => module.id));
|
|
9426
|
+
const openModuleIds = type === "single" ? rawOpenModuleIds.filter((id) => visibleModuleIds.has(id)).slice(0, 1) : rawOpenModuleIds;
|
|
9427
|
+
const toggleModule = (moduleId) => {
|
|
9428
|
+
const isOpen = openModuleIds.includes(moduleId);
|
|
9429
|
+
if (type === "multiple") {
|
|
9430
|
+
setOpenModuleIds(
|
|
9431
|
+
isOpen ? openModuleIds.filter((id) => id !== moduleId) : [...openModuleIds, moduleId]
|
|
9432
|
+
);
|
|
9433
|
+
} else {
|
|
9434
|
+
setOpenModuleIds(isOpen ? [] : [moduleId]);
|
|
9435
|
+
}
|
|
9436
|
+
};
|
|
9437
|
+
const nav = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9438
|
+
"nav",
|
|
9439
|
+
{
|
|
9440
|
+
...navProps,
|
|
9441
|
+
ref: (node) => {
|
|
9442
|
+
navRef.current = node;
|
|
9443
|
+
if (typeof ref === "function") return ref(node);
|
|
9444
|
+
if (ref) ref.current = node;
|
|
9445
|
+
},
|
|
9446
|
+
onPointerDownCapture: (event) => {
|
|
9447
|
+
lastUsedSidebar = event.currentTarget;
|
|
9448
|
+
onPointerDownCapture?.(event);
|
|
9449
|
+
},
|
|
9450
|
+
onFocusCapture: (event) => {
|
|
9451
|
+
lastUsedSidebar = event.currentTarget;
|
|
9452
|
+
onFocusCapture?.(event);
|
|
9453
|
+
},
|
|
9454
|
+
"data-slot": "floating-sidebar",
|
|
9455
|
+
"data-shortcut": shortcut ? "" : void 0,
|
|
9456
|
+
"data-state": collapsed ? "collapsed" : "expanded",
|
|
9457
|
+
"data-side": side,
|
|
9458
|
+
"aria-label": labels.navigation,
|
|
9459
|
+
"aria-busy": showSkeletons || void 0,
|
|
9460
|
+
className: cn(
|
|
9461
|
+
"flex h-full min-h-0 flex-col gap-3",
|
|
9462
|
+
// useIsMobile only resolves after mount; hide the inline layout on phones with CSS
|
|
9463
|
+
// so the first paint never shows it before the drawer takes over.
|
|
9464
|
+
!isMobile && "max-md:hidden",
|
|
9465
|
+
className
|
|
9466
|
+
),
|
|
9467
|
+
style: isMobile ? style : {
|
|
9468
|
+
...style,
|
|
9469
|
+
width: collapsed ? railWidth : width,
|
|
9470
|
+
transition: transition2(reduced, t("width", MOTION_MS))
|
|
9471
|
+
},
|
|
9472
|
+
children: [
|
|
9473
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9474
|
+
"div",
|
|
9475
|
+
{
|
|
9476
|
+
"data-slot": "floating-sidebar-header",
|
|
9477
|
+
className: cn(
|
|
9478
|
+
"flex h-10 shrink-0 items-center",
|
|
9479
|
+
side === "right" && "flex-row-reverse"
|
|
9480
|
+
),
|
|
9481
|
+
children: [
|
|
9482
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9483
|
+
"span",
|
|
9484
|
+
{
|
|
9485
|
+
title: labels.title,
|
|
9486
|
+
className: "text-muted-foreground overflow-hidden pl-1.5 text-[11px] font-medium tracking-[.12em] text-ellipsis whitespace-nowrap uppercase",
|
|
9487
|
+
style: {
|
|
9488
|
+
opacity: collapsed ? 0 : 1,
|
|
9489
|
+
maxWidth: collapsed ? 0 : 200,
|
|
9490
|
+
transition: transition2(
|
|
9491
|
+
reduced,
|
|
9492
|
+
t("opacity", FADE_MS, collapsed ? 0 : FADE_MS),
|
|
9493
|
+
t("max-width", MOTION_MS)
|
|
9494
|
+
)
|
|
9495
|
+
},
|
|
9496
|
+
children: labels.title
|
|
9497
|
+
}
|
|
9498
|
+
),
|
|
9499
|
+
!isMobile && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9500
|
+
"button",
|
|
9501
|
+
{
|
|
9502
|
+
type: "button",
|
|
9503
|
+
"data-slot": "floating-sidebar-toggle",
|
|
9504
|
+
"aria-label": toggleLabel,
|
|
9505
|
+
"aria-expanded": !collapsed,
|
|
9506
|
+
title: shortcut ? `${toggleLabel} (Ctrl/\u2318 + B)` : toggleLabel,
|
|
9507
|
+
onClick: toggle,
|
|
9508
|
+
className: cn(
|
|
9509
|
+
"text-primary focus-visible:ring-primary bg-sidebar border-floating-sidebar-card-border hover:bg-floating-sidebar-toggle-hover flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full border shadow-[0_2px_6px_color-mix(in_srgb,var(--color-primary)_6%,transparent)] outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
9510
|
+
side === "right" ? "mr-auto" : "ml-auto"
|
|
9511
|
+
),
|
|
9512
|
+
style: {
|
|
9513
|
+
// The auto margin keeps the toggle on the edge while the width animates;
|
|
9514
|
+
// only the outer margin changes, to center it on the collapsed rail.
|
|
9515
|
+
// (`auto` cannot be interpolated, so animating it made the toggle jump.)
|
|
9516
|
+
[side === "right" ? "marginLeft" : "marginRight"]: collapsed ? (railWidth - 32) / 2 : 0,
|
|
9517
|
+
transition: transition2(
|
|
9518
|
+
reduced,
|
|
9519
|
+
t(side === "right" ? "margin-left" : "margin-right", MOTION_MS)
|
|
9520
|
+
)
|
|
9521
|
+
},
|
|
9522
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9523
|
+
"span",
|
|
9524
|
+
{
|
|
9525
|
+
className: "flex",
|
|
9526
|
+
style: {
|
|
9527
|
+
// The chevrons point towards the edge when they collapse the sidebar.
|
|
9528
|
+
transform: collapsed !== (side === "right") ? "rotate(180deg)" : "rotate(0deg)",
|
|
9529
|
+
transition: transition2(reduced, t("transform", MOTION_MS))
|
|
9530
|
+
},
|
|
9531
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeft, { "aria-hidden": "true", className: "size-5", strokeWidth: 1.5 })
|
|
9532
|
+
}
|
|
9533
|
+
)
|
|
9534
|
+
}
|
|
9535
|
+
)
|
|
9536
|
+
]
|
|
9537
|
+
}
|
|
9538
|
+
),
|
|
9539
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9540
|
+
"div",
|
|
9541
|
+
{
|
|
9542
|
+
"data-slot": "floating-sidebar-modules",
|
|
9543
|
+
className: "flex min-h-0 flex-1 flex-col",
|
|
9544
|
+
style: {
|
|
9545
|
+
gap: collapsed ? 8 : 12,
|
|
9546
|
+
transition: transition2(reduced, t("gap", MOTION_MS))
|
|
9547
|
+
},
|
|
9548
|
+
children: [
|
|
9549
|
+
showSkeletons && Array.from({ length: 4 }, (_, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "floating-sidebar-skeleton", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9550
|
+
Skeleton,
|
|
9551
|
+
{
|
|
9552
|
+
className: collapsed ? "rounded-[14px]" : "h-[58px] w-full rounded-2xl",
|
|
9553
|
+
style: collapsed ? { width: railWidth, height: railWidth } : void 0
|
|
9554
|
+
}
|
|
9555
|
+
) }, index)),
|
|
9556
|
+
!showSkeletons && visibleModules.length === 0 && emptyState,
|
|
9557
|
+
!showSkeletons && visibleModules.map((module) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9558
|
+
ModuleCard,
|
|
9559
|
+
{
|
|
9560
|
+
tileSize: railWidth,
|
|
9561
|
+
module,
|
|
9562
|
+
regionId: `${baseId}-${module.id}`,
|
|
9563
|
+
flyoutRegionId: `${baseId}-${module.id}-flyout`,
|
|
9564
|
+
bodyWidth: isMobile ? void 0 : width - 2,
|
|
9565
|
+
collapsed,
|
|
9566
|
+
side,
|
|
9567
|
+
open: !collapsed && openModuleIds.includes(module.id),
|
|
9568
|
+
flyoutOpen: collapsed && flyoutId === module.id,
|
|
9569
|
+
anyFlyoutOpen: collapsed && flyoutId !== null,
|
|
9570
|
+
settling,
|
|
9571
|
+
tooltipOpen: collapsed && hoverId === module.id && !flyoutId,
|
|
9572
|
+
onTooltipOpenChange: (next) => setHoverId(
|
|
9573
|
+
(current) => next ? module.id : current === module.id ? null : current
|
|
9574
|
+
),
|
|
9575
|
+
onFlyoutClose: () => setFlyoutId((current) => current === module.id ? null : current),
|
|
9576
|
+
list,
|
|
9577
|
+
query: queries[module.id] ?? "",
|
|
9578
|
+
onQueryChange: (query) => setQueries((current) => ({ ...current, [module.id]: query })),
|
|
9579
|
+
onHeaderClick: () => {
|
|
9580
|
+
if (collapsed) {
|
|
9581
|
+
setHoverId(null);
|
|
9582
|
+
setFlyoutId(flyoutId === module.id ? null : module.id);
|
|
9583
|
+
} else {
|
|
9584
|
+
toggleModule(module.id);
|
|
9585
|
+
}
|
|
9586
|
+
},
|
|
9587
|
+
onSelect: (item, navigates) => selectItem(item, module, navigates)
|
|
9588
|
+
},
|
|
9589
|
+
module.id
|
|
9590
|
+
))
|
|
9591
|
+
]
|
|
9592
|
+
}
|
|
9593
|
+
)
|
|
9594
|
+
]
|
|
9595
|
+
}
|
|
9596
|
+
);
|
|
9597
|
+
if (isMobile) {
|
|
9598
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
|
|
9599
|
+
mobileOpenProp === void 0 && /* @__PURE__ */ jsxRuntime.jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9600
|
+
"button",
|
|
9601
|
+
{
|
|
9602
|
+
type: "button",
|
|
9603
|
+
"data-slot": "floating-sidebar-mobile-trigger",
|
|
9604
|
+
"aria-label": labels.openMenu,
|
|
9605
|
+
className: "text-primary focus-visible:ring-primary bg-sidebar hover:bg-sidebar-accent flex size-10 cursor-pointer items-center justify-center rounded-[10px] shadow-[0_8px_24px_color-mix(in_srgb,var(--color-primary)_8%,transparent)] outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
9606
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { "aria-hidden": "true", className: "size-5", strokeWidth: 1.5 })
|
|
9607
|
+
}
|
|
9608
|
+
) }),
|
|
9609
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9610
|
+
SheetContent,
|
|
9611
|
+
{
|
|
9612
|
+
side,
|
|
9613
|
+
"aria-describedby": void 0,
|
|
9614
|
+
className: "p-4 pt-12",
|
|
9615
|
+
onEscapeKeyDown: (event) => {
|
|
9616
|
+
const active = document.activeElement;
|
|
9617
|
+
if (active instanceof HTMLInputElement && active.value && active.closest('[data-slot="floating-sidebar-search"]')) {
|
|
9618
|
+
event.preventDefault();
|
|
9619
|
+
}
|
|
9620
|
+
},
|
|
9621
|
+
children: [
|
|
9622
|
+
/* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: labels.title }),
|
|
9623
|
+
nav
|
|
9624
|
+
]
|
|
9625
|
+
}
|
|
9626
|
+
)
|
|
9627
|
+
] }) });
|
|
9628
|
+
}
|
|
9629
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { delayDuration: 300, children: nav });
|
|
9630
|
+
}
|
|
9631
|
+
function ModuleSearch({
|
|
9632
|
+
moduleLabel,
|
|
9633
|
+
query,
|
|
9634
|
+
focusable,
|
|
9635
|
+
labels,
|
|
9636
|
+
onQueryChange,
|
|
9637
|
+
className
|
|
9638
|
+
}) {
|
|
9639
|
+
const tabIndex = focusable ? 0 : -1;
|
|
9640
|
+
const inputRef = react.useRef(null);
|
|
9641
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9642
|
+
"div",
|
|
9643
|
+
{
|
|
9644
|
+
"data-slot": "floating-sidebar-search",
|
|
9645
|
+
className: cn(
|
|
9646
|
+
"text-muted-foreground border-floating-sidebar-search-border bg-floating-sidebar-search flex h-[38px] items-center gap-2 rounded-[10px] border pr-1 pl-3",
|
|
9647
|
+
className
|
|
9648
|
+
),
|
|
9649
|
+
children: [
|
|
9650
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { "aria-hidden": "true", className: "size-4 shrink-0", strokeWidth: 1.5 }),
|
|
9651
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9652
|
+
"input",
|
|
9653
|
+
{
|
|
9654
|
+
ref: inputRef,
|
|
9655
|
+
type: "search",
|
|
9656
|
+
"aria-label": labels.searchLabel(moduleLabel),
|
|
9657
|
+
placeholder: labels.searchPlaceholder(moduleLabel),
|
|
9658
|
+
tabIndex,
|
|
9659
|
+
value: query,
|
|
9660
|
+
onChange: (event) => onQueryChange(event.target.value),
|
|
9661
|
+
onKeyDown: (event) => {
|
|
9662
|
+
if (event.key === "Escape" && query) {
|
|
9663
|
+
event.stopPropagation();
|
|
9664
|
+
onQueryChange("");
|
|
9665
|
+
}
|
|
9666
|
+
},
|
|
9667
|
+
className: "text-foreground placeholder:text-muted-foreground h-[34px] min-w-0 flex-1 border-0 bg-transparent p-0 text-[13px] outline-none [&::-webkit-search-cancel-button]:appearance-none"
|
|
9668
|
+
}
|
|
9669
|
+
),
|
|
9670
|
+
query && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9671
|
+
"button",
|
|
9672
|
+
{
|
|
9673
|
+
type: "button",
|
|
9674
|
+
"aria-label": labels.clearSearch,
|
|
9675
|
+
tabIndex,
|
|
9676
|
+
onClick: () => {
|
|
9677
|
+
onQueryChange("");
|
|
9678
|
+
inputRef.current?.focus();
|
|
9679
|
+
},
|
|
9680
|
+
className: "focus-visible:ring-primary hover:bg-accent/60 flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-lg border-0 bg-transparent outline-none focus-visible:ring-2",
|
|
9681
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true", className: "size-4", strokeWidth: 1.5 })
|
|
9682
|
+
}
|
|
9683
|
+
)
|
|
9684
|
+
]
|
|
9685
|
+
}
|
|
9686
|
+
);
|
|
9687
|
+
}
|
|
9688
|
+
function NoMatches({
|
|
9689
|
+
show,
|
|
9690
|
+
moduleLabel,
|
|
9691
|
+
query,
|
|
9692
|
+
labels,
|
|
9693
|
+
compact
|
|
9694
|
+
}) {
|
|
9695
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "data-slot": "floating-sidebar-no-matches", children: show && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9696
|
+
NoMatchesMessage,
|
|
9697
|
+
{
|
|
9698
|
+
moduleLabel,
|
|
9699
|
+
query,
|
|
9700
|
+
labels,
|
|
9701
|
+
compact
|
|
9702
|
+
}
|
|
9703
|
+
) });
|
|
9704
|
+
}
|
|
9705
|
+
function NoMatchesMessage({
|
|
9706
|
+
moduleLabel,
|
|
9707
|
+
query,
|
|
9708
|
+
labels,
|
|
9709
|
+
compact = false
|
|
9710
|
+
}) {
|
|
9711
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9712
|
+
"div",
|
|
9713
|
+
{
|
|
9714
|
+
className: cn(
|
|
9715
|
+
"flex flex-col items-center text-center",
|
|
9716
|
+
compact ? "gap-1 px-3 py-4" : "gap-1.5 px-3 py-5"
|
|
9717
|
+
),
|
|
9718
|
+
children: [
|
|
9719
|
+
!compact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9720
|
+
lucideReact.Search,
|
|
9721
|
+
{
|
|
9722
|
+
"aria-hidden": "true",
|
|
9723
|
+
className: "text-muted-foreground size-5",
|
|
9724
|
+
strokeWidth: 1.5
|
|
9725
|
+
}
|
|
9726
|
+
),
|
|
9727
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary text-sm font-semibold", children: labels.noMatchesTitle }),
|
|
9728
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-[13px] leading-[1.4]", children: compact ? labels.flyoutNoMatches(query) : labels.noMatches(moduleLabel, query) })
|
|
9729
|
+
]
|
|
9730
|
+
}
|
|
9731
|
+
);
|
|
9732
|
+
}
|
|
9733
|
+
function ModuleCard({
|
|
9734
|
+
module,
|
|
9735
|
+
tileSize,
|
|
9736
|
+
regionId,
|
|
9737
|
+
flyoutRegionId,
|
|
9738
|
+
bodyWidth,
|
|
9739
|
+
side,
|
|
9740
|
+
collapsed,
|
|
9741
|
+
open,
|
|
9742
|
+
flyoutOpen,
|
|
9743
|
+
anyFlyoutOpen,
|
|
9744
|
+
settling,
|
|
9745
|
+
tooltipOpen,
|
|
9746
|
+
onTooltipOpenChange,
|
|
9747
|
+
onFlyoutClose,
|
|
9748
|
+
list,
|
|
9749
|
+
query,
|
|
9750
|
+
onQueryChange,
|
|
9751
|
+
onHeaderClick,
|
|
9752
|
+
onSelect
|
|
9753
|
+
}) {
|
|
9754
|
+
const { activeItemId, reduced, labels, resolveIcon } = list;
|
|
9755
|
+
const hasActive = module.items.some((item) => item.id === activeItemId);
|
|
9756
|
+
const tileActive = collapsed && hasActive;
|
|
9757
|
+
const tileSelected = anyFlyoutOpen ? flyoutOpen : tileActive;
|
|
9758
|
+
const fillAfterCollapse = tileSelected && tileActive && settling && !reduced;
|
|
9759
|
+
const fillTransition = fillAfterCollapse ? `0ms linear ${MOTION_MS}ms` : `${FADE_MS}ms linear 0ms`;
|
|
9760
|
+
const iconFlipDelay = fillAfterCollapse ? MOTION_MS : FADE_MS / 2;
|
|
9761
|
+
const tilePadding = (tileSize - 2 - 20) / 2;
|
|
9762
|
+
const cardRef = react.useRef(null);
|
|
9763
|
+
const wasCollapsed = react.useRef(collapsed);
|
|
9764
|
+
react.useEffect(() => {
|
|
9765
|
+
const justCollapsed = collapsed && !wasCollapsed.current;
|
|
9766
|
+
wasCollapsed.current = collapsed;
|
|
9767
|
+
if (!justCollapsed || !hasActive || reduced) return;
|
|
9768
|
+
const animation2 = cardRef.current?.animate?.(BOUNCE_KEYFRAMES, {
|
|
9769
|
+
duration: BOUNCE_MS,
|
|
9770
|
+
delay: MOTION_MS,
|
|
9771
|
+
easing: "ease-out"
|
|
9772
|
+
});
|
|
9773
|
+
return () => animation2?.cancel();
|
|
9774
|
+
}, [collapsed, hasActive, reduced]);
|
|
9775
|
+
const items = filterItems(module.items, query);
|
|
9776
|
+
const isEmpty = module.items.length === 0;
|
|
9777
|
+
const emptyMessage = /* @__PURE__ */ jsxRuntime.jsx(
|
|
9778
|
+
"p",
|
|
9779
|
+
{
|
|
9780
|
+
"data-slot": "floating-sidebar-empty-module",
|
|
9781
|
+
className: "text-muted-foreground px-3 py-4 text-center text-[13px] leading-[1.4]",
|
|
9782
|
+
children: labels.emptyModule
|
|
9783
|
+
}
|
|
9784
|
+
);
|
|
9785
|
+
const tileRef = react.useRef(null);
|
|
9786
|
+
const closedFromOutside = react.useRef(false);
|
|
9787
|
+
const skipNextTooltip = react.useRef(false);
|
|
9788
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Popover, { open: flyoutOpen, onOpenChange: (next) => !next && onFlyoutClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9789
|
+
"div",
|
|
9790
|
+
{
|
|
9791
|
+
ref: cardRef,
|
|
9792
|
+
"data-slot": "floating-sidebar-module",
|
|
9793
|
+
"data-module-id": module.id,
|
|
9794
|
+
"data-state": open ? "open" : "closed",
|
|
9795
|
+
"data-active": hasActive ? "true" : void 0,
|
|
9796
|
+
className: cn(
|
|
9797
|
+
"relative flex min-h-0 w-full flex-col",
|
|
9798
|
+
"border",
|
|
9799
|
+
collapsed ? "rounded-[14px]" : "rounded-2xl",
|
|
9800
|
+
tileSelected ? "border-primary bg-primary" : "bg-sidebar border-floating-sidebar-card-border",
|
|
9801
|
+
open ? "shadow-[0_8px_24px_color-mix(in_srgb,var(--color-primary)_8%,transparent)]" : "shadow-[0_2px_8px_color-mix(in_srgb,var(--color-primary)_4%,transparent)]"
|
|
9802
|
+
),
|
|
9803
|
+
style: {
|
|
9804
|
+
flex: open ? "0 1 auto" : "0 0 auto",
|
|
9805
|
+
transition: transition2(
|
|
9806
|
+
reduced,
|
|
9807
|
+
t("border-radius", MOTION_MS),
|
|
9808
|
+
`background-color ${fillTransition}`,
|
|
9809
|
+
`border-color ${fillTransition}`,
|
|
9810
|
+
t("box-shadow", MOTION_MS)
|
|
9811
|
+
)
|
|
9812
|
+
},
|
|
9813
|
+
children: [
|
|
9814
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9815
|
+
Tooltip,
|
|
9816
|
+
{
|
|
9817
|
+
open: tooltipOpen,
|
|
9818
|
+
onOpenChange: (next) => {
|
|
9819
|
+
if (next && skipNextTooltip.current) return;
|
|
9820
|
+
onTooltipOpenChange(collapsed && next);
|
|
9821
|
+
},
|
|
9822
|
+
children: [
|
|
9823
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9824
|
+
"button",
|
|
9825
|
+
{
|
|
9826
|
+
ref: tileRef,
|
|
9827
|
+
type: "button",
|
|
9828
|
+
"data-slot": "floating-sidebar-module-trigger",
|
|
9829
|
+
"aria-label": collapsed && hasActive ? module.label + labels.currentPageSuffix : module.label,
|
|
9830
|
+
"aria-expanded": collapsed ? flyoutOpen : open,
|
|
9831
|
+
"aria-controls": collapsed ? flyoutOpen ? flyoutRegionId : void 0 : regionId,
|
|
9832
|
+
onClick: onHeaderClick,
|
|
9833
|
+
className: cn(
|
|
9834
|
+
"group/head focus-visible:ring-primary relative flex w-full shrink-0 cursor-pointer items-center gap-3 overflow-hidden border-0 bg-transparent text-left outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
9835
|
+
collapsed ? "rounded-[14px]" : "h-[58px] rounded-2xl",
|
|
9836
|
+
tileSelected ? "text-primary-foreground" : "text-primary"
|
|
9837
|
+
),
|
|
9838
|
+
style: {
|
|
9839
|
+
// Collapsed: a square tile (border included) with the icon centered.
|
|
9840
|
+
...collapsed && { height: tileSize - 2 },
|
|
9841
|
+
paddingLeft: collapsed ? tilePadding : 20,
|
|
9842
|
+
paddingRight: collapsed ? tilePadding : 20,
|
|
9843
|
+
transition: transition2(
|
|
9844
|
+
reduced,
|
|
9845
|
+
t("height", MOTION_MS),
|
|
9846
|
+
t("padding", MOTION_MS),
|
|
9847
|
+
`color 0ms linear ${iconFlipDelay}ms`,
|
|
9848
|
+
t("border-radius", MOTION_MS)
|
|
9849
|
+
)
|
|
9850
|
+
},
|
|
9851
|
+
children: [
|
|
9852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9853
|
+
"span",
|
|
9854
|
+
{
|
|
9855
|
+
"aria-hidden": "true",
|
|
9856
|
+
"data-slot": "floating-sidebar-module-hover",
|
|
9857
|
+
className: cn(
|
|
9858
|
+
"pointer-events-none absolute transition-colors duration-180 ease-out",
|
|
9859
|
+
// Inset on expanded cards; edge to edge on collapsed tiles.
|
|
9860
|
+
collapsed ? "inset-0 rounded-[inherit]" : "inset-1.5 rounded-[10px]",
|
|
9861
|
+
!open && (tileSelected ? "group-hover/head:bg-primary-foreground/12" : "group-hover/head:bg-floating-sidebar-hover")
|
|
9862
|
+
)
|
|
9863
|
+
}
|
|
9864
|
+
),
|
|
9865
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9866
|
+
"span",
|
|
9867
|
+
{
|
|
9868
|
+
"data-slot": "floating-sidebar-module-icon",
|
|
9869
|
+
className: "relative flex shrink-0 items-center justify-center",
|
|
9870
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SidebarIcon, { icon: module.icon, resolveIcon })
|
|
9871
|
+
}
|
|
9872
|
+
),
|
|
9873
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9874
|
+
"span",
|
|
9875
|
+
{
|
|
9876
|
+
"data-slot": "floating-sidebar-module-label",
|
|
9877
|
+
"aria-hidden": collapsed || void 0,
|
|
9878
|
+
className: "relative min-w-0 flex-1 text-sm font-medium whitespace-nowrap",
|
|
9879
|
+
style: {
|
|
9880
|
+
opacity: collapsed ? 0 : 1,
|
|
9881
|
+
transition: transition2(
|
|
9882
|
+
reduced,
|
|
9883
|
+
t("opacity", FADE_MS, collapsed ? 0 : FADE_MS)
|
|
9884
|
+
)
|
|
9885
|
+
},
|
|
9886
|
+
children: module.label
|
|
9887
|
+
}
|
|
9888
|
+
),
|
|
9889
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9890
|
+
"span",
|
|
9891
|
+
{
|
|
9892
|
+
"data-slot": "floating-sidebar-module-chevron",
|
|
9893
|
+
"aria-hidden": "true",
|
|
9894
|
+
className: cn(
|
|
9895
|
+
"relative flex shrink-0",
|
|
9896
|
+
!tileSelected && "text-muted-foreground"
|
|
9897
|
+
),
|
|
9898
|
+
style: {
|
|
9899
|
+
opacity: collapsed ? 0 : 1,
|
|
9900
|
+
transform: open ? "rotate(180deg)" : "rotate(0deg)",
|
|
9901
|
+
transition: transition2(
|
|
9902
|
+
reduced,
|
|
9903
|
+
t("transform", 220),
|
|
9904
|
+
t("opacity", FADE_MS, collapsed ? 0 : FADE_MS)
|
|
9905
|
+
)
|
|
9906
|
+
},
|
|
9907
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-3.5", strokeWidth: 1.5 })
|
|
9908
|
+
}
|
|
9909
|
+
)
|
|
9910
|
+
]
|
|
9911
|
+
}
|
|
9912
|
+
) }) }),
|
|
9913
|
+
collapsed && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9914
|
+
TooltipContent,
|
|
9915
|
+
{
|
|
9916
|
+
side: side === "right" ? "left" : "right",
|
|
9917
|
+
sideOffset: 12,
|
|
9918
|
+
"data-slot": "floating-sidebar-tooltip",
|
|
9919
|
+
children: module.label
|
|
9920
|
+
}
|
|
9921
|
+
)
|
|
9922
|
+
]
|
|
9923
|
+
}
|
|
9924
|
+
),
|
|
9925
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9926
|
+
"div",
|
|
9927
|
+
{
|
|
9928
|
+
className: "grid min-h-0 flex-[1_1_auto]",
|
|
9929
|
+
style: {
|
|
9930
|
+
gridTemplateRows: open ? "1fr" : "0fr",
|
|
9931
|
+
transition: transition2(reduced, t("grid-template-rows", MOTION_MS))
|
|
9932
|
+
},
|
|
9933
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9934
|
+
"div",
|
|
9935
|
+
{
|
|
9936
|
+
id: regionId,
|
|
9937
|
+
"data-slot": "floating-sidebar-module-content",
|
|
9938
|
+
"data-state": open ? "open" : "closed",
|
|
9939
|
+
"data-scroll": "muted",
|
|
9940
|
+
className: cn("min-h-0 overflow-x-hidden", SUBTLE_SCROLLBAR),
|
|
9941
|
+
style: {
|
|
9942
|
+
overflowY: open ? "auto" : "hidden",
|
|
9943
|
+
visibility: open ? "visible" : "hidden",
|
|
9944
|
+
transition: open ? "visibility 0s" : `visibility 0s linear ${MOTION_MS}ms`
|
|
9945
|
+
},
|
|
9946
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "floating-sidebar-module-body", style: { width: bodyWidth }, children: [
|
|
9947
|
+
isEmpty && emptyMessage,
|
|
9948
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9949
|
+
"div",
|
|
9950
|
+
{
|
|
9951
|
+
"data-slot": "floating-sidebar-search-bar",
|
|
9952
|
+
className: "bg-sidebar sticky top-0 z-[2] px-3 pb-3",
|
|
9953
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9954
|
+
ModuleSearch,
|
|
9955
|
+
{
|
|
9956
|
+
moduleLabel: module.label,
|
|
9957
|
+
query,
|
|
9958
|
+
focusable: open,
|
|
9959
|
+
labels,
|
|
9960
|
+
onQueryChange
|
|
9961
|
+
}
|
|
9962
|
+
)
|
|
9963
|
+
}
|
|
9964
|
+
),
|
|
9965
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9966
|
+
"ul",
|
|
9967
|
+
{
|
|
9968
|
+
"data-slot": "floating-sidebar-item-list",
|
|
9969
|
+
className: "flex flex-col gap-0.5 px-3 pb-3",
|
|
9970
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9971
|
+
ItemRow,
|
|
9972
|
+
{
|
|
9973
|
+
item,
|
|
9974
|
+
list,
|
|
9975
|
+
visible: open,
|
|
9976
|
+
staggerIndex: index,
|
|
9977
|
+
onSelect: (navigates) => onSelect(item, navigates)
|
|
9978
|
+
},
|
|
9979
|
+
item.id
|
|
9980
|
+
))
|
|
9981
|
+
}
|
|
9982
|
+
),
|
|
9983
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9984
|
+
NoMatches,
|
|
9985
|
+
{
|
|
9986
|
+
show: items.length === 0,
|
|
9987
|
+
moduleLabel: module.label,
|
|
9988
|
+
query,
|
|
9989
|
+
labels
|
|
9990
|
+
}
|
|
9991
|
+
)
|
|
9992
|
+
] })
|
|
9993
|
+
}
|
|
9994
|
+
)
|
|
9995
|
+
}
|
|
9996
|
+
),
|
|
9997
|
+
collapsed && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9998
|
+
PopoverContent,
|
|
9999
|
+
{
|
|
10000
|
+
id: flyoutRegionId,
|
|
10001
|
+
role: "group",
|
|
10002
|
+
"aria-label": module.label,
|
|
10003
|
+
"data-slot": "floating-sidebar-flyout",
|
|
10004
|
+
"data-side": side,
|
|
10005
|
+
side: side === "right" ? "left" : "right",
|
|
10006
|
+
align: "start",
|
|
10007
|
+
sideOffset: 16,
|
|
10008
|
+
collisionPadding: 8,
|
|
10009
|
+
className: "ring-floating-sidebar-card-border max-h-(--radix-popover-content-available-height) w-[268px] gap-0 rounded-2xl px-2 pt-4 pb-2",
|
|
10010
|
+
onEscapeKeyDown: (event) => {
|
|
10011
|
+
if (!query) return;
|
|
10012
|
+
event.preventDefault();
|
|
10013
|
+
onQueryChange("");
|
|
10014
|
+
},
|
|
10015
|
+
onInteractOutside: (event) => {
|
|
10016
|
+
if (tileRef.current?.contains(event.target)) {
|
|
10017
|
+
event.preventDefault();
|
|
10018
|
+
return;
|
|
10019
|
+
}
|
|
10020
|
+
closedFromOutside.current = true;
|
|
10021
|
+
},
|
|
10022
|
+
onCloseAutoFocus: (event) => {
|
|
10023
|
+
event.preventDefault();
|
|
10024
|
+
if (!closedFromOutside.current) {
|
|
10025
|
+
skipNextTooltip.current = true;
|
|
10026
|
+
tileRef.current?.focus();
|
|
10027
|
+
skipNextTooltip.current = false;
|
|
10028
|
+
}
|
|
10029
|
+
closedFromOutside.current = false;
|
|
10030
|
+
},
|
|
10031
|
+
children: [
|
|
10032
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10033
|
+
"div",
|
|
10034
|
+
{
|
|
10035
|
+
"data-slot": "floating-sidebar-flyout-title",
|
|
10036
|
+
className: "text-muted-foreground px-3 pb-2.5 text-[11px] font-medium tracking-[.1em] uppercase",
|
|
10037
|
+
children: module.label
|
|
10038
|
+
}
|
|
10039
|
+
),
|
|
10040
|
+
isEmpty && emptyMessage,
|
|
10041
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10042
|
+
ModuleSearch,
|
|
10043
|
+
{
|
|
10044
|
+
moduleLabel: module.label,
|
|
10045
|
+
query,
|
|
10046
|
+
focusable: flyoutOpen,
|
|
10047
|
+
labels,
|
|
10048
|
+
onQueryChange,
|
|
10049
|
+
className: "mx-2 mb-2"
|
|
10050
|
+
}
|
|
10051
|
+
),
|
|
10052
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10053
|
+
"div",
|
|
10054
|
+
{
|
|
10055
|
+
"data-slot": "floating-sidebar-flyout-list",
|
|
10056
|
+
"data-scroll": "muted",
|
|
10057
|
+
className: cn(
|
|
10058
|
+
"max-h-[420px] min-h-0 overflow-y-auto",
|
|
10059
|
+
SUBTLE_SCROLLBAR
|
|
10060
|
+
),
|
|
10061
|
+
children: [
|
|
10062
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10063
|
+
"ul",
|
|
10064
|
+
{
|
|
10065
|
+
"data-slot": "floating-sidebar-item-list",
|
|
10066
|
+
className: "flex flex-col gap-0.5",
|
|
10067
|
+
children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10068
|
+
ItemRow,
|
|
10069
|
+
{
|
|
10070
|
+
item,
|
|
10071
|
+
list,
|
|
10072
|
+
visible: flyoutOpen,
|
|
10073
|
+
onSelect: (navigates) => onSelect(item, navigates)
|
|
10074
|
+
},
|
|
10075
|
+
item.id
|
|
10076
|
+
))
|
|
10077
|
+
}
|
|
10078
|
+
),
|
|
10079
|
+
!isEmpty && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10080
|
+
NoMatches,
|
|
10081
|
+
{
|
|
10082
|
+
show: items.length === 0,
|
|
10083
|
+
moduleLabel: module.label,
|
|
10084
|
+
query,
|
|
10085
|
+
labels,
|
|
10086
|
+
compact: true
|
|
10087
|
+
}
|
|
10088
|
+
)
|
|
10089
|
+
]
|
|
10090
|
+
}
|
|
10091
|
+
)
|
|
10092
|
+
]
|
|
10093
|
+
}
|
|
10094
|
+
)
|
|
10095
|
+
]
|
|
10096
|
+
}
|
|
10097
|
+
) });
|
|
10098
|
+
}
|
|
10099
|
+
function ItemRow({ item, list, visible, staggerIndex, onSelect }) {
|
|
10100
|
+
const { activeItemId, favoriteIds, reduced, labels, resolveIcon, renderLink } = list;
|
|
10101
|
+
const active = item.id === activeItemId;
|
|
10102
|
+
const favorite = favoriteIds?.includes(item.id) ?? false;
|
|
10103
|
+
const tabIndex = visible ? 0 : -1;
|
|
10104
|
+
const staggered = staggerIndex !== void 0;
|
|
10105
|
+
const delay = staggered && visible ? Math.min(staggerIndex * 20, FADE_MS) : 0;
|
|
10106
|
+
const rowStyle = staggered ? {
|
|
10107
|
+
opacity: visible ? 1 : 0,
|
|
10108
|
+
transition: transition2(
|
|
10109
|
+
reduced,
|
|
10110
|
+
t("opacity", FADE_MS, delay),
|
|
10111
|
+
"background-color 180ms ease-out"
|
|
10112
|
+
)
|
|
10113
|
+
} : { transition: "background-color 180ms ease-out" };
|
|
10114
|
+
const className = cn(
|
|
10115
|
+
"focus-visible:ring-primary flex min-h-[46px] min-w-0 flex-1 cursor-pointer items-start gap-3 rounded-[10px] border-0 bg-transparent py-[13px] pr-1 pl-3 text-left text-[13px] leading-5 transition-transform duration-180 ease-[cubic-bezier(.2,.8,.2,1)] outline-none hover:text-primary focus-visible:ring-2 focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-50",
|
|
10116
|
+
active ? "text-primary font-bold" : "font-normal text-floating-sidebar-item-foreground hover:translate-x-0.5 motion-reduce:hover:translate-x-0"
|
|
10117
|
+
);
|
|
10118
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10119
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10120
|
+
"span",
|
|
10121
|
+
{
|
|
10122
|
+
className: cn("flex shrink-0", active ? "text-primary" : "text-muted-foreground"),
|
|
10123
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(SidebarIcon, { icon: item.icon, resolveIcon, small: true })
|
|
10124
|
+
}
|
|
10125
|
+
),
|
|
10126
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 [overflow-wrap:anywhere]", children: item.label })
|
|
10127
|
+
] });
|
|
10128
|
+
const common = {
|
|
10129
|
+
className,
|
|
10130
|
+
tabIndex,
|
|
10131
|
+
"aria-current": active ? "page" : void 0,
|
|
10132
|
+
"data-slot": "floating-sidebar-item",
|
|
10133
|
+
"data-active": active ? "true" : void 0
|
|
10134
|
+
};
|
|
10135
|
+
let control;
|
|
10136
|
+
if (item.href && !item.disabled) {
|
|
10137
|
+
const linkProps = {
|
|
10138
|
+
...common,
|
|
10139
|
+
href: item.href,
|
|
10140
|
+
children: content,
|
|
10141
|
+
// Only a plain click on an in-app link moves the current page; external links and
|
|
10142
|
+
// modifier or middle clicks open elsewhere and leave this tab where it is.
|
|
10143
|
+
onClick: (event) => onSelect(
|
|
10144
|
+
!item.external && event.button === 0 && !(event.ctrlKey || event.metaKey || event.shiftKey || event.altKey)
|
|
10145
|
+
),
|
|
10146
|
+
...item.external ? { target: "_blank", rel: "noopener noreferrer" } : {}
|
|
10147
|
+
};
|
|
10148
|
+
control = renderLink ? renderLink(linkProps, item) : /* @__PURE__ */ jsxRuntime.jsx("a", { ...linkProps });
|
|
10149
|
+
} else {
|
|
10150
|
+
control = /* @__PURE__ */ jsxRuntime.jsx(
|
|
10151
|
+
"button",
|
|
10152
|
+
{
|
|
10153
|
+
type: "button",
|
|
10154
|
+
...common,
|
|
10155
|
+
disabled: item.disabled,
|
|
10156
|
+
onClick: () => onSelect(false),
|
|
10157
|
+
children: content
|
|
10158
|
+
}
|
|
10159
|
+
);
|
|
10160
|
+
}
|
|
10161
|
+
const favoriteLabel = favorite ? labels.removeFavorite(item.label) : labels.addFavorite(item.label);
|
|
10162
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10163
|
+
"li",
|
|
10164
|
+
{
|
|
10165
|
+
"data-slot": "floating-sidebar-item-row",
|
|
10166
|
+
className: cn(
|
|
10167
|
+
"group/row relative flex shrink-0 items-start rounded-[10px]",
|
|
10168
|
+
active ? "bg-accent/70" : "hover:bg-floating-sidebar-hover"
|
|
10169
|
+
),
|
|
10170
|
+
style: rowStyle,
|
|
10171
|
+
children: [
|
|
10172
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10173
|
+
"span",
|
|
10174
|
+
{
|
|
10175
|
+
"aria-hidden": "true",
|
|
10176
|
+
"data-slot": "floating-sidebar-item-indicator",
|
|
10177
|
+
className: "bg-floating-sidebar-indicator absolute top-3.5 bottom-3.5 left-0 w-[3px] rounded-r-[3px]",
|
|
10178
|
+
style: { opacity: active ? 1 : 0, transition: "opacity 160ms ease-out" }
|
|
10179
|
+
}
|
|
10180
|
+
),
|
|
10181
|
+
control,
|
|
10182
|
+
favoriteIds && item.favoritable !== false && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10183
|
+
"button",
|
|
10184
|
+
{
|
|
10185
|
+
type: "button",
|
|
10186
|
+
"data-slot": "floating-sidebar-favorite",
|
|
10187
|
+
"data-favorite": favorite ? "true" : void 0,
|
|
10188
|
+
"aria-pressed": favorite,
|
|
10189
|
+
"aria-label": favoriteLabel,
|
|
10190
|
+
title: favoriteLabel,
|
|
10191
|
+
tabIndex,
|
|
10192
|
+
onClick: (event) => {
|
|
10193
|
+
event.stopPropagation();
|
|
10194
|
+
if (!reduced) {
|
|
10195
|
+
event.currentTarget.animate?.(
|
|
10196
|
+
[
|
|
10197
|
+
{ transform: "scale(1)" },
|
|
10198
|
+
{ transform: "scale(1.3)" },
|
|
10199
|
+
{ transform: "scale(1)" }
|
|
10200
|
+
],
|
|
10201
|
+
{ duration: 220, easing: "ease-out" }
|
|
10202
|
+
);
|
|
10203
|
+
}
|
|
10204
|
+
list.onToggleFavorite(item.id);
|
|
10205
|
+
},
|
|
10206
|
+
className: cn(
|
|
10207
|
+
"focus-visible:ring-primary hover:bg-primary/6 mt-[9px] mr-1.5 flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-lg border-0 bg-transparent outline-none focus-visible:ring-2",
|
|
10208
|
+
"hover:text-secondary",
|
|
10209
|
+
// Stars stay hidden until their row is hovered or focused, unless favorited.
|
|
10210
|
+
favorite ? "text-secondary opacity-100" : (
|
|
10211
|
+
// Revealed on row hover or focus; always shown on touch, where there is no hover.
|
|
10212
|
+
"text-muted-foreground opacity-0 group-focus-within/row:opacity-100 group-hover/row:opacity-100 [@media(hover:none)]:opacity-100"
|
|
10213
|
+
)
|
|
10214
|
+
),
|
|
10215
|
+
style: {
|
|
10216
|
+
transition: "color 120ms ease-out, background 120ms ease-out, opacity 120ms ease-out"
|
|
10217
|
+
},
|
|
10218
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10219
|
+
lucideReact.Star,
|
|
10220
|
+
{
|
|
10221
|
+
"aria-hidden": "true",
|
|
10222
|
+
className: cn("size-3.5", favorite && "fill-secondary/10"),
|
|
10223
|
+
strokeWidth: 1.5
|
|
10224
|
+
}
|
|
10225
|
+
)
|
|
10226
|
+
}
|
|
10227
|
+
)
|
|
10228
|
+
]
|
|
10229
|
+
}
|
|
10230
|
+
);
|
|
10231
|
+
}
|
|
9203
10232
|
var DrawerContext = react.createContext({ isOpen: false, modal: true });
|
|
9204
10233
|
function Drawer({ children, open, onOpenChange, modal = true, ...props }) {
|
|
9205
10234
|
const [internalOpen, setInternalOpen] = react.useState(props.defaultOpen ?? false);
|
|
@@ -9576,8 +10605,9 @@ function SignaturePad({
|
|
|
9576
10605
|
className: cn(
|
|
9577
10606
|
// Fixed light "paper": the pen is black and the PNG is read on white by others. The
|
|
9578
10607
|
// primitive keeps the pad light for consumers that define a dark theme, where a themed
|
|
9579
|
-
// surface (`background`, `border`) would turn dark and hide the black ink.
|
|
9580
|
-
|
|
10608
|
+
// surface (`background`, `border`) would turn dark and hide the black ink. The edge
|
|
10609
|
+
// uses `dark-400` (4.66:1 on white) so the pad reads as a control (WCAG 1.4.11).
|
|
10610
|
+
"bg-main-alternative-secondary border-dark-400 relative overflow-hidden rounded-xl border",
|
|
9581
10611
|
"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
|
|
9582
10612
|
className
|
|
9583
10613
|
),
|
|
@@ -9595,21 +10625,23 @@ function SignaturePad({
|
|
|
9595
10625
|
className: "block w-full touch-none"
|
|
9596
10626
|
}
|
|
9597
10627
|
),
|
|
9598
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10628
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9599
10629
|
Button,
|
|
9600
10630
|
{
|
|
9601
10631
|
type: "button",
|
|
9602
10632
|
variant: "ghost",
|
|
9603
|
-
size: "
|
|
10633
|
+
size: "sm",
|
|
9604
10634
|
"data-slot": "signature-pad-clear",
|
|
9605
|
-
"aria-label": clearLabel,
|
|
9606
10635
|
disabled,
|
|
9607
10636
|
"aria-disabled": empty && !disabled ? true : void 0,
|
|
9608
10637
|
onClick: () => {
|
|
9609
10638
|
if (!emptyRef.current) clear();
|
|
9610
10639
|
},
|
|
9611
|
-
className: "bg-main-white text-dark-600 border-dark-
|
|
9612
|
-
children:
|
|
10640
|
+
className: "bg-main-white text-dark-600 border-dark-400 hover:bg-dark-100 hover:text-main-black aria-disabled:hover:bg-main-white absolute right-2 bottom-2 h-11 max-w-[calc(100%-1rem)] gap-1.5 rounded-full border border-solid px-4 text-sm aria-disabled:cursor-not-allowed aria-disabled:opacity-70",
|
|
10641
|
+
children: [
|
|
10642
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BrushCleaning, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
10643
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: clearLabel })
|
|
10644
|
+
]
|
|
9613
10645
|
}
|
|
9614
10646
|
)
|
|
9615
10647
|
]
|
|
@@ -9765,6 +10797,7 @@ exports.FieldError = FieldError;
|
|
|
9765
10797
|
exports.FieldGroup = FieldGroup;
|
|
9766
10798
|
exports.FieldLabel = FieldLabel;
|
|
9767
10799
|
exports.FilterOption = FilterOption;
|
|
10800
|
+
exports.FloatingSidebar = FloatingSidebar;
|
|
9768
10801
|
exports.Input = Input;
|
|
9769
10802
|
exports.Item = Item;
|
|
9770
10803
|
exports.ItemActions = ItemActions;
|