@pollinations/ui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +219 -0
  2. package/dist/Button-CNzpisJf.d.cts +26 -0
  3. package/dist/Button-DMJ2K6Gr.d.ts +26 -0
  4. package/dist/Chip-BS8ronOu.d.ts +20 -0
  5. package/dist/Chip-DyqWrq0r.d.cts +20 -0
  6. package/dist/app.css +87 -0
  7. package/dist/assets/logo-wordmark.svg +1 -0
  8. package/dist/assets/logo.svg +4 -0
  9. package/dist/auth/index.cjs +225 -0
  10. package/dist/auth/index.cjs.map +1 -0
  11. package/dist/auth/index.d.cts +28 -0
  12. package/dist/auth/index.d.ts +28 -0
  13. package/dist/auth/index.js +194 -0
  14. package/dist/auth/index.js.map +1 -0
  15. package/dist/auth/sdk.cjs +220 -0
  16. package/dist/auth/sdk.cjs.map +1 -0
  17. package/dist/auth/sdk.d.cts +53 -0
  18. package/dist/auth/sdk.d.ts +53 -0
  19. package/dist/auth/sdk.js +187 -0
  20. package/dist/auth/sdk.js.map +1 -0
  21. package/dist/fonts/fraunces-soft-bold.woff2 +0 -0
  22. package/dist/fonts/lct-mogi-a.woff2 +0 -0
  23. package/dist/fonts/uncut-sans-variable.woff2 +0 -0
  24. package/dist/index.cjs +1771 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.d.cts +340 -0
  27. package/dist/index.d.ts +340 -0
  28. package/dist/index.js +1706 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/licenses/Fraunces-OFL.txt +93 -0
  31. package/dist/licenses/LCT-Mogi-OFL.txt +93 -0
  32. package/dist/licenses/UncutSans-OFL.txt +94 -0
  33. package/dist/modality/index.cjs +115 -0
  34. package/dist/modality/index.cjs.map +1 -0
  35. package/dist/modality/index.d.cts +45 -0
  36. package/dist/modality/index.d.ts +45 -0
  37. package/dist/modality/index.js +87 -0
  38. package/dist/modality/index.js.map +1 -0
  39. package/dist/showcase/index.cjs +2851 -0
  40. package/dist/showcase/index.cjs.map +1 -0
  41. package/dist/showcase/index.d.cts +19 -0
  42. package/dist/showcase/index.d.ts +19 -0
  43. package/dist/showcase/index.js +2839 -0
  44. package/dist/showcase/index.js.map +1 -0
  45. package/dist/styles.css +2 -0
  46. package/dist/theme-DfHMjWB7.d.cts +16 -0
  47. package/dist/theme-DfHMjWB7.d.ts +16 -0
  48. package/dist/wallet/index.cjs +190 -0
  49. package/dist/wallet/index.cjs.map +1 -0
  50. package/dist/wallet/index.d.cts +30 -0
  51. package/dist/wallet/index.d.ts +30 -0
  52. package/dist/wallet/index.js +157 -0
  53. package/dist/wallet/index.js.map +1 -0
  54. package/dist/wallet/sdk.cjs +203 -0
  55. package/dist/wallet/sdk.cjs.map +1 -0
  56. package/dist/wallet/sdk.d.cts +33 -0
  57. package/dist/wallet/sdk.d.ts +33 -0
  58. package/dist/wallet/sdk.js +172 -0
  59. package/dist/wallet/sdk.js.map +1 -0
  60. package/dist/wallet.css +73 -0
  61. package/package.json +105 -0
package/dist/index.js ADDED
@@ -0,0 +1,1706 @@
1
+ // src/lib/cn-app.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(...inputs));
6
+ }
7
+
8
+ // src/lib/period.ts
9
+ var MS_PER_DAY = 864e5;
10
+ function startOfUtcDay(date = /* @__PURE__ */ new Date()) {
11
+ return new Date(
12
+ Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
13
+ );
14
+ }
15
+ function addUtcDays(date, days) {
16
+ const next = new Date(date);
17
+ next.setUTCDate(next.getUTCDate() + days);
18
+ return next;
19
+ }
20
+ function startOfUtcMonth(date) {
21
+ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1));
22
+ }
23
+ function addUtcMonths(date, months) {
24
+ return new Date(
25
+ Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, 1)
26
+ );
27
+ }
28
+ function startOfUtcIsoWeek(date) {
29
+ const day = date.getUTCDay() || 7;
30
+ return addUtcDays(startOfUtcDay(date), 1 - day);
31
+ }
32
+ function getUtcIsoWeekPeriod(date) {
33
+ const day = date.getUTCDay() || 7;
34
+ const thursday = addUtcDays(startOfUtcDay(date), 4 - day);
35
+ const isoYear = thursday.getUTCFullYear();
36
+ const yearStart = new Date(Date.UTC(isoYear, 0, 1));
37
+ const isoWeek = Math.ceil(
38
+ ((thursday.getTime() - yearStart.getTime()) / MS_PER_DAY + 1) / 7
39
+ );
40
+ return `${isoYear}-W${String(isoWeek).padStart(2, "0")}`;
41
+ }
42
+ function formatUtcDatePeriod(date) {
43
+ return date.toISOString().slice(0, 10);
44
+ }
45
+ function formatUtcHourPeriod(date) {
46
+ return date.toISOString().slice(0, 13).replace("T", " ");
47
+ }
48
+ function formatUtcMonthPeriod(date) {
49
+ return date.toISOString().slice(0, 7);
50
+ }
51
+ function periodFromDate(granularity, date = /* @__PURE__ */ new Date()) {
52
+ if (granularity === "day") {
53
+ return {
54
+ granularity,
55
+ period: formatUtcDatePeriod(startOfUtcDay(date))
56
+ };
57
+ }
58
+ if (granularity === "week") {
59
+ return { granularity, period: getUtcIsoWeekPeriod(date) };
60
+ }
61
+ return { granularity, period: formatUtcMonthPeriod(startOfUtcMonth(date)) };
62
+ }
63
+ function currentPeriod() {
64
+ return periodFromDate("day");
65
+ }
66
+ function periodToWindow(selection) {
67
+ if (selection.granularity === "day") {
68
+ const start2 = /* @__PURE__ */ new Date(`${selection.period}T00:00:00.000Z`);
69
+ return { start: start2, end: addUtcDays(start2, 1) };
70
+ }
71
+ if (selection.granularity === "week") {
72
+ const [yearText2, weekText] = selection.period.split("-W");
73
+ const isoYear = Number(yearText2);
74
+ const isoWeek = Number(weekText);
75
+ const jan4 = new Date(Date.UTC(isoYear, 0, 4));
76
+ const start2 = addUtcDays(startOfUtcIsoWeek(jan4), (isoWeek - 1) * 7);
77
+ return { start: start2, end: addUtcDays(start2, 7) };
78
+ }
79
+ const [yearText, monthText] = selection.period.split("-");
80
+ const start = new Date(
81
+ Date.UTC(Number(yearText), Number(monthText) - 1, 1)
82
+ );
83
+ return { start, end: addUtcMonths(start, 1) };
84
+ }
85
+ function formatPeriodLabel(selection) {
86
+ const { start, end } = periodToWindow(selection);
87
+ if (selection.granularity === "day") {
88
+ const today = startOfUtcDay();
89
+ const yesterday = addUtcDays(today, -1);
90
+ if (start.getTime() === today.getTime()) return "Today";
91
+ if (start.getTime() === yesterday.getTime()) return "Yesterday";
92
+ return start.toLocaleDateString("en-US", {
93
+ timeZone: "UTC",
94
+ month: "short",
95
+ day: "numeric",
96
+ year: "numeric"
97
+ });
98
+ }
99
+ if (selection.granularity === "week") {
100
+ const weekEnd = addUtcDays(end, -1);
101
+ return `${start.toLocaleDateString("en-US", {
102
+ timeZone: "UTC",
103
+ month: "short",
104
+ day: "numeric"
105
+ })} - ${weekEnd.toLocaleDateString("en-US", {
106
+ timeZone: "UTC",
107
+ month: "short",
108
+ day: "numeric",
109
+ year: "numeric"
110
+ })}`;
111
+ }
112
+ return start.toLocaleDateString("en-US", {
113
+ timeZone: "UTC",
114
+ month: "long",
115
+ year: "numeric"
116
+ });
117
+ }
118
+ function getPeriodBucketKeys(selection) {
119
+ const { start, end } = periodToWindow(selection);
120
+ const bucketKeys = [];
121
+ const cursor = new Date(start);
122
+ if (selection.granularity === "day") {
123
+ while (cursor < end) {
124
+ bucketKeys.push(`${formatUtcHourPeriod(cursor)}:00:00`);
125
+ cursor.setUTCHours(cursor.getUTCHours() + 1);
126
+ }
127
+ return bucketKeys;
128
+ }
129
+ while (cursor < end) {
130
+ bucketKeys.push(formatUtcDatePeriod(cursor));
131
+ cursor.setUTCDate(cursor.getUTCDate() + 1);
132
+ }
133
+ return bucketKeys;
134
+ }
135
+ function periodBucketKeyToDate(bucketKey, granularity) {
136
+ if (granularity === "day") {
137
+ return /* @__PURE__ */ new Date(`${bucketKey.replace(" ", "T")}.000Z`);
138
+ }
139
+ return /* @__PURE__ */ new Date(`${bucketKey}T00:00:00.000Z`);
140
+ }
141
+ function isPeriodSelectable(selection, minDate = /* @__PURE__ */ new Date(0), maxDate = startOfUtcDay()) {
142
+ const { start, end } = periodToWindow(selection);
143
+ return end > minDate && start <= maxDate;
144
+ }
145
+
146
+ // src/lib/use-scroll-lock.ts
147
+ import { useEffect } from "react";
148
+ function useScrollLock(enabled = true) {
149
+ useEffect(() => {
150
+ if (!enabled) return;
151
+ const originalBody = document.body.style.overflow;
152
+ const originalHtml = document.documentElement.style.overflow;
153
+ document.body.style.overflow = "hidden";
154
+ document.documentElement.style.overflow = "hidden";
155
+ return () => {
156
+ document.body.style.overflow = originalBody;
157
+ document.documentElement.style.overflow = originalHtml;
158
+ };
159
+ }, [enabled]);
160
+ }
161
+
162
+ // src/lib/cn.ts
163
+ import { clsx as clsx2 } from "clsx";
164
+ import { extendTailwindMerge } from "tailwind-merge";
165
+ var twMerge2 = extendTailwindMerge({ prefix: "polli" });
166
+ function cn2(...inputs) {
167
+ return twMerge2(clsx2(...inputs));
168
+ }
169
+
170
+ // src/primitives/Button.tsx
171
+ import { jsx } from "react/jsx-runtime";
172
+ var sizes = {
173
+ small: "polli:px-2 polli:pt-0.5 polli:pb-1",
174
+ medium: "polli:px-4 polli:pt-1.5 polli:pb-2",
175
+ large: "polli:px-6 polli:py-3"
176
+ };
177
+ var themeClasses = "polli:bg-theme-bg-active polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:transition-colors";
178
+ var intentClasses = {
179
+ danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text polli:hover:bg-[oklch(0.88_0.075_25)] polli:transition-colors"
180
+ };
181
+ var buttonClasses = ({
182
+ theme: _theme,
183
+ intent,
184
+ size,
185
+ className,
186
+ disabled
187
+ }) => {
188
+ const colorClasses = intent ? intentClasses[intent] : themeClasses;
189
+ return cn2(
190
+ "polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:self-center polli:placeholder-green-950 polli:font-medium polli:leading-normal polli:box-border",
191
+ disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
192
+ colorClasses,
193
+ sizes[size || "medium"],
194
+ className
195
+ );
196
+ };
197
+ function Button({
198
+ as,
199
+ children,
200
+ theme,
201
+ intent,
202
+ size,
203
+ className,
204
+ disabled,
205
+ ...buttonProps
206
+ }) {
207
+ const Component = as || "button";
208
+ return /* @__PURE__ */ jsx(
209
+ Component,
210
+ {
211
+ "data-theme": intent ? void 0 : theme,
212
+ className: buttonClasses({
213
+ theme,
214
+ intent,
215
+ size,
216
+ className,
217
+ disabled
218
+ }),
219
+ disabled,
220
+ ...buttonProps,
221
+ children
222
+ }
223
+ );
224
+ }
225
+
226
+ // src/primitives/ChevronIcon.tsx
227
+ import { jsx as jsx2 } from "react/jsx-runtime";
228
+ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ jsx2(
229
+ "svg",
230
+ {
231
+ "aria-hidden": "true",
232
+ width: "12",
233
+ height: "12",
234
+ viewBox: "0 0 12 12",
235
+ className: cn2(
236
+ "polli:shrink-0 polli:transition-transform polli:duration-200 polli:ease-out",
237
+ expanded && "polli:rotate-180",
238
+ className
239
+ ),
240
+ children: /* @__PURE__ */ jsx2(
241
+ "path",
242
+ {
243
+ d: "M3 4.5 6 7.5l3-3",
244
+ fill: "none",
245
+ stroke: "currentColor",
246
+ strokeLinecap: "round",
247
+ strokeLinejoin: "round",
248
+ strokeWidth: "1.5"
249
+ }
250
+ )
251
+ }
252
+ );
253
+
254
+ // src/primitives/Chip.tsx
255
+ import { jsx as jsx3 } from "react/jsx-runtime";
256
+ var chipSizes = {
257
+ sm: "polli:px-2 polli:py-0.5 polli:text-xs",
258
+ md: "polli:px-2.5 polli:py-0.5 polli:text-sm",
259
+ lg: "polli:px-3 polli:py-1 polli:text-sm"
260
+ };
261
+ var intentClasses2 = {
262
+ news: "polli:bg-[oklch(0.935_0.06_158)] polli:text-[oklch(0.46_0.13_158)]",
263
+ alpha: "polli:bg-[oklch(0.93_0.06_300)] polli:text-[oklch(0.42_0.18_300)]",
264
+ neutral: "polli:border polli:border-gray-400/70 polli:bg-gray-100/80 polli:text-gray-900"
265
+ };
266
+ var Chip = ({
267
+ theme,
268
+ intent,
269
+ size = "md",
270
+ className,
271
+ children,
272
+ ...rest
273
+ }) => {
274
+ const intentClass = intent ? intentClasses2[intent] : "polli:bg-theme-bg-active polli:text-theme-text-strong";
275
+ return /* @__PURE__ */ jsx3(
276
+ "span",
277
+ {
278
+ ...rest,
279
+ "data-theme": theme,
280
+ className: cn2(
281
+ "polli:inline-flex polli:shrink-0 polli:items-center polli:gap-1 polli:rounded-lg polli:font-medium polli:leading-normal",
282
+ chipSizes[size],
283
+ intentClass,
284
+ className
285
+ ),
286
+ children
287
+ }
288
+ );
289
+ };
290
+
291
+ // src/primitives/Collapsible.tsx
292
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
293
+ var Collapsible = ({
294
+ label,
295
+ expanded,
296
+ onToggle,
297
+ children,
298
+ disabled = false,
299
+ wrapperClassName,
300
+ hoverClassName = "polli:hover:bg-theme-bg-active",
301
+ focusClassName,
302
+ panelClassName = "polli:border-t polli:border-theme-border polli:px-3 polli:pt-3 polli:pb-3",
303
+ ariaLabel
304
+ }) => /* @__PURE__ */ jsxs(
305
+ "div",
306
+ {
307
+ className: cn2(
308
+ "polli:rounded-lg polli:border polli:transition-all",
309
+ wrapperClassName,
310
+ disabled && "polli:opacity-50"
311
+ ),
312
+ children: [
313
+ /* @__PURE__ */ jsxs(
314
+ "button",
315
+ {
316
+ type: "button",
317
+ "aria-expanded": expanded,
318
+ "aria-label": ariaLabel,
319
+ disabled,
320
+ onClick: onToggle,
321
+ className: cn2(
322
+ "polli:w-full polli:flex polli:items-center polli:gap-3 polli:px-3 polli:py-2 polli:text-left polli:transition-colors",
323
+ expanded ? "polli:rounded-t-lg" : "polli:rounded-lg",
324
+ !disabled && hoverClassName,
325
+ focusClassName,
326
+ disabled ? "polli:cursor-not-allowed" : "polli:cursor-pointer"
327
+ ),
328
+ children: [
329
+ /* @__PURE__ */ jsx4("div", { className: "polli:flex-1 polli:min-w-0", children: label }),
330
+ /* @__PURE__ */ jsx4(
331
+ ChevronIcon,
332
+ {
333
+ expanded,
334
+ className: "polli:text-theme-text-soft"
335
+ }
336
+ )
337
+ ]
338
+ }
339
+ ),
340
+ expanded && /* @__PURE__ */ jsx4("div", { className: panelClassName, children })
341
+ ]
342
+ }
343
+ );
344
+
345
+ // src/primitives/CopyButton.tsx
346
+ import {
347
+ useEffect as useEffect2,
348
+ useRef as useRef2,
349
+ useState as useState2
350
+ } from "react";
351
+
352
+ // src/primitives/Tooltip.tsx
353
+ import {
354
+ useRef,
355
+ useState
356
+ } from "react";
357
+ import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
358
+ var TOOLTIP_MAX_WIDTH = 288;
359
+ var TOOLTIP_VIEWPORT_MARGIN = 12;
360
+ var Tooltip = ({
361
+ children,
362
+ content,
363
+ ariaLabel,
364
+ className,
365
+ onClick,
366
+ style,
367
+ triggerAs = "button",
368
+ displayContents = false
369
+ }) => {
370
+ const [showTooltip, setShowTooltip] = useState(false);
371
+ const [tooltipPosition, setTooltipPosition] = useState({
372
+ top: 0,
373
+ left: 0,
374
+ maxWidth: TOOLTIP_MAX_WIDTH
375
+ });
376
+ const triggerRef = useRef(null);
377
+ const updateTooltipPosition = () => {
378
+ if (triggerRef.current) {
379
+ const rect = triggerRef.current.getBoundingClientRect();
380
+ const maxWidth = Math.min(
381
+ TOOLTIP_MAX_WIDTH,
382
+ window.innerWidth - TOOLTIP_VIEWPORT_MARGIN * 2
383
+ );
384
+ const left = Math.min(
385
+ Math.max(rect.left, TOOLTIP_VIEWPORT_MARGIN),
386
+ Math.max(
387
+ TOOLTIP_VIEWPORT_MARGIN,
388
+ window.innerWidth - maxWidth - TOOLTIP_VIEWPORT_MARGIN
389
+ )
390
+ );
391
+ setTooltipPosition({
392
+ top: rect.bottom + 4,
393
+ left,
394
+ maxWidth
395
+ });
396
+ }
397
+ };
398
+ const triggerClassName = cn2(
399
+ "polli:relative polli:cursor-help polli:text-left polli:inline-flex polli:items-center",
400
+ className
401
+ );
402
+ const cursorClass = displayContents ? "polli:contents" : "polli:cursor-help";
403
+ const popupClasses = "polli:fixed polli:w-max polli:px-2 polli:py-1 polli:bg-theme-bg-pale polli:text-theme-text-strong polli:border polli:border-theme-border polli:text-xs polli:rounded-md polli:shadow-sm polli:z-50 polli:pointer-events-none polli:transition-opacity polli:whitespace-pre-line polli:break-words";
404
+ const contentNode = /* @__PURE__ */ jsxs2(Fragment, { children: [
405
+ /* @__PURE__ */ jsx5("span", { className: cursorClass, children }),
406
+ /* @__PURE__ */ jsx5(
407
+ "span",
408
+ {
409
+ style: {
410
+ top: tooltipPosition.top,
411
+ left: tooltipPosition.left,
412
+ maxWidth: tooltipPosition.maxWidth
413
+ },
414
+ className: `${showTooltip ? "polli:visible polli:opacity-100" : "polli:invisible polli:opacity-0"} ${popupClasses}`,
415
+ children: content
416
+ }
417
+ )
418
+ ] });
419
+ const sharedProps = {
420
+ "aria-label": ariaLabel,
421
+ className: triggerClassName,
422
+ onMouseEnter: () => {
423
+ updateTooltipPosition();
424
+ setShowTooltip(true);
425
+ },
426
+ onMouseLeave: () => setShowTooltip(false),
427
+ onClick: (e) => {
428
+ e.stopPropagation();
429
+ if (onClick) {
430
+ onClick();
431
+ }
432
+ if (triggerAs === "span") {
433
+ return;
434
+ }
435
+ updateTooltipPosition();
436
+ setShowTooltip((prev) => !prev);
437
+ },
438
+ style
439
+ };
440
+ if (triggerAs === "span") {
441
+ return /* @__PURE__ */ jsx5(
442
+ "span",
443
+ {
444
+ ref: (node) => {
445
+ triggerRef.current = node;
446
+ },
447
+ ...sharedProps,
448
+ children: contentNode
449
+ }
450
+ );
451
+ }
452
+ return /* @__PURE__ */ jsx5(
453
+ "button",
454
+ {
455
+ ref: (node) => {
456
+ triggerRef.current = node;
457
+ },
458
+ type: "button",
459
+ "aria-label": ariaLabel,
460
+ className: triggerClassName,
461
+ onMouseEnter: sharedProps.onMouseEnter,
462
+ onMouseLeave: sharedProps.onMouseLeave,
463
+ onClick: sharedProps.onClick,
464
+ style,
465
+ children: contentNode
466
+ }
467
+ );
468
+ };
469
+
470
+ // src/primitives/CopyButton.tsx
471
+ import { jsx as jsx6 } from "react/jsx-runtime";
472
+ function CopyButton({
473
+ value,
474
+ children,
475
+ copiedTimeoutMs = 2e3,
476
+ tooltip = "Click to copy",
477
+ copiedTooltip = "Copied!",
478
+ tooltipClassName,
479
+ className,
480
+ onCopied,
481
+ onCopyError,
482
+ ...buttonProps
483
+ }) {
484
+ const [copied, setCopied] = useState2(false);
485
+ const timeoutRef = useRef2(null);
486
+ useEffect2(
487
+ () => () => {
488
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
489
+ },
490
+ []
491
+ );
492
+ async function handleCopy(event) {
493
+ event.stopPropagation();
494
+ try {
495
+ const text = typeof value === "function" ? await value() : value;
496
+ await navigator.clipboard.writeText(text);
497
+ setCopied(true);
498
+ onCopied?.();
499
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
500
+ timeoutRef.current = setTimeout(
501
+ () => setCopied(false),
502
+ copiedTimeoutMs
503
+ );
504
+ } catch (error) {
505
+ onCopyError?.(error);
506
+ }
507
+ }
508
+ const button = /* @__PURE__ */ jsx6(
509
+ "button",
510
+ {
511
+ ...buttonProps,
512
+ type: "button",
513
+ onClick: handleCopy,
514
+ className: cn2(
515
+ typeof className === "function" ? className(copied) : className
516
+ ),
517
+ children: typeof children === "function" ? children(copied) : children
518
+ }
519
+ );
520
+ return /* @__PURE__ */ jsx6(
521
+ Tooltip,
522
+ {
523
+ triggerAs: "span",
524
+ content: copied ? copiedTooltip : tooltip,
525
+ className: tooltipClassName,
526
+ children: button
527
+ }
528
+ );
529
+ }
530
+
531
+ // src/primitives/Dialog.tsx
532
+ import { Dialog as ArkDialog } from "@ark-ui/react/dialog";
533
+ import { Portal } from "@ark-ui/react/portal";
534
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
535
+ var sizeClasses = {
536
+ sm: "polli:max-w-md",
537
+ md: "polli:max-w-xl",
538
+ lg: "polli:max-w-2xl"
539
+ };
540
+ var Dialog = ({
541
+ open,
542
+ onOpenChange,
543
+ trigger,
544
+ triggerAsChild = false,
545
+ triggerClassName,
546
+ title,
547
+ titleClassName,
548
+ ariaLabel,
549
+ labelledBy,
550
+ theme = "blue",
551
+ size = "md",
552
+ showBackdrop = true,
553
+ backdropClassName,
554
+ positionerClassName,
555
+ contentClassName,
556
+ children
557
+ }) => /* @__PURE__ */ jsxs3(
558
+ ArkDialog.Root,
559
+ {
560
+ open,
561
+ onOpenChange: (details) => onOpenChange?.(details.open),
562
+ children: [
563
+ trigger && /* @__PURE__ */ jsx7(
564
+ ArkDialog.Trigger,
565
+ {
566
+ asChild: triggerAsChild,
567
+ className: triggerClassName,
568
+ children: trigger
569
+ }
570
+ ),
571
+ /* @__PURE__ */ jsxs3(Portal, { children: [
572
+ showBackdrop && /* @__PURE__ */ jsx7(
573
+ ArkDialog.Backdrop,
574
+ {
575
+ className: cn2(
576
+ "polli:fixed polli:inset-0 polli:z-[100] polli:bg-gray-950/50",
577
+ backdropClassName
578
+ )
579
+ }
580
+ ),
581
+ /* @__PURE__ */ jsx7(
582
+ ArkDialog.Positioner,
583
+ {
584
+ className: cn2(
585
+ "polli:fixed polli:inset-0 polli:z-[110] polli:flex polli:h-dvh polli:items-start polli:justify-center polli:overflow-hidden polli:p-4",
586
+ positionerClassName
587
+ ),
588
+ children: /* @__PURE__ */ jsxs3(
589
+ ArkDialog.Content,
590
+ {
591
+ "data-theme": theme,
592
+ "aria-label": ariaLabel,
593
+ "aria-labelledby": labelledBy,
594
+ className: cn2(
595
+ "polli:my-auto polli:w-full polli:overflow-hidden polli:rounded-lg polli:border-2 polli:border-theme-border polli:bg-white polli:shadow-lg",
596
+ sizeClasses[size],
597
+ contentClassName
598
+ ),
599
+ children: [
600
+ title && /* @__PURE__ */ jsx7(
601
+ DialogTitle,
602
+ {
603
+ className: cn2(
604
+ "polli:px-6 polli:pt-6 polli:font-subheading polli:text-xl polli:text-theme-text-strong",
605
+ titleClassName
606
+ ),
607
+ children: title
608
+ }
609
+ ),
610
+ children
611
+ ]
612
+ }
613
+ )
614
+ }
615
+ )
616
+ ] })
617
+ ]
618
+ }
619
+ );
620
+ var DialogTitle = ArkDialog.Title;
621
+
622
+ // src/primitives/Dropdown.tsx
623
+ import { Popover } from "@ark-ui/react/popover";
624
+ import { Portal as Portal2 } from "@ark-ui/react/portal";
625
+ import { useState as useState3 } from "react";
626
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
627
+ var DEFAULT_PANEL = "polli:rounded-lg polli:border polli:border-theme-border polli:bg-surface-white polli:shadow-lg";
628
+ var Dropdown = ({
629
+ theme,
630
+ trigger,
631
+ children,
632
+ align = "start",
633
+ open: openProp,
634
+ onOpenChange,
635
+ panelClassName,
636
+ className
637
+ }) => {
638
+ const [internalOpen, setInternalOpen] = useState3(false);
639
+ const isControlled = openProp !== void 0;
640
+ const open = isControlled ? openProp : internalOpen;
641
+ const setOpen = (next) => {
642
+ if (!isControlled) setInternalOpen(next);
643
+ onOpenChange?.(next);
644
+ };
645
+ return /* @__PURE__ */ jsxs4(
646
+ Popover.Root,
647
+ {
648
+ open,
649
+ onOpenChange: (details) => setOpen(details.open),
650
+ positioning: {
651
+ placement: align === "end" ? "bottom-end" : "bottom-start"
652
+ },
653
+ children: [
654
+ /* @__PURE__ */ jsx8(Popover.Trigger, { asChild: true, children: trigger(open) }),
655
+ /* @__PURE__ */ jsx8(Portal2, { children: /* @__PURE__ */ jsx8(Popover.Positioner, { children: /* @__PURE__ */ jsx8(
656
+ Popover.Content,
657
+ {
658
+ "data-theme": theme,
659
+ className: cn2(
660
+ "polli:z-50 polli:overflow-hidden polli:focus:outline-none",
661
+ panelClassName ?? DEFAULT_PANEL,
662
+ className
663
+ ),
664
+ children: typeof children === "function" ? children(() => setOpen(false)) : children
665
+ }
666
+ ) }) })
667
+ ]
668
+ }
669
+ );
670
+ };
671
+
672
+ // src/primitives/icons/index.tsx
673
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
674
+ var strokeProps = {
675
+ fill: "none",
676
+ stroke: "currentColor",
677
+ strokeWidth: 2,
678
+ strokeLinecap: "round",
679
+ strokeLinejoin: "round"
680
+ };
681
+ function AppIcon(props) {
682
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
683
+ /* @__PURE__ */ jsx9("rect", { x: "2", y: "4", width: "20", height: "14", rx: "2" }),
684
+ /* @__PURE__ */ jsx9("path", { d: "M2 20h20" })
685
+ ] });
686
+ }
687
+ function BeakerIcon(props) {
688
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
689
+ /* @__PURE__ */ jsx9("path", { d: "M9 3h6" }),
690
+ /* @__PURE__ */ jsx9("path", { d: "M10 3v6.5L4.5 18a2 2 0 0 0 1.7 3h11.6a2 2 0 0 0 1.7-3L14 9.5V3" }),
691
+ /* @__PURE__ */ jsx9("path", { d: "M7 14h10" })
692
+ ] });
693
+ }
694
+ function BookIcon(props) {
695
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
696
+ /* @__PURE__ */ jsx9("path", { d: "M4 4h5a3 3 0 0 1 3 3v13a2 2 0 0 0-2-2H4z" }),
697
+ /* @__PURE__ */ jsx9("path", { d: "M20 4h-5a3 3 0 0 0-3 3v13a2 2 0 0 1 2-2h6z" })
698
+ ] });
699
+ }
700
+ function CheckIcon(props) {
701
+ return /* @__PURE__ */ jsx9(
702
+ "svg",
703
+ {
704
+ "aria-hidden": "true",
705
+ viewBox: "0 0 24 24",
706
+ ...strokeProps,
707
+ strokeWidth: 2.5,
708
+ ...props,
709
+ children: /* @__PURE__ */ jsx9("polyline", { points: "20 6 9 17 4 12" })
710
+ }
711
+ );
712
+ }
713
+ function ClipboardIcon(props) {
714
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
715
+ /* @__PURE__ */ jsx9("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
716
+ /* @__PURE__ */ jsx9("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
717
+ ] });
718
+ }
719
+ function ClockIcon(props) {
720
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
721
+ /* @__PURE__ */ jsx9("circle", { cx: "12", cy: "12", r: "9" }),
722
+ /* @__PURE__ */ jsx9("path", { d: "M12 7v5l3 2" })
723
+ ] });
724
+ }
725
+ function DiscordIcon(props) {
726
+ return /* @__PURE__ */ jsx9("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx9(
727
+ "path",
728
+ {
729
+ fill: "currentColor",
730
+ d: "M20.32 4.37A19.8 19.8 0 0 0 15.36 2.83a.07.07 0 0 0-.08.04c-.21.38-.45.88-.62 1.27a18.27 18.27 0 0 0-5.52 0 12.84 12.84 0 0 0-.63-1.27.08.08 0 0 0-.08-.04A19.74 19.74 0 0 0 3.47 4.37a.07.07 0 0 0-.03.03C.31 9.07-.55 13.61-.13 18.1a.08.08 0 0 0 .03.06 19.9 19.9 0 0 0 6.08 3.07.08.08 0 0 0 .09-.03c.47-.64.88-1.31 1.24-2.02a.08.08 0 0 0-.04-.1 13.08 13.08 0 0 1-1.9-.91.08.08 0 0 1-.01-.13c.13-.1.25-.2.37-.29a.07.07 0 0 1 .08-.01 14.24 14.24 0 0 0 12.38 0 .07.07 0 0 1 .08.01c.12.1.25.2.38.3a.08.08 0 0 1-.01.12 12.22 12.22 0 0 1-1.9.9.08.08 0 0 0-.04.11c.36.7.77 1.38 1.23 2.02a.08.08 0 0 0 .1.03 19.84 19.84 0 0 0 6.08-3.07.08.08 0 0 0 .03-.05c.5-5.2-.84-9.7-3.77-13.71a.06.06 0 0 0-.03-.03ZM8.02 15.37c-1.18 0-2.16-1.08-2.16-2.4 0-1.32.96-2.4 2.16-2.4 1.2 0 2.18 1.09 2.16 2.4 0 1.32-.96 2.4-2.16 2.4Zm7.96 0c-1.18 0-2.16-1.08-2.16-2.4 0-1.32.96-2.4 2.16-2.4 1.2 0 2.18 1.09 2.16 2.4 0 1.32-.95 2.4-2.16 2.4Z"
731
+ }
732
+ ) });
733
+ }
734
+ function DownloadIcon(props) {
735
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
736
+ /* @__PURE__ */ jsx9("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
737
+ /* @__PURE__ */ jsx9("polyline", { points: "7 10 12 15 17 10" }),
738
+ /* @__PURE__ */ jsx9("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
739
+ ] });
740
+ }
741
+ function ExternalLinkIcon(props) {
742
+ return /* @__PURE__ */ jsx9("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: /* @__PURE__ */ jsx9("path", { d: "M7 17 17 7M9 7h8v8" }) });
743
+ }
744
+ function GenApiIcon(props) {
745
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
746
+ /* @__PURE__ */ jsx9("path", { d: "m8 3 4 1.5L16 3v18l-4-1.5L8 21z" }),
747
+ /* @__PURE__ */ jsx9("path", { d: "M8 3v18M16 3v18" })
748
+ ] });
749
+ }
750
+ function GitHubIcon(props) {
751
+ return /* @__PURE__ */ jsx9("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", ...props, children: /* @__PURE__ */ jsx9(
752
+ "path",
753
+ {
754
+ fill: "currentColor",
755
+ d: "M12 .5A11.5 11.5 0 0 0 8.36 22.9c.58.11.79-.25.79-.56v-2.16c-3.21.7-3.89-1.38-3.89-1.38-.53-1.34-1.29-1.7-1.29-1.7-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.04 1.76 2.71 1.25 3.37.96.11-.75.4-1.25.74-1.54-2.56-.29-5.26-1.28-5.26-5.7 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.46.11-3.06 0 0 .97-.31 3.16 1.18a10.88 10.88 0 0 1 5.76 0c2.19-1.49 3.15-1.18 3.15-1.18.63 1.6.23 2.77.11 3.06.74.81 1.19 1.84 1.19 3.1 0 4.43-2.7 5.4-5.27 5.69.41.36.78 1.06.78 2.14v3.19c0 .31.21.68.8.56A11.5 11.5 0 0 0 12 .5Z"
756
+ }
757
+ ) });
758
+ }
759
+ function ImageIcon(props) {
760
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
761
+ /* @__PURE__ */ jsx9("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
762
+ /* @__PURE__ */ jsx9("circle", { cx: "9", cy: "9", r: "2" }),
763
+ /* @__PURE__ */ jsx9("path", { d: "m21 15-5-5L5 21" })
764
+ ] });
765
+ }
766
+ function LockIcon(props) {
767
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
768
+ /* @__PURE__ */ jsx9("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
769
+ /* @__PURE__ */ jsx9("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
770
+ ] });
771
+ }
772
+ function MailIcon(props) {
773
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
774
+ /* @__PURE__ */ jsx9("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
775
+ /* @__PURE__ */ jsx9("path", { d: "m3 7 9 7 9-7" })
776
+ ] });
777
+ }
778
+ function McpIcon(props) {
779
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
780
+ /* @__PURE__ */ jsx9("rect", { x: "2", y: "7", width: "8", height: "10", rx: "1.5" }),
781
+ /* @__PURE__ */ jsx9("rect", { x: "14", y: "7", width: "8", height: "10", rx: "1.5" }),
782
+ /* @__PURE__ */ jsx9("path", { d: "M10 12h4" })
783
+ ] });
784
+ }
785
+ function MenuIcon(props) {
786
+ return /* @__PURE__ */ jsx9("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: /* @__PURE__ */ jsx9("path", { d: "M4 7h16M4 12h16M4 17h16" }) });
787
+ }
788
+ function TerminalIcon(props) {
789
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
790
+ /* @__PURE__ */ jsx9("polyline", { points: "4 8 8 12 4 16" }),
791
+ /* @__PURE__ */ jsx9("line", { x1: "12", y1: "20", x2: "20", y2: "20" })
792
+ ] });
793
+ }
794
+ function TokensIcon(props) {
795
+ return /* @__PURE__ */ jsx9("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: /* @__PURE__ */ jsx9("path", { d: "M4 9h16M4 15h16M10 3 8 21M16 3l-2 18" }) });
796
+ }
797
+ function TrendUpIcon(props) {
798
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
799
+ /* @__PURE__ */ jsx9("polyline", { points: "3 17 9 11 13 15 21 7" }),
800
+ /* @__PURE__ */ jsx9("polyline", { points: "15 7 21 7 21 13" })
801
+ ] });
802
+ }
803
+ function WalletIcon(props) {
804
+ return /* @__PURE__ */ jsxs5("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
805
+ /* @__PURE__ */ jsx9("path", { d: "M3 7a2 2 0 0 1 2-2h13a2 2 0 0 1 2 2v2H5a2 2 0 0 0-2 2V7Z" }),
806
+ /* @__PURE__ */ jsx9("path", { d: "M3 11a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6Z" }),
807
+ /* @__PURE__ */ jsx9("circle", { cx: "17", cy: "14", r: "1.25", fill: "currentColor" })
808
+ ] });
809
+ }
810
+ function XIcon(props) {
811
+ return /* @__PURE__ */ jsx9("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: /* @__PURE__ */ jsx9("path", { d: "M18 6 6 18M6 6l12 12" }) });
812
+ }
813
+
814
+ // src/primitives/ExternalLinkButton.tsx
815
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
816
+ var ExternalLinkButton = ({
817
+ theme,
818
+ href,
819
+ size = "medium",
820
+ className,
821
+ children
822
+ }) => /* @__PURE__ */ jsxs6(
823
+ Button,
824
+ {
825
+ as: "a",
826
+ href,
827
+ target: "_blank",
828
+ rel: "noopener noreferrer",
829
+ theme,
830
+ size,
831
+ className: cn2("polli:gap-2", className),
832
+ children: [
833
+ /* @__PURE__ */ jsx10("span", { children }),
834
+ /* @__PURE__ */ jsx10(
835
+ ExternalLinkIcon,
836
+ {
837
+ className: "polli:h-4 polli:w-4 polli:shrink-0 polli:opacity-60",
838
+ "aria-hidden": "true"
839
+ }
840
+ )
841
+ ]
842
+ }
843
+ );
844
+
845
+ // src/primitives/Field.tsx
846
+ import { Field } from "@ark-ui/react/field";
847
+
848
+ // src/primitives/IconButton.tsx
849
+ import { jsx as jsx11 } from "react/jsx-runtime";
850
+ var intentClasses3 = {
851
+ danger: "polli:bg-intent-danger-bg-light polli:hover:bg-[oklch(0.88_0.075_25)] polli:text-intent-danger-text"
852
+ };
853
+ var defaultClasses = "polli:bg-theme-bg-active polli:hover:bg-theme-bg-hover polli:text-theme-text-soft polli:hover:text-theme-text-strong";
854
+ var IconButton = ({
855
+ intent,
856
+ title,
857
+ onClick,
858
+ children,
859
+ className
860
+ }) => /* @__PURE__ */ jsx11(
861
+ "button",
862
+ {
863
+ type: "button",
864
+ onClick,
865
+ title,
866
+ "aria-label": title,
867
+ className: cn2(
868
+ "polli:inline-flex polli:h-6 polli:w-6 polli:cursor-pointer polli:items-center polli:justify-center polli:rounded polli:transition-colors",
869
+ intent ? intentClasses3[intent] : defaultClasses,
870
+ className
871
+ ),
872
+ children
873
+ }
874
+ );
875
+
876
+ // src/primitives/InfoTip.tsx
877
+ import { jsx as jsx12 } from "react/jsx-runtime";
878
+ var InfoTip = ({
879
+ text,
880
+ content,
881
+ label = "More info"
882
+ }) => /* @__PURE__ */ jsx12(Tooltip, { content: content ?? text, ariaLabel: label, className: "polli:ml-1", children: /* @__PURE__ */ jsx12("span", { className: "polli:inline-flex polli:h-3.5 polli:w-3.5 polli:items-center polli:justify-center polli:rounded-full polli:border polli:border-theme-border polli:bg-theme-bg-active polli:font-bold polli:text-micro polli:text-theme-text-strong polli:transition-colors", children: "i" }) });
883
+
884
+ // src/primitives/Input.tsx
885
+ import { forwardRef } from "react";
886
+ import { jsx as jsx13 } from "react/jsx-runtime";
887
+ var Input = forwardRef(
888
+ ({ className, error, hideNumberSteppers, ...props }, ref) => /* @__PURE__ */ jsx13(
889
+ "input",
890
+ {
891
+ ref,
892
+ className: cn2(
893
+ "polli:px-3 polli:py-2 polli:border polli:rounded-lg",
894
+ "polli:disabled:opacity-50 polli:disabled:cursor-not-allowed",
895
+ error ? "polli:border-red-400" : "polli:border-gray-300",
896
+ hideNumberSteppers && "polli-input-number-clean",
897
+ className
898
+ ),
899
+ ...props
900
+ }
901
+ )
902
+ );
903
+
904
+ // src/primitives/ScrollArea.tsx
905
+ import {
906
+ forwardRef as forwardRef2,
907
+ useCallback,
908
+ useEffect as useEffect3,
909
+ useRef as useRef3
910
+ } from "react";
911
+ import { jsx as jsx14 } from "react/jsx-runtime";
912
+ var axisClasses = {
913
+ y: "polli:overflow-y-auto polli:overflow-x-hidden",
914
+ x: "polli:overflow-x-auto polli:overflow-y-hidden",
915
+ both: "polli:overflow-auto"
916
+ };
917
+ function assignRef(ref, value) {
918
+ if (typeof ref === "function") ref(value);
919
+ else if (ref) ref.current = value;
920
+ }
921
+ var ScrollArea = forwardRef2(
922
+ ({ theme, axis = "y", hideDelayMs = 2e3, className, children, ...rest }, externalRef) => {
923
+ const innerRef = useRef3(null);
924
+ const setRef = useCallback(
925
+ (node) => {
926
+ innerRef.current = node;
927
+ assignRef(externalRef, node);
928
+ },
929
+ [externalRef]
930
+ );
931
+ useEffect3(() => {
932
+ const element = innerRef.current;
933
+ if (!element) return;
934
+ let hideTimer = null;
935
+ const clearHideTimer = () => {
936
+ if (hideTimer !== null) {
937
+ window.clearTimeout(hideTimer);
938
+ hideTimer = null;
939
+ }
940
+ };
941
+ const show = () => {
942
+ element.dataset.scrollbarActive = "true";
943
+ clearHideTimer();
944
+ };
945
+ const hide = () => {
946
+ element.dataset.scrollbarActive = "false";
947
+ clearHideTimer();
948
+ };
949
+ const scheduleHide = () => {
950
+ clearHideTimer();
951
+ hideTimer = window.setTimeout(hide, hideDelayMs);
952
+ };
953
+ const handleInteraction = () => {
954
+ show();
955
+ scheduleHide();
956
+ };
957
+ hide();
958
+ element.addEventListener("scroll", handleInteraction, {
959
+ passive: true
960
+ });
961
+ element.addEventListener("wheel", handleInteraction, {
962
+ passive: true
963
+ });
964
+ element.addEventListener("touchstart", handleInteraction, {
965
+ passive: true
966
+ });
967
+ element.addEventListener("pointerdown", handleInteraction);
968
+ element.addEventListener("keydown", handleInteraction);
969
+ element.addEventListener("focusin", handleInteraction);
970
+ element.addEventListener("focusout", scheduleHide);
971
+ return () => {
972
+ clearHideTimer();
973
+ element.removeEventListener("scroll", handleInteraction);
974
+ element.removeEventListener("wheel", handleInteraction);
975
+ element.removeEventListener("touchstart", handleInteraction);
976
+ element.removeEventListener("pointerdown", handleInteraction);
977
+ element.removeEventListener("keydown", handleInteraction);
978
+ element.removeEventListener("focusin", handleInteraction);
979
+ element.removeEventListener("focusout", scheduleHide);
980
+ };
981
+ }, [hideDelayMs]);
982
+ return /* @__PURE__ */ jsx14(
983
+ "div",
984
+ {
985
+ ...rest,
986
+ ref: setRef,
987
+ "data-theme": theme,
988
+ className: cn2(
989
+ "polli-scrollbar-subtle",
990
+ axisClasses[axis],
991
+ className
992
+ ),
993
+ children
994
+ }
995
+ );
996
+ }
997
+ );
998
+ ScrollArea.displayName = "ScrollArea";
999
+
1000
+ // src/primitives/MultiSelect.tsx
1001
+ import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
1002
+ var TRIGGER_BASE = "polli:inline-flex polli:min-h-8 polli:min-w-[140px] polli:items-center polli:gap-2 polli:rounded-full polli:border polli:px-3 polli:py-1.5 polli:text-xs polli:font-medium polli:transition-all polli:duration-200";
1003
+ var ROW_BASE = "polli:flex polli:w-full polli:items-center polli:gap-3 polli:px-3 polli:py-2 polli:text-left polli:text-xs polli:transition-colors";
1004
+ var CHECK_BASE = "polli:flex polli:h-4 polli:w-4 polli:flex-shrink-0 polli:items-center polli:justify-center polli:rounded polli:border polli:border-theme-border polli:text-xs";
1005
+ var MultiSelect = ({
1006
+ options,
1007
+ selected,
1008
+ onChange,
1009
+ placeholder,
1010
+ disabled,
1011
+ disabledText,
1012
+ align = "start",
1013
+ label,
1014
+ theme
1015
+ }) => {
1016
+ const isAllSelected = selected.length === 0;
1017
+ const toggleItem = (itemId) => {
1018
+ if (selected.includes(itemId)) {
1019
+ onChange(selected.filter((m) => m !== itemId));
1020
+ } else {
1021
+ onChange([...selected, itemId]);
1022
+ }
1023
+ };
1024
+ const selectAll = () => onChange([]);
1025
+ const displayText = disabled ? disabledText : isAllSelected ? "All" : `${selected.length} selected`;
1026
+ const labelNode = label ? /* @__PURE__ */ jsx15("span", { className: "polli:text-xs polli:font-medium polli:text-theme-text-soft", children: label }) : null;
1027
+ if (disabled) {
1028
+ return /* @__PURE__ */ jsxs7(
1029
+ "div",
1030
+ {
1031
+ "data-theme": theme,
1032
+ className: "polli:group polli:relative polli:flex polli:items-center polli:gap-2",
1033
+ children: [
1034
+ labelNode,
1035
+ /* @__PURE__ */ jsxs7(
1036
+ "button",
1037
+ {
1038
+ type: "button",
1039
+ disabled: true,
1040
+ className: cn2(
1041
+ TRIGGER_BASE,
1042
+ "polli:cursor-not-allowed polli:border-theme-border polli:bg-theme-bg-subtle polli:opacity-60"
1043
+ ),
1044
+ children: [
1045
+ /* @__PURE__ */ jsx15("span", { className: "polli:flex-1 polli:truncate polli:text-left polli:text-theme-text-soft/60", children: displayText }),
1046
+ /* @__PURE__ */ jsx15(
1047
+ ChevronIcon,
1048
+ {
1049
+ expanded: false,
1050
+ className: "polli:h-3 polli:w-3 polli:text-theme-text-soft"
1051
+ }
1052
+ )
1053
+ ]
1054
+ }
1055
+ ),
1056
+ /* @__PURE__ */ jsx15("span", { className: "polli:pointer-events-none polli:absolute polli:-top-8 polli:left-1/2 polli:z-[100] polli:-translate-x-1/2 polli:whitespace-nowrap polli:rounded-md polli:border polli:border-theme-border polli:bg-theme-bg-pale polli:px-2 polli:py-1 polli:text-xs polli:text-theme-text-strong polli:opacity-0 polli:shadow-sm polli:transition-opacity polli:group-hover:opacity-100", children: "No items available" })
1057
+ ]
1058
+ }
1059
+ );
1060
+ }
1061
+ return /* @__PURE__ */ jsxs7(
1062
+ "div",
1063
+ {
1064
+ "data-theme": theme,
1065
+ className: "polli:flex polli:items-center polli:gap-2",
1066
+ children: [
1067
+ labelNode,
1068
+ /* @__PURE__ */ jsx15(
1069
+ Dropdown,
1070
+ {
1071
+ theme,
1072
+ align,
1073
+ className: "polli:min-w-[320px]",
1074
+ trigger: (open) => /* @__PURE__ */ jsxs7(
1075
+ "button",
1076
+ {
1077
+ type: "button",
1078
+ className: cn2(
1079
+ TRIGGER_BASE,
1080
+ open ? "polli:border-theme-border polli:bg-theme-bg-active" : "polli:border-theme-border polli:bg-theme-bg-subtle polli:hover:bg-theme-bg-pale"
1081
+ ),
1082
+ children: [
1083
+ /* @__PURE__ */ jsx15(
1084
+ "span",
1085
+ {
1086
+ className: cn2(
1087
+ "polli:flex-1 polli:truncate polli:text-left",
1088
+ open ? "polli:text-theme-text-strong" : "polli:text-theme-text-base"
1089
+ ),
1090
+ children: displayText
1091
+ }
1092
+ ),
1093
+ /* @__PURE__ */ jsx15(
1094
+ ChevronIcon,
1095
+ {
1096
+ expanded: open,
1097
+ className: cn2(
1098
+ "polli:h-3 polli:w-3 polli:transition-transform",
1099
+ open ? "polli:text-theme-text-strong" : "polli:text-theme-text-soft"
1100
+ )
1101
+ }
1102
+ )
1103
+ ]
1104
+ }
1105
+ ),
1106
+ children: /* @__PURE__ */ jsxs7(ScrollArea, { theme, className: "polli:max-h-64", children: [
1107
+ /* @__PURE__ */ jsxs7(
1108
+ "button",
1109
+ {
1110
+ type: "button",
1111
+ onClick: selectAll,
1112
+ className: cn2(
1113
+ ROW_BASE,
1114
+ isAllSelected ? "polli:bg-theme-bg-active polli:font-medium polli:text-theme-text-strong" : "polli:text-theme-text-base polli:hover:bg-theme-bg-subtle"
1115
+ ),
1116
+ children: [
1117
+ /* @__PURE__ */ jsx15(
1118
+ "span",
1119
+ {
1120
+ className: cn2(
1121
+ CHECK_BASE,
1122
+ isAllSelected && "polli:bg-theme-bg-active polli:text-theme-text-strong"
1123
+ ),
1124
+ children: isAllSelected && "\u2713"
1125
+ }
1126
+ ),
1127
+ placeholder
1128
+ ]
1129
+ }
1130
+ ),
1131
+ options.map((opt) => {
1132
+ const isChecked = selected.includes(opt.value);
1133
+ return /* @__PURE__ */ jsxs7(
1134
+ "button",
1135
+ {
1136
+ type: "button",
1137
+ onClick: () => toggleItem(opt.value),
1138
+ className: cn2(
1139
+ ROW_BASE,
1140
+ isChecked ? "polli:bg-theme-bg-active polli:text-theme-text-strong" : "polli:text-theme-text-base polli:hover:bg-theme-bg-subtle"
1141
+ ),
1142
+ children: [
1143
+ /* @__PURE__ */ jsx15(
1144
+ "span",
1145
+ {
1146
+ className: cn2(
1147
+ CHECK_BASE,
1148
+ isChecked && "polli:bg-theme-bg-active polli:text-theme-text-strong"
1149
+ ),
1150
+ children: isChecked && "\u2713"
1151
+ }
1152
+ ),
1153
+ /* @__PURE__ */ jsx15("span", { className: "polli:whitespace-nowrap", children: opt.label })
1154
+ ]
1155
+ },
1156
+ opt.value
1157
+ );
1158
+ })
1159
+ ] })
1160
+ }
1161
+ )
1162
+ ]
1163
+ }
1164
+ );
1165
+ };
1166
+
1167
+ // src/primitives/PeriodPicker.tsx
1168
+ import { useEffect as useEffect4, useMemo, useState as useState4 } from "react";
1169
+
1170
+ // src/primitives/TabButton.tsx
1171
+ import { jsx as jsx16 } from "react/jsx-runtime";
1172
+ var sizeClasses2 = {
1173
+ medium: "polli:px-4 polli:py-1.5 polli:text-base",
1174
+ small: "polli:px-3 polli:py-1.5 polli:text-sm"
1175
+ };
1176
+ var TabButton = ({
1177
+ theme,
1178
+ active,
1179
+ onClick,
1180
+ children,
1181
+ size = "medium",
1182
+ ariaLabel,
1183
+ disabled = false,
1184
+ className
1185
+ }) => {
1186
+ return /* @__PURE__ */ jsx16(
1187
+ "button",
1188
+ {
1189
+ type: "button",
1190
+ "data-theme": theme,
1191
+ onClick,
1192
+ "aria-label": ariaLabel,
1193
+ "aria-pressed": active,
1194
+ disabled,
1195
+ className: cn2(
1196
+ "polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:border polli:font-medium polli:leading-normal polli:transition-all polli:duration-200",
1197
+ active ? "polli:bg-theme-bg-active polli:text-theme-text-strong polli:border-theme-border" : "polli:bg-theme-bg-subtle polli:text-theme-text-base polli:border-theme-border polli:hover:bg-theme-bg-active",
1198
+ disabled && "polli:cursor-not-allowed polli:opacity-50",
1199
+ sizeClasses2[size],
1200
+ className
1201
+ ),
1202
+ children
1203
+ }
1204
+ );
1205
+ };
1206
+
1207
+ // src/primitives/PeriodPicker.tsx
1208
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
1209
+ var WEEKDAY_LABELS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
1210
+ var MONTH_LABELS = [
1211
+ "Jan",
1212
+ "Feb",
1213
+ "Mar",
1214
+ "Apr",
1215
+ "May",
1216
+ "Jun",
1217
+ "Jul",
1218
+ "Aug",
1219
+ "Sep",
1220
+ "Oct",
1221
+ "Nov",
1222
+ "Dec"
1223
+ ];
1224
+ var NAV_BUTTON = "polli:rounded-full polli:px-2 polli:py-1 polli:text-xs polli:font-semibold polli:text-theme-text-base polli:transition-colors polli:hover:bg-theme-bg-subtle";
1225
+ function addUtcMonths2(date, months) {
1226
+ return new Date(
1227
+ Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, 1)
1228
+ );
1229
+ }
1230
+ function monthGridDates(viewMonth) {
1231
+ const firstDay = new Date(
1232
+ Date.UTC(viewMonth.getUTCFullYear(), viewMonth.getUTCMonth(), 1)
1233
+ );
1234
+ const firstWeekday = firstDay.getUTCDay() || 7;
1235
+ const cursor = addUtcDays(firstDay, 1 - firstWeekday);
1236
+ return Array.from({ length: 42 }, (_, index) => addUtcDays(cursor, index));
1237
+ }
1238
+ function sameUtcDay(left, right) {
1239
+ return left.getTime() === right.getTime();
1240
+ }
1241
+ function periodDate(value) {
1242
+ return periodToWindow(value).start;
1243
+ }
1244
+ function viewBounds(viewDate, granularity) {
1245
+ if (granularity === "month") {
1246
+ const start2 = new Date(Date.UTC(viewDate.getUTCFullYear(), 0, 1));
1247
+ return { start: start2, end: addUtcMonths2(start2, 12) };
1248
+ }
1249
+ const start = new Date(
1250
+ Date.UTC(viewDate.getUTCFullYear(), viewDate.getUTCMonth(), 1)
1251
+ );
1252
+ return { start, end: addUtcMonths2(start, 1) };
1253
+ }
1254
+ var PeriodPicker = ({
1255
+ value,
1256
+ onChange,
1257
+ theme,
1258
+ minDate = /* @__PURE__ */ new Date(0),
1259
+ maxDate
1260
+ }) => {
1261
+ const [open, setOpen] = useState4(false);
1262
+ const [viewDate, setViewDate] = useState4(() => periodDate(value));
1263
+ const { granularity, period } = value;
1264
+ useEffect4(() => {
1265
+ setViewDate(periodDate({ granularity, period }));
1266
+ }, [granularity, period]);
1267
+ const dates = useMemo(() => monthGridDates(viewDate), [viewDate]);
1268
+ const selectedWindow = periodToWindow(value);
1269
+ const today = startOfUtcDay(maxDate);
1270
+ const previousViewDate = value.granularity === "month" ? addUtcMonths2(viewDate, -12) : addUtcMonths2(viewDate, -1);
1271
+ const nextViewDate = value.granularity === "month" ? addUtcMonths2(viewDate, 12) : addUtcMonths2(viewDate, 1);
1272
+ const previousBounds = viewBounds(previousViewDate, value.granularity);
1273
+ const nextBounds = viewBounds(nextViewDate, value.granularity);
1274
+ const previousDisabled = previousBounds.end <= minDate;
1275
+ const nextDisabled = nextBounds.start > today;
1276
+ const setGranularity = (granularity2) => {
1277
+ onChange(periodFromDate(granularity2, periodDate(value)));
1278
+ };
1279
+ const selectDate = (date) => {
1280
+ onChange(periodFromDate(value.granularity, date));
1281
+ setOpen(false);
1282
+ };
1283
+ const viewLabel = value.granularity === "month" ? String(viewDate.getUTCFullYear()) : viewDate.toLocaleDateString("en-US", {
1284
+ timeZone: "UTC",
1285
+ month: "long",
1286
+ year: "numeric"
1287
+ });
1288
+ return /* @__PURE__ */ jsxs8(
1289
+ "div",
1290
+ {
1291
+ "data-theme": theme,
1292
+ className: "polli:flex polli:flex-wrap polli:items-center polli:gap-2",
1293
+ children: [
1294
+ /* @__PURE__ */ jsx17("div", { className: "polli:flex polli:flex-wrap polli:gap-1.5", children: ["day", "week", "month"].map(
1295
+ (granularity2) => /* @__PURE__ */ jsx17(
1296
+ TabButton,
1297
+ {
1298
+ active: value.granularity === granularity2,
1299
+ onClick: () => setGranularity(granularity2),
1300
+ children: granularity2[0].toUpperCase() + granularity2.slice(1)
1301
+ },
1302
+ granularity2
1303
+ )
1304
+ ) }),
1305
+ /* @__PURE__ */ jsxs8(
1306
+ Dropdown,
1307
+ {
1308
+ theme,
1309
+ open,
1310
+ onOpenChange: setOpen,
1311
+ className: "polli:w-[304px] polli:rounded-xl polli:p-3",
1312
+ trigger: (isOpen) => /* @__PURE__ */ jsxs8(
1313
+ "button",
1314
+ {
1315
+ type: "button",
1316
+ "aria-label": `Select period, current ${formatPeriodLabel(value)}`,
1317
+ className: cn2(
1318
+ "polli:inline-flex polli:min-w-[150px] polli:items-center polli:justify-between polli:gap-2 polli:rounded-full polli:border polli:px-4 polli:pt-1.5 polli:pb-2 polli:text-left polli:text-base polli:font-medium polli:leading-normal",
1319
+ "polli:border-theme-border polli:bg-theme-bg-subtle polli:text-theme-text-base",
1320
+ "polli:transition-all polli:duration-200 polli:ease-out polli:hover:bg-theme-bg-pale",
1321
+ isOpen && "polli:bg-theme-bg-active polli:text-theme-text-strong polli:shadow-sm"
1322
+ ),
1323
+ children: [
1324
+ /* @__PURE__ */ jsx17("span", { children: formatPeriodLabel(value) }),
1325
+ /* @__PURE__ */ jsx17(ChevronIcon, { expanded: isOpen })
1326
+ ]
1327
+ }
1328
+ ),
1329
+ children: [
1330
+ /* @__PURE__ */ jsxs8("div", { className: "polli:mb-3 polli:flex polli:items-center polli:justify-between", children: [
1331
+ /* @__PURE__ */ jsx17(
1332
+ "button",
1333
+ {
1334
+ type: "button",
1335
+ "aria-label": value.granularity === "month" ? "Previous year" : "Previous month",
1336
+ disabled: previousDisabled,
1337
+ onClick: () => setViewDate(previousViewDate),
1338
+ className: cn2(
1339
+ NAV_BUTTON,
1340
+ previousDisabled && "polli:cursor-not-allowed polli:opacity-30 polli:hover:bg-transparent"
1341
+ ),
1342
+ children: "<"
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ jsx17("div", { className: "polli:text-sm polli:font-bold polli:text-theme-text-base", children: viewLabel }),
1346
+ /* @__PURE__ */ jsx17(
1347
+ "button",
1348
+ {
1349
+ type: "button",
1350
+ "aria-label": value.granularity === "month" ? "Next year" : "Next month",
1351
+ disabled: nextDisabled,
1352
+ onClick: () => setViewDate(nextViewDate),
1353
+ className: cn2(
1354
+ NAV_BUTTON,
1355
+ nextDisabled && "polli:cursor-not-allowed polli:opacity-30 polli:hover:bg-transparent"
1356
+ ),
1357
+ children: ">"
1358
+ }
1359
+ )
1360
+ ] }),
1361
+ value.granularity === "month" ? /* @__PURE__ */ jsx17("div", { className: "polli:grid polli:grid-cols-3 polli:gap-1.5", children: MONTH_LABELS.map((label, monthIndex) => {
1362
+ const date = new Date(
1363
+ Date.UTC(
1364
+ viewDate.getUTCFullYear(),
1365
+ monthIndex,
1366
+ 1
1367
+ )
1368
+ );
1369
+ const selectable = isPeriodSelectable(
1370
+ periodFromDate("month", date),
1371
+ minDate,
1372
+ today
1373
+ );
1374
+ const ariaLabel = date.toLocaleDateString("en-US", {
1375
+ timeZone: "UTC",
1376
+ month: "long",
1377
+ year: "numeric"
1378
+ });
1379
+ const selected = date.getUTCFullYear() === selectedWindow.start.getUTCFullYear() && date.getUTCMonth() === selectedWindow.start.getUTCMonth();
1380
+ return /* @__PURE__ */ jsx17(
1381
+ "button",
1382
+ {
1383
+ type: "button",
1384
+ "aria-label": ariaLabel,
1385
+ disabled: !selectable,
1386
+ onClick: () => selectDate(date),
1387
+ className: cn2(
1388
+ "polli:rounded-lg polli:px-3 polli:py-2 polli:text-xs polli:font-medium polli:transition-colors polli:duration-150",
1389
+ selected ? "polli:bg-theme-bg-active polli:text-theme-text-strong" : "polli:text-gray-700 polli:hover:bg-theme-bg-subtle",
1390
+ !selectable && "polli:cursor-not-allowed polli:text-gray-300 polli:hover:bg-transparent"
1391
+ ),
1392
+ children: label
1393
+ },
1394
+ label
1395
+ );
1396
+ }) }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
1397
+ /* @__PURE__ */ jsx17("div", { className: "polli:mb-1 polli:grid polli:grid-cols-7 polli:gap-1 polli:text-center polli:text-micro polli:font-bold polli:uppercase polli:text-gray-400", children: WEEKDAY_LABELS.map((label) => /* @__PURE__ */ jsx17("div", { children: label }, label)) }),
1398
+ /* @__PURE__ */ jsx17("div", { className: "polli:grid polli:grid-cols-7 polli:gap-1", children: dates.map((date) => {
1399
+ const inCurrentMonth = date.getUTCMonth() === viewDate.getUTCMonth();
1400
+ const selectable = isPeriodSelectable(
1401
+ periodFromDate(value.granularity, date),
1402
+ minDate,
1403
+ today
1404
+ );
1405
+ const ariaLabel = value.granularity === "week" ? `Select week ${formatPeriodLabel(periodFromDate("week", date))}` : `Select ${date.toLocaleDateString(
1406
+ "en-US",
1407
+ {
1408
+ timeZone: "UTC",
1409
+ weekday: "long",
1410
+ month: "long",
1411
+ day: "numeric",
1412
+ year: "numeric"
1413
+ }
1414
+ )}`;
1415
+ const selected = value.granularity === "day" ? sameUtcDay(date, selectedWindow.start) : date >= selectedWindow.start && date < selectedWindow.end;
1416
+ return /* @__PURE__ */ jsx17(
1417
+ "button",
1418
+ {
1419
+ type: "button",
1420
+ "aria-label": ariaLabel,
1421
+ disabled: !selectable,
1422
+ onClick: () => selectDate(date),
1423
+ className: cn2(
1424
+ "polli:aspect-square polli:rounded-lg polli:text-xs polli:font-medium polli:transition-colors polli:duration-150",
1425
+ !inCurrentMonth && "polli:text-gray-300",
1426
+ sameUtcDay(date, today) && "polli:ring-1 polli:ring-theme-border",
1427
+ selected ? "polli:bg-theme-bg-active polli:text-theme-text-strong" : "polli:text-gray-700 polli:hover:bg-theme-bg-subtle",
1428
+ !selectable && "polli:cursor-not-allowed polli:text-gray-300 polli:hover:bg-transparent"
1429
+ ),
1430
+ children: date.getUTCDate()
1431
+ },
1432
+ date.toISOString()
1433
+ );
1434
+ }) })
1435
+ ] })
1436
+ ]
1437
+ }
1438
+ )
1439
+ ]
1440
+ }
1441
+ );
1442
+ };
1443
+
1444
+ // src/primitives/Surface.tsx
1445
+ import { jsx as jsx18 } from "react/jsx-runtime";
1446
+ var variantClasses = {
1447
+ panel: "polli:rounded-2xl polli:border polli:border-theme-border polli:bg-theme-bg-subtle polli:p-6",
1448
+ card: "polli:rounded-xl polli:bg-surface-white polli:p-4",
1449
+ "card-themed": "polli:rounded-xl polli:bg-theme-bg-pale polli:p-4"
1450
+ };
1451
+ var Surface = ({
1452
+ theme,
1453
+ variant = "card",
1454
+ className,
1455
+ children,
1456
+ ...rest
1457
+ }) => /* @__PURE__ */ jsx18(
1458
+ "div",
1459
+ {
1460
+ ...rest,
1461
+ "data-theme": theme,
1462
+ className: cn2("polli:min-w-0", variantClasses[variant], className),
1463
+ children
1464
+ }
1465
+ );
1466
+
1467
+ // src/primitives/Section.tsx
1468
+ import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
1469
+ var Section = ({
1470
+ title,
1471
+ theme,
1472
+ id,
1473
+ framed = false,
1474
+ action,
1475
+ actionClassName,
1476
+ children,
1477
+ className
1478
+ }) => /* @__PURE__ */ jsxs9("section", { id, className: cn2("scroll-mt-10 space-y-2", className), children: [
1479
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap items-center justify-between gap-3 px-1", children: [
1480
+ /* @__PURE__ */ jsx19(
1481
+ "h2",
1482
+ {
1483
+ "data-theme": theme,
1484
+ className: "text-left text-lg font-semibold sm:text-xl text-theme-text-strong",
1485
+ children: title
1486
+ }
1487
+ ),
1488
+ action && /* @__PURE__ */ jsx19("div", { className: cn2("shrink-0", actionClassName), children: action })
1489
+ ] }),
1490
+ framed ? /* @__PURE__ */ jsx19(Surface, { variant: "panel", theme, children }) : children
1491
+ ] });
1492
+
1493
+ // src/primitives/Slider.tsx
1494
+ import { forwardRef as forwardRef3 } from "react";
1495
+ import { jsx as jsx20 } from "react/jsx-runtime";
1496
+ var toNumber = (value) => {
1497
+ if (typeof value === "number") return value;
1498
+ if (typeof value !== "string" || value.trim() === "") return void 0;
1499
+ const numericValue = Number(value);
1500
+ return Number.isFinite(numericValue) ? numericValue : void 0;
1501
+ };
1502
+ var clampPercent = (value) => Math.min(100, Math.max(0, value));
1503
+ var getProgressPercent = ({
1504
+ progress,
1505
+ value,
1506
+ defaultValue,
1507
+ min,
1508
+ max
1509
+ }) => {
1510
+ if (typeof progress === "number" && Number.isFinite(progress)) {
1511
+ return clampPercent(progress);
1512
+ }
1513
+ const numericValue = toNumber(value ?? defaultValue);
1514
+ if (numericValue === void 0) return void 0;
1515
+ const numericMin = toNumber(min) ?? 0;
1516
+ const numericMax = toNumber(max) ?? 100;
1517
+ if (numericMax <= numericMin) return 100;
1518
+ return clampPercent(
1519
+ (numericValue - numericMin) / (numericMax - numericMin) * 100
1520
+ );
1521
+ };
1522
+ var Slider = forwardRef3(
1523
+ ({ className, defaultValue, max, min, progress, style, value, ...props }, ref) => {
1524
+ const progressPercent = getProgressPercent({
1525
+ progress,
1526
+ value,
1527
+ defaultValue,
1528
+ min,
1529
+ max
1530
+ });
1531
+ const sliderStyle = {
1532
+ ...style,
1533
+ ...progressPercent === void 0 ? null : { "--polli-slider-progress": `${progressPercent}%` }
1534
+ };
1535
+ return /* @__PURE__ */ jsx20(
1536
+ "input",
1537
+ {
1538
+ ref,
1539
+ type: "range",
1540
+ min,
1541
+ max,
1542
+ value,
1543
+ defaultValue,
1544
+ style: sliderStyle,
1545
+ className: cn2("polli-slider", className),
1546
+ ...props
1547
+ }
1548
+ );
1549
+ }
1550
+ );
1551
+
1552
+ // src/primitives/StatCard.tsx
1553
+ import { jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
1554
+ var StatCard = ({
1555
+ label,
1556
+ value,
1557
+ detail,
1558
+ theme,
1559
+ className,
1560
+ labelClassName,
1561
+ valueClassName,
1562
+ detailClassName
1563
+ }) => /* @__PURE__ */ jsxs10("div", { "data-theme": theme, className: cn2("polli:text-sm", className), children: [
1564
+ /* @__PURE__ */ jsx21(
1565
+ "div",
1566
+ {
1567
+ className: cn2(
1568
+ "polli:text-micro polli:font-bold polli:uppercase polli:tracking-wide polli:text-theme-text-strong",
1569
+ labelClassName
1570
+ ),
1571
+ children: label
1572
+ }
1573
+ ),
1574
+ /* @__PURE__ */ jsx21(
1575
+ "div",
1576
+ {
1577
+ className: cn2(
1578
+ "polli:mt-1 polli:min-h-8 polli:break-words polli:text-2xl polli:font-bold polli:leading-tight polli:tabular-nums polli:text-theme-text-strong",
1579
+ valueClassName
1580
+ ),
1581
+ children: value
1582
+ }
1583
+ ),
1584
+ detail && /* @__PURE__ */ jsx21(
1585
+ "div",
1586
+ {
1587
+ className: cn2(
1588
+ "polli:mt-2 polli:text-xs polli:text-theme-text-soft",
1589
+ detailClassName
1590
+ ),
1591
+ children: detail
1592
+ }
1593
+ )
1594
+ ] });
1595
+
1596
+ // src/primitives/Switch.tsx
1597
+ import { jsx as jsx22 } from "react/jsx-runtime";
1598
+ var trackClasses = {
1599
+ off: "polli:bg-gray-200",
1600
+ on: "polli:bg-[oklch(0.88_0.12_158)]",
1601
+ invalid: "polli:bg-[oklch(0.88_0.12_25)]"
1602
+ };
1603
+ var Switch = ({
1604
+ checked,
1605
+ onChange,
1606
+ status,
1607
+ ariaLabel,
1608
+ disabled = false,
1609
+ className
1610
+ }) => {
1611
+ const effectiveStatus = status ?? (checked ? "on" : "off");
1612
+ const resolvedAriaLabel = ariaLabel ?? (checked ? "Turn off toggle" : "Turn on toggle");
1613
+ return /* @__PURE__ */ jsx22(
1614
+ "button",
1615
+ {
1616
+ type: "button",
1617
+ role: "switch",
1618
+ "aria-checked": checked,
1619
+ "aria-label": resolvedAriaLabel,
1620
+ onClick: () => onChange(!checked),
1621
+ disabled,
1622
+ className: cn2(
1623
+ "polli:relative polli:inline-flex polli:h-7 polli:w-12 polli:shrink-0 polli:items-center polli:rounded-full polli:transition polli:disabled:cursor-not-allowed polli:disabled:opacity-60",
1624
+ trackClasses[effectiveStatus],
1625
+ className
1626
+ ),
1627
+ children: /* @__PURE__ */ jsx22(
1628
+ "span",
1629
+ {
1630
+ className: cn2(
1631
+ "polli:inline-block polli:h-5 polli:w-5 polli:rounded-full polli:bg-white polli:shadow-sm polli:transition-transform",
1632
+ checked ? "polli:translate-x-6" : "polli:translate-x-1"
1633
+ )
1634
+ }
1635
+ )
1636
+ }
1637
+ );
1638
+ };
1639
+
1640
+ // src/theme.ts
1641
+ var themes = [
1642
+ "amber",
1643
+ "blue",
1644
+ "pink",
1645
+ "teal",
1646
+ "violet",
1647
+ "green"
1648
+ ];
1649
+ var themeColors = {
1650
+ amber: "#FEF3C7",
1651
+ blue: "#DBEAFE"
1652
+ };
1653
+ export {
1654
+ AppIcon,
1655
+ BeakerIcon,
1656
+ BookIcon,
1657
+ Button,
1658
+ CheckIcon,
1659
+ ChevronIcon,
1660
+ Chip,
1661
+ ClipboardIcon,
1662
+ ClockIcon,
1663
+ Collapsible,
1664
+ CopyButton,
1665
+ Dialog,
1666
+ DialogTitle,
1667
+ DiscordIcon,
1668
+ DownloadIcon,
1669
+ Dropdown,
1670
+ ExternalLinkButton,
1671
+ ExternalLinkIcon,
1672
+ Field,
1673
+ GenApiIcon,
1674
+ GitHubIcon,
1675
+ IconButton,
1676
+ ImageIcon,
1677
+ InfoTip,
1678
+ Input,
1679
+ LockIcon,
1680
+ MailIcon,
1681
+ McpIcon,
1682
+ MenuIcon,
1683
+ MultiSelect,
1684
+ PeriodPicker,
1685
+ ScrollArea,
1686
+ Section,
1687
+ Slider,
1688
+ StatCard,
1689
+ Surface,
1690
+ Switch,
1691
+ TabButton,
1692
+ TerminalIcon,
1693
+ TokensIcon,
1694
+ Tooltip,
1695
+ TrendUpIcon,
1696
+ WalletIcon,
1697
+ XIcon,
1698
+ cn,
1699
+ currentPeriod,
1700
+ getPeriodBucketKeys,
1701
+ periodBucketKeyToDate,
1702
+ themeColors,
1703
+ themes,
1704
+ useScrollLock
1705
+ };
1706
+ //# sourceMappingURL=index.js.map