@dxos/react-ui-editor 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (90) hide show
  1. package/dist/lib/browser/index.mjs +298 -377
  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 +298 -377
  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/Editor/Editor.d.ts.map +1 -1
  8. package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts +1 -3
  9. package/dist/types/src/components/EditorMenuProvider/EditorMenuProvider.d.ts.map +1 -1
  10. package/dist/types/src/components/EditorMenuProvider/menu-presets.d.ts.map +1 -1
  11. package/dist/types/src/components/EditorMenuProvider/useEditorMenu.d.ts.map +1 -1
  12. package/dist/types/src/components/EditorPreviewProvider/EditorPreviewProvider.d.ts.map +1 -1
  13. package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -1
  14. package/dist/types/src/components/EditorToolbar/blocks.d.ts +3 -17
  15. package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -1
  16. package/dist/types/src/components/EditorToolbar/formatting.d.ts +3 -17
  17. package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -1
  18. package/dist/types/src/components/EditorToolbar/headings.d.ts +3 -17
  19. package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -1
  20. package/dist/types/src/components/EditorToolbar/image.d.ts +3 -8
  21. package/dist/types/src/components/EditorToolbar/image.d.ts.map +1 -1
  22. package/dist/types/src/components/EditorToolbar/index.d.ts +0 -1
  23. package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -1
  24. package/dist/types/src/components/EditorToolbar/lists.d.ts +6 -0
  25. package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
  26. package/dist/types/src/components/EditorToolbar/search.d.ts +3 -8
  27. package/dist/types/src/components/EditorToolbar/search.d.ts.map +1 -1
  28. package/dist/types/src/components/EditorToolbar/view-mode.d.ts +3 -17
  29. package/dist/types/src/components/EditorToolbar/view-mode.d.ts.map +1 -1
  30. package/dist/types/src/stories/Automerge.stories.d.ts +25 -24
  31. package/dist/types/src/stories/Automerge.stories.d.ts.map +1 -1
  32. package/dist/types/src/stories/Comments.stories.d.ts +1 -1
  33. package/dist/types/src/stories/EditorToolbar.stories.d.ts +26 -26
  34. package/dist/types/src/stories/EditorToolbar.stories.d.ts.map +1 -1
  35. package/dist/types/src/stories/Experimental.stories.d.ts +1 -1
  36. package/dist/types/src/stories/Markdown.stories.d.ts +1 -1
  37. package/dist/types/src/stories/Outliner.stories.d.ts +2 -2
  38. package/dist/types/src/stories/Outliner.stories.d.ts.map +1 -1
  39. package/dist/types/src/stories/Popover.stories.d.ts +2 -2
  40. package/dist/types/src/stories/Popover.stories.d.ts.map +1 -1
  41. package/dist/types/src/stories/Preview.stories.d.ts +1 -1
  42. package/dist/types/src/stories/Preview.stories.d.ts.map +1 -1
  43. package/dist/types/src/stories/TextEditor.stories.d.ts +1 -1
  44. package/dist/types/src/stories/components/EditorStory.d.ts +3 -3
  45. package/dist/types/src/stories/components/EditorStory.d.ts.map +1 -1
  46. package/dist/types/src/stories/components/util.d.ts +3 -3
  47. package/dist/types/src/stories/components/util.d.ts.map +1 -1
  48. package/dist/types/src/translations.d.ts +24 -24
  49. package/dist/types/src/translations.d.ts.map +1 -1
  50. package/dist/types/src/util/react.d.ts +1 -4
  51. package/dist/types/src/util/react.d.ts.map +1 -1
  52. package/dist/types/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +45 -45
  54. package/src/components/Editor/Editor.stories.tsx +2 -2
  55. package/src/components/Editor/Editor.tsx +12 -6
  56. package/src/components/EditorContent/EditorContent.tsx +1 -1
  57. package/src/components/EditorMenuProvider/EditorMenuProvider.tsx +21 -28
  58. package/src/components/EditorMenuProvider/menu-presets.ts +1 -0
  59. package/src/components/EditorMenuProvider/useEditorMenu.ts +8 -1
  60. package/src/components/EditorPreviewProvider/EditorPreviewProvider.tsx +5 -7
  61. package/src/components/EditorToolbar/EditorToolbar.tsx +24 -61
  62. package/src/components/EditorToolbar/blocks.ts +54 -46
  63. package/src/components/EditorToolbar/formatting.ts +43 -44
  64. package/src/components/EditorToolbar/headings.ts +42 -48
  65. package/src/components/EditorToolbar/image.ts +16 -21
  66. package/src/components/EditorToolbar/index.ts +0 -1
  67. package/src/components/EditorToolbar/lists.ts +57 -0
  68. package/src/components/EditorToolbar/search.ts +16 -21
  69. package/src/components/EditorToolbar/view-mode.ts +34 -40
  70. package/src/stories/Automerge.stories.tsx +8 -10
  71. package/src/stories/Comments.stories.tsx +4 -4
  72. package/src/stories/EditorToolbar.stories.tsx +32 -17
  73. package/src/stories/Experimental.stories.tsx +3 -3
  74. package/src/stories/Markdown.stories.tsx +2 -2
  75. package/src/stories/Outliner.stories.tsx +4 -4
  76. package/src/stories/Popover.stories.tsx +6 -6
  77. package/src/stories/Preview.stories.tsx +58 -48
  78. package/src/stories/Tags.stories.tsx +5 -5
  79. package/src/stories/TextEditor.stories.tsx +2 -2
  80. package/src/stories/Theme.stories.tsx +2 -2
  81. package/src/stories/components/EditorStory.tsx +17 -12
  82. package/src/stories/components/util.tsx +19 -22
  83. package/src/translations.ts +29 -24
  84. package/src/util/react.tsx +2 -11
  85. package/dist/types/src/components/EditorToolbar/actions.d.ts +0 -24
  86. package/dist/types/src/components/EditorToolbar/actions.d.ts.map +0 -1
  87. package/dist/types/src/stories/CommandDialog.stories.d.ts +0 -14
  88. package/dist/types/src/stories/CommandDialog.stories.d.ts.map +0 -1
  89. package/src/components/EditorToolbar/actions.ts +0 -87
  90. package/src/stories/CommandDialog.stories.tsx +0 -81
@@ -4,30 +4,30 @@ var translations = [
4
4
  {
5
5
  "en-US": {
6
6
  [translationKey]: {
7
- "strong label": "Bold",
8
- "emphasis label": "Italics",
9
- "strikethrough label": "Strikethrough",
10
- "code label": "Code",
11
- "link label": "Link",
12
- "list-bullet label": "Bullet list",
13
- "list-ordered label": "Numbered list",
14
- "list-task label": "Task list",
15
- "blockquote label": "Block quote",
16
- "codeblock label": "Code block",
17
- "comment label": "Create comment",
18
- "selection overlaps existing comment label": "Selection overlaps existing comment",
19
- "select text to comment label": "Select text to comment",
20
- "image label": "Insert image",
21
- "table label": "Create table",
22
- "heading label": "Heading level",
23
- "heading level label_zero": "Paragraph",
24
- "heading level label_one": "Heading level {{count}}",
25
- "heading level label_other": "Heading level {{count}}",
26
- "search label": "Search",
27
- "view mode label": "Editor view",
28
- "preview mode label": "Markdown",
29
- "readonly mode label": "Read only",
30
- "source mode label": "Plain text"
7
+ "comment.label": "Create comment",
8
+ "image.label": "Insert image",
9
+ "search.label": "Search",
10
+ "block.label": "Block",
11
+ "block.blockquote.label": "Block quote",
12
+ "block.codeblock.label": "Code block",
13
+ "block.table.label": "Create table",
14
+ "formatting.label": "Formatting",
15
+ "formatting.strong.label": "Bold",
16
+ "formatting.emphasis.label": "Italics",
17
+ "formatting.strikethrough.label": "Strikethrough",
18
+ "formatting.code.label": "Code",
19
+ "formatting.link.label": "Link",
20
+ "list.bullet.label": "Bullet list",
21
+ "list.ordered.label": "Numbered list",
22
+ "list.task.label": "Task list",
23
+ "heading.label": "Heading level",
24
+ "heading-level.label_zero": "Paragraph",
25
+ "heading-level.label_one": "Heading level {{count}}",
26
+ "heading-level.label_other": "Heading level {{count}}",
27
+ "view-mode.label": "Editor view",
28
+ "view-mode.preview.label": "Markdown",
29
+ "view-mode.source.label": "Plain text",
30
+ "view-mode.readonly.label": "Read only"
31
31
  }
32
32
  }
33
33
  }
@@ -296,7 +296,7 @@ var EditorContent = /* @__PURE__ */ forwardRef(({ classNames, id, extensions, se
296
296
  ]);
297
297
  return /* @__PURE__ */ React.createElement("div", {
298
298
  role: "none",
299
- className: mx("is-full outline-none focus:border-accentSurface focus-within:border-neutralFocusIndicator", classNames),
299
+ className: mx("w-full outline-hidden focus:border-accent-surface focus-within:border-neutral-focus-indicator", classNames),
300
300
  ref: parentRef,
301
301
  ...focusable ? focusAttributes : {}
302
302
  });
@@ -702,7 +702,7 @@ import { useControllableState } from "@radix-ui/react-use-controllable-state";
702
702
  import React2, { Fragment, useCallback as useCallback2, useEffect as useEffect3, useRef as useRef2, useState as useState2 } from "react";
703
703
  import { addEventListener } from "@dxos/async";
704
704
  import { invariant } from "@dxos/invariant";
705
- import { DX_ANCHOR_ACTIVATE, Icon, Popover, toLocalizedString, useDynamicRef, useThemeContext, useTranslation } from "@dxos/react-ui";
705
+ import { DX_ANCHOR_ACTIVATE, Icon, Popover, ScrollArea, toLocalizedString, useDynamicRef, useThemeContext, useTranslation } from "@dxos/react-ui";
706
706
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-editor/src/components/EditorMenuProvider/EditorMenuProvider.tsx";
707
707
  var EditorMenuProvider = ({ children, view, groups, currentItem, open: openProp, defaultOpen, numItems = 8, onOpenChange, onActivate, onSelect, onCancel }) => {
708
708
  const { tx } = useThemeContext();
@@ -714,7 +714,7 @@ var EditorMenuProvider = ({ children, view, groups, currentItem, open: openProp,
714
714
  onChange: (open2) => {
715
715
  invariant(viewRef.current, void 0, {
716
716
  F: __dxlog_file2,
717
- L: 65,
717
+ L: 64,
718
718
  S: void 0,
719
719
  A: [
720
720
  "viewRef.current",
@@ -733,8 +733,8 @@ var EditorMenuProvider = ({ children, view, groups, currentItem, open: openProp,
733
733
  return;
734
734
  }
735
735
  return addEventListener(root, DX_ANCHOR_ACTIVATE, (event) => {
736
- const { trigger, refId } = event;
737
- if (!refId) {
736
+ const { trigger, dxn } = event;
737
+ if (!dxn) {
738
738
  triggerRef.current = trigger;
739
739
  if (onActivate) {
740
740
  onActivate({
@@ -756,7 +756,7 @@ var EditorMenuProvider = ({ children, view, groups, currentItem, open: openProp,
756
756
  const handleSelect = useCallback2((item) => {
757
757
  invariant(viewRef.current, void 0, {
758
758
  F: __dxlog_file2,
759
- L: 102,
759
+ L: 99,
760
760
  S: void 0,
761
761
  A: [
762
762
  "viewRef.current",
@@ -780,34 +780,36 @@ var EditorMenuProvider = ({ children, view, groups, currentItem, open: openProp,
780
780
  virtualRef: triggerRef
781
781
  }), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
782
782
  align: "start",
783
- classNames: tx("menu.content", "menu--exotic-unfocusable", {
784
- elevation: "positioned"
785
- }, [
786
- "overflow-y-auto",
783
+ classNames: [
784
+ "flex flex-col",
787
785
  !menuGroups.length && "hidden"
788
- ]),
786
+ ],
789
787
  style: {
790
788
  maxBlockSize: 36 * numItems + 10
791
789
  },
792
- /**
793
- * NOTE: We keep the focus in the editor, but Radix routes escape key.
794
- */
790
+ // NOTE: We keep the focus in the editor, but Radix routes escape key.
795
791
  onEscapeKeyDown: () => {
796
- onCancel?.({
797
- view
798
- });
792
+ const currentView = viewRef.current;
793
+ if (currentView) {
794
+ onCancel?.({
795
+ view: currentView
796
+ });
797
+ }
799
798
  },
800
799
  onOpenAutoFocus: (event) => event.preventDefault()
801
800
  }, /* @__PURE__ */ React2.createElement(Popover.Viewport, {
802
- classNames: tx("menu.viewport", "menu__viewport--exotic-unfocusable", {})
803
- }, /* @__PURE__ */ React2.createElement(Menu, {
801
+ asChild: true,
802
+ classNames: "dx-container"
803
+ }, /* @__PURE__ */ React2.createElement(ScrollArea.Root, {
804
+ thin: true
805
+ }, /* @__PURE__ */ React2.createElement(ScrollArea.Viewport, null, /* @__PURE__ */ React2.createElement(Menu, {
804
806
  groups: menuGroups,
805
807
  currentItem,
806
808
  onSelect: handleSelect
807
- })), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))), /* @__PURE__ */ React2.createElement("div", {
808
- ref: setRoot,
809
+ })))), /* @__PURE__ */ React2.createElement(Popover.Arrow, null))), /* @__PURE__ */ React2.createElement("div", {
809
810
  role: "none",
810
- className: "contents"
811
+ className: "contents",
812
+ ref: setRoot
811
813
  }, children));
812
814
  };
813
815
  var Menu = ({ groups, currentItem, onSelect }) => {
@@ -819,14 +821,14 @@ var Menu = ({ groups, currentItem, onSelect }) => {
819
821
  currentItem,
820
822
  onSelect
821
823
  }), index < groups.length - 1 && /* @__PURE__ */ React2.createElement("div", {
822
- className: tx("menu.separator", "menu__item", {})
824
+ className: tx("menu.separator", {})
823
825
  }))));
824
826
  };
825
827
  var MenuGroup = ({ group, currentItem, onSelect }) => {
826
828
  const { tx } = useThemeContext();
827
829
  const { t } = useTranslation();
828
830
  return /* @__PURE__ */ React2.createElement(React2.Fragment, null, group.label && /* @__PURE__ */ React2.createElement("div", {
829
- className: tx("menu.groupLabel", "menu__group__label", {})
831
+ className: tx("menu.groupLabel", {})
830
832
  }, /* @__PURE__ */ React2.createElement("span", null, toLocalizedString(group.label, t))), group.items.map((item) => /* @__PURE__ */ React2.createElement(MenuItem, {
831
833
  key: item.id,
832
834
  item,
@@ -854,13 +856,12 @@ var MenuItem = ({ item, current, onSelect }) => {
854
856
  ]);
855
857
  return /* @__PURE__ */ React2.createElement("li", {
856
858
  ref: listRef,
857
- className: tx("menu.item", "menu__item--exotic-unfocusable", {}, [
858
- current && "bg-hoverSurface"
859
+ className: tx("menu.item", {}, [
860
+ current && "bg-hover-surface"
859
861
  ]),
860
862
  onClick: handleSelect
861
863
  }, item.icon && /* @__PURE__ */ React2.createElement(Icon, {
862
- icon: item.icon,
863
- size: 5
864
+ icon: item.icon
864
865
  }), /* @__PURE__ */ React2.createElement("span", {
865
866
  className: "grow truncate"
866
867
  }, toLocalizedString(item.label, t)));
@@ -883,7 +884,7 @@ var useEditorMenu = ({ trigger, triggerKey, placeholder: placeholder2, filter =
883
884
  trigger: trigger2,
884
885
  ...props
885
886
  }) ?? [];
886
- return filter ? filterMenuGroups(groups, (item) => text ? item.label.toLowerCase().startsWith(text.toLowerCase()) : true) : groups;
887
+ return filter && trigger2 !== "@" ? filterMenuGroups(groups, (item) => text ? item.label.toLowerCase().startsWith(text.toLowerCase()) : true) : groups;
887
888
  }, [
888
889
  getMenu,
889
890
  filter
@@ -891,7 +892,7 @@ var useEditorMenu = ({ trigger, triggerKey, placeholder: placeholder2, filter =
891
892
  const handleOpenChange = useCallback3(async ({ view, open: open2 }) => {
892
893
  invariant2(view, void 0, {
893
894
  F: __dxlog_file3,
894
- L: 76,
895
+ L: 77,
895
896
  S: void 0,
896
897
  A: [
897
898
  "view",
@@ -934,10 +935,21 @@ var useEditorMenu = ({ trigger, triggerKey, placeholder: placeholder2, filter =
934
935
  handleOpenChange
935
936
  ]);
936
937
  const handleSelect = useCallback3(({ view, item }) => {
938
+ const { range } = view.state.field(popoverStateField) ?? {};
939
+ if (range) {
940
+ view.dispatch({
941
+ changes: {
942
+ from: range.from,
943
+ to: range.to,
944
+ insert: ""
945
+ }
946
+ });
947
+ }
937
948
  void item.onSelect?.({
938
949
  view,
939
950
  head: view.state.selection.main.head
940
951
  });
952
+ view.focus();
941
953
  }, []);
942
954
  const handleCancel = useCallback3(({ view }) => {
943
955
  const { range, trigger: trigger2 } = view.state.field(popoverStateField) ?? {};
@@ -1019,144 +1031,110 @@ var useEditorMenu = ({ trigger, triggerKey, placeholder: placeholder2, filter =
1019
1031
  import { Atom } from "@effect-atom/atom-react";
1020
1032
  import React3, { memo, useMemo as useMemo3 } from "react";
1021
1033
  import { ElevationProvider } from "@dxos/react-ui";
1022
- import { MenuProvider, ToolbarMenu, createGapSeparator, useMenuActions } from "@dxos/react-ui-menu";
1034
+ import { Menu as Menu2, MenuBuilder, useMenuActions } from "@dxos/react-ui-menu";
1023
1035
 
1024
- // src/components/EditorToolbar/actions.ts
1025
- import { createMenuAction, createMenuItemGroup } from "@dxos/react-ui-menu";
1036
+ // src/components/EditorToolbar/lists.ts
1026
1037
  import { List, addList, removeList } from "@dxos/ui-editor";
1027
1038
  var listStyles = {
1028
1039
  bullet: "ph--list-bullets--regular",
1029
1040
  ordered: "ph--list-numbers--regular",
1030
1041
  task: "ph--list-checks--regular"
1031
1042
  };
1032
- var createLists = (state, getView) => {
1043
+ var addLists = (state, getView) => (builder) => {
1033
1044
  const value = state.listStyle ?? "";
1034
- const listGroupAction = createListGroupAction(value);
1035
- const listActionsMap = createListActions(value, getView);
1036
- return {
1037
- nodes: [
1038
- listGroupAction,
1039
- ...listActionsMap
1040
- ],
1041
- edges: [
1045
+ builder.group("list", {
1046
+ label: [
1047
+ "list.label",
1042
1048
  {
1043
- source: "root",
1044
- target: "list"
1045
- },
1046
- ...listActionsMap.map(({ id }) => ({
1047
- source: listGroupAction.id,
1048
- target: id
1049
- }))
1050
- ]
1051
- };
1052
- };
1053
- var createEditorAction = (id, props, invoke) => {
1054
- const { label = [
1055
- `${id} label`,
1056
- {
1057
- ns: translationKey
1058
- }
1059
- ], ...rest } = props;
1060
- return createMenuAction(id, invoke, {
1061
- label,
1062
- ...rest
1063
- });
1064
- };
1065
- var createEditorActionGroup = (id, props, icon) => {
1066
- const { label = [
1067
- `${id} label`,
1068
- {
1069
- ns: translationKey
1070
- }
1071
- ], ...rest } = props;
1072
- return createMenuItemGroup(id, {
1073
- label,
1074
- icon,
1049
+ ns: translationKey
1050
+ }
1051
+ ],
1075
1052
  iconOnly: true,
1076
- ...rest
1077
- });
1078
- };
1079
- var createListGroupAction = (value) => createEditorActionGroup("list", {
1080
- variant: "toggleGroup",
1081
- selectCardinality: "single",
1082
- value
1083
- });
1084
- var createListActions = (value, getView) => Object.entries(listStyles).map(([listStyle, icon]) => {
1085
- const checked = value === listStyle;
1086
- return createEditorAction(`list-${listStyle}`, {
1087
- checked,
1088
- icon
1089
- }, () => {
1090
- const view = getView();
1091
- if (!view) {
1092
- return;
1093
- }
1094
- const listType = listStyle === "ordered" ? List.Ordered : listStyle === "bullet" ? List.Bullet : List.Task;
1095
- if (checked) {
1096
- removeList(listType)(view);
1097
- } else {
1098
- addList(listType)(view);
1053
+ variant: "toggleGroup",
1054
+ selectCardinality: "single",
1055
+ value
1056
+ }, (group) => {
1057
+ for (const [listStyle, icon] of Object.entries(listStyles)) {
1058
+ const checked = value === listStyle;
1059
+ group.action(`list-${listStyle}`, {
1060
+ label: [
1061
+ `list.${listStyle}.label`,
1062
+ {
1063
+ ns: translationKey
1064
+ }
1065
+ ],
1066
+ checked,
1067
+ icon
1068
+ }, () => {
1069
+ const view = getView();
1070
+ if (!view) {
1071
+ return;
1072
+ }
1073
+ const listType = listStyle === "ordered" ? List.Ordered : listStyle === "bullet" ? List.Bullet : List.Task;
1074
+ if (checked) {
1075
+ removeList(listType)(view);
1076
+ } else {
1077
+ addList(listType)(view);
1078
+ }
1079
+ });
1099
1080
  }
1100
1081
  });
1101
- });
1082
+ };
1102
1083
 
1103
1084
  // src/components/EditorToolbar/blocks.ts
1104
1085
  import { addBlockquote, addCodeblock, insertTable, removeBlockquote, removeCodeblock } from "@dxos/ui-editor";
1105
- var createBlockGroupAction = (value) => createEditorActionGroup("block", {
1106
- variant: "toggleGroup",
1107
- selectCardinality: "single",
1108
- value
1109
- });
1110
- var createBlockActions = (value, getView, blankLine) => Object.entries({
1086
+ var blockTypes = {
1111
1087
  blockquote: "ph--quotes--regular",
1112
1088
  codeblock: "ph--code-block--regular",
1113
1089
  table: "ph--table--regular"
1114
- }).map(([type, icon]) => {
1115
- const checked = type === value;
1116
- return createEditorAction(type, {
1117
- checked,
1118
- ...type === "table" && {
1119
- disabled: !!blankLine
1120
- },
1121
- icon
1122
- }, () => {
1123
- const view = getView();
1124
- if (!view) {
1125
- return;
1126
- }
1127
- switch (type) {
1128
- case "blockquote":
1129
- checked ? removeBlockquote(view) : addBlockquote(view);
1130
- break;
1131
- case "codeblock":
1132
- checked ? removeCodeblock(view) : addCodeblock(view);
1133
- break;
1134
- case "table":
1135
- insertTable(view);
1136
- break;
1137
- }
1138
- });
1139
- });
1140
- var createBlocks = (state, getView) => {
1090
+ };
1091
+ var addBlocks = (state, getView) => (builder) => {
1141
1092
  const value = state?.blockQuote ? "blockquote" : state.blockType ?? "";
1142
- const blockGroupAction = createBlockGroupAction(value);
1143
- const blockActions = createBlockActions(value, getView, state.blankLine);
1144
- return {
1145
- nodes: [
1146
- blockGroupAction,
1147
- ...blockActions
1148
- ],
1149
- edges: [
1093
+ builder.group("block", {
1094
+ label: [
1095
+ "block.label",
1150
1096
  {
1151
- source: "root",
1152
- target: "block"
1153
- },
1154
- ...blockActions.map(({ id }) => ({
1155
- source: blockGroupAction.id,
1156
- target: id
1157
- }))
1158
- ]
1159
- };
1097
+ ns: translationKey
1098
+ }
1099
+ ],
1100
+ iconOnly: true,
1101
+ variant: "toggleGroup",
1102
+ selectCardinality: "single",
1103
+ value
1104
+ }, (group) => {
1105
+ for (const [type, icon] of Object.entries(blockTypes)) {
1106
+ const checked = type === value;
1107
+ group.action(type, {
1108
+ label: [
1109
+ `block.${type}.label`,
1110
+ {
1111
+ ns: translationKey
1112
+ }
1113
+ ],
1114
+ checked,
1115
+ ...type === "table" && {
1116
+ disabled: !!state.blankLine
1117
+ },
1118
+ icon
1119
+ }, () => {
1120
+ const view = getView();
1121
+ if (!view) {
1122
+ return;
1123
+ }
1124
+ switch (type) {
1125
+ case "blockquote":
1126
+ checked ? removeBlockquote(view) : addBlockquote(view);
1127
+ break;
1128
+ case "codeblock":
1129
+ checked ? removeCodeblock(view) : addCodeblock(view);
1130
+ break;
1131
+ case "table":
1132
+ insertTable(view);
1133
+ break;
1134
+ }
1135
+ });
1136
+ }
1137
+ });
1160
1138
  };
1161
1139
 
1162
1140
  // src/components/EditorToolbar/formatting.ts
@@ -1168,201 +1146,174 @@ var formats = {
1168
1146
  code: "ph--code--regular",
1169
1147
  link: "ph--link--regular"
1170
1148
  };
1171
- var createFormattingGroup = (formatting) => createEditorActionGroup("formatting", {
1172
- variant: "toggleGroup",
1173
- selectCardinality: "multiple",
1174
- value: Object.keys(formats).filter((key) => !!formatting[key])
1175
- });
1176
- var createFormattingActions = (formatting, getView) => Object.entries(formats).map(([type, icon]) => {
1177
- const checked = !!formatting[type];
1178
- return createEditorAction(type, {
1179
- checked,
1180
- icon
1181
- }, () => {
1182
- const view = getView();
1183
- if (!view) {
1184
- return;
1185
- }
1186
- if (type === "link") {
1187
- checked ? removeLink(view) : addLink()(view);
1188
- return;
1149
+ var addFormatting = (state, getView) => (builder) => {
1150
+ const formatting = state;
1151
+ builder.group("formatting", {
1152
+ label: [
1153
+ "formatting.label",
1154
+ {
1155
+ ns: translationKey
1156
+ }
1157
+ ],
1158
+ iconOnly: true,
1159
+ variant: "toggleGroup",
1160
+ selectCardinality: "multiple",
1161
+ value: Object.keys(formats).filter((key) => !!formatting[key])
1162
+ }, (group) => {
1163
+ for (const [type, icon] of Object.entries(formats)) {
1164
+ const checked = !!formatting[type];
1165
+ group.action(type, {
1166
+ label: [
1167
+ `formatting.${type}.label`,
1168
+ {
1169
+ ns: translationKey
1170
+ }
1171
+ ],
1172
+ checked,
1173
+ icon
1174
+ }, () => {
1175
+ const view = getView();
1176
+ if (!view) {
1177
+ return;
1178
+ }
1179
+ if (type === "link") {
1180
+ checked ? removeLink(view) : addLink()(view);
1181
+ return;
1182
+ }
1183
+ setStyle(type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code, !checked)(view);
1184
+ });
1189
1185
  }
1190
- const inlineType = type === "strong" ? Inline.Strong : type === "emphasis" ? Inline.Emphasis : type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
1191
- setStyle(inlineType, !checked)(view);
1192
1186
  });
1193
- });
1194
- var createFormatting = (state, getView) => {
1195
- const formattingGroupAction = createFormattingGroup(state);
1196
- const formattingActions = createFormattingActions(state, getView);
1197
- return {
1198
- nodes: [
1199
- formattingGroupAction,
1200
- ...formattingActions
1201
- ],
1202
- edges: [
1203
- {
1204
- source: "root",
1205
- target: "formatting"
1206
- },
1207
- ...formattingActions.map(({ id }) => ({
1208
- source: formattingGroupAction.id,
1209
- target: id
1210
- }))
1211
- ]
1212
- };
1213
1187
  };
1214
1188
 
1215
1189
  // src/components/EditorToolbar/headings.ts
1216
1190
  import { setHeading } from "@dxos/ui-editor";
1217
- var createHeadingGroupAction = (value) => createEditorActionGroup("heading", {
1218
- variant: "dropdownMenu",
1219
- applyActive: true,
1220
- selectCardinality: "single",
1221
- // TODO(wittjosiah): Remove? Not sure this does anything.
1222
- value
1223
- }, "ph--text-h--regular");
1224
- var createHeadingActions = (currentLevel, getView) => Object.entries({
1225
- "0": "ph--paragraph--regular",
1226
- "1": "ph--text-h-one--regular",
1227
- "2": "ph--text-h-two--regular",
1228
- "3": "ph--text-h-three--regular",
1229
- "4": "ph--text-h-four--regular",
1230
- "5": "ph--text-h-five--regular",
1231
- "6": "ph--text-h-six--regular"
1232
- }).map(([levelStr, icon]) => {
1233
- const level = parseInt(levelStr);
1234
- return createEditorAction(`heading--${levelStr}`, {
1235
- label: [
1236
- "heading level label",
1237
- {
1238
- count: level,
1239
- ns: translationKey
1240
- }
1241
- ],
1242
- icon,
1243
- checked: levelStr === currentLevel
1244
- }, () => setHeading(level)(getView()));
1245
- });
1191
+ var headingIcons = {
1192
+ 0: "ph--paragraph--regular",
1193
+ 1: "ph--text-h-one--regular",
1194
+ 2: "ph--text-h-two--regular",
1195
+ 3: "ph--text-h-three--regular",
1196
+ 4: "ph--text-h-four--regular",
1197
+ 5: "ph--text-h-five--regular",
1198
+ 6: "ph--text-h-six--regular"
1199
+ };
1246
1200
  var computeHeadingValue = (state) => {
1247
1201
  const blockType = state ? state.blockType : "paragraph";
1248
1202
  const heading = blockType && /heading(\d)/.exec(blockType);
1249
1203
  return heading ? heading[1] : blockType === "paragraph" || !blockType ? "0" : "";
1250
1204
  };
1251
- var createHeadings = (state, getView) => {
1205
+ var addHeadings = (state, getView) => (builder) => {
1252
1206
  const headingValue = computeHeadingValue(state);
1253
- const headingGroupAction = createHeadingGroupAction(headingValue);
1254
- const headingActions = createHeadingActions(headingValue, getView);
1255
- return {
1256
- nodes: [
1257
- headingGroupAction,
1258
- ...headingActions
1259
- ],
1260
- edges: [
1207
+ builder.group("heading", {
1208
+ label: [
1209
+ "heading.label",
1261
1210
  {
1262
- source: "root",
1263
- target: "heading"
1264
- },
1265
- ...headingActions.map(({ id }) => ({
1266
- source: headingGroupAction.id,
1267
- target: id
1268
- }))
1269
- ]
1270
- };
1211
+ ns: translationKey
1212
+ }
1213
+ ],
1214
+ icon: "ph--text-h--regular",
1215
+ iconOnly: true,
1216
+ variant: "dropdownMenu",
1217
+ applyActive: true,
1218
+ selectCardinality: "single",
1219
+ // TODO(wittjosiah): Remove? Not sure this does anything.
1220
+ value: headingValue
1221
+ }, (group) => {
1222
+ for (const [levelStr, icon] of Object.entries(headingIcons)) {
1223
+ const level = parseInt(levelStr);
1224
+ group.action(`heading--${levelStr}`, {
1225
+ label: [
1226
+ "heading-level.label",
1227
+ {
1228
+ count: level,
1229
+ ns: translationKey
1230
+ }
1231
+ ],
1232
+ icon,
1233
+ checked: levelStr === headingValue
1234
+ }, () => setHeading(level)(getView()));
1235
+ }
1236
+ });
1271
1237
  };
1272
1238
 
1273
1239
  // src/components/EditorToolbar/image.ts
1274
- var createImageUploadAction = (onImageUpload) => createEditorAction("image", {
1275
- testId: "editor.toolbar.image",
1276
- icon: "ph--image-square--regular"
1277
- }, onImageUpload);
1278
- var createImageUpload = (onImageUpload) => ({
1279
- nodes: [
1280
- createImageUploadAction(onImageUpload)
1281
- ],
1282
- edges: [
1283
- {
1284
- source: "root",
1285
- target: "image"
1286
- }
1287
- ]
1288
- });
1240
+ var addImageUpload = (onImageUpload) => (builder) => {
1241
+ builder.action("image", {
1242
+ label: [
1243
+ "image.label",
1244
+ {
1245
+ ns: translationKey
1246
+ }
1247
+ ],
1248
+ testId: "editor.toolbar.image",
1249
+ icon: "ph--image-square--regular"
1250
+ }, onImageUpload);
1251
+ };
1289
1252
 
1290
1253
  // src/components/EditorToolbar/search.ts
1291
1254
  import { openSearchPanel } from "@codemirror/search";
1292
- var createSearchAction = (getView) => createEditorAction("search", {
1293
- testId: "editor.toolbar.search",
1294
- icon: "ph--magnifying-glass--regular"
1295
- }, () => openSearchPanel(getView()));
1296
- var createSearch = (getView) => ({
1297
- nodes: [
1298
- createSearchAction(getView)
1299
- ],
1300
- edges: [
1301
- {
1302
- source: "root",
1303
- target: "search"
1304
- }
1305
- ]
1306
- });
1255
+ var addSearch = (getView) => (builder) => {
1256
+ builder.action("search", {
1257
+ label: [
1258
+ "search.label",
1259
+ {
1260
+ ns: translationKey
1261
+ }
1262
+ ],
1263
+ testId: "editor.toolbar.search",
1264
+ icon: "ph--magnifying-glass--regular"
1265
+ }, () => openSearchPanel(getView()));
1266
+ };
1307
1267
 
1308
1268
  // src/components/EditorToolbar/view-mode.ts
1309
- var createViewModeGroupAction = (value) => createEditorActionGroup("viewMode", {
1310
- variant: "dropdownMenu",
1311
- applyActive: true,
1312
- selectCardinality: "single",
1313
- value
1314
- }, "ph--eye--regular");
1315
- var createViewModeActions = (value, onViewModeChange) => Object.entries({
1269
+ var viewModes = {
1316
1270
  preview: "ph--eye--regular",
1317
1271
  source: "ph--pencil-simple--regular",
1318
1272
  readonly: "ph--pencil-slash--regular"
1319
- }).map(([viewMode, icon]) => {
1320
- const checked = viewMode === value;
1321
- return createEditorAction(`view-mode--${viewMode}`, {
1273
+ };
1274
+ var addViewMode = (state, onViewModeChange) => (builder) => {
1275
+ const value = state.viewMode ?? "source";
1276
+ builder.group("viewMode", {
1322
1277
  label: [
1323
- `${viewMode} mode label`,
1278
+ "view-mode.label",
1324
1279
  {
1325
1280
  ns: translationKey
1326
1281
  }
1327
1282
  ],
1328
- checked,
1329
- icon
1330
- }, () => onViewModeChange(viewMode));
1331
- });
1332
- var createViewMode = (state, onViewModeChange) => {
1333
- const value = state.viewMode ?? "source";
1334
- const viewModeGroupAction = createViewModeGroupAction(value);
1335
- const viewModeActions = createViewModeActions(value, onViewModeChange);
1336
- return {
1337
- nodes: [
1338
- viewModeGroupAction,
1339
- ...viewModeActions
1340
- ],
1341
- edges: [
1342
- {
1343
- source: "root",
1344
- target: "viewMode"
1345
- },
1346
- ...viewModeActions.map(({ id }) => ({
1347
- source: viewModeGroupAction.id,
1348
- target: id
1349
- }))
1350
- ]
1351
- };
1283
+ icon: "ph--eye--regular",
1284
+ iconOnly: true,
1285
+ variant: "dropdownMenu",
1286
+ applyActive: true,
1287
+ selectCardinality: "single",
1288
+ value
1289
+ }, (group) => {
1290
+ for (const [viewMode, icon] of Object.entries(viewModes)) {
1291
+ const checked = viewMode === value;
1292
+ group.action(`view-mode--${viewMode}`, {
1293
+ label: [
1294
+ `view-mode.${viewMode}.label`,
1295
+ {
1296
+ ns: translationKey
1297
+ }
1298
+ ],
1299
+ checked,
1300
+ icon
1301
+ }, () => onViewModeChange(viewMode));
1302
+ }
1303
+ });
1352
1304
  };
1353
1305
 
1354
1306
  // src/components/EditorToolbar/EditorToolbar.tsx
1355
1307
  var EditorToolbar = /* @__PURE__ */ memo(({ classNames, role, attendableId, onAction, ...props }) => {
1356
- const menuProps = useEditorToolbarActionGraph(props);
1308
+ const menuActions = useEditorToolbarActionGraph(props);
1357
1309
  return /* @__PURE__ */ React3.createElement(ElevationProvider, {
1358
1310
  elevation: role === "section" ? "positioned" : "base"
1359
- }, /* @__PURE__ */ React3.createElement(MenuProvider, {
1360
- ...menuProps,
1311
+ }, /* @__PURE__ */ React3.createElement(Menu2.Root, {
1312
+ ...menuActions,
1361
1313
  attendableId,
1362
1314
  onAction
1363
- }, /* @__PURE__ */ React3.createElement(ToolbarMenu, {
1364
- classNames,
1365
- textBlockWidth: true
1315
+ }, /* @__PURE__ */ React3.createElement(Menu2.Toolbar, {
1316
+ classNames
1366
1317
  })));
1367
1318
  });
1368
1319
  var useEditorToolbarActionGraph = ({ state, getView, customActions, ...features }) => {
@@ -1387,41 +1338,8 @@ var useEditorToolbarActionGraph = ({ state, getView, customActions, ...features
1387
1338
  };
1388
1339
  var createToolbarActions = ({ state, getView, customActions, ...features }) => {
1389
1340
  return Atom.make((get) => {
1390
- const graph = {
1391
- nodes: [],
1392
- edges: []
1393
- };
1394
- const addSubGraph = (graph2, subGraph) => {
1395
- graph2.nodes.push(...subGraph.nodes);
1396
- graph2.edges.push(...subGraph.edges);
1397
- };
1398
1341
  const stateSnapshot = get(state);
1399
- if (features?.showHeadings ?? true) {
1400
- addSubGraph(graph, createHeadings(stateSnapshot, getView));
1401
- }
1402
- if (features?.showFormatting ?? true) {
1403
- addSubGraph(graph, createFormatting(stateSnapshot, getView));
1404
- }
1405
- if (features?.showLists ?? true) {
1406
- addSubGraph(graph, createLists(stateSnapshot, getView));
1407
- }
1408
- if (features?.showBlocks ?? true) {
1409
- addSubGraph(graph, createBlocks(stateSnapshot, getView));
1410
- }
1411
- if (features?.onImageUpload) {
1412
- addSubGraph(graph, createImageUpload(features.onImageUpload));
1413
- }
1414
- addSubGraph(graph, createGapSeparator());
1415
- if (customActions) {
1416
- addSubGraph(graph, get(customActions));
1417
- }
1418
- if (features?.showSearch ?? true) {
1419
- addSubGraph(graph, createSearch(getView));
1420
- }
1421
- if (features?.onViewModeChange) {
1422
- addSubGraph(graph, createViewMode(stateSnapshot, features.onViewModeChange));
1423
- }
1424
- return graph;
1342
+ return MenuBuilder.make().subgraph(features?.showHeadings !== false && addHeadings(stateSnapshot, getView)).subgraph(features?.showFormatting !== false && addFormatting(stateSnapshot, getView)).subgraph(features?.showLists !== false && addLists(stateSnapshot, getView)).subgraph(features?.showBlocks !== false && addBlocks(stateSnapshot, getView)).subgraph(features?.onImageUpload && addImageUpload(features.onImageUpload)).separator("gap").subgraph(customActions && get(customActions)).subgraph(features?.showSearch !== false && addSearch(getView)).subgraph(features?.onViewModeChange && addViewMode(stateSnapshot, features.onViewModeChange)).build();
1425
1343
  });
1426
1344
  };
1427
1345
 
@@ -1463,15 +1381,17 @@ var EditorRoot = /* @__PURE__ */ forwardRef2(({ children, extensions: extensions
1463
1381
  }, children));
1464
1382
  });
1465
1383
  EditorRoot.displayName = "Editor.Root";
1384
+ var EDITOR_VIEWPORT_NAME = "Editor.Viewport";
1466
1385
  var EditorViewport = ({ classNames, children }) => {
1467
1386
  return /* @__PURE__ */ React4.createElement("div", {
1468
1387
  role: "none",
1469
- className: mx2("grid grid-rows-[min-content_1fr] bs-full overflow-hidden", classNames)
1388
+ className: mx2("grid grid-rows-[min-content_1fr] h-full overflow-hidden", classNames)
1470
1389
  }, children);
1471
1390
  };
1472
- EditorViewport.displayName = "Editor.Viewport";
1391
+ EditorViewport.displayName = EDITOR_VIEWPORT_NAME;
1392
+ var EDITOR_CONTENT_NAME = "Editor.Content";
1473
1393
  var EditorContent2 = ({ extensions: providedExtensions, ...props }) => {
1474
- const { extensions: additionalExtensions = [], setController } = useEditorContext(EditorContent2.displayName);
1394
+ const { extensions: additionalExtensions = [], setController } = useEditorContext(EDITOR_CONTENT_NAME);
1475
1395
  const extensions = useMemo5(() => [
1476
1396
  additionalExtensions,
1477
1397
  providedExtensions
@@ -1485,13 +1405,14 @@ var EditorContent2 = ({ extensions: providedExtensions, ...props }) => {
1485
1405
  ref: setController
1486
1406
  });
1487
1407
  };
1488
- EditorContent2.displayName = "Editor.Content";
1408
+ EditorContent2.displayName = EDITOR_CONTENT_NAME;
1409
+ var EDITOR_TOOLBAR_NAME = "Editor.Toolbar";
1489
1410
  var EditorToolbar2 = (props) => {
1490
- const { controller, state } = useEditorContext(EditorToolbar2.displayName);
1411
+ const { controller, state } = useEditorContext(EDITOR_TOOLBAR_NAME);
1491
1412
  const getView = useCallback4(() => {
1492
1413
  invariant3(controller?.view, void 0, {
1493
1414
  F: __dxlog_file4,
1494
- L: 140,
1415
+ L: 146,
1495
1416
  S: void 0,
1496
1417
  A: [
1497
1418
  "controller?.view",
@@ -1508,7 +1429,7 @@ var EditorToolbar2 = (props) => {
1508
1429
  state
1509
1430
  });
1510
1431
  };
1511
- EditorToolbar2.displayName = "Editor.Toolbar";
1432
+ EditorToolbar2.displayName = EDITOR_TOOLBAR_NAME;
1512
1433
  var Editor = {
1513
1434
  Root: EditorRoot,
1514
1435
  Viewport: EditorViewport,
@@ -1527,20 +1448,20 @@ var EditorPreviewProvider = ({ children, onLookup }) => {
1527
1448
  const [value, setValue] = useState5({});
1528
1449
  const [open, setOpen] = useState5(false);
1529
1450
  const handleActivate = useCallback5((event) => {
1530
- const { refId, label, trigger: dxTrigger } = event;
1451
+ const { dxn, label, trigger } = event;
1531
1452
  setValue((value2) => ({
1532
1453
  ...value2,
1533
1454
  link: {
1534
1455
  label,
1535
- ref: refId
1456
+ dxn
1536
1457
  },
1537
1458
  pending: true
1538
1459
  }));
1539
- triggerRef.current = dxTrigger;
1460
+ triggerRef.current = trigger;
1540
1461
  queueMicrotask(() => setOpen(true));
1541
1462
  void onLookup?.({
1542
1463
  label,
1543
- ref: refId
1464
+ dxn
1544
1465
  }).then((target) => setValue((value2) => ({
1545
1466
  ...value2,
1546
1467
  target: target ?? void 0,
@@ -1572,9 +1493,9 @@ var EditorPreviewProvider = ({ children, onLookup }) => {
1572
1493
  }, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
1573
1494
  virtualRef: triggerRef
1574
1495
  }), /* @__PURE__ */ React5.createElement("div", {
1575
- ref: setRoot,
1576
1496
  role: "none",
1577
- className: "contents"
1497
+ className: "contents",
1498
+ ref: setRoot
1578
1499
  }, children)));
1579
1500
  };
1580
1501
  export {