@scripso-homepad/ui 0.4.40 → 0.4.42

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.
@@ -27566,7 +27566,7 @@ var require_react_dom_development = __commonJS({
27566
27566
  return root2;
27567
27567
  }
27568
27568
  var ReactVersion = "18.3.1";
27569
- function createPortal3(children, containerInfo, implementation) {
27569
+ function createPortal4(children, containerInfo, implementation) {
27570
27570
  var key = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : null;
27571
27571
  {
27572
27572
  checkKeyStringCoercion(key);
@@ -28422,7 +28422,7 @@ var require_react_dom_development = __commonJS({
28422
28422
  if (!isValidContainer(container)) {
28423
28423
  throw new Error("Target container is not a DOM element.");
28424
28424
  }
28425
- return createPortal3(children, container, null, key);
28425
+ return createPortal4(children, container, null, key);
28426
28426
  }
28427
28427
  function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
28428
28428
  return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback);
@@ -29580,7 +29580,12 @@ function isNavItemActive(pathname, item) {
29580
29580
  }
29581
29581
  return pathname === item.to || pathname.startsWith(`${item.to}/`);
29582
29582
  }
29583
- function SidebarNavItem({ item, isOpen, isActive, onNavigate }) {
29583
+ function SidebarNavItem({
29584
+ item,
29585
+ isOpen,
29586
+ isActive,
29587
+ onNavigate
29588
+ }) {
29584
29589
  if (item.hidden) {
29585
29590
  return null;
29586
29591
  }
@@ -29598,6 +29603,7 @@ function SidebarNavItem({ item, isOpen, isActive, onNavigate }) {
29598
29603
  type: "button",
29599
29604
  onClick: handleClick,
29600
29605
  "aria-current": isActive ? "page" : void 0,
29606
+ "data-onboarding": item.onboardingId,
29601
29607
  "aria-disabled": item.disabled,
29602
29608
  disabled: item.disabled,
29603
29609
  tabIndex: item.disabled ? -1 : void 0,
@@ -29867,12 +29873,12 @@ function Sidebar({
29867
29873
  )
29868
29874
  }
29869
29875
  ),
29870
- showCollapsedRail && mobileOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-screen w-[76px] shrink-0", "aria-hidden": true }) : null,
29876
+ showCollapsedRail && mobileOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-dvh w-[76px] shrink-0", "aria-hidden": true }) : null,
29871
29877
  /* @__PURE__ */ jsxRuntime.jsxs(
29872
29878
  "aside",
29873
29879
  {
29874
29880
  className: cn(
29875
- "fixed inset-y-0 left-0 z-50 flex h-screen w-[min(300px,85vw)] flex-col gap-8 overflow-hidden bg-navy p-4 shadow-xl",
29881
+ "fixed inset-y-0 left-0 z-50 flex h-dvh w-[min(300px,85vw)] flex-col gap-8 overflow-hidden bg-navy p-4 shadow-xl",
29876
29882
  "transition-[transform,width,padding,gap] duration-300 ease-in-out will-change-[transform,width]",
29877
29883
  mobileOpen ? "translate-x-0" : "-translate-x-full pointer-events-none",
29878
29884
  "md:relative md:z-auto md:w-[76px] md:translate-x-0 md:pointer-events-auto md:shadow-none md:items-center md:gap-2 md:px-3 md:py-4",
@@ -30005,9 +30011,9 @@ function DashboardLayout({
30005
30011
  className,
30006
30012
  mainClassName
30007
30013
  }) {
30008
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-screen min-w-0 overflow-hidden flex-row bg-storm-gray-0", className), children: [
30009
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-md:contents md:h-screen md:shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Sidebar, { ...sidebar }) }),
30010
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-screen min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: [
30014
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-dvh min-w-0 overflow-hidden flex-row bg-storm-gray-0", className), children: [
30015
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-md:contents md:h-dvh md:shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Sidebar, { ...sidebar }) }),
30016
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-dvh min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: [
30011
30017
  /* @__PURE__ */ jsxRuntime.jsx(SidebarMobileHeader, { ...mobileHeader }),
30012
30018
  /* @__PURE__ */ jsxRuntime.jsx(AppHeader, { ...header }),
30013
30019
  /* @__PURE__ */ jsxRuntime.jsx("main", { className: mainClassName ?? "min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto p-4 xl:p-6", children })
@@ -30539,16 +30545,16 @@ function TableHead({
30539
30545
  sortDirection = null,
30540
30546
  onSort,
30541
30547
  children,
30548
+ onClick,
30549
+ onKeyDown,
30542
30550
  ...props
30543
30551
  }) {
30544
30552
  const isSortable = sortable && onSort != null;
30545
30553
  const content = isSortable ? /* @__PURE__ */ jsxRuntime.jsxs(
30546
- "button",
30554
+ "span",
30547
30555
  {
30548
- type: "button",
30549
- onClick: onSort,
30550
30556
  className: cn(
30551
- "inline-flex w-full cursor-pointer items-center gap-2.5 border-0 bg-transparent p-0 font-[inherit] text-[length:inherit] leading-[inherit] tracking-[inherit] text-inherit transition-colors hover:text-storm-gray-500",
30557
+ "inline-flex w-full items-center gap-2.5 font-[inherit] text-[length:inherit] leading-[inherit] tracking-[inherit] text-inherit",
30552
30558
  tableHeadSortButtonAlignClasses[align]
30553
30559
  ),
30554
30560
  children: [
@@ -30565,10 +30571,29 @@ function TableHead({
30565
30571
  tableHeadPaddingClassName,
30566
30572
  tableHeaderClassName,
30567
30573
  !isSortable && tableAlignClasses[align],
30574
+ isSortable && "cursor-pointer select-none hover:text-storm-gray-500",
30568
30575
  className
30569
30576
  ),
30570
30577
  "aria-sort": resolveAriaSort(sortDirection, isSortable),
30578
+ tabIndex: isSortable ? 0 : void 0,
30571
30579
  ...props,
30580
+ onClick: (event) => {
30581
+ onClick?.(event);
30582
+ if (event.defaultPrevented || !isSortable) {
30583
+ return;
30584
+ }
30585
+ onSort();
30586
+ },
30587
+ onKeyDown: (event) => {
30588
+ onKeyDown?.(event);
30589
+ if (event.defaultPrevented || !isSortable) {
30590
+ return;
30591
+ }
30592
+ if (event.key === "Enter" || event.key === " ") {
30593
+ event.preventDefault();
30594
+ onSort();
30595
+ }
30596
+ },
30572
30597
  children: content
30573
30598
  }
30574
30599
  );
@@ -30670,7 +30695,10 @@ function clampMenuLeft(left, menuWidth) {
30670
30695
  return left;
30671
30696
  }
30672
30697
  const minLeft = MENU_VIEWPORT_MARGIN_PX;
30673
- const maxLeft = Math.max(minLeft, window.innerWidth - menuWidth - MENU_VIEWPORT_MARGIN_PX);
30698
+ const maxLeft = Math.max(
30699
+ minLeft,
30700
+ window.innerWidth - menuWidth - MENU_VIEWPORT_MARGIN_PX
30701
+ );
30674
30702
  return Math.min(Math.max(left, minLeft), maxLeft);
30675
30703
  }
30676
30704
  function resolveMenuItemIcon(item) {
@@ -30693,7 +30721,9 @@ function TableActionsMenu({
30693
30721
  menuClassName,
30694
30722
  triggerIcon,
30695
30723
  menuWidth = MENU_WIDTH_PX,
30696
- menuFitContent = true
30724
+ menuFitContent = true,
30725
+ forceOpen,
30726
+ menuOnboardingId
30697
30727
  }) {
30698
30728
  const [open, setOpen] = react.useState(false);
30699
30729
  const [menuPosition, setMenuPosition] = react.useState(null);
@@ -30702,8 +30732,17 @@ function TableActionsMenu({
30702
30732
  const triggerRef = react.useRef(null);
30703
30733
  const menuId = react.useId();
30704
30734
  const closeMenu = react.useCallback(() => {
30735
+ if (forceOpen) {
30736
+ return;
30737
+ }
30705
30738
  setOpen(false);
30706
- }, []);
30739
+ }, [forceOpen]);
30740
+ react.useEffect(() => {
30741
+ if (forceOpen === void 0) {
30742
+ return;
30743
+ }
30744
+ setOpen(forceOpen);
30745
+ }, [forceOpen]);
30707
30746
  const updateMenuPosition = react.useCallback(() => {
30708
30747
  const trigger = triggerRef.current;
30709
30748
  const menuEl = menuRef.current;
@@ -30713,7 +30752,10 @@ function TableActionsMenu({
30713
30752
  const rect = trigger.getBoundingClientRect();
30714
30753
  const viewportMaxWidth = typeof window === "undefined" ? menuWidth : Math.max(menuWidth, window.innerWidth - MENU_VIEWPORT_MARGIN_PX * 2);
30715
30754
  const measuredWidth = menuFitContent ? menuEl?.offsetWidth || menuEl?.getBoundingClientRect().width || menuWidth : menuWidth;
30716
- const resolvedMenuWidth = Math.min(Math.max(measuredWidth, 1), viewportMaxWidth);
30755
+ const resolvedMenuWidth = Math.min(
30756
+ Math.max(measuredWidth, 1),
30757
+ viewportMaxWidth
30758
+ );
30717
30759
  setMenuPosition({
30718
30760
  top: rect.bottom + MENU_OFFSET_PX,
30719
30761
  left: clampMenuLeft(rect.right - resolvedMenuWidth, resolvedMenuWidth)
@@ -30732,6 +30774,9 @@ function TableActionsMenu({
30732
30774
  return;
30733
30775
  }
30734
30776
  const closeOnScroll = () => {
30777
+ if (forceOpen) {
30778
+ return;
30779
+ }
30735
30780
  closeMenu();
30736
30781
  };
30737
30782
  window.addEventListener("resize", updateMenuPosition);
@@ -30748,7 +30793,7 @@ function TableActionsMenu({
30748
30793
  window.removeEventListener("scroll", closeOnScroll, true);
30749
30794
  document.removeEventListener("keydown", closeOnEscape);
30750
30795
  };
30751
- }, [closeMenu, open, updateMenuPosition]);
30796
+ }, [closeMenu, forceOpen, open, updateMenuPosition]);
30752
30797
  if (items.length === 0) {
30753
30798
  return null;
30754
30799
  }
@@ -30768,6 +30813,7 @@ function TableActionsMenu({
30768
30813
  visibility: menuPosition != null ? "visible" : "hidden",
30769
30814
  pointerEvents: menuPosition != null ? "auto" : "none"
30770
30815
  },
30816
+ ...menuOnboardingId ? { "data-onboarding": menuOnboardingId } : {},
30771
30817
  className: cn(
30772
30818
  "z-50 overflow-hidden rounded-2xl border border-storm-gray-50 bg-white shadow-[0_4px_20px_0_rgba(0,0,0,0.05)]",
30773
30819
  menuClassName
@@ -31246,6 +31292,7 @@ function Modal({
31246
31292
  closeOnBackdrop = true,
31247
31293
  closeOnEscape = true,
31248
31294
  containerClassName,
31295
+ containerDataOnboarding,
31249
31296
  contentClassName,
31250
31297
  buttonClassName
31251
31298
  }) {
@@ -31270,14 +31317,11 @@ function Modal({
31270
31317
  if (!open) {
31271
31318
  return null;
31272
31319
  }
31273
- const sharedButtonClassName = cn(
31274
- "btn h-13 w-full! min-w-0! justify-center!",
31275
- buttonClassName
31276
- );
31320
+ const sharedButtonClassName = cn("btn h-13 w-full! min-w-0! justify-center!", buttonClassName);
31277
31321
  const modal = /* @__PURE__ */ jsxRuntime.jsx(
31278
31322
  "div",
31279
31323
  {
31280
- className: "fixed inset-0 z-[100] flex items-center justify-center p-4 backdrop-blur-[12px] bg-storm-gray-850/40",
31324
+ className: "homepad-modal-in fixed inset-0 z-[100] flex items-center justify-center bg-storm-gray-850/40 p-4 backdrop-blur-[12px]",
31281
31325
  onPointerDown: backdropDismiss.onPointerDown,
31282
31326
  onClick: backdropDismiss.onClick,
31283
31327
  role: "presentation",
@@ -31288,6 +31332,7 @@ function Modal({
31288
31332
  "aria-modal": "true",
31289
31333
  "aria-labelledby": "homepad-modal-title",
31290
31334
  ...subtitle ? { "aria-describedby": "homepad-modal-subtitle" } : {},
31335
+ ...containerDataOnboarding ? { "data-onboarding": containerDataOnboarding } : {},
31291
31336
  className: cn(
31292
31337
  "flex max-h-[min(90dvh,calc(100dvh-2rem))] w-full max-w-2xl flex-col gap-6 rounded-2xl bg-white p-4 opacity-100 md:p-6",
31293
31338
  containerClassName
@@ -31326,7 +31371,16 @@ function Modal({
31326
31371
  ) : null
31327
31372
  ] })
31328
31373
  ] }),
31329
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("drawer-scroll-area min-h-0 min-w-0 flex-1 overflow-y-auto", contentClassName), children }),
31374
+ /* @__PURE__ */ jsxRuntime.jsx(
31375
+ "div",
31376
+ {
31377
+ className: cn(
31378
+ "drawer-scroll-area min-h-0 min-w-0 flex-1 overflow-y-auto",
31379
+ contentClassName
31380
+ ),
31381
+ children
31382
+ }
31383
+ ),
31330
31384
  /* @__PURE__ */ jsxRuntime.jsxs(
31331
31385
  "footer",
31332
31386
  {
@@ -31369,16 +31423,22 @@ function Modal({
31369
31423
  );
31370
31424
  return typeof document !== "undefined" ? (0, import_react_dom2.createPortal)(modal, document.body) : modal;
31371
31425
  }
31426
+
31427
+ // src/web/components/Drawer.tsx
31428
+ var import_react_dom3 = __toESM(require_react_dom());
31372
31429
  var DRAWER_TRANSITION_MS = 300;
31373
31430
  var bodyScrollLockCount = 0;
31374
31431
  var previousBodyOverflow = "";
31432
+ var previousHtmlOverflow = "";
31375
31433
  function lockBodyScroll() {
31376
31434
  if (typeof document === "undefined") {
31377
31435
  return;
31378
31436
  }
31379
31437
  if (bodyScrollLockCount === 0) {
31380
31438
  previousBodyOverflow = document.body.style.overflow;
31439
+ previousHtmlOverflow = document.documentElement.style.overflow;
31381
31440
  document.body.style.overflow = "hidden";
31441
+ document.documentElement.style.overflow = "hidden";
31382
31442
  }
31383
31443
  bodyScrollLockCount += 1;
31384
31444
  }
@@ -31389,7 +31449,9 @@ function unlockBodyScroll() {
31389
31449
  bodyScrollLockCount = Math.max(0, bodyScrollLockCount - 1);
31390
31450
  if (bodyScrollLockCount === 0) {
31391
31451
  document.body.style.overflow = previousBodyOverflow;
31452
+ document.documentElement.style.overflow = previousHtmlOverflow;
31392
31453
  previousBodyOverflow = "";
31454
+ previousHtmlOverflow = "";
31393
31455
  }
31394
31456
  }
31395
31457
  function Drawer({
@@ -31460,13 +31522,13 @@ function Drawer({
31460
31522
  window.removeEventListener("keydown", handleKeyDown);
31461
31523
  };
31462
31524
  }, [isPresent, onClose]);
31463
- if (!isPresent) {
31525
+ if (!open && !isPresent) {
31464
31526
  return null;
31465
31527
  }
31466
- return /* @__PURE__ */ jsxRuntime.jsxs(
31528
+ const drawer = /* @__PURE__ */ jsxRuntime.jsxs(
31467
31529
  "div",
31468
31530
  {
31469
- className: "fixed inset-0 z-50 flex justify-end p-2 max-md:p-0",
31531
+ className: "fixed inset-0 z-50 flex justify-end overscroll-none p-2 max-md:p-0",
31470
31532
  role: "presentation",
31471
31533
  children: [
31472
31534
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -31490,7 +31552,7 @@ function Drawer({
31490
31552
  "aria-labelledby": "homepad-drawer-title",
31491
31553
  ...subtitle ? { "aria-describedby": "homepad-drawer-subtitle" } : {},
31492
31554
  className: cn(
31493
- "relative z-10 flex h-[calc(100dvh-16px)] min-h-0 cursor-auto flex-col overflow-hidden rounded-[16px] bg-white shadow-2xl transition-transform duration-300 ease-in-out max-md:h-dvh max-md:rounded-none",
31555
+ "relative z-10 flex h-full max-h-full min-h-0 cursor-auto flex-col overflow-hidden rounded-[16px] bg-white shadow-2xl transition-transform duration-300 ease-in-out max-md:rounded-none",
31494
31556
  // Keep GPU transform only while animating — settled translate-x-0 blurs text.
31495
31557
  !isTransformSettled && "will-change-transform",
31496
31558
  isAnimatedIn ? isTransformSettled ? "transform-none" : "translate-x-0" : "translate-x-full",
@@ -31498,48 +31560,48 @@ function Drawer({
31498
31560
  className
31499
31561
  ),
31500
31562
  children: [
31501
- /* @__PURE__ */ jsxRuntime.jsxs(
31502
- "header",
31503
- {
31504
- className: cn("shrink-0 border-b border-storm-gray-50", headerClassName),
31505
- children: [
31506
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between pt-6 pr-6 pb-4 pl-6", children: [
31507
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex flex-col gap-1", children: [
31508
- /* @__PURE__ */ jsxRuntime.jsx(
31509
- "h2",
31510
- {
31511
- id: "homepad-drawer-title",
31512
- className: "typography-title-sm tracking-normal text-black",
31513
- children: title
31514
- }
31563
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: cn("shrink-0 border-b border-storm-gray-50", headerClassName), children: [
31564
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between pt-6 pr-6 pb-4 pl-6", children: [
31565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex flex-col gap-1", children: [
31566
+ /* @__PURE__ */ jsxRuntime.jsx(
31567
+ "h2",
31568
+ {
31569
+ id: "homepad-drawer-title",
31570
+ className: "typography-title-sm tracking-normal text-black",
31571
+ children: title
31572
+ }
31573
+ ),
31574
+ subtitle ? /* @__PURE__ */ jsxRuntime.jsx(
31575
+ "p",
31576
+ {
31577
+ id: "homepad-drawer-subtitle",
31578
+ className: cn(
31579
+ "typography-body tracking-normal text-storm-gray-400",
31580
+ subtitleClassName
31515
31581
  ),
31516
- subtitle ? /* @__PURE__ */ jsxRuntime.jsx(
31517
- "p",
31518
- {
31519
- id: "homepad-drawer-subtitle",
31520
- className: cn(
31521
- "typography-body tracking-normal text-storm-gray-400",
31522
- subtitleClassName
31523
- ),
31524
- children: subtitle
31525
- }
31526
- ) : null
31527
- ] }),
31528
- /* @__PURE__ */ jsxRuntime.jsx(
31529
- "button",
31582
+ children: subtitle
31583
+ }
31584
+ ) : null
31585
+ ] }),
31586
+ /* @__PURE__ */ jsxRuntime.jsx(
31587
+ "button",
31588
+ {
31589
+ type: "button",
31590
+ "aria-label": closeAriaLabel,
31591
+ className: "flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-lg text-storm-gray-400 transition-colors hover:bg-storm-gray-50 hover:text-storm-gray-600",
31592
+ onClick: onClose,
31593
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31594
+ lucideReact.X,
31530
31595
  {
31531
- type: "button",
31532
- "aria-label": closeAriaLabel,
31533
- className: "flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-lg text-storm-gray-400 transition-colors hover:bg-storm-gray-50 hover:text-storm-gray-600",
31534
- onClick: onClose,
31535
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-5", strokeWidth: 1.75 })
31596
+ className: "size-5",
31597
+ strokeWidth: 1.75
31536
31598
  }
31537
31599
  )
31538
- ] }),
31539
- headerBottom ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-storm-gray-50 px-6", children: headerBottom }) : null
31540
- ]
31541
- }
31542
- ),
31600
+ }
31601
+ )
31602
+ ] }),
31603
+ headerBottom ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-storm-gray-50 px-6", children: headerBottom }) : null
31604
+ ] }),
31543
31605
  /* @__PURE__ */ jsxRuntime.jsx(
31544
31606
  "div",
31545
31607
  {
@@ -31557,6 +31619,7 @@ function Drawer({
31557
31619
  ]
31558
31620
  }
31559
31621
  );
31622
+ return typeof document !== "undefined" ? (0, import_react_dom3.createPortal)(drawer, document.body) : drawer;
31560
31623
  }
31561
31624
  function TimelineCheckIcon({ className, ...props }) {
31562
31625
  return /* @__PURE__ */ jsxRuntime.jsx(