@scripso-homepad/ui 0.4.36 → 0.4.38

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.
@@ -103,6 +103,7 @@ type SidebarProps = {
103
103
  className?: string;
104
104
  mobileOpen: boolean;
105
105
  onMobileClose?: () => void;
106
+ onMobileOpen?: () => void;
106
107
  /**
107
108
  * Host-owned navigation. Call `navigate(item.to)` from the app router here.
108
109
  * The sidebar never imports react-router, so this must perform the route change.
@@ -115,7 +116,7 @@ type SidebarProps = {
115
116
  collapsed?: boolean;
116
117
  onCollapsedChange?: (collapsed: boolean) => void;
117
118
  };
118
- declare function Sidebar({ navItems, footerNavItems, branding, labels, sidebarStorageKey, pathname, user, onLogout, className, mobileOpen, onMobileClose, onNavItemClick, collapseIcon, expandIcon, closeIcon, initialCollapsed, collapsed, onCollapsedChange, }: SidebarProps): react.JSX.Element;
119
+ declare function Sidebar({ navItems, footerNavItems, branding, labels, sidebarStorageKey, pathname, user, onLogout, className, mobileOpen, onMobileClose, onMobileOpen, onNavItemClick, collapseIcon, expandIcon, closeIcon, initialCollapsed, collapsed, onCollapsedChange, }: SidebarProps): react.JSX.Element;
119
120
 
120
121
  type SidebarMobileHeaderProps = {
121
122
  branding: Pick<AdminSidebarBranding, 'logoIconSrc' | 'logoTitle' | 'logoTagline'>;
@@ -123,8 +124,10 @@ type SidebarMobileHeaderProps = {
123
124
  onOpenMenu: () => void;
124
125
  menuOpen?: boolean;
125
126
  className?: string;
127
+ /** Rendered on the right side of the mobile header (e.g. notifications). */
128
+ end?: ReactNode;
126
129
  };
127
- declare function SidebarMobileHeader({ branding, openMenuLabel, onOpenMenu, menuOpen, className, }: SidebarMobileHeaderProps): react.JSX.Element;
130
+ declare function SidebarMobileHeader({ branding, openMenuLabel, onOpenMenu, menuOpen, className, end, }: SidebarMobileHeaderProps): react.JSX.Element;
128
131
 
129
132
  type DashboardLayoutProps = {
130
133
  sidebar: SidebarProps;
@@ -268,6 +271,7 @@ type PaginationProps = {
268
271
  */
269
272
  variant?: PaginationVariant;
270
273
  className?: string;
274
+ /** Hide the entire bar when there is only one page. Page buttons are always hidden in that case. */
271
275
  hideOnSinglePage?: boolean;
272
276
  };
273
277
  declare function Pagination({ page, pageSize, total, onPageChange, labels, maxPageButtons, variant, className, hideOnSinglePage, }: PaginationProps): react.JSX.Element | null;
@@ -103,6 +103,7 @@ type SidebarProps = {
103
103
  className?: string;
104
104
  mobileOpen: boolean;
105
105
  onMobileClose?: () => void;
106
+ onMobileOpen?: () => void;
106
107
  /**
107
108
  * Host-owned navigation. Call `navigate(item.to)` from the app router here.
108
109
  * The sidebar never imports react-router, so this must perform the route change.
@@ -115,7 +116,7 @@ type SidebarProps = {
115
116
  collapsed?: boolean;
116
117
  onCollapsedChange?: (collapsed: boolean) => void;
117
118
  };
118
- declare function Sidebar({ navItems, footerNavItems, branding, labels, sidebarStorageKey, pathname, user, onLogout, className, mobileOpen, onMobileClose, onNavItemClick, collapseIcon, expandIcon, closeIcon, initialCollapsed, collapsed, onCollapsedChange, }: SidebarProps): react.JSX.Element;
119
+ declare function Sidebar({ navItems, footerNavItems, branding, labels, sidebarStorageKey, pathname, user, onLogout, className, mobileOpen, onMobileClose, onMobileOpen, onNavItemClick, collapseIcon, expandIcon, closeIcon, initialCollapsed, collapsed, onCollapsedChange, }: SidebarProps): react.JSX.Element;
119
120
 
120
121
  type SidebarMobileHeaderProps = {
121
122
  branding: Pick<AdminSidebarBranding, 'logoIconSrc' | 'logoTitle' | 'logoTagline'>;
@@ -123,8 +124,10 @@ type SidebarMobileHeaderProps = {
123
124
  onOpenMenu: () => void;
124
125
  menuOpen?: boolean;
125
126
  className?: string;
127
+ /** Rendered on the right side of the mobile header (e.g. notifications). */
128
+ end?: ReactNode;
126
129
  };
127
- declare function SidebarMobileHeader({ branding, openMenuLabel, onOpenMenu, menuOpen, className, }: SidebarMobileHeaderProps): react.JSX.Element;
130
+ declare function SidebarMobileHeader({ branding, openMenuLabel, onOpenMenu, menuOpen, className, end, }: SidebarMobileHeaderProps): react.JSX.Element;
128
131
 
129
132
  type DashboardLayoutProps = {
130
133
  sidebar: SidebarProps;
@@ -268,6 +271,7 @@ type PaginationProps = {
268
271
  */
269
272
  variant?: PaginationVariant;
270
273
  className?: string;
274
+ /** Hide the entire bar when there is only one page. Page buttons are always hidden in that case. */
271
275
  hideOnSinglePage?: boolean;
272
276
  };
273
277
  declare function Pagination({ page, pageSize, total, onPageChange, labels, maxPageButtons, variant, className, hideOnSinglePage, }: PaginationProps): react.JSX.Element | null;
package/dist/web/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { __commonJS, __require, __toESM, Input, Button } from '../chunk-AOBKWDGW.js';
2
- import { ChevronsUpDown, Search, LogOut, X, Menu, ChevronLeft, ChevronRight } from 'lucide-react';
1
+ import { __commonJS, __require, __toESM, Input, Button } from '../chunk-4FBZM62E.js';
2
+ import { ChevronsUpDown, Search, LogOut, ChevronLeft, ChevronRight, X } from 'lucide-react';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -5344,7 +5344,7 @@ var require_react_dom_production_min = __commonJS({
5344
5344
  if (5 === d || 6 === d) a = a.stateNode, b ? c.insertBefore(a, b) : c.appendChild(a);
5345
5345
  else if (4 !== d && (a = a.child, null !== a)) for (Wj(a, b, c), a = a.sibling; null !== a; ) Wj(a, b, c), a = a.sibling;
5346
5346
  }
5347
- var X3 = null;
5347
+ var X2 = null;
5348
5348
  var Xj = false;
5349
5349
  function Yj(a, b, c) {
5350
5350
  for (c = c.child; null !== c; ) Zj(a, b, c), c = c.sibling;
@@ -5358,23 +5358,23 @@ var require_react_dom_production_min = __commonJS({
5358
5358
  case 5:
5359
5359
  U || Lj(c, b);
5360
5360
  case 6:
5361
- var d = X3, e = Xj;
5362
- X3 = null;
5361
+ var d = X2, e = Xj;
5362
+ X2 = null;
5363
5363
  Yj(a, b, c);
5364
- X3 = d;
5364
+ X2 = d;
5365
5365
  Xj = e;
5366
- null !== X3 && (Xj ? (a = X3, c = c.stateNode, 8 === a.nodeType ? a.parentNode.removeChild(c) : a.removeChild(c)) : X3.removeChild(c.stateNode));
5366
+ null !== X2 && (Xj ? (a = X2, c = c.stateNode, 8 === a.nodeType ? a.parentNode.removeChild(c) : a.removeChild(c)) : X2.removeChild(c.stateNode));
5367
5367
  break;
5368
5368
  case 18:
5369
- null !== X3 && (Xj ? (a = X3, c = c.stateNode, 8 === a.nodeType ? Kf(a.parentNode, c) : 1 === a.nodeType && Kf(a, c), bd(a)) : Kf(X3, c.stateNode));
5369
+ null !== X2 && (Xj ? (a = X2, c = c.stateNode, 8 === a.nodeType ? Kf(a.parentNode, c) : 1 === a.nodeType && Kf(a, c), bd(a)) : Kf(X2, c.stateNode));
5370
5370
  break;
5371
5371
  case 4:
5372
- d = X3;
5372
+ d = X2;
5373
5373
  e = Xj;
5374
- X3 = c.stateNode.containerInfo;
5374
+ X2 = c.stateNode.containerInfo;
5375
5375
  Xj = true;
5376
5376
  Yj(a, b, c);
5377
- X3 = d;
5377
+ X2 = d;
5378
5378
  Xj = e;
5379
5379
  break;
5380
5380
  case 0:
@@ -5431,23 +5431,23 @@ var require_react_dom_production_min = __commonJS({
5431
5431
  a: for (; null !== h; ) {
5432
5432
  switch (h.tag) {
5433
5433
  case 5:
5434
- X3 = h.stateNode;
5434
+ X2 = h.stateNode;
5435
5435
  Xj = false;
5436
5436
  break a;
5437
5437
  case 3:
5438
- X3 = h.stateNode.containerInfo;
5438
+ X2 = h.stateNode.containerInfo;
5439
5439
  Xj = true;
5440
5440
  break a;
5441
5441
  case 4:
5442
- X3 = h.stateNode.containerInfo;
5442
+ X2 = h.stateNode.containerInfo;
5443
5443
  Xj = true;
5444
5444
  break a;
5445
5445
  }
5446
5446
  h = h.return;
5447
5447
  }
5448
- if (null === X3) throw Error(p(160));
5448
+ if (null === X2) throw Error(p(160));
5449
5449
  Zj(f, g, e);
5450
- X3 = null;
5450
+ X2 = null;
5451
5451
  Xj = false;
5452
5452
  var k = e.alternate;
5453
5453
  null !== k && (k.return = null);
@@ -29169,6 +29169,7 @@ function Sidebar({
29169
29169
  className,
29170
29170
  mobileOpen,
29171
29171
  onMobileClose,
29172
+ onMobileOpen,
29172
29173
  onNavItemClick,
29173
29174
  collapseIcon,
29174
29175
  expandIcon,
@@ -29177,12 +29178,14 @@ function Sidebar({
29177
29178
  collapsed,
29178
29179
  onCollapsedChange
29179
29180
  }) {
29180
- const isDesktop = useMediaQuery("(min-width: 768px)");
29181
+ const isDesktop = useMediaQuery("(min-width: 1024px)");
29182
+ const isRailLayout = useMediaQuery("(min-width: 768px)");
29181
29183
  const [internalCollapsed, setInternalCollapsed] = useState(
29182
29184
  () => readInitialCollapsedState(sidebarStorageKey, initialCollapsed)
29183
29185
  );
29184
29186
  const isCollapsed = collapsed ?? internalCollapsed;
29185
- const isExpanded = isDesktop ? !isCollapsed : true;
29187
+ const isExpanded = isDesktop ? !isCollapsed : mobileOpen;
29188
+ const showCollapsedRail = isRailLayout && !isDesktop;
29186
29189
  const setCollapsed = useCallback(
29187
29190
  (next) => {
29188
29191
  if (collapsed === void 0) {
@@ -29201,8 +29204,12 @@ function Sidebar({
29201
29204
  toggleCollapsed();
29202
29205
  return;
29203
29206
  }
29204
- onMobileClose?.();
29205
- }, [isDesktop, onMobileClose, toggleCollapsed]);
29207
+ if (mobileOpen) {
29208
+ onMobileClose?.();
29209
+ return;
29210
+ }
29211
+ onMobileOpen?.();
29212
+ }, [isDesktop, mobileOpen, onMobileClose, onMobileOpen, toggleCollapsed]);
29206
29213
  const handleNavItemNavigate = useCallback(
29207
29214
  (item) => {
29208
29215
  onNavItemClick?.(item);
@@ -29242,23 +29249,26 @@ function Sidebar({
29242
29249
  "aria-label": labels.closeMenu,
29243
29250
  onClick: onMobileClose,
29244
29251
  className: cn(
29245
- "fixed inset-0 z-40 bg-navy-800/60 backdrop-blur-[1px] transition-opacity duration-300 ease-in-out md:hidden",
29252
+ "fixed inset-0 z-40 bg-navy-800/60 backdrop-blur-[1px] transition-opacity duration-300 ease-in-out lg:hidden",
29246
29253
  mobileOpen ? "opacity-100" : "pointer-events-none opacity-0"
29247
29254
  )
29248
29255
  }
29249
29256
  ),
29257
+ showCollapsedRail && mobileOpen ? /* @__PURE__ */ jsx("div", { className: "h-screen w-[76px] shrink-0", "aria-hidden": true }) : null,
29250
29258
  /* @__PURE__ */ jsxs(
29251
29259
  "aside",
29252
29260
  {
29253
29261
  className: cn(
29254
29262
  "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",
29255
29263
  "transition-[transform,width,padding,gap] duration-300 ease-in-out will-change-[transform,width]",
29256
- mobileOpen ? "translate-x-0" : "-translate-x-full",
29257
- "md:relative md:z-auto md:w-[300px] md:translate-x-0 md:shadow-none",
29258
- isExpanded ? "md:w-[300px]" : "md:w-[76px] md:items-center md:gap-2 md:px-3 md:py-4",
29264
+ mobileOpen ? "translate-x-0" : "-translate-x-full pointer-events-none",
29265
+ "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",
29266
+ mobileOpen && "md:fixed md:z-50 md:w-[min(300px,85vw)] md:items-stretch md:gap-8 md:p-4 md:shadow-xl",
29267
+ "lg:relative lg:z-auto lg:translate-x-0 lg:pointer-events-auto lg:shadow-none",
29268
+ isExpanded ? "lg:w-[300px] lg:items-stretch lg:gap-8 lg:p-4" : "lg:w-[76px] lg:items-center lg:gap-2 lg:px-3 lg:py-4",
29259
29269
  className
29260
29270
  ),
29261
- "aria-hidden": !isDesktop && !mobileOpen,
29271
+ "aria-hidden": !isDesktop && !mobileOpen && !showCollapsedRail,
29262
29272
  children: [
29263
29273
  /* @__PURE__ */ jsxs(
29264
29274
  "div",
@@ -29290,8 +29300,8 @@ function Sidebar({
29290
29300
  type: "button",
29291
29301
  onClick: handleHeaderAction,
29292
29302
  className: "shrink-0 cursor-pointer text-white transition-[opacity,transform] duration-200 hover:opacity-80 active:scale-95",
29293
- "aria-label": isDesktop ? isExpanded ? labels.collapse : labels.expand : labels.closeMenu,
29294
- children: isDesktop ? isExpanded ? collapseIcon ?? /* @__PURE__ */ jsx(SidebarCollapseIcon, {}) : expandIcon ?? /* @__PURE__ */ jsx(SidebarExpandIcon, {}) : closeIcon ?? /* @__PURE__ */ jsx(X, { size: 20, strokeWidth: 1.75 })
29303
+ "aria-label": isExpanded ? isDesktop ? labels.collapse : labels.closeMenu : labels.expand,
29304
+ children: isExpanded ? collapseIcon ?? closeIcon ?? /* @__PURE__ */ jsx(SidebarCollapseIcon, {}) : expandIcon ?? /* @__PURE__ */ jsx(SidebarExpandIcon, {})
29295
29305
  }
29296
29306
  )
29297
29307
  ]
@@ -29340,7 +29350,8 @@ function SidebarMobileHeader({
29340
29350
  openMenuLabel,
29341
29351
  onOpenMenu,
29342
29352
  menuOpen = false,
29343
- className
29353
+ className,
29354
+ end
29344
29355
  }) {
29345
29356
  return /* @__PURE__ */ jsxs(
29346
29357
  "header",
@@ -29358,16 +29369,17 @@ function SidebarMobileHeader({
29358
29369
  className: "flex size-10 items-center justify-center rounded-xl text-navy transition-colors hover:bg-storm-gray-50",
29359
29370
  "aria-label": openMenuLabel,
29360
29371
  "aria-expanded": menuOpen,
29361
- children: /* @__PURE__ */ jsx(Menu, { size: 22, strokeWidth: 1.75 })
29372
+ children: /* @__PURE__ */ jsx(SidebarExpandIcon, { size: 22 })
29362
29373
  }
29363
29374
  ),
29364
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
29375
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
29365
29376
  /* @__PURE__ */ jsx("img", { src: branding.logoIconSrc, alt: "", className: "h-[30px] w-[42px] shrink-0" }),
29366
29377
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 leading-none", children: [
29367
29378
  /* @__PURE__ */ jsx("p", { className: "truncate text-base font-bold tracking-tight text-navy", children: branding.logoTitle }),
29368
29379
  /* @__PURE__ */ jsx("p", { className: "truncate text-[6.5px] font-normal tracking-[-0.26px] text-navy-300 uppercase", children: branding.logoTagline })
29369
29380
  ] })
29370
- ] })
29381
+ ] }),
29382
+ end ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: end }) : null
29371
29383
  ]
29372
29384
  }
29373
29385
  );
@@ -29380,12 +29392,12 @@ function DashboardLayout({
29380
29392
  className,
29381
29393
  mainClassName
29382
29394
  }) {
29383
- return /* @__PURE__ */ jsxs("div", { className: cn("flex h-screen overflow-hidden flex-row bg-storm-gray-0", className), children: [
29384
- /* @__PURE__ */ jsx("div", { className: "h-screen shrink-0", children: /* @__PURE__ */ jsx(Sidebar, { ...sidebar }) }),
29395
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-screen min-w-0 overflow-hidden flex-row bg-storm-gray-0", className), children: [
29396
+ /* @__PURE__ */ jsx("div", { className: "max-md:contents md:h-screen md:shrink-0", children: /* @__PURE__ */ jsx(Sidebar, { ...sidebar }) }),
29385
29397
  /* @__PURE__ */ jsxs("div", { className: "flex h-screen min-h-0 min-w-0 flex-1 flex-col overflow-hidden", children: [
29386
29398
  /* @__PURE__ */ jsx(SidebarMobileHeader, { ...mobileHeader }),
29387
29399
  /* @__PURE__ */ jsx(AppHeader, { ...header }),
29388
- /* @__PURE__ */ jsx("main", { className: mainClassName ?? "min-h-0 flex-1 overflow-y-auto p-4 md:p-6", children })
29400
+ /* @__PURE__ */ jsx("main", { className: mainClassName ?? "min-h-0 min-w-0 flex-1 overflow-x-hidden overflow-y-auto p-4 xl:p-6", children })
29389
29401
  ] })
29390
29402
  ] });
29391
29403
  }
@@ -29721,21 +29733,22 @@ function Pagination({
29721
29733
  const visiblePages = getVisiblePageNumbers(safePage, totalPages, maxPageButtons);
29722
29734
  const canGoPrevious = safePage > 1;
29723
29735
  const canGoNext = safePage < totalPages;
29724
- if (hideOnSinglePage && totalPages <= 1) {
29736
+ const showPageControls = totalPages > 1;
29737
+ if (hideOnSinglePage && !showPageControls) {
29725
29738
  return null;
29726
29739
  }
29727
29740
  return /* @__PURE__ */ jsxs(
29728
29741
  "div",
29729
29742
  {
29730
29743
  className: cn(
29731
- "flex flex-col gap-4 px-4 pb-4 pt-4 font-[family-name:var(--font-sans)] sm:flex-row sm:items-center sm:justify-between",
29744
+ "flex flex-col items-center gap-4 px-4 pb-4 pt-4 text-center font-[family-name:var(--font-sans)] sm:flex-row sm:items-center sm:justify-between sm:text-left",
29732
29745
  variant === "standalone" && cn("rounded-xl border bg-storm-gray-0", "border-storm-gray-50"),
29733
29746
  dataTableClassNames.pagination,
29734
29747
  className
29735
29748
  ),
29736
29749
  children: [
29737
29750
  /* @__PURE__ */ jsx("p", { className: "typography-12 font-medium text-storm-gray-200", children: mergedLabels.showing({ start, end, total }) }),
29738
- /* @__PURE__ */ jsxs(
29751
+ showPageControls ? /* @__PURE__ */ jsxs(
29739
29752
  "nav",
29740
29753
  {
29741
29754
  "aria-label": "Pagination",
@@ -29803,7 +29816,7 @@ function Pagination({
29803
29816
  )
29804
29817
  ]
29805
29818
  }
29806
- )
29819
+ ) : null
29807
29820
  ]
29808
29821
  }
29809
29822
  );
@@ -30245,7 +30258,7 @@ function TableScrollArea({
30245
30258
  "div",
30246
30259
  {
30247
30260
  className: cn(
30248
- "table-scroll-area w-full overflow-auto",
30261
+ "table-scroll-area w-full min-w-0 max-w-full overflow-auto",
30249
30262
  fillHeight && "min-h-0 flex-1",
30250
30263
  className
30251
30264
  ),
@@ -30299,7 +30312,7 @@ function DataTable({
30299
30312
  }),
30300
30313
  [className, classNames, footerClassName, scrollClassName, tableClassName]
30301
30314
  );
30302
- return /* @__PURE__ */ jsx(DataTableClassNamesContext.Provider, { value: mergedClassNames, children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", fillHeight && "min-h-0 flex-1", mergedClassNames.root), children: [
30315
+ return /* @__PURE__ */ jsx(DataTableClassNamesContext.Provider, { value: mergedClassNames, children: /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 flex-col", fillHeight && "min-h-0 flex-1", mergedClassNames.root), children: [
30303
30316
  /* @__PURE__ */ jsx(
30304
30317
  "div",
30305
30318
  {
@@ -30327,6 +30340,7 @@ function DataTable({
30327
30340
  "div",
30328
30341
  {
30329
30342
  className: cn(
30343
+ "shrink-0",
30330
30344
  tableFooterShellClassName,
30331
30345
  tableBorderClassName,
30332
30346
  mergedClassNames.footer
@@ -30638,7 +30652,7 @@ function Drawer({
30638
30652
  type: "button",
30639
30653
  "aria-label": closeAriaLabel,
30640
30654
  className: cn(
30641
- "absolute inset-0 bg-storm-gray-850/40 backdrop-blur-[12px] transition-opacity duration-300 ease-in-out",
30655
+ "absolute inset-0 z-0 cursor-pointer bg-storm-gray-850/40 backdrop-blur-[12px] transition-opacity duration-300 ease-in-out",
30642
30656
  isAnimatedIn ? "opacity-100" : "opacity-0"
30643
30657
  ),
30644
30658
  onClick: onClose
@@ -30652,7 +30666,7 @@ function Drawer({
30652
30666
  "aria-labelledby": "homepad-drawer-title",
30653
30667
  ...subtitle ? { "aria-describedby": "homepad-drawer-subtitle" } : {},
30654
30668
  className: cn(
30655
- "relative z-10 flex h-[calc(100dvh-16px)] min-h-0 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",
30669
+ "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",
30656
30670
  // Keep GPU transform only while animating — settled translate-x-0 blurs text.
30657
30671
  !isTransformSettled && "will-change-transform",
30658
30672
  isAnimatedIn ? isTransformSettled ? "transform-none" : "translate-x-0" : "translate-x-full",