@bizapps/design-system-testing 1.7.1 → 1.8.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/editor.cjs +82 -76
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.d.cts +58 -31
- package/dist/editor.d.ts +58 -31
- package/dist/editor.js +82 -76
- package/dist/editor.js.map +1 -1
- package/package.json +1 -1
package/dist/editor.d.cts
CHANGED
|
@@ -164,6 +164,36 @@ interface InsertImageDialogProps {
|
|
|
164
164
|
*/
|
|
165
165
|
declare function InsertImageDialog({ open, onOpenChange, labels, url, onUrlChange, alt, onAltChange, file, onFileChange, uploading, onApply, onCancel, removable, onRemove, maxSizeBytes, accept, }: InsertImageDialogProps): react.JSX.Element;
|
|
166
166
|
|
|
167
|
+
interface LinkBubbleMenuLabels {
|
|
168
|
+
open: string;
|
|
169
|
+
edit: string;
|
|
170
|
+
remove: string;
|
|
171
|
+
}
|
|
172
|
+
interface LinkBubbleMenuProps {
|
|
173
|
+
editor: Editor | null;
|
|
174
|
+
labels: LinkBubbleMenuLabels;
|
|
175
|
+
/** Opens the consumer's link dialog, pre-filled with the current href. */
|
|
176
|
+
onEdit: () => void;
|
|
177
|
+
/**
|
|
178
|
+
* Follows the link. Left to the consumer for the cases this package cannot
|
|
179
|
+
* judge — routing instead of navigating, or confirming first.
|
|
180
|
+
*
|
|
181
|
+
* Defaults to opening a new tab, which is also what Ctrl/Cmd-click does, so
|
|
182
|
+
* the author never loses unsaved work just by checking a URL.
|
|
183
|
+
*/
|
|
184
|
+
onOpen?: (href: string) => void;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* A floating bar that appears when the caret sits inside a link, offering to
|
|
188
|
+
* open, edit or unlink it.
|
|
189
|
+
*
|
|
190
|
+
* It exists because an editor cannot let a plain click navigate: clicking is how
|
|
191
|
+
* you place the caret to fix a typo, so `openOnClick` stays false and this gives
|
|
192
|
+
* the author a deliberate way out to the URL. Ctrl/Cmd-click is wired separately,
|
|
193
|
+
* on the editor itself, for people who expect the shortcut.
|
|
194
|
+
*/
|
|
195
|
+
declare function LinkBubbleMenu({ editor, labels, onEdit, onOpen }: LinkBubbleMenuProps): react.JSX.Element | null;
|
|
196
|
+
|
|
167
197
|
/**
|
|
168
198
|
* Whatever `useEditor` accepts in its `extensions` array.
|
|
169
199
|
*
|
|
@@ -190,6 +220,8 @@ interface RichTextEditorLabels {
|
|
|
190
220
|
bullet: string;
|
|
191
221
|
ordered: string;
|
|
192
222
|
};
|
|
223
|
+
/** The floating bar shown while the caret sits inside a link. */
|
|
224
|
+
link: LinkBubbleMenuLabels;
|
|
193
225
|
table: TableMenuLabels;
|
|
194
226
|
highlight: string;
|
|
195
227
|
}
|
|
@@ -217,13 +249,38 @@ interface UseRichTextEditorOptions {
|
|
|
217
249
|
after?: string;
|
|
218
250
|
items: ToolbarItem[];
|
|
219
251
|
}[];
|
|
252
|
+
/**
|
|
253
|
+
* Replaces a built-in entry, keyed by its id.
|
|
254
|
+
*
|
|
255
|
+
* For when a product needs a richer version of something the preset already
|
|
256
|
+
* provides — swapping the single highlight button for a palette of shades,
|
|
257
|
+
* say. Replacing rather than adding keeps the toolbar from carrying both.
|
|
258
|
+
*/
|
|
259
|
+
replaceToolbar?: Record<string, ToolbarItem>;
|
|
220
260
|
/** Merged on top of the built-in content styles. */
|
|
221
261
|
contentClassName?: string;
|
|
222
262
|
/** Allows data: URIs in images. Off by default: uploads belong in storage. */
|
|
223
263
|
allowBase64Images?: boolean;
|
|
264
|
+
/**
|
|
265
|
+
* Merged into the editor's `editorProps`. For behaviour only a product can
|
|
266
|
+
* define — clamping pasted tables to a contract's row limit, say.
|
|
267
|
+
*
|
|
268
|
+
* `attributes` and `handleClick` are set by the hook and are not overridable:
|
|
269
|
+
* they carry the accessible name and the link shortcut, which are the
|
|
270
|
+
* defaults consumers were getting wrong by hand.
|
|
271
|
+
*/
|
|
272
|
+
editorProps?: Omit<NonNullable<EditorOptions['editorProps']>, 'attributes' | 'handleClick'>;
|
|
224
273
|
}
|
|
225
274
|
interface UseRichTextEditorResult {
|
|
226
275
|
editor: Editor | null;
|
|
276
|
+
/**
|
|
277
|
+
* The floating link bar, ready to render beside `<RichTextEditor />`.
|
|
278
|
+
*
|
|
279
|
+
* Returned as an element rather than left to the consumer because it is easy
|
|
280
|
+
* to forget, and an editor without it gives the author no way to reach or
|
|
281
|
+
* remove a link they have already inserted.
|
|
282
|
+
*/
|
|
283
|
+
linkMenu: ReactNode;
|
|
227
284
|
/** Ready for `<RichTextEditor items={...} />`. */
|
|
228
285
|
toolbar: ToolbarItem[];
|
|
229
286
|
/** True when the caret has no selection, so a new link needs its own text. */
|
|
@@ -245,7 +302,7 @@ interface UseRichTextEditorResult {
|
|
|
245
302
|
* What stays with the consumer is what only it can know: the marks its document
|
|
246
303
|
* contract allows, and the copy. Both arrive as options.
|
|
247
304
|
*/
|
|
248
|
-
declare function useRichTextEditor({ labels, onUpdate, content, onInsertLink, onInsertImage, extraExtensions, extraToolbar, contentClassName, allowBase64Images, }: UseRichTextEditorOptions): UseRichTextEditorResult;
|
|
305
|
+
declare function useRichTextEditor({ labels, onUpdate, content, onInsertLink, onInsertImage, extraExtensions, extraToolbar, replaceToolbar, contentClassName, allowBase64Images, editorProps, }: UseRichTextEditorOptions): UseRichTextEditorResult;
|
|
249
306
|
|
|
250
307
|
/**
|
|
251
308
|
* One entry in the palette.
|
|
@@ -354,36 +411,6 @@ interface InsertLinkDialogProps {
|
|
|
354
411
|
*/
|
|
355
412
|
declare function InsertLinkDialog({ open, onOpenChange, labels, url, onUrlChange, text, onTextChange, needsText, onApply, onCancel, }: InsertLinkDialogProps): react.JSX.Element;
|
|
356
413
|
|
|
357
|
-
interface LinkBubbleMenuLabels {
|
|
358
|
-
open: string;
|
|
359
|
-
edit: string;
|
|
360
|
-
remove: string;
|
|
361
|
-
}
|
|
362
|
-
interface LinkBubbleMenuProps {
|
|
363
|
-
editor: Editor | null;
|
|
364
|
-
labels: LinkBubbleMenuLabels;
|
|
365
|
-
/** Opens the consumer's link dialog, pre-filled with the current href. */
|
|
366
|
-
onEdit: () => void;
|
|
367
|
-
/**
|
|
368
|
-
* Follows the link. Left to the consumer for the cases this package cannot
|
|
369
|
-
* judge — routing instead of navigating, or confirming first.
|
|
370
|
-
*
|
|
371
|
-
* Defaults to opening a new tab, which is also what Ctrl/Cmd-click does, so
|
|
372
|
-
* the author never loses unsaved work just by checking a URL.
|
|
373
|
-
*/
|
|
374
|
-
onOpen?: (href: string) => void;
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* A floating bar that appears when the caret sits inside a link, offering to
|
|
378
|
-
* open, edit or unlink it.
|
|
379
|
-
*
|
|
380
|
-
* It exists because an editor cannot let a plain click navigate: clicking is how
|
|
381
|
-
* you place the caret to fix a typo, so `openOnClick` stays false and this gives
|
|
382
|
-
* the author a deliberate way out to the URL. Ctrl/Cmd-click is wired separately,
|
|
383
|
-
* on the editor itself, for people who expect the shortcut.
|
|
384
|
-
*/
|
|
385
|
-
declare function LinkBubbleMenu({ editor, labels, onEdit, onOpen }: LinkBubbleMenuProps): react.JSX.Element | null;
|
|
386
|
-
|
|
387
414
|
interface ResizableImageOptions {
|
|
388
415
|
/** Already translated: names the resize handle for assistive tech. */
|
|
389
416
|
resizeLabel: string;
|
package/dist/editor.d.ts
CHANGED
|
@@ -164,6 +164,36 @@ interface InsertImageDialogProps {
|
|
|
164
164
|
*/
|
|
165
165
|
declare function InsertImageDialog({ open, onOpenChange, labels, url, onUrlChange, alt, onAltChange, file, onFileChange, uploading, onApply, onCancel, removable, onRemove, maxSizeBytes, accept, }: InsertImageDialogProps): react.JSX.Element;
|
|
166
166
|
|
|
167
|
+
interface LinkBubbleMenuLabels {
|
|
168
|
+
open: string;
|
|
169
|
+
edit: string;
|
|
170
|
+
remove: string;
|
|
171
|
+
}
|
|
172
|
+
interface LinkBubbleMenuProps {
|
|
173
|
+
editor: Editor | null;
|
|
174
|
+
labels: LinkBubbleMenuLabels;
|
|
175
|
+
/** Opens the consumer's link dialog, pre-filled with the current href. */
|
|
176
|
+
onEdit: () => void;
|
|
177
|
+
/**
|
|
178
|
+
* Follows the link. Left to the consumer for the cases this package cannot
|
|
179
|
+
* judge — routing instead of navigating, or confirming first.
|
|
180
|
+
*
|
|
181
|
+
* Defaults to opening a new tab, which is also what Ctrl/Cmd-click does, so
|
|
182
|
+
* the author never loses unsaved work just by checking a URL.
|
|
183
|
+
*/
|
|
184
|
+
onOpen?: (href: string) => void;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* A floating bar that appears when the caret sits inside a link, offering to
|
|
188
|
+
* open, edit or unlink it.
|
|
189
|
+
*
|
|
190
|
+
* It exists because an editor cannot let a plain click navigate: clicking is how
|
|
191
|
+
* you place the caret to fix a typo, so `openOnClick` stays false and this gives
|
|
192
|
+
* the author a deliberate way out to the URL. Ctrl/Cmd-click is wired separately,
|
|
193
|
+
* on the editor itself, for people who expect the shortcut.
|
|
194
|
+
*/
|
|
195
|
+
declare function LinkBubbleMenu({ editor, labels, onEdit, onOpen }: LinkBubbleMenuProps): react.JSX.Element | null;
|
|
196
|
+
|
|
167
197
|
/**
|
|
168
198
|
* Whatever `useEditor` accepts in its `extensions` array.
|
|
169
199
|
*
|
|
@@ -190,6 +220,8 @@ interface RichTextEditorLabels {
|
|
|
190
220
|
bullet: string;
|
|
191
221
|
ordered: string;
|
|
192
222
|
};
|
|
223
|
+
/** The floating bar shown while the caret sits inside a link. */
|
|
224
|
+
link: LinkBubbleMenuLabels;
|
|
193
225
|
table: TableMenuLabels;
|
|
194
226
|
highlight: string;
|
|
195
227
|
}
|
|
@@ -217,13 +249,38 @@ interface UseRichTextEditorOptions {
|
|
|
217
249
|
after?: string;
|
|
218
250
|
items: ToolbarItem[];
|
|
219
251
|
}[];
|
|
252
|
+
/**
|
|
253
|
+
* Replaces a built-in entry, keyed by its id.
|
|
254
|
+
*
|
|
255
|
+
* For when a product needs a richer version of something the preset already
|
|
256
|
+
* provides — swapping the single highlight button for a palette of shades,
|
|
257
|
+
* say. Replacing rather than adding keeps the toolbar from carrying both.
|
|
258
|
+
*/
|
|
259
|
+
replaceToolbar?: Record<string, ToolbarItem>;
|
|
220
260
|
/** Merged on top of the built-in content styles. */
|
|
221
261
|
contentClassName?: string;
|
|
222
262
|
/** Allows data: URIs in images. Off by default: uploads belong in storage. */
|
|
223
263
|
allowBase64Images?: boolean;
|
|
264
|
+
/**
|
|
265
|
+
* Merged into the editor's `editorProps`. For behaviour only a product can
|
|
266
|
+
* define — clamping pasted tables to a contract's row limit, say.
|
|
267
|
+
*
|
|
268
|
+
* `attributes` and `handleClick` are set by the hook and are not overridable:
|
|
269
|
+
* they carry the accessible name and the link shortcut, which are the
|
|
270
|
+
* defaults consumers were getting wrong by hand.
|
|
271
|
+
*/
|
|
272
|
+
editorProps?: Omit<NonNullable<EditorOptions['editorProps']>, 'attributes' | 'handleClick'>;
|
|
224
273
|
}
|
|
225
274
|
interface UseRichTextEditorResult {
|
|
226
275
|
editor: Editor | null;
|
|
276
|
+
/**
|
|
277
|
+
* The floating link bar, ready to render beside `<RichTextEditor />`.
|
|
278
|
+
*
|
|
279
|
+
* Returned as an element rather than left to the consumer because it is easy
|
|
280
|
+
* to forget, and an editor without it gives the author no way to reach or
|
|
281
|
+
* remove a link they have already inserted.
|
|
282
|
+
*/
|
|
283
|
+
linkMenu: ReactNode;
|
|
227
284
|
/** Ready for `<RichTextEditor items={...} />`. */
|
|
228
285
|
toolbar: ToolbarItem[];
|
|
229
286
|
/** True when the caret has no selection, so a new link needs its own text. */
|
|
@@ -245,7 +302,7 @@ interface UseRichTextEditorResult {
|
|
|
245
302
|
* What stays with the consumer is what only it can know: the marks its document
|
|
246
303
|
* contract allows, and the copy. Both arrive as options.
|
|
247
304
|
*/
|
|
248
|
-
declare function useRichTextEditor({ labels, onUpdate, content, onInsertLink, onInsertImage, extraExtensions, extraToolbar, contentClassName, allowBase64Images, }: UseRichTextEditorOptions): UseRichTextEditorResult;
|
|
305
|
+
declare function useRichTextEditor({ labels, onUpdate, content, onInsertLink, onInsertImage, extraExtensions, extraToolbar, replaceToolbar, contentClassName, allowBase64Images, editorProps, }: UseRichTextEditorOptions): UseRichTextEditorResult;
|
|
249
306
|
|
|
250
307
|
/**
|
|
251
308
|
* One entry in the palette.
|
|
@@ -354,36 +411,6 @@ interface InsertLinkDialogProps {
|
|
|
354
411
|
*/
|
|
355
412
|
declare function InsertLinkDialog({ open, onOpenChange, labels, url, onUrlChange, text, onTextChange, needsText, onApply, onCancel, }: InsertLinkDialogProps): react.JSX.Element;
|
|
356
413
|
|
|
357
|
-
interface LinkBubbleMenuLabels {
|
|
358
|
-
open: string;
|
|
359
|
-
edit: string;
|
|
360
|
-
remove: string;
|
|
361
|
-
}
|
|
362
|
-
interface LinkBubbleMenuProps {
|
|
363
|
-
editor: Editor | null;
|
|
364
|
-
labels: LinkBubbleMenuLabels;
|
|
365
|
-
/** Opens the consumer's link dialog, pre-filled with the current href. */
|
|
366
|
-
onEdit: () => void;
|
|
367
|
-
/**
|
|
368
|
-
* Follows the link. Left to the consumer for the cases this package cannot
|
|
369
|
-
* judge — routing instead of navigating, or confirming first.
|
|
370
|
-
*
|
|
371
|
-
* Defaults to opening a new tab, which is also what Ctrl/Cmd-click does, so
|
|
372
|
-
* the author never loses unsaved work just by checking a URL.
|
|
373
|
-
*/
|
|
374
|
-
onOpen?: (href: string) => void;
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* A floating bar that appears when the caret sits inside a link, offering to
|
|
378
|
-
* open, edit or unlink it.
|
|
379
|
-
*
|
|
380
|
-
* It exists because an editor cannot let a plain click navigate: clicking is how
|
|
381
|
-
* you place the caret to fix a typo, so `openOnClick` stays false and this gives
|
|
382
|
-
* the author a deliberate way out to the URL. Ctrl/Cmd-click is wired separately,
|
|
383
|
-
* on the editor itself, for people who expect the shortcut.
|
|
384
|
-
*/
|
|
385
|
-
declare function LinkBubbleMenu({ editor, labels, onEdit, onOpen }: LinkBubbleMenuProps): react.JSX.Element | null;
|
|
386
|
-
|
|
387
414
|
interface ResizableImageOptions {
|
|
388
415
|
/** Already translated: names the resize handle for assistive tech. */
|
|
389
416
|
resizeLabel: string;
|
package/dist/editor.js
CHANGED
|
@@ -974,6 +974,78 @@ function createResizableImage(options) {
|
|
|
974
974
|
}
|
|
975
975
|
});
|
|
976
976
|
}
|
|
977
|
+
function LinkActions({ editor, labels, onEdit, onOpen }) {
|
|
978
|
+
const href = useEditorState({
|
|
979
|
+
editor,
|
|
980
|
+
selector: ({ editor: current }) => current.getAttributes("link").href ?? ""
|
|
981
|
+
});
|
|
982
|
+
return /* @__PURE__ */ jsxs(
|
|
983
|
+
"div",
|
|
984
|
+
{
|
|
985
|
+
"data-slot": "link-bubble-menu",
|
|
986
|
+
className: "bg-popover text-popover-foreground flex items-center gap-1 rounded-md border p-1 shadow-md",
|
|
987
|
+
children: [
|
|
988
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground max-w-[16rem] truncate px-2 text-xs", children: href }),
|
|
989
|
+
/* @__PURE__ */ jsx(
|
|
990
|
+
Button,
|
|
991
|
+
{
|
|
992
|
+
type: "button",
|
|
993
|
+
size: "sm",
|
|
994
|
+
variant: "ghost",
|
|
995
|
+
title: labels.open,
|
|
996
|
+
"aria-label": labels.open,
|
|
997
|
+
disabled: !href,
|
|
998
|
+
onClick: () => {
|
|
999
|
+
if (!href) return;
|
|
1000
|
+
if (onOpen) {
|
|
1001
|
+
onOpen(href);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
1005
|
+
},
|
|
1006
|
+
children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" })
|
|
1007
|
+
}
|
|
1008
|
+
),
|
|
1009
|
+
/* @__PURE__ */ jsx(
|
|
1010
|
+
Button,
|
|
1011
|
+
{
|
|
1012
|
+
type: "button",
|
|
1013
|
+
size: "sm",
|
|
1014
|
+
variant: "ghost",
|
|
1015
|
+
title: labels.edit,
|
|
1016
|
+
"aria-label": labels.edit,
|
|
1017
|
+
onClick: onEdit,
|
|
1018
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
|
|
1019
|
+
}
|
|
1020
|
+
),
|
|
1021
|
+
/* @__PURE__ */ jsx(
|
|
1022
|
+
Button,
|
|
1023
|
+
{
|
|
1024
|
+
type: "button",
|
|
1025
|
+
size: "sm",
|
|
1026
|
+
variant: "ghost",
|
|
1027
|
+
className: "text-destructive",
|
|
1028
|
+
title: labels.remove,
|
|
1029
|
+
"aria-label": labels.remove,
|
|
1030
|
+
onClick: () => editor.chain().focus().extendMarkRange("link").unsetLink().run(),
|
|
1031
|
+
children: /* @__PURE__ */ jsx(Unlink, { className: "h-4 w-4" })
|
|
1032
|
+
}
|
|
1033
|
+
)
|
|
1034
|
+
]
|
|
1035
|
+
}
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
function LinkBubbleMenu({ editor, labels, onEdit, onOpen }) {
|
|
1039
|
+
const shouldShow = useCallback(
|
|
1040
|
+
// Only while the caret is actually in a link — otherwise this bar would
|
|
1041
|
+
// compete with any other bubble menu the consumer adds.
|
|
1042
|
+
({ editor: current }) => current.isActive("link"),
|
|
1043
|
+
[]
|
|
1044
|
+
);
|
|
1045
|
+
const options = useMemo(() => ({ placement: "bottom", offset: 8 }), []);
|
|
1046
|
+
if (!editor) return null;
|
|
1047
|
+
return /* @__PURE__ */ jsx(BubbleMenu, { editor, shouldShow, options, children: /* @__PURE__ */ jsx(LinkActions, { editor, labels, onEdit, onOpen }) });
|
|
1048
|
+
}
|
|
977
1049
|
function ListMenu({ editor, triggerLabel, icon, options }) {
|
|
978
1050
|
const active = options.find((option) => editor?.isActive(option.node));
|
|
979
1051
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
@@ -1026,8 +1098,10 @@ function useRichTextEditor({
|
|
|
1026
1098
|
onInsertImage,
|
|
1027
1099
|
extraExtensions = [],
|
|
1028
1100
|
extraToolbar = [],
|
|
1101
|
+
replaceToolbar,
|
|
1029
1102
|
contentClassName,
|
|
1030
|
-
allowBase64Images = false
|
|
1103
|
+
allowBase64Images = false,
|
|
1104
|
+
editorProps
|
|
1031
1105
|
}) {
|
|
1032
1106
|
const [linkNeedsText, setLinkNeedsText] = useState(false);
|
|
1033
1107
|
const editor = useEditor({
|
|
@@ -1050,6 +1124,7 @@ function useRichTextEditor({
|
|
|
1050
1124
|
// repaint as the selection and attributes change.
|
|
1051
1125
|
shouldRerenderOnTransaction: true,
|
|
1052
1126
|
editorProps: {
|
|
1127
|
+
...editorProps,
|
|
1053
1128
|
attributes: {
|
|
1054
1129
|
// ProseMirror's editable div needs its own accessible name: a
|
|
1055
1130
|
// visible <Label> beside it is decoration, and a screen reader
|
|
@@ -1219,7 +1294,9 @@ function useRichTextEditor({
|
|
|
1219
1294
|
)
|
|
1220
1295
|
}
|
|
1221
1296
|
];
|
|
1222
|
-
let items = builtIn
|
|
1297
|
+
let items = replaceToolbar ? builtIn.map(
|
|
1298
|
+
(item) => item.kind !== "separator" && replaceToolbar[item.id] ? replaceToolbar[item.id] : item
|
|
1299
|
+
) : builtIn;
|
|
1223
1300
|
const appended = [];
|
|
1224
1301
|
for (const group of extraToolbar) {
|
|
1225
1302
|
if (!group.after) {
|
|
@@ -1236,8 +1313,9 @@ function useRichTextEditor({
|
|
|
1236
1313
|
items = [...items.slice(0, at + 1), ...group.items, ...items.slice(at + 1)];
|
|
1237
1314
|
}
|
|
1238
1315
|
return [...items, ...appended];
|
|
1239
|
-
}, [labels, extraToolbar, onInsertImage, openLink]);
|
|
1240
|
-
|
|
1316
|
+
}, [labels, extraToolbar, replaceToolbar, onInsertImage, openLink]);
|
|
1317
|
+
const linkMenu = /* @__PURE__ */ jsx(LinkBubbleMenu, { editor, labels: labels.link, onEdit: openLink });
|
|
1318
|
+
return { editor, toolbar, linkMenu, linkNeedsText, currentLinkHref, applyLink };
|
|
1241
1319
|
}
|
|
1242
1320
|
function ColorMenu({ editor, labels, icon, swatches }) {
|
|
1243
1321
|
const active = swatches.find((swatch) => editor?.isActive(swatch.mark));
|
|
@@ -1377,78 +1455,6 @@ function InsertLinkDialog({
|
|
|
1377
1455
|
] })
|
|
1378
1456
|
] }) });
|
|
1379
1457
|
}
|
|
1380
|
-
function LinkActions({ editor, labels, onEdit, onOpen }) {
|
|
1381
|
-
const href = useEditorState({
|
|
1382
|
-
editor,
|
|
1383
|
-
selector: ({ editor: current }) => current.getAttributes("link").href ?? ""
|
|
1384
|
-
});
|
|
1385
|
-
return /* @__PURE__ */ jsxs(
|
|
1386
|
-
"div",
|
|
1387
|
-
{
|
|
1388
|
-
"data-slot": "link-bubble-menu",
|
|
1389
|
-
className: "bg-popover text-popover-foreground flex items-center gap-1 rounded-md border p-1 shadow-md",
|
|
1390
|
-
children: [
|
|
1391
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground max-w-[16rem] truncate px-2 text-xs", children: href }),
|
|
1392
|
-
/* @__PURE__ */ jsx(
|
|
1393
|
-
Button,
|
|
1394
|
-
{
|
|
1395
|
-
type: "button",
|
|
1396
|
-
size: "sm",
|
|
1397
|
-
variant: "ghost",
|
|
1398
|
-
title: labels.open,
|
|
1399
|
-
"aria-label": labels.open,
|
|
1400
|
-
disabled: !href,
|
|
1401
|
-
onClick: () => {
|
|
1402
|
-
if (!href) return;
|
|
1403
|
-
if (onOpen) {
|
|
1404
|
-
onOpen(href);
|
|
1405
|
-
return;
|
|
1406
|
-
}
|
|
1407
|
-
window.open(href, "_blank", "noopener,noreferrer");
|
|
1408
|
-
},
|
|
1409
|
-
children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-4 w-4" })
|
|
1410
|
-
}
|
|
1411
|
-
),
|
|
1412
|
-
/* @__PURE__ */ jsx(
|
|
1413
|
-
Button,
|
|
1414
|
-
{
|
|
1415
|
-
type: "button",
|
|
1416
|
-
size: "sm",
|
|
1417
|
-
variant: "ghost",
|
|
1418
|
-
title: labels.edit,
|
|
1419
|
-
"aria-label": labels.edit,
|
|
1420
|
-
onClick: onEdit,
|
|
1421
|
-
children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
|
|
1422
|
-
}
|
|
1423
|
-
),
|
|
1424
|
-
/* @__PURE__ */ jsx(
|
|
1425
|
-
Button,
|
|
1426
|
-
{
|
|
1427
|
-
type: "button",
|
|
1428
|
-
size: "sm",
|
|
1429
|
-
variant: "ghost",
|
|
1430
|
-
className: "text-destructive",
|
|
1431
|
-
title: labels.remove,
|
|
1432
|
-
"aria-label": labels.remove,
|
|
1433
|
-
onClick: () => editor.chain().focus().extendMarkRange("link").unsetLink().run(),
|
|
1434
|
-
children: /* @__PURE__ */ jsx(Unlink, { className: "h-4 w-4" })
|
|
1435
|
-
}
|
|
1436
|
-
)
|
|
1437
|
-
]
|
|
1438
|
-
}
|
|
1439
|
-
);
|
|
1440
|
-
}
|
|
1441
|
-
function LinkBubbleMenu({ editor, labels, onEdit, onOpen }) {
|
|
1442
|
-
const shouldShow = useCallback(
|
|
1443
|
-
// Only while the caret is actually in a link — otherwise this bar would
|
|
1444
|
-
// compete with any other bubble menu the consumer adds.
|
|
1445
|
-
({ editor: current }) => current.isActive("link"),
|
|
1446
|
-
[]
|
|
1447
|
-
);
|
|
1448
|
-
const options = useMemo(() => ({ placement: "bottom", offset: 8 }), []);
|
|
1449
|
-
if (!editor) return null;
|
|
1450
|
-
return /* @__PURE__ */ jsx(BubbleMenu, { editor, shouldShow, options, children: /* @__PURE__ */ jsx(LinkActions, { editor, labels, onEdit, onOpen }) });
|
|
1451
|
-
}
|
|
1452
1458
|
|
|
1453
1459
|
export { ColorMenu, EDITOR_CONTENT_STYLE, InsertImageDialog, InsertLinkDialog, LinkBubbleMenu, ListMenu, RichTextEditor, RichTextToolbar, TableMenu, createResizableImage, useRichTextEditor };
|
|
1454
1460
|
//# sourceMappingURL=editor.js.map
|