@xenide-io/the-old-ui-theme 0.2.3

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.
@@ -0,0 +1,3913 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ Accordion: () => Accordion,
24
+ Alert: () => Alert,
25
+ Avatar: () => Avatar,
26
+ AvatarGroup: () => AvatarGroup,
27
+ Badge: () => Badge,
28
+ Breadcrumbs: () => Breadcrumbs,
29
+ Button: () => Button,
30
+ ButtonChrome: () => ButtonChrome,
31
+ Calendar: () => Calendar,
32
+ Caption: () => Caption,
33
+ Card: () => Card,
34
+ ChatBubble: () => ChatBubble,
35
+ Checkbox: () => Checkbox,
36
+ CodeBlock: () => CodeBlock,
37
+ CollapsibleSection: () => CollapsibleSection,
38
+ CommandPalette: () => CommandPalette,
39
+ ComponentDocs: () => ComponentDocs,
40
+ DEFAULT_THEME_ID: () => DEFAULT_THEME_ID,
41
+ DashboardFiltersBar: () => DashboardFiltersBar,
42
+ DashboardGrid: () => DashboardGrid,
43
+ DashboardInsightPlaceholder: () => DashboardInsightPlaceholder,
44
+ DashboardKpiCard: () => DashboardKpiCard,
45
+ DashboardToolbar: () => DashboardToolbar,
46
+ DashboardWell: () => DashboardWell,
47
+ Display: () => Display,
48
+ Drawer: () => Drawer,
49
+ DropdownButton: () => DropdownButton,
50
+ DropdownItem: () => DropdownItem,
51
+ DropdownMenu: () => DropdownMenu,
52
+ EmptyState: () => EmptyState,
53
+ FileUpload: () => FileUpload,
54
+ FilterChips: () => FilterChips,
55
+ H1: () => H1,
56
+ H2: () => H2,
57
+ H3: () => H3,
58
+ H4: () => H4,
59
+ H5: () => H5,
60
+ HogTrendLineChart: () => HogTrendLineChart,
61
+ HoverCard: () => HoverCard,
62
+ Icon: () => IconBase,
63
+ IconActivity: () => IconActivity,
64
+ IconAreaChart: () => IconAreaChart,
65
+ IconArrowDown: () => IconArrowDown,
66
+ IconArrowUp: () => IconArrowUp,
67
+ IconBase: () => IconBase,
68
+ IconBell: () => IconBell,
69
+ IconBellOff: () => IconBellOff,
70
+ IconBolt: () => IconBolt,
71
+ IconBox: () => IconBox,
72
+ IconByName: () => IconByName,
73
+ IconCancel: () => IconCancel,
74
+ IconCheck: () => IconCheck,
75
+ IconCheckCircle: () => IconCheckCircle,
76
+ IconChevronDown: () => IconChevronDown,
77
+ IconChevronLeft: () => IconChevronLeft,
78
+ IconChevronRight: () => IconChevronRight,
79
+ IconClipboardEdit: () => IconClipboardEdit,
80
+ IconClose: () => IconClose,
81
+ IconCohort: () => IconCohort,
82
+ IconCopy: () => IconCopy,
83
+ IconCumulativeChart: () => IconCumulativeChart,
84
+ IconDatabase: () => IconDatabase,
85
+ IconDownload: () => IconDownload,
86
+ IconEdit: () => IconEdit,
87
+ IconErrorOutline: () => IconErrorOutline,
88
+ IconExclamation: () => IconExclamation,
89
+ IconFlag: () => IconFlag,
90
+ IconFlare: () => IconFlare,
91
+ IconFlask: () => IconFlask,
92
+ IconGift: () => IconGift,
93
+ IconGridView: () => IconGridView,
94
+ IconHandClick: () => IconHandClick,
95
+ IconHome: () => IconHome,
96
+ IconLayers: () => IconLayers,
97
+ IconListView: () => IconListView,
98
+ IconLogout: () => IconLogout,
99
+ IconMail: () => IconMail,
100
+ IconMoon: () => IconMoon,
101
+ IconPanelRight: () => IconPanelRight,
102
+ IconPerson: () => IconPerson,
103
+ IconPlayCircle: () => IconPlayCircle,
104
+ IconPlus: () => IconPlus,
105
+ IconPremium: () => IconPremium,
106
+ IconQueryEditor: () => IconQueryEditor,
107
+ IconRadar: () => IconRadar,
108
+ IconRecording: () => IconRecording,
109
+ IconRobot: () => IconRobot,
110
+ IconRocket: () => IconRocket,
111
+ IconSave: () => IconSave,
112
+ IconSearch: () => IconSearch,
113
+ IconSelectEvents: () => IconSelectEvents,
114
+ IconShoppingCart: () => IconShoppingCart,
115
+ IconSpinner: () => IconSpinner,
116
+ IconStar: () => IconStar,
117
+ IconSubArrowRight: () => IconSubArrowRight,
118
+ IconSun: () => IconSun,
119
+ IconSurveys: () => IconSurveys,
120
+ IconSync: () => IconSync,
121
+ IconTableChart: () => IconTableChart,
122
+ IconTerminal: () => IconTerminal,
123
+ IconToggle: () => IconToggle,
124
+ IconTrash: () => IconTrash,
125
+ IconTuning: () => IconTuning,
126
+ IconUpload: () => IconUpload,
127
+ IconVolume: () => IconVolume,
128
+ IconVolumeOff: () => IconVolumeOff,
129
+ Indicator: () => Indicator,
130
+ Input: () => Input,
131
+ InsightDoughnutChart: () => InsightDoughnutChart,
132
+ InsightHorizontalBarChart: () => InsightHorizontalBarChart,
133
+ InsightMiniCard: () => InsightMiniCard,
134
+ InsightPolarAreaChart: () => InsightPolarAreaChart,
135
+ InsightShell: () => InsightShell,
136
+ InsightShellHeader: () => InsightShellHeader,
137
+ InsightStackedBarChart: () => InsightStackedBarChart,
138
+ InsightVerticalBarChart: () => InsightVerticalBarChart,
139
+ Kbd: () => Kbd,
140
+ Label: () => Label,
141
+ Lead: () => Lead,
142
+ MiniTrendBars: () => MiniTrendBars,
143
+ Modal: () => Modal,
144
+ Mono: () => Mono,
145
+ Overline: () => Overline,
146
+ P: () => P,
147
+ PH_ICONS: () => PH_ICONS,
148
+ Pagination: () => Pagination,
149
+ Panel: () => Panel,
150
+ Progress: () => Progress,
151
+ Radio: () => Radio,
152
+ Range: () => Range,
153
+ Rating: () => Rating,
154
+ SearchGroup: () => SearchGroup,
155
+ SearchInput: () => SearchInput,
156
+ SegmentedControl: () => SegmentedControl,
157
+ Select: () => Select,
158
+ ShowcaseWrapper: () => ShowcaseWrapper,
159
+ Small: () => Small,
160
+ Stat: () => Stat,
161
+ Stepper: () => Stepper,
162
+ THEMES: () => THEMES,
163
+ THEME_GROUPS: () => THEME_GROUPS,
164
+ THEME_INIT_SCRIPT: () => THEME_INIT_SCRIPT,
165
+ Table: () => Table,
166
+ Tabs: () => Tabs,
167
+ Terminal: () => Terminal,
168
+ Textarea: () => Textarea,
169
+ ThemeDomSync: () => ThemeDomSync,
170
+ ThemeManager: () => ThemeManager,
171
+ ThemeSwitcher: () => ThemeSwitcher,
172
+ Timeline: () => Timeline,
173
+ Toast: () => Toast,
174
+ ToastStack: () => ToastStack,
175
+ Toggle: () => Toggle,
176
+ createIconBase: () => createIconBase,
177
+ createIconBasePath: () => createIconBasePath,
178
+ getTheme: () => getTheme,
179
+ isThemeId: () => isThemeId,
180
+ persistTheme: () => persistTheme,
181
+ readStoredTheme: () => readStoredTheme
182
+ });
183
+ module.exports = __toCommonJS(src_exports);
184
+
185
+ // src/components/ui/ButtonChrome.tsx
186
+ var import_jsx_runtime = require("react/jsx-runtime");
187
+ function ButtonChrome({ label, icon, sideIcon, split }) {
188
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ph-btn-chrome", children: [
189
+ icon != null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ph-btn-icon", children: icon }) : null,
190
+ label != null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ph-btn-label", children: label }) : null,
191
+ split ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ph-btn-split-divider", "aria-hidden": true }) : null,
192
+ sideIcon != null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ph-btn-side-icon", children: sideIcon }) : null
193
+ ] });
194
+ }
195
+
196
+ // src/lib/cn.ts
197
+ function cn(...parts) {
198
+ return parts.filter(Boolean).join(" ");
199
+ }
200
+
201
+ // src/components/ui/Button.tsx
202
+ var import_jsx_runtime2 = require("react/jsx-runtime");
203
+ var variantClass = {
204
+ primary: "ph-btn-primary",
205
+ secondary: "ph-btn-secondary",
206
+ tertiary: "ph-btn-tertiary",
207
+ signal: "ph-btn-signal",
208
+ accent: "ph-btn-accent",
209
+ neutral: "ph-btn-neutral",
210
+ info: "ph-btn-info",
211
+ success: "ph-btn-success",
212
+ warning: "ph-btn-warning",
213
+ danger: "ph-btn-danger",
214
+ ghost: "ph-btn-ghost",
215
+ link: "ph-btn-link"
216
+ };
217
+ var sizeClass = {
218
+ xs: "ph-btn-xs",
219
+ sm: "ph-btn-sm",
220
+ md: "",
221
+ lg: "ph-btn-lg"
222
+ };
223
+ var shapeClass = {
224
+ default: "",
225
+ circle: "ph-btn-circle",
226
+ square: "ph-btn-square",
227
+ wide: "ph-btn-wide"
228
+ };
229
+ function Button({
230
+ variant = "secondary",
231
+ size = "md",
232
+ shape = "default",
233
+ outline = false,
234
+ split = false,
235
+ icon,
236
+ sideIcon,
237
+ className,
238
+ children,
239
+ type = "button",
240
+ ...props
241
+ }) {
242
+ const usesLemonChrome = variant === "primary" || variant === "secondary";
243
+ const content = usesLemonChrome ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ButtonChrome, { label: children, icon, sideIcon, split }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
244
+ icon != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ph-btn-icon", children: icon }) : null,
245
+ children != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ph-btn-label", children }) : null,
246
+ split ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ph-btn-split-divider", "aria-hidden": true }) : null,
247
+ sideIcon != null ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ph-btn-side-icon", children: sideIcon }) : null
248
+ ] });
249
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
250
+ "button",
251
+ {
252
+ type,
253
+ className: cn(
254
+ "ph-btn",
255
+ outline && "ph-btn-outline",
256
+ variantClass[variant],
257
+ sizeClass[size],
258
+ shapeClass[shape],
259
+ split && "ph-btn-split",
260
+ className
261
+ ),
262
+ ...props,
263
+ children: content
264
+ }
265
+ );
266
+ }
267
+
268
+ // src/components/icons/IconBase.tsx
269
+ var import_jsx_runtime3 = require("react/jsx-runtime");
270
+ function IconBase({
271
+ className,
272
+ size,
273
+ children,
274
+ viewBox = "0 0 24 24",
275
+ fill: fill2 = "none",
276
+ xmlns = "http://www.w3.org/2000/svg",
277
+ focusable = "false",
278
+ ...props
279
+ }) {
280
+ const dimensionProps = size != null ? { width: size, height: size } : {};
281
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
282
+ "svg",
283
+ {
284
+ className: cn("ph-icon", className),
285
+ ...dimensionProps,
286
+ viewBox,
287
+ fill: fill2,
288
+ xmlns,
289
+ focusable,
290
+ "aria-hidden": props["aria-hidden"] ?? true,
291
+ ...props,
292
+ children
293
+ }
294
+ );
295
+ }
296
+
297
+ // src/components/icons/createIconBase.tsx
298
+ var import_jsx_runtime4 = require("react/jsx-runtime");
299
+ function createIconBase({ viewBox = "0 0 24 24", paths }) {
300
+ return function IconGlyph(props) {
301
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconBase, { viewBox, ...props, children: paths });
302
+ };
303
+ }
304
+ function createIconBasePath(d, viewBox = "0 0 24 24") {
305
+ return createIconBase({
306
+ viewBox,
307
+ paths: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d, fill: "currentColor" })
308
+ });
309
+ }
310
+
311
+ // src/components/icons/icons.tsx
312
+ var import_jsx_runtime5 = require("react/jsx-runtime");
313
+ var fill = (d) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d, fill: "currentColor" });
314
+ var IconAreaChart = createIconBase({
315
+ paths: fill("M3 20V7l4 3 5-7 5 4h4v13Zm5-3 4-5.5 7 5.45V9h-2.7l-3.9-3.125-4.95 6.95L5 11v3.6Z")
316
+ });
317
+ var IconCumulativeChart = createIconBase({
318
+ paths: fill(
319
+ "M20.8805 7.97408C15.0614 18.7809 6.51281 19.5979 2.71265 18.4578L3.28734 16.5422C6.15384 17.4021 13.7386 17.0191 19.1195 7.02588L20.8805 7.97408Z"
320
+ )
321
+ });
322
+ var IconTableChart = createIconBase({
323
+ paths: fill(
324
+ "M20 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 2v3H5V5h15zm-5 14h-5v-9h5v9zM5 10h3v9H5v-9zm12 9v-9h3v9h-3z"
325
+ )
326
+ });
327
+ var IconHandClick = createIconBase({
328
+ viewBox: "0 0 18 18",
329
+ paths: fill(
330
+ "M14.9942 7.90164C14.9942 7.82992 14.9583 7.46993 14.6342 7.10993C14.2925 6.71407 13.7524 6.49822 13.05 6.44407C12.9783 6.33579 12.8883 6.22822 12.7442 6.11993C12.3483 5.81407 11.7359 5.65164 10.9442 5.63407C10.8724 5.54407 10.7459 5.43578 10.6024 5.32822C10.2425 5.0765 9.79245 4.93236 9.23416 4.87822V3.41993C9.23416 3.27579 9.25244 2.66407 8.83831 2.23164C8.65831 2.03335 8.31659 1.79993 7.74002 1.79993C7.14587 1.79993 6.80416 2.03407 6.60587 2.23164C6.22759 2.64578 6.22759 3.18578 6.22759 3.31164V8.46C5.88587 8.1 5.50759 7.70414 5.29173 7.56C4.84173 7.21829 3.99587 7.39828 3.51002 7.75829C3.04173 8.1 2.88002 8.62243 3.06002 9.12658C3.38416 10.0266 4.19416 10.9266 4.39173 11.1424C4.57173 11.4841 5.38173 12.9782 6.10173 13.5182C6.48002 13.8065 6.76759 14.9941 6.84002 15.7499L6.87588 16.1457H13.6801V14.364C13.7701 14.1123 13.9859 13.5723 14.2201 13.3199C14.7783 12.7616 14.9583 11.3582 14.9583 10.9257V7.91986L14.9942 7.90164ZM14.1117 10.89C14.1117 11.4117 13.8959 12.4017 13.6259 12.6717C13.1576 13.14 12.87 14.04 12.8517 14.13L12.8335 14.1841V15.2283H7.68583C7.64997 15.03 7.61411 14.7783 7.54169 14.5083C7.32583 13.6441 7.03754 13.0866 6.65998 12.7983C6.13826 12.4024 5.39998 11.1241 5.16583 10.6566L5.09411 10.5484C5.09411 10.5301 4.2124 9.63008 3.90582 8.80251C3.86996 8.69423 3.86996 8.60422 3.99582 8.47836C4.22997 8.26251 4.67997 8.20836 4.78754 8.24422C5.05754 8.46008 5.88582 9.34251 6.35339 9.86422L7.12754 10.7284L7.12824 3.29418V3.25762C7.12824 3.1859 7.14652 2.95176 7.27238 2.82591C7.36238 2.71763 7.52409 2.66419 7.75824 2.66419C7.95652 2.66419 8.09995 2.71833 8.20824 2.80833C8.35238 2.97005 8.36996 3.25833 8.36996 3.36662V8.02826H9.25167V5.7599C10.0617 5.8499 10.2958 6.19161 10.3317 6.24575L10.3675 6.33575V8.02747H11.2492V6.53332C12.0051 6.60504 12.2934 6.83918 12.3651 6.94747V8.65747H13.2468V7.34332C14.021 7.4516 14.1468 7.86504 14.1651 7.95504L14.1658 10.8899L14.1117 10.89Z"
331
+ )
332
+ });
333
+ var IconSurveys = createIconBase({
334
+ paths: fill(
335
+ "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.17l-.59.59-.58.58V4h16v12zm-9.5-2H18v-2h-5.5zm3.86-5.87c.2-.2.2-.51 0-.71l-1.77-1.77c-.2-.2-.51-.2-.71 0L6 11.53V14h2.47l5.89-5.87z"
336
+ )
337
+ });
338
+ var IconCohort = createIconBase({
339
+ paths: fill(
340
+ "m4 13c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm1.13 1.1c-.37-.06-.74-.1-1.13-.1-.99 0-1.93.21-2.78.58-.74.32-1.22 1.04-1.22 1.85v1.57h4.5v-1.61c0-.83.23-1.61.63-2.29zm14.87-1.1c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4 3.43c0-.81-.48-1.53-1.22-1.85-.85-.37-1.79-.58-2.78-.58-.39 0-.76.04-1.13.1.4.68.63 1.46.63 2.29v1.61h4.5zm-7.76-2.78c-1.17-.52-2.61-.9-4.24-.9s-3.07.39-4.24.9c-1.08.48-1.76 1.56-1.76 2.74v1.61h12v-1.61c0-1.18-.68-2.26-1.76-2.74zm-8.17 2.35c.09-.23.13-.39.91-.69.97-.38 1.99-.56 3.02-.56s2.05.18 3.02.56c.77.3.81.46.91.69zm3.93-8c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0-2c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
341
+ )
342
+ });
343
+ var IconRecording = createIconBase({
344
+ paths: fill(
345
+ "m10 8v8l5-4zm9-5h-14c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2zm0 16h-14v-14h14z"
346
+ )
347
+ });
348
+ var IconFlare = createIconBase({
349
+ paths: fill(
350
+ "m7 11h-6v2h6zm2.17-3.24-2.12-2.12-1.41 1.41 2.12 2.12zm3.83-6.76h-2v6h2zm5.36 6.05-1.41-1.41-2.12 2.12 1.41 1.41zm-1.36 3.95v2h6v-2zm-5-2c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm2.83 7.24 2.12 2.12 1.41-1.41-2.12-2.12zm-9.19.71 1.41 1.41 2.12-2.12-1.41-1.41zm5.36 6.05h2v-6h-2z"
351
+ )
352
+ });
353
+ var IconSelectEvents = createIconBase({
354
+ paths: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
355
+ fill("M17.5 9L16.56 6.94L14.5 6L16.56 5.06L17.5 3L18.44 5.06L20.5 6L18.44 6.94L17.5 9Z"),
356
+ fill("M6 12.5L6.94 14.56L9 15.5L6.94 16.44L6 18.5L5.06 16.44L3 15.5L5.06 14.56L6 12.5Z"),
357
+ fill("M6 9L5.06 6.94L3 6L5.06 5.06L6 3L6.94 5.06L9 6L6.94 6.94L6 9Z"),
358
+ fill("M16.23 14.26L20 13L10 10L13 20L14.26 16.23L18.53 20.5L20.51 18.52L16.23 14.26Z")
359
+ ] })
360
+ });
361
+ var IconClipboardEdit = createIconBase({
362
+ paths: fill(
363
+ "M21.04 12.13C21.18 12.13 21.31 12.19 21.42 12.3L22.7 13.58C22.92 13.79 22.92 14.14 22.7 14.35L21.7 15.35L19.65 13.3L20.65 12.3C20.76 12.19 20.9 12.13 21.04 12.13M19.07 13.88L21.12 15.93L15.06 22H13V19.94L19.07 13.88M11 19L9 21H5C3.9 21 3 20.1 3 19V5C3 3.9 3.9 3 5 3H9.18C9.6 1.84 10.7 1 12 1C13.3 1 14.4 1.84 14.82 3H19C20.1 3 21 3.9 21 5V9L19 11V5H17V7H7V5H5V19H11M12 3C11.45 3 11 3.45 11 4C11 4.55 11.45 5 12 5C12.55 5 13 4.55 13 4C13 3.45 12.55 3 12 3Z"
364
+ )
365
+ });
366
+ var IconQueryEditor = createIconBase({
367
+ paths: fill(
368
+ "M4,14V17C4,19 7.05,20.72 11,21V18.11L11.13,18C7.12,17.76 4,16.06 4,14M12,13C7.58,13 4,11.21 4,9V12C4,14.21 7.58,16 12,16C12.39,16 12.77,16 13.16,16L17,12.12C15.4,12.72 13.71,13 12,13M12,3C7.58,3 4,4.79 4,7C4,9.21 7.58,11 12,11C16.42,11 20,9.21 20,7C20,4.79 16.42,3 12,3M21,11.13C20.85,11.13 20.71,11.19 20.61,11.3L19.61,12.3L21.66,14.3L22.66,13.3C22.87,13.1 22.88,12.76 22.66,12.53L21.42,11.3C21.32,11.19 21.18,11.13 21.04,11.13M19.04,12.88L13,18.94V21H15.06L21.12,14.93L19.04,12.88Z"
369
+ )
370
+ });
371
+ var IconTuning = createIconBase({
372
+ paths: fill(
373
+ "M3,17V19H9V17H3M3,5V7H13V5H3M13,21V19H21V17H13V15H11V21H13M7,9V11H3V13H7V15H9V9H7M21,13V11H11V13H21M15,9H17V7H21V5H17V3H15V9Z"
374
+ )
375
+ });
376
+ var IconSync = createIconBase({
377
+ paths: fill(
378
+ "m12.5 4v-3l-4 4 4 4v-3c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46c.78-1.23 1.24-2.69 1.24-4.26 0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8l-1.46-1.46c-.78 1.23-1.24 2.69-1.24 4.26 0 4.42 3.58 8 8 8v3l4-4-4-4z"
379
+ )
380
+ });
381
+ var IconPlayCircle = createIconBase({
382
+ paths: fill(
383
+ "M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20ZM9.5 16.5L16.5 12L9.5 7.5V16.5Z"
384
+ )
385
+ });
386
+ var IconGridView = createIconBase({
387
+ paths: fill("M3 3v8h8V3H3zm6 6H5V5h4v4zm-6 4v8h8v-8H3zm6 6H5v-4h4v4zm4-16v8h8V3h-8zm6 6h-4V5h4v4zm-6 4v8h8v-8h-8zm6 6h-4v-4h4v4z")
388
+ });
389
+ var IconListView = createIconBase({
390
+ paths: fill(
391
+ "M3,5v14h18V5H3z M7,7v2H5V7H7z M5,13v-2h2v2H5z M5,15h2v2H5V15z M19,17H9v-2h10V17z M19,13H9v-2h10V13z M19,9H9V7h10V9z"
392
+ )
393
+ });
394
+ var IconPremium = createIconBase({
395
+ paths: fill(
396
+ "m9.68 13.69 2.32-1.76 2.31 1.76-.88-2.85 2.32-1.84h-2.84l-.91-2.81-.91 2.81h-2.84l2.31 1.84zm10.32-3.69c0-4.42-3.58-8-8-8s-8 3.58-8 8c0 2.03.76 3.87 2 5.28v7.72l6-2 6 2v-7.72c1.24-1.41 2-3.25 2-5.28zm-8-6c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6 2.69-6 6-6zm0 15-4 1.02v-3.1c1.18.68 2.54 1.08 4 1.08s2.82-.4 4-1.08v3.1z"
397
+ )
398
+ });
399
+ var IconGift = createIconBase({
400
+ paths: fill(
401
+ "M14.4495 4.55495C15.264 4.31223 15.8631 4.48426 16.1 4.80007C16.4013 5.20182 16.4765 5.57305 16.4336 5.91424C16.3888 6.27088 16.2084 6.63998 15.9211 7.00139C15.3397 7.73275 14.4193 8.30877 13.8244 8.53186C13.598 8.61674 13.4648 8.85138 13.508 9.08924C13.5511 9.32709 13.7582 9.50002 13.9999 9.50002L19.4999 9.50002V12.5H17.9999C17.7237 12.5 17.4999 12.7239 17.4999 13V20.5H6.49988V14.5C6.49988 14.2239 6.27602 14 5.99988 14C5.72374 14 5.49988 14.2239 5.49988 14.5V21C5.49988 21.2762 5.72374 21.5 5.99988 21.5H17.9999C18.276 21.5 18.4999 21.2762 18.4999 21V13.5H19.9999C20.276 13.5 20.4999 13.2762 20.4999 13V9.00002C20.4999 8.86741 20.4472 8.74023 20.3534 8.64646C20.2597 8.5527 20.1325 8.50002 19.9999 8.50002L15.8202 8.50002C16.1407 8.24235 16.4465 7.94742 16.7039 7.62365C17.0625 7.17257 17.3508 6.63541 17.4258 6.03894C17.5027 5.42702 17.3487 4.79826 16.8999 4.20003C16.2882 3.3845 15.1373 3.30652 14.1639 3.5966C13.3806 3.83005 12.5842 4.3279 12.0008 5.07014C11.4285 4.33982 10.6586 3.86464 9.88727 3.64427C8.91382 3.36616 7.82238 3.47045 7.14633 4.14645C6.65753 4.63523 6.41235 5.18234 6.41347 5.75925C6.41457 6.32144 6.64952 6.84016 6.97799 7.28883C7.30058 7.72946 7.7389 8.13769 8.22434 8.50002L3.99988 8.50002C3.86727 8.50002 3.74009 8.5527 3.64632 8.64646C3.55256 8.74023 3.49988 8.86741 3.49988 9.00002V13C3.49988 13.2762 3.72374 13.5 3.99988 13.5H15.4999C15.776 13.5 15.9999 13.2762 15.9999 13C15.9999 12.7239 15.776 12.5 15.4999 12.5H4.49988V9.50002L9.99995 9.50002C10.2318 9.50002 10.4333 9.34058 10.4866 9.1149C10.5398 8.88921 10.431 8.65651 10.2236 8.55281C9.25206 8.06706 8.29723 7.39797 7.78487 6.69811C7.53216 6.35292 7.41402 6.03722 7.41347 5.7573C7.41295 5.49209 7.51758 5.1894 7.85342 4.85358C8.17738 4.52964 8.83597 4.38393 9.61256 4.6058C10.3657 4.82096 11.1212 5.36045 11.5528 6.22359C11.6375 6.39298 11.8106 6.49997 12 6.49997C12.1894 6.49997 12.3625 6.39297 12.4472 6.22358C12.8783 5.36141 13.672 4.78667 14.4495 4.55495Z"
402
+ )
403
+ });
404
+ var IconRobot = createIconBase({
405
+ paths: fill(
406
+ "M17.5 15.5C17.5 16.61 16.61 17.5 15.5 17.5S13.5 16.61 13.5 15.5 14.4 13.5 15.5 13.5 17.5 14.4 17.5 15.5M8.5 13.5C7.4 13.5 6.5 14.4 6.5 15.5S7.4 17.5 8.5 17.5 10.5 16.61 10.5 15.5 9.61 13.5 8.5 13.5M23 15V18C23 18.55 22.55 19 22 19H21V20C21 21.11 20.11 22 19 22H5C3.9 22 3 21.11 3 20V19H2C1.45 19 1 18.55 1 18V15C1 14.45 1.45 14 2 14H3C3 10.13 6.13 7 10 7H11V5.73C10.4 5.39 10 4.74 10 4C10 2.9 10.9 2 12 2S14 2.9 14 4C14 4.74 13.6 5.39 13 5.73V7H14C17.87 7 21 10.13 21 14H22C22.55 14 23 14.45 23 15M21 16H19V14C19 11.24 16.76 9 14 9H10C7.24 9 5 11.24 5 14V16H3V17H5V20H19V17H21V16Z"
407
+ )
408
+ });
409
+ var IconExclamation = createIconBase({
410
+ paths: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("g", { fill: "currentColor", children: [
411
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m12 21c1.1046 0 2-.8954 2-2s-.8954-2-2-2-2 .8954-2 2 .8954 2 2 2z" }),
412
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m10 3h4v12h-4z" })
413
+ ] })
414
+ });
415
+ var IconErrorOutline = createIconBase({
416
+ paths: fill(
417
+ "m11 15h2v2h-2zm0-8h2v6h-2zm.99-5c-5.52 0-9.99 4.48-9.99 10s4.47 10 9.99 10c5.53 0 10.01-4.48 10.01-10s-4.48-10-10.01-10zm.01 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
418
+ )
419
+ });
420
+ var IconCancel = createIconBase({
421
+ paths: fill(
422
+ "m12 2c-5.53 0-10 4.47-10 10s4.47 10 10 10 10-4.47 10-10-4.47-10-10-10zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13-3.59 3.59-3.59-3.59-1.41 1.41 3.59 3.59-3.59 3.59 1.41 1.41 3.59-3.59 3.59 3.59 1.41-1.41-3.59-3.59 3.59-3.59z"
423
+ )
424
+ });
425
+ var IconCheckCircle = createIconBase({
426
+ paths: fill(
427
+ "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"
428
+ )
429
+ });
430
+ var IconArrowUp = createIconBase({
431
+ paths: fill("M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z")
432
+ });
433
+ var IconArrowDown = createIconBase({
434
+ paths: fill("M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z")
435
+ });
436
+ var IconChevronLeft = createIconBasePath("M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z");
437
+ var IconChevronRight = createIconBasePath("M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z");
438
+ var IconChevronDown = createIconBasePath("M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z");
439
+ var IconSubArrowRight = createIconBase({
440
+ paths: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("g", { transform: "translate(4 5.5)", children: fill("M2 0H0V10H12.01V13L16 9L12.01 5V8H2V0Z") })
441
+ });
442
+ var IconSearch = createIconBasePath(
443
+ "M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
444
+ );
445
+ var IconBell = createIconBasePath(
446
+ "M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2m6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1z"
447
+ );
448
+ var IconBellOff = createIconBasePath(
449
+ "M20 18.69 7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2m6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01z"
450
+ );
451
+ var IconPerson = createIconBasePath(
452
+ "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
453
+ );
454
+ var IconHome = createIconBasePath("M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z");
455
+ var IconPanelRight = createIconBasePath(
456
+ "M3 5v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2zm12 4h-5v10h5V9zm-7 0H5v10h3V9z"
457
+ );
458
+ var IconPlus = createIconBasePath("M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z");
459
+ var IconCheck = createIconBasePath("M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z");
460
+ var IconClose = createIconBasePath("M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z");
461
+ var IconTrash = createIconBasePath("M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z");
462
+ var IconDownload = createIconBasePath("M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z");
463
+ var IconUpload = createIconBasePath("M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z");
464
+ var IconSave = createIconBasePath(
465
+ "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"
466
+ );
467
+ var IconCopy = createIconBasePath(
468
+ "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"
469
+ );
470
+ var IconEdit = createIconBasePath(
471
+ "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
472
+ );
473
+ var IconLogout = createIconBasePath(
474
+ "M17 7l-1.41 1.41L18.17 11H8v2h10.17l-2.58 2.59L17 17l5-5zM4 5h8V3H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8v-2H4V5z"
475
+ );
476
+ var IconStar = createIconBasePath(
477
+ "M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"
478
+ );
479
+ var IconMail = createIconBasePath(
480
+ "M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"
481
+ );
482
+ var IconShoppingCart = createIconBasePath(
483
+ "M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"
484
+ );
485
+ var IconMoon = createIconBasePath(
486
+ "M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"
487
+ );
488
+ var IconSun = createIconBasePath(
489
+ "M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"
490
+ );
491
+ var IconVolume = createIconBasePath(
492
+ "M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"
493
+ );
494
+ var IconVolumeOff = createIconBasePath(
495
+ "M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"
496
+ );
497
+ var IconFlag = createIconBasePath("M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6h-5.6z");
498
+ var IconDatabase = createIconBasePath(
499
+ "M12 3C7.58 3 4 4.79 4 7s3.58 4 8 4 8-1.79 8-4-3.58-4-8-4zM4 9v3c0 2.21 3.58 4 8 4s8-1.79 8-4V9c0 2.21-3.58 4-8 4s-8-1.79-8-4zm0 5v3c0 2.21 3.58 4 8 4s8-1.79 8-4v-3c0 2.21-3.58 4-8 4s-8-1.79-8-4z"
500
+ );
501
+ var IconLayers = createIconBasePath("M11.99 18.54l-7.37-5.73L3 14.07l9 7 9-7-1.63-1.27-7.38 5.74zM12 16l7.36-5.73L21 9l-9-7-9 7 1.63 1.27L12 16z");
502
+ var IconBox = createIconBasePath(
503
+ "M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
504
+ );
505
+ var IconBolt = createIconBasePath(
506
+ "M11 21h-1l1-7H7.5c-.58 0-.57-.32-.38-.66-.19-.34-.04-.12-.07-.12C8.48 10.94 10.42 7.54 11 7V3h1v4c.58 0 .57.32.38.66-.19-.34-.04-.12-.07-.12-.95 2.28-2.96 5.66-3.31 6.22H13l-1 7h-1z"
507
+ );
508
+ var IconRadar = createIconBasePath(
509
+ "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm-5.5-2.5l7.51-3.49L17.5 6.5 9.99 9.99 6.5 17.5zm5.5-6.6c.61 0 1.1.49 1.1 1.1s-.49 1.1-1.1 1.1-1.1-.49-1.1-1.1.49-1.1 1.1-1.1z"
510
+ );
511
+ var IconToggle = createIconBasePath(
512
+ "M17 7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h10c2.76 0 5-2.24 5-5s-2.24-5-5-5zm0 8H7c-1.66 0-3-1.34-3-3s1.34-3 3-3h10c1.66 0 3 1.34 3 3s-1.34 3-3 3zM7 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"
513
+ );
514
+ var IconRocket = createIconBasePath(
515
+ "M9.19 6.35c-2.04 2.29-3.44 5.58-3.57 5.89L2 10.69l4.05-4.05c.47-.47 1.15-.68 1.81-.55l1.33 1.26zm5.45 8.67l-1.33-1.26c-.66-.13-1.34.08-1.81.55L2 18.31l3.62 3.57c.31-.13 3.6-1.53 5.89-3.57 1.53-1.72 2.52-3.76 2.87-5.02zM12 2c-1.1 0-2 .9-2 2v1.09c2.84.48 5 2.94 5 5.91 0 2.97-2.16 5.43-5 5.91V20c0 1.1.9 2 2 2s2-.9 2-2v-1.09c-2.84-.48-5-2.94-5-5.91 0-2.97 2.16-5.43 5-5.91V4c0-1.1-.9-2-2-2z"
516
+ );
517
+ var IconTerminal = createIconBasePath("M20 4H4c-1.11 0-2 .89-2 2v12c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4V8l8 5 8-5v10zm-8-7L4 6h16l-8 5z");
518
+ var IconActivity = createIconBasePath(
519
+ "M22 12h-4l-3 9L9 3l-3 9H2v2h6.76l2.24-6.72L15 15l2.24-6.72L19 14h3v-2z"
520
+ );
521
+ var IconFlask = createIconBasePath(
522
+ "M19.8 18.4L14 10.67V6.5l1.35-1.35c.39-.39.39-1.02 0-1.41L14.65 2.7a.9959.9959 0 0 0-1.41 0L9.35 6.54c-.39.39-.39 1.02 0 1.41L10.7 9.3v4.17L4.2 18.4C3.53 19.07 4.04 20.25 5 20.25h14c.96 0 1.47-1.18.8-1.85zM6.91 18.25l5.09-5.09 5.09 5.09H6.91z"
523
+ );
524
+ function IconSpinner({ className, ...props }) {
525
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconSync, { className: cn("ph-icon-spin", className), ...props });
526
+ }
527
+ var PH_ICONS = {
528
+ activity: IconActivity,
529
+ areaChart: IconAreaChart,
530
+ arrowDown: IconArrowDown,
531
+ arrowUp: IconArrowUp,
532
+ bell: IconBell,
533
+ bellOff: IconBellOff,
534
+ bolt: IconBolt,
535
+ box: IconBox,
536
+ cancel: IconCancel,
537
+ check: IconCheck,
538
+ checkCircle: IconCheckCircle,
539
+ chevronDown: IconChevronDown,
540
+ chevronLeft: IconChevronLeft,
541
+ chevronRight: IconChevronRight,
542
+ clipboard: IconClipboardEdit,
543
+ close: IconClose,
544
+ cohort: IconCohort,
545
+ copy: IconCopy,
546
+ cumulativeChart: IconCumulativeChart,
547
+ database: IconDatabase,
548
+ download: IconDownload,
549
+ edit: IconEdit,
550
+ errorOutline: IconErrorOutline,
551
+ exclamation: IconExclamation,
552
+ flag: IconFlag,
553
+ flare: IconFlare,
554
+ flask: IconFlask,
555
+ gift: IconGift,
556
+ grid: IconGridView,
557
+ handClick: IconHandClick,
558
+ home: IconHome,
559
+ info: IconErrorOutline,
560
+ layers: IconLayers,
561
+ list: IconListView,
562
+ logout: IconLogout,
563
+ mail: IconMail,
564
+ moon: IconMoon,
565
+ panelRight: IconPanelRight,
566
+ person: IconPerson,
567
+ play: IconPlayCircle,
568
+ plus: IconPlus,
569
+ premium: IconPremium,
570
+ queryEditor: IconQueryEditor,
571
+ radar: IconRadar,
572
+ recording: IconRecording,
573
+ robot: IconRobot,
574
+ rocket: IconRocket,
575
+ save: IconSave,
576
+ search: IconSearch,
577
+ selectEvents: IconSelectEvents,
578
+ settings: IconTuning,
579
+ shoppingCart: IconShoppingCart,
580
+ spinner: IconSpinner,
581
+ star: IconStar,
582
+ subArrowRight: IconSubArrowRight,
583
+ sun: IconSun,
584
+ surveys: IconSurveys,
585
+ sync: IconSync,
586
+ tableChart: IconTableChart,
587
+ terminal: IconTerminal,
588
+ toggle: IconToggle,
589
+ trash: IconTrash,
590
+ trendingUp: IconArrowUp,
591
+ upload: IconUpload,
592
+ volume: IconVolume,
593
+ volumeOff: IconVolumeOff,
594
+ warning: IconExclamation,
595
+ xCircle: IconCancel
596
+ };
597
+ function IconByName({ name, ...props }) {
598
+ const Icon = PH_ICONS[name];
599
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { ...props });
600
+ }
601
+
602
+ // src/components/ui/Alert.tsx
603
+ var import_jsx_runtime6 = require("react/jsx-runtime");
604
+ var statusConfig = {
605
+ info: { icon: IconErrorOutline, color: "text-ph-info" },
606
+ success: { icon: IconCheckCircle, color: "text-ph-success" },
607
+ warning: { icon: IconExclamation, color: "text-ph-warning" },
608
+ danger: { icon: IconCancel, color: "text-ph-danger" }
609
+ };
610
+ var statusClassMap = {
611
+ info: "ph-alert-info",
612
+ success: "ph-alert-success",
613
+ warning: "ph-alert-warning",
614
+ danger: "ph-alert-danger"
615
+ };
616
+ function Alert({
617
+ status = "info",
618
+ title,
619
+ description,
620
+ icon,
621
+ children,
622
+ className,
623
+ onDismiss
624
+ }) {
625
+ const config = statusConfig[status];
626
+ const Icon = config.icon;
627
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
628
+ "div",
629
+ {
630
+ role: "alert",
631
+ className: cn("ph-alert", statusClassMap[status], className),
632
+ children: [
633
+ icon ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { className: cn("mt-0.5 h-5 w-5 shrink-0", config.color) }),
634
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex-1", children: [
635
+ title && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "font-semibold", children: title }),
636
+ description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mt-1 text-sm text-ph-subtle", children: description }),
637
+ children
638
+ ] }),
639
+ onDismiss && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
640
+ "button",
641
+ {
642
+ type: "button",
643
+ onClick: onDismiss,
644
+ className: "shrink-0 rounded-md p-1 text-ph-subtle hover:bg-black/5 hover:text-ph-ink",
645
+ "aria-label": "Dismiss",
646
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) })
647
+ }
648
+ )
649
+ ]
650
+ }
651
+ );
652
+ }
653
+
654
+ // src/components/ui/Badge.tsx
655
+ var import_jsx_runtime7 = require("react/jsx-runtime");
656
+ var variantMap = {
657
+ brand: "ph-badge-brand",
658
+ neutral: "ph-badge-neutral",
659
+ success: "ph-badge-success",
660
+ warning: "ph-badge-warning",
661
+ danger: "ph-badge-danger",
662
+ info: "ph-badge-info",
663
+ outline: "ph-badge-outline"
664
+ };
665
+ var sizeMap = {
666
+ sm: "text-[10px] px-1.5 py-0.5",
667
+ md: ""
668
+ };
669
+ function Badge({
670
+ variant = "neutral",
671
+ size = "md",
672
+ children,
673
+ className
674
+ }) {
675
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
676
+ "span",
677
+ {
678
+ className: cn(
679
+ "ph-badge",
680
+ variantMap[variant],
681
+ sizeMap[size],
682
+ className
683
+ ),
684
+ children
685
+ }
686
+ );
687
+ }
688
+
689
+ // src/components/ui/Card.tsx
690
+ var import_jsx_runtime8 = require("react/jsx-runtime");
691
+ var variantMap2 = {
692
+ default: "bg-ph-surface",
693
+ outlined: "border-2 border-ph-border bg-ph-surface",
694
+ elevated: "bg-ph-surface shadow-ph-md",
695
+ highlighted: "border border-ph-brand/35 bg-orange-50/40 shadow-ph"
696
+ };
697
+ function Card({
698
+ children,
699
+ title,
700
+ description,
701
+ actions,
702
+ footer,
703
+ media,
704
+ variant = "default",
705
+ className,
706
+ bodyClassName
707
+ }) {
708
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
709
+ "div",
710
+ {
711
+ className: cn(
712
+ "ph-card",
713
+ variantMap2[variant],
714
+ className
715
+ ),
716
+ children: [
717
+ media && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "-mx-6 -mt-6 mb-4", children: media }),
718
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn("ph-card-body", bodyClassName), children: [
719
+ title && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "ph-card-title", children: title }),
720
+ description && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-sm text-ph-subtle", children: description }),
721
+ children,
722
+ actions && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "ph-card-actions", children: actions })
723
+ ] }),
724
+ footer && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "border-t border-ph-border px-6 py-4 text-xs text-ph-subtle", children: footer })
725
+ ]
726
+ }
727
+ );
728
+ }
729
+
730
+ // src/components/ui/Drawer.tsx
731
+ var import_jsx_runtime9 = require("react/jsx-runtime");
732
+ var sideMap = {
733
+ left: "left-0 border-r",
734
+ right: "right-0 border-l"
735
+ };
736
+ var sizeMap2 = {
737
+ sm: "w-[min(100%,18rem)]",
738
+ md: "w-[min(100%,22rem)]",
739
+ lg: "w-[min(100%,30rem)]"
740
+ };
741
+ function Drawer({
742
+ open = false,
743
+ onClose,
744
+ title,
745
+ children,
746
+ footer,
747
+ side = "right",
748
+ size = "md",
749
+ className,
750
+ showCloseButton = true
751
+ }) {
752
+ if (!open) return null;
753
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
754
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fixed inset-0 z-[120] bg-black/45 backdrop-blur-[2px]", role: "presentation", onClick: onClose }),
755
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
756
+ "aside",
757
+ {
758
+ className: cn(
759
+ "fixed inset-y-0 z-[130] flex flex-col overflow-y-auto border-ph-border bg-ph-surface shadow-ph-md",
760
+ sideMap[side],
761
+ sizeMap2[size],
762
+ className
763
+ ),
764
+ children: [
765
+ (title || showCloseButton) && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("header", { className: "flex items-center justify-between border-b border-ph-border px-4 py-3", children: [
766
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm font-bold text-ph-ink", children: title }),
767
+ showCloseButton && onClose && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { variant: "ghost", className: "ph-btn-circle", onClick: onClose, "aria-label": "Close drawer", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconClose, { className: "h-5 w-5" }) })
768
+ ] }),
769
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex-1", children }),
770
+ footer && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("footer", { className: "border-t border-ph-border px-4 py-3", children: footer })
771
+ ]
772
+ }
773
+ )
774
+ ] });
775
+ }
776
+
777
+ // src/components/ui/Kbd.tsx
778
+ var import_jsx_runtime10 = require("react/jsx-runtime");
779
+ function Kbd({ variant = "shortcut", keys, children, className, ...props }) {
780
+ if (variant === "token") {
781
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("code", { className: cn("ph-kbd text-ph-ink", className), ...props, children });
782
+ }
783
+ const content = (keys == null ? void 0 : keys.length) ? keys.join(" ") : normalizeShortcut(children);
784
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("kbd", { className: cn("ph-shortcut", className), ...props, children: content });
785
+ }
786
+ function normalizeShortcut(children) {
787
+ if (typeof children !== "string") return children;
788
+ return children.replace(/\bCommand\b|\bCmd\b/g, "\u2318").replace(/\bOption\b|\bAlt\b/g, "\u2325").replace(/\bShift\b/g, "\u21E7").replace(/\bControl\b|\bCtrl\b/g, "\u2303");
789
+ }
790
+
791
+ // src/components/ui/DropdownMenu.tsx
792
+ var import_jsx_runtime11 = require("react/jsx-runtime");
793
+ var sizeClass2 = {
794
+ xs: "ph-btn-xs",
795
+ sm: "ph-btn-sm",
796
+ md: "",
797
+ lg: "ph-btn-lg"
798
+ };
799
+ var variantClass2 = {
800
+ primary: "ph-btn-primary",
801
+ secondary: "ph-btn-secondary",
802
+ accent: "ph-btn-accent"
803
+ };
804
+ function dropdownPanelClass(align, panelClassName) {
805
+ return cn(
806
+ "ph-dropdown-panel absolute top-full z-50 mt-0",
807
+ align === "end" ? "right-0" : "left-0",
808
+ panelClassName
809
+ );
810
+ }
811
+ function DropdownMenu({
812
+ trigger,
813
+ children,
814
+ align = "start",
815
+ className,
816
+ panelClassName,
817
+ "aria-label": ariaLabel,
818
+ ...props
819
+ }) {
820
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("details", { className: cn("relative", className), ...props, children: [
821
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
822
+ "summary",
823
+ {
824
+ className: "cursor-pointer list-none [&::-webkit-details-marker]:hidden",
825
+ "aria-label": ariaLabel,
826
+ children: trigger
827
+ }
828
+ ),
829
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: dropdownPanelClass(align, panelClassName), children })
830
+ ] });
831
+ }
832
+ function DropdownButton({
833
+ label,
834
+ variant = "secondary",
835
+ outline = false,
836
+ size = "md",
837
+ split = false,
838
+ icon,
839
+ sideIcon,
840
+ children,
841
+ align = "start",
842
+ className,
843
+ panelClassName,
844
+ "aria-label": ariaLabel,
845
+ ...props
846
+ }) {
847
+ const usesLemonChrome = variant === "primary" || variant === "secondary";
848
+ const chevron = /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconChevronDown, { className: "h-4 w-4", "aria-hidden": true });
849
+ const trailing = sideIcon ?? chevron;
850
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("details", { className: cn("relative", className), ...props, children: [
851
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
852
+ "summary",
853
+ {
854
+ className: cn(
855
+ "ph-btn cursor-pointer list-none [&::-webkit-details-marker]:hidden",
856
+ variantClass2[variant],
857
+ outline && "ph-btn-outline",
858
+ sizeClass2[size],
859
+ split && "ph-btn-split"
860
+ ),
861
+ "aria-label": ariaLabel ?? label,
862
+ children: usesLemonChrome ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ButtonChrome, { label, icon, sideIcon: trailing, split }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
863
+ icon != null ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ph-btn-icon", children: icon }) : null,
864
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ph-btn-label", children: label }),
865
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "ph-btn-side-icon", children: trailing })
866
+ ] })
867
+ }
868
+ ),
869
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: dropdownPanelClass(align, panelClassName), children })
870
+ ] });
871
+ }
872
+ function DropdownItem({
873
+ className,
874
+ children,
875
+ ...props
876
+ }) {
877
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: cn("ph-dropdown-item w-full text-left", className), ...props, children });
878
+ }
879
+
880
+ // src/components/ui/Input.tsx
881
+ var import_react = require("react");
882
+ var import_jsx_runtime12 = require("react/jsx-runtime");
883
+ var sizeMap3 = {
884
+ sm: "ph-input-sm",
885
+ md: "",
886
+ lg: "ph-input-lg"
887
+ };
888
+ function Input({
889
+ id: idProp,
890
+ label,
891
+ hideLabel = false,
892
+ error,
893
+ helperText,
894
+ size = "md",
895
+ variant = "default",
896
+ className,
897
+ wrapperClassName,
898
+ disabled,
899
+ ...props
900
+ }) {
901
+ const autoId = (0, import_react.useId)();
902
+ const id = idProp ?? autoId;
903
+ const hasError = Boolean(error);
904
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
905
+ label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
906
+ "label",
907
+ {
908
+ htmlFor: id,
909
+ className: cn(
910
+ "ph-label",
911
+ hideLabel && "sr-only",
912
+ disabled && "opacity-50"
913
+ ),
914
+ children: label
915
+ }
916
+ ),
917
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
918
+ "input",
919
+ {
920
+ id,
921
+ disabled,
922
+ "aria-invalid": hasError || void 0,
923
+ className: cn(
924
+ "ph-input w-full",
925
+ sizeMap3[size],
926
+ variant === "ghost" && "ph-input-ghost",
927
+ hasError && "ph-input-error",
928
+ disabled && "cursor-not-allowed opacity-60",
929
+ className
930
+ ),
931
+ ...props
932
+ }
933
+ ),
934
+ helperText && !hasError && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs text-ph-subtle", children: helperText }),
935
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs font-medium text-ph-danger", children: error })
936
+ ] });
937
+ }
938
+ function Select({
939
+ id: idProp,
940
+ label,
941
+ hideLabel = false,
942
+ error,
943
+ helperText,
944
+ size = "md",
945
+ className,
946
+ wrapperClassName,
947
+ disabled,
948
+ children,
949
+ ...props
950
+ }) {
951
+ const autoId = (0, import_react.useId)();
952
+ const id = idProp ?? autoId;
953
+ const hasError = Boolean(error);
954
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
955
+ label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
956
+ "label",
957
+ {
958
+ htmlFor: id,
959
+ className: cn("ph-label", hideLabel && "sr-only", disabled && "opacity-50"),
960
+ children: label
961
+ }
962
+ ),
963
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
964
+ "select",
965
+ {
966
+ id,
967
+ disabled,
968
+ "aria-invalid": hasError || void 0,
969
+ className: cn(
970
+ "ph-select w-full",
971
+ sizeMap3[size],
972
+ hasError && "border-ph-danger focus:border-ph-danger focus:ring-ph-danger/20",
973
+ disabled && "cursor-not-allowed opacity-60",
974
+ className
975
+ ),
976
+ ...props,
977
+ children
978
+ }
979
+ ),
980
+ helperText && !hasError && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs text-ph-subtle", children: helperText }),
981
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs font-medium text-ph-danger", children: error })
982
+ ] });
983
+ }
984
+ function Textarea({
985
+ id: idProp,
986
+ label,
987
+ hideLabel = false,
988
+ error,
989
+ helperText,
990
+ size = "md",
991
+ className,
992
+ wrapperClassName,
993
+ disabled,
994
+ ...props
995
+ }) {
996
+ const autoId = (0, import_react.useId)();
997
+ const id = idProp ?? autoId;
998
+ const hasError = Boolean(error);
999
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
1000
+ label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1001
+ "label",
1002
+ {
1003
+ htmlFor: id,
1004
+ className: cn("ph-label", hideLabel && "sr-only", disabled && "opacity-50"),
1005
+ children: label
1006
+ }
1007
+ ),
1008
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1009
+ "textarea",
1010
+ {
1011
+ id,
1012
+ disabled,
1013
+ "aria-invalid": hasError || void 0,
1014
+ className: cn(
1015
+ "ph-textarea w-full",
1016
+ sizeMap3[size],
1017
+ hasError && "border-ph-danger focus:border-ph-danger focus:ring-ph-danger/20",
1018
+ disabled && "cursor-not-allowed opacity-60",
1019
+ className
1020
+ ),
1021
+ ...props
1022
+ }
1023
+ ),
1024
+ helperText && !hasError && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs text-ph-subtle", children: helperText }),
1025
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs font-medium text-ph-danger", children: error })
1026
+ ] });
1027
+ }
1028
+ function Checkbox({
1029
+ id: idProp,
1030
+ label,
1031
+ error,
1032
+ helperText,
1033
+ className,
1034
+ wrapperClassName,
1035
+ disabled,
1036
+ ...props
1037
+ }) {
1038
+ const autoId = (0, import_react.useId)();
1039
+ const id = idProp ?? autoId;
1040
+ const hasError = Boolean(error);
1041
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-control-row", wrapperClassName), children: [
1042
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1043
+ "input",
1044
+ {
1045
+ id,
1046
+ type: "checkbox",
1047
+ disabled,
1048
+ "aria-invalid": hasError || void 0,
1049
+ className: cn(
1050
+ "ph-checkbox",
1051
+ hasError && "border-ph-danger",
1052
+ disabled && "cursor-not-allowed opacity-60",
1053
+ className
1054
+ ),
1055
+ ...props
1056
+ }
1057
+ ),
1058
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { htmlFor: id, className: cn("cursor-pointer", disabled && "opacity-60"), children: label }),
1059
+ helperText && !hasError && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-0.5 text-xs text-ph-subtle", children: helperText }),
1060
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-0.5 text-xs font-medium text-ph-danger", children: error })
1061
+ ] });
1062
+ }
1063
+ function Radio({
1064
+ id: idProp,
1065
+ label,
1066
+ className,
1067
+ wrapperClassName,
1068
+ disabled,
1069
+ ...props
1070
+ }) {
1071
+ const autoId = (0, import_react.useId)();
1072
+ const id = idProp ?? autoId;
1073
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-control-row", wrapperClassName, disabled && "opacity-60"), children: [
1074
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1075
+ "input",
1076
+ {
1077
+ id,
1078
+ type: "radio",
1079
+ disabled,
1080
+ className: cn("ph-radio", disabled && "cursor-not-allowed", className),
1081
+ ...props
1082
+ }
1083
+ ),
1084
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { htmlFor: id, className: cn("cursor-pointer", disabled && "opacity-60"), children: label })
1085
+ ] });
1086
+ }
1087
+ function Toggle({
1088
+ id: idProp,
1089
+ label,
1090
+ className,
1091
+ wrapperClassName,
1092
+ disabled,
1093
+ ...props
1094
+ }) {
1095
+ const autoId = (0, import_react.useId)();
1096
+ const id = idProp ?? autoId;
1097
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: cn("ph-control-row-between", wrapperClassName, disabled && "opacity-60"), children: [
1098
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: disabled ? "opacity-60" : void 0, children: label }),
1099
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1100
+ "input",
1101
+ {
1102
+ id,
1103
+ type: "checkbox",
1104
+ role: "switch",
1105
+ disabled,
1106
+ className: cn("ph-toggle", disabled && "cursor-not-allowed", className),
1107
+ ...props
1108
+ }
1109
+ )
1110
+ ] });
1111
+ }
1112
+ function Range({
1113
+ label,
1114
+ minLabel,
1115
+ maxLabel,
1116
+ valueLabel,
1117
+ wrapperClassName,
1118
+ className,
1119
+ ...props
1120
+ }) {
1121
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
1122
+ label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { className: "ph-label", children: label }),
1123
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "range", className: cn("ph-range", className), ...props }),
1124
+ (minLabel || valueLabel || maxLabel) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex justify-between text-xs text-ph-mutedtext", children: [
1125
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: minLabel }),
1126
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: valueLabel }),
1127
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: maxLabel })
1128
+ ] })
1129
+ ] });
1130
+ }
1131
+ function FileUpload({ label, prompt = "Drop file or browse", wrapperClassName, className, ...props }) {
1132
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
1133
+ label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { className: "ph-label", children: label }),
1134
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex cursor-pointer items-center gap-3 rounded-lg border border-dashed border-ph-border bg-ph-surface px-4 py-6 text-sm text-ph-subtle transition hover:bg-ph-muted/60", children: [
1135
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "file", className: cn("sr-only", className), ...props }),
1136
+ prompt
1137
+ ] })
1138
+ ] });
1139
+ }
1140
+
1141
+ // src/components/ui/Modal.tsx
1142
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1143
+ var sizeMap4 = {
1144
+ sm: "max-w-sm",
1145
+ md: "max-w-lg",
1146
+ lg: "max-w-2xl",
1147
+ xl: "max-w-4xl",
1148
+ full: "max-w-[calc(100%-2rem)]"
1149
+ };
1150
+ function Modal({
1151
+ open = false,
1152
+ onClose,
1153
+ title,
1154
+ description,
1155
+ children,
1156
+ footer,
1157
+ size = "md",
1158
+ className,
1159
+ showCloseButton = true
1160
+ }) {
1161
+ if (!open) return null;
1162
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ph-modal-overlay", role: "presentation", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
1163
+ "div",
1164
+ {
1165
+ role: "dialog",
1166
+ "aria-modal": true,
1167
+ className: cn(
1168
+ "ph-modal-panel",
1169
+ sizeMap4[size],
1170
+ className
1171
+ ),
1172
+ onClick: (e) => e.stopPropagation(),
1173
+ children: [
1174
+ (title || showCloseButton) && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("header", { className: "flex items-start justify-between gap-4", children: [
1175
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
1176
+ title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-lg font-bold text-ph-ink", children: title }),
1177
+ description && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 text-sm text-ph-subtle", children: description })
1178
+ ] }),
1179
+ showCloseButton && onClose && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1180
+ "button",
1181
+ {
1182
+ type: "button",
1183
+ onClick: onClose,
1184
+ className: "shrink-0 rounded-md p-1 text-ph-subtle hover:bg-black/5 hover:text-ph-ink",
1185
+ "aria-label": "Close",
1186
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconClose, { className: "h-5 w-5" })
1187
+ }
1188
+ )
1189
+ ] }),
1190
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-4", children }),
1191
+ footer && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-6 flex justify-end gap-2 border-t border-ph-border pt-5", children: footer })
1192
+ ]
1193
+ }
1194
+ ) });
1195
+ }
1196
+
1197
+ // src/components/ui/Navigation.tsx
1198
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1199
+ function Breadcrumbs({ items, label = "Breadcrumb", className }) {
1200
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("nav", { "aria-label": label, className: cn("ph-breadcrumbs", className), children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "contents", children: [
1201
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ph-breadcrumb-sep", "aria-hidden": "true", children: "/" }) : null,
1202
+ item.current || !item.href ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ph-breadcrumb-current", "aria-current": item.current ? "page" : void 0, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("a", { href: item.href, className: "ph-breadcrumb-link", children: item.label })
1203
+ ] }, `${item.label}-${index}`)) });
1204
+ }
1205
+ function Pagination({
1206
+ page,
1207
+ totalPages,
1208
+ onPageChange,
1209
+ label = "Pagination",
1210
+ compact = false,
1211
+ className
1212
+ }) {
1213
+ const pages = compact ? [Math.max(1, page - 1), page, Math.min(totalPages, page + 1)] : [1, 2, 3, totalPages];
1214
+ const uniquePages = Array.from(new Set(pages)).filter((n) => n >= 1 && n <= totalPages);
1215
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("nav", { "aria-label": label, className: cn("ph-pagination", className), children: [
1216
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1217
+ "button",
1218
+ {
1219
+ type: "button",
1220
+ className: "ph-pagination-btn",
1221
+ disabled: page <= 1,
1222
+ "aria-label": "Previous page",
1223
+ onClick: () => onPageChange == null ? void 0 : onPageChange(page - 1),
1224
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconChevronLeft, { className: "mx-auto h-4 w-4", "aria-hidden": true })
1225
+ }
1226
+ ),
1227
+ uniquePages.map((pageNumber, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "contents", children: [
1228
+ !compact && index === uniquePages.length - 1 && pageNumber > 4 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ph-pagination-ellipsis", "aria-hidden": "true", children: "..." }) : null,
1229
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1230
+ "button",
1231
+ {
1232
+ type: "button",
1233
+ className: cn("ph-pagination-btn", pageNumber === page && "ph-pagination-btn-active"),
1234
+ "aria-current": pageNumber === page ? "page" : void 0,
1235
+ onClick: () => onPageChange == null ? void 0 : onPageChange(pageNumber),
1236
+ children: pageNumber
1237
+ }
1238
+ )
1239
+ ] }, pageNumber)),
1240
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1241
+ "button",
1242
+ {
1243
+ type: "button",
1244
+ className: "ph-pagination-btn",
1245
+ disabled: page >= totalPages,
1246
+ "aria-label": "Next page",
1247
+ onClick: () => onPageChange == null ? void 0 : onPageChange(page + 1),
1248
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconChevronRight, { className: "mx-auto h-4 w-4", "aria-hidden": true })
1249
+ }
1250
+ )
1251
+ ] });
1252
+ }
1253
+
1254
+ // src/components/ui/Panel.tsx
1255
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1256
+ function Panel({ title, description, children, className, ...props }) {
1257
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: cn("ph-panel", className), ...props, children: [
1258
+ title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { className: "text-sm font-semibold uppercase tracking-wider text-ph-mutedtext", children: title }),
1259
+ description && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-ph-subtle", children: description }),
1260
+ children
1261
+ ] });
1262
+ }
1263
+
1264
+ // src/components/ui/Rating.tsx
1265
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1266
+ function Rating({
1267
+ label,
1268
+ value = 0,
1269
+ max = 5,
1270
+ readOnly = true,
1271
+ onChange,
1272
+ className,
1273
+ wrapperClassName,
1274
+ ...props
1275
+ }) {
1276
+ const stars = Array.from({ length: max }, (_, index) => index + 1);
1277
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
1278
+ label && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "ph-label", children: label }),
1279
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1280
+ "div",
1281
+ {
1282
+ className: cn("ph-rating flex", className),
1283
+ role: readOnly ? "img" : "radiogroup",
1284
+ "aria-label": label ?? `Rating: ${value} out of ${max}`,
1285
+ ...props,
1286
+ children: stars.map((star) => {
1287
+ const active = star <= value;
1288
+ if (readOnly) {
1289
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1290
+ IconStar,
1291
+ {
1292
+ className: cn("h-6 w-6", active ? "text-amber-500" : "text-ph-border"),
1293
+ "aria-hidden": true
1294
+ },
1295
+ star
1296
+ );
1297
+ }
1298
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1299
+ "button",
1300
+ {
1301
+ type: "button",
1302
+ className: "rounded p-0.5 transition hover:scale-105 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ph-brand",
1303
+ role: "radio",
1304
+ "aria-checked": active,
1305
+ "aria-label": `${star} out of ${max}`,
1306
+ onClick: () => onChange == null ? void 0 : onChange(star),
1307
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IconStar, { className: cn("h-6 w-6", active ? "text-amber-500" : "text-ph-border") })
1308
+ },
1309
+ star
1310
+ );
1311
+ })
1312
+ }
1313
+ )
1314
+ ] });
1315
+ }
1316
+
1317
+ // src/components/ui/SearchInput.tsx
1318
+ var import_react2 = require("react");
1319
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1320
+ function SearchInput({
1321
+ id: idProp,
1322
+ label = "Search",
1323
+ hideLabel = false,
1324
+ shortcut,
1325
+ density = "default",
1326
+ className,
1327
+ wrapperClassName,
1328
+ placeholder,
1329
+ ...props
1330
+ }) {
1331
+ const autoId = (0, import_react2.useId)();
1332
+ const id = idProp ?? autoId;
1333
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cn("relative", wrapperClassName), children: [
1334
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { htmlFor: id, className: hideLabel ? "sr-only" : "ph-label mb-1.5 block", children: label }),
1335
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative", children: [
1336
+ shortcut != null ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1337
+ "span",
1338
+ {
1339
+ className: "ph-shortcut pointer-events-none absolute left-3 top-1/2 z-10 -translate-y-1/2 text-xs",
1340
+ "aria-hidden": true,
1341
+ children: shortcut
1342
+ }
1343
+ ) : null,
1344
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1345
+ "input",
1346
+ {
1347
+ id,
1348
+ type: "search",
1349
+ placeholder,
1350
+ "aria-label": hideLabel ? label : void 0,
1351
+ className: cn(
1352
+ "ph-input w-full",
1353
+ density === "compact" && "max-w-xs !min-h-[2rem] py-1.5 text-sm",
1354
+ shortcut != null && "pl-[3.25rem]",
1355
+ className
1356
+ ),
1357
+ ...props
1358
+ }
1359
+ )
1360
+ ] })
1361
+ ] });
1362
+ }
1363
+ function SearchGroup({
1364
+ id: idProp,
1365
+ label = "Search records",
1366
+ submitLabel = "Search",
1367
+ placeholder = "Persons, actions, flags\u2026",
1368
+ wrapperClassName,
1369
+ className,
1370
+ ...props
1371
+ }) {
1372
+ const autoId = (0, import_react2.useId)();
1373
+ const id = idProp ?? autoId;
1374
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cn("ph-field", wrapperClassName), children: [
1375
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { htmlFor: id, className: "ph-label", children: label }),
1376
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "ph-search-group flex w-full max-w-lg min-h-[2.3125rem] items-stretch divide-x divide-ph-border", children: [
1377
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1378
+ "input",
1379
+ {
1380
+ id,
1381
+ type: "search",
1382
+ placeholder,
1383
+ className: cn("ph-input ph-input-group-field min-w-0 flex-1", className),
1384
+ ...props
1385
+ }
1386
+ ),
1387
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1388
+ Button,
1389
+ {
1390
+ type: "submit",
1391
+ variant: "primary",
1392
+ icon: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconSearch, { className: "h-4 w-4", "aria-hidden": true }),
1393
+ className: "ph-search-group__submit",
1394
+ "aria-label": submitLabel
1395
+ }
1396
+ )
1397
+ ] })
1398
+ ] });
1399
+ }
1400
+
1401
+ // src/components/ui/Table.tsx
1402
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1403
+ function Table({
1404
+ data,
1405
+ columns,
1406
+ zebra = false,
1407
+ compact = false,
1408
+ ribbon = false,
1409
+ getRowStyle,
1410
+ className,
1411
+ caption
1412
+ }) {
1413
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: cn("ph-table-wrap", compact && "ph-table-compact", className), children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("table", { className: cn("ph-table", zebra && "ph-table-zebra", ribbon && "ph-table--ribbon"), children: [
1414
+ caption && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("caption", { className: "sr-only", children: caption }),
1415
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("tr", { children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("th", { className: col.className, children: col.header }, col.key)) }) }),
1416
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("tbody", { children: data.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("tr", { style: getRowStyle == null ? void 0 : getRowStyle(row), children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("td", { className: col.className, children: col.cell(row) }, col.key)) }, i)) })
1417
+ ] }) });
1418
+ }
1419
+
1420
+ // src/components/ui/Stat.tsx
1421
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1422
+ var toneMap = {
1423
+ default: "text-ph-ink",
1424
+ brand: "text-ph-brand",
1425
+ blue: "text-ph-blue",
1426
+ purple: "text-ph-purple",
1427
+ warning: "text-amber-900"
1428
+ };
1429
+ var statMap = {
1430
+ default: "",
1431
+ brand: "",
1432
+ blue: "",
1433
+ purple: "",
1434
+ warning: "border-amber-200 bg-amber-50/70"
1435
+ };
1436
+ function Stat({ icon, label, value, footer, tone = "default", className, ...props }) {
1437
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("article", { className: cn("ph-stat", statMap[tone], className), ...props, children: [
1438
+ icon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("mb-2 h-7 w-7", toneMap[tone]), children: icon }),
1439
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("ph-stat-label", tone === "warning" && toneMap[tone]), children: label }),
1440
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("ph-stat-val", toneMap[tone]), children: value }),
1441
+ footer && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-xs text-ph-subtle", children: footer })
1442
+ ] });
1443
+ }
1444
+
1445
+ // src/components/ui/Toast.tsx
1446
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1447
+ var statusConfig2 = {
1448
+ info: { icon: IconErrorOutline, color: "text-ph-info", bg: "ph-toast-info" },
1449
+ success: { icon: IconCheckCircle, color: "text-ph-success", bg: "ph-toast-success" },
1450
+ warning: { icon: IconExclamation, color: "text-ph-warning", bg: "ph-toast-warning" },
1451
+ danger: { icon: IconCancel, color: "text-ph-danger", bg: "ph-toast-danger" }
1452
+ };
1453
+ function Toast({
1454
+ status = "info",
1455
+ title,
1456
+ description,
1457
+ onDismiss,
1458
+ className
1459
+ }) {
1460
+ const config = statusConfig2[status];
1461
+ const Icon = config.icon;
1462
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("ph-toast", config.bg, className), children: [
1463
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, { className: cn("mt-0.5 h-5 w-5 shrink-0", config.color), "aria-hidden": true }),
1464
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "pr-8", children: [
1465
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "font-semibold", children: title }),
1466
+ description && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1 text-xs text-ph-subtle", children: description })
1467
+ ] }),
1468
+ onDismiss && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1469
+ "button",
1470
+ {
1471
+ type: "button",
1472
+ "aria-label": `Dismiss ${title}`,
1473
+ className: "absolute right-2 top-2 ph-btn ph-btn-ghost ph-btn-xs ph-btn-circle",
1474
+ onClick: onDismiss,
1475
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(IconClose, { className: "h-4 w-4" })
1476
+ }
1477
+ )
1478
+ ] });
1479
+ }
1480
+ function ToastStack({ children, className }) {
1481
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("ph-toast-stack", className), children });
1482
+ }
1483
+
1484
+ // src/components/ui/Tabs.tsx
1485
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1486
+ function Tabs({ items, value, onChange, variant = "pill", className }) {
1487
+ if (variant === "underline") {
1488
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn("flex gap-6 border-b border-ph-border", className), children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1489
+ "button",
1490
+ {
1491
+ type: "button",
1492
+ onClick: () => onChange(item.value),
1493
+ className: cn(
1494
+ "-mb-px border-b-2 pb-2 text-sm font-semibold transition",
1495
+ value === item.value ? "border-ph-brand text-ph-ink" : "border-transparent text-ph-mutedtext hover:text-ph-ink"
1496
+ ),
1497
+ children: item.label
1498
+ },
1499
+ item.value
1500
+ )) });
1501
+ }
1502
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn("ph-tabs-row inline-flex", className), children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1503
+ "button",
1504
+ {
1505
+ type: "button",
1506
+ onClick: () => onChange(item.value),
1507
+ className: cn("ph-tab", value === item.value && "ph-tab-active"),
1508
+ children: item.label
1509
+ },
1510
+ item.value
1511
+ )) });
1512
+ }
1513
+
1514
+ // src/components/ui/ThemeDomSync.tsx
1515
+ var import_react3 = require("react");
1516
+
1517
+ // src/themes/registry.ts
1518
+ var DEFAULT_THEME_ID = "hedgehog-light";
1519
+ var THEMES = [
1520
+ {
1521
+ id: "hedgehog-light",
1522
+ name: "HedgeHog Light",
1523
+ description: "Default Quill warm greys and orange Lemon chrome.",
1524
+ colorScheme: "light",
1525
+ group: "HedgeHog"
1526
+ },
1527
+ {
1528
+ id: "hedgehog-dark",
1529
+ name: "HedgeHog Dark",
1530
+ description: "Dark app shell with HedgeHog orange accents.",
1531
+ colorScheme: "dark",
1532
+ group: "HedgeHog"
1533
+ },
1534
+ {
1535
+ id: "catppuccin-light",
1536
+ name: "Catppuccin Light",
1537
+ description: "Catppuccin Latte \u2014 soft pastels and mauve accent.",
1538
+ colorScheme: "light",
1539
+ group: "Catppuccin"
1540
+ },
1541
+ {
1542
+ id: "catppuccin-dark",
1543
+ name: "Catppuccin Dark",
1544
+ description: "Catppuccin Mocha \u2014 deep base and lavender peach.",
1545
+ colorScheme: "dark",
1546
+ group: "Catppuccin"
1547
+ },
1548
+ {
1549
+ id: "sheets",
1550
+ name: "Sheets",
1551
+ description: "Spreadsheet green on office neutrals.",
1552
+ colorScheme: "light",
1553
+ group: "Productivity"
1554
+ },
1555
+ {
1556
+ id: "sheets-dark",
1557
+ name: "Sheets Dark",
1558
+ description: "Dark shell with spreadsheet green accent.",
1559
+ colorScheme: "dark",
1560
+ group: "Productivity"
1561
+ },
1562
+ {
1563
+ id: "note",
1564
+ name: "Note",
1565
+ description: "Notebook purple on lavender-white chrome.",
1566
+ colorScheme: "light",
1567
+ group: "Productivity"
1568
+ },
1569
+ {
1570
+ id: "note-dark",
1571
+ name: "Note Dark",
1572
+ description: "Dark notebook purple \u2014 night reading mode.",
1573
+ colorScheme: "dark",
1574
+ group: "Productivity"
1575
+ },
1576
+ {
1577
+ id: "presentation",
1578
+ name: "Presentation",
1579
+ description: "Orange-red on office neutrals.",
1580
+ colorScheme: "light",
1581
+ group: "Productivity"
1582
+ },
1583
+ {
1584
+ id: "presentation-dark",
1585
+ name: "Presentation Dark",
1586
+ description: "Dark shell with orange-red accent.",
1587
+ colorScheme: "dark",
1588
+ group: "Productivity"
1589
+ },
1590
+ {
1591
+ id: "socials",
1592
+ name: "Socials",
1593
+ description: "Meta blue accent on familiar social greys.",
1594
+ colorScheme: "light",
1595
+ group: "Social"
1596
+ },
1597
+ {
1598
+ id: "socials-dark",
1599
+ name: "Socials Dark",
1600
+ description: "Social dark mode \u2014 #18191A base and Meta blue.",
1601
+ colorScheme: "dark",
1602
+ group: "Social"
1603
+ },
1604
+ {
1605
+ id: "chats-light",
1606
+ name: "Chats Light",
1607
+ description: "Aubergine brand on clean workspace neutrals.",
1608
+ colorScheme: "light",
1609
+ group: "Chats"
1610
+ },
1611
+ {
1612
+ id: "chats-dark",
1613
+ name: "Chats Dark",
1614
+ description: "Dark sidebar \u2014 #1A1D21 base and green highlights.",
1615
+ colorScheme: "dark",
1616
+ group: "Chats"
1617
+ },
1618
+ {
1619
+ id: "xenide-light",
1620
+ name: "Xenide Light",
1621
+ description: "xenide.io light \u2014 Excel green + purple on neutral greys.",
1622
+ colorScheme: "light",
1623
+ group: "Xenide"
1624
+ },
1625
+ {
1626
+ id: "xenide-dark",
1627
+ name: "Xenide Dark",
1628
+ description: "xenide.io dark \u2014 #0A0A0F base, emerald green + violet.",
1629
+ colorScheme: "dark",
1630
+ group: "Xenide"
1631
+ },
1632
+ {
1633
+ id: "bikini-bottom",
1634
+ name: "Bikini Bottom",
1635
+ description: "SpongeBob palette \u2014 ocean canvas, readable surfaces, character accents.",
1636
+ colorScheme: "light",
1637
+ group: "Fun"
1638
+ },
1639
+ {
1640
+ id: "bikini-bottom-dark",
1641
+ name: "Bikini Bottom Dark",
1642
+ description: "Bikini Bottom at night \u2014 deep ocean with neon character accents.",
1643
+ colorScheme: "dark",
1644
+ group: "Fun"
1645
+ },
1646
+ {
1647
+ id: "turtletime",
1648
+ name: "TurtleTime",
1649
+ description: "Turtle mascot palette \u2014 shell orange, leaf green, and warm cream.",
1650
+ colorScheme: "light",
1651
+ group: "Fun"
1652
+ },
1653
+ {
1654
+ id: "turtletime-dark",
1655
+ name: "TurtleTime Dark",
1656
+ description: "TurtleTime after dusk \u2014 dark olive shell with bright orange clock accents.",
1657
+ colorScheme: "dark",
1658
+ group: "Fun"
1659
+ },
1660
+ {
1661
+ id: "github-light",
1662
+ name: "GitHub Light",
1663
+ description: "GitHub Primer \u2014 #f6f8fa canvas and emphasis blue accents.",
1664
+ colorScheme: "light",
1665
+ group: "GitHub"
1666
+ },
1667
+ {
1668
+ id: "github-dark",
1669
+ name: "GitHub Dark",
1670
+ description: "GitHub dark dimmed \u2014 #0d1117 base and #4493f8 links.",
1671
+ colorScheme: "dark",
1672
+ group: "GitHub"
1673
+ },
1674
+ {
1675
+ id: "rosepine-light",
1676
+ name: "Ros\xE9 Pine Dawn",
1677
+ description: "Ros\xE9 Pine Dawn \u2014 warm paper base with muted iris accents.",
1678
+ colorScheme: "light",
1679
+ group: "Ros\xE9 Pine"
1680
+ },
1681
+ {
1682
+ id: "rosepine-dark",
1683
+ name: "Ros\xE9 Pine",
1684
+ description: "Ros\xE9 Pine Main \u2014 moonlit base with iris and love accents.",
1685
+ colorScheme: "dark",
1686
+ group: "Ros\xE9 Pine"
1687
+ }
1688
+ ];
1689
+ var THEME_GROUPS = Array.from(new Set(THEMES.map((theme) => theme.group)));
1690
+ function isThemeId(value) {
1691
+ return THEMES.some((theme) => theme.id === value);
1692
+ }
1693
+ function getTheme(id) {
1694
+ return THEMES.find((theme) => theme.id === id);
1695
+ }
1696
+
1697
+ // src/themes/init-theme.ts
1698
+ var STORAGE_KEY = "ph-theme";
1699
+ var VALID_THEMES = THEMES.map((theme) => theme.id);
1700
+ var THEME_INIT_SCRIPT = `(function(){try{var k="${STORAGE_KEY}",d="${DEFAULT_THEME_ID}",v=${JSON.stringify(VALID_THEMES)},t=localStorage.getItem(k);if(t==="xenide")t="xenide-light";if(!t||v.indexOf(t)<0)t=d;document.documentElement.setAttribute("data-theme",t)}catch(e){document.documentElement.setAttribute("data-theme","${DEFAULT_THEME_ID}")}})();`;
1701
+ function persistTheme(themeId) {
1702
+ if (typeof window === "undefined") {
1703
+ return;
1704
+ }
1705
+ if (!isThemeId(themeId)) {
1706
+ return;
1707
+ }
1708
+ document.documentElement.setAttribute("data-theme", themeId);
1709
+ localStorage.setItem(STORAGE_KEY, themeId);
1710
+ }
1711
+ function readStoredTheme() {
1712
+ if (typeof window === "undefined") {
1713
+ return DEFAULT_THEME_ID;
1714
+ }
1715
+ const stored = localStorage.getItem(STORAGE_KEY);
1716
+ if (stored === "xenide") {
1717
+ return "xenide-light";
1718
+ }
1719
+ return stored && isThemeId(stored) ? stored : DEFAULT_THEME_ID;
1720
+ }
1721
+
1722
+ // src/components/ui/ThemeDomSync.tsx
1723
+ function ThemeDomSync() {
1724
+ (0, import_react3.useLayoutEffect)(() => {
1725
+ persistTheme(readStoredTheme());
1726
+ }, []);
1727
+ return null;
1728
+ }
1729
+
1730
+ // src/components/ui/ThemeManager.tsx
1731
+ var import_react4 = require("react");
1732
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1733
+ function ThemeManager({ children }) {
1734
+ (0, import_react4.useLayoutEffect)(() => {
1735
+ persistTheme(readStoredTheme());
1736
+ }, []);
1737
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_jsx_runtime22.Fragment, { children });
1738
+ }
1739
+
1740
+ // src/components/ui/ThemeSwitcher.tsx
1741
+ var import_react5 = require("react");
1742
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1743
+ function ThemeSwitcher({ className }) {
1744
+ const [themeId, setThemeId] = (0, import_react5.useState)("hedgehog-light");
1745
+ (0, import_react5.useEffect)(() => {
1746
+ const id = readStoredTheme();
1747
+ persistTheme(id);
1748
+ setThemeId(id);
1749
+ }, []);
1750
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: cn("flex min-w-0 items-center gap-2", className), children: [
1751
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "shrink-0 text-xs font-medium text-ph-mutedtext sm:text-sm", children: "Theme" }),
1752
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1753
+ "select",
1754
+ {
1755
+ className: "ph-select max-w-[11rem] !min-h-[2rem] py-1 pl-2.5 pr-8 text-xs sm:max-w-[14rem] sm:text-sm",
1756
+ value: themeId,
1757
+ "aria-label": "Colour theme",
1758
+ onChange: (event) => {
1759
+ const next = event.target.value;
1760
+ persistTheme(next);
1761
+ setThemeId(next);
1762
+ },
1763
+ children: THEME_GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("optgroup", { label: group, children: THEMES.filter((theme) => theme.group === group).map((theme) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: theme.id, children: theme.name }, theme.id)) }, group))
1764
+ }
1765
+ )
1766
+ ] });
1767
+ }
1768
+
1769
+ // src/components/ui/Accordion.tsx
1770
+ var import_react6 = require("react");
1771
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1772
+ function Accordion({
1773
+ items,
1774
+ allowMultiple = false,
1775
+ defaultOpen = [],
1776
+ className
1777
+ }) {
1778
+ const [openItems, setOpenItems] = (0, import_react6.useState)(new Set(defaultOpen));
1779
+ const toggleItem = (id) => {
1780
+ setOpenItems((prev) => {
1781
+ const next = new Set(prev);
1782
+ if (next.has(id)) {
1783
+ next.delete(id);
1784
+ } else {
1785
+ if (!allowMultiple) {
1786
+ next.clear();
1787
+ }
1788
+ next.add(id);
1789
+ }
1790
+ return next;
1791
+ });
1792
+ };
1793
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("divide-y divide-ph-border rounded-xl border border-ph-border bg-ph-surface", className), children: items.map((item) => {
1794
+ const isOpen = openItems.has(item.id);
1795
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "first:rounded-t-xl last:rounded-b-xl", children: [
1796
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
1797
+ "button",
1798
+ {
1799
+ type: "button",
1800
+ onClick: () => toggleItem(item.id),
1801
+ className: "flex w-full items-center justify-between px-5 py-4 text-left transition hover:bg-ph-muted",
1802
+ children: [
1803
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-ph-ink", children: item.title }),
1804
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1805
+ IconChevronDown,
1806
+ {
1807
+ className: cn(
1808
+ "h-5 w-5 text-ph-mutedtext transition-transform duration-200",
1809
+ isOpen && "rotate-180"
1810
+ )
1811
+ }
1812
+ )
1813
+ ]
1814
+ }
1815
+ ),
1816
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1817
+ "div",
1818
+ {
1819
+ className: cn(
1820
+ "grid transition-all duration-200",
1821
+ isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
1822
+ ),
1823
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "px-5 pb-4 text-ph-subtle", children: item.content }) })
1824
+ }
1825
+ )
1826
+ ] }, item.id);
1827
+ }) });
1828
+ }
1829
+
1830
+ // src/components/ui/Stepper.tsx
1831
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1832
+ function Stepper({ steps, currentStep, className }) {
1833
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: cn("flex items-start gap-2", className), children: steps.map((step, index) => {
1834
+ const isCompleted = index < currentStep;
1835
+ const isCurrent = index === currentStep;
1836
+ const isPending = index > currentStep;
1837
+ const isError = step.status === "error";
1838
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-1 items-start gap-2", children: [
1839
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-1 flex-col items-center", children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1841
+ "div",
1842
+ {
1843
+ className: cn(
1844
+ "flex h-9 w-9 items-center justify-center rounded-full text-sm font-bold transition-colors",
1845
+ isCompleted && "bg-ph-success text-white",
1846
+ isCurrent && !isError && "bg-ph-brand text-white ring-4 ring-ph-brand/20",
1847
+ isCurrent && isError && "bg-ph-danger text-white",
1848
+ isPending && "bg-ph-muted text-ph-mutedtext"
1849
+ ),
1850
+ children: isCompleted ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M5 13l4 4L19 7" }) }) : index + 1
1851
+ }
1852
+ ),
1853
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "mt-2 text-center", children: [
1854
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1855
+ "p",
1856
+ {
1857
+ className: cn(
1858
+ "text-sm font-semibold",
1859
+ isCurrent && "text-ph-ink",
1860
+ !isCurrent && "text-ph-mutedtext"
1861
+ ),
1862
+ children: step.label
1863
+ }
1864
+ ),
1865
+ step.description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "mt-0.5 text-xs text-ph-mutedtext", children: step.description })
1866
+ ] })
1867
+ ] }),
1868
+ index < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1869
+ "div",
1870
+ {
1871
+ className: cn(
1872
+ "mt-4 h-0.5 flex-1 rounded-full transition-colors",
1873
+ isCompleted ? "bg-ph-success" : "bg-ph-border"
1874
+ )
1875
+ }
1876
+ )
1877
+ ] }, step.id);
1878
+ }) });
1879
+ }
1880
+
1881
+ // src/components/ui/SegmentedControl.tsx
1882
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1883
+ function SegmentedControl({ options, value, onChange, className }) {
1884
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1885
+ "div",
1886
+ {
1887
+ className: cn(
1888
+ "inline-flex rounded-lg bg-ph-muted p-1",
1889
+ className
1890
+ ),
1891
+ children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
1892
+ "button",
1893
+ {
1894
+ type: "button",
1895
+ onClick: () => onChange(option.value),
1896
+ className: cn(
1897
+ "relative flex items-center gap-1.5 rounded-md px-3.5 py-1.5 text-sm font-medium transition-all",
1898
+ value === option.value ? "bg-ph-surface text-ph-ink shadow-ph" : "text-ph-subtle hover:text-ph-ink"
1899
+ ),
1900
+ children: [
1901
+ option.icon && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "h-4 w-4", children: option.icon }),
1902
+ option.label
1903
+ ]
1904
+ },
1905
+ option.value
1906
+ ))
1907
+ }
1908
+ );
1909
+ }
1910
+
1911
+ // src/components/ui/CommandPalette.tsx
1912
+ var import_react7 = require("react");
1913
+ var import_jsx_runtime27 = require("react/jsx-runtime");
1914
+ function CommandPalette({
1915
+ items,
1916
+ isOpen,
1917
+ onClose,
1918
+ placeholder = "Type a command or search...",
1919
+ className
1920
+ }) {
1921
+ const [query, setQuery] = (0, import_react7.useState)("");
1922
+ const [selectedIndex, setSelectedIndex] = (0, import_react7.useState)(0);
1923
+ const inputRef = (0, import_react7.useRef)(null);
1924
+ const filtered = items.filter(
1925
+ (item) => item.label.toLowerCase().includes(query.toLowerCase())
1926
+ );
1927
+ (0, import_react7.useEffect)(() => {
1928
+ var _a;
1929
+ if (isOpen) {
1930
+ setQuery("");
1931
+ setSelectedIndex(0);
1932
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1933
+ }
1934
+ }, [isOpen]);
1935
+ (0, import_react7.useEffect)(() => {
1936
+ const handleKeyDown = (e) => {
1937
+ var _a;
1938
+ if (!isOpen) return;
1939
+ switch (e.key) {
1940
+ case "ArrowDown":
1941
+ e.preventDefault();
1942
+ setSelectedIndex((i) => (i + 1) % filtered.length);
1943
+ break;
1944
+ case "ArrowUp":
1945
+ e.preventDefault();
1946
+ setSelectedIndex((i) => (i - 1 + filtered.length) % filtered.length);
1947
+ break;
1948
+ case "Enter":
1949
+ e.preventDefault();
1950
+ (_a = filtered[selectedIndex]) == null ? void 0 : _a.onSelect();
1951
+ onClose();
1952
+ break;
1953
+ case "Escape":
1954
+ onClose();
1955
+ break;
1956
+ }
1957
+ };
1958
+ window.addEventListener("keydown", handleKeyDown);
1959
+ return () => window.removeEventListener("keydown", handleKeyDown);
1960
+ }, [isOpen, filtered, selectedIndex, onClose]);
1961
+ if (!isOpen) return null;
1962
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "fixed inset-0 z-50 flex items-start justify-center bg-black/40 pt-[20vh] backdrop-blur-sm", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1963
+ "div",
1964
+ {
1965
+ className: cn(
1966
+ "w-full max-w-xl overflow-hidden rounded-xl border border-ph-border bg-ph-surface shadow-ph-md",
1967
+ className
1968
+ ),
1969
+ children: [
1970
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-3 border-b border-ph-border px-4 py-3", children: [
1971
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(IconSearch, { className: "h-5 w-5 text-ph-mutedtext" }),
1972
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
1973
+ "input",
1974
+ {
1975
+ ref: inputRef,
1976
+ type: "text",
1977
+ value: query,
1978
+ onChange: (e) => {
1979
+ setQuery(e.target.value);
1980
+ setSelectedIndex(0);
1981
+ },
1982
+ placeholder,
1983
+ className: "flex-1 bg-transparent text-ph-ink outline-none placeholder:text-ph-mutedtext"
1984
+ }
1985
+ ),
1986
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("kbd", { className: "rounded border border-ph-border bg-ph-muted px-1.5 py-0.5 text-xs text-ph-mutedtext", children: "ESC" })
1987
+ ] }),
1988
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "max-h-[50vh] overflow-y-auto py-2", children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "px-4 py-8 text-center text-sm text-ph-mutedtext", children: "No results found." }) : filtered.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
1989
+ "button",
1990
+ {
1991
+ type: "button",
1992
+ onClick: () => {
1993
+ item.onSelect();
1994
+ onClose();
1995
+ },
1996
+ onMouseEnter: () => setSelectedIndex(index),
1997
+ className: cn(
1998
+ "flex w-full items-center gap-3 px-4 py-2.5 text-left text-sm transition-colors",
1999
+ index === selectedIndex ? "bg-ph-muted text-ph-ink" : "text-ph-subtle"
2000
+ ),
2001
+ children: [
2002
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "h-5 w-5", children: item.icon }),
2003
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "flex-1", children: item.label }),
2004
+ item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("kbd", { className: "rounded border border-ph-border bg-ph-surface px-1.5 py-0.5 text-xs text-ph-mutedtext", children: item.shortcut })
2005
+ ]
2006
+ },
2007
+ item.id
2008
+ )) })
2009
+ ]
2010
+ }
2011
+ ) });
2012
+ }
2013
+
2014
+ // src/components/ui/Calendar.tsx
2015
+ var import_react8 = require("react");
2016
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2017
+ function Calendar({ value, onChange, className }) {
2018
+ const [currentMonth, setCurrentMonth] = (0, import_react8.useState)(value || /* @__PURE__ */ new Date());
2019
+ const today = /* @__PURE__ */ new Date();
2020
+ const year = currentMonth.getFullYear();
2021
+ const month = currentMonth.getMonth();
2022
+ const firstDay = new Date(year, month, 1).getDay();
2023
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
2024
+ const prevMonth = () => setCurrentMonth(new Date(year, month - 1, 1));
2025
+ const nextMonth = () => setCurrentMonth(new Date(year, month + 1, 1));
2026
+ const monthNames = [
2027
+ "January",
2028
+ "February",
2029
+ "March",
2030
+ "April",
2031
+ "May",
2032
+ "June",
2033
+ "July",
2034
+ "August",
2035
+ "September",
2036
+ "October",
2037
+ "November",
2038
+ "December"
2039
+ ];
2040
+ const weekDays = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
2041
+ const isSelected = (day) => {
2042
+ if (!value) return false;
2043
+ return value.getDate() === day && value.getMonth() === month && value.getFullYear() === year;
2044
+ };
2045
+ const isToday = (day) => {
2046
+ return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year;
2047
+ };
2048
+ const handleSelect = (day) => {
2049
+ onChange == null ? void 0 : onChange(new Date(year, month, day));
2050
+ };
2051
+ const days = [];
2052
+ for (let i = 0; i < firstDay; i++) {
2053
+ days.push(null);
2054
+ }
2055
+ for (let i = 1; i <= daysInMonth; i++) {
2056
+ days.push(i);
2057
+ }
2058
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cn("w-[280px] rounded-xl border border-ph-border bg-ph-surface p-4 shadow-ph", className), children: [
2059
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "mb-4 flex items-center justify-between", children: [
2060
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2061
+ "button",
2062
+ {
2063
+ type: "button",
2064
+ onClick: prevMonth,
2065
+ className: "rounded-lg p-1 text-ph-subtle transition hover:bg-ph-muted hover:text-ph-ink",
2066
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M15 18l-6-6 6-6" }) })
2067
+ }
2068
+ ),
2069
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "text-sm font-semibold text-ph-ink", children: [
2070
+ monthNames[month],
2071
+ " ",
2072
+ year
2073
+ ] }),
2074
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2075
+ "button",
2076
+ {
2077
+ type: "button",
2078
+ onClick: nextMonth,
2079
+ className: "rounded-lg p-1 text-ph-subtle transition hover:bg-ph-muted hover:text-ph-ink",
2080
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { d: "M9 18l6-6-6-6" }) })
2081
+ }
2082
+ )
2083
+ ] }),
2084
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "grid grid-cols-7 gap-1", children: [
2085
+ weekDays.map((day) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "py-1 text-center text-xs font-medium text-ph-mutedtext", children: day }, day)),
2086
+ days.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "aspect-square", children: day && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2087
+ "button",
2088
+ {
2089
+ type: "button",
2090
+ onClick: () => handleSelect(day),
2091
+ className: cn(
2092
+ "flex h-full w-full items-center justify-center rounded-lg text-sm transition-colors",
2093
+ isSelected(day) ? "bg-ph-brand font-semibold text-white shadow-ph" : isToday(day) ? "bg-ph-muted font-semibold text-ph-brand ring-1 ring-ph-brand/30" : "text-ph-ink hover:bg-ph-muted"
2094
+ ),
2095
+ children: day
2096
+ }
2097
+ ) }, index))
2098
+ ] })
2099
+ ] });
2100
+ }
2101
+
2102
+ // src/components/ui/HoverCard.tsx
2103
+ var import_react9 = require("react");
2104
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2105
+ function HoverCard({ trigger, children, className }) {
2106
+ const [isVisible, setIsVisible] = (0, import_react9.useState)(false);
2107
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
2108
+ "div",
2109
+ {
2110
+ className: "relative inline-block",
2111
+ onMouseEnter: () => setIsVisible(true),
2112
+ onMouseLeave: () => setIsVisible(false),
2113
+ children: [
2114
+ trigger,
2115
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
2116
+ "div",
2117
+ {
2118
+ className: cn(
2119
+ "absolute left-1/2 top-full z-50 mt-2 w-64 -translate-x-1/2 rounded-lg border border-ph-border bg-ph-surface p-4 shadow-ph-md transition-all duration-150",
2120
+ isVisible ? "visible translate-y-0 opacity-100" : "invisible -translate-y-1 opacity-0",
2121
+ className
2122
+ ),
2123
+ children: [
2124
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "absolute -top-1.5 left-1/2 h-3 w-3 -translate-x-1/2 rotate-45 border-l border-t border-ph-border bg-ph-surface" }),
2125
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "relative", children })
2126
+ ]
2127
+ }
2128
+ )
2129
+ ]
2130
+ }
2131
+ );
2132
+ }
2133
+
2134
+ // src/components/ui/EmptyState.tsx
2135
+ var import_jsx_runtime30 = require("react/jsx-runtime");
2136
+ function EmptyState({ icon, title, description, action, className }) {
2137
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
2138
+ "div",
2139
+ {
2140
+ className: cn(
2141
+ "flex flex-col items-center justify-center rounded-xl border border-dashed border-ph-border bg-ph-muted/50 px-8 py-16 text-center",
2142
+ className
2143
+ ),
2144
+ children: [
2145
+ icon && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-ph-muted text-ph-mutedtext", children: icon }),
2146
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h3", { className: "text-base font-semibold text-ph-ink", children: title }),
2147
+ description && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "mt-1 max-w-sm text-sm text-ph-subtle", children: description }),
2148
+ action && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "mt-4", children: action })
2149
+ ]
2150
+ }
2151
+ );
2152
+ }
2153
+
2154
+ // src/components/ui/FilterChips.tsx
2155
+ var import_jsx_runtime31 = require("react/jsx-runtime");
2156
+ function FilterChips({ chips, onToggle, onRemove, className }) {
2157
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn("flex flex-wrap gap-2", className), children: chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
2158
+ "button",
2159
+ {
2160
+ type: "button",
2161
+ onClick: () => onToggle(chip.id),
2162
+ className: cn(
2163
+ "inline-flex items-center gap-1.5 rounded-full px-3 py-1.5 text-sm font-medium transition-colors",
2164
+ chip.active ? "bg-ph-brand text-white" : "bg-ph-muted text-ph-subtle hover:bg-ph-border hover:text-ph-ink"
2165
+ ),
2166
+ children: [
2167
+ chip.label,
2168
+ chip.active && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
2169
+ "span",
2170
+ {
2171
+ onClick: (e) => {
2172
+ e.stopPropagation();
2173
+ onRemove(chip.id);
2174
+ },
2175
+ className: "ml-0.5 flex h-4 w-4 cursor-pointer items-center justify-center rounded-full hover:bg-white/20",
2176
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(IconClose, { className: "h-3 w-3" })
2177
+ }
2178
+ )
2179
+ ]
2180
+ },
2181
+ chip.id
2182
+ )) });
2183
+ }
2184
+
2185
+ // src/components/ui/CodeBlock.tsx
2186
+ var import_react10 = require("react");
2187
+ var import_jsx_runtime32 = require("react/jsx-runtime");
2188
+ function CodeBlock({ code, language = "tsx", filename, className }) {
2189
+ const [copied, setCopied] = (0, import_react10.useState)(false);
2190
+ const handleCopy = async () => {
2191
+ await navigator.clipboard.writeText(code);
2192
+ setCopied(true);
2193
+ setTimeout(() => setCopied(false), 2e3);
2194
+ };
2195
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cn("overflow-hidden rounded-lg border border-ph-border bg-[#1a1a2e]", className), children: [
2196
+ (filename || language) && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between border-b border-white/10 px-4 py-2", children: [
2197
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
2198
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex gap-1.5", children: [
2199
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-3 w-3 rounded-full bg-red-400" }),
2200
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-3 w-3 rounded-full bg-amber-400" }),
2201
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-3 w-3 rounded-full bg-emerald-400" })
2202
+ ] }),
2203
+ filename && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "ml-2 text-xs text-white/60", children: filename })
2204
+ ] }),
2205
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
2206
+ "button",
2207
+ {
2208
+ type: "button",
2209
+ onClick: handleCopy,
2210
+ className: "text-xs text-white/60 transition hover:text-white",
2211
+ children: copied ? "Copied!" : "Copy"
2212
+ }
2213
+ )
2214
+ ] }),
2215
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("pre", { className: "overflow-x-auto p-4 text-sm leading-relaxed", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("code", { className: "font-mono text-[#e4e4e7]", children: code }) })
2216
+ ] });
2217
+ }
2218
+
2219
+ // src/components/ui/ComponentDocs.tsx
2220
+ var import_jsx_runtime33 = require("react/jsx-runtime");
2221
+ function ComponentDocs({ title = "Props & variants", rows, defaultOpen = false, className }) {
2222
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("details", { className: cn("ph-panel group overflow-hidden p-0", className), open: defaultOpen, children: [
2223
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("summary", { className: "flex cursor-pointer list-none items-center justify-between gap-4 border-b border-ph-border px-4 py-3 transition hover:bg-ph-muted/60 [&::-webkit-details-marker]:hidden", children: [
2224
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("h3", { className: "text-xs font-semibold uppercase tracking-wider text-ph-mutedtext", children: title }),
2225
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "rounded-full border border-ph-border bg-ph-surface px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-ph-mutedtext transition group-open:bg-ph-brand group-open:text-white", children: [
2226
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "group-open:hidden", children: "Show" }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "hidden group-open:inline", children: "Hide" })
2228
+ ] })
2229
+ ] }),
2230
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "overflow-x-auto border-t border-ph-border", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("table", { className: "w-full text-left text-sm", children: [
2231
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("thead", { className: "bg-ph-muted text-xs uppercase tracking-wider text-ph-mutedtext", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("tr", { children: [
2232
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("th", { className: "px-4 py-2 font-semibold", children: "Prop" }),
2233
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("th", { className: "px-4 py-2 font-semibold", children: "Type" }),
2234
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("th", { className: "px-4 py-2 font-semibold", children: "Default" }),
2235
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("th", { className: "px-4 py-2 font-semibold", children: "Use" })
2236
+ ] }) }),
2237
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("tbody", { className: "divide-y divide-ph-border", children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("tr", { children: [
2238
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("td", { className: "px-4 py-3 align-top font-mono text-xs text-ph-ink", children: row.name }),
2239
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("td", { className: "px-4 py-3 align-top font-mono text-xs text-ph-subtle", children: row.type }),
2240
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("td", { className: "px-4 py-3 align-top font-mono text-xs text-ph-subtle", children: row.defaultValue ?? "-" }),
2241
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("td", { className: "px-4 py-3 align-top text-ph-subtle", children: row.description })
2242
+ ] }, row.name)) })
2243
+ ] }) })
2244
+ ] });
2245
+ }
2246
+
2247
+ // src/components/ui/ShowcaseWrapper.tsx
2248
+ var import_react11 = require("react");
2249
+ var import_jsx_runtime34 = require("react/jsx-runtime");
2250
+ function ShowcaseWrapper({
2251
+ id,
2252
+ title,
2253
+ description,
2254
+ docs,
2255
+ code,
2256
+ filename = "Example.tsx",
2257
+ children,
2258
+ className
2259
+ }) {
2260
+ const [showCode, setShowCode] = (0, import_react11.useState)(false);
2261
+ const fallbackId = titleIdMap[title] ?? title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
2262
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("section", { id: id ?? fallbackId, className: cn("scroll-mt-20", className), children: [
2263
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "ph-h2-rule mb-8", children: [
2264
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2265
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h2", { children: title }),
2266
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2267
+ "button",
2268
+ {
2269
+ type: "button",
2270
+ onClick: () => setShowCode(!showCode),
2271
+ className: cn(
2272
+ "flex h-10 w-10 items-center justify-center rounded-full border transition-all",
2273
+ showCode ? "border-ph-brand bg-ph-brand text-white shadow-lg shadow-ph-brand/25" : "border-ph-border bg-ph-surface text-ph-subtle hover:border-ph-brand hover:text-ph-brand"
2274
+ ),
2275
+ title: showCode ? "Hide code" : "Show code",
2276
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2277
+ "svg",
2278
+ {
2279
+ className: "h-5 w-5",
2280
+ viewBox: "0 0 24 24",
2281
+ fill: "none",
2282
+ stroke: "currentColor",
2283
+ strokeWidth: "2",
2284
+ strokeLinecap: "round",
2285
+ strokeLinejoin: "round",
2286
+ children: [
2287
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2", ry: "2" }),
2288
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "8", y1: "21", x2: "16", y2: "21" }),
2289
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "12", y1: "17", x2: "12", y2: "21" }),
2290
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "6", y1: "8", x2: "6", y2: "8" }),
2291
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("line", { x1: "10", y1: "8", x2: "10", y2: "8" })
2292
+ ]
2293
+ }
2294
+ )
2295
+ }
2296
+ )
2297
+ ] }),
2298
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("hr", {})
2299
+ ] }),
2300
+ description && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "mb-6 text-sm text-ph-subtle", children: description }),
2301
+ docs && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mb-6", children: docs }),
2302
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2303
+ "div",
2304
+ {
2305
+ className: cn(
2306
+ "gap-6",
2307
+ showCode ? "lg:grid lg:grid-cols-[1fr,minmax(360px,420px)]" : "block"
2308
+ ),
2309
+ children: [
2310
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: cn("min-w-0", showCode && "lg:pr-2"), children }),
2311
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2312
+ "div",
2313
+ {
2314
+ className: cn(
2315
+ "transition-all duration-300",
2316
+ showCode ? "block opacity-100" : "hidden opacity-0 lg:hidden"
2317
+ ),
2318
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "sticky top-20", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(CodeBlock, { code, filename }) })
2319
+ }
2320
+ )
2321
+ ]
2322
+ }
2323
+ )
2324
+ ] });
2325
+ }
2326
+ var titleIdMap = {
2327
+ "Icons": "icons",
2328
+ "Colour tokens": "colors",
2329
+ "Buttons": "buttons",
2330
+ "Badges": "badges",
2331
+ "Alerts": "alerts",
2332
+ "Toasts": "toasts",
2333
+ "Cards": "cards",
2334
+ "Forms": "forms",
2335
+ "Inputs & Forms": "forms",
2336
+ "Tables": "tables",
2337
+ "Accordion": "accordion",
2338
+ "Calendar": "calendar",
2339
+ "Hover Card": "hovercard",
2340
+ "Modals": "modals",
2341
+ "Drawers": "drawers",
2342
+ "Navigation chrome": "navigation",
2343
+ "Navigation utilities": "utilities",
2344
+ "Stepper": "stepper",
2345
+ "Command Palette": "command",
2346
+ "Filter Chips": "filters",
2347
+ "Empty State": "emptystate",
2348
+ "Charts (PostHog-style)": "charts",
2349
+ "Dashboard shells": "dashboard",
2350
+ "Tabs": "tabs",
2351
+ "Dropdowns": "dropdowns",
2352
+ "Progress & loading": "progress",
2353
+ "Tooltip": "tooltip",
2354
+ "Avatars": "avatars",
2355
+ "Stats & conversational UI": "stats",
2356
+ "Timeline": "timeline",
2357
+ "Countdown motif": "countdown",
2358
+ "Keyboard glyphs": "kbd",
2359
+ "Icon swap": "swap",
2360
+ "Stacked surfaces": "stack",
2361
+ "Diff slider": "diff",
2362
+ "Badge hotspots": "indicator",
2363
+ "Terminal capture": "code-mockup"
2364
+ };
2365
+
2366
+ // src/components/ui/CollapsibleSection.tsx
2367
+ var import_react12 = require("react");
2368
+ var import_jsx_runtime35 = require("react/jsx-runtime");
2369
+ function CollapsibleSection({ title, children, defaultOpen = true, id }) {
2370
+ const [isOpen, setIsOpen] = (0, import_react12.useState)(defaultOpen);
2371
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { id, className: "scroll-mt-20", children: [
2372
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
2373
+ "button",
2374
+ {
2375
+ type: "button",
2376
+ onClick: () => setIsOpen(!isOpen),
2377
+ className: "mb-6 flex w-full items-center justify-between rounded-lg border border-ph-border bg-ph-muted px-5 py-4 text-left transition hover:bg-ph-muted/80",
2378
+ children: [
2379
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "text-lg font-bold text-ph-ink", children: title }),
2380
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2381
+ "svg",
2382
+ {
2383
+ className: cn(
2384
+ "h-5 w-5 text-ph-subtle transition-transform duration-200",
2385
+ isOpen && "rotate-180"
2386
+ ),
2387
+ viewBox: "0 0 24 24",
2388
+ fill: "none",
2389
+ stroke: "currentColor",
2390
+ strokeWidth: "2",
2391
+ strokeLinecap: "round",
2392
+ strokeLinejoin: "round",
2393
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("path", { d: "M6 9l6 6 6-6" })
2394
+ }
2395
+ )
2396
+ ]
2397
+ }
2398
+ ),
2399
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2400
+ "div",
2401
+ {
2402
+ className: cn(
2403
+ "overflow-hidden transition-all duration-300",
2404
+ isOpen ? "max-h-[50000px] opacity-100" : "max-h-0 opacity-0"
2405
+ ),
2406
+ children
2407
+ }
2408
+ )
2409
+ ] });
2410
+ }
2411
+
2412
+ // src/components/ui/Typography.tsx
2413
+ var import_jsx_runtime36 = require("react/jsx-runtime");
2414
+ var toneMap2 = {
2415
+ default: "text-ph-ink",
2416
+ muted: "text-ph-mutedtext",
2417
+ subtle: "text-ph-subtle",
2418
+ brand: "text-ph-brand",
2419
+ danger: "text-ph-danger",
2420
+ success: "text-ph-success",
2421
+ warning: "text-ph-warning",
2422
+ info: "text-ph-info",
2423
+ inherit: ""
2424
+ };
2425
+ var weightMap = {
2426
+ normal: "font-normal",
2427
+ medium: "font-medium",
2428
+ semibold: "font-semibold",
2429
+ bold: "font-bold",
2430
+ extrabold: "font-extrabold"
2431
+ };
2432
+ function textClass(base, tone, weight, truncate, className) {
2433
+ return cn(base, toneMap2[tone], weight && weightMap[weight], truncate && "truncate", className);
2434
+ }
2435
+ function Display({
2436
+ children,
2437
+ tone = "default",
2438
+ weight,
2439
+ truncate,
2440
+ className
2441
+ }) {
2442
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h1", { className: textClass("text-4xl font-extrabold tracking-tight md:text-5xl", tone, weight, truncate, className), children });
2443
+ }
2444
+ function H1({ children, tone = "default", weight, truncate, className }) {
2445
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h1", { className: textClass("text-3xl font-bold tracking-tight md:text-4xl", tone, weight, truncate, className), children });
2446
+ }
2447
+ function H2({ children, tone = "default", weight, truncate, className }) {
2448
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h2", { className: textClass("text-2xl font-bold tracking-tight", tone, weight, truncate, className), children });
2449
+ }
2450
+ function H3({ children, tone = "default", weight, truncate, className }) {
2451
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h3", { className: textClass("text-xl font-semibold", tone, weight, truncate, className), children });
2452
+ }
2453
+ function H4({ children, tone = "default", weight, truncate, className }) {
2454
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h4", { className: textClass("text-lg font-semibold", tone, weight, truncate, className), children });
2455
+ }
2456
+ function H5({ children, tone = "default", weight, truncate, className }) {
2457
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h5", { className: textClass("text-base font-semibold", tone, weight, truncate, className), children });
2458
+ }
2459
+ function P({ children, tone = "default", weight, truncate, className }) {
2460
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: textClass("text-base leading-relaxed", tone, weight, truncate, className), children });
2461
+ }
2462
+ function Small({ children, tone = "default", weight, truncate, className }) {
2463
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: textClass("text-sm leading-relaxed", tone, weight, truncate, className), children });
2464
+ }
2465
+ function Caption({ children, tone = "muted", weight, truncate, className }) {
2466
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: textClass("text-[11px] font-medium uppercase tracking-wider", tone, weight, truncate, className), children });
2467
+ }
2468
+ function Overline({ children, tone = "muted", weight, truncate, className }) {
2469
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: textClass("text-[10px] font-bold uppercase tracking-[0.15em]", tone, weight, truncate, className), children });
2470
+ }
2471
+ function Lead({ children, tone = "subtle", weight, truncate, className }) {
2472
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: textClass("text-lg leading-relaxed", tone, weight, truncate, className), children });
2473
+ }
2474
+ function Mono({ children, tone = "default", weight, truncate, className }) {
2475
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { className: textClass("text-sm font-mono leading-relaxed", tone, weight, truncate, className), children });
2476
+ }
2477
+ function Label({ children, tone = "default", weight, truncate, className }) {
2478
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("label", { className: textClass("text-sm font-medium", tone, weight, truncate, className), children });
2479
+ }
2480
+
2481
+ // src/components/ui/Avatar.tsx
2482
+ var import_jsx_runtime37 = require("react/jsx-runtime");
2483
+ var sizeMap5 = {
2484
+ xs: "h-8 w-8 text-[10px]",
2485
+ sm: "h-10 w-10 text-xs",
2486
+ md: "h-12 w-12 text-base",
2487
+ lg: "h-16 w-16 text-xl",
2488
+ xl: "h-24 w-24 text-3xl"
2489
+ };
2490
+ var statusMap = {
2491
+ online: "bg-emerald-500",
2492
+ offline: "bg-ph-mutedtext",
2493
+ away: "bg-amber-400",
2494
+ busy: "bg-ph-danger"
2495
+ };
2496
+ function Avatar({
2497
+ label,
2498
+ icon,
2499
+ size = "md",
2500
+ color = "bg-ph-brand text-white",
2501
+ status,
2502
+ badge,
2503
+ className,
2504
+ ...props
2505
+ }) {
2506
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn("relative inline-flex shrink-0", className), ...props, children: [
2507
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2508
+ "div",
2509
+ {
2510
+ className: cn(
2511
+ "flex items-center justify-center rounded-full border border-ph-border font-bold shadow-ph",
2512
+ sizeMap5[size],
2513
+ color
2514
+ ),
2515
+ children: icon || label
2516
+ }
2517
+ ),
2518
+ status && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2519
+ "span",
2520
+ {
2521
+ className: cn(
2522
+ "absolute bottom-0 right-1 h-2.5 w-2.5 rounded-full border-2 border-white",
2523
+ statusMap[status]
2524
+ )
2525
+ }
2526
+ ),
2527
+ badge && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "absolute -bottom-1 -right-1 flex min-w-[22px] items-center justify-center rounded-full bg-ph-brand px-1.5 py-px text-[10px] font-bold text-white", children: badge })
2528
+ ] });
2529
+ }
2530
+ function AvatarGroup({ children, max, className, ...props }) {
2531
+ const items = Array.isArray(children) ? children : [children];
2532
+ const visible = max ? items.slice(0, max) : items;
2533
+ const remaining = max ? items.length - max : 0;
2534
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn("-space-x-3 flex rtl:space-x-reverse", className), ...props, children: [
2535
+ visible,
2536
+ remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2537
+ Avatar,
2538
+ {
2539
+ label: `+${remaining}`,
2540
+ size: "md",
2541
+ color: "bg-ph-toolbar text-ph-subtle"
2542
+ }
2543
+ )
2544
+ ] });
2545
+ }
2546
+
2547
+ // src/components/ui/Progress.tsx
2548
+ var import_jsx_runtime38 = require("react/jsx-runtime");
2549
+ var sizeMap6 = {
2550
+ sm: "h-1",
2551
+ md: "h-2",
2552
+ lg: "h-3"
2553
+ };
2554
+ function Progress({
2555
+ value,
2556
+ max = 100,
2557
+ color = "bg-ph-brand",
2558
+ label,
2559
+ showPercentage = false,
2560
+ size = "md",
2561
+ className,
2562
+ ...props
2563
+ }) {
2564
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
2565
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: cn("w-full", className), ...props, children: [
2566
+ (label || showPercentage) && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "mb-1.5 flex justify-between text-sm text-ph-subtle", children: [
2567
+ label && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: label }),
2568
+ showPercentage && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "tabular-nums", children: [
2569
+ Math.round(percentage),
2570
+ "%"
2571
+ ] })
2572
+ ] }),
2573
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: cn("ph-progress", sizeMap6[size]), children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
2574
+ "div",
2575
+ {
2576
+ className: cn("ph-progress-bar", color),
2577
+ style: { width: `${percentage}%` },
2578
+ role: "progressbar",
2579
+ "aria-valuenow": value,
2580
+ "aria-valuemin": 0,
2581
+ "aria-valuemax": max
2582
+ }
2583
+ ) })
2584
+ ] });
2585
+ }
2586
+
2587
+ // src/components/ui/ChatBubble.tsx
2588
+ var import_jsx_runtime39 = require("react/jsx-runtime");
2589
+ function ChatBubble({
2590
+ children,
2591
+ avatar,
2592
+ name,
2593
+ time,
2594
+ variant = "from",
2595
+ footer,
2596
+ className,
2597
+ ...props
2598
+ }) {
2599
+ const isSelf = variant === "self";
2600
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2601
+ "div",
2602
+ {
2603
+ className: cn(
2604
+ "flex gap-3",
2605
+ isSelf && "flex-row-reverse",
2606
+ className
2607
+ ),
2608
+ ...props,
2609
+ children: [
2610
+ avatar && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "shrink-0", children: avatar }),
2611
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cn("min-w-0 flex-1", isSelf && "text-right"), children: [
2612
+ (name || time) && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
2613
+ "header",
2614
+ {
2615
+ className: cn(
2616
+ "flex gap-2 text-xs text-ph-mutedtext",
2617
+ isSelf && "flex-row-reverse justify-end"
2618
+ ),
2619
+ children: [
2620
+ name && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-semibold text-ph-ink", children: name }),
2621
+ time && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: time })
2622
+ ]
2623
+ }
2624
+ ),
2625
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
2626
+ "div",
2627
+ {
2628
+ className: cn(
2629
+ "mt-2 inline-block text-left shadow-ph",
2630
+ isSelf ? "ph-chat-self" : "ph-chat-from"
2631
+ ),
2632
+ children
2633
+ }
2634
+ ),
2635
+ footer && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("footer", { className: "mt-2 text-[11px] text-ph-mutedtext", children: footer })
2636
+ ] })
2637
+ ]
2638
+ }
2639
+ );
2640
+ }
2641
+
2642
+ // src/components/ui/Terminal.tsx
2643
+ var import_jsx_runtime40 = require("react/jsx-runtime");
2644
+ function Terminal({
2645
+ title = "sandbox",
2646
+ lines,
2647
+ children,
2648
+ className,
2649
+ ...props
2650
+ }) {
2651
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
2652
+ "div",
2653
+ {
2654
+ className: cn(
2655
+ "overflow-hidden rounded-xl border border-ph-border shadow-ph-md",
2656
+ className
2657
+ ),
2658
+ ...props,
2659
+ children: [
2660
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("header", { className: "flex items-center gap-2 border-b border-ph-border bg-ph-muted px-4 py-3", children: [
2661
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "h-3 w-3 rounded-full bg-red-400" }),
2662
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "h-3 w-3 rounded-full bg-amber-400" }),
2663
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "h-3 w-3 rounded-full bg-emerald-400" }),
2664
+ title && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "text-xs font-medium text-ph-mutedtext", children: title })
2665
+ ] }),
2666
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "ph-code rounded-none border-x-0 border-b-0 text-[13px] leading-relaxed", children: children || /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_jsx_runtime40.Fragment, { children: lines == null ? void 0 : lines.map((line, i) => {
2667
+ const text = typeof line === "string" ? line : line.text;
2668
+ const color = typeof line === "string" ? void 0 : line.color;
2669
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { children: [
2670
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: color || "text-neutral-600", children: text }),
2671
+ i < lines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("br", {})
2672
+ ] }, i);
2673
+ }) }) })
2674
+ ]
2675
+ }
2676
+ );
2677
+ }
2678
+
2679
+ // src/components/ui/Indicator.tsx
2680
+ var import_jsx_runtime41 = require("react/jsx-runtime");
2681
+ var positionMap = {
2682
+ "top-right": "-right-[2px] -top-[2px]",
2683
+ "top-left": "-left-[2px] -top-[2px]",
2684
+ "bottom-right": "-right-[2px] -bottom-[2px]",
2685
+ "bottom-left": "-left-[2px] -bottom-[2px]"
2686
+ };
2687
+ function Indicator({
2688
+ children,
2689
+ badge,
2690
+ color = "bg-ph-brand",
2691
+ position = "top-right",
2692
+ dot = false,
2693
+ className,
2694
+ ...props
2695
+ }) {
2696
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: cn("relative inline-flex items-center justify-center", className), ...props, children: [
2697
+ dot ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2698
+ "span",
2699
+ {
2700
+ className: cn(
2701
+ "absolute z-10 h-2.5 w-2.5 rounded-full border-2 border-white",
2702
+ color,
2703
+ positionMap[position]
2704
+ )
2705
+ }
2706
+ ) : badge != null ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
2707
+ "span",
2708
+ {
2709
+ className: cn(
2710
+ "absolute z-10 flex min-h-[22px] min-w-[22px] items-center justify-center rounded-full px-1 text-[11px] font-bold text-white",
2711
+ color,
2712
+ positionMap[position]
2713
+ ),
2714
+ children: badge
2715
+ }
2716
+ ) : null,
2717
+ children
2718
+ ] });
2719
+ }
2720
+
2721
+ // src/components/ui/Timeline.tsx
2722
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2723
+ function Timeline({
2724
+ events,
2725
+ alternate = false,
2726
+ className,
2727
+ ...props
2728
+ }) {
2729
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2730
+ "ol",
2731
+ {
2732
+ className: cn("relative space-y-8", className),
2733
+ ...props,
2734
+ children: events.map((event, idx) => {
2735
+ const align = alternate && idx % 2 !== 0 ? "lg:flex-row-reverse" : "";
2736
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: cn("relative flex gap-6", align), children: [
2737
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2738
+ "div",
2739
+ {
2740
+ className: cn(
2741
+ "relative z-10 flex h-12 w-12 shrink-0 items-center justify-center rounded-full ring-8 ring-ph-muted shadow-md",
2742
+ event.color || "bg-ph-brand text-white"
2743
+ ),
2744
+ children: event.icon
2745
+ }
2746
+ ),
2747
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "flex-1 rounded-xl border border-ph-border bg-ph-surface p-4 shadow-ph", children: [
2748
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap items-baseline gap-3", children: [
2749
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-base font-semibold text-ph-ink", children: event.title }),
2750
+ event.time && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("time", { className: "text-[11px] font-semibold uppercase tracking-wide text-ph-mutedtext", children: event.time })
2751
+ ] }),
2752
+ event.description && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mt-2 text-sm text-ph-subtle", children: event.description })
2753
+ ] })
2754
+ ] }, event.id);
2755
+ })
2756
+ }
2757
+ );
2758
+ }
2759
+
2760
+ // src/components/charts/ph-insight-charts.tsx
2761
+ var import_react15 = require("react");
2762
+ var import_react_chartjs_2 = require("react-chartjs-2");
2763
+
2764
+ // src/lib/chart/with-alpha.ts
2765
+ function withAlpha(color, alpha) {
2766
+ const trimmed = color.trim();
2767
+ const hex8 = trimmed.match(/^#([\da-f]{8})$/i);
2768
+ if (hex8 == null ? void 0 : hex8[1]) {
2769
+ const n = hex8[1];
2770
+ const r = parseInt(n.slice(0, 2), 16);
2771
+ const g = parseInt(n.slice(2, 4), 16);
2772
+ const b = parseInt(n.slice(4, 6), 16);
2773
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
2774
+ }
2775
+ const hexLong = trimmed.match(/^#([\da-f]{6})$/i);
2776
+ if (hexLong == null ? void 0 : hexLong[1]) {
2777
+ const n = hexLong[1];
2778
+ const r = parseInt(n.slice(0, 2), 16);
2779
+ const g = parseInt(n.slice(2, 4), 16);
2780
+ const b = parseInt(n.slice(4, 6), 16);
2781
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
2782
+ }
2783
+ const hexShort = trimmed.match(/^#([\da-f]{3})$/i);
2784
+ if (hexShort == null ? void 0 : hexShort[1]) {
2785
+ const [, h] = hexShort;
2786
+ const r = parseInt(h[0] + h[0], 16);
2787
+ const g = parseInt(h[1] + h[1], 16);
2788
+ const b = parseInt(h[2] + h[2], 16);
2789
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
2790
+ }
2791
+ return trimmed;
2792
+ }
2793
+
2794
+ // src/lib/chart/ph-chart-options.ts
2795
+ function readAppRadiusPx() {
2796
+ if (typeof document === "undefined") {
2797
+ return 6;
2798
+ }
2799
+ const raw = getComputedStyle(document.documentElement).getPropertyValue("--ph-radius-app").trim();
2800
+ const n = Number.parseFloat(raw);
2801
+ if (!Number.isFinite(n)) {
2802
+ return 6;
2803
+ }
2804
+ return raw.endsWith("rem") ? n * 16 : n;
2805
+ }
2806
+ function buildInsightLegend(tokens) {
2807
+ return {
2808
+ display: true,
2809
+ position: "bottom",
2810
+ labels: {
2811
+ color: tokens.text,
2812
+ boxWidth: 10,
2813
+ boxHeight: 10,
2814
+ padding: 14,
2815
+ usePointStyle: true,
2816
+ font: { size: 12 }
2817
+ }
2818
+ };
2819
+ }
2820
+ function buildInsightTooltipLine(tokens) {
2821
+ return {
2822
+ backgroundColor: tokens.surface,
2823
+ titleColor: tokens.text,
2824
+ bodyColor: tokens.textMuted,
2825
+ borderColor: tokens.borderStrong,
2826
+ borderWidth: 1,
2827
+ padding: 12,
2828
+ cornerRadius: readAppRadiusPx(),
2829
+ displayColors: true,
2830
+ caretPadding: 8,
2831
+ titleSpacing: 6,
2832
+ bodySpacing: 6,
2833
+ multiKeyBackground: tokens.surface
2834
+ };
2835
+ }
2836
+ function buildInsightTooltipBar(tokens) {
2837
+ return buildInsightTooltipLine(tokens);
2838
+ }
2839
+ function radialLegend(tokens) {
2840
+ return {
2841
+ display: true,
2842
+ position: "bottom",
2843
+ labels: {
2844
+ color: tokens.text,
2845
+ boxWidth: 10,
2846
+ boxHeight: 10,
2847
+ padding: 14,
2848
+ usePointStyle: true,
2849
+ font: { size: 12 }
2850
+ }
2851
+ };
2852
+ }
2853
+ function radialInsightTooltip(tokens) {
2854
+ return {
2855
+ backgroundColor: tokens.surface,
2856
+ titleColor: tokens.text,
2857
+ bodyColor: tokens.textMuted,
2858
+ borderColor: tokens.borderStrong,
2859
+ borderWidth: 1,
2860
+ padding: 12,
2861
+ cornerRadius: readAppRadiusPx(),
2862
+ displayColors: true,
2863
+ caretPadding: 8,
2864
+ titleSpacing: 6,
2865
+ bodySpacing: 6,
2866
+ multiKeyBackground: tokens.surface
2867
+ };
2868
+ }
2869
+ function buildVerticalBarDemo(tokens) {
2870
+ return {
2871
+ type: "bar",
2872
+ data: {
2873
+ labels: ["Chrome", "Safari", "Firefox", "Edge", "Other"],
2874
+ datasets: [
2875
+ {
2876
+ label: "Unique users",
2877
+ data: [18400, 12100, 4200, 3100, 900],
2878
+ backgroundColor: withAlpha(tokens.series[0], 0.85),
2879
+ borderColor: tokens.borderStrong,
2880
+ borderWidth: 1,
2881
+ borderRadius: 4
2882
+ }
2883
+ ]
2884
+ },
2885
+ options: {
2886
+ responsive: true,
2887
+ maintainAspectRatio: false,
2888
+ plugins: {
2889
+ legend: { display: false },
2890
+ tooltip: buildInsightTooltipBar(tokens)
2891
+ },
2892
+ scales: {
2893
+ x: {
2894
+ border: { display: false },
2895
+ ticks: { color: tokens.textMuted, font: { size: 11 } },
2896
+ grid: { display: false }
2897
+ },
2898
+ y: {
2899
+ beginAtZero: true,
2900
+ border: { display: false },
2901
+ ticks: { color: tokens.textMuted, font: { size: 11 } },
2902
+ grid: { color: tokens.grid }
2903
+ }
2904
+ }
2905
+ }
2906
+ };
2907
+ }
2908
+ function buildHorizontalBarDemo(tokens) {
2909
+ return {
2910
+ type: "bar",
2911
+ data: {
2912
+ labels: [
2913
+ "/project/settings",
2914
+ "/insights/new",
2915
+ "/feature-flags",
2916
+ "/dashboard",
2917
+ "/session-replay"
2918
+ ],
2919
+ datasets: [
2920
+ {
2921
+ label: "Pageviews",
2922
+ data: [12800, 9400, 7200, 6100, 4300],
2923
+ backgroundColor: [
2924
+ withAlpha(tokens.series[0], 0.85),
2925
+ withAlpha(tokens.series[1], 0.85),
2926
+ withAlpha(tokens.series[2], 0.85),
2927
+ withAlpha(tokens.series[3], 0.85),
2928
+ withAlpha(tokens.series[4], 0.85)
2929
+ ],
2930
+ borderWidth: 0,
2931
+ borderRadius: 4
2932
+ }
2933
+ ]
2934
+ },
2935
+ options: {
2936
+ indexAxis: "y",
2937
+ responsive: true,
2938
+ maintainAspectRatio: false,
2939
+ plugins: {
2940
+ legend: { display: false },
2941
+ tooltip: buildInsightTooltipBar(tokens)
2942
+ },
2943
+ scales: {
2944
+ x: {
2945
+ beginAtZero: true,
2946
+ border: { display: false },
2947
+ grid: { color: tokens.grid },
2948
+ ticks: { color: tokens.textMuted, font: { size: 11 } }
2949
+ },
2950
+ y: {
2951
+ border: { display: false },
2952
+ grid: { display: false },
2953
+ ticks: { color: tokens.textMuted, font: { size: 11 } }
2954
+ }
2955
+ }
2956
+ }
2957
+ };
2958
+ }
2959
+ function buildStackedBarDemo(tokens) {
2960
+ return {
2961
+ type: "bar",
2962
+ data: {
2963
+ labels: ["US", "GB", "DE", "AU", "IN"],
2964
+ datasets: [
2965
+ {
2966
+ label: "Direct",
2967
+ data: [120, 98, 45, 40, 210],
2968
+ backgroundColor: withAlpha(tokens.series[0], 0.92),
2969
+ borderRadius: 4
2970
+ },
2971
+ {
2972
+ label: "Organic search",
2973
+ data: [80, 72, 38, 30, 160],
2974
+ backgroundColor: withAlpha(tokens.series[1], 0.92),
2975
+ borderRadius: 4
2976
+ },
2977
+ {
2978
+ label: "Referral",
2979
+ data: [44, 22, 18, 12, 90],
2980
+ backgroundColor: withAlpha(tokens.series[2], 0.92),
2981
+ borderRadius: 4
2982
+ }
2983
+ ]
2984
+ },
2985
+ options: {
2986
+ responsive: true,
2987
+ maintainAspectRatio: false,
2988
+ plugins: {
2989
+ legend: buildInsightLegend(tokens),
2990
+ tooltip: buildInsightTooltipBar(tokens)
2991
+ },
2992
+ scales: {
2993
+ x: {
2994
+ stacked: true,
2995
+ border: { display: false },
2996
+ grid: { display: false },
2997
+ ticks: { color: tokens.textMuted, font: { size: 11 } }
2998
+ },
2999
+ y: {
3000
+ stacked: true,
3001
+ beginAtZero: true,
3002
+ border: { display: false },
3003
+ grid: { color: tokens.grid },
3004
+ ticks: { color: tokens.textMuted, font: { size: 11 } }
3005
+ }
3006
+ }
3007
+ }
3008
+ };
3009
+ }
3010
+ function buildDoughnutDemo(tokens) {
3011
+ return {
3012
+ type: "doughnut",
3013
+ data: {
3014
+ labels: ["Direct", "Organic search", "Referral", "Paid", "Other"],
3015
+ datasets: [
3016
+ {
3017
+ label: "Channel mix",
3018
+ data: [42, 28, 14, 10, 6],
3019
+ backgroundColor: [
3020
+ withAlpha(tokens.series[0], 0.88),
3021
+ withAlpha(tokens.series[1], 0.88),
3022
+ withAlpha(tokens.series[2], 0.88),
3023
+ withAlpha(tokens.series[3], 0.88),
3024
+ withAlpha(tokens.series[4], 0.88)
3025
+ ],
3026
+ borderColor: tokens.surface,
3027
+ borderWidth: 2,
3028
+ hoverOffset: 6
3029
+ }
3030
+ ]
3031
+ },
3032
+ options: {
3033
+ responsive: true,
3034
+ maintainAspectRatio: false,
3035
+ cutout: "62%",
3036
+ plugins: {
3037
+ legend: radialLegend(tokens),
3038
+ tooltip: radialInsightTooltip(tokens)
3039
+ }
3040
+ }
3041
+ };
3042
+ }
3043
+ function buildPolarAreaDemo(tokens) {
3044
+ return {
3045
+ type: "polarArea",
3046
+ data: {
3047
+ labels: ["Chrome", "Safari", "Firefox", "Edge", "Other"],
3048
+ datasets: [
3049
+ {
3050
+ label: "Browser share",
3051
+ data: [52, 24, 12, 8, 4],
3052
+ backgroundColor: [
3053
+ withAlpha(tokens.series[0], 0.72),
3054
+ withAlpha(tokens.series[1], 0.72),
3055
+ withAlpha(tokens.series[2], 0.72),
3056
+ withAlpha(tokens.series[3], 0.72),
3057
+ withAlpha(tokens.series[4], 0.72)
3058
+ ],
3059
+ borderWidth: 1,
3060
+ borderColor: tokens.surface
3061
+ }
3062
+ ]
3063
+ },
3064
+ options: {
3065
+ responsive: true,
3066
+ maintainAspectRatio: false,
3067
+ scales: {
3068
+ r: {
3069
+ ticks: {
3070
+ color: tokens.textMuted,
3071
+ backdropColor: tokens.surface,
3072
+ font: { size: 10 }
3073
+ },
3074
+ grid: {
3075
+ color: tokens.grid
3076
+ },
3077
+ angleLines: {
3078
+ color: tokens.grid
3079
+ },
3080
+ pointLabels: {
3081
+ color: tokens.textMuted,
3082
+ font: { size: 11 }
3083
+ }
3084
+ }
3085
+ },
3086
+ plugins: {
3087
+ legend: {
3088
+ display: false
3089
+ },
3090
+ tooltip: radialInsightTooltip(tokens)
3091
+ }
3092
+ }
3093
+ };
3094
+ }
3095
+
3096
+ // src/lib/chart/use-ph-chart-tokens.ts
3097
+ var import_react13 = require("react");
3098
+
3099
+ // src/lib/chart/ph-chart-tokens.ts
3100
+ var FALLBACK_CHART_TOKENS = {
3101
+ series: ["#1d4aff", "#621da6", "#42827e", "#ce0e74", "#f14f58", "#529a0a", "#fe729e"],
3102
+ grid: "hsl(78 13% 85%)",
3103
+ text: "hsl(0 0% 25%)",
3104
+ textMuted: "hsl(0 0% 42%)",
3105
+ surface: "#ffffff",
3106
+ borderStrong: "hsl(69 8% 65%)",
3107
+ accent: "hsl(19deg 100% 48%)"
3108
+ };
3109
+ function readCssVar(el, key) {
3110
+ return getComputedStyle(el).getPropertyValue(key).trim();
3111
+ }
3112
+ function readChartTokens(root) {
3113
+ if (typeof document === "undefined") {
3114
+ return FALLBACK_CHART_TOKENS;
3115
+ }
3116
+ const el = root ?? document.documentElement;
3117
+ const series = [1, 2, 3, 4, 5, 6, 7].map((index) => {
3118
+ const raw = readCssVar(el, `--ph-data-${index}`);
3119
+ return raw !== "" ? raw : FALLBACK_CHART_TOKENS.series[index - 1];
3120
+ });
3121
+ const grid = readCssVar(el, "--ph-border") || FALLBACK_CHART_TOKENS.grid;
3122
+ const text = readCssVar(el, "--ph-text-secondary") || FALLBACK_CHART_TOKENS.text;
3123
+ const textMuted = readCssVar(el, "--ph-text-tertiary") || FALLBACK_CHART_TOKENS.textMuted;
3124
+ const surface = readCssVar(el, "--ph-surface") || FALLBACK_CHART_TOKENS.surface;
3125
+ const borderStrong = readCssVar(el, "--ph-border-strong") || FALLBACK_CHART_TOKENS.borderStrong;
3126
+ const accent = readCssVar(el, "--ph-accent") || FALLBACK_CHART_TOKENS.accent;
3127
+ return { series, grid, text, textMuted, surface, borderStrong, accent };
3128
+ }
3129
+
3130
+ // src/lib/chart/use-ph-chart-tokens.ts
3131
+ function useChartTokens() {
3132
+ const [tokens, setTokens] = (0, import_react13.useState)(FALLBACK_CHART_TOKENS);
3133
+ (0, import_react13.useEffect)(() => {
3134
+ const root = document.documentElement;
3135
+ const refresh = () => {
3136
+ setTokens(readChartTokens(root));
3137
+ };
3138
+ refresh();
3139
+ const observer = new MutationObserver(refresh);
3140
+ observer.observe(root, { attributes: true, attributeFilter: ["data-theme"] });
3141
+ return () => observer.disconnect();
3142
+ }, []);
3143
+ return tokens;
3144
+ }
3145
+
3146
+ // src/lib/hog-charts-lite/build-theme.ts
3147
+ function buildHogChartTheme(tokens) {
3148
+ return {
3149
+ colors: tokens.series.slice(),
3150
+ backgroundColor: tokens.surface,
3151
+ axisColor: tokens.textMuted,
3152
+ gridColor: tokens.grid,
3153
+ crosshairColor: tokens.borderStrong
3154
+ };
3155
+ }
3156
+
3157
+ // src/lib/hog-charts-lite/CanvasTrendLineChart.tsx
3158
+ var import_d3_scale = require("d3-scale");
3159
+ var import_react14 = require("react");
3160
+ var import_jsx_runtime43 = require("react/jsx-runtime");
3161
+ var HOG_LITE_DEFAULT_MARGINS = { top: 16, right: 16, bottom: 32, left: 48 };
3162
+ function resolveDisplayedSeries(series, palette) {
3163
+ const visible = series.filter((s) => {
3164
+ var _a;
3165
+ return !((_a = s.visibility) == null ? void 0 : _a.excluded);
3166
+ });
3167
+ return visible.map((s, visibleIndex) => {
3168
+ const hasExplicit = s.color != null && String(s.color).trim() !== "";
3169
+ const resolvedColor = hasExplicit ? String(s.color).trim() : palette[visibleIndex % palette.length];
3170
+ return { ...s, resolvedColor };
3171
+ });
3172
+ }
3173
+ function yDomainForSeries(resolved) {
3174
+ let ymin = Number.POSITIVE_INFINITY;
3175
+ let ymax = Number.NEGATIVE_INFINITY;
3176
+ for (const s of resolved) {
3177
+ for (const v of s.data) {
3178
+ if (typeof v === "number" && Number.isFinite(v)) {
3179
+ ymin = Math.min(ymin, v);
3180
+ ymax = Math.max(ymax, v);
3181
+ }
3182
+ }
3183
+ }
3184
+ if (!Number.isFinite(ymin) || !Number.isFinite(ymax)) {
3185
+ return [0, 1];
3186
+ }
3187
+ ymin = Math.min(0, ymin);
3188
+ if (ymax < 0) {
3189
+ ymax = 0;
3190
+ }
3191
+ if (ymax === ymin) {
3192
+ ymax = ymin + 1;
3193
+ }
3194
+ return [ymin, ymax];
3195
+ }
3196
+ function drawHighlightPoint(ctx, x, y, color, backgroundColor, radius = 4) {
3197
+ ctx.fillStyle = backgroundColor;
3198
+ ctx.beginPath();
3199
+ ctx.arc(x, y, radius + 2, 0, Math.PI * 2);
3200
+ ctx.fill();
3201
+ ctx.fillStyle = color;
3202
+ ctx.beginPath();
3203
+ ctx.arc(x, y, radius, 0, Math.PI * 2);
3204
+ ctx.fill();
3205
+ }
3206
+ function CanvasTrendLineChart({
3207
+ labels,
3208
+ series,
3209
+ theme,
3210
+ showGrid = true,
3211
+ showCrosshair = true,
3212
+ className = ""
3213
+ }) {
3214
+ const containerRef = (0, import_react14.useRef)(null);
3215
+ const canvasRef = (0, import_react14.useRef)(null);
3216
+ const [size, setSize] = (0, import_react14.useState)({ width: 0, height: 0 });
3217
+ const [hoverIndex, setHoverIndex] = (0, import_react14.useState)(null);
3218
+ (0, import_react14.useEffect)(() => {
3219
+ const el = containerRef.current;
3220
+ if (!el) {
3221
+ return;
3222
+ }
3223
+ const update = () => {
3224
+ setSize({ width: el.clientWidth, height: el.clientHeight });
3225
+ };
3226
+ update();
3227
+ const ro = new ResizeObserver(update);
3228
+ ro.observe(el);
3229
+ return () => ro.disconnect();
3230
+ }, []);
3231
+ const resolved = (0, import_react14.useMemo)(() => resolveDisplayedSeries(series, theme.colors), [series, theme.colors]);
3232
+ const draw = (0, import_react14.useCallback)(() => {
3233
+ var _a, _b, _c;
3234
+ const canvas = canvasRef.current;
3235
+ const container = containerRef.current;
3236
+ if (!canvas || !container) {
3237
+ return;
3238
+ }
3239
+ const { width: cssW, height: cssH } = size;
3240
+ if (cssW < 20 || cssH < 20) {
3241
+ return;
3242
+ }
3243
+ const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
3244
+ canvas.width = Math.floor(cssW * dpr);
3245
+ canvas.height = Math.floor(cssH * dpr);
3246
+ canvas.style.width = `${cssW}px`;
3247
+ canvas.style.height = `${cssH}px`;
3248
+ const ctx = canvas.getContext("2d");
3249
+ if (!ctx) {
3250
+ return;
3251
+ }
3252
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
3253
+ const m = HOG_LITE_DEFAULT_MARGINS;
3254
+ const plotLeft = m.left;
3255
+ const plotTop = m.top;
3256
+ const plotWidth = cssW - m.left - m.right;
3257
+ const plotHeight = cssH - m.top - m.bottom;
3258
+ if (plotWidth <= 4 || plotHeight <= 4) {
3259
+ return;
3260
+ }
3261
+ const bg = theme.backgroundColor ?? "#ffffff";
3262
+ ctx.fillStyle = bg;
3263
+ ctx.fillRect(0, 0, cssW, cssH);
3264
+ const labelList = [...labels];
3265
+ const xScale = (0, import_d3_scale.scalePoint)().domain(labelList).range([plotLeft, plotLeft + plotWidth]).padding(0.5);
3266
+ const [y0, y1] = yDomainForSeries(resolved);
3267
+ const yScale = (0, import_d3_scale.scaleLinear)().domain([y0, y1]).nice().range([plotTop + plotHeight, plotTop]);
3268
+ const axisColor = theme.axisColor ?? "#666";
3269
+ const gridColor = theme.gridColor ?? "rgba(0,0,0,0.08)";
3270
+ if (showGrid) {
3271
+ const ticks = yScale.ticks(6);
3272
+ ctx.strokeStyle = gridColor;
3273
+ ctx.lineWidth = 1;
3274
+ ctx.setLineDash([]);
3275
+ for (const t of ticks) {
3276
+ const y = Math.round(yScale(t)) + 0.5;
3277
+ ctx.beginPath();
3278
+ ctx.moveTo(plotLeft, y);
3279
+ ctx.lineTo(plotLeft + plotWidth, y);
3280
+ ctx.stroke();
3281
+ }
3282
+ }
3283
+ const xAt = (i) => {
3284
+ const label = labels[i];
3285
+ return label !== void 0 ? xScale(label) : void 0;
3286
+ };
3287
+ for (const s of resolved) {
3288
+ if (s.overlay || !s.fill) {
3289
+ continue;
3290
+ }
3291
+ const opacity = s.fill.opacity ?? 0.45;
3292
+ const baseline = yScale(0);
3293
+ ctx.save();
3294
+ ctx.globalAlpha = opacity;
3295
+ ctx.fillStyle = s.resolvedColor;
3296
+ ctx.beginPath();
3297
+ let started = false;
3298
+ for (let i = 0; i < labels.length; i++) {
3299
+ const x = xAt(i);
3300
+ const v = s.data[i];
3301
+ if (x == null || typeof v !== "number" || !Number.isFinite(v)) {
3302
+ started = false;
3303
+ continue;
3304
+ }
3305
+ const y = yScale(v);
3306
+ if (!started) {
3307
+ ctx.moveTo(x, y);
3308
+ started = true;
3309
+ } else {
3310
+ ctx.lineTo(x, y);
3311
+ }
3312
+ }
3313
+ for (let i = labels.length - 1; i >= 0; i--) {
3314
+ const x = xAt(i);
3315
+ if (x == null) {
3316
+ continue;
3317
+ }
3318
+ ctx.lineTo(x, baseline);
3319
+ }
3320
+ ctx.closePath();
3321
+ ctx.fill();
3322
+ ctx.restore();
3323
+ }
3324
+ for (const s of resolved) {
3325
+ if ((_a = s.visibility) == null ? void 0 : _a.excluded) {
3326
+ continue;
3327
+ }
3328
+ const pattern = ((_b = s.stroke) == null ? void 0 : _b.pattern) ?? [];
3329
+ ctx.strokeStyle = s.resolvedColor;
3330
+ ctx.lineWidth = 2;
3331
+ ctx.lineJoin = "round";
3332
+ ctx.lineCap = "round";
3333
+ ctx.setLineDash(pattern);
3334
+ ctx.beginPath();
3335
+ let started = false;
3336
+ for (let i = 0; i < labels.length; i++) {
3337
+ const x = xAt(i);
3338
+ const v = s.data[i];
3339
+ if (x == null || typeof v !== "number" || !Number.isFinite(v)) {
3340
+ started = false;
3341
+ continue;
3342
+ }
3343
+ const y = yScale(v);
3344
+ if (!started) {
3345
+ ctx.moveTo(x, y);
3346
+ started = true;
3347
+ } else {
3348
+ ctx.lineTo(x, y);
3349
+ }
3350
+ }
3351
+ ctx.stroke();
3352
+ ctx.setLineDash([]);
3353
+ }
3354
+ ctx.fillStyle = axisColor;
3355
+ const bodyFamily = typeof document !== "undefined" ? window.getComputedStyle(document.body).fontFamily.trim() : "ui-sans-serif, system-ui, sans-serif";
3356
+ ctx.font = `11px ${bodyFamily || "ui-sans-serif, system-ui, sans-serif"}`;
3357
+ ctx.textAlign = "right";
3358
+ ctx.textBaseline = "middle";
3359
+ const yTicks = yScale.ticks(6);
3360
+ for (const t of yTicks) {
3361
+ const y = yScale(t);
3362
+ ctx.fillText(String(Number.isInteger(t) ? t : Number(t.toFixed(2))), plotLeft - 8, y);
3363
+ }
3364
+ ctx.textAlign = "center";
3365
+ ctx.textBaseline = "top";
3366
+ const step = Math.max(1, Math.ceil(labels.length / 8));
3367
+ for (let i = 0; i < labels.length; i += step) {
3368
+ const x = xAt(i);
3369
+ if (x == null) {
3370
+ continue;
3371
+ }
3372
+ const text = labels[i];
3373
+ if (text === void 0) {
3374
+ continue;
3375
+ }
3376
+ ctx.fillText(text.length > 8 ? `${text.slice(0, 7)}\u2026` : text, x, plotTop + plotHeight + 8);
3377
+ }
3378
+ const hi = hoverIndex;
3379
+ if (hi != null && hi >= 0 && hi < labels.length && showCrosshair) {
3380
+ const cx = xAt(hi);
3381
+ if (cx != null) {
3382
+ const cross = theme.crosshairColor ?? gridColor;
3383
+ ctx.strokeStyle = cross;
3384
+ ctx.lineWidth = 1;
3385
+ ctx.setLineDash([4, 4]);
3386
+ ctx.beginPath();
3387
+ ctx.moveTo(cx, plotTop);
3388
+ ctx.lineTo(cx, plotTop + plotHeight);
3389
+ ctx.stroke();
3390
+ ctx.setLineDash([]);
3391
+ for (const s of resolved) {
3392
+ if (s.overlay || ((_c = s.visibility) == null ? void 0 : _c.excluded)) {
3393
+ continue;
3394
+ }
3395
+ const v = s.data[hi];
3396
+ if (typeof v !== "number" || !Number.isFinite(v)) {
3397
+ continue;
3398
+ }
3399
+ const y = yScale(v);
3400
+ drawHighlightPoint(ctx, cx, y, s.resolvedColor, bg, 4);
3401
+ }
3402
+ }
3403
+ }
3404
+ }, [hoverIndex, labels, resolved, showCrosshair, showGrid, size.height, size.width, theme]);
3405
+ (0, import_react14.useEffect)(() => {
3406
+ draw();
3407
+ }, [draw]);
3408
+ const onMouseMove = (event) => {
3409
+ const canvas = canvasRef.current;
3410
+ if (!canvas) {
3411
+ return;
3412
+ }
3413
+ const mx = event.nativeEvent.offsetX;
3414
+ const m = HOG_LITE_DEFAULT_MARGINS;
3415
+ const plotLeft = m.left;
3416
+ const plotWidth = size.width - m.left - m.right;
3417
+ if (plotWidth <= 4) {
3418
+ return;
3419
+ }
3420
+ const labelList = [...labels];
3421
+ const xScale = (0, import_d3_scale.scalePoint)().domain(labelList).range([plotLeft, plotLeft + plotWidth]).padding(0.5);
3422
+ let best = 0;
3423
+ let bestDist = Number.POSITIVE_INFINITY;
3424
+ labels.forEach((lab, i) => {
3425
+ const xi = xScale(lab);
3426
+ if (xi == null) {
3427
+ return;
3428
+ }
3429
+ const d = Math.abs(mx - xi);
3430
+ if (d < bestDist) {
3431
+ bestDist = d;
3432
+ best = i;
3433
+ }
3434
+ });
3435
+ setHoverIndex(best);
3436
+ };
3437
+ const onMouseLeave = () => {
3438
+ setHoverIndex(null);
3439
+ };
3440
+ const tooltipRows = (0, import_react14.useMemo)(() => {
3441
+ if (hoverIndex == null) {
3442
+ return null;
3443
+ }
3444
+ const label = labels[hoverIndex];
3445
+ if (label === void 0) {
3446
+ return null;
3447
+ }
3448
+ return resolved.filter((s) => {
3449
+ var _a;
3450
+ return !s.overlay && !((_a = s.visibility) == null ? void 0 : _a.excluded);
3451
+ }).map((s) => ({
3452
+ label: s.label,
3453
+ color: s.resolvedColor,
3454
+ value: s.data[hoverIndex]
3455
+ })).filter((row) => typeof row.value === "number" && Number.isFinite(row.value));
3456
+ }, [hoverIndex, labels, resolved]);
3457
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { ref: containerRef, className: `relative w-full ${className}`.trim(), children: [
3458
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3459
+ "canvas",
3460
+ {
3461
+ ref: canvasRef,
3462
+ className: "block w-full cursor-crosshair rounded-[2px]",
3463
+ "aria-label": "Trend line chart canvas",
3464
+ onMouseMove,
3465
+ onMouseLeave
3466
+ }
3467
+ ),
3468
+ tooltipRows != null && tooltipRows.length > 0 && hoverIndex != null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
3469
+ "div",
3470
+ {
3471
+ className: "pointer-events-none absolute z-20 max-w-xs rounded-[var(--ph-radius-app)] border border-ph-border-strong bg-ph-surface px-3 py-2 text-xs shadow-ph-md",
3472
+ style: {
3473
+ left: 12,
3474
+ top: 8
3475
+ },
3476
+ children: [
3477
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "font-semibold text-ph-ink", children: labels[hoverIndex] }),
3478
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "mt-1 space-y-0.5 text-ph-mutedtext", children: tooltipRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "flex items-center gap-2", children: [
3479
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "h-2 w-2 shrink-0 rounded-full", style: { background: row.color } }),
3480
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "min-w-0 truncate", children: row.label }),
3481
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-auto tabular-nums text-ph-ink", children: row.value })
3482
+ ] }, row.label)) })
3483
+ ]
3484
+ }
3485
+ ) : null
3486
+ ] });
3487
+ }
3488
+
3489
+ // src/components/charts/ph-insight-charts.tsx
3490
+ var import_jsx_runtime44 = require("react/jsx-runtime");
3491
+ var DEMO_LABELS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
3492
+ function useClientMounted() {
3493
+ const [mounted, setMounted] = (0, import_react15.useState)(false);
3494
+ (0, import_react15.useEffect)(() => setMounted(true), []);
3495
+ return mounted;
3496
+ }
3497
+ function ChartSkeleton({ className = "h-[280px]" }) {
3498
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3499
+ "div",
3500
+ {
3501
+ className: `w-full animate-pulse rounded-lemon bg-ph-muted ${className}`,
3502
+ "aria-hidden": true
3503
+ }
3504
+ );
3505
+ }
3506
+ function HogTrendLineChart() {
3507
+ const mounted = useClientMounted();
3508
+ const tokens = useChartTokens();
3509
+ const theme = (0, import_react15.useMemo)(() => buildHogChartTheme(tokens), [tokens]);
3510
+ const series = (0, import_react15.useMemo)(
3511
+ () => [
3512
+ {
3513
+ key: "pageview",
3514
+ label: "$pageview",
3515
+ data: [4200, 5100, 4800, 6200, 5900, 3100, 2800],
3516
+ color: tokens.series[0],
3517
+ fill: { opacity: 0.35 }
3518
+ },
3519
+ {
3520
+ key: "signup",
3521
+ label: "signup_completed",
3522
+ data: [920, 990, 940, 1040, 1012, 540, 510],
3523
+ color: tokens.series[1],
3524
+ stroke: { pattern: [5, 5] }
3525
+ }
3526
+ ],
3527
+ [tokens.series]
3528
+ );
3529
+ if (!mounted) {
3530
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartSkeleton, {});
3531
+ }
3532
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative h-[280px] w-full min-h-[220px]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3533
+ CanvasTrendLineChart,
3534
+ {
3535
+ labels: DEMO_LABELS,
3536
+ series,
3537
+ theme,
3538
+ showGrid: true,
3539
+ showCrosshair: true,
3540
+ className: "h-full min-h-[220px]"
3541
+ }
3542
+ ) });
3543
+ }
3544
+ function InsightVerticalBarChart() {
3545
+ const mounted = useClientMounted();
3546
+ const tokens = useChartTokens();
3547
+ const config = (0, import_react15.useMemo)(() => buildVerticalBarDemo(tokens), [tokens]);
3548
+ if (!mounted) {
3549
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartSkeleton, {});
3550
+ }
3551
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative h-[280px] w-full min-h-[220px]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_chartjs_2.Bar, { data: config.data, options: config.options }) });
3552
+ }
3553
+ function InsightHorizontalBarChart() {
3554
+ const mounted = useClientMounted();
3555
+ const tokens = useChartTokens();
3556
+ const config = (0, import_react15.useMemo)(() => buildHorizontalBarDemo(tokens), [tokens]);
3557
+ if (!mounted) {
3558
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartSkeleton, { className: "h-[320px]" });
3559
+ }
3560
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative h-[320px] w-full min-h-[260px]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_chartjs_2.Bar, { data: config.data, options: config.options }) });
3561
+ }
3562
+ function InsightStackedBarChart() {
3563
+ const mounted = useClientMounted();
3564
+ const tokens = useChartTokens();
3565
+ const config = (0, import_react15.useMemo)(() => buildStackedBarDemo(tokens), [tokens]);
3566
+ if (!mounted) {
3567
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartSkeleton, { className: "h-[300px]" });
3568
+ }
3569
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative h-[300px] w-full min-h-[240px]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_chartjs_2.Bar, { data: config.data, options: config.options }) });
3570
+ }
3571
+ function InsightDoughnutChart() {
3572
+ const mounted = useClientMounted();
3573
+ const tokens = useChartTokens();
3574
+ const config = (0, import_react15.useMemo)(() => buildDoughnutDemo(tokens), [tokens]);
3575
+ if (!mounted) {
3576
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartSkeleton, { className: "h-[260px]" });
3577
+ }
3578
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative mx-auto h-[260px] w-full max-w-[280px] min-h-[220px]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_chartjs_2.Doughnut, { data: config.data, options: config.options }) });
3579
+ }
3580
+ function InsightPolarAreaChart() {
3581
+ const mounted = useClientMounted();
3582
+ const tokens = useChartTokens();
3583
+ const config = (0, import_react15.useMemo)(() => buildPolarAreaDemo(tokens), [tokens]);
3584
+ if (!mounted) {
3585
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartSkeleton, { className: "h-[280px]" });
3586
+ }
3587
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "relative mx-auto h-[280px] w-full max-w-[320px] min-h-[240px]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_react_chartjs_2.PolarArea, { data: config.data, options: config.options }) });
3588
+ }
3589
+
3590
+ // src/components/dashboard/DashboardWell.tsx
3591
+ var import_jsx_runtime45 = require("react/jsx-runtime");
3592
+ function DashboardWell({ className, ...props }) {
3593
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cn("ph-dashboard-well", className), ...props });
3594
+ }
3595
+
3596
+ // src/components/dashboard/DashboardToolbar.tsx
3597
+ var import_jsx_runtime46 = require("react/jsx-runtime");
3598
+ function DashboardToolbar({ title, description, actions, className }) {
3599
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: cn("flex flex-wrap items-baseline justify-between gap-4", className), children: [
3600
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "min-w-0", children: [
3601
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h3", { className: "text-lg font-bold text-ph-ink", children: title }),
3602
+ description ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "mt-0.5 text-sm text-ph-mutedtext", children: description }) : null
3603
+ ] }),
3604
+ actions != null ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
3605
+ ] });
3606
+ }
3607
+
3608
+ // src/components/dashboard/DashboardGrid.tsx
3609
+ var import_jsx_runtime47 = require("react/jsx-runtime");
3610
+ var presetClass = {
3611
+ insights: "grid gap-4 md:grid-cols-2 xl:grid-cols-3",
3612
+ dense: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
3613
+ };
3614
+ function DashboardGrid({
3615
+ preset = "insights",
3616
+ className,
3617
+ ...props
3618
+ }) {
3619
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: cn(presetClass[preset], className), ...props });
3620
+ }
3621
+
3622
+ // src/components/dashboard/DashboardFiltersBar.tsx
3623
+ var import_jsx_runtime48 = require("react/jsx-runtime");
3624
+ function DashboardFiltersBar({ className, ...props }) {
3625
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3626
+ "div",
3627
+ {
3628
+ className: cn(
3629
+ "flex flex-wrap items-center gap-2 rounded-[var(--ph-radius-app)] border border-solid bg-ph-surface px-3 py-2 text-sm text-ph-subtle [border-color:var(--ph-border-control)]",
3630
+ "[box-shadow:var(--ph-chrome-inset-face-top),var(--ph-chrome-inset-face-bottom),var(--ph-shadow-elevation-3000)]",
3631
+ className
3632
+ ),
3633
+ ...props
3634
+ }
3635
+ );
3636
+ }
3637
+
3638
+ // src/components/dashboard/DashboardKpiCard.tsx
3639
+ var import_jsx_runtime49 = require("react/jsx-runtime");
3640
+ function DashboardKpiCard({ label, value, footer, icon, className, children, ...props }) {
3641
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("article", { className: cn("ph-stat", className), ...props, children: [
3642
+ icon != null ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "mb-2 [&>svg]:h-7 [&>svg]:w-7", children: icon }) : null,
3643
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "ph-stat-label", children: label }),
3644
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "ph-stat-val", children: value }),
3645
+ footer != null ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-1 text-xs text-ph-subtle", children: footer }) : null,
3646
+ children
3647
+ ] });
3648
+ }
3649
+
3650
+ // src/components/dashboard/DashboardInsightPlaceholder.tsx
3651
+ var import_jsx_runtime50 = require("react/jsx-runtime");
3652
+ function DashboardInsightPlaceholder({
3653
+ label = "Add insight",
3654
+ className,
3655
+ children,
3656
+ type = "button",
3657
+ ...props
3658
+ }) {
3659
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
3660
+ "button",
3661
+ {
3662
+ type,
3663
+ "aria-label": label,
3664
+ className: cn(
3665
+ "ph-dashboard-placeholder group text-left outline-none transition",
3666
+ "focus-visible:ring-2 focus-visible:ring-ph-brand focus-visible:ring-offset-2",
3667
+ className
3668
+ ),
3669
+ ...props,
3670
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "font-medium text-ph-subtle group-hover:text-ph-ink", children: label })
3671
+ }
3672
+ );
3673
+ }
3674
+
3675
+ // src/components/dashboard/InsightShell.tsx
3676
+ var import_jsx_runtime51 = require("react/jsx-runtime");
3677
+ function InsightShell({
3678
+ ribbonColour,
3679
+ bodyClassName,
3680
+ className,
3681
+ children,
3682
+ ...props
3683
+ }) {
3684
+ const ribbon = ribbonColour != null && String(ribbonColour).trim() !== "" ? String(ribbonColour).trim() : null;
3685
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("article", { className: cn("ph-insight-shell flex-row", className), ...props, children: [
3686
+ ribbon != null ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
3687
+ "div",
3688
+ {
3689
+ className: "ph-insight-shell__ribbon min-h-[7rem] shrink-0 self-stretch",
3690
+ style: { background: ribbon },
3691
+ "aria-hidden": true
3692
+ }
3693
+ ) : null,
3694
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: cn("flex min-w-0 flex-1 flex-col gap-3 p-4", bodyClassName), children })
3695
+ ] });
3696
+ }
3697
+
3698
+ // src/components/dashboard/InsightShellHeader.tsx
3699
+ var import_jsx_runtime52 = require("react/jsx-runtime");
3700
+ function InsightShellHeader({ title, subtitle, actions, className }) {
3701
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("header", { className: cn("flex gap-3", actions != null ? "items-start justify-between" : "", className), children: [
3702
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "min-w-0 flex-1", children: [
3703
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("h4", { className: "font-semibold leading-snug text-ph-ink", children: title }),
3704
+ subtitle != null ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "mt-0.5 text-xs text-ph-mutedtext", children: subtitle }) : null
3705
+ ] }),
3706
+ actions != null ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "flex shrink-0 items-center gap-1", children: actions }) : null
3707
+ ] });
3708
+ }
3709
+
3710
+ // src/components/dashboard/MiniTrendBars.tsx
3711
+ var import_jsx_runtime53 = require("react/jsx-runtime");
3712
+ var DEFAULT_SERIES_CYCLE = [1, 2, 3, 4, 5, 6, 7];
3713
+ function clampPct(n) {
3714
+ if (!Number.isFinite(n)) {
3715
+ return 0;
3716
+ }
3717
+ return Math.max(0, Math.min(100, n));
3718
+ }
3719
+ function MiniTrendBars({
3720
+ heights,
3721
+ rowClassName = "h-28",
3722
+ seriesResolver,
3723
+ className
3724
+ }) {
3725
+ const resolveSeries = seriesResolver ?? ((i) => DEFAULT_SERIES_CYCLE[i % DEFAULT_SERIES_CYCLE.length] ?? 1);
3726
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: cn("flex items-end gap-0.5", rowClassName, className), children: heights.map((raw, i) => {
3727
+ const pct = clampPct(raw);
3728
+ const series = resolveSeries(i, pct);
3729
+ const style = {
3730
+ height: `${pct}%`,
3731
+ background: `var(--ph-data-${String(series)})`,
3732
+ minHeight: pct > 0 ? 4 : 0
3733
+ };
3734
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "min-h-0 flex-1 rounded-t-[3px]", style }, `bar-${String(i)}`);
3735
+ }) });
3736
+ }
3737
+
3738
+ // src/components/dashboard/InsightMiniCard.tsx
3739
+ var import_jsx_runtime54 = require("react/jsx-runtime");
3740
+ function InsightMiniCard({
3741
+ title,
3742
+ subtitle,
3743
+ heights,
3744
+ ribbonColour,
3745
+ ...shellProps
3746
+ }) {
3747
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(InsightShell, { ribbonColour, ...shellProps, children: [
3748
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(InsightShellHeader, { title, subtitle }),
3749
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(MiniTrendBars, { heights })
3750
+ ] });
3751
+ }
3752
+ // Annotate the CommonJS export names for ESM import in node:
3753
+ 0 && (module.exports = {
3754
+ Accordion,
3755
+ Alert,
3756
+ Avatar,
3757
+ AvatarGroup,
3758
+ Badge,
3759
+ Breadcrumbs,
3760
+ Button,
3761
+ ButtonChrome,
3762
+ Calendar,
3763
+ Caption,
3764
+ Card,
3765
+ ChatBubble,
3766
+ Checkbox,
3767
+ CodeBlock,
3768
+ CollapsibleSection,
3769
+ CommandPalette,
3770
+ ComponentDocs,
3771
+ DEFAULT_THEME_ID,
3772
+ DashboardFiltersBar,
3773
+ DashboardGrid,
3774
+ DashboardInsightPlaceholder,
3775
+ DashboardKpiCard,
3776
+ DashboardToolbar,
3777
+ DashboardWell,
3778
+ Display,
3779
+ Drawer,
3780
+ DropdownButton,
3781
+ DropdownItem,
3782
+ DropdownMenu,
3783
+ EmptyState,
3784
+ FileUpload,
3785
+ FilterChips,
3786
+ H1,
3787
+ H2,
3788
+ H3,
3789
+ H4,
3790
+ H5,
3791
+ HogTrendLineChart,
3792
+ HoverCard,
3793
+ Icon,
3794
+ IconActivity,
3795
+ IconAreaChart,
3796
+ IconArrowDown,
3797
+ IconArrowUp,
3798
+ IconBase,
3799
+ IconBell,
3800
+ IconBellOff,
3801
+ IconBolt,
3802
+ IconBox,
3803
+ IconByName,
3804
+ IconCancel,
3805
+ IconCheck,
3806
+ IconCheckCircle,
3807
+ IconChevronDown,
3808
+ IconChevronLeft,
3809
+ IconChevronRight,
3810
+ IconClipboardEdit,
3811
+ IconClose,
3812
+ IconCohort,
3813
+ IconCopy,
3814
+ IconCumulativeChart,
3815
+ IconDatabase,
3816
+ IconDownload,
3817
+ IconEdit,
3818
+ IconErrorOutline,
3819
+ IconExclamation,
3820
+ IconFlag,
3821
+ IconFlare,
3822
+ IconFlask,
3823
+ IconGift,
3824
+ IconGridView,
3825
+ IconHandClick,
3826
+ IconHome,
3827
+ IconLayers,
3828
+ IconListView,
3829
+ IconLogout,
3830
+ IconMail,
3831
+ IconMoon,
3832
+ IconPanelRight,
3833
+ IconPerson,
3834
+ IconPlayCircle,
3835
+ IconPlus,
3836
+ IconPremium,
3837
+ IconQueryEditor,
3838
+ IconRadar,
3839
+ IconRecording,
3840
+ IconRobot,
3841
+ IconRocket,
3842
+ IconSave,
3843
+ IconSearch,
3844
+ IconSelectEvents,
3845
+ IconShoppingCart,
3846
+ IconSpinner,
3847
+ IconStar,
3848
+ IconSubArrowRight,
3849
+ IconSun,
3850
+ IconSurveys,
3851
+ IconSync,
3852
+ IconTableChart,
3853
+ IconTerminal,
3854
+ IconToggle,
3855
+ IconTrash,
3856
+ IconTuning,
3857
+ IconUpload,
3858
+ IconVolume,
3859
+ IconVolumeOff,
3860
+ Indicator,
3861
+ Input,
3862
+ InsightDoughnutChart,
3863
+ InsightHorizontalBarChart,
3864
+ InsightMiniCard,
3865
+ InsightPolarAreaChart,
3866
+ InsightShell,
3867
+ InsightShellHeader,
3868
+ InsightStackedBarChart,
3869
+ InsightVerticalBarChart,
3870
+ Kbd,
3871
+ Label,
3872
+ Lead,
3873
+ MiniTrendBars,
3874
+ Modal,
3875
+ Mono,
3876
+ Overline,
3877
+ P,
3878
+ PH_ICONS,
3879
+ Pagination,
3880
+ Panel,
3881
+ Progress,
3882
+ Radio,
3883
+ Range,
3884
+ Rating,
3885
+ SearchGroup,
3886
+ SearchInput,
3887
+ SegmentedControl,
3888
+ Select,
3889
+ ShowcaseWrapper,
3890
+ Small,
3891
+ Stat,
3892
+ Stepper,
3893
+ THEMES,
3894
+ THEME_GROUPS,
3895
+ THEME_INIT_SCRIPT,
3896
+ Table,
3897
+ Tabs,
3898
+ Terminal,
3899
+ Textarea,
3900
+ ThemeDomSync,
3901
+ ThemeManager,
3902
+ ThemeSwitcher,
3903
+ Timeline,
3904
+ Toast,
3905
+ ToastStack,
3906
+ Toggle,
3907
+ createIconBase,
3908
+ createIconBasePath,
3909
+ getTheme,
3910
+ isThemeId,
3911
+ persistTheme,
3912
+ readStoredTheme
3913
+ });