@thangph2146/lexical-editor 0.0.6 → 0.0.7
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/dist/editor-x/editor.cjs +599 -482
- package/dist/editor-x/editor.cjs.map +1 -1
- package/dist/editor-x/editor.css +157 -69
- package/dist/editor-x/editor.css.map +1 -1
- package/dist/editor-x/editor.js +339 -222
- package/dist/editor-x/editor.js.map +1 -1
- package/dist/index.cjs +605 -488
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +157 -69
- package/dist/index.css.map +1 -1
- package/dist/index.js +339 -222
- package/dist/index.js.map +1 -1
- package/package.json +86 -86
- package/src/editor-x/plugins.tsx +5 -4
- package/src/plugins/images-plugin.tsx +3 -2
- package/src/plugins/layout-plugin.tsx +96 -61
- package/src/themes/_mixins.scss +12 -7
- package/src/themes/_variables.scss +2 -1
- package/src/themes/core/_reset.scss +10 -6
- package/src/themes/plugins/_color-picker.scss +1 -0
- package/src/themes/plugins/_layout.scss +3 -7
- package/src/themes/plugins/_list-color.scss +2 -0
- package/src/themes/plugins/_toolbar.scss +7 -7
- package/src/themes/ui-components/_button.scss +3 -3
- package/src/themes/ui-components/_flex.scss +2 -0
- package/src/themes/ui-components/_number-input.scss +81 -0
- package/src/themes/ui-components/_text-utilities.scss +1 -1
- package/src/themes/ui-components.scss +1 -0
- package/src/ui/flex.tsx +9 -2
- package/src/ui/number-input.tsx +104 -0
package/package.json
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@thangph2146/lexical-editor",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Rich Text Editor library based on Lexical for React/Next.js",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"private": false,
|
|
8
|
-
"main": "./dist/index.cjs",
|
|
9
|
-
"module": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"files": [
|
|
12
|
-
"dist",
|
|
13
|
-
"src"
|
|
14
|
-
],
|
|
15
|
-
"publishConfig": {
|
|
16
|
-
"access": "public"
|
|
17
|
-
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"@lexical/
|
|
27
|
-
"@lexical/
|
|
28
|
-
"@lexical/
|
|
29
|
-
"@lexical/
|
|
30
|
-
"@lexical/
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"@
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"@
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"@
|
|
54
|
-
"@workspace/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@thangph2146/lexical-editor",
|
|
3
|
+
"version": "0.0.7",
|
|
4
|
+
"description": "Rich Text Editor library based on Lexical for React/Next.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@lexical/code": "^0.38.2",
|
|
20
|
+
"@lexical/file": "^0.38.2",
|
|
21
|
+
"@lexical/hashtag": "^0.38.2",
|
|
22
|
+
"@lexical/link": "^0.38.2",
|
|
23
|
+
"@lexical/list": "^0.38.2",
|
|
24
|
+
"@lexical/markdown": "^0.38.2",
|
|
25
|
+
"@lexical/overflow": "^0.38.2",
|
|
26
|
+
"@lexical/rich-text": "^0.38.2",
|
|
27
|
+
"@lexical/selection": "^0.38.2",
|
|
28
|
+
"@lexical/table": "^0.38.2",
|
|
29
|
+
"@lexical/text": "^0.38.2",
|
|
30
|
+
"@lexical/utils": "^0.38.2",
|
|
31
|
+
"@radix-ui/react-slider": "^1.2.3",
|
|
32
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
33
|
+
"framer-motion": "^12.4.7",
|
|
34
|
+
"lucide-react": "^0.552.0",
|
|
35
|
+
"sonner": "^2.0.7"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@lexical/react": "^0.38.2",
|
|
39
|
+
"lexical": "^0.38.2",
|
|
40
|
+
"react": ">=18",
|
|
41
|
+
"react-dom": ">=18"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^25.1.0",
|
|
45
|
+
"@types/react": "^19.2.10",
|
|
46
|
+
"@types/react-dom": "^19.2.3",
|
|
47
|
+
"esbuild-sass-plugin": "^3.3.1",
|
|
48
|
+
"eslint": "^9.39.2",
|
|
49
|
+
"next": "16.1.6",
|
|
50
|
+
"sass": "^1.83.0",
|
|
51
|
+
"tsup": "^8.4.0",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
|
+
"@workspace/eslint-config": "0.0.0",
|
|
54
|
+
"@workspace/typescript-config": "0.0.0"
|
|
55
|
+
},
|
|
56
|
+
"exports": {
|
|
57
|
+
".": {
|
|
58
|
+
"types": "./dist/index.d.ts",
|
|
59
|
+
"import": "./dist/index.js",
|
|
60
|
+
"require": "./dist/index.cjs"
|
|
61
|
+
},
|
|
62
|
+
"./style.css": "./dist/index.css",
|
|
63
|
+
"./editor": {
|
|
64
|
+
"types": "./dist/editor-x/editor.d.ts",
|
|
65
|
+
"import": "./dist/editor-x/editor.js",
|
|
66
|
+
"require": "./dist/editor-x/editor.cjs"
|
|
67
|
+
},
|
|
68
|
+
"./styles": {
|
|
69
|
+
"sass": "./src/themes/editor-theme.scss",
|
|
70
|
+
"default": "./src/themes/editor-theme.scss"
|
|
71
|
+
},
|
|
72
|
+
"./variables": {
|
|
73
|
+
"sass": "./src/themes/_variables.scss",
|
|
74
|
+
"default": "./src/themes/_variables.scss"
|
|
75
|
+
},
|
|
76
|
+
"./themes/*": "./src/themes/*.ts",
|
|
77
|
+
"./utils/*": "./src/utils/*.ts"
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"build": "tsup",
|
|
81
|
+
"dev": "tsup --watch",
|
|
82
|
+
"lint": "eslint",
|
|
83
|
+
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
|
84
|
+
"typecheck": "tsc --noEmit"
|
|
85
|
+
}
|
|
86
|
+
}
|
package/src/editor-x/plugins.tsx
CHANGED
|
@@ -110,6 +110,7 @@ import { TABLE } from "../transformers/markdown-table-transformer"
|
|
|
110
110
|
import { TWEET } from "../transformers/markdown-tweet-transformer"
|
|
111
111
|
import { UNORDERED_LIST } from "../transformers/markdown-list-transformer"
|
|
112
112
|
import { Separator } from "../ui/separator"
|
|
113
|
+
import { Flex } from "../ui/flex"
|
|
113
114
|
|
|
114
115
|
export function Plugins({
|
|
115
116
|
readOnly = false,
|
|
@@ -349,11 +350,11 @@ export function Plugins({
|
|
|
349
350
|
{!readOnly && (
|
|
350
351
|
<ActionsPlugin>
|
|
351
352
|
<div className="editor-actions-bar">
|
|
352
|
-
<
|
|
353
|
+
<Flex align="center" className="editor-flex-shrink-0">
|
|
353
354
|
<CounterCharacterPlugin charset="UTF-16" />
|
|
354
|
-
</
|
|
355
|
+
</Flex>
|
|
355
356
|
<div className="editor-flex-1" />
|
|
356
|
-
<
|
|
357
|
+
<Flex align="center" justify="end" gap={1} wrap="nowrap" className="editor-flex-shrink-0">
|
|
357
358
|
<SpeechToTextPlugin />
|
|
358
359
|
<ShareContentPlugin />
|
|
359
360
|
<ImportExportPlugin />
|
|
@@ -376,7 +377,7 @@ export function Plugins({
|
|
|
376
377
|
<EditModeTogglePlugin />
|
|
377
378
|
<ClearEditorActionPlugin />
|
|
378
379
|
<TreeViewPlugin />
|
|
379
|
-
</
|
|
380
|
+
</Flex>
|
|
380
381
|
</div>
|
|
381
382
|
</ActionsPlugin>
|
|
382
383
|
)}
|
|
@@ -41,6 +41,7 @@ import { Button } from "../ui/button"
|
|
|
41
41
|
import { DialogFooter } from "../ui/dialog"
|
|
42
42
|
import { Input } from "../ui/input"
|
|
43
43
|
import { Label } from "../ui/label"
|
|
44
|
+
import { Flex } from "../ui/flex"
|
|
44
45
|
import {
|
|
45
46
|
Tabs,
|
|
46
47
|
TabsContent,
|
|
@@ -337,9 +338,9 @@ export function InsertImageUploadsDialogBody({
|
|
|
337
338
|
<div className="editor-form-item">
|
|
338
339
|
<Label>Chọn hình ảnh từ thư viện</Label>
|
|
339
340
|
{isLoading ? (
|
|
340
|
-
<
|
|
341
|
+
<Flex align="center" justify="center" className="editor-py-8">
|
|
341
342
|
<Loader2 className="editor-loader" />
|
|
342
|
-
</
|
|
343
|
+
</Flex>
|
|
343
344
|
) : !folderTree || (folderTree.subfolders.length === 0 && folderTree.images.length === 0) ? (
|
|
344
345
|
<div className="editor-empty-state">
|
|
345
346
|
<TypographySpanSmallMuted>Chưa có hình ảnh nào được upload</TypographySpanSmallMuted>
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
LayoutItemNode,
|
|
44
44
|
} from "../nodes/layout-item-node"
|
|
45
45
|
import { Button } from "../ui/button"
|
|
46
|
+
import { NumberInput } from "../ui/number-input"
|
|
46
47
|
import {
|
|
47
48
|
Select,
|
|
48
49
|
SelectContent,
|
|
@@ -82,14 +83,16 @@ type InsertLayoutPayload =
|
|
|
82
83
|
| {
|
|
83
84
|
template: string
|
|
84
85
|
itemBackgroundColor?: string
|
|
85
|
-
|
|
86
|
+
itemPaddingXPx?: number
|
|
87
|
+
itemPaddingYPx?: number
|
|
86
88
|
itemBorderRadiusPx?: number
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
type LayoutDialogValues = {
|
|
90
92
|
template: string
|
|
91
93
|
itemBackgroundColor: string
|
|
92
|
-
|
|
94
|
+
itemPaddingXPx: number
|
|
95
|
+
itemPaddingYPx: number
|
|
93
96
|
itemBorderRadiusPx: number
|
|
94
97
|
}
|
|
95
98
|
|
|
@@ -116,13 +119,15 @@ export function InsertLayoutDialog({
|
|
|
116
119
|
const [backgroundColor, setBackgroundColor] = useState(
|
|
117
120
|
initialValues?.itemBackgroundColor ?? "#ffffff"
|
|
118
121
|
)
|
|
119
|
-
const [
|
|
122
|
+
const [paddingXPx, setPaddingXPx] = useState(initialValues?.itemPaddingXPx ?? 12)
|
|
123
|
+
const [paddingYPx, setPaddingYPx] = useState(initialValues?.itemPaddingYPx ?? 12)
|
|
120
124
|
const [borderRadiusPx, setBorderRadiusPx] = useState(
|
|
121
125
|
initialValues?.itemBorderRadiusPx ?? 8
|
|
122
126
|
)
|
|
123
127
|
const layoutRef = useRef(layout)
|
|
124
128
|
const backgroundColorRef = useRef(backgroundColor)
|
|
125
|
-
const
|
|
129
|
+
const paddingXPxRef = useRef(paddingXPx)
|
|
130
|
+
const paddingYPxRef = useRef(paddingYPx)
|
|
126
131
|
const borderRadiusPxRef = useRef(borderRadiusPx)
|
|
127
132
|
|
|
128
133
|
useEffect(() => {
|
|
@@ -132,8 +137,11 @@ export function InsertLayoutDialog({
|
|
|
132
137
|
backgroundColorRef.current = backgroundColor
|
|
133
138
|
}, [backgroundColor])
|
|
134
139
|
useEffect(() => {
|
|
135
|
-
|
|
136
|
-
}, [
|
|
140
|
+
paddingXPxRef.current = paddingXPx
|
|
141
|
+
}, [paddingXPx])
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
paddingYPxRef.current = paddingYPx
|
|
144
|
+
}, [paddingYPx])
|
|
137
145
|
useEffect(() => {
|
|
138
146
|
borderRadiusPxRef.current = borderRadiusPx
|
|
139
147
|
}, [borderRadiusPx])
|
|
@@ -143,10 +151,16 @@ export function InsertLayoutDialog({
|
|
|
143
151
|
setBackgroundColor(value)
|
|
144
152
|
}
|
|
145
153
|
|
|
146
|
-
const
|
|
154
|
+
const onPaddingXChange = (next: number) => {
|
|
147
155
|
const value = Math.min(Math.max(next, 0), 64)
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
paddingXPxRef.current = value
|
|
157
|
+
setPaddingXPx(value)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const onPaddingYChange = (next: number) => {
|
|
161
|
+
const value = Math.min(Math.max(next, 0), 64)
|
|
162
|
+
paddingYPxRef.current = value
|
|
163
|
+
setPaddingYPx(value)
|
|
150
164
|
}
|
|
151
165
|
|
|
152
166
|
const onBorderRadiusChange = (next: number) => {
|
|
@@ -160,7 +174,8 @@ export function InsertLayoutDialog({
|
|
|
160
174
|
const values: LayoutDialogValues = {
|
|
161
175
|
template: layoutRef.current,
|
|
162
176
|
itemBackgroundColor: backgroundColorRef.current,
|
|
163
|
-
|
|
177
|
+
itemPaddingXPx: paddingXPxRef.current,
|
|
178
|
+
itemPaddingYPx: paddingYPxRef.current,
|
|
164
179
|
itemBorderRadiusPx: borderRadiusPxRef.current,
|
|
165
180
|
}
|
|
166
181
|
logger.info("[Layout] Submit dialog values", {
|
|
@@ -177,7 +192,7 @@ export function InsertLayoutDialog({
|
|
|
177
192
|
}
|
|
178
193
|
|
|
179
194
|
return (
|
|
180
|
-
|
|
195
|
+
<Flex direction="column" gap={4}>
|
|
181
196
|
<Select onValueChange={setLayout} value={layout}>
|
|
182
197
|
<SelectTrigger className="editor-input-lg editor-w-full">
|
|
183
198
|
<SelectValue placeholder={buttonLabel} />
|
|
@@ -191,7 +206,7 @@ export function InsertLayoutDialog({
|
|
|
191
206
|
</SelectContent>
|
|
192
207
|
</Select>
|
|
193
208
|
<div className="editor-layout-dialog-grid">
|
|
194
|
-
<
|
|
209
|
+
<Flex direction="column" gap={1.5}>
|
|
195
210
|
<div className="editor-text-xs-muted">Background</div>
|
|
196
211
|
<ColorPicker
|
|
197
212
|
modal
|
|
@@ -227,48 +242,37 @@ export function InsertLayoutDialog({
|
|
|
227
242
|
<ColorPickerPresets />
|
|
228
243
|
</ColorPickerContent>
|
|
229
244
|
</ColorPicker>
|
|
230
|
-
</
|
|
231
|
-
<
|
|
232
|
-
<div className="editor-text-xs-muted">Padding (px)</div>
|
|
233
|
-
<
|
|
234
|
-
type="number"
|
|
245
|
+
</Flex>
|
|
246
|
+
<Flex direction="column" gap={1.5}>
|
|
247
|
+
<div className="editor-text-xs-muted">Padding X (px)</div>
|
|
248
|
+
<NumberInput
|
|
235
249
|
min={0}
|
|
236
250
|
max={64}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
onChange={(event) => {
|
|
240
|
-
const next = Number.parseInt(event.target.value, 10)
|
|
241
|
-
if (Number.isFinite(next)) {
|
|
242
|
-
onPaddingChange(next)
|
|
243
|
-
} else {
|
|
244
|
-
onPaddingChange(0)
|
|
245
|
-
}
|
|
246
|
-
}}
|
|
247
|
-
className="editor-input-lg editor-w-full"
|
|
251
|
+
value={paddingXPx}
|
|
252
|
+
onValueChange={onPaddingXChange}
|
|
248
253
|
/>
|
|
249
|
-
</
|
|
250
|
-
<
|
|
254
|
+
</Flex>
|
|
255
|
+
<Flex direction="column" gap={1.5}>
|
|
256
|
+
<div className="editor-text-xs-muted">Padding Y (px)</div>
|
|
257
|
+
<NumberInput
|
|
258
|
+
min={0}
|
|
259
|
+
max={64}
|
|
260
|
+
value={paddingYPx}
|
|
261
|
+
onValueChange={onPaddingYChange}
|
|
262
|
+
/>
|
|
263
|
+
</Flex>
|
|
264
|
+
<Flex direction="column" gap={1.5}>
|
|
251
265
|
<div className="editor-text-xs-muted">Border radius (px)</div>
|
|
252
|
-
<
|
|
253
|
-
type="number"
|
|
266
|
+
<NumberInput
|
|
254
267
|
min={0}
|
|
255
268
|
max={64}
|
|
256
|
-
step={1}
|
|
257
269
|
value={borderRadiusPx}
|
|
258
|
-
|
|
259
|
-
const next = Number.parseInt(event.target.value, 10)
|
|
260
|
-
if (Number.isFinite(next)) {
|
|
261
|
-
onBorderRadiusChange(next)
|
|
262
|
-
} else {
|
|
263
|
-
onBorderRadiusChange(0)
|
|
264
|
-
}
|
|
265
|
-
}}
|
|
266
|
-
className="editor-input-lg editor-w-full"
|
|
270
|
+
onValueChange={onBorderRadiusChange}
|
|
267
271
|
/>
|
|
268
|
-
</
|
|
272
|
+
</Flex>
|
|
269
273
|
</div>
|
|
270
274
|
<Button onClick={onClick}>{submitLabel}</Button>
|
|
271
|
-
|
|
275
|
+
</Flex>
|
|
272
276
|
)
|
|
273
277
|
}
|
|
274
278
|
|
|
@@ -339,29 +343,42 @@ export function LayoutPlugin(): JSX.Element | null {
|
|
|
339
343
|
return match?.[1]?.trim()
|
|
340
344
|
}
|
|
341
345
|
|
|
342
|
-
const extractNumericStyle = (style: string, property: string): number | undefined => {
|
|
346
|
+
const extractNumericStyle = (style: string, property: string): number[] | undefined => {
|
|
343
347
|
const value = extractStyleValue(style, property)
|
|
344
348
|
if (!value) {
|
|
345
349
|
return undefined
|
|
346
350
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
// Remove !important and split by whitespace
|
|
352
|
+
const values = value.replace(/!important/gi, "").trim().split(/\s+/)
|
|
353
|
+
const parsedValues = values
|
|
354
|
+
.map((v) => {
|
|
355
|
+
const match = v.match(/^(\d+)px/i)
|
|
356
|
+
if (!match?.[1]) return null
|
|
357
|
+
const parsed = Number.parseInt(match[1], 10)
|
|
358
|
+
return Number.isFinite(parsed) ? parsed : null
|
|
359
|
+
})
|
|
360
|
+
.filter((v): v is number => v !== null)
|
|
361
|
+
|
|
362
|
+
if (parsedValues.length === 0) return undefined
|
|
363
|
+
return parsedValues
|
|
353
364
|
}
|
|
354
365
|
|
|
355
366
|
const buildLayoutItemStyle = ({
|
|
356
367
|
itemBackgroundColor,
|
|
357
|
-
|
|
368
|
+
itemPaddingXPx,
|
|
369
|
+
itemPaddingYPx,
|
|
358
370
|
itemBorderRadiusPx,
|
|
359
371
|
}: LayoutDialogValues): string => {
|
|
360
372
|
const itemStyles: string[] = []
|
|
361
373
|
if (itemBackgroundColor.trim()) {
|
|
362
374
|
itemStyles.push(`background-color: ${itemBackgroundColor.trim()}`)
|
|
363
375
|
}
|
|
364
|
-
itemStyles.push(
|
|
376
|
+
itemStyles.push(
|
|
377
|
+
`padding: ${Math.min(Math.max(itemPaddingYPx, 0), 64)}px ${Math.min(
|
|
378
|
+
Math.max(itemPaddingXPx, 0),
|
|
379
|
+
64
|
|
380
|
+
)}px`
|
|
381
|
+
)
|
|
365
382
|
itemStyles.push(
|
|
366
383
|
`border-radius: ${Math.min(Math.max(itemBorderRadiusPx, 0), 64)}px`
|
|
367
384
|
)
|
|
@@ -376,7 +393,10 @@ export function LayoutPlugin(): JSX.Element | null {
|
|
|
376
393
|
}
|
|
377
394
|
|
|
378
395
|
const background = values.itemBackgroundColor.trim()
|
|
379
|
-
const padding = `${Math.min(Math.max(values.
|
|
396
|
+
const padding = `${Math.min(Math.max(values.itemPaddingYPx, 0), 64)}px ${Math.min(
|
|
397
|
+
Math.max(values.itemPaddingXPx, 0),
|
|
398
|
+
64
|
|
399
|
+
)}px`
|
|
380
400
|
const borderRadius = `${Math.min(Math.max(values.itemBorderRadiusPx, 0), 64)}px`
|
|
381
401
|
if (background) {
|
|
382
402
|
element.style.setProperty("background-color", background)
|
|
@@ -438,6 +458,9 @@ export function LayoutPlugin(): JSX.Element | null {
|
|
|
438
458
|
}
|
|
439
459
|
|
|
440
460
|
const style = layoutItem.getStyle()
|
|
461
|
+
const paddingValues = extractNumericStyle(style, "padding")
|
|
462
|
+
const borderRadiusValues = extractNumericStyle(style, "border-radius")
|
|
463
|
+
|
|
441
464
|
payload = {
|
|
442
465
|
containerKey: parentContainer.getKey(),
|
|
443
466
|
layoutItemKey: layoutItem.getKey(),
|
|
@@ -445,8 +468,12 @@ export function LayoutPlugin(): JSX.Element | null {
|
|
|
445
468
|
template: parentContainer.getTemplateColumns(),
|
|
446
469
|
itemBackgroundColor:
|
|
447
470
|
extractStyleValue(style, "background-color") ?? "#ffffff",
|
|
448
|
-
|
|
449
|
-
|
|
471
|
+
itemPaddingXPx:
|
|
472
|
+
paddingValues && paddingValues.length > 1
|
|
473
|
+
? paddingValues[1]
|
|
474
|
+
: (paddingValues?.[0] ?? 12),
|
|
475
|
+
itemPaddingYPx: paddingValues?.[0] ?? 12,
|
|
476
|
+
itemBorderRadiusPx: borderRadiusValues?.[0] ?? 8,
|
|
450
477
|
},
|
|
451
478
|
}
|
|
452
479
|
logger.debug("[Layout] Resolved payload from target", payload)
|
|
@@ -566,12 +593,19 @@ export function LayoutPlugin(): JSX.Element | null {
|
|
|
566
593
|
typeof payload === "string"
|
|
567
594
|
? undefined
|
|
568
595
|
: payload.itemBackgroundColor?.trim()
|
|
569
|
-
const
|
|
596
|
+
const itemPaddingXPx =
|
|
597
|
+
typeof payload === "string"
|
|
598
|
+
? undefined
|
|
599
|
+
: typeof payload.itemPaddingXPx === "number" &&
|
|
600
|
+
Number.isFinite(payload.itemPaddingXPx)
|
|
601
|
+
? Math.min(Math.max(payload.itemPaddingXPx, 0), 64)
|
|
602
|
+
: undefined
|
|
603
|
+
const itemPaddingYPx =
|
|
570
604
|
typeof payload === "string"
|
|
571
605
|
? undefined
|
|
572
|
-
: typeof payload.
|
|
573
|
-
Number.isFinite(payload.
|
|
574
|
-
? Math.min(Math.max(payload.
|
|
606
|
+
: typeof payload.itemPaddingYPx === "number" &&
|
|
607
|
+
Number.isFinite(payload.itemPaddingYPx)
|
|
608
|
+
? Math.min(Math.max(payload.itemPaddingYPx, 0), 64)
|
|
575
609
|
: undefined
|
|
576
610
|
const itemBorderRadiusPx =
|
|
577
611
|
typeof payload === "string"
|
|
@@ -584,7 +618,8 @@ export function LayoutPlugin(): JSX.Element | null {
|
|
|
584
618
|
const itemStyle = buildLayoutItemStyle({
|
|
585
619
|
template,
|
|
586
620
|
itemBackgroundColor: itemBackgroundColor ?? "#ffffff",
|
|
587
|
-
|
|
621
|
+
itemPaddingXPx: itemPaddingXPx ?? 12,
|
|
622
|
+
itemPaddingYPx: itemPaddingYPx ?? 12,
|
|
588
623
|
itemBorderRadiusPx: itemBorderRadiusPx ?? 8,
|
|
589
624
|
})
|
|
590
625
|
|
package/src/themes/_mixins.scss
CHANGED
|
@@ -26,9 +26,14 @@
|
|
|
26
26
|
justify-content: space-between;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
@mixin flex-row {
|
|
30
|
+
display: flex !important;
|
|
31
|
+
flex-direction: row !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
@mixin flex-col {
|
|
30
|
-
display: flex;
|
|
31
|
-
flex-direction: column;
|
|
35
|
+
display: flex !important;
|
|
36
|
+
flex-direction: column !important;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
@mixin flex-center-justify {
|
|
@@ -63,19 +68,19 @@
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
@mixin shadow-sm {
|
|
66
|
-
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
71
|
+
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05) !important;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
@mixin shadow-md {
|
|
70
|
-
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
75
|
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
@mixin shadow-lg {
|
|
74
|
-
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
79
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05) !important;
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
@mixin shadow-xl {
|
|
78
|
-
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
83
|
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04) !important;
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
@mixin absolute-full {
|
|
@@ -138,7 +143,7 @@
|
|
|
138
143
|
// --- Unified Hover Styles ---
|
|
139
144
|
@mixin editor-hover-base {
|
|
140
145
|
transform: translateY(-1px);
|
|
141
|
-
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
146
|
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
@mixin editor-active-base {
|
|
@@ -172,7 +172,8 @@ $editor-popover-max-height: 300px !default;
|
|
|
172
172
|
$editor-format-select-width: 72px !default;
|
|
173
173
|
$editor-floating-toolbar-max-width: 560px !default;
|
|
174
174
|
$editor-color-picker-height: 160px !default;
|
|
175
|
-
|
|
175
|
+
$editor-color-picker-width: 380px !default;
|
|
176
|
+
$editor-scroll-area-max-height: 350px !default;
|
|
176
177
|
$editor-link-editor-max-width: 400px !default;
|
|
177
178
|
$editor-component-picker-width: 250px !default;
|
|
178
179
|
$editor-mentions-width: 200px !default;
|
|
@@ -11,6 +11,15 @@
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// Global resets
|
|
15
|
+
*, *::before, *::after {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
|
|
18
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
19
|
+
outline-color: color-mix(in oklab, var(--ring) 50%, transparent);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
// Lexical Editor Root
|
|
15
24
|
.lexical-editor-root {
|
|
16
25
|
font-family: $editor-font-family !important;
|
|
@@ -24,12 +33,7 @@
|
|
|
24
33
|
text-align: left !important;
|
|
25
34
|
box-sizing: border-box !important;
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
*, *::before, *::after {
|
|
29
|
-
box-sizing: border-box;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
p, ul, ol, li, span, strong, em, b, i, blockquote, h1, h2, h3, h4, h5, h6 {
|
|
36
|
+
p, div, ul, ol, li, span, strong, em, b, i, blockquote, h1, h2, h3, h4, h5, h6 {
|
|
33
37
|
margin: 0 !important;
|
|
34
38
|
padding: 0;
|
|
35
39
|
border: 0 !important;
|
|
@@ -4,17 +4,13 @@
|
|
|
4
4
|
.editor-layout-dialog-grid {
|
|
5
5
|
display: grid;
|
|
6
6
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
7
|
-
gap: $editor-gap-
|
|
7
|
+
gap: $editor-gap-4;
|
|
8
8
|
|
|
9
|
-
@media (min-width:
|
|
10
|
-
grid-template-columns: repeat(
|
|
9
|
+
@media (min-width: 480px) {
|
|
10
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
.editor-layout-dialog-group {
|
|
15
|
-
@include flex-col;
|
|
16
|
-
gap: $editor-gap-1-5;
|
|
17
|
-
}
|
|
18
14
|
|
|
19
15
|
.editor-layout-color-trigger {
|
|
20
16
|
height: $editor-control-size-xl; // h-11
|