@k2b/ui 0.39.0 → 0.41.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.
Files changed (98) hide show
  1. package/dist/browser/chat/ChatComposer.js +759 -570
  2. package/dist/browser/chat/ChatComposer.js.map +1 -1
  3. package/dist/browser/inputs/ChoiceGroups.js +30 -18
  4. package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
  5. package/dist/browser/inputs/Select.js +32 -19
  6. package/dist/browser/inputs/Select.js.map +1 -1
  7. package/dist/browser/inputs/SpecialInputs.js +54 -25
  8. package/dist/browser/inputs/SpecialInputs.js.map +1 -1
  9. package/dist/browser/inputs/choice.js +4 -1
  10. package/dist/browser/inputs/choice.js.map +1 -1
  11. package/dist/browser/inputs/dictation/Dictation.js +546 -0
  12. package/dist/browser/inputs/dictation/Dictation.js.map +1 -0
  13. package/dist/browser/inputs/dictation/create-dictation.js +324 -0
  14. package/dist/browser/inputs/dictation/create-dictation.js.map +1 -0
  15. package/dist/browser/inputs/dictation/dictation-messages.js +115 -0
  16. package/dist/browser/inputs/dictation/dictation-messages.js.map +1 -0
  17. package/dist/browser/inputs/dictation/text-dictation.js +152 -0
  18. package/dist/browser/inputs/dictation/text-dictation.js.map +1 -0
  19. package/dist/browser/inputs/dictation/types.js +2 -0
  20. package/dist/browser/inputs/dictation/types.js.map +1 -0
  21. package/dist/browser/inputs/icon-messages.js +29 -2
  22. package/dist/browser/inputs/icon-messages.js.map +1 -1
  23. package/dist/browser/inputs/icon-texts.js +172 -0
  24. package/dist/browser/inputs/icon-texts.js.map +1 -0
  25. package/dist/browser/inputs/index.js +2 -0
  26. package/dist/browser/inputs/index.js.map +1 -1
  27. package/dist/browser/layout/AnchoredPopover.js +1 -1
  28. package/dist/browser/layout/AnchoredPopover.js.map +1 -1
  29. package/dist/browser/layout/AppWorkspace.js +31 -17
  30. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  31. package/dist/browser/layout/SettingsModal.js +10 -5
  32. package/dist/browser/layout/SettingsModal.js.map +1 -1
  33. package/dist/browser/layout/app-workspace-controller.js +49 -5
  34. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  35. package/dist/browser/text-editor/TextEditor.js +74 -25
  36. package/dist/browser/text-editor/TextEditor.js.map +1 -1
  37. package/dist/browser/text-editor/dictation.js +166 -0
  38. package/dist/browser/text-editor/dictation.js.map +1 -0
  39. package/dist/browser/text-editor.js +1 -0
  40. package/dist/browser/text-editor.js.map +1 -1
  41. package/dist/ssr/chat/ChatComposer.js +271 -99
  42. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  43. package/dist/ssr/inputs/ChoiceGroups.js +12 -3
  44. package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
  45. package/dist/ssr/inputs/Select.js +8 -2
  46. package/dist/ssr/inputs/Select.js.map +1 -1
  47. package/dist/ssr/inputs/SpecialInputs.js +54 -25
  48. package/dist/ssr/inputs/SpecialInputs.js.map +1 -1
  49. package/dist/ssr/inputs/choice.js +4 -1
  50. package/dist/ssr/inputs/choice.js.map +1 -1
  51. package/dist/ssr/inputs/dictation/Dictation.js +386 -0
  52. package/dist/ssr/inputs/dictation/Dictation.js.map +1 -0
  53. package/dist/ssr/inputs/dictation/create-dictation.js +324 -0
  54. package/dist/ssr/inputs/dictation/create-dictation.js.map +1 -0
  55. package/dist/ssr/inputs/dictation/dictation-messages.js +115 -0
  56. package/dist/ssr/inputs/dictation/dictation-messages.js.map +1 -0
  57. package/dist/ssr/inputs/dictation/text-dictation.js +152 -0
  58. package/dist/ssr/inputs/dictation/text-dictation.js.map +1 -0
  59. package/dist/ssr/inputs/dictation/types.js +2 -0
  60. package/dist/ssr/inputs/dictation/types.js.map +1 -0
  61. package/dist/ssr/inputs/icon-messages.js +29 -2
  62. package/dist/ssr/inputs/icon-messages.js.map +1 -1
  63. package/dist/ssr/inputs/icon-texts.js +172 -0
  64. package/dist/ssr/inputs/icon-texts.js.map +1 -0
  65. package/dist/ssr/inputs/index.js +2 -0
  66. package/dist/ssr/inputs/index.js.map +1 -1
  67. package/dist/ssr/layout/AnchoredPopover.js +1 -1
  68. package/dist/ssr/layout/AnchoredPopover.js.map +1 -1
  69. package/dist/ssr/layout/AppWorkspace.js +31 -17
  70. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  71. package/dist/ssr/layout/SettingsModal.js +10 -5
  72. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  73. package/dist/ssr/layout/app-workspace-controller.js +49 -5
  74. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  75. package/dist/ssr/text-editor/TextEditor.js +74 -25
  76. package/dist/ssr/text-editor/TextEditor.js.map +1 -1
  77. package/dist/ssr/text-editor/dictation.js +166 -0
  78. package/dist/ssr/text-editor/dictation.js.map +1 -0
  79. package/dist/ssr/text-editor.js +1 -0
  80. package/dist/ssr/text-editor.js.map +1 -1
  81. package/dist/styles.css +1 -1
  82. package/dist/types/chat/ChatComposer.d.ts +9 -0
  83. package/dist/types/inputs/SpecialInputs.d.ts +8 -0
  84. package/dist/types/inputs/dictation/Dictation.d.ts +26 -0
  85. package/dist/types/inputs/dictation/create-dictation.d.ts +77 -0
  86. package/dist/types/inputs/dictation/dictation-messages.d.ts +54 -0
  87. package/dist/types/inputs/dictation/text-dictation.d.ts +36 -0
  88. package/dist/types/inputs/dictation/types.d.ts +74 -0
  89. package/dist/types/inputs/icon-messages.d.ts +14 -0
  90. package/dist/types/inputs/icon-texts.d.ts +13 -0
  91. package/dist/types/inputs/index.d.ts +5 -0
  92. package/dist/types/layout/AnchoredPopover.d.ts +5 -0
  93. package/dist/types/layout/AppWorkspace.d.ts +14 -0
  94. package/dist/types/layout/app-workspace-controller.d.ts +2 -0
  95. package/dist/types/text-editor/TextEditor.d.ts +10 -1
  96. package/dist/types/text-editor/dictation.d.ts +20 -0
  97. package/dist/types/text-editor.d.ts +1 -0
  98. package/package.json +1 -1
@@ -36,17 +36,20 @@ var _tmpl$ = /*#__PURE__*/_$template(`<div class=k2b-ste-size-picker><!$><!/><!$
36
36
  import { history, historyKeymap, redo, undo } from "@codemirror/commands";
37
37
  import { EditorView, keymap } from "@codemirror/view";
38
38
  import { clipboard } from "@k2b/stdlib/solid";
39
- import { createEffect, createSignal, createUniqueId, For, onCleanup, onMount, Show, untrack } from "solid-js";
39
+ import { children, createEffect, createMemo, createSignal, createUniqueId, For, on, onCleanup, onMount, Show, untrack } from "solid-js";
40
40
  import { Button, IconButton } from "../actions/Button";
41
41
  import { Dropdown } from "../actions/Dropdown";
42
42
  import { SegmentedControl } from "../actions/SegmentedControl";
43
43
  import { Toolbar } from "../actions/Toolbar";
44
44
  import { Kbd } from "../content/Kbd";
45
45
  import { dialogCore } from "../feedback/dialog-core";
46
+ import { createDictation } from "../inputs/dictation/create-dictation";
47
+ import { DictationBar, DictationButton, dictationBarShown } from "../inputs/dictation/Dictation";
46
48
  import { NumberInput } from "../inputs/NumberInput";
47
49
  import { LocaleProvider, useLocale } from "../intl/locale";
48
50
  import { formatShortcut, keyboardPlatform } from "../intl/shortcut";
49
51
  import BottomSheet, { bottomSheetAdaptiveOptions } from "../layout/BottomSheet";
52
+ import { codeMirrorDictationTarget, dictationExtension } from "./dictation";
50
53
  import { createTextEditor } from "./engine";
51
54
  import { commands, formatLabels } from "./format";
52
55
  import { findTables, inspectTableStructure } from "./markdown-table";
@@ -332,6 +335,7 @@ export function TextEditor(props) {
332
335
  const locale = useLocale();
333
336
  const t = () => textEditorMessages.resolve([locale()]).t;
334
337
  const [mode, setMode] = createSignal(props.mode ?? "formatted");
338
+ const status = children(() => props.status);
335
339
  const [ready, setReady] = createSignal(false);
336
340
  const [recovery, setRecovery] = createSignal();
337
341
  const [notice, setNotice] = createSignal();
@@ -444,6 +448,26 @@ export function TextEditor(props) {
444
448
  let root;
445
449
  let mount;
446
450
  let editor;
451
+ // The view is read-only while it loads or recovers, too; dictation only runs where words can land.
452
+ const dictationWritable = () => !props.readOnly && !props.loading && ready() && recovery() === undefined && mode() !== "plain";
453
+ const dictation = createDictation({
454
+ source: {
455
+ start: options => props.dictation.source.start(options),
456
+ devices: () => props.dictation?.source.devices() ?? Promise.resolve([])
457
+ },
458
+ get alternative() {
459
+ return props.dictation?.alternative;
460
+ },
461
+ target: codeMirrorDictationTarget(() => editor?.view),
462
+ disabled: () => !props.dictation || !dictationWritable()
463
+ });
464
+ // A field that turns read-only or plain hides the toolbar; dictation then ends and the words so far stay.
465
+ // A memo compares the value, so ordinary edits never end it.
466
+ const dictationScope = createMemo(() => `${Boolean(props.dictation)}:${dictationWritable()}`);
467
+ createEffect(on(dictationScope, () => dictation.end(), {
468
+ defer: true
469
+ }));
470
+ const dictating = () => Boolean(props.dictation) && dictationBarShown(dictation);
447
471
  const menuBlocked = () => !!props.loading || !ready() || recovery() !== undefined;
448
472
  const blocked = () => !!props.readOnly || menuBlocked();
449
473
  const updateCheck = () => {
@@ -937,7 +961,8 @@ export function TextEditor(props) {
937
961
  }
938
962
  });
939
963
  const selectMode = next => {
940
- const restoreEditorFocus = !!editor?.view.contentDOM.contains(document.activeElement);
964
+ // Returning from the source view removes its switch; keyboard focus then moves into the text.
965
+ const restoreEditorFocus = !!editor?.view.contentDOM.contains(document.activeElement) || !!root.querySelector(".k2b-ste-views")?.contains(document.activeElement);
941
966
  menuOpen = false;
942
967
  setCell(undefined);
943
968
  setMode(next);
@@ -969,7 +994,7 @@ export function TextEditor(props) {
969
994
  }), EditorView.updateListener.of(update => {
970
995
  schedulePosition();
971
996
  if (update.docChanged) queueMicrotask(() => setDocumentRevision(revision => revision + 1));
972
- }), props.extensions ?? []],
997
+ }), props.extensions ?? [], props.dictation ? dictationExtension() : []],
973
998
  host: {
974
999
  ...props.host,
975
1000
  undo: props.host?.undo ?? (() => editor && undo(editor.view)),
@@ -1188,14 +1213,14 @@ export function TextEditor(props) {
1188
1213
  _$insert(_el$23, announcement);
1189
1214
  _$insert(_el$22, _$createComponent(Show, {
1190
1215
  get when() {
1191
- return !props.presentation || "status" in props || check();
1216
+ return _$memo(() => !!(status() !== undefined && status() !== null))() && status() !== false || check();
1192
1217
  },
1193
1218
  get children() {
1194
1219
  var _el$24 = _$getNextElement(_tmpl$10),
1195
1220
  _el$25 = _el$24.firstChild,
1196
1221
  _el$30 = _el$25.nextSibling,
1197
1222
  [_el$31, _co$6] = _$getNextMarker(_el$30.nextSibling);
1198
- _$insert(_el$25, () => props.status);
1223
+ _$insert(_el$25, status);
1199
1224
  _$insert(_el$24, _$createComponent(Show, {
1200
1225
  get when() {
1201
1226
  return check();
@@ -1253,9 +1278,18 @@ export function TextEditor(props) {
1253
1278
  return t().formatting;
1254
1279
  },
1255
1280
  get children() {
1256
- return [_$createComponent(For, {
1281
+ return [_$createComponent(Show, {
1282
+ get when() {
1283
+ return dictating();
1284
+ },
1285
+ get children() {
1286
+ return _$createComponent(DictationBar, {
1287
+ dictation: dictation
1288
+ });
1289
+ }
1290
+ }), _$createComponent(For, {
1257
1291
  get each() {
1258
- return [toolbar.slice(0, 3), toolbar.slice(3, 6), toolbar.slice(6)];
1292
+ return _$memo(() => !!dictating())() ? [] : [toolbar.slice(0, 3), toolbar.slice(3, 6), toolbar.slice(6)];
1259
1293
  },
1260
1294
  children: group => _$createComponent(Toolbar.Group, {
1261
1295
  "class": "k2b-ste-tool-group",
@@ -1299,27 +1333,42 @@ export function TextEditor(props) {
1299
1333
  });
1300
1334
  }
1301
1335
  })
1302
- }), _$createComponent(SegmentedControl, {
1303
- "class": "k2b-ste-views",
1304
- size: "sm",
1305
- get ariaLabel() {
1306
- return t().view;
1307
- },
1308
- get value() {
1309
- return mode() === "source" ? "source" : "formatted";
1336
+ }), _$createComponent(Show, {
1337
+ get when() {
1338
+ return _$memo(() => mode() === "source")() && !dictating();
1310
1339
  },
1311
- get options() {
1312
- return [{
1313
- value: "formatted",
1314
- label: t().formatted,
1315
- icon: "ti ti-typography"
1316
- }, {
1340
+ get children() {
1341
+ return _$createComponent(SegmentedControl, {
1342
+ "class": "k2b-ste-views",
1343
+ size: "sm",
1344
+ get ariaLabel() {
1345
+ return t().view;
1346
+ },
1317
1347
  value: "source",
1318
- label: t().source,
1319
- icon: "ti ti-markdown"
1320
- }];
1348
+ get options() {
1349
+ return [{
1350
+ value: "formatted",
1351
+ label: t().formatted,
1352
+ icon: "ti ti-typography"
1353
+ }, {
1354
+ value: "source",
1355
+ label: t().source,
1356
+ icon: "ti ti-markdown"
1357
+ }];
1358
+ },
1359
+ onValueChange: selectMode
1360
+ });
1361
+ }
1362
+ }), _$createComponent(Show, {
1363
+ get when() {
1364
+ return _$memo(() => !!props.dictation)() && !dictating();
1321
1365
  },
1322
- onValueChange: selectMode
1366
+ get children() {
1367
+ return _$createComponent(DictationButton, {
1368
+ dictation: dictation,
1369
+ "class": "k2b-ste-tool k2b-ste-dictate"
1370
+ });
1371
+ }
1323
1372
  })];
1324
1373
  }
1325
1374
  }));