remirror/remirror

View on GitHub
packages/storybook-react/stories/react-editors/checkbox-extension.ts

Summary

Maintainability
A
0 mins
Test Coverage
F
0%
import {
  ApplySchemaAttributes,
  extension,
  ExtensionTag,
  InputRule,
  NodeExtension,
  NodeExtensionSpec,
  NodeSpecOverride,
  ProsemirrorAttributes,
} from 'remirror';
import { textblockTypeInputRule } from '@remirror/pm/inputrules';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface CheckboxOptions {}

// eslint-disable-next-line @typescript-eslint/ban-types
export type CheckboxExtensionAttributes = ProsemirrorAttributes<{
  checked?: boolean;
}>;

@extension<CheckboxOptions>({
  defaultOptions: {},
})
export class CheckboxExtension extends NodeExtension<CheckboxOptions> {
  get name() {
    return 'checkbox' as const;
  }

  createTags() {
    return [ExtensionTag.Block, ExtensionTag.TextBlock, ExtensionTag.FormattingNode];
  }

  createNodeSpec(extra: ApplySchemaAttributes, override: NodeSpecOverride): NodeExtensionSpec {
    return {
      content: 'inline*',
      defining: true,
      draggable: false,
      ...override,
      attrs: {
        ...extra.defaults(),
        checked: { default: false },
      },
      parseDOM: [
        {
          tag: 'input[type=checkbox]',
          getAttrs: (dom) => ({
            ...extra.parse(dom),
            checked: (dom as HTMLInputElement).checked,
          }),
        },
        ...(override.parseDOM ?? []),
      ],
      toDOM: (mark) => [
        'label',
        extra.dom(mark),
        [
          'input',
          {
            type: 'checkbox',
            checked: mark.attrs.checked,
          },
          0,
        ],
      ],
    };
  }

  createInputRules(): InputRule[] {
    return [
      textblockTypeInputRule(/^\s*\[]\s$/, this.type, { checked: false }),
      textblockTypeInputRule(/^\s*\[x]\s$/, this.type, { checked: true }),
    ];
  }
}