@seorii/tiptap 0.0.1

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.
Files changed (37) hide show
  1. package/README.md +38 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +4 -0
  4. package/dist/plugin/iframe.d.ts +18 -0
  5. package/dist/plugin/iframe.js +43 -0
  6. package/dist/plugin/indent.d.ts +20 -0
  7. package/dist/plugin/indent.js +116 -0
  8. package/dist/plugin/orderedlist/index.d.ts +3 -0
  9. package/dist/plugin/orderedlist/index.js +81 -0
  10. package/dist/plugin/orderedlist/korean.scss +22 -0
  11. package/dist/plugin/orderedlist/toggleList.d.ts +2 -0
  12. package/dist/plugin/orderedlist/toggleList.js +67 -0
  13. package/dist/plugin/table/deleteTable.d.ts +3 -0
  14. package/dist/plugin/table/deleteTable.js +24 -0
  15. package/dist/plugin/table/index.d.ts +3 -0
  16. package/dist/plugin/table/index.js +69 -0
  17. package/dist/plugin/table/style/cell.scss +16 -0
  18. package/dist/plugin/table/style/grip.scss +72 -0
  19. package/dist/plugin/table/style/resize.scss +28 -0
  20. package/dist/plugin/table/style/table.scss +83 -0
  21. package/dist/plugin/table/style/theme.scss +6 -0
  22. package/dist/plugin/table/style.scss +5 -0
  23. package/dist/plugin/table/tableCell/index.d.ts +2 -0
  24. package/dist/plugin/table/tableCell/index.js +80 -0
  25. package/dist/plugin/table/tableHeader/index.d.ts +2 -0
  26. package/dist/plugin/table/tableHeader/index.js +59 -0
  27. package/dist/plugin/table/tableRow/index.d.ts +2 -0
  28. package/dist/plugin/table/tableRow/index.js +4 -0
  29. package/dist/plugin/table/util.d.ts +46 -0
  30. package/dist/plugin/table/util.js +195 -0
  31. package/dist/tiptap/TipTap.svelte +144 -0
  32. package/dist/tiptap/TipTap.svelte.d.ts +19 -0
  33. package/dist/tiptap/index.d.ts +2 -0
  34. package/dist/tiptap/index.js +3 -0
  35. package/dist/tiptap/tiptap.d.ts +3 -0
  36. package/dist/tiptap/tiptap.js +56 -0
  37. package/package.json +83 -0
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # create-svelte
2
+
3
+ Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
4
+
5
+ ## Creating a project
6
+
7
+ If you're seeing this, you've probably already done this step. Congrats!
8
+
9
+ ```bash
10
+ # create a new project in the current directory
11
+ npm create svelte@latest
12
+
13
+ # create a new project in my-app
14
+ npm create svelte@latest my-app
15
+ ```
16
+
17
+ ## Developing
18
+
19
+ Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
+
21
+ ```bash
22
+ npm run dev
23
+
24
+ # or start the server and open the app in a new browser tab
25
+ npm run dev -- --open
26
+ ```
27
+
28
+ ## Building
29
+
30
+ To create a production version of your app:
31
+
32
+ ```bash
33
+ npm run build
34
+ ```
35
+
36
+ You can preview the production build with `npm run preview`.
37
+
38
+ > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
@@ -0,0 +1,2 @@
1
+ export default TipTap;
2
+ import TipTap from "./tiptap";
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // Reexport your entry components here
2
+ import TipTap from "./tiptap";
3
+
4
+ export default TipTap;
@@ -0,0 +1,18 @@
1
+ import { Node } from '@tiptap/core';
2
+ export interface IframeOptions {
3
+ allowFullscreen: boolean;
4
+ HTMLAttributes: {
5
+ [key: string]: any;
6
+ };
7
+ }
8
+ declare module '@tiptap/core' {
9
+ interface Commands<ReturnType> {
10
+ iframe: {
11
+ setIframe: (options: {
12
+ src: string;
13
+ }) => ReturnType;
14
+ };
15
+ }
16
+ }
17
+ declare const _default: Node<IframeOptions, any>;
18
+ export default _default;
@@ -0,0 +1,43 @@
1
+ import { mergeAttributes, Node } from '@tiptap/core';
2
+ export default Node.create({
3
+ name: 'iframe',
4
+ group: 'block',
5
+ atom: true,
6
+ addOptions() {
7
+ return {
8
+ allowFullscreen: true,
9
+ HTMLAttributes: {
10
+ class: 'iframe-wrapper',
11
+ },
12
+ };
13
+ },
14
+ addAttributes() {
15
+ return {
16
+ src: { default: null },
17
+ frameborder: { default: 0 },
18
+ allowfullscreen: {
19
+ default: this.options.allowFullscreen,
20
+ parseHTML: () => this.options.allowFullscreen,
21
+ },
22
+ };
23
+ },
24
+ parseHTML() {
25
+ return [{
26
+ tag: 'iframe',
27
+ }];
28
+ },
29
+ renderHTML({ HTMLAttributes }) {
30
+ return ['div', this.options.HTMLAttributes, ['iframe', mergeAttributes(HTMLAttributes, { credentialless: true })]];
31
+ },
32
+ addCommands() {
33
+ return {
34
+ setIframe: (options) => ({ tr, dispatch }) => {
35
+ const { selection } = tr;
36
+ const node = this.type.create(options);
37
+ if (dispatch)
38
+ tr.replaceRangeWith(selection.from, selection.to, node);
39
+ return true;
40
+ },
41
+ };
42
+ },
43
+ });
@@ -0,0 +1,20 @@
1
+ import { Extension } from '@tiptap/core';
2
+ declare module '@tiptap/core' {
3
+ interface Commands<ReturnType> {
4
+ indent: {
5
+ indent: () => ReturnType;
6
+ outdent: () => ReturnType;
7
+ };
8
+ }
9
+ }
10
+ type IndentOptions = {
11
+ names: Array<string>;
12
+ indentRange: number;
13
+ minIndentLevel: number;
14
+ maxIndentLevel: number;
15
+ defaultIndentLevel: number;
16
+ HTMLAttributes: Record<string, any>;
17
+ };
18
+ export declare const Indent: Extension<IndentOptions, never>;
19
+ export declare const clamp: (val: number, min: number, max: number) => number;
20
+ export {};
@@ -0,0 +1,116 @@
1
+ /* eslint-disable no-param-reassign */
2
+ // Sources:
3
+ // https://github.com/ueberdosis/tiptap/issues/1036#issuecomment-981094752
4
+ // https://github.com/django-tiptap/django_tiptap/blob/main/django_tiptap/templates/forms/tiptap_textarea.html#L453-L602
5
+ import { Extension, isList, } from '@tiptap/core';
6
+ import { TextSelection, Transaction } from 'prosemirror-state';
7
+ export const Indent = Extension.create({
8
+ name: 'indent',
9
+ addOptions() {
10
+ return {
11
+ names: ['heading', 'paragraph'],
12
+ indentRange: 24,
13
+ minIndentLevel: 0,
14
+ maxIndentLevel: 24 * 10,
15
+ defaultIndentLevel: 0,
16
+ HTMLAttributes: {},
17
+ };
18
+ },
19
+ addGlobalAttributes() {
20
+ return [
21
+ {
22
+ types: this.options.names,
23
+ attributes: {
24
+ indent: {
25
+ default: this.options.defaultIndentLevel,
26
+ renderHTML: (attributes) => ({
27
+ style: `margin-left: ${attributes.indent}px!important;`,
28
+ }),
29
+ parseHTML: (element) => parseInt(element.style.marginLeft, 10) ||
30
+ this.options.defaultIndentLevel,
31
+ },
32
+ },
33
+ },
34
+ ];
35
+ },
36
+ addCommands() {
37
+ return {
38
+ indent: () => ({ tr, state, dispatch, editor }) => {
39
+ const { selection } = state;
40
+ tr = tr.setSelection(selection);
41
+ tr = updateIndentLevel(tr, this.options, editor.extensionManager.extensions, 'indent');
42
+ if (tr.docChanged && dispatch) {
43
+ dispatch(tr);
44
+ return true;
45
+ }
46
+ editor.chain().focus().run();
47
+ return false;
48
+ },
49
+ outdent: () => ({ tr, state, dispatch, editor }) => {
50
+ const { selection } = state;
51
+ tr = tr.setSelection(selection);
52
+ tr = updateIndentLevel(tr, this.options, editor.extensionManager.extensions, 'outdent');
53
+ if (tr.docChanged && dispatch) {
54
+ dispatch(tr);
55
+ return true;
56
+ }
57
+ editor.chain().focus().run();
58
+ return false;
59
+ },
60
+ };
61
+ },
62
+ addKeyboardShortcuts() {
63
+ return {
64
+ Tab: indent(),
65
+ 'Shift-Tab': outdent(false),
66
+ Backspace: outdent(true),
67
+ 'Mod-]': indent(),
68
+ 'Mod-[': outdent(false),
69
+ };
70
+ },
71
+ });
72
+ export const clamp = (val, min, max) => {
73
+ if (val < min)
74
+ return min;
75
+ if (val > max)
76
+ return max;
77
+ return val;
78
+ };
79
+ function setNodeIndentMarkup(tr, pos, delta, min, max) {
80
+ if (!tr.doc)
81
+ return tr;
82
+ const node = tr.doc.nodeAt(pos);
83
+ if (!node)
84
+ return tr;
85
+ const indent = clamp((node.attrs.indent || 0) + delta, min, max);
86
+ if (indent === node.attrs.indent)
87
+ return tr;
88
+ const nodeAttrs = { ...node.attrs, indent };
89
+ return tr.setNodeMarkup(pos, node.type, nodeAttrs, node.marks);
90
+ }
91
+ const updateIndentLevel = (tr, options, extensions, type) => {
92
+ const { doc, selection } = tr;
93
+ if (!doc || !selection)
94
+ return tr;
95
+ if (!(selection instanceof TextSelection))
96
+ return tr;
97
+ const { from, to } = selection;
98
+ doc.nodesBetween(from, to, (node, pos) => {
99
+ if (options.names.includes(node.type.name)) {
100
+ tr = setNodeIndentMarkup(tr, pos, options.indentRange * (type === 'indent' ? 1 : -1), options.minIndentLevel, options.maxIndentLevel);
101
+ return false;
102
+ }
103
+ return !isList(node.type.name, extensions);
104
+ });
105
+ return tr;
106
+ };
107
+ const indent = () => ({ editor }) => {
108
+ if (!isList(editor.state.doc.type.name, editor.extensionManager.extensions))
109
+ return editor.commands.indent();
110
+ return false;
111
+ };
112
+ const outdent = (outdentOnlyAtHead) => ({ editor }) => {
113
+ if (!(isList(editor.state.doc.type.name, editor.extensionManager.extensions) || (outdentOnlyAtHead && editor.state.selection.$head.parentOffset !== 0)))
114
+ return editor.commands.outdent();
115
+ return false;
116
+ };
@@ -0,0 +1,3 @@
1
+ import './korean.scss';
2
+ declare const _default: import("@tiptap/core").Node<import("@tiptap/extension-ordered-list").OrderedListOptions, any>;
3
+ export default _default;
@@ -0,0 +1,81 @@
1
+ import { wrappingInputRule } from "@tiptap/core";
2
+ import OrderedListBase from '@tiptap/extension-ordered-list';
3
+ import toggleList from "./toggleList";
4
+ import './korean.scss';
5
+ export default OrderedListBase.extend({
6
+ priority: 20,
7
+ addAttributes() {
8
+ return {
9
+ start: {
10
+ default: 1,
11
+ parseHTML: (element) => {
12
+ return element.hasAttribute('start')
13
+ ? parseInt(element.getAttribute('start') || '', 10)
14
+ : 1;
15
+ },
16
+ },
17
+ type: {
18
+ default: '1',
19
+ }
20
+ };
21
+ },
22
+ addInputRules() {
23
+ return [
24
+ wrappingInputRule({
25
+ find: /^(\d+)\.\s$/,
26
+ type: this.type,
27
+ getAttributes: match => ({ start: +match[1], type: '1' }),
28
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
29
+ }),
30
+ wrappingInputRule({
31
+ find: /^([i])\.\s$/,
32
+ type: this.type,
33
+ getAttributes: match => ({ start: 1, type: 'i' }),
34
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
35
+ }),
36
+ wrappingInputRule({
37
+ find: /^([I])\.\s$/,
38
+ type: this.type,
39
+ getAttributes: match => ({ start: 1, type: 'I' }),
40
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
41
+ }),
42
+ wrappingInputRule({
43
+ find: /^([A-Z])\.\s$/,
44
+ type: this.type,
45
+ getAttributes: match => ({ start: match[1].charCodeAt(0) - 64, type: 'A' }),
46
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
47
+ }),
48
+ wrappingInputRule({
49
+ find: /^([a-z])\.\s$/,
50
+ type: this.type,
51
+ getAttributes: match => ({ start: match[1].charCodeAt(0) - 96, type: 'a' }),
52
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
53
+ }),
54
+ wrappingInputRule({
55
+ find: /^([ㄱ-ㅎ])\.\s$/,
56
+ type: this.type,
57
+ getAttributes: match => ({
58
+ start: 1 + ['ㄱ', 'ㄴ', 'ㄷ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅅ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'].indexOf(match[1]),
59
+ type: 'kors'
60
+ }),
61
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
62
+ }),
63
+ wrappingInputRule({
64
+ find: /^([가-하])\.\s$/,
65
+ type: this.type,
66
+ getAttributes: match => ({
67
+ start: 1 + ['가', '나', '다', '라', '마', '바', '사', '아', '자', '차', '카', '타', '파', '하'].indexOf(match[1]),
68
+ type: 'korc'
69
+ }),
70
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
71
+ }),
72
+ ];
73
+ },
74
+ addCommands() {
75
+ return {
76
+ toggleOrderedList: (option) => (context) => {
77
+ return toggleList(this.name, this.options.itemTypeName, option)(context);
78
+ },
79
+ };
80
+ },
81
+ });
@@ -0,0 +1,22 @@
1
+ @counter-style kors {
2
+ system: cyclic;
3
+ symbols: "ㄱ." "ㄴ." "ㄷ." "ㄹ." "ㅁ." "ㅂ." "ㅅ." "ㅇ." "ㅈ." "ㅊ." "ㅋ." "ㅌ." "ㅍ." "ㅎ.";
4
+ suffix: " ";
5
+ }
6
+
7
+ @counter-style korc {
8
+ system: cyclic;
9
+ symbols: "가." "나." "다." "라." "마." "바." "사." "아." "자." "차." "카." "타." "파." "하.";
10
+ suffix: " ";
11
+ }
12
+
13
+ .ProseMirror {
14
+ ol[type="kors"] {
15
+ list-style-type: kors;
16
+ }
17
+
18
+ ol[type="korc"] {
19
+ list-style-type: korc;
20
+ }
21
+ }
22
+
@@ -0,0 +1,2 @@
1
+ declare const _default: (listTypeOrName: string, itemTypeOrName: string, attrs: any) => ({ editor, tr, state, dispatch, chain, commands, can }: any) => any;
2
+ export default _default;
@@ -0,0 +1,67 @@
1
+ import { canJoin } from 'prosemirror-transform';
2
+ import { getNodeType, findParentNode, isList } from "@tiptap/core";
3
+ const joinListBackwards = (tr, listType) => {
4
+ const list = findParentNode(node => node.type === listType)(tr.selection);
5
+ if (!list)
6
+ return true;
7
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
8
+ if (before === undefined)
9
+ return true;
10
+ const nodeBefore = tr.doc.nodeAt(before);
11
+ const canJoinBackwards = list.node.type === nodeBefore?.type && canJoin(tr.doc, list.pos);
12
+ if (!canJoinBackwards)
13
+ return true;
14
+ tr.join(list.pos);
15
+ return true;
16
+ };
17
+ const joinListForwards = (tr, listType) => {
18
+ const list = findParentNode(node => node.type === listType)(tr.selection);
19
+ if (!list)
20
+ return true;
21
+ const after = tr.doc.resolve(list.start).after(list.depth);
22
+ if (after === undefined)
23
+ return true;
24
+ const nodeAfter = tr.doc.nodeAt(after);
25
+ const canJoinForwards = list.node.type === nodeAfter?.type && canJoin(tr.doc, after);
26
+ if (!canJoinForwards)
27
+ return true;
28
+ tr.join(after);
29
+ return true;
30
+ };
31
+ export default (listTypeOrName, itemTypeOrName, attrs) => ({ editor, tr, state, dispatch, chain, commands, can }) => {
32
+ const { extensions } = editor.extensionManager;
33
+ const listType = getNodeType(listTypeOrName, state.schema);
34
+ const itemType = getNodeType(itemTypeOrName, state.schema);
35
+ const { selection } = state;
36
+ const { $from, $to } = selection;
37
+ const range = $from.blockRange($to);
38
+ if (!range)
39
+ return false;
40
+ const parentList = findParentNode(node => isList(node.type.name, extensions))(selection);
41
+ if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
42
+ if (parentList.node.type === listType && parentList?.node?.attrs?.type === attrs?.type)
43
+ return commands.liftListItem(itemType);
44
+ if (isList(parentList.node.type.name, extensions)
45
+ && listType.validContent(parentList.node.content)
46
+ && dispatch)
47
+ return chain()
48
+ .command(() => {
49
+ tr.setNodeMarkup(parentList.pos, listType, attrs);
50
+ return true;
51
+ })
52
+ .command(() => joinListBackwards(tr, listType))
53
+ .command(() => joinListForwards(tr, listType))
54
+ .run();
55
+ }
56
+ return chain()
57
+ .command(() => {
58
+ const canWrapInList = can().wrapInList(listType, attrs);
59
+ if (canWrapInList)
60
+ return true;
61
+ return commands.clearNodes();
62
+ })
63
+ .wrapInList(listType, attrs)
64
+ .command(() => joinListBackwards(tr, listType))
65
+ .command(() => joinListForwards(tr, listType))
66
+ .run();
67
+ };
@@ -0,0 +1,3 @@
1
+ import type { KeyboardShortcutCommand } from "@tiptap/core";
2
+ export declare const deleteTable: KeyboardShortcutCommand;
3
+ export default deleteTable;
@@ -0,0 +1,24 @@
1
+ import { isColumnSelected, isTableSelected } from "./util";
2
+ import { TableMap } from "prosemirror-tables";
3
+ export const deleteTable = ({ editor }) => {
4
+ const { selection } = editor.state;
5
+ if (!selection || !selection.$anchorCell)
6
+ return false;
7
+ if (isTableSelected(selection))
8
+ return editor.commands.deleteTable();
9
+ const { height, width } = TableMap.get(selection.$anchorCell.node(-1));
10
+ for (let i = width - 1; i >= 0; i--) {
11
+ if (isColumnSelected(i)(selection)) {
12
+ editor.commands.deleteColumn();
13
+ return true;
14
+ }
15
+ }
16
+ for (let i = height - 1; i >= 0; i--) {
17
+ if (isColumnSelected(i)(selection)) {
18
+ editor.commands.deleteRow();
19
+ return true;
20
+ }
21
+ }
22
+ return false;
23
+ };
24
+ export default deleteTable;
@@ -0,0 +1,3 @@
1
+ import './style.scss';
2
+ declare const _default: import("@tiptap/core").Node<import("@tiptap/extension-table").TableOptions, any>;
3
+ export default _default;
@@ -0,0 +1,69 @@
1
+ import BuiltInTable from '@tiptap/extension-table';
2
+ import { Plugin } from 'prosemirror-state';
3
+ import { tableEditing, columnResizing } from 'prosemirror-tables';
4
+ import { Decoration, DecorationSet } from 'prosemirror-view';
5
+ import deleteTable from './deleteTable';
6
+ import './style.scss';
7
+ export default BuiltInTable.extend({
8
+ renderHTML() {
9
+ return [
10
+ 'div',
11
+ { class: 'node-table' },
12
+ ['div', { class: `scrollable` }, ['table', { class: `as-table render-wrapper` }, ['tbody', 0]]],
13
+ ];
14
+ },
15
+ addProseMirrorPlugins() {
16
+ const { isEditable } = this.editor;
17
+ return [
18
+ tableEditing(),
19
+ columnResizing({}),
20
+ new Plugin({
21
+ props: {
22
+ decorations: (state) => {
23
+ const { doc } = state;
24
+ const decorations = [];
25
+ let index = 0;
26
+ doc.descendants((node, pos) => {
27
+ if (node.type.name !== this.name)
28
+ return;
29
+ const elements = document.getElementsByClassName('as-table');
30
+ const table = elements[index];
31
+ if (!table)
32
+ return;
33
+ if (!isEditable)
34
+ table.classList.add('is-readonly');
35
+ const element = table.parentElement;
36
+ const shadowRight = !!(element && element.scrollWidth > element.clientWidth);
37
+ if (shadowRight)
38
+ decorations.push(Decoration.widget(pos + 1, () => {
39
+ const shadow = document.createElement('div');
40
+ shadow.className = `scrollable-shadow right ${isEditable ? 'is-editable' : ''}`;
41
+ return shadow;
42
+ }));
43
+ index++;
44
+ });
45
+ return DecorationSet.create(doc, decorations);
46
+ },
47
+ },
48
+ }),
49
+ ];
50
+ },
51
+ addKeyboardShortcuts() {
52
+ return {
53
+ Tab: () => {
54
+ if (this.editor.commands.goToNextCell()) {
55
+ return true;
56
+ }
57
+ if (!this.editor.can().addRowAfter()) {
58
+ return false;
59
+ }
60
+ return this.editor.chain().addRowAfter().goToNextCell().run();
61
+ },
62
+ 'Shift-Tab': () => this.editor.commands.goToPreviousCell(),
63
+ Backspace: deleteTable,
64
+ 'Mod-Backspace': deleteTable,
65
+ Delete: deleteTable,
66
+ 'Mod-Delete': deleteTable,
67
+ };
68
+ },
69
+ }).configure({ resizable: true, lastColumnResizable: false });
@@ -0,0 +1,16 @@
1
+ .ProseMirror table {
2
+ td, th {
3
+ position: relative;
4
+ min-width: 100px;
5
+ padding: 4px 8px;
6
+ text-align: left;
7
+ vertical-align: center;
8
+ border: 1px solid var(--primary-light3) !important;
9
+ transition: all 0.1s ease-in-out;
10
+ font-weight: normal;
11
+
12
+ > * {
13
+ margin-bottom: 0;
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,72 @@
1
+ $grip-margin: 3px;
2
+
3
+ .ProseMirror table {
4
+ .grip-column {
5
+ position: absolute;
6
+ top: -0.7em;
7
+ left: 0;
8
+ z-index: 10;
9
+ display: block;
10
+ width: calc(100% - 2 * #{$grip-margin});
11
+ height: 0.4em;
12
+ margin: 0 $grip-margin 3px $grip-margin;
13
+ background: var(--primary-light3);
14
+ opacity: 0;
15
+ border-radius: 10px;
16
+
17
+ transition: all 0.1s ease-in-out;
18
+
19
+ &:hover,
20
+ &.selected {
21
+ background: var(--primary-light6);
22
+ }
23
+ }
24
+
25
+ .grip-row {
26
+ position: absolute;
27
+ top: 0;
28
+ left: -0.7em;
29
+ z-index: 10;
30
+ display: block;
31
+ width: 0.4em;
32
+ height: calc(100% - 2 * #{$grip-margin});
33
+ margin: $grip-margin 3px $grip-margin 0;
34
+ background: var(--primary-light3);
35
+ opacity: 0;
36
+ border-radius: 10px;
37
+
38
+ transition: all 0.1s ease-in-out;
39
+
40
+ &:hover,
41
+ &.selected {
42
+ background: var(--primary-light6);
43
+ }
44
+ }
45
+
46
+ .grip-table {
47
+ position: absolute;
48
+ top: -0.8em;
49
+ left: -0.8em;
50
+ z-index: 10;
51
+ display: block;
52
+ width: 0.6em;
53
+ height: 0.6em;
54
+ background: var(--primary-light3);
55
+ border-radius: 50%;
56
+ opacity: 0;
57
+
58
+ transition: all 0.1s ease-in-out;
59
+
60
+ &:hover,
61
+ &.selected {
62
+ background: var(--primary-light6);
63
+ }
64
+ }
65
+
66
+ .editor & {
67
+ .grip-column, .grip-row, .grip-table {
68
+ opacity: 1;
69
+ cursor: pointer;
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,28 @@
1
+ .ProseMirror {
2
+ table .column-resize-handle {
3
+ position: absolute;
4
+ top: 0;
5
+ right: -2px;
6
+ bottom: -2px;
7
+ width: 4px;
8
+ pointer-events: none;
9
+ background-color: var(--primary-light6);
10
+ opacity: 0;
11
+
12
+ .editor & {
13
+ opacity: 1;
14
+ }
15
+ }
16
+
17
+ &.resize-cursor {
18
+ pointer-events: none;
19
+
20
+ .editor & {
21
+ pointer-events: initial;
22
+ cursor: ew-resize;
23
+ cursor: col-resize; /* stylelint-disable declaration-block-no-duplicate-properties */
24
+ }
25
+ }
26
+ }
27
+
28
+