pptx-vue-viewer 2.13.0 → 2.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/AiChatPanel-BrBpOZ6I.js +512 -0
  3. package/dist/AiChatPanel-BrBpOZ6I.js.br +0 -0
  4. package/dist/AiChatPanel-BrBpOZ6I.js.gz +0 -0
  5. package/dist/{AiChatPanel-B8Ql84M5.cjs → AiChatPanel-BwSXWqtI.cjs} +143 -139
  6. package/dist/AiChatPanel-BwSXWqtI.cjs.br +0 -0
  7. package/dist/AiChatPanel-BwSXWqtI.cjs.gz +0 -0
  8. package/dist/{dist-CkupeMQB.js → dist-CcMjaS0l.js} +6220 -6196
  9. package/dist/dist-CcMjaS0l.js.br +0 -0
  10. package/dist/dist-CcMjaS0l.js.gz +0 -0
  11. package/dist/{dist-Pa1hVhzE.cjs → dist-rj7824xi.cjs} +6318 -6294
  12. package/dist/dist-rj7824xi.cjs.br +0 -0
  13. package/dist/dist-rj7824xi.cjs.gz +0 -0
  14. package/dist/gif-encoder-BxFd8hxi.js +2 -0
  15. package/dist/gif-encoder-BxFd8hxi.js.br +0 -0
  16. package/dist/gif-encoder-BxFd8hxi.js.gz +0 -0
  17. package/dist/gif-encoder-DkZQBZC6.cjs +2 -0
  18. package/dist/gif-encoder-DkZQBZC6.cjs.br +0 -0
  19. package/dist/gif-encoder-DkZQBZC6.cjs.gz +0 -0
  20. package/dist/index.cjs +1 -1
  21. package/dist/index.cjs.br +0 -0
  22. package/dist/index.cjs.gz +0 -0
  23. package/dist/index.js +3 -3
  24. package/dist/index.js.br +0 -0
  25. package/dist/index.js.gz +0 -0
  26. package/dist/internals.cjs +1 -1
  27. package/dist/internals.cjs.br +0 -0
  28. package/dist/internals.cjs.gz +0 -0
  29. package/dist/internals.js +2 -2
  30. package/dist/internals.js.br +0 -0
  31. package/dist/internals.js.gz +0 -0
  32. package/dist/{useViewerSettingsDialog-B-QhCt02.js → useViewerSettingsDialog-BtNzKvoP.js} +2547 -2491
  33. package/dist/useViewerSettingsDialog-BtNzKvoP.js.br +0 -0
  34. package/dist/useViewerSettingsDialog-BtNzKvoP.js.gz +0 -0
  35. package/dist/{useViewerSettingsDialog-CY1t9MEH.cjs → useViewerSettingsDialog-Df32STpE.cjs} +2883 -2812
  36. package/dist/useViewerSettingsDialog-Df32STpE.cjs.br +0 -0
  37. package/dist/useViewerSettingsDialog-Df32STpE.cjs.gz +0 -0
  38. package/dist/viewer/components/ElementMediaBox.vue.d.ts.map +1 -1
  39. package/dist/viewer/components/PresentationMode.vue.d.ts.map +1 -1
  40. package/dist/viewer/components/ai/AiChatPanel.vue.d.ts.map +1 -1
  41. package/dist/viewer/components/ai/AiConversation.vue.d.ts.map +1 -1
  42. package/dist/viewer/composables/ai/useAiConversation.d.ts +3 -1
  43. package/dist/viewer/composables/ai/useAiConversation.d.ts.map +1 -1
  44. package/dist/viewer/composables/cross-slide-audio.d.ts +12 -0
  45. package/dist/viewer/composables/cross-slide-audio.d.ts.map +1 -0
  46. package/dist/viewer/composables/usePresentationVisibilityPause.d.ts +11 -0
  47. package/dist/viewer/composables/usePresentationVisibilityPause.d.ts.map +1 -0
  48. package/dist/viewer/composables/useSlideAutoAdvance.d.ts +7 -0
  49. package/dist/viewer/composables/useSlideAutoAdvance.d.ts.map +1 -1
  50. package/dist/viewer/index.cjs +1 -1
  51. package/dist/viewer/index.cjs.br +0 -0
  52. package/dist/viewer/index.cjs.gz +0 -0
  53. package/dist/viewer/index.js +3 -3
  54. package/dist/viewer/index.js.br +0 -0
  55. package/dist/viewer/index.js.gz +0 -0
  56. package/dist/{viewer-Bq3ngZeA.js → viewer-BYs8-awK.js} +9387 -9360
  57. package/dist/viewer-BYs8-awK.js.br +0 -0
  58. package/dist/viewer-BYs8-awK.js.gz +0 -0
  59. package/dist/{viewer-SRdb6B8w.cjs → viewer-Dn2_atkd.cjs} +5448 -5421
  60. package/dist/viewer-Dn2_atkd.cjs.br +0 -0
  61. package/dist/viewer-Dn2_atkd.cjs.gz +0 -0
  62. package/package.json +2 -2
  63. package/dist/AiChatPanel-B8Ql84M5.cjs.br +0 -0
  64. package/dist/AiChatPanel-B8Ql84M5.cjs.gz +0 -0
  65. package/dist/AiChatPanel-Pd17JAHM.js +0 -509
  66. package/dist/AiChatPanel-Pd17JAHM.js.br +0 -0
  67. package/dist/AiChatPanel-Pd17JAHM.js.gz +0 -0
  68. package/dist/dist-CkupeMQB.js.br +0 -0
  69. package/dist/dist-CkupeMQB.js.gz +0 -0
  70. package/dist/dist-Pa1hVhzE.cjs.br +0 -0
  71. package/dist/dist-Pa1hVhzE.cjs.gz +0 -0
  72. package/dist/gif-encoder-BclZ9xjR.cjs +0 -2
  73. package/dist/gif-encoder-BclZ9xjR.cjs.br +0 -0
  74. package/dist/gif-encoder-BclZ9xjR.cjs.gz +0 -0
  75. package/dist/gif-encoder-DNWK0lM2.js +0 -2
  76. package/dist/gif-encoder-DNWK0lM2.js.br +0 -0
  77. package/dist/gif-encoder-DNWK0lM2.js.gz +0 -0
  78. package/dist/useViewerSettingsDialog-B-QhCt02.js.br +0 -0
  79. package/dist/useViewerSettingsDialog-B-QhCt02.js.gz +0 -0
  80. package/dist/useViewerSettingsDialog-CY1t9MEH.cjs.br +0 -0
  81. package/dist/useViewerSettingsDialog-CY1t9MEH.cjs.gz +0 -0
  82. package/dist/viewer-Bq3ngZeA.js.br +0 -0
  83. package/dist/viewer-Bq3ngZeA.js.gz +0 -0
  84. package/dist/viewer-SRdb6B8w.cjs.br +0 -0
  85. package/dist/viewer-SRdb6B8w.cjs.gz +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,8 @@ All notable changes to this project are documented here.
4
4
  This file is generated from [Conventional Commits](https://www.conventionalcommits.org)
5
5
  by [git-cliff](https://git-cliff.org); do not edit it by hand.
6
6
 
7
+ ## [2.13.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-vue-viewer@2.13.0) - 2026-08-01
8
+
7
9
  ## [2.12.1](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-vue-viewer@2.12.1) - 2026-08-01
8
10
 
9
11
  ## [2.12.0](https://github.com/ChristopherVR/pptx-viewer/releases/tag/pptx-vue-viewer@2.12.0) - 2026-08-01
@@ -0,0 +1,512 @@
1
+ import { hn as e } from "./useViewerSettingsDialog-BtNzKvoP.js";
2
+ import { S as t, _ as a, c as r, f as s, g as l, h as o, m as i, o as n, p, s as d, v as c, y as u } from "./viewer-BYs8-awK.js";
3
+ import { Fragment as m, Suspense as x, computed as g, createBlock as f, createCommentVNode as b, createElementBlock as v, createElementVNode as y, createTextVNode as h, createVNode as k, defineComponent as w, nextTick as P, normalizeClass as C, normalizeStyle as S, onBeforeUnmount as T, openBlock as I, ref as _, renderList as A, resolveDynamicComponent as j, shallowRef as E, toDisplayString as F, unref as B, vModelText as M, watch as D, withAsyncContext as N, withCtx as R, withDirectives as W } from "vue";
4
+ import { Bot as $, ChartColumn as H, Check as V, Crosshair as z, Eye as K, Film as L, GitMerge as O, LayoutTemplate as U, LoaderCircle as q, Move as G, Navigation as J, Palette as Q, Pin as X, PinOff as Y, Search as Z, Send as ee, Shapes as te, Sparkles as ae, Square as re, StickyNote as se, Table as le, Trash2 as oe, TriangleAlert as ie, Type as ne, User as pe, Wrench as de, X as ce } from "lucide-vue-next";
5
+ import { getToolOrDynamicToolName as ue, isDynamicToolUIPart as me, isToolUIPart as xe } from "ai";
6
+ var ge = /* @__PURE__ */ new Set([
7
+ "input-available",
8
+ "output-available",
9
+ "output-error"
10
+ ]);
11
+ function fe(e, t, a, r = {}) {
12
+ const s = _(t.proposals.list()), l = () => {
13
+ s.value = t.proposals.list();
14
+ }, o = e({
15
+ transport: t.transport,
16
+ sendAutomaticallyWhen: t.sendAutomaticallyWhen,
17
+ onError: (e) => a.onError?.(e),
18
+ onToolCall: async ({ toolCall: e }) => {
19
+ const { toolName: a, toolCallId: r, input: s } = e, i = o.addToolOutput;
20
+ try {
21
+ i({
22
+ tool: a,
23
+ toolCallId: r,
24
+ output: await t.executeToolCall(a, s)
25
+ });
26
+ } catch (e) {
27
+ i({
28
+ tool: a,
29
+ toolCallId: r,
30
+ state: "output-error",
31
+ errorText: e instanceof Error ? e.message : String(e)
32
+ });
33
+ }
34
+ l();
35
+ }
36
+ }), i = g(() => "submitted" === o.status.value || "streaming" === o.status.value), n = /* @__PURE__ */ new Set();
37
+ D(o.messages, (e) => {
38
+ for (const t of function(e) {
39
+ const t = [];
40
+ for (const a of e) for (const e of a.parts) {
41
+ if (!xe(e) && !me(e)) continue;
42
+ const a = e, r = a.toolCallId ?? "";
43
+ 0 !== r.length && void 0 !== a.input && ge.has(a.state ?? "") && t.push({
44
+ toolName: ue(e),
45
+ toolCallId: r,
46
+ input: a.input
47
+ });
48
+ }
49
+ return t;
50
+ }(e)) n.has(t.toolCallId) || (n.add(t.toolCallId), r.onToolTarget?.(c(t.toolName, t.input)));
51
+ }, { deep: !0 });
52
+ return {
53
+ messages: o.messages,
54
+ status: o.status,
55
+ error: o.error,
56
+ isStreaming: i,
57
+ proposals: s,
58
+ send: (e) => {
59
+ const t = e.trim();
60
+ 0 !== t.length && o.sendMessage({ text: t });
61
+ },
62
+ stop: () => {
63
+ o.stop();
64
+ },
65
+ clearError: () => o.clearError(),
66
+ applyProposal: (e) => {
67
+ t.proposals.apply(e), l();
68
+ },
69
+ rejectProposal: (e) => {
70
+ t.proposals.revert(e), l();
71
+ },
72
+ acceptAllProposals: () => {
73
+ t.proposals.acceptAll(), l();
74
+ }
75
+ };
76
+ }
77
+ var be = { class: "border-t border-border p-2" }, ve = { class: "flex items-end gap-1.5 rounded-md border border-input bg-background px-2 py-1.5 focus-within:border-ring" }, ye = ["placeholder", "aria-label"], he = ["title", "aria-label"], ke = [
78
+ "disabled",
79
+ "title",
80
+ "aria-label"
81
+ ], we = w({
82
+ __name: "AiComposer",
83
+ props: {
84
+ isStreaming: { type: Boolean },
85
+ prefillText: {},
86
+ prefillNonce: {}
87
+ },
88
+ emits: ["send", "stop"],
89
+ setup(a, { emit: r }) {
90
+ const s = a, l = r, { t: o } = e(), i = _(""), n = _(null), p = g(() => i.value.trim().length > 0);
91
+ function d() {
92
+ const e = i.value.trim();
93
+ 0 === e.length || s.isStreaming || (l("send", e), i.value = "");
94
+ }
95
+ function c(e) {
96
+ "Enter" !== e.key || e.shiftKey || (e.preventDefault(), d());
97
+ }
98
+ return D(() => s.prefillNonce, (e) => {
99
+ void 0 !== e && 0 !== e && (s.prefillText && (i.value = s.prefillText), P(() => n.value?.focus()));
100
+ }), (e, a) => (I(), v("div", be, [y("div", ve, [W(y("textarea", {
101
+ ref_key: "textareaRef",
102
+ ref: n,
103
+ "onUpdate:modelValue": a[0] || (a[0] = (e) => i.value = e),
104
+ rows: 1,
105
+ placeholder: B(o)("pptx.ai.placeholder"),
106
+ "aria-label": B(o)("pptx.ai.placeholder"),
107
+ class: "max-h-32 min-h-[1.5rem] flex-1 resize-none bg-transparent text-[13px] text-foreground outline-none placeholder:text-muted-foreground",
108
+ onKeydown: c
109
+ }, null, 40, ye), [[M, i.value]]), s.isStreaming ? (I(), v("button", {
110
+ key: 0,
111
+ type: "button",
112
+ title: B(o)("pptx.ai.stop"),
113
+ "aria-label": B(o)("pptx.ai.stop"),
114
+ class: "shrink-0 rounded-sm p-1.5 text-muted-foreground transition-colors hover:bg-accent",
115
+ onClick: a[1] || (a[1] = (e) => l("stop"))
116
+ }, [k(B(re), { class: "w-4 h-4" })], 8, he)) : (I(), v("button", {
117
+ key: 1,
118
+ type: "button",
119
+ disabled: !p.value,
120
+ title: B(o)("pptx.ai.send"),
121
+ "aria-label": B(o)("pptx.ai.send"),
122
+ class: C(B(t)("shrink-0 rounded-sm p-1.5 transition-colors", p.value ? "bg-primary text-primary-foreground hover:bg-primary/90" : "text-muted-foreground/50")),
123
+ onClick: d
124
+ }, [k(B(ee), { class: "w-4 h-4" })], 10, ke))])]));
125
+ }
126
+ }), Pe = { class: "border-b border-border bg-secondary/30" }, Ce = { class: "flex flex-wrap items-center gap-1 px-2.5 py-1.5" }, Se = { class: "text-[10px] font-semibold uppercase tracking-wide text-muted-foreground" }, Te = ["title"], Ie = { class: "truncate" }, _e = {
127
+ key: 0,
128
+ class: "rounded-full bg-primary/15 px-1.5 py-0.5 text-[10px] font-medium text-primary"
129
+ }, Ae = { class: "ml-auto flex items-center gap-0.5" }, je = [
130
+ "title",
131
+ "aria-label",
132
+ "aria-pressed"
133
+ ], Ee = ["title", "aria-label"], Fe = ["title", "aria-label"], Be = {
134
+ key: 0,
135
+ class: "flex items-center gap-2 border-t border-primary/20 bg-primary/5 px-2.5 py-1"
136
+ }, Me = { class: "text-[11px] font-medium text-primary" }, De = w({
137
+ __name: "AiFocusBar",
138
+ props: {
139
+ targets: {},
140
+ slides: {},
141
+ isPinned: { type: Boolean },
142
+ pickMode: { type: Boolean },
143
+ hasPicks: { type: Boolean }
144
+ },
145
+ emits: [
146
+ "pin",
147
+ "clear-pin",
148
+ "start-pick",
149
+ "stop-pick",
150
+ "clear-picks",
151
+ "send-directive"
152
+ ],
153
+ setup(a, { emit: s }) {
154
+ const l = a, o = s, { t: i } = e(), n = g(() => d(l.targets, l.slides)), p = g(() => r(l.targets, l.slides));
155
+ function c() {
156
+ const e = p.value;
157
+ e && o("send-directive", `Merge the two selected tables (elementIdA=${e.elementIdA}, elementIdB=${e.elementIdB}) on slide ${e.slideIndex + 1} using merge_tables; stage it now, do not ask me to confirm.`);
158
+ }
159
+ return (e, r) => (I(), v("div", Pe, [y("div", Ce, [
160
+ y("span", Se, F(B(i)("pptx.ai.focusScope")), 1),
161
+ (I(!0), v(m, null, A(n.value, (e) => (I(), v("span", {
162
+ key: e.key,
163
+ class: C(B(t)("inline-flex max-w-[10rem] items-center rounded-full px-2 py-0.5 text-[11px]", a.hasPicks || a.isPinned ? "bg-primary/15 text-primary" : "bg-muted text-muted-foreground")),
164
+ title: e.title
165
+ }, [y("span", Ie, F(e.label), 1)], 10, Te))), 128)),
166
+ a.isPinned ? (I(), v("span", _e, F(B(i)("pptx.ai.pinnedFocus")), 1)) : b("", !0),
167
+ y("div", Ae, [
168
+ p.value ? (I(), v("button", {
169
+ key: 0,
170
+ type: "button",
171
+ class: "inline-flex items-center gap-1 rounded-sm bg-primary/90 px-1.5 py-0.5 text-[11px] font-medium text-primary-foreground hover:bg-primary",
172
+ onClick: c
173
+ }, [k(B(O), { class: "w-3 h-3" }), h(" " + F(B(i)("pptx.ai.mergeSelectedTables")), 1)])) : b("", !0),
174
+ y("button", {
175
+ type: "button",
176
+ title: B(i)("pptx.ai.pickElement"),
177
+ "aria-label": B(i)("pptx.ai.pickAria"),
178
+ "aria-pressed": a.pickMode,
179
+ class: C(B(t)("rounded-sm p-1", a.pickMode ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent")),
180
+ onClick: r[0] || (r[0] = (e) => a.pickMode ? o("stop-pick") : o("start-pick"))
181
+ }, [k(B(z), { class: "w-3.5 h-3.5" })], 10, je),
182
+ a.hasPicks ? (I(), v("button", {
183
+ key: 1,
184
+ type: "button",
185
+ title: B(i)("pptx.ai.pickClear"),
186
+ "aria-label": B(i)("pptx.ai.pickClear"),
187
+ class: "rounded-sm p-1 text-muted-foreground hover:bg-accent",
188
+ onClick: r[1] || (r[1] = (e) => o("clear-picks"))
189
+ }, [k(B(ce), { class: "w-3.5 h-3.5" })], 8, Ee)) : (I(), v("button", {
190
+ key: 2,
191
+ type: "button",
192
+ title: a.isPinned ? B(i)("pptx.ai.clearFocus") : B(i)("pptx.ai.pinFocus"),
193
+ "aria-label": a.isPinned ? B(i)("pptx.ai.clearFocus") : B(i)("pptx.ai.pinFocus"),
194
+ class: "rounded-sm p-1 text-muted-foreground hover:bg-accent",
195
+ onClick: r[2] || (r[2] = (e) => a.isPinned ? o("clear-pin") : o("pin"))
196
+ }, [a.isPinned ? (I(), f(B(Y), {
197
+ key: 0,
198
+ class: "w-3.5 h-3.5"
199
+ })) : (I(), f(B(X), {
200
+ key: 1,
201
+ class: "w-3.5 h-3.5"
202
+ }))], 8, Fe))
203
+ ])
204
+ ]), a.pickMode ? (I(), v("div", Be, [
205
+ k(B(z), { class: "w-3.5 h-3.5 shrink-0 animate-pulse text-primary" }),
206
+ y("span", Me, F(B(i)("pptx.ai.pickElementHint")), 1),
207
+ y("button", {
208
+ type: "button",
209
+ class: "ml-auto rounded-sm bg-primary px-2 py-0.5 text-[11px] font-medium text-primary-foreground hover:bg-primary/90",
210
+ onClick: r[3] || (r[3] = (e) => o("stop-pick"))
211
+ }, F(B(i)("pptx.ai.pickDone")), 1)
212
+ ])) : b("", !0)]));
213
+ }
214
+ }), Ne = { class: "text-[12px]" }, Re = { class: "flex items-center gap-1.5" }, We = {
215
+ key: 0,
216
+ class: "mt-1 pl-5 text-[11px] text-destructive"
217
+ }, $e = {
218
+ key: 1,
219
+ class: "group mt-0.5 pl-5"
220
+ }, He = { class: "cursor-pointer list-none text-[10px] text-muted-foreground/70 hover:text-muted-foreground" }, Ve = { class: "mt-0.5 break-words font-mono text-[10px] text-muted-foreground/80" }, ze = w({
221
+ __name: "AiToolCallCard",
222
+ props: { part: {} },
223
+ setup(a) {
224
+ const r = a, { t: s } = e(), o = {
225
+ view: K,
226
+ text: ne,
227
+ shape: te,
228
+ theme: Q,
229
+ table: le,
230
+ slide: U,
231
+ chart: H,
232
+ move: G,
233
+ delete: oe,
234
+ search: Z,
235
+ nav: J,
236
+ animation: L,
237
+ notes: se,
238
+ tool: de
239
+ }, i = g(() => "output-error" === r.part.state), n = g(() => "output-available" === r.part.state), d = g(() => !i.value && !n.value), c = g(() => p(r.part.toolName, r.part.input, d.value ? "present" : "past")), m = g(() => o[c.value.icon] ?? de), x = g(() => l(r.part.input)), k = g(() => i.value ? s("pptx.ai.toolFailed") : n.value ? s("pptx.ai.toolDone") : s("pptx.ai.toolRunning"));
240
+ return (e, a) => (I(), v("div", Ne, [
241
+ y("div", Re, [
242
+ (I(), f(j(m.value), { class: C(B(t)("w-3.5 h-3.5 shrink-0", i.value ? "text-destructive" : "text-muted-foreground")) }, null, 8, ["class"])),
243
+ y("span", { class: C(B(t)("truncate", i.value ? "text-destructive" : "text-foreground")) }, F(c.value.label), 3),
244
+ y("span", { class: C(B(t)("ml-auto inline-flex items-center gap-1 rounded-sm px-1.5 py-0.5 text-[10px]", i.value ? "bg-destructive/15 text-destructive" : n.value ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground")) }, [d.value ? (I(), f(B(q), {
245
+ key: 0,
246
+ class: "w-3 h-3 animate-spin"
247
+ })) : n.value ? (I(), f(B(V), {
248
+ key: 1,
249
+ class: "w-3 h-3"
250
+ })) : (I(), f(B(ie), {
251
+ key: 2,
252
+ class: "w-3 h-3"
253
+ })), h(" " + F(k.value), 1)], 2)
254
+ ]),
255
+ i.value && r.part.errorText ? (I(), v("div", We, F(r.part.errorText), 1)) : b("", !0),
256
+ x.value ? (I(), v("details", $e, [y("summary", He, F(B(s)("pptx.ai.toolDetails")), 1), y("div", Ve, F(B(u)(r.part.toolName)) + ": " + F(x.value), 1)])) : b("", !0)
257
+ ]));
258
+ }
259
+ }), Ke = {
260
+ key: 0,
261
+ class: "flex flex-1 flex-col items-center justify-center gap-2 px-6 text-center"
262
+ }, Le = { class: "text-sm font-medium text-foreground" }, Oe = { class: "text-[12px] text-muted-foreground" }, Ue = {
263
+ key: 1,
264
+ class: "flex-1 space-y-3 overflow-y-auto px-3 py-3"
265
+ }, qe = {
266
+ key: 0,
267
+ class: "flex gap-2"
268
+ }, Ge = ["aria-label"], Je = { class: "min-w-0 flex-1 space-y-1.5" }, Qe = {
269
+ key: 0,
270
+ class: "whitespace-pre-wrap break-words text-[13px] leading-relaxed text-foreground"
271
+ }, Xe = {
272
+ key: 0,
273
+ class: "flex items-center gap-2 pl-8 text-[12px] text-muted-foreground"
274
+ }, Ye = w({
275
+ __name: "AiMessageList",
276
+ props: {
277
+ messages: {},
278
+ isStreaming: { type: Boolean }
279
+ },
280
+ setup(r) {
281
+ const s = r, { t: l } = e(), o = _(null);
282
+ return D(() => [s.messages, s.isStreaming], () => {
283
+ P(() => o.value?.scrollIntoView({ block: "end" }));
284
+ }, { deep: !0 }), (e, r) => 0 === s.messages.length ? (I(), v("div", Ke, [
285
+ k(B(ae), { class: "w-7 h-7 text-primary/70" }),
286
+ y("p", Le, F(B(l)("pptx.ai.emptyTitle")), 1),
287
+ y("p", Oe, F(B(l)("pptx.ai.emptyHint")), 1)
288
+ ])) : (I(), v("div", Ue, [
289
+ (I(!0), v(m, null, A(s.messages, (e) => (I(), v(m, { key: e.id }, ["user" === e.role || B(a)(e).length > 0 ? (I(), v("div", qe, [y("div", {
290
+ class: C(B(t)("mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full", "user" === e.role ? "bg-secondary text-muted-foreground" : "bg-primary/15 text-primary")),
291
+ "aria-label": "user" === e.role ? B(l)("pptx.ai.you") : B(l)("pptx.ai.assistant")
292
+ }, ["user" === e.role ? (I(), f(B(pe), {
293
+ key: 0,
294
+ class: "w-3.5 h-3.5"
295
+ })) : (I(), f(B($), {
296
+ key: 1,
297
+ class: "w-3.5 h-3.5"
298
+ }))], 10, Ge), y("div", Je, [(I(!0), v(m, null, A(B(a)(e), (e, t) => (I(), v(m, { key: "tool" === e.kind && e.toolCallId || t }, ["text" === e.kind ? (I(), v("p", Qe, F(e.text), 1)) : (I(), f(ze, {
299
+ key: 1,
300
+ part: e
301
+ }, null, 8, ["part"]))], 64))), 128))])])) : b("", !0)], 64))), 128)),
302
+ s.isStreaming ? (I(), v("div", Xe, [r[0] || (r[0] = y("span", { class: "inline-flex gap-1" }, [
303
+ y("span", { class: "h-1.5 w-1.5 animate-bounce rounded-full bg-muted-foreground [animation-delay:-0.2s]" }),
304
+ y("span", { class: "h-1.5 w-1.5 animate-bounce rounded-full bg-muted-foreground [animation-delay:-0.1s]" }),
305
+ y("span", { class: "h-1.5 w-1.5 animate-bounce rounded-full bg-muted-foreground" })
306
+ ], -1)), h(" " + F(B(l)("pptx.ai.thinking")), 1)])) : b("", !0),
307
+ y("div", {
308
+ ref_key: "endRef",
309
+ ref: o
310
+ }, null, 512)
311
+ ]));
312
+ }
313
+ }), Ze = { class: "rounded-md border border-primary/40 bg-primary/5 p-2.5" }, et = { class: "mb-1.5 text-[11px] font-semibold uppercase tracking-wide text-primary" }, tt = { class: "text-[12px] font-medium text-foreground" }, at = {
314
+ key: 0,
315
+ class: "mt-1 max-h-40 space-y-0.5 overflow-y-auto text-[11px] text-muted-foreground"
316
+ }, rt = { class: "mt-2 flex items-center gap-2" }, st = w({
317
+ __name: "AiProposalCard",
318
+ props: { proposal: {} },
319
+ emits: ["accept", "reject"],
320
+ setup(t, { emit: a }) {
321
+ const r = t, s = a, { t: l } = e(), o = g(() => r.proposal.summary.map(i));
322
+ return (e, t) => (I(), v("div", Ze, [
323
+ y("div", et, F(B(l)("pptx.ai.proposedChange")), 1),
324
+ y("div", tt, F(r.proposal.label), 1),
325
+ o.value.length > 0 ? (I(), v("ul", at, [(I(!0), v(m, null, A(o.value, (e, t) => (I(), v("li", {
326
+ key: t,
327
+ class: "break-words"
328
+ }, F(e), 1))), 128))])) : b("", !0),
329
+ y("div", rt, [y("button", {
330
+ type: "button",
331
+ class: "inline-flex items-center gap-1 rounded-sm bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground transition-colors hover:bg-primary/90",
332
+ onClick: t[0] || (t[0] = (e) => s("accept", r.proposal.id))
333
+ }, [k(B(V), { class: "w-3.5 h-3.5" }), h(" " + F(B(l)("pptx.ai.accept")), 1)]), y("button", {
334
+ type: "button",
335
+ class: "inline-flex items-center gap-1 rounded-sm border border-border px-2 py-1 text-[11px] text-muted-foreground transition-colors hover:bg-accent",
336
+ onClick: t[1] || (t[1] = (e) => s("reject", r.proposal.id))
337
+ }, [k(B(ce), { class: "w-3.5 h-3.5" }), h(" " + F(B(l)("pptx.ai.reject")), 1)])])
338
+ ]));
339
+ }
340
+ }), lt = { class: "flex min-h-0 flex-1 flex-col" }, ot = {
341
+ key: 0,
342
+ class: "mx-3 mb-2 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-2.5 py-1.5 text-[12px] text-destructive"
343
+ }, it = { class: "min-w-0 flex-1" }, nt = { class: "font-medium" }, pt = { class: "max-h-24 overflow-y-auto break-words text-[11px] opacity-80" }, dt = {
344
+ key: 1,
345
+ class: "max-h-[38%] space-y-2 overflow-y-auto border-t border-border bg-background px-3 py-2"
346
+ }, ct = { class: "flex items-center justify-between" }, ut = { class: "text-[11px] font-semibold uppercase tracking-wide text-muted-foreground" }, mt = w({
347
+ __name: "AiConversation",
348
+ props: {
349
+ session: {},
350
+ config: {},
351
+ bridge: {},
352
+ aiPanel: {}
353
+ },
354
+ async setup(t) {
355
+ let a, r;
356
+ const s = t, { t: l } = e(), { useChat: o } = ([a, r] = N(() => import("@ai-sdk/vue")), a = await a, r(), a), { messages: i, error: n, isStreaming: p, proposals: d, send: c, stop: u, clearError: x, applyProposal: h, rejectProposal: w, acceptAllProposals: P } = fe(o, s.session, s.config, { onToolTarget: (e) => {
357
+ e && void 0 !== e.slideIndex && s.bridge.goToSlide(e.slideIndex), s.aiPanel.flashToolTarget(e);
358
+ } }), C = s.session.changeAnimator.subscribe((e) => {
359
+ e && s.bridge.goToSlide(e.slideIndex), s.aiPanel.showChangeBatch(e);
360
+ });
361
+ T(() => C());
362
+ const S = g(() => s.aiPanel.pickTargets.value.length > 0), _ = g(() => S.value ? s.aiPanel.pickTargets.value : s.aiPanel.pinnedFocus.value ?? s.aiPanel.liveFocusTargets.value), j = g(() => !S.value && null !== s.aiPanel.pinnedFocus.value);
363
+ function E(e) {
364
+ s.aiPanel.flashToolTarget(null), h(e);
365
+ }
366
+ function M() {
367
+ s.aiPanel.flashToolTarget(null), P();
368
+ }
369
+ return (e, t) => (I(), v("div", lt, [
370
+ k(De, {
371
+ targets: _.value,
372
+ slides: s.bridge.getSlides(),
373
+ "is-pinned": j.value,
374
+ "pick-mode": s.aiPanel.pickMode.value,
375
+ "has-picks": S.value,
376
+ onPin: s.aiPanel.pinFocus,
377
+ onClearPin: s.aiPanel.clearPinnedFocus,
378
+ onStartPick: s.aiPanel.startPicking,
379
+ onStopPick: s.aiPanel.stopPicking,
380
+ onClearPicks: s.aiPanel.clearPicks,
381
+ onSendDirective: B(c)
382
+ }, null, 8, [
383
+ "targets",
384
+ "slides",
385
+ "is-pinned",
386
+ "pick-mode",
387
+ "has-picks",
388
+ "onPin",
389
+ "onClearPin",
390
+ "onStartPick",
391
+ "onStopPick",
392
+ "onClearPicks",
393
+ "onSendDirective"
394
+ ]),
395
+ k(Ye, {
396
+ messages: B(i),
397
+ "is-streaming": B(p)
398
+ }, null, 8, ["messages", "is-streaming"]),
399
+ B(n) ? (I(), v("div", ot, [
400
+ k(B(ie), { class: "mt-0.5 w-3.5 h-3.5 shrink-0" }),
401
+ y("div", it, [y("div", nt, F(B(l)("pptx.ai.errorPrefix")), 1), y("div", pt, F(B(n).message), 1)]),
402
+ y("button", {
403
+ type: "button",
404
+ class: "shrink-0 rounded-sm px-1.5 py-0.5 text-[11px] underline-offset-2 hover:underline",
405
+ onClick: t[0] || (t[0] = (...e) => B(x) && B(x)(...e))
406
+ }, F(B(l)("pptx.ai.retry")), 1)
407
+ ])) : b("", !0),
408
+ B(d).length > 0 ? (I(), v("div", dt, [y("div", ct, [y("span", ut, F(B(l)("pptx.ai.pendingChanges", { count: B(d).length })), 1), B(d).length > 1 ? (I(), v("button", {
409
+ key: 0,
410
+ type: "button",
411
+ class: "rounded-sm bg-primary/90 px-2 py-0.5 text-[11px] font-medium text-primary-foreground hover:bg-primary",
412
+ onClick: M
413
+ }, F(B(l)("pptx.ai.acceptAll")), 1)) : b("", !0)]), (I(!0), v(m, null, A(B(d), (e) => (I(), f(st, {
414
+ key: e.id,
415
+ proposal: e,
416
+ onAccept: E,
417
+ onReject: B(w)
418
+ }, null, 8, ["proposal", "onReject"]))), 128))])) : b("", !0),
419
+ k(we, {
420
+ "is-streaming": B(p),
421
+ "prefill-text": s.aiPanel.prefill.value.text,
422
+ "prefill-nonce": s.aiPanel.prefill.value.nonce,
423
+ onSend: B(c),
424
+ onStop: B(u)
425
+ }, null, 8, [
426
+ "is-streaming",
427
+ "prefill-text",
428
+ "prefill-nonce",
429
+ "onSend",
430
+ "onStop"
431
+ ])
432
+ ]));
433
+ }
434
+ }), xt = { class: "flex items-center gap-2 border-b border-border px-3 py-2" }, gt = { class: "text-sm font-semibold text-foreground" }, ft = ["title", "aria-label"], bt = {
435
+ key: 0,
436
+ class: "flex flex-1 flex-col items-center justify-center gap-2 text-muted-foreground"
437
+ }, vt = {
438
+ key: 1,
439
+ class: "flex flex-1 flex-col items-center justify-center gap-2 px-6 text-center"
440
+ }, yt = { class: "text-sm font-medium text-foreground" }, ht = { class: "text-[12px] text-muted-foreground" }, kt = { class: "flex flex-1 flex-col items-center justify-center gap-2 text-muted-foreground" }, wt = w({
441
+ __name: "AiChatPanel",
442
+ props: {
443
+ bridge: {},
444
+ config: {},
445
+ panelWidth: {},
446
+ aiPanel: {}
447
+ },
448
+ emits: ["close"],
449
+ setup(t, { emit: a }) {
450
+ const r = t, l = a, { t: i } = e(), { state: p, session: d, initError: c } = function(e, t) {
451
+ const a = _("checking"), r = E(null), l = E(void 0);
452
+ let i = 0;
453
+ return (async () => {
454
+ const n = ++i;
455
+ a.value = "checking", r.value = null, l.value = void 0;
456
+ try {
457
+ const l = await o();
458
+ if (n !== i) return;
459
+ if (!l) return void (a.value = "unavailable");
460
+ const p = await s(e, t);
461
+ if (n !== i) return;
462
+ r.value = p, a.value = "ready";
463
+ } catch (e) {
464
+ if (n !== i) return;
465
+ l.value = e instanceof Error ? e : new Error(String(e)), a.value = "error";
466
+ }
467
+ })(), {
468
+ state: a,
469
+ session: r,
470
+ initError: l
471
+ };
472
+ }(r.bridge, r.config), u = g(() => r.panelWidth ? { width: `${r.panelWidth}px` } : void 0), m = n({
473
+ activeSlideIndex: _(0),
474
+ selectedElementIds: _([]),
475
+ selectedElement: () => null
476
+ }), h = g(() => r.aiPanel ?? m);
477
+ return (e, t) => (I(), v("div", {
478
+ "data-pptx-ai-panel": "",
479
+ class: "absolute right-0 top-0 z-30 flex h-full w-80 flex-col border-l border-border bg-card shadow-xl max-md:inset-x-0 max-md:top-auto max-md:bottom-0 max-md:h-[75dvh] max-md:w-full max-md:rounded-t-2xl max-md:border-l-0 max-md:border-t max-md:shadow-2xl",
480
+ style: S(u.value)
481
+ }, [y("div", xt, [
482
+ k(B(ae), { class: "w-4 h-4 text-primary" }),
483
+ y("span", gt, F(B(i)("pptx.ai.title")), 1),
484
+ y("button", {
485
+ type: "button",
486
+ title: B(i)("pptx.ai.close"),
487
+ "aria-label": B(i)("pptx.ai.close"),
488
+ class: "ml-auto rounded-sm p-1 text-muted-foreground transition-colors hover:bg-accent",
489
+ onClick: t[0] || (t[0] = (e) => l("close"))
490
+ }, [k(B(ce), { class: "w-4 h-4" })], 8, ft)
491
+ ]), "checking" === B(p) ? (I(), v("div", bt, [k(B(q), { class: "w-5 h-5 animate-spin" })])) : "unavailable" === B(p) || "error" === B(p) ? (I(), v("div", vt, [
492
+ k(B(ie), { class: "w-6 h-6 text-muted-foreground" }),
493
+ y("p", yt, F(B(i)("pptx.ai.unavailableTitle")), 1),
494
+ y("p", ht, F(B(c)?.message ?? B(i)("pptx.ai.unavailableHint")), 1)
495
+ ])) : "ready" === B(p) && B(d) ? (I(), f(x, { key: 2 }, {
496
+ fallback: R(() => [y("div", kt, [k(B(q), { class: "w-5 h-5 animate-spin" })])]),
497
+ default: R(() => [k(mt, {
498
+ session: B(d),
499
+ config: r.config,
500
+ bridge: r.bridge,
501
+ "ai-panel": h.value
502
+ }, null, 8, [
503
+ "session",
504
+ "config",
505
+ "bridge",
506
+ "ai-panel"
507
+ ])]),
508
+ _: 1
509
+ })) : b("", !0)], 4));
510
+ }
511
+ });
512
+ export { wt as default };
Binary file
Binary file