@dxos/react-ui-chat 0.8.4-main.b97322e → 0.8.4-main.bc674ce

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 (32) hide show
  1. package/dist/lib/browser/index.mjs +136 -331
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +136 -331
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/ChatDialog/ChatDialog.d.ts +1 -1
  8. package/dist/types/src/components/ChatDialog/ChatDialog.d.ts.map +1 -1
  9. package/dist/types/src/components/ChatDialog/ChatDialog.stories.d.ts +35 -5
  10. package/dist/types/src/components/ChatDialog/ChatDialog.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/ChatEditor/ChatEditor.d.ts +7 -8
  12. package/dist/types/src/components/ChatEditor/ChatEditor.d.ts.map +1 -1
  13. package/dist/types/src/components/ChatEditor/ChatEditor.stories.d.ts +20 -5
  14. package/dist/types/src/components/ChatEditor/ChatEditor.stories.d.ts.map +1 -1
  15. package/dist/types/src/components/ChatEditor/references.d.ts +4 -0
  16. package/dist/types/src/components/ChatEditor/references.d.ts.map +1 -1
  17. package/dist/types/src/index.d.ts +1 -0
  18. package/dist/types/src/index.d.ts.map +1 -1
  19. package/dist/types/src/translations.d.ts +2 -35
  20. package/dist/types/src/translations.d.ts.map +1 -1
  21. package/dist/types/tsconfig.tsbuildinfo +1 -1
  22. package/package.json +43 -39
  23. package/src/components/ChatDialog/ChatDialog.stories.tsx +9 -10
  24. package/src/components/ChatDialog/ChatDialog.tsx +10 -10
  25. package/src/components/ChatEditor/ChatEditor.stories.tsx +24 -23
  26. package/src/components/ChatEditor/ChatEditor.tsx +33 -63
  27. package/src/components/ChatEditor/references.ts +18 -12
  28. package/src/index.ts +1 -0
  29. package/src/translations.ts +2 -41
  30. package/dist/types/src/components/ChatEditor/autocomplete.d.ts +0 -25
  31. package/dist/types/src/components/ChatEditor/autocomplete.d.ts.map +0 -1
  32. package/src/components/ChatEditor/autocomplete.ts +0 -218
@@ -1,121 +1,95 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
 
3
3
  // src/components/ChatDialog/ChatDialog.tsx
4
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
5
4
  import { createContext } from "@radix-ui/react-context";
6
5
  import React, { useEffect, useState } from "react";
7
6
  import { Dialog, Icon, IconButton, useControlledState } from "@dxos/react-ui";
8
- import { resizeAttributes, ResizeHandle, sizeStyle } from "@dxos/react-ui-dnd";
9
- import { mx } from "@dxos/react-ui-theme";
7
+ import { ResizeHandle, resizeAttributes, sizeStyle } from "@dxos/react-ui-dnd";
8
+ import { mx } from "@dxos/ui-theme";
10
9
  var preventDefault = (event) => event.preventDefault();
11
10
  var Endcap = ({ children }) => {
12
- var _effect = _useSignals();
13
- try {
14
- return /* @__PURE__ */ React.createElement("div", {
15
- className: "grid w-[var(--rail-action)] h-[var(--rail-action)] items-center justify-center"
16
- }, children);
17
- } finally {
18
- _effect.f();
19
- }
11
+ return /* @__PURE__ */ React.createElement("div", {
12
+ className: "grid is-[var(--rail-action)] bs-[var(--rail-action)] items-center justify-center"
13
+ }, children);
20
14
  };
21
15
  var [ChatDialogContextProvider, useChatDialogContext] = createContext("ChatDialog");
22
- var ChatDialogRoot = ({ children, open: _open = false, expanded: _expanded = false, onOpenChange, onExpandedChange, onEscape }) => {
23
- var _effect = _useSignals();
24
- try {
25
- const [size, setSize] = useState("min-content");
26
- const [open, setOpen] = useControlledState(_open, onOpenChange);
27
- const [expanded, setExpanded] = useControlledState(_expanded, onExpandedChange);
28
- return /* @__PURE__ */ React.createElement(ChatDialogContextProvider, {
29
- open,
30
- setOpen,
31
- expanded,
32
- setExpanded,
33
- size,
34
- setSize
35
- }, /* @__PURE__ */ React.createElement(Dialog.Root, {
36
- modal: false,
37
- open,
38
- onOpenChange: setOpen
39
- }, /* @__PURE__ */ React.createElement("div", {
40
- role: "none",
41
- className: "dx-dialog__overlay bg-transparent pointer-events-none",
42
- "data-block-align": "end"
43
- }, /* @__PURE__ */ React.createElement(Dialog.Content, {
44
- inOverlayLayout: true,
45
- classNames: [
46
- "grid grid-rows-[var(--rail-action)_1fr_min-content] p-0 overflow-hidden",
47
- "box-content md:is-[35rem] md:max-is-none pointer-events-auto"
48
- ],
49
- onEscapeKeyDown: onEscape,
50
- onInteractOutside: preventDefault
51
- }, children))));
52
- } finally {
53
- _effect.f();
54
- }
16
+ var ChatDialogRoot = ({ children, open: openProp = false, expanded: expandedProp = false, onOpenChange, onExpandedChange, onEscape }) => {
17
+ const [size, setSize] = useState("min-content");
18
+ const [open, setOpen] = useControlledState(openProp, onOpenChange);
19
+ const [expanded, setExpanded] = useControlledState(expandedProp, onExpandedChange);
20
+ return /* @__PURE__ */ React.createElement(ChatDialogContextProvider, {
21
+ open,
22
+ setOpen,
23
+ expanded,
24
+ setExpanded,
25
+ size,
26
+ setSize
27
+ }, /* @__PURE__ */ React.createElement(Dialog.Root, {
28
+ modal: false,
29
+ open,
30
+ onOpenChange: setOpen
31
+ }, /* @__PURE__ */ React.createElement("div", {
32
+ role: "none",
33
+ className: "dx-dialog__overlay bg-transparent pointer-events-none",
34
+ "data-block-align": "end"
35
+ }, /* @__PURE__ */ React.createElement(Dialog.Content, {
36
+ inOverlayLayout: true,
37
+ classNames: [
38
+ "grid grid-rows-[var(--rail-action)_1fr_min-content] p-0 overflow-hidden",
39
+ "box-content md:is-[35rem] md:max-is-none pointer-events-auto"
40
+ ],
41
+ onEscapeKeyDown: onEscape,
42
+ onInteractOutside: preventDefault
43
+ }, children))));
55
44
  };
56
45
  ChatDialogRoot.displayName = "ChatDialog.Root";
57
46
  var ChatDialogHeader = ({ classNames, title }) => {
58
- var _effect = _useSignals();
59
- try {
60
- const { expanded, setExpanded } = useChatDialogContext(ChatDialogHeader.displayName);
61
- return /* @__PURE__ */ React.createElement("div", {
62
- className: mx("grid grid-cols-[var(--rail-action)_1fr_min-content] items-center overflow-hidden", classNames)
63
- }, /* @__PURE__ */ React.createElement(Endcap, null, /* @__PURE__ */ React.createElement(Dialog.Close, null, /* @__PURE__ */ React.createElement(Icon, {
64
- icon: "ph--x--regular"
65
- }))), /* @__PURE__ */ React.createElement(Dialog.Title, {
66
- classNames: "flex w-full justify-center text-sm text-subdued select-none cursor-pointer",
67
- onClick: () => setExpanded((expanded2) => !expanded2)
68
- }, title), /* @__PURE__ */ React.createElement(Endcap, null, /* @__PURE__ */ React.createElement(IconButton, {
69
- variant: "ghost",
70
- icon: "ph--caret-up--regular",
71
- iconOnly: true,
72
- classNames: mx("!p-1 [&>svg]:transition [&>svg]:duration-200", expanded && "[&>svg]:rotate-180"),
73
- label: expanded ? "Close" : "Open",
74
- onClick: () => setExpanded((expanded2) => !expanded2)
75
- })));
76
- } finally {
77
- _effect.f();
78
- }
47
+ const { expanded, setExpanded } = useChatDialogContext(ChatDialogHeader.displayName);
48
+ return /* @__PURE__ */ React.createElement("div", {
49
+ className: mx("grid grid-cols-[var(--rail-action)_1fr_min-content] items-center overflow-hidden", classNames)
50
+ }, /* @__PURE__ */ React.createElement(Endcap, null, /* @__PURE__ */ React.createElement(Dialog.Close, null, /* @__PURE__ */ React.createElement(Icon, {
51
+ icon: "ph--x--regular"
52
+ }))), /* @__PURE__ */ React.createElement(Dialog.Title, {
53
+ classNames: "flex is-full justify-center text-sm text-subdued select-none cursor-pointer",
54
+ onClick: () => setExpanded((expanded2) => !expanded2)
55
+ }, title), /* @__PURE__ */ React.createElement(Endcap, null, /* @__PURE__ */ React.createElement(IconButton, {
56
+ variant: "ghost",
57
+ icon: "ph--caret-up--regular",
58
+ iconOnly: true,
59
+ classNames: mx("!p-1 [&>svg]:transition [&>svg]:duration-200", expanded && "[&>svg]:rotate-180"),
60
+ label: expanded ? "Close" : "Open",
61
+ onClick: () => setExpanded((expanded2) => !expanded2)
62
+ })));
79
63
  };
80
64
  ChatDialogHeader.displayName = "ChatDialog.Header";
81
65
  var ChatDialogContent = ({ children, classNames }) => {
82
- var _effect = _useSignals();
83
- try {
84
- const { expanded, size, setSize } = useChatDialogContext(ChatDialogContent.displayName);
85
- useEffect(() => {
86
- setSize(expanded ? "min-content" : 0);
87
- }, [
88
- expanded
89
- ]);
90
- return /* @__PURE__ */ React.createElement("div", {
91
- className: mx("flex flex-col overflow-y-auto border-t border-b border-subduedSeparator", 'transition-[block-size] ease-in-out duration-0 [&:not([data-dx-resizing="true"])]:duration-200', classNames),
92
- style: {
93
- ...sizeStyle(size, "vertical", true),
94
- maxBlockSize: "calc(100dvh - env(safe-area-inset-bottom) - env(safe-area-inset-top) - 14rem)"
95
- },
96
- ...resizeAttributes
97
- }, /* @__PURE__ */ React.createElement(ResizeHandle, {
98
- side: "block-start",
99
- iconPosition: "center",
100
- defaultSize: "min-content",
101
- fallbackSize: 0,
102
- minSize: 0,
103
- onSizeChange: setSize
104
- }), children);
105
- } finally {
106
- _effect.f();
107
- }
66
+ const { expanded, size, setSize } = useChatDialogContext(ChatDialogContent.displayName);
67
+ useEffect(() => {
68
+ setSize(expanded ? "min-content" : 0);
69
+ }, [
70
+ expanded
71
+ ]);
72
+ return /* @__PURE__ */ React.createElement("div", {
73
+ className: mx("flex flex-col overflow-y-auto border-bs border-be border-subduedSeparator", 'transition-[block-size] ease-in-out duration-0 [&:not([data-dx-resizing="true"])]:duration-200', classNames),
74
+ style: {
75
+ ...sizeStyle(size, "vertical", true),
76
+ maxBlockSize: "calc(100dvh - env(safe-area-inset-bottom) - env(safe-area-inset-top) - 14rem)"
77
+ },
78
+ ...resizeAttributes
79
+ }, /* @__PURE__ */ React.createElement(ResizeHandle, {
80
+ side: "block-start",
81
+ iconPosition: "center",
82
+ defaultSize: "min-content",
83
+ fallbackSize: 0,
84
+ minSize: 0,
85
+ onSizeChange: setSize
86
+ }), children);
108
87
  };
109
88
  ChatDialogContent.displayName = "ChatDialog.Content";
110
89
  var ChatDialogFooter = ({ children, classNames }) => {
111
- var _effect = _useSignals();
112
- try {
113
- return /* @__PURE__ */ React.createElement("div", {
114
- className: mx(classNames)
115
- }, children);
116
- } finally {
117
- _effect.f();
118
- }
90
+ return /* @__PURE__ */ React.createElement("div", {
91
+ className: mx(classNames)
92
+ }, children);
119
93
  };
120
94
  ChatDialogFooter.displayName = "ChatDialog.Footer";
121
95
  var ChatDialog = {
@@ -135,7 +109,7 @@ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-chat/src/components/Chat
135
109
  var references = ({ provider, triggerCharacter = "@", debug = false }) => {
136
110
  invariant(triggerCharacter.length === 1, void 0, {
137
111
  F: __dxlog_file,
138
- L: 50,
112
+ L: 56,
139
113
  S: void 0,
140
114
  A: [
141
115
  "triggerCharacter.length === 1",
@@ -143,10 +117,10 @@ var references = ({ provider, triggerCharacter = "@", debug = false }) => {
143
117
  ]
144
118
  });
145
119
  const decorationField = ViewPlugin.fromClass(class ReferenceView {
120
+ // TODO(burdon): Why?
121
+ _mutex = new Mutex();
122
+ decorations = Decoration.set([]);
146
123
  constructor(view) {
147
- // TODO(burdon): Why?
148
- this._mutex = new Mutex();
149
- this.decorations = Decoration.set([]);
150
124
  queueMicrotask(async () => {
151
125
  const guard = await this._mutex.acquire();
152
126
  try {
@@ -188,7 +162,7 @@ var references = ({ provider, triggerCharacter = "@", debug = false }) => {
188
162
  }
189
163
  }, {
190
164
  decorations: (v) => v.decorations,
191
- provide: (plugin) => [
165
+ provide: () => [
192
166
  EditorView.atomicRanges.of((view) => view.plugin(decorationField)?.decorations ?? RangeSet.empty)
193
167
  ]
194
168
  });
@@ -232,251 +206,82 @@ var references = ({ provider, triggerCharacter = "@", debug = false }) => {
232
206
  ];
233
207
  };
234
208
  var ReferenceWidget = class extends WidgetType {
209
+ data;
235
210
  constructor(data) {
236
211
  super(), this.data = data;
237
212
  }
238
- toDOM() {
239
- const span = document.createElement("span");
240
- span.textContent = `@ ${this.data.label}`;
241
- span.className = "cm-reference-pill";
242
- return span;
243
- }
244
- eq(other) {
245
- return other.data.uri === this.data.uri;
246
- }
247
213
  ignoreEvent() {
248
214
  return true;
249
215
  }
250
- };
251
-
252
- // src/components/ChatEditor/ChatEditor.tsx
253
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
254
- import React2, { forwardRef, useImperativeHandle } from "react";
255
- import { useThemeContext } from "@dxos/react-ui";
256
- import { createBasicExtensions, createThemeExtensions, useTextEditor } from "@dxos/react-ui-editor";
257
- import { mx as mx2 } from "@dxos/react-ui-theme";
258
- import { isNonNullable } from "@dxos/util";
259
-
260
- // src/components/ChatEditor/autocomplete.ts
261
- import { Prec } from "@codemirror/state";
262
- import { EditorView as EditorView2, Decoration as Decoration2, ViewPlugin as ViewPlugin2, keymap as keymap2, WidgetType as WidgetType2 } from "@codemirror/view";
263
- var autocomplete = ({ onSubmit, onSuggest, onCancel }) => {
264
- const suggest = ViewPlugin2.fromClass(class {
265
- constructor(view) {
266
- this._currentSuggestion = null;
267
- this._decorations = this.computeDecorations(view);
268
- }
269
- update(update) {
270
- if (update.docChanged || update.selectionSet) {
271
- this._decorations = this.computeDecorations(update.view);
272
- }
273
- }
274
- computeDecorations(view) {
275
- const text = view.state.doc.toString();
276
- const suggestions = onSuggest?.(text) ?? [];
277
- if (!suggestions.length) {
278
- this._currentSuggestion = null;
279
- return Decoration2.none;
280
- }
281
- this._currentSuggestion = suggestions[0];
282
- const suffix = this._currentSuggestion.slice(text.length);
283
- if (!suffix) {
284
- return Decoration2.none;
285
- }
286
- return Decoration2.set([
287
- Decoration2.widget({
288
- widget: new InlineSuggestionWidget(suffix),
289
- side: 1
290
- }).range(view.state.doc.length)
291
- ]);
292
- }
293
- completeSuggestion(view) {
294
- if (!this._currentSuggestion) {
295
- return false;
296
- }
297
- const text = view.state.doc.toString();
298
- const suffix = this._currentSuggestion.slice(text.length);
299
- if (!suffix) {
300
- return false;
301
- }
302
- view.dispatch({
303
- changes: {
304
- from: view.state.doc.length,
305
- insert: suffix
306
- },
307
- selection: {
308
- anchor: view.state.doc.length + suffix.length
309
- }
310
- });
311
- return true;
312
- }
313
- }, {
314
- decorations: (v) => v._decorations
315
- });
316
- return [
317
- suggest,
318
- EditorView2.theme({
319
- ".cm-inline-suggestion": {
320
- opacity: 0.4
321
- }
322
- }),
323
- Prec.highest(keymap2.of([
324
- {
325
- key: "Tab",
326
- preventDefault: true,
327
- run: (view) => {
328
- const plugin = view.plugin(suggest);
329
- return plugin?.completeSuggestion(view) ?? false;
330
- }
331
- },
332
- {
333
- key: "ArrowRight",
334
- preventDefault: true,
335
- run: (view) => {
336
- if (view.state.selection.main.head !== view.state.doc.length) {
337
- return false;
338
- }
339
- const plugin = view.plugin(suggest);
340
- return plugin?.completeSuggestion(view) ?? false;
341
- }
342
- },
343
- {
344
- key: "Enter",
345
- preventDefault: true,
346
- run: (view) => {
347
- const text = view.state.doc.toString().trim();
348
- if (text.length > 0 && onSubmit) {
349
- const reset = onSubmit(text);
350
- if (reset) {
351
- view.dispatch({
352
- changes: {
353
- from: 0,
354
- to: view.state.doc.length,
355
- insert: ""
356
- }
357
- });
358
- }
359
- }
360
- return true;
361
- }
362
- },
363
- {
364
- key: "Shift-Enter",
365
- preventDefault: true,
366
- run: (view) => {
367
- view.dispatch({
368
- changes: {
369
- from: view.state.selection.main.head,
370
- insert: "\n"
371
- },
372
- selection: {
373
- anchor: view.state.selection.main.head + 1,
374
- head: view.state.selection.main.head + 1
375
- }
376
- });
377
- return true;
378
- }
379
- },
380
- {
381
- key: "Escape",
382
- preventDefault: true,
383
- run: (view) => {
384
- view.dispatch({
385
- changes: {
386
- from: 0,
387
- to: view.state.doc.length,
388
- insert: ""
389
- }
390
- });
391
- onCancel?.();
392
- return true;
393
- }
394
- }
395
- ]))
396
- ];
397
- };
398
- var InlineSuggestionWidget = class extends WidgetType2 {
399
- constructor(suffix) {
400
- super(), this.suffix = suffix;
216
+ eq(other) {
217
+ return this.data.uri === other.data.uri;
401
218
  }
402
219
  toDOM() {
403
220
  const span = document.createElement("span");
404
- span.textContent = this.suffix;
405
- span.className = "cm-inline-suggestion";
221
+ span.textContent = `@${this.data.label}`;
222
+ span.className = "cm-reference-pill";
406
223
  return span;
407
224
  }
408
- eq(other) {
409
- return other.suffix === this.suffix;
410
- }
411
225
  };
412
226
 
413
227
  // src/components/ChatEditor/ChatEditor.tsx
414
- var ChatEditor = /* @__PURE__ */ forwardRef(({ classNames, extensions, references: references2, autoFocus, lineWrapping = false, placeholder, onSubmit, onSuggest, onCancel }, forwardRef2) => {
415
- var _effect = _useSignals2();
416
- try {
417
- const { themeMode } = useThemeContext();
418
- const { parentRef, view } = useTextEditor({
419
- debug: true,
420
- autoFocus,
421
- extensions: [
422
- createThemeExtensions({
423
- themeMode
424
- }),
425
- autocomplete({
426
- onSubmit,
427
- onSuggest,
428
- onCancel
429
- }),
430
- references2 ? references({
431
- provider: references2.provider
432
- }) : [],
433
- createBasicExtensions({
434
- bracketMatching: false,
435
- lineWrapping,
436
- placeholder
437
- }),
438
- extensions
439
- ].filter(isNonNullable)
440
- }, [
441
- themeMode,
442
- extensions,
443
- onSubmit,
444
- onSuggest
445
- ]);
446
- useImperativeHandle(forwardRef2, () => {
447
- return {
448
- focus: () => {
449
- view?.focus();
450
- },
451
- setText: (text) => {
452
- view?.dispatch({
453
- changes: {
454
- from: 0,
455
- to: view.state.doc.length,
456
- insert: text
457
- },
458
- selection: {
459
- anchor: text.length,
460
- head: text.length
461
- }
462
- });
463
- }
464
- };
465
- }, [
466
- view,
228
+ import React2, { forwardRef, useMemo } from "react";
229
+ import { useThemeContext } from "@dxos/react-ui";
230
+ import { Editor } from "@dxos/react-ui-editor";
231
+ import { createBasicExtensions, createThemeExtensions, submit } from "@dxos/ui-editor";
232
+ import { isTruthy } from "@dxos/util";
233
+ var useChatExtensions = ({ extensions, lineWrapping = false, placeholder, onSubmit }) => {
234
+ const { themeMode } = useThemeContext();
235
+ return useMemo(() => [
236
+ createThemeExtensions({
237
+ themeMode
238
+ }),
239
+ createBasicExtensions({
240
+ bracketMatching: false,
241
+ lineWrapping,
242
+ placeholder
243
+ }),
244
+ submit({
467
245
  onSubmit
468
- ]);
469
- return /* @__PURE__ */ React2.createElement("div", {
470
- ref: parentRef,
471
- className: mx2("is-full", classNames)
472
- });
473
- } finally {
474
- _effect.f();
475
- }
246
+ }),
247
+ extensions
248
+ ].filter(isTruthy), [
249
+ themeMode,
250
+ extensions,
251
+ onSubmit
252
+ ]);
253
+ };
254
+ var ChatEditor = /* @__PURE__ */ forwardRef(({ classNames, autoFocus, extensions: extensionsProp, lineWrapping = false, placeholder, onSubmit }, forwardRef2) => {
255
+ const extensions = useChatExtensions({
256
+ extensions: extensionsProp,
257
+ lineWrapping,
258
+ placeholder,
259
+ onSubmit
260
+ });
261
+ return /* @__PURE__ */ React2.createElement(Editor.Root, {
262
+ ref: forwardRef2
263
+ }, /* @__PURE__ */ React2.createElement(Editor.Content, {
264
+ classNames,
265
+ autoFocus,
266
+ extensions
267
+ }));
476
268
  });
269
+
270
+ // src/translations.ts
271
+ var translationKey = "@dxos/react-ui-chat";
272
+ var translations = [
273
+ {
274
+ "en-US": {
275
+ [translationKey]: {}
276
+ }
277
+ }
278
+ ];
477
279
  export {
478
280
  ChatDialog,
479
281
  ChatEditor,
480
- references
282
+ references,
283
+ translationKey,
284
+ translations,
285
+ useChatExtensions
481
286
  };
482
287
  //# sourceMappingURL=index.mjs.map