@withpotter/components 0.13.0-next.124 → 0.13.0-next.58

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 (132) hide show
  1. package/dist/billing/overview-tab.js +3 -4
  2. package/dist/billing/overview-tab.js.map +1 -1
  3. package/dist/billing/plans-tab.js +12 -6
  4. package/dist/billing/plans-tab.js.map +1 -1
  5. package/dist/charts/index.d.ts +1 -1
  6. package/dist/charts/index.js +1 -3
  7. package/dist/charts/index.js.map +1 -1
  8. package/dist/dashboard/activity-feed.d.ts +0 -2
  9. package/dist/dashboard/activity-feed.js +1 -4
  10. package/dist/dashboard/activity-feed.js.map +1 -1
  11. package/dist/dashboard/home/ask-controls.js +0 -1
  12. package/dist/dashboard/home/ask-controls.js.map +1 -1
  13. package/dist/dashboard/home/ask-mode-chip.js +4 -4
  14. package/dist/dashboard/home/ask-mode-chip.js.map +1 -1
  15. package/dist/dashboard/home/home-ask.js +3 -3
  16. package/dist/dashboard/home/home-ask.js.map +1 -1
  17. package/dist/dashboard/home/home-quick-actions.js +1 -9
  18. package/dist/dashboard/home/home-quick-actions.js.map +1 -1
  19. package/dist/dashboard/home/widgets/activity-widget.js +43 -56
  20. package/dist/dashboard/home/widgets/activity-widget.js.map +1 -1
  21. package/dist/dashboard/home/widgets/home-widgets.js +2 -3
  22. package/dist/dashboard/home/widgets/home-widgets.js.map +1 -1
  23. package/dist/dashboard/home/widgets/money-widgets.js +4 -9
  24. package/dist/dashboard/home/widgets/money-widgets.js.map +1 -1
  25. package/dist/dashboard/home/widgets/registry.d.ts +3 -6
  26. package/dist/dashboard/home/widgets/registry.js +2 -12
  27. package/dist/dashboard/home/widgets/registry.js.map +1 -1
  28. package/dist/dashboard/home/widgets/team-widget.js +3 -15
  29. package/dist/dashboard/home/widgets/team-widget.js.map +1 -1
  30. package/dist/dashboard/home/widgets/types.d.ts +1 -13
  31. package/dist/dashboard/home/widgets/types.js.map +1 -1
  32. package/dist/dashboard/home/widgets/use-home-layout.js +4 -9
  33. package/dist/dashboard/home/widgets/use-home-layout.js.map +1 -1
  34. package/dist/dashboard/home/widgets/website-widget.js +1 -9
  35. package/dist/dashboard/home/widgets/website-widget.js.map +1 -1
  36. package/dist/dashboard/page-transition.d.ts +0 -11
  37. package/dist/dashboard/page-transition.js +2 -9
  38. package/dist/dashboard/page-transition.js.map +1 -1
  39. package/dist/features/gift-card-artwork.js +1 -1
  40. package/dist/features/gift-card-artwork.js.map +1 -1
  41. package/dist/features/gift-cards/gift-cards-feature.js +518 -656
  42. package/dist/features/gift-cards/gift-cards-feature.js.map +1 -1
  43. package/dist/features/product-form.js +1 -1
  44. package/dist/features/product-form.js.map +1 -1
  45. package/dist/mobile/screens/billing-flows.js +6 -7
  46. package/dist/mobile/screens/billing-flows.js.map +1 -1
  47. package/dist/mobile/screens/billing.js +2 -2
  48. package/dist/mobile/screens/billing.js.map +1 -1
  49. package/dist/notifications-dropdown.js +1 -11
  50. package/dist/notifications-dropdown.js.map +1 -1
  51. package/dist/shell/notification-kinds.d.ts +2 -11
  52. package/dist/shell/notification-kinds.js +1 -16
  53. package/dist/shell/notification-kinds.js.map +1 -1
  54. package/dist/shell/notification-row.d.ts +2 -6
  55. package/dist/shell/notification-row.js +33 -59
  56. package/dist/shell/notification-row.js.map +1 -1
  57. package/dist/shell/product-switcher.js +0 -3
  58. package/dist/shell/product-switcher.js.map +1 -1
  59. package/dist/shell/settings-modal-context.d.ts +0 -2
  60. package/dist/shell/settings-modal-context.js +2 -4
  61. package/dist/shell/settings-modal-context.js.map +1 -1
  62. package/dist/shell/settings-panels.js +9 -29
  63. package/dist/shell/settings-panels.js.map +1 -1
  64. package/dist/shell/settings-rows.d.ts +2 -7
  65. package/dist/shell/settings-rows.js +36 -93
  66. package/dist/shell/settings-rows.js.map +1 -1
  67. package/dist/shell/shell.css +0 -192
  68. package/dist/shell/sidebar-footer.js +2 -6
  69. package/dist/shell/sidebar-footer.js.map +1 -1
  70. package/dist/shell/unified-settings-modal.d.ts +2 -3
  71. package/dist/shell/unified-settings-modal.js +74 -151
  72. package/dist/shell/unified-settings-modal.js.map +1 -1
  73. package/dist/sidebar/config.js +3 -19
  74. package/dist/sidebar/config.js.map +1 -1
  75. package/dist/sidebar/more-group.js +1 -1
  76. package/dist/sidebar/more-group.js.map +1 -1
  77. package/dist/sidebar/nav-renderers.js +0 -2
  78. package/dist/sidebar/nav-renderers.js.map +1 -1
  79. package/dist/sidebar/nav-section.js +3 -5
  80. package/dist/sidebar/nav-section.js.map +1 -1
  81. package/dist/sidebar/setup-progress.d.ts +1 -3
  82. package/dist/sidebar/setup-progress.js +2 -2
  83. package/dist/sidebar/setup-progress.js.map +1 -1
  84. package/dist/sidebar/spine-groups.js +1 -7
  85. package/dist/sidebar/spine-groups.js.map +1 -1
  86. package/dist/sidebar.js +5 -5
  87. package/dist/sidebar.js.map +1 -1
  88. package/dist/templates/template-live-thumb.js +5 -16
  89. package/dist/templates/template-live-thumb.js.map +1 -1
  90. package/package.json +5 -5
  91. package/dist/dashboard/activity-paid.d.ts +0 -10
  92. package/dist/dashboard/activity-paid.js +0 -7
  93. package/dist/dashboard/activity-paid.js.map +0 -1
  94. package/dist/dashboard/home/host-quick-actions.d.ts +0 -19
  95. package/dist/dashboard/home/host-quick-actions.js +0 -12
  96. package/dist/dashboard/home/host-quick-actions.js.map +0 -1
  97. package/dist/dashboard/home/widgets/host-widgets.d.ts +0 -6
  98. package/dist/dashboard/home/widgets/host-widgets.js +0 -16
  99. package/dist/dashboard/home/widgets/host-widgets.js.map +0 -1
  100. package/dist/dashboard/home/widgets/member-label.d.ts +0 -11
  101. package/dist/dashboard/home/widgets/member-label.js +0 -10
  102. package/dist/dashboard/home/widgets/member-label.js.map +0 -1
  103. package/dist/dashboard/home/widgets/middle-ellipsis.d.ts +0 -5
  104. package/dist/dashboard/home/widgets/middle-ellipsis.js +0 -11
  105. package/dist/dashboard/home/widgets/middle-ellipsis.js.map +0 -1
  106. package/dist/dashboard/home/widgets/revenue-series.d.ts +0 -12
  107. package/dist/dashboard/home/widgets/revenue-series.js +0 -26
  108. package/dist/dashboard/home/widgets/revenue-series.js.map +0 -1
  109. package/dist/dashboard/page-transition-key.d.ts +0 -7
  110. package/dist/dashboard/page-transition-key.js +0 -11
  111. package/dist/dashboard/page-transition-key.js.map +0 -1
  112. package/dist/features/gift-cards/gift-card-logic.d.ts +0 -41
  113. package/dist/features/gift-cards/gift-card-logic.js +0 -65
  114. package/dist/features/gift-cards/gift-card-logic.js.map +0 -1
  115. package/dist/features/gift-cards/hint.d.ts +0 -9
  116. package/dist/features/gift-cards/hint.js +0 -25
  117. package/dist/features/gift-cards/hint.js.map +0 -1
  118. package/dist/shell/notification-actions.d.ts +0 -12
  119. package/dist/shell/notification-actions.js +0 -18
  120. package/dist/shell/notification-actions.js.map +0 -1
  121. package/dist/shell/settings-groups.d.ts +0 -23
  122. package/dist/shell/settings-groups.js +0 -22
  123. package/dist/shell/settings-groups.js.map +0 -1
  124. package/dist/shell/settings-host.d.ts +0 -39
  125. package/dist/shell/settings-host.js +0 -37
  126. package/dist/shell/settings-host.js.map +0 -1
  127. package/dist/shell/sidebar-cards.d.ts +0 -32
  128. package/dist/shell/sidebar-cards.js +0 -37
  129. package/dist/shell/sidebar-cards.js.map +0 -1
  130. package/dist/templates/template-tile-source.d.ts +0 -24
  131. package/dist/templates/template-tile-source.js +0 -18
  132. package/dist/templates/template-tile-source.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/dashboard/activity-paid.ts"],"sourcesContent":["/**\n * Whether the money for an order has actually arrived.\n *\n * One answer for the activity feed's wording (\"started a ticket order\" versus\n * \"bought a ticket\") and for how quiet its row looks, so the two cannot drift.\n * The signal is the order's own `paymentStatus`, never the wording of a title.\n * An order with no payment status is treated as unpaid, which is what the\n * wording has always done.\n */\nexport function isOrderPaid(paymentStatus: string | null | undefined): boolean {\n return (\n paymentStatus === 'paid' ||\n paymentStatus === 'partially_refunded' ||\n paymentStatus === 'refunded'\n );\n}\n"],"mappings":"AASO,SAAS,YAAY,eAAmD;AAC7E,SACE,kBAAkB,UAClB,kBAAkB,wBAClB,kBAAkB;AAEtB;","names":[]}
@@ -1,19 +0,0 @@
1
- import type { LucideIcon } from 'lucide-react';
2
- /**
3
- * A quick action a host adds under the Home search box, such as "Send money"
4
- * from an engine this package knows nothing of. Registered once, where the
5
- * host builds its dashboard layout, like `registerHostWidget`. Registering the
6
- * same id again replaces it.
7
- */
8
- export interface HostQuickAction {
9
- id: string;
10
- label: string;
11
- Icon: LucideIcon;
12
- /** Where it goes. */
13
- href: string;
14
- /** Hide it from members who may not use it. Shown to everyone when absent. */
15
- allowed?: (can: (permission: string) => boolean) => boolean;
16
- }
17
- export declare function registerHostQuickAction(action: HostQuickAction): void;
18
- /** The host's quick actions, in the order they were registered. */
19
- export declare function hostQuickActions(): HostQuickAction[];
@@ -1,12 +0,0 @@
1
- const HOST_ACTIONS = /* @__PURE__ */ new Map();
2
- function registerHostQuickAction(action) {
3
- HOST_ACTIONS.set(action.id, action);
4
- }
5
- function hostQuickActions() {
6
- return [...HOST_ACTIONS.values()];
7
- }
8
- export {
9
- hostQuickActions,
10
- registerHostQuickAction
11
- };
12
- //# sourceMappingURL=host-quick-actions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/dashboard/home/host-quick-actions.ts"],"sourcesContent":["import type { LucideIcon } from 'lucide-react';\n\n/**\n * A quick action a host adds under the Home search box, such as \"Send money\"\n * from an engine this package knows nothing of. Registered once, where the\n * host builds its dashboard layout, like `registerHostWidget`. Registering the\n * same id again replaces it.\n */\nexport interface HostQuickAction {\n id: string;\n label: string;\n Icon: LucideIcon;\n /** Where it goes. */\n href: string;\n /** Hide it from members who may not use it. Shown to everyone when absent. */\n allowed?: (can: (permission: string) => boolean) => boolean;\n}\n\nconst HOST_ACTIONS = new Map<string, HostQuickAction>();\n\nexport function registerHostQuickAction(action: HostQuickAction): void {\n HOST_ACTIONS.set(action.id, action);\n}\n\n/** The host's quick actions, in the order they were registered. */\nexport function hostQuickActions(): HostQuickAction[] {\n return [...HOST_ACTIONS.values()];\n}\n"],"mappings":"AAkBA,MAAM,eAAe,oBAAI,IAA6B;AAE/C,SAAS,wBAAwB,QAA+B;AACrE,eAAa,IAAI,OAAO,IAAI,MAAM;AACpC;AAGO,SAAS,mBAAsC;AACpD,SAAO,CAAC,GAAG,aAAa,OAAO,CAAC;AAClC;","names":[]}
@@ -1,6 +0,0 @@
1
- import type { WidgetDef } from './types';
2
- export declare function registerHostWidget(def: WidgetDef): void;
3
- /** The host's widgets, in the order they were registered. */
4
- export declare function hostWidgets(): WidgetDef[];
5
- /** A host's widget by id, or undefined. */
6
- export declare function hostWidget(id: string): WidgetDef | undefined;
@@ -1,16 +0,0 @@
1
- const HOST_WIDGETS = /* @__PURE__ */ new Map();
2
- function registerHostWidget(def) {
3
- HOST_WIDGETS.set(def.id, def);
4
- }
5
- function hostWidgets() {
6
- return [...HOST_WIDGETS.values()];
7
- }
8
- function hostWidget(id) {
9
- return HOST_WIDGETS.get(id);
10
- }
11
- export {
12
- hostWidget,
13
- hostWidgets,
14
- registerHostWidget
15
- };
16
- //# sourceMappingURL=host-widgets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/dashboard/home/widgets/host-widgets.ts"],"sourcesContent":["import type { WidgetDef } from './types';\n\n/**\n * Widgets a host adds to the board. The catalogue in registry.tsx is what this package draws; a host with\n * something of its own to say (a wallet balance, from an engine this package knows nothing of)\n * registers it once, where its dashboard layout is built. Registering the same id again replaces it.\n */\nconst HOST_WIDGETS = new Map<string, WidgetDef>();\n\nexport function registerHostWidget(def: WidgetDef): void {\n HOST_WIDGETS.set(def.id, def);\n}\n\n/** The host's widgets, in the order they were registered. */\nexport function hostWidgets(): WidgetDef[] {\n return [...HOST_WIDGETS.values()];\n}\n\n/** A host's widget by id, or undefined. */\nexport function hostWidget(id: string): WidgetDef | undefined {\n return HOST_WIDGETS.get(id);\n}\n"],"mappings":"AAOA,MAAM,eAAe,oBAAI,IAAuB;AAEzC,SAAS,mBAAmB,KAAsB;AACvD,eAAa,IAAI,IAAI,IAAI,GAAG;AAC9B;AAGO,SAAS,cAA2B;AACzC,SAAO,CAAC,GAAG,aAAa,OAAO,CAAC;AAClC;AAGO,SAAS,WAAW,IAAmC;AAC5D,SAAO,aAAa,IAAI,EAAE;AAC5B;","names":[]}
@@ -1,11 +0,0 @@
1
- /**
2
- * Who a row is. An engine that lists people by the address they were invited with and gives no name
3
- * (Olive's) still has something to show: the part before the @, as the team page names them. Only a
4
- * person with no name and no address at all is a "Team member".
5
- */
6
- export declare function memberLabel(m: {
7
- name?: string | null;
8
- email?: string | null;
9
- inviteEmail?: string | null;
10
- role?: string;
11
- }): string;
@@ -1,10 +0,0 @@
1
- function memberLabel(m) {
2
- const address = (m.email || m.inviteEmail || "").trim();
3
- if (m.name?.trim()) return m.name.trim();
4
- if (address) return address.includes("@") ? address.split("@")[0] : address;
5
- return m.role === "owner" ? "Owner" : "Team member";
6
- }
7
- export {
8
- memberLabel
9
- };
10
- //# sourceMappingURL=member-label.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/dashboard/home/widgets/member-label.ts"],"sourcesContent":["/**\n * Who a row is. An engine that lists people by the address they were invited with and gives no name\n * (Olive's) still has something to show: the part before the @, as the team page names them. Only a\n * person with no name and no address at all is a \"Team member\".\n */\nexport function memberLabel(m: {\n name?: string | null;\n email?: string | null;\n inviteEmail?: string | null;\n role?: string;\n}): string {\n const address = (m.email || m.inviteEmail || '').trim();\n if (m.name?.trim()) return m.name.trim();\n if (address) return address.includes('@') ? address.split('@')[0] : address;\n return m.role === 'owner' ? 'Owner' : 'Team member';\n}\n\n"],"mappings":"AAKO,SAAS,YAAY,GAKjB;AACT,QAAM,WAAW,EAAE,SAAS,EAAE,eAAe,IAAI,KAAK;AACtD,MAAI,EAAE,MAAM,KAAK,EAAG,QAAO,EAAE,KAAK,KAAK;AACvC,MAAI,QAAS,QAAO,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,CAAC,IAAI;AACpE,SAAO,EAAE,SAAS,UAAU,UAAU;AACxC;","names":[]}
@@ -1,5 +0,0 @@
1
- /**
2
- * A long address shortened in the middle, keeping both ends: the start says whose it is and the end
3
- * says where it lives. Cut at the end, "fubi.box-9825bee8a691fdce..." lost the part that matters.
4
- */
5
- export declare function middleEllipsis(text: string, max?: number): string;
@@ -1,11 +0,0 @@
1
- function middleEllipsis(text, max = 28) {
2
- if (max < 5 || text.length <= max) return text;
3
- const keep = max - 1;
4
- const head = Math.ceil(keep * 0.6);
5
- const tail = keep - head;
6
- return `${text.slice(0, head)}\u2026${text.slice(text.length - tail)}`;
7
- }
8
- export {
9
- middleEllipsis
10
- };
11
- //# sourceMappingURL=middle-ellipsis.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/dashboard/home/widgets/middle-ellipsis.ts"],"sourcesContent":["/**\n * A long address shortened in the middle, keeping both ends: the start says whose it is and the end\n * says where it lives. Cut at the end, \"fubi.box-9825bee8a691fdce...\" lost the part that matters.\n */\nexport function middleEllipsis(text: string, max = 28): string {\n if (max < 5 || text.length <= max) return text;\n const keep = max - 1;\n const head = Math.ceil(keep * 0.6);\n const tail = keep - head;\n return `${text.slice(0, head)}\\u2026${text.slice(text.length - tail)}`;\n}\n"],"mappings":"AAIO,SAAS,eAAe,MAAc,MAAM,IAAY;AAC7D,MAAI,MAAM,KAAK,KAAK,UAAU,IAAK,QAAO;AAC1C,QAAM,OAAO,MAAM;AACnB,QAAM,OAAO,KAAK,KAAK,OAAO,GAAG;AACjC,QAAM,OAAO,OAAO;AACpB,SAAO,GAAG,KAAK,MAAM,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,KAAK,SAAS,IAAI,CAAC;AACtE;","names":[]}
@@ -1,12 +0,0 @@
1
- import type { TimeSeriesPoint } from '@withpotter/lib/api/types';
2
- /**
3
- * One point per day for the whole window, zero where nothing sold.
4
- *
5
- * The API sends only the days that had a sale, and the chart draws one bar per point and stretches
6
- * each to share the width, so a single day with a sale was one bar the full width of the card, a
7
- * flat block that read as broken. Laid out across the window, that day is a bar on its own day.
8
- *
9
- * The window ends today, or on the newest point if that is later (a day ahead in another zone).
10
- * Dates the chart cannot read as days are left as they came.
11
- */
12
- export declare function spreadByDay(series: TimeSeriesPoint[], days: number, now?: Date): TimeSeriesPoint[];
@@ -1,26 +0,0 @@
1
- const DAY = /^\d{4}-\d{2}-\d{2}/;
2
- const dayKey = (time) => new Date(time).toISOString().slice(0, 10);
3
- function spreadByDay(series, days, now = /* @__PURE__ */ new Date()) {
4
- if (!Number.isFinite(days) || days < 1) return series;
5
- if (series.length === 0 || !series.every((p) => DAY.test(p.date))) {
6
- return series;
7
- }
8
- const byDay = /* @__PURE__ */ new Map();
9
- for (const point of series) {
10
- const key = point.date.slice(0, 10);
11
- byDay.set(key, (byDay.get(key) ?? 0) + point.value);
12
- }
13
- const newest = [...byDay.keys()].sort().at(-1);
14
- const today = dayKey(now.getTime());
15
- const end = Date.parse(`${newest > today ? newest : today}T00:00:00Z`);
16
- const out = [];
17
- for (let i = days - 1; i >= 0; i -= 1) {
18
- const date = dayKey(end - i * 864e5);
19
- out.push({ date, value: byDay.get(date) ?? 0 });
20
- }
21
- return out;
22
- }
23
- export {
24
- spreadByDay
25
- };
26
- //# sourceMappingURL=revenue-series.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/dashboard/home/widgets/revenue-series.ts"],"sourcesContent":["import type { TimeSeriesPoint } from '@withpotter/lib/api/types';\n\nconst DAY = /^\\d{4}-\\d{2}-\\d{2}/;\n\nconst dayKey = (time: number) => new Date(time).toISOString().slice(0, 10);\n\n/**\n * One point per day for the whole window, zero where nothing sold.\n *\n * The API sends only the days that had a sale, and the chart draws one bar per point and stretches\n * each to share the width, so a single day with a sale was one bar the full width of the card, a\n * flat block that read as broken. Laid out across the window, that day is a bar on its own day.\n *\n * The window ends today, or on the newest point if that is later (a day ahead in another zone).\n * Dates the chart cannot read as days are left as they came.\n */\nexport function spreadByDay(\n series: TimeSeriesPoint[],\n days: number,\n now: Date = new Date(),\n): TimeSeriesPoint[] {\n if (!Number.isFinite(days) || days < 1) return series;\n if (series.length === 0 || !series.every((p) => DAY.test(p.date))) {\n return series;\n }\n\n const byDay = new Map<string, number>();\n for (const point of series) {\n const key = point.date.slice(0, 10);\n byDay.set(key, (byDay.get(key) ?? 0) + point.value);\n }\n\n const newest = [...byDay.keys()].sort().at(-1)!;\n const today = dayKey(now.getTime());\n const end = Date.parse(`${newest > today ? newest : today}T00:00:00Z`);\n\n const out: TimeSeriesPoint[] = [];\n for (let i = days - 1; i >= 0; i -= 1) {\n const date = dayKey(end - i * 86_400_000);\n out.push({ date, value: byDay.get(date) ?? 0 });\n }\n return out;\n}\n"],"mappings":"AAEA,MAAM,MAAM;AAEZ,MAAM,SAAS,CAAC,SAAiB,IAAI,KAAK,IAAI,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAYlE,SAAS,YACd,QACA,MACA,MAAY,oBAAI,KAAK,GACF;AACnB,MAAI,CAAC,OAAO,SAAS,IAAI,KAAK,OAAO,EAAG,QAAO;AAC/C,MAAI,OAAO,WAAW,KAAK,CAAC,OAAO,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,IAAI,CAAC,GAAG;AACjE,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,MAAM,KAAK,MAAM,GAAG,EAAE;AAClC,UAAM,IAAI,MAAM,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,KAAK;AAAA,EACpD;AAEA,QAAM,SAAS,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;AAC7C,QAAM,QAAQ,OAAO,IAAI,QAAQ,CAAC;AAClC,QAAM,MAAM,KAAK,MAAM,GAAG,SAAS,QAAQ,SAAS,KAAK,YAAY;AAErE,QAAM,MAAyB,CAAC;AAChC,WAAS,IAAI,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG;AACrC,UAAM,OAAO,OAAO,MAAM,IAAI,KAAU;AACxC,QAAI,KAAK,EAAE,MAAM,OAAO,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;AAAA,EAChD;AACA,SAAO;AACT;","names":[]}
@@ -1,7 +0,0 @@
1
- /**
2
- * Which "arrival" a path belongs to. A page fades and settles in when this key changes, and
3
- * everything inside it is drawn again. Most paths are their own arrival; a host names the sections
4
- * whose pages are tabs of one place (`/dashboard/staff` and its tabs), so moving between the tabs
5
- * does not make the title and tab bar arrive again.
6
- */
7
- export declare function transitionPath(pathname: string | null | undefined, groups: readonly string[]): string;
@@ -1,11 +0,0 @@
1
- function transitionPath(pathname, groups) {
2
- const path = pathname ?? "";
3
- for (const group of groups) {
4
- if (path === group || path.startsWith(`${group}/`)) return group;
5
- }
6
- return path;
7
- }
8
- export {
9
- transitionPath
10
- };
11
- //# sourceMappingURL=page-transition-key.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/dashboard/page-transition-key.ts"],"sourcesContent":["/**\n * Which \"arrival\" a path belongs to. A page fades and settles in when this key changes, and\n * everything inside it is drawn again. Most paths are their own arrival; a host names the sections\n * whose pages are tabs of one place (`/dashboard/staff` and its tabs), so moving between the tabs\n * does not make the title and tab bar arrive again.\n */\nexport function transitionPath(\n pathname: string | null | undefined,\n groups: readonly string[],\n): string {\n const path = pathname ?? '';\n for (const group of groups) {\n if (path === group || path.startsWith(`${group}/`)) return group;\n }\n return path;\n}\n"],"mappings":"AAMO,SAAS,eACd,UACA,QACQ;AACR,QAAM,OAAO,YAAY;AACzB,aAAW,SAAS,QAAQ;AAC1B,QAAI,SAAS,SAAS,KAAK,WAAW,GAAG,KAAK,GAAG,EAAG,QAAO;AAAA,EAC7D;AACA,SAAO;AACT;","names":[]}
@@ -1,41 +0,0 @@
1
- import type { GiftCardStatus } from '@withpotter/lib/api';
2
- /**
3
- * One vocabulary for a card's state, used by the filter chips, the status badge
4
- * in the list and the hints. "Used" and "Redeemed" used to describe two
5
- * different things with nearly the same word: a card whose balance is all
6
- * spent, and the amount spent across every card. The state is now "Fully
7
- * spent" and the amount is "Spent".
8
- */
9
- export declare const STATUS_LABEL: Record<GiftCardStatus, string>;
10
- export declare const STATUS_HINT: Record<GiftCardStatus, string>;
11
- export declare const ALL_HINT = "Every card, whatever its state.";
12
- export interface StatusFilter {
13
- value: GiftCardStatus | '';
14
- label: string;
15
- hint: string;
16
- }
17
- export declare const STATUS_FILTERS: StatusFilter[];
18
- /** The two lines behind the info icon beside the page title. */
19
- export declare const PAGE_HINT_LINES: string[];
20
- /**
21
- * True when there is nothing to show and nothing narrowing the list: no cards
22
- * have ever been issued. A filtered list that comes back empty is not first
23
- * run, and neither is a page still loading.
24
- */
25
- export declare function isFirstRun(input: {
26
- loading: boolean;
27
- search: string;
28
- status: GiftCardStatus | '';
29
- count: number;
30
- totalIssued: number | null | undefined;
31
- }): boolean;
32
- /** The symbol a currency is written with, falling back to its code. */
33
- export declare function currencySymbol(currency: string): string;
34
- /**
35
- * Shares one request between callers asking for the same thing at the same
36
- * time. A key is forgotten the moment its request settles, so a later call
37
- * (a reload, a poll) still goes to the network.
38
- */
39
- export declare function createInFlightDeduper(): {
40
- run<T>(key: string, start: () => Promise<T>): Promise<T>;
41
- };
@@ -1,65 +0,0 @@
1
- const STATUS_LABEL = {
2
- active: "Active",
3
- used: "Fully spent",
4
- expired: "Expired",
5
- cancelled: "Cancelled"
6
- };
7
- const STATUS_HINT = {
8
- active: "Can still be spent.",
9
- used: "The whole balance has been spent.",
10
- expired: "Passed its expiry date.",
11
- cancelled: "Voided by you. The record is kept."
12
- };
13
- const ALL_HINT = "Every card, whatever its state.";
14
- const STATUS_FILTERS = [
15
- { value: "", label: "All", hint: ALL_HINT },
16
- ...["active", "used", "expired", "cancelled"].map((value) => ({
17
- value,
18
- label: STATUS_LABEL[value],
19
- hint: STATUS_HINT[value]
20
- }))
21
- ];
22
- const PAGE_HINT_LINES = [
23
- "Credit a customer pays for now and spends later. Share the code with them.",
24
- "Open a card to email it or redeem some of its balance. Check balance looks up a code."
25
- ];
26
- function isFirstRun(input) {
27
- return !input.loading && !input.search.trim() && !input.status && input.count === 0 && (input.totalIssued ?? 0) === 0;
28
- }
29
- function currencySymbol(currency) {
30
- try {
31
- const part = new Intl.NumberFormat("en", {
32
- style: "currency",
33
- currency,
34
- currencyDisplay: "narrowSymbol"
35
- }).formatToParts(0).find((p) => p.type === "currency");
36
- return part?.value ?? currency;
37
- } catch {
38
- return currency;
39
- }
40
- }
41
- function createInFlightDeduper() {
42
- const inFlight = /* @__PURE__ */ new Map();
43
- return {
44
- run(key, start) {
45
- const existing = inFlight.get(key);
46
- if (existing) return existing;
47
- const promise = start().finally(() => {
48
- if (inFlight.get(key) === promise) inFlight.delete(key);
49
- });
50
- inFlight.set(key, promise);
51
- return promise;
52
- }
53
- };
54
- }
55
- export {
56
- ALL_HINT,
57
- PAGE_HINT_LINES,
58
- STATUS_FILTERS,
59
- STATUS_HINT,
60
- STATUS_LABEL,
61
- createInFlightDeduper,
62
- currencySymbol,
63
- isFirstRun
64
- };
65
- //# sourceMappingURL=gift-card-logic.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/features/gift-cards/gift-card-logic.ts"],"sourcesContent":["import type { GiftCardStatus } from '@withpotter/lib/api';\n\n/**\n * One vocabulary for a card's state, used by the filter chips, the status badge\n * in the list and the hints. \"Used\" and \"Redeemed\" used to describe two\n * different things with nearly the same word: a card whose balance is all\n * spent, and the amount spent across every card. The state is now \"Fully\n * spent\" and the amount is \"Spent\".\n */\nexport const STATUS_LABEL: Record<GiftCardStatus, string> = {\n active: 'Active',\n used: 'Fully spent',\n expired: 'Expired',\n cancelled: 'Cancelled',\n};\n\nexport const STATUS_HINT: Record<GiftCardStatus, string> = {\n active: 'Can still be spent.',\n used: 'The whole balance has been spent.',\n expired: 'Passed its expiry date.',\n cancelled: 'Voided by you. The record is kept.',\n};\n\nexport const ALL_HINT = 'Every card, whatever its state.';\n\nexport interface StatusFilter {\n value: GiftCardStatus | '';\n label: string;\n hint: string;\n}\n\nexport const STATUS_FILTERS: StatusFilter[] = [\n { value: '', label: 'All', hint: ALL_HINT },\n ...(['active', 'used', 'expired', 'cancelled'] as const).map((value) => ({\n value,\n label: STATUS_LABEL[value],\n hint: STATUS_HINT[value],\n })),\n];\n\n/** The two lines behind the info icon beside the page title. */\nexport const PAGE_HINT_LINES = [\n 'Credit a customer pays for now and spends later. Share the code with them.',\n 'Open a card to email it or redeem some of its balance. Check balance looks up a code.',\n];\n\n/**\n * True when there is nothing to show and nothing narrowing the list: no cards\n * have ever been issued. A filtered list that comes back empty is not first\n * run, and neither is a page still loading.\n */\nexport function isFirstRun(input: {\n loading: boolean;\n search: string;\n status: GiftCardStatus | '';\n count: number;\n totalIssued: number | null | undefined;\n}): boolean {\n return (\n !input.loading &&\n !input.search.trim() &&\n !input.status &&\n input.count === 0 &&\n (input.totalIssued ?? 0) === 0\n );\n}\n\n/** The symbol a currency is written with, falling back to its code. */\nexport function currencySymbol(currency: string): string {\n try {\n const part = new Intl.NumberFormat('en', {\n style: 'currency',\n currency,\n currencyDisplay: 'narrowSymbol',\n })\n .formatToParts(0)\n .find((p) => p.type === 'currency');\n return part?.value ?? currency;\n } catch {\n return currency;\n }\n}\n\n/**\n * Shares one request between callers asking for the same thing at the same\n * time. A key is forgotten the moment its request settles, so a later call\n * (a reload, a poll) still goes to the network.\n */\nexport function createInFlightDeduper() {\n const inFlight = new Map<string, Promise<unknown>>();\n return {\n run<T>(key: string, start: () => Promise<T>): Promise<T> {\n const existing = inFlight.get(key);\n if (existing) return existing as Promise<T>;\n const promise = start().finally(() => {\n if (inFlight.get(key) === promise) inFlight.delete(key);\n });\n inFlight.set(key, promise);\n return promise;\n },\n };\n}\n"],"mappings":"AASO,MAAM,eAA+C;AAAA,EAC1D,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,WAAW;AACb;AAEO,MAAM,cAA8C;AAAA,EACzD,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,WAAW;AACb;AAEO,MAAM,WAAW;AAQjB,MAAM,iBAAiC;AAAA,EAC5C,EAAE,OAAO,IAAI,OAAO,OAAO,MAAM,SAAS;AAAA,EAC1C,GAAI,CAAC,UAAU,QAAQ,WAAW,WAAW,EAAY,IAAI,CAAC,WAAW;AAAA,IACvE;AAAA,IACA,OAAO,aAAa,KAAK;AAAA,IACzB,MAAM,YAAY,KAAK;AAAA,EACzB,EAAE;AACJ;AAGO,MAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AACF;AAOO,SAAS,WAAW,OAMf;AACV,SACE,CAAC,MAAM,WACP,CAAC,MAAM,OAAO,KAAK,KACnB,CAAC,MAAM,UACP,MAAM,UAAU,MACf,MAAM,eAAe,OAAO;AAEjC;AAGO,SAAS,eAAe,UAA0B;AACvD,MAAI;AACF,UAAM,OAAO,IAAI,KAAK,aAAa,MAAM;AAAA,MACvC,OAAO;AAAA,MACP;AAAA,MACA,iBAAiB;AAAA,IACnB,CAAC,EACE,cAAc,CAAC,EACf,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU;AACpC,WAAO,MAAM,SAAS;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOO,SAAS,wBAAwB;AACtC,QAAM,WAAW,oBAAI,IAA8B;AACnD,SAAO;AAAA,IACL,IAAO,KAAa,OAAqC;AACvD,YAAM,WAAW,SAAS,IAAI,GAAG;AACjC,UAAI,SAAU,QAAO;AACrB,YAAM,UAAU,MAAM,EAAE,QAAQ,MAAM;AACpC,YAAI,SAAS,IAAI,GAAG,MAAM,QAAS,UAAS,OAAO,GAAG;AAAA,MACxD,CAAC;AACD,eAAS,IAAI,KAAK,OAAO;AACzB,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -1,9 +0,0 @@
1
- /**
2
- * The small info icon that holds a page's helper text, so the sentence is one
3
- * hover or focus away instead of sitting on the page. `lines` render one under
4
- * the other; screen readers get them joined as the button's name.
5
- */
6
- export declare function Hint({ lines, topic }: {
7
- lines: string[];
8
- topic: string;
9
- }): import("react").JSX.Element;
@@ -1,25 +0,0 @@
1
- "use client";
2
- import { jsx } from "react/jsx-runtime";
3
- import { Info } from "lucide-react";
4
- import { Tooltip } from "@withpotter/ui-kit/tooltip";
5
- function Hint({ lines, topic }) {
6
- return /* @__PURE__ */ jsx(
7
- Tooltip,
8
- {
9
- label: /* @__PURE__ */ jsx("span", { className: "block space-y-1", children: lines.map((line) => /* @__PURE__ */ jsx("span", { className: "block", children: line }, line)) }),
10
- children: /* @__PURE__ */ jsx(
11
- "button",
12
- {
13
- type: "button",
14
- "aria-label": `About ${topic}. ${lines.join(" ")}`,
15
- className: "inline-flex items-center rounded-md p-1 text-[var(--text-muted)] hover:text-[var(--text-secondary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
16
- children: /* @__PURE__ */ jsx(Info, { className: "size-4", "aria-hidden": true })
17
- }
18
- )
19
- }
20
- );
21
- }
22
- export {
23
- Hint
24
- };
25
- //# sourceMappingURL=hint.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/features/gift-cards/hint.tsx"],"sourcesContent":["'use client';\n\nimport { Info } from 'lucide-react';\nimport { Tooltip } from '@withpotter/ui-kit/tooltip';\n\n/**\n * The small info icon that holds a page's helper text, so the sentence is one\n * hover or focus away instead of sitting on the page. `lines` render one under\n * the other; screen readers get them joined as the button's name.\n */\nexport function Hint({ lines, topic }: { lines: string[]; topic: string }) {\n return (\n <Tooltip\n label={\n <span className=\"block space-y-1\">\n {lines.map((line) => (\n <span key={line} className=\"block\">\n {line}\n </span>\n ))}\n </span>\n }\n >\n <button\n type=\"button\"\n aria-label={`About ${topic}. ${lines.join(' ')}`}\n className=\"inline-flex items-center rounded-md p-1 text-[var(--text-muted)] hover:text-[var(--text-secondary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]\"\n >\n <Info className=\"size-4\" aria-hidden />\n </button>\n </Tooltip>\n );\n}\n"],"mappings":";AAgBY;AAdZ,SAAS,YAAY;AACrB,SAAS,eAAe;AAOjB,SAAS,KAAK,EAAE,OAAO,MAAM,GAAuC;AACzE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OACE,oBAAC,UAAK,WAAU,mBACb,gBAAM,IAAI,CAAC,SACV,oBAAC,UAAgB,WAAU,SACxB,kBADQ,IAEX,CACD,GACH;AAAA,MAGF;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAY,SAAS,KAAK,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,UAC9C,WAAU;AAAA,UAEV,8BAAC,QAAK,WAAU,UAAS,eAAW,MAAC;AAAA;AAAA,MACvC;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1,12 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import type { MerchantNotification } from '@withpotter/lib/api/types';
3
- /**
4
- * What a press on a bell row's pill does. The row only knows the intent ("pay", "keep", "resume"); the host knows what
5
- * that means in its product, so it answers here. Without a provider the pill is not drawn at all.
6
- */
7
- export type NotificationActionHandler = (intent: string, notification: MerchantNotification) => void;
8
- export declare function NotificationActionsProvider({ onAction, children, }: {
9
- onAction: NotificationActionHandler | null;
10
- children: ReactNode;
11
- }): import("react").JSX.Element;
12
- export declare function useNotificationActions(): NotificationActionHandler | null;
@@ -1,18 +0,0 @@
1
- "use client";
2
- import { jsx } from "react/jsx-runtime";
3
- import { createContext, useContext } from "react";
4
- const Context = createContext(null);
5
- function NotificationActionsProvider({
6
- onAction,
7
- children
8
- }) {
9
- return /* @__PURE__ */ jsx(Context.Provider, { value: onAction, children });
10
- }
11
- function useNotificationActions() {
12
- return useContext(Context);
13
- }
14
- export {
15
- NotificationActionsProvider,
16
- useNotificationActions
17
- };
18
- //# sourceMappingURL=notification-actions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/shell/notification-actions.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, type ReactNode } from 'react';\nimport type { MerchantNotification } from '@withpotter/lib/api/types';\n\n/**\n * What a press on a bell row's pill does. The row only knows the intent (\"pay\", \"keep\", \"resume\"); the host knows what\n * that means in its product, so it answers here. Without a provider the pill is not drawn at all.\n */\nexport type NotificationActionHandler = (\n intent: string,\n notification: MerchantNotification,\n) => void;\n\nconst Context = createContext<NotificationActionHandler | null>(null);\n\nexport function NotificationActionsProvider({\n onAction,\n children,\n}: {\n onAction: NotificationActionHandler | null;\n children: ReactNode;\n}) {\n return <Context.Provider value={onAction}>{children}</Context.Provider>;\n}\n\nexport function useNotificationActions(): NotificationActionHandler | null {\n return useContext(Context);\n}\n"],"mappings":";AAuBS;AArBT,SAAS,eAAe,kBAAkC;AAY1D,MAAM,UAAU,cAAgD,IAAI;AAE7D,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AACF,GAGG;AACD,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAO,UAAW,UAAS;AACtD;AAEO,SAAS,yBAA2D;AACzE,SAAO,WAAW,OAAO;AAC3B;","names":[]}
@@ -1,23 +0,0 @@
1
- /**
2
- * The rail of the settings window is two groups: the business's settings, and the person's own. A row belongs to
3
- * Business unless it is one of the few that are about the signed-in person. A host's own rows are the business's.
4
- */
5
- export declare const SettingsGroupKey: {
6
- readonly Business: "business";
7
- readonly You: "you";
8
- };
9
- export type SettingsGroupKey = (typeof SettingsGroupKey)[keyof typeof SettingsGroupKey];
10
- export declare const SETTINGS_GROUP_LABEL: Record<SettingsGroupKey, string>;
11
- export declare function groupOf(id: string): SettingsGroupKey;
12
- export interface SettingsGroup<T> {
13
- key: SettingsGroupKey;
14
- label: string;
15
- rows: T[];
16
- }
17
- /**
18
- * The rows split under their group labels, each group in the order the rows came in, Business first. A group with no
19
- * rows (a search that matches none of them) is left out, so no label is ever drawn over nothing.
20
- */
21
- export declare function groupRows<T extends {
22
- id: string;
23
- }>(rows: T[]): SettingsGroup<T>[];
@@ -1,22 +0,0 @@
1
- const SettingsGroupKey = {
2
- Business: "business",
3
- You: "you"
4
- };
5
- const SETTINGS_GROUP_LABEL = {
6
- [SettingsGroupKey.Business]: "Business",
7
- [SettingsGroupKey.You]: "You"
8
- };
9
- const PERSONAL = /* @__PURE__ */ new Set(["profile", "security", "notifications", "preferences"]);
10
- function groupOf(id) {
11
- return PERSONAL.has(id) ? SettingsGroupKey.You : SettingsGroupKey.Business;
12
- }
13
- function groupRows(rows) {
14
- return [SettingsGroupKey.Business, SettingsGroupKey.You].map((key) => ({ key, label: SETTINGS_GROUP_LABEL[key], rows: rows.filter((row) => groupOf(row.id) === key) })).filter((group) => group.rows.length > 0);
15
- }
16
- export {
17
- SETTINGS_GROUP_LABEL,
18
- SettingsGroupKey,
19
- groupOf,
20
- groupRows
21
- };
22
- //# sourceMappingURL=settings-groups.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/shell/settings-groups.ts"],"sourcesContent":["/**\n * The rail of the settings window is two groups: the business's settings, and the person's own. A row belongs to\n * Business unless it is one of the few that are about the signed-in person. A host's own rows are the business's.\n */\nexport const SettingsGroupKey = {\n Business: 'business',\n You: 'you',\n} as const;\nexport type SettingsGroupKey = (typeof SettingsGroupKey)[keyof typeof SettingsGroupKey];\n\nexport const SETTINGS_GROUP_LABEL: Record<SettingsGroupKey, string> = {\n [SettingsGroupKey.Business]: 'Business',\n [SettingsGroupKey.You]: 'You',\n};\n\n/** The rows that are about the person, not the business. */\nconst PERSONAL = new Set(['profile', 'security', 'notifications', 'preferences']);\n\nexport function groupOf(id: string): SettingsGroupKey {\n return PERSONAL.has(id) ? SettingsGroupKey.You : SettingsGroupKey.Business;\n}\n\nexport interface SettingsGroup<T> {\n key: SettingsGroupKey;\n label: string;\n rows: T[];\n}\n\n/**\n * The rows split under their group labels, each group in the order the rows came in, Business first. A group with no\n * rows (a search that matches none of them) is left out, so no label is ever drawn over nothing.\n */\nexport function groupRows<T extends { id: string }>(rows: T[]): SettingsGroup<T>[] {\n return [SettingsGroupKey.Business, SettingsGroupKey.You]\n .map((key) => ({ key, label: SETTINGS_GROUP_LABEL[key], rows: rows.filter((row) => groupOf(row.id) === key) }))\n .filter((group) => group.rows.length > 0);\n}\n"],"mappings":"AAIO,MAAM,mBAAmB;AAAA,EAC9B,UAAU;AAAA,EACV,KAAK;AACP;AAGO,MAAM,uBAAyD;AAAA,EACpE,CAAC,iBAAiB,QAAQ,GAAG;AAAA,EAC7B,CAAC,iBAAiB,GAAG,GAAG;AAC1B;AAGA,MAAM,WAAW,oBAAI,IAAI,CAAC,WAAW,YAAY,iBAAiB,aAAa,CAAC;AAEzE,SAAS,QAAQ,IAA8B;AACpD,SAAO,SAAS,IAAI,EAAE,IAAI,iBAAiB,MAAM,iBAAiB;AACpE;AAYO,SAAS,UAAoC,MAA+B;AACjF,SAAO,CAAC,iBAAiB,UAAU,iBAAiB,GAAG,EACpD,IAAI,CAAC,SAAS,EAAE,KAAK,OAAO,qBAAqB,GAAG,GAAG,MAAM,KAAK,OAAO,CAAC,QAAQ,QAAQ,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,EAC7G,OAAO,CAAC,UAAU,MAAM,KAAK,SAAS,CAAC;AAC5C;","names":[]}
@@ -1,39 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import type { LucideIcon } from 'lucide-react';
3
- /**
4
- * A row a host adds to the settings window, with the screen behind it.
5
- *
6
- * Olive's plans come from its own engine, so its Plan & billing is its own screen rather than the shared Billing page.
7
- * A host that never wraps the dashboard in `SettingsHostProvider` gets the window it had.
8
- */
9
- export interface HostSettingsRow {
10
- id: string;
11
- name: string;
12
- /** The line under the title when the row is open. */
13
- subtitle?: string;
14
- icon: LucideIcon;
15
- /** Addresses this row owns: a link to any of them opens the window on it. */
16
- paths: string[];
17
- /** What search also matches. */
18
- keywords: string[];
19
- /** The row it is placed after. Default: after General. */
20
- after?: string;
21
- /** The screen drawn in the window. */
22
- render: () => ReactNode;
23
- }
24
- export declare function SettingsHostProvider({ rows, generalRows, children, }: {
25
- rows: HostSettingsRow[];
26
- /**
27
- * Rows a host adds to General as their own Verification section, between the business's own details and the contact. Olive
28
- * shows its CAC certificate there. A host that passes nothing gets General as it was: no Verification heading is drawn.
29
- */
30
- generalRows?: () => ReactNode;
31
- children: ReactNode;
32
- }): import("react").JSX.Element;
33
- /** What a host drew into a slot, or null when there is no host, or the host has nothing to show right now. */
34
- export declare function slotContent(render: (() => ReactNode) | null | undefined): ReactNode;
35
- /** The host's rows for the Verification section of General, drawn by General itself. */
36
- export declare function useGeneralHostRows(): ReactNode;
37
- export declare function useSettingsHostRows(): HostSettingsRow[];
38
- /** The host row that owns an address: the address is one of its paths or sits below one. */
39
- export declare function hostRowForHref(rows: HostSettingsRow[], href: string | null | undefined): HostSettingsRow | undefined;
@@ -1,37 +0,0 @@
1
- "use client";
2
- import { jsx } from "react/jsx-runtime";
3
- import { createContext, useContext } from "react";
4
- const Context = createContext([]);
5
- const GeneralSlotContext = createContext(null);
6
- function SettingsHostProvider({
7
- rows,
8
- generalRows,
9
- children
10
- }) {
11
- return /* @__PURE__ */ jsx(Context.Provider, { value: rows, children: /* @__PURE__ */ jsx(GeneralSlotContext.Provider, { value: generalRows ?? null, children }) });
12
- }
13
- function slotContent(render) {
14
- if (!render) return null;
15
- const content = render();
16
- return content === void 0 || content === false ? null : content;
17
- }
18
- function useGeneralHostRows() {
19
- return slotContent(useContext(GeneralSlotContext));
20
- }
21
- function useSettingsHostRows() {
22
- return useContext(Context);
23
- }
24
- function hostRowForHref(rows, href) {
25
- const path = (href ?? "").split(/[?#]/)[0];
26
- return rows.find(
27
- (row) => row.paths.some((p) => path === p || path.startsWith(`${p}/`))
28
- );
29
- }
30
- export {
31
- SettingsHostProvider,
32
- hostRowForHref,
33
- slotContent,
34
- useGeneralHostRows,
35
- useSettingsHostRows
36
- };
37
- //# sourceMappingURL=settings-host.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/shell/settings-host.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, type ReactNode } from 'react';\nimport type { LucideIcon } from 'lucide-react';\n\n/**\n * A row a host adds to the settings window, with the screen behind it.\n *\n * Olive's plans come from its own engine, so its Plan & billing is its own screen rather than the shared Billing page.\n * A host that never wraps the dashboard in `SettingsHostProvider` gets the window it had.\n */\nexport interface HostSettingsRow {\n id: string;\n name: string;\n /** The line under the title when the row is open. */\n subtitle?: string;\n icon: LucideIcon;\n /** Addresses this row owns: a link to any of them opens the window on it. */\n paths: string[];\n /** What search also matches. */\n keywords: string[];\n /** The row it is placed after. Default: after General. */\n after?: string;\n /** The screen drawn in the window. */\n render: () => ReactNode;\n}\n\nconst Context = createContext<HostSettingsRow[]>([]);\nconst GeneralSlotContext = createContext<(() => ReactNode) | null>(null);\n\nexport function SettingsHostProvider({\n rows,\n generalRows,\n children,\n}: {\n rows: HostSettingsRow[];\n /**\n * Rows a host adds to General as their own Verification section, between the business's own details and the contact. Olive\n * shows its CAC certificate there. A host that passes nothing gets General as it was: no Verification heading is drawn.\n */\n generalRows?: () => ReactNode;\n children: ReactNode;\n}) {\n return (\n <Context.Provider value={rows}>\n <GeneralSlotContext.Provider value={generalRows ?? null}>\n {children}\n </GeneralSlotContext.Provider>\n </Context.Provider>\n );\n}\n\n/** What a host drew into a slot, or null when there is no host, or the host has nothing to show right now. */\nexport function slotContent(render: (() => ReactNode) | null | undefined): ReactNode {\n if (!render) return null;\n\n const content = render();\n\n return content === undefined || content === false ? null : content;\n}\n\n/** The host's rows for the Verification section of General, drawn by General itself. */\nexport function useGeneralHostRows(): ReactNode {\n return slotContent(useContext(GeneralSlotContext));\n}\n\nexport function useSettingsHostRows(): HostSettingsRow[] {\n return useContext(Context);\n}\n\n/** The host row that owns an address: the address is one of its paths or sits below one. */\nexport function hostRowForHref(\n rows: HostSettingsRow[],\n href: string | null | undefined,\n): HostSettingsRow | undefined {\n const path = (href ?? '').split(/[?#]/)[0];\n\n return rows.find((row) =>\n row.paths.some((p) => path === p || path.startsWith(`${p}/`)),\n );\n}\n"],"mappings":";AA6CM;AA3CN,SAAS,eAAe,kBAAkC;AAyB1D,MAAM,UAAU,cAAiC,CAAC,CAAC;AACnD,MAAM,qBAAqB,cAAwC,IAAI;AAEhE,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,SACE,oBAAC,QAAQ,UAAR,EAAiB,OAAO,MACvB,8BAAC,mBAAmB,UAAnB,EAA4B,OAAO,eAAe,MAChD,UACH,GACF;AAEJ;AAGO,SAAS,YAAY,QAAyD;AACnF,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,UAAU,OAAO;AAEvB,SAAO,YAAY,UAAa,YAAY,QAAQ,OAAO;AAC7D;AAGO,SAAS,qBAAgC;AAC9C,SAAO,YAAY,WAAW,kBAAkB,CAAC;AACnD;AAEO,SAAS,sBAAyC;AACvD,SAAO,WAAW,OAAO;AAC3B;AAGO,SAAS,eACd,MACA,MAC6B;AAC7B,QAAM,QAAQ,QAAQ,IAAI,MAAM,MAAM,EAAE,CAAC;AAEzC,SAAO,KAAK;AAAA,IAAK,CAAC,QAChB,IAAI,MAAM,KAAK,CAAC,MAAM,SAAS,KAAK,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC;AAAA,EAC9D;AACF;","names":[]}
@@ -1,32 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- /**
3
- * What a host adds to the rail's foot and the business menu for its plan.
4
- *
5
- * Nothing here is on by default: a host that never wraps the dashboard in
6
- * `SidebarCardsProvider` gets the rail it had. Olive does, because its plans
7
- * come from its own engine and the pricing switches this package reads
8
- * (`menuUpgrade`) are not what turns them on there.
9
- */
10
- export interface SidebarCardsConfig {
11
- /** The front card: where to go to change plan. Leave out on the top plan. */
12
- upgrade?: {
13
- title: string;
14
- hint: string;
15
- href: string;
16
- };
17
- /** The plan, as a tag on the current business in the business menu. */
18
- planLabel?: string;
19
- }
20
- export declare function SidebarCardsProvider({ value, children, }: {
21
- value: SidebarCardsConfig | null;
22
- children: ReactNode;
23
- }): import("react").JSX.Element;
24
- export declare function useSidebarCards(): SidebarCardsConfig | null;
25
- /**
26
- * Two standing cards stacked at the foot of the rail, the way Lovable does it.
27
- * At rest the Upgrade card sits in front with the next card's edge showing
28
- * beneath it; on hover or focus the stack opens and both are readable. The back
29
- * card is the setup progress, and it is simply absent once setup is done, which
30
- * leaves the Upgrade card alone.
31
- */
32
- export declare function SidebarCardStack(): import("react").JSX.Element | null;
@@ -1,37 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import Link from "next/link";
4
- import { createContext, useContext } from "react";
5
- import { Zap } from "lucide-react";
6
- import { SetupProgress } from "../sidebar/setup-progress";
7
- const Context = createContext(null);
8
- function SidebarCardsProvider({
9
- value,
10
- children
11
- }) {
12
- return /* @__PURE__ */ jsx(Context.Provider, { value, children });
13
- }
14
- function useSidebarCards() {
15
- return useContext(Context);
16
- }
17
- function SidebarCardStack() {
18
- const config = useSidebarCards();
19
- if (!config?.upgrade) return null;
20
- const { title, hint, href } = config.upgrade;
21
- return /* @__PURE__ */ jsx("div", { className: "side-stack", children: /* @__PURE__ */ jsxs("div", { className: "side-stack-in", children: [
22
- /* @__PURE__ */ jsxs(Link, { href, className: "side-stack-card side-stack-front", children: [
23
- /* @__PURE__ */ jsxs("span", { className: "side-stack-text", children: [
24
- /* @__PURE__ */ jsx("b", { children: title }),
25
- /* @__PURE__ */ jsx("span", { children: hint })
26
- ] }),
27
- /* @__PURE__ */ jsx("span", { className: "side-stack-glyph", "aria-hidden": true, children: /* @__PURE__ */ jsx(Zap, { width: 15, height: 15 }) })
28
- ] }),
29
- /* @__PURE__ */ jsx(SetupProgress, { stacked: true })
30
- ] }) });
31
- }
32
- export {
33
- SidebarCardStack,
34
- SidebarCardsProvider,
35
- useSidebarCards
36
- };
37
- //# sourceMappingURL=sidebar-cards.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/shell/sidebar-cards.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { createContext, useContext, type ReactNode } from 'react';\nimport { Zap } from 'lucide-react';\nimport { SetupProgress } from '../sidebar/setup-progress';\n\n/**\n * What a host adds to the rail's foot and the business menu for its plan.\n *\n * Nothing here is on by default: a host that never wraps the dashboard in\n * `SidebarCardsProvider` gets the rail it had. Olive does, because its plans\n * come from its own engine and the pricing switches this package reads\n * (`menuUpgrade`) are not what turns them on there.\n */\nexport interface SidebarCardsConfig {\n /** The front card: where to go to change plan. Leave out on the top plan. */\n upgrade?: { title: string; hint: string; href: string };\n /** The plan, as a tag on the current business in the business menu. */\n planLabel?: string;\n}\n\nconst Context = createContext<SidebarCardsConfig | null>(null);\n\nexport function SidebarCardsProvider({\n value,\n children,\n}: {\n value: SidebarCardsConfig | null;\n children: ReactNode;\n}) {\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\nexport function useSidebarCards(): SidebarCardsConfig | null {\n return useContext(Context);\n}\n\n/**\n * Two standing cards stacked at the foot of the rail, the way Lovable does it.\n * At rest the Upgrade card sits in front with the next card's edge showing\n * beneath it; on hover or focus the stack opens and both are readable. The back\n * card is the setup progress, and it is simply absent once setup is done, which\n * leaves the Upgrade card alone.\n */\nexport function SidebarCardStack() {\n const config = useSidebarCards();\n\n if (!config?.upgrade) return null;\n\n const { title, hint, href } = config.upgrade;\n\n return (\n <div className=\"side-stack\">\n <div className=\"side-stack-in\">\n <Link href={href} className=\"side-stack-card side-stack-front\">\n <span className=\"side-stack-text\">\n <b>{title}</b>\n <span>{hint}</span>\n </span>\n <span className=\"side-stack-glyph\" aria-hidden>\n <Zap width={15} height={15} />\n </span>\n </Link>\n <SetupProgress stacked />\n </div>\n </div>\n );\n}\n"],"mappings":";AA+BS,cAyBC,YAzBD;AA7BT,OAAO,UAAU;AACjB,SAAS,eAAe,kBAAkC;AAC1D,SAAS,WAAW;AACpB,SAAS,qBAAqB;AAiB9B,MAAM,UAAU,cAAyC,IAAI;AAEtD,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AACF,GAGG;AACD,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAe,UAAS;AACnD;AAEO,SAAS,kBAA6C;AAC3D,SAAO,WAAW,OAAO;AAC3B;AASO,SAAS,mBAAmB;AACjC,QAAM,SAAS,gBAAgB;AAE/B,MAAI,CAAC,QAAQ,QAAS,QAAO;AAE7B,QAAM,EAAE,OAAO,MAAM,KAAK,IAAI,OAAO;AAErC,SACE,oBAAC,SAAI,WAAU,cACb,+BAAC,SAAI,WAAU,iBACb;AAAA,yBAAC,QAAK,MAAY,WAAU,oCAC1B;AAAA,2BAAC,UAAK,WAAU,mBACd;AAAA,4BAAC,OAAG,iBAAM;AAAA,QACV,oBAAC,UAAM,gBAAK;AAAA,SACd;AAAA,MACA,oBAAC,UAAK,WAAU,oBAAmB,eAAW,MAC5C,8BAAC,OAAI,OAAO,IAAI,QAAQ,IAAI,GAC9B;AAAA,OACF;AAAA,IACA,oBAAC,iBAAc,SAAO,MAAC;AAAA,KACzB,GACF;AAEJ;","names":[]}