@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
@@ -8,6 +8,8 @@ var jsxRuntime = require('react/jsx-runtime');
8
8
  var clsx = require('clsx');
9
9
  var tailwindMerge = require('tailwind-merge');
10
10
  var reactRouterDom = require('react-router-dom');
11
+ var sonner = require('sonner');
12
+ require('sonner/dist/styles.css');
11
13
 
12
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
15
 
@@ -5381,7 +5383,7 @@ var require_react_dom_production_min = __commonJS({
5381
5383
  if (5 === d || 6 === d) a = a.stateNode, b ? c.insertBefore(a, b) : c.appendChild(a);
5382
5384
  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;
5383
5385
  }
5384
- var X2 = null;
5386
+ var X3 = null;
5385
5387
  var Xj = false;
5386
5388
  function Yj(a, b, c) {
5387
5389
  for (c = c.child; null !== c; ) Zj(a, b, c), c = c.sibling;
@@ -5395,23 +5397,23 @@ var require_react_dom_production_min = __commonJS({
5395
5397
  case 5:
5396
5398
  U || Lj(c, b);
5397
5399
  case 6:
5398
- var d = X2, e = Xj;
5399
- X2 = null;
5400
+ var d = X3, e = Xj;
5401
+ X3 = null;
5400
5402
  Yj(a, b, c);
5401
- X2 = d;
5403
+ X3 = d;
5402
5404
  Xj = e;
5403
- null !== X2 && (Xj ? (a = X2, c = c.stateNode, 8 === a.nodeType ? a.parentNode.removeChild(c) : a.removeChild(c)) : X2.removeChild(c.stateNode));
5405
+ null !== X3 && (Xj ? (a = X3, c = c.stateNode, 8 === a.nodeType ? a.parentNode.removeChild(c) : a.removeChild(c)) : X3.removeChild(c.stateNode));
5404
5406
  break;
5405
5407
  case 18:
5406
- 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));
5408
+ 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));
5407
5409
  break;
5408
5410
  case 4:
5409
- d = X2;
5411
+ d = X3;
5410
5412
  e = Xj;
5411
- X2 = c.stateNode.containerInfo;
5413
+ X3 = c.stateNode.containerInfo;
5412
5414
  Xj = true;
5413
5415
  Yj(a, b, c);
5414
- X2 = d;
5416
+ X3 = d;
5415
5417
  Xj = e;
5416
5418
  break;
5417
5419
  case 0:
@@ -5468,23 +5470,23 @@ var require_react_dom_production_min = __commonJS({
5468
5470
  a: for (; null !== h; ) {
5469
5471
  switch (h.tag) {
5470
5472
  case 5:
5471
- X2 = h.stateNode;
5473
+ X3 = h.stateNode;
5472
5474
  Xj = false;
5473
5475
  break a;
5474
5476
  case 3:
5475
- X2 = h.stateNode.containerInfo;
5477
+ X3 = h.stateNode.containerInfo;
5476
5478
  Xj = true;
5477
5479
  break a;
5478
5480
  case 4:
5479
- X2 = h.stateNode.containerInfo;
5481
+ X3 = h.stateNode.containerInfo;
5480
5482
  Xj = true;
5481
5483
  break a;
5482
5484
  }
5483
5485
  h = h.return;
5484
5486
  }
5485
- if (null === X2) throw Error(p(160));
5487
+ if (null === X3) throw Error(p(160));
5486
5488
  Zj(f, g, e);
5487
- X2 = null;
5489
+ X3 = null;
5488
5490
  Xj = false;
5489
5491
  var k = e.alternate;
5490
5492
  null !== k && (k.return = null);
@@ -27565,7 +27567,7 @@ var require_react_dom_development = __commonJS({
27565
27567
  return root2;
27566
27568
  }
27567
27569
  var ReactVersion = "18.3.1";
27568
- function createPortal2(children, containerInfo, implementation) {
27570
+ function createPortal3(children, containerInfo, implementation) {
27569
27571
  var key = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : null;
27570
27572
  {
27571
27573
  checkKeyStringCoercion(key);
@@ -28421,7 +28423,7 @@ var require_react_dom_development = __commonJS({
28421
28423
  if (!isValidContainer(container)) {
28422
28424
  throw new Error("Target container is not a DOM element.");
28423
28425
  }
28424
- return createPortal2(children, container, null, key);
28426
+ return createPortal3(children, container, null, key);
28425
28427
  }
28426
28428
  function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
28427
28429
  return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback);
@@ -29217,7 +29219,7 @@ function BuildingSelect({
29217
29219
  ),
29218
29220
  children: [
29219
29221
  buildingIcon ?? /* @__PURE__ */ jsxRuntime.jsx(BuildingIcon, { className: "shrink-0 text-navy" }),
29220
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-slate-blue", children: displayLabel }),
29222
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate typography-14 font-medium text-slate-blue", children: displayLabel }),
29221
29223
  chevronIcon ?? /* @__PURE__ */ jsxRuntime.jsx(
29222
29224
  lucideReact.ChevronsUpDown,
29223
29225
  {
@@ -29265,7 +29267,7 @@ function BuildingSelect({
29265
29267
  },
29266
29268
  onClick: () => selectOption(option),
29267
29269
  className: cn(
29268
- "flex w-full rounded-lg px-3 py-2.5 text-left text-sm font-medium text-slate-blue transition-colors",
29270
+ "flex w-full rounded-lg px-3 py-2.5 text-left typography-14 font-medium text-slate-blue transition-colors",
29269
29271
  !option.disabled && "cursor-pointer hover:bg-storm-gray-50",
29270
29272
  (isSelected || isHighlighted) && !option.disabled && "bg-storm-gray-50",
29271
29273
  option.disabled && "cursor-not-allowed opacity-50"
@@ -29318,7 +29320,7 @@ function AppHeader({
29318
29320
  className
29319
29321
  ),
29320
29322
  children: [
29321
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate text-xl font-bold text-slate-blue", children: title }),
29323
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "truncate typography-title text-slate-blue", children: title }),
29322
29324
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [
29323
29325
  hasBuildingSelect ? /* @__PURE__ */ jsxRuntime.jsx(
29324
29326
  BuildingSelect,
@@ -29421,7 +29423,7 @@ function SidebarNavItem({ item, isOpen, onNavigate }) {
29421
29423
  "span",
29422
29424
  {
29423
29425
  className: cn(
29424
- "overflow-hidden text-sm font-semibold whitespace-nowrap transition-[max-width,opacity] duration-300 ease-in-out",
29426
+ "overflow-hidden typography-14 font-semibold whitespace-nowrap transition-[max-width,opacity] duration-300 ease-in-out",
29425
29427
  isOpen ? "max-w-[180px] opacity-100" : "max-w-0 opacity-0"
29426
29428
  ),
29427
29429
  children: item.label
@@ -29458,15 +29460,15 @@ function SidebarUserCard({
29458
29460
  /* @__PURE__ */ jsxRuntime.jsx(
29459
29461
  "div",
29460
29462
  {
29461
- className: "flex size-11 shrink-0 items-center justify-center rounded-full bg-white/5 text-sm font-bold text-white",
29463
+ className: "flex size-11 shrink-0 items-center justify-center rounded-full bg-white/5 typography-14 font-bold text-white",
29462
29464
  "aria-hidden": true,
29463
29465
  children: initials
29464
29466
  }
29465
29467
  ),
29466
29468
  isOpen ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
29467
29469
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
29468
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-bold text-white", children: user.fullName }),
29469
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-storm-gray-100", children: user.email })
29470
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate typography-14 font-bold text-white", children: user.fullName }),
29471
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate typography-12 text-storm-gray-100", children: user.email })
29470
29472
  ] }),
29471
29473
  /* @__PURE__ */ jsxRuntime.jsx(
29472
29474
  "button",
@@ -30047,7 +30049,7 @@ var defaultLabels = {
30047
30049
  page: (pageNumber) => `Page ${pageNumber}`,
30048
30050
  showing: ({ start, end, total }) => `Showing ${start}-${end} of ${total}`
30049
30051
  };
30050
- 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";
30052
+ 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";
30051
30053
  var paginationHoverClassName = "cursor-pointer hover:bg-storm-gray-0";
30052
30054
  function Pagination({
30053
30055
  page,
@@ -30081,7 +30083,7 @@ function Pagination({
30081
30083
  className
30082
30084
  ),
30083
30085
  children: [
30084
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium leading-none text-storm-gray-200", children: mergedLabels.showing({ start, end, total }) }),
30086
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "typography-12 font-medium text-storm-gray-200", children: mergedLabels.showing({ start, end, total }) }),
30085
30087
  /* @__PURE__ */ jsxRuntime.jsxs(
30086
30088
  "nav",
30087
30089
  {
@@ -30168,8 +30170,8 @@ var tableCellPaddingClassName = "px-3 py-3";
30168
30170
  var tableHeadPaddingClassName = "px-3 py-4";
30169
30171
  var tableShellClassName = "flex flex-col overflow-hidden border bg-storm-gray-0";
30170
30172
  var tableFooterShellClassName = "overflow-hidden rounded-b-xl border bg-storm-gray-0";
30171
- var tableHeaderClassName = "bg-storm-gray-0 font-sans text-xs font-normal leading-none tracking-normal text-storm-gray-400";
30172
- var tableBodyClassName = "bg-white font-sans text-sm font-medium leading-none tracking-normal text-storm-gray-900";
30173
+ var tableHeaderClassName = "bg-storm-gray-0 typography-12 font-normal tracking-normal text-storm-gray-400";
30174
+ var tableBodyClassName = "bg-white typography-14 font-medium tracking-normal text-storm-gray-900";
30173
30175
  var tableAlignClasses = {
30174
30176
  left: "",
30175
30177
  right: "text-right",
@@ -30347,10 +30349,10 @@ function TableActionsCell({ className, children, ...props }) {
30347
30349
 
30348
30350
  // src/web/components/TableActionsMenu.tsx
30349
30351
  var import_react_dom = __toESM(require_react_dom());
30350
- 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";
30352
+ 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";
30351
30353
  var variantClasses = {
30352
- approve: actionButtonClassName,
30353
- reject: actionButtonClassName,
30354
+ approve: inlineActionClassName,
30355
+ reject: inlineActionClassName,
30354
30356
  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"
30355
30357
  };
30356
30358
  var inlineActionIconClassName = "inline-flex size-4 shrink-0 items-center justify-center [&_svg]:size-4";
@@ -30506,7 +30508,7 @@ function TableActionsMenu({
30506
30508
  item.onSelect();
30507
30509
  },
30508
30510
  className: cn(
30509
- "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",
30511
+ "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",
30510
30512
  index > 0 && "border-t border-storm-gray-50",
30511
30513
  item.disabled && "cursor-not-allowed opacity-50"
30512
30514
  ),
@@ -30737,7 +30739,7 @@ function Badge({ children, variant = "neutral", icon, className }) {
30737
30739
  "span",
30738
30740
  {
30739
30741
  className: cn(
30740
- "inline-flex items-center gap-2 rounded-[28px] px-3 py-1.5 font-sans text-xs font-semibold leading-none whitespace-nowrap",
30742
+ "inline-flex items-center gap-2 rounded-[28px] px-3 py-1.5 typography-12 font-semibold whitespace-nowrap",
30741
30743
  badgeVariantClasses[variant],
30742
30744
  className
30743
30745
  ),
@@ -30756,7 +30758,7 @@ function TableIconText({ icon, children, className }) {
30756
30758
  "span",
30757
30759
  {
30758
30760
  className: cn(
30759
- "inline-flex items-center gap-2 font-sans text-sm font-medium leading-none tracking-normal text-storm-gray-900",
30761
+ "inline-flex items-center gap-2 typography-14 font-medium tracking-normal text-storm-gray-900",
30760
30762
  className
30761
30763
  ),
30762
30764
  children: [
@@ -30767,6 +30769,9 @@ function TableIconText({ icon, children, className }) {
30767
30769
  );
30768
30770
  }
30769
30771
 
30772
+ // src/web/components/Modal.tsx
30773
+ var import_react_dom2 = __toESM(require_react_dom());
30774
+
30770
30775
  // src/icons/arrowUpRightPath.ts
30771
30776
  var ARROW_UP_RIGHT_PATH = "M14.1667 14.1668V5.8335H5.83333M14.1667 5.8335L5.83333 14.1668";
30772
30777
  function ArrowUpRightIcon({
@@ -30977,6 +30982,7 @@ function Modal({
30977
30982
  cancelDisabled = false,
30978
30983
  confirmDisabled = false,
30979
30984
  closeOnBackdrop = true,
30985
+ closeOnEscape = true,
30980
30986
  containerClassName,
30981
30987
  contentClassName,
30982
30988
  buttonClassName
@@ -30985,29 +30991,36 @@ function Modal({
30985
30991
  if (!open) {
30986
30992
  return;
30987
30993
  }
30994
+ const previousOverflow = document.body.style.overflow;
30995
+ document.body.style.overflow = "hidden";
30988
30996
  const handleKeyDown = (event) => {
30989
- if (event.key === "Escape") {
30997
+ if (event.key === "Escape" && closeOnEscape) {
30990
30998
  onCancel();
30991
30999
  }
30992
31000
  };
30993
31001
  window.addEventListener("keydown", handleKeyDown);
30994
31002
  return () => {
31003
+ document.body.style.overflow = previousOverflow;
30995
31004
  window.removeEventListener("keydown", handleKeyDown);
30996
31005
  };
30997
- }, [open, onCancel]);
31006
+ }, [open, onCancel, closeOnEscape]);
30998
31007
  if (!open) {
30999
31008
  return null;
31000
31009
  }
31001
31010
  const sharedButtonClassName = cn(
31002
31011
  "btn h-13 justify-center!",
31003
- footerLayout === "split" && "min-w-0 flex-1",
31004
- buttonClassName
31012
+ footerLayout === "split" && "min-w-0 flex-1 basis-0",
31013
+ footerLayout !== "split" && buttonClassName
31005
31014
  );
31006
- return /* @__PURE__ */ jsxRuntime.jsx(
31015
+ const modal = /* @__PURE__ */ jsxRuntime.jsx(
31007
31016
  "div",
31008
31017
  {
31009
- className: "fixed inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-[12px] bg-storm-gray-850/40",
31010
- onClick: closeOnBackdrop ? onCancel : void 0,
31018
+ className: "fixed inset-0 z-[100] flex items-center justify-center p-4 backdrop-blur-[12px] bg-storm-gray-850/40",
31019
+ onClick: closeOnBackdrop ? (event) => {
31020
+ if (event.target === event.currentTarget) {
31021
+ onCancel();
31022
+ }
31023
+ } : void 0,
31011
31024
  role: "presentation",
31012
31025
  children: /* @__PURE__ */ jsxRuntime.jsxs(
31013
31026
  "div",
@@ -31017,14 +31030,14 @@ function Modal({
31017
31030
  "aria-labelledby": "homepad-modal-title",
31018
31031
  ...subtitle ? { "aria-describedby": "homepad-modal-subtitle" } : {},
31019
31032
  className: cn(
31020
- "flex w-full max-w-2xl flex-col gap-6 rounded-2xl bg-white p-4 opacity-100 md:p-6",
31033
+ "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",
31021
31034
  containerClassName
31022
31035
  ),
31023
31036
  onClick: (event) => {
31024
31037
  event.stopPropagation();
31025
31038
  },
31026
31039
  children: [
31027
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: cn("flex", icon ? "items-center gap-2.5" : void 0), children: [
31040
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: cn("flex shrink-0", icon ? "items-center gap-2.5" : void 0), children: [
31028
31041
  icon ? /* @__PURE__ */ jsxRuntime.jsx(
31029
31042
  "div",
31030
31043
  {
@@ -31040,7 +31053,7 @@ function Modal({
31040
31053
  "h2",
31041
31054
  {
31042
31055
  id: "homepad-modal-title",
31043
- className: "font-sans text-lg font-bold leading-none tracking-normal text-black",
31056
+ className: "typography-title-sm tracking-normal text-black",
31044
31057
  children: title
31045
31058
  }
31046
31059
  ),
@@ -31048,18 +31061,18 @@ function Modal({
31048
31061
  "p",
31049
31062
  {
31050
31063
  id: "homepad-modal-subtitle",
31051
- className: "font-sans text-xs font-normal leading-none tracking-normal text-storm-gray-400",
31064
+ className: "typography-caption tracking-normal text-storm-gray-400",
31052
31065
  children: subtitle
31053
31066
  }
31054
31067
  ) : null
31055
31068
  ] })
31056
31069
  ] }),
31057
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-w-0", contentClassName), children }),
31070
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-h-0 min-w-0 flex-1 overflow-y-auto", contentClassName), children }),
31058
31071
  /* @__PURE__ */ jsxRuntime.jsxs(
31059
31072
  "footer",
31060
31073
  {
31061
31074
  className: cn(
31062
- "flex gap-4",
31075
+ "flex shrink-0 gap-4",
31063
31076
  footerLayout === "split" ? "w-full" : footerAlignClasses[footerAlign]
31064
31077
  ),
31065
31078
  children: [
@@ -31093,6 +31106,387 @@ function Modal({
31093
31106
  )
31094
31107
  }
31095
31108
  );
31109
+ return typeof document !== "undefined" ? (0, import_react_dom2.createPortal)(modal, document.body) : modal;
31110
+ }
31111
+ var DRAWER_TRANSITION_MS = 300;
31112
+ function Drawer({
31113
+ open,
31114
+ title,
31115
+ subtitle,
31116
+ children,
31117
+ footer,
31118
+ onClose,
31119
+ closeAriaLabel = "Close",
31120
+ widthClassName = "w-full md:w-[464px]",
31121
+ className,
31122
+ headerClassName,
31123
+ contentClassName,
31124
+ footerClassName
31125
+ }) {
31126
+ const [isPresent, setIsPresent] = react.useState(open);
31127
+ const [isAnimatedIn, setIsAnimatedIn] = react.useState(false);
31128
+ react.useEffect(() => {
31129
+ if (open) {
31130
+ setIsPresent(true);
31131
+ const frame = window.requestAnimationFrame(() => {
31132
+ window.requestAnimationFrame(() => {
31133
+ setIsAnimatedIn(true);
31134
+ });
31135
+ });
31136
+ return () => {
31137
+ window.cancelAnimationFrame(frame);
31138
+ };
31139
+ }
31140
+ setIsAnimatedIn(false);
31141
+ const timeout = window.setTimeout(() => {
31142
+ setIsPresent(false);
31143
+ }, DRAWER_TRANSITION_MS);
31144
+ return () => {
31145
+ window.clearTimeout(timeout);
31146
+ };
31147
+ }, [open]);
31148
+ react.useEffect(() => {
31149
+ if (!isPresent) {
31150
+ return;
31151
+ }
31152
+ const previousOverflow = document.body.style.overflow;
31153
+ document.body.style.overflow = "hidden";
31154
+ const handleKeyDown = (event) => {
31155
+ if (event.key === "Escape") {
31156
+ onClose();
31157
+ }
31158
+ };
31159
+ window.addEventListener("keydown", handleKeyDown);
31160
+ return () => {
31161
+ document.body.style.overflow = previousOverflow;
31162
+ window.removeEventListener("keydown", handleKeyDown);
31163
+ };
31164
+ }, [isPresent, onClose]);
31165
+ if (!isPresent) {
31166
+ return null;
31167
+ }
31168
+ return /* @__PURE__ */ jsxRuntime.jsxs(
31169
+ "div",
31170
+ {
31171
+ className: "fixed inset-0 z-50 flex justify-end p-2 max-md:p-0",
31172
+ role: "presentation",
31173
+ children: [
31174
+ /* @__PURE__ */ jsxRuntime.jsx(
31175
+ "button",
31176
+ {
31177
+ type: "button",
31178
+ "aria-label": closeAriaLabel,
31179
+ className: cn(
31180
+ "absolute inset-0 bg-storm-gray-850/40 backdrop-blur-[12px] transition-opacity duration-300 ease-in-out",
31181
+ isAnimatedIn ? "opacity-100" : "opacity-0"
31182
+ ),
31183
+ onClick: onClose
31184
+ }
31185
+ ),
31186
+ /* @__PURE__ */ jsxRuntime.jsxs(
31187
+ "aside",
31188
+ {
31189
+ role: "dialog",
31190
+ "aria-modal": "true",
31191
+ "aria-labelledby": "homepad-drawer-title",
31192
+ ...subtitle ? { "aria-describedby": "homepad-drawer-subtitle" } : {},
31193
+ className: cn(
31194
+ "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",
31195
+ isAnimatedIn ? "translate-x-0" : "translate-x-full",
31196
+ widthClassName,
31197
+ className
31198
+ ),
31199
+ children: [
31200
+ /* @__PURE__ */ jsxRuntime.jsxs(
31201
+ "header",
31202
+ {
31203
+ className: cn(
31204
+ "flex h-[87px] shrink-0 items-start justify-between border-b border-storm-gray-50 pt-6 pr-6 pb-4 pl-6",
31205
+ headerClassName
31206
+ ),
31207
+ children: [
31208
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex flex-col gap-1", children: [
31209
+ /* @__PURE__ */ jsxRuntime.jsx(
31210
+ "h2",
31211
+ {
31212
+ id: "homepad-drawer-title",
31213
+ className: "typography-title-sm tracking-normal text-black",
31214
+ children: title
31215
+ }
31216
+ ),
31217
+ subtitle ? /* @__PURE__ */ jsxRuntime.jsx(
31218
+ "p",
31219
+ {
31220
+ id: "homepad-drawer-subtitle",
31221
+ className: "typography-body tracking-normal text-storm-gray-400",
31222
+ children: subtitle
31223
+ }
31224
+ ) : null
31225
+ ] }),
31226
+ /* @__PURE__ */ jsxRuntime.jsx(
31227
+ "button",
31228
+ {
31229
+ type: "button",
31230
+ "aria-label": closeAriaLabel,
31231
+ 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",
31232
+ onClick: onClose,
31233
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-5", strokeWidth: 1.75 })
31234
+ }
31235
+ )
31236
+ ]
31237
+ }
31238
+ ),
31239
+ /* @__PURE__ */ jsxRuntime.jsx(
31240
+ "div",
31241
+ {
31242
+ className: cn(
31243
+ "drawer-scroll-area min-h-0 flex-1 overflow-y-auto px-6 pt-6 pb-0",
31244
+ contentClassName
31245
+ ),
31246
+ children
31247
+ }
31248
+ ),
31249
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("footer", { className: cn("shrink-0 px-6 py-5", footerClassName), children: footer }) : null
31250
+ ]
31251
+ }
31252
+ )
31253
+ ]
31254
+ }
31255
+ );
31256
+ }
31257
+ function TimelineCheckIcon({ className, ...props }) {
31258
+ return /* @__PURE__ */ jsxRuntime.jsx(
31259
+ "svg",
31260
+ {
31261
+ width: "16",
31262
+ height: "16",
31263
+ viewBox: "0 0 16 16",
31264
+ fill: "none",
31265
+ xmlns: "http://www.w3.org/2000/svg",
31266
+ className,
31267
+ "aria-hidden": true,
31268
+ ...props,
31269
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31270
+ "path",
31271
+ {
31272
+ d: "M13.3346 4L6.0013 11.3333L2.66797 8",
31273
+ stroke: "#279D54",
31274
+ strokeWidth: "1.5",
31275
+ strokeLinecap: "round",
31276
+ strokeLinejoin: "round"
31277
+ }
31278
+ )
31279
+ }
31280
+ );
31281
+ }
31282
+ function HistoryTimeline({ events }) {
31283
+ return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "m-0 flex list-none flex-col gap-1 p-0", children: events.map((event, index) => {
31284
+ const isLast = index === events.length - 1;
31285
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3", children: [
31286
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-8 shrink-0 flex-col items-center", children: [
31287
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-[28px] border border-storm-gray-50 bg-white", children: /* @__PURE__ */ jsxRuntime.jsx(TimelineCheckIcon, { className: "size-4 shrink-0" }) }),
31288
+ !isLast ? /* @__PURE__ */ jsxRuntime.jsx(
31289
+ "div",
31290
+ {
31291
+ "aria-hidden": true,
31292
+ className: "mt-1 h-[31px] w-px shrink-0 border-l border-dashed border-storm-gray-100"
31293
+ }
31294
+ ) : null
31295
+ ] }),
31296
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2 pt-1.5", children: [
31297
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "typography-14 font-medium tracking-normal text-slate-blue", children: event.title }),
31298
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "typography-caption tracking-normal text-storm-gray-300", children: event.timestamp })
31299
+ ] })
31300
+ ] }, event.id);
31301
+ }) });
31302
+ }
31303
+ function ToastCloseIcon(props) {
31304
+ return /* @__PURE__ */ jsxRuntime.jsx(
31305
+ "svg",
31306
+ {
31307
+ width: "20",
31308
+ height: "20",
31309
+ viewBox: "0 0 20 20",
31310
+ fill: "none",
31311
+ xmlns: "http://www.w3.org/2000/svg",
31312
+ "aria-hidden": true,
31313
+ ...props,
31314
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31315
+ "path",
31316
+ {
31317
+ d: "M15 5L5 15M5 5L15 15",
31318
+ stroke: "#B5BCC1",
31319
+ strokeWidth: "2",
31320
+ strokeLinecap: "round",
31321
+ strokeLinejoin: "round"
31322
+ }
31323
+ )
31324
+ }
31325
+ );
31326
+ }
31327
+ function ToastSuccessIcon(props) {
31328
+ return /* @__PURE__ */ jsxRuntime.jsx(
31329
+ "svg",
31330
+ {
31331
+ width: "24",
31332
+ height: "24",
31333
+ viewBox: "0 0 24 24",
31334
+ fill: "none",
31335
+ xmlns: "http://www.w3.org/2000/svg",
31336
+ "aria-hidden": true,
31337
+ ...props,
31338
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31339
+ "path",
31340
+ {
31341
+ d: "M20 6L9 17L4 12",
31342
+ stroke: "#279D54",
31343
+ strokeWidth: "2",
31344
+ strokeLinecap: "round",
31345
+ strokeLinejoin: "round"
31346
+ }
31347
+ )
31348
+ }
31349
+ );
31350
+ }
31351
+ function ToastErrorIcon(props) {
31352
+ return /* @__PURE__ */ jsxRuntime.jsx(
31353
+ "svg",
31354
+ {
31355
+ width: "24",
31356
+ height: "24",
31357
+ viewBox: "0 0 24 24",
31358
+ fill: "none",
31359
+ xmlns: "http://www.w3.org/2000/svg",
31360
+ "aria-hidden": true,
31361
+ ...props,
31362
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31363
+ "path",
31364
+ {
31365
+ d: "M18 6L6 18M6 6L18 18",
31366
+ stroke: "#AE0011",
31367
+ strokeWidth: "2",
31368
+ strokeLinecap: "round",
31369
+ strokeLinejoin: "round"
31370
+ }
31371
+ )
31372
+ }
31373
+ );
31374
+ }
31375
+ function ToastWarningIcon(props) {
31376
+ return /* @__PURE__ */ jsxRuntime.jsx(
31377
+ "svg",
31378
+ {
31379
+ width: "24",
31380
+ height: "24",
31381
+ viewBox: "0 0 24 24",
31382
+ fill: "none",
31383
+ xmlns: "http://www.w3.org/2000/svg",
31384
+ "aria-hidden": true,
31385
+ ...props,
31386
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31387
+ "path",
31388
+ {
31389
+ 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",
31390
+ stroke: "#F2A800",
31391
+ strokeWidth: "2",
31392
+ strokeLinecap: "round",
31393
+ strokeLinejoin: "round"
31394
+ }
31395
+ )
31396
+ }
31397
+ );
31398
+ }
31399
+ function ToastInfoIcon(props) {
31400
+ return /* @__PURE__ */ jsxRuntime.jsx(
31401
+ "svg",
31402
+ {
31403
+ width: "24",
31404
+ height: "24",
31405
+ viewBox: "0 0 24 24",
31406
+ fill: "none",
31407
+ xmlns: "http://www.w3.org/2000/svg",
31408
+ "aria-hidden": true,
31409
+ ...props,
31410
+ children: /* @__PURE__ */ jsxRuntime.jsx(
31411
+ "path",
31412
+ {
31413
+ 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",
31414
+ stroke: "#0F52C7",
31415
+ strokeWidth: "2",
31416
+ strokeLinecap: "round",
31417
+ strokeLinejoin: "round"
31418
+ }
31419
+ )
31420
+ }
31421
+ );
31422
+ }
31423
+ function ToastIconBadge({
31424
+ tone,
31425
+ children
31426
+ }) {
31427
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `homepad-toast__icon-badge homepad-toast__icon-badge--${tone}`, children });
31428
+ }
31429
+ var homepadToastIcons = {
31430
+ success: /* @__PURE__ */ jsxRuntime.jsx(ToastIconBadge, { tone: "success", children: /* @__PURE__ */ jsxRuntime.jsx(ToastSuccessIcon, {}) }),
31431
+ error: /* @__PURE__ */ jsxRuntime.jsx(ToastIconBadge, { tone: "error", children: /* @__PURE__ */ jsxRuntime.jsx(ToastErrorIcon, {}) }),
31432
+ warning: /* @__PURE__ */ jsxRuntime.jsx(ToastIconBadge, { tone: "warning", children: /* @__PURE__ */ jsxRuntime.jsx(ToastWarningIcon, {}) }),
31433
+ info: /* @__PURE__ */ jsxRuntime.jsx(ToastIconBadge, { tone: "info", children: /* @__PURE__ */ jsxRuntime.jsx(ToastInfoIcon, {}) }),
31434
+ close: /* @__PURE__ */ jsxRuntime.jsx(ToastCloseIcon, {})
31435
+ };
31436
+ function Toaster({
31437
+ className,
31438
+ position = "bottom-right",
31439
+ theme = "light",
31440
+ closeButton = true,
31441
+ gap = 12,
31442
+ offset = 20,
31443
+ toastOptions,
31444
+ icons,
31445
+ ...props
31446
+ }) {
31447
+ return /* @__PURE__ */ jsxRuntime.jsx(
31448
+ sonner.Toaster,
31449
+ {
31450
+ className: ["homepad-toaster", className].filter(Boolean).join(" "),
31451
+ theme,
31452
+ position,
31453
+ closeButton,
31454
+ gap,
31455
+ offset,
31456
+ mobileOffset: 8,
31457
+ icons: { ...homepadToastIcons, ...icons },
31458
+ toastOptions: {
31459
+ duration: 4e3,
31460
+ classNames: {
31461
+ toast: "homepad-toast",
31462
+ title: "homepad-toast__title",
31463
+ description: "homepad-toast__description",
31464
+ content: "homepad-toast__content",
31465
+ icon: "homepad-toast__icon",
31466
+ closeButton: "homepad-toast__close",
31467
+ ...toastOptions?.classNames
31468
+ },
31469
+ ...toastOptions
31470
+ },
31471
+ ...props
31472
+ }
31473
+ );
31474
+ }
31475
+ function ToasterProvider() {
31476
+ return /* @__PURE__ */ jsxRuntime.jsx(Toaster, {});
31477
+ }
31478
+
31479
+ // src/web/mutation-toast.ts
31480
+ async function runMutationWithToast(action, messages, options) {
31481
+ try {
31482
+ await action();
31483
+ sonner.toast.success(messages.success);
31484
+ return { success: true };
31485
+ } catch (error) {
31486
+ const errorMessage = options?.getErrorMessage?.(error) ?? messages.error;
31487
+ sonner.toast.error(errorMessage);
31488
+ return { success: false, errorMessage };
31489
+ }
31096
31490
  }
31097
31491
  function ConfirmModal({
31098
31492
  open,
@@ -31152,7 +31546,7 @@ function ConfirmModal({
31152
31546
  "h2",
31153
31547
  {
31154
31548
  id: "homepad-confirm-modal-title",
31155
- className: "font-sans text-xl font-bold leading-6.75 tracking-normal text-black",
31549
+ className: "typography-title tracking-normal text-black",
31156
31550
  children: title
31157
31551
  }
31158
31552
  ),
@@ -31160,7 +31554,7 @@ function ConfirmModal({
31160
31554
  "div",
31161
31555
  {
31162
31556
  id: "homepad-confirm-modal-description",
31163
- className: "text-center font-sans text-sm font-normal leading-4.75 tracking-normal text-storm-gray-400",
31557
+ className: "text-center typography-body tracking-normal text-storm-gray-400",
31164
31558
  children: description
31165
31559
  }
31166
31560
  )
@@ -31257,6 +31651,10 @@ react-dom/cjs/react-dom.development.js:
31257
31651
  *)
31258
31652
  */
31259
31653
 
31654
+ Object.defineProperty(exports, "toast", {
31655
+ enumerable: true,
31656
+ get: function () { return sonner.toast; }
31657
+ });
31260
31658
  exports.AppHeader = AppHeader;
31261
31659
  exports.Badge = Badge;
31262
31660
  exports.BellIcon = BellIcon;
@@ -31266,6 +31664,8 @@ exports.ConfirmModal = ConfirmModal;
31266
31664
  exports.DEFAULT_TABLE_BODY_MIN_HEIGHT = DEFAULT_TABLE_BODY_MIN_HEIGHT;
31267
31665
  exports.DashboardLayout = DashboardLayout;
31268
31666
  exports.DataTable = DataTable;
31667
+ exports.Drawer = Drawer;
31668
+ exports.HistoryTimeline = HistoryTimeline;
31269
31669
  exports.Modal = Modal;
31270
31670
  exports.Pagination = Pagination;
31271
31671
  exports.Sidebar = Sidebar;
@@ -31296,10 +31696,13 @@ exports.TableRowStatusActions = TableRowStatusActions;
31296
31696
  exports.TableScrollArea = TableScrollArea;
31297
31697
  exports.TableSortIcon = TableSortIcon;
31298
31698
  exports.TableStatusActionsCell = TableStatusActionsCell;
31699
+ exports.Toaster = Toaster;
31700
+ exports.ToasterProvider = ToasterProvider;
31299
31701
  exports.cn = cn;
31300
31702
  exports.getPaginationRange = getPaginationRange;
31301
31703
  exports.getTotalPages = getTotalPages;
31302
31704
  exports.getVisiblePageNumbers = getVisiblePageNumbers;
31705
+ exports.runMutationWithToast = runMutationWithToast;
31303
31706
  exports.tableRowDisabledCellClassName = tableRowDisabledCellClassName;
31304
31707
  exports.useMediaQuery = useMediaQuery;
31305
31708
  exports.useOnClickOutside = useOnClickOutside;