@kieksme/csp-plugin-chat 0.12.0 → 0.13.0

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/README.md CHANGED
@@ -31,3 +31,5 @@ Users can mark a chat **Problem gelöst** and start a new chat afterward. With a
31
31
  The assistant asks one short clarifying question for vague requests (for example “Hallo, meine Email”) before offering tickets. It uses supplied help/status facts and reserves ticket links for escalation or an explicit ticket request. Model behaviour requires a real-provider acceptance test.
32
32
 
33
33
  Long histories follow new messages while the visitor reads at the bottom; scrolling up preserves the reading position and offers **Neue Nachrichten ↓**. Real OpenAI providers expose editable dictation through the server-only transcription API. With a support transport, **Ich möchte mit einer echten Person sprechen** pauses the bot immediately and queues a persistent, directed support request. See [chat behaviour and APIs](../../docs/chat.md) and [runtime options](../../docs/configuration.md#spracheingabe-und-supportanfragen).
34
+
35
+ Both chat modes share a service-chat header and composer. Visitor messages align to the right, assistant and human replies to the left with visible sender labels. Customer theme colours, dark mode and mobile layouts apply throughout. See [chat design](../../docs/chat.md#gestaltung).
package/dist/browser.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cspPlugin
3
- } from "./chunk-DZ3YQB4V.js";
3
+ } from "./chunk-W5TFART7.js";
4
4
 
5
5
  // src/tools.ts
6
6
  import {
@@ -309,7 +309,7 @@ function sendShortcut(event, disabled) {
309
309
  function Shortcut({ id }) {
310
310
  const [mac, setMac] = useState(false);
311
311
  useEffect(() => setMac(/Mac|iPhone|iPad/.test(navigator.platform)), []);
312
- return /* @__PURE__ */ jsxs("span", { id, className: "block text-[0.6875rem] text-muted mt-2", children: [
312
+ return /* @__PURE__ */ jsxs("span", { id, className: "chat-shortcut", children: [
313
313
  mac ? "\u2318" : "Strg",
314
314
  " Enter zum Senden"
315
315
  ] });
@@ -353,15 +353,46 @@ function NewMessages({
353
353
  visible,
354
354
  follow
355
355
  }) {
356
- return visible ? /* @__PURE__ */ jsx(
357
- "button",
358
- {
359
- type: "button",
360
- className: "border border-line rounded-card px-3 py-2 mb-3 text-[0.8125rem]",
361
- onClick: follow,
362
- children: "Neue Nachrichten \u2193"
363
- }
364
- ) : null;
356
+ return visible ? /* @__PURE__ */ jsx("button", { type: "button", className: "chat-new-messages", onClick: follow, children: "Neue Nachrichten \u2193" }) : null;
357
+ }
358
+ function ChatHeading({
359
+ status,
360
+ state = "bot",
361
+ notice,
362
+ headingLevel = 2
363
+ }) {
364
+ const Heading = headingLevel === 2 ? "h2" : "h3";
365
+ return /* @__PURE__ */ jsxs("header", { className: "chat-heading", "data-state": state, children: [
366
+ /* @__PURE__ */ jsx("span", { className: "chat-emblem", "aria-hidden": "true", children: /* @__PURE__ */ jsxs(
367
+ "svg",
368
+ {
369
+ viewBox: "0 0 24 24",
370
+ fill: "none",
371
+ stroke: "currentColor",
372
+ strokeWidth: "1.6",
373
+ children: [
374
+ /* @__PURE__ */ jsx("path", { d: "M5 10a7 7 0 0 1 14 0v6a3 3 0 0 1-3 3h-4" }),
375
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "10", width: "4", height: "7", rx: "2" }),
376
+ /* @__PURE__ */ jsx("rect", { x: "17", y: "10", width: "4", height: "7", rx: "2" }),
377
+ /* @__PURE__ */ jsx("path", { d: "M10 19h3" })
378
+ ]
379
+ }
380
+ ) }),
381
+ /* @__PURE__ */ jsxs("div", { className: "chat-heading-copy", children: [
382
+ /* @__PURE__ */ jsx(Heading, { children: "Service-Chat" }),
383
+ /* @__PURE__ */ jsxs("p", { className: "chat-status", role: "status", children: [
384
+ /* @__PURE__ */ jsx("span", { className: "chat-status-dot", "aria-hidden": "true" }),
385
+ status
386
+ ] }),
387
+ notice && /* @__PURE__ */ jsx("p", { className: "chat-notice", children: notice })
388
+ ] })
389
+ ] });
390
+ }
391
+ function ChatWelcome() {
392
+ return /* @__PURE__ */ jsxs("div", { className: "chat-welcome", children: [
393
+ /* @__PURE__ */ jsx("p", { className: "chat-welcome-title", children: "Was k\xF6nnen wir f\xFCr Sie tun?" }),
394
+ /* @__PURE__ */ jsx("p", { children: "Beschreiben Sie kurz Ihr Anliegen. Wir helfen Ihnen Schritt f\xFCr Schritt weiter." })
395
+ ] });
365
396
  }
366
397
 
367
398
  // src/voice-input.tsx
@@ -543,12 +574,12 @@ function VoiceInput({
543
574
  }
544
575
  }
545
576
  if (!enabled) return null;
546
- return /* @__PURE__ */ jsxs2("div", { className: "mt-3 text-[0.8125rem]", children: [
577
+ return /* @__PURE__ */ jsxs2("div", { className: "chat-voice", "data-recording": state === "recording", children: [
547
578
  state === "idle" ? /* @__PURE__ */ jsxs2(
548
579
  "button",
549
580
  {
550
581
  type: "button",
551
- className: "border border-line rounded-card px-3 py-2",
582
+ className: "chat-voice-button",
552
583
  disabled,
553
584
  onClick: () => void start(),
554
585
  children: [
@@ -573,12 +604,12 @@ function VoiceInput({
573
604
  ]
574
605
  }
575
606
  ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
576
- /* @__PURE__ */ jsx2("span", { role: "status", children: state === "recording" ? "\u25CF Aufnahme l\xE4uft \xB7 maximal 60 Sekunden" : state === "starting" ? "Mikrofon wird gestartet \u2026" : "Sprache wird in Text umgewandelt \u2026" }),
607
+ /* @__PURE__ */ jsx2("span", { role: "status", className: "chat-voice-status", children: state === "recording" ? "\u25CF Aufnahme l\xE4uft \xB7 maximal 60 Sekunden" : state === "starting" ? "Mikrofon wird gestartet \u2026" : "Sprache wird in Text umgewandelt \u2026" }),
577
608
  state === "recording" && /* @__PURE__ */ jsx2(
578
609
  "button",
579
610
  {
580
611
  type: "button",
581
- className: "border border-line rounded-card px-3 py-2 ml-2",
612
+ className: "chat-voice-button",
582
613
  onClick: () => recorder.current?.stop(),
583
614
  children: "Aufnahme stoppen"
584
615
  }
@@ -587,7 +618,7 @@ function VoiceInput({
587
618
  "button",
588
619
  {
589
620
  type: "button",
590
- className: "underline ml-2",
621
+ className: "chat-voice-cancel",
591
622
  onClick: () => {
592
623
  operation.current++;
593
624
  cancelled.current = true;
@@ -601,7 +632,7 @@ function VoiceInput({
601
632
  }
602
633
  )
603
634
  ] }),
604
- /* @__PURE__ */ jsx2("p", { className: "text-[0.6875rem] text-muted mt-2", children: "Die Aufnahme wird zur Texterkennung an OpenAI gesendet. Pr\xFCfen Sie den Text vor dem Senden." }),
635
+ /* @__PURE__ */ jsx2("p", { className: "chat-voice-notice", children: "Die Aufnahme wird zur Texterkennung an OpenAI gesendet. Pr\xFCfen Sie den Text vor dem Senden." }),
605
636
  error && /* @__PURE__ */ jsx2("p", { role: "alert", className: "text-danger dark:text-warning mt-2", children: error })
606
637
  ] });
607
638
  }
@@ -825,25 +856,35 @@ function SupportChat(ctx) {
825
856
  }
826
857
  }
827
858
  return /* @__PURE__ */ jsxs3("div", { className: "chat-panel support-chat text-ink bg-card border border-line p-6 rounded-card compact:p-4", children: [
828
- /* @__PURE__ */ jsx3("p", { className: "text-[0.75rem] text-ink mb-3", children: demo ? "Synthetische Support-Demo. Keine \xDCbertragung an einen Support-Channel." : `Ihre Nachrichten und die Antworten werden an den Support in ${ctx.config.chatSupport?.mode === "slack" ? "Slack" : ctx.config.chatSupport?.mode === "telegram" ? "Telegram" : "Microsoft Teams"} weitergegeben.` }),
829
- /* @__PURE__ */ jsxs3("p", { role: "status", className: "text-[0.8125rem] mb-3", children: [
830
- current?.status === "support" ? `${current.support?.name} \xB7 Support` : current?.status === "waiting" ? current.supportRequest?.notification === "sent" ? "Support-Team informiert \xB7 KI pausiert" : current.supportRequest?.notification === "failed" ? "Zustellung verz\xF6gert \xB7 erneuter Versuch l\xE4uft \xB7 KI pausiert" : "Pers\xF6nlicher Support angefragt \xB7 KI pausiert" : current?.status === "closed" ? current.resolution ? "Problem gel\xF6st" : "Gespr\xE4ch abgeschlossen" : "Digitaler Assistent",
831
- auth && ready && !demo ? anonymous ? ` \xB7 ${auth.name}` : ` \xB7 Angemeldet als ${auth.name}` : ""
832
- ] }),
859
+ /* @__PURE__ */ jsx3(
860
+ ChatHeading,
861
+ {
862
+ headingLevel: ctx.surface === "hero" ? 2 : 3,
863
+ state: current?.status ?? "bot",
864
+ notice: demo ? "Synthetische Demo \xB7 keine Weiterleitung an den Support." : `Nachrichten werden mit dem Support in ${ctx.config.chatSupport?.mode === "slack" ? "Slack" : ctx.config.chatSupport?.mode === "telegram" ? "Telegram" : "Microsoft Teams"} geteilt.`,
865
+ status: /* @__PURE__ */ jsxs3(Fragment2, { children: [
866
+ current?.status === "support" ? `${current.support?.name} \xB7 Support` : current?.status === "waiting" ? current.supportRequest?.notification === "sent" ? "Support-Team informiert \xB7 KI pausiert" : current.supportRequest?.notification === "failed" ? "Zustellung verz\xF6gert \xB7 erneuter Versuch l\xE4uft \xB7 KI pausiert" : "Pers\xF6nlicher Support angefragt \xB7 KI pausiert" : current?.status === "closed" ? current.resolution ? "Problem gel\xF6st" : "Gespr\xE4ch abgeschlossen" : "Digitaler Assistent",
867
+ auth && ready && !demo ? anonymous ? ` \xB7 ${auth.name}` : ` \xB7 Angemeldet als ${auth.name}` : ""
868
+ ] })
869
+ }
870
+ ),
871
+ !current?.messages.length && /* @__PURE__ */ jsx3(ChatWelcome, {}),
833
872
  /* @__PURE__ */ jsx3(
834
873
  "div",
835
874
  {
836
875
  ref: scroll.history,
837
876
  onScroll: scroll.onScroll,
877
+ tabIndex: 0,
878
+ role: "log",
838
879
  className: "chat-history grid gap-3 max-h-[min(400px,45dvh)] overflow-auto overscroll-contain mb-4",
839
880
  "aria-live": "polite",
840
881
  "aria-label": "Gespr\xE4chsverlauf",
841
882
  children: current?.messages.map((m) => /* @__PURE__ */ jsxs3(
842
883
  "div",
843
884
  {
844
- className: `message ${m.kind === "user" ? "user bg-soft p-3 rounded-card" : "assistant border-l-2 border-accent pl-4"} text-[0.8125rem] whitespace-pre-wrap [overflow-wrap:anywhere]`,
885
+ className: `message ${m.kind === "user" ? "user" : m.kind === "system" ? "system" : m.kind === "support" ? "assistant human" : "assistant"} text-[0.8125rem] whitespace-pre-wrap [overflow-wrap:anywhere]`,
845
886
  children: [
846
- /* @__PURE__ */ jsx3("span", { className: "block text-[0.6875rem] text-ink mb-1", children: m.kind === "user" ? "Sie" : m.kind === "support" ? `${m.name} \xB7 Support` : m.kind === "bot" ? m.responder?.role === "on-duty" && m.responder.name ? `Digitaler Assistent von ${m.responder.name}` : "Digitaler Assistent des Service-Teams" : "Gespr\xE4ch" }),
887
+ /* @__PURE__ */ jsx3("span", { className: "chat-author", children: m.kind === "user" ? "Sie" : m.kind === "support" ? `${m.name} \xB7 Support` : m.kind === "bot" ? m.responder?.role === "on-duty" && m.responder.name ? `Digitaler Assistent von ${m.responder.name}` : "Digitaler Assistent des Service-Teams" : "Gespr\xE4ch" }),
847
888
  m.kind === "bot" ? answerParts(m.content, m.sources ?? [], !m.complete).map(
848
889
  (part, i) => part.href ? /* @__PURE__ */ jsx3(
849
890
  "a",
@@ -879,7 +920,7 @@ function SupportChat(ctx) {
879
920
  children: anonymous ? "Chat neu verbinden" : ctx.config.chatSupport?.auth === "session" ? "Portal-Anmeldung erneuern" : "Mit Microsoft anmelden"
880
921
  }
881
922
  ),
882
- ready && /* @__PURE__ */ jsxs3("div", { children: [
923
+ ready && /* @__PURE__ */ jsxs3("div", { className: "chat-composer", children: [
883
924
  /* @__PURE__ */ jsxs3("form", { onSubmit: submit, className: "chat-form flex gap-2.5 items-end", children: [
884
925
  /* @__PURE__ */ jsx3("label", { htmlFor: "support-chat-input", className: "sr-only", children: "Ihre Nachricht" }),
885
926
  /* @__PURE__ */ jsx3(
@@ -902,7 +943,7 @@ function SupportChat(ctx) {
902
943
  "button",
903
944
  {
904
945
  type: "submit",
905
- className: "bg-accent text-accent-ink rounded-card p-3",
946
+ className: "chat-send",
906
947
  disabled: blocked || !input.trim(),
907
948
  children: "Senden"
908
949
  }
@@ -921,21 +962,24 @@ function SupportChat(ctx) {
921
962
  }
922
963
  )
923
964
  ] }),
924
- ready && (!current || current.status === "bot") && /* @__PURE__ */ jsx3(
965
+ ready && (!current || current.status === "bot") && /* @__PURE__ */ jsxs3(
925
966
  "button",
926
967
  {
927
968
  type: "button",
928
- className: "border border-line rounded-card px-4 py-2 mt-3",
969
+ className: "chat-action chat-human-request",
929
970
  disabled: busy,
930
971
  onClick: () => void requestHuman(),
931
- children: "Ich m\xF6chte mit einer echten Person sprechen"
972
+ children: [
973
+ /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", className: "chat-action-icon", children: "\u2197" }),
974
+ "Ich m\xF6chte mit einer echten Person sprechen"
975
+ ]
932
976
  }
933
977
  ),
934
978
  ready && current && current.status !== "closed" && current.messages.some((m) => m.kind === "user") && /* @__PURE__ */ jsx3(
935
979
  "button",
936
980
  {
937
981
  type: "button",
938
- className: "border border-line rounded-card px-4 py-2 mt-3",
982
+ className: "chat-action",
939
983
  disabled: busy,
940
984
  onClick: () => void resolve(),
941
985
  children: "Problem gel\xF6st"
@@ -1153,104 +1197,104 @@ function LegacyChat(ctx) {
1153
1197
  /* @__PURE__ */ jsx4("p", { className: "data-state font-mono text-[0.625rem] text-muted m-[calc(var(--spacing)_*_3)_0_0] [&.warning]:text-warning", children: "\xD6ffentlicher Chat \xB7 Verlauf nur in dieser Sitzung" })
1154
1198
  ] }),
1155
1199
  /* @__PURE__ */ jsxs4("div", { className: "chat-panel text-ink compact:p-4 bg-card border border-line p-6 rounded-card", children: [
1156
- /* @__PURE__ */ jsxs4(
1200
+ /* @__PURE__ */ jsx4(
1201
+ ChatHeading,
1202
+ {
1203
+ headingLevel: ctx.surface === "hero" ? 2 : 3,
1204
+ state: resolved ? "closed" : "bot",
1205
+ status: resolved ? "Problem gel\xF6st" : "Digitaler Assistent",
1206
+ notice: "Ihre Frage wird automatisch beantwortet. Pers\xF6nlichen Kontakt finden Sie \xFCber die Hotline."
1207
+ }
1208
+ ),
1209
+ !messages.length && /* @__PURE__ */ jsx4(ChatWelcome, {}),
1210
+ /* @__PURE__ */ jsx4(
1157
1211
  "div",
1158
1212
  {
1159
1213
  ref: scroll.history,
1160
1214
  onScroll: scroll.onScroll,
1215
+ tabIndex: 0,
1216
+ role: "log",
1161
1217
  className: "chat-history empty:hidden grid gap-3.75 max-h-[min(400px,45dvh)] overflow-auto overscroll-contain mb-4",
1162
1218
  "aria-label": "Gespr\xE4chsverlauf",
1163
1219
  "aria-live": "polite",
1164
1220
  "aria-busy": busy,
1165
- children: [
1166
- !messages.length && ctx.surface !== "hero" && /* @__PURE__ */ jsx4("p", { className: "message assistant text-[0.8125rem] leading-[1.8] whitespace-pre-wrap [overflow-wrap:anywhere] [&.user]:bg-soft [&.user]:pt-3 [&.user]:pb-3 [&.user]:pl-4 [&.user]:pr-4 [&.user]:rounded-card [&.assistant]:[border-left:2px_solid_var(--accent)] [&.assistant]:pt-[0] [&.assistant]:pb-[0] [&.assistant]:pl-4 [&.assistant]:pr-4", children: "Wie kann ich Ihnen helfen?" }),
1167
- messages.map((m, i) => /* @__PURE__ */ jsxs4(
1168
- "div",
1169
- {
1170
- className: "message text-[0.8125rem] leading-[1.8] whitespace-pre-wrap [overflow-wrap:anywhere] [&.user]:bg-soft [&.user]:pt-3 [&.user]:pb-3 [&.user]:pl-4 [&.user]:pr-4 [&.user]:rounded-card [&.assistant]:[border-left:2px_solid_var(--accent)] [&.assistant]:pt-[0] [&.assistant]:pb-[0] [&.assistant]:pl-4 [&.assistant]:pr-4 " + m.role,
1171
- children: [
1172
- m.role === "user" ? /* @__PURE__ */ jsx4("span", { className: "sr-only", children: "Sie: " }) : /* @__PURE__ */ jsx4("span", { className: "block text-[0.6875rem] text-muted mb-1", children: m.responder?.role === "on-duty" && m.responder.name ? `Digitaler Assistent von ${m.responder.name}` : "Digitaler Assistent des Service-Teams" }),
1173
- m.role === "user" ? m.content : m.content ? answerParts(m.content, m.sources ?? [], !m.complete).map(
1174
- (part, index) => part.href ? /* @__PURE__ */ jsx4("a", { href: part.href, children: part.text }, index) : /* @__PURE__ */ jsx4("span", { children: part.text }, index)
1175
- ) : "Antwort wird vorbereitet \u2026",
1176
- m.role === "assistant" && !!m.sources?.length && /* @__PURE__ */ jsxs4("div", { className: "sources text-[0.6875rem] text-muted mt-3 mb-1 [&_a]:mr-3", children: [
1177
- "Referenzquellen:",
1178
- " ",
1179
- m.sources.map(
1180
- (source) => sourceHref(source.href) ? /* @__PURE__ */ jsxs4("a", { href: sourceHref(source.href), children: [
1181
- source.title,
1182
- source.stale ? " (veraltet)" : ""
1183
- ] }, source.id) : /* @__PURE__ */ jsxs4("span", { children: [
1184
- source.title,
1185
- " "
1186
- ] }, source.id)
1187
- )
1188
- ] })
1189
- ]
1190
- },
1191
- i
1192
- ))
1193
- ]
1221
+ children: messages.map((m, i) => /* @__PURE__ */ jsxs4("div", { className: "message " + m.role, children: [
1222
+ m.role === "user" ? /* @__PURE__ */ jsx4("span", { className: "chat-author", children: "Sie" }) : /* @__PURE__ */ jsx4("span", { className: "chat-author", children: m.responder?.role === "on-duty" && m.responder.name ? `Digitaler Assistent von ${m.responder.name}` : "Digitaler Assistent des Service-Teams" }),
1223
+ m.role === "user" ? m.content : m.content ? answerParts(m.content, m.sources ?? [], !m.complete).map(
1224
+ (part, index) => part.href ? /* @__PURE__ */ jsx4("a", { href: part.href, children: part.text }, index) : /* @__PURE__ */ jsx4("span", { children: part.text }, index)
1225
+ ) : "Antwort wird vorbereitet \u2026",
1226
+ m.role === "assistant" && !!m.sources?.length && /* @__PURE__ */ jsxs4("div", { className: "sources text-[0.6875rem] text-muted mt-3 mb-1 [&_a]:mr-3", children: [
1227
+ "Referenzquellen:",
1228
+ " ",
1229
+ m.sources.map(
1230
+ (source) => sourceHref(source.href) ? /* @__PURE__ */ jsxs4("a", { href: sourceHref(source.href), children: [
1231
+ source.title,
1232
+ source.stale ? " (veraltet)" : ""
1233
+ ] }, source.id) : /* @__PURE__ */ jsxs4("span", { children: [
1234
+ source.title,
1235
+ " "
1236
+ ] }, source.id)
1237
+ )
1238
+ ] })
1239
+ ] }, i))
1194
1240
  }
1195
1241
  ),
1196
1242
  /* @__PURE__ */ jsx4(NewMessages, { visible: scroll.unread, follow: scroll.follow }),
1197
- /* @__PURE__ */ jsxs4(
1198
- "form",
1199
- {
1200
- className: "chat-form flex gap-2.5 items-end [&_textarea]:resize-none [&_textarea]:min-h-[50px] [&_textarea]:[flex:1] [&_textarea]:min-w-0 [&_button]:bg-accent [&_button]:text-accent-ink [&_button]:[border:0] [&_button]:w-[50px] [&_button]:h-[50px] [&_button]:rounded-card [&_button]:text-[1.25rem] [&_button:disabled]:opacity-[0.5]",
1201
- onSubmit: submit,
1202
- children: [
1203
- /* @__PURE__ */ jsx4("label", { className: "sr-only", htmlFor: "chat-input", children: "Ihre Frage" }),
1204
- /* @__PURE__ */ jsxs4("div", { className: "relative flex-1 min-w-0", children: [
1205
- /* @__PURE__ */ jsx4(
1206
- "textarea",
1207
- {
1208
- id: "chat-input",
1209
- ref: inputField,
1210
- rows: 1,
1211
- autoFocus: true,
1212
- className: "search bg-card border border-line rounded-card pt-3.5 pb-7 px-4.5 text-ink w-full block max-h-[180px] overflow-auto",
1213
- value: input,
1214
- disabled: resolved,
1215
- maxLength: 4e3,
1216
- onChange: (e) => setInput(e.target.value),
1217
- onKeyDown: (e) => sendShortcut(e, busy || voiceBusy || resolved || !input.trim()),
1218
- "aria-keyshortcuts": "Control+Enter Meta+Enter",
1219
- "aria-describedby": "chat-shortcut",
1220
- placeholder: "Ihre Frage an unser Team \u2026",
1221
- required: true
1222
- }
1223
- ),
1224
- /* @__PURE__ */ jsx4(Shortcut, { id: "chat-shortcut" })
1225
- ] }),
1243
+ /* @__PURE__ */ jsxs4("div", { className: "chat-composer", children: [
1244
+ /* @__PURE__ */ jsxs4("form", { className: "chat-form flex gap-2.5 items-end", onSubmit: submit, children: [
1245
+ /* @__PURE__ */ jsx4("label", { className: "sr-only", htmlFor: "chat-input", children: "Ihre Frage" }),
1246
+ /* @__PURE__ */ jsxs4("div", { className: "relative flex-1 min-w-0", children: [
1226
1247
  /* @__PURE__ */ jsx4(
1227
- "button",
1248
+ "textarea",
1228
1249
  {
1229
- type: "submit",
1230
- disabled: busy || voiceBusy || resolved || !input.trim(),
1231
- "aria-label": "Frage senden",
1232
- children: "\u2191"
1250
+ id: "chat-input",
1251
+ ref: inputField,
1252
+ rows: 1,
1253
+ autoFocus: true,
1254
+ className: "search bg-card border border-line rounded-card pt-3.5 pb-7 px-4.5 text-ink w-full block max-h-[180px] overflow-auto",
1255
+ value: input,
1256
+ disabled: resolved,
1257
+ maxLength: 4e3,
1258
+ onChange: (e) => setInput(e.target.value),
1259
+ onKeyDown: (e) => sendShortcut(
1260
+ e,
1261
+ busy || voiceBusy || resolved || !input.trim()
1262
+ ),
1263
+ "aria-keyshortcuts": "Control+Enter Meta+Enter",
1264
+ "aria-describedby": "chat-shortcut",
1265
+ placeholder: "Ihre Frage an unser Team \u2026",
1266
+ required: true
1233
1267
  }
1234
- )
1235
- ]
1236
- }
1237
- ),
1238
- /* @__PURE__ */ jsx4(
1239
- VoiceInput,
1240
- {
1241
- ctx,
1242
- value: input,
1243
- setValue: setInput,
1244
- disabled: resolved,
1245
- onBusy: setVoiceBusy
1246
- }
1247
- ),
1248
- ctx.surface === "hero" && /* @__PURE__ */ jsx4("p", { className: "data-state font-mono text-[0.625rem] text-muted mt-3 mb-0", children: "Digitaler Assistent \xB7 Ihre Frage wird automatisch beantwortet. F\xFCr pers\xF6nlichen Kontakt nutzen Sie die Hotline." }),
1268
+ ),
1269
+ /* @__PURE__ */ jsx4(Shortcut, { id: "chat-shortcut" })
1270
+ ] }),
1271
+ /* @__PURE__ */ jsx4(
1272
+ "button",
1273
+ {
1274
+ type: "submit",
1275
+ disabled: busy || voiceBusy || resolved || !input.trim(),
1276
+ className: "chat-send",
1277
+ "aria-label": "Frage senden",
1278
+ children: "Senden"
1279
+ }
1280
+ )
1281
+ ] }),
1282
+ /* @__PURE__ */ jsx4(
1283
+ VoiceInput,
1284
+ {
1285
+ ctx,
1286
+ value: input,
1287
+ setValue: setInput,
1288
+ disabled: resolved,
1289
+ onBusy: setVoiceBusy
1290
+ }
1291
+ )
1292
+ ] }),
1249
1293
  messages.length > 0 && !resolved && /* @__PURE__ */ jsx4(
1250
1294
  "button",
1251
1295
  {
1252
1296
  type: "button",
1253
- className: "border border-line rounded-card px-4 py-2 mt-3",
1297
+ className: "chat-action",
1254
1298
  onClick: () => {
1255
1299
  abort.current?.abort();
1256
1300
  setResolved(true);
@@ -1269,25 +1313,22 @@ function LegacyChat(ctx) {
1269
1313
  children: "Problem gel\xF6st"
1270
1314
  }
1271
1315
  ),
1272
- resolved && /* @__PURE__ */ jsxs4("div", { className: "mt-3", children: [
1273
- /* @__PURE__ */ jsx4("p", { role: "status", children: "Problem gel\xF6st" }),
1274
- /* @__PURE__ */ jsx4(
1275
- "button",
1276
- {
1277
- type: "button",
1278
- className: "underline mt-2",
1279
- disabled: busy,
1280
- onClick: () => {
1281
- scroll.follow();
1282
- setMessages([]);
1283
- setResolved(false);
1284
- setInput("");
1285
- setError("");
1286
- },
1287
- children: "Neuen Chat starten"
1288
- }
1289
- )
1290
- ] }),
1316
+ resolved && /* @__PURE__ */ jsx4("div", { className: "mt-3", children: /* @__PURE__ */ jsx4(
1317
+ "button",
1318
+ {
1319
+ type: "button",
1320
+ className: "underline mt-2",
1321
+ disabled: busy,
1322
+ onClick: () => {
1323
+ scroll.follow();
1324
+ setMessages([]);
1325
+ setResolved(false);
1326
+ setInput("");
1327
+ setError("");
1328
+ },
1329
+ children: "Neuen Chat starten"
1330
+ }
1331
+ ) }),
1291
1332
  error && /* @__PURE__ */ jsx4(
1292
1333
  "p",
1293
1334
  {
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var cspPlugin = {
3
3
  id: "chat",
4
- sdkVersion: "^0.12.0",
4
+ sdkVersion: "^0.13.0",
5
5
  browser: "./browser",
6
6
  server: "./server"
7
7
  };
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cspPlugin
3
- } from "./chunk-DZ3YQB4V.js";
3
+ } from "./chunk-W5TFART7.js";
4
4
 
5
5
  // src/server.ts
6
6
  import { z as z2 } from "zod";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kieksme/csp-plugin-chat",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@azure/msal-browser": "^5.25.0",
26
- "@kieksme/csp-sdk": "^0.12.0",
26
+ "@kieksme/csp-sdk": "^0.13.0",
27
27
  "openai": "^6.3.0",
28
28
  "zod": "^3.25.76"
29
29
  },
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "cspPlugin": {
37
37
  "id": "chat",
38
- "sdkVersion": "^0.12.0",
38
+ "sdkVersion": "^0.13.0",
39
39
  "browser": "./browser",
40
40
  "server": "./server"
41
41
  },