pika-plugin-ai 0.6.8

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.
package/dist/index.mjs ADDED
@@ -0,0 +1,1846 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
+ var __objRest = (source, exclude) => {
22
+ var target = {};
23
+ for (var prop in source)
24
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
25
+ target[prop] = source[prop];
26
+ if (source != null && __getOwnPropSymbols)
27
+ for (var prop of __getOwnPropSymbols(source)) {
28
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
29
+ target[prop] = source[prop];
30
+ }
31
+ return target;
32
+ };
33
+ var __async = (__this, __arguments, generator) => {
34
+ return new Promise((resolve, reject) => {
35
+ var fulfilled = (value) => {
36
+ try {
37
+ step(generator.next(value));
38
+ } catch (e) {
39
+ reject(e);
40
+ }
41
+ };
42
+ var rejected = (value) => {
43
+ try {
44
+ step(generator.throw(value));
45
+ } catch (e) {
46
+ reject(e);
47
+ }
48
+ };
49
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
50
+ step((generator = generator.apply(__this, __arguments)).next());
51
+ });
52
+ };
53
+
54
+ // ../tsup-config/react-import.js
55
+ import React from "react";
56
+
57
+ // index.tsx
58
+ import {
59
+ useState,
60
+ useCallback,
61
+ useEffect,
62
+ useRef,
63
+ useContext,
64
+ createContext,
65
+ useMemo
66
+ } from "react";
67
+ import { useGetPuck, createUsePuck } from "pika-editor-core";
68
+ import { useChat } from "@ai-sdk/react";
69
+ import {
70
+ DefaultChatTransport,
71
+ getToolName,
72
+ isDataUIPart,
73
+ isFileUIPart,
74
+ isReasoningUIPart,
75
+ isTextUIPart,
76
+ isToolUIPart
77
+ } from "ai";
78
+ import ReactMarkdown from "react-markdown";
79
+ import TextareaAutosize from "react-textarea-autosize";
80
+ import { useStickToBottom } from "use-stick-to-bottom";
81
+
82
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/createLucideIcon.js
83
+ import { forwardRef as forwardRef2, createElement as createElement2 } from "react";
84
+
85
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/shared/src/utils.js
86
+ var toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
87
+ var mergeClasses = (...classes) => classes.filter((className, index, array) => {
88
+ return Boolean(className) && array.indexOf(className) === index;
89
+ }).join(" ");
90
+
91
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/Icon.js
92
+ import { forwardRef, createElement } from "react";
93
+
94
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/defaultAttributes.js
95
+ var defaultAttributes = {
96
+ xmlns: "http://www.w3.org/2000/svg",
97
+ width: 24,
98
+ height: 24,
99
+ viewBox: "0 0 24 24",
100
+ fill: "none",
101
+ stroke: "currentColor",
102
+ strokeWidth: 2,
103
+ strokeLinecap: "round",
104
+ strokeLinejoin: "round"
105
+ };
106
+
107
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/Icon.js
108
+ var Icon = forwardRef(
109
+ (_a, ref) => {
110
+ var _b = _a, {
111
+ color = "currentColor",
112
+ size = 24,
113
+ strokeWidth = 2,
114
+ absoluteStrokeWidth,
115
+ className = "",
116
+ children,
117
+ iconNode
118
+ } = _b, rest = __objRest(_b, [
119
+ "color",
120
+ "size",
121
+ "strokeWidth",
122
+ "absoluteStrokeWidth",
123
+ "className",
124
+ "children",
125
+ "iconNode"
126
+ ]);
127
+ return createElement(
128
+ "svg",
129
+ __spreadValues(__spreadProps(__spreadValues({
130
+ ref
131
+ }, defaultAttributes), {
132
+ width: size,
133
+ height: size,
134
+ stroke: color,
135
+ strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
136
+ className: mergeClasses("lucide", className)
137
+ }), rest),
138
+ [
139
+ ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
140
+ ...Array.isArray(children) ? children : [children]
141
+ ]
142
+ );
143
+ }
144
+ );
145
+
146
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/createLucideIcon.js
147
+ var createLucideIcon = (iconName, iconNode) => {
148
+ const Component = forwardRef2(
149
+ (_a, ref) => {
150
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
151
+ return createElement2(Icon, __spreadValues({
152
+ ref,
153
+ iconNode,
154
+ className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className)
155
+ }, props));
156
+ }
157
+ );
158
+ Component.displayName = `${iconName}`;
159
+ return Component;
160
+ };
161
+
162
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-left.js
163
+ var ArrowLeft = createLucideIcon("ArrowLeft", [
164
+ ["path", { d: "m12 19-7-7 7-7", key: "1l729n" }],
165
+ ["path", { d: "M19 12H5", key: "x3x0zl" }]
166
+ ]);
167
+
168
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-up.js
169
+ var ArrowUp = createLucideIcon("ArrowUp", [
170
+ ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
171
+ ["path", { d: "M12 19V5", key: "x0mq9r" }]
172
+ ]);
173
+
174
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/bot.js
175
+ var Bot = createLucideIcon("Bot", [
176
+ ["path", { d: "M12 8V4H8", key: "hb8ula" }],
177
+ ["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
178
+ ["path", { d: "M2 14h2", key: "vft8re" }],
179
+ ["path", { d: "M20 14h2", key: "4cs60a" }],
180
+ ["path", { d: "M15 13v2", key: "1xurst" }],
181
+ ["path", { d: "M9 13v2", key: "rq6x2g" }]
182
+ ]);
183
+
184
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/check.js
185
+ var Check = createLucideIcon("Check", [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]]);
186
+
187
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/eye-off.js
188
+ var EyeOff = createLucideIcon("EyeOff", [
189
+ [
190
+ "path",
191
+ {
192
+ d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",
193
+ key: "ct8e1f"
194
+ }
195
+ ],
196
+ ["path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242", key: "151rxh" }],
197
+ [
198
+ "path",
199
+ {
200
+ d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",
201
+ key: "13bj9a"
202
+ }
203
+ ],
204
+ ["path", { d: "m2 2 20 20", key: "1ooewy" }]
205
+ ]);
206
+
207
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/eye.js
208
+ var Eye = createLucideIcon("Eye", [
209
+ [
210
+ "path",
211
+ {
212
+ d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",
213
+ key: "1nclc0"
214
+ }
215
+ ],
216
+ ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
217
+ ]);
218
+
219
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/image.js
220
+ var Image = createLucideIcon("Image", [
221
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
222
+ ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
223
+ ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
224
+ ]);
225
+
226
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/rotate-ccw.js
227
+ var RotateCcw = createLucideIcon("RotateCcw", [
228
+ ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
229
+ ["path", { d: "M3 3v5h5", key: "1xhq8a" }]
230
+ ]);
231
+
232
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/settings.js
233
+ var Settings = createLucideIcon("Settings", [
234
+ [
235
+ "path",
236
+ {
237
+ d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",
238
+ key: "1qme2f"
239
+ }
240
+ ],
241
+ ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
242
+ ]);
243
+
244
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/trash-2.js
245
+ var Trash2 = createLucideIcon("Trash2", [
246
+ ["path", { d: "M3 6h18", key: "d0wm0j" }],
247
+ ["path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6", key: "4alrt4" }],
248
+ ["path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2", key: "v07s0e" }],
249
+ ["line", { x1: "10", x2: "10", y1: "11", y2: "17", key: "1uufr5" }],
250
+ ["line", { x1: "14", x2: "14", y1: "11", y2: "17", key: "xtxkd" }]
251
+ ]);
252
+
253
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/triangle-alert.js
254
+ var TriangleAlert = createLucideIcon("TriangleAlert", [
255
+ [
256
+ "path",
257
+ {
258
+ d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
259
+ key: "wmoenq"
260
+ }
261
+ ],
262
+ ["path", { d: "M12 9v4", key: "juzpu7" }],
263
+ ["path", { d: "M12 17h.01", key: "p32p05" }]
264
+ ]);
265
+
266
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/wrench.js
267
+ var Wrench = createLucideIcon("Wrench", [
268
+ [
269
+ "path",
270
+ {
271
+ d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z",
272
+ key: "cbrjhi"
273
+ }
274
+ ]
275
+ ]);
276
+
277
+ // ../../node_modules/.pnpm/lucide-react@0.452.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/x.js
278
+ var X = createLucideIcon("X", [
279
+ ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
280
+ ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
281
+ ]);
282
+
283
+ // index.tsx
284
+ import qler from "qler";
285
+ import { ulid } from "ulid";
286
+ import html2canvas from "html2canvas-pro";
287
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
288
+ function readFileAsDataURL(file) {
289
+ return new Promise((resolve, reject) => {
290
+ const reader = new FileReader();
291
+ reader.onload = () => resolve(reader.result);
292
+ reader.onerror = reject;
293
+ reader.readAsDataURL(file);
294
+ });
295
+ }
296
+ function filesToAttachedImages(files) {
297
+ return __async(this, null, function* () {
298
+ const results = [];
299
+ for (const file of Array.from(files)) {
300
+ if (!file.type.startsWith("image/")) continue;
301
+ const dataUrl = yield readFileAsDataURL(file);
302
+ results.push({ id: prefixedUlid("img"), dataUrl, name: file.name });
303
+ }
304
+ return results;
305
+ });
306
+ }
307
+ function mediaTypeFromDataUrl(dataUrl) {
308
+ if (!dataUrl.startsWith("data:")) return "application/octet-stream";
309
+ const rest = dataUrl.slice(5);
310
+ const semi = rest.indexOf(";");
311
+ const comma = rest.indexOf(",");
312
+ const end = semi === -1 ? comma : semi;
313
+ if (end <= 0) return "application/octet-stream";
314
+ return rest.slice(0, end) || "application/octet-stream";
315
+ }
316
+ function attachedImageToFileUIPart(img) {
317
+ return {
318
+ type: "file",
319
+ mediaType: mediaTypeFromDataUrl(img.dataUrl),
320
+ url: img.dataUrl,
321
+ filename: img.name
322
+ };
323
+ }
324
+ var DEFAULT_AI_SETTINGS = {
325
+ thinkingLevel: "none",
326
+ urlContext: false,
327
+ googleSearch: false,
328
+ enterpriseWebSearch: false,
329
+ browserCapture: false,
330
+ pageMigrationIr: false,
331
+ figmaToken: ""
332
+ };
333
+ var AI_SETTINGS_STORAGE_KEY = "puck-ai-settings";
334
+ function useAiSettings(storageKey = AI_SETTINGS_STORAGE_KEY) {
335
+ const [settings, setSettingsState] = useState(() => {
336
+ try {
337
+ if (typeof window !== "undefined") {
338
+ const stored = localStorage.getItem(storageKey);
339
+ if (stored) return __spreadValues(__spreadValues({}, DEFAULT_AI_SETTINGS), JSON.parse(stored));
340
+ }
341
+ } catch (e) {
342
+ }
343
+ return __spreadValues({}, DEFAULT_AI_SETTINGS);
344
+ });
345
+ const setSettings = useCallback(
346
+ (update) => {
347
+ setSettingsState((prev) => {
348
+ const next = __spreadValues(__spreadValues({}, prev), update);
349
+ try {
350
+ localStorage.setItem(storageKey, JSON.stringify(next));
351
+ } catch (e) {
352
+ }
353
+ return next;
354
+ });
355
+ },
356
+ [storageKey]
357
+ );
358
+ return [settings, setSettings];
359
+ }
360
+ var prefixedUlid = (prefix = "") => `${prefix ? `${prefix}_` : ""}${ulid()}`;
361
+ var q = qler();
362
+ var getSelectorForId = (state, id) => {
363
+ var _a, _b, _c, _d;
364
+ const node = (_b = (_a = state == null ? void 0 : state.indexes) == null ? void 0 : _a.nodes) == null ? void 0 : _b[id];
365
+ if (!node) return void 0;
366
+ const zoneCompound = `${node.parentId}:${node.zone}`;
367
+ const index = (_d = (_c = state.indexes.zones[zoneCompound]) == null ? void 0 : _c.contentIds) == null ? void 0 : _d.indexOf(id);
368
+ return { zone: zoneCompound, index };
369
+ };
370
+ var getItemById = (state, id) => {
371
+ var _a, _b, _c;
372
+ return (_c = (_b = (_a = state == null ? void 0 : state.indexes) == null ? void 0 : _a.nodes) == null ? void 0 : _b[id]) == null ? void 0 : _c.data;
373
+ };
374
+ var applyArrayDefaults = (oldProps, newProps, fields) => {
375
+ const updatedProps = __spreadValues(__spreadValues({}, oldProps), newProps);
376
+ for (const fieldName in fields) {
377
+ const field = fields[fieldName];
378
+ if (field.type === "array") {
379
+ const arrayField = field;
380
+ const arrayFields = arrayField.arrayFields;
381
+ updatedProps[fieldName] = (updatedProps[fieldName] || []).map(
382
+ (item, index) => {
383
+ var _a, _b, _c, _d, _e;
384
+ const newItem = {};
385
+ const defaultValue = typeof arrayField.defaultItemProps === "function" ? arrayField.defaultItemProps(index) : arrayField.defaultItemProps;
386
+ for (const arrayFieldName in arrayFields) {
387
+ const subField = arrayFields[arrayFieldName];
388
+ if (subField.type === "slot") {
389
+ newItem[arrayFieldName] = (_d = (_c = item[arrayFieldName]) != null ? _c : (_b = (_a = oldProps[fieldName]) == null ? void 0 : _a[index]) == null ? void 0 : _b[arrayFieldName]) != null ? _d : defaultValue == null ? void 0 : defaultValue[arrayFieldName];
390
+ } else {
391
+ newItem[arrayFieldName] = (_e = item[arrayFieldName]) != null ? _e : defaultValue == null ? void 0 : defaultValue[arrayFieldName];
392
+ }
393
+ }
394
+ return newItem;
395
+ }
396
+ );
397
+ }
398
+ }
399
+ return updatedProps;
400
+ };
401
+ var scheduleReplacePropsAfterAddInsert = (operation, {
402
+ getState,
403
+ dispatchAction,
404
+ config
405
+ }) => {
406
+ const maxAttempts = 8;
407
+ const tryApply = (attempt) => {
408
+ var _a, _b, _c, _d, _e;
409
+ const existing = getItemById(getState(), operation.id);
410
+ if (existing) {
411
+ const newData = __spreadProps(__spreadValues({}, existing), {
412
+ props: applyArrayDefaults(
413
+ existing.props,
414
+ operation.props,
415
+ (_b = (_a = config.components[existing.type]) == null ? void 0 : _a.fields) != null ? _b : {}
416
+ )
417
+ });
418
+ dispatchAction({
419
+ type: "replace",
420
+ destinationIndex: operation.index,
421
+ destinationZone: operation.zone,
422
+ data: newData,
423
+ recordHistory: false
424
+ });
425
+ return;
426
+ }
427
+ if (attempt >= maxAttempts) {
428
+ const zoneOk = Boolean((_e = (_d = (_c = getState()) == null ? void 0 : _c.indexes) == null ? void 0 : _d.zones) == null ? void 0 : _e[operation.zone]);
429
+ console.error(
430
+ "Puck AI: could not find inserted item after add.",
431
+ zoneOk ? "State may not have synced yet." : `Target zone may be invalid or not yet in the tree: ${operation.zone}`,
432
+ operation
433
+ );
434
+ return;
435
+ }
436
+ const delay = attempt === 0 ? 0 : attempt === 1 ? 0 : attempt === 2 ? 10 : attempt === 3 ? 50 : attempt === 4 ? 100 : 200;
437
+ setTimeout(() => tryApply(attempt + 1), delay);
438
+ };
439
+ queueMicrotask(() => tryApply(0));
440
+ };
441
+ var dispatchOp = (operation, {
442
+ getState,
443
+ dispatchAction,
444
+ config
445
+ }) => {
446
+ var _a, _b, _c, _d, _e, _f, _g;
447
+ const state = getState();
448
+ try {
449
+ if (operation.op === "add") {
450
+ if (operation.zone) {
451
+ dispatchAction({
452
+ type: "insert",
453
+ destinationIndex: operation.index,
454
+ destinationZone: operation.zone,
455
+ componentType: operation.type,
456
+ id: operation.id,
457
+ recordHistory: false
458
+ });
459
+ scheduleReplacePropsAfterAddInsert(operation, {
460
+ getState,
461
+ dispatchAction,
462
+ config
463
+ });
464
+ }
465
+ } else if (operation.op === "update") {
466
+ const selector = getSelectorForId(state, operation.id);
467
+ const existing = getItemById(state, operation.id);
468
+ if (!selector || !existing) {
469
+ throw new Error(
470
+ `Tried to update an item that doesn't exist: ${operation.id}`
471
+ );
472
+ }
473
+ const newData = __spreadProps(__spreadValues({}, existing), {
474
+ props: applyArrayDefaults(
475
+ existing.props,
476
+ operation.props,
477
+ (_b = (_a = config.components[existing.type]) == null ? void 0 : _a.fields) != null ? _b : {}
478
+ )
479
+ });
480
+ dispatchAction({
481
+ type: "replace",
482
+ destinationIndex: selector.index,
483
+ destinationZone: selector.zone,
484
+ data: newData,
485
+ recordHistory: false
486
+ });
487
+ } else if (operation.op === "updateRoot") {
488
+ const existing = (_c = state == null ? void 0 : state.data) == null ? void 0 : _c.root;
489
+ const defaultProps = (_e = (_d = config.root) == null ? void 0 : _d.defaultProps) != null ? _e : {};
490
+ dispatchAction({
491
+ type: "replaceRoot",
492
+ root: __spreadProps(__spreadValues({}, existing), {
493
+ props: __spreadValues(__spreadValues(__spreadValues({}, defaultProps), existing == null ? void 0 : existing.props), operation.props)
494
+ }),
495
+ recordHistory: false
496
+ });
497
+ } else if (operation.op === "delete") {
498
+ const selector = getSelectorForId(state, operation.id);
499
+ if (!selector) {
500
+ throw new Error(
501
+ `Tried to delete an item that doesn't exist: ${operation.id}`
502
+ );
503
+ }
504
+ dispatchAction({
505
+ type: "remove",
506
+ zone: selector.zone,
507
+ index: selector.index,
508
+ recordHistory: false
509
+ });
510
+ } else if (operation.op === "duplicate") {
511
+ const selector = getSelectorForId(state, operation.id);
512
+ if (!selector) {
513
+ throw new Error(
514
+ `Tried to duplicate an item that doesn't exist: ${operation.id}`
515
+ );
516
+ }
517
+ dispatchAction({
518
+ type: "duplicate",
519
+ sourceZone: selector.zone,
520
+ sourceIndex: selector.index,
521
+ recordHistory: false
522
+ });
523
+ } else if (operation.op === "move") {
524
+ const selector = getSelectorForId(state, operation.id);
525
+ if (!selector) {
526
+ throw new Error(
527
+ `Tried to move an item that doesn't exist: ${operation.id}`
528
+ );
529
+ }
530
+ dispatchAction({
531
+ type: "move",
532
+ sourceZone: selector.zone,
533
+ sourceIndex: selector.index,
534
+ destinationIndex: operation.index,
535
+ destinationZone: operation.zone,
536
+ recordHistory: false
537
+ });
538
+ } else if (operation.op === "reset") {
539
+ const defaultRootProps = (_g = (_f = config.root) == null ? void 0 : _f.defaultProps) != null ? _g : {};
540
+ dispatchAction({
541
+ type: "setData",
542
+ data: { content: [], root: defaultRootProps },
543
+ recordHistory: false
544
+ });
545
+ } else {
546
+ throw new Error(`Unknown operation: ${operation.op}`);
547
+ }
548
+ } catch (e) {
549
+ console.error("Error applying operation, skipping...", operation, e);
550
+ }
551
+ };
552
+ var toolStatusContext = createContext({});
553
+ var ToolStatusProvider = toolStatusContext.Provider;
554
+ function Loader({ size = 16 }) {
555
+ return /* @__PURE__ */ jsx(
556
+ "span",
557
+ {
558
+ className: "puck-ai-loader",
559
+ style: { width: size, height: size },
560
+ "aria-label": "loading"
561
+ }
562
+ );
563
+ }
564
+ function ToolStatusDisplay({ status }) {
565
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-data", children: /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-data-inner", children: [
566
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-data-icon", children: status.error ? /* @__PURE__ */ jsx(TriangleAlert, { size: 18 }) : status.loading ? /* @__PURE__ */ jsx(Loader, { size: 16 }) : /* @__PURE__ */ jsx(Check, { size: 18 }) }),
567
+ /* @__PURE__ */ jsx("div", { children: status.label })
568
+ ] }) });
569
+ }
570
+ function PuckTool({
571
+ toolCallId,
572
+ output,
573
+ status: mergedStatus,
574
+ defaultLabel = "Thinking..."
575
+ }) {
576
+ const toolStatusMap = useContext(toolStatusContext);
577
+ const contextStatus = toolStatusMap[toolCallId];
578
+ const outputObj = output;
579
+ const status = mergedStatus != null ? mergedStatus : outputObj && "status" in outputObj ? outputObj.status : contextStatus != null ? contextStatus : { loading: true, label: defaultLabel };
580
+ return /* @__PURE__ */ jsx(ToolStatusDisplay, { status });
581
+ }
582
+ function safeJsonPreview(value, maxLen = 4e3) {
583
+ try {
584
+ const s = JSON.stringify(value, null, 2);
585
+ if (s.length <= maxLen) return s;
586
+ return `${s.slice(0, maxLen)}
587
+ \u2026`;
588
+ } catch (e) {
589
+ return String(value);
590
+ }
591
+ }
592
+ function FileMessagePart({
593
+ part,
594
+ role
595
+ }) {
596
+ var _a, _b;
597
+ const isImage = part.mediaType.startsWith("image/");
598
+ if (isImage) {
599
+ return /* @__PURE__ */ jsxs(
600
+ "div",
601
+ {
602
+ className: `puck-ai-chat-message-file${role === "user" ? " puck-ai-chat-message-file--user" : ""}`,
603
+ children: [
604
+ /* @__PURE__ */ jsx(
605
+ "img",
606
+ {
607
+ src: part.url,
608
+ alt: (_a = part.filename) != null ? _a : "Attached image",
609
+ className: "puck-ai-chat-message-file-image"
610
+ }
611
+ ),
612
+ part.filename ? /* @__PURE__ */ jsx("span", { className: "puck-ai-chat-message-file-caption", children: part.filename }) : null
613
+ ]
614
+ }
615
+ );
616
+ }
617
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-file puck-ai-chat-message-file--document", children: /* @__PURE__ */ jsx(
618
+ "a",
619
+ {
620
+ href: part.url,
621
+ target: "_blank",
622
+ rel: "noopener noreferrer",
623
+ download: part.filename,
624
+ children: (_b = part.filename) != null ? _b : part.mediaType
625
+ }
626
+ ) });
627
+ }
628
+ function ReasoningMessagePart({
629
+ part
630
+ }) {
631
+ const streaming = part.state === "streaming";
632
+ return /* @__PURE__ */ jsxs("details", { className: "puck-ai-chat-message-reasoning", open: streaming, children: [
633
+ /* @__PURE__ */ jsxs("summary", { className: "puck-ai-chat-message-reasoning-summary", children: [
634
+ "Reasoning",
635
+ streaming ? /* @__PURE__ */ jsx(
636
+ "span",
637
+ {
638
+ className: "puck-ai-chat-message-reasoning-streaming",
639
+ "aria-live": "polite",
640
+ children: /* @__PURE__ */ jsx(Loader, { size: 12 })
641
+ }
642
+ ) : null
643
+ ] }),
644
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-reasoning-body", children: /* @__PURE__ */ jsx(ReactMarkdown, { children: part.text }) })
645
+ ] });
646
+ }
647
+ function SdkToolInvocation({ part }) {
648
+ const name = getToolName(part);
649
+ const state = part.state;
650
+ let stateLabel;
651
+ if (state === "input-streaming") stateLabel = "Preparing\u2026";
652
+ else if (state === "input-available") stateLabel = "Running\u2026";
653
+ else if (state === "output-available") stateLabel = "Done";
654
+ else if (state === "output-error") stateLabel = "Error";
655
+ else if (state === "approval-requested") stateLabel = "Awaiting approval";
656
+ else if (state === "approval-responded") stateLabel = "Approval recorded";
657
+ else if (state === "output-denied") stateLabel = "Denied";
658
+ else stateLabel = state;
659
+ const loading = state === "input-streaming" || state === "input-available" || state === "approval-requested";
660
+ const input = "input" in part ? part.input : void 0;
661
+ const output = "output" in part ? part.output : void 0;
662
+ const errorText = "errorText" in part ? part.errorText : void 0;
663
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-tool", children: [
664
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-tool-header", children: [
665
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-chat-message-tool-icon", "aria-hidden": true, children: /* @__PURE__ */ jsx(Wrench, { size: 14 }) }),
666
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-chat-message-tool-name", children: name }),
667
+ /* @__PURE__ */ jsxs("span", { className: "puck-ai-chat-message-tool-state", children: [
668
+ loading ? /* @__PURE__ */ jsx(Loader, { size: 12 }) : null,
669
+ stateLabel
670
+ ] })
671
+ ] }),
672
+ state === "output-error" && errorText ? /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-tool-error", children: errorText }) : null,
673
+ /* @__PURE__ */ jsxs("details", { className: "puck-ai-chat-message-tool-details", children: [
674
+ /* @__PURE__ */ jsx("summary", { children: "Input / output" }),
675
+ input !== void 0 ? /* @__PURE__ */ jsx("pre", { className: "puck-ai-chat-message-tool-pre", children: safeJsonPreview(input) }) : null,
676
+ state === "output-available" && output !== void 0 ? /* @__PURE__ */ jsx("pre", { className: "puck-ai-chat-message-tool-pre", children: safeJsonPreview(output) }) : null
677
+ ] })
678
+ ] });
679
+ }
680
+ function DataMessagePart({ part }) {
681
+ var _a, _b, _c, _d;
682
+ if (part.type === "data-puck-actions") {
683
+ const actions = part.data;
684
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-data-summary", children: [
685
+ "Applied ",
686
+ actions.length,
687
+ " editor action",
688
+ actions.length === 1 ? "" : "s"
689
+ ] });
690
+ }
691
+ if (part.type === "data-build-op") {
692
+ const op = part.data;
693
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-data-summary", children: [
694
+ "Build operation: ",
695
+ /* @__PURE__ */ jsx("code", { children: op.op })
696
+ ] });
697
+ }
698
+ if (part.type === "data-finish") {
699
+ const d = part.data;
700
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-data-summary", children: [
701
+ "Tokens: in ",
702
+ (_b = (_a = d.tokenUsage) == null ? void 0 : _a.inputTokens) != null ? _b : "\u2014",
703
+ " \xB7 out",
704
+ " ",
705
+ (_d = (_c = d.tokenUsage) == null ? void 0 : _c.outputTokens) != null ? _d : "\u2014",
706
+ d.totalCost !== void 0 ? ` \xB7 cost ${d.totalCost}` : ""
707
+ ] });
708
+ }
709
+ if (part.type === "data-page") {
710
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-data-summary", children: "Page snapshot attached" });
711
+ }
712
+ if (part.type === "data-new-chat-created" || part.type === "data-tool-status" || part.type === "data-send-screenshot") {
713
+ return null;
714
+ }
715
+ return /* @__PURE__ */ jsxs("details", { className: "puck-ai-chat-message-data-raw", children: [
716
+ /* @__PURE__ */ jsx("summary", { children: part.type.replace(/^data-/, "") }),
717
+ /* @__PURE__ */ jsx("pre", { className: "puck-ai-chat-message-tool-pre", children: safeJsonPreview(part.data) })
718
+ ] });
719
+ }
720
+ function ChatMessagePart({ part, role }) {
721
+ var _a;
722
+ if (isTextUIPart(part)) {
723
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-text", children: role === "assistant" || role === "user" ? /* @__PURE__ */ jsx(ReactMarkdown, { children: part.text }) : /* @__PURE__ */ jsx("span", { children: part.text }) });
724
+ }
725
+ if (isReasoningUIPart(part)) {
726
+ return /* @__PURE__ */ jsx(ReasoningMessagePart, { part });
727
+ }
728
+ if (isFileUIPart(part)) {
729
+ return /* @__PURE__ */ jsx(FileMessagePart, { part, role });
730
+ }
731
+ if (part.type === "source-url") {
732
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-source", children: /* @__PURE__ */ jsx("a", { href: part.url, target: "_blank", rel: "noopener noreferrer", children: (_a = part.title) != null ? _a : part.url }) });
733
+ }
734
+ if (part.type === "source-document") {
735
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-message-source", children: [
736
+ /* @__PURE__ */ jsx("span", { title: part.filename, children: part.title }),
737
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-chat-message-source-meta", children: part.mediaType })
738
+ ] });
739
+ }
740
+ if (part.type === "step-start") {
741
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-chat-message-step", "aria-hidden": true });
742
+ }
743
+ if (isToolUIPart(part)) {
744
+ if (part.type === "tool-createPage" || part.type === "tool-updatePage" || part.type === "tool-userTool") {
745
+ return /* @__PURE__ */ jsx(PuckTool, __spreadValues({}, part));
746
+ }
747
+ return /* @__PURE__ */ jsx(SdkToolInvocation, { part });
748
+ }
749
+ if (isDataUIPart(part)) {
750
+ return /* @__PURE__ */ jsx(DataMessagePart, { part });
751
+ }
752
+ return null;
753
+ }
754
+ function ChatMessage({ message }) {
755
+ const { role, parts } = message;
756
+ return /* @__PURE__ */ jsx(
757
+ "div",
758
+ {
759
+ className: `puck-ai-chat-message${role === "user" ? " puck-ai-chat-message--user-role" : ""}`,
760
+ "data-message-id": message.id,
761
+ children: parts.map((part, i) => /* @__PURE__ */ jsx(
762
+ ChatMessagePart,
763
+ {
764
+ part,
765
+ role
766
+ },
767
+ `${message.id}-${part.type}-${i}`
768
+ ))
769
+ }
770
+ );
771
+ }
772
+ function ExamplePrompt({
773
+ label,
774
+ href,
775
+ onClick
776
+ }) {
777
+ const El = href ? "a" : "button";
778
+ return /* @__PURE__ */ jsxs(
779
+ El,
780
+ {
781
+ className: "puck-ai-chatbody-example-prompt",
782
+ href,
783
+ onClick,
784
+ children: [
785
+ /* @__PURE__ */ jsx("div", { children: label }),
786
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-example-prompt-arrow", children: /* @__PURE__ */ jsx(ArrowUp, { size: 16 }) })
787
+ ]
788
+ }
789
+ );
790
+ }
791
+ function PromptForm({
792
+ handleSubmit,
793
+ inputRef,
794
+ isLoading,
795
+ glow,
796
+ placeholder = "What do you want to build?",
797
+ minRows = 2,
798
+ maxRows = 5,
799
+ value = "",
800
+ images = [],
801
+ onImagesChange
802
+ }) {
803
+ const [prompt, setPrompt] = useState(value);
804
+ const [isDragOver, setIsDragOver] = useState(false);
805
+ const hasSetInitialPrompt = useRef(false);
806
+ const internalRef = useRef(null);
807
+ const fileInputRef = useRef(null);
808
+ useEffect(() => {
809
+ setPrompt(value);
810
+ }, [value]);
811
+ useEffect(() => {
812
+ const currentUrl = new URL(location.href);
813
+ const initialPrompt = currentUrl.searchParams.get("initialPrompt");
814
+ if (!hasSetInitialPrompt.current && initialPrompt && prompt === "") {
815
+ hasSetInitialPrompt.current = true;
816
+ setPrompt(initialPrompt);
817
+ }
818
+ }, []);
819
+ const addImages = useCallback(
820
+ (files) => __async(null, null, function* () {
821
+ const newImgs = yield filesToAttachedImages(files);
822
+ if (newImgs.length > 0) {
823
+ onImagesChange == null ? void 0 : onImagesChange([...images, ...newImgs]);
824
+ }
825
+ }),
826
+ [images, onImagesChange]
827
+ );
828
+ const removeImage = useCallback(
829
+ (id) => {
830
+ onImagesChange == null ? void 0 : onImagesChange(images.filter((img) => img.id !== id));
831
+ },
832
+ [images, onImagesChange]
833
+ );
834
+ const sendPrompt = () => {
835
+ if (isLoading) return;
836
+ if (prompt.trim() || images.length > 0) {
837
+ handleSubmit(prompt);
838
+ }
839
+ setPrompt("");
840
+ };
841
+ const handleDragOver = (e) => {
842
+ e.preventDefault();
843
+ if (e.dataTransfer.types.some((t) => t === "Files")) {
844
+ setIsDragOver(true);
845
+ }
846
+ };
847
+ const handleDragLeave = (e) => {
848
+ if (!e.currentTarget.contains(e.relatedTarget)) {
849
+ setIsDragOver(false);
850
+ }
851
+ };
852
+ const handleDrop = (e) => __async(null, null, function* () {
853
+ e.preventDefault();
854
+ setIsDragOver(false);
855
+ if (e.dataTransfer.files.length > 0) {
856
+ yield addImages(e.dataTransfer.files);
857
+ }
858
+ });
859
+ const handlePaste = (e) => __async(null, null, function* () {
860
+ const items = Array.from(e.clipboardData.items);
861
+ const imageFiles = items.filter((item) => item.kind === "file" && item.type.startsWith("image/")).map((item) => item.getAsFile()).filter((file) => file !== null);
862
+ if (imageFiles.length > 0) {
863
+ yield addImages(imageFiles);
864
+ }
865
+ });
866
+ const classNames = [
867
+ "puck-ai-prompt-form",
868
+ glow ? "puck-ai-prompt-form--glow" : "",
869
+ isLoading ? "puck-ai-prompt-form--is-loading" : "",
870
+ isDragOver ? "puck-ai-prompt-form--drag-over" : ""
871
+ ].filter(Boolean).join(" ");
872
+ return /* @__PURE__ */ jsx(
873
+ "div",
874
+ {
875
+ className: classNames,
876
+ onDragOver: handleDragOver,
877
+ onDragEnter: handleDragOver,
878
+ onDragLeave: handleDragLeave,
879
+ onDrop: handleDrop,
880
+ children: /* @__PURE__ */ jsxs("div", { className: "puck-ai-prompt-form-inner", children: [
881
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-prompt-form-glow" }),
882
+ /* @__PURE__ */ jsx(
883
+ "input",
884
+ {
885
+ ref: fileInputRef,
886
+ type: "file",
887
+ accept: "image/*",
888
+ multiple: true,
889
+ style: { display: "none" },
890
+ onChange: (e) => __async(null, null, function* () {
891
+ if (e.target.files) {
892
+ yield addImages(e.target.files);
893
+ e.target.value = "";
894
+ }
895
+ })
896
+ }
897
+ ),
898
+ /* @__PURE__ */ jsxs(
899
+ "form",
900
+ {
901
+ onSubmit: (e) => {
902
+ e.preventDefault();
903
+ sendPrompt();
904
+ },
905
+ children: [
906
+ images.length > 0 && /* @__PURE__ */ jsx("div", { className: "puck-ai-image-thumbnails", children: images.map((img) => /* @__PURE__ */ jsxs("div", { className: "puck-ai-image-thumbnail", children: [
907
+ /* @__PURE__ */ jsx("img", { src: img.dataUrl, alt: img.name }),
908
+ /* @__PURE__ */ jsx(
909
+ "button",
910
+ {
911
+ type: "button",
912
+ className: "puck-ai-image-thumbnail-remove",
913
+ onClick: () => removeImage(img.id),
914
+ title: "Remove image",
915
+ children: /* @__PURE__ */ jsx(X, { size: 10 })
916
+ }
917
+ )
918
+ ] }, img.id)) }),
919
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-prompt-form-form-inner", children: [
920
+ /* @__PURE__ */ jsx(
921
+ TextareaAutosize,
922
+ {
923
+ className: "puck-ai-prompt-form-input",
924
+ name: "prompt",
925
+ minRows,
926
+ maxRows,
927
+ placeholder: isDragOver ? "Drop images here\u2026" : placeholder,
928
+ disabled: isLoading,
929
+ value: prompt,
930
+ ref: (node) => {
931
+ if (inputRef) {
932
+ inputRef.current = node;
933
+ }
934
+ internalRef.current = node;
935
+ },
936
+ onChange: (e) => setPrompt(e.target.value),
937
+ onPaste: handlePaste,
938
+ onKeyDown: (e) => {
939
+ if (!e.shiftKey && e.key === "Enter") {
940
+ e.preventDefault();
941
+ }
942
+ },
943
+ onKeyUp: (e) => {
944
+ if (!e.shiftKey && e.key === "Enter") {
945
+ e.preventDefault();
946
+ sendPrompt();
947
+ }
948
+ }
949
+ }
950
+ ),
951
+ /* @__PURE__ */ jsxs(
952
+ "div",
953
+ {
954
+ className: "puck-ai-prompt-form-actions",
955
+ onClick: () => {
956
+ var _a;
957
+ return (_a = internalRef.current) == null ? void 0 : _a.focus();
958
+ },
959
+ children: [
960
+ /* @__PURE__ */ jsx(
961
+ "div",
962
+ {
963
+ className: "puck-ai-prompt-form-actions-left",
964
+ onClick: (e) => e.stopPropagation(),
965
+ children: /* @__PURE__ */ jsx(
966
+ "button",
967
+ {
968
+ type: "button",
969
+ className: "puck-ai-image-attach-btn",
970
+ title: "Attach image",
971
+ onClick: () => {
972
+ var _a;
973
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
974
+ },
975
+ disabled: isLoading,
976
+ children: /* @__PURE__ */ jsx(Image, { size: 15 })
977
+ }
978
+ )
979
+ }
980
+ ),
981
+ /* @__PURE__ */ jsx(
982
+ "div",
983
+ {
984
+ className: "puck-ai-prompt-form-actions-right",
985
+ onClick: (e) => e.stopPropagation(),
986
+ children: /* @__PURE__ */ jsx(
987
+ "button",
988
+ {
989
+ className: "puck-ai-prompt-form-action-submit",
990
+ type: "submit",
991
+ disabled: isLoading,
992
+ children: /* @__PURE__ */ jsx(ArrowUp, { size: 24 })
993
+ }
994
+ )
995
+ }
996
+ )
997
+ ]
998
+ }
999
+ )
1000
+ ] })
1001
+ ]
1002
+ }
1003
+ )
1004
+ ] })
1005
+ }
1006
+ );
1007
+ }
1008
+ function ChatBody({
1009
+ children,
1010
+ examplePrompts,
1011
+ handleSubmit,
1012
+ hideInput,
1013
+ inputRef,
1014
+ messages = [],
1015
+ status,
1016
+ error,
1017
+ handleRetry,
1018
+ promptValue,
1019
+ targetComponent,
1020
+ onClearTarget,
1021
+ images,
1022
+ onImagesChange
1023
+ }) {
1024
+ const { scrollRef, contentRef } = useStickToBottom();
1025
+ const hasMessages = messages && messages.length > 0;
1026
+ const classNames = [
1027
+ "puck-ai-chatbody",
1028
+ hasMessages ? "puck-ai-chatbody--has-messages" : "",
1029
+ children ? "puck-ai-chatbody--has-children" : "",
1030
+ hideInput ? "puck-ai-chatbody--hide-input" : ""
1031
+ ].filter(Boolean).join(" ");
1032
+ return /* @__PURE__ */ jsxs("div", { className: classNames, children: [
1033
+ children ? /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-default", children }) : null,
1034
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-chatbody-inner", ref: scrollRef, children: [
1035
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-messages", ref: contentRef, children: [...messages].reverse().map((message) => /* @__PURE__ */ jsx(ChatMessage, { message }, message.id)) }),
1036
+ status === "submitted" && /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-loader", children: /* @__PURE__ */ jsx(Loader, { size: 14 }) }),
1037
+ error && /* @__PURE__ */ jsxs("div", { className: "puck-ai-chatbody-error", children: [
1038
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-error-label", children: "Something went wrong." }),
1039
+ handleRetry && /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-error-action", children: /* @__PURE__ */ jsx(
1040
+ "button",
1041
+ {
1042
+ className: "puck-ai-icon-button",
1043
+ title: "Retry",
1044
+ onClick: handleRetry,
1045
+ children: /* @__PURE__ */ jsx(RotateCcw, { size: 14 })
1046
+ }
1047
+ ) })
1048
+ ] }),
1049
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-chatbody-form", children: [
1050
+ targetComponent && /* @__PURE__ */ jsxs("div", { className: "puck-ai-target-banner", children: [
1051
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-target-banner-label", children: "Targeting:" }),
1052
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-target-banner-name", children: targetComponent.label || targetComponent.type }),
1053
+ /* @__PURE__ */ jsx("code", { className: "puck-ai-target-banner-id", children: targetComponent.id }),
1054
+ onClearTarget && /* @__PURE__ */ jsx(
1055
+ "button",
1056
+ {
1057
+ className: "puck-ai-target-banner-clear",
1058
+ onClick: onClearTarget,
1059
+ title: "Clear target",
1060
+ type: "button",
1061
+ children: "\xD7"
1062
+ }
1063
+ )
1064
+ ] }),
1065
+ /* @__PURE__ */ jsx(
1066
+ PromptForm,
1067
+ {
1068
+ glow: !hasMessages && !targetComponent,
1069
+ handleSubmit,
1070
+ inputRef,
1071
+ isLoading: status === "submitted" || status === "streaming",
1072
+ placeholder: targetComponent ? `What should I do with the ${targetComponent.label || targetComponent.type}?` : "What do you want to build?",
1073
+ value: promptValue,
1074
+ images,
1075
+ onImagesChange
1076
+ }
1077
+ ),
1078
+ examplePrompts ? /* @__PURE__ */ jsx("div", { className: "puck-ai-chatbody-example-prompts", children: examplePrompts }) : null
1079
+ ] })
1080
+ ] })
1081
+ ] });
1082
+ }
1083
+ function isScrolledIntoView(el) {
1084
+ const rect = el.getBoundingClientRect();
1085
+ return rect.top >= 0 && rect.bottom <= window.innerHeight;
1086
+ }
1087
+ function Placeholder({
1088
+ dispatch,
1089
+ inputRef,
1090
+ pluginRef
1091
+ }) {
1092
+ const handleEnterPromptClick = () => {
1093
+ var _a;
1094
+ (_a = inputRef.current) == null ? void 0 : _a.focus({ preventScroll: true });
1095
+ setTimeout(() => {
1096
+ if (pluginRef.current && inputRef.current && !isScrolledIntoView(inputRef.current)) {
1097
+ const box = pluginRef.current.getBoundingClientRect();
1098
+ const top = box.top - (window.innerHeight - box.height) / 2;
1099
+ window.scrollTo({ behavior: "smooth", top });
1100
+ }
1101
+ }, 10);
1102
+ };
1103
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-placeholder", children: [
1104
+ /* @__PURE__ */ jsx(Bot, { size: 24 }),
1105
+ /* @__PURE__ */ jsx("div", { children: "Use AI to build a page using the available blocks" }),
1106
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-actions", children: [
1107
+ /* @__PURE__ */ jsx(
1108
+ "button",
1109
+ {
1110
+ className: "puck-ai-chat-action",
1111
+ onClick: handleEnterPromptClick,
1112
+ children: "Enter prompt"
1113
+ }
1114
+ ),
1115
+ /* @__PURE__ */ jsx(
1116
+ "button",
1117
+ {
1118
+ className: "puck-ai-chat-action-outlined",
1119
+ onClick: () => {
1120
+ dispatch({ type: "setUi", ui: { plugin: { current: "blocks" } } });
1121
+ },
1122
+ children: "Build manually"
1123
+ }
1124
+ )
1125
+ ] })
1126
+ ] });
1127
+ }
1128
+ function scrollIntoViewLocal(el, win, behavior = "smooth") {
1129
+ var _a, _b;
1130
+ const scroller = ((_a = el.ownerDocument) == null ? void 0 : _a.scrollingElement) || ((_b = el.ownerDocument) == null ? void 0 : _b.documentElement);
1131
+ const rect = el.getBoundingClientRect();
1132
+ const vpH = win.innerHeight;
1133
+ const current = scroller.scrollTop;
1134
+ const offset = win.innerHeight / 2;
1135
+ let targetTop = current;
1136
+ if (rect.top < 0) {
1137
+ targetTop = current + rect.top;
1138
+ } else if (rect.bottom > vpH) {
1139
+ targetTop = current + (rect.bottom - vpH);
1140
+ }
1141
+ if (targetTop !== current) {
1142
+ scroller.scrollTo({ top: targetTop + offset, behavior });
1143
+ }
1144
+ }
1145
+ function useFrameMutationObserver(callback) {
1146
+ return useCallback(() => {
1147
+ var _a;
1148
+ const frame = document == null ? void 0 : document.getElementById(
1149
+ "preview-frame"
1150
+ );
1151
+ if (!frame) return;
1152
+ let observer = null;
1153
+ const win = frame.contentWindow;
1154
+ let enabled = true;
1155
+ const disable = () => {
1156
+ enabled = false;
1157
+ };
1158
+ const attachObserver = () => {
1159
+ const win2 = frame.contentWindow;
1160
+ const doc = frame.contentDocument || (win2 == null ? void 0 : win2.document);
1161
+ if (!win2 || !doc) return;
1162
+ const target = doc.querySelector("#frame-root > div");
1163
+ if (!target) return;
1164
+ observer = new MutationObserver((entries) => {
1165
+ if (enabled) callback(entries, win2);
1166
+ });
1167
+ observer.observe(target, { childList: true, subtree: true });
1168
+ win2.addEventListener("pointerdown", disable);
1169
+ win2.addEventListener("wheel", disable);
1170
+ };
1171
+ if (((_a = frame.contentDocument) == null ? void 0 : _a.readyState) === "complete") {
1172
+ attachObserver();
1173
+ } else {
1174
+ frame.addEventListener("load", attachObserver, { once: true });
1175
+ }
1176
+ return () => {
1177
+ frame.removeEventListener("load", attachObserver);
1178
+ win == null ? void 0 : win.removeEventListener("pointerdown", disable);
1179
+ win == null ? void 0 : win.removeEventListener("wheel", disable);
1180
+ observer == null ? void 0 : observer.disconnect();
1181
+ };
1182
+ }, [callback]);
1183
+ }
1184
+ function ScrollTracking({ children }) {
1185
+ const followedRefs = useRef([]);
1186
+ const follow = useFrameMutationObserver((records, win) => {
1187
+ if (records.length > 0) {
1188
+ const lastRecord = records[records.length - 1];
1189
+ if (followedRefs.current.includes(lastRecord.target)) return;
1190
+ followedRefs.current.push(lastRecord.target);
1191
+ requestAnimationFrame(() => {
1192
+ const el = lastRecord.target;
1193
+ scrollIntoViewLocal(el, win);
1194
+ });
1195
+ }
1196
+ });
1197
+ useEffect(() => {
1198
+ const cleanup = follow();
1199
+ return cleanup;
1200
+ }, [follow]);
1201
+ return /* @__PURE__ */ jsx(Fragment, { children });
1202
+ }
1203
+ function Toggle({
1204
+ checked,
1205
+ onChange,
1206
+ id,
1207
+ disabled
1208
+ }) {
1209
+ return /* @__PURE__ */ jsxs(
1210
+ "label",
1211
+ {
1212
+ className: `puck-ai-toggle${disabled ? " puck-ai-toggle--disabled" : ""}`,
1213
+ htmlFor: id,
1214
+ children: [
1215
+ /* @__PURE__ */ jsx(
1216
+ "input",
1217
+ {
1218
+ type: "checkbox",
1219
+ id,
1220
+ checked,
1221
+ disabled,
1222
+ onChange: (e) => onChange(e.target.checked),
1223
+ className: "puck-ai-toggle-input"
1224
+ }
1225
+ ),
1226
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-toggle-slider" })
1227
+ ]
1228
+ }
1229
+ );
1230
+ }
1231
+ function SettingsPanel({
1232
+ settings,
1233
+ onChange,
1234
+ onClearChatHistory,
1235
+ hasChatMessages
1236
+ }) {
1237
+ const [showToken, setShowToken] = useState(false);
1238
+ return /* @__PURE__ */ jsx("div", { className: "puck-ai-settings-scroll", children: /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings", children: [
1239
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-section", children: [
1240
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-settings-section-title", children: "Model settings" }),
1241
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row", children: [
1242
+ /* @__PURE__ */ jsxs(
1243
+ "label",
1244
+ {
1245
+ className: "puck-ai-settings-label",
1246
+ htmlFor: "puck-ai-thinking-level",
1247
+ children: [
1248
+ "Thinking level",
1249
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Extended reasoning budget" })
1250
+ ]
1251
+ }
1252
+ ),
1253
+ /* @__PURE__ */ jsxs(
1254
+ "select",
1255
+ {
1256
+ id: "puck-ai-thinking-level",
1257
+ className: "puck-ai-settings-select",
1258
+ value: settings.thinkingLevel,
1259
+ onChange: (e) => onChange({ thinkingLevel: e.target.value }),
1260
+ children: [
1261
+ /* @__PURE__ */ jsx("option", { value: "none", children: "Off" }),
1262
+ /* @__PURE__ */ jsx("option", { value: "low", children: "Low" }),
1263
+ /* @__PURE__ */ jsx("option", { value: "medium", children: "Medium" }),
1264
+ /* @__PURE__ */ jsx("option", { value: "high", children: "High" })
1265
+ ]
1266
+ }
1267
+ )
1268
+ ] }),
1269
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row", children: [
1270
+ /* @__PURE__ */ jsxs(
1271
+ "label",
1272
+ {
1273
+ className: "puck-ai-settings-label",
1274
+ htmlFor: "puck-ai-url-context",
1275
+ children: [
1276
+ "URL context",
1277
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Fetch linked URLs during generation" })
1278
+ ]
1279
+ }
1280
+ ),
1281
+ /* @__PURE__ */ jsx(
1282
+ Toggle,
1283
+ {
1284
+ id: "puck-ai-url-context",
1285
+ checked: settings.urlContext,
1286
+ onChange: (v) => onChange({ urlContext: v })
1287
+ }
1288
+ )
1289
+ ] }),
1290
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row", children: [
1291
+ /* @__PURE__ */ jsxs(
1292
+ "label",
1293
+ {
1294
+ className: "puck-ai-settings-label",
1295
+ htmlFor: "puck-ai-browser-capture",
1296
+ children: [
1297
+ "Browser capture",
1298
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Run server-side browser migration (screenshot + DOM bundle) when a migration URL is in the prompt. Turn off to use URL context only without Worker/Puppeteer." })
1299
+ ]
1300
+ }
1301
+ ),
1302
+ /* @__PURE__ */ jsx(
1303
+ Toggle,
1304
+ {
1305
+ id: "puck-ai-browser-capture",
1306
+ checked: settings.browserCapture,
1307
+ onChange: (v) => onChange(__spreadValues({
1308
+ browserCapture: v
1309
+ }, v ? {} : { pageMigrationIr: false }))
1310
+ }
1311
+ )
1312
+ ] }),
1313
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row", children: [
1314
+ /* @__PURE__ */ jsxs(
1315
+ "label",
1316
+ {
1317
+ className: "puck-ai-settings-label",
1318
+ htmlFor: "puck-ai-page-migration-ir",
1319
+ children: [
1320
+ "Page migration IR",
1321
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Full DOM bundle + structured plan when a source URL is captured (slower; screenshot-only when off). Requires Browser capture." })
1322
+ ]
1323
+ }
1324
+ ),
1325
+ /* @__PURE__ */ jsx(
1326
+ Toggle,
1327
+ {
1328
+ id: "puck-ai-page-migration-ir",
1329
+ disabled: !settings.browserCapture,
1330
+ checked: settings.pageMigrationIr,
1331
+ onChange: (v) => onChange({ pageMigrationIr: v })
1332
+ }
1333
+ )
1334
+ ] }),
1335
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row", children: [
1336
+ /* @__PURE__ */ jsxs(
1337
+ "label",
1338
+ {
1339
+ className: "puck-ai-settings-label",
1340
+ htmlFor: "puck-ai-google-search",
1341
+ children: [
1342
+ "Google Search",
1343
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Ground responses with live search" })
1344
+ ]
1345
+ }
1346
+ ),
1347
+ /* @__PURE__ */ jsx(
1348
+ Toggle,
1349
+ {
1350
+ id: "puck-ai-google-search",
1351
+ checked: settings.googleSearch,
1352
+ onChange: (v) => onChange({ googleSearch: v })
1353
+ }
1354
+ )
1355
+ ] }),
1356
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row", children: [
1357
+ /* @__PURE__ */ jsxs(
1358
+ "label",
1359
+ {
1360
+ className: "puck-ai-settings-label",
1361
+ htmlFor: "puck-ai-enterprise-search",
1362
+ children: [
1363
+ "Enterprise web search",
1364
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Advanced grounding via Vertex AI" })
1365
+ ]
1366
+ }
1367
+ ),
1368
+ /* @__PURE__ */ jsx(
1369
+ Toggle,
1370
+ {
1371
+ id: "puck-ai-enterprise-search",
1372
+ checked: settings.enterpriseWebSearch,
1373
+ onChange: (v) => onChange({ enterpriseWebSearch: v })
1374
+ }
1375
+ )
1376
+ ] })
1377
+ ] }),
1378
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-section", children: [
1379
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-settings-section-title", children: "Figma integration" }),
1380
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row puck-ai-settings-row--column", children: [
1381
+ /* @__PURE__ */ jsx(
1382
+ "label",
1383
+ {
1384
+ className: "puck-ai-settings-label",
1385
+ htmlFor: "puck-ai-figma-token",
1386
+ children: "Personal access token"
1387
+ }
1388
+ ),
1389
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-input-wrap", children: [
1390
+ /* @__PURE__ */ jsx(
1391
+ "input",
1392
+ {
1393
+ id: "puck-ai-figma-token",
1394
+ type: showToken ? "text" : "password",
1395
+ className: "puck-ai-settings-input",
1396
+ placeholder: "figd_xxxxxxxxxxxx",
1397
+ value: settings.figmaToken,
1398
+ onChange: (e) => onChange({ figmaToken: e.target.value }),
1399
+ autoComplete: "off",
1400
+ spellCheck: false
1401
+ }
1402
+ ),
1403
+ /* @__PURE__ */ jsx(
1404
+ "button",
1405
+ {
1406
+ type: "button",
1407
+ className: "puck-ai-settings-input-action",
1408
+ onClick: () => setShowToken((v) => !v),
1409
+ title: showToken ? "Hide token" : "Show token",
1410
+ children: showToken ? /* @__PURE__ */ jsx(EyeOff, { size: 14 }) : /* @__PURE__ */ jsx(Eye, { size: 14 })
1411
+ }
1412
+ )
1413
+ ] }),
1414
+ /* @__PURE__ */ jsx(
1415
+ "a",
1416
+ {
1417
+ href: "https://www.figma.com/settings",
1418
+ target: "_blank",
1419
+ rel: "noopener noreferrer",
1420
+ className: "puck-ai-settings-link",
1421
+ children: "Get your Figma access token \u2192"
1422
+ }
1423
+ ),
1424
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", style: { marginTop: 4 }, children: "Paste a Figma URL in chat to generate from your design. Token overrides server config." })
1425
+ ] })
1426
+ ] }),
1427
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-section", children: [
1428
+ /* @__PURE__ */ jsx("div", { className: "puck-ai-settings-section-title", children: "Chat" }),
1429
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-settings-row puck-ai-settings-row--column", children: [
1430
+ /* @__PURE__ */ jsxs(
1431
+ "label",
1432
+ {
1433
+ className: "puck-ai-settings-label",
1434
+ htmlFor: "puck-ai-clear-chat",
1435
+ children: [
1436
+ "Clear chat history",
1437
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-settings-hint", children: "Remove all messages and reset the conversation context for this session." })
1438
+ ]
1439
+ }
1440
+ ),
1441
+ /* @__PURE__ */ jsxs(
1442
+ "button",
1443
+ {
1444
+ id: "puck-ai-clear-chat",
1445
+ type: "button",
1446
+ className: "puck-ai-settings-clear-chat",
1447
+ disabled: !hasChatMessages,
1448
+ onClick: onClearChatHistory,
1449
+ children: [
1450
+ /* @__PURE__ */ jsx(Trash2, { size: 14, "aria-hidden": true }),
1451
+ "Clear messages"
1452
+ ]
1453
+ }
1454
+ )
1455
+ ] })
1456
+ ] })
1457
+ ] }) });
1458
+ }
1459
+ var usePuck = createUsePuck();
1460
+ function Chat({
1461
+ chat,
1462
+ host = "/api/puck/chat",
1463
+ prepareRequest,
1464
+ settings
1465
+ }) {
1466
+ const { examplePrompts } = chat != null ? chat : {};
1467
+ const puckDispatch = usePuck((s) => s.dispatch);
1468
+ const getPuck = useGetPuck();
1469
+ const localChatId = useRef("");
1470
+ const inputRef = useRef(null);
1471
+ const pluginRef = useRef(null);
1472
+ const [error, setError] = useState();
1473
+ const [toolStatus, setToolStatus] = useState({});
1474
+ const [showSettings, setShowSettings] = useState(false);
1475
+ const [aiSettings, setAiSettings] = useAiSettings(settings == null ? void 0 : settings.storageKey);
1476
+ const aiSettingsRef = useRef(aiSettings);
1477
+ useEffect(() => {
1478
+ aiSettingsRef.current = aiSettings;
1479
+ }, [aiSettings]);
1480
+ const uploadScreenshot = useCallback(
1481
+ (width, bucketUrl) => __async(null, null, function* () {
1482
+ var _a, _b, _c;
1483
+ const iframeDocument = (_c = (_b = (_a = document == null ? void 0 : document.getElementById("preview-frame")) == null ? void 0 : _a.contentDocument) == null ? void 0 : _b.documentElement) != null ? _c : null;
1484
+ if (!iframeDocument) return;
1485
+ const canvas = yield html2canvas(iframeDocument, {
1486
+ scale: 2,
1487
+ backgroundColor: "#ffffff",
1488
+ width,
1489
+ windowWidth: width,
1490
+ foreignObjectRendering: false,
1491
+ imageTimeout: 3e4,
1492
+ logging: false,
1493
+ allowTaint: false,
1494
+ useCORS: true,
1495
+ scrollY: 0,
1496
+ ignoreElements: (el) => Array.from(el.classList).some(
1497
+ (c) => c.startsWith("_DraggableComponent--hover") || c.startsWith("_ActionBar")
1498
+ )
1499
+ });
1500
+ const image = canvas.toDataURL("image/webp", 0.8);
1501
+ const blob = yield (yield fetch(image)).blob();
1502
+ yield fetch(bucketUrl, { method: "PUT", body: blob });
1503
+ }),
1504
+ []
1505
+ );
1506
+ const processData = useCallback(
1507
+ (dataPart) => {
1508
+ switch (dataPart.type) {
1509
+ case "data-new-chat-created": {
1510
+ localChatId.current = dataPart.data.chatId;
1511
+ return;
1512
+ }
1513
+ case "data-puck-actions": {
1514
+ dataPart.data.forEach((action) => {
1515
+ try {
1516
+ puckDispatch(action);
1517
+ } catch (e) {
1518
+ console.error("Bad action: ", action);
1519
+ console.error(e);
1520
+ }
1521
+ });
1522
+ return;
1523
+ }
1524
+ case "data-build-op": {
1525
+ const data = dataPart.data;
1526
+ q.queue(() => {
1527
+ const puck = getPuck();
1528
+ if (!puck) return;
1529
+ dispatchOp(data, {
1530
+ getState: () => {
1531
+ var _a;
1532
+ return (_a = puck.__private) == null ? void 0 : _a.appState;
1533
+ },
1534
+ dispatchAction: puck.dispatch,
1535
+ config: puck.config
1536
+ });
1537
+ });
1538
+ return;
1539
+ }
1540
+ case "data-tool-status": {
1541
+ const { toolCallId, status: toolSt } = dataPart.data;
1542
+ setToolStatus((s) => __spreadProps(__spreadValues({}, s), { [toolCallId]: toolSt }));
1543
+ return;
1544
+ }
1545
+ case "data-send-screenshot": {
1546
+ const { urls } = dataPart.data;
1547
+ urls.forEach((obj) => {
1548
+ const entries = Object.entries(obj);
1549
+ if (entries.length === 0) return;
1550
+ const [key, value] = entries[0];
1551
+ const breakpoint = Number(key);
1552
+ uploadScreenshot(breakpoint, value);
1553
+ });
1554
+ return;
1555
+ }
1556
+ default:
1557
+ console.warn("dataPart without case:", dataPart);
1558
+ return;
1559
+ }
1560
+ },
1561
+ [getPuck, puckDispatch, uploadScreenshot]
1562
+ );
1563
+ const { messages, status, sendMessage, regenerate, setMessages } = useChat({
1564
+ generateId: () => prefixedUlid("msg"),
1565
+ messages: [],
1566
+ transport: new DefaultChatTransport({
1567
+ api: host,
1568
+ prepareSendMessagesRequest: (opts) => __async(null, null, function* () {
1569
+ var _a, _b, _c, _d;
1570
+ const puck = getPuck();
1571
+ const config = (_a = puck == null ? void 0 : puck.config) != null ? _a : { components: {} };
1572
+ const appState = (_b = puck == null ? void 0 : puck.appState) != null ? _b : {
1573
+ data: { root: { props: {} }, content: [], zones: {} }
1574
+ };
1575
+ const root = (_c = config.root) != null ? _c : {
1576
+ fields: {
1577
+ title: {
1578
+ type: "text",
1579
+ ai: { instructions: "The title for the page" }
1580
+ }
1581
+ }
1582
+ };
1583
+ const configWithRoot = __spreadProps(__spreadValues({}, config), { root });
1584
+ const currentSettings = aiSettingsRef.current;
1585
+ const geminiConfig = {};
1586
+ if (currentSettings.thinkingLevel !== "none")
1587
+ geminiConfig.thinkingLevel = currentSettings.thinkingLevel;
1588
+ if (currentSettings.urlContext) geminiConfig.urlContext = true;
1589
+ if (currentSettings.browserCapture) {
1590
+ geminiConfig.browserCapture = true;
1591
+ if (currentSettings.pageMigrationIr)
1592
+ geminiConfig.pageMigrationIr = true;
1593
+ }
1594
+ if (currentSettings.googleSearch) geminiConfig.googleSearch = true;
1595
+ if (currentSettings.enterpriseWebSearch)
1596
+ geminiConfig.enterpriseWebSearch = true;
1597
+ if (currentSettings.figmaToken)
1598
+ geminiConfig.figmaToken = currentSettings.figmaToken;
1599
+ const defaultBody = __spreadValues(__spreadValues(__spreadValues(__spreadProps(__spreadValues({}, opts.body), {
1600
+ chatId: localChatId.current,
1601
+ trigger: opts.trigger,
1602
+ messages: opts.messages,
1603
+ pageData: appState.data,
1604
+ config: configWithRoot
1605
+ }), Object.keys(geminiConfig).length > 0 ? { geminiConfig } : {}), targetComponentRef.current ? { selectedComponentId: targetComponentRef.current.id } : {}), pendingSendImagesRef.current.length > 0 ? (() => {
1606
+ const imgs = pendingSendImagesRef.current;
1607
+ pendingSendImagesRef.current = [];
1608
+ return { images: imgs };
1609
+ })() : {});
1610
+ const defaultOptions = {
1611
+ headers: opts.headers,
1612
+ credentials: opts.credentials,
1613
+ body: defaultBody
1614
+ };
1615
+ if (prepareRequest) {
1616
+ const userOptions = yield prepareRequest(defaultOptions);
1617
+ return {
1618
+ headers: __spreadValues(__spreadValues({}, defaultOptions.headers), userOptions.headers),
1619
+ credentials: (_d = userOptions.credentials) != null ? _d : defaultOptions.credentials,
1620
+ body: __spreadValues(__spreadValues({}, defaultBody), userOptions.body)
1621
+ };
1622
+ }
1623
+ return {
1624
+ headers: defaultOptions.headers,
1625
+ credentials: defaultOptions.credentials,
1626
+ body: defaultBody
1627
+ };
1628
+ })
1629
+ }),
1630
+ onData: processData,
1631
+ onError: (e) => {
1632
+ console.error(e);
1633
+ setError(e.message);
1634
+ },
1635
+ onFinish: () => {
1636
+ const puck = getPuck();
1637
+ if (puck == null ? void 0 : puck.appState) {
1638
+ puckDispatch({
1639
+ type: "set",
1640
+ state: puck.appState,
1641
+ recordHistory: true
1642
+ });
1643
+ }
1644
+ }
1645
+ });
1646
+ const [forcedStatus, setForcedStatus] = useState();
1647
+ const resolvedStatus = useMemo(
1648
+ () => forcedStatus != null ? forcedStatus : status,
1649
+ [status, forcedStatus]
1650
+ );
1651
+ const [promptValue, setPromptValue] = useState("");
1652
+ const [attachedImages, setAttachedImages] = useState([]);
1653
+ const pendingSendImagesRef = useRef([]);
1654
+ const [targetComponent, setTargetComponent] = useState(null);
1655
+ const targetComponentRef = useRef(null);
1656
+ useEffect(() => {
1657
+ targetComponentRef.current = targetComponent;
1658
+ }, [targetComponent]);
1659
+ useEffect(() => {
1660
+ window.__PUCK_AI = {
1661
+ processData,
1662
+ setMessages,
1663
+ setStatus: setForcedStatus,
1664
+ sendMessage,
1665
+ setPrompt: (value) => {
1666
+ var _a;
1667
+ setPromptValue(value);
1668
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1669
+ },
1670
+ setTargetComponent: (target) => {
1671
+ var _a;
1672
+ setTargetComponent(target);
1673
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1674
+ }
1675
+ };
1676
+ }, [processData, setMessages, sendMessage]);
1677
+ const handleSubmit = (prompt) => {
1678
+ const text = prompt.trim();
1679
+ if (chat == null ? void 0 : chat.onSubmit) {
1680
+ chat.onSubmit(text);
1681
+ return;
1682
+ }
1683
+ if (!text && attachedImages.length === 0) return;
1684
+ setError("");
1685
+ setPromptValue("");
1686
+ pendingSendImagesRef.current = attachedImages.map((img) => img.dataUrl);
1687
+ const fileParts = attachedImages.map(attachedImageToFileUIPart);
1688
+ setAttachedImages([]);
1689
+ const sendPayload = {};
1690
+ if (text) sendPayload.text = text;
1691
+ if (fileParts.length > 0) sendPayload.files = fileParts;
1692
+ sendMessage(sendPayload).catch((e) => {
1693
+ console.error(e);
1694
+ });
1695
+ };
1696
+ const messagesWithStatuses = useMemo(() => {
1697
+ return messages.map((msg) => __spreadProps(__spreadValues({}, msg), {
1698
+ parts: msg.parts.map((part) => {
1699
+ if ("toolCallId" in part) {
1700
+ return __spreadProps(__spreadValues({}, part), { status: toolStatus[part.toolCallId] });
1701
+ }
1702
+ return part;
1703
+ })
1704
+ }));
1705
+ }, [messages, toolStatus]);
1706
+ const handleClearChatHistory = useCallback(() => {
1707
+ if (!window.confirm("Clear all messages in this chat?")) return;
1708
+ setMessages([]);
1709
+ setToolStatus({});
1710
+ setError(void 0);
1711
+ localChatId.current = "";
1712
+ setPromptValue("");
1713
+ setAttachedImages([]);
1714
+ pendingSendImagesRef.current = [];
1715
+ setForcedStatus(void 0);
1716
+ }, [setMessages]);
1717
+ return /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat", ref: pluginRef, children: [
1718
+ /* @__PURE__ */ jsxs("div", { className: "puck-ai-chat-header", children: [
1719
+ showSettings && /* @__PURE__ */ jsx(
1720
+ "button",
1721
+ {
1722
+ className: "puck-ai-icon-button",
1723
+ onClick: () => setShowSettings(false),
1724
+ title: "Back to chat",
1725
+ type: "button",
1726
+ children: /* @__PURE__ */ jsx(ArrowLeft, { size: 16 })
1727
+ }
1728
+ ),
1729
+ /* @__PURE__ */ jsx("span", { className: "puck-ai-chat-header-title", children: showSettings ? "Settings" : "AI page builder" }),
1730
+ !showSettings && /* @__PURE__ */ jsx(
1731
+ "button",
1732
+ {
1733
+ className: "puck-ai-icon-button",
1734
+ onClick: () => setShowSettings(true),
1735
+ title: "Settings",
1736
+ type: "button",
1737
+ children: /* @__PURE__ */ jsx(Settings, { size: 16 })
1738
+ }
1739
+ )
1740
+ ] }),
1741
+ showSettings ? /* @__PURE__ */ jsx(
1742
+ SettingsPanel,
1743
+ {
1744
+ settings: aiSettings,
1745
+ onChange: setAiSettings,
1746
+ onClearChatHistory: handleClearChatHistory,
1747
+ hasChatMessages: messages.length > 0
1748
+ }
1749
+ ) : /* @__PURE__ */ jsx(ToolStatusProvider, { value: toolStatus, children: /* @__PURE__ */ jsx(
1750
+ ChatBody,
1751
+ {
1752
+ messages: messagesWithStatuses,
1753
+ handleSubmit,
1754
+ inputRef,
1755
+ status: resolvedStatus,
1756
+ examplePrompts: examplePrompts == null ? void 0 : examplePrompts.map(({ label, href, onClick }) => /* @__PURE__ */ jsx(
1757
+ ExamplePrompt,
1758
+ {
1759
+ label,
1760
+ href,
1761
+ onClick
1762
+ },
1763
+ label
1764
+ )),
1765
+ error,
1766
+ handleRetry: () => {
1767
+ setError("");
1768
+ regenerate();
1769
+ },
1770
+ promptValue,
1771
+ targetComponent,
1772
+ onClearTarget: () => setTargetComponent(null),
1773
+ images: attachedImages,
1774
+ onImagesChange: setAttachedImages,
1775
+ children: /* @__PURE__ */ jsx(
1776
+ Placeholder,
1777
+ {
1778
+ dispatch: puckDispatch,
1779
+ inputRef,
1780
+ pluginRef
1781
+ }
1782
+ )
1783
+ }
1784
+ ) })
1785
+ ] });
1786
+ }
1787
+ function createAiPlugin(opts = {}) {
1788
+ const { scrollTracking = true, host, chat, prepareRequest, settings } = opts;
1789
+ return {
1790
+ label: "AI",
1791
+ name: "ai",
1792
+ icon: /* @__PURE__ */ jsx(Bot, {}),
1793
+ mobilePanelHeight: "min-content",
1794
+ render: () => /* @__PURE__ */ jsx(
1795
+ Chat,
1796
+ {
1797
+ host,
1798
+ chat,
1799
+ prepareRequest,
1800
+ settings
1801
+ }
1802
+ ),
1803
+ overrides: {
1804
+ preview: ({ children }) => {
1805
+ if (scrollTracking) {
1806
+ return /* @__PURE__ */ jsx(ScrollTracking, { children });
1807
+ }
1808
+ return /* @__PURE__ */ jsx(Fragment, { children });
1809
+ }
1810
+ }
1811
+ };
1812
+ }
1813
+ var index_default = createAiPlugin;
1814
+ export {
1815
+ Chat,
1816
+ createAiPlugin,
1817
+ index_default as default
1818
+ };
1819
+ /*! Bundled license information:
1820
+
1821
+ lucide-react/dist/esm/shared/src/utils.js:
1822
+ lucide-react/dist/esm/defaultAttributes.js:
1823
+ lucide-react/dist/esm/Icon.js:
1824
+ lucide-react/dist/esm/createLucideIcon.js:
1825
+ lucide-react/dist/esm/icons/arrow-left.js:
1826
+ lucide-react/dist/esm/icons/arrow-up.js:
1827
+ lucide-react/dist/esm/icons/bot.js:
1828
+ lucide-react/dist/esm/icons/check.js:
1829
+ lucide-react/dist/esm/icons/eye-off.js:
1830
+ lucide-react/dist/esm/icons/eye.js:
1831
+ lucide-react/dist/esm/icons/image.js:
1832
+ lucide-react/dist/esm/icons/rotate-ccw.js:
1833
+ lucide-react/dist/esm/icons/settings.js:
1834
+ lucide-react/dist/esm/icons/trash-2.js:
1835
+ lucide-react/dist/esm/icons/triangle-alert.js:
1836
+ lucide-react/dist/esm/icons/wrench.js:
1837
+ lucide-react/dist/esm/icons/x.js:
1838
+ lucide-react/dist/esm/lucide-react.js:
1839
+ (**
1840
+ * @license lucide-react v0.452.0 - ISC
1841
+ *
1842
+ * This source code is licensed under the ISC license.
1843
+ * See the LICENSE file in the root directory of this source tree.
1844
+ *)
1845
+ */
1846
+ //# sourceMappingURL=index.mjs.map