@pollinations/ui 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (91) hide show
  1. package/README.md +148 -36
  2. package/dist/Button-BGqClaBr.d.cts +29 -0
  3. package/dist/Button-BGqClaBr.d.ts +29 -0
  4. package/dist/Chip-v-ADv6cz.d.cts +18 -0
  5. package/dist/Chip-v-ADv6cz.d.ts +18 -0
  6. package/dist/Dialog-D3Nqt8cE.d.cts +66 -0
  7. package/dist/Dialog-D3Nqt8cE.d.ts +66 -0
  8. package/dist/app-user-menu/sdk.cjs +684 -243
  9. package/dist/app-user-menu/sdk.cjs.map +1 -1
  10. package/dist/app-user-menu/sdk.d.cts +18 -7
  11. package/dist/app-user-menu/sdk.d.ts +18 -7
  12. package/dist/app-user-menu/sdk.js +689 -241
  13. package/dist/app-user-menu/sdk.js.map +1 -1
  14. package/dist/app.css +19 -122
  15. package/dist/auth/index.cjs +1372 -86
  16. package/dist/auth/index.cjs.map +1 -1
  17. package/dist/auth/index.d.cts +91 -6
  18. package/dist/auth/index.d.ts +91 -6
  19. package/dist/auth/index.js +1369 -85
  20. package/dist/auth/index.js.map +1 -1
  21. package/dist/auth/sdk.cjs +250 -0
  22. package/dist/auth/sdk.cjs.map +1 -0
  23. package/dist/auth/sdk.d.cts +40 -0
  24. package/dist/auth/sdk.d.ts +40 -0
  25. package/dist/auth/sdk.js +219 -0
  26. package/dist/auth/sdk.js.map +1 -0
  27. package/dist/brand/badge-made-with.svg +1 -0
  28. package/dist/brand/lockup-horizontal-black.png +0 -0
  29. package/dist/brand/lockup-horizontal-black.svg +4 -0
  30. package/dist/brand/lockup-horizontal-white.png +0 -0
  31. package/dist/brand/lockup-horizontal-white.svg +4 -0
  32. package/dist/brand/lockup-horizontal.svg +4 -0
  33. package/dist/brand/lockup-stacked-black.png +0 -0
  34. package/dist/brand/lockup-stacked-black.svg +4 -0
  35. package/dist/brand/lockup-stacked-white.png +0 -0
  36. package/dist/brand/lockup-stacked-white.svg +4 -0
  37. package/dist/brand/lockup-stacked.svg +4 -0
  38. package/dist/brand/mark-black.png +0 -0
  39. package/dist/brand/mark-black.svg +1 -0
  40. package/dist/brand/mark-white.png +0 -0
  41. package/dist/brand/mark-white.svg +1 -0
  42. package/dist/brand/mark.svg +1 -0
  43. package/dist/brand/polli/polli-lockup-horizontal-black.png +0 -0
  44. package/dist/brand/polli/polli-lockup-horizontal-white.png +0 -0
  45. package/dist/brand/polli/polli-lockup-stacked-black.png +0 -0
  46. package/dist/brand/polli/polli-lockup-stacked-white.png +0 -0
  47. package/dist/brand/polli/polli.png +0 -0
  48. package/dist/brand/wordmark-black.png +0 -0
  49. package/dist/brand/wordmark-black.svg +1 -0
  50. package/dist/brand/wordmark-white.png +0 -0
  51. package/dist/brand/wordmark-white.svg +1 -0
  52. package/dist/brand/wordmark.svg +1 -0
  53. package/dist/fonts/geist-pixel-square.woff2 +0 -0
  54. package/dist/gen/index.cjs +459 -218
  55. package/dist/gen/index.cjs.map +1 -1
  56. package/dist/gen/index.d.cts +75 -19
  57. package/dist/gen/index.d.ts +75 -19
  58. package/dist/gen/index.js +453 -216
  59. package/dist/gen/index.js.map +1 -1
  60. package/dist/index.browser.min.js +2 -0
  61. package/dist/index.browser.min.js.map +1 -0
  62. package/dist/index.cjs +3907 -1626
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +682 -199
  65. package/dist/index.d.ts +682 -199
  66. package/dist/index.js +3671 -1457
  67. package/dist/index.js.map +1 -1
  68. package/dist/licenses/Geist-OFL.txt +93 -0
  69. package/dist/markdown.cjs +836 -0
  70. package/dist/markdown.cjs.map +1 -0
  71. package/dist/markdown.d.cts +16 -0
  72. package/dist/markdown.d.ts +16 -0
  73. package/dist/markdown.js +807 -0
  74. package/dist/markdown.js.map +1 -0
  75. package/dist/styles.css +1 -1
  76. package/dist/theme.css +94 -0
  77. package/dist/types-CCy9JNu9.d.cts +6 -0
  78. package/dist/types-CCy9JNu9.d.ts +6 -0
  79. package/dist/wallet/index.cjs +295 -65
  80. package/dist/wallet/index.cjs.map +1 -1
  81. package/dist/wallet/index.d.cts +30 -7
  82. package/dist/wallet/index.d.ts +30 -7
  83. package/dist/wallet/index.js +294 -65
  84. package/dist/wallet/index.js.map +1 -1
  85. package/package.json +106 -89
  86. package/dist/Chip-CQCq34kS.d.cts +0 -20
  87. package/dist/Chip-Cj4xG7Te.d.ts +0 -20
  88. package/dist/assets/logo-wordmark.svg +0 -1
  89. package/dist/assets/logo.svg +0 -4
  90. package/dist/theme-jRPPBmld.d.cts +0 -20
  91. package/dist/theme-jRPPBmld.d.ts +0 -20
@@ -20,82 +20,430 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/modules/gen/index.ts
21
21
  var gen_exports = {};
22
22
  __export(gen_exports, {
23
- CATEGORY_LABELS: () => CATEGORY_LABELS,
23
+ ModalityChip: () => ModalityChip,
24
+ ModalityDot: () => ModalityDot,
25
+ ModalityTab: () => ModalityTab,
26
+ ModelAccessIcon: () => ModelAccessIcon,
24
27
  ModelSelector: () => ModelSelector,
25
28
  categoryLabel: () => categoryLabel,
26
- getModalityTheme: () => getModalityTheme,
27
- modalityTheme: () => modalityTheme
29
+ getModalityKey: () => getModalityKey,
30
+ modalityBgVar: () => modalityBgVar,
31
+ modalityTextColor: () => modalityTextColor
28
32
  });
29
33
  module.exports = __toCommonJS(gen_exports);
30
34
 
31
35
  // src/lib/cn.ts
32
36
  var import_clsx = require("clsx");
33
37
  var import_tailwind_merge = require("tailwind-merge");
34
- var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({ prefix: "polli" });
38
+ var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
39
+ prefix: "polli",
40
+ extend: { theme: { text: ["micro"] } }
41
+ });
35
42
  function cn(...inputs) {
36
43
  return twMerge((0, import_clsx.clsx)(...inputs));
37
44
  }
38
45
 
39
- // src/primitives/Button.tsx
46
+ // src/primitives/Chip.tsx
40
47
  var import_jsx_runtime = require("react/jsx-runtime");
41
- var sizes = {
42
- sm: "polli:px-2 polli:pt-0.5 polli:pb-1",
43
- md: "polli:px-4 polli:pt-1.5 polli:pb-2",
44
- lg: "polli:px-6 polli:py-3"
48
+ var chipSizes = {
49
+ icon: "polli:h-5 polli:w-5 polli:p-0 polli:text-xs",
50
+ sm: "polli:h-5 polli:px-2 polli:text-xs",
51
+ md: "polli:h-6 polli:px-2.5 polli:text-sm",
52
+ lg: "polli:h-7 polli:px-3 polli:text-sm"
45
53
  };
46
- var themeClasses = "polli:bg-theme-bg-active polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:transition-colors";
47
54
  var intentClasses = {
48
- danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text polli:hover:bg-intent-danger-bg-hover polli:transition-colors"
55
+ news: "polli:bg-intent-news-bg-light polli:text-intent-news-text",
56
+ new: "polli:bg-intent-new-bg-light polli:text-intent-new-text",
57
+ free: "polli:bg-intent-free-bg-light polli:text-intent-free-text",
58
+ alpha: "polli:bg-intent-alpha-bg-light polli:text-intent-alpha-text",
59
+ neutral: "polli:bg-ink-100/80 polli:text-ink-900",
60
+ success: "polli:bg-intent-success-bg-bright/15 polli:text-intent-success-text",
61
+ warning: "polli:bg-intent-warning-bg-light polli:text-intent-warning-text",
62
+ info: "polli:bg-intent-info-bg-light polli:text-intent-info-text",
63
+ danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text"
64
+ };
65
+ var Chip = ({
66
+ intent,
67
+ size = "md",
68
+ className,
69
+ children,
70
+ ...rest
71
+ }) => {
72
+ const intentClass = intent ? intentClasses[intent] : "polli:bg-theme-bg-active polli:text-theme-text-strong";
73
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
74
+ "span",
75
+ {
76
+ ...rest,
77
+ className: cn(
78
+ "polli:inline-flex polli:shrink-0 polli:items-center polli:justify-center polli:gap-1 polli:rounded-lg polli:font-medium polli:leading-none",
79
+ chipSizes[size],
80
+ intentClass,
81
+ className
82
+ ),
83
+ children
84
+ }
85
+ );
86
+ };
87
+
88
+ // src/modules/gen/themes.ts
89
+ var MODALITIES = [
90
+ "text",
91
+ "image",
92
+ "video",
93
+ "audio",
94
+ "realtime",
95
+ "embedding"
96
+ ];
97
+ function getModalityKey(category) {
98
+ const lower = category.toLowerCase();
99
+ if (lower === "images") return "image";
100
+ if (lower === "embeddings") return "embedding";
101
+ return MODALITIES.includes(lower) ? lower : null;
102
+ }
103
+ var modalityColorVar = (key) => `var(--polli-color-modality-${key})`;
104
+ var modalityBgVar = (key) => `var(--polli-color-modality-${key}-bg)`;
105
+ var modalityTextColor = (key) => `color-mix(in oklab, ${modalityColorVar(key)} 60%, var(--polli-color-text-strong))`;
106
+
107
+ // src/modules/gen/ModalityChip.tsx
108
+ var import_jsx_runtime2 = require("react/jsx-runtime");
109
+ function ModalityChip({
110
+ modality,
111
+ size = "sm",
112
+ className,
113
+ children
114
+ }) {
115
+ const key = getModalityKey(modality);
116
+ if (!key) {
117
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Chip, { intent: "neutral", size, className, children });
118
+ }
119
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
120
+ Chip,
121
+ {
122
+ size,
123
+ className,
124
+ style: {
125
+ backgroundColor: modalityBgVar(key),
126
+ color: modalityTextColor(key)
127
+ },
128
+ children
129
+ }
130
+ );
131
+ }
132
+
133
+ // src/modules/gen/ModalityDot.tsx
134
+ var import_jsx_runtime3 = require("react/jsx-runtime");
135
+ function ModalityDot({
136
+ modality,
137
+ className
138
+ }) {
139
+ const key = getModalityKey(modality);
140
+ if (!key) return null;
141
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
142
+ "span",
143
+ {
144
+ "aria-hidden": "true",
145
+ className: cn(
146
+ "polli:inline-block polli:size-2 polli:shrink-0 polli:rounded-full",
147
+ className
148
+ ),
149
+ style: { backgroundColor: modalityColorVar(key) }
150
+ }
151
+ );
152
+ }
153
+
154
+ // src/primitives/TabButton.tsx
155
+ var import_jsx_runtime4 = require("react/jsx-runtime");
156
+ var tabButtonBaseClass = "polli-control polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:font-medium polli:leading-normal polli:transition-colors polli:duration-200";
157
+ var tabButtonSizeClass = {
158
+ xs: "polli:px-2.5 polli:py-1 polli:text-xs",
159
+ lg: "polli:px-5 polli:py-2 polli:text-lg",
160
+ md: "polli:px-4 polli:py-1.5 polli:text-base",
161
+ sm: "polli:px-3 polli:py-1.5 polli:text-sm"
162
+ };
163
+ var variantClasses = {
164
+ // The default tab look: borderless and monochrome. Selected uses `bg-active`
165
+ // — the same light resting fill as the site's normal buttons. Both states
166
+ // deepen to `bg-hover` and use the theme's hover label color. Non-selected
167
+ // uses the quiet `bg-subtle` token until then.
168
+ soft: {
169
+ base: "",
170
+ active: "polli:bg-theme-bg-active polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
171
+ mixed: "polli:bg-theme-bg-active/45 polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
172
+ inactive: "polli:bg-theme-bg-subtle polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover"
173
+ },
174
+ // Transparent until hovered or selected — for multi-select toggles and
175
+ // inline rows where a filled idle pill would read as a hard selection.
176
+ ghost: {
177
+ base: "polli:border polli:border-transparent",
178
+ active: "polli:bg-theme-bg-active polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
179
+ mixed: "polli:bg-theme-bg-active/45 polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
180
+ inactive: "polli:bg-transparent polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover"
181
+ }
182
+ };
183
+ var intentClasses2 = {
184
+ amber: {
185
+ active: "polli:bg-paid-pale polli:text-paid-deep",
186
+ inactive: "polli:bg-transparent polli:text-theme-text-base polli:hover:bg-paid-pale/60"
187
+ },
188
+ green: {
189
+ active: "polli:bg-tier-pale polli:text-tier-deep",
190
+ inactive: "polli:bg-transparent polli:text-tier-deep polli:hover:bg-tier-pale/60"
191
+ },
192
+ // Site navigation: the current page is the one full brand pill; hover
193
+ // only previews it, so "where you are" never doubles up.
194
+ brand: {
195
+ active: "polli:bg-brand-accent polli:font-bold polli:text-brand-dark",
196
+ inactive: "polli:bg-transparent polli:font-bold polli:text-theme-text-strong polli:hover:bg-brand-accent/60 polli:hover:text-brand-dark"
197
+ }
198
+ };
199
+ function TabButton({
200
+ as,
201
+ active,
202
+ onClick,
203
+ children,
204
+ icon,
205
+ size = "md",
206
+ variant = "soft",
207
+ intent,
208
+ detail,
209
+ ariaLabel,
210
+ disabled = false,
211
+ className,
212
+ ...rest
213
+ }) {
214
+ const Component = as || "button";
215
+ const isButton = Component === "button";
216
+ const colors = intent === "neutral" ? variantClasses.soft : intent ? {
217
+ ...intentClasses2[intent],
218
+ mixed: intentClasses2[intent].active
219
+ } : variantClasses[variant];
220
+ const handleClick = disabled ? (event) => {
221
+ event.preventDefault();
222
+ event.stopPropagation();
223
+ } : onClick;
224
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
225
+ Component,
226
+ {
227
+ ...rest,
228
+ ...isButton ? { type: "button", disabled } : {},
229
+ ...!isButton && disabled ? { "aria-disabled": true, tabIndex: -1 } : {},
230
+ ...Component === "a" && disabled ? { href: void 0 } : {},
231
+ onClick: handleClick,
232
+ ...ariaLabel !== void 0 ? { "aria-label": ariaLabel } : {},
233
+ ...isButton ? { "aria-pressed": active } : { "aria-current": active === true ? "page" : void 0 },
234
+ className: cn(
235
+ tabButtonBaseClass,
236
+ variantClasses[variant].base,
237
+ active === "mixed" ? colors.mixed : active ? colors.active : colors.inactive,
238
+ disabled && "polli:pointer-events-none polli:cursor-not-allowed polli:opacity-50",
239
+ tabButtonSizeClass[size],
240
+ className
241
+ ),
242
+ children: [
243
+ icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
244
+ "span",
245
+ {
246
+ "aria-hidden": "true",
247
+ className: "polli:mr-1.5 polli:flex polli:size-4 polli:shrink-0 polli:[&>svg]:size-full",
248
+ children: icon
249
+ }
250
+ ),
251
+ children,
252
+ detail != null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "polli:ml-1 polli:font-normal polli:opacity-70", children: detail })
253
+ ]
254
+ }
255
+ );
256
+ }
257
+
258
+ // src/modules/gen/ModalityTab.tsx
259
+ var import_jsx_runtime5 = require("react/jsx-runtime");
260
+ function ModalityTab({
261
+ active,
262
+ onClick,
263
+ children,
264
+ size = "md",
265
+ disabled = false,
266
+ className,
267
+ icon: Icon,
268
+ modality,
269
+ ...rest
270
+ }) {
271
+ const tint = modality && !active ? modalityTextColor(modality) : void 0;
272
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
273
+ TabButton,
274
+ {
275
+ ...rest,
276
+ active,
277
+ onClick,
278
+ size,
279
+ disabled,
280
+ className: cn(tint && "polli:group", className),
281
+ icon: Icon && (tint ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
282
+ Icon,
283
+ {
284
+ className: "polli:text-(--polli-tab-icon) polli:group-hover:text-current",
285
+ style: { "--polli-tab-icon": tint }
286
+ }
287
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, {})),
288
+ children
289
+ }
290
+ );
291
+ }
292
+
293
+ // src/primitives/icons/index.tsx
294
+ var import_jsx_runtime6 = require("react/jsx-runtime");
295
+ var strokeProps = {
296
+ fill: "none",
297
+ stroke: "currentColor",
298
+ strokeWidth: 2,
299
+ strokeLinecap: "round",
300
+ strokeLinejoin: "round"
301
+ };
302
+ function CardIcon(props) {
303
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
304
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2" }),
305
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M2 10h20" })
306
+ ] });
307
+ }
308
+ function SproutIcon(props) {
309
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
310
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M7 20h10" }),
311
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M10 20c5.5-2.5.8-6.4 3-10" }),
312
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9.5 9.4c1.1.8 1.8 2.2 2.3 3.7-2 .4-3.5.4-4.8-.3-1.2-.6-2.3-1.9-3-4.2 2.8-.5 4.4 0 5.5.8z" }),
313
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M14.1 6a7 7 0 0 0-1.1 4c1.9-.1 3.3-.6 4.3-1.4 1-1 1.6-2.3 1.7-4.6-2.7.1-4 1-4.9 2z" })
314
+ ] });
315
+ }
316
+
317
+ // src/modules/gen/ModelAccessIcon.tsx
318
+ var import_jsx_runtime7 = require("react/jsx-runtime");
319
+ function ModelAccessIcon({
320
+ paidOnly = false,
321
+ className = "polli:h-3.5 polli:w-3.5"
322
+ }) {
323
+ const label = paidOnly ? "Paid Pollen required" : "Works with any Pollen";
324
+ const Icon = paidOnly ? CardIcon : SproutIcon;
325
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
326
+ "span",
327
+ {
328
+ role: "img",
329
+ "aria-label": label,
330
+ title: label,
331
+ className: "polli:inline-flex polli:shrink-0",
332
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { className })
333
+ }
334
+ );
335
+ }
336
+
337
+ // src/primitives/Button.tsx
338
+ var import_jsx_runtime8 = require("react/jsx-runtime");
339
+ var pillSizes = {
340
+ icon: "polli:h-12 polli:w-12 polli:p-0",
341
+ xs: "polli:h-5 polli:px-1.5 polli:py-0 polli:text-[11px] polli:leading-none",
342
+ sm: "polli:min-h-7 polli:px-2 polli:pt-0.5 polli:pb-1",
343
+ md: "polli:min-h-9 polli:px-4 polli:pt-1.5 polli:pb-2",
344
+ lg: "polli:min-h-12 polli:px-6 polli:py-3 polli:text-base"
345
+ };
346
+ var raisedSizes = {
347
+ icon: "polli:h-12 polli:w-12 polli:p-0",
348
+ xs: "polli:px-2 polli:py-1 polli:text-xs",
349
+ sm: "polli:px-4 polli:py-2 polli:text-sm",
350
+ md: "polli:px-7 polli:py-3.5 polli:text-base",
351
+ lg: "polli:px-8 polli:py-4 polli:text-lg"
352
+ };
353
+ var appearanceClasses = {
354
+ pill: "polli:rounded-full",
355
+ raised: "polli:rounded-xl polli:border-r-[3px] polli:border-b-[3px] polli:border-solid polli:border-theme-text-strong/20 polli:hover:border-theme-text-strong/45"
356
+ };
357
+ var themeClasses = "polli:bg-theme-bg-active polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover polli:transition-colors";
358
+ var outlined = "polli:border polli:border-theme-text-soft polli:bg-theme-bg-active/30 polli:text-theme-text-strong polli:transition-colors polli:[.dark_&]:bg-transparent";
359
+ var intentClasses3 = {
360
+ brand: `${outlined} polli:hover:bg-theme-bg-active/50 polli:[.dark_&]:hover:bg-theme-text-soft/10`,
361
+ commit: `${outlined} polli:hover:border-theme-bg-active polli:hover:bg-theme-bg-active polli:focus-visible:border-theme-bg-active polli:focus-visible:bg-theme-bg-active polli:[.dark_&]:hover:bg-theme-bg-active polli:[.dark_&]:focus-visible:bg-theme-bg-active`,
362
+ danger: "polli:border polli:border-intent-danger-text polli:bg-intent-danger-bg-light polli:text-intent-danger-text polli:hover:bg-intent-danger-bg-hover polli:focus-visible:bg-intent-danger-bg-hover polli:transition-colors polli:[.dark_&]:bg-transparent polli:[.dark_&]:hover:bg-intent-danger-bg-hover polli:[.dark_&]:focus-visible:bg-intent-danger-bg-hover",
363
+ info: "polli:bg-intent-info-bg-light polli:text-intent-info-text polli:hover:bg-intent-info-bg-hover polli:transition-colors",
364
+ // A quiet white pill on the desk, like the colour toggle; hover previews
365
+ // the accent as the ambient button does.
366
+ surface: "polli:bg-surface-opaque polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover polli:transition-colors",
367
+ // Secondary actions never take the accent: one step stronger grey on hover.
368
+ neutral: "polli:bg-theme-bg-subtle polli:text-theme-text-base polli:hover:bg-theme-text-muted/25 polli:hover:text-theme-text-strong polli:transition-colors"
49
369
  };
50
370
  var buttonClasses = ({
51
- theme: _theme,
52
371
  intent,
372
+ appearance = "pill",
53
373
  size,
54
374
  className,
55
- disabled
375
+ disabled,
376
+ busy
56
377
  }) => {
57
- const colorClasses = intent ? intentClasses[intent] : themeClasses;
378
+ const colorClasses = intent ? intentClasses3[intent] : themeClasses;
379
+ const sizeClasses = appearance === "raised" ? raisedSizes : pillSizes;
58
380
  return cn(
59
- "polli-control polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:self-center polli:font-medium polli:leading-normal polli:box-border",
60
- disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
381
+ "polli-control polli:inline-flex polli:items-center polli:justify-center polli:self-center polli:font-body polli:text-sm polli:font-medium polli:leading-normal polli:box-border polli:border polli:border-transparent",
382
+ // A busy button is working, not unavailable: it keeps its strength.
383
+ busy ? "polli:cursor-progress" : disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
61
384
  colorClasses,
62
- sizes[size || "md"],
385
+ appearanceClasses[appearance],
386
+ sizeClasses[size || "md"],
63
387
  className
64
388
  );
65
389
  };
66
390
  function Button({
67
391
  as,
68
392
  children,
69
- theme,
393
+ icon,
70
394
  intent,
395
+ appearance,
71
396
  size,
72
397
  className,
73
398
  disabled,
74
399
  ...buttonProps
75
400
  }) {
76
401
  const Component = as || "button";
77
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
402
+ const isButton = Component === "button";
403
+ const isAnchor = Component === "a";
404
+ const buttonType = buttonProps.type;
405
+ const onClick = buttonProps.onClick;
406
+ const ariaBusy = buttonProps["aria-busy"];
407
+ const busy = ariaBusy === true || ariaBusy === "true";
408
+ const handleClick = disabled ? (event) => {
409
+ event.preventDefault();
410
+ event.stopPropagation();
411
+ } : onClick;
412
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
78
413
  Component,
79
414
  {
80
- "data-theme": intent ? void 0 : theme,
415
+ ...buttonProps,
81
416
  "data-intent": intent,
417
+ ...isButton ? { type: buttonType ?? "button", disabled } : {},
418
+ ...!isButton && disabled ? { "aria-disabled": true, tabIndex: -1 } : {},
419
+ ...isAnchor && disabled ? { href: void 0 } : {},
420
+ onClick: handleClick,
82
421
  className: buttonClasses({
83
- theme,
84
422
  intent,
423
+ appearance,
85
424
  size,
86
425
  className,
87
- disabled
426
+ disabled,
427
+ busy
88
428
  }),
89
- disabled,
90
- ...buttonProps,
91
- children
429
+ children: [
430
+ icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
431
+ "span",
432
+ {
433
+ "aria-hidden": "true",
434
+ className: "polli:mr-2 polli:flex polli:size-4 polli:shrink-0 polli:[&>svg]:size-full",
435
+ children: busy ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "polli:block polli:size-full polli:animate-spin polli:rounded-full polli:border-2 polli:border-current polli:border-r-transparent polli:motion-reduce:animate-none" }) : icon
436
+ }
437
+ ),
438
+ children
439
+ ]
92
440
  }
93
441
  );
94
442
  }
95
443
 
96
444
  // src/primitives/ChevronIcon.tsx
97
- var import_jsx_runtime2 = require("react/jsx-runtime");
98
- var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
445
+ var import_jsx_runtime9 = require("react/jsx-runtime");
446
+ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
99
447
  "svg",
100
448
  {
101
449
  "aria-hidden": "true",
@@ -107,7 +455,7 @@ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ (0, import_jsx_ru
107
455
  expanded && "polli:rotate-180",
108
456
  className
109
457
  ),
110
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
458
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
111
459
  "path",
112
460
  {
113
461
  d: "M3 4.5 6 7.5l3-3",
@@ -121,61 +469,24 @@ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ (0, import_jsx_ru
121
469
  }
122
470
  );
123
471
 
124
- // src/primitives/Chip.tsx
125
- var import_jsx_runtime3 = require("react/jsx-runtime");
126
- var chipSizes = {
127
- sm: "polli:px-2 polli:py-0.5 polli:text-xs",
128
- md: "polli:px-2.5 polli:py-0.5 polli:text-sm",
129
- lg: "polli:px-3 polli:py-1 polli:text-sm"
130
- };
131
- var intentClasses2 = {
132
- news: "polli:bg-intent-news-bg-light polli:text-intent-news-text",
133
- alpha: "polli:bg-intent-alpha-bg-light polli:text-intent-alpha-text",
134
- neutral: "polli:bg-ink-100/80 polli:text-ink-900",
135
- success: "polli:bg-intent-success-bg-light polli:text-intent-success-text",
136
- warning: "polli:bg-intent-warning-bg-light polli:text-intent-warning-text",
137
- danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text"
138
- };
139
- var Chip = ({
140
- theme,
141
- intent,
142
- size = "md",
143
- className,
144
- children,
145
- ...rest
146
- }) => {
147
- const intentClass = intent ? intentClasses2[intent] : "polli:bg-theme-bg-active polli:text-theme-text-strong";
148
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
149
- "span",
150
- {
151
- ...rest,
152
- "data-theme": theme,
153
- className: cn(
154
- "polli:inline-flex polli:shrink-0 polli:items-center polli:gap-1 polli:rounded-lg polli:font-medium polli:leading-normal",
155
- chipSizes[size],
156
- intentClass,
157
- className
158
- ),
159
- children
160
- }
161
- );
162
- };
163
-
164
472
  // src/primitives/Dropdown.tsx
165
473
  var import_popover = require("@ark-ui/react/popover");
166
474
  var import_portal = require("@ark-ui/react/portal");
167
475
  var import_react = require("react");
168
- var import_jsx_runtime4 = require("react/jsx-runtime");
169
- var DEFAULT_PANEL = "polli:rounded-lg polli:border polli:border-theme-border polli:bg-theme-bg-pale polli:shadow-lg";
476
+ var import_jsx_runtime10 = require("react/jsx-runtime");
477
+ var DEFAULT_PANEL = "polli:rounded-lg polli:bg-surface-menu polli:shadow-lg";
170
478
  var Dropdown = ({
171
- theme,
172
479
  trigger,
173
480
  children,
174
481
  align = "start",
482
+ side = "bottom",
175
483
  open: openProp,
484
+ portalled = true,
176
485
  onOpenChange,
177
- className
486
+ className,
487
+ panelStyle
178
488
  }) => {
489
+ const triggerId = (0, import_react.useId)();
179
490
  const [internalOpen, setInternalOpen] = (0, import_react.useState)(false);
180
491
  const isControlled = openProp !== void 0;
181
492
  const open = isControlled ? openProp : internalOpen;
@@ -183,22 +494,26 @@ var Dropdown = ({
183
494
  if (!isControlled) setInternalOpen(next);
184
495
  onOpenChange?.(next);
185
496
  };
186
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
497
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
187
498
  import_popover.Popover.Root,
188
499
  {
500
+ ids: { trigger: triggerId },
189
501
  open,
502
+ portalled,
190
503
  onOpenChange: (details) => setOpen(details.open),
191
504
  positioning: {
192
- placement: align === "end" ? "bottom-end" : "bottom-start"
505
+ placement: `${side}-${align}`,
506
+ strategy: portalled ? "absolute" : "fixed"
193
507
  },
194
508
  children: [
195
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_popover.Popover.Trigger, { asChild: true, children: trigger(open) }),
196
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_popover.Popover.Positioner, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
509
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_popover.Popover.Trigger, { asChild: true, children: trigger(open) }),
510
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_portal.Portal, { disabled: !portalled, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_popover.Popover.Positioner, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
197
511
  import_popover.Popover.Content,
198
512
  {
199
- "data-theme": theme,
513
+ "aria-labelledby": triggerId,
514
+ style: panelStyle,
200
515
  className: cn(
201
- "polli:z-50 polli:overflow-hidden polli:focus:outline-none",
516
+ "polli:z-[120] polli:overflow-hidden polli:focus:outline-none",
202
517
  DEFAULT_PANEL,
203
518
  className
204
519
  ),
@@ -212,17 +527,18 @@ var Dropdown = ({
212
527
 
213
528
  // src/primitives/ScrollArea.tsx
214
529
  var import_react2 = require("react");
215
- var import_jsx_runtime5 = require("react/jsx-runtime");
530
+ var import_jsx_runtime11 = require("react/jsx-runtime");
216
531
  var axisClasses = {
217
532
  y: "polli:overflow-y-auto polli:overflow-x-hidden",
218
- x: "polli:overflow-x-auto polli:overflow-y-hidden"
533
+ x: "polli:overflow-x-auto polli:overflow-y-hidden",
534
+ both: "polli:overflow-auto"
219
535
  };
220
536
  function assignRef(ref, value) {
221
537
  if (typeof ref === "function") ref(value);
222
538
  else if (ref) ref.current = value;
223
539
  }
224
540
  var ScrollArea = (0, import_react2.forwardRef)(
225
- ({ theme, axis = "y", className, children, ...rest }, externalRef) => {
541
+ ({ axis = "y", scrollbar = "subtle", className, children, ...rest }, externalRef) => {
226
542
  const innerRef = (0, import_react2.useRef)(null);
227
543
  const setRef = (0, import_react2.useCallback)(
228
544
  (node) => {
@@ -232,6 +548,7 @@ var ScrollArea = (0, import_react2.forwardRef)(
232
548
  [externalRef]
233
549
  );
234
550
  (0, import_react2.useEffect)(() => {
551
+ if (scrollbar === "native") return;
235
552
  const element = innerRef.current;
236
553
  if (!element) return;
237
554
  let hideTimer = null;
@@ -281,15 +598,15 @@ var ScrollArea = (0, import_react2.forwardRef)(
281
598
  element.removeEventListener("focusin", handleInteraction);
282
599
  element.removeEventListener("focusout", scheduleHide);
283
600
  };
284
- }, []);
285
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
601
+ }, [scrollbar]);
602
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
286
603
  "div",
287
604
  {
288
605
  ...rest,
289
606
  ref: setRef,
290
- "data-theme": theme,
291
607
  className: cn(
292
- "polli-scrollbar-subtle polli:min-w-0 polli:max-w-full",
608
+ scrollbar === "subtle" && "polli-scrollbar-subtle",
609
+ "polli:min-w-0 polli:max-w-full",
293
610
  axisClasses[axis],
294
611
  className
295
612
  ),
@@ -300,96 +617,22 @@ var ScrollArea = (0, import_react2.forwardRef)(
300
617
  );
301
618
  ScrollArea.displayName = "ScrollArea";
302
619
 
303
- // src/primitives/TabButton.tsx
304
- var import_jsx_runtime6 = require("react/jsx-runtime");
305
- var sizeClasses = {
306
- md: "polli:px-4 polli:py-1.5 polli:text-base",
307
- sm: "polli:px-3 polli:py-1.5 polli:text-sm"
308
- };
309
- var variantClasses = {
310
- default: {
311
- base: "polli:border",
312
- active: "polli:bg-theme-bg-active polli:text-theme-text-strong polli:border-theme-border",
313
- inactive: "polli:bg-theme-bg-subtle polli:text-theme-text-base polli:border-theme-border polli:hover:bg-theme-bg-active"
314
- },
315
- ghost: {
316
- base: "polli:border polli:border-transparent",
317
- active: "polli:bg-theme-bg-active polli:text-theme-text-strong",
318
- inactive: "polli:bg-transparent polli:text-theme-text-base polli:hover:bg-theme-bg-subtle polli:hover:text-theme-text-strong"
319
- }
320
- };
321
- var TabButton = ({
322
- theme,
323
- active,
324
- onClick,
325
- children,
326
- size = "md",
327
- variant = "default",
328
- ariaLabel,
329
- disabled = false,
330
- className
331
- }) => {
332
- const classes = variantClasses[variant];
333
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
334
- "button",
335
- {
336
- type: "button",
337
- "data-theme": theme,
338
- onClick,
339
- "aria-label": ariaLabel,
340
- "aria-pressed": active,
341
- disabled,
342
- className: cn(
343
- "polli-control polli:inline-flex polli:items-center polli:justify-center polli:rounded-full polli:font-medium polli:leading-normal polli:transition-all polli:duration-200",
344
- classes.base,
345
- active ? classes.active : classes.inactive,
346
- disabled && "polli:cursor-not-allowed polli:opacity-50",
347
- sizeClasses[size],
348
- className
349
- ),
350
- children
351
- }
352
- );
353
- };
354
-
355
- // src/modules/gen/themes.ts
356
- var MODALITY_THEMES = {
357
- text: "blue",
358
- image: "pink",
359
- video: "teal",
360
- audio: "amber",
361
- realtime: "coral",
362
- embedding: "violet"
363
- };
364
- function modalityTheme(category) {
365
- return MODALITY_THEMES[category];
366
- }
367
- function normalize(category) {
368
- const lower = category.toLowerCase();
369
- if (lower === "images") return "image";
370
- if (lower === "embeddings") return "embedding";
371
- return lower in MODALITY_THEMES ? lower : null;
372
- }
373
- function getModalityTheme(category) {
374
- const key = normalize(category);
375
- return key ? MODALITY_THEMES[key] : null;
376
- }
377
-
378
620
  // src/modules/gen/ModelSelector.tsx
379
- var import_jsx_runtime7 = require("react/jsx-runtime");
621
+ var import_jsx_runtime12 = require("react/jsx-runtime");
380
622
  var CATEGORY_LABELS = {
381
623
  image: "Image",
382
624
  video: "Video",
383
625
  text: "Text",
384
626
  audio: "Audio",
627
+ "3d": "3D",
385
628
  embedding: "Embeddings",
386
629
  realtime: "Realtime"
387
630
  };
388
631
  function categoryLabel(category) {
389
632
  return CATEGORY_LABELS[category];
390
633
  }
391
- function displayModelName(model) {
392
- return model.title;
634
+ function modelId(model) {
635
+ return model.id ?? model.name;
393
636
  }
394
637
  function ModelSelector({
395
638
  models,
@@ -398,80 +641,78 @@ function ModelSelector({
398
641
  isLoading = false,
399
642
  onChange
400
643
  }) {
401
- const filteredModels = models.filter(
402
- (model) => model.category === category
403
- );
404
- const currentModel = models.find((model) => model.id === value);
405
- const theme = modalityTheme(category);
406
- const modelLabel = currentModel ? displayModelName(currentModel) : "Select";
644
+ const filteredModels = models.filter((model) => model.category === category).sort((a, b) => modelId(a).localeCompare(modelId(b)));
645
+ const currentModel = models.find((model) => modelId(model) === value);
646
+ const modelLabel = currentModel ? currentModel.title ?? currentModel.name : "Select";
407
647
  const accessibleLabel = currentModel ? `${CATEGORY_LABELS[category]} model: ${modelLabel}` : `Select ${CATEGORY_LABELS[category].toLowerCase()} model`;
408
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
648
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
409
649
  Dropdown,
410
650
  {
411
- theme,
412
- align: "end",
651
+ align: "start",
413
652
  className: "polli:w-[min(24rem,calc(100vw-2rem))] polli:p-2",
414
- trigger: (open) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
653
+ trigger: (open) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
415
654
  Button,
416
655
  {
417
656
  type: "button",
418
- theme,
419
657
  "aria-label": accessibleLabel,
420
658
  className: "polli:min-w-64 polli:max-w-full polli:self-start polli:justify-between polli:gap-2",
421
659
  children: [
422
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "polli:truncate", children: modelLabel }),
423
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronIcon, { expanded: open })
660
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "polli:flex polli:min-w-0 polli:items-center polli:gap-2", children: [
661
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "polli:truncate", children: modelLabel }),
662
+ currentModel && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
663
+ ModelAccessIcon,
664
+ {
665
+ paidOnly: currentModel.paid_only
666
+ }
667
+ )
668
+ ] }),
669
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChevronIcon, { expanded: open })
424
670
  ]
425
671
  }
426
672
  ),
427
- children: (close) => isLoading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "polli:m-0 polli:px-2 polli:py-2 polli:text-sm polli:text-theme-text-soft", children: "Loading models..." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
428
- ScrollArea,
429
- {
430
- theme,
431
- className: "polli:max-h-64 polli:pr-2",
432
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "polli:flex polli:flex-col polli:gap-1", children: filteredModels.map((model) => {
433
- const isActive = value === model.id;
434
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
435
- TabButton,
436
- {
437
- active: isActive,
438
- theme: modalityTheme(model.category),
439
- size: "sm",
440
- variant: "ghost",
441
- className: "polli:w-full polli:justify-between polli:text-left",
442
- onClick: () => {
443
- onChange(model.id);
444
- close();
445
- },
446
- children: [
447
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "polli:truncate", children: displayModelName(model) }),
448
- model.paidOnly && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
449
- Chip,
450
- {
451
- size: "sm",
452
- className: cn(
453
- "polli:shrink-0",
454
- isActive && "polli:bg-surface-white"
455
- ),
456
- children: "paid"
457
- }
458
- )
459
- ]
460
- },
461
- model.id
462
- );
463
- }) })
464
- }
465
- )
673
+ children: (close) => isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "polli:m-0 polli:px-2 polli:py-2 polli:text-sm polli:text-theme-text-soft", children: "Loading models..." }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollArea, { className: "polli:max-h-80 polli:pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "polli:flex polli:flex-col polli:gap-1", children: filteredModels.map((model) => {
674
+ const id = modelId(model);
675
+ const isActive = value === id;
676
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
677
+ TabButton,
678
+ {
679
+ active: isActive,
680
+ size: "sm",
681
+ variant: "ghost",
682
+ className: "polli:w-full polli:justify-start polli:text-left",
683
+ onClick: () => {
684
+ onChange(id);
685
+ close();
686
+ },
687
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "polli:flex polli:min-w-0 polli:flex-col polli:gap-0.5", children: [
688
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "polli:flex polli:min-w-0 polli:items-center polli:gap-2", children: [
689
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "polli:truncate", children: model.title ?? model.name }),
690
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
691
+ ModelAccessIcon,
692
+ {
693
+ paidOnly: model.paid_only
694
+ }
695
+ )
696
+ ] }),
697
+ model.description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "polli:truncate polli:text-xs polli:font-normal polli:text-theme-text-muted", children: model.description })
698
+ ] })
699
+ },
700
+ id
701
+ );
702
+ }) }) })
466
703
  }
467
704
  );
468
705
  }
469
706
  // Annotate the CommonJS export names for ESM import in node:
470
707
  0 && (module.exports = {
471
- CATEGORY_LABELS,
708
+ ModalityChip,
709
+ ModalityDot,
710
+ ModalityTab,
711
+ ModelAccessIcon,
472
712
  ModelSelector,
473
713
  categoryLabel,
474
- getModalityTheme,
475
- modalityTheme
714
+ getModalityKey,
715
+ modalityBgVar,
716
+ modalityTextColor
476
717
  });
477
718
  //# sourceMappingURL=index.cjs.map