UNPKG

@mantine/tiptap

Version:

Rich text editor based on tiptap

1 lines 6.87 kB
{"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"}