@crystallize/design-system 1.12.0 → 1.13.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/CHANGELOG.md +19 -0
- package/dist/draggable-block-menu-KKHDNKJA.svg +1 -0
- package/dist/index.css +565 -1025
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3295 -3431
- package/dist/index.mjs +3199 -3335
- package/package.json +6 -7
- package/src/button/Button.stories.tsx +1 -0
- package/src/card/card.stories.tsx +1 -0
- package/src/checkbox/checkbox.stories.tsx +1 -1
- package/src/checkbox/checkbox.tsx +1 -1
- package/src/colors/Colors.stories.tsx +3 -3
- package/src/dialog/config.tsx +1 -1
- package/src/dialog/index.tsx +1 -1
- package/src/dropdown-menu/dropdown-menu-item.tsx +2 -2
- package/src/dropdown-menu/dropdown-menu-label.tsx +1 -1
- package/src/icon-button/IconButton.stories.tsx +1 -0
- package/src/iconography/Icon.stories.tsx +1 -0
- package/src/inline-radio/inline-radio.stories.tsx +3 -3
- package/src/inline-radio/inline-radio.tsx +2 -2
- package/src/input/input.tsx +1 -1
- package/src/input-with-label/input-with-label.tsx +1 -1
- package/src/label/label.stories.tsx +1 -0
- package/src/progress/Progress.stories.tsx +2 -1
- package/src/progress/progress.tsx +1 -1
- package/src/radio/radio.stories.tsx +1 -1
- package/src/radio/radio.tsx +1 -1
- package/src/rich-text-editor/i18n/translations/en.ts +2 -2
- package/src/rich-text-editor/plugins/ActionsPlugin/index.css +3 -0
- package/src/rich-text-editor/plugins/ActionsPlugin/index.tsx +1 -2
- package/src/rich-text-editor/plugins/AutoLinkPlugin/index.tsx +1 -1
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/components/CopyButton/index.tsx +6 -2
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/components/PrettierButton/index.tsx +10 -6
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/index.css +32 -17
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/index.tsx +3 -4
- package/src/rich-text-editor/plugins/DimensionsDetectorPlugin/index.tsx +49 -0
- package/src/rich-text-editor/plugins/DraggableBlockPlugin/index.css +14 -14
- package/src/rich-text-editor/plugins/DraggableBlockPlugin/index.tsx +4 -4
- package/src/rich-text-editor/plugins/FloatingLinkEditorPlugin/index.css +87 -21
- package/src/rich-text-editor/plugins/FloatingLinkEditorPlugin/index.tsx +11 -17
- package/src/rich-text-editor/plugins/FloatingTextFormatToolbarPlugin/index.css +10 -2
- package/src/rich-text-editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx +17 -17
- package/src/rich-text-editor/plugins/LinkPlugin/index.tsx +1 -1
- package/src/rich-text-editor/plugins/ListMaxIndentLevelPlugin/index.ts +10 -21
- package/src/rich-text-editor/plugins/TableActionMenuPlugin/index.css +6 -0
- package/src/rich-text-editor/plugins/TableActionMenuPlugin/index.tsx +2 -2
- package/src/rich-text-editor/plugins/ToolbarPlugin/index.css +115 -0
- package/src/rich-text-editor/plugins/ToolbarPlugin/index.tsx +57 -78
- package/src/rich-text-editor/plugins/ToolbarPlugin/insert-table.tsx +5 -5
- package/src/rich-text-editor/rich-text-editor-icons.css +213 -0
- package/src/rich-text-editor/rich-text-editor.css +33 -913
- package/src/rich-text-editor/rich-text-editor.stories.tsx +11 -0
- package/src/rich-text-editor/rich-text-editor.tsx +13 -27
- package/src/rich-text-editor/themes/CrystallizeRTEditorTheme.ts +1 -1
- package/src/rich-text-editor/ui/LinkPreview.tsx +7 -8
- package/src/rich-text-editor/utils/getSelectedNode.ts +4 -5
- package/src/rich-text-editor/utils/point.ts +4 -7
- package/src/rich-text-editor/utils/rect.ts +18 -41
- package/src/rich-text-editor/utils/url.ts +1 -2
- package/src/select/select-root.tsx +1 -1
- package/src/select/select.stories.tsx +1 -1
- package/src/select/select.ts +0 -1
- package/src/slider/Slider.stories.tsx +2 -1
- package/src/slider/slider.tsx +2 -2
- package/src/spinner/Spinner.stories.tsx +1 -0
- package/src/spinner/index.tsx +1 -1
- package/src/tag/Tag.stories.tsx +1 -0
- package/dist/camera-CR7D2PNH.svg +0 -1
- package/dist/clipboard-OSEFDF25.svg +0 -1
- package/dist/gear-ICMT4NTP.svg +0 -1
- package/dist/journal-code-XUT44HDV.svg +0 -1
- package/dist/lock-WCYOZOHW.svg +0 -1
- package/dist/lock-fill-JZSKOSHK.svg +0 -1
- package/dist/pencil-fill-STFSC26F.svg +0 -1
- package/dist/plug-HGGGEVS3.svg +0 -1
- package/dist/plug-fill-OTG3U4TN.svg +0 -1
- package/src/rich-text-editor/hooks/useReport.ts +0 -64
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/components/PrettierButton/index.css +0 -14
- package/src/rich-text-editor/ui/LinkPreview.css +0 -57
- package/src/rich-text-editor/utils/isMobileWidth.ts +0 -7
- package/src/rich-text-editor/utils/joinClasses.ts +0 -13
- package/src/rich-text-editor/utils/swipe.ts +0 -127
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crystallize/design-system",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.2",
|
|
4
4
|
"types": "./dist/index.d.ts",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -70,15 +70,14 @@
|
|
|
70
70
|
"@storybook/addons": "^6.5.15",
|
|
71
71
|
"@storybook/react": "7.0.7",
|
|
72
72
|
"@storybook/react-vite": "7.0.7",
|
|
73
|
-
"@storybook/testing-library": "^0.0.13",
|
|
74
73
|
"@storybook/theming": "7.0.7",
|
|
75
|
-
"@testing-library/jest-dom": "
|
|
76
|
-
"@testing-library/react": "
|
|
77
|
-
"@testing-library/user-event": "
|
|
74
|
+
"@testing-library/jest-dom": "5.16.4",
|
|
75
|
+
"@testing-library/react": "12.0.0",
|
|
76
|
+
"@testing-library/user-event": "14.4.3",
|
|
78
77
|
"@types/prettier": "2.7.2",
|
|
79
78
|
"@types/react": "17.0.1",
|
|
80
79
|
"@types/react-dom": "17.0.1",
|
|
81
|
-
"@types/testing-library__jest-dom": "
|
|
80
|
+
"@types/testing-library__jest-dom": "5.14.5",
|
|
82
81
|
"@vitejs/plugin-react": "^3.0.1",
|
|
83
82
|
"concurrently": "^7.6.0",
|
|
84
83
|
"hex-rgb": "4.3.0",
|
|
@@ -88,7 +87,7 @@
|
|
|
88
87
|
"storybook-dark-mode": "^2.0.5",
|
|
89
88
|
"tailwindcss": "^3.3.0",
|
|
90
89
|
"tsup": "^6.5.0",
|
|
91
|
-
"typescript": "
|
|
90
|
+
"typescript": "4.9.4",
|
|
92
91
|
"vite": "4.3.4",
|
|
93
92
|
"vitest": "0.30.1",
|
|
94
93
|
"tsconfig": "0.0.0"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
1
|
import { cx } from 'class-variance-authority';
|
|
3
2
|
import { useDarkMode } from 'storybook-dark-mode';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
4
|
|
|
5
|
-
import rawColors from './colors.json';
|
|
6
|
-
import colorPairing from './color-pairing.json';
|
|
7
5
|
import colorDefaults from './color-defaults.json';
|
|
6
|
+
import colorPairing from './color-pairing.json';
|
|
7
|
+
import rawColors from './colors.json';
|
|
8
8
|
import type { Color, ColorName, Colors } from './types';
|
|
9
9
|
|
|
10
10
|
const meta: Meta = {
|
package/src/dialog/config.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { unmountComponentAtNode, render as DOMRender } from 'react-dom';
|
|
2
|
-
import { ConfirmDialog } from './confirm-dialog';
|
|
3
2
|
|
|
3
|
+
import { ConfirmDialog } from './confirm-dialog';
|
|
4
4
|
import { destroyFns } from './destroyFns';
|
|
5
5
|
import type { ConfigUpdate, DialogFuncProps } from './types';
|
|
6
6
|
|
package/src/dialog/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { confirm, withWarning, withConfirm, withDialog, withError, withInfo } from './config';
|
|
1
2
|
import { destroyFns } from './destroyFns';
|
|
2
3
|
import { DialogBase } from './dialog';
|
|
3
4
|
import type { DialogFuncProps } from './types';
|
|
4
|
-
import { confirm, withWarning, withConfirm, withDialog, withError, withInfo } from './config';
|
|
5
5
|
|
|
6
6
|
type DialogType = typeof DialogBase & DialogFuncProps;
|
|
7
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
2
|
-
import { cx } from 'class-variance-authority';
|
|
3
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import { cx } from 'class-variance-authority';
|
|
3
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
4
4
|
|
|
5
5
|
type DropdownMenuItemProps = DropdownMenuPrimitive.MenuItemProps & {
|
|
6
6
|
children: ReactNode;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
-
import { InlineRadio } from './inline-radio';
|
|
3
|
-
import { Icon } from '../iconography';
|
|
4
|
-
|
|
5
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
6
3
|
|
|
4
|
+
import { Icon } from '../iconography';
|
|
5
|
+
import { InlineRadio } from './inline-radio';
|
|
6
|
+
|
|
7
7
|
const meta: Meta<typeof InlineRadio.Group> = {
|
|
8
8
|
title: 'Components/InlineRadio',
|
|
9
9
|
component: InlineRadio.Group,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
2
|
-
import { cx, cva, VariantProps } from 'class-variance-authority';
|
|
3
1
|
import type { ComponentProps } from 'react';
|
|
2
|
+
import { cx, cva, VariantProps } from 'class-variance-authority';
|
|
3
|
+
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
4
4
|
|
|
5
5
|
import './inline-radio.css';
|
|
6
6
|
|
package/src/input/input.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef, ComponentPropsWithRef, forwardRef, ReactNode } from 'react';
|
|
2
2
|
import { cva, cx, VariantProps } from 'class-variance-authority';
|
|
3
3
|
|
|
4
|
+
import { Triangle } from '../iconography/triangle';
|
|
4
5
|
import { Input } from '../input';
|
|
5
6
|
import { Label } from '../label';
|
|
6
|
-
import { Triangle } from '../iconography/triangle';
|
|
7
7
|
|
|
8
8
|
const inputWithLabelStyles = cva(['c-input-with-label'], {
|
|
9
9
|
variants: {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
|
|
4
|
-
import { Radio } from './radio';
|
|
5
4
|
import { Label } from '../label';
|
|
5
|
+
import { Radio } from './radio';
|
|
6
6
|
|
|
7
7
|
const meta: Meta<typeof Radio.Group> = {
|
|
8
8
|
title: 'Components/Radio',
|
package/src/radio/radio.tsx
CHANGED
|
@@ -26,8 +26,8 @@ const translations: I18N = {
|
|
|
26
26
|
actionFormatCode: 'Format code with Prettier',
|
|
27
27
|
actionTableInsertRowsAbove: 'Insert row above',
|
|
28
28
|
actionTableInsertRowsAbove_plural: 'Insert {{rows}} rows above',
|
|
29
|
-
actionTableInsertRowsBelow: 'Insert row
|
|
30
|
-
actionTableInsertRowsBelow_plural: 'Insert {{rows}} rows
|
|
29
|
+
actionTableInsertRowsBelow: 'Insert row below',
|
|
30
|
+
actionTableInsertRowsBelow_plural: 'Insert {{rows}} rows below',
|
|
31
31
|
actionTableInsertColumnsBefore: 'Insert column left',
|
|
32
32
|
actionTableInsertColumnsBefore_plural: 'Insert {{columns}} columns left',
|
|
33
33
|
actionTableInsertColumnsAfter: 'Insert column right',
|
|
@@ -38,8 +38,7 @@ export default function ActionsPlugin({
|
|
|
38
38
|
const actionMenuAnchorRef = useRef<HTMLDivElement>(null);
|
|
39
39
|
|
|
40
40
|
return (
|
|
41
|
-
<div ref={actionMenuAnchorRef} className="
|
|
42
|
-
<div></div>
|
|
41
|
+
<div ref={actionMenuAnchorRef} className="c-rte-actions-plugin">
|
|
43
42
|
<ActionMenu container={actionMenuAnchorRef.current}>
|
|
44
43
|
{!prepend
|
|
45
44
|
? null
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin';
|
|
10
9
|
import * as React from 'react';
|
|
10
|
+
import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin';
|
|
11
11
|
|
|
12
12
|
const URL_MATCHER =
|
|
13
13
|
/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
|
|
@@ -57,8 +57,12 @@ export function CopyButton({ editor, getCodeDOMNode }: Props) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
return (
|
|
60
|
-
<button className="
|
|
61
|
-
{isCopyCompleted ?
|
|
60
|
+
<button className="c-rte-code-button" onClick={handleClick} aria-label={tr('actionCopyCode')}>
|
|
61
|
+
{isCopyCompleted ? (
|
|
62
|
+
<i className="c-rte-code-button__icon c-rte-icon-success" />
|
|
63
|
+
) : (
|
|
64
|
+
<i className="c-rte-code-button__icon c-rte-icon-copy" />
|
|
65
|
+
)}
|
|
62
66
|
</button>
|
|
63
67
|
);
|
|
64
68
|
}
|
package/src/rich-text-editor/plugins/CodeActionMenuPlugin/components/PrettierButton/index.tsx
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
import * as React from 'react';
|
|
10
10
|
import { useState } from 'react';
|
|
11
11
|
import { $getNearestNodeFromDOMNode, LexicalEditor } from 'lexical';
|
|
@@ -98,7 +98,7 @@ export function PrettierButton({ lang, editor, getCodeDOMNode }: Props) {
|
|
|
98
98
|
/**
|
|
99
99
|
* Remove EOF from prettier output. This is useful when
|
|
100
100
|
* using prettier on files, but becomes weird when the code
|
|
101
|
-
* is embedded within a larger portion of text
|
|
101
|
+
* is embedded within a larger portion of text (like we do)
|
|
102
102
|
*/
|
|
103
103
|
parsed = parsed.replace(/[\r\n]+$/, '');
|
|
104
104
|
|
|
@@ -133,17 +133,21 @@ export function PrettierButton({ lang, editor, getCodeDOMNode }: Props) {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
return (
|
|
136
|
-
<div className="prettier-wrapper">
|
|
136
|
+
<div className="c-rte-prettier-wrapper">
|
|
137
137
|
<button
|
|
138
|
-
className="
|
|
138
|
+
className="c-rte-code-button"
|
|
139
139
|
onClick={handleClick}
|
|
140
140
|
onMouseEnter={handleMouseEnter}
|
|
141
141
|
onMouseLeave={handleMouseLeave}
|
|
142
142
|
aria-label={tr('actionFormatCode')}
|
|
143
143
|
>
|
|
144
|
-
{syntaxError ?
|
|
144
|
+
{syntaxError ? (
|
|
145
|
+
<i className="c-rte-code-button__icon c-rte-icon-prettier-error" />
|
|
146
|
+
) : (
|
|
147
|
+
<i className="c-rte-code-button__icon c-rte-icon-prettier" />
|
|
148
|
+
)}
|
|
145
149
|
</button>
|
|
146
|
-
{tipsVisible ? <pre className="code-error-tips">{syntaxError}</pre> : null}
|
|
150
|
+
{tipsVisible ? <pre className="c-rte-code-error-tips">{syntaxError}</pre> : null}
|
|
147
151
|
</div>
|
|
148
152
|
);
|
|
149
153
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.code-action-menu-container {
|
|
1
|
+
.c-rte-code-action-menu-container {
|
|
2
2
|
height: 35.8px;
|
|
3
3
|
font-size: 10px;
|
|
4
4
|
color: rgba(0, 0, 0, 0.5);
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
user-select: none;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
.
|
|
12
|
+
.c-rte-code-highlight-language {
|
|
13
13
|
margin-right: 4px;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
.
|
|
16
|
+
.c-rte-code-button {
|
|
17
17
|
border: 1px solid transparent;
|
|
18
18
|
border-radius: 4px;
|
|
19
19
|
padding: 4px;
|
|
@@ -24,23 +24,38 @@
|
|
|
24
24
|
align-items: center;
|
|
25
25
|
color: rgba(0, 0, 0, 0.5);
|
|
26
26
|
text-transform: uppercase;
|
|
27
|
-
}
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
&:hover {
|
|
29
|
+
border: 1px solid rgba(0, 0, 0, 0.3);
|
|
30
|
+
opacity: 0.9;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:active {
|
|
34
|
+
background-color: rgba(223, 232, 250);
|
|
35
|
+
border: 1px solid rgba(0, 0, 0, 0.45);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&__icon {
|
|
39
|
+
height: 16px;
|
|
40
|
+
width: 16px;
|
|
41
|
+
opacity: 0.6;
|
|
42
|
+
display: flex;
|
|
43
|
+
color: rgba(0, 0, 0, 0.5);
|
|
44
|
+
background-size: contain;
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
47
|
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
opacity: 0.9;
|
|
48
|
+
.c-rte-prettier-wrapper {
|
|
49
|
+
position: relative;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
border:
|
|
52
|
+
.c-rte-code-error-tips {
|
|
53
|
+
padding: 5px;
|
|
54
|
+
border-radius: 4px;
|
|
55
|
+
color: #fff;
|
|
56
|
+
background: #222;
|
|
57
|
+
margin-top: 4px;
|
|
58
|
+
position: absolute;
|
|
59
|
+
top: 26px;
|
|
60
|
+
right: 0;
|
|
46
61
|
}
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import './index.css';
|
|
10
9
|
import { useEffect, useRef, useState } from 'react';
|
|
11
10
|
import { $getNearestNodeFromDOMNode } from 'lexical';
|
|
12
11
|
import { createPortal } from 'react-dom';
|
|
@@ -119,8 +118,8 @@ function CodeActionMenuContainer({ anchorElem }: { anchorElem: HTMLElement }): J
|
|
|
119
118
|
return (
|
|
120
119
|
<>
|
|
121
120
|
{isShown ? (
|
|
122
|
-
<div className="code-action-menu-container" style={{ ...position }}>
|
|
123
|
-
<div className="code-highlight-language">{codeFriendlyName}</div>
|
|
121
|
+
<div className="c-rte-code-action-menu-container" style={{ ...position }}>
|
|
122
|
+
<div className="c-rte-code-highlight-language">{codeFriendlyName}</div>
|
|
124
123
|
<CopyButton editor={editor} getCodeDOMNode={getCodeDOMNode} />
|
|
125
124
|
{canBePrettier(normalizedLang) ? (
|
|
126
125
|
<PrettierButton editor={editor} getCodeDOMNode={getCodeDOMNode} lang={normalizedLang} />
|
|
@@ -139,7 +138,7 @@ function getMouseInfo(event: MouseEvent): {
|
|
|
139
138
|
|
|
140
139
|
if (target && target instanceof HTMLElement) {
|
|
141
140
|
const codeDOMNode = target.closest<HTMLElement>('code.CrystallizeRTEditorTheme__code');
|
|
142
|
-
const isOutside = !(codeDOMNode || target.closest<HTMLElement>('div.code-action-menu-container'));
|
|
141
|
+
const isOutside = !(codeDOMNode || target.closest<HTMLElement>('div.c-rte-code-action-menu-container'));
|
|
143
142
|
|
|
144
143
|
return { codeDOMNode, isOutside };
|
|
145
144
|
} else {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
type Dimensions = {
|
|
4
|
+
isSmallWidth: boolean;
|
|
5
|
+
width: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type DimensionDetectorPluginProps = {
|
|
9
|
+
onChange: (p: Dimensions) => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function DimensionDetectorPlugin({ onChange }: DimensionDetectorPluginProps) {
|
|
13
|
+
const [dimensions, setDimensions] = useState<Dimensions>();
|
|
14
|
+
const ref = useRef<HTMLDivElement | null>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (ref.current) {
|
|
18
|
+
const el = ref.current;
|
|
19
|
+
const resizeObserver = new ResizeObserver(entries => {
|
|
20
|
+
const [first] = entries;
|
|
21
|
+
if (first) {
|
|
22
|
+
const [contentBox] = first.contentBoxSize;
|
|
23
|
+
if (contentBox) {
|
|
24
|
+
const width = contentBox.inlineSize;
|
|
25
|
+
setDimensions({
|
|
26
|
+
width,
|
|
27
|
+
/**
|
|
28
|
+
* 600 is (currently) the point before action button crashes with
|
|
29
|
+
* the rest of the toolbar buttons.
|
|
30
|
+
*/
|
|
31
|
+
isSmallWidth: width < 600,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
resizeObserver.observe(el);
|
|
37
|
+
|
|
38
|
+
return () => resizeObserver.disconnect();
|
|
39
|
+
}
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (dimensions) {
|
|
44
|
+
onChange(dimensions);
|
|
45
|
+
}
|
|
46
|
+
}, [dimensions, onChange]);
|
|
47
|
+
|
|
48
|
+
return <div ref={ref} style={{ height: 1, marginTop: -1 }} />;
|
|
49
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.draggable-block-menu {
|
|
1
|
+
.c-rte-draggable-block-menu {
|
|
2
2
|
border-radius: 4px;
|
|
3
3
|
padding: 2px 1px;
|
|
4
4
|
cursor: grab;
|
|
@@ -7,24 +7,24 @@
|
|
|
7
7
|
left: 0;
|
|
8
8
|
top: 0;
|
|
9
9
|
will-change: transform;
|
|
10
|
-
}
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
opacity: 0.3;
|
|
16
|
-
background-image: url(../../images/icons/draggable-block-menu.svg);
|
|
17
|
-
}
|
|
11
|
+
&:active {
|
|
12
|
+
cursor: grabbing;
|
|
13
|
+
}
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
15
|
+
&:hover {
|
|
16
|
+
background-color: #efefef;
|
|
17
|
+
}
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
&__icon {
|
|
20
|
+
width: 16px;
|
|
21
|
+
height: 16px;
|
|
22
|
+
opacity: 0.3;
|
|
23
|
+
background-image: url(../../images/icons/draggable-block-menu.svg);
|
|
24
|
+
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
.draggable-block-target-line {
|
|
27
|
+
.c-rte-draggable-block-target-line {
|
|
28
28
|
pointer-events: none;
|
|
29
29
|
background: deepskyblue;
|
|
30
30
|
height: 4px;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
import * as React from 'react';
|
|
10
10
|
import { DragEvent as ReactDragEvent, useEffect, useRef, useState } from 'react';
|
|
11
11
|
import {
|
|
@@ -323,15 +323,15 @@ function useDraggableBlockMenu(editor: LexicalEditor, anchorElem: HTMLElement, i
|
|
|
323
323
|
return createPortal(
|
|
324
324
|
<>
|
|
325
325
|
<div
|
|
326
|
-
className="
|
|
326
|
+
className="c-rte-draggable-block-menu"
|
|
327
327
|
ref={menuRef}
|
|
328
328
|
draggable={true}
|
|
329
329
|
onDragStart={onDragStart}
|
|
330
330
|
onDragEnd={onDragEnd}
|
|
331
331
|
>
|
|
332
|
-
<div className={isEditable ? '
|
|
332
|
+
<div className={isEditable ? 'c-rte-draggable-block-menu__icon' : ''} />
|
|
333
333
|
</div>
|
|
334
|
-
<div className="draggable-block-target-line" ref={targetLineRef} />
|
|
334
|
+
<div className="c-rte-draggable-block-target-line" ref={targetLineRef} />
|
|
335
335
|
</>,
|
|
336
336
|
anchorElem,
|
|
337
337
|
);
|