@xenide-io/the-old-ui-theme 0.10.0 → 0.11.0

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 (42) hide show
  1. package/dist/{Chip-DKT-82Lf.d.mts → Chip-Dw2g2t8D.d.mts} +14 -2
  2. package/dist/{Chip-DKT-82Lf.d.ts → Chip-Dw2g2t8D.d.ts} +14 -2
  3. package/dist/{chunk-LHE4ROON.mjs → chunk-RIPGN6FG.mjs} +412 -61
  4. package/dist/index.d.mts +3 -2
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.js +355 -23
  7. package/dist/index.mjs +11 -3
  8. package/dist/suite-analytics--Mf1RZbw.d.mts +29 -0
  9. package/dist/suite-analytics--Mf1RZbw.d.ts +29 -0
  10. package/dist/suite.d.mts +14 -4
  11. package/dist/suite.d.ts +14 -4
  12. package/dist/suite.js +920 -513
  13. package/dist/suite.mjs +898 -523
  14. package/dist/ui.d.mts +2 -2
  15. package/dist/ui.d.ts +2 -2
  16. package/dist/ui.js +401 -66
  17. package/dist/ui.mjs +3 -1
  18. package/package.json +1 -1
  19. package/src/app/globals.css +57 -1
  20. package/src/components/ui/BrandSpinner.tsx +256 -0
  21. package/src/components/ui/CodeBlock.tsx +11 -1
  22. package/src/components/ui/Marketing.tsx +17 -1
  23. package/src/components/ui/SettingsLayout.tsx +4 -0
  24. package/src/components/ui/Table.tsx +32 -9
  25. package/src/components/ui/brand-spinner.test.tsx +62 -0
  26. package/src/components/ui/index.ts +7 -0
  27. package/src/components/ui/table.test.tsx +31 -4
  28. package/src/styles/suite-skin.css +78 -46
  29. package/src/suite/components/ai-draft-editor.tsx +184 -0
  30. package/src/suite/components/ai-panel-workflows.test.tsx +179 -0
  31. package/src/suite/components/ai-panel.tsx +184 -14
  32. package/src/suite/components/app-switcher.tsx +13 -0
  33. package/src/suite/components/command-palette-host.tsx +20 -2
  34. package/src/suite/components/suite-notification-bell.tsx +23 -2
  35. package/src/suite/components/suite-notification-settings.tsx +11 -0
  36. package/src/suite/components/suite-settings-layout.tsx +1 -1
  37. package/src/suite/components/suite-settings-mobile-nav.tsx +5 -1
  38. package/src/suite/components/suite-sidebar.tsx +2 -2
  39. package/src/suite/components/theme-provider.tsx +2 -0
  40. package/src/suite/components/today-ui.tsx +33 -28
  41. package/src/suite/index.ts +8 -0
  42. package/src/suite/lib/suite-notifications.tsx +5 -0
package/dist/ui.js CHANGED
@@ -70,6 +70,7 @@ __export(ui_exports, {
70
70
  AvatarGroup: () => AvatarGroup,
71
71
  Badge: () => Badge,
72
72
  BarChart: () => BarChart,
73
+ BrandSpinner: () => BrandSpinner,
73
74
  Button: () => Button,
74
75
  ButtonChrome: () => ButtonChrome,
75
76
  Calendar: () => Calendar,
@@ -274,18 +275,32 @@ function MarketingHeader(_a) {
274
275
  "actions",
275
276
  "className"
276
277
  ]);
277
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("header", __spreadProps(__spreadValues({}, props), { className: cn("marketing-header", className), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "marketing-header__inner", children: [
278
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "marketing-header__brand", children: brand }),
279
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
280
- "nav",
281
- {
282
- className: "marketing-header__navigation",
283
- "aria-label": "Product navigation",
284
- children: navigation
285
- }
286
- ),
287
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "marketing-header__actions", children: actions })
288
- ] }) }));
278
+ const [scrolled, setScrolled] = (0, import_react2.useState)(false);
279
+ (0, import_react2.useEffect)(() => {
280
+ const onScroll = () => setScrolled(window.scrollY > 4);
281
+ onScroll();
282
+ window.addEventListener("scroll", onScroll, { passive: true });
283
+ return () => window.removeEventListener("scroll", onScroll);
284
+ }, []);
285
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
286
+ "header",
287
+ __spreadProps(__spreadValues({}, props), {
288
+ "data-scrolled": scrolled ? "true" : "false",
289
+ className: cn("marketing-header", className),
290
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "marketing-header__inner", children: [
291
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "marketing-header__brand", children: brand }),
292
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
293
+ "nav",
294
+ {
295
+ className: "marketing-header__navigation",
296
+ "aria-label": "Product navigation",
297
+ children: navigation
298
+ }
299
+ ),
300
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "marketing-header__actions", children: actions })
301
+ ] })
302
+ })
303
+ );
289
304
  }
290
305
  function MarketingLink(_a) {
291
306
  var _b = _a, {
@@ -1639,6 +1654,20 @@ function AuthDivider(_a) {
1639
1654
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", __spreadProps(__spreadValues({ className: cn("ph-auth-divider", className) }, props), { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children }) }));
1640
1655
  }
1641
1656
 
1657
+ // src/lib/suite-analytics.ts
1658
+ var SUITE_ANALYTICS_EVENT = "shellstack:analytics";
1659
+ function trackSuiteEvent(event, properties) {
1660
+ if (typeof window === "undefined" || !event) return;
1661
+ try {
1662
+ window.dispatchEvent(
1663
+ new CustomEvent(SUITE_ANALYTICS_EVENT, {
1664
+ detail: { event, properties }
1665
+ })
1666
+ );
1667
+ } catch (e) {
1668
+ }
1669
+ }
1670
+
1642
1671
  // src/components/ui/SettingsLayout.tsx
1643
1672
  var import_jsx_runtime14 = require("react/jsx-runtime");
1644
1673
  function SettingsNav(_a) {
@@ -1656,6 +1685,7 @@ function SettingsNav(_a) {
1656
1685
  item.active && "ph-settings-nav__item--active"
1657
1686
  ),
1658
1687
  "aria-current": item.active ? "page" : void 0,
1688
+ onClick: () => trackSuiteEvent("Tab Viewed", { tab: item.id }),
1659
1689
  children: [
1660
1690
  item.icon ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ph-settings-nav__icon", children: item.icon }) : null,
1661
1691
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: item.label }),
@@ -2621,24 +2651,41 @@ function Table({
2621
2651
  getRowStyle,
2622
2652
  getRowKey,
2623
2653
  className,
2654
+ tableClassName,
2655
+ variant = "default",
2624
2656
  caption,
2625
2657
  emptyState = "No data available."
2626
2658
  }) {
2627
2659
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2628
2660
  "div",
2629
2661
  {
2630
- className: cn("ph-table-wrap", compact && "ph-table-compact", className),
2662
+ className: cn(
2663
+ variant === "report" ? "ph-table-report-wrap" : "ph-table-wrap",
2664
+ compact && "ph-table-compact",
2665
+ className
2666
+ ),
2631
2667
  role: "region",
2632
2668
  "aria-label": caption != null ? caption : "Data table",
2633
2669
  tabIndex: 0,
2634
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("table", { className: cn("ph-table", zebra && "ph-table-zebra", ribbon && "ph-table--ribbon"), children: [
2635
- caption && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("caption", { className: "sr-only", children: caption }),
2636
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("th", { className: col.className, children: col.header }, col.key)) }) }),
2637
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tbody", { children: data.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { colSpan: columns.length, className: "ph-table-empty", children: emptyState }) }) : data.map((row, i) => {
2638
- var _a;
2639
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { style: getRowStyle == null ? void 0 : getRowStyle(row), children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { className: col.className, children: col.cell(row) }, col.key)) }, (_a = getRowKey == null ? void 0 : getRowKey(row, i)) != null ? _a : i);
2640
- }) })
2641
- ] })
2670
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2671
+ "table",
2672
+ {
2673
+ className: cn(
2674
+ variant === "report" ? "ph-table-report" : "ph-table",
2675
+ zebra && "ph-table-zebra",
2676
+ ribbon && "ph-table--ribbon",
2677
+ tableClassName
2678
+ ),
2679
+ children: [
2680
+ caption && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("caption", { className: "sr-only", children: caption }),
2681
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("th", { scope: "col", className: col.className, children: col.header }, col.key)) }) }),
2682
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tbody", { children: data.length === 0 ? emptyState === null ? null : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { colSpan: columns.length, className: "ph-table-empty", children: emptyState }) }) : data.map((row, i) => {
2683
+ var _a;
2684
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("tr", { style: getRowStyle == null ? void 0 : getRowStyle(row), children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("td", { className: col.className, children: col.cell(row) }, col.key)) }, (_a = getRowKey == null ? void 0 : getRowKey(row, i)) != null ? _a : i);
2685
+ }) })
2686
+ ]
2687
+ }
2688
+ )
2642
2689
  }
2643
2690
  );
2644
2691
  }
@@ -3737,7 +3784,16 @@ var import_jsx_runtime33 = require("react/jsx-runtime");
3737
3784
  function CodeBlock({ code, language = "tsx", filename, className }) {
3738
3785
  const [copied, setCopied] = (0, import_react22.useState)(false);
3739
3786
  const handleCopy = async () => {
3740
- await navigator.clipboard.writeText(code);
3787
+ try {
3788
+ await navigator.clipboard.writeText(code);
3789
+ } catch (e) {
3790
+ return;
3791
+ }
3792
+ trackSuiteEvent("Link Copied", {
3793
+ kind: "code",
3794
+ copy_kind: "code_block",
3795
+ label: filename != null ? filename : language
3796
+ });
3741
3797
  setCopied(true);
3742
3798
  setTimeout(() => setCopied(false), 2e3);
3743
3799
  };
@@ -4219,8 +4275,286 @@ function Spinner(_a) {
4219
4275
  }
4220
4276
  Spinner.displayName = "Spinner";
4221
4277
 
4222
- // src/components/ui/Dot.tsx
4278
+ // src/components/ui/BrandSpinner.tsx
4279
+ var import_react29 = require("react");
4223
4280
  var import_jsx_runtime42 = require("react/jsx-runtime");
4281
+ var sizes = { sm: 20, md: 40, lg: 56 };
4282
+ var reducedMotionQuery = "(prefers-reduced-motion: reduce)";
4283
+ function subscribeMotion(onChange) {
4284
+ var _a;
4285
+ const media = (_a = window.matchMedia) == null ? void 0 : _a.call(window, reducedMotionQuery);
4286
+ media == null ? void 0 : media.addEventListener("change", onChange);
4287
+ return () => media == null ? void 0 : media.removeEventListener("change", onChange);
4288
+ }
4289
+ function readReducedMotion() {
4290
+ var _a, _b;
4291
+ return (_b = (_a = window.matchMedia) == null ? void 0 : _a.call(window, reducedMotionQuery).matches) != null ? _b : false;
4292
+ }
4293
+ function BrandSpinner(_a) {
4294
+ var _b = _a, {
4295
+ variant = "ring",
4296
+ size = "md",
4297
+ label = "Loading",
4298
+ className
4299
+ } = _b, props = __objRest(_b, [
4300
+ "variant",
4301
+ "size",
4302
+ "label",
4303
+ "className"
4304
+ ]);
4305
+ const gradientId = `ph-spinner-${(0, import_react29.useId)().replace(/:/g, "")}`;
4306
+ const reducedMotion = (0, import_react29.useSyncExternalStore)(
4307
+ subscribeMotion,
4308
+ readReducedMotion,
4309
+ () => true
4310
+ );
4311
+ const dimension = sizes[size];
4312
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4313
+ "div",
4314
+ __spreadProps(__spreadValues({
4315
+ role: "status",
4316
+ "aria-label": label,
4317
+ "data-test": "app-spinner",
4318
+ className: cn(
4319
+ "inline-flex shrink-0",
4320
+ variant !== "orbit" && "text-ph-brand",
4321
+ className
4322
+ )
4323
+ }, props), {
4324
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4325
+ "svg",
4326
+ {
4327
+ width: dimension,
4328
+ height: dimension,
4329
+ viewBox: variant === "ring" ? "0 0 24 24" : "0 0 40 40",
4330
+ "aria-hidden": true,
4331
+ className: variant === "timer" || variant === "ring" ? "animate-spin motion-reduce:animate-none" : void 0,
4332
+ children: variant === "ring" ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
4333
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4334
+ "circle",
4335
+ {
4336
+ cx: "12",
4337
+ cy: "12",
4338
+ r: "10",
4339
+ fill: "none",
4340
+ stroke: "currentColor",
4341
+ strokeWidth: "3",
4342
+ opacity: "0.2"
4343
+ }
4344
+ ),
4345
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4346
+ "path",
4347
+ {
4348
+ d: "M12 2a10 10 0 0 1 10 10",
4349
+ fill: "none",
4350
+ stroke: "currentColor",
4351
+ strokeWidth: "3",
4352
+ strokeLinecap: "round"
4353
+ }
4354
+ )
4355
+ ] }) : variant === "timer" ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
4356
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4357
+ "circle",
4358
+ {
4359
+ cx: "20",
4360
+ cy: "20",
4361
+ r: "15",
4362
+ fill: "none",
4363
+ stroke: "currentColor",
4364
+ strokeOpacity: "0.18",
4365
+ strokeWidth: "2.5"
4366
+ }
4367
+ ),
4368
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4369
+ "circle",
4370
+ {
4371
+ cx: "20",
4372
+ cy: "20",
4373
+ r: "15",
4374
+ fill: "none",
4375
+ stroke: "currentColor",
4376
+ strokeWidth: "2.5",
4377
+ strokeLinecap: "round",
4378
+ strokeDasharray: "24 70"
4379
+ }
4380
+ ),
4381
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("circle", { cx: "20", cy: "5", r: "2.25", fill: "currentColor" })
4382
+ ] }) : variant === "columns" ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
4383
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4384
+ "rect",
4385
+ {
4386
+ x: "9",
4387
+ y: "16",
4388
+ width: "6",
4389
+ height: "14",
4390
+ rx: "2",
4391
+ fill: "currentColor",
4392
+ fillOpacity: "0.35",
4393
+ className: "ph-brand-spinner__column"
4394
+ }
4395
+ ),
4396
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4397
+ "rect",
4398
+ {
4399
+ x: "17",
4400
+ y: "11",
4401
+ width: "6",
4402
+ height: "19",
4403
+ rx: "2",
4404
+ fill: "currentColor",
4405
+ className: "ph-brand-spinner__column",
4406
+ style: { animationDelay: "0.14s" }
4407
+ }
4408
+ ),
4409
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4410
+ "rect",
4411
+ {
4412
+ x: "25",
4413
+ y: "14",
4414
+ width: "6",
4415
+ height: "16",
4416
+ rx: "2",
4417
+ fill: "currentColor",
4418
+ fillOpacity: "0.55",
4419
+ className: "ph-brand-spinner__column",
4420
+ style: { animationDelay: "0.28s" }
4421
+ }
4422
+ )
4423
+ ] }) : variant === "orbit" ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
4424
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
4425
+ "linearGradient",
4426
+ {
4427
+ id: gradientId,
4428
+ x1: "0%",
4429
+ y1: "0%",
4430
+ x2: "100%",
4431
+ y2: "100%",
4432
+ children: [
4433
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("stop", { offset: "0%", stopColor: "#1877f2" }),
4434
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("stop", { offset: "100%", stopColor: "#ebbcba" })
4435
+ ]
4436
+ }
4437
+ ) }),
4438
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4439
+ "circle",
4440
+ {
4441
+ cx: "20",
4442
+ cy: "20",
4443
+ r: "15",
4444
+ fill: "none",
4445
+ stroke: `url(#${gradientId})`,
4446
+ strokeOpacity: "0.25",
4447
+ strokeWidth: "2"
4448
+ }
4449
+ ),
4450
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("g", { className: "origin-[20px_20px] animate-spin motion-reduce:animate-none", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4451
+ "circle",
4452
+ {
4453
+ cx: "20",
4454
+ cy: "20",
4455
+ r: "15",
4456
+ fill: "none",
4457
+ stroke: `url(#${gradientId})`,
4458
+ strokeWidth: "2.5",
4459
+ strokeLinecap: "round",
4460
+ strokeDasharray: "22 72"
4461
+ }
4462
+ ) }),
4463
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("g", { className: "origin-[20px_20px] animate-[spin_1.6s_linear_infinite_reverse] motion-reduce:animate-none", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4464
+ "circle",
4465
+ {
4466
+ cx: "20",
4467
+ cy: "20",
4468
+ r: "9",
4469
+ fill: "none",
4470
+ stroke: "#ebbcba",
4471
+ strokeWidth: "2",
4472
+ strokeLinecap: "round",
4473
+ strokeDasharray: "12 45",
4474
+ strokeOpacity: "0.9"
4475
+ }
4476
+ ) }),
4477
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4478
+ "circle",
4479
+ {
4480
+ cx: "20",
4481
+ cy: "20",
4482
+ r: "2.5",
4483
+ fill: "#1877f2",
4484
+ className: "animate-pulse motion-reduce:animate-none"
4485
+ }
4486
+ )
4487
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
4488
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("g", { children: [
4489
+ !reducedMotion ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4490
+ "animateTransform",
4491
+ {
4492
+ attributeName: "transform",
4493
+ type: "rotate",
4494
+ from: "0 20 20",
4495
+ to: "360 20 20",
4496
+ dur: "2.4s",
4497
+ repeatCount: "indefinite"
4498
+ }
4499
+ ) : null,
4500
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4501
+ "circle",
4502
+ {
4503
+ cx: "20",
4504
+ cy: "20",
4505
+ r: "16",
4506
+ fill: "none",
4507
+ stroke: "currentColor",
4508
+ strokeOpacity: "0.2",
4509
+ strokeWidth: "1.5",
4510
+ strokeDasharray: "3 5"
4511
+ }
4512
+ )
4513
+ ] }),
4514
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("g", { children: [
4515
+ !reducedMotion ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4516
+ "animateTransform",
4517
+ {
4518
+ attributeName: "transform",
4519
+ type: "rotate",
4520
+ from: "360 20 20",
4521
+ to: "0 20 20",
4522
+ dur: "1.1s",
4523
+ repeatCount: "indefinite"
4524
+ }
4525
+ ) : null,
4526
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4527
+ "circle",
4528
+ {
4529
+ cx: "20",
4530
+ cy: "20",
4531
+ r: "11",
4532
+ fill: "none",
4533
+ stroke: "currentColor",
4534
+ strokeWidth: "2",
4535
+ strokeLinecap: "round",
4536
+ strokeDasharray: "18 52"
4537
+ }
4538
+ )
4539
+ ] }),
4540
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4541
+ "path",
4542
+ {
4543
+ d: "M16 14h8v12a1 1 0 0 1-1.4.9L20 25.5l-2.6 1.4A1 1 0 0 1 16 26V14z",
4544
+ fill: "currentColor",
4545
+ fillOpacity: "0.85",
4546
+ className: "animate-pulse motion-reduce:animate-none"
4547
+ }
4548
+ )
4549
+ ] })
4550
+ }
4551
+ )
4552
+ })
4553
+ );
4554
+ }
4555
+
4556
+ // src/components/ui/Dot.tsx
4557
+ var import_jsx_runtime43 = require("react/jsx-runtime");
4224
4558
  var colorMap = {
4225
4559
  green: "bg-ph-success",
4226
4560
  yellow: "bg-ph-warning",
@@ -4230,7 +4564,7 @@ var colorMap = {
4230
4564
  };
4231
4565
  function Dot(_a) {
4232
4566
  var _b = _a, { color = "gray", size = "md", className } = _b, props = __objRest(_b, ["color", "size", "className"]);
4233
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4567
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
4234
4568
  "span",
4235
4569
  __spreadValues({
4236
4570
  className: cn(
@@ -4246,9 +4580,9 @@ function Dot(_a) {
4246
4580
  Dot.displayName = "Dot";
4247
4581
 
4248
4582
  // src/components/ui/Chip.tsx
4249
- var import_react29 = require("react");
4250
- var import_jsx_runtime43 = require("react/jsx-runtime");
4251
- var Chip = (0, import_react29.forwardRef)(function Chip2(_a, ref) {
4583
+ var import_react30 = require("react");
4584
+ var import_jsx_runtime44 = require("react/jsx-runtime");
4585
+ var Chip = (0, import_react30.forwardRef)(function Chip2(_a, ref) {
4252
4586
  var _b = _a, {
4253
4587
  selected = false,
4254
4588
  onRemove,
@@ -4267,18 +4601,18 @@ var Chip = (0, import_react29.forwardRef)(function Chip2(_a, ref) {
4267
4601
  );
4268
4602
  if (onRemove) {
4269
4603
  const removeLabel = typeof children === "string" ? `Remove ${children}` : "Remove";
4270
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: chipClassName, children: [
4271
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
4604
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: chipClassName, children: [
4605
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4272
4606
  "button",
4273
4607
  __spreadProps(__spreadValues({
4274
4608
  ref,
4275
4609
  type: "button",
4276
4610
  className: "min-w-0 bg-transparent p-0 text-inherit"
4277
4611
  }, props), {
4278
- children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ph-chip__text", children })
4612
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "ph-chip__text", children })
4279
4613
  })
4280
4614
  ),
4281
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
4615
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4282
4616
  "button",
4283
4617
  {
4284
4618
  type: "button",
@@ -4286,26 +4620,26 @@ var Chip = (0, import_react29.forwardRef)(function Chip2(_a, ref) {
4286
4620
  disabled: props.disabled,
4287
4621
  className: "ph-chip__remove",
4288
4622
  "aria-label": removeLabel,
4289
- children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("path", { d: "M2 2l6 6M8 2l-6 6" }) })
4623
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M2 2l6 6M8 2l-6 6" }) })
4290
4624
  }
4291
4625
  )
4292
4626
  ] });
4293
4627
  }
4294
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
4628
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4295
4629
  "button",
4296
4630
  __spreadProps(__spreadValues({
4297
4631
  ref,
4298
4632
  type: "button",
4299
4633
  className: chipClassName
4300
4634
  }, props), {
4301
- children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ph-chip__text", children })
4635
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "ph-chip__text", children })
4302
4636
  })
4303
4637
  );
4304
4638
  });
4305
4639
  Chip.displayName = "Chip";
4306
4640
 
4307
4641
  // src/lib/chart/use-ph-chart-tokens.ts
4308
- var import_react30 = require("react");
4642
+ var import_react31 = require("react");
4309
4643
  var DEFAULT_TOKENS = {
4310
4644
  series: ["#1d4aff", "#621da6", "#42827e", "#ce0e74", "#f14f58", "#529a0a", "#fe729e"],
4311
4645
  muted: "hsl(220 9% 90%)",
@@ -4336,20 +4670,20 @@ function readTokens() {
4336
4670
  };
4337
4671
  }
4338
4672
  function useChartTokens() {
4339
- const [tokens, setTokens] = (0, import_react30.useState)(DEFAULT_TOKENS);
4340
- (0, import_react30.useEffect)(() => {
4673
+ const [tokens, setTokens] = (0, import_react31.useState)(DEFAULT_TOKENS);
4674
+ (0, import_react31.useEffect)(() => {
4341
4675
  setTokens(readTokens());
4342
4676
  }, []);
4343
4677
  return tokens;
4344
4678
  }
4345
4679
 
4346
4680
  // src/components/ui/Charts.tsx
4347
- var import_jsx_runtime44 = require("react/jsx-runtime");
4681
+ var import_jsx_runtime45 = require("react/jsx-runtime");
4348
4682
  function percent(value, total) {
4349
4683
  return total > 0 ? Math.round(value / total * 100) : 0;
4350
4684
  }
4351
4685
  function EmptyChart() {
4352
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-sm text-ph-subtle", children: "No data for this period." });
4686
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-sm text-ph-subtle", children: "No data for this period." });
4353
4687
  }
4354
4688
  function sliceColour(slice, index, series) {
4355
4689
  var _a;
@@ -4359,7 +4693,7 @@ function DonutChart({ slices, label, formatValue, className }) {
4359
4693
  const { series } = useChartTokens();
4360
4694
  const visible = slices.filter((slice) => slice.value > 0);
4361
4695
  const total = visible.reduce((sum, slice) => sum + slice.value, 0);
4362
- if (total <= 0) return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(EmptyChart, {});
4696
+ if (total <= 0) return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EmptyChart, {});
4363
4697
  const stops = visible.map((slice, index) => {
4364
4698
  const colour = sliceColour(slice, index, series);
4365
4699
  const before = visible.slice(0, index).reduce((sum, item) => sum + item.value, 0);
@@ -4367,15 +4701,15 @@ function DonutChart({ slices, label, formatValue, className }) {
4367
4701
  const end = (before + slice.value) / total * 360;
4368
4702
  return `${colour} ${start}deg ${end}deg`;
4369
4703
  }).join(", ");
4370
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cn("flex flex-col items-center gap-4 sm:flex-row sm:items-center", className), children: [
4371
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4704
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: cn("flex flex-col items-center gap-4 sm:flex-row sm:items-center", className), children: [
4705
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4372
4706
  "div",
4373
4707
  {
4374
4708
  role: "img",
4375
4709
  "aria-label": label,
4376
4710
  className: "relative h-36 w-36 shrink-0 rounded-full",
4377
4711
  style: { background: `conic-gradient(${stops})` },
4378
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4712
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4379
4713
  "span",
4380
4714
  {
4381
4715
  className: "absolute inset-[22%] rounded-full bg-ph-surface ring-1 ring-ph-border",
@@ -4384,14 +4718,14 @@ function DonutChart({ slices, label, formatValue, className }) {
4384
4718
  )
4385
4719
  }
4386
4720
  ),
4387
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: "min-w-0 w-full flex-1 space-y-2", children: visible.map((slice, index) => {
4721
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "min-w-0 w-full flex-1 space-y-2", children: visible.map((slice, index) => {
4388
4722
  const colour = sliceColour(slice, index, series);
4389
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "flex items-center justify-between gap-3 text-sm", children: [
4390
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "flex min-w-0 items-center gap-2 text-ph-subtle", children: [
4391
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "h-2.5 w-2.5 shrink-0 rounded-full", style: { background: colour } }),
4392
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate", children: slice.label })
4723
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("li", { className: "flex items-center justify-between gap-3 text-sm", children: [
4724
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "flex min-w-0 items-center gap-2 text-ph-subtle", children: [
4725
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "h-2.5 w-2.5 shrink-0 rounded-full", style: { background: colour } }),
4726
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate", children: slice.label })
4393
4727
  ] }),
4394
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "shrink-0 tabular-nums text-ph-ink", children: formatValue ? formatValue(slice.value) : `${percent(slice.value, total)}%` })
4728
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "shrink-0 tabular-nums text-ph-ink", children: formatValue ? formatValue(slice.value) : `${percent(slice.value, total)}%` })
4395
4729
  ] }, slice.label);
4396
4730
  }) })
4397
4731
  ] });
@@ -4400,15 +4734,15 @@ function BarChart({ items, formatValue, className }) {
4400
4734
  const { series } = useChartTokens();
4401
4735
  const visible = items.filter((item) => item.value > 0);
4402
4736
  const max = Math.max(...visible.map((item) => item.value), 1);
4403
- if (!visible.length) return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(EmptyChart, {});
4404
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: cn("space-y-3", className), children: visible.map((item, index) => {
4737
+ if (!visible.length) return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EmptyChart, {});
4738
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: cn("space-y-3", className), children: visible.map((item, index) => {
4405
4739
  const colour = sliceColour(item, index, series);
4406
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { children: [
4407
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-3 text-sm", children: [
4408
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate text-ph-subtle", children: item.label }),
4409
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "shrink-0 tabular-nums text-ph-ink", children: formatValue ? formatValue(item.value) : item.value.toLocaleString("en-AU") })
4740
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("li", { children: [
4741
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-3 text-sm", children: [
4742
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate text-ph-subtle", children: item.label }),
4743
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "shrink-0 tabular-nums text-ph-ink", children: formatValue ? formatValue(item.value) : item.value.toLocaleString("en-AU") })
4410
4744
  ] }),
4411
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "h-2.5 rounded-full bg-ph-muted ring-1 ring-ph-border", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4745
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "h-2.5 rounded-full bg-ph-muted ring-1 ring-ph-border", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4412
4746
  "div",
4413
4747
  {
4414
4748
  className: "h-full rounded-full transition-[width] duration-300 ease-out motion-reduce:transition-none",
@@ -4430,15 +4764,15 @@ function StackedBarChart({
4430
4764
  const { series } = useChartTokens();
4431
4765
  const visible = slices.filter((slice) => slice.value > 0);
4432
4766
  const total = visible.reduce((sum, slice) => sum + slice.value, 0);
4433
- if (total <= 0) return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(EmptyChart, {});
4434
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cn("space-y-3", className), children: [
4435
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4767
+ if (total <= 0) return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(EmptyChart, {});
4768
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: cn("space-y-3", className), children: [
4769
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4436
4770
  "div",
4437
4771
  {
4438
4772
  role: "img",
4439
4773
  "aria-label": label,
4440
4774
  className: "flex h-3 overflow-hidden rounded-full bg-ph-muted ring-1 ring-ph-border",
4441
- children: visible.map((slice, index) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
4775
+ children: visible.map((slice, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4442
4776
  "span",
4443
4777
  {
4444
4778
  className: "h-full",
@@ -4451,14 +4785,14 @@ function StackedBarChart({
4451
4785
  ))
4452
4786
  }
4453
4787
  ),
4454
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: "space-y-2", children: visible.map((slice, index) => {
4788
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "space-y-2", children: visible.map((slice, index) => {
4455
4789
  const colour = sliceColour(slice, index, series);
4456
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "flex items-center justify-between gap-3 text-sm", children: [
4457
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "flex min-w-0 items-center gap-2 text-ph-subtle", children: [
4458
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "h-2.5 w-2.5 shrink-0 rounded-full", style: { background: colour } }),
4459
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate", children: slice.label })
4790
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("li", { className: "flex items-center justify-between gap-3 text-sm", children: [
4791
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "flex min-w-0 items-center gap-2 text-ph-subtle", children: [
4792
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "h-2.5 w-2.5 shrink-0 rounded-full", style: { background: colour } }),
4793
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "truncate", children: slice.label })
4460
4794
  ] }),
4461
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "shrink-0 tabular-nums text-ph-ink", children: formatValue ? formatValue(slice.value) : `${percent(slice.value, total)}%` })
4795
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "shrink-0 tabular-nums text-ph-ink", children: formatValue ? formatValue(slice.value) : `${percent(slice.value, total)}%` })
4462
4796
  ] }, slice.label);
4463
4797
  }) })
4464
4798
  ] });
@@ -4475,6 +4809,7 @@ function StackedBarChart({
4475
4809
  AvatarGroup,
4476
4810
  Badge,
4477
4811
  BarChart,
4812
+ BrandSpinner,
4478
4813
  Button,
4479
4814
  ButtonChrome,
4480
4815
  Calendar,