@8wave/ai-elements 0.98.0 → 0.99.0-beta.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 (76) hide show
  1. package/README.md +24 -5
  2. package/dist/_chunks/{PkToolShowForm-BNV4Ja6g.js → PkToolShowForm-dFuoqTPs.js} +84 -80
  3. package/dist/_chunks/PkToolShowForm-dFuoqTPs.js.map +1 -0
  4. package/dist/ai-elements.es.js +3153 -2982
  5. package/dist/ai-elements.es.js.map +1 -1
  6. package/dist-vue/PkChatbot.js +1 -1
  7. package/dist-vue/PkChatbotMessages.js +1 -1
  8. package/dist-vue/PkChatbotStepToolDetail.js +1 -1
  9. package/dist-vue/PkChatbotSteps.js +1 -1
  10. package/dist-vue/PkChatbotViewChat.js +1 -1
  11. package/dist-vue/PkChatbotViewConversations.js +1 -1
  12. package/dist-vue/PkChatbotViewFiles.js +1 -1
  13. package/dist-vue/PkChatbotViewProfile.js +1 -1
  14. package/dist-vue/_chunks/{PkChatbot-DHkhT0Jf.js → PkChatbot-BlG1WlAO.js} +7 -7
  15. package/dist-vue/_chunks/{PkChatbot-DHkhT0Jf.js.map → PkChatbot-BlG1WlAO.js.map} +1 -1
  16. package/dist-vue/_chunks/PkChatbotMessages-BrufA7o1.js +752 -0
  17. package/dist-vue/_chunks/PkChatbotMessages-BrufA7o1.js.map +1 -0
  18. package/dist-vue/_chunks/{PkChatbotStepToolDetail-ldThv0t5.js → PkChatbotStepToolDetail-BVI72gyx.js} +2 -2
  19. package/dist-vue/_chunks/{PkChatbotStepToolDetail-ldThv0t5.js.map → PkChatbotStepToolDetail-BVI72gyx.js.map} +1 -1
  20. package/dist-vue/_chunks/PkChatbotSteps-Dv9NkYER.js +172 -0
  21. package/dist-vue/_chunks/{PkChatbotSteps-BpqdFhsG.js.map → PkChatbotSteps-Dv9NkYER.js.map} +1 -1
  22. package/dist-vue/_chunks/{PkChatbotViewChat-C08TsXiL.js → PkChatbotViewChat-CAqvbbfN.js} +66 -66
  23. package/dist-vue/_chunks/PkChatbotViewChat-CAqvbbfN.js.map +1 -0
  24. package/dist-vue/_chunks/{PkChatbotViewConversations-BQZi5kSC.js → PkChatbotViewConversations-Cq41H-tc.js} +2 -2
  25. package/dist-vue/_chunks/{PkChatbotViewConversations-BQZi5kSC.js.map → PkChatbotViewConversations-Cq41H-tc.js.map} +1 -1
  26. package/dist-vue/_chunks/{PkChatbotViewFiles-TLKE_tRw.js → PkChatbotViewFiles-DNuzmBJc.js} +2 -2
  27. package/dist-vue/_chunks/{PkChatbotViewFiles-TLKE_tRw.js.map → PkChatbotViewFiles-DNuzmBJc.js.map} +1 -1
  28. package/dist-vue/_chunks/{PkChatbotViewProfile-B6ANZY96.js → PkChatbotViewProfile-C0BXIY2N.js} +2 -2
  29. package/dist-vue/_chunks/{PkChatbotViewProfile-B6ANZY96.js.map → PkChatbotViewProfile-C0BXIY2N.js.map} +1 -1
  30. package/dist-vue/_chunks/{PkToolShowForm-C-mWyeka.js → PkToolShowForm-CQuX08lk.js} +62 -58
  31. package/dist-vue/_chunks/PkToolShowForm-CQuX08lk.js.map +1 -0
  32. package/dist-vue/_chunks/{createChatbotApiClient-BOBdBxmf.js → createChatbotApiClient-BMZltBLh.js} +367 -363
  33. package/dist-vue/_chunks/createChatbotApiClient-BMZltBLh.js.map +1 -0
  34. package/dist-vue/_chunks/{useChatbotStore-BJ-EDmND.js → useChatbotStore-DZiorgLW.js} +113 -103
  35. package/dist-vue/_chunks/{useChatbotStore-BJ-EDmND.js.map → useChatbotStore-DZiorgLW.js.map} +1 -1
  36. package/dist-vue/_chunks/{utils-BMa8jwJS.js → utils-Cru8TJxe.js} +48 -30
  37. package/dist-vue/_chunks/utils-Cru8TJxe.js.map +1 -0
  38. package/dist-vue/api.js +1 -1
  39. package/dist-vue/composables.js +3 -3
  40. package/dist-vue/index.js +4351 -4041
  41. package/dist-vue/index.js.map +1 -1
  42. package/dist-vue/locales.js +16 -0
  43. package/dist-vue/packages/components/src/PkCheckboxField.d.ts +45 -0
  44. package/dist-vue/packages/components/src/PkEditorRepeater.d.ts +2 -2
  45. package/dist-vue/packages/components/src/PkPwaInstallPrompt.d.ts +4 -0
  46. package/dist-vue/packages/components/src/PkPwaOfflineNotice.d.ts +4 -0
  47. package/dist-vue/packages/components/src/chat/PkAgentSettingsPanel.d.ts +11 -2
  48. package/dist-vue/packages/components/src/chat/PkChatbotMessages.d.ts +24 -2
  49. package/dist-vue/packages/components/src/chat/PkToolApprovalBadge.d.ts +4 -0
  50. package/dist-vue/packages/components/src/chat/PkToolApprovalCard.d.ts +35 -0
  51. package/dist-vue/packages/components/src/chat/PkToolApprovalPreviewMessage.d.ts +11 -0
  52. package/dist-vue/packages/components/src/chat/index.d.ts +2 -1
  53. package/dist-vue/packages/components/src/chat/toolApprovalPreviews.d.ts +12 -0
  54. package/dist-vue/packages/components/src/chat/toolComponentMap.d.ts +5 -3
  55. package/dist-vue/packages/components/src/chat/useChatScroll.d.ts +6 -0
  56. package/dist-vue/packages/components/src/chat/utils.d.ts +13 -0
  57. package/dist-vue/packages/components/src/index.d.ts +4 -1
  58. package/dist-vue/packages/composable/src/chatbot/useChatbotStore.d.ts +34 -1
  59. package/dist-vue/packages/models/src/schema/Agent.d.ts +48 -0
  60. package/dist-vue/packages/models/src/schema/ReasoningChat.d.ts +6 -0
  61. package/dist-vue/packages/models/src/schema/SubAgent.d.ts +6 -0
  62. package/dist-vue/style.css +1 -1
  63. package/package.json +1 -1
  64. package/dist/_chunks/PkToolRequestConfirm-FQ9nDFXy.js +0 -48
  65. package/dist/_chunks/PkToolRequestConfirm-FQ9nDFXy.js.map +0 -1
  66. package/dist/_chunks/PkToolShowForm-BNV4Ja6g.js.map +0 -1
  67. package/dist-vue/_chunks/PkChatbotMessages-B4qfTNOJ.js +0 -630
  68. package/dist-vue/_chunks/PkChatbotMessages-B4qfTNOJ.js.map +0 -1
  69. package/dist-vue/_chunks/PkChatbotSteps-BpqdFhsG.js +0 -172
  70. package/dist-vue/_chunks/PkChatbotViewChat-C08TsXiL.js.map +0 -1
  71. package/dist-vue/_chunks/PkToolRequestConfirm-CQNa3seA.js +0 -48
  72. package/dist-vue/_chunks/PkToolRequestConfirm-CQNa3seA.js.map +0 -1
  73. package/dist-vue/_chunks/PkToolShowForm-C-mWyeka.js.map +0 -1
  74. package/dist-vue/_chunks/createChatbotApiClient-BOBdBxmf.js.map +0 -1
  75. package/dist-vue/_chunks/utils-BMa8jwJS.js.map +0 -1
  76. package/dist-vue/packages/components/src/chat/PkToolRequestConfirm.d.ts +0 -11
@@ -115,19 +115,19 @@ var j = /* @__PURE__ */ v({
115
115
  }, ce = { class: "flex justify-between text-10 text-word-3" }, le = { class: "h-4 bg-surface-3 rounded-full overflow-hidden" }, ue = { class: "px-sm py-16 flex flex-col gap-12" }, de = { class: "leading-normal text-12" }, fe = { class: "font-semibold" }, pe = { class: "text-12" }, me = { class: "font-semibold" }, he = {
116
116
  key: 0,
117
117
  class: "text-word-3"
118
- }, N = { class: "text-12" }, P = { class: "font-semibold" }, F = {
118
+ }, ge = { class: "text-12" }, N = { class: "font-semibold" }, P = {
119
119
  key: 0,
120
120
  class: "text-word-3"
121
- }, I = {
121
+ }, F = {
122
122
  key: 2,
123
123
  class: "flex flex-col gap-6 w-full"
124
- }, L = {
124
+ }, I = {
125
125
  key: 0,
126
126
  class: "px-sm pb-sm border-t border-surface-3"
127
- }, R = {
127
+ }, L = {
128
128
  key: 1,
129
129
  class: "px-sm py-10 bg-surface border-t border-surface-3 flex justify-between gap-12"
130
- }, ge = { key: 1 }, _e = { class: "px-sm py-12 bg-surface space-y-10" }, ve = { class: "flex flex-col gap-8" }, ye = { class: "text-12 text-word-3" }, z = { class: "text-12 text-word-2 font-semibold" }, be = { class: "px-sm py-12 bg-surface border-t border-surface-3 flex items-center gap-10" }, xe = { class: "w-20 h-20 rounded-full border border-success text-success flex items-center justify-center" }, Se = { class: "flex flex-col" }, Ce = { class: "font-semibold text-12 text-word-1 leading-tight" }, B = /*@__PURE__*/ v({
130
+ }, _e = { key: 1 }, R = { class: "px-sm py-12 bg-surface space-y-10" }, ve = { class: "flex flex-col gap-8" }, ye = { class: "text-12 text-word-3" }, be = { class: "text-12 text-word-2 font-semibold" }, xe = { class: "px-sm py-12 bg-surface border-t border-surface-3 flex items-center gap-10" }, Se = { class: "w-20 h-20 rounded-full border border-success text-success flex items-center justify-center" }, Ce = { class: "flex flex-col" }, we = { class: "font-semibold text-12 text-word-1 leading-tight" }, z = /*@__PURE__*/ v({
131
131
  __name: "PkToolShowForm",
132
132
  props: {
133
133
  part: {},
@@ -138,34 +138,34 @@ var j = /* @__PURE__ */ v({
138
138
  let i = e, s = r, { t: c, d: g } = ie({ useScope: "global" }), v = u(() => JSON.parse(JSON.stringify(i.part))), y = u(() => v.value.toolName === "showMultipleChoice" || v.value.type === "tool-showMultipleChoice"), b = u(() => v.value.state === "input-available"), w = u(() => {
139
139
  let e = H.value;
140
140
  return e ? B.value.length === 1 && !e.allowFreeformInput && !i.allowCustomAnswer : !1;
141
- }), D = u(() => y.value && B.value.length === 1 && !H.value?.multiSelect), B = u(() => {
141
+ }), D = u(() => y.value && B.value.length === 1 && !H.value?.multiSelect), z = u(() => !!H.value?.options && !H.value?.multiSelect && (w.value || D.value)), B = u(() => {
142
142
  let e = v.value.input;
143
143
  return e?.steps?.length ? e.steps : e?.question && e?.options ? [{
144
144
  id: "legacy",
145
145
  question: e.question,
146
146
  options: e.options.map((e) => typeof e == "string" ? { label: e } : e)
147
147
  }] : [];
148
- }), V = S(0), H = u(() => B.value[V.value]), U = u(() => V.value > 0), W = u(() => V.value < B.value.length - 1), G = u(() => B.value.length > 1), K = u(() => G.value ? Math.round((V.value + 1) / B.value.length * 100) : null), q = ne({}), J = S(""), Y = u({
148
+ }), V = S(0), H = u(() => B.value[V.value]), U = u(() => V.value > 0), W = u(() => V.value < B.value.length - 1), Te = u(() => B.value.length > 1), G = u(() => Te.value ? Math.round((V.value + 1) / B.value.length * 100) : null), K = ne({}), q = S(""), J = u({
149
149
  get: () => {
150
- let e = H.value ? q[H.value.id] : void 0;
150
+ let e = H.value ? K[H.value.id] : void 0;
151
151
  if (!(e == null || Array.isArray(e))) return e;
152
152
  },
153
153
  set: (e) => {
154
- H.value && (q[H.value.id] = e ?? null);
154
+ H.value && (K[H.value.id] = e ?? null);
155
155
  }
156
- }), X = u({
156
+ }), Y = u({
157
157
  get: () => {
158
- let e = H.value ? q[H.value.id] : void 0;
158
+ let e = H.value ? K[H.value.id] : void 0;
159
159
  return Array.isArray(e) ? e : [];
160
160
  },
161
161
  set: (e) => {
162
- H.value && (q[H.value.id] = e ?? []);
162
+ H.value && (K[H.value.id] = e ?? []);
163
163
  }
164
164
  });
165
165
  O(() => v.value.output, (e) => {
166
166
  if (e) {
167
- if (typeof e == "string") B.value.length === 1 && (q[B.value[0].id] = e);
168
- else if (e.answers) for (let t of e.answers) q[t.id] = t.value;
167
+ if (typeof e == "string") B.value.length === 1 && (K[B.value[0].id] = e);
168
+ else if (e.answers) for (let t of e.answers) K[t.id] = t.value;
169
169
  }
170
170
  }, { immediate: !0 }), O(u(() => {
171
171
  let e = v.value.output;
@@ -177,39 +177,43 @@ var j = /* @__PURE__ */ v({
177
177
  }
178
178
  }
179
179
  }), (e) => {
180
- !e || !H.value || (H.value.options ?? []).map((e) => e.label).includes(e) || (J.value = e);
180
+ !e || !H.value || (H.value.options ?? []).map((e) => e.label).includes(e) || (q.value = e);
181
181
  }, { immediate: !0 });
182
- let Z = u(() => H.value?.options ? H.value.options.map((e) => ({
182
+ let X = u(() => H.value?.options ? H.value.options.map((e) => ({
183
183
  label: e.label,
184
184
  value: e.label,
185
185
  description: e.description
186
186
  })) : []);
187
- function Q() {
188
- W.value ? V.value++ : $();
187
+ function Z() {
188
+ if (q.value.trim()) {
189
+ $();
190
+ return;
191
+ }
192
+ W.value ? V.value++ : Q();
189
193
  }
190
- function we() {
194
+ function Ee() {
191
195
  U.value && V.value--;
192
196
  }
193
- function $() {
197
+ function Q() {
194
198
  if (!b.value) return;
195
199
  let e = B.value.map((e) => ({
196
200
  id: e.id,
197
- value: q[e.id] ?? null
201
+ value: K[e.id] ?? null
198
202
  }));
199
203
  if (D.value && !H.value?.allowFreeformInput) {
200
204
  let t = e[0].value;
201
205
  s("select", Array.isArray(t) ? t[0] : t);
202
206
  } else s("select", { answers: e });
203
207
  }
204
- function Te() {
205
- let e = J.value.trim();
206
- e && (q[H.value.id] = e, B.value.length === 1 ? $() : Q(), J.value = "");
208
+ function $() {
209
+ let e = q.value.trim();
210
+ e && (K[H.value.id] = e, q.value = "", B.value.length === 1 ? Q() : Z());
207
211
  }
208
- function Ee() {
209
- b.value && (w.value || D.value) && $();
212
+ function De() {
213
+ b.value && (w.value || D.value) && Q();
210
214
  }
211
- function De(e) {
212
- let t = q[e.id];
215
+ function Oe(e) {
216
+ let t = K[e.id];
213
217
  return t == null ? "—" : Array.isArray(t) ? t.join(", ") : e.type === "date" ? g(new Date(t), "short") : t;
214
218
  }
215
219
  return (e, r) => {
@@ -220,9 +224,9 @@ var j = /* @__PURE__ */ v({
220
224
  }, T(v.value.input?.title), 3)) : f("", !0), b.value && B.value.length > 1 ? (x(), p("div", se, [m("div", ce, [m("span", null, T(E(c)("showForm.step", {
221
225
  current: V.value + 1,
222
226
  total: B.value.length
223
- })), 1), m("span", null, T(K.value) + "%", 1)]), m("div", le, [m("div", {
227
+ })), 1), m("span", null, T(G.value) + "%", 1)]), m("div", le, [m("div", {
224
228
  class: "h-full bg-word-4 transition-all duration-300",
225
- style: te({ width: `${K.value}%` })
229
+ style: te({ width: `${G.value}%` })
226
230
  }, null, 4)])])) : f("", !0)])) : f("", !0), b.value ? (x(), p(l, { key: 1 }, [
227
231
  m("div", ue, [m("div", de, [m("strong", fe, T(H.value.question), 1), H.value.message ? (x(), d(t, {
228
232
  key: 0,
@@ -230,14 +234,14 @@ var j = /* @__PURE__ */ v({
230
234
  class: "text-word-2 mt-4"
231
235
  }, null, 8, ["markdown"])) : f("", !0)]), H.value.options && H.value.multiSelect ? (x(), d(M, {
232
236
  key: 0,
233
- modelValue: X.value,
234
- "onUpdate:modelValue": r[0] ||= (e) => X.value = e,
237
+ modelValue: Y.value,
238
+ "onUpdate:modelValue": r[0] ||= (e) => Y.value = e,
235
239
  name: H.value.id,
236
- options: Z.value,
240
+ options: X.value,
237
241
  readonly: !b.value,
238
242
  class: "mb-0",
239
243
  vertical: ""
240
- }, h({ _: 2 }, [C(Z.value, (e) => ({
244
+ }, h({ _: 2 }, [C(X.value, (e) => ({
241
245
  name: e.value,
242
246
  fn: k(() => [m("div", pe, [m("div", me, T(e.label), 1), e.description ? (x(), p("div", he, T(e.description), 1)) : f("", !0)])])
243
247
  }))]), 1032, [
@@ -247,31 +251,31 @@ var j = /* @__PURE__ */ v({
247
251
  "readonly"
248
252
  ])) : H.value.options && !H.value.multiSelect ? (x(), d(j, {
249
253
  key: 1,
250
- modelValue: Y.value,
251
- "onUpdate:modelValue": [r[1] ||= (e) => Y.value = e, Ee],
254
+ modelValue: J.value,
255
+ "onUpdate:modelValue": [r[1] ||= (e) => J.value = e, De],
252
256
  name: H.value.id,
253
- options: Z.value,
257
+ options: X.value,
254
258
  readonly: !b.value,
255
259
  vertical: "",
256
260
  class: "mb-0"
257
- }, h({ _: 2 }, [C(Z.value, (e) => ({
261
+ }, h({ _: 2 }, [C(X.value, (e) => ({
258
262
  name: e.value,
259
- fn: k(() => [m("div", N, [m("div", P, T(e.label), 1), e.description ? (x(), p("div", F, T(e.description), 1)) : f("", !0)])])
263
+ fn: k(() => [m("div", ge, [m("div", N, T(e.label), 1), e.description ? (x(), p("div", P, T(e.description), 1)) : f("", !0)])])
260
264
  }))]), 1032, [
261
265
  "modelValue",
262
266
  "name",
263
267
  "options",
264
268
  "readonly"
265
- ])) : H.value.options ? f("", !0) : (x(), p("div", I, [_(i, {
266
- modelValue: Y.value,
267
- "onUpdate:modelValue": r[2] ||= (e) => Y.value = e,
269
+ ])) : H.value.options ? f("", !0) : (x(), p("div", F, [_(i, {
270
+ modelValue: J.value,
271
+ "onUpdate:modelValue": r[2] ||= (e) => J.value = e,
268
272
  placeholder: H.value.placeholder || E(c)("placeholder.insert"),
269
273
  type: H.value.type,
270
274
  class: "w-full",
271
275
  name: H.value.id,
272
276
  modifiers: "compact rounded",
273
277
  disabled: !b.value,
274
- onKeyup: re(Q, ["enter"])
278
+ onKeyup: re(Z, ["enter"])
275
279
  }, null, 8, [
276
280
  "modelValue",
277
281
  "placeholder",
@@ -279,12 +283,12 @@ var j = /* @__PURE__ */ v({
279
283
  "name",
280
284
  "disabled"
281
285
  ])]))]),
282
- H.value.allowFreeformInput && H.value.options ? (x(), p("div", L, [m("form", {
286
+ H.value.allowFreeformInput && H.value.options ? (x(), p("div", I, [m("form", {
283
287
  class: "flex gap-xs pt-sm",
284
- onSubmit: A(Te, ["prevent"])
288
+ onSubmit: A($, ["prevent"])
285
289
  }, [_(i, {
286
- modelValue: J.value,
287
- "onUpdate:modelValue": r[3] ||= (e) => J.value = e,
290
+ modelValue: q.value,
291
+ "onUpdate:modelValue": r[3] ||= (e) => q.value = e,
288
292
  class: "flex-1",
289
293
  name: `${H.value.id}-custom`,
290
294
  modifiers: "compact rounded",
@@ -296,34 +300,34 @@ var j = /* @__PURE__ */ v({
296
300
  "disabled",
297
301
  "placeholder"
298
302
  ])], 32)])) : f("", !0),
299
- G.value || H.value.multiSelect || !H.value.options ? (x(), p("div", R, [U.value ? (x(), d(s, {
303
+ z.value ? f("", !0) : (x(), p("div", L, [U.value ? (x(), d(s, {
300
304
  key: 0,
301
305
  modifiers: "action-quiet",
302
306
  icon: "ri:arrow-left-s-line",
303
307
  label: E(c)("action.back"),
304
- onClick: A(we, ["stop"])
305
- }, null, 8, ["label"])) : (x(), p("div", ge)), _(s, {
308
+ onClick: A(Ee, ["stop"])
309
+ }, null, 8, ["label"])) : (x(), p("div", _e)), _(s, {
306
310
  modifiers: W.value ? "action-quiet" : "action-primary",
307
311
  icon: W.value ? "ri:arrow-right-s-line" : "ri:send-plane-2-line",
308
312
  "icon-position": "right",
309
313
  label: W.value ? E(c)("action.next") : E(c)("action.submit"),
310
- onClick: A(Q, ["stop"])
314
+ onClick: A(Z, ["stop"])
311
315
  }, null, 8, [
312
316
  "modifiers",
313
317
  "icon",
314
318
  "label"
315
- ])])) : f("", !0)
316
- ], 64)) : (x(), p(l, { key: 2 }, [m("div", _e, [m("ul", ve, [(x(!0), p(l, null, C(B.value, (e) => (x(), p("li", {
319
+ ])]))
320
+ ], 64)) : (x(), p(l, { key: 2 }, [m("div", R, [m("ul", ve, [(x(!0), p(l, null, C(B.value, (e) => (x(), p("li", {
317
321
  key: e.id,
318
322
  class: "leading-normal"
319
- }, [m("div", ye, T(e.question), 1), m("span", z, T(De(e)), 1)]))), 128))])]), m("div", be, [m("div", xe, [_(u, {
323
+ }, [m("div", ye, T(e.question), 1), m("span", be, T(Oe(e)), 1)]))), 128))])]), m("div", xe, [m("div", Se, [_(u, {
320
324
  name: "ri:check-line",
321
325
  class: "text-12"
322
- })]), m("div", Se, [m("span", Ce, T(E(c)("showForm.completed")), 1)])])], 64))])) : f("", !0);
326
+ })]), m("div", Ce, [m("span", we, T(E(c)("showForm.completed")), 1)])])], 64))])) : f("", !0);
323
327
  };
324
328
  }
325
- }), V = /* @__PURE__ */ e({ default: () => H }), H = B;
329
+ }), B = /* @__PURE__ */ e({ default: () => V }), V = z;
326
330
  //#endregion
327
- export { j as i, V as n, M as r, H as t };
331
+ export { j as i, B as n, M as r, V as t };
328
332
 
329
- //# sourceMappingURL=PkToolShowForm-C-mWyeka.js.map
333
+ //# sourceMappingURL=PkToolShowForm-CQuX08lk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PkToolShowForm-CQuX08lk.js","names":[],"sources":["../../../../packages/components/src/PkEditorRadioButtons.vue","../../../../packages/components/src/PkEditorRadioButtons.vue","../../../../packages/components/src/PkEditorCheckboxButtons.vue","../../../../packages/components/src/PkEditorCheckboxButtons.vue","../../../../packages/components/src/chat/PkToolShowForm.vue","../../../../packages/components/src/chat/PkToolShowForm.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import type { Option } from '@volverjs/ui-vue'\n import { computed } from 'vue'\n\n const props = defineProps<{\n name: string\n required?: boolean\n options: Option[]\n readonly?: boolean\n disabled?: boolean\n modifiers?: string | string[]\n }>()\n\n const modelValue = defineModel<\n string | number | boolean | symbol | unknown[] | undefined\n >()\n\n const radioModifiers = computed(() => {\n const toReturn = props.modifiers\n ? Array.isArray(props.modifiers)\n ? props.modifiers\n : [props.modifiers]\n : []\n return [...toReturn, 'button']\n })\n</script>\n\n<template>\n <VvRadioGroup v-model=\"modelValue\" :name modifiers=\"buttons\">\n <VvRadio\n v-for=\"(option, key) in options\"\n :key\n :name\n :required\n :readonly\n :disabled\n :value=\"option.value\"\n :modifiers=\"radioModifiers\">\n <slot :name=\"option.value\" v-bind=\"{ option }\">\n {{ option.label }}\n </slot>\n </VvRadio>\n </VvRadioGroup>\n</template>\n","<script setup lang=\"ts\">\n import type { Option } from '@volverjs/ui-vue'\n import { computed } from 'vue'\n\n const props = defineProps<{\n name: string\n required?: boolean\n options: Option[]\n readonly?: boolean\n disabled?: boolean\n modifiers?: string | string[]\n }>()\n\n const modelValue = defineModel<\n string | number | boolean | symbol | unknown[] | undefined\n >()\n\n const radioModifiers = computed(() => {\n const toReturn = props.modifiers\n ? Array.isArray(props.modifiers)\n ? props.modifiers\n : [props.modifiers]\n : []\n return [...toReturn, 'button']\n })\n</script>\n\n<template>\n <VvRadioGroup v-model=\"modelValue\" :name modifiers=\"buttons\">\n <VvRadio\n v-for=\"(option, key) in options\"\n :key\n :name\n :required\n :readonly\n :disabled\n :value=\"option.value\"\n :modifiers=\"radioModifiers\">\n <slot :name=\"option.value\" v-bind=\"{ option }\">\n {{ option.label }}\n </slot>\n </VvRadio>\n </VvRadioGroup>\n</template>\n","<script setup lang=\"ts\">\n import type { Option } from '@volverjs/ui-vue'\n\n defineProps<{\n name: string\n required?: boolean\n options: Option[]\n readonly?: boolean\n disabled?: boolean\n }>()\n\n const modelValue = defineModel<unknown[] | undefined>()\n</script>\n\n<template>\n <VvCheckboxGroup v-model=\"modelValue\" :name modifiers=\"buttons\">\n <VvCheckbox\n v-for=\"(option, key) in options\"\n :key\n :name\n :required\n :readonly\n :disabled\n :value=\"option.value\"\n modifiers=\"button\">\n <slot :name=\"String(option.value)\" v-bind=\"{ option }\">\n {{ option.label }}\n </slot>\n </VvCheckbox>\n </VvCheckboxGroup>\n</template>\n","<script setup lang=\"ts\">\n import type { Option } from '@volverjs/ui-vue'\n\n defineProps<{\n name: string\n required?: boolean\n options: Option[]\n readonly?: boolean\n disabled?: boolean\n }>()\n\n const modelValue = defineModel<unknown[] | undefined>()\n</script>\n\n<template>\n <VvCheckboxGroup v-model=\"modelValue\" :name modifiers=\"buttons\">\n <VvCheckbox\n v-for=\"(option, key) in options\"\n :key\n :name\n :required\n :readonly\n :disabled\n :value=\"option.value\"\n modifiers=\"button\">\n <slot :name=\"String(option.value)\" v-bind=\"{ option }\">\n {{ option.label }}\n </slot>\n </VvCheckbox>\n </VvCheckboxGroup>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, reactive, watch } from 'vue'\n import { useI18n } from 'vue-i18n'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkEditorRadioButtons from '../PkEditorRadioButtons.vue'\n import PkEditorCheckboxButtons from '../PkEditorCheckboxButtons.vue'\n\n // --- Types ---\n\n interface FormOption {\n label: string\n description?: string\n }\n\n interface FormStep {\n id: string\n question: string\n message?: string\n type?: 'text' | 'number' | 'date'\n options?: FormOption[]\n multiSelect?: boolean\n allowFreeformInput?: boolean\n placeholder?: string\n }\n\n interface FormAnswer {\n id: string\n value: string | string[] | number | null\n }\n\n interface ToolPartShape {\n state?: 'input-available' | 'output-available'\n toolCallId?: string\n // AI SDK v5 encodes the tool name in `type` (e.g. 'tool-showMultipleChoice').\n // `toolName` is kept for backward compatibility but is normally absent.\n type?: string\n toolName?: string\n input?: {\n title?: string\n steps?: FormStep[]\n // Legacy showMultipleChoice fields\n question?: string\n options?: (string | FormOption)[]\n }\n output?: string | { answers: FormAnswer[] }\n }\n\n type AnswerValue = string | string[] | number | null\n\n // --- Props & Emits ---\n\n const props = defineProps<{\n part: unknown\n allowCustomAnswer?: boolean\n }>()\n\n const emit = defineEmits<{\n select: [answer: string | { answers: FormAnswer[] }]\n }>()\n\n const { t: $t, d: $d } = useI18n({ useScope: 'global' })\n\n // --- Parsed tool part ---\n\n const toolPart = computed(\n () => JSON.parse(JSON.stringify(props.part)) as ToolPartShape,\n )\n\n const isLegacy = computed(\n () =>\n toolPart.value.toolName === 'showMultipleChoice' ||\n toolPart.value.type === 'tool-showMultipleChoice',\n )\n\n const isInteractive = computed(\n () => toolPart.value.state === 'input-available',\n )\n\n /** Single-step with no custom-answer and no freeform → auto-submit on option pick */\n const isAutoSubmitStep = computed(() => {\n const step = currentStep.value\n if (!step) return false\n return (\n steps.value.length === 1 &&\n !step.allowFreeformInput &&\n !props.allowCustomAnswer\n )\n })\n\n /** Legacy tool should auto-submit on option pick regardless of allowCustomAnswer */\n const isLegacyAutoSubmit = computed(\n () =>\n isLegacy.value &&\n steps.value.length === 1 &&\n !currentStep.value?.multiSelect,\n )\n\n /**\n * True only for the steps that send themselves as soon as an option is\n * picked: the single case where the footer button would be redundant.\n * Every other shape needs it, single-step forms included: with\n * `allowFreeformInput` (or `allowCustomAnswer`) the radio pick no longer\n * auto-submits, so without the footer the user was left with a chosen\n * option and no way to send it.\n */\n const isSelfSubmitting = computed(\n () =>\n Boolean(currentStep.value?.options) &&\n !currentStep.value?.multiSelect &&\n (isAutoSubmitStep.value || isLegacyAutoSubmit.value),\n )\n\n // --- Steps ---\n\n const steps = computed<FormStep[]>(() => {\n const input = toolPart.value.input\n if (input?.steps?.length) {\n return input.steps\n }\n // Legacy showMultipleChoice → normalize into a single step\n if (input?.question && input?.options) {\n return [\n {\n id: 'legacy',\n question: input.question,\n options: input.options.map((o) =>\n typeof o === 'string' ? { label: o } : o,\n ),\n },\n ]\n }\n return []\n })\n\n // --- Navigation state ---\n\n const currentStepIndex = ref(0)\n const currentStep = computed(() => steps.value[currentStepIndex.value])\n const canGoBack = computed(() => currentStepIndex.value > 0)\n const canGoNext = computed(\n () => currentStepIndex.value < steps.value.length - 1,\n )\n const isMultiStep = computed(() => steps.value.length > 1)\n\n const progress = computed(() => {\n if (!isMultiStep.value) return null\n return Math.round(\n ((currentStepIndex.value + 1) / steps.value.length) * 100,\n )\n })\n\n // --- Answers ---\n\n const answers = reactive<Record<string, AnswerValue>>({})\n const customAnswer = ref('')\n\n // Single scalar answer shared by radio buttons and freeform text/number/date inputs.\n const scalarValue = computed<string | number | undefined>({\n get: () => {\n const val = currentStep.value\n ? answers[currentStep.value.id]\n : undefined\n if (val == null || Array.isArray(val)) return undefined\n return val\n },\n set: (val) => {\n if (currentStep.value) {\n answers[currentStep.value.id] = val ?? null\n }\n },\n })\n\n const activeCheckboxValue = computed<unknown[] | undefined>({\n get: () => {\n const val = currentStep.value\n ? answers[currentStep.value.id]\n : undefined\n return Array.isArray(val) ? val : []\n },\n set: (val) => {\n if (currentStep.value) {\n answers[currentStep.value.id] = (val as string[]) ?? []\n }\n },\n })\n\n // --- Initialize answers from existing output ---\n\n watch(\n () => toolPart.value.output,\n (output) => {\n if (!output) return\n if (typeof output === 'string') {\n if (steps.value.length === 1) {\n answers[steps.value[0].id] = output\n }\n } else if (output.answers) {\n for (const a of output.answers) {\n answers[a.id] = a.value\n }\n }\n },\n { immediate: true },\n )\n\n // --- Restore custom answer from output when it doesn't match any option ---\n\n const normalizedOutput = computed(() => {\n const out = toolPart.value.output\n if (!out) return undefined\n if (typeof out === 'string') return out\n if (out.answers?.length === 1) {\n const val = out.answers[0].value\n return Array.isArray(val) ? val.join(', ') : String(val)\n }\n return undefined\n })\n\n watch(\n normalizedOutput,\n (value) => {\n if (!value || !currentStep.value) return\n const optionLabels = (currentStep.value.options ?? []).map(\n (o) => o.label,\n )\n if (!optionLabels.includes(value)) {\n customAnswer.value = value\n }\n },\n { immediate: true },\n )\n\n // --- Option mapping for radio/checkbox components ---\n\n const radioOptions = computed(() => {\n if (!currentStep.value?.options) return []\n return currentStep.value.options.map((option) => ({\n label: option.label,\n value: option.label,\n description: option.description,\n }))\n })\n\n // --- Navigation & Submission ---\n\n function goNext() {\n // A typed freeform answer wins over the picked option: it is the more\n // recent intent, and the footer button is now the visible way to send\n // it (the freeform field only submits on Enter).\n if (customAnswer.value.trim()) {\n submitCustomAnswer()\n return\n }\n if (canGoNext.value) {\n currentStepIndex.value++\n } else {\n submitForm()\n }\n }\n\n function goBack() {\n if (canGoBack.value) {\n currentStepIndex.value--\n }\n }\n\n function submitForm() {\n if (!isInteractive.value) return\n\n const finalAnswers: FormAnswer[] = steps.value.map((step) => ({\n id: step.id,\n value: answers[step.id] ?? null,\n }))\n\n // Legacy backward compatibility: single-step, single-select → return plain string\n if (\n isLegacyAutoSubmit.value &&\n !currentStep.value?.allowFreeformInput\n ) {\n const val = finalAnswers[0].value\n emit('select', Array.isArray(val) ? val[0] : (val as string))\n } else {\n emit('select', { answers: finalAnswers })\n }\n }\n\n function submitCustomAnswer() {\n const value = customAnswer.value.trim()\n if (!value) return\n\n answers[currentStep.value.id] = value\n // Cleared before navigating: `goNext()` reads it back to route a typed\n // answer here, so leaving it set would recurse.\n customAnswer.value = ''\n if (steps.value.length === 1) {\n submitForm()\n } else {\n goNext()\n }\n }\n\n function onRadioChange() {\n if (!isInteractive.value) return\n if (isAutoSubmitStep.value || isLegacyAutoSubmit.value) {\n submitForm()\n }\n }\n\n // --- Summary helpers ---\n\n function getSummaryValue(step: FormStep) {\n const val = answers[step.id]\n if (val == null) return '—'\n if (Array.isArray(val)) return val.join(', ')\n if (step.type === 'date') return $d(new Date(val), 'short')\n return val\n }\n</script>\n\n<template>\n <div\n v-if=\"steps.length\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden flex flex-col transition-all bg-surface\">\n <!-- Header -->\n <div\n v-if=\"toolPart.input?.title || (isInteractive && steps.length > 1)\"\n class=\"text-12 border-b border-surface-3 text-word-3 bg-surface-1\">\n <div\n v-if=\"toolPart.input?.title\"\n class=\"px-sm py-10 font-bold\"\n :class=\"{\n 'border-b border-surface-3':\n isInteractive && steps.length > 1,\n }\">\n {{ toolPart.input?.title }}\n </div>\n <!-- Progress for multi-step -->\n <div\n v-if=\"isInteractive && steps.length > 1\"\n class=\"flex flex-col gap-4 p-sm\">\n <div class=\"flex justify-between text-10 text-word-3\">\n <span>\n {{\n $t('showForm.step', {\n current: currentStepIndex + 1,\n total: steps.length,\n })\n }}\n </span>\n <span>{{ progress }}%</span>\n </div>\n <div class=\"h-4 bg-surface-3 rounded-full overflow-hidden\">\n <div\n class=\"h-full bg-word-4 transition-all duration-300\"\n :style=\"{ width: `${progress}%` }\"></div>\n </div>\n </div>\n </div>\n\n <!-- Input Available State -->\n <template v-if=\"isInteractive\">\n <!-- Current Step Content -->\n <div class=\"px-sm py-16 flex flex-col gap-12\">\n <div class=\"leading-normal text-12\">\n <strong class=\"font-semibold\">\n {{ currentStep.question }}\n </strong>\n <PkStreamingMarkdown\n v-if=\"currentStep.message\"\n :markdown=\"currentStep.message\"\n class=\"text-word-2 mt-4\" />\n </div>\n\n <!-- Checkbox list for multi-select -->\n <PkEditorCheckboxButtons\n v-if=\"currentStep.options && currentStep.multiSelect\"\n v-model=\"activeCheckboxValue\"\n :name=\"currentStep.id\"\n :options=\"radioOptions\"\n :readonly=\"!isInteractive\"\n class=\"mb-0\"\n vertical>\n <template\n v-for=\"option in radioOptions\"\n :key=\"option.value\"\n #[option.value]>\n <!-- Shared option layout: label + optional description -->\n <div class=\"text-12\">\n <div class=\"font-semibold\">{{ option.label }}</div>\n <div v-if=\"option.description\" class=\"text-word-3\">\n {{ option.description }}\n </div>\n </div>\n </template>\n </PkEditorCheckboxButtons>\n\n <!-- Radio buttons for single-select -->\n <PkEditorRadioButtons\n v-else-if=\"currentStep.options && !currentStep.multiSelect\"\n v-model=\"scalarValue\"\n :name=\"currentStep.id\"\n :options=\"radioOptions\"\n :readonly=\"!isInteractive\"\n vertical\n class=\"mb-0\"\n @update:model-value=\"onRadioChange\">\n <template\n v-for=\"option in radioOptions\"\n :key=\"option.value\"\n #[option.value]>\n <!-- Shared option layout: label + optional description -->\n <div class=\"text-12\">\n <div class=\"font-semibold\">{{ option.label }}</div>\n <div v-if=\"option.description\" class=\"text-word-3\">\n {{ option.description }}\n </div>\n </div>\n </template>\n </PkEditorRadioButtons>\n\n <!-- Pure Freeform Input (text, number, date) -->\n <div\n v-else-if=\"!currentStep.options\"\n class=\"flex flex-col gap-6 w-full\">\n <VvInputText\n v-model=\"scalarValue\"\n :placeholder=\"\n currentStep.placeholder || $t('placeholder.insert')\n \"\n :type=\"currentStep.type\"\n class=\"w-full\"\n :name=\"currentStep.id\"\n modifiers=\"compact rounded\"\n :disabled=\"!isInteractive\"\n @keyup.enter=\"goNext\" />\n </div>\n </div>\n\n <!-- Custom footer freeform input (shown alongside options when allowFreeformInput) -->\n <div\n v-if=\"currentStep.allowFreeformInput && currentStep.options\"\n class=\"px-sm pb-sm border-t border-surface-3\">\n <form\n class=\"flex gap-xs pt-sm\"\n @submit.prevent=\"submitCustomAnswer\">\n <VvInputText\n v-model=\"customAnswer\"\n class=\"flex-1\"\n :name=\"`${currentStep.id}-custom`\"\n modifiers=\"compact rounded\"\n :disabled=\"!isInteractive\"\n :placeholder=\"\n currentStep.placeholder ||\n $t('showForm.otherPlaceholder')\n \" />\n </form>\n </div>\n\n <!-- Footer navigation: shown for every step that does not submit\n itself on option pick (see `isSelfSubmitting`). -->\n <div\n v-if=\"!isSelfSubmitting\"\n class=\"px-sm py-10 bg-surface border-t border-surface-3 flex justify-between gap-12\">\n <VvButton\n v-if=\"canGoBack\"\n modifiers=\"action-quiet\"\n icon=\"ri:arrow-left-s-line\"\n :label=\"$t('action.back')\"\n @click.stop=\"goBack\" />\n <div v-else></div>\n\n <VvButton\n :modifiers=\"canGoNext ? 'action-quiet' : 'action-primary'\"\n :icon=\"\n canGoNext\n ? 'ri:arrow-right-s-line'\n : 'ri:send-plane-2-line'\n \"\n icon-position=\"right\"\n :label=\"canGoNext ? $t('action.next') : $t('action.submit')\"\n @click.stop=\"goNext\" />\n </div>\n </template>\n\n <!-- Output Available State (Multi-step Summary) -->\n <template v-else>\n <div class=\"px-sm py-12 bg-surface space-y-10\">\n <ul class=\"flex flex-col gap-8\">\n <li\n v-for=\"step in steps\"\n :key=\"step.id\"\n class=\"leading-normal\">\n <div class=\"text-12 text-word-3\">\n {{ step.question }}\n </div>\n <span class=\"text-12 text-word-2 font-semibold\">\n {{ getSummaryValue(step) }}\n </span>\n </li>\n </ul>\n </div>\n <div\n class=\"px-sm py-12 bg-surface border-t border-surface-3 flex items-center gap-10\">\n <div\n class=\"w-20 h-20 rounded-full border border-success text-success flex items-center justify-center\">\n <VvIcon name=\"ri:check-line\" class=\"text-12\" />\n </div>\n <div class=\"flex flex-col\">\n <span\n class=\"font-semibold text-12 text-word-1 leading-tight\">\n {{ $t('showForm.completed') }}\n </span>\n </div>\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\n import { computed, ref, reactive, watch } from 'vue'\n import { useI18n } from 'vue-i18n'\n import PkStreamingMarkdown from './PkStreamingMarkdown.vue'\n import PkEditorRadioButtons from '../PkEditorRadioButtons.vue'\n import PkEditorCheckboxButtons from '../PkEditorCheckboxButtons.vue'\n\n // --- Types ---\n\n interface FormOption {\n label: string\n description?: string\n }\n\n interface FormStep {\n id: string\n question: string\n message?: string\n type?: 'text' | 'number' | 'date'\n options?: FormOption[]\n multiSelect?: boolean\n allowFreeformInput?: boolean\n placeholder?: string\n }\n\n interface FormAnswer {\n id: string\n value: string | string[] | number | null\n }\n\n interface ToolPartShape {\n state?: 'input-available' | 'output-available'\n toolCallId?: string\n // AI SDK v5 encodes the tool name in `type` (e.g. 'tool-showMultipleChoice').\n // `toolName` is kept for backward compatibility but is normally absent.\n type?: string\n toolName?: string\n input?: {\n title?: string\n steps?: FormStep[]\n // Legacy showMultipleChoice fields\n question?: string\n options?: (string | FormOption)[]\n }\n output?: string | { answers: FormAnswer[] }\n }\n\n type AnswerValue = string | string[] | number | null\n\n // --- Props & Emits ---\n\n const props = defineProps<{\n part: unknown\n allowCustomAnswer?: boolean\n }>()\n\n const emit = defineEmits<{\n select: [answer: string | { answers: FormAnswer[] }]\n }>()\n\n const { t: $t, d: $d } = useI18n({ useScope: 'global' })\n\n // --- Parsed tool part ---\n\n const toolPart = computed(\n () => JSON.parse(JSON.stringify(props.part)) as ToolPartShape,\n )\n\n const isLegacy = computed(\n () =>\n toolPart.value.toolName === 'showMultipleChoice' ||\n toolPart.value.type === 'tool-showMultipleChoice',\n )\n\n const isInteractive = computed(\n () => toolPart.value.state === 'input-available',\n )\n\n /** Single-step with no custom-answer and no freeform → auto-submit on option pick */\n const isAutoSubmitStep = computed(() => {\n const step = currentStep.value\n if (!step) return false\n return (\n steps.value.length === 1 &&\n !step.allowFreeformInput &&\n !props.allowCustomAnswer\n )\n })\n\n /** Legacy tool should auto-submit on option pick regardless of allowCustomAnswer */\n const isLegacyAutoSubmit = computed(\n () =>\n isLegacy.value &&\n steps.value.length === 1 &&\n !currentStep.value?.multiSelect,\n )\n\n /**\n * True only for the steps that send themselves as soon as an option is\n * picked: the single case where the footer button would be redundant.\n * Every other shape needs it, single-step forms included: with\n * `allowFreeformInput` (or `allowCustomAnswer`) the radio pick no longer\n * auto-submits, so without the footer the user was left with a chosen\n * option and no way to send it.\n */\n const isSelfSubmitting = computed(\n () =>\n Boolean(currentStep.value?.options) &&\n !currentStep.value?.multiSelect &&\n (isAutoSubmitStep.value || isLegacyAutoSubmit.value),\n )\n\n // --- Steps ---\n\n const steps = computed<FormStep[]>(() => {\n const input = toolPart.value.input\n if (input?.steps?.length) {\n return input.steps\n }\n // Legacy showMultipleChoice → normalize into a single step\n if (input?.question && input?.options) {\n return [\n {\n id: 'legacy',\n question: input.question,\n options: input.options.map((o) =>\n typeof o === 'string' ? { label: o } : o,\n ),\n },\n ]\n }\n return []\n })\n\n // --- Navigation state ---\n\n const currentStepIndex = ref(0)\n const currentStep = computed(() => steps.value[currentStepIndex.value])\n const canGoBack = computed(() => currentStepIndex.value > 0)\n const canGoNext = computed(\n () => currentStepIndex.value < steps.value.length - 1,\n )\n const isMultiStep = computed(() => steps.value.length > 1)\n\n const progress = computed(() => {\n if (!isMultiStep.value) return null\n return Math.round(\n ((currentStepIndex.value + 1) / steps.value.length) * 100,\n )\n })\n\n // --- Answers ---\n\n const answers = reactive<Record<string, AnswerValue>>({})\n const customAnswer = ref('')\n\n // Single scalar answer shared by radio buttons and freeform text/number/date inputs.\n const scalarValue = computed<string | number | undefined>({\n get: () => {\n const val = currentStep.value\n ? answers[currentStep.value.id]\n : undefined\n if (val == null || Array.isArray(val)) return undefined\n return val\n },\n set: (val) => {\n if (currentStep.value) {\n answers[currentStep.value.id] = val ?? null\n }\n },\n })\n\n const activeCheckboxValue = computed<unknown[] | undefined>({\n get: () => {\n const val = currentStep.value\n ? answers[currentStep.value.id]\n : undefined\n return Array.isArray(val) ? val : []\n },\n set: (val) => {\n if (currentStep.value) {\n answers[currentStep.value.id] = (val as string[]) ?? []\n }\n },\n })\n\n // --- Initialize answers from existing output ---\n\n watch(\n () => toolPart.value.output,\n (output) => {\n if (!output) return\n if (typeof output === 'string') {\n if (steps.value.length === 1) {\n answers[steps.value[0].id] = output\n }\n } else if (output.answers) {\n for (const a of output.answers) {\n answers[a.id] = a.value\n }\n }\n },\n { immediate: true },\n )\n\n // --- Restore custom answer from output when it doesn't match any option ---\n\n const normalizedOutput = computed(() => {\n const out = toolPart.value.output\n if (!out) return undefined\n if (typeof out === 'string') return out\n if (out.answers?.length === 1) {\n const val = out.answers[0].value\n return Array.isArray(val) ? val.join(', ') : String(val)\n }\n return undefined\n })\n\n watch(\n normalizedOutput,\n (value) => {\n if (!value || !currentStep.value) return\n const optionLabels = (currentStep.value.options ?? []).map(\n (o) => o.label,\n )\n if (!optionLabels.includes(value)) {\n customAnswer.value = value\n }\n },\n { immediate: true },\n )\n\n // --- Option mapping for radio/checkbox components ---\n\n const radioOptions = computed(() => {\n if (!currentStep.value?.options) return []\n return currentStep.value.options.map((option) => ({\n label: option.label,\n value: option.label,\n description: option.description,\n }))\n })\n\n // --- Navigation & Submission ---\n\n function goNext() {\n // A typed freeform answer wins over the picked option: it is the more\n // recent intent, and the footer button is now the visible way to send\n // it (the freeform field only submits on Enter).\n if (customAnswer.value.trim()) {\n submitCustomAnswer()\n return\n }\n if (canGoNext.value) {\n currentStepIndex.value++\n } else {\n submitForm()\n }\n }\n\n function goBack() {\n if (canGoBack.value) {\n currentStepIndex.value--\n }\n }\n\n function submitForm() {\n if (!isInteractive.value) return\n\n const finalAnswers: FormAnswer[] = steps.value.map((step) => ({\n id: step.id,\n value: answers[step.id] ?? null,\n }))\n\n // Legacy backward compatibility: single-step, single-select → return plain string\n if (\n isLegacyAutoSubmit.value &&\n !currentStep.value?.allowFreeformInput\n ) {\n const val = finalAnswers[0].value\n emit('select', Array.isArray(val) ? val[0] : (val as string))\n } else {\n emit('select', { answers: finalAnswers })\n }\n }\n\n function submitCustomAnswer() {\n const value = customAnswer.value.trim()\n if (!value) return\n\n answers[currentStep.value.id] = value\n // Cleared before navigating: `goNext()` reads it back to route a typed\n // answer here, so leaving it set would recurse.\n customAnswer.value = ''\n if (steps.value.length === 1) {\n submitForm()\n } else {\n goNext()\n }\n }\n\n function onRadioChange() {\n if (!isInteractive.value) return\n if (isAutoSubmitStep.value || isLegacyAutoSubmit.value) {\n submitForm()\n }\n }\n\n // --- Summary helpers ---\n\n function getSummaryValue(step: FormStep) {\n const val = answers[step.id]\n if (val == null) return '—'\n if (Array.isArray(val)) return val.join(', ')\n if (step.type === 'date') return $d(new Date(val), 'short')\n return val\n }\n</script>\n\n<template>\n <div\n v-if=\"steps.length\"\n class=\"border border-surface-3 rounded-xl w-full overflow-hidden flex flex-col transition-all bg-surface\">\n <!-- Header -->\n <div\n v-if=\"toolPart.input?.title || (isInteractive && steps.length > 1)\"\n class=\"text-12 border-b border-surface-3 text-word-3 bg-surface-1\">\n <div\n v-if=\"toolPart.input?.title\"\n class=\"px-sm py-10 font-bold\"\n :class=\"{\n 'border-b border-surface-3':\n isInteractive && steps.length > 1,\n }\">\n {{ toolPart.input?.title }}\n </div>\n <!-- Progress for multi-step -->\n <div\n v-if=\"isInteractive && steps.length > 1\"\n class=\"flex flex-col gap-4 p-sm\">\n <div class=\"flex justify-between text-10 text-word-3\">\n <span>\n {{\n $t('showForm.step', {\n current: currentStepIndex + 1,\n total: steps.length,\n })\n }}\n </span>\n <span>{{ progress }}%</span>\n </div>\n <div class=\"h-4 bg-surface-3 rounded-full overflow-hidden\">\n <div\n class=\"h-full bg-word-4 transition-all duration-300\"\n :style=\"{ width: `${progress}%` }\"></div>\n </div>\n </div>\n </div>\n\n <!-- Input Available State -->\n <template v-if=\"isInteractive\">\n <!-- Current Step Content -->\n <div class=\"px-sm py-16 flex flex-col gap-12\">\n <div class=\"leading-normal text-12\">\n <strong class=\"font-semibold\">\n {{ currentStep.question }}\n </strong>\n <PkStreamingMarkdown\n v-if=\"currentStep.message\"\n :markdown=\"currentStep.message\"\n class=\"text-word-2 mt-4\" />\n </div>\n\n <!-- Checkbox list for multi-select -->\n <PkEditorCheckboxButtons\n v-if=\"currentStep.options && currentStep.multiSelect\"\n v-model=\"activeCheckboxValue\"\n :name=\"currentStep.id\"\n :options=\"radioOptions\"\n :readonly=\"!isInteractive\"\n class=\"mb-0\"\n vertical>\n <template\n v-for=\"option in radioOptions\"\n :key=\"option.value\"\n #[option.value]>\n <!-- Shared option layout: label + optional description -->\n <div class=\"text-12\">\n <div class=\"font-semibold\">{{ option.label }}</div>\n <div v-if=\"option.description\" class=\"text-word-3\">\n {{ option.description }}\n </div>\n </div>\n </template>\n </PkEditorCheckboxButtons>\n\n <!-- Radio buttons for single-select -->\n <PkEditorRadioButtons\n v-else-if=\"currentStep.options && !currentStep.multiSelect\"\n v-model=\"scalarValue\"\n :name=\"currentStep.id\"\n :options=\"radioOptions\"\n :readonly=\"!isInteractive\"\n vertical\n class=\"mb-0\"\n @update:model-value=\"onRadioChange\">\n <template\n v-for=\"option in radioOptions\"\n :key=\"option.value\"\n #[option.value]>\n <!-- Shared option layout: label + optional description -->\n <div class=\"text-12\">\n <div class=\"font-semibold\">{{ option.label }}</div>\n <div v-if=\"option.description\" class=\"text-word-3\">\n {{ option.description }}\n </div>\n </div>\n </template>\n </PkEditorRadioButtons>\n\n <!-- Pure Freeform Input (text, number, date) -->\n <div\n v-else-if=\"!currentStep.options\"\n class=\"flex flex-col gap-6 w-full\">\n <VvInputText\n v-model=\"scalarValue\"\n :placeholder=\"\n currentStep.placeholder || $t('placeholder.insert')\n \"\n :type=\"currentStep.type\"\n class=\"w-full\"\n :name=\"currentStep.id\"\n modifiers=\"compact rounded\"\n :disabled=\"!isInteractive\"\n @keyup.enter=\"goNext\" />\n </div>\n </div>\n\n <!-- Custom footer freeform input (shown alongside options when allowFreeformInput) -->\n <div\n v-if=\"currentStep.allowFreeformInput && currentStep.options\"\n class=\"px-sm pb-sm border-t border-surface-3\">\n <form\n class=\"flex gap-xs pt-sm\"\n @submit.prevent=\"submitCustomAnswer\">\n <VvInputText\n v-model=\"customAnswer\"\n class=\"flex-1\"\n :name=\"`${currentStep.id}-custom`\"\n modifiers=\"compact rounded\"\n :disabled=\"!isInteractive\"\n :placeholder=\"\n currentStep.placeholder ||\n $t('showForm.otherPlaceholder')\n \" />\n </form>\n </div>\n\n <!-- Footer navigation: shown for every step that does not submit\n itself on option pick (see `isSelfSubmitting`). -->\n <div\n v-if=\"!isSelfSubmitting\"\n class=\"px-sm py-10 bg-surface border-t border-surface-3 flex justify-between gap-12\">\n <VvButton\n v-if=\"canGoBack\"\n modifiers=\"action-quiet\"\n icon=\"ri:arrow-left-s-line\"\n :label=\"$t('action.back')\"\n @click.stop=\"goBack\" />\n <div v-else></div>\n\n <VvButton\n :modifiers=\"canGoNext ? 'action-quiet' : 'action-primary'\"\n :icon=\"\n canGoNext\n ? 'ri:arrow-right-s-line'\n : 'ri:send-plane-2-line'\n \"\n icon-position=\"right\"\n :label=\"canGoNext ? $t('action.next') : $t('action.submit')\"\n @click.stop=\"goNext\" />\n </div>\n </template>\n\n <!-- Output Available State (Multi-step Summary) -->\n <template v-else>\n <div class=\"px-sm py-12 bg-surface space-y-10\">\n <ul class=\"flex flex-col gap-8\">\n <li\n v-for=\"step in steps\"\n :key=\"step.id\"\n class=\"leading-normal\">\n <div class=\"text-12 text-word-3\">\n {{ step.question }}\n </div>\n <span class=\"text-12 text-word-2 font-semibold\">\n {{ getSummaryValue(step) }}\n </span>\n </li>\n </ul>\n </div>\n <div\n class=\"px-sm py-12 bg-surface border-t border-surface-3 flex items-center gap-10\">\n <div\n class=\"w-20 h-20 rounded-full border border-success text-success flex items-center justify-center\">\n <VvIcon name=\"ri:check-line\" class=\"text-12\" />\n </div>\n <div class=\"flex flex-col\">\n <span\n class=\"font-semibold text-12 text-word-1 leading-tight\">\n {{ $t('showForm.completed') }}\n </span>\n </div>\n </div>\n </template>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;EAII,IAAM,IAAQ,GASR,IAAa,EAElB,GAAA,YAAC,GAEI,IAAiB,QAMZ,CAAC,GALS,EAAM,YACjB,MAAM,QAAQ,EAAM,SAAS,IACzB,EAAM,YACN,CAAC,EAAM,SAAS,IACpB,CAAC,GACc,QAAQ,CAChC;;;eAID,EAce,GAAA;gBAdQ,EAAA;6CAAU,QAAA;IAAG,MAAA,EAAA;IAAK,WAAU;;qBAEX,EAAA,EAAA,EAAA,GADpC,EAYU,GAAA,MAAA,EAXkB,EAAA,UAAhB,GAAQ,YADpB,EAYU,GAAA;KAVL;KACA,MAAA,EAAA;KACA,UAAA,EAAA;KACA,UAAA,EAAA;KACA,UAAA,EAAA;KACA,OAAO,EAAO;KACd,WAAW,EAAA;;sBAGL,CAFP,EAEO,EAAA,QAFM,EAAO,OAApB,EAEO,EAAA,SAAA,GAAA,GAAA,EAF8B,UAAM,CAAA,SAEpC,CAAA,EAAA,EADA,EAAO,KAAK,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;EE5B3B,IAAM,IAAa,EAAkC,GAAA,YAAC;;;eAItD,EAckB,GAAA;gBAdQ,EAAA;6CAAU,QAAA;IAAG,MAAA,EAAA;IAAK,WAAU;;qBAEd,EAAA,EAAA,EAAA,GADpC,EAYa,GAAA,MAAA,EAXe,EAAA,UAAhB,GAAQ,YADpB,EAYa,GAAA;KAVR;KACA,MAAA,EAAA;KACA,UAAA,EAAA;KACA,UAAA,EAAA;KACA,UAAA,EAAA;KACA,OAAO,EAAO;KACf,WAAU;;sBAGH,CAFP,EAEO,EAAA,QAFM,OAAO,EAAO,KAAK,GAAhC,EAEO,EAAA,SAAA,GAAA,GAAA,EAFsC,UAAM,CAAA,SAE5C,CAAA,EAAA,EADA,EAAO,KAAK,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEyB3B,IAAM,IAAQ,GAKR,IAAO,GAIP,EAAE,GAAG,GAAI,GAAG,MAAO,GAAQ,EAAE,UAAU,SAAS,CAAC,GAIjD,IAAW,QACP,KAAK,MAAM,KAAK,UAAU,EAAM,IAAI,CAAC,CAC/C,GAEM,IAAW,QAET,EAAS,MAAM,aAAa,wBAC5B,EAAS,MAAM,SAAS,yBAChC,GAEM,IAAgB,QACZ,EAAS,MAAM,UAAU,iBACnC,GAGM,IAAmB,QAAe;GACpC,IAAM,IAAO,EAAY;GAEzB,OADK,IAED,EAAM,MAAM,WAAW,KACvB,CAAC,EAAK,sBACN,CAAC,EAAM,oBAJO;EAMtB,CAAC,GAGK,IAAqB,QAEnB,EAAS,SACT,EAAM,MAAM,WAAW,KACvB,CAAC,EAAY,OAAO,WAC5B,GAUM,IAAmB,QAEjB,EAAQ,EAAY,OAAO,WAC3B,CAAC,EAAY,OAAO,gBACnB,EAAiB,SAAS,EAAmB,MACtD,GAIM,IAAQ,QAA2B;GACrC,IAAM,IAAQ,EAAS,MAAM;GAgB7B,OAfI,GAAO,OAAO,SACP,EAAM,QAGb,GAAO,YAAY,GAAO,UACnB,CACH;IACI,IAAI;IACJ,UAAU,EAAM;IAChB,SAAS,EAAM,QAAQ,KAAK,MACxB,OAAO,KAAM,WAAW,EAAE,OAAO,EAAE,IAAI,CAC3C;GACJ,CACJ,IAEG,CAAC;EACZ,CAAC,GAIK,IAAmB,EAAI,CAAC,GACxB,IAAc,QAAe,EAAM,MAAM,EAAiB,MAAM,GAChE,IAAY,QAAe,EAAiB,QAAQ,CAAC,GACrD,IAAY,QACR,EAAiB,QAAQ,EAAM,MAAM,SAAS,CACxD,GACM,KAAc,QAAe,EAAM,MAAM,SAAS,CAAC,GAEnD,IAAW,QACR,GAAY,QACV,KAAK,OACN,EAAiB,QAAQ,KAAK,EAAM,MAAM,SAAU,GAC1D,IAH+B,IAIlC,GAIK,IAAU,GAAsC,CAAC,CAAC,GAClD,IAAe,EAAI,EAAE,GAGrB,IAAc,EAAsC;GACtD,WAAW;IACP,IAAM,IAAM,EAAY,QAClB,EAAQ,EAAY,MAAM,MAC1B,KAAA;IACF,WAAO,QAAQ,MAAM,QAAQ,CAAG,IACpC,OAAO;GACX;GACA,MAAM,MAAQ;IACV,AAAI,EAAY,UACZ,EAAQ,EAAY,MAAM,MAAM,KAAO;GAE/C;EACJ,CAAC,GAEK,IAAsB,EAAgC;GACxD,WAAW;IACP,IAAM,IAAM,EAAY,QAClB,EAAQ,EAAY,MAAM,MAC1B,KAAA;IACN,OAAO,MAAM,QAAQ,CAAG,IAAI,IAAM,CAAC;GACvC;GACA,MAAM,MAAQ;IACV,AAAI,EAAY,UACZ,EAAQ,EAAY,MAAM,MAAO,KAAoB,CAAC;GAE9D;EACJ,CAAC;EAkCD,AA9BA,QACU,EAAS,MAAM,SACpB,MAAW;GACH,OACL;QAAI,OAAO,KAAW,UACd,EAAM,MAAM,WAAW,MACvB,EAAQ,EAAM,MAAM,EAAE,CAAC,MAAM;SAE9B,IAAI,EAAO,SACd,KAAK,IAAM,KAAK,EAAO,SACnB,EAAQ,EAAE,MAAM,EAAE;GAAA;EAG9B,GACA,EAAE,WAAW,GAAK,CACtB,GAeA,EAXyB,QAAe;GACpC,IAAM,IAAM,EAAS,MAAM;GACtB,OACL;QAAI,OAAO,KAAQ,UAAU,OAAO;IACpC,IAAI,EAAI,SAAS,WAAW,GAAG;KAC3B,IAAM,IAAM,EAAI,QAAQ,EAAE,CAAC;KAC3B,OAAO,MAAM,QAAQ,CAAG,IAAI,EAAI,KAAK,IAAI,IAAI,OAAO,CAAG;IAC3D;GAJoC;EAMxC,CAGI,IACC,MAAU;GACH,CAAC,KAAS,CAAC,EAAY,UACL,EAAY,MAAM,WAAW,CAAC,EAAA,CAAG,KAClD,MAAM,EAAE,KAER,CAAA,CAAa,SAAS,CAAK,MAC5B,EAAa,QAAQ;EAE7B,GACA,EAAE,WAAW,GAAK,CACtB;EAIA,IAAM,IAAe,QACZ,EAAY,OAAO,UACjB,EAAY,MAAM,QAAQ,KAAK,OAAY;GAC9C,OAAO,EAAO;GACd,OAAO,EAAO;GACd,aAAa,EAAO;EACxB,EAAE,IALsC,CAAC,CAM5C;EAID,SAAS,IAAS;GAId,IAAI,EAAa,MAAM,KAAK,GAAG;IAC3B,EAAmB;IACnB;GACJ;GACA,AAAI,EAAU,QACV,EAAiB,UAEjB,EAAW;EAEnB;EAEA,SAAS,KAAS;GACd,AAAI,EAAU,SACV,EAAiB;EAEzB;EAEA,SAAS,IAAa;GAClB,IAAI,CAAC,EAAc,OAAO;GAE1B,IAAM,IAA6B,EAAM,MAAM,KAAK,OAAU;IAC1D,IAAI,EAAK;IACT,OAAO,EAAQ,EAAK,OAAO;GAC/B,EAAE;GAGF,IACI,EAAmB,SACnB,CAAC,EAAY,OAAO,oBACtB;IACE,IAAM,IAAM,EAAa,EAAE,CAAC;IAC5B,EAAK,UAAU,MAAM,QAAQ,CAAG,IAAI,EAAI,KAAM,CAAc;GAChE,OACI,EAAK,UAAU,EAAE,SAAS,EAAa,CAAC;EAEhD;EAEA,SAAS,IAAqB;GAC1B,IAAM,IAAQ,EAAa,MAAM,KAAK;GACjC,MAEL,EAAQ,EAAY,MAAM,MAAM,GAGhC,EAAa,QAAQ,IACjB,EAAM,MAAM,WAAW,IACvB,EAAW,IAEX,EAAO;EAEf;EAEA,SAAS,KAAgB;GAChB,EAAc,UACf,EAAiB,SAAS,EAAmB,UAC7C,EAAW;EAEnB;EAIA,SAAS,GAAgB,GAAgB;GACrC,IAAM,IAAM,EAAQ,EAAK;GAIzB,OAHI,KAAO,OAAa,MACpB,MAAM,QAAQ,CAAG,IAAU,EAAI,KAAK,IAAI,IACxC,EAAK,SAAS,SAAe,EAAG,IAAI,KAAK,CAAG,GAAG,OAAO,IACnD;EACX;;;UAKU,EAAA,MAAM,UAAA,EAAA,GADhB,EAmMM,OAnMN,IAmMM,CA9LQ,EAAA,MAAS,OAAO,SAAU,EAAA,SAAiB,EAAA,MAAM,SAAM,KAAA,EAAA,GADjE,EAiCM,OAjCN,IAiCM,CA7BQ,EAAA,MAAS,OAAO,SAAA,EAAA,GAD1B,EAQM,OAAA;;IANF,OAAK,GAAA,CAAC,yBAAuB,EAAA,6BACsD,EAAA,SAAiB,EAAA,MAAM,SAAM,EAAA,CAAA,CAAA;QAI7G,EAAA,MAAS,OAAO,KAAK,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAIlB,EAAA,SAAiB,EAAA,MAAM,SAAM,KAAA,EAAA,GADvC,EAmBM,OAnBN,IAmBM,CAhBF,EAUM,OAVN,IAUM,CATF,EAOO,QAAA,MAAA,EALC,EAAA,CAAA,CAAE,CAAA,iBAAA;aAA6D,EAAA,QAAgB;WAA6C,EAAA,MAAM;YAM1I,EAA4B,QAAA,MAAA,EAAnB,EAAA,KAAQ,IAAG,KAAC,CAAA,CAAA,CAAA,GAEzB,EAIM,OAJN,IAIM,CAHF,EAE6C,OAAA;IADzC,OAAM;IACL,OAAK,GAAA,EAAA,OAAA,GAAc,EAAA,MAAQ,GAAA,CAAA;gDAM5B,EAAA,SAAA,EAAA,GAAhB,EA0HW,GAAA,EAAA,KAAA,EAAA,GAAA;IAxHP,EA0EM,OA1EN,IA0EM,CAzEF,EAQM,OARN,IAQM,CAPF,EAES,UAFT,IAES,EADF,EAAA,MAAY,QAAQ,GAAA,CAAA,GAGjB,EAAA,MAAY,WAAA,EAAA,GADtB,EAG+B,GAAA;;KAD1B,UAAU,EAAA,MAAY;KACvB,OAAM;8CAKJ,EAAA,MAAY,WAAW,EAAA,MAAY,eAAA,EAAA,GAD7C,EAoB0B,GAAA;;iBAlBb,EAAA;8CAAmB,QAAA;KAC3B,MAAM,EAAA,MAAY;KAClB,SAAS,EAAA;KACT,UAAQ,CAAG,EAAA;KACZ,OAAM;KACN,UAAA;sBAEqB,EAAA,QAAV;WAEN,EAAO;iBAOF,CALN,EAKM,OALN,IAKM,CAJF,EAAmD,OAAnD,IAAmD,EAArB,EAAO,KAAK,GAAA,CAAA,GAC/B,EAAO,eAAA,EAAA,GAAlB,EAEM,OAFN,IAEM,EADC,EAAO,WAAW,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA;;;;;;UAQtB,EAAA,MAAY,WAAO,CAAK,EAAA,MAAY,eAAA,EAAA,GADnD,EAqBuB,GAAA;;iBAnBV,EAAA;+CAAW,QAAA,GAMC,EAAA;KALpB,MAAM,EAAA,MAAY;KAClB,SAAS,EAAA;KACT,UAAQ,CAAG,EAAA;KACZ,UAAA;KACA,OAAM;sBAGe,EAAA,QAAV;WAEN,EAAO;iBAOF,CALN,EAKM,OALN,IAKM,CAJF,EAAmD,OAAnD,GAAmD,EAArB,EAAO,KAAK,GAAA,CAAA,GAC/B,EAAO,eAAA,EAAA,GAAlB,EAEM,OAFN,GAEM,EADC,EAAO,WAAW,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,CAAA,CAAA;;;;;;UAQrB,EAAA,MAAY,uBAAA,EAAA,GAD5B,EAcM,OAdN,GAcM,CAXF,EAU4B,GAAA;iBATf,EAAA;8CAAW,QAAA;KACnB,aAA0C,EAAA,MAAY,eAAe,EAAA,CAAA,CAAE,CAAA,oBAAA;KAGvE,MAAM,EAAA,MAAY;KACnB,OAAM;KACL,MAAM,EAAA,MAAY;KACnB,WAAU;KACT,UAAQ,CAAG,EAAA;KACX,SAAK,GAAQ,GAAM,CAAA,OAAA,CAAA;;;;;;;;IAMtB,EAAA,MAAY,sBAAsB,EAAA,MAAY,WAAA,EAAA,GADxD,EAiBM,OAjBN,GAiBM,CAdF,EAaO,QAAA;KAZH,OAAM;KACL,UAAM,EAAU,GAAkB,CAAA,SAAA,CAAA;QACnC,EASQ,GAAA;iBARK,EAAA;8CAAY,QAAA;KACrB,OAAM;KACL,MAAI,GAAK,EAAA,MAAY,GAAE;KACxB,WAAU;KACT,UAAQ,CAAG,EAAA;KACX,aAA0C,EAAA,MAAY,eAA2C,EAAA,CAAA,CAAE,CAAA,2BAAA;;;;;;;IAUrG,EAAA,qBAAA,EAAA,GADX,EAqBM,OArBN,GAqBM,CAjBQ,EAAA,SAAA,EAAA,GADV,EAK2B,GAAA;;KAHvB,WAAU;KACV,MAAK;KACJ,OAAO,EAAA,CAAA,CAAE,CAAA,aAAA;KACT,SAAK,EAAO,IAAM,CAAA,MAAA,CAAA;oCACvB,EAAkB,OAAA,EAAA,IAElB,EAS2B,GAAA;KARtB,WAAW,EAAA,QAAS,iBAAA;KACpB,MAA+B,EAAA,QAAA,0BAAA;KAKhC,iBAAc;KACb,OAAO,EAAA,QAAY,EAAA,CAAA,CAAE,CAAA,aAAA,IAAkB,EAAA,CAAA,CAAE,CAAA,eAAA;KACzC,SAAK,EAAO,GAAM,CAAA,MAAA,CAAA;;;;;;mBAK/B,EA6BW,GAAA,EAAA,KAAA,EAAA,GAAA,CA5BP,EAcM,OAdN,GAcM,CAbF,EAYK,MAZL,IAYK,EAAA,EAAA,EAAA,GAXD,EAUK,GAAA,MAAA,EATc,EAAA,QAAR,YADX,EAUK,MAAA;IARA,KAAK,EAAK;IACX,OAAM;OACN,EAEM,OAFN,IAEM,EADC,EAAK,QAAQ,GAAA,CAAA,GAEpB,EAEO,QAFP,IAEO,EADA,GAAgB,CAAI,CAAA,GAAA,CAAA,CAAA,CAAA,gBAKvC,EAYM,OAZN,IAYM,CAVF,EAGM,OAHN,IAGM,CADF,EAA+C,GAAA;IAAvC,MAAK;IAAgB,OAAM;SAEvC,EAKM,OALN,IAKM,CAJF,EAGO,QAHP,IAGO,EADA,EAAA,CAAA,CAAE,CAAA,oBAAA,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}