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

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 (88) hide show
  1. package/README.md +148 -36
  2. package/dist/Button-ByKwRtdw.d.cts +29 -0
  3. package/dist/Button-ByKwRtdw.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 +698 -242
  9. package/dist/app-user-menu/sdk.cjs.map +1 -1
  10. package/dist/app-user-menu/sdk.d.cts +22 -7
  11. package/dist/app-user-menu/sdk.d.ts +22 -7
  12. package/dist/app-user-menu/sdk.js +703 -240
  13. package/dist/app-user-menu/sdk.js.map +1 -1
  14. package/dist/app.css +12 -122
  15. package/dist/auth/index.cjs +1365 -85
  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 +1362 -84
  20. package/dist/auth/index.js.map +1 -1
  21. package/dist/auth/sdk.cjs +244 -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 +213 -0
  26. package/dist/auth/sdk.js.map +1 -0
  27. package/dist/brand/lockup-horizontal-black.png +0 -0
  28. package/dist/brand/lockup-horizontal-black.svg +4 -0
  29. package/dist/brand/lockup-horizontal-white.png +0 -0
  30. package/dist/brand/lockup-horizontal-white.svg +4 -0
  31. package/dist/brand/lockup-horizontal.svg +4 -0
  32. package/dist/brand/lockup-stacked-black.png +0 -0
  33. package/dist/brand/lockup-stacked-black.svg +4 -0
  34. package/dist/brand/lockup-stacked-white.png +0 -0
  35. package/dist/brand/lockup-stacked-white.svg +4 -0
  36. package/dist/brand/lockup-stacked.svg +4 -0
  37. package/dist/brand/mark-black.png +0 -0
  38. package/dist/brand/mark-black.svg +1 -0
  39. package/dist/brand/mark-white.png +0 -0
  40. package/dist/brand/mark-white.svg +1 -0
  41. package/dist/brand/mark.svg +1 -0
  42. package/dist/brand/polli/polli-lockup-horizontal-black.png +0 -0
  43. package/dist/brand/polli/polli-lockup-horizontal-white.png +0 -0
  44. package/dist/brand/polli/polli-lockup-stacked-black.png +0 -0
  45. package/dist/brand/polli/polli-lockup-stacked-white.png +0 -0
  46. package/dist/brand/polli/polli.png +0 -0
  47. package/dist/brand/wordmark-black.png +0 -0
  48. package/dist/brand/wordmark-black.svg +1 -0
  49. package/dist/brand/wordmark-white.png +0 -0
  50. package/dist/brand/wordmark-white.svg +1 -0
  51. package/dist/brand/wordmark.svg +1 -0
  52. package/dist/fonts/geist-pixel-square.woff2 +0 -0
  53. package/dist/gen/index.cjs +427 -217
  54. package/dist/gen/index.cjs.map +1 -1
  55. package/dist/gen/index.d.cts +68 -19
  56. package/dist/gen/index.d.ts +68 -19
  57. package/dist/gen/index.js +421 -215
  58. package/dist/gen/index.js.map +1 -1
  59. package/dist/index.browser.min.js +2 -0
  60. package/dist/index.browser.min.js.map +1 -0
  61. package/dist/index.cjs +3711 -1590
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +548 -178
  64. package/dist/index.d.ts +548 -178
  65. package/dist/index.js +3713 -1655
  66. package/dist/index.js.map +1 -1
  67. package/dist/licenses/Geist-OFL.txt +93 -0
  68. package/dist/markdown.cjs +826 -0
  69. package/dist/markdown.cjs.map +1 -0
  70. package/dist/markdown.d.cts +16 -0
  71. package/dist/markdown.d.ts +16 -0
  72. package/dist/markdown.js +797 -0
  73. package/dist/markdown.js.map +1 -0
  74. package/dist/styles.css +1 -1
  75. package/dist/theme.css +87 -0
  76. package/dist/wallet/index.cjs +291 -64
  77. package/dist/wallet/index.cjs.map +1 -1
  78. package/dist/wallet/index.d.cts +30 -7
  79. package/dist/wallet/index.d.ts +30 -7
  80. package/dist/wallet/index.js +290 -64
  81. package/dist/wallet/index.js.map +1 -1
  82. package/package.json +106 -89
  83. package/dist/Chip-CQCq34kS.d.cts +0 -20
  84. package/dist/Chip-Cj4xG7Te.d.ts +0 -20
  85. package/dist/assets/logo-wordmark.svg +0 -1
  86. package/dist/assets/logo.svg +0 -4
  87. package/dist/theme-jRPPBmld.d.cts +0 -20
  88. package/dist/theme-jRPPBmld.d.ts +0 -20
package/dist/gen/index.js CHANGED
@@ -6,66 +6,379 @@ function cn(...inputs) {
6
6
  return twMerge(clsx(...inputs));
7
7
  }
8
8
 
9
- // src/primitives/Button.tsx
9
+ // src/primitives/Chip.tsx
10
10
  import { jsx } from "react/jsx-runtime";
11
- var sizes = {
12
- sm: "polli:px-2 polli:pt-0.5 polli:pb-1",
13
- md: "polli:px-4 polli:pt-1.5 polli:pb-2",
14
- lg: "polli:px-6 polli:py-3"
11
+ var chipSizes = {
12
+ icon: "polli:h-5 polli:w-5 polli:p-0 polli:text-xs",
13
+ sm: "polli:h-5 polli:px-2 polli:text-xs",
14
+ md: "polli:h-6 polli:px-2.5 polli:text-sm",
15
+ lg: "polli:h-7 polli:px-3 polli:text-sm"
15
16
  };
16
- var themeClasses = "polli:bg-theme-bg-active polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:transition-colors";
17
17
  var intentClasses = {
18
- danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text polli:hover:bg-intent-danger-bg-hover polli:transition-colors"
18
+ news: "polli:bg-intent-news-bg-light polli:text-intent-news-text",
19
+ new: "polli:bg-intent-new-bg-light polli:text-intent-new-text",
20
+ free: "polli:bg-intent-free-bg-light polli:text-intent-free-text",
21
+ alpha: "polli:bg-intent-alpha-bg-light polli:text-intent-alpha-text",
22
+ neutral: "polli:bg-ink-100/80 polli:text-ink-900",
23
+ success: "polli:bg-intent-success-bg-bright/15 polli:text-intent-success-text",
24
+ warning: "polli:bg-intent-warning-bg-light polli:text-intent-warning-text",
25
+ info: "polli:bg-intent-info-bg-light polli:text-intent-info-text",
26
+ danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text"
27
+ };
28
+ var Chip = ({
29
+ intent,
30
+ size = "md",
31
+ className,
32
+ children,
33
+ ...rest
34
+ }) => {
35
+ const intentClass = intent ? intentClasses[intent] : "polli:bg-theme-bg-active polli:text-theme-text-strong";
36
+ return /* @__PURE__ */ jsx(
37
+ "span",
38
+ {
39
+ ...rest,
40
+ className: cn(
41
+ "polli:inline-flex polli:shrink-0 polli:items-center polli:justify-center polli:gap-1 polli:rounded-lg polli:font-medium polli:leading-none",
42
+ chipSizes[size],
43
+ intentClass,
44
+ className
45
+ ),
46
+ children
47
+ }
48
+ );
49
+ };
50
+
51
+ // src/modules/gen/themes.ts
52
+ var MODALITIES = [
53
+ "text",
54
+ "image",
55
+ "video",
56
+ "audio",
57
+ "realtime",
58
+ "embedding"
59
+ ];
60
+ function getModalityKey(category) {
61
+ const lower = category.toLowerCase();
62
+ if (lower === "images") return "image";
63
+ if (lower === "embeddings") return "embedding";
64
+ return MODALITIES.includes(lower) ? lower : null;
65
+ }
66
+ var modalityColorVar = (key) => `var(--polli-color-modality-${key})`;
67
+ var modalityBgVar = (key) => `var(--polli-color-modality-${key}-bg)`;
68
+ var modalityTextColor = (key) => `color-mix(in oklab, ${modalityColorVar(key)} 72%, var(--polli-color-text-strong))`;
69
+
70
+ // src/modules/gen/ModalityChip.tsx
71
+ import { jsx as jsx2 } from "react/jsx-runtime";
72
+ function ModalityChip({
73
+ modality,
74
+ size = "sm",
75
+ className,
76
+ children
77
+ }) {
78
+ const key = getModalityKey(modality);
79
+ if (!key) {
80
+ return /* @__PURE__ */ jsx2(Chip, { intent: "neutral", size, className, children });
81
+ }
82
+ return /* @__PURE__ */ jsx2(
83
+ Chip,
84
+ {
85
+ size,
86
+ className,
87
+ style: {
88
+ backgroundColor: modalityBgVar(key),
89
+ color: modalityTextColor(key)
90
+ },
91
+ children
92
+ }
93
+ );
94
+ }
95
+
96
+ // src/modules/gen/ModalityDot.tsx
97
+ import { jsx as jsx3 } from "react/jsx-runtime";
98
+ function ModalityDot({
99
+ modality,
100
+ className
101
+ }) {
102
+ const key = getModalityKey(modality);
103
+ if (!key) return null;
104
+ return /* @__PURE__ */ jsx3(
105
+ "span",
106
+ {
107
+ "aria-hidden": "true",
108
+ className: cn(
109
+ "polli:inline-block polli:size-2 polli:shrink-0 polli:rounded-full",
110
+ className
111
+ ),
112
+ style: { backgroundColor: modalityColorVar(key) }
113
+ }
114
+ );
115
+ }
116
+
117
+ // src/primitives/TabButton.tsx
118
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
119
+ 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";
120
+ var tabButtonSizeClass = {
121
+ xs: "polli:px-2.5 polli:py-1 polli:text-xs",
122
+ lg: "polli:px-5 polli:py-2 polli:text-lg",
123
+ md: "polli:px-4 polli:py-1.5 polli:text-base",
124
+ sm: "polli:px-3 polli:py-1.5 polli:text-sm"
125
+ };
126
+ var variantClasses = {
127
+ // The default tab look: borderless and monochrome. Selected uses `bg-active`
128
+ // — the same light resting fill as the site's normal buttons. Both states
129
+ // deepen to `bg-hover` and use the theme's hover label color. Non-selected
130
+ // uses the quiet `bg-subtle` token until then.
131
+ soft: {
132
+ base: "",
133
+ active: "polli:bg-theme-bg-active polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
134
+ mixed: "polli:bg-theme-bg-active/45 polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
135
+ inactive: "polli:bg-theme-bg-subtle polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover"
136
+ },
137
+ // Transparent until hovered or selected — for multi-select toggles and
138
+ // inline rows where a filled idle pill would read as a hard selection.
139
+ ghost: {
140
+ base: "polli:border polli:border-transparent",
141
+ active: "polli:bg-theme-bg-active polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
142
+ mixed: "polli:bg-theme-bg-active/45 polli:text-theme-text-strong polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
143
+ inactive: "polli:bg-transparent polli:text-theme-text-base polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover"
144
+ }
145
+ };
146
+ var intentClasses2 = {
147
+ amber: {
148
+ active: "polli:bg-paid-pale polli:text-paid-deep",
149
+ inactive: "polli:bg-transparent polli:text-theme-text-base polli:hover:bg-paid-pale/60"
150
+ },
151
+ green: {
152
+ active: "polli:bg-tier-pale polli:text-tier-deep",
153
+ inactive: "polli:bg-transparent polli:text-tier-deep polli:hover:bg-tier-pale/60"
154
+ }
155
+ };
156
+ function TabButton({
157
+ as,
158
+ active,
159
+ onClick,
160
+ children,
161
+ size = "md",
162
+ variant = "soft",
163
+ intent,
164
+ detail,
165
+ ariaLabel,
166
+ disabled = false,
167
+ className,
168
+ ...rest
169
+ }) {
170
+ const Component = as || "button";
171
+ const isButton = Component === "button";
172
+ const colors = intent === "neutral" ? variantClasses.soft : intent ? {
173
+ ...intentClasses2[intent],
174
+ mixed: intentClasses2[intent].active
175
+ } : variantClasses[variant];
176
+ const handleClick = disabled ? (event) => {
177
+ event.preventDefault();
178
+ event.stopPropagation();
179
+ } : onClick;
180
+ return /* @__PURE__ */ jsxs(
181
+ Component,
182
+ {
183
+ ...rest,
184
+ ...isButton ? { type: "button", disabled } : {},
185
+ ...!isButton && disabled ? { "aria-disabled": true, tabIndex: -1 } : {},
186
+ ...Component === "a" && disabled ? { href: void 0 } : {},
187
+ onClick: handleClick,
188
+ ...ariaLabel !== void 0 ? { "aria-label": ariaLabel } : {},
189
+ ...isButton ? { "aria-pressed": active } : { "aria-current": active === true ? "page" : void 0 },
190
+ className: cn(
191
+ tabButtonBaseClass,
192
+ variantClasses[variant].base,
193
+ active === "mixed" ? colors.mixed : active ? colors.active : colors.inactive,
194
+ disabled && "polli:pointer-events-none polli:cursor-not-allowed polli:opacity-50",
195
+ tabButtonSizeClass[size],
196
+ className
197
+ ),
198
+ children: [
199
+ children,
200
+ detail != null && /* @__PURE__ */ jsx4("span", { className: "polli:ml-1 polli:font-normal polli:opacity-70", children: detail })
201
+ ]
202
+ }
203
+ );
204
+ }
205
+
206
+ // src/modules/gen/ModalityTab.tsx
207
+ import { jsx as jsx5 } from "react/jsx-runtime";
208
+ function ModalityTab({
209
+ active,
210
+ onClick,
211
+ children,
212
+ size = "md",
213
+ disabled = false,
214
+ className,
215
+ ...rest
216
+ }) {
217
+ return /* @__PURE__ */ jsx5(
218
+ TabButton,
219
+ {
220
+ ...rest,
221
+ active,
222
+ onClick,
223
+ size,
224
+ disabled,
225
+ className,
226
+ children
227
+ }
228
+ );
229
+ }
230
+
231
+ // src/primitives/icons/index.tsx
232
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
233
+ var strokeProps = {
234
+ fill: "none",
235
+ stroke: "currentColor",
236
+ strokeWidth: 2,
237
+ strokeLinecap: "round",
238
+ strokeLinejoin: "round"
239
+ };
240
+ function CardIcon(props) {
241
+ return /* @__PURE__ */ jsxs2("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
242
+ /* @__PURE__ */ jsx6("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2" }),
243
+ /* @__PURE__ */ jsx6("path", { d: "M2 10h20" })
244
+ ] });
245
+ }
246
+ function SproutIcon(props) {
247
+ return /* @__PURE__ */ jsxs2("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
248
+ /* @__PURE__ */ jsx6("path", { d: "M7 20h10" }),
249
+ /* @__PURE__ */ jsx6("path", { d: "M10 20c5.5-2.5.8-6.4 3-10" }),
250
+ /* @__PURE__ */ jsx6("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" }),
251
+ /* @__PURE__ */ jsx6("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" })
252
+ ] });
253
+ }
254
+
255
+ // src/modules/gen/ModelAccessIcon.tsx
256
+ import { jsx as jsx7 } from "react/jsx-runtime";
257
+ function ModelAccessIcon({
258
+ paidOnly = false,
259
+ className = "polli:h-3.5 polli:w-3.5"
260
+ }) {
261
+ const label = paidOnly ? "Paid Pollen required" : "Works with any Pollen";
262
+ const Icon = paidOnly ? CardIcon : SproutIcon;
263
+ return /* @__PURE__ */ jsx7(
264
+ "span",
265
+ {
266
+ role: "img",
267
+ "aria-label": label,
268
+ title: label,
269
+ className: "polli:inline-flex polli:shrink-0",
270
+ children: /* @__PURE__ */ jsx7(Icon, { className })
271
+ }
272
+ );
273
+ }
274
+
275
+ // src/primitives/Button.tsx
276
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
277
+ var pillSizes = {
278
+ icon: "polli:h-12 polli:w-12 polli:p-0",
279
+ xs: "polli:h-5 polli:px-1.5 polli:py-0 polli:text-[11px] polli:leading-none",
280
+ sm: "polli:min-h-7 polli:px-2 polli:pt-0.5 polli:pb-1",
281
+ md: "polli:min-h-9 polli:px-4 polli:pt-1.5 polli:pb-2",
282
+ lg: "polli:min-h-12 polli:px-6 polli:py-3 polli:text-base"
283
+ };
284
+ var raisedSizes = {
285
+ icon: "polli:h-12 polli:w-12 polli:p-0",
286
+ xs: "polli:px-2 polli:py-1 polli:text-xs",
287
+ sm: "polli:px-4 polli:py-2 polli:text-sm",
288
+ md: "polli:px-7 polli:py-3.5 polli:text-base",
289
+ lg: "polli:px-8 polli:py-4 polli:text-lg"
290
+ };
291
+ var appearanceClasses = {
292
+ pill: "polli:rounded-full",
293
+ 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"
294
+ };
295
+ 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";
296
+ 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";
297
+ var intentClasses3 = {
298
+ brand: `${outlined} polli:hover:bg-theme-bg-active/50 polli:[.dark_&]:hover:bg-theme-text-soft/10`,
299
+ 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`,
300
+ 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",
301
+ info: "polli:bg-intent-info-bg-light polli:text-intent-info-text polli:hover:bg-intent-info-bg-hover polli:transition-colors",
302
+ // Secondary actions never take the accent: one step stronger grey on hover.
303
+ 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"
19
304
  };
20
305
  var buttonClasses = ({
21
- theme: _theme,
22
306
  intent,
307
+ appearance = "pill",
23
308
  size,
24
309
  className,
25
- disabled
310
+ disabled,
311
+ busy
26
312
  }) => {
27
- const colorClasses = intent ? intentClasses[intent] : themeClasses;
313
+ const colorClasses = intent ? intentClasses3[intent] : themeClasses;
314
+ const sizeClasses = appearance === "raised" ? raisedSizes : pillSizes;
28
315
  return cn(
29
- "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",
30
- disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
316
+ "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",
317
+ // A busy button is working, not unavailable: it keeps its strength.
318
+ busy ? "polli:cursor-progress" : disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
31
319
  colorClasses,
32
- sizes[size || "md"],
320
+ appearanceClasses[appearance],
321
+ sizeClasses[size || "md"],
33
322
  className
34
323
  );
35
324
  };
36
325
  function Button({
37
326
  as,
38
327
  children,
39
- theme,
328
+ icon,
40
329
  intent,
330
+ appearance,
41
331
  size,
42
332
  className,
43
333
  disabled,
44
334
  ...buttonProps
45
335
  }) {
46
336
  const Component = as || "button";
47
- return /* @__PURE__ */ jsx(
337
+ const isButton = Component === "button";
338
+ const isAnchor = Component === "a";
339
+ const buttonType = buttonProps.type;
340
+ const onClick = buttonProps.onClick;
341
+ const ariaBusy = buttonProps["aria-busy"];
342
+ const busy = ariaBusy === true || ariaBusy === "true";
343
+ const handleClick = disabled ? (event) => {
344
+ event.preventDefault();
345
+ event.stopPropagation();
346
+ } : onClick;
347
+ return /* @__PURE__ */ jsxs3(
48
348
  Component,
49
349
  {
50
- "data-theme": intent ? void 0 : theme,
350
+ ...buttonProps,
51
351
  "data-intent": intent,
352
+ ...isButton ? { type: buttonType ?? "button", disabled } : {},
353
+ ...!isButton && disabled ? { "aria-disabled": true, tabIndex: -1 } : {},
354
+ ...isAnchor && disabled ? { href: void 0 } : {},
355
+ onClick: handleClick,
52
356
  className: buttonClasses({
53
- theme,
54
357
  intent,
358
+ appearance,
55
359
  size,
56
360
  className,
57
- disabled
361
+ disabled,
362
+ busy
58
363
  }),
59
- disabled,
60
- ...buttonProps,
61
- children
364
+ children: [
365
+ icon && /* @__PURE__ */ jsx8(
366
+ "span",
367
+ {
368
+ "aria-hidden": "true",
369
+ className: "polli:mr-2 polli:flex polli:size-4 polli:shrink-0 polli:[&>svg]:size-full",
370
+ children: busy ? /* @__PURE__ */ jsx8("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
371
+ }
372
+ ),
373
+ children
374
+ ]
62
375
  }
63
376
  );
64
377
  }
65
378
 
66
379
  // src/primitives/ChevronIcon.tsx
67
- import { jsx as jsx2 } from "react/jsx-runtime";
68
- var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ jsx2(
380
+ import { jsx as jsx9 } from "react/jsx-runtime";
381
+ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ jsx9(
69
382
  "svg",
70
383
  {
71
384
  "aria-hidden": "true",
@@ -77,7 +390,7 @@ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ jsx2(
77
390
  expanded && "polli:rotate-180",
78
391
  className
79
392
  ),
80
- children: /* @__PURE__ */ jsx2(
393
+ children: /* @__PURE__ */ jsx9(
81
394
  "path",
82
395
  {
83
396
  d: "M3 4.5 6 7.5l3-3",
@@ -91,61 +404,24 @@ var ChevronIcon = ({ expanded, className }) => /* @__PURE__ */ jsx2(
91
404
  }
92
405
  );
93
406
 
94
- // src/primitives/Chip.tsx
95
- import { jsx as jsx3 } from "react/jsx-runtime";
96
- var chipSizes = {
97
- sm: "polli:px-2 polli:py-0.5 polli:text-xs",
98
- md: "polli:px-2.5 polli:py-0.5 polli:text-sm",
99
- lg: "polli:px-3 polli:py-1 polli:text-sm"
100
- };
101
- var intentClasses2 = {
102
- news: "polli:bg-intent-news-bg-light polli:text-intent-news-text",
103
- alpha: "polli:bg-intent-alpha-bg-light polli:text-intent-alpha-text",
104
- neutral: "polli:bg-ink-100/80 polli:text-ink-900",
105
- success: "polli:bg-intent-success-bg-light polli:text-intent-success-text",
106
- warning: "polli:bg-intent-warning-bg-light polli:text-intent-warning-text",
107
- danger: "polli:bg-intent-danger-bg-light polli:text-intent-danger-text"
108
- };
109
- var Chip = ({
110
- theme,
111
- intent,
112
- size = "md",
113
- className,
114
- children,
115
- ...rest
116
- }) => {
117
- const intentClass = intent ? intentClasses2[intent] : "polli:bg-theme-bg-active polli:text-theme-text-strong";
118
- return /* @__PURE__ */ jsx3(
119
- "span",
120
- {
121
- ...rest,
122
- "data-theme": theme,
123
- className: cn(
124
- "polli:inline-flex polli:shrink-0 polli:items-center polli:gap-1 polli:rounded-lg polli:font-medium polli:leading-normal",
125
- chipSizes[size],
126
- intentClass,
127
- className
128
- ),
129
- children
130
- }
131
- );
132
- };
133
-
134
407
  // src/primitives/Dropdown.tsx
135
408
  import { Popover } from "@ark-ui/react/popover";
136
409
  import { Portal } from "@ark-ui/react/portal";
137
- import { useState } from "react";
138
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
139
- var DEFAULT_PANEL = "polli:rounded-lg polli:border polli:border-theme-border polli:bg-theme-bg-pale polli:shadow-lg";
410
+ import { useId, useState } from "react";
411
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
412
+ var DEFAULT_PANEL = "polli:rounded-lg polli:bg-surface-menu polli:shadow-lg";
140
413
  var Dropdown = ({
141
- theme,
142
414
  trigger,
143
415
  children,
144
416
  align = "start",
417
+ side = "bottom",
145
418
  open: openProp,
419
+ portalled = true,
146
420
  onOpenChange,
147
- className
421
+ className,
422
+ panelStyle
148
423
  }) => {
424
+ const triggerId = useId();
149
425
  const [internalOpen, setInternalOpen] = useState(false);
150
426
  const isControlled = openProp !== void 0;
151
427
  const open = isControlled ? openProp : internalOpen;
@@ -153,22 +429,26 @@ var Dropdown = ({
153
429
  if (!isControlled) setInternalOpen(next);
154
430
  onOpenChange?.(next);
155
431
  };
156
- return /* @__PURE__ */ jsxs(
432
+ return /* @__PURE__ */ jsxs4(
157
433
  Popover.Root,
158
434
  {
435
+ ids: { trigger: triggerId },
159
436
  open,
437
+ portalled,
160
438
  onOpenChange: (details) => setOpen(details.open),
161
439
  positioning: {
162
- placement: align === "end" ? "bottom-end" : "bottom-start"
440
+ placement: `${side}-${align}`,
441
+ strategy: portalled ? "absolute" : "fixed"
163
442
  },
164
443
  children: [
165
- /* @__PURE__ */ jsx4(Popover.Trigger, { asChild: true, children: trigger(open) }),
166
- /* @__PURE__ */ jsx4(Portal, { children: /* @__PURE__ */ jsx4(Popover.Positioner, { children: /* @__PURE__ */ jsx4(
444
+ /* @__PURE__ */ jsx10(Popover.Trigger, { asChild: true, children: trigger(open) }),
445
+ /* @__PURE__ */ jsx10(Portal, { disabled: !portalled, children: /* @__PURE__ */ jsx10(Popover.Positioner, { children: /* @__PURE__ */ jsx10(
167
446
  Popover.Content,
168
447
  {
169
- "data-theme": theme,
448
+ "aria-labelledby": triggerId,
449
+ style: panelStyle,
170
450
  className: cn(
171
- "polli:z-50 polli:overflow-hidden polli:focus:outline-none",
451
+ "polli:z-[120] polli:overflow-hidden polli:focus:outline-none",
172
452
  DEFAULT_PANEL,
173
453
  className
174
454
  ),
@@ -187,17 +467,18 @@ import {
187
467
  useEffect,
188
468
  useRef
189
469
  } from "react";
190
- import { jsx as jsx5 } from "react/jsx-runtime";
470
+ import { jsx as jsx11 } from "react/jsx-runtime";
191
471
  var axisClasses = {
192
472
  y: "polli:overflow-y-auto polli:overflow-x-hidden",
193
- x: "polli:overflow-x-auto polli:overflow-y-hidden"
473
+ x: "polli:overflow-x-auto polli:overflow-y-hidden",
474
+ both: "polli:overflow-auto"
194
475
  };
195
476
  function assignRef(ref, value) {
196
477
  if (typeof ref === "function") ref(value);
197
478
  else if (ref) ref.current = value;
198
479
  }
199
480
  var ScrollArea = forwardRef(
200
- ({ theme, axis = "y", className, children, ...rest }, externalRef) => {
481
+ ({ axis = "y", scrollbar = "subtle", className, children, ...rest }, externalRef) => {
201
482
  const innerRef = useRef(null);
202
483
  const setRef = useCallback(
203
484
  (node) => {
@@ -207,6 +488,7 @@ var ScrollArea = forwardRef(
207
488
  [externalRef]
208
489
  );
209
490
  useEffect(() => {
491
+ if (scrollbar === "native") return;
210
492
  const element = innerRef.current;
211
493
  if (!element) return;
212
494
  let hideTimer = null;
@@ -256,15 +538,15 @@ var ScrollArea = forwardRef(
256
538
  element.removeEventListener("focusin", handleInteraction);
257
539
  element.removeEventListener("focusout", scheduleHide);
258
540
  };
259
- }, []);
260
- return /* @__PURE__ */ jsx5(
541
+ }, [scrollbar]);
542
+ return /* @__PURE__ */ jsx11(
261
543
  "div",
262
544
  {
263
545
  ...rest,
264
546
  ref: setRef,
265
- "data-theme": theme,
266
547
  className: cn(
267
- "polli-scrollbar-subtle polli:min-w-0 polli:max-w-full",
548
+ scrollbar === "subtle" && "polli-scrollbar-subtle",
549
+ "polli:min-w-0 polli:max-w-full",
268
550
  axisClasses[axis],
269
551
  className
270
552
  ),
@@ -275,96 +557,22 @@ var ScrollArea = forwardRef(
275
557
  );
276
558
  ScrollArea.displayName = "ScrollArea";
277
559
 
278
- // src/primitives/TabButton.tsx
279
- import { jsx as jsx6 } from "react/jsx-runtime";
280
- var sizeClasses = {
281
- md: "polli:px-4 polli:py-1.5 polli:text-base",
282
- sm: "polli:px-3 polli:py-1.5 polli:text-sm"
283
- };
284
- var variantClasses = {
285
- default: {
286
- base: "polli:border",
287
- active: "polli:bg-theme-bg-active polli:text-theme-text-strong polli:border-theme-border",
288
- inactive: "polli:bg-theme-bg-subtle polli:text-theme-text-base polli:border-theme-border polli:hover:bg-theme-bg-active"
289
- },
290
- ghost: {
291
- base: "polli:border polli:border-transparent",
292
- active: "polli:bg-theme-bg-active polli:text-theme-text-strong",
293
- inactive: "polli:bg-transparent polli:text-theme-text-base polli:hover:bg-theme-bg-subtle polli:hover:text-theme-text-strong"
294
- }
295
- };
296
- var TabButton = ({
297
- theme,
298
- active,
299
- onClick,
300
- children,
301
- size = "md",
302
- variant = "default",
303
- ariaLabel,
304
- disabled = false,
305
- className
306
- }) => {
307
- const classes = variantClasses[variant];
308
- return /* @__PURE__ */ jsx6(
309
- "button",
310
- {
311
- type: "button",
312
- "data-theme": theme,
313
- onClick,
314
- "aria-label": ariaLabel,
315
- "aria-pressed": active,
316
- disabled,
317
- className: cn(
318
- "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",
319
- classes.base,
320
- active ? classes.active : classes.inactive,
321
- disabled && "polli:cursor-not-allowed polli:opacity-50",
322
- sizeClasses[size],
323
- className
324
- ),
325
- children
326
- }
327
- );
328
- };
329
-
330
- // src/modules/gen/themes.ts
331
- var MODALITY_THEMES = {
332
- text: "blue",
333
- image: "pink",
334
- video: "teal",
335
- audio: "amber",
336
- realtime: "coral",
337
- embedding: "violet"
338
- };
339
- function modalityTheme(category) {
340
- return MODALITY_THEMES[category];
341
- }
342
- function normalize(category) {
343
- const lower = category.toLowerCase();
344
- if (lower === "images") return "image";
345
- if (lower === "embeddings") return "embedding";
346
- return lower in MODALITY_THEMES ? lower : null;
347
- }
348
- function getModalityTheme(category) {
349
- const key = normalize(category);
350
- return key ? MODALITY_THEMES[key] : null;
351
- }
352
-
353
560
  // src/modules/gen/ModelSelector.tsx
354
- import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
561
+ import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
355
562
  var CATEGORY_LABELS = {
356
563
  image: "Image",
357
564
  video: "Video",
358
565
  text: "Text",
359
566
  audio: "Audio",
567
+ "3d": "3D",
360
568
  embedding: "Embeddings",
361
569
  realtime: "Realtime"
362
570
  };
363
571
  function categoryLabel(category) {
364
572
  return CATEGORY_LABELS[category];
365
573
  }
366
- function displayModelName(model) {
367
- return model.title;
574
+ function modelId(model) {
575
+ return model.id ?? model.name;
368
576
  }
369
577
  function ModelSelector({
370
578
  models,
@@ -373,79 +581,77 @@ function ModelSelector({
373
581
  isLoading = false,
374
582
  onChange
375
583
  }) {
376
- const filteredModels = models.filter(
377
- (model) => model.category === category
378
- );
379
- const currentModel = models.find((model) => model.id === value);
380
- const theme = modalityTheme(category);
381
- const modelLabel = currentModel ? displayModelName(currentModel) : "Select";
584
+ const filteredModels = models.filter((model) => model.category === category).sort((a, b) => modelId(a).localeCompare(modelId(b)));
585
+ const currentModel = models.find((model) => modelId(model) === value);
586
+ const modelLabel = currentModel ? currentModel.title ?? currentModel.name : "Select";
382
587
  const accessibleLabel = currentModel ? `${CATEGORY_LABELS[category]} model: ${modelLabel}` : `Select ${CATEGORY_LABELS[category].toLowerCase()} model`;
383
- return /* @__PURE__ */ jsx7(
588
+ return /* @__PURE__ */ jsx12(
384
589
  Dropdown,
385
590
  {
386
- theme,
387
- align: "end",
591
+ align: "start",
388
592
  className: "polli:w-[min(24rem,calc(100vw-2rem))] polli:p-2",
389
- trigger: (open) => /* @__PURE__ */ jsxs2(
593
+ trigger: (open) => /* @__PURE__ */ jsxs5(
390
594
  Button,
391
595
  {
392
596
  type: "button",
393
- theme,
394
597
  "aria-label": accessibleLabel,
395
598
  className: "polli:min-w-64 polli:max-w-full polli:self-start polli:justify-between polli:gap-2",
396
599
  children: [
397
- /* @__PURE__ */ jsx7("span", { className: "polli:truncate", children: modelLabel }),
398
- /* @__PURE__ */ jsx7(ChevronIcon, { expanded: open })
600
+ /* @__PURE__ */ jsxs5("span", { className: "polli:flex polli:min-w-0 polli:items-center polli:gap-2", children: [
601
+ /* @__PURE__ */ jsx12("span", { className: "polli:truncate", children: modelLabel }),
602
+ currentModel && /* @__PURE__ */ jsx12(
603
+ ModelAccessIcon,
604
+ {
605
+ paidOnly: currentModel.paid_only
606
+ }
607
+ )
608
+ ] }),
609
+ /* @__PURE__ */ jsx12(ChevronIcon, { expanded: open })
399
610
  ]
400
611
  }
401
612
  ),
402
- children: (close) => isLoading ? /* @__PURE__ */ jsx7("p", { className: "polli:m-0 polli:px-2 polli:py-2 polli:text-sm polli:text-theme-text-soft", children: "Loading models..." }) : /* @__PURE__ */ jsx7(
403
- ScrollArea,
404
- {
405
- theme,
406
- className: "polli:max-h-64 polli:pr-2",
407
- children: /* @__PURE__ */ jsx7("div", { className: "polli:flex polli:flex-col polli:gap-1", children: filteredModels.map((model) => {
408
- const isActive = value === model.id;
409
- return /* @__PURE__ */ jsxs2(
410
- TabButton,
411
- {
412
- active: isActive,
413
- theme: modalityTheme(model.category),
414
- size: "sm",
415
- variant: "ghost",
416
- className: "polli:w-full polli:justify-between polli:text-left",
417
- onClick: () => {
418
- onChange(model.id);
419
- close();
420
- },
421
- children: [
422
- /* @__PURE__ */ jsx7("span", { className: "polli:truncate", children: displayModelName(model) }),
423
- model.paidOnly && /* @__PURE__ */ jsx7(
424
- Chip,
425
- {
426
- size: "sm",
427
- className: cn(
428
- "polli:shrink-0",
429
- isActive && "polli:bg-surface-white"
430
- ),
431
- children: "paid"
432
- }
433
- )
434
- ]
435
- },
436
- model.id
437
- );
438
- }) })
439
- }
440
- )
613
+ children: (close) => isLoading ? /* @__PURE__ */ jsx12("p", { className: "polli:m-0 polli:px-2 polli:py-2 polli:text-sm polli:text-theme-text-soft", children: "Loading models..." }) : /* @__PURE__ */ jsx12(ScrollArea, { className: "polli:max-h-80 polli:pr-2", children: /* @__PURE__ */ jsx12("div", { className: "polli:flex polli:flex-col polli:gap-1", children: filteredModels.map((model) => {
614
+ const id = modelId(model);
615
+ const isActive = value === id;
616
+ return /* @__PURE__ */ jsx12(
617
+ TabButton,
618
+ {
619
+ active: isActive,
620
+ size: "sm",
621
+ variant: "ghost",
622
+ className: "polli:w-full polli:justify-start polli:text-left",
623
+ onClick: () => {
624
+ onChange(id);
625
+ close();
626
+ },
627
+ children: /* @__PURE__ */ jsxs5("span", { className: "polli:flex polli:min-w-0 polli:flex-col polli:gap-0.5", children: [
628
+ /* @__PURE__ */ jsxs5("span", { className: "polli:flex polli:min-w-0 polli:items-center polli:gap-2", children: [
629
+ /* @__PURE__ */ jsx12("span", { className: "polli:truncate", children: model.title ?? model.name }),
630
+ /* @__PURE__ */ jsx12(
631
+ ModelAccessIcon,
632
+ {
633
+ paidOnly: model.paid_only
634
+ }
635
+ )
636
+ ] }),
637
+ model.description && /* @__PURE__ */ jsx12("span", { className: "polli:truncate polli:text-xs polli:font-normal polli:text-theme-text-muted", children: model.description })
638
+ ] })
639
+ },
640
+ id
641
+ );
642
+ }) }) })
441
643
  }
442
644
  );
443
645
  }
444
646
  export {
445
- CATEGORY_LABELS,
647
+ ModalityChip,
648
+ ModalityDot,
649
+ ModalityTab,
650
+ ModelAccessIcon,
446
651
  ModelSelector,
447
652
  categoryLabel,
448
- getModalityTheme,
449
- modalityTheme
653
+ getModalityKey,
654
+ modalityBgVar,
655
+ modalityTextColor
450
656
  };
451
657
  //# sourceMappingURL=index.js.map