@scripso-homepad/ui 0.4.9 → 0.4.11

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.
Files changed (48) hide show
  1. package/dist/index.cjs +245 -127
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +4 -2
  4. package/dist/index.d.ts +4 -2
  5. package/dist/index.js +247 -129
  6. package/dist/index.js.map +1 -1
  7. package/dist/web/index.cjs +451 -48
  8. package/dist/web/index.cjs.map +1 -1
  9. package/dist/web/index.css +161 -0
  10. package/dist/web/index.css.map +1 -1
  11. package/dist/web/index.d.cts +50 -2
  12. package/dist/web/index.d.ts +50 -2
  13. package/dist/web/index.js +444 -49
  14. package/dist/web/index.js.map +1 -1
  15. package/package.json +10 -3
  16. package/src/components/Calendar.tsx +10 -2
  17. package/src/components/DatePicker.tsx +40 -6
  18. package/src/components/Select.tsx +133 -38
  19. package/src/theme/select.ts +1 -1
  20. package/src/utils/calendarDays.ts +15 -6
  21. package/src/web/components/Badge.tsx +1 -1
  22. package/src/web/components/ConfirmModal.tsx +2 -2
  23. package/src/web/components/Drawer.stories.tsx +234 -0
  24. package/src/web/components/Drawer.tsx +169 -0
  25. package/src/web/components/HistoryTimeline.tsx +46 -0
  26. package/src/web/components/Modal.stories.tsx +1 -1
  27. package/src/web/components/Modal.tsx +30 -13
  28. package/src/web/components/Pagination.tsx +2 -2
  29. package/src/web/components/TableActionButton.tsx +4 -4
  30. package/src/web/components/TableActionsMenu.tsx +1 -1
  31. package/src/web/components/TableIconText.tsx +1 -1
  32. package/src/web/components/Toaster.stories.tsx +106 -0
  33. package/src/web/components/Toaster.tsx +92 -0
  34. package/src/web/components/ToasterProvider.tsx +6 -0
  35. package/src/web/components/drawer-scroll.css +41 -0
  36. package/src/web/components/sonner-toast.css +141 -0
  37. package/src/web/components/table/constants.ts +2 -2
  38. package/src/web/icons/TimelineCheckIcon.tsx +24 -0
  39. package/src/web/icons/ToastIcons.tsx +119 -0
  40. package/src/web/index.ts +20 -0
  41. package/src/web/layout/AppHeader.tsx +1 -1
  42. package/src/web/layout/BuildingSelect.tsx +2 -2
  43. package/src/web/layout/DashboardLayout.stories.tsx +1 -1
  44. package/src/web/layout/SidebarNavItem.tsx +1 -1
  45. package/src/web/layout/SidebarUserCard.tsx +3 -3
  46. package/src/web/mutation-toast.ts +33 -0
  47. package/src/web/styles/typography.css +99 -0
  48. package/src/web/toast.ts +1 -0
package/dist/web/index.js CHANGED
@@ -5,6 +5,9 @@ import { twMerge } from 'tailwind-merge';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
6
  import { createContext, forwardRef, useRef, useEffect, useState, useId, useCallback, useMemo, useContext, useLayoutEffect } from 'react';
7
7
  import { NavLink, useLocation } from 'react-router-dom';
8
+ import { Toaster as Toaster$1, toast } from 'sonner';
9
+ export { toast } from 'sonner';
10
+ import 'sonner/dist/styles.css';
8
11
 
9
12
  // node_modules/react-dom/node_modules/scheduler/cjs/scheduler.production.min.js
10
13
  var require_scheduler_production_min = __commonJS({
@@ -5342,7 +5345,7 @@ var require_react_dom_production_min = __commonJS({
5342
5345
  if (5 === d || 6 === d) a = a.stateNode, b ? c.insertBefore(a, b) : c.appendChild(a);
5343
5346
  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;
5344
5347
  }
5345
- var X2 = null;
5348
+ var X3 = null;
5346
5349
  var Xj = false;
5347
5350
  function Yj(a, b, c) {
5348
5351
  for (c = c.child; null !== c; ) Zj(a, b, c), c = c.sibling;
@@ -5356,23 +5359,23 @@ var require_react_dom_production_min = __commonJS({
5356
5359
  case 5:
5357
5360
  U || Lj(c, b);
5358
5361
  case 6:
5359
- var d = X2, e = Xj;
5360
- X2 = null;
5362
+ var d = X3, e = Xj;
5363
+ X3 = null;
5361
5364
  Yj(a, b, c);
5362
- X2 = d;
5365
+ X3 = d;
5363
5366
  Xj = e;
5364
- null !== X2 && (Xj ? (a = X2, c = c.stateNode, 8 === a.nodeType ? a.parentNode.removeChild(c) : a.removeChild(c)) : X2.removeChild(c.stateNode));
5367
+ null !== X3 && (Xj ? (a = X3, c = c.stateNode, 8 === a.nodeType ? a.parentNode.removeChild(c) : a.removeChild(c)) : X3.removeChild(c.stateNode));
5365
5368
  break;
5366
5369
  case 18:
5367
- 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
+ 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));
5368
5371
  break;
5369
5372
  case 4:
5370
- d = X2;
5373
+ d = X3;
5371
5374
  e = Xj;
5372
- X2 = c.stateNode.containerInfo;
5375
+ X3 = c.stateNode.containerInfo;
5373
5376
  Xj = true;
5374
5377
  Yj(a, b, c);
5375
- X2 = d;
5378
+ X3 = d;
5376
5379
  Xj = e;
5377
5380
  break;
5378
5381
  case 0:
@@ -5429,23 +5432,23 @@ var require_react_dom_production_min = __commonJS({
5429
5432
  a: for (; null !== h; ) {
5430
5433
  switch (h.tag) {
5431
5434
  case 5:
5432
- X2 = h.stateNode;
5435
+ X3 = h.stateNode;
5433
5436
  Xj = false;
5434
5437
  break a;
5435
5438
  case 3:
5436
- X2 = h.stateNode.containerInfo;
5439
+ X3 = h.stateNode.containerInfo;
5437
5440
  Xj = true;
5438
5441
  break a;
5439
5442
  case 4:
5440
- X2 = h.stateNode.containerInfo;
5443
+ X3 = h.stateNode.containerInfo;
5441
5444
  Xj = true;
5442
5445
  break a;
5443
5446
  }
5444
5447
  h = h.return;
5445
5448
  }
5446
- if (null === X2) throw Error(p(160));
5449
+ if (null === X3) throw Error(p(160));
5447
5450
  Zj(f, g, e);
5448
- X2 = null;
5451
+ X3 = null;
5449
5452
  Xj = false;
5450
5453
  var k = e.alternate;
5451
5454
  null !== k && (k.return = null);
@@ -27526,7 +27529,7 @@ var require_react_dom_development = __commonJS({
27526
27529
  return root2;
27527
27530
  }
27528
27531
  var ReactVersion = "18.3.1";
27529
- function createPortal2(children, containerInfo, implementation) {
27532
+ function createPortal3(children, containerInfo, implementation) {
27530
27533
  var key = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : null;
27531
27534
  {
27532
27535
  checkKeyStringCoercion(key);
@@ -28382,7 +28385,7 @@ var require_react_dom_development = __commonJS({
28382
28385
  if (!isValidContainer(container)) {
28383
28386
  throw new Error("Target container is not a DOM element.");
28384
28387
  }
28385
- return createPortal2(children, container, null, key);
28388
+ return createPortal3(children, container, null, key);
28386
28389
  }
28387
28390
  function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
28388
28391
  return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback);
@@ -28705,7 +28708,7 @@ function BuildingSelect({
28705
28708
  ),
28706
28709
  children: [
28707
28710
  buildingIcon ?? /* @__PURE__ */ jsx(BuildingIcon, { className: "shrink-0 text-navy" }),
28708
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-slate-blue", children: displayLabel }),
28711
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate typography-14 font-medium text-slate-blue", children: displayLabel }),
28709
28712
  chevronIcon ?? /* @__PURE__ */ jsx(
28710
28713
  ChevronsUpDown,
28711
28714
  {
@@ -28753,7 +28756,7 @@ function BuildingSelect({
28753
28756
  },
28754
28757
  onClick: () => selectOption(option),
28755
28758
  className: cn(
28756
- "flex w-full rounded-lg px-3 py-2.5 text-left text-sm font-medium text-slate-blue transition-colors",
28759
+ "flex w-full rounded-lg px-3 py-2.5 text-left typography-14 font-medium text-slate-blue transition-colors",
28757
28760
  !option.disabled && "cursor-pointer hover:bg-storm-gray-50",
28758
28761
  (isSelected || isHighlighted) && !option.disabled && "bg-storm-gray-50",
28759
28762
  option.disabled && "cursor-not-allowed opacity-50"
@@ -28806,7 +28809,7 @@ function AppHeader({
28806
28809
  className
28807
28810
  ),
28808
28811
  children: [
28809
- /* @__PURE__ */ jsx("h1", { className: "truncate text-xl font-bold text-slate-blue", children: title }),
28812
+ /* @__PURE__ */ jsx("h1", { className: "truncate typography-title text-slate-blue", children: title }),
28810
28813
  /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [
28811
28814
  hasBuildingSelect ? /* @__PURE__ */ jsx(
28812
28815
  BuildingSelect,
@@ -28909,7 +28912,7 @@ function SidebarNavItem({ item, isOpen, onNavigate }) {
28909
28912
  "span",
28910
28913
  {
28911
28914
  className: cn(
28912
- "overflow-hidden text-sm font-semibold whitespace-nowrap transition-[max-width,opacity] duration-300 ease-in-out",
28915
+ "overflow-hidden typography-14 font-semibold whitespace-nowrap transition-[max-width,opacity] duration-300 ease-in-out",
28913
28916
  isOpen ? "max-w-[180px] opacity-100" : "max-w-0 opacity-0"
28914
28917
  ),
28915
28918
  children: item.label
@@ -28946,15 +28949,15 @@ function SidebarUserCard({
28946
28949
  /* @__PURE__ */ jsx(
28947
28950
  "div",
28948
28951
  {
28949
- className: "flex size-11 shrink-0 items-center justify-center rounded-full bg-white/5 text-sm font-bold text-white",
28952
+ className: "flex size-11 shrink-0 items-center justify-center rounded-full bg-white/5 typography-14 font-bold text-white",
28950
28953
  "aria-hidden": true,
28951
28954
  children: initials
28952
28955
  }
28953
28956
  ),
28954
28957
  isOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
28955
28958
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
28956
- /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-bold text-white", children: user.fullName }),
28957
- /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-storm-gray-100", children: user.email })
28959
+ /* @__PURE__ */ jsx("p", { className: "truncate typography-14 font-bold text-white", children: user.fullName }),
28960
+ /* @__PURE__ */ jsx("p", { className: "truncate typography-12 text-storm-gray-100", children: user.email })
28958
28961
  ] }),
28959
28962
  /* @__PURE__ */ jsx(
28960
28963
  "button",
@@ -29535,7 +29538,7 @@ var defaultLabels = {
29535
29538
  page: (pageNumber) => `Page ${pageNumber}`,
29536
29539
  showing: ({ start, end, total }) => `Showing ${start}-${end} of ${total}`
29537
29540
  };
29538
- var paginationControlClassName = "inline-flex size-7 items-center justify-center rounded-lg border border-storm-gray-50 p-1 text-xs font-medium leading-none text-storm-gray-500 transition-colors";
29541
+ var paginationControlClassName = "inline-flex size-7 items-center justify-center rounded-lg border border-storm-gray-50 p-1 typography-12 font-medium text-storm-gray-500 transition-colors";
29539
29542
  var paginationHoverClassName = "cursor-pointer hover:bg-storm-gray-0";
29540
29543
  function Pagination({
29541
29544
  page,
@@ -29569,7 +29572,7 @@ function Pagination({
29569
29572
  className
29570
29573
  ),
29571
29574
  children: [
29572
- /* @__PURE__ */ jsx("p", { className: "text-xs font-medium leading-none text-storm-gray-200", children: mergedLabels.showing({ start, end, total }) }),
29575
+ /* @__PURE__ */ jsx("p", { className: "typography-12 font-medium text-storm-gray-200", children: mergedLabels.showing({ start, end, total }) }),
29573
29576
  /* @__PURE__ */ jsxs(
29574
29577
  "nav",
29575
29578
  {
@@ -29656,8 +29659,8 @@ var tableCellPaddingClassName = "px-3 py-3";
29656
29659
  var tableHeadPaddingClassName = "px-3 py-4";
29657
29660
  var tableShellClassName = "flex flex-col overflow-hidden border bg-storm-gray-0";
29658
29661
  var tableFooterShellClassName = "overflow-hidden rounded-b-xl border bg-storm-gray-0";
29659
- var tableHeaderClassName = "bg-storm-gray-0 font-sans text-xs font-normal leading-none tracking-normal text-storm-gray-400";
29660
- var tableBodyClassName = "bg-white font-sans text-sm font-medium leading-none tracking-normal text-storm-gray-900";
29662
+ var tableHeaderClassName = "bg-storm-gray-0 typography-12 font-normal tracking-normal text-storm-gray-400";
29663
+ var tableBodyClassName = "bg-white typography-14 font-medium tracking-normal text-storm-gray-900";
29661
29664
  var tableAlignClasses = {
29662
29665
  left: "",
29663
29666
  right: "text-right",
@@ -29835,10 +29838,10 @@ function TableActionsCell({ className, children, ...props }) {
29835
29838
 
29836
29839
  // src/web/components/TableActionsMenu.tsx
29837
29840
  var import_react_dom = __toESM(require_react_dom(), 1);
29838
- var actionButtonClassName = "inline-flex cursor-pointer items-center gap-1 rounded-lg border border-storm-gray-50 bg-white px-3 py-2 font-sans text-xs font-medium leading-none text-storm-gray-900 transition-colors hover:bg-storm-gray-0";
29841
+ var inlineActionClassName = "inline-flex cursor-pointer items-center gap-1 rounded-lg border border-storm-gray-50 bg-white px-3 py-2 typography-12 font-medium text-storm-gray-900 transition-colors hover:bg-storm-gray-0";
29839
29842
  var variantClasses = {
29840
- approve: actionButtonClassName,
29841
- reject: actionButtonClassName,
29843
+ approve: inlineActionClassName,
29844
+ reject: inlineActionClassName,
29842
29845
  menu: "inline-flex size-7 cursor-pointer items-center justify-center rounded-lg text-storm-gray-500 transition-colors hover:bg-storm-gray-0 hover:text-storm-gray-900"
29843
29846
  };
29844
29847
  var inlineActionIconClassName = "inline-flex size-4 shrink-0 items-center justify-center [&_svg]:size-4";
@@ -29994,7 +29997,7 @@ function TableActionsMenu({
29994
29997
  item.onSelect();
29995
29998
  },
29996
29999
  className: cn(
29997
- "flex h-[51px] w-full cursor-pointer items-center gap-2.5 px-3 text-left font-sans text-sm font-medium leading-none text-storm-gray-900 transition-colors hover:bg-storm-gray-0",
30000
+ "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",
29998
30001
  index > 0 && "border-t border-storm-gray-50",
29999
30002
  item.disabled && "cursor-not-allowed opacity-50"
30000
30003
  ),
@@ -30225,7 +30228,7 @@ function Badge({ children, variant = "neutral", icon, className }) {
30225
30228
  "span",
30226
30229
  {
30227
30230
  className: cn(
30228
- "inline-flex items-center gap-2 rounded-[28px] px-3 py-1.5 font-sans text-xs font-semibold leading-none whitespace-nowrap",
30231
+ "inline-flex items-center gap-2 rounded-[28px] px-3 py-1.5 typography-12 font-semibold whitespace-nowrap",
30229
30232
  badgeVariantClasses[variant],
30230
30233
  className
30231
30234
  ),
@@ -30244,7 +30247,7 @@ function TableIconText({ icon, children, className }) {
30244
30247
  "span",
30245
30248
  {
30246
30249
  className: cn(
30247
- "inline-flex items-center gap-2 font-sans text-sm font-medium leading-none tracking-normal text-storm-gray-900",
30250
+ "inline-flex items-center gap-2 typography-14 font-medium tracking-normal text-storm-gray-900",
30248
30251
  className
30249
30252
  ),
30250
30253
  children: [
@@ -30254,6 +30257,9 @@ function TableIconText({ icon, children, className }) {
30254
30257
  }
30255
30258
  );
30256
30259
  }
30260
+
30261
+ // src/web/components/Modal.tsx
30262
+ var import_react_dom2 = __toESM(require_react_dom(), 1);
30257
30263
  var footerAlignClasses = {
30258
30264
  left: "justify-start",
30259
30265
  center: "justify-center",
@@ -30275,6 +30281,7 @@ function Modal({
30275
30281
  cancelDisabled = false,
30276
30282
  confirmDisabled = false,
30277
30283
  closeOnBackdrop = true,
30284
+ closeOnEscape = true,
30278
30285
  containerClassName,
30279
30286
  contentClassName,
30280
30287
  buttonClassName
@@ -30283,29 +30290,36 @@ function Modal({
30283
30290
  if (!open) {
30284
30291
  return;
30285
30292
  }
30293
+ const previousOverflow = document.body.style.overflow;
30294
+ document.body.style.overflow = "hidden";
30286
30295
  const handleKeyDown = (event) => {
30287
- if (event.key === "Escape") {
30296
+ if (event.key === "Escape" && closeOnEscape) {
30288
30297
  onCancel();
30289
30298
  }
30290
30299
  };
30291
30300
  window.addEventListener("keydown", handleKeyDown);
30292
30301
  return () => {
30302
+ document.body.style.overflow = previousOverflow;
30293
30303
  window.removeEventListener("keydown", handleKeyDown);
30294
30304
  };
30295
- }, [open, onCancel]);
30305
+ }, [open, onCancel, closeOnEscape]);
30296
30306
  if (!open) {
30297
30307
  return null;
30298
30308
  }
30299
30309
  const sharedButtonClassName = cn(
30300
30310
  "btn h-13 justify-center!",
30301
- footerLayout === "split" && "min-w-0 flex-1",
30302
- buttonClassName
30311
+ footerLayout === "split" && "min-w-0 flex-1 basis-0",
30312
+ footerLayout !== "split" && buttonClassName
30303
30313
  );
30304
- return /* @__PURE__ */ jsx(
30314
+ const modal = /* @__PURE__ */ jsx(
30305
30315
  "div",
30306
30316
  {
30307
- className: "fixed inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-[12px] bg-storm-gray-850/40",
30308
- onClick: closeOnBackdrop ? onCancel : void 0,
30317
+ className: "fixed inset-0 z-[100] flex items-center justify-center p-4 backdrop-blur-[12px] bg-storm-gray-850/40",
30318
+ onClick: closeOnBackdrop ? (event) => {
30319
+ if (event.target === event.currentTarget) {
30320
+ onCancel();
30321
+ }
30322
+ } : void 0,
30309
30323
  role: "presentation",
30310
30324
  children: /* @__PURE__ */ jsxs(
30311
30325
  "div",
@@ -30315,14 +30329,14 @@ function Modal({
30315
30329
  "aria-labelledby": "homepad-modal-title",
30316
30330
  ...subtitle ? { "aria-describedby": "homepad-modal-subtitle" } : {},
30317
30331
  className: cn(
30318
- "flex w-full max-w-2xl flex-col gap-6 rounded-2xl bg-white p-4 opacity-100 md:p-6",
30332
+ "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",
30319
30333
  containerClassName
30320
30334
  ),
30321
30335
  onClick: (event) => {
30322
30336
  event.stopPropagation();
30323
30337
  },
30324
30338
  children: [
30325
- /* @__PURE__ */ jsxs("header", { className: cn("flex", icon ? "items-center gap-2.5" : void 0), children: [
30339
+ /* @__PURE__ */ jsxs("header", { className: cn("flex shrink-0", icon ? "items-center gap-2.5" : void 0), children: [
30326
30340
  icon ? /* @__PURE__ */ jsx(
30327
30341
  "div",
30328
30342
  {
@@ -30338,7 +30352,7 @@ function Modal({
30338
30352
  "h2",
30339
30353
  {
30340
30354
  id: "homepad-modal-title",
30341
- className: "font-sans text-lg font-bold leading-none tracking-normal text-black",
30355
+ className: "typography-title-sm tracking-normal text-black",
30342
30356
  children: title
30343
30357
  }
30344
30358
  ),
@@ -30346,18 +30360,18 @@ function Modal({
30346
30360
  "p",
30347
30361
  {
30348
30362
  id: "homepad-modal-subtitle",
30349
- className: "font-sans text-xs font-normal leading-none tracking-normal text-storm-gray-400",
30363
+ className: "typography-caption tracking-normal text-storm-gray-400",
30350
30364
  children: subtitle
30351
30365
  }
30352
30366
  ) : null
30353
30367
  ] })
30354
30368
  ] }),
30355
- /* @__PURE__ */ jsx("div", { className: cn("min-w-0", contentClassName), children }),
30369
+ /* @__PURE__ */ jsx("div", { className: cn("min-h-0 min-w-0 flex-1 overflow-y-auto", contentClassName), children }),
30356
30370
  /* @__PURE__ */ jsxs(
30357
30371
  "footer",
30358
30372
  {
30359
30373
  className: cn(
30360
- "flex gap-4",
30374
+ "flex shrink-0 gap-4",
30361
30375
  footerLayout === "split" ? "w-full" : footerAlignClasses[footerAlign]
30362
30376
  ),
30363
30377
  children: [
@@ -30391,6 +30405,387 @@ function Modal({
30391
30405
  )
30392
30406
  }
30393
30407
  );
30408
+ return typeof document !== "undefined" ? (0, import_react_dom2.createPortal)(modal, document.body) : modal;
30409
+ }
30410
+ var DRAWER_TRANSITION_MS = 300;
30411
+ function Drawer({
30412
+ open,
30413
+ title,
30414
+ subtitle,
30415
+ children,
30416
+ footer,
30417
+ onClose,
30418
+ closeAriaLabel = "Close",
30419
+ widthClassName = "w-full md:w-[464px]",
30420
+ className,
30421
+ headerClassName,
30422
+ contentClassName,
30423
+ footerClassName
30424
+ }) {
30425
+ const [isPresent, setIsPresent] = useState(open);
30426
+ const [isAnimatedIn, setIsAnimatedIn] = useState(false);
30427
+ useEffect(() => {
30428
+ if (open) {
30429
+ setIsPresent(true);
30430
+ const frame = window.requestAnimationFrame(() => {
30431
+ window.requestAnimationFrame(() => {
30432
+ setIsAnimatedIn(true);
30433
+ });
30434
+ });
30435
+ return () => {
30436
+ window.cancelAnimationFrame(frame);
30437
+ };
30438
+ }
30439
+ setIsAnimatedIn(false);
30440
+ const timeout = window.setTimeout(() => {
30441
+ setIsPresent(false);
30442
+ }, DRAWER_TRANSITION_MS);
30443
+ return () => {
30444
+ window.clearTimeout(timeout);
30445
+ };
30446
+ }, [open]);
30447
+ useEffect(() => {
30448
+ if (!isPresent) {
30449
+ return;
30450
+ }
30451
+ const previousOverflow = document.body.style.overflow;
30452
+ document.body.style.overflow = "hidden";
30453
+ const handleKeyDown = (event) => {
30454
+ if (event.key === "Escape") {
30455
+ onClose();
30456
+ }
30457
+ };
30458
+ window.addEventListener("keydown", handleKeyDown);
30459
+ return () => {
30460
+ document.body.style.overflow = previousOverflow;
30461
+ window.removeEventListener("keydown", handleKeyDown);
30462
+ };
30463
+ }, [isPresent, onClose]);
30464
+ if (!isPresent) {
30465
+ return null;
30466
+ }
30467
+ return /* @__PURE__ */ jsxs(
30468
+ "div",
30469
+ {
30470
+ className: "fixed inset-0 z-50 flex justify-end p-2 max-md:p-0",
30471
+ role: "presentation",
30472
+ children: [
30473
+ /* @__PURE__ */ jsx(
30474
+ "button",
30475
+ {
30476
+ type: "button",
30477
+ "aria-label": closeAriaLabel,
30478
+ className: cn(
30479
+ "absolute inset-0 bg-storm-gray-850/40 backdrop-blur-[12px] transition-opacity duration-300 ease-in-out",
30480
+ isAnimatedIn ? "opacity-100" : "opacity-0"
30481
+ ),
30482
+ onClick: onClose
30483
+ }
30484
+ ),
30485
+ /* @__PURE__ */ jsxs(
30486
+ "aside",
30487
+ {
30488
+ role: "dialog",
30489
+ "aria-modal": "true",
30490
+ "aria-labelledby": "homepad-drawer-title",
30491
+ ...subtitle ? { "aria-describedby": "homepad-drawer-subtitle" } : {},
30492
+ className: cn(
30493
+ "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 will-change-transform max-md:h-dvh max-md:rounded-none",
30494
+ isAnimatedIn ? "translate-x-0" : "translate-x-full",
30495
+ widthClassName,
30496
+ className
30497
+ ),
30498
+ children: [
30499
+ /* @__PURE__ */ jsxs(
30500
+ "header",
30501
+ {
30502
+ className: cn(
30503
+ "flex h-[87px] shrink-0 items-start justify-between border-b border-storm-gray-50 pt-6 pr-6 pb-4 pl-6",
30504
+ headerClassName
30505
+ ),
30506
+ children: [
30507
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex flex-col gap-1", children: [
30508
+ /* @__PURE__ */ jsx(
30509
+ "h2",
30510
+ {
30511
+ id: "homepad-drawer-title",
30512
+ className: "typography-title-sm tracking-normal text-black",
30513
+ children: title
30514
+ }
30515
+ ),
30516
+ subtitle ? /* @__PURE__ */ jsx(
30517
+ "p",
30518
+ {
30519
+ id: "homepad-drawer-subtitle",
30520
+ className: "typography-body tracking-normal text-storm-gray-400",
30521
+ children: subtitle
30522
+ }
30523
+ ) : null
30524
+ ] }),
30525
+ /* @__PURE__ */ jsx(
30526
+ "button",
30527
+ {
30528
+ type: "button",
30529
+ "aria-label": closeAriaLabel,
30530
+ 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",
30531
+ onClick: onClose,
30532
+ children: /* @__PURE__ */ jsx(X, { className: "size-5", strokeWidth: 1.75 })
30533
+ }
30534
+ )
30535
+ ]
30536
+ }
30537
+ ),
30538
+ /* @__PURE__ */ jsx(
30539
+ "div",
30540
+ {
30541
+ className: cn(
30542
+ "drawer-scroll-area min-h-0 flex-1 overflow-y-auto px-6 pt-6 pb-0",
30543
+ contentClassName
30544
+ ),
30545
+ children
30546
+ }
30547
+ ),
30548
+ footer ? /* @__PURE__ */ jsx("footer", { className: cn("shrink-0 px-6 py-5", footerClassName), children: footer }) : null
30549
+ ]
30550
+ }
30551
+ )
30552
+ ]
30553
+ }
30554
+ );
30555
+ }
30556
+ function TimelineCheckIcon({ className, ...props }) {
30557
+ return /* @__PURE__ */ jsx(
30558
+ "svg",
30559
+ {
30560
+ width: "16",
30561
+ height: "16",
30562
+ viewBox: "0 0 16 16",
30563
+ fill: "none",
30564
+ xmlns: "http://www.w3.org/2000/svg",
30565
+ className,
30566
+ "aria-hidden": true,
30567
+ ...props,
30568
+ children: /* @__PURE__ */ jsx(
30569
+ "path",
30570
+ {
30571
+ d: "M13.3346 4L6.0013 11.3333L2.66797 8",
30572
+ stroke: "#279D54",
30573
+ strokeWidth: "1.5",
30574
+ strokeLinecap: "round",
30575
+ strokeLinejoin: "round"
30576
+ }
30577
+ )
30578
+ }
30579
+ );
30580
+ }
30581
+ function HistoryTimeline({ events }) {
30582
+ return /* @__PURE__ */ jsx("ol", { className: "m-0 flex list-none flex-col gap-1 p-0", children: events.map((event, index) => {
30583
+ const isLast = index === events.length - 1;
30584
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3", children: [
30585
+ /* @__PURE__ */ jsxs("div", { className: "flex w-8 shrink-0 flex-col items-center", children: [
30586
+ /* @__PURE__ */ jsx("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-[28px] border border-storm-gray-50 bg-white", children: /* @__PURE__ */ jsx(TimelineCheckIcon, { className: "size-4 shrink-0" }) }),
30587
+ !isLast ? /* @__PURE__ */ jsx(
30588
+ "div",
30589
+ {
30590
+ "aria-hidden": true,
30591
+ className: "mt-1 h-[31px] w-px shrink-0 border-l border-dashed border-storm-gray-100"
30592
+ }
30593
+ ) : null
30594
+ ] }),
30595
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2 pt-1.5", children: [
30596
+ /* @__PURE__ */ jsx("p", { className: "typography-14 font-medium tracking-normal text-slate-blue", children: event.title }),
30597
+ /* @__PURE__ */ jsx("p", { className: "typography-caption tracking-normal text-storm-gray-300", children: event.timestamp })
30598
+ ] })
30599
+ ] }, event.id);
30600
+ }) });
30601
+ }
30602
+ function ToastCloseIcon(props) {
30603
+ return /* @__PURE__ */ jsx(
30604
+ "svg",
30605
+ {
30606
+ width: "20",
30607
+ height: "20",
30608
+ viewBox: "0 0 20 20",
30609
+ fill: "none",
30610
+ xmlns: "http://www.w3.org/2000/svg",
30611
+ "aria-hidden": true,
30612
+ ...props,
30613
+ children: /* @__PURE__ */ jsx(
30614
+ "path",
30615
+ {
30616
+ d: "M15 5L5 15M5 5L15 15",
30617
+ stroke: "#B5BCC1",
30618
+ strokeWidth: "2",
30619
+ strokeLinecap: "round",
30620
+ strokeLinejoin: "round"
30621
+ }
30622
+ )
30623
+ }
30624
+ );
30625
+ }
30626
+ function ToastSuccessIcon(props) {
30627
+ return /* @__PURE__ */ jsx(
30628
+ "svg",
30629
+ {
30630
+ width: "24",
30631
+ height: "24",
30632
+ viewBox: "0 0 24 24",
30633
+ fill: "none",
30634
+ xmlns: "http://www.w3.org/2000/svg",
30635
+ "aria-hidden": true,
30636
+ ...props,
30637
+ children: /* @__PURE__ */ jsx(
30638
+ "path",
30639
+ {
30640
+ d: "M20 6L9 17L4 12",
30641
+ stroke: "#279D54",
30642
+ strokeWidth: "2",
30643
+ strokeLinecap: "round",
30644
+ strokeLinejoin: "round"
30645
+ }
30646
+ )
30647
+ }
30648
+ );
30649
+ }
30650
+ function ToastErrorIcon(props) {
30651
+ return /* @__PURE__ */ jsx(
30652
+ "svg",
30653
+ {
30654
+ width: "24",
30655
+ height: "24",
30656
+ viewBox: "0 0 24 24",
30657
+ fill: "none",
30658
+ xmlns: "http://www.w3.org/2000/svg",
30659
+ "aria-hidden": true,
30660
+ ...props,
30661
+ children: /* @__PURE__ */ jsx(
30662
+ "path",
30663
+ {
30664
+ d: "M18 6L6 18M6 6L18 18",
30665
+ stroke: "#AE0011",
30666
+ strokeWidth: "2",
30667
+ strokeLinecap: "round",
30668
+ strokeLinejoin: "round"
30669
+ }
30670
+ )
30671
+ }
30672
+ );
30673
+ }
30674
+ function ToastWarningIcon(props) {
30675
+ return /* @__PURE__ */ jsx(
30676
+ "svg",
30677
+ {
30678
+ width: "24",
30679
+ height: "24",
30680
+ viewBox: "0 0 24 24",
30681
+ fill: "none",
30682
+ xmlns: "http://www.w3.org/2000/svg",
30683
+ "aria-hidden": true,
30684
+ ...props,
30685
+ children: /* @__PURE__ */ jsx(
30686
+ "path",
30687
+ {
30688
+ d: "M12.0001 9.00022V13.0002M12.0001 17.0002H12.0101M21.7301 18.0002L13.7301 4.00022C13.5556 3.69243 13.3027 3.43641 12.997 3.25829C12.6913 3.08017 12.3438 2.98633 11.9901 2.98633C11.6363 2.98633 11.2888 3.08017 10.9831 3.25829C10.6774 3.43641 10.4245 3.69243 10.2501 4.00022L2.25005 18.0002C2.07373 18.3056 1.98128 18.6521 1.98206 19.0047C1.98284 19.3573 2.07683 19.7035 2.2545 20.008C2.43217 20.3126 2.6872 20.5648 2.99375 20.7391C3.30029 20.9133 3.64746 21.0034 4.00005 21.0002H20.0001C20.351 20.9999 20.6956 20.9072 20.9993 20.7315C21.3031 20.5558 21.5553 20.3033 21.7306 19.9993C21.9059 19.6954 21.9981 19.3506 21.998 18.9997C21.9979 18.6488 21.9055 18.3041 21.7301 18.0002Z",
30689
+ stroke: "#F2A800",
30690
+ strokeWidth: "2",
30691
+ strokeLinecap: "round",
30692
+ strokeLinejoin: "round"
30693
+ }
30694
+ )
30695
+ }
30696
+ );
30697
+ }
30698
+ function ToastInfoIcon(props) {
30699
+ return /* @__PURE__ */ jsx(
30700
+ "svg",
30701
+ {
30702
+ width: "24",
30703
+ height: "24",
30704
+ viewBox: "0 0 24 24",
30705
+ fill: "none",
30706
+ xmlns: "http://www.w3.org/2000/svg",
30707
+ "aria-hidden": true,
30708
+ ...props,
30709
+ children: /* @__PURE__ */ jsx(
30710
+ "path",
30711
+ {
30712
+ d: "M12 16V12M12 8H12.01M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12Z",
30713
+ stroke: "#0F52C7",
30714
+ strokeWidth: "2",
30715
+ strokeLinecap: "round",
30716
+ strokeLinejoin: "round"
30717
+ }
30718
+ )
30719
+ }
30720
+ );
30721
+ }
30722
+ function ToastIconBadge({
30723
+ tone,
30724
+ children
30725
+ }) {
30726
+ return /* @__PURE__ */ jsx("div", { className: `homepad-toast__icon-badge homepad-toast__icon-badge--${tone}`, children });
30727
+ }
30728
+ var homepadToastIcons = {
30729
+ success: /* @__PURE__ */ jsx(ToastIconBadge, { tone: "success", children: /* @__PURE__ */ jsx(ToastSuccessIcon, {}) }),
30730
+ error: /* @__PURE__ */ jsx(ToastIconBadge, { tone: "error", children: /* @__PURE__ */ jsx(ToastErrorIcon, {}) }),
30731
+ warning: /* @__PURE__ */ jsx(ToastIconBadge, { tone: "warning", children: /* @__PURE__ */ jsx(ToastWarningIcon, {}) }),
30732
+ info: /* @__PURE__ */ jsx(ToastIconBadge, { tone: "info", children: /* @__PURE__ */ jsx(ToastInfoIcon, {}) }),
30733
+ close: /* @__PURE__ */ jsx(ToastCloseIcon, {})
30734
+ };
30735
+ function Toaster({
30736
+ className,
30737
+ position = "bottom-right",
30738
+ theme = "light",
30739
+ closeButton = true,
30740
+ gap = 12,
30741
+ offset = 20,
30742
+ toastOptions,
30743
+ icons,
30744
+ ...props
30745
+ }) {
30746
+ return /* @__PURE__ */ jsx(
30747
+ Toaster$1,
30748
+ {
30749
+ className: ["homepad-toaster", className].filter(Boolean).join(" "),
30750
+ theme,
30751
+ position,
30752
+ closeButton,
30753
+ gap,
30754
+ offset,
30755
+ mobileOffset: 8,
30756
+ icons: { ...homepadToastIcons, ...icons },
30757
+ toastOptions: {
30758
+ duration: 4e3,
30759
+ classNames: {
30760
+ toast: "homepad-toast",
30761
+ title: "homepad-toast__title",
30762
+ description: "homepad-toast__description",
30763
+ content: "homepad-toast__content",
30764
+ icon: "homepad-toast__icon",
30765
+ closeButton: "homepad-toast__close",
30766
+ ...toastOptions?.classNames
30767
+ },
30768
+ ...toastOptions
30769
+ },
30770
+ ...props
30771
+ }
30772
+ );
30773
+ }
30774
+ function ToasterProvider() {
30775
+ return /* @__PURE__ */ jsx(Toaster, {});
30776
+ }
30777
+
30778
+ // src/web/mutation-toast.ts
30779
+ async function runMutationWithToast(action, messages, options) {
30780
+ try {
30781
+ await action();
30782
+ toast.success(messages.success);
30783
+ return { success: true };
30784
+ } catch (error) {
30785
+ const errorMessage = options?.getErrorMessage?.(error) ?? messages.error;
30786
+ toast.error(errorMessage);
30787
+ return { success: false, errorMessage };
30788
+ }
30394
30789
  }
30395
30790
  function ConfirmModal({
30396
30791
  open,
@@ -30450,7 +30845,7 @@ function ConfirmModal({
30450
30845
  "h2",
30451
30846
  {
30452
30847
  id: "homepad-confirm-modal-title",
30453
- className: "font-sans text-xl font-bold leading-6.75 tracking-normal text-black",
30848
+ className: "typography-title tracking-normal text-black",
30454
30849
  children: title
30455
30850
  }
30456
30851
  ),
@@ -30458,7 +30853,7 @@ function ConfirmModal({
30458
30853
  "div",
30459
30854
  {
30460
30855
  id: "homepad-confirm-modal-description",
30461
- className: "text-center font-sans text-sm font-normal leading-4.75 tracking-normal text-storm-gray-400",
30856
+ className: "text-center typography-body tracking-normal text-storm-gray-400",
30462
30857
  children: description
30463
30858
  }
30464
30859
  )
@@ -30555,6 +30950,6 @@ react-dom/cjs/react-dom.development.js:
30555
30950
  *)
30556
30951
  */
30557
30952
 
30558
- export { AppHeader, Badge, BellIcon, BuildingIcon, BuildingSelect, ConfirmModal, DEFAULT_TABLE_BODY_MIN_HEIGHT, DashboardLayout, DataTable, Modal, Pagination, Sidebar, SidebarMobileHeader, SidebarNavItem, SidebarUserCard, StatusBadge, Table, TableActionButton, TableActionsCell, TableActionsMenu, TableBody, TableCell, TableHead, TableHeader, TableIconText, TableMenuActivateIcon, TableMenuCheckIcon, TableMenuCloseIcon, TableMenuEditIcon, TableMenuInfoIcon, TableMenuRefreshIcon, TableMenuSuspendIcon, TableMenuTrashIcon, TableMoreIcon, TableRow, TableRowStatusActions, TableScrollArea, TableSortIcon, TableStatusActionsCell, cn, getPaginationRange, getTotalPages, getVisiblePageNumbers, tableRowDisabledCellClassName, useMediaQuery, useOnClickOutside };
30953
+ export { AppHeader, Badge, BellIcon, BuildingIcon, BuildingSelect, ConfirmModal, DEFAULT_TABLE_BODY_MIN_HEIGHT, DashboardLayout, DataTable, Drawer, HistoryTimeline, Modal, Pagination, Sidebar, SidebarMobileHeader, SidebarNavItem, SidebarUserCard, StatusBadge, Table, TableActionButton, TableActionsCell, TableActionsMenu, TableBody, TableCell, TableHead, TableHeader, TableIconText, TableMenuActivateIcon, TableMenuCheckIcon, TableMenuCloseIcon, TableMenuEditIcon, TableMenuInfoIcon, TableMenuRefreshIcon, TableMenuSuspendIcon, TableMenuTrashIcon, TableMoreIcon, TableRow, TableRowStatusActions, TableScrollArea, TableSortIcon, TableStatusActionsCell, Toaster, ToasterProvider, cn, getPaginationRange, getTotalPages, getVisiblePageNumbers, runMutationWithToast, tableRowDisabledCellClassName, useMediaQuery, useOnClickOutside };
30559
30954
  //# sourceMappingURL=index.js.map
30560
30955
  //# sourceMappingURL=index.js.map