@mdxeditor/editor 0.19.0 → 0.20.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.
- package/dist/plugins/frontmatter/FrontmatterEditor.js +22 -24
- package/dist/plugins/frontmatter/index.d.ts +28 -4
- package/dist/plugins/frontmatter/index.js +25 -2
- package/dist/plugins/link-dialog/LinkDialog.d.ts +3 -2
- package/dist/plugins/link-dialog/LinkDialog.js +14 -13
- package/dist/plugins/link-dialog/index.d.ts +9 -7
- package/dist/plugins/link-dialog/index.js +16 -4
- package/dist/plugins/toolbar/components/InsertFrontmatter.js +14 -1
- package/dist/style.css +218 -175
- package/dist/styles/ui.module.css.js +101 -86
- package/package.json +1 -1
- package/dist/icons/arrow_right.svg.js +0 -8
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
import * as Dialog from "@radix-ui/react-dialog";
|
|
1
2
|
import classNames from "classnames";
|
|
2
3
|
import YamlParser from "js-yaml";
|
|
3
4
|
import React__default from "react";
|
|
4
5
|
import { useForm, useFieldArray } from "react-hook-form";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
6
|
+
import { frontmatterPluginHooks } from "./index.js";
|
|
7
|
+
import CloseIcon from "../../icons/close.svg.js";
|
|
7
8
|
import DeleteIcon from "../../icons/delete.svg.js";
|
|
8
9
|
import styles from "../../styles/ui.module.css.js";
|
|
9
10
|
import { corePluginHooks } from "../core/index.js";
|
|
10
11
|
const FrontmatterEditor = ({ yaml, onChange }) => {
|
|
11
|
-
const [
|
|
12
|
-
const [
|
|
12
|
+
const [readOnly, editorRootElementRef] = corePluginHooks.useEmitterValues("readOnly", "editorRootElementRef");
|
|
13
|
+
const [frontmatterDialogOpen] = frontmatterPluginHooks.useEmitterValues("frontmatterDialogOpen");
|
|
14
|
+
const setFrontmatterDialogOpen = frontmatterPluginHooks.usePublisher("frontmatterDialogOpen");
|
|
15
|
+
const removeFrontmatter = frontmatterPluginHooks.usePublisher("removeFrontmatter");
|
|
13
16
|
const yamlConfig = React__default.useMemo(() => {
|
|
14
17
|
if (!yaml) {
|
|
15
18
|
return [];
|
|
16
19
|
}
|
|
17
20
|
return Object.entries(YamlParser.load(yaml)).map(([key, value]) => ({ key, value }));
|
|
18
21
|
}, [yaml]);
|
|
19
|
-
const { register, control,
|
|
22
|
+
const { register, control, handleSubmit } = useForm({
|
|
20
23
|
defaultValues: {
|
|
21
24
|
yamlConfig
|
|
22
25
|
}
|
|
@@ -25,8 +28,13 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
|
|
|
25
28
|
control,
|
|
26
29
|
name: "yamlConfig"
|
|
27
30
|
});
|
|
28
|
-
React__default.
|
|
29
|
-
|
|
31
|
+
const onSubmit = React__default.useCallback(
|
|
32
|
+
({ yamlConfig: yamlConfig2 }) => {
|
|
33
|
+
if (yamlConfig2.length === 0) {
|
|
34
|
+
removeFrontmatter(true);
|
|
35
|
+
setFrontmatterDialogOpen(false);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
30
38
|
const yaml2 = yamlConfig2.reduce((acc, { key, value }) => {
|
|
31
39
|
if (key && value) {
|
|
32
40
|
acc[key] = value;
|
|
@@ -34,34 +42,24 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
|
|
|
34
42
|
return acc;
|
|
35
43
|
}, {});
|
|
36
44
|
onChange(YamlParser.dump(yaml2).trim());
|
|
37
|
-
|
|
38
|
-
return () => subscription.unsubscribe();
|
|
39
|
-
}, [watch, onChange]);
|
|
40
|
-
return /* @__PURE__ */ React__default.createElement("div", { className: styles.frontmatterWrapper, "data-expanded": expanded, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(
|
|
41
|
-
"button",
|
|
42
|
-
{
|
|
43
|
-
className: styles.frontmatterToggleButton,
|
|
44
|
-
onClick: (e) => {
|
|
45
|
-
e.preventDefault();
|
|
46
|
-
setExpanded((v) => !v);
|
|
47
|
-
}
|
|
45
|
+
setFrontmatterDialogOpen(false);
|
|
48
46
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
),
|
|
47
|
+
[onChange, setFrontmatterDialogOpen, removeFrontmatter]
|
|
48
|
+
);
|
|
49
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog.Root, { open: frontmatterDialogOpen, onOpenChange: (open) => setFrontmatterDialogOpen(open) }, /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, "Edit document frontmatter"), /* @__PURE__ */ React__default.createElement("form", { onSubmit: handleSubmit(onSubmit), onReset: () => setFrontmatterDialogOpen(false) }, /* @__PURE__ */ React__default.createElement("table", { className: styles.propertyEditorTable }, /* @__PURE__ */ React__default.createElement("colgroup", null, /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null)), /* @__PURE__ */ React__default.createElement("thead", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("th", null, "Key"), /* @__PURE__ */ React__default.createElement("th", null, "Value"), /* @__PURE__ */ React__default.createElement("th", null))), /* @__PURE__ */ React__default.createElement("tbody", null, fields.map((item, index) => {
|
|
52
50
|
return /* @__PURE__ */ React__default.createElement("tr", { key: item.id }, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.key`, { required: true }), autofocusIfEmpty: true, readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.value`, { required: true }), readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement("button", { type: "button", onClick: () => remove(index), className: styles.iconButton, disabled: readOnly }, /* @__PURE__ */ React__default.createElement(DeleteIcon, null))));
|
|
53
51
|
})), /* @__PURE__ */ React__default.createElement("tfoot", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(
|
|
54
52
|
"button",
|
|
55
53
|
{
|
|
56
54
|
disabled: readOnly,
|
|
57
|
-
className: styles.primaryButton,
|
|
55
|
+
className: classNames(styles.primaryButton, styles.smallButton),
|
|
58
56
|
type: "button",
|
|
59
57
|
onClick: () => {
|
|
60
58
|
append({ key: "", value: "" });
|
|
61
59
|
}
|
|
62
60
|
},
|
|
63
|
-
"Add
|
|
64
|
-
)))))));
|
|
61
|
+
"Add entry"
|
|
62
|
+
))))), /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "reset", className: styles.secondaryButton }, "Cancel"), /* @__PURE__ */ React__default.createElement("button", { type: "submit", className: styles.primaryButton }, "Save"))), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { className: styles.dialogCloseButton, "aria-label": "Close" }, /* @__PURE__ */ React__default.createElement(CloseIcon, null)))))));
|
|
65
63
|
};
|
|
66
64
|
const TableInput = React__default.forwardRef(({ className, autofocusIfEmpty: _, ...props }, ref) => {
|
|
67
65
|
return /* @__PURE__ */ React__default.createElement("input", { className: classNames(styles.propertyEditorInput, className), ...props, ref });
|
|
@@ -64,7 +64,7 @@ export declare const frontmatterSystem: SystemSpec<[SystemSpec<[], (r: Realm) =>
|
|
|
64
64
|
convertSelectionToNode: RealmNode<() => ElementNode>;
|
|
65
65
|
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
66
66
|
onBlur: RealmNode<FocusEvent>;
|
|
67
|
-
}>], (r: Realm, [{ rootEditor }]: [{
|
|
67
|
+
}>], (r: Realm, [{ rootEditor, createRootEditorSubscription }]: [{
|
|
68
68
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
69
69
|
inFocus: RealmNode<boolean>;
|
|
70
70
|
historyState: RealmNode<HistoryState>;
|
|
@@ -118,6 +118,9 @@ export declare const frontmatterSystem: SystemSpec<[SystemSpec<[], (r: Realm) =>
|
|
|
118
118
|
onBlur: RealmNode<FocusEvent>;
|
|
119
119
|
}]) => {
|
|
120
120
|
insertFrontmatter: RealmNode<true>;
|
|
121
|
+
removeFrontmatter: RealmNode<true>;
|
|
122
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
123
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
121
124
|
}>;
|
|
122
125
|
export declare const
|
|
123
126
|
/** @internal */
|
|
@@ -173,7 +176,7 @@ frontmatterPlugin: PluginConstructor<SystemSpec<[SystemSpec<[], (r: Realm) => {
|
|
|
173
176
|
convertSelectionToNode: RealmNode<() => ElementNode>;
|
|
174
177
|
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
175
178
|
onBlur: RealmNode<FocusEvent>;
|
|
176
|
-
}>], (r: Realm, [{ rootEditor }]: [{
|
|
179
|
+
}>], (r: Realm, [{ rootEditor, createRootEditorSubscription }]: [{
|
|
177
180
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
178
181
|
inFocus: RealmNode<boolean>;
|
|
179
182
|
historyState: RealmNode<HistoryState>;
|
|
@@ -227,11 +230,17 @@ frontmatterPlugin: PluginConstructor<SystemSpec<[SystemSpec<[], (r: Realm) => {
|
|
|
227
230
|
onBlur: RealmNode<FocusEvent>;
|
|
228
231
|
}]) => {
|
|
229
232
|
insertFrontmatter: RealmNode<true>;
|
|
233
|
+
removeFrontmatter: RealmNode<true>;
|
|
234
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
235
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
230
236
|
}>, object>,
|
|
231
237
|
/** @internal */
|
|
232
238
|
frontmatterPluginHooks: {
|
|
233
239
|
useRealmContext: () => TypedRealm<{
|
|
234
240
|
insertFrontmatter: RealmNode<true>;
|
|
241
|
+
removeFrontmatter: RealmNode<true>;
|
|
242
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
243
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
235
244
|
} & {
|
|
236
245
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
237
246
|
inFocus: RealmNode<boolean>;
|
|
@@ -285,8 +294,11 @@ frontmatterPluginHooks: {
|
|
|
285
294
|
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
286
295
|
onBlur: RealmNode<FocusEvent>;
|
|
287
296
|
}>;
|
|
288
|
-
useEmitter: <K extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "insertFrontmatter">(key: K, callback: (value: ValueForKey<{
|
|
297
|
+
useEmitter: <K extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "insertFrontmatter" | "removeFrontmatter" | "hasFrontmatter" | "frontmatterDialogOpen">(key: K, callback: (value: ValueForKey<{
|
|
289
298
|
insertFrontmatter: RealmNode<true>;
|
|
299
|
+
removeFrontmatter: RealmNode<true>;
|
|
300
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
301
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
290
302
|
} & {
|
|
291
303
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
292
304
|
inFocus: RealmNode<boolean>;
|
|
@@ -342,6 +354,9 @@ frontmatterPluginHooks: {
|
|
|
342
354
|
}, K>) => void) => void;
|
|
343
355
|
useEmitterValues: <K_1 extends SystemKeys<{
|
|
344
356
|
insertFrontmatter: RealmNode<true>;
|
|
357
|
+
removeFrontmatter: RealmNode<true>;
|
|
358
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
359
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
345
360
|
} & {
|
|
346
361
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
347
362
|
inFocus: RealmNode<boolean>;
|
|
@@ -396,6 +411,9 @@ frontmatterPluginHooks: {
|
|
|
396
411
|
onBlur: RealmNode<FocusEvent>;
|
|
397
412
|
}>>(...keys: K_1) => ValuesForKeys<{
|
|
398
413
|
insertFrontmatter: RealmNode<true>;
|
|
414
|
+
removeFrontmatter: RealmNode<true>;
|
|
415
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
416
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
399
417
|
} & {
|
|
400
418
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
401
419
|
inFocus: RealmNode<boolean>;
|
|
@@ -451,6 +469,9 @@ frontmatterPluginHooks: {
|
|
|
451
469
|
}, K_1>;
|
|
452
470
|
usePubKeys: () => (values: SystemDict<{
|
|
453
471
|
insertFrontmatter: RealmNode<true>;
|
|
472
|
+
removeFrontmatter: RealmNode<true>;
|
|
473
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
474
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
454
475
|
} & {
|
|
455
476
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
456
477
|
inFocus: RealmNode<boolean>;
|
|
@@ -504,8 +525,11 @@ frontmatterPluginHooks: {
|
|
|
504
525
|
insertDecoratorNode: RealmNode<() => DecoratorNode<unknown>>;
|
|
505
526
|
onBlur: RealmNode<FocusEvent>;
|
|
506
527
|
}>) => void;
|
|
507
|
-
usePublisher: <K_2 extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "insertFrontmatter">(key: K_2) => (value: ValueForKey<{
|
|
528
|
+
usePublisher: <K_2 extends "jsxComponentDescriptors" | "jsxIsAvailable" | "toMarkdownOptions" | "toMarkdownExtensions" | "mdastExtensions" | "syntaxExtensions" | "markdown" | "activeEditor" | "inFocus" | "historyState" | "currentSelection" | "initialRootEditorState" | "rootEditor" | "createRootEditorSubscription" | "createActiveEditorSubscription" | "importVisitors" | "usedLexicalNodes" | "addImportVisitor" | "addLexicalNode" | "addSyntaxExtension" | "addMdastExtension" | "addToMarkdownExtension" | "addExportVisitor" | "exportVisitors" | "initialMarkdown" | "setMarkdown" | "editorRootElementRef" | "contentEditableClassName" | "placeholder" | "autoFocus" | "readOnly" | "composerChildren" | "addComposerChild" | "topAreaChildren" | "addTopAreaChild" | "nestedEditorChildren" | "addNestedEditorChild" | "editorWrappers" | "addEditorWrapper" | "currentFormat" | "editorInFocus" | "applyFormat" | "currentBlockType" | "applyBlockType" | "convertSelectionToNode" | "insertDecoratorNode" | "onBlur" | "insertFrontmatter" | "removeFrontmatter" | "hasFrontmatter" | "frontmatterDialogOpen">(key: K_2) => (value: ValueForKey<{
|
|
508
529
|
insertFrontmatter: RealmNode<true>;
|
|
530
|
+
removeFrontmatter: RealmNode<true>;
|
|
531
|
+
hasFrontmatter: RealmNode<boolean>;
|
|
532
|
+
frontmatterDialogOpen: RealmNode<boolean>;
|
|
509
533
|
} & {
|
|
510
534
|
activeEditor: RealmNode<LexicalEditor | null>;
|
|
511
535
|
inFocus: RealmNode<boolean>;
|
|
@@ -8,8 +8,11 @@ import { $isFrontmatterNode, $createFrontmatterNode, FrontmatterNode } from "./F
|
|
|
8
8
|
import { system } from "../../gurx/realmFactory.js";
|
|
9
9
|
import { realmPlugin } from "../../gurx/react.js";
|
|
10
10
|
const frontmatterSystem = system(
|
|
11
|
-
(r, [{ rootEditor }]) => {
|
|
11
|
+
(r, [{ rootEditor, createRootEditorSubscription }]) => {
|
|
12
12
|
const insertFrontmatter = r.node();
|
|
13
|
+
const removeFrontmatter = r.node();
|
|
14
|
+
const frontmatterDialogOpen = r.node(false);
|
|
15
|
+
const hasFrontmatter = r.node(false);
|
|
13
16
|
r.sub(r.pipe(insertFrontmatter, r.o.withLatestFrom(rootEditor)), ([, theEditor]) => {
|
|
14
17
|
theEditor == null ? void 0 : theEditor.update(() => {
|
|
15
18
|
const firstItem = $getRoot().getFirstChild();
|
|
@@ -22,9 +25,29 @@ const frontmatterSystem = system(
|
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
});
|
|
28
|
+
r.pub(frontmatterDialogOpen, true);
|
|
29
|
+
});
|
|
30
|
+
r.sub(r.pipe(removeFrontmatter, r.o.withLatestFrom(rootEditor)), ([, theEditor]) => {
|
|
31
|
+
theEditor == null ? void 0 : theEditor.update(() => {
|
|
32
|
+
const firstItem = $getRoot().getFirstChild();
|
|
33
|
+
if ($isFrontmatterNode(firstItem)) {
|
|
34
|
+
firstItem.remove();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
r.pub(frontmatterDialogOpen, false);
|
|
38
|
+
});
|
|
39
|
+
r.pub(createRootEditorSubscription, (rootEditor2) => {
|
|
40
|
+
return rootEditor2.registerUpdateListener(({ editorState }) => {
|
|
41
|
+
editorState.read(() => {
|
|
42
|
+
r.pub(hasFrontmatter, $isFrontmatterNode($getRoot().getFirstChild()));
|
|
43
|
+
});
|
|
44
|
+
});
|
|
25
45
|
});
|
|
26
46
|
return {
|
|
27
|
-
insertFrontmatter
|
|
47
|
+
insertFrontmatter,
|
|
48
|
+
removeFrontmatter,
|
|
49
|
+
hasFrontmatter,
|
|
50
|
+
frontmatterDialogOpen
|
|
28
51
|
};
|
|
29
52
|
},
|
|
30
53
|
[coreSystem]
|
|
@@ -3,10 +3,11 @@ import { LexicalCommand } from 'lexical';
|
|
|
3
3
|
export declare const OPEN_LINK_DIALOG: LexicalCommand<undefined>;
|
|
4
4
|
interface LinkEditFormProps {
|
|
5
5
|
initialUrl: string;
|
|
6
|
-
|
|
6
|
+
initialTitle: string;
|
|
7
|
+
onSubmit: (link: [string, string]) => void;
|
|
7
8
|
onCancel: () => void;
|
|
8
9
|
linkAutocompleteSuggestions: string[];
|
|
9
10
|
}
|
|
10
|
-
export declare function LinkEditForm({ initialUrl, onSubmit, onCancel, linkAutocompleteSuggestions }: LinkEditFormProps): React.JSX.Element;
|
|
11
|
+
export declare function LinkEditForm({ initialUrl, initialTitle, onSubmit, onCancel, linkAutocompleteSuggestions }: LinkEditFormProps): React.JSX.Element;
|
|
11
12
|
export declare const LinkDialog: React.FC;
|
|
12
13
|
export {};
|
|
@@ -3,7 +3,6 @@ import * as Tooltip from "@radix-ui/react-tooltip";
|
|
|
3
3
|
import React__default from "react";
|
|
4
4
|
import { createCommand } from "lexical";
|
|
5
5
|
import CheckIcon from "../../icons/check.svg.js";
|
|
6
|
-
import CloseIcon from "../../icons/close.svg.js";
|
|
7
6
|
import CopyIcon from "../../icons/content_copy.svg.js";
|
|
8
7
|
import EditIcon from "../../icons/edit.svg.js";
|
|
9
8
|
import LinkOffIcon from "../../icons/link_off.svg.js";
|
|
@@ -16,15 +15,16 @@ import { corePluginHooks } from "../core/index.js";
|
|
|
16
15
|
import { linkDialogPluginHooks } from "./index.js";
|
|
17
16
|
createCommand();
|
|
18
17
|
const MAX_SUGGESTIONS = 20;
|
|
19
|
-
function LinkEditForm({ initialUrl, onSubmit, onCancel, linkAutocompleteSuggestions }) {
|
|
18
|
+
function LinkEditForm({ initialUrl, initialTitle, onSubmit, onCancel, linkAutocompleteSuggestions }) {
|
|
20
19
|
const [items, setItems] = React__default.useState(linkAutocompleteSuggestions.slice(0, MAX_SUGGESTIONS));
|
|
21
|
-
const
|
|
20
|
+
const [title, setTitle] = React__default.useState(initialTitle);
|
|
21
|
+
const { isOpen, getToggleButtonProps, getMenuProps, getInputProps, highlightedIndex, getItemProps, selectedItem, inputValue } = useCombobox({
|
|
22
22
|
initialInputValue: initialUrl,
|
|
23
|
-
onInputValueChange({ inputValue }) {
|
|
24
|
-
|
|
23
|
+
onInputValueChange({ inputValue: inputValue2 }) {
|
|
24
|
+
inputValue2 = (inputValue2 == null ? void 0 : inputValue2.toLowerCase()) || "";
|
|
25
25
|
const matchingItems = [];
|
|
26
26
|
for (const url of linkAutocompleteSuggestions) {
|
|
27
|
-
if (url.toLowerCase().includes(
|
|
27
|
+
if (url.toLowerCase().includes(inputValue2)) {
|
|
28
28
|
matchingItems.push(url);
|
|
29
29
|
if (matchingItems.length >= MAX_SUGGESTIONS) {
|
|
30
30
|
break;
|
|
@@ -40,7 +40,7 @@ function LinkEditForm({ initialUrl, onSubmit, onCancel, linkAutocompleteSuggesti
|
|
|
40
40
|
});
|
|
41
41
|
const onSubmitEH = (e) => {
|
|
42
42
|
e.preventDefault();
|
|
43
|
-
onSubmit(
|
|
43
|
+
onSubmit([inputValue, title]);
|
|
44
44
|
};
|
|
45
45
|
const onKeyDownEH = React__default.useCallback(
|
|
46
46
|
(e) => {
|
|
@@ -49,10 +49,10 @@ function LinkEditForm({ initialUrl, onSubmit, onCancel, linkAutocompleteSuggesti
|
|
|
49
49
|
(_a = e.target.form) == null ? void 0 : _a.reset();
|
|
50
50
|
} else if (e.key === "Enter" && (!isOpen || items.length === 0)) {
|
|
51
51
|
e.preventDefault();
|
|
52
|
-
onSubmit(e.target.value);
|
|
52
|
+
onSubmit([e.target.value, title]);
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
|
-
[isOpen, items, onSubmit]
|
|
55
|
+
[isOpen, items, onSubmit, title]
|
|
56
56
|
);
|
|
57
57
|
const downshiftInputProps = getInputProps();
|
|
58
58
|
const inputProps = {
|
|
@@ -63,7 +63,7 @@ function LinkEditForm({ initialUrl, onSubmit, onCancel, linkAutocompleteSuggesti
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
const dropdownIsVisible = isOpen && items.length > 0;
|
|
66
|
-
return /* @__PURE__ */ React__default.createElement("form", { onSubmit: onSubmitEH, onReset: onCancel, className: classNames(styles.linkDialogEditForm) }, /* @__PURE__ */ React__default.createElement("div", { className: styles.linkDialogInputContainer }, /* @__PURE__ */ React__default.createElement("div", { "data-visible-dropdown": dropdownIsVisible, className: styles.linkDialogInputWrapper }, /* @__PURE__ */ React__default.createElement("input", { className: styles.linkDialogInput, ...inputProps, autoFocus: true, size:
|
|
66
|
+
return /* @__PURE__ */ React__default.createElement("form", { onSubmit: onSubmitEH, onReset: onCancel, className: classNames(styles.linkDialogEditForm) }, /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "link-url" }, "URL")), /* @__PURE__ */ React__default.createElement("div", { className: styles.linkDialogInputContainer }, /* @__PURE__ */ React__default.createElement("div", { "data-visible-dropdown": dropdownIsVisible, className: styles.linkDialogInputWrapper }, /* @__PURE__ */ React__default.createElement("input", { id: "link-url", className: styles.linkDialogInput, ...inputProps, autoFocus: true, size: 40, "data-editor-dialog": true }), /* @__PURE__ */ React__default.createElement("button", { "aria-label": "toggle menu", type: "button", ...getToggleButtonProps() }, /* @__PURE__ */ React__default.createElement(DropDownIcon, null))), /* @__PURE__ */ React__default.createElement("div", { className: styles.linkDialogAutocompleteContainer }, /* @__PURE__ */ React__default.createElement("ul", { ...getMenuProps(), "data-visible": dropdownIsVisible }, items.map((item, index) => /* @__PURE__ */ React__default.createElement(
|
|
67
67
|
"li",
|
|
68
68
|
{
|
|
69
69
|
"data-selected": selectedItem === item,
|
|
@@ -72,7 +72,7 @@ function LinkEditForm({ initialUrl, onSubmit, onCancel, linkAutocompleteSuggesti
|
|
|
72
72
|
...getItemProps({ item, index })
|
|
73
73
|
},
|
|
74
74
|
item
|
|
75
|
-
))))), /* @__PURE__ */ React__default.createElement(
|
|
75
|
+
))))), /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "link-title" }, "Title")), /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement("div", { className: styles.linkDialogInputWrapper }, /* @__PURE__ */ React__default.createElement("input", { id: "link-title", className: styles.linkDialogInput, size: 40, value: title, onChange: (e) => setTitle(e.target.value) }))), /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "reset", title: "Cancel change", "aria-label": "Cancel change", className: classNames(styles.secondaryButton) }, "Cancel"), /* @__PURE__ */ React__default.createElement("button", { type: "submit", title: "Set URL", "aria-label": "Set URL", className: classNames(styles.primaryButton) }, "Save")));
|
|
76
76
|
}
|
|
77
77
|
const LinkDialog = () => {
|
|
78
78
|
const [editorRootElementRef] = corePluginHooks.useEmitterValues("editorRootElementRef");
|
|
@@ -103,8 +103,8 @@ const LinkDialog = () => {
|
|
|
103
103
|
const [copyUrlTooltipOpen, setCopyUrlTooltipOpen] = React__default.useState(false);
|
|
104
104
|
const theRect = linkDialogState == null ? void 0 : linkDialogState.rectangle;
|
|
105
105
|
const onSubmitEH = React__default.useCallback(
|
|
106
|
-
(
|
|
107
|
-
updateLinkUrl(
|
|
106
|
+
(payload) => {
|
|
107
|
+
updateLinkUrl(payload);
|
|
108
108
|
applyLinkChanges(true);
|
|
109
109
|
},
|
|
110
110
|
[applyLinkChanges, updateLinkUrl]
|
|
@@ -134,6 +134,7 @@ const LinkDialog = () => {
|
|
|
134
134
|
LinkEditForm,
|
|
135
135
|
{
|
|
136
136
|
initialUrl: linkDialogState.url,
|
|
137
|
+
initialTitle: linkDialogState.title,
|
|
137
138
|
onSubmit: onSubmitEH,
|
|
138
139
|
onCancel: cancelLinkEdit.bind(null, true),
|
|
139
140
|
linkAutocompleteSuggestions
|
|
@@ -26,7 +26,9 @@ type PreviewLinkDialog = {
|
|
|
26
26
|
type EditLinkDialog = {
|
|
27
27
|
type: 'edit';
|
|
28
28
|
initialUrl: string;
|
|
29
|
+
initialTitle?: string;
|
|
29
30
|
url: string;
|
|
31
|
+
title: string;
|
|
30
32
|
linkNodeKey: string;
|
|
31
33
|
rectangle: RectData;
|
|
32
34
|
};
|
|
@@ -140,7 +142,7 @@ linkDialogPlugin: PluginConstructor<SystemSpec<[SystemSpec<[], (r: Realm) => {
|
|
|
140
142
|
dialogState: RealmNode<boolean>;
|
|
141
143
|
onWindowChange: RealmNode<true>;
|
|
142
144
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
143
|
-
updateLinkUrl: RealmNode<string>;
|
|
145
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
144
146
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
145
147
|
cancelLinkEdit: RealmNode<true>;
|
|
146
148
|
removeLink: RealmNode<true>;
|
|
@@ -156,7 +158,7 @@ linkDialogPluginHooks: {
|
|
|
156
158
|
dialogState: RealmNode<boolean>;
|
|
157
159
|
onWindowChange: RealmNode<true>;
|
|
158
160
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
159
|
-
updateLinkUrl: RealmNode<string>;
|
|
161
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
160
162
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
161
163
|
cancelLinkEdit: RealmNode<true>;
|
|
162
164
|
removeLink: RealmNode<true>;
|
|
@@ -220,7 +222,7 @@ linkDialogPluginHooks: {
|
|
|
220
222
|
dialogState: RealmNode<boolean>;
|
|
221
223
|
onWindowChange: RealmNode<true>;
|
|
222
224
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
223
|
-
updateLinkUrl: RealmNode<string>;
|
|
225
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
224
226
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
225
227
|
cancelLinkEdit: RealmNode<true>;
|
|
226
228
|
removeLink: RealmNode<true>;
|
|
@@ -284,7 +286,7 @@ linkDialogPluginHooks: {
|
|
|
284
286
|
dialogState: RealmNode<boolean>;
|
|
285
287
|
onWindowChange: RealmNode<true>;
|
|
286
288
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
287
|
-
updateLinkUrl: RealmNode<string>;
|
|
289
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
288
290
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
289
291
|
cancelLinkEdit: RealmNode<true>;
|
|
290
292
|
removeLink: RealmNode<true>;
|
|
@@ -347,7 +349,7 @@ linkDialogPluginHooks: {
|
|
|
347
349
|
dialogState: RealmNode<boolean>;
|
|
348
350
|
onWindowChange: RealmNode<true>;
|
|
349
351
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
350
|
-
updateLinkUrl: RealmNode<string>;
|
|
352
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
351
353
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
352
354
|
cancelLinkEdit: RealmNode<true>;
|
|
353
355
|
removeLink: RealmNode<true>;
|
|
@@ -411,7 +413,7 @@ linkDialogPluginHooks: {
|
|
|
411
413
|
dialogState: RealmNode<boolean>;
|
|
412
414
|
onWindowChange: RealmNode<true>;
|
|
413
415
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
414
|
-
updateLinkUrl: RealmNode<string>;
|
|
416
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
415
417
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
416
418
|
cancelLinkEdit: RealmNode<true>;
|
|
417
419
|
removeLink: RealmNode<true>;
|
|
@@ -475,7 +477,7 @@ linkDialogPluginHooks: {
|
|
|
475
477
|
dialogState: RealmNode<boolean>;
|
|
476
478
|
onWindowChange: RealmNode<true>;
|
|
477
479
|
linkDialogState: RealmNode<InactiveLinkDialog | PreviewLinkDialog | EditLinkDialog>;
|
|
478
|
-
updateLinkUrl: RealmNode<string>;
|
|
480
|
+
updateLinkUrl: RealmNode<[string, string]>;
|
|
479
481
|
switchFromPreviewToLinkEdit: RealmNode<true>;
|
|
480
482
|
cancelLinkEdit: RealmNode<true>;
|
|
481
483
|
removeLink: RealmNode<true>;
|
|
@@ -45,7 +45,9 @@ const linkDialogSystem = system(
|
|
|
45
45
|
r.pub(linkDialogState, {
|
|
46
46
|
type: "edit",
|
|
47
47
|
initialUrl: node.getURL(),
|
|
48
|
+
initialTitle: node.getTitle() || "",
|
|
48
49
|
url: node.getURL(),
|
|
50
|
+
title: node.getTitle() || "",
|
|
49
51
|
linkNodeKey: node.getKey(),
|
|
50
52
|
rectangle
|
|
51
53
|
});
|
|
@@ -53,6 +55,8 @@ const linkDialogSystem = system(
|
|
|
53
55
|
r.pub(linkDialogState, {
|
|
54
56
|
type: "edit",
|
|
55
57
|
initialUrl: "",
|
|
58
|
+
initialTitle: "",
|
|
59
|
+
title: "",
|
|
56
60
|
url: "",
|
|
57
61
|
linkNodeKey: "",
|
|
58
62
|
rectangle
|
|
@@ -84,7 +88,7 @@ const linkDialogSystem = system(
|
|
|
84
88
|
(event) => {
|
|
85
89
|
if (event.key === "k" && (IS_APPLE ? event.metaKey : event.ctrlKey)) {
|
|
86
90
|
const selection = $getSelection();
|
|
87
|
-
if ($isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
91
|
+
if ($isRangeSelection(selection) && (getLinkNodeInSelection(selection) || !selection.isCollapsed())) {
|
|
88
92
|
r.pub(openLinkEditDialog, true);
|
|
89
93
|
event.stopPropagation();
|
|
90
94
|
return true;
|
|
@@ -120,8 +124,15 @@ const linkDialogSystem = system(
|
|
|
120
124
|
r.sub(r.pipe(applyLinkChanges, r.o.withLatestFrom(linkDialogState, activeEditor)), ([, state, editor]) => {
|
|
121
125
|
if (state.type === "edit") {
|
|
122
126
|
const url = state.url.trim();
|
|
127
|
+
const title = state.title.trim();
|
|
123
128
|
if (url.trim() !== "") {
|
|
124
|
-
editor == null ? void 0 : editor.dispatchCommand(TOGGLE_LINK_COMMAND, url);
|
|
129
|
+
editor == null ? void 0 : editor.dispatchCommand(TOGGLE_LINK_COMMAND, { url, title });
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
editor == null ? void 0 : editor.update(() => {
|
|
132
|
+
const node = getLinkNodeInSelection($getSelection());
|
|
133
|
+
node == null ? void 0 : node.setTitle(title);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
125
136
|
r.pub(linkDialogState, {
|
|
126
137
|
type: "preview",
|
|
127
138
|
linkNodeKey: state.linkNodeKey,
|
|
@@ -144,11 +155,12 @@ const linkDialogSystem = system(
|
|
|
144
155
|
r.pipe(
|
|
145
156
|
updateLinkUrl,
|
|
146
157
|
r.o.withLatestFrom(linkDialogState),
|
|
147
|
-
r.o.map(([url, state]) => {
|
|
158
|
+
r.o.map(([[url, title], state]) => {
|
|
148
159
|
if (state.type === "edit") {
|
|
149
160
|
return {
|
|
150
161
|
...state,
|
|
151
|
-
url
|
|
162
|
+
url,
|
|
163
|
+
title
|
|
152
164
|
};
|
|
153
165
|
} else {
|
|
154
166
|
throw new Error("Cannot update link url when not in edit mode");
|
|
@@ -2,9 +2,22 @@ import React__default from "react";
|
|
|
2
2
|
import { ButtonWithTooltip } from "../primitives/toolbar.js";
|
|
3
3
|
import FrontmatterIcon from "../../../icons/frontmatter.svg.js";
|
|
4
4
|
import { frontmatterPluginHooks } from "../../frontmatter/index.js";
|
|
5
|
+
import styles from "../../../styles/ui.module.css.js";
|
|
6
|
+
import classNames from "classnames";
|
|
5
7
|
const InsertFrontmatter = () => {
|
|
6
8
|
const insertFrontmatter = frontmatterPluginHooks.usePublisher("insertFrontmatter");
|
|
7
|
-
|
|
9
|
+
const [hasFrontmatter] = frontmatterPluginHooks.useEmitterValues("hasFrontmatter");
|
|
10
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
11
|
+
ButtonWithTooltip,
|
|
12
|
+
{
|
|
13
|
+
title: hasFrontmatter ? "Edit frontmatter" : "Insert frontmatter",
|
|
14
|
+
className: classNames({
|
|
15
|
+
[styles.activeToolbarButton]: hasFrontmatter
|
|
16
|
+
}),
|
|
17
|
+
onClick: insertFrontmatter.bind(null, true)
|
|
18
|
+
},
|
|
19
|
+
/* @__PURE__ */ React__default.createElement(FrontmatterIcon, null)
|
|
20
|
+
);
|
|
8
21
|
};
|
|
9
22
|
export {
|
|
10
23
|
InsertFrontmatter
|