@syscore/ui-library 1.16.0 → 1.18.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/client/components/ui/mobile-nav.tsx +112 -73
- package/client/global.css +68 -2
- package/client/ui/MobileNav.stories.tsx +119 -63
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +100 -69
- package/package.json +1 -1
package/dist/index.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import React__default, { useState, useEffect, useCallback, useRef, createContext, useMemo, useContext } from "react";
|
|
3
|
+
import React__default, { useState, useEffect, useCallback, useRef, createContext, useMemo, useLayoutEffect, useContext } from "react";
|
|
4
4
|
import { motion, AnimatePresence, useMotionValue, animate } from "motion/react";
|
|
5
5
|
import { clsx } from "clsx";
|
|
6
6
|
import { twMerge } from "tailwind-merge";
|
|
@@ -12410,10 +12410,7 @@ const MobileNavPanel = ({ className, children }) => {
|
|
|
12410
12410
|
return (nav == null ? void 0 : nav.offsetHeight) ?? 0;
|
|
12411
12411
|
};
|
|
12412
12412
|
const getAvailableHeight = () => {
|
|
12413
|
-
|
|
12414
|
-
const parent = (_a = panelRef.current) == null ? void 0 : _a.parentElement;
|
|
12415
|
-
const container = (parent == null ? void 0 : parent.clientHeight) ?? window.innerHeight;
|
|
12416
|
-
return container - getNavBarHeight();
|
|
12413
|
+
return window.innerHeight - getNavBarHeight();
|
|
12417
12414
|
};
|
|
12418
12415
|
const measureContentHeight = () => {
|
|
12419
12416
|
const content = contentRef.current;
|
|
@@ -12432,91 +12429,122 @@ const MobileNavPanel = ({ className, children }) => {
|
|
|
12432
12429
|
});
|
|
12433
12430
|
stopAnimation.current = () => controls.stop();
|
|
12434
12431
|
};
|
|
12435
|
-
|
|
12436
|
-
let cancelled = false;
|
|
12432
|
+
useLayoutEffect(() => {
|
|
12437
12433
|
if (open) {
|
|
12438
12434
|
stateRef.current = "initial";
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
cachedInitialHeight.current = h;
|
|
12443
|
-
springTo(h);
|
|
12444
|
-
});
|
|
12435
|
+
const h = measureContentHeight();
|
|
12436
|
+
cachedInitialHeight.current = h;
|
|
12437
|
+
springTo(h);
|
|
12445
12438
|
} else {
|
|
12446
12439
|
stateRef.current = "closed";
|
|
12447
12440
|
cachedInitialHeight.current = 0;
|
|
12448
12441
|
springTo(0);
|
|
12449
12442
|
}
|
|
12450
|
-
return () => {
|
|
12451
|
-
cancelled = true;
|
|
12452
|
-
};
|
|
12453
12443
|
}, [open]);
|
|
12444
|
+
useLayoutEffect(() => {
|
|
12445
|
+
if (!open) return;
|
|
12446
|
+
const h = measureContentHeight();
|
|
12447
|
+
cachedInitialHeight.current = h;
|
|
12448
|
+
if (stateRef.current !== "full") {
|
|
12449
|
+
stateRef.current = "initial";
|
|
12450
|
+
springTo(h);
|
|
12451
|
+
}
|
|
12452
|
+
}, [activeKey]);
|
|
12454
12453
|
useEffect(() => {
|
|
12455
12454
|
if (!open) return;
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
requestAnimationFrame(() => {
|
|
12459
|
-
if (cancelled) return;
|
|
12460
|
-
const h = measureContentHeight();
|
|
12461
|
-
cachedInitialHeight.current = h;
|
|
12462
|
-
if (stateRef.current === "initial" || stateRef.current === "closed") {
|
|
12463
|
-
stateRef.current = "initial";
|
|
12464
|
-
springTo(h);
|
|
12465
|
-
}
|
|
12466
|
-
});
|
|
12467
|
-
});
|
|
12468
|
-
return () => {
|
|
12469
|
-
cancelled = true;
|
|
12455
|
+
const handleKeyDown = (e) => {
|
|
12456
|
+
if (e.key === "Escape") close();
|
|
12470
12457
|
};
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12458
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
12459
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
12460
|
+
}, [open, close]);
|
|
12461
|
+
const isDragging = useRef(false);
|
|
12462
|
+
const lastY = useRef(0);
|
|
12463
|
+
const dragStartY = useRef(0);
|
|
12464
|
+
const dragStartTime = useRef(0);
|
|
12465
|
+
const dragMaxHeight = useRef(0);
|
|
12466
|
+
const handlePointerDown = (e) => {
|
|
12467
|
+
var _a;
|
|
12468
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
12469
|
+
(_a = stopAnimation.current) == null ? void 0 : _a.call(stopAnimation);
|
|
12470
|
+
isDragging.current = true;
|
|
12471
|
+
lastY.current = e.clientY;
|
|
12472
|
+
dragStartY.current = e.clientY;
|
|
12473
|
+
dragStartTime.current = Date.now();
|
|
12474
|
+
dragMaxHeight.current = getAvailableHeight();
|
|
12475
12475
|
};
|
|
12476
|
-
const
|
|
12477
|
-
|
|
12476
|
+
const handlePointerMove = (e) => {
|
|
12477
|
+
if (!isDragging.current) return;
|
|
12478
|
+
const dy = e.clientY - lastY.current;
|
|
12479
|
+
lastY.current = e.clientY;
|
|
12480
|
+
const current = heightMV.get();
|
|
12481
|
+
const next = Math.max(0, current - dy);
|
|
12482
|
+
heightMV.set(Math.min(next, dragMaxHeight.current));
|
|
12478
12483
|
};
|
|
12479
|
-
const
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12484
|
+
const handlePointerUp = (e) => {
|
|
12485
|
+
if (!isDragging.current) return;
|
|
12486
|
+
isDragging.current = false;
|
|
12487
|
+
const currentHeight = heightMV.get();
|
|
12488
|
+
const initial = cachedInitialHeight.current;
|
|
12489
|
+
const full = dragMaxHeight.current;
|
|
12490
|
+
const elapsed = Date.now() - dragStartTime.current;
|
|
12491
|
+
const totalDy = e.clientY - dragStartY.current;
|
|
12492
|
+
const velocity = elapsed > 0 ? totalDy / elapsed * 1e3 : 0;
|
|
12493
|
+
const VELOCITY_THRESHOLD = 500;
|
|
12494
|
+
if (velocity > VELOCITY_THRESHOLD) {
|
|
12488
12495
|
if (stateRef.current === "full") {
|
|
12489
12496
|
stateRef.current = "initial";
|
|
12490
|
-
springTo(
|
|
12491
|
-
} else
|
|
12497
|
+
springTo(initial);
|
|
12498
|
+
} else {
|
|
12492
12499
|
stateRef.current = "closed";
|
|
12493
12500
|
springTo(0);
|
|
12494
12501
|
close();
|
|
12495
12502
|
}
|
|
12503
|
+
} else if (velocity < -VELOCITY_THRESHOLD) {
|
|
12504
|
+
stateRef.current = "full";
|
|
12505
|
+
springTo(full);
|
|
12506
|
+
} else {
|
|
12507
|
+
const midInitial = initial / 2;
|
|
12508
|
+
const midFull = (initial + full) / 2;
|
|
12509
|
+
if (currentHeight < midInitial) {
|
|
12510
|
+
stateRef.current = "closed";
|
|
12511
|
+
springTo(0);
|
|
12512
|
+
close();
|
|
12513
|
+
} else if (currentHeight < midFull) {
|
|
12514
|
+
stateRef.current = "initial";
|
|
12515
|
+
springTo(initial);
|
|
12516
|
+
} else {
|
|
12517
|
+
stateRef.current = "full";
|
|
12518
|
+
springTo(full);
|
|
12519
|
+
}
|
|
12496
12520
|
}
|
|
12497
12521
|
};
|
|
12498
|
-
return /* @__PURE__ */ jsxs(
|
|
12499
|
-
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12522
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12523
|
+
open && /* @__PURE__ */ jsx("div", { className: "mobile-nav-overlay", onClick: close, "aria-hidden": true }),
|
|
12524
|
+
/* @__PURE__ */ jsxs(
|
|
12525
|
+
motion.div,
|
|
12526
|
+
{
|
|
12527
|
+
ref: panelRef,
|
|
12528
|
+
className: cn("mobile-nav-panel", className),
|
|
12529
|
+
"data-closed": !open || void 0,
|
|
12530
|
+
style: { height: heightMV },
|
|
12531
|
+
children: [
|
|
12532
|
+
/* @__PURE__ */ jsx(
|
|
12533
|
+
"div",
|
|
12534
|
+
{
|
|
12535
|
+
className: "mobile-nav-handle",
|
|
12536
|
+
onPointerDown: handlePointerDown,
|
|
12537
|
+
onPointerMove: handlePointerMove,
|
|
12538
|
+
onPointerUp: handlePointerUp,
|
|
12539
|
+
onPointerCancel: handlePointerUp,
|
|
12540
|
+
children: /* @__PURE__ */ jsx("div", { className: "mobile-nav-handle-bar" })
|
|
12541
|
+
}
|
|
12542
|
+
),
|
|
12543
|
+
/* @__PURE__ */ jsx("div", { ref: contentRef, className: "mobile-nav-content", children: activeKey ? children(activeKey) : null })
|
|
12544
|
+
]
|
|
12545
|
+
}
|
|
12546
|
+
)
|
|
12547
|
+
] });
|
|
12520
12548
|
};
|
|
12521
12549
|
const MobileNavBar = ({ className, children }) => /* @__PURE__ */ jsx("nav", { className: cn("mobile-nav-bar", className), children: /* @__PURE__ */ jsx("div", { className: "mobile-nav-bar-inner", children }) });
|
|
12522
12550
|
const MobileNavTrigger = ({
|
|
@@ -12524,6 +12552,7 @@ const MobileNavTrigger = ({
|
|
|
12524
12552
|
children,
|
|
12525
12553
|
label,
|
|
12526
12554
|
onAction,
|
|
12555
|
+
disabled,
|
|
12527
12556
|
className
|
|
12528
12557
|
}) => {
|
|
12529
12558
|
const { activeKey, open, toggle, close } = useMobileNav();
|
|
@@ -12539,7 +12568,9 @@ const MobileNavTrigger = ({
|
|
|
12539
12568
|
"button",
|
|
12540
12569
|
{
|
|
12541
12570
|
onClick: handleClick,
|
|
12571
|
+
disabled,
|
|
12542
12572
|
"data-active": activeKey === value || void 0,
|
|
12573
|
+
"aria-expanded": activeKey === value && open,
|
|
12543
12574
|
className: cn("mobile-nav-trigger group", className),
|
|
12544
12575
|
"aria-label": label,
|
|
12545
12576
|
children
|