@pollinations/ui 0.1.0-alpha.0 → 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 (117) hide show
  1. package/README.md +162 -87
  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 +938 -0
  9. package/dist/app-user-menu/sdk.cjs.map +1 -0
  10. package/dist/app-user-menu/sdk.d.cts +29 -0
  11. package/dist/app-user-menu/sdk.d.ts +29 -0
  12. package/dist/app-user-menu/sdk.js +917 -0
  13. package/dist/app-user-menu/sdk.js.map +1 -0
  14. package/dist/app.css +20 -32
  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 +93 -64
  22. package/dist/auth/sdk.cjs.map +1 -1
  23. package/dist/auth/sdk.d.cts +2 -15
  24. package/dist/auth/sdk.d.ts +2 -15
  25. package/dist/auth/sdk.js +92 -61
  26. package/dist/auth/sdk.js.map +1 -1
  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 +718 -0
  55. package/dist/gen/index.cjs.map +1 -0
  56. package/dist/gen/index.d.cts +91 -0
  57. package/dist/gen/index.d.ts +91 -0
  58. package/dist/gen/index.js +688 -0
  59. package/dist/gen/index.js.map +1 -0
  60. package/dist/index.browser.min.js +2 -0
  61. package/dist/index.browser.min.js.map +1 -0
  62. package/dist/index.cjs +4250 -1517
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +794 -221
  65. package/dist/index.d.ts +794 -221
  66. package/dist/index.js +4154 -1493
  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 +298 -68
  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 +297 -68
  84. package/dist/wallet/index.js.map +1 -1
  85. package/package.json +104 -102
  86. package/dist/Button-BvLF_Km2.d.cts +0 -26
  87. package/dist/Button-DQAZzvyQ.d.ts +0 -26
  88. package/dist/Chip-C5impfYd.d.ts +0 -20
  89. package/dist/Chip-SM52sUbZ.d.cts +0 -20
  90. package/dist/assets/logo-wordmark.svg +0 -1
  91. package/dist/assets/logo.svg +0 -4
  92. package/dist/compositions/app-user.cjs +0 -497
  93. package/dist/compositions/app-user.cjs.map +0 -1
  94. package/dist/compositions/app-user.d.cts +0 -18
  95. package/dist/compositions/app-user.d.ts +0 -18
  96. package/dist/compositions/app-user.js +0 -469
  97. package/dist/compositions/app-user.js.map +0 -1
  98. package/dist/modality/index.cjs +0 -86
  99. package/dist/modality/index.cjs.map +0 -1
  100. package/dist/modality/index.d.cts +0 -26
  101. package/dist/modality/index.d.ts +0 -26
  102. package/dist/modality/index.js +0 -59
  103. package/dist/modality/index.js.map +0 -1
  104. package/dist/models/index.cjs +0 -508
  105. package/dist/models/index.cjs.map +0 -1
  106. package/dist/models/index.d.cts +0 -22
  107. package/dist/models/index.d.ts +0 -22
  108. package/dist/models/index.js +0 -486
  109. package/dist/models/index.js.map +0 -1
  110. package/dist/theme-VMRlhqST.d.cts +0 -9
  111. package/dist/theme-VMRlhqST.d.ts +0 -9
  112. package/dist/wallet/sdk.cjs +0 -206
  113. package/dist/wallet/sdk.cjs.map +0 -1
  114. package/dist/wallet/sdk.d.cts +0 -33
  115. package/dist/wallet/sdk.d.ts +0 -33
  116. package/dist/wallet/sdk.js +0 -175
  117. package/dist/wallet/sdk.js.map +0 -1
@@ -0,0 +1,836 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/markdown.ts
31
+ var markdown_exports = {};
32
+ __export(markdown_exports, {
33
+ Markdown: () => Markdown,
34
+ Prose: () => Prose
35
+ });
36
+ module.exports = __toCommonJS(markdown_exports);
37
+
38
+ // src/compositions/Markdown.tsx
39
+ var import_react3 = require("react");
40
+ var import_react_markdown = __toESM(require("react-markdown"), 1);
41
+ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
42
+
43
+ // src/lib/cn.ts
44
+ var import_clsx = require("clsx");
45
+ var import_tailwind_merge = require("tailwind-merge");
46
+ var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
47
+ prefix: "polli",
48
+ extend: { theme: { text: ["micro"] } }
49
+ });
50
+ function cn(...inputs) {
51
+ return twMerge((0, import_clsx.clsx)(...inputs));
52
+ }
53
+
54
+ // src/lib/link.ts
55
+ function isExternalHref(href, origin = globalThis.location?.origin) {
56
+ if (typeof href !== "string" || !/^(https?:)?\/\//i.test(href))
57
+ return false;
58
+ if (!origin) return true;
59
+ try {
60
+ return new URL(href, origin).origin !== origin;
61
+ } catch {
62
+ return false;
63
+ }
64
+ }
65
+
66
+ // src/primitives/icons/index.tsx
67
+ var import_jsx_runtime = require("react/jsx-runtime");
68
+ var strokeProps = {
69
+ fill: "none",
70
+ stroke: "currentColor",
71
+ strokeWidth: 2,
72
+ strokeLinecap: "round",
73
+ strokeLinejoin: "round"
74
+ };
75
+ function CheckIcon(props) {
76
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
77
+ "svg",
78
+ {
79
+ "aria-hidden": "true",
80
+ viewBox: "0 0 24 24",
81
+ ...strokeProps,
82
+ strokeWidth: 2.5,
83
+ ...props,
84
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "20 6 9 17 4 12" })
85
+ }
86
+ );
87
+ }
88
+ function ClipboardIcon(props) {
89
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
92
+ ] });
93
+ }
94
+ function ExternalLinkIcon(props) {
95
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", ...strokeProps, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7 17 17 7M9 7h8v8" }) });
96
+ }
97
+
98
+ // src/primitives/InlineLink.tsx
99
+ var import_jsx_runtime2 = require("react/jsx-runtime");
100
+ function InlineLink({
101
+ as,
102
+ external,
103
+ showIcon = true,
104
+ size = "inherit",
105
+ tone = "accent",
106
+ className,
107
+ children,
108
+ ...linkProps
109
+ }) {
110
+ const Component = as || "a";
111
+ const isExternal = external ?? isExternalHref(linkProps.href);
112
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
113
+ Component,
114
+ {
115
+ target: isExternal && as !== "button" ? "_blank" : void 0,
116
+ rel: isExternal && as !== "button" ? "noopener noreferrer" : void 0,
117
+ className: ["polli-link", className].filter(Boolean).join(" "),
118
+ "data-size": size,
119
+ "data-tone": tone,
120
+ ...linkProps,
121
+ children: [
122
+ children,
123
+ showIcon && isExternal && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
124
+ ExternalLinkIcon,
125
+ {
126
+ "aria-hidden": "true",
127
+ className: "polli-link-external-icon"
128
+ }
129
+ )
130
+ ]
131
+ }
132
+ );
133
+ }
134
+
135
+ // src/compositions/CopyButton.tsx
136
+ var import_react2 = require("react");
137
+
138
+ // src/primitives/Button.tsx
139
+ var import_jsx_runtime3 = require("react/jsx-runtime");
140
+ var pillSizes = {
141
+ icon: "polli:h-12 polli:w-12 polli:p-0",
142
+ xs: "polli:h-5 polli:px-1.5 polli:py-0 polli:text-[11px] polli:leading-none",
143
+ sm: "polli:min-h-7 polli:px-2 polli:pt-0.5 polli:pb-1",
144
+ md: "polli:min-h-9 polli:px-4 polli:pt-1.5 polli:pb-2",
145
+ lg: "polli:min-h-12 polli:px-6 polli:py-3 polli:text-base"
146
+ };
147
+ var raisedSizes = {
148
+ icon: "polli:h-12 polli:w-12 polli:p-0",
149
+ xs: "polli:px-2 polli:py-1 polli:text-xs",
150
+ sm: "polli:px-4 polli:py-2 polli:text-sm",
151
+ md: "polli:px-7 polli:py-3.5 polli:text-base",
152
+ lg: "polli:px-8 polli:py-4 polli:text-lg"
153
+ };
154
+ var appearanceClasses = {
155
+ pill: "polli:rounded-full",
156
+ 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"
157
+ };
158
+ 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";
159
+ 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";
160
+ var intentClasses = {
161
+ brand: `${outlined} polli:hover:bg-theme-bg-active/50 polli:[.dark_&]:hover:bg-theme-text-soft/10`,
162
+ 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`,
163
+ 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",
164
+ info: "polli:bg-intent-info-bg-light polli:text-intent-info-text polli:hover:bg-intent-info-bg-hover polli:transition-colors",
165
+ // A quiet white pill on the desk, like the colour toggle; hover previews
166
+ // the accent as the ambient button does.
167
+ 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",
168
+ // Secondary actions never take the accent: one step stronger grey on hover.
169
+ 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"
170
+ };
171
+ var buttonClasses = ({
172
+ intent,
173
+ appearance = "pill",
174
+ size,
175
+ className,
176
+ disabled,
177
+ busy
178
+ }) => {
179
+ const colorClasses = intent ? intentClasses[intent] : themeClasses;
180
+ const sizeClasses = appearance === "raised" ? raisedSizes : pillSizes;
181
+ return cn(
182
+ "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",
183
+ // A busy button is working, not unavailable: it keeps its strength.
184
+ busy ? "polli:cursor-progress" : disabled ? "polli:opacity-50 polli:cursor-not-allowed" : "polli:hover:filter polli:hover:brightness-105 polli:cursor-pointer",
185
+ colorClasses,
186
+ appearanceClasses[appearance],
187
+ sizeClasses[size || "md"],
188
+ className
189
+ );
190
+ };
191
+ function Button({
192
+ as,
193
+ children,
194
+ icon,
195
+ intent,
196
+ appearance,
197
+ size,
198
+ className,
199
+ disabled,
200
+ ...buttonProps
201
+ }) {
202
+ const Component = as || "button";
203
+ const isButton = Component === "button";
204
+ const isAnchor = Component === "a";
205
+ const buttonType = buttonProps.type;
206
+ const onClick = buttonProps.onClick;
207
+ const ariaBusy = buttonProps["aria-busy"];
208
+ const busy = ariaBusy === true || ariaBusy === "true";
209
+ const handleClick = disabled ? (event) => {
210
+ event.preventDefault();
211
+ event.stopPropagation();
212
+ } : onClick;
213
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
214
+ Component,
215
+ {
216
+ ...buttonProps,
217
+ "data-intent": intent,
218
+ ...isButton ? { type: buttonType ?? "button", disabled } : {},
219
+ ...!isButton && disabled ? { "aria-disabled": true, tabIndex: -1 } : {},
220
+ ...isAnchor && disabled ? { href: void 0 } : {},
221
+ onClick: handleClick,
222
+ className: buttonClasses({
223
+ intent,
224
+ appearance,
225
+ size,
226
+ className,
227
+ disabled,
228
+ busy
229
+ }),
230
+ children: [
231
+ icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
232
+ "span",
233
+ {
234
+ "aria-hidden": "true",
235
+ className: "polli:mr-2 polli:flex polli:size-4 polli:shrink-0 polli:[&>svg]:size-full",
236
+ children: busy ? /* @__PURE__ */ (0, import_jsx_runtime3.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
237
+ }
238
+ ),
239
+ children
240
+ ]
241
+ }
242
+ );
243
+ }
244
+
245
+ // src/primitives/Tooltip.tsx
246
+ var import_react = require("react");
247
+ var import_react_dom = require("react-dom");
248
+ var import_jsx_runtime4 = require("react/jsx-runtime");
249
+ var TOOLTIP_MAX_WIDTH = 288;
250
+ var TOOLTIP_VIEWPORT_MARGIN = 12;
251
+ var Tooltip = ({
252
+ children,
253
+ content,
254
+ align = "start",
255
+ ariaLabel,
256
+ clampToViewport = true,
257
+ className,
258
+ maxWidth = TOOLTIP_MAX_WIDTH,
259
+ onClick,
260
+ stopClickPropagation = true,
261
+ style,
262
+ tapEnabled = false,
263
+ triggerAs = "button",
264
+ displayContents = false
265
+ }) => {
266
+ const [showTooltip, setShowTooltip] = (0, import_react.useState)(false);
267
+ const [tooltipPosition, setTooltipPosition] = (0, import_react.useState)({
268
+ top: 0,
269
+ left: 0,
270
+ maxWidth
271
+ });
272
+ const triggerRef = (0, import_react.useRef)(null);
273
+ const tapPinnedRef = (0, import_react.useRef)(false);
274
+ const tooltipId = (0, import_react.useId)();
275
+ const closeTooltip = () => {
276
+ tapPinnedRef.current = false;
277
+ setShowTooltip(false);
278
+ };
279
+ (0, import_react.useEffect)(() => {
280
+ if (!showTooltip) return;
281
+ const dismissOnOutsideTap = (event) => {
282
+ if (triggerRef.current?.contains(event.target)) return;
283
+ tapPinnedRef.current = false;
284
+ setShowTooltip(false);
285
+ };
286
+ const dismissOnEscape = (event) => {
287
+ if (event.key !== "Escape") return;
288
+ tapPinnedRef.current = false;
289
+ setShowTooltip(false);
290
+ };
291
+ const dismissOnViewportChange = () => {
292
+ tapPinnedRef.current = false;
293
+ setShowTooltip(false);
294
+ };
295
+ document.addEventListener("pointerdown", dismissOnOutsideTap);
296
+ document.addEventListener("keydown", dismissOnEscape);
297
+ window.addEventListener("scroll", dismissOnViewportChange, {
298
+ capture: true,
299
+ passive: true
300
+ });
301
+ window.addEventListener("resize", dismissOnViewportChange);
302
+ return () => {
303
+ document.removeEventListener("pointerdown", dismissOnOutsideTap);
304
+ document.removeEventListener("keydown", dismissOnEscape);
305
+ window.removeEventListener("scroll", dismissOnViewportChange, true);
306
+ window.removeEventListener("resize", dismissOnViewportChange);
307
+ };
308
+ }, [showTooltip]);
309
+ const updateTooltipPosition = () => {
310
+ if (triggerRef.current) {
311
+ const rect = triggerRef.current.getBoundingClientRect();
312
+ const availableMaxWidth = Math.min(
313
+ maxWidth,
314
+ window.innerWidth - TOOLTIP_VIEWPORT_MARGIN * 2
315
+ );
316
+ let left = align === "center" ? rect.left + rect.width / 2 : rect.left;
317
+ let transform = align === "center" ? "translateX(-50%)" : void 0;
318
+ if (clampToViewport) {
319
+ left = Math.min(
320
+ Math.max(rect.left, TOOLTIP_VIEWPORT_MARGIN),
321
+ Math.max(
322
+ TOOLTIP_VIEWPORT_MARGIN,
323
+ window.innerWidth - availableMaxWidth - TOOLTIP_VIEWPORT_MARGIN
324
+ )
325
+ );
326
+ transform = void 0;
327
+ }
328
+ setTooltipPosition({
329
+ top: rect.bottom + 4,
330
+ left,
331
+ maxWidth: availableMaxWidth,
332
+ transform
333
+ });
334
+ }
335
+ };
336
+ const triggerClassName = cn(
337
+ "polli-control polli:relative polli:cursor-help polli:text-left polli:inline-flex polli:items-center",
338
+ className
339
+ );
340
+ const cursorClass = displayContents ? "polli:contents" : "polli:cursor-inherit";
341
+ const popupClasses = "polli:fixed polli:w-max polli:px-2 polli:py-1 polli:bg-surface-menu polli:text-theme-text-base polli:font-normal polli:leading-snug polli:tracking-normal polli:normal-case polli:not-italic polli:text-xs polli:rounded-md polli:shadow-md polli:z-[130] polli:pointer-events-none polli:transition-opacity polli:whitespace-pre-line polli:break-words";
342
+ const popupNode = content ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
343
+ "span",
344
+ {
345
+ id: tooltipId,
346
+ role: "tooltip",
347
+ "aria-hidden": !showTooltip,
348
+ style: {
349
+ top: tooltipPosition.top,
350
+ left: tooltipPosition.left,
351
+ maxWidth: tooltipPosition.maxWidth,
352
+ transform: tooltipPosition.transform
353
+ },
354
+ className: `${showTooltip ? "polli:visible polli:opacity-100" : "polli:invisible polli:opacity-0"} ${popupClasses}`,
355
+ children: content
356
+ }
357
+ ) : null;
358
+ const tooltipPopup = popupNode && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(
359
+ popupNode,
360
+ triggerRef.current?.closest('[role="dialog"]') ?? document.body
361
+ ) : popupNode;
362
+ const contentNode = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
363
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: cursorClass, children }),
364
+ tooltipPopup
365
+ ] });
366
+ const sharedProps = {
367
+ "aria-label": ariaLabel,
368
+ "aria-describedby": content && showTooltip ? tooltipId : void 0,
369
+ className: triggerClassName,
370
+ onMouseEnter: () => {
371
+ updateTooltipPosition();
372
+ setShowTooltip(true);
373
+ },
374
+ onMouseLeave: () => {
375
+ if (!tapPinnedRef.current) setShowTooltip(false);
376
+ },
377
+ onClick: (e) => {
378
+ if (stopClickPropagation) e.stopPropagation();
379
+ if (onClick) {
380
+ onClick();
381
+ }
382
+ if (!tapEnabled || !content) return;
383
+ updateTooltipPosition();
384
+ if (tapPinnedRef.current) {
385
+ closeTooltip();
386
+ return;
387
+ }
388
+ tapPinnedRef.current = true;
389
+ setShowTooltip(true);
390
+ },
391
+ onFocus: () => {
392
+ updateTooltipPosition();
393
+ setShowTooltip(true);
394
+ },
395
+ onBlur: closeTooltip,
396
+ style
397
+ };
398
+ if (triggerAs === "span") {
399
+ const handleKeyDown = (event) => {
400
+ if (!tapEnabled || !content) return;
401
+ if (event.key !== "Enter" && event.key !== " ") return;
402
+ event.preventDefault();
403
+ updateTooltipPosition();
404
+ if (tapPinnedRef.current) {
405
+ closeTooltip();
406
+ return;
407
+ }
408
+ tapPinnedRef.current = true;
409
+ setShowTooltip(true);
410
+ };
411
+ const spanInteractionProps = {
412
+ ...sharedProps,
413
+ role: tapEnabled && content ? "button" : void 0,
414
+ tabIndex: tapEnabled && content ? 0 : void 0,
415
+ onKeyDown: tapEnabled && content ? handleKeyDown : void 0
416
+ };
417
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
418
+ "span",
419
+ {
420
+ ref: (node) => {
421
+ triggerRef.current = node;
422
+ },
423
+ ...spanInteractionProps,
424
+ children: contentNode
425
+ }
426
+ );
427
+ }
428
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
429
+ "button",
430
+ {
431
+ ref: (node) => {
432
+ triggerRef.current = node;
433
+ },
434
+ type: "button",
435
+ "aria-label": ariaLabel,
436
+ "aria-describedby": content && showTooltip ? tooltipId : void 0,
437
+ className: triggerClassName,
438
+ onMouseEnter: sharedProps.onMouseEnter,
439
+ onMouseLeave: sharedProps.onMouseLeave,
440
+ onClick: sharedProps.onClick,
441
+ onFocus: sharedProps.onFocus,
442
+ onBlur: sharedProps.onBlur,
443
+ style,
444
+ children: contentNode
445
+ }
446
+ );
447
+ };
448
+
449
+ // src/compositions/CopyButton.tsx
450
+ var import_jsx_runtime5 = require("react/jsx-runtime");
451
+ function CopyButton({
452
+ value,
453
+ children,
454
+ copiedTimeoutMs = 2e3,
455
+ tooltip = "\u{1F4CB} Click to copy",
456
+ tooltipAlign,
457
+ tooltipClampToViewport,
458
+ tooltipMaxWidth,
459
+ copiedTooltip = "\u2705 Copied!",
460
+ tooltipClassName,
461
+ className,
462
+ variant = "plain",
463
+ intent,
464
+ onCopied,
465
+ onCopyError,
466
+ ...buttonProps
467
+ }) {
468
+ const [copied, setCopied] = (0, import_react2.useState)(false);
469
+ const timeoutRef = (0, import_react2.useRef)(null);
470
+ (0, import_react2.useEffect)(
471
+ () => () => {
472
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
473
+ },
474
+ []
475
+ );
476
+ async function handleCopy(event) {
477
+ event.stopPropagation();
478
+ try {
479
+ const text = typeof value === "function" ? await value() : value;
480
+ await navigator.clipboard.writeText(text);
481
+ setCopied(true);
482
+ onCopied?.();
483
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
484
+ timeoutRef.current = setTimeout(
485
+ () => setCopied(false),
486
+ copiedTimeoutMs
487
+ );
488
+ } catch (error) {
489
+ onCopyError?.(error);
490
+ }
491
+ }
492
+ const Control = variant === "button" ? Button : "button";
493
+ const button = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
494
+ Control,
495
+ {
496
+ ...buttonProps,
497
+ ...variant === "button" && intent ? { intent } : {},
498
+ type: "button",
499
+ onClick: handleCopy,
500
+ className: cn(
501
+ "polli-control",
502
+ buttonProps.disabled ? "polli:cursor-not-allowed" : "polli:cursor-pointer",
503
+ typeof className === "function" ? className(copied) : className
504
+ ),
505
+ children: typeof children === "function" ? children(copied) : children
506
+ }
507
+ );
508
+ if (tooltip === null) {
509
+ return button;
510
+ }
511
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
512
+ Tooltip,
513
+ {
514
+ triggerAs: "span",
515
+ content: copied ? copiedTooltip : tooltip,
516
+ align: tooltipAlign,
517
+ clampToViewport: tooltipClampToViewport,
518
+ maxWidth: tooltipMaxWidth,
519
+ displayContents: true,
520
+ tapEnabled: false,
521
+ className: cn(
522
+ buttonProps.disabled ? "polli:cursor-not-allowed" : "polli:cursor-pointer",
523
+ tooltipClassName
524
+ ),
525
+ children: button
526
+ }
527
+ );
528
+ }
529
+
530
+ // src/compositions/CodeBlock.tsx
531
+ var import_jsx_runtime6 = require("react/jsx-runtime");
532
+ var CodeBlock = ({
533
+ code,
534
+ codeClassName,
535
+ language,
536
+ className,
537
+ ...rest
538
+ }) => {
539
+ const label = language || "Code";
540
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
541
+ "div",
542
+ {
543
+ ...rest,
544
+ className: cn(
545
+ "polli:min-w-0 polli:max-w-full polli:overflow-hidden polli:rounded-lg polli:border polli:border-theme-border polli:bg-theme-bg-pale",
546
+ className
547
+ ),
548
+ children: [
549
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "polli:flex polli:min-h-9 polli:items-center polli:justify-between polli:gap-3 polli:bg-theme-bg-subtle polli:px-3 polli:py-1.5", children: [
550
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "polli:truncate polli:font-mono polli:text-[11px] polli:font-medium polli:uppercase polli:tracking-wide polli:text-theme-text-muted", children: label }),
551
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
552
+ CopyButton,
553
+ {
554
+ value: code,
555
+ tooltip: null,
556
+ "aria-label": "Copy code",
557
+ className: "polli:flex polli:items-center polli:gap-1.5 polli:rounded-md polli:px-2 polli:py-1 polli:text-xs polli:font-medium polli:text-theme-text-base polli:transition-colors polli:hover:bg-theme-bg-hover polli:hover:text-theme-text-hover",
558
+ children: (copied) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
559
+ copied ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckIcon, { className: "polli:size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ClipboardIcon, { className: "polli:size-3.5" }),
560
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: copied ? "Copied" : "Copy" })
561
+ ] })
562
+ }
563
+ )
564
+ ] }),
565
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
566
+ "pre",
567
+ {
568
+ className: cn(
569
+ "polli:m-0 polli:min-w-0 polli:whitespace-pre-wrap polli:break-words polli:[overflow-wrap:anywhere] polli:[tab-size:4] polli:p-3 polli:font-mono polli:text-xs polli:leading-6 polli:text-theme-text-strong",
570
+ codeClassName
571
+ ),
572
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: code })
573
+ }
574
+ )
575
+ ]
576
+ }
577
+ );
578
+ };
579
+
580
+ // src/compositions/Markdown.tsx
581
+ var import_jsx_runtime7 = require("react/jsx-runtime");
582
+ function textContent(value) {
583
+ if (typeof value === "string" || typeof value === "number") {
584
+ return String(value);
585
+ }
586
+ if (Array.isArray(value)) return value.map(textContent).join("");
587
+ if ((0, import_react3.isValidElement)(value)) {
588
+ return textContent(value.props.children);
589
+ }
590
+ return "";
591
+ }
592
+ var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set(["m4v", "mov", "mp4", "webm"]);
593
+ var AUDIO_EXTENSIONS = /* @__PURE__ */ new Set([
594
+ "aac",
595
+ "flac",
596
+ "m4a",
597
+ "mp3",
598
+ "ogg",
599
+ "opus",
600
+ "wav"
601
+ ]);
602
+ function urlExtension(src) {
603
+ try {
604
+ const { pathname } = new URL(src, "http://localhost");
605
+ return pathname.split(".").pop()?.toLowerCase() ?? "";
606
+ } catch {
607
+ return "";
608
+ }
609
+ }
610
+ function inlineMedia(src, label) {
611
+ if (!src) return null;
612
+ const extension = urlExtension(src);
613
+ const video = VIDEO_EXTENSIONS.has(extension) || label === "Generated video";
614
+ const audio = AUDIO_EXTENSIONS.has(extension) || label === "Generated audio";
615
+ if (!video && !audio) return null;
616
+ const Element = video ? "video" : "audio";
617
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
618
+ Element,
619
+ {
620
+ src,
621
+ "aria-label": label,
622
+ controls: true,
623
+ playsInline: video || void 0,
624
+ preload: "metadata",
625
+ className: "polli:max-w-full polli:rounded-lg"
626
+ }
627
+ );
628
+ }
629
+ function MarkdownCodeBlock({ children }) {
630
+ const child = (0, import_react3.isValidElement)(children) ? children : null;
631
+ const language = child?.props.className?.match(/language-([^\s]+)/)?.[1];
632
+ const code = textContent(child?.props.children ?? children).replace(
633
+ /\n$/,
634
+ ""
635
+ );
636
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodeBlock, { code, language, className: "polli:my-3" });
637
+ }
638
+ var components = {
639
+ ul: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
640
+ "ul",
641
+ {
642
+ className: "polli:flex polli:min-w-0 polli:list-disc polli:flex-col polli:gap-1 polli:pl-5 polli:marker:text-theme-text-muted",
643
+ ...props
644
+ }
645
+ ),
646
+ ol: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
647
+ "ol",
648
+ {
649
+ className: "polli:flex polli:min-w-0 polli:list-decimal polli:flex-col polli:gap-1 polli:pl-5 polli:marker:text-theme-text-muted",
650
+ ...props
651
+ }
652
+ ),
653
+ p: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "polli:mb-2 polli:last:mb-0", ...props }),
654
+ strong: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
655
+ "strong",
656
+ {
657
+ className: "polli:font-semibold polli:text-theme-text-strong",
658
+ ...props
659
+ }
660
+ ),
661
+ code: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
662
+ "code",
663
+ {
664
+ className: "polli:break-words polli:rounded polli:bg-theme-bg-subtle polli:px-1 polli:py-0.5 polli:font-mono polli:text-xs",
665
+ ...props
666
+ }
667
+ ),
668
+ pre: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MarkdownCodeBlock, { children }),
669
+ img: ({ node, src, alt, ...props }) => {
670
+ const media = inlineMedia(
671
+ typeof src === "string" ? src : void 0,
672
+ alt
673
+ );
674
+ if (media) return media;
675
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
676
+ "img",
677
+ {
678
+ src,
679
+ alt,
680
+ loading: "lazy",
681
+ className: "polli:max-w-full polli:rounded-lg",
682
+ ...props
683
+ }
684
+ );
685
+ },
686
+ a: ({ node, href, ...props }) => {
687
+ const media = inlineMedia(href, textContent(props.children));
688
+ if (media) return media;
689
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(InlineLink, { href, ...props });
690
+ }
691
+ };
692
+ function Markdown({ children, className }) {
693
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
694
+ "div",
695
+ {
696
+ className: cn(
697
+ "polli:min-w-0 polli:font-body polli:leading-relaxed",
698
+ className
699
+ ),
700
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default], components, children })
701
+ }
702
+ );
703
+ }
704
+
705
+ // src/compositions/Prose.tsx
706
+ var import_react_markdown2 = __toESM(require("react-markdown"), 1);
707
+ var import_rehype_slug = __toESM(require("rehype-slug"), 1);
708
+ var import_remark_gfm2 = __toESM(require("remark-gfm"), 1);
709
+
710
+ // src/primitives/Typography.tsx
711
+ var import_jsx_runtime8 = require("react/jsx-runtime");
712
+ var headingSizeClasses = {
713
+ display: "polli:font-heading polli:text-5xl polli:leading-none",
714
+ title: "polli:font-heading polli:text-4xl polli:leading-none",
715
+ section: "polli:font-subheading polli:text-2xl polli:leading-tight",
716
+ subsection: "polli:font-subheading polli:text-xl polli:leading-tight",
717
+ card: "polli:font-subheading polli:text-lg polli:leading-tight"
718
+ };
719
+ function headingClassName(size, className) {
720
+ return cn(
721
+ "polli:break-words polli:text-theme-text-strong",
722
+ headingSizeClasses[size],
723
+ className
724
+ );
725
+ }
726
+
727
+ // src/compositions/Prose.tsx
728
+ var import_jsx_runtime9 = require("react/jsx-runtime");
729
+ var components2 = {
730
+ h1: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
731
+ "h1",
732
+ {
733
+ className: headingClassName("title", "polli:mt-0 polli:mb-5"),
734
+ ...props
735
+ }
736
+ ),
737
+ h2: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
738
+ "h2",
739
+ {
740
+ className: headingClassName("section", "polli:mt-8 polli:mb-3"),
741
+ ...props
742
+ }
743
+ ),
744
+ h3: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
745
+ "h3",
746
+ {
747
+ className: headingClassName("subsection", "polli:mt-6 polli:mb-2"),
748
+ ...props
749
+ }
750
+ ),
751
+ p: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "polli:my-4 polli:leading-relaxed", ...props }),
752
+ a: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(InlineLink, { ...props }),
753
+ ul: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
754
+ "ul",
755
+ {
756
+ className: "polli:my-4 polli:list-disc polli:pl-6 polli:leading-relaxed",
757
+ ...props
758
+ }
759
+ ),
760
+ ol: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
761
+ "ol",
762
+ {
763
+ className: "polli:my-4 polli:list-decimal polli:pl-6 polli:leading-relaxed",
764
+ ...props
765
+ }
766
+ ),
767
+ blockquote: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
768
+ "blockquote",
769
+ {
770
+ className: "polli:my-4 polli:border-l-4 polli:border-theme-border polli:pl-4 polli:text-theme-text-soft",
771
+ ...props
772
+ }
773
+ ),
774
+ code: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
775
+ "code",
776
+ {
777
+ className: "polli:rounded polli:bg-theme-bg-active polli:px-1 polli:py-0.5 polli:font-pixel polli:text-sm",
778
+ ...props
779
+ }
780
+ ),
781
+ pre: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
782
+ "pre",
783
+ {
784
+ className: "polli:my-4 polli:overflow-x-auto polli:rounded-lg polli:bg-theme-bg-active polli:p-4",
785
+ ...props
786
+ }
787
+ ),
788
+ table: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
789
+ "table",
790
+ {
791
+ className: "polli:my-4 polli:w-full polli:border-collapse polli:text-sm",
792
+ ...props
793
+ }
794
+ ),
795
+ th: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
796
+ "th",
797
+ {
798
+ className: "polli:border polli:border-theme-border polli:px-3 polli:py-2 polli:text-left polli:font-semibold",
799
+ ...props
800
+ }
801
+ ),
802
+ td: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
803
+ "td",
804
+ {
805
+ className: "polli:border polli:border-theme-border polli:px-3 polli:py-2",
806
+ ...props
807
+ }
808
+ ),
809
+ hr: ({ node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("hr", { className: "polli:my-6 polli:border-theme-border", ...props })
810
+ };
811
+ function Prose({ children, className }) {
812
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
813
+ "div",
814
+ {
815
+ className: cn(
816
+ "polli:font-body polli:text-theme-text-base polli:leading-relaxed",
817
+ className
818
+ ),
819
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
820
+ import_react_markdown2.default,
821
+ {
822
+ remarkPlugins: [import_remark_gfm2.default],
823
+ rehypePlugins: [import_rehype_slug.default],
824
+ components: components2,
825
+ children
826
+ }
827
+ )
828
+ }
829
+ );
830
+ }
831
+ // Annotate the CommonJS export names for ESM import in node:
832
+ 0 && (module.exports = {
833
+ Markdown,
834
+ Prose
835
+ });
836
+ //# sourceMappingURL=markdown.cjs.map