@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/package.json CHANGED
@@ -1,86 +1,86 @@
1
- {
2
- "name": "@thangph2146/lexical-editor",
3
- "version": "0.0.6",
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
- "scripts": {
19
- "build": "tsup",
20
- "dev": "tsup --watch",
21
- "lint": "eslint",
22
- "format": "prettier --write \"**/*.{ts,tsx}\"",
23
- "typecheck": "tsc --noEmit"
24
- },
25
- "dependencies": {
26
- "@lexical/code": "^0.38.2",
27
- "@lexical/file": "^0.38.2",
28
- "@lexical/hashtag": "^0.38.2",
29
- "@lexical/link": "^0.38.2",
30
- "@lexical/list": "^0.38.2",
31
- "@lexical/markdown": "^0.38.2",
32
- "@lexical/overflow": "^0.38.2",
33
- "@lexical/rich-text": "^0.38.2",
34
- "@lexical/selection": "^0.38.2",
35
- "@lexical/table": "^0.38.2",
36
- "@lexical/text": "^0.38.2",
37
- "@lexical/utils": "^0.38.2",
38
- "@radix-ui/react-slider": "^1.2.3",
39
- "@radix-ui/react-slot": "^1.2.4",
40
- "framer-motion": "^12.4.7",
41
- "lucide-react": "^0.552.0",
42
- "sonner": "^2.0.7"
43
- },
44
- "peerDependencies": {
45
- "@lexical/react": "^0.38.2",
46
- "lexical": "^0.38.2",
47
- "react": ">=18",
48
- "react-dom": ">=18"
49
- },
50
- "devDependencies": {
51
- "@types/node": "^25.1.0",
52
- "@types/react": "^19.2.10",
53
- "@types/react-dom": "^19.2.3",
54
- "@workspace/eslint-config": "workspace:*",
55
- "@workspace/typescript-config": "workspace:*",
56
- "esbuild-sass-plugin": "^3.3.1",
57
- "eslint": "^9.39.2",
58
- "next": "16.1.6",
59
- "sass": "^1.83.0",
60
- "tsup": "^8.4.0",
61
- "typescript": "^5.9.3"
62
- },
63
- "exports": {
64
- ".": {
65
- "types": "./dist/index.d.ts",
66
- "import": "./dist/index.js",
67
- "require": "./dist/index.cjs"
68
- },
69
- "./style.css": "./dist/index.css",
70
- "./editor": {
71
- "types": "./dist/editor-x/editor.d.ts",
72
- "import": "./dist/editor-x/editor.js",
73
- "require": "./dist/editor-x/editor.cjs"
74
- },
75
- "./styles": {
76
- "sass": "./src/themes/editor-theme.scss",
77
- "default": "./src/themes/editor-theme.scss"
78
- },
79
- "./variables": {
80
- "sass": "./src/themes/_variables.scss",
81
- "default": "./src/themes/_variables.scss"
82
- },
83
- "./themes/*": "./src/themes/*.ts",
84
- "./utils/*": "./src/utils/*.ts"
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
+ }
@@ -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
- <div className="editor-flex-shrink-0">
353
+ <Flex align="center" className="editor-flex-shrink-0">
353
354
  <CounterCharacterPlugin charset="UTF-16" />
354
- </div>
355
+ </Flex>
355
356
  <div className="editor-flex-1" />
356
- <div className="editor-flex-shrink-0 editor-flex-end">
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
- </div>
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
- <div className="editor-flex-center-justify-py-8">
341
+ <Flex align="center" justify="center" className="editor-py-8">
341
342
  <Loader2 className="editor-loader" />
342
- </div>
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
- itemPaddingPx?: number
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
- itemPaddingPx: number
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 [paddingPx, setPaddingPx] = useState(initialValues?.itemPaddingPx ?? 12)
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 paddingPxRef = useRef(paddingPx)
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
- paddingPxRef.current = paddingPx
136
- }, [paddingPx])
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 onPaddingChange = (next: number) => {
154
+ const onPaddingXChange = (next: number) => {
147
155
  const value = Math.min(Math.max(next, 0), 64)
148
- paddingPxRef.current = value
149
- setPaddingPx(value)
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
- itemPaddingPx: paddingPxRef.current,
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
- <div className="editor-layout-dialog-group">
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
- </div>
231
- <div className="editor-layout-dialog-group">
232
- <div className="editor-text-xs-muted">Padding (px)</div>
233
- <Input
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
- step={1}
238
- value={paddingPx}
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
- </div>
250
- <div className="editor-layout-dialog-group">
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
- <Input
253
- type="number"
266
+ <NumberInput
254
267
  min={0}
255
268
  max={64}
256
- step={1}
257
269
  value={borderRadiusPx}
258
- onChange={(event) => {
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
- </div>
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
- const match = value.match(/^(\d+)px$/i)
348
- if (!match?.[1]) {
349
- return undefined
350
- }
351
- const parsed = Number.parseInt(match[1], 10)
352
- return Number.isFinite(parsed) ? parsed : undefined
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
- itemPaddingPx,
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(`padding: ${Math.min(Math.max(itemPaddingPx, 0), 64)}px`)
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.itemPaddingPx, 0), 64)}px`
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
- itemPaddingPx: extractNumericStyle(style, "padding") ?? 12,
449
- itemBorderRadiusPx: extractNumericStyle(style, "border-radius") ?? 8,
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 itemPaddingPx =
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.itemPaddingPx === "number" &&
573
- Number.isFinite(payload.itemPaddingPx)
574
- ? Math.min(Math.max(payload.itemPaddingPx, 0), 64)
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
- itemPaddingPx: itemPaddingPx ?? 12,
621
+ itemPaddingXPx: itemPaddingXPx ?? 12,
622
+ itemPaddingYPx: itemPaddingYPx ?? 12,
588
623
  itemBorderRadiusPx: itemBorderRadiusPx ?? 8,
589
624
  })
590
625
 
@@ -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
- $editor-scroll-area-max-height: 350px !default;
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
- // Reset common elements
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;
@@ -3,6 +3,7 @@
3
3
 
4
4
  .editor-color-picker-content {
5
5
  @include flex-col;
6
+ width: $editor-color-picker-width;
6
7
  gap: $editor-gap-4;
7
8
  padding: $editor-gap-4;
8
9
  }
@@ -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-3;
7
+ gap: $editor-gap-4;
8
8
 
9
- @media (min-width: 768px) {
10
- grid-template-columns: repeat(3, minmax(0, 1fr));
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
@@ -2,6 +2,8 @@
2
2
  @use "../mixins" as *;
3
3
 
4
4
  .editor-list-color-dialog {
5
+ @include flex-col;
6
+ gap: $editor-gap-4;
5
7
  padding: $editor-gap-2 0;
6
8
  animation: editor-fade-in $editor-transition-slow;
7
9
  }