@scripso-homepad/ui 0.4.15 → 0.4.16

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.js CHANGED
@@ -1,5 +1,5 @@
1
- import { spacing, colors, fontWeight, fontSize, fonts, radii, INPUT_ICON_GAP, useApplyWebClassName, resolveInputVisualState, Label, getInputFieldStyles, inputFieldMetrics } from './chunk-3G3ZKFHX.js';
2
- export { Button, Input, Label, brand, buttonTypography, colors, emeraldGreen, fontSize, fontWeight, fonts, labelTypography, navy, radii, rubyRed, shadows, spacing, stormGray, typographyScale } from './chunk-3G3ZKFHX.js';
1
+ import { spacing, colors, fontWeight, fontSize, fonts, radii, INPUT_ICON_GAP, useApplyWebClassName, resolveInputVisualState, Label, getInputFieldStyles, inputFieldMetrics } from './chunk-U7OSCJKA.js';
2
+ export { Button, Input, Label, brand, buttonTypography, colors, emeraldGreen, fontSize, fontWeight, fonts, labelTypography, navy, radii, rubyRed, shadows, spacing, stormGray, typographyScale } from './chunk-U7OSCJKA.js';
3
3
  import { createContext, useRef, useState, useMemo, useEffect, useLayoutEffect, useContext, isValidElement, cloneElement } from 'react';
4
4
  import { Platform, StyleSheet, Animated, Easing, View, Pressable, Text, Modal, ScrollView, TextInput, Dimensions } from 'react-native';
5
5
  import Svg2, { Path } from 'react-native-svg';
@@ -7,7 +7,6 @@ var Svg = require('react-native-svg');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var clsx = require('clsx');
9
9
  var tailwindMerge = require('tailwind-merge');
10
- var reactRouterDom = require('react-router-dom');
11
10
  var sonner = require('sonner');
12
11
  require('sonner/dist/styles.css');
13
12
 
@@ -7409,7 +7408,7 @@ var require_react_dom_development = __commonJS({
7409
7408
  var HostPortal = 4;
7410
7409
  var HostComponent = 5;
7411
7410
  var HostText = 6;
7412
- var Fragment5 = 7;
7411
+ var Fragment4 = 7;
7413
7412
  var Mode = 8;
7414
7413
  var ContextConsumer = 9;
7415
7414
  var ContextProvider = 10;
@@ -8564,7 +8563,7 @@ var require_react_dom_development = __commonJS({
8564
8563
  return "DehydratedFragment";
8565
8564
  case ForwardRef:
8566
8565
  return getWrappedName$1(type, type.render, "ForwardRef");
8567
- case Fragment5:
8566
+ case Fragment4:
8568
8567
  return "Fragment";
8569
8568
  case HostComponent:
8570
8569
  return type;
@@ -16989,7 +16988,7 @@ var require_react_dom_development = __commonJS({
16989
16988
  }
16990
16989
  }
16991
16990
  function updateFragment2(returnFiber, current2, fragment, lanes, key) {
16992
- if (current2 === null || current2.tag !== Fragment5) {
16991
+ if (current2 === null || current2.tag !== Fragment4) {
16993
16992
  var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key);
16994
16993
  created.return = returnFiber;
16995
16994
  return created;
@@ -17392,7 +17391,7 @@ var require_react_dom_development = __commonJS({
17392
17391
  if (child.key === key) {
17393
17392
  var elementType = element.type;
17394
17393
  if (elementType === REACT_FRAGMENT_TYPE) {
17395
- if (child.tag === Fragment5) {
17394
+ if (child.tag === Fragment4) {
17396
17395
  deleteRemainingChildren(returnFiber, child.sibling);
17397
17396
  var existing = useFiber(child, element.props.children);
17398
17397
  existing.return = returnFiber;
@@ -22866,7 +22865,7 @@ var require_react_dom_development = __commonJS({
22866
22865
  var _resolvedProps2 = workInProgress2.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
22867
22866
  return updateForwardRef(current2, workInProgress2, type, _resolvedProps2, renderLanes2);
22868
22867
  }
22869
- case Fragment5:
22868
+ case Fragment4:
22870
22869
  return updateFragment(current2, workInProgress2, renderLanes2);
22871
22870
  case Mode:
22872
22871
  return updateMode(current2, workInProgress2, renderLanes2);
@@ -23138,7 +23137,7 @@ var require_react_dom_development = __commonJS({
23138
23137
  case SimpleMemoComponent:
23139
23138
  case FunctionComponent:
23140
23139
  case ForwardRef:
23141
- case Fragment5:
23140
+ case Fragment4:
23142
23141
  case Mode:
23143
23142
  case Profiler:
23144
23143
  case ContextConsumer:
@@ -27390,7 +27389,7 @@ var require_react_dom_development = __commonJS({
27390
27389
  return fiber;
27391
27390
  }
27392
27391
  function createFiberFromFragment(elements, mode, lanes, key) {
27393
- var fiber = createFiber(Fragment5, elements, key, mode);
27392
+ var fiber = createFiber(Fragment4, elements, key, mode);
27394
27393
  fiber.lanes = lanes;
27395
27394
  return fiber;
27396
27395
  }
@@ -28808,12 +28807,25 @@ function resolveWebElement(ref) {
28808
28807
  function useApplyWebClassName(ref, className, enabled = true) {
28809
28808
  react.useLayoutEffect(() => {
28810
28809
  if (!enabled || reactNative.Platform.OS !== "web" || !className?.trim()) return;
28811
- const element = resolveWebElement(ref);
28812
- if (!element) return;
28810
+ let cancelled = false;
28811
+ let rafId = 0;
28812
+ let appliedElement = null;
28813
28813
  const classes = className.trim().split(/\s+/);
28814
- element.classList.add(...classes);
28814
+ const apply = () => {
28815
+ if (cancelled) return;
28816
+ const element = resolveWebElement(ref);
28817
+ if (!element) {
28818
+ rafId = requestAnimationFrame(apply);
28819
+ return;
28820
+ }
28821
+ appliedElement = element;
28822
+ element.classList.add(...classes);
28823
+ };
28824
+ apply();
28815
28825
  return () => {
28816
- element.classList.remove(...classes);
28826
+ cancelled = true;
28827
+ if (rafId) cancelAnimationFrame(rafId);
28828
+ appliedElement?.classList.remove(...classes);
28817
28829
  };
28818
28830
  }, [ref, className, enabled]);
28819
28831
  }
@@ -28989,6 +29001,7 @@ function Input({
28989
29001
  var styles2 = reactNative.StyleSheet.create({
28990
29002
  wrapper: {
28991
29003
  width: "100%",
29004
+ minWidth: 0,
28992
29005
  gap: spacing.sm
28993
29006
  },
28994
29007
  iconSlot: {
@@ -29410,29 +29423,48 @@ function useMediaQuery(query) {
29410
29423
  }, [query]);
29411
29424
  return matches;
29412
29425
  }
29413
- function SidebarNavItem({ item, isOpen, onNavigate }) {
29426
+
29427
+ // src/web/layout/nav-active.ts
29428
+ function isNavItemActive(pathname, item) {
29429
+ if (item.end) {
29430
+ return pathname === item.to;
29431
+ }
29432
+ return pathname === item.to || pathname.startsWith(`${item.to}/`);
29433
+ }
29434
+ function isModifiedClick(event) {
29435
+ return event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0;
29436
+ }
29437
+ function SidebarNavItem({ item, isOpen, isActive, onNavigate }) {
29414
29438
  if (item.hidden) {
29415
29439
  return null;
29416
29440
  }
29417
- const handleClick = () => {
29441
+ const handleClick = (event) => {
29442
+ if (item.disabled) {
29443
+ event.preventDefault();
29444
+ return;
29445
+ }
29446
+ if (event.defaultPrevented || isModifiedClick(event)) {
29447
+ return;
29448
+ }
29449
+ event.preventDefault();
29418
29450
  item.onClick?.();
29419
29451
  onNavigate?.(item);
29420
29452
  };
29421
- return /* @__PURE__ */ jsxRuntime.jsx(
29422
- reactRouterDom.NavLink,
29453
+ return /* @__PURE__ */ jsxRuntime.jsxs(
29454
+ "a",
29423
29455
  {
29424
- to: item.to,
29425
- end: item.end,
29456
+ href: item.to,
29426
29457
  onClick: handleClick,
29458
+ "aria-current": isActive ? "page" : void 0,
29427
29459
  "aria-disabled": item.disabled,
29428
29460
  tabIndex: item.disabled ? -1 : void 0,
29429
- className: ({ isActive }) => cn(
29461
+ className: cn(
29430
29462
  "relative flex items-center rounded-xl px-4 py-3 transition-[background-color,color,gap,padding] duration-300 ease-in-out",
29431
29463
  isOpen ? "w-full gap-4" : "justify-center gap-0 px-3",
29432
29464
  item.disabled && "pointer-events-none opacity-50",
29433
29465
  isActive ? "bg-black/12 text-white" : "text-navy-100 hover:bg-white/5"
29434
29466
  ),
29435
- children: ({ isActive }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29467
+ children: [
29436
29468
  /* @__PURE__ */ jsxRuntime.jsx(
29437
29469
  "span",
29438
29470
  {
@@ -29454,7 +29486,7 @@ function SidebarNavItem({ item, isOpen, onNavigate }) {
29454
29486
  children: item.label
29455
29487
  }
29456
29488
  )
29457
- ] })
29489
+ ]
29458
29490
  }
29459
29491
  );
29460
29492
  }
@@ -29529,6 +29561,7 @@ function Sidebar({
29529
29561
  branding,
29530
29562
  labels,
29531
29563
  sidebarStorageKey,
29564
+ pathname,
29532
29565
  user,
29533
29566
  onLogout,
29534
29567
  className,
@@ -29542,7 +29575,6 @@ function Sidebar({
29542
29575
  collapsed,
29543
29576
  onCollapsedChange
29544
29577
  }) {
29545
- const location = reactRouterDom.useLocation();
29546
29578
  const isDesktop = useMediaQuery("(min-width: 768px)");
29547
29579
  const [internalCollapsed, setInternalCollapsed] = react.useState(
29548
29580
  () => readInitialCollapsedState(sidebarStorageKey, initialCollapsed)
@@ -29578,16 +29610,16 @@ function Sidebar({
29578
29610
  },
29579
29611
  [isDesktop, onMobileClose, onNavItemClick]
29580
29612
  );
29581
- const pathnameRef = react.useRef(location.pathname);
29613
+ const pathnameRef = react.useRef(pathname);
29582
29614
  react.useEffect(() => {
29583
- if (pathnameRef.current === location.pathname) {
29615
+ if (pathnameRef.current === pathname) {
29584
29616
  return;
29585
29617
  }
29586
- pathnameRef.current = location.pathname;
29618
+ pathnameRef.current = pathname;
29587
29619
  if (!isDesktop) {
29588
29620
  onMobileClose?.();
29589
29621
  }
29590
- }, [location.pathname, isDesktop, onMobileClose]);
29622
+ }, [pathname, isDesktop, onMobileClose]);
29591
29623
  react.useEffect(() => {
29592
29624
  if (!mobileOpen || isDesktop) {
29593
29625
  return;
@@ -29668,6 +29700,7 @@ function Sidebar({
29668
29700
  {
29669
29701
  item,
29670
29702
  isOpen: isExpanded,
29703
+ isActive: isNavItemActive(pathname, item),
29671
29704
  onNavigate: handleNavItemNavigate
29672
29705
  },
29673
29706
  item.to
@@ -29678,6 +29711,7 @@ function Sidebar({
29678
29711
  {
29679
29712
  item,
29680
29713
  isOpen: isExpanded,
29714
+ isActive: isNavItemActive(pathname, item),
29681
29715
  onNavigate: handleNavItemNavigate
29682
29716
  },
29683
29717
  item.to
@@ -30440,7 +30474,7 @@ function TableActionsMenu({
30440
30474
  className,
30441
30475
  menuClassName,
30442
30476
  menuWidth = MENU_WIDTH_PX,
30443
- menuFitContent = false
30477
+ menuFitContent = true
30444
30478
  }) {
30445
30479
  const [open, setOpen] = react.useState(false);
30446
30480
  const [menuPosition, setMenuPosition] = react.useState(null);
@@ -30453,11 +30487,14 @@ function TableActionsMenu({
30453
30487
  }, []);
30454
30488
  const updateMenuPosition = react.useCallback(() => {
30455
30489
  const trigger = triggerRef.current;
30490
+ const menuEl = menuRef.current;
30456
30491
  if (!trigger) {
30457
30492
  return;
30458
30493
  }
30459
30494
  const rect = trigger.getBoundingClientRect();
30460
- const resolvedMenuWidth = menuFitContent ? menuRef.current?.getBoundingClientRect().width ?? menuWidth : menuWidth;
30495
+ const viewportMaxWidth = typeof window === "undefined" ? menuWidth : Math.max(menuWidth, window.innerWidth - MENU_VIEWPORT_MARGIN_PX * 2);
30496
+ const measuredWidth = menuFitContent ? menuEl?.offsetWidth || menuEl?.getBoundingClientRect().width || menuWidth : menuWidth;
30497
+ const resolvedMenuWidth = Math.min(Math.max(measuredWidth, 1), viewportMaxWidth);
30461
30498
  setMenuPosition({
30462
30499
  top: rect.bottom + MENU_OFFSET_PX,
30463
30500
  left: clampMenuLeft(rect.right - resolvedMenuWidth, resolvedMenuWidth)
@@ -30470,13 +30507,7 @@ function TableActionsMenu({
30470
30507
  return;
30471
30508
  }
30472
30509
  updateMenuPosition();
30473
- }, [open, updateMenuPosition]);
30474
- useIsomorphicLayoutEffect(() => {
30475
- if (!open || !menuFitContent) {
30476
- return;
30477
- }
30478
- updateMenuPosition();
30479
- }, [items, menuFitContent, open, updateMenuPosition]);
30510
+ }, [open, items, menuFitContent, updateMenuPosition]);
30480
30511
  react.useEffect(() => {
30481
30512
  if (!open) {
30482
30513
  return;
@@ -30502,7 +30533,7 @@ function TableActionsMenu({
30502
30533
  if (items.length === 0) {
30503
30534
  return null;
30504
30535
  }
30505
- const menu = open && menuPosition != null ? /* @__PURE__ */ jsxRuntime.jsx(
30536
+ const menu = open ? /* @__PURE__ */ jsxRuntime.jsx(
30506
30537
  "div",
30507
30538
  {
30508
30539
  ref: menuRef,
@@ -30510,9 +30541,13 @@ function TableActionsMenu({
30510
30541
  role: "menu",
30511
30542
  style: {
30512
30543
  position: "fixed",
30513
- top: menuPosition.top,
30514
- left: menuPosition.left,
30515
- ...menuFitContent ? { width: "max-content" } : { width: menuWidth }
30544
+ top: menuPosition?.top ?? 0,
30545
+ left: menuPosition?.left ?? 0,
30546
+ maxWidth: `calc(100vw - ${MENU_VIEWPORT_MARGIN_PX * 2}px)`,
30547
+ ...menuFitContent ? { width: "max-content" } : { width: menuWidth },
30548
+ // Hide until we have a measured viewport-safe position.
30549
+ visibility: menuPosition != null ? "visible" : "hidden",
30550
+ pointerEvents: menuPosition != null ? "auto" : "none"
30516
30551
  },
30517
30552
  className: cn(
30518
30553
  "z-50 overflow-hidden rounded-2xl border border-storm-gray-50 bg-white shadow-[0_4px_20px_0_rgba(0,0,0,0.05)]",
@@ -30534,14 +30569,13 @@ function TableActionsMenu({
30534
30569
  item.onSelect();
30535
30570
  },
30536
30571
  className: cn(
30537
- "flex h-[51px] cursor-pointer items-center gap-2.5 px-3 text-left typography-14 font-medium text-storm-gray-900 transition-colors hover:bg-storm-gray-0",
30538
- menuFitContent ? "w-auto" : "w-full",
30572
+ "flex h-[51px] w-full cursor-pointer items-center gap-2.5 px-3 text-left typography-14 font-medium text-storm-gray-900 transition-colors hover:bg-storm-gray-0",
30539
30573
  index > 0 && "border-t border-storm-gray-50",
30540
30574
  item.disabled && "cursor-not-allowed opacity-50"
30541
30575
  ),
30542
30576
  children: [
30543
30577
  icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex size-5 shrink-0 items-center justify-center text-storm-gray-200", children: icon }) : null,
30544
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label })
30578
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: item.label })
30545
30579
  ]
30546
30580
  },
30547
30581
  item.id
@@ -30845,6 +30879,8 @@ var variantConfig = {
30845
30879
  };
30846
30880
  var sizeConfig = {
30847
30881
  lg: {
30882
+ /** Matches Tailwind `h-13` so size stays stable before web classNames attach. */
30883
+ minHeight: 52,
30848
30884
  borderRadius: 16,
30849
30885
  paddingTop: 8,
30850
30886
  paddingRight: 8,
@@ -30858,6 +30894,7 @@ var sizeConfig = {
30858
30894
  iconSize: 20
30859
30895
  },
30860
30896
  sm: {
30897
+ minHeight: 40,
30861
30898
  borderRadius: 12,
30862
30899
  paddingTop: 8,
30863
30900
  paddingRight: 8,
@@ -30903,6 +30940,7 @@ function Button({
30903
30940
  const containerStyle = [
30904
30941
  styles3.base,
30905
30942
  {
30943
+ minHeight: metrics.minHeight,
30906
30944
  borderRadius: metrics.borderRadius,
30907
30945
  backgroundColor: preset.backgroundColor,
30908
30946
  paddingTop: metrics.paddingTop,
@@ -31533,6 +31571,7 @@ function ConfirmModal({
31533
31571
  confirmText,
31534
31572
  onCancel,
31535
31573
  onConfirm,
31574
+ icon,
31536
31575
  cancelDisabled = false,
31537
31576
  confirmDisabled = false,
31538
31577
  closeOnBackdrop = true,
@@ -31578,7 +31617,8 @@ function ConfirmModal({
31578
31617
  event.stopPropagation();
31579
31618
  },
31580
31619
  children: [
31581
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-3 text-center", children: [
31620
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-center gap-3 text-center", children: [
31621
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-14 items-center justify-center rounded-2xl bg-storm-gray-50 text-storm-gray-500", children: icon }) : null,
31582
31622
  /* @__PURE__ */ jsxRuntime.jsx(
31583
31623
  "h2",
31584
31624
  {
@@ -31739,6 +31779,7 @@ exports.cn = cn;
31739
31779
  exports.getPaginationRange = getPaginationRange;
31740
31780
  exports.getTotalPages = getTotalPages;
31741
31781
  exports.getVisiblePageNumbers = getVisiblePageNumbers;
31782
+ exports.isNavItemActive = isNavItemActive;
31742
31783
  exports.runMutationWithToast = runMutationWithToast;
31743
31784
  exports.tableRowDisabledCellClassName = tableRowDisabledCellClassName;
31744
31785
  exports.useMediaQuery = useMediaQuery;