@kieksme/csp-plugin-chat 0.13.1 → 0.13.2

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
@@ -34,4 +34,4 @@ Long histories follow new messages while the visitor reads at the bottom; scroll
34
34
 
35
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).
36
36
 
37
- Dictation uses an icon-only microphone button with the accessible name and tooltip “Nachricht diktieren”. Its privacy notice stays visible alongside the button, and mobile touch targets remain 44 × 44 px.
37
+ Dictation uses an icon-only microphone button with the accessible name and tooltip “Nachricht diktieren”. The microphone sits directly beside Send in the composer toolbar. Its privacy notice stays visible underneath, and mobile touch targets remain 44 × 44 px.
package/dist/browser.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  cspPlugin
3
- } from "./chunk-B7EKNOQK.js";
3
+ } from "./chunk-OGWLCI3O.js";
4
4
 
5
5
  // src/tools.ts
6
6
  import {
@@ -404,7 +404,8 @@ function VoiceInput({
404
404
  setValue,
405
405
  disabled,
406
406
  token,
407
- onBusy
407
+ onBusy,
408
+ children
408
409
  }) {
409
410
  const [enabled, setEnabled] = useState2(false), [state, setState] = useState2("idle"), [error, setError] = useState2("");
410
411
  const recorder = useRef2(null), stream = useRef2(null), timer = useRef2(null), request = useRef2(null);
@@ -573,74 +574,75 @@ function VoiceInput({
573
574
  }
574
575
  }
575
576
  }
576
- if (!enabled) return null;
577
- return /* @__PURE__ */ jsxs2(
577
+ if (!enabled) return children(null, null);
578
+ const controls = state === "idle" ? /* @__PURE__ */ jsx2(
579
+ "button",
580
+ {
581
+ type: "button",
582
+ className: "chat-voice-button chat-microphone",
583
+ "aria-label": "Nachricht diktieren",
584
+ title: "Nachricht diktieren",
585
+ disabled,
586
+ onClick: () => void start(),
587
+ children: /* @__PURE__ */ jsxs2(
588
+ "svg",
589
+ {
590
+ "aria-hidden": "true",
591
+ viewBox: "0 0 24 24",
592
+ width: "16",
593
+ height: "16",
594
+ fill: "none",
595
+ stroke: "currentColor",
596
+ strokeWidth: "2",
597
+ children: [
598
+ /* @__PURE__ */ jsx2("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
599
+ /* @__PURE__ */ jsx2("path", { d: "M5 10v2a7 7 0 0 0 14 0v-2M12 19v3M8 22h8" })
600
+ ]
601
+ }
602
+ )
603
+ }
604
+ ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
605
+ state === "recording" && /* @__PURE__ */ jsx2(
606
+ "button",
607
+ {
608
+ type: "button",
609
+ className: "chat-voice-button",
610
+ onClick: () => recorder.current?.stop(),
611
+ children: "Aufnahme stoppen"
612
+ }
613
+ ),
614
+ /* @__PURE__ */ jsx2(
615
+ "button",
616
+ {
617
+ type: "button",
618
+ className: "chat-voice-cancel",
619
+ onClick: () => {
620
+ operation.current++;
621
+ cancelled.current = true;
622
+ request.current?.abort();
623
+ if (recorder.current?.state === "recording")
624
+ recorder.current.stop();
625
+ release();
626
+ idle();
627
+ },
628
+ children: "Abbrechen"
629
+ }
630
+ )
631
+ ] });
632
+ const details = /* @__PURE__ */ jsxs2(
578
633
  "div",
579
634
  {
580
635
  className: "chat-voice",
581
636
  "data-state": state,
582
637
  "data-recording": state === "recording",
583
638
  children: [
584
- state === "idle" ? /* @__PURE__ */ jsx2(
585
- "button",
586
- {
587
- type: "button",
588
- className: "chat-voice-button chat-microphone",
589
- "aria-label": "Nachricht diktieren",
590
- title: "Nachricht diktieren",
591
- disabled,
592
- onClick: () => void start(),
593
- children: /* @__PURE__ */ jsxs2(
594
- "svg",
595
- {
596
- "aria-hidden": "true",
597
- viewBox: "0 0 24 24",
598
- width: "16",
599
- height: "16",
600
- fill: "none",
601
- stroke: "currentColor",
602
- strokeWidth: "2",
603
- children: [
604
- /* @__PURE__ */ jsx2("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
605
- /* @__PURE__ */ jsx2("path", { d: "M5 10v2a7 7 0 0 0 14 0v-2M12 19v3M8 22h8" })
606
- ]
607
- }
608
- )
609
- }
610
- ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
611
- /* @__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" }),
612
- state === "recording" && /* @__PURE__ */ jsx2(
613
- "button",
614
- {
615
- type: "button",
616
- className: "chat-voice-button",
617
- onClick: () => recorder.current?.stop(),
618
- children: "Aufnahme stoppen"
619
- }
620
- ),
621
- /* @__PURE__ */ jsx2(
622
- "button",
623
- {
624
- type: "button",
625
- className: "chat-voice-cancel",
626
- onClick: () => {
627
- operation.current++;
628
- cancelled.current = true;
629
- request.current?.abort();
630
- if (recorder.current?.state === "recording")
631
- recorder.current.stop();
632
- release();
633
- idle();
634
- },
635
- children: "Abbrechen"
636
- }
637
- )
638
- ] }),
639
+ state !== "idle" && /* @__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" }),
639
640
  /* @__PURE__ */ jsx2("p", { className: "chat-voice-notice", children: "Die Aufnahme wird zur Texterkennung an OpenAI gesendet. Pr\xFCfen Sie den Text vor dem Senden." }),
640
641
  error && /* @__PURE__ */ jsx2("p", { role: "alert", className: "text-danger dark:text-warning mt-2", children: error })
641
642
  ]
642
643
  }
643
644
  );
645
+ return children(controls, details);
644
646
  }
645
647
 
646
648
  // src/support-chat.tsx
@@ -926,48 +928,61 @@ function SupportChat(ctx) {
926
928
  children: anonymous ? "Chat neu verbinden" : ctx.config.chatSupport?.auth === "session" ? "Portal-Anmeldung erneuern" : "Mit Microsoft anmelden"
927
929
  }
928
930
  ),
929
- ready && /* @__PURE__ */ jsxs3("div", { className: "chat-composer", children: [
930
- /* @__PURE__ */ jsxs3("form", { onSubmit: submit, className: "chat-form flex gap-2.5 items-end", children: [
931
- /* @__PURE__ */ jsx3("label", { htmlFor: "support-chat-input", className: "sr-only", children: "Ihre Nachricht" }),
932
- /* @__PURE__ */ jsx3(
933
- "textarea",
934
- {
935
- id: "support-chat-input",
936
- value: input,
937
- rows: 2,
938
- maxLength: 4e3,
939
- disabled: current?.status === "closed",
940
- className: "flex-1 min-w-0 max-h-[180px] overflow-auto resize-none border border-line rounded-card bg-card p-3",
941
- onChange: (e) => setInput(e.target.value),
942
- onKeyDown: (e) => sendShortcut(e, blocked || !input.trim()),
943
- "aria-keyshortcuts": "Control+Enter Meta+Enter",
944
- "aria-describedby": "support-chat-shortcut",
945
- placeholder: "Wie k\xF6nnen wir Ihnen helfen?"
946
- }
947
- ),
948
- /* @__PURE__ */ jsx3(
949
- "button",
950
- {
951
- type: "submit",
952
- className: "chat-send",
953
- disabled: blocked || !input.trim(),
954
- children: "Senden"
955
- }
956
- )
957
- ] }),
958
- /* @__PURE__ */ jsx3(Shortcut, { id: "support-chat-shortcut" }),
959
- /* @__PURE__ */ jsx3(
960
- VoiceInput,
961
- {
962
- ctx,
963
- value: input,
964
- setValue: setInput,
965
- disabled: current?.status === "closed",
966
- token: auth?.token,
967
- onBusy: setVoiceBusy
968
- }
969
- )
970
- ] }),
931
+ ready && /* @__PURE__ */ jsx3("div", { className: "chat-composer", children: /* @__PURE__ */ jsx3(
932
+ VoiceInput,
933
+ {
934
+ ctx,
935
+ value: input,
936
+ setValue: setInput,
937
+ disabled: current?.status === "closed",
938
+ token: auth?.token,
939
+ onBusy: setVoiceBusy,
940
+ children: (controls, details) => /* @__PURE__ */ jsxs3(Fragment2, { children: [
941
+ /* @__PURE__ */ jsxs3(
942
+ "form",
943
+ {
944
+ onSubmit: submit,
945
+ className: "chat-form flex gap-2.5 items-end",
946
+ children: [
947
+ /* @__PURE__ */ jsx3("label", { htmlFor: "support-chat-input", className: "sr-only", children: "Ihre Nachricht" }),
948
+ /* @__PURE__ */ jsx3(
949
+ "textarea",
950
+ {
951
+ id: "support-chat-input",
952
+ value: input,
953
+ rows: 2,
954
+ maxLength: 4e3,
955
+ disabled: current?.status === "closed",
956
+ className: "flex-1 min-w-0 max-h-[180px] overflow-auto resize-none border border-line rounded-card bg-card p-3",
957
+ onChange: (e) => setInput(e.target.value),
958
+ onKeyDown: (e) => sendShortcut(e, blocked || !input.trim()),
959
+ "aria-keyshortcuts": "Control+Enter Meta+Enter",
960
+ "aria-describedby": "support-chat-shortcut",
961
+ placeholder: "Wie k\xF6nnen wir Ihnen helfen?"
962
+ }
963
+ ),
964
+ /* @__PURE__ */ jsxs3("div", { className: "chat-compose-toolbar", children: [
965
+ /* @__PURE__ */ jsx3(Shortcut, { id: "support-chat-shortcut" }),
966
+ /* @__PURE__ */ jsxs3("div", { className: "chat-compose-actions", children: [
967
+ controls,
968
+ /* @__PURE__ */ jsx3(
969
+ "button",
970
+ {
971
+ type: "submit",
972
+ className: "chat-send",
973
+ disabled: blocked || !input.trim(),
974
+ children: "Senden"
975
+ }
976
+ )
977
+ ] })
978
+ ] })
979
+ ]
980
+ }
981
+ ),
982
+ details
983
+ ] })
984
+ }
985
+ ) }),
971
986
  ready && (!current || current.status === "bot") && /* @__PURE__ */ jsxs3(
972
987
  "button",
973
988
  {
@@ -1062,7 +1077,7 @@ function SupportChat(ctx) {
1062
1077
  }
1063
1078
 
1064
1079
  // src/browser.tsx
1065
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1080
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1066
1081
  function resizeInput(field) {
1067
1082
  if (!field) return;
1068
1083
  field.style.height = "auto";
@@ -1246,56 +1261,67 @@ function LegacyChat(ctx) {
1246
1261
  }
1247
1262
  ),
1248
1263
  /* @__PURE__ */ jsx4(NewMessages, { visible: scroll.unread, follow: scroll.follow }),
1249
- /* @__PURE__ */ jsxs4("div", { className: "chat-composer", children: [
1250
- /* @__PURE__ */ jsxs4("form", { className: "chat-form flex gap-2.5 items-end", onSubmit: submit, children: [
1251
- /* @__PURE__ */ jsx4("label", { className: "sr-only", htmlFor: "chat-input", children: "Ihre Frage" }),
1252
- /* @__PURE__ */ jsxs4("div", { className: "relative flex-1 min-w-0", children: [
1253
- /* @__PURE__ */ jsx4(
1254
- "textarea",
1264
+ /* @__PURE__ */ jsx4("div", { className: "chat-composer", children: /* @__PURE__ */ jsx4(
1265
+ VoiceInput,
1266
+ {
1267
+ ctx,
1268
+ value: input,
1269
+ setValue: setInput,
1270
+ disabled: resolved,
1271
+ onBusy: setVoiceBusy,
1272
+ children: (controls, details) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
1273
+ /* @__PURE__ */ jsxs4(
1274
+ "form",
1255
1275
  {
1256
- id: "chat-input",
1257
- ref: inputField,
1258
- rows: 1,
1259
- autoFocus: true,
1260
- 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",
1261
- value: input,
1262
- disabled: resolved,
1263
- maxLength: 4e3,
1264
- onChange: (e) => setInput(e.target.value),
1265
- onKeyDown: (e) => sendShortcut(
1266
- e,
1267
- busy || voiceBusy || resolved || !input.trim()
1268
- ),
1269
- "aria-keyshortcuts": "Control+Enter Meta+Enter",
1270
- "aria-describedby": "chat-shortcut",
1271
- placeholder: "Ihre Frage an unser Team \u2026",
1272
- required: true
1276
+ className: "chat-form flex gap-2.5 items-end",
1277
+ onSubmit: submit,
1278
+ children: [
1279
+ /* @__PURE__ */ jsx4("label", { className: "sr-only", htmlFor: "chat-input", children: "Ihre Frage" }),
1280
+ /* @__PURE__ */ jsx4(
1281
+ "textarea",
1282
+ {
1283
+ id: "chat-input",
1284
+ ref: inputField,
1285
+ rows: 1,
1286
+ autoFocus: true,
1287
+ 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",
1288
+ value: input,
1289
+ disabled: resolved,
1290
+ maxLength: 4e3,
1291
+ onChange: (e) => setInput(e.target.value),
1292
+ onKeyDown: (e) => sendShortcut(
1293
+ e,
1294
+ busy || voiceBusy || resolved || !input.trim()
1295
+ ),
1296
+ "aria-keyshortcuts": "Control+Enter Meta+Enter",
1297
+ "aria-describedby": "chat-shortcut",
1298
+ placeholder: "Ihre Frage an unser Team \u2026",
1299
+ required: true
1300
+ }
1301
+ ),
1302
+ /* @__PURE__ */ jsxs4("div", { className: "chat-compose-toolbar", children: [
1303
+ /* @__PURE__ */ jsx4(Shortcut, { id: "chat-shortcut" }),
1304
+ /* @__PURE__ */ jsxs4("div", { className: "chat-compose-actions", children: [
1305
+ controls,
1306
+ /* @__PURE__ */ jsx4(
1307
+ "button",
1308
+ {
1309
+ type: "submit",
1310
+ disabled: busy || voiceBusy || resolved || !input.trim(),
1311
+ className: "chat-send",
1312
+ "aria-label": "Frage senden",
1313
+ children: "Senden"
1314
+ }
1315
+ )
1316
+ ] })
1317
+ ] })
1318
+ ]
1273
1319
  }
1274
1320
  ),
1275
- /* @__PURE__ */ jsx4(Shortcut, { id: "chat-shortcut" })
1276
- ] }),
1277
- /* @__PURE__ */ jsx4(
1278
- "button",
1279
- {
1280
- type: "submit",
1281
- disabled: busy || voiceBusy || resolved || !input.trim(),
1282
- className: "chat-send",
1283
- "aria-label": "Frage senden",
1284
- children: "Senden"
1285
- }
1286
- )
1287
- ] }),
1288
- /* @__PURE__ */ jsx4(
1289
- VoiceInput,
1290
- {
1291
- ctx,
1292
- value: input,
1293
- setValue: setInput,
1294
- disabled: resolved,
1295
- onBusy: setVoiceBusy
1296
- }
1297
- )
1298
- ] }),
1321
+ details
1322
+ ] })
1323
+ }
1324
+ ) }),
1299
1325
  messages.length > 0 && !resolved && /* @__PURE__ */ jsx4(
1300
1326
  "button",
1301
1327
  {
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var cspPlugin = {
3
3
  id: "chat",
4
- sdkVersion: "^0.13.1",
4
+ sdkVersion: "^0.13.2",
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-B7EKNOQK.js";
3
+ } from "./chunk-OGWLCI3O.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.13.1",
3
+ "version": "0.13.2",
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.13.1",
26
+ "@kieksme/csp-sdk": "^0.13.2",
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.13.1",
38
+ "sdkVersion": "^0.13.2",
39
39
  "browser": "./browser",
40
40
  "server": "./server"
41
41
  },