@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/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
- var _a;
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
- useEffect(() => {
12436
- let cancelled = false;
12432
+ useLayoutEffect(() => {
12437
12433
  if (open) {
12438
12434
  stateRef.current = "initial";
12439
- requestAnimationFrame(() => {
12440
- if (cancelled) return;
12441
- const h = measureContentHeight();
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
- let cancelled = false;
12457
- requestAnimationFrame(() => {
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
- }, [activeKey]);
12472
- const dragDirection = useRef(null);
12473
- const handlePanStart = () => {
12474
- dragDirection.current = null;
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 handlePan = (_, info) => {
12477
- dragDirection.current = info.offset.y < 0 ? "up" : "down";
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 handlePanEnd = () => {
12480
- const dir = dragDirection.current;
12481
- if (!dir) return;
12482
- if (dir === "up") {
12483
- if (stateRef.current === "initial") {
12484
- stateRef.current = "full";
12485
- springTo(getAvailableHeight());
12486
- }
12487
- } else {
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(cachedInitialHeight.current);
12491
- } else if (stateRef.current === "initial") {
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
- motion.div,
12500
- {
12501
- ref: panelRef,
12502
- className: cn("mobile-nav-panel", className),
12503
- "data-closed": !open || void 0,
12504
- style: { height: heightMV },
12505
- children: [
12506
- /* @__PURE__ */ jsx(
12507
- motion.div,
12508
- {
12509
- className: "mobile-nav-handle",
12510
- onPanStart: handlePanStart,
12511
- onPan: handlePan,
12512
- onPanEnd: handlePanEnd,
12513
- children: /* @__PURE__ */ jsx("div", { className: "mobile-nav-handle-bar" })
12514
- }
12515
- ),
12516
- /* @__PURE__ */ jsx("div", { ref: contentRef, className: "mobile-nav-content", children: activeKey ? children(activeKey) : null })
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syscore/ui-library",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "A comprehensive React component library built with Radix UI, Tailwind CSS, and TypeScript",
5
5
  "private": false,
6
6
  "type": "module",