@dxos/react-ui-chat 0.8.4-main.f5c0578 → 0.8.4-main.fcfe5033a5

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