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