@elevasis/ui 2.34.0 → 2.36.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 (116) hide show
  1. package/dist/api/index.js +3 -3
  2. package/dist/app/index.d.ts +37 -30
  3. package/dist/app/index.js +25 -23
  4. package/dist/charts/index.js +3 -5
  5. package/dist/{chunk-ND5TDV2J.js → chunk-57OZ3AEG.js} +1 -1
  6. package/dist/{chunk-E4WQGJNS.js → chunk-7FPLLSHN.js} +14 -1
  7. package/dist/{chunk-RQA2EVN3.js → chunk-AKW7KISS.js} +39 -3
  8. package/dist/chunk-AUDNF2Q7.js +2050 -0
  9. package/dist/chunk-F6EFC2MJ.js +41101 -0
  10. package/dist/{chunk-TYRUKGGD.js → chunk-GX6XBRRF.js} +1 -2
  11. package/dist/{chunk-RIAXZ6AH.js → chunk-K4UZU3TU.js} +2 -2
  12. package/dist/{chunk-V6SZ4ECN.js → chunk-LUYVRATI.js} +257 -6
  13. package/dist/{chunk-DTFKWZ7A.js → chunk-O2Q4VMRN.js} +589 -932
  14. package/dist/{chunk-X4WBGKJQ.js → chunk-R3VCBZDC.js} +50 -3
  15. package/dist/chunk-SIQ3P4OR.js +1764 -0
  16. package/dist/{chunk-3FV6HBXS.js → chunk-WF7CONXF.js} +23 -23
  17. package/dist/{chunk-3QXJK5IY.js → chunk-YYX7OPZQ.js} +1 -1
  18. package/dist/components/index.d.ts +74 -71
  19. package/dist/components/index.js +20 -2795
  20. package/dist/components/navigation/index.js +25 -5
  21. package/dist/execution/index.d.ts +11 -11
  22. package/dist/execution/index.js +1 -2
  23. package/dist/features/auth/index.d.ts +3 -0
  24. package/dist/features/auth/index.js +23 -2
  25. package/dist/features/clients/index.js +20 -26
  26. package/dist/features/crm/index.d.ts +3 -0
  27. package/dist/features/crm/index.js +20 -30
  28. package/dist/features/dashboard/index.d.ts +69 -69
  29. package/dist/features/dashboard/index.js +20 -28
  30. package/dist/features/delivery/index.d.ts +3 -0
  31. package/dist/features/delivery/index.js +20 -30
  32. package/dist/features/knowledge/index.js +25 -9
  33. package/dist/features/lead-gen/index.d.ts +295 -57
  34. package/dist/features/lead-gen/index.js +20 -31
  35. package/dist/features/monitoring/index.js +20 -30
  36. package/dist/features/monitoring/requests/index.js +20 -25
  37. package/dist/features/operations/index.d.ts +183 -183
  38. package/dist/features/operations/index.js +18 -37
  39. package/dist/features/seo/index.js +3 -4
  40. package/dist/features/settings/index.d.ts +3 -0
  41. package/dist/features/settings/index.js +20 -27
  42. package/dist/graph/index.js +1 -1
  43. package/dist/hooks/delivery/index.d.ts +3 -0
  44. package/dist/hooks/delivery/index.js +30 -2
  45. package/dist/hooks/index.d.ts +112 -99
  46. package/dist/hooks/index.js +20 -21
  47. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +46 -46
  48. package/dist/hooks/published.d.ts +112 -99
  49. package/dist/hooks/published.js +20 -20
  50. package/dist/index.css +532 -532
  51. package/dist/index.d.ts +9385 -5915
  52. package/dist/index.js +22 -26
  53. package/dist/initialization/index.d.ts +3 -0
  54. package/dist/knowledge/index.d.ts +42 -42
  55. package/dist/knowledge/index.js +10 -17
  56. package/dist/{knowledge-search-index-ORIJCEZX.js → knowledge-search-index-NBCTFIOH.js} +2 -2
  57. package/dist/layout/index.js +4 -10
  58. package/dist/organization/index.js +27 -1
  59. package/dist/profile/index.d.ts +3 -0
  60. package/dist/provider/index.d.ts +72 -39
  61. package/dist/provider/index.js +20 -15
  62. package/dist/provider/published.d.ts +40 -34
  63. package/dist/provider/published.js +20 -11
  64. package/dist/sse/index.js +26 -5
  65. package/dist/supabase/index.d.ts +6 -0
  66. package/dist/test-utils/index.js +3 -3
  67. package/dist/theme/index.js +2 -3
  68. package/dist/theme/presets/index.d.ts +28 -3
  69. package/dist/theme/presets/index.js +1 -1
  70. package/dist/typeform/index.js +1 -2049
  71. package/dist/types/index.d.ts +82 -79
  72. package/dist/utils/index.d.ts +47 -47
  73. package/dist/utils/index.js +1 -1
  74. package/dist/zustand/index.d.ts +6 -6
  75. package/dist/zustand/index.js +0 -3
  76. package/package.json +5 -5
  77. package/dist/chunk-3AJVNMY5.js +0 -4769
  78. package/dist/chunk-3MEXPLWT.js +0 -265
  79. package/dist/chunk-3ZMAGTWF.js +0 -18
  80. package/dist/chunk-4O4MII5S.js +0 -4716
  81. package/dist/chunk-5EYJ2GIN.js +0 -122
  82. package/dist/chunk-7M2VOCYN.js +0 -1
  83. package/dist/chunk-BPQVTIUP.js +0 -105
  84. package/dist/chunk-BZZCNLT6.js +0 -12
  85. package/dist/chunk-CLDCYJQT.js +0 -1
  86. package/dist/chunk-E565XMTQ.js +0 -17
  87. package/dist/chunk-HRWLKKWM.js +0 -758
  88. package/dist/chunk-IGDYWFNE.js +0 -5198
  89. package/dist/chunk-IIMU5YAJ.js +0 -53
  90. package/dist/chunk-IVGI4GDL.js +0 -1593
  91. package/dist/chunk-JFL3GRD4.js +0 -39
  92. package/dist/chunk-LAWLB6CT.js +0 -951
  93. package/dist/chunk-LGKLC5MG.js +0 -44
  94. package/dist/chunk-LRWTWOGP.js +0 -1778
  95. package/dist/chunk-MP3GPBPX.js +0 -1874
  96. package/dist/chunk-N55DVMAG.js +0 -14
  97. package/dist/chunk-NLBQTDOW.js +0 -12051
  98. package/dist/chunk-O6JXQ6UQ.js +0 -468
  99. package/dist/chunk-OBBQ2JCM.js +0 -68
  100. package/dist/chunk-PDHTXPSF.js +0 -12
  101. package/dist/chunk-PLP3NYPL.js +0 -356
  102. package/dist/chunk-R2XR4FCV.js +0 -48
  103. package/dist/chunk-R66W5UDG.js +0 -26
  104. package/dist/chunk-RYTEQBAO.js +0 -37
  105. package/dist/chunk-SDXSB3HN.js +0 -425
  106. package/dist/chunk-TKAYX2SP.js +0 -204
  107. package/dist/chunk-TUMSNGTX.js +0 -35
  108. package/dist/chunk-VNAZTCHA.js +0 -65
  109. package/dist/chunk-VNFR57DF.js +0 -87
  110. package/dist/chunk-VTXTZXAU.js +0 -539
  111. package/dist/chunk-W73ZABT6.js +0 -85
  112. package/dist/chunk-WU4FNWCW.js +0 -2281
  113. package/dist/chunk-XZGSCABI.js +0 -383
  114. package/dist/chunk-YNWZIWJL.js +0 -1863
  115. /package/dist/{chunk-2RJMVWFJ.js → chunk-GEFWMU26.js} +0 -0
  116. /package/dist/{chunk-22UVE3RA.js → chunk-HENXLGVD.js} +0 -0
@@ -1,758 +0,0 @@
1
- import { StyledMarkdown } from './chunk-3KMDHCAR.js';
2
- import { useRouterContext } from './chunk-Q7DJKLEN.js';
3
- import { getErrorInfo, getErrorTitle, getResourceIcon, formatTimeAgo } from './chunk-2RJMVWFJ.js';
4
- import { ResourceStatusColors } from './chunk-KRWALB24.js';
5
- import { useAuthContext } from './chunk-BRJ3QZ4E.js';
6
- import { Center, Stack, Title, Text, Button, Box, Loader, Badge, Group, Collapse, ScrollArea, Card, Select, Alert, Code, ThemeIcon, Paper, Grid, Timeline, Space } from '@mantine/core';
7
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { IconMinus, IconTrendingUp, IconTrendingDown, IconChevronUp, IconChevronDown, IconAlertCircle, IconClock, IconInfoCircle, IconBan, IconChevronRight, IconInbox, IconHeartHandshake, IconUserOff, IconMailForward, IconBell, IconCalendarEvent, IconCalendarCancel, IconMessageReply, IconCircleCheck, IconCreditCard, IconX, IconEye, IconSend, IconFileText, IconArrowRight, IconPlus, IconActivity } from '@tabler/icons-react';
9
- import { forwardRef, useState } from 'react';
10
- import { Prism } from 'react-syntax-highlighter';
11
- import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
12
-
13
- function EmptyState({ icon: Icon, title, description, action, py = "xl" }) {
14
- return /* @__PURE__ */ jsx(Center, { py, children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: "xs", children: [
15
- /* @__PURE__ */ jsx(Icon, { size: 48, style: { opacity: 0.5 } }),
16
- /* @__PURE__ */ jsx(Title, { order: 4, children: title }),
17
- description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ta: "center", children: description }),
18
- action && /* @__PURE__ */ jsx(Button, { variant: "light", onClick: action.onClick, leftSection: action.icon, mt: "sm", children: action.label })
19
- ] }) });
20
- }
21
- function TabCountBadge({ count, isLoading }) {
22
- return /* @__PURE__ */ jsx(Box, { miw: 20, h: 20, style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: isLoading ? /* @__PURE__ */ jsx(Loader, { size: 12 }) : /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", circle: count < 10, children: count }) });
23
- }
24
- function TrendIndicator({ current, previous, inverse }) {
25
- const change = previous === 0 ? 0 : (current - previous) / previous * 100;
26
- const isPositive = inverse ? change < 0 : change > 0;
27
- const isFlat = Math.abs(change) < 0.1;
28
- const color = isFlat ? "gray" : isPositive ? "green" : "red";
29
- const Icon = isFlat ? IconMinus : change > 0 ? IconTrendingUp : IconTrendingDown;
30
- return /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
31
- /* @__PURE__ */ jsx(Icon, { size: 12 }),
32
- /* @__PURE__ */ jsx(Badge, { size: "sm", color, variant: "light", children: isFlat ? "No change" : `${isPositive ? "+" : ""}${Math.abs(change).toFixed(1)}%` })
33
- ] });
34
- }
35
- function CollapsibleSection({
36
- title,
37
- count,
38
- countLabel,
39
- children,
40
- emptyMessage,
41
- defaultExpanded = true,
42
- maxHeight = 300
43
- }) {
44
- const [expanded, setExpanded] = useState(defaultExpanded);
45
- const isEmpty = count === 0;
46
- return /* @__PURE__ */ jsxs(
47
- "div",
48
- {
49
- style: {
50
- borderRadius: "8px",
51
- padding: "8px",
52
- border: "1px solid var(--color-border)",
53
- boxShadow: "var(--standard-box-shadow)"
54
- },
55
- children: [
56
- /* @__PURE__ */ jsxs(
57
- Group,
58
- {
59
- gap: "xs",
60
- mb: expanded ? "xs" : 0,
61
- justify: "space-between",
62
- align: "center",
63
- style: { cursor: "pointer" },
64
- onClick: () => setExpanded(!expanded),
65
- children: [
66
- /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", style: { flex: 1 }, children: [
67
- typeof title === "string" ? /* @__PURE__ */ jsx(
68
- Text,
69
- {
70
- fw: 600,
71
- size: "sm",
72
- c: "var(--color-text)",
73
- style: { fontFamily: "var(--elevasis-font-family-subtitle)" },
74
- children: title
75
- }
76
- ) : title,
77
- count !== void 0 && countLabel && /* @__PURE__ */ jsxs(Badge, { size: "sm", variant: "light", color: "gray", children: [
78
- count,
79
- " ",
80
- count === 1 ? countLabel.replace(/s$/, "") : countLabel
81
- ] })
82
- ] }),
83
- expanded ? /* @__PURE__ */ jsx(IconChevronUp, { size: 16 }) : /* @__PURE__ */ jsx(IconChevronDown, { size: 16 })
84
- ]
85
- }
86
- ),
87
- /* @__PURE__ */ jsx(Collapse, { in: expanded, children: isEmpty && emptyMessage ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: emptyMessage }) : /* @__PURE__ */ jsx(ScrollArea, { h: maxHeight, type: "scroll", offsetScrollbars: true, children }) })
88
- ]
89
- }
90
- );
91
- }
92
- var PageTitleCaption = ({ title, caption, rightSection }) => {
93
- const renderCaption = () => {
94
- if (!caption) return null;
95
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Text, { style: { fontFamily: "var(--elevasis-font-family-subtitle)", color: "var(--color-text-dimmed)" }, children: caption }) });
96
- };
97
- const titleContent = /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
98
- /* @__PURE__ */ jsx(Title, { order: 1, children: title }),
99
- /* @__PURE__ */ jsx(Space, { h: "4" }),
100
- renderCaption()
101
- ] });
102
- if (!rightSection) {
103
- return titleContent;
104
- }
105
- return /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "end", children: [
106
- titleContent,
107
- rightSection
108
- ] });
109
- };
110
- function StatsCardSkeleton({ chartHeight = 200 }) {
111
- return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { mih: chartHeight, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) }) });
112
- }
113
- function ListSkeleton({ rows = 3, rowHeight = 50 }) {
114
- return /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(Center, { mih: rows * rowHeight, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) }) });
115
- }
116
- function DetailCardSkeleton({ rows = 3 }) {
117
- return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { mih: rows * 60 + 100, children: /* @__PURE__ */ jsx(Loader, { size: "md" }) }) });
118
- }
119
- function CustomSelector({
120
- value,
121
- onChange,
122
- data,
123
- leftSection,
124
- placeholder,
125
- w,
126
- withCheckIcon = false,
127
- disabled
128
- }) {
129
- return /* @__PURE__ */ jsx(
130
- Select,
131
- {
132
- value,
133
- onChange,
134
- data,
135
- leftSection,
136
- placeholder,
137
- w,
138
- size: "xs",
139
- variant: "unstyled",
140
- withCheckIcon,
141
- disabled,
142
- styles: {
143
- wrapper: {
144
- border: "1px solid var(--color-border)",
145
- borderRadius: "var(--mantine-radius-default)",
146
- backgroundColor: "var(--color-surface)",
147
- transition: "border-color 150ms ease, background-color 150ms ease",
148
- "&:hover": {
149
- borderColor: "var(--color-border-hover, var(--mantine-color-dark-3))"
150
- }
151
- },
152
- input: {
153
- fontSize: "var(--mantine-font-size-xs)",
154
- fontWeight: 500,
155
- height: "30px",
156
- minHeight: "30px",
157
- paddingLeft: leftSection ? "30px" : void 0,
158
- borderRadius: "var(--mantine-radius-default)",
159
- cursor: "pointer"
160
- },
161
- section: {
162
- color: "var(--color-text-subtle)"
163
- },
164
- dropdown: {
165
- border: "1px solid var(--color-border)",
166
- backgroundColor: "var(--color-surface)",
167
- boxShadow: "var(--card-shadow)"
168
- },
169
- option: {
170
- fontSize: "var(--mantine-font-size-xs)"
171
- }
172
- }
173
- }
174
- );
175
- }
176
- function APIErrorAlert({
177
- error,
178
- title,
179
- showRequestId = true,
180
- icon = /* @__PURE__ */ jsx(IconAlertCircle, {}),
181
- color = "red"
182
- }) {
183
- const { message, code, requestId, retryAfter } = getErrorInfo(error);
184
- const alertTitle = title || getErrorTitle(code);
185
- return /* @__PURE__ */ jsxs(Alert, { icon, title: alertTitle, color, variant: "light", children: [
186
- /* @__PURE__ */ jsx(Text, { size: "sm", children: message }),
187
- retryAfter && /* @__PURE__ */ jsxs(Text, { size: "sm", mt: "xs", children: [
188
- "Please wait ",
189
- retryAfter,
190
- " seconds before retrying."
191
- ] }),
192
- showRequestId && requestId && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mt: "xs", children: [
193
- "Request ID: ",
194
- /* @__PURE__ */ jsx(Code, { children: requestId })
195
- ] })
196
- ] });
197
- }
198
- function CenteredErrorState({ error, title, h = 300, py }) {
199
- return /* @__PURE__ */ jsx(Center, { h, py, children: /* @__PURE__ */ jsx(APIErrorAlert, { error, title }) });
200
- }
201
-
202
- // src/components/display/StatCard.module.css.js
203
- var StatCard_module_css_default = { "heroCard": "heroCard", "iconRing": "iconRing", "iconRingSm": "iconRingSm", "heroValue": "heroValue", "heroValueSm": "heroValueSm", "heroLabel": "heroLabel", "heroLabelSm": "heroLabelSm" };
204
- function StatCard(props) {
205
- if (props.variant === "hero") {
206
- return /* @__PURE__ */ jsx(HeroStatCard, { ...props });
207
- }
208
- const { label, value, icon: IconComponent, color } = props;
209
- return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
210
- /* @__PURE__ */ jsx(ThemeIcon, { size: "lg", variant: "light", color, children: /* @__PURE__ */ jsx(IconComponent, { size: 18 }) }),
211
- /* @__PURE__ */ jsxs("div", { children: [
212
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: label }),
213
- /* @__PURE__ */ jsx(Text, { size: "lg", fw: 600, style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, children: value })
214
- ] })
215
- ] }) });
216
- }
217
- function HeroStatCard({
218
- icon: IconComponent,
219
- value,
220
- label,
221
- valueColor,
222
- isLoading,
223
- size = "sm",
224
- children
225
- }) {
226
- const sm = size === "sm";
227
- const iconSize = sm ? 36 : 46;
228
- if (isLoading) {
229
- return /* @__PURE__ */ jsx(Paper, { p: sm ? "md" : "lg", className: StatCard_module_css_default.heroCard, children: /* @__PURE__ */ jsx(Center, { mih: iconSize + 16, children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) });
230
- }
231
- return /* @__PURE__ */ jsx(Paper, { p: sm ? "md" : "lg", className: StatCard_module_css_default.heroCard, children: /* @__PURE__ */ jsxs(Group, { gap: sm ? "sm" : "md", wrap: "nowrap", children: [
232
- /* @__PURE__ */ jsx("div", { className: sm ? StatCard_module_css_default.iconRingSm : StatCard_module_css_default.iconRing, children: /* @__PURE__ */ jsx(IconComponent, { size: sm ? 18 : 22 }) }),
233
- /* @__PURE__ */ jsxs(Stack, { gap: 2, style: { flex: children ? 1 : void 0 }, children: [
234
- /* @__PURE__ */ jsx(
235
- "span",
236
- {
237
- className: sm ? StatCard_module_css_default.heroValueSm : StatCard_module_css_default.heroValue,
238
- style: valueColor ? { color: valueColor } : void 0,
239
- children: value
240
- }
241
- ),
242
- children ? /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", style: { flex: 1 }, children: [
243
- /* @__PURE__ */ jsx("span", { className: sm ? StatCard_module_css_default.heroLabelSm : StatCard_module_css_default.heroLabel, children: label }),
244
- /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children })
245
- ] }) : /* @__PURE__ */ jsx("span", { className: sm ? StatCard_module_css_default.heroLabelSm : StatCard_module_css_default.heroLabel, children: label })
246
- ] })
247
- ] }) });
248
- }
249
- function StatCardSkeleton() {
250
- return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { mih: 60, children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) });
251
- }
252
- var jsonTheme = Object.fromEntries(
253
- Object.entries(oneDark).map(([key, value]) => [
254
- key,
255
- typeof value === "object" && value !== null ? { ...value, background: "none", backgroundColor: "none" } : value
256
- ])
257
- );
258
- function JsonViewer({ data, maxHeight, fontSize = "0.8rem" }) {
259
- const jsonString = typeof data === "string" ? data : JSON.stringify(data, null, 2);
260
- return /* @__PURE__ */ jsx(
261
- Prism,
262
- {
263
- language: "json",
264
- style: jsonTheme,
265
- customStyle: {
266
- margin: 0,
267
- fontSize,
268
- maxHeight,
269
- overflow: maxHeight ? "auto" : void 0,
270
- overflowX: "auto"
271
- },
272
- children: jsonString
273
- }
274
- );
275
- }
276
- var subtleMarkdownComponents = {
277
- p: ({ children }) => /* @__PURE__ */ jsx(Text, { size: "sm", m: 0, c: "var(--color-text-subtle)", style: { whiteSpace: "pre-wrap" }, children })
278
- };
279
- var subtleMarkdownWrapperStyle = {
280
- display: "flex",
281
- flexDirection: "column",
282
- gap: 8
283
- };
284
- function ContextViewer({ data }) {
285
- return /* @__PURE__ */ jsx(ContextNode, { data, depth: 0 });
286
- }
287
- function ContextNode({ data, depth }) {
288
- if (data === null || data === void 0) {
289
- return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", fs: "italic", children: "No context provided" });
290
- }
291
- if (typeof data === "string") {
292
- return /* @__PURE__ */ jsx(StyledMarkdown, { components: subtleMarkdownComponents, style: subtleMarkdownWrapperStyle, children: data });
293
- }
294
- if (typeof data === "number" || typeof data === "boolean") {
295
- return /* @__PURE__ */ jsx(Text, { size: "sm", children: String(data) });
296
- }
297
- if (Array.isArray(data)) {
298
- return /* @__PURE__ */ jsx(ArrayView, { items: data, depth });
299
- }
300
- if (typeof data === "object") {
301
- return /* @__PURE__ */ jsx(ObjectView, { data, depth });
302
- }
303
- return /* @__PURE__ */ jsx(Text, { size: "sm", children: String(data) });
304
- }
305
- var ACRONYMS = ["AI", "URL", "UUID", "ID", "API", "HTTP", "JSON"];
306
- function formatLabel(key) {
307
- const titleCased = key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
308
- return titleCased.replace(
309
- new RegExp(`\\b(${ACRONYMS.map((a) => a[0] + a.slice(1).toLowerCase()).join("|")})\\b`, "g"),
310
- (match) => match.toUpperCase()
311
- );
312
- }
313
- function hasMarkdown(value) {
314
- return /(\*\*.+\*\*|^#{1,6}\s|^\s*[-*]\s|\[.+\]\(.+\)|^\|.+\|$|^>\s|```)/.test(value);
315
- }
316
- function NestedSection({ title, children }) {
317
- const [expanded, setExpanded] = useState(true);
318
- return /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
319
- /* @__PURE__ */ jsxs(Group, { gap: 4, style: { cursor: "pointer", userSelect: "none" }, onClick: () => setExpanded((v) => !v), children: [
320
- expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14, color: "var(--color-primary)", style: { flexShrink: 0 } }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14, color: "var(--color-primary)", style: { flexShrink: 0 } }),
321
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: title })
322
- ] }),
323
- expanded && /* @__PURE__ */ jsx(Box, { pl: "sm", style: { borderLeft: "2px solid var(--color-border)" }, children })
324
- ] });
325
- }
326
- function PrimitiveValue({ value }) {
327
- if (value === null || value === void 0) {
328
- return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", fs: "italic", children: "\u2014" });
329
- }
330
- if (typeof value === "boolean") {
331
- return /* @__PURE__ */ jsx(Text, { size: "sm", m: 0, children: value ? "Yes" : "No" });
332
- }
333
- if (typeof value === "number") {
334
- return /* @__PURE__ */ jsx(Text, { size: "sm", m: 0, children: value.toLocaleString() });
335
- }
336
- const str = String(value);
337
- if (hasMarkdown(str)) {
338
- return /* @__PURE__ */ jsx(StyledMarkdown, { components: subtleMarkdownComponents, children: str });
339
- }
340
- return /* @__PURE__ */ jsx(Text, { size: "sm", m: 0, c: "var(--color-text-subtle)", style: { whiteSpace: "pre-wrap" }, children: str });
341
- }
342
- function ArrayView({ items, depth }) {
343
- if (items.length === 0) {
344
- return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", fs: "italic", children: "Empty list" });
345
- }
346
- const allPrimitive = items.every((item) => typeof item !== "object" || item === null);
347
- if (allPrimitive) {
348
- return /* @__PURE__ */ jsx(Stack, { gap: 2, children: items.map((item, i) => /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "flex-start", children: [
349
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { userSelect: "none" }, children: "\u2022" }),
350
- /* @__PURE__ */ jsx(PrimitiveValue, { value: item })
351
- ] }, i)) });
352
- }
353
- return /* @__PURE__ */ jsx(Stack, { gap: "sm", children: items.map((item, i) => /* @__PURE__ */ jsx(Paper, { p: "sm", style: { border: "1px solid var(--color-border)" }, children: /* @__PURE__ */ jsx(ContextNode, { data: item, depth: depth + 1 }) }, i)) });
354
- }
355
- function ObjectView({ data, depth }) {
356
- const entries = Object.entries(data);
357
- if (entries.length === 0) {
358
- return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", fs: "italic", children: "Empty" });
359
- }
360
- const simpleEntries = [];
361
- const complexEntries = [];
362
- for (const [key, value] of entries) {
363
- if (value === null || value === void 0 || typeof value === "boolean" || typeof value === "number") {
364
- simpleEntries.push([key, value]);
365
- } else if (typeof value === "string") {
366
- if (hasMarkdown(value) || value.length > 120) {
367
- complexEntries.push([key, value]);
368
- } else {
369
- simpleEntries.push([key, value]);
370
- }
371
- } else {
372
- complexEntries.push([key, value]);
373
- }
374
- }
375
- return /* @__PURE__ */ jsxs(Stack, { gap: 10, children: [
376
- simpleEntries.length > 0 && /* @__PURE__ */ jsx(Stack, { gap: 6, children: simpleEntries.map(([key, value]) => /* @__PURE__ */ jsxs(Group, { gap: "sm", align: "flex-start", wrap: "nowrap", children: [
377
- /* @__PURE__ */ jsx(
378
- Text,
379
- {
380
- size: "sm",
381
- style: { minWidth: 140, flexShrink: 0, fontFamily: "var(--mantine-font-family-headings)" },
382
- children: formatLabel(key)
383
- }
384
- ),
385
- /* @__PURE__ */ jsx(PrimitiveValue, { value })
386
- ] }, key)) }),
387
- complexEntries.map(([key, value]) => /* @__PURE__ */ jsx(NestedSection, { title: formatLabel(key), children: /* @__PURE__ */ jsx(ContextNode, { data: value, depth: depth + 1 }) }, key))
388
- ] });
389
- }
390
- var TIME_RANGE_OPTIONS = [
391
- { value: "1h", label: "Last 1 hour" },
392
- { value: "24h", label: "Last 24 hours" },
393
- { value: "7d", label: "Last 7 days" },
394
- { value: "30d", label: "Last 30 days" }
395
- ];
396
- function TimeRangeSelector({ value, onChange, width = 180 }) {
397
- return /* @__PURE__ */ jsx(
398
- CustomSelector,
399
- {
400
- value,
401
- onChange: (newValue) => newValue && onChange(newValue),
402
- data: TIME_RANGE_OPTIONS,
403
- leftSection: /* @__PURE__ */ jsx(IconClock, { size: 16, color: "var(--color-text-subtle)" }),
404
- w: width,
405
- withCheckIcon: true
406
- }
407
- );
408
- }
409
- function PageNotFound() {
410
- const { currentPath, navigate } = useRouterContext();
411
- const { user, isLoading } = useAuthContext();
412
- const isAuthPage = currentPath === "/login" || currentPath === "/auth-redirect";
413
- const shouldShowSidebar = user && !isLoading && !isAuthPage;
414
- const height = shouldShowSidebar ? "100%" : "100vh";
415
- return /* @__PURE__ */ jsx(Center, { h: height, bg: "var(--color-background)", children: /* @__PURE__ */ jsxs(Stack, { align: "center", justify: "center", children: [
416
- /* @__PURE__ */ jsx(IconInfoCircle, { size: 60, color: "var(--color-text-subtle)" }),
417
- /* @__PURE__ */ jsx(Title, { order: 1, children: "Page Not Found" }),
418
- /* @__PURE__ */ jsx(Text, { c: "dimmed", size: "lg", children: "The page you are looking for does not exist." }),
419
- /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(Button, { size: "md", onClick: () => navigate("/"), children: "Go Home" }) })
420
- ] }) });
421
- }
422
- function FeatureUnavailableState({ path }) {
423
- const { navigate } = useRouterContext();
424
- return /* @__PURE__ */ jsx(
425
- Center,
426
- {
427
- style: {
428
- flex: 1,
429
- minHeight: "100%",
430
- width: "100%",
431
- padding: 24,
432
- background: "linear-gradient(180deg, color-mix(in srgb, var(--color-surface) 72%, transparent), transparent)"
433
- },
434
- children: /* @__PURE__ */ jsxs(
435
- Stack,
436
- {
437
- align: "center",
438
- gap: "md",
439
- style: {
440
- maxWidth: 560,
441
- padding: "32px 28px",
442
- borderRadius: 24,
443
- border: "1px solid var(--color-border)",
444
- background: "color-mix(in srgb, var(--glass-background) 86%, transparent)",
445
- boxShadow: "var(--card-shadow)",
446
- backdropFilter: "var(--glass-blur)",
447
- textAlign: "center"
448
- },
449
- children: [
450
- /* @__PURE__ */ jsx(IconBan, { size: 44, stroke: 1.8, color: "var(--color-text-subtle)" }),
451
- /* @__PURE__ */ jsxs(Stack, { gap: 6, align: "center", children: [
452
- /* @__PURE__ */ jsx(Title, { order: 2, children: "This section is unavailable" }),
453
- /* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", maw: 420, children: path ? `The requested route ${path} is currently disabled in this workspace.` : "The requested subsection is currently disabled in this workspace." })
454
- ] }),
455
- /* @__PURE__ */ jsx(Group, { gap: "sm", justify: "center", children: /* @__PURE__ */ jsx(Button, { onClick: () => navigate("/"), children: "Go home" }) })
456
- ]
457
- }
458
- )
459
- }
460
- );
461
- }
462
- function ResourceCard({
463
- resource,
464
- onClick,
465
- layout = "stack",
466
- rightSection,
467
- topSection,
468
- lastRunLabel,
469
- style,
470
- ...rest
471
- }) {
472
- const Icon = getResourceIcon(resource.type);
473
- if (!Icon) {
474
- return /* @__PURE__ */ jsx(Card, { shadow: "sm", withBorder: true, children: /* @__PURE__ */ jsxs(Text, { children: [
475
- "Invalid resource type: ",
476
- resource.type
477
- ] }) });
478
- }
479
- const cardStyle = {
480
- cursor: "pointer",
481
- ...layout === "grid" || layout === "card" ? { transition: "box-shadow var(--duration-fast) var(--easing)" } : {},
482
- ...style
483
- };
484
- const iconSize = layout === "grid" ? 28 : 20;
485
- const details = /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
486
- /* @__PURE__ */ jsx(Icon, { size: iconSize, color: "var(--color-primary)" }),
487
- /* @__PURE__ */ jsxs(Stack, { gap: 4, style: { flex: 1, minWidth: 0 }, children: [
488
- /* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", children: [
489
- /* @__PURE__ */ jsx(
490
- Text,
491
- {
492
- fw: 600,
493
- size: "sm",
494
- style: { fontFamily: "var(--elevasis-font-family-subtitle)" },
495
- ...layout === "stack" ? { lineClamp: 1 } : { truncate: true },
496
- children: resource.name
497
- }
498
- ),
499
- /* @__PURE__ */ jsx(Badge, { variant: "light", size: layout === "grid" ? "xs" : "sm", children: resource.type })
500
- ] }),
501
- resource.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", ...layout === "stack" ? { lineClamp: 1 } : { truncate: true }, children: resource.description }),
502
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
503
- resource.version && /* @__PURE__ */ jsxs(Badge, { variant: "outline", size: "xs", children: [
504
- "v",
505
- resource.version
506
- ] }),
507
- /* @__PURE__ */ jsx(Badge, { color: ResourceStatusColors[resource.status], variant: "outline", size: layout === "grid" ? "xs" : "sm", children: resource.status.toUpperCase() })
508
- ] }),
509
- lastRunLabel && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: lastRunLabel }),
510
- /* @__PURE__ */ jsx(Text, { size: layout === "grid" ? "sm" : "xs", c: "dimmed", ff: "monospace", children: resource.resourceId })
511
- ] })
512
- ] });
513
- if (layout === "card") {
514
- return /* @__PURE__ */ jsx(
515
- Card,
516
- {
517
- withBorder: true,
518
- padding: 0,
519
- style: cardStyle,
520
- onClick: () => onClick(resource),
521
- "data-resource-id": rest["data-resource-id"],
522
- children: /* @__PURE__ */ jsxs(Stack, { gap: 8, p: "sm", pb: "xs", children: [
523
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", justify: "space-between", children: [
524
- /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 0 }, children: [
525
- /* @__PURE__ */ jsx(Icon, { size: 20, color: "var(--color-primary)", style: { flexShrink: 0 } }),
526
- /* @__PURE__ */ jsx(Text, { fw: 600, size: "md", style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, truncate: true, children: resource.name })
527
- ] }),
528
- /* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", style: { flexShrink: 0 }, children: [
529
- resource.version && /* @__PURE__ */ jsxs(Badge, { variant: "light", size: "sm", children: [
530
- "v",
531
- resource.version
532
- ] }),
533
- /* @__PURE__ */ jsx(Badge, { color: ResourceStatusColors[resource.status], variant: "light", size: "sm", children: resource.status.toUpperCase() })
534
- ] })
535
- ] }),
536
- resource.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", truncate: true, children: resource.description }),
537
- /* @__PURE__ */ jsxs(Group, { gap: "xs", justify: "space-between", wrap: "nowrap", children: [
538
- rightSection || /* @__PURE__ */ jsx("span", {}),
539
- lastRunLabel && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { whiteSpace: "nowrap" }, children: lastRunLabel })
540
- ] }),
541
- topSection
542
- ] })
543
- }
544
- );
545
- }
546
- if (layout === "row") {
547
- const [hovered, setHovered] = useState(false);
548
- return /* @__PURE__ */ jsx(
549
- Card,
550
- {
551
- padding: 0,
552
- style: {
553
- cursor: "pointer",
554
- border: "1px solid var(--color-border)",
555
- transition: "background 150ms ease",
556
- background: hovered ? "var(--active-background)" : "var(--color-surface)",
557
- ...style
558
- },
559
- onClick: () => onClick(resource),
560
- onMouseEnter: () => setHovered(true),
561
- onMouseLeave: () => setHovered(false),
562
- "data-resource-id": rest["data-resource-id"],
563
- children: /* @__PURE__ */ jsxs(
564
- "div",
565
- {
566
- style: {
567
- display: "grid",
568
- gridTemplateColumns: "18px 200px 120px 1fr 180px 200px 14px",
569
- alignItems: "center",
570
- gap: "var(--mantine-spacing-sm)"
571
- },
572
- children: [
573
- /* @__PURE__ */ jsx(Icon, { size: 18, color: "var(--color-primary)" }),
574
- /* @__PURE__ */ jsx(Text, { fw: 600, size: "md", truncate: true, style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, children: resource.name }),
575
- /* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
576
- resource.version && /* @__PURE__ */ jsxs(Badge, { variant: "light", size: "sm", children: [
577
- "v",
578
- resource.version
579
- ] }),
580
- /* @__PURE__ */ jsx(Badge, { color: ResourceStatusColors[resource.status], variant: "light", size: "sm", children: resource.status.toUpperCase() })
581
- ] }),
582
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", truncate: true, style: { minWidth: 0 }, children: resource.description || "" }),
583
- /* @__PURE__ */ jsx("div", { style: { whiteSpace: "nowrap" }, children: rightSection }),
584
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { whiteSpace: "nowrap", textAlign: "right" }, children: lastRunLabel || "" }),
585
- /* @__PURE__ */ jsx(
586
- IconChevronRight,
587
- {
588
- size: 14,
589
- style: {
590
- opacity: hovered ? 0.7 : 0,
591
- transition: "opacity 150ms ease"
592
- }
593
- }
594
- )
595
- ]
596
- }
597
- )
598
- }
599
- );
600
- }
601
- if (layout === "grid") {
602
- return /* @__PURE__ */ jsx(
603
- Card,
604
- {
605
- withBorder: true,
606
- padding: "sm",
607
- style: cardStyle,
608
- onClick: () => onClick(resource),
609
- "data-resource-id": rest["data-resource-id"],
610
- children: /* @__PURE__ */ jsxs(Grid, { gutter: "sm", align: "center", children: [
611
- /* @__PURE__ */ jsx(Grid.Col, { span: 8, children: details }),
612
- rightSection && /* @__PURE__ */ jsx(Grid.Col, { span: 4, children: /* @__PURE__ */ jsx(Group, { justify: "flex-end", gap: "md", wrap: "nowrap", children: rightSection }) })
613
- ] })
614
- }
615
- );
616
- }
617
- return /* @__PURE__ */ jsx(
618
- Card,
619
- {
620
- shadow: "sm",
621
- withBorder: true,
622
- style: cardStyle,
623
- onClick: () => onClick(resource),
624
- "data-resource-id": rest["data-resource-id"],
625
- children: /* @__PURE__ */ jsx(Stack, { children: details })
626
- }
627
- );
628
- }
629
- function CardHeader({
630
- icon,
631
- title,
632
- subtitle,
633
- rightSection,
634
- titleOrder = 3,
635
- iconColor,
636
- mb = "md"
637
- }) {
638
- const wrappedIcon = icon ? /* @__PURE__ */ jsx(ThemeIcon, { size: "md", variant: "light", color: iconColor, children: icon }) : null;
639
- return /* @__PURE__ */ jsxs(Group, { justify: "space-between", mb, gap: "md", align: "flex-start", wrap: "nowrap", children: [
640
- subtitle ? /* @__PURE__ */ jsxs(Box, { style: { minWidth: 0 }, children: [
641
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
642
- wrappedIcon,
643
- /* @__PURE__ */ jsx(Title, { order: titleOrder, style: { overflowWrap: "anywhere" }, children: title })
644
- ] }),
645
- /* @__PURE__ */ jsx(Text, { size: "sm", mt: 2, style: { color: "var(--color-text-dimmed)", overflowWrap: "anywhere" }, children: subtitle })
646
- ] }) : /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
647
- wrappedIcon,
648
- /* @__PURE__ */ jsx(Title, { order: titleOrder, style: { overflowWrap: "anywhere" }, children: title })
649
- ] }),
650
- rightSection
651
- ] });
652
- }
653
-
654
- // src/components/display/ElevasisLoader.module.css.js
655
- var ElevasisLoader_module_css_default = { "wrapper": "wrapper", "loader": "loader", "chevron": "chevron", "c1": "c1", "c2": "c2", "c3": "c3" };
656
- var ElevasisLoader = forwardRef(({ style, className, ...others }, ref) => /* @__PURE__ */ jsx("div", { ref, style, className: `${ElevasisLoader_module_css_default.wrapper} ${className ?? ""}`, ...others, children: /* @__PURE__ */ jsxs("svg", { className: ElevasisLoader_module_css_default.loader, viewBox: "-10 -5 60 50", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
657
- /* @__PURE__ */ jsx("polyline", { className: `${ElevasisLoader_module_css_default.chevron} ${ElevasisLoader_module_css_default.c1}`, points: "5,36 20,25 35,36" }),
658
- /* @__PURE__ */ jsx("polyline", { className: `${ElevasisLoader_module_css_default.chevron} ${ElevasisLoader_module_css_default.c2}`, points: "9,23 20,14 31,23" }),
659
- /* @__PURE__ */ jsx("polyline", { className: `${ElevasisLoader_module_css_default.chevron} ${ElevasisLoader_module_css_default.c3}`, points: "13,11 20,5 27,11" })
660
- ] }) }));
661
- ElevasisLoader.displayName = "ElevasisLoader";
662
- var SIZE_MAP = {
663
- sm: { dot: 7, inner: 6, outer: 12 },
664
- md: { dot: 10, inner: 8, outer: 16 },
665
- lg: { dot: 12, inner: 10, outer: 20 }
666
- };
667
- function GlowDot({ color, size = "md" }) {
668
- const { dot, inner, outer } = SIZE_MAP[size];
669
- return /* @__PURE__ */ jsx(
670
- "div",
671
- {
672
- style: {
673
- width: dot,
674
- height: dot,
675
- borderRadius: "50%",
676
- backgroundColor: color,
677
- boxShadow: `0 0 ${inner}px ${color}, 0 0 ${outer}px ${color}40`,
678
- flexShrink: 0
679
- }
680
- }
681
- );
682
- }
683
- var STATUS_COLORS = {
684
- // Project
685
- active: "blue",
686
- on_track: "green",
687
- at_risk: "yellow",
688
- blocked: "red",
689
- completed: "teal",
690
- paused: "gray",
691
- // Milestone
692
- upcoming: "gray",
693
- in_progress: "blue",
694
- overdue: "red",
695
- // Task
696
- pending: "gray",
697
- planned: "gray",
698
- submitted: "yellow",
699
- approved: "green",
700
- rejected: "red",
701
- revision_requested: "orange",
702
- cancelled: "gray",
703
- // Note
704
- call_note: "blue",
705
- status_update: "green",
706
- issue: "yellow",
707
- blocker: "red",
708
- agent_learning: "grape"
709
- };
710
- function StatusBadge({ status, ...props }) {
711
- const label = status.split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
712
- return /* @__PURE__ */ jsx(Badge, { variant: "light", color: STATUS_COLORS[status] || "gray", size: "sm", ...props, children: label });
713
- }
714
- var ICON_MAP = {
715
- deal_created: IconPlus,
716
- stage_change: IconArrowRight,
717
- discovery_submitted: IconFileText,
718
- proposal_generated: IconFileText,
719
- proposal_sent: IconSend,
720
- proposal_reviewed: IconEye,
721
- closed_lost: IconX,
722
- fees_updated: IconCreditCard,
723
- closed_won: IconCircleCheck,
724
- reply_received: IconMessageReply,
725
- booking_cancelled: IconCalendarCancel,
726
- booking_rescheduled: IconCalendarEvent,
727
- reminder_sent: IconBell,
728
- reply_sent_to_lead: IconMailForward,
729
- followup_email_sent: IconMailForward,
730
- no_show: IconUserOff,
731
- moved_to_nurturing: IconHeartHandshake
732
- };
733
- function ActivityTimeline({ activities }) {
734
- if (!activities.length) {
735
- return /* @__PURE__ */ jsx(EmptyState, { icon: IconInbox, title: "No activity events yet" });
736
- }
737
- const sorted = [...activities].reverse();
738
- return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Timeline, { active: sorted.length - 1, bulletSize: 28, lineWidth: 2, color: "var(--color-primary)", children: sorted.map((activity, index) => {
739
- const Icon = ICON_MAP[activity.type] || IconActivity;
740
- return /* @__PURE__ */ jsx(
741
- Timeline.Item,
742
- {
743
- bullet: /* @__PURE__ */ jsx(ThemeIcon, { size: 28, variant: "filled", color: "var(--color-primary)", radius: "xl", children: /* @__PURE__ */ jsx(Icon, { size: 14 }) }),
744
- children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
745
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: activity.title }),
746
- activity.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: activity.description }),
747
- /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
748
- formatTimeAgo(activity.occurredAt),
749
- activity.actor && ` by ${activity.actor}`
750
- ] })
751
- ] })
752
- },
753
- index
754
- );
755
- }) }) });
756
- }
757
-
758
- export { APIErrorAlert, ActivityTimeline, CardHeader, CenteredErrorState, CollapsibleSection, ContextViewer, CustomSelector, DetailCardSkeleton, ElevasisLoader, EmptyState, FeatureUnavailableState, GlowDot, JsonViewer, ListSkeleton, PageNotFound, PageTitleCaption, ResourceCard, StatCard, StatCardSkeleton, StatsCardSkeleton, StatusBadge, TabCountBadge, TimeRangeSelector, TrendIndicator };