@mantine/tiptap 9.2.1 → 9.2.2
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/cjs/RichTextEditorControl/RichTextEditorControl.cjs +12 -6
- package/cjs/RichTextEditorControl/RichTextEditorControl.cjs.map +1 -1
- package/cjs/RichTextEditorControl/RichTextEditorLinkControl.cjs +1 -1
- package/cjs/RichTextEditorControl/RichTextEditorLinkControl.cjs.map +1 -1
- package/esm/RichTextEditorControl/RichTextEditorControl.mjs +12 -6
- package/esm/RichTextEditorControl/RichTextEditorControl.mjs.map +1 -1
- package/esm/RichTextEditorControl/RichTextEditorLinkControl.mjs +1 -1
- package/esm/RichTextEditorControl/RichTextEditorLinkControl.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -50,13 +50,16 @@ function createControl({ label, isActive, operation, icon, isDisabled }) {
|
|
|
50
50
|
const _label = labels[label];
|
|
51
51
|
const editorState = (0, _tiptap_react.useEditorState)({
|
|
52
52
|
editor: editor ?? null,
|
|
53
|
-
selector: (ctx) =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
selector: (ctx) => {
|
|
54
|
+
const safeEditor = ctx.editor && !ctx.editor.isDestroyed ? ctx.editor : null;
|
|
55
|
+
return {
|
|
56
|
+
active: safeEditor && isActive?.name ? safeEditor.isActive(isActive.name, isActive.attributes) : false,
|
|
57
|
+
disabled: safeEditor ? isDisabled?.(safeEditor) ?? false : true
|
|
58
|
+
};
|
|
59
|
+
}
|
|
57
60
|
});
|
|
58
61
|
const active = editorState?.active ?? false;
|
|
59
|
-
const disabled = editorState?.disabled ??
|
|
62
|
+
const disabled = editorState?.disabled ?? true;
|
|
60
63
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RichTextEditorControlBase, {
|
|
61
64
|
"aria-label": _label,
|
|
62
65
|
title: _label,
|
|
@@ -64,7 +67,10 @@ function createControl({ label, isActive, operation, icon, isDisabled }) {
|
|
|
64
67
|
icon: props.icon || icon,
|
|
65
68
|
disabled,
|
|
66
69
|
...props,
|
|
67
|
-
onClick: () =>
|
|
70
|
+
onClick: () => {
|
|
71
|
+
if (!editor || editor.isDestroyed) return;
|
|
72
|
+
editor.chain().focus()[operation.name](operation.attributes).run();
|
|
73
|
+
}
|
|
68
74
|
});
|
|
69
75
|
};
|
|
70
76
|
Control.displayName = `@mantine/tiptap/${label}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorControl.cjs","names":["useRichTextEditorContext","UnstyledButton","classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorControl.tsx"],"sourcesContent":["import { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n UnstyledButton,\n useProps,\n} from '@mantine/core';\nimport { RichTextEditorLabels } from '../labels';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorControlStylesNames = 'control';\n\nexport interface RichTextEditorControlProps\n extends BoxProps, CompoundStylesApiProps<RichTextEditorControlFactory>, ElementProps<'button'> {\n /** Determines whether the control should have active state @default false */\n active?: boolean;\n\n /** Determines whether the control can be interacted with, set `false` to make the control to act as a label */\n interactive?: boolean;\n}\n\nexport type RichTextEditorControlFactory = Factory<{\n props: RichTextEditorControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorControlStylesNames;\n compound: true;\n}>;\n\nconst defaultProps = {\n interactive: true,\n} satisfies Partial<RichTextEditorControlProps>;\n\nexport const RichTextEditorControl = factory<RichTextEditorControlFactory>((_props) => {\n const props = useProps('RichTextEditorControl', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n interactive,\n active,\n onMouseDown,\n disabled,\n ...others\n } = props;\n const ctx = useRichTextEditorContext();\n\n return (\n <UnstyledButton\n {...others}\n {...ctx.getStyles('control', { className, style, classNames, styles })}\n disabled={disabled}\n data-rich-text-editor-control\n tabIndex={interactive ? 0 : -1}\n data-interactive={interactive || undefined}\n data-disabled={disabled || undefined}\n data-active={active || undefined}\n aria-pressed={(active && interactive) || undefined}\n aria-hidden={!interactive || undefined}\n unstyled={ctx.unstyled}\n variant={ctx.variant || 'default'}\n onMouseDown={(event) => {\n event.preventDefault();\n onMouseDown?.(event);\n }}\n />\n );\n});\n\nRichTextEditorControl.classes = classes;\nRichTextEditorControl.displayName = '@mantine/tiptap/RichTextEditorControl';\n\nexport interface RichTextEditorControlBaseProps extends RichTextEditorControlProps {\n icon?: React.FC<{ style: React.CSSProperties }>;\n}\n\nexport function RichTextEditorControlBase({\n className,\n icon: Icon,\n ...others\n}: RichTextEditorControlBaseProps & { icon: React.FC<{ style: React.CSSProperties }> }) {\n const ctx = useRichTextEditorContext();\n\n return (\n <RichTextEditorControl {...others}>\n <Icon {...ctx.getStyles('controlIcon')} />\n </RichTextEditorControl>\n );\n}\n\nRichTextEditorControlBase.displayName = '@mantine/tiptap/RichTextEditorControlBase';\n\nexport interface CreateControlProps {\n label: keyof RichTextEditorLabels;\n icon: React.FC<{ style: React.CSSProperties }>;\n isActive?: { name: string; attributes?: Record<string, any> | string };\n isDisabled?: (editor: any) => boolean;\n operation: { name: string; attributes?: Record<string, any> | string };\n}\n\nexport function createControl({\n label,\n isActive,\n operation,\n icon,\n isDisabled,\n}: CreateControlProps) {\n const Control = (props: RichTextEditorControlBaseProps) => {\n const { editor, labels } = useRichTextEditorContext();\n const _label = labels[label] as string;\n const editorState = useEditorState({\n editor: editor ?? null,\n selector: (ctx) =>
|
|
1
|
+
{"version":3,"file":"RichTextEditorControl.cjs","names":["useRichTextEditorContext","UnstyledButton","classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorControl.tsx"],"sourcesContent":["import { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n UnstyledButton,\n useProps,\n} from '@mantine/core';\nimport { RichTextEditorLabels } from '../labels';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorControlStylesNames = 'control';\n\nexport interface RichTextEditorControlProps\n extends BoxProps, CompoundStylesApiProps<RichTextEditorControlFactory>, ElementProps<'button'> {\n /** Determines whether the control should have active state @default false */\n active?: boolean;\n\n /** Determines whether the control can be interacted with, set `false` to make the control to act as a label */\n interactive?: boolean;\n}\n\nexport type RichTextEditorControlFactory = Factory<{\n props: RichTextEditorControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorControlStylesNames;\n compound: true;\n}>;\n\nconst defaultProps = {\n interactive: true,\n} satisfies Partial<RichTextEditorControlProps>;\n\nexport const RichTextEditorControl = factory<RichTextEditorControlFactory>((_props) => {\n const props = useProps('RichTextEditorControl', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n interactive,\n active,\n onMouseDown,\n disabled,\n ...others\n } = props;\n const ctx = useRichTextEditorContext();\n\n return (\n <UnstyledButton\n {...others}\n {...ctx.getStyles('control', { className, style, classNames, styles })}\n disabled={disabled}\n data-rich-text-editor-control\n tabIndex={interactive ? 0 : -1}\n data-interactive={interactive || undefined}\n data-disabled={disabled || undefined}\n data-active={active || undefined}\n aria-pressed={(active && interactive) || undefined}\n aria-hidden={!interactive || undefined}\n unstyled={ctx.unstyled}\n variant={ctx.variant || 'default'}\n onMouseDown={(event) => {\n event.preventDefault();\n onMouseDown?.(event);\n }}\n />\n );\n});\n\nRichTextEditorControl.classes = classes;\nRichTextEditorControl.displayName = '@mantine/tiptap/RichTextEditorControl';\n\nexport interface RichTextEditorControlBaseProps extends RichTextEditorControlProps {\n icon?: React.FC<{ style: React.CSSProperties }>;\n}\n\nexport function RichTextEditorControlBase({\n className,\n icon: Icon,\n ...others\n}: RichTextEditorControlBaseProps & { icon: React.FC<{ style: React.CSSProperties }> }) {\n const ctx = useRichTextEditorContext();\n\n return (\n <RichTextEditorControl {...others}>\n <Icon {...ctx.getStyles('controlIcon')} />\n </RichTextEditorControl>\n );\n}\n\nRichTextEditorControlBase.displayName = '@mantine/tiptap/RichTextEditorControlBase';\n\nexport interface CreateControlProps {\n label: keyof RichTextEditorLabels;\n icon: React.FC<{ style: React.CSSProperties }>;\n isActive?: { name: string; attributes?: Record<string, any> | string };\n isDisabled?: (editor: any) => boolean;\n operation: { name: string; attributes?: Record<string, any> | string };\n}\n\nexport function createControl({\n label,\n isActive,\n operation,\n icon,\n isDisabled,\n}: CreateControlProps) {\n const Control = (props: RichTextEditorControlBaseProps) => {\n const { editor, labels } = useRichTextEditorContext();\n const _label = labels[label] as string;\n const editorState = useEditorState({\n editor: editor ?? null,\n selector: (ctx) => {\n // `ctx.editor` is `null` on the first render before `useEditor()` produces an\n // instance, and `editor.commandManager` is set to `null` by `editor.destroy()`.\n // Either state would make `isDisabled?.(ctx.editor)` (which typically calls\n // `editor.can()`) throw, taking down the surrounding tree.\n const safeEditor = ctx.editor && !ctx.editor.isDestroyed ? ctx.editor : null;\n return {\n active:\n safeEditor && isActive?.name\n ? safeEditor.isActive(isActive.name, isActive.attributes)\n : false,\n // Without a usable editor the operation cannot run, so the control must\n // appear disabled regardless of whether a user-provided `isDisabled` exists.\n disabled: safeEditor ? (isDisabled?.(safeEditor) ?? false) : true,\n };\n },\n });\n\n const active = editorState?.active ?? false;\n const disabled = editorState?.disabled ?? true;\n\n return (\n <RichTextEditorControlBase\n aria-label={_label}\n title={_label}\n active={active}\n icon={props.icon || icon}\n disabled={disabled}\n {...props}\n onClick={() => {\n // Mirror the selector's guard so a click landing during teardown does not\n // invoke commands on a `null`/destroyed editor.\n if (!editor || editor.isDestroyed) {\n return;\n }\n (editor as any).chain().focus()[operation.name](operation.attributes).run();\n }}\n />\n );\n };\n\n Control.displayName = `@mantine/tiptap/${label}`;\n\n return Control;\n}\n"],"mappings":";;;;;;;;AAgCA,MAAM,eAAe,EACnB,aAAa,KACf;AAEA,MAAa,yBAAA,GAAA,cAAA,UAA+D,WAAW;CAErF,MAAM,EACJ,YACA,WACA,OACA,QACA,MACA,aACA,QACA,aACA,UACA,GAAG,YAAA,GAAA,cAAA,UAXkB,yBAAyB,cAAc,MAYtD;CACR,MAAM,MAAMA,+BAAAA,yBAAyB;CAErC,OACE,iBAAA,GAAA,kBAAA,KAACC,cAAAA,gBAAD;EACE,GAAI;EACJ,GAAI,IAAI,UAAU,WAAW;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EAC3D;EACV,iCAAA;EACA,UAAU,cAAc,IAAI;EAC5B,oBAAkB,eAAe,KAAA;EACjC,iBAAe,YAAY,KAAA;EAC3B,eAAa,UAAU,KAAA;EACvB,gBAAe,UAAU,eAAgB,KAAA;EACzC,eAAa,CAAC,eAAe,KAAA;EAC7B,UAAU,IAAI;EACd,SAAS,IAAI,WAAW;EACxB,cAAc,UAAU;GACtB,MAAM,eAAe;GACrB,cAAc,KAAK;EACrB;CACD,CAAA;AAEL,CAAC;AAED,sBAAsB,UAAUC,8BAAAA;AAChC,sBAAsB,cAAc;AAMpC,SAAgB,0BAA0B,EACxC,WACA,MAAM,MACN,GAAG,UACmF;CACtF,MAAM,MAAMF,+BAAAA,yBAAyB;CAErC,OACE,iBAAA,GAAA,kBAAA,KAAC,uBAAD;EAAuB,GAAI;YACzB,iBAAA,GAAA,kBAAA,KAAC,MAAD,EAAM,GAAI,IAAI,UAAU,aAAa,EAAI,CAAA;CACpB,CAAA;AAE3B;AAEA,0BAA0B,cAAc;AAUxC,SAAgB,cAAc,EAC5B,OACA,UACA,WACA,MACA,cACqB;CACrB,MAAM,WAAW,UAA0C;EACzD,MAAM,EAAE,QAAQ,WAAWA,+BAAAA,yBAAyB;EACpD,MAAM,SAAS,OAAO;EACtB,MAAM,eAAA,GAAA,cAAA,gBAA6B;GACjC,QAAQ,UAAU;GAClB,WAAW,QAAQ;IAKjB,MAAM,aAAa,IAAI,UAAU,CAAC,IAAI,OAAO,cAAc,IAAI,SAAS;IACxE,OAAO;KACL,QACE,cAAc,UAAU,OACpB,WAAW,SAAS,SAAS,MAAM,SAAS,UAAU,IACtD;KAGN,UAAU,aAAc,aAAa,UAAU,KAAK,QAAS;IAC/D;GACF;EACF,CAAC;EAED,MAAM,SAAS,aAAa,UAAU;EACtC,MAAM,WAAW,aAAa,YAAY;EAE1C,OACE,iBAAA,GAAA,kBAAA,KAAC,2BAAD;GACE,cAAY;GACZ,OAAO;GACC;GACR,MAAM,MAAM,QAAQ;GACV;GACV,GAAI;GACJ,eAAe;IAGb,IAAI,CAAC,UAAU,OAAO,aACpB;IAEF,OAAgB,MAAM,EAAE,MAAM,EAAE,UAAU,MAAM,UAAU,UAAU,EAAE,IAAI;GAC5E;EACD,CAAA;CAEL;CAEA,QAAQ,cAAc,mBAAmB;CAEzC,OAAO;AACT"}
|
|
@@ -49,7 +49,7 @@ const RichTextEditorLinkControl = (0, _mantine_core.factory)((_props) => {
|
|
|
49
49
|
(0, _mantine_hooks.useWindowEvent)("edit-link", handleOpen, false);
|
|
50
50
|
const active = (0, _tiptap_react.useEditorState)({
|
|
51
51
|
editor: ctx.editor ?? null,
|
|
52
|
-
selector: (state) => state.editor
|
|
52
|
+
selector: (state) => state.editor && !state.editor.isDestroyed ? state.editor.isActive("link") : false
|
|
53
53
|
});
|
|
54
54
|
const { resolvedClassNames, resolvedStyles } = (0, _mantine_core.useResolvedStylesApi)({
|
|
55
55
|
classNames,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorLinkControl.cjs","names":["IconLink","useRichTextEditorContext","Popover","RichTextEditorControlBase","TextInput","Tooltip","UnstyledButton","IconExternalLink","Button","classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorLinkControl.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n Button,\n CompoundStylesApiProps,\n factory,\n Factory,\n Popover,\n PopoverProps,\n rem,\n TextInput,\n Tooltip,\n UnstyledButton,\n useProps,\n useResolvedStylesApi,\n} from '@mantine/core';\nimport { useDisclosure, useInputState, useWindowEvent } from '@mantine/hooks';\nimport { IconExternalLink, IconLink } from '../icons/Icons';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport { RichTextEditorControlBase, RichTextEditorControlBaseProps } from './RichTextEditorControl';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorLinkControlStylesNames =\n | 'control'\n | 'linkEditor'\n | 'linkEditorDropdown'\n | 'linkEditorSave'\n | 'linkEditorInput'\n | 'linkEditorExternalControl';\n\nexport interface RichTextEditorLinkControlProps\n extends\n BoxProps,\n Omit<RichTextEditorControlBaseProps, 'classNames' | 'styles' | 'vars'>,\n CompoundStylesApiProps<RichTextEditorLinkControlFactory> {\n /** Props passed down to Popover component */\n popoverProps?: Partial<PopoverProps>;\n\n /** Determines whether external link control tooltip should be disabled @default false */\n disableTooltips?: boolean;\n\n /** Initial state for determining whether the link should be an external @default false */\n initialExternal?: boolean;\n}\n\nexport type RichTextEditorLinkControlFactory = Factory<{\n props: RichTextEditorLinkControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorLinkControlStylesNames;\n compound: true;\n}>;\n\nconst LinkIcon: RichTextEditorControlBaseProps['icon'] = (props) => <IconLink {...props} />;\n\nexport const RichTextEditorLinkControl = factory<RichTextEditorLinkControlFactory>((_props) => {\n const props = useProps('RichTextEditorLinkControl', null, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n icon,\n popoverProps,\n disableTooltips,\n initialExternal,\n ...others\n } = props;\n\n const ctx = useRichTextEditorContext();\n\n const stylesApiProps = { classNames, styles };\n\n const [url, setUrl] = useInputState('');\n const [external, setExternal] = useState(initialExternal);\n const [opened, { open, close }] = useDisclosure(false);\n\n const handleOpen = () => {\n open();\n const linkData = ctx.editor?.getAttributes('link');\n setUrl(linkData?.href || '');\n setExternal(linkData?.href ? linkData?.target === '_blank' : initialExternal);\n };\n\n const handleClose = () => {\n close();\n setUrl('');\n setExternal(initialExternal);\n };\n\n const setLink = () => {\n handleClose();\n url === ''\n ? ctx.editor?.chain().focus().extendMarkRange('link').unsetLink().run()\n : ctx.editor\n ?.chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href: url, target: external ? '_blank' : null })\n .run();\n };\n\n const handleInputKeydown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n setLink();\n }\n };\n\n useWindowEvent('edit-link', handleOpen, false);\n\n const active = useEditorState({\n editor: ctx.editor ?? null,\n selector: (state)
|
|
1
|
+
{"version":3,"file":"RichTextEditorLinkControl.cjs","names":["IconLink","useRichTextEditorContext","Popover","RichTextEditorControlBase","TextInput","Tooltip","UnstyledButton","IconExternalLink","Button","classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorLinkControl.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n Button,\n CompoundStylesApiProps,\n factory,\n Factory,\n Popover,\n PopoverProps,\n rem,\n TextInput,\n Tooltip,\n UnstyledButton,\n useProps,\n useResolvedStylesApi,\n} from '@mantine/core';\nimport { useDisclosure, useInputState, useWindowEvent } from '@mantine/hooks';\nimport { IconExternalLink, IconLink } from '../icons/Icons';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport { RichTextEditorControlBase, RichTextEditorControlBaseProps } from './RichTextEditorControl';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorLinkControlStylesNames =\n | 'control'\n | 'linkEditor'\n | 'linkEditorDropdown'\n | 'linkEditorSave'\n | 'linkEditorInput'\n | 'linkEditorExternalControl';\n\nexport interface RichTextEditorLinkControlProps\n extends\n BoxProps,\n Omit<RichTextEditorControlBaseProps, 'classNames' | 'styles' | 'vars'>,\n CompoundStylesApiProps<RichTextEditorLinkControlFactory> {\n /** Props passed down to Popover component */\n popoverProps?: Partial<PopoverProps>;\n\n /** Determines whether external link control tooltip should be disabled @default false */\n disableTooltips?: boolean;\n\n /** Initial state for determining whether the link should be an external @default false */\n initialExternal?: boolean;\n}\n\nexport type RichTextEditorLinkControlFactory = Factory<{\n props: RichTextEditorLinkControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorLinkControlStylesNames;\n compound: true;\n}>;\n\nconst LinkIcon: RichTextEditorControlBaseProps['icon'] = (props) => <IconLink {...props} />;\n\nexport const RichTextEditorLinkControl = factory<RichTextEditorLinkControlFactory>((_props) => {\n const props = useProps('RichTextEditorLinkControl', null, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n icon,\n popoverProps,\n disableTooltips,\n initialExternal,\n ...others\n } = props;\n\n const ctx = useRichTextEditorContext();\n\n const stylesApiProps = { classNames, styles };\n\n const [url, setUrl] = useInputState('');\n const [external, setExternal] = useState(initialExternal);\n const [opened, { open, close }] = useDisclosure(false);\n\n const handleOpen = () => {\n open();\n const linkData = ctx.editor?.getAttributes('link');\n setUrl(linkData?.href || '');\n setExternal(linkData?.href ? linkData?.target === '_blank' : initialExternal);\n };\n\n const handleClose = () => {\n close();\n setUrl('');\n setExternal(initialExternal);\n };\n\n const setLink = () => {\n handleClose();\n url === ''\n ? ctx.editor?.chain().focus().extendMarkRange('link').unsetLink().run()\n : ctx.editor\n ?.chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href: url, target: external ? '_blank' : null })\n .run();\n };\n\n const handleInputKeydown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n setLink();\n }\n };\n\n useWindowEvent('edit-link', handleOpen, false);\n\n const active = useEditorState({\n editor: ctx.editor ?? null,\n selector: (state) =>\n state.editor && !state.editor.isDestroyed ? state.editor.isActive('link') : false,\n });\n\n const { resolvedClassNames, resolvedStyles } =\n useResolvedStylesApi<RichTextEditorLinkControlFactory>({ classNames, styles, props });\n\n return (\n <Popover\n trapFocus\n shadow=\"md\"\n withinPortal\n opened={opened}\n onChange={(_opened) => !_opened && handleClose()}\n offset={-44}\n zIndex={10000}\n {...popoverProps}\n >\n <Popover.Target>\n <RichTextEditorControlBase\n icon={icon || LinkIcon}\n {...others}\n aria-label={ctx.labels.linkControlLabel}\n title={ctx.labels.linkControlLabel}\n onClick={handleOpen}\n active={active ?? false}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n className={className}\n style={style}\n variant={ctx.variant}\n />\n </Popover.Target>\n\n <Popover.Dropdown {...ctx.getStyles('linkEditorDropdown', stylesApiProps)}>\n <div {...ctx.getStyles('linkEditor', stylesApiProps)}>\n <TextInput\n placeholder={ctx.labels.linkEditorInputPlaceholder}\n aria-label={ctx.labels.linkEditorInputLabel}\n type=\"url\"\n value={url}\n onChange={setUrl}\n classNames={{ input: ctx.getStyles('linkEditorInput', stylesApiProps).className }}\n onKeyDown={handleInputKeydown}\n rightSection={\n <Tooltip\n label={\n external ? ctx.labels.linkEditorExternalLink : ctx.labels.linkEditorInternalLink\n }\n events={{ hover: true, focus: true, touch: true }}\n withinPortal\n withArrow\n disabled={disableTooltips}\n zIndex={10000}\n >\n <UnstyledButton\n onClick={() => setExternal((e) => !e)}\n data-active={external || undefined}\n {...ctx.getStyles('linkEditorExternalControl', stylesApiProps)}\n >\n <IconExternalLink style={{ width: rem(14), height: rem(14) }} />\n </UnstyledButton>\n </Tooltip>\n }\n />\n\n <Button\n variant=\"default\"\n onClick={setLink}\n {...ctx.getStyles('linkEditorSave', stylesApiProps)}\n >\n {ctx.labels.linkEditorSave}\n </Button>\n </div>\n </Popover.Dropdown>\n </Popover>\n );\n});\n\nRichTextEditorLinkControl.classes = classes;\nRichTextEditorLinkControl.displayName = '@mantine/tiptap/RichTextEditorLinkControl';\n"],"mappings":"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"}
|
|
@@ -49,13 +49,16 @@ function createControl({ label, isActive, operation, icon, isDisabled }) {
|
|
|
49
49
|
const _label = labels[label];
|
|
50
50
|
const editorState = useEditorState({
|
|
51
51
|
editor: editor ?? null,
|
|
52
|
-
selector: (ctx) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
selector: (ctx) => {
|
|
53
|
+
const safeEditor = ctx.editor && !ctx.editor.isDestroyed ? ctx.editor : null;
|
|
54
|
+
return {
|
|
55
|
+
active: safeEditor && isActive?.name ? safeEditor.isActive(isActive.name, isActive.attributes) : false,
|
|
56
|
+
disabled: safeEditor ? isDisabled?.(safeEditor) ?? false : true
|
|
57
|
+
};
|
|
58
|
+
}
|
|
56
59
|
});
|
|
57
60
|
const active = editorState?.active ?? false;
|
|
58
|
-
const disabled = editorState?.disabled ??
|
|
61
|
+
const disabled = editorState?.disabled ?? true;
|
|
59
62
|
return /* @__PURE__ */ jsx(RichTextEditorControlBase, {
|
|
60
63
|
"aria-label": _label,
|
|
61
64
|
title: _label,
|
|
@@ -63,7 +66,10 @@ function createControl({ label, isActive, operation, icon, isDisabled }) {
|
|
|
63
66
|
icon: props.icon || icon,
|
|
64
67
|
disabled,
|
|
65
68
|
...props,
|
|
66
|
-
onClick: () =>
|
|
69
|
+
onClick: () => {
|
|
70
|
+
if (!editor || editor.isDestroyed) return;
|
|
71
|
+
editor.chain().focus()[operation.name](operation.attributes).run();
|
|
72
|
+
}
|
|
67
73
|
});
|
|
68
74
|
};
|
|
69
75
|
Control.displayName = `@mantine/tiptap/${label}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorControl.mjs","names":["classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorControl.tsx"],"sourcesContent":["import { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n UnstyledButton,\n useProps,\n} from '@mantine/core';\nimport { RichTextEditorLabels } from '../labels';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorControlStylesNames = 'control';\n\nexport interface RichTextEditorControlProps\n extends BoxProps, CompoundStylesApiProps<RichTextEditorControlFactory>, ElementProps<'button'> {\n /** Determines whether the control should have active state @default false */\n active?: boolean;\n\n /** Determines whether the control can be interacted with, set `false` to make the control to act as a label */\n interactive?: boolean;\n}\n\nexport type RichTextEditorControlFactory = Factory<{\n props: RichTextEditorControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorControlStylesNames;\n compound: true;\n}>;\n\nconst defaultProps = {\n interactive: true,\n} satisfies Partial<RichTextEditorControlProps>;\n\nexport const RichTextEditorControl = factory<RichTextEditorControlFactory>((_props) => {\n const props = useProps('RichTextEditorControl', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n interactive,\n active,\n onMouseDown,\n disabled,\n ...others\n } = props;\n const ctx = useRichTextEditorContext();\n\n return (\n <UnstyledButton\n {...others}\n {...ctx.getStyles('control', { className, style, classNames, styles })}\n disabled={disabled}\n data-rich-text-editor-control\n tabIndex={interactive ? 0 : -1}\n data-interactive={interactive || undefined}\n data-disabled={disabled || undefined}\n data-active={active || undefined}\n aria-pressed={(active && interactive) || undefined}\n aria-hidden={!interactive || undefined}\n unstyled={ctx.unstyled}\n variant={ctx.variant || 'default'}\n onMouseDown={(event) => {\n event.preventDefault();\n onMouseDown?.(event);\n }}\n />\n );\n});\n\nRichTextEditorControl.classes = classes;\nRichTextEditorControl.displayName = '@mantine/tiptap/RichTextEditorControl';\n\nexport interface RichTextEditorControlBaseProps extends RichTextEditorControlProps {\n icon?: React.FC<{ style: React.CSSProperties }>;\n}\n\nexport function RichTextEditorControlBase({\n className,\n icon: Icon,\n ...others\n}: RichTextEditorControlBaseProps & { icon: React.FC<{ style: React.CSSProperties }> }) {\n const ctx = useRichTextEditorContext();\n\n return (\n <RichTextEditorControl {...others}>\n <Icon {...ctx.getStyles('controlIcon')} />\n </RichTextEditorControl>\n );\n}\n\nRichTextEditorControlBase.displayName = '@mantine/tiptap/RichTextEditorControlBase';\n\nexport interface CreateControlProps {\n label: keyof RichTextEditorLabels;\n icon: React.FC<{ style: React.CSSProperties }>;\n isActive?: { name: string; attributes?: Record<string, any> | string };\n isDisabled?: (editor: any) => boolean;\n operation: { name: string; attributes?: Record<string, any> | string };\n}\n\nexport function createControl({\n label,\n isActive,\n operation,\n icon,\n isDisabled,\n}: CreateControlProps) {\n const Control = (props: RichTextEditorControlBaseProps) => {\n const { editor, labels } = useRichTextEditorContext();\n const _label = labels[label] as string;\n const editorState = useEditorState({\n editor: editor ?? null,\n selector: (ctx) =>
|
|
1
|
+
{"version":3,"file":"RichTextEditorControl.mjs","names":["classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorControl.tsx"],"sourcesContent":["import { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n CompoundStylesApiProps,\n ElementProps,\n factory,\n Factory,\n UnstyledButton,\n useProps,\n} from '@mantine/core';\nimport { RichTextEditorLabels } from '../labels';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorControlStylesNames = 'control';\n\nexport interface RichTextEditorControlProps\n extends BoxProps, CompoundStylesApiProps<RichTextEditorControlFactory>, ElementProps<'button'> {\n /** Determines whether the control should have active state @default false */\n active?: boolean;\n\n /** Determines whether the control can be interacted with, set `false` to make the control to act as a label */\n interactive?: boolean;\n}\n\nexport type RichTextEditorControlFactory = Factory<{\n props: RichTextEditorControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorControlStylesNames;\n compound: true;\n}>;\n\nconst defaultProps = {\n interactive: true,\n} satisfies Partial<RichTextEditorControlProps>;\n\nexport const RichTextEditorControl = factory<RichTextEditorControlFactory>((_props) => {\n const props = useProps('RichTextEditorControl', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n interactive,\n active,\n onMouseDown,\n disabled,\n ...others\n } = props;\n const ctx = useRichTextEditorContext();\n\n return (\n <UnstyledButton\n {...others}\n {...ctx.getStyles('control', { className, style, classNames, styles })}\n disabled={disabled}\n data-rich-text-editor-control\n tabIndex={interactive ? 0 : -1}\n data-interactive={interactive || undefined}\n data-disabled={disabled || undefined}\n data-active={active || undefined}\n aria-pressed={(active && interactive) || undefined}\n aria-hidden={!interactive || undefined}\n unstyled={ctx.unstyled}\n variant={ctx.variant || 'default'}\n onMouseDown={(event) => {\n event.preventDefault();\n onMouseDown?.(event);\n }}\n />\n );\n});\n\nRichTextEditorControl.classes = classes;\nRichTextEditorControl.displayName = '@mantine/tiptap/RichTextEditorControl';\n\nexport interface RichTextEditorControlBaseProps extends RichTextEditorControlProps {\n icon?: React.FC<{ style: React.CSSProperties }>;\n}\n\nexport function RichTextEditorControlBase({\n className,\n icon: Icon,\n ...others\n}: RichTextEditorControlBaseProps & { icon: React.FC<{ style: React.CSSProperties }> }) {\n const ctx = useRichTextEditorContext();\n\n return (\n <RichTextEditorControl {...others}>\n <Icon {...ctx.getStyles('controlIcon')} />\n </RichTextEditorControl>\n );\n}\n\nRichTextEditorControlBase.displayName = '@mantine/tiptap/RichTextEditorControlBase';\n\nexport interface CreateControlProps {\n label: keyof RichTextEditorLabels;\n icon: React.FC<{ style: React.CSSProperties }>;\n isActive?: { name: string; attributes?: Record<string, any> | string };\n isDisabled?: (editor: any) => boolean;\n operation: { name: string; attributes?: Record<string, any> | string };\n}\n\nexport function createControl({\n label,\n isActive,\n operation,\n icon,\n isDisabled,\n}: CreateControlProps) {\n const Control = (props: RichTextEditorControlBaseProps) => {\n const { editor, labels } = useRichTextEditorContext();\n const _label = labels[label] as string;\n const editorState = useEditorState({\n editor: editor ?? null,\n selector: (ctx) => {\n // `ctx.editor` is `null` on the first render before `useEditor()` produces an\n // instance, and `editor.commandManager` is set to `null` by `editor.destroy()`.\n // Either state would make `isDisabled?.(ctx.editor)` (which typically calls\n // `editor.can()`) throw, taking down the surrounding tree.\n const safeEditor = ctx.editor && !ctx.editor.isDestroyed ? ctx.editor : null;\n return {\n active:\n safeEditor && isActive?.name\n ? safeEditor.isActive(isActive.name, isActive.attributes)\n : false,\n // Without a usable editor the operation cannot run, so the control must\n // appear disabled regardless of whether a user-provided `isDisabled` exists.\n disabled: safeEditor ? (isDisabled?.(safeEditor) ?? false) : true,\n };\n },\n });\n\n const active = editorState?.active ?? false;\n const disabled = editorState?.disabled ?? true;\n\n return (\n <RichTextEditorControlBase\n aria-label={_label}\n title={_label}\n active={active}\n icon={props.icon || icon}\n disabled={disabled}\n {...props}\n onClick={() => {\n // Mirror the selector's guard so a click landing during teardown does not\n // invoke commands on a `null`/destroyed editor.\n if (!editor || editor.isDestroyed) {\n return;\n }\n (editor as any).chain().focus()[operation.name](operation.attributes).run();\n }}\n />\n );\n };\n\n Control.displayName = `@mantine/tiptap/${label}`;\n\n return Control;\n}\n"],"mappings":";;;;;;;AAgCA,MAAM,eAAe,EACnB,aAAa,KACf;AAEA,MAAa,wBAAwB,SAAuC,WAAW;CAErF,MAAM,EACJ,YACA,WACA,OACA,QACA,MACA,aACA,QACA,aACA,UACA,GAAG,WAXS,SAAS,yBAAyB,cAAc,MAYtD;CACR,MAAM,MAAM,yBAAyB;CAErC,OACE,oBAAC,gBAAD;EACE,GAAI;EACJ,GAAI,IAAI,UAAU,WAAW;GAAE;GAAW;GAAO;GAAY;EAAO,CAAC;EAC3D;EACV,iCAAA;EACA,UAAU,cAAc,IAAI;EAC5B,oBAAkB,eAAe,KAAA;EACjC,iBAAe,YAAY,KAAA;EAC3B,eAAa,UAAU,KAAA;EACvB,gBAAe,UAAU,eAAgB,KAAA;EACzC,eAAa,CAAC,eAAe,KAAA;EAC7B,UAAU,IAAI;EACd,SAAS,IAAI,WAAW;EACxB,cAAc,UAAU;GACtB,MAAM,eAAe;GACrB,cAAc,KAAK;EACrB;CACD,CAAA;AAEL,CAAC;AAED,sBAAsB,UAAUA;AAChC,sBAAsB,cAAc;AAMpC,SAAgB,0BAA0B,EACxC,WACA,MAAM,MACN,GAAG,UACmF;CACtF,MAAM,MAAM,yBAAyB;CAErC,OACE,oBAAC,uBAAD;EAAuB,GAAI;YACzB,oBAAC,MAAD,EAAM,GAAI,IAAI,UAAU,aAAa,EAAI,CAAA;CACpB,CAAA;AAE3B;AAEA,0BAA0B,cAAc;AAUxC,SAAgB,cAAc,EAC5B,OACA,UACA,WACA,MACA,cACqB;CACrB,MAAM,WAAW,UAA0C;EACzD,MAAM,EAAE,QAAQ,WAAW,yBAAyB;EACpD,MAAM,SAAS,OAAO;EACtB,MAAM,cAAc,eAAe;GACjC,QAAQ,UAAU;GAClB,WAAW,QAAQ;IAKjB,MAAM,aAAa,IAAI,UAAU,CAAC,IAAI,OAAO,cAAc,IAAI,SAAS;IACxE,OAAO;KACL,QACE,cAAc,UAAU,OACpB,WAAW,SAAS,SAAS,MAAM,SAAS,UAAU,IACtD;KAGN,UAAU,aAAc,aAAa,UAAU,KAAK,QAAS;IAC/D;GACF;EACF,CAAC;EAED,MAAM,SAAS,aAAa,UAAU;EACtC,MAAM,WAAW,aAAa,YAAY;EAE1C,OACE,oBAAC,2BAAD;GACE,cAAY;GACZ,OAAO;GACC;GACR,MAAM,MAAM,QAAQ;GACV;GACV,GAAI;GACJ,eAAe;IAGb,IAAI,CAAC,UAAU,OAAO,aACpB;IAEF,OAAgB,MAAM,EAAE,MAAM,EAAE,UAAU,MAAM,UAAU,UAAU,EAAE,IAAI;GAC5E;EACD,CAAA;CAEL;CAEA,QAAQ,cAAc,mBAAmB;CAEzC,OAAO;AACT"}
|
|
@@ -48,7 +48,7 @@ const RichTextEditorLinkControl = factory((_props) => {
|
|
|
48
48
|
useWindowEvent("edit-link", handleOpen, false);
|
|
49
49
|
const active = useEditorState({
|
|
50
50
|
editor: ctx.editor ?? null,
|
|
51
|
-
selector: (state) => state.editor
|
|
51
|
+
selector: (state) => state.editor && !state.editor.isDestroyed ? state.editor.isActive("link") : false
|
|
52
52
|
});
|
|
53
53
|
const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi({
|
|
54
54
|
classNames,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorLinkControl.mjs","names":["classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorLinkControl.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n Button,\n CompoundStylesApiProps,\n factory,\n Factory,\n Popover,\n PopoverProps,\n rem,\n TextInput,\n Tooltip,\n UnstyledButton,\n useProps,\n useResolvedStylesApi,\n} from '@mantine/core';\nimport { useDisclosure, useInputState, useWindowEvent } from '@mantine/hooks';\nimport { IconExternalLink, IconLink } from '../icons/Icons';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport { RichTextEditorControlBase, RichTextEditorControlBaseProps } from './RichTextEditorControl';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorLinkControlStylesNames =\n | 'control'\n | 'linkEditor'\n | 'linkEditorDropdown'\n | 'linkEditorSave'\n | 'linkEditorInput'\n | 'linkEditorExternalControl';\n\nexport interface RichTextEditorLinkControlProps\n extends\n BoxProps,\n Omit<RichTextEditorControlBaseProps, 'classNames' | 'styles' | 'vars'>,\n CompoundStylesApiProps<RichTextEditorLinkControlFactory> {\n /** Props passed down to Popover component */\n popoverProps?: Partial<PopoverProps>;\n\n /** Determines whether external link control tooltip should be disabled @default false */\n disableTooltips?: boolean;\n\n /** Initial state for determining whether the link should be an external @default false */\n initialExternal?: boolean;\n}\n\nexport type RichTextEditorLinkControlFactory = Factory<{\n props: RichTextEditorLinkControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorLinkControlStylesNames;\n compound: true;\n}>;\n\nconst LinkIcon: RichTextEditorControlBaseProps['icon'] = (props) => <IconLink {...props} />;\n\nexport const RichTextEditorLinkControl = factory<RichTextEditorLinkControlFactory>((_props) => {\n const props = useProps('RichTextEditorLinkControl', null, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n icon,\n popoverProps,\n disableTooltips,\n initialExternal,\n ...others\n } = props;\n\n const ctx = useRichTextEditorContext();\n\n const stylesApiProps = { classNames, styles };\n\n const [url, setUrl] = useInputState('');\n const [external, setExternal] = useState(initialExternal);\n const [opened, { open, close }] = useDisclosure(false);\n\n const handleOpen = () => {\n open();\n const linkData = ctx.editor?.getAttributes('link');\n setUrl(linkData?.href || '');\n setExternal(linkData?.href ? linkData?.target === '_blank' : initialExternal);\n };\n\n const handleClose = () => {\n close();\n setUrl('');\n setExternal(initialExternal);\n };\n\n const setLink = () => {\n handleClose();\n url === ''\n ? ctx.editor?.chain().focus().extendMarkRange('link').unsetLink().run()\n : ctx.editor\n ?.chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href: url, target: external ? '_blank' : null })\n .run();\n };\n\n const handleInputKeydown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n setLink();\n }\n };\n\n useWindowEvent('edit-link', handleOpen, false);\n\n const active = useEditorState({\n editor: ctx.editor ?? null,\n selector: (state)
|
|
1
|
+
{"version":3,"file":"RichTextEditorLinkControl.mjs","names":["classes"],"sources":["../../src/RichTextEditorControl/RichTextEditorLinkControl.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useEditorState } from '@tiptap/react';\nimport {\n BoxProps,\n Button,\n CompoundStylesApiProps,\n factory,\n Factory,\n Popover,\n PopoverProps,\n rem,\n TextInput,\n Tooltip,\n UnstyledButton,\n useProps,\n useResolvedStylesApi,\n} from '@mantine/core';\nimport { useDisclosure, useInputState, useWindowEvent } from '@mantine/hooks';\nimport { IconExternalLink, IconLink } from '../icons/Icons';\nimport { useRichTextEditorContext } from '../RichTextEditor.context';\nimport { RichTextEditorControlBase, RichTextEditorControlBaseProps } from './RichTextEditorControl';\nimport classes from '../RichTextEditor.module.css';\n\nexport type RichTextEditorLinkControlStylesNames =\n | 'control'\n | 'linkEditor'\n | 'linkEditorDropdown'\n | 'linkEditorSave'\n | 'linkEditorInput'\n | 'linkEditorExternalControl';\n\nexport interface RichTextEditorLinkControlProps\n extends\n BoxProps,\n Omit<RichTextEditorControlBaseProps, 'classNames' | 'styles' | 'vars'>,\n CompoundStylesApiProps<RichTextEditorLinkControlFactory> {\n /** Props passed down to Popover component */\n popoverProps?: Partial<PopoverProps>;\n\n /** Determines whether external link control tooltip should be disabled @default false */\n disableTooltips?: boolean;\n\n /** Initial state for determining whether the link should be an external @default false */\n initialExternal?: boolean;\n}\n\nexport type RichTextEditorLinkControlFactory = Factory<{\n props: RichTextEditorLinkControlProps;\n ref: HTMLButtonElement;\n stylesNames: RichTextEditorLinkControlStylesNames;\n compound: true;\n}>;\n\nconst LinkIcon: RichTextEditorControlBaseProps['icon'] = (props) => <IconLink {...props} />;\n\nexport const RichTextEditorLinkControl = factory<RichTextEditorLinkControlFactory>((_props) => {\n const props = useProps('RichTextEditorLinkControl', null, _props);\n const {\n classNames,\n className,\n style,\n styles,\n vars,\n icon,\n popoverProps,\n disableTooltips,\n initialExternal,\n ...others\n } = props;\n\n const ctx = useRichTextEditorContext();\n\n const stylesApiProps = { classNames, styles };\n\n const [url, setUrl] = useInputState('');\n const [external, setExternal] = useState(initialExternal);\n const [opened, { open, close }] = useDisclosure(false);\n\n const handleOpen = () => {\n open();\n const linkData = ctx.editor?.getAttributes('link');\n setUrl(linkData?.href || '');\n setExternal(linkData?.href ? linkData?.target === '_blank' : initialExternal);\n };\n\n const handleClose = () => {\n close();\n setUrl('');\n setExternal(initialExternal);\n };\n\n const setLink = () => {\n handleClose();\n url === ''\n ? ctx.editor?.chain().focus().extendMarkRange('link').unsetLink().run()\n : ctx.editor\n ?.chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href: url, target: external ? '_blank' : null })\n .run();\n };\n\n const handleInputKeydown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n setLink();\n }\n };\n\n useWindowEvent('edit-link', handleOpen, false);\n\n const active = useEditorState({\n editor: ctx.editor ?? null,\n selector: (state) =>\n state.editor && !state.editor.isDestroyed ? state.editor.isActive('link') : false,\n });\n\n const { resolvedClassNames, resolvedStyles } =\n useResolvedStylesApi<RichTextEditorLinkControlFactory>({ classNames, styles, props });\n\n return (\n <Popover\n trapFocus\n shadow=\"md\"\n withinPortal\n opened={opened}\n onChange={(_opened) => !_opened && handleClose()}\n offset={-44}\n zIndex={10000}\n {...popoverProps}\n >\n <Popover.Target>\n <RichTextEditorControlBase\n icon={icon || LinkIcon}\n {...others}\n aria-label={ctx.labels.linkControlLabel}\n title={ctx.labels.linkControlLabel}\n onClick={handleOpen}\n active={active ?? false}\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n className={className}\n style={style}\n variant={ctx.variant}\n />\n </Popover.Target>\n\n <Popover.Dropdown {...ctx.getStyles('linkEditorDropdown', stylesApiProps)}>\n <div {...ctx.getStyles('linkEditor', stylesApiProps)}>\n <TextInput\n placeholder={ctx.labels.linkEditorInputPlaceholder}\n aria-label={ctx.labels.linkEditorInputLabel}\n type=\"url\"\n value={url}\n onChange={setUrl}\n classNames={{ input: ctx.getStyles('linkEditorInput', stylesApiProps).className }}\n onKeyDown={handleInputKeydown}\n rightSection={\n <Tooltip\n label={\n external ? ctx.labels.linkEditorExternalLink : ctx.labels.linkEditorInternalLink\n }\n events={{ hover: true, focus: true, touch: true }}\n withinPortal\n withArrow\n disabled={disableTooltips}\n zIndex={10000}\n >\n <UnstyledButton\n onClick={() => setExternal((e) => !e)}\n data-active={external || undefined}\n {...ctx.getStyles('linkEditorExternalControl', stylesApiProps)}\n >\n <IconExternalLink style={{ width: rem(14), height: rem(14) }} />\n </UnstyledButton>\n </Tooltip>\n }\n />\n\n <Button\n variant=\"default\"\n onClick={setLink}\n {...ctx.getStyles('linkEditorSave', stylesApiProps)}\n >\n {ctx.labels.linkEditorSave}\n </Button>\n </div>\n </Popover.Dropdown>\n </Popover>\n );\n});\n\nRichTextEditorLinkControl.classes = classes;\nRichTextEditorLinkControl.displayName = '@mantine/tiptap/RichTextEditorLinkControl';\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mantine/tiptap",
|
|
3
|
-
"version": "9.2.
|
|
3
|
+
"version": "9.2.2",
|
|
4
4
|
"description": "Rich text editor based on tiptap",
|
|
5
5
|
"homepage": "https://mantine.dev/x/tiptap",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"directory": "packages/@mantine/tiptap"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@mantine/core": "9.2.
|
|
48
|
-
"@mantine/hooks": "9.2.
|
|
47
|
+
"@mantine/core": "9.2.2",
|
|
48
|
+
"@mantine/hooks": "9.2.2",
|
|
49
49
|
"@tiptap/extension-link": ">=3.3.0",
|
|
50
50
|
"@tiptap/react": ">=3.3.0",
|
|
51
51
|
"react": "^19.2.0",
|