@dxos/react-ui-editor 0.4.2 → 0.4.3-main.068d254

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 (49) hide show
  1. package/dist/lib/browser/index.mjs +290 -212
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +23 -0
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +0 -3
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +20 -0
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/automerge.stories.d.ts +22 -2
  11. package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
  12. package/dist/types/src/components/TextEditor/hooks.stories.d.ts +20 -0
  13. package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
  14. package/dist/types/src/components/Toolbar/Toolbar.d.ts +7 -10
  15. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  16. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +23 -6
  17. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  18. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  19. package/dist/types/src/extensions/automerge/{semaphore.d.ts → sync.d.ts} +6 -5
  20. package/dist/types/src/extensions/automerge/sync.d.ts.map +1 -0
  21. package/dist/types/src/extensions/index.d.ts +1 -0
  22. package/dist/types/src/extensions/index.d.ts.map +1 -1
  23. package/dist/types/src/extensions/modes.d.ts +11 -0
  24. package/dist/types/src/extensions/modes.d.ts.map +1 -0
  25. package/dist/types/src/index.d.ts +3 -3
  26. package/dist/types/src/index.d.ts.map +1 -1
  27. package/dist/types/src/styles/index.d.ts +1 -0
  28. package/dist/types/src/styles/index.d.ts.map +1 -1
  29. package/dist/types/src/styles/layout.d.ts +2 -0
  30. package/dist/types/src/styles/layout.d.ts.map +1 -0
  31. package/dist/types/src/translations.d.ts +20 -0
  32. package/dist/types/src/translations.d.ts.map +1 -0
  33. package/package.json +25 -25
  34. package/src/components/TextEditor/MarkdownEditor.stories.tsx +23 -17
  35. package/src/components/TextEditor/TextEditor.stories.tsx +11 -14
  36. package/src/components/TextEditor/TextEditor.tsx +32 -53
  37. package/src/components/TextEditor/automerge.stories.tsx +38 -44
  38. package/src/components/TextEditor/hooks.stories.tsx +15 -16
  39. package/src/components/Toolbar/Toolbar.stories.tsx +16 -12
  40. package/src/components/Toolbar/Toolbar.tsx +156 -129
  41. package/src/extensions/automerge/automerge.ts +5 -21
  42. package/src/extensions/automerge/{semaphore.ts → sync.ts} +32 -34
  43. package/src/extensions/index.ts +1 -0
  44. package/src/extensions/modes.ts +36 -0
  45. package/src/index.ts +4 -3
  46. package/src/styles/index.ts +1 -0
  47. package/src/styles/layout.ts +6 -0
  48. package/src/translations.ts +25 -0
  49. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +0 -1
@@ -1,7 +1,7 @@
1
1
  // packages/ui/react-ui-editor/src/index.ts
2
+ import { keymap as keymap8 } from "@codemirror/view";
2
3
  import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
3
4
  import { Doc, YText, YXmlFragment } from "@dxos/text-model";
4
- import { keymap as keymap7 } from "@codemirror/view";
5
5
 
6
6
  // packages/ui/react-ui-editor/src/components/TextEditor/index.ts
7
7
  import { tags as tags2 } from "@lezer/highlight";
@@ -9,12 +9,12 @@ import { tags as tags2 } from "@lezer/highlight";
9
9
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
10
10
  import { EditorState as EditorState2 } from "@codemirror/state";
11
11
  import { EditorView as EditorView15 } from "@codemirror/view";
12
- import { vim } from "@replit/codemirror-vim";
12
+ import { useFocusableGroup } from "@fluentui/react-tabster";
13
13
  import defaultsDeep2 from "lodash.defaultsdeep";
14
14
  import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2 } from "react";
15
15
  import { log as log2 } from "@dxos/log";
16
16
  import { useThemeContext } from "@dxos/react-ui";
17
- import { focusRing, mx as mx3 } from "@dxos/react-ui-theme";
17
+ import { focusRing } from "@dxos/react-ui-theme";
18
18
  import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
19
19
 
20
20
  // packages/ui/react-ui-editor/src/extensions/annotations.ts
@@ -154,7 +154,6 @@ var autocomplete = ({ onSearch }) => {
154
154
  };
155
155
 
156
156
  // packages/ui/react-ui-editor/src/extensions/automerge/automerge.ts
157
- import { invertedEffects } from "@codemirror/commands";
158
157
  import { StateField as StateField2 } from "@codemirror/state";
159
158
  import { EditorView as EditorView2, ViewPlugin } from "@codemirror/view";
160
159
  import { next as A4 } from "@dxos/automerge/automerge";
@@ -208,7 +207,7 @@ var isReconcile = (tr) => {
208
207
  return !!tr.annotation(reconcileAnnotation);
209
208
  };
210
209
 
211
- // packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
210
+ // packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
212
211
  import { next as A3 } from "@dxos/automerge/automerge";
213
212
 
214
213
  // packages/ui/react-ui-editor/src/extensions/automerge/update-automerge.ts
@@ -349,40 +348,42 @@ var charPath = (textPath, candidatePath) => {
349
348
  return null;
350
349
  };
351
350
 
352
- // packages/ui/react-ui-editor/src/extensions/automerge/semaphore.ts
353
- var PatchSemaphore = class {
351
+ // packages/ui/react-ui-editor/src/extensions/automerge/sync.ts
352
+ var Syncer = class {
354
353
  // prettier-ignore
355
354
  constructor(_handle, _state) {
356
355
  this._handle = _handle;
357
356
  this._state = _state;
358
- this._inReconcile = false;
357
+ this._pending = false;
359
358
  }
360
- reconcile(view) {
361
- if (!this._inReconcile) {
362
- this._inReconcile = true;
363
- this.doReconcile(view);
364
- this._inReconcile = false;
359
+ reconcile(view, editor) {
360
+ if (this._pending) {
361
+ return;
365
362
  }
363
+ this._pending = true;
364
+ if (editor) {
365
+ this.onEditorChange(view);
366
+ } else {
367
+ this.onAutomergeChange(view);
368
+ }
369
+ this._pending = false;
366
370
  }
367
- doReconcile(view) {
368
- const path = getPath(view.state, this._state);
369
- const oldHeads = getLastHeads(view.state, this._state);
370
- let selection = view.state.selection;
371
+ onEditorChange(view) {
371
372
  const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcile(tx));
372
- const toInvert = transactions.slice().reverse();
373
- for (const tr of toInvert) {
374
- const inverted = tr.changes.invert(tr.startState.doc);
375
- selection = selection.map(inverted);
373
+ const newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
374
+ if (newHeads) {
376
375
  view.dispatch({
377
- changes: inverted,
378
- annotations: reconcileAnnotation.of(true)
376
+ effects: updateHeads(newHeads),
377
+ annotations: reconcileAnnotation.of(false)
379
378
  });
380
379
  }
381
- let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
382
- if (newHeads === null || newHeads === void 0) {
383
- newHeads = A3.getHeads(this._handle.docSync());
384
- }
380
+ }
381
+ onAutomergeChange(view) {
382
+ const oldHeads = getLastHeads(view.state, this._state);
383
+ const newHeads = A3.getHeads(this._handle.docSync());
385
384
  const diff = A3.equals(oldHeads, newHeads) ? [] : A3.diff(this._handle.docSync(), oldHeads, newHeads);
385
+ const selection = view.state.selection;
386
+ const path = getPath(view.state, this._state);
386
387
  updateCodeMirror(view, selection, path, diff);
387
388
  view.dispatch({
388
389
  effects: updateHeads(newHeads),
@@ -422,7 +423,7 @@ var automerge = ({ handle, path }) => {
422
423
  return result;
423
424
  }
424
425
  });
425
- const semaphore = new PatchSemaphore(handle, syncState);
426
+ const syncer = new Syncer(handle, syncState);
426
427
  return [
427
428
  Cursor.converter.of(cursorConverter(handle, path)),
428
429
  syncState,
@@ -436,25 +437,14 @@ var automerge = ({ handle, path }) => {
436
437
  handle.removeListener("change", this._handleChange.bind(this));
437
438
  }
438
439
  _handleChange() {
439
- semaphore.reconcile(this._view);
440
+ syncer.reconcile(this._view, false);
440
441
  }
441
442
  }),
442
443
  // Reconcile local updates.
443
444
  EditorView2.updateListener.of(({ view, changes }) => {
444
445
  if (!changes.empty) {
445
- semaphore.reconcile(view);
446
+ syncer.reconcile(view, true);
446
447
  }
447
- }),
448
- // TODO(burdon): Record undo transactions.
449
- // See https://github.com/yjs/y-codemirror.next/tree/main
450
- // https://codemirror.net/examples/inverted-effect
451
- invertedEffects.of((tr) => {
452
- const effects = [];
453
- if (!tr.changes.empty) {
454
- tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
455
- });
456
- }
457
- return effects;
458
448
  })
459
449
  ];
460
450
  };
@@ -1025,7 +1015,7 @@ var random = (min, max) => {
1025
1015
  };
1026
1016
 
1027
1017
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1028
- import { invertedEffects as invertedEffects2 } from "@codemirror/commands";
1018
+ import { invertedEffects } from "@codemirror/commands";
1029
1019
  import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
1030
1020
  import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
1031
1021
  import sortBy from "lodash.sortby";
@@ -1100,6 +1090,9 @@ import { tailwindConfig } from "@dxos/react-ui-theme";
1100
1090
  var tokens = tailwindConfig({}).theme;
1101
1091
  var getToken = (path, defaultValue = void 0) => get2(tokens, path, defaultValue);
1102
1092
 
1093
+ // packages/ui/react-ui-editor/src/styles/layout.ts
1094
+ var editorWithToolbarLayout = "fixed inset-0 grid grid-cols-1 grid-rows-[min-content_1fr] justify-center content-start overflow-hidden";
1095
+
1103
1096
  // packages/ui/react-ui-editor/src/util.ts
1104
1097
  import { log } from "@dxos/log";
1105
1098
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/util.ts";
@@ -1269,7 +1262,7 @@ var trackPastedComments = (onUpdate) => {
1269
1262
  copy: handleTrack
1270
1263
  }),
1271
1264
  // Track deleted comments.
1272
- invertedEffects2.of((tr) => {
1265
+ invertedEffects.of((tr) => {
1273
1266
  const { comments: comments2 } = tr.startState.field(commentsState);
1274
1267
  const effects = [];
1275
1268
  tr.changes.iterChangedRanges((fromA, toA) => {
@@ -3524,13 +3517,42 @@ var mention = ({ onSearch }) => {
3524
3517
  });
3525
3518
  };
3526
3519
 
3520
+ // packages/ui/react-ui-editor/src/extensions/modes.ts
3521
+ import { Facet as Facet4 } from "@codemirror/state";
3522
+ import { keymap as keymap6 } from "@codemirror/view";
3523
+ import { vim } from "@replit/codemirror-vim";
3524
+ var editorMode = Facet4.define({
3525
+ combine: (modes) => modes[0] ?? {}
3526
+ });
3527
+ var EditorModes = {
3528
+ default: [],
3529
+ vim: [
3530
+ vim(),
3531
+ editorMode.of({
3532
+ type: "vim",
3533
+ noTabster: true
3534
+ }),
3535
+ keymap6.of([
3536
+ {
3537
+ key: "Alt-Escape",
3538
+ run: (view) => {
3539
+ view.dispatch({
3540
+ userEvent: "focus.container"
3541
+ });
3542
+ return true;
3543
+ }
3544
+ }
3545
+ ])
3546
+ ]
3547
+ };
3548
+
3527
3549
  // packages/ui/react-ui-editor/src/extensions/outliner.ts
3528
3550
  var outliner = (options = {}) => {
3529
3551
  return [];
3530
3552
  };
3531
3553
 
3532
3554
  // packages/ui/react-ui-editor/src/extensions/typewriter.ts
3533
- import { keymap as keymap6 } from "@codemirror/view";
3555
+ import { keymap as keymap7 } from "@codemirror/view";
3534
3556
  var defaultItems = [
3535
3557
  "hello world!",
3536
3558
  "this is a test.",
@@ -3540,7 +3562,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
3540
3562
  let t;
3541
3563
  let idx = 0;
3542
3564
  return [
3543
- keymap6.of([
3565
+ keymap7.of([
3544
3566
  {
3545
3567
  // Reset.
3546
3568
  key: "alt-meta-'",
@@ -3828,11 +3850,10 @@ var codeTheme = {
3828
3850
 
3829
3851
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
3830
3852
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
3831
- var EditorModes = [
3832
- "default",
3833
- "vim"
3834
- ];
3835
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, editorMode, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
3853
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo, selection, theme, slots = defaultSlots, extensions = [], debug }, forwardedRef) => {
3854
+ const tabsterDOMAttribute = useFocusableGroup({
3855
+ tabBehavior: "limited"
3856
+ });
3836
3857
  const { themeMode } = useThemeContext();
3837
3858
  const rootRef = useRef(null);
3838
3859
  const [view, setView] = useState2(null);
@@ -3867,7 +3888,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3867
3888
  EditorView15.exceptionSink.of((err) => {
3868
3889
  log2.catch(err, void 0, {
3869
3890
  F: __dxlog_file3,
3870
- L: 135,
3891
+ L: 112,
3871
3892
  S: void 0,
3872
3893
  C: (f, a) => f(...a)
3873
3894
  });
@@ -3883,14 +3904,20 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3883
3904
  EditorView15.contentAttributes.of({
3884
3905
  class: slots.content?.className ?? ""
3885
3906
  }),
3907
+ // Focus.
3908
+ EditorView15.updateListener.of((update2) => {
3909
+ update2.transactions.forEach((transaction) => {
3910
+ if (transaction.isUserEvent("focus.container")) {
3911
+ rootRef.current?.focus();
3912
+ }
3913
+ });
3914
+ }),
3886
3915
  // State.
3887
3916
  EditorView15.editable.of(!readonly),
3888
3917
  EditorState2.readOnly.of(!!readonly),
3889
3918
  // Storage and replication.
3890
3919
  // NOTE: This must come before user extensions.
3891
3920
  model.extension,
3892
- // TODO(burdon): Factor out? (Requires special handling for Escape/Enter below).
3893
- editorMode === "vim" && vim(),
3894
3921
  // Custom.
3895
3922
  ...extensions
3896
3923
  ].filter(isNotFalsy4)
@@ -3910,6 +3937,9 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3910
3937
  });
3911
3938
  view?.destroy();
3912
3939
  setView(newView);
3940
+ if (state.facet(editorMode).noTabster) {
3941
+ rootRef.current.removeAttribute("data-tabster");
3942
+ }
3913
3943
  return () => {
3914
3944
  newView?.destroy();
3915
3945
  setView(null);
@@ -3918,35 +3948,27 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3918
3948
  rootRef,
3919
3949
  model,
3920
3950
  readonly,
3921
- editorMode,
3922
3951
  themeMode
3923
3952
  ]);
3924
3953
  const handleKeyUp = useCallback((event) => {
3925
- const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
3954
+ const { key } = event;
3926
3955
  switch (key) {
3927
3956
  case "Enter": {
3928
3957
  view?.focus();
3929
3958
  break;
3930
3959
  }
3931
- case "Escape": {
3932
- if (editorMode === "vim" && (altKey || shiftKey || metaKey || ctrlKey)) {
3933
- view?.focus();
3934
- }
3935
- break;
3936
- }
3937
3960
  }
3938
3961
  }, [
3939
- view,
3940
- editorMode
3962
+ view
3941
3963
  ]);
3942
3964
  return /* @__PURE__ */ React.createElement("div", {
3943
- key: model.id,
3944
3965
  role: "none",
3966
+ ref: rootRef,
3967
+ key: model.id,
3945
3968
  tabIndex: 0,
3946
- ...slots.root,
3947
- // {...(editorMode !== 'vim' && tabsterDOMAttribute)}
3948
3969
  onKeyUp: handleKeyUp,
3949
- ref: rootRef
3970
+ ...slots.root,
3971
+ ...tabsterDOMAttribute
3950
3972
  });
3951
3973
  });
3952
3974
  var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
@@ -3988,10 +4010,10 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeh
3988
4010
  });
3989
4011
  var defaultSlots = {
3990
4012
  root: {
3991
- className: mx3("grow", focusRing)
4013
+ className: focusRing
3992
4014
  },
3993
4015
  editor: {
3994
- className: "bs-full"
4016
+ className: "min-bs-full"
3995
4017
  }
3996
4018
  };
3997
4019
  var defaultTextSlots = {
@@ -4002,11 +4024,35 @@ var defaultMarkdownSlots = {
4002
4024
  };
4003
4025
 
4004
4026
  // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
4005
- import { CaretRight, ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic } from "@phosphor-icons/react";
4027
+ import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, Quotes, CaretDown } from "@phosphor-icons/react";
4006
4028
  import { createContext } from "@radix-ui/react-context";
4007
4029
  import React2 from "react";
4008
- import { Button, DensityProvider, Select } from "@dxos/react-ui";
4009
- import { getSize, mx as mx4 } from "@dxos/react-ui-theme";
4030
+ import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, useTranslation } from "@dxos/react-ui";
4031
+ import { getSize } from "@dxos/react-ui-theme";
4032
+
4033
+ // packages/ui/react-ui-editor/src/translations.ts
4034
+ var translationKey = "react-ui-editor";
4035
+ var translations_default = [
4036
+ {
4037
+ "en-US": {
4038
+ [translationKey]: {
4039
+ "strong label": "Strong",
4040
+ "emphasis label": "Emphasis",
4041
+ "strikethrough label": "Strike-through",
4042
+ "code label": "Code",
4043
+ "bullet label": "Bullet list",
4044
+ "ordered label": "Numbered list",
4045
+ "task label": "Task list",
4046
+ "blockquote label": "Block quote",
4047
+ "codeblock label": "Code block",
4048
+ "comment label": "Create comment",
4049
+ "heading label": "Heading level"
4050
+ }
4051
+ }
4052
+ }
4053
+ ];
4054
+
4055
+ // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
4010
4056
  var HeadingIcons = {
4011
4057
  "0": Paragraph,
4012
4058
  "1": TextHOne,
@@ -4017,42 +4063,40 @@ var HeadingIcons = {
4017
4063
  "6": TextHSix
4018
4064
  };
4019
4065
  var [ToolbarContextProvider, useToolbarContext] = createContext("Toolbar");
4020
- var ToolbarRoot = ({ children, onAction, state }) => {
4066
+ var ToolbarRoot = ({ children, onAction, classNames, state }) => {
4021
4067
  return /* @__PURE__ */ React2.createElement(ToolbarContextProvider, {
4022
4068
  onAction,
4023
4069
  state
4024
4070
  }, /* @__PURE__ */ React2.createElement(DensityProvider, {
4025
4071
  density: "fine"
4026
- }, /* @__PURE__ */ React2.createElement("div", {
4027
- role: "toolbar",
4028
- className: "flex w-full shrink-0 p-1 gap-4 items-center whitespace-nowrap overflow-hidden"
4029
- }, children)));
4072
+ }, /* @__PURE__ */ React2.createElement(ElevationProvider, {
4073
+ elevation: "chrome"
4074
+ }, /* @__PURE__ */ React2.createElement(NaturalToolbar.Root, {
4075
+ classNames: [
4076
+ "is-full shrink-0 overflow-x-auto p-1",
4077
+ classNames
4078
+ ]
4079
+ }, children))));
4030
4080
  };
4031
- var ToolbarButton = ({ Icon, onClick, title, getState, disable }) => {
4032
- const { onAction, state } = useToolbarContext("ToolbarButton");
4033
- const active = getState && state ? getState(state) : false;
4034
- const disabled = disable && state ? disable(state) : false;
4035
- const handleClick = (event) => {
4036
- const action = onClick(state);
4037
- if (action) {
4038
- onAction?.(action);
4039
- event.preventDefault();
4040
- }
4041
- };
4042
- return /* @__PURE__ */ React2.createElement(Button, {
4081
+ var buttonStyles = "min-bs-0 p-2";
4082
+ var iconStyles = getSize(4);
4083
+ var ToolbarButton = ({ Icon, children, ...props }) => {
4084
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroupItem, {
4043
4085
  variant: "ghost",
4044
- classNames: mx4("p-2", active && "ring-[1px]"),
4045
- onMouseDown: handleClick,
4046
- title,
4047
- disabled
4086
+ ...props,
4087
+ classNames: buttonStyles
4048
4088
  }, /* @__PURE__ */ React2.createElement(Icon, {
4049
- className: getSize(5)
4050
- }));
4089
+ className: iconStyles
4090
+ }), /* @__PURE__ */ React2.createElement("span", {
4091
+ className: "sr-only"
4092
+ }, children));
4051
4093
  };
4052
4094
  var ToolbarSeparator = () => /* @__PURE__ */ React2.createElement("div", {
4095
+ role: "separator",
4053
4096
  className: "grow"
4054
4097
  });
4055
4098
  var MarkdownHeading = () => {
4099
+ const { t } = useTranslation(translationKey);
4056
4100
  const { onAction, state } = useToolbarContext("MarkdownFormatting");
4057
4101
  const blockType = state ? state.blockType : "paragraph";
4058
4102
  const header = blockType && /heading(\d)/.exec(blockType);
@@ -4065,9 +4109,19 @@ var MarkdownHeading = () => {
4065
4109
  type: "heading",
4066
4110
  data: parseInt(value2)
4067
4111
  })
4068
- }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, null, /* @__PURE__ */ React2.createElement(HeadingIcon, {
4069
- className: getSize(5)
4070
- })), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
4112
+ }, /* @__PURE__ */ React2.createElement(Select.Trigger, {
4113
+ asChild: true
4114
+ }, /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
4115
+ variant: "ghost",
4116
+ classNames: buttonStyles
4117
+ }, /* @__PURE__ */ React2.createElement("span", {
4118
+ className: "sr-only"
4119
+ }, t("heading label")), /* @__PURE__ */ React2.createElement(HeadingIcon, {
4120
+ className: iconStyles
4121
+ }), /* @__PURE__ */ React2.createElement(CaretDown, {
4122
+ className: getSize(2),
4123
+ weight: "bold"
4124
+ }))), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.ScrollUpButton, null), /* @__PURE__ */ React2.createElement(Select.Viewport, null, /* @__PURE__ */ React2.createElement(Select.Option, {
4071
4125
  value: "0"
4072
4126
  }, "Paragraph"), [
4073
4127
  1,
@@ -4079,120 +4133,142 @@ var MarkdownHeading = () => {
4079
4133
  ].map((level) => /* @__PURE__ */ React2.createElement(Select.Option, {
4080
4134
  key: level,
4081
4135
  value: String(level)
4082
- }, "Heading ", level))))));
4136
+ }, "Heading ", level))), /* @__PURE__ */ React2.createElement(Select.ScrollDownButton, null), /* @__PURE__ */ React2.createElement(Select.Arrow, null))));
4137
+ };
4138
+ var markdownStyles = [
4139
+ {
4140
+ key: "strong",
4141
+ Icon: TextB
4142
+ },
4143
+ {
4144
+ key: "emphasis",
4145
+ Icon: TextItalic
4146
+ },
4147
+ {
4148
+ key: "strikethrough",
4149
+ Icon: TextStrikethrough
4150
+ },
4151
+ {
4152
+ key: "code",
4153
+ Icon: Code
4154
+ },
4155
+ {
4156
+ key: "link",
4157
+ Icon: Link
4158
+ }
4159
+ ];
4160
+ var MarkdownStyles = () => {
4161
+ const { onAction, state } = useToolbarContext("MarkdownStyles");
4162
+ const { t } = useTranslation(translationKey);
4163
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4164
+ type: "multiple",
4165
+ value: markdownStyles.filter(({ key }) => !!state?.[key]).map(({ key }) => key)
4166
+ }, markdownStyles.map(({ key, Icon }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4167
+ key,
4168
+ value: key,
4169
+ Icon,
4170
+ disabled: state?.blockType === "codeblock",
4171
+ onClick: () => onAction?.({
4172
+ type: key,
4173
+ data: state ? !state[key] : null
4174
+ })
4175
+ }, t(`${key} label`))));
4176
+ };
4177
+ var markdownLists = [
4178
+ {
4179
+ key: "bullet",
4180
+ Icon: ListBullets,
4181
+ actionType: "list-bullet"
4182
+ },
4183
+ {
4184
+ key: "ordered",
4185
+ Icon: ListNumbers,
4186
+ actionType: "list-ordered"
4187
+ },
4188
+ {
4189
+ key: "task",
4190
+ Icon: ListChecks,
4191
+ actionType: "list-tasks"
4192
+ }
4193
+ ];
4194
+ var MarkdownLists = () => {
4195
+ const { onAction, state } = useToolbarContext("MarkdownStyles");
4196
+ const { t } = useTranslation(translationKey);
4197
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4198
+ type: "single",
4199
+ value: state?.listStyle ?? void 0
4200
+ }, markdownLists.map(({ key, Icon, actionType }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4201
+ key,
4202
+ value: key,
4203
+ Icon,
4204
+ onClick: () => onAction?.({
4205
+ type: actionType,
4206
+ data: state ? state.listStyle !== key : null
4207
+ })
4208
+ }, t(`${key} label`))));
4209
+ };
4210
+ var markdownBlocks = [
4211
+ {
4212
+ key: "blockquote",
4213
+ Icon: Quotes,
4214
+ pressed: (state) => state?.blockQuote,
4215
+ action: (state) => ({
4216
+ type: "blockquote",
4217
+ data: state ? !state.blockQuote : null
4218
+ }),
4219
+ disabled: (state) => false
4220
+ },
4221
+ {
4222
+ key: "codeblock",
4223
+ Icon: CodeBlock,
4224
+ pressed: (state) => state?.blockType === "codeblock",
4225
+ action: (state) => ({
4226
+ type: "blockquote",
4227
+ data: state ? !state.blockQuote : null
4228
+ }),
4229
+ disabled: (state) => !state?.blankLine
4230
+ }
4231
+ ];
4232
+ var MarkdownBlocks = () => {
4233
+ const { onAction, state } = useToolbarContext("MarkdownStyles");
4234
+ const { t } = useTranslation(translationKey);
4235
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(NaturalToolbar.ToggleGroup, {
4236
+ type: "multiple",
4237
+ value: markdownBlocks.filter(({ pressed }) => pressed(state)).map(({ key }) => key)
4238
+ }, markdownBlocks.map(({ key, Icon, action }) => /* @__PURE__ */ React2.createElement(ToolbarButton, {
4239
+ key,
4240
+ value: key,
4241
+ Icon,
4242
+ onClick: () => onAction?.(action(state))
4243
+ }, t(`${key} label`)))), /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
4244
+ variant: "ghost",
4245
+ disabled: !state?.blankLine,
4246
+ onClick: () => onAction?.({
4247
+ type: "table"
4248
+ }),
4249
+ classNames: buttonStyles
4250
+ }, /* @__PURE__ */ React2.createElement(Table2, {
4251
+ className: iconStyles
4252
+ }), /* @__PURE__ */ React2.createElement("span", {
4253
+ className: "sr-only"
4254
+ }, t("table label"))));
4255
+ };
4256
+ var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null));
4257
+ var MarkdownExtended = () => {
4258
+ const { onAction } = useToolbarContext("MarkdownStyles");
4259
+ const { t } = useTranslation(translationKey);
4260
+ return /* @__PURE__ */ React2.createElement(NaturalToolbar.Button, {
4261
+ variant: "ghost",
4262
+ onClick: () => onAction?.({
4263
+ type: "comment"
4264
+ }),
4265
+ classNames: buttonStyles
4266
+ }, /* @__PURE__ */ React2.createElement(ChatText, {
4267
+ className: iconStyles
4268
+ }), /* @__PURE__ */ React2.createElement("span", {
4269
+ className: "sr-only"
4270
+ }, t("comment label")));
4083
4271
  };
4084
- var MarkdownStyles = () => /* @__PURE__ */ React2.createElement("div", {
4085
- role: "none"
4086
- }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
4087
- Icon: TextB,
4088
- title: "String",
4089
- disable: (s) => s.blockType === "codeblock",
4090
- getState: (s) => s.strong,
4091
- onClick: (s) => ({
4092
- type: "strong",
4093
- data: s ? !s.strong : null
4094
- })
4095
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4096
- Icon: TextItalic,
4097
- title: "Emphasis",
4098
- disable: (s) => s.blockType === "codeblock",
4099
- getState: (s) => s.emphasis,
4100
- onClick: (s) => ({
4101
- type: "emphasis",
4102
- data: s ? !s.emphasis : null
4103
- })
4104
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4105
- Icon: TextStrikethrough,
4106
- title: "Strike-through",
4107
- disable: (s) => s.blockType === "codeblock",
4108
- getState: (s) => s.strikethrough,
4109
- onClick: (s) => ({
4110
- type: "strikethrough",
4111
- data: s ? !s.strikethrough : null
4112
- })
4113
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4114
- Icon: Code,
4115
- title: "Inline code",
4116
- disable: (s) => s.blockType === "codeblock",
4117
- getState: (s) => s.code,
4118
- onClick: (s) => ({
4119
- type: "code",
4120
- data: s ? !s.code : null
4121
- })
4122
- }));
4123
- var MarkdownLists = () => /* @__PURE__ */ React2.createElement("div", {
4124
- role: "none"
4125
- }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
4126
- Icon: ListBullets,
4127
- title: "Bullet list",
4128
- getState: (s) => s.listStyle === "bullet",
4129
- onClick: (s) => ({
4130
- type: "list-bullet",
4131
- data: s ? s.listStyle !== "bullet" : null
4132
- })
4133
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4134
- Icon: ListNumbers,
4135
- title: "Numbered list",
4136
- getState: (s) => s.listStyle === "ordered",
4137
- onClick: (s) => ({
4138
- type: "list-ordered",
4139
- data: s ? s.listStyle !== "ordered" : null
4140
- })
4141
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4142
- Icon: ListChecks,
4143
- title: "Task list",
4144
- getState: (s) => s.listStyle === "task",
4145
- onClick: (s) => ({
4146
- type: "list-tasks",
4147
- data: s ? s.listStyle !== "task" : null
4148
- })
4149
- }));
4150
- var MarkdownBlocks = () => /* @__PURE__ */ React2.createElement("div", {
4151
- role: "none"
4152
- }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
4153
- Icon: CaretRight,
4154
- title: "Block quote",
4155
- getState: (s) => s.blockQuote,
4156
- onClick: (s) => ({
4157
- type: "blockquote",
4158
- data: s ? !s.blockQuote : null
4159
- })
4160
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4161
- Icon: CodeBlock,
4162
- title: "Code block",
4163
- disable: (s) => !s.blankLine,
4164
- getState: (s) => s.blockType === "codeblock",
4165
- onClick: (s) => ({
4166
- type: "codeblock",
4167
- data: s ? s.blockType !== "codeblock" : null
4168
- })
4169
- }), /* @__PURE__ */ React2.createElement(ToolbarButton, {
4170
- Icon: Table2,
4171
- title: "Table",
4172
- disable: (s) => !s.blankLine,
4173
- onClick: () => ({
4174
- type: "table"
4175
- })
4176
- }));
4177
- var MarkdownLinks = () => /* @__PURE__ */ React2.createElement("div", {
4178
- role: "none"
4179
- }, /* @__PURE__ */ React2.createElement(ToolbarButton, {
4180
- Icon: Link,
4181
- title: "Link",
4182
- getState: (s) => s.link,
4183
- onClick: (s) => ({
4184
- type: "link",
4185
- data: s ? !s.link : null
4186
- })
4187
- }));
4188
- var MarkdownStandard = () => /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(MarkdownHeading, null), /* @__PURE__ */ React2.createElement(MarkdownStyles, null), /* @__PURE__ */ React2.createElement(MarkdownLists, null), /* @__PURE__ */ React2.createElement(MarkdownBlocks, null), /* @__PURE__ */ React2.createElement(MarkdownLinks, null));
4189
- var MarkdownExtended = () => /* @__PURE__ */ React2.createElement(Toolbar.Button, {
4190
- Icon: ChatText,
4191
- title: "Create comment",
4192
- onClick: () => ({
4193
- type: "comment"
4194
- })
4195
- });
4196
4272
  var Toolbar = {
4197
4273
  Root: ToolbarRoot,
4198
4274
  Button: ToolbarButton,
@@ -4596,6 +4672,8 @@ export {
4596
4672
  defaultSlots,
4597
4673
  defaultTextSlots,
4598
4674
  defaultTheme,
4675
+ editorMode,
4676
+ editorWithToolbarLayout,
4599
4677
  focusComment,
4600
4678
  formatting,
4601
4679
  getFormatting,
@@ -4604,7 +4682,7 @@ export {
4604
4682
  hr,
4605
4683
  image,
4606
4684
  insertTable,
4607
- keymap7 as keymap,
4685
+ keymap8 as keymap,
4608
4686
  link,
4609
4687
  listener,
4610
4688
  logChanges,