@platecms/delta-smart-text 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/.env.example +7 -0
  2. package/__generated__/fragment-masking.ts +87 -0
  3. package/__generated__/gql.ts +238 -0
  4. package/__generated__/graphql.ts +3441 -0
  5. package/__generated__/index.ts +2 -0
  6. package/codegen.config.ts +24 -0
  7. package/eslint.config.mjs +43 -0
  8. package/i18n.js +28 -0
  9. package/package.json +5 -5
  10. package/project.json +54 -0
  11. package/src/components/DeltaSlateEditor.vue +74 -0
  12. package/src/components/icon/FontAwesomeIcon.vue +21 -0
  13. package/src/graphql/apiTokens/apiTokens.fragments.gql +8 -0
  14. package/src/graphql/assets/assets.fragments.gql +10 -0
  15. package/src/graphql/blueprints/blueprints.fragments.gql +52 -0
  16. package/src/graphql/buildingBlockFieldFulfillments/buildingBlockFieldFullfillment.fragements.gql +6 -0
  17. package/src/graphql/buildingBlockFields/buildingBlockField.fragments.gql +8 -0
  18. package/src/graphql/buildingBlocks/buildingBlocks.fragments.gql +11 -0
  19. package/src/graphql/channels/channels.fragments.gql +9 -0
  20. package/src/graphql/contentExperiences/allContentExperiences.query.gql +24 -0
  21. package/src/graphql/contentExperiences/contentExperience.query.gql +20 -0
  22. package/src/graphql/contentExperiences/contentExperiences.fragments.gql +14 -0
  23. package/src/graphql/contentFields/contentFields.fragments.gql +7 -0
  24. package/src/graphql/contentItems/allContentItems.query.gql +48 -0
  25. package/src/graphql/contentItems/contentItems.fragments.gql +11 -0
  26. package/src/graphql/contentTypes/allContentTypes.query.gql +26 -0
  27. package/src/graphql/contentTypes/contentTypes.fragments.gql +11 -0
  28. package/src/graphql/contentValidations/contentValidationRule.fragments.gql +34 -0
  29. package/src/graphql/contentValues/allContentValues.query.gql +41 -0
  30. package/src/graphql/contentValues/contentValues.fragments.gql +9 -0
  31. package/src/graphql/contentValues/createContentValue.mutation.gql +17 -0
  32. package/src/graphql/experienceComponents/experienceComponent.fragments.gql +13 -0
  33. package/src/graphql/fragments.gql +6 -0
  34. package/src/graphql/gridDefinition/gridDefinition.fragments.gql +5 -0
  35. package/src/graphql/gridPlacements/gridPlacement.fragments.gql +7 -0
  36. package/src/graphql/grids/grid.fragments.gql +7 -0
  37. package/src/graphql/invitations/invitations.fragments.gql +7 -0
  38. package/src/graphql/organizations/organizations.fragments.gql +13 -0
  39. package/src/graphql/pathParts/pathParts.fragments.gql +19 -0
  40. package/src/graphql/plateMaintainers/plateMaintainer.fragements.gql +10 -0
  41. package/src/graphql/roleAssignments/roleAssignment.fragments.gql +9 -0
  42. package/src/graphql/roles/roles.fragments.gql +7 -0
  43. package/src/graphql/subject/subject.fragments.gql +8 -0
  44. package/src/graphql/tags/tags.fragments.gql +17 -0
  45. package/src/graphql/themes/themes.fragments.gql +8 -0
  46. package/src/index.css +1 -0
  47. package/src/index.ts +21 -0
  48. package/src/locales/en.json +52 -0
  49. package/src/locales/nl.json +52 -0
  50. package/src/react/components/DeltaSlateEditor.tsx +243 -0
  51. package/src/react/components/DeltaSlateEditorConnector.tsx +50 -0
  52. package/src/react/components/Element.spec.tsx +244 -0
  53. package/src/react/components/Element.tsx +151 -0
  54. package/src/react/components/FontAwesomeIcon.tsx +17 -0
  55. package/src/react/components/Leaf.spec.tsx +61 -0
  56. package/src/react/components/Leaf.tsx +22 -0
  57. package/src/react/components/elements/CodeElement.tsx +16 -0
  58. package/src/react/components/elements/ContentValueElement.tsx +33 -0
  59. package/src/react/components/elements/LinkElement.tsx +44 -0
  60. package/src/react/components/inputs/SearchInput.tsx +22 -0
  61. package/src/react/components/inputs/TextInput.tsx +30 -0
  62. package/src/react/components/menus/ContentAndFormatMenu.tsx +272 -0
  63. package/src/react/components/menus/ContentLibraryMenu.tsx +48 -0
  64. package/src/react/components/menus/ReusableContentMenu.tsx +190 -0
  65. package/src/react/components/menus/content/ContentItemsMenu.tsx +215 -0
  66. package/src/react/components/menus/content/ContentTypesMenu.tsx +129 -0
  67. package/src/react/components/menus/content/partials/ContentFieldMenuItem.tsx +11 -0
  68. package/src/react/components/menus/content/partials/ContentValueMenuItem.tsx +58 -0
  69. package/src/react/components/menus/link/AnchorInput.tsx +123 -0
  70. package/src/react/components/menus/link/LinkInput.tsx +195 -0
  71. package/src/react/components/menus/link/LinkMenu.spec.tsx +145 -0
  72. package/src/react/components/menus/link/LinkMenu.tsx +289 -0
  73. package/src/react/components/menus/partials/MenuButton.tsx +52 -0
  74. package/src/react/components/menus/partials/MenuContainer.tsx +9 -0
  75. package/src/react/components/menus/partials/MenuHeader.tsx +11 -0
  76. package/src/react/components/toolbar/Toolbar.tsx +249 -0
  77. package/src/react/components/toolbar/ToolbarBlockButton.tsx +31 -0
  78. package/src/react/components/toolbar/ToolbarHeadingDropdownButton.tsx +76 -0
  79. package/src/react/components/toolbar/ToolbarLinkButton.tsx +33 -0
  80. package/src/react/components/toolbar/ToolbarMarkButton.tsx +25 -0
  81. package/src/react/components/toolbar/content/ContentExtractToolbarButton.tsx +68 -0
  82. package/src/react/components/toolbar/content/ContentLibraryToolbarButton.tsx +43 -0
  83. package/src/react/components/toolbar/content/ContentToolbar.tsx +37 -0
  84. package/src/react/components/toolbar/link/ToolbarDisplayLink.tsx +36 -0
  85. package/src/react/components/toolbar/link/UnlinkButton.tsx +25 -0
  86. package/src/react/config/hotkeys.ts +8 -0
  87. package/src/react/plugins/index.ts +59 -0
  88. package/src/react/store/editorSlice.ts +124 -0
  89. package/src/react/store/store.ts +12 -0
  90. package/src/react/types.ts +87 -0
  91. package/src/react/utils/decorator.ts +61 -0
  92. package/src/react/utils/index.ts +110 -0
  93. package/src/vue-shims.d.ts +5 -0
  94. package/tsconfig.json +26 -0
  95. package/tsconfig.lib.json +25 -0
  96. package/tsconfig.spec.json +22 -0
  97. package/vite.config.ts +67 -0
  98. package/components/DeltaSlateEditor.vue.d.ts +0 -26
  99. package/index.cjs +0 -381
  100. package/index.css +0 -1
  101. package/index.d.ts +0 -12
  102. package/index.js +0 -49254
  103. package/react/components/DeltaSlateEditor.d.ts +0 -7
  104. package/react/components/DeltaSlateEditorConnector.d.ts +0 -12
  105. package/react/components/Element.d.ts +0 -8
  106. package/react/components/FontAwesomeIcon.d.ts +0 -6
  107. package/react/components/Leaf.d.ts +0 -3
  108. package/react/components/elements/CodeElement.d.ts +0 -8
  109. package/react/components/elements/ContentValueElement.d.ts +0 -8
  110. package/react/components/elements/LinkElement.d.ts +0 -8
  111. package/react/components/inputs/SearchInput.d.ts +0 -5
  112. package/react/components/inputs/TextInput.d.ts +0 -7
  113. package/react/components/menus/ContentAndFormatMenu.d.ts +0 -10
  114. package/react/components/menus/ContentLibraryMenu.d.ts +0 -4
  115. package/react/components/menus/ReusableContentMenu.d.ts +0 -3
  116. package/react/components/menus/content/ContentItemsMenu.d.ts +0 -5
  117. package/react/components/menus/content/ContentTypesMenu.d.ts +0 -6
  118. package/react/components/menus/content/partials/ContentFieldMenuItem.d.ts +0 -6
  119. package/react/components/menus/content/partials/ContentValueMenuItem.d.ts +0 -7
  120. package/react/components/menus/link/AnchorInput.d.ts +0 -8
  121. package/react/components/menus/link/LinkInput.d.ts +0 -11
  122. package/react/components/menus/link/LinkMenu.d.ts +0 -18
  123. package/react/components/menus/partials/MenuButton.d.ts +0 -7
  124. package/react/components/menus/partials/MenuContainer.d.ts +0 -4
  125. package/react/components/menus/partials/MenuHeader.d.ts +0 -5
  126. package/react/components/toolbar/Toolbar.d.ts +0 -6
  127. package/react/components/toolbar/ToolbarBlockButton.d.ts +0 -12
  128. package/react/components/toolbar/ToolbarHeadingDropdownButton.d.ts +0 -2
  129. package/react/components/toolbar/ToolbarLinkButton.d.ts +0 -6
  130. package/react/components/toolbar/ToolbarMarkButton.d.ts +0 -6
  131. package/react/components/toolbar/content/ContentExtractToolbarButton.d.ts +0 -2
  132. package/react/components/toolbar/content/ContentLibraryToolbarButton.d.ts +0 -5
  133. package/react/components/toolbar/content/ContentToolbar.d.ts +0 -4
  134. package/react/components/toolbar/link/ToolbarDisplayLink.d.ts +0 -2
  135. package/react/components/toolbar/link/UnlinkButton.d.ts +0 -2
  136. package/react/config/hotkeys.d.ts +0 -2
  137. package/react/plugins/index.d.ts +0 -3
  138. package/react/store/editorSlice.d.ts +0 -169
  139. package/react/store/store.d.ts +0 -5
  140. package/react/types.d.ts +0 -65
  141. package/react/utils/decorator.d.ts +0 -15
  142. package/react/utils/index.d.ts +0 -17
@@ -0,0 +1,59 @@
1
+ import { Editor, NodeEntry, Range, Text } from "slate";
2
+ import Prism, { Token } from "prismjs";
3
+
4
+ export function withContentValues(editor: Editor): Editor {
5
+ const { isInline, isVoid, markableVoid } = editor;
6
+
7
+ editor.isInline = (element): boolean =>
8
+ element.type === "contentValue" || element.type === "link" ? true : isInline(element);
9
+
10
+ editor.isVoid = (element): boolean => (element.type === "contentValue" ? true : isVoid(element));
11
+
12
+ editor.markableVoid = (element): boolean => (element.type === "contentValue" ? true : markableVoid(element));
13
+
14
+ return editor;
15
+ }
16
+
17
+ export function decorate([node, path]: NodeEntry): Range[] {
18
+ const ranges: Range[] = [];
19
+
20
+ if (!Text.isText(node)) {
21
+ return ranges;
22
+ }
23
+
24
+ function getLength(token: Token | string): number {
25
+ if (typeof token === "string") {
26
+ return token.length;
27
+ }
28
+
29
+ if (typeof token.content === "string") {
30
+ return token.content.length;
31
+ }
32
+
33
+ if (Array.isArray(token.content)) {
34
+ return token.content.reduce((length, tokenContent): number => length + getLength(tokenContent), 0);
35
+ }
36
+
37
+ return 0;
38
+ }
39
+
40
+ const tokens = Prism.tokenize(node.text, Prism.languages.markdown);
41
+ let start = 0;
42
+
43
+ for (const token of tokens) {
44
+ const length = getLength(token);
45
+ const end = start + length;
46
+
47
+ if (typeof token !== "string") {
48
+ ranges.push({
49
+ [token.type]: true,
50
+ anchor: { path, offset: start },
51
+ focus: { path, offset: end },
52
+ });
53
+ }
54
+
55
+ start = end;
56
+ }
57
+
58
+ return ranges;
59
+ }
@@ -0,0 +1,124 @@
1
+ import { BaseSelection, Descendant } from "slate";
2
+ import { createSelector, createSlice } from "@reduxjs/toolkit";
3
+ import { ContentItem, ContentType, Organization } from "../../../__generated__/graphql";
4
+
5
+ interface EditorSlice {
6
+ organization: Organization | undefined;
7
+ states: EditorState[];
8
+ }
9
+
10
+ export interface EditorState {
11
+ uuid: string;
12
+ search: string;
13
+ target: BaseSelection | undefined;
14
+ initialValue: Descendant[];
15
+ value: Descendant[];
16
+ selected: {
17
+ contentType: string | undefined;
18
+ contentItem: string | undefined;
19
+ };
20
+ options: {
21
+ contentTypes: ContentType[];
22
+ contentItems: Record<string, ContentItem[]>;
23
+ };
24
+ }
25
+
26
+ export const defaultEditorFieldState: Omit<EditorState, "uuid"> = {
27
+ search: "",
28
+ initialValue: [],
29
+ value: [],
30
+ target: undefined,
31
+ selected: {
32
+ contentType: undefined,
33
+ contentItem: undefined,
34
+ },
35
+ options: {
36
+ contentTypes: [],
37
+ contentItems: {},
38
+ },
39
+ };
40
+
41
+ const initialState: EditorSlice = {
42
+ organization: undefined,
43
+ states: [],
44
+ };
45
+
46
+ function selectStates(state: EditorSlice): EditorState[] {
47
+ return state.states;
48
+ }
49
+
50
+ function selectStateIndex(state: EditorSlice, uuid: string): number {
51
+ return state.states.findIndex((stateToFilter) => stateToFilter.uuid === uuid);
52
+ }
53
+
54
+ function selectCurrentOrganization(state: EditorSlice): Organization | undefined {
55
+ return state.organization;
56
+ }
57
+
58
+ const selectStateById = createSelector([selectStates, selectStateIndex], (states, index) => states[index]);
59
+
60
+ const editorSlice = createSlice({
61
+ name: "editor",
62
+ initialState,
63
+ reducers: {
64
+ setOrganization: (state, action: { payload: { organization: Organization | undefined } }) => {
65
+ state.organization = action.payload.organization;
66
+ },
67
+ setState: (
68
+ state,
69
+ action: { payload: { uuid: string; state?: Partial<Omit<EditorState, "uuid">>; context?: string } },
70
+ ) => {
71
+ const currentState = state.states.find((stateToFilter) => stateToFilter.uuid === action.payload.uuid);
72
+
73
+ if (!currentState) {
74
+ state.states.push({
75
+ uuid: action.payload.uuid,
76
+ ...defaultEditorFieldState,
77
+ ...action.payload.state,
78
+ });
79
+ return;
80
+ }
81
+
82
+ if (action.payload.state?.search !== undefined) {
83
+ currentState.search = action.payload.state.search;
84
+ }
85
+ if (action.payload.state?.selected) {
86
+ currentState.selected = action.payload.state.selected;
87
+ }
88
+
89
+ if (action.payload.state && "target" in action.payload.state) {
90
+ currentState.target = action.payload.state.target;
91
+ }
92
+ currentState.value = action.payload.state?.value ?? currentState.value;
93
+ currentState.initialValue = action.payload.state?.initialValue ?? currentState.initialValue;
94
+ },
95
+ setInitialValue: (state, action: { payload: { uuid: string; initialValue: Descendant[] } }) => {
96
+ const currentState = state.states.find((stateToFilter) => stateToFilter.uuid === action.payload.uuid);
97
+
98
+ if (!currentState) {
99
+ return;
100
+ }
101
+
102
+ currentState.initialValue = action.payload.initialValue;
103
+ },
104
+ },
105
+ selectors: {
106
+ selectStates,
107
+ selectStateIndex,
108
+ selectStateById,
109
+ selectCurrentOrganization,
110
+ selectStateByIdTarget: createSelector([selectStateById], (state) => state.target),
111
+ selectStateByIdSelected: createSelector([selectStateById], (state) => state.selected),
112
+ },
113
+ });
114
+
115
+ export const {
116
+ selectStateById: selectById,
117
+ selectStateByIdTarget: selectByIdTarget,
118
+ selectStateByIdSelected: selectByIdSelected,
119
+ selectCurrentOrganization: selectOrganization,
120
+ } = editorSlice.selectors;
121
+
122
+ export const { setState, setOrganization, setInitialValue } = editorSlice.actions;
123
+
124
+ export default editorSlice.reducer;
@@ -0,0 +1,12 @@
1
+ import { Action, Store, ThunkAction, configureStore } from "@reduxjs/toolkit";
2
+ import editorReducer from "./editorSlice";
3
+
4
+ export const store: Store = configureStore({
5
+ reducer: {
6
+ editor: editorReducer,
7
+ },
8
+ });
9
+
10
+ export type RootState = ReturnType<typeof store.getState>;
11
+ export type AppDispatch = typeof store.dispatch;
12
+ export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>;
@@ -0,0 +1,87 @@
1
+ import { BaseEditor } from "slate";
2
+ import { ReactEditor } from "slate-react";
3
+ import { Root } from "@platecms/delta-cast";
4
+
5
+ declare module "slate" {
6
+ interface CustomTypes {
7
+ Editor: BaseEditor & ReactEditor;
8
+ Element: DeltaElement;
9
+ Text: DeltaLeaf;
10
+ }
11
+ }
12
+
13
+ export interface DeltaLeafMarkdown {
14
+ title?: boolean;
15
+ }
16
+
17
+ export type DeltaElement =
18
+ | BlockquoteElement
19
+ | CodeElement
20
+ | ContentValueElement
21
+ | HeadingElement
22
+ | LinkElement
23
+ | ListElement
24
+ | ListItemElement
25
+ | ParagraphElement;
26
+
27
+ export type DeltaLeaf = DeltaLeafMarkdown & {
28
+ text: string;
29
+ bold?: true;
30
+ italic?: true;
31
+ underline?: true;
32
+ strikethrough?: true;
33
+ inlineCode?: true;
34
+ highlight?: true;
35
+ };
36
+
37
+ export interface ParagraphElement {
38
+ type: "paragraph";
39
+ children: (ContentValueElement | DeltaLeaf | LinkElement)[];
40
+ }
41
+
42
+ export interface HeadingElement {
43
+ type: "heading";
44
+ level: 1 | 2 | 3 | 4 | 5 | 6;
45
+ children: DeltaLeaf[];
46
+ }
47
+
48
+ export interface ListElement {
49
+ type: "list";
50
+ ordered: boolean;
51
+ children: ListItemElement[];
52
+ }
53
+
54
+ export interface ListItemElement {
55
+ type: "listItem";
56
+ children: DeltaLeaf[];
57
+ }
58
+
59
+ export interface BlockquoteElement {
60
+ type: "blockquote";
61
+ children: DeltaLeaf[];
62
+ }
63
+
64
+ export interface CodeElement {
65
+ type: "code";
66
+ children: DeltaLeaf[];
67
+ }
68
+
69
+ export interface ContentValueElement {
70
+ type: "contentValue";
71
+ prn: string;
72
+ root: Root | undefined;
73
+ children: DeltaLeaf[];
74
+ }
75
+
76
+ export interface LinkElement {
77
+ type: "link";
78
+ url: string;
79
+ children: DeltaLeaf[];
80
+
81
+ target?: "_parent" | "_top" | "blank" | "self";
82
+
83
+ internal?: {
84
+ prn: string;
85
+ anchor?: boolean;
86
+ };
87
+ }
@@ -0,0 +1,61 @@
1
+ import { DeltaLeaf } from "../types";
2
+
3
+ export type Decorator<T> = (element: T, decorations: string[]) => string[];
4
+ export type LeafDecorator = Decorator<DeltaLeaf>;
5
+
6
+ function fontWeight(leaf: DeltaLeaf, decorations: string[]): string[] {
7
+ if (leaf.bold) {
8
+ decorations.push("font-bold");
9
+ }
10
+
11
+ return decorations;
12
+ }
13
+
14
+ function fontSize(leaf: DeltaLeaf, decorations: string[]): string[] {
15
+ if (leaf.title) {
16
+ decorations.push(`text-2xl`);
17
+ }
18
+
19
+ return decorations;
20
+ }
21
+
22
+ function fontStyle(leaf: DeltaLeaf, decorations: string[]): string[] {
23
+ if (leaf.italic) {
24
+ decorations.push("italic");
25
+ }
26
+
27
+ return decorations;
28
+ }
29
+
30
+ function textDecoration(leaf: DeltaLeaf, decorations: string[]): string[] {
31
+ if (leaf.underline) {
32
+ decorations.push("underline");
33
+ }
34
+ if (leaf.strikethrough) {
35
+ decorations.push("line-through");
36
+ }
37
+
38
+ return decorations;
39
+ }
40
+
41
+ export class DecoratorBuilder<T extends object> {
42
+ private readonly decorators: Decorator<T>[] = [];
43
+
44
+ public constructor(private readonly element: T) {}
45
+
46
+ public add(decorator: Decorator<T>): DecoratorBuilder<T> {
47
+ this.decorators.push(decorator);
48
+
49
+ return this;
50
+ }
51
+
52
+ public build(): (decorations: string[]) => string[] {
53
+ return (decorations: string[]): string[] => {
54
+ this.decorators.forEach((decorator) => decorator(this.element, decorations));
55
+
56
+ return decorations;
57
+ };
58
+ }
59
+ }
60
+
61
+ export { fontSize, fontWeight, fontStyle, textDecoration };
@@ -0,0 +1,110 @@
1
+ import { BaseEditor, Editor, Element, Node, Transforms } from "slate";
2
+ import { DeltaElement, DeltaLeaf, HeadingElement, ListElement } from "../types";
3
+ import { ReactEditor } from "slate-react";
4
+ import React, { useEffect } from "react";
5
+
6
+ export function hasMark(editor: Editor, format: keyof Omit<DeltaLeaf, "text">): boolean {
7
+ const marks: Omit<DeltaLeaf, "text"> | null = Editor.marks(editor);
8
+
9
+ return marks ? marks[format] === true : false;
10
+ }
11
+
12
+ export function toggleMark(editor: Editor, format: keyof Omit<DeltaLeaf, "text">): void {
13
+ const isActive = hasMark(editor, format);
14
+
15
+ if (isActive) {
16
+ Editor.removeMark(editor, format);
17
+ return;
18
+ }
19
+
20
+ Editor.addMark(editor, format, true);
21
+ }
22
+
23
+ export function isBlockActive(
24
+ editor: BaseEditor & ReactEditor,
25
+ format: "code" | "heading" | "list",
26
+ properties?: { level?: HeadingElement["level"]; ordered?: ListElement["ordered"] },
27
+ ): boolean {
28
+ const { selection } = editor;
29
+ if (!selection) {
30
+ return false;
31
+ }
32
+
33
+ const [match] = Array.from(
34
+ Editor.nodes(editor, {
35
+ at: Editor.unhangRange(editor, selection),
36
+ match: (node: Node) =>
37
+ !Editor.isEditor(node) &&
38
+ Element.isElement(node) &&
39
+ node.type === format &&
40
+ (node.type === "heading" ? node.level === properties?.level : true) &&
41
+ (node.type === "list" ? node.ordered === properties?.ordered : true),
42
+ }),
43
+ );
44
+
45
+ return Boolean(match);
46
+ }
47
+
48
+ export function toggleBlock(
49
+ editor: BaseEditor & ReactEditor,
50
+ format: "code" | "heading" | "list",
51
+ properties?: { level?: HeadingElement["level"]; ordered?: ListElement["ordered"] },
52
+ ): void {
53
+ const isActive = isBlockActive(editor, format, properties);
54
+
55
+ Transforms.unwrapNodes(editor, {
56
+ match: (node) => Element.isElement(node) && node.type === "list",
57
+ split: true,
58
+ });
59
+
60
+ let newProperties: Partial<DeltaElement>;
61
+
62
+ if (!isActive) {
63
+ newProperties = { type: format === "list" ? "listItem" : format, level: properties?.level };
64
+ } else {
65
+ newProperties = { type: "paragraph" };
66
+ }
67
+
68
+ Transforms.setNodes<DeltaElement>(editor, newProperties);
69
+
70
+ if (!isActive && format === "list") {
71
+ const block = { type: format, ordered: properties?.ordered, children: [] };
72
+ Transforms.wrapNodes(editor, block as DeltaElement);
73
+ }
74
+ }
75
+
76
+ export function useClickOutside(ref: React.RefObject<HTMLElement | null>, callback: () => void): void {
77
+ useEffect(() => {
78
+ function handleClickOutside(event: MouseEvent): void {
79
+ if (ref.current && !ref.current.contains(event.target as HTMLElement)) {
80
+ callback();
81
+ }
82
+ }
83
+ // Bind the event listener
84
+ document.addEventListener("mousedown", handleClickOutside);
85
+ return (): void => {
86
+ // Unbind the event listener on clean up
87
+ document.removeEventListener("mousedown", handleClickOutside);
88
+ };
89
+ }, [ref]);
90
+ }
91
+
92
+ /**
93
+ * Finds the element of the given type at the selection.
94
+ * @param editor - The editor instance.
95
+ * @param elementType - The type of element to find.
96
+ * @returns The element and its path if found, otherwise undefined.
97
+ */
98
+ export function findElement(editor: Editor, elementType: string): [Element, number[]] | undefined {
99
+ if (!editor.selection) {
100
+ return undefined;
101
+ }
102
+
103
+ return Editor.above(editor, {
104
+ match: (node) => !Editor.isEditor(node) && Element.isElement(node) && node.type === elementType,
105
+ }) as [Element, number[]] | undefined;
106
+ }
107
+
108
+ export function hasElementSelected(editor: Editor, elementType: string): boolean {
109
+ return findElement(editor, elementType) !== undefined;
110
+ }
@@ -0,0 +1,5 @@
1
+ declare module "*.vue" {
2
+ import { defineComponent } from "vue";
3
+ const component: ReturnType<typeof defineComponent>;
4
+ export default component;
5
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "esModuleInterop": false,
5
+ "allowImportingTsExtensions": true,
6
+ "allowSyntheticDefaultImports": true,
7
+ "strict": true,
8
+ "module": "esnext",
9
+ "jsx": "react-jsx",
10
+ "jsxImportSource": "react",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "lib": ["es2022", "dom"]
14
+ },
15
+ "files": [],
16
+ "include": [],
17
+ "references": [
18
+ {
19
+ "path": "./tsconfig.lib.json"
20
+ },
21
+ {
22
+ "path": "./tsconfig.spec.json"
23
+ }
24
+ ],
25
+ "extends": "../../tsconfig.base.json"
26
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../generated/dist/packages/delta-smart-text",
5
+ "types": ["vite/client"]
6
+ },
7
+ "exclude": [
8
+ "src/**/__tests__/*",
9
+ "src/**/*.spec.vue",
10
+ "src/**/*.test.vue",
11
+ "vite.config.ts",
12
+ "vite.config.mts",
13
+ "vitest.config.ts",
14
+ "vitest.config.mts",
15
+ "src/**/*.test.ts",
16
+ "src/**/*.spec.ts",
17
+ "src/**/*.test.tsx",
18
+ "src/**/*.spec.tsx",
19
+ "src/**/*.test.js",
20
+ "src/**/*.spec.js",
21
+ "src/**/*.test.jsx",
22
+ "src/**/*.spec.jsx"
23
+ ],
24
+ "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "codegen.config.ts"]
25
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../generated/dist/packages/delta-smart-text",
5
+ "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node", "vitest"]
6
+ },
7
+ "include": [
8
+ "vite.config.ts",
9
+ "vite.config.mts",
10
+ "vitest.config.ts",
11
+ "vitest.config.mts",
12
+ "src/**/*.test.ts",
13
+ "src/**/*.spec.ts",
14
+ "src/**/*.test.tsx",
15
+ "src/**/*.spec.tsx",
16
+ "src/**/*.test.js",
17
+ "src/**/*.spec.js",
18
+ "src/**/*.test.jsx",
19
+ "src/**/*.spec.jsx",
20
+ "src/**/*.d.ts"
21
+ ]
22
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,67 @@
1
+ /// <reference types='vitest' />
2
+ import { defineConfig } from "vite";
3
+ import vue from "@vitejs/plugin-vue";
4
+ import dts from "vite-plugin-dts";
5
+ import * as path from "path";
6
+ import { nxViteTsPaths } from "@nx/vite/plugins/nx-tsconfig-paths.plugin";
7
+ import { nxCopyAssetsPlugin } from "@nx/vite/plugins/nx-copy-assets.plugin";
8
+ import tailwindcss from "@tailwindcss/vite";
9
+ import react from "@vitejs/plugin-react";
10
+
11
+ export default defineConfig({
12
+ root: __dirname,
13
+ cacheDir: "../../node_modules/.vite/packages/delta-smart-text",
14
+ plugins: [
15
+ vue(),
16
+ react(),
17
+ tailwindcss(),
18
+ nxViteTsPaths(),
19
+ nxCopyAssetsPlugin(["*.md"]),
20
+ dts({ entryRoot: "src", tsconfigPath: path.join(__dirname, "tsconfig.lib.json") }),
21
+ ],
22
+ // Uncomment this if you are using workers.
23
+ // worker: {
24
+ // plugins: [ nxViteTsPaths() ],
25
+ // },
26
+ // Configuration for building your library.
27
+ // See: https://vitejs.dev/guide/build.html#library-mode
28
+ build: {
29
+ outDir: "../../dist/packages/delta-smart-text",
30
+ emptyOutDir: true,
31
+ reportCompressedSize: true,
32
+ commonjsOptions: {
33
+ transformMixedEsModules: true,
34
+ },
35
+ lib: {
36
+ // Could also be a dictionary or array of multiple entry points.
37
+ entry: "src/index.ts",
38
+ name: "delta-smart-text",
39
+ fileName: "index",
40
+ // Change this to the formats you want to support.
41
+ // Don't forget to update your package.json as well.
42
+ formats: ["es", "cjs"],
43
+ },
44
+ rollupOptions: {
45
+ // External packages that should not be bundled into your library.
46
+ external: ["vue", "react", "react-dom"],
47
+ output: {
48
+ globals: {
49
+ vue: "Vue",
50
+ react: "React",
51
+ "react-dom": "ReactDOM",
52
+ },
53
+ },
54
+ },
55
+ },
56
+ test: {
57
+ watch: false,
58
+ globals: true,
59
+ environment: "jsdom",
60
+ passWithNoTests: true,
61
+ reporters: ["default"],
62
+ coverage: {
63
+ reportsDirectory: "../../generated/coverage/packages/delta-smart-text",
64
+ clean: true,
65
+ },
66
+ },
67
+ });
@@ -1,26 +0,0 @@
1
- import { Descendant } from 'slate';
2
- import { ApolloClient, NormalizedCacheObject } from '@apollo/client';
3
- import { Organization } from '../../__generated__/graphql';
4
- type __VLS_Props = {
5
- uuid?: string;
6
- initialValue?: Descendant[];
7
- context: HTMLElement | null;
8
- client: ApolloClient<NormalizedCacheObject>;
9
- organization: Organization | undefined;
10
- isDisabled?: boolean;
11
- };
12
- type __VLS_PublicProps = {
13
- 'tree'?: any;
14
- } & __VLS_Props;
15
- declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {
16
- setValue: (value: Descendant[]) => void;
17
- setInitialValue: (value: Descendant[]) => void;
18
- }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
19
- "update:tree": (value: any) => any;
20
- }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
21
- "onUpdate:tree"?: ((value: any) => any) | undefined;
22
- }>, {
23
- uuid: string;
24
- initialValue: Descendant[];
25
- }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
26
- export default _default;