@thangph2146/lexical-editor 0.0.6 → 0.0.9

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@thangph2146/lexical-editor",
3
- "version": "0.0.6",
3
+ "version": "0.0.9",
4
4
  "description": "Rich Text Editor library based on Lexical for React/Next.js",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,7 +20,8 @@
20
20
  "dev": "tsup --watch",
21
21
  "lint": "eslint",
22
22
  "format": "prettier --write \"**/*.{ts,tsx}\"",
23
- "typecheck": "tsc --noEmit"
23
+ "typecheck": "tsc --noEmit",
24
+ "prepublishOnly": "pnpm build && pnpm typecheck"
24
25
  },
25
26
  "dependencies": {
26
27
  "@lexical/code": "^0.38.2",
@@ -1,42 +1,30 @@
1
- import { JSX } from "react"
2
- import { ContentEditable as LexicalContentEditable } from "@lexical/react/LexicalContentEditable"
3
- import { cn } from "../lib/utils"
4
-
5
- type Props = {
6
- placeholder: string
7
- className?: string
8
- placeholderClassName?: string
9
- placeholderDefaults?: boolean // apply default positioning/padding for placeholder
10
- }
11
-
12
- export function ContentEditable({
13
- placeholder,
14
- className,
15
- placeholderClassName,
16
- placeholderDefaults = true,
17
- }: Props): JSX.Element {
18
- const isReadOnlyOrReview = className?.includes("--readonly") || className?.includes("--review")
19
-
20
- return (
21
- <LexicalContentEditable
22
- className={cn(
23
- "ContentEditable__root relative block focus:outline-none",
24
- !isReadOnlyOrReview && "min-h-72 px-8 py-4",
25
- className
26
- )}
27
- aria-placeholder={placeholder}
28
- aria-label={placeholder || "Editor nội dung"}
29
- placeholder={
30
- <div
31
- className={cn(
32
- placeholderClassName,
33
- "text-muted-foreground pointer-events-none select-none",
34
- placeholderDefaults && !isReadOnlyOrReview && "absolute top-0 left-0 overflow-hidden px-8 py-[18px] text-ellipsis"
35
- )}
36
- >
37
- {placeholder}
38
- </div>
39
- }
40
- />
41
- )
42
- }
1
+ import { JSX } from "react"
2
+ import { ContentEditable as LexicalContentEditable } from "@lexical/react/LexicalContentEditable"
3
+ import { cn } from "../lib/utils"
4
+
5
+ type Props = {
6
+ placeholder?: string
7
+ className?: string
8
+ placeholderClassName?: string
9
+ placeholderDefaults?: boolean // apply default positioning/padding for placeholder
10
+ }
11
+
12
+ export function ContentEditable({
13
+ placeholder,
14
+ className,
15
+ placeholderClassName,
16
+ placeholderDefaults = true,
17
+ }: Props): JSX.Element {
18
+ const isReadOnlyOrReview = className?.includes("--readonly") || className?.includes("--review")
19
+
20
+ return (
21
+ <LexicalContentEditable
22
+ className={cn(
23
+ "ContentEditable__root relative block focus:outline-none",
24
+ !isReadOnlyOrReview && "min-h-72 px-8 py-4",
25
+ className
26
+ )}
27
+ aria-label={"Editor nội dung"}
28
+ />
29
+ )
30
+ }
@@ -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,
@@ -227,11 +228,13 @@ export function Plugins({
227
228
  <div className={cn("editor-relative-full")}>
228
229
  <div className={cn("editor-relative-full")} ref={onRef}>
229
230
  <ContentEditable
230
- placeholder={readOnly ? "" : placeholder}
231
+ placeholder=""
231
232
  className={cn(
232
233
  "editor-content-editable",
233
234
  readOnly && "editor-content-editable--readonly"
234
235
  )}
236
+ placeholderClassName="editor-placeholder"
237
+ placeholderDefaults={false}
235
238
  />
236
239
  </div>
237
240
  </div>
@@ -349,11 +352,11 @@ export function Plugins({
349
352
  {!readOnly && (
350
353
  <ActionsPlugin>
351
354
  <div className="editor-actions-bar">
352
- <div className="editor-flex-shrink-0">
355
+ <Flex align="center" className="editor-flex-shrink-0">
353
356
  <CounterCharacterPlugin charset="UTF-16" />
354
- </div>
357
+ </Flex>
355
358
  <div className="editor-flex-1" />
356
- <div className="editor-flex-shrink-0 editor-flex-end">
359
+ <Flex align="center" justify="end" gap={1} wrap="nowrap" className="editor-flex-shrink-0">
357
360
  <SpeechToTextPlugin />
358
361
  <ShareContentPlugin />
359
362
  <ImportExportPlugin />
@@ -376,7 +379,7 @@ export function Plugins({
376
379
  <EditModeTogglePlugin />
377
380
  <ClearEditorActionPlugin />
378
381
  <TreeViewPlugin />
379
- </div>
382
+ </Flex>
380
383
  </div>
381
384
  </ActionsPlugin>
382
385
  )}
@@ -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,
@@ -62,7 +63,6 @@ import {
62
63
  ColorPickerPresets,
63
64
  ColorPickerTrigger,
64
65
  } from "../editor-ui/color-picker"
65
- import { Input } from "../ui/input"
66
66
  import { Flex } from "../ui/flex"
67
67
  import { useEditorModal } from "../editor-hooks/use-modal"
68
68
  import { logger } from "../lib/logger"
@@ -82,14 +82,16 @@ type InsertLayoutPayload =
82
82
  | {
83
83
  template: string
84
84
  itemBackgroundColor?: string
85
- itemPaddingPx?: number
85
+ itemPaddingXPx?: number
86
+ itemPaddingYPx?: number
86
87
  itemBorderRadiusPx?: number
87
88
  }
88
89
 
89
90
  type LayoutDialogValues = {
90
91
  template: string
91
92
  itemBackgroundColor: string
92
- itemPaddingPx: number
93
+ itemPaddingXPx: number
94
+ itemPaddingYPx: number
93
95
  itemBorderRadiusPx: number
94
96
  }
95
97
 
@@ -116,13 +118,15 @@ export function InsertLayoutDialog({
116
118
  const [backgroundColor, setBackgroundColor] = useState(
117
119
  initialValues?.itemBackgroundColor ?? "#ffffff"
118
120
  )
119
- const [paddingPx, setPaddingPx] = useState(initialValues?.itemPaddingPx ?? 12)
121
+ const [paddingXPx, setPaddingXPx] = useState(initialValues?.itemPaddingXPx ?? 12)
122
+ const [paddingYPx, setPaddingYPx] = useState(initialValues?.itemPaddingYPx ?? 12)
120
123
  const [borderRadiusPx, setBorderRadiusPx] = useState(
121
124
  initialValues?.itemBorderRadiusPx ?? 8
122
125
  )
123
126
  const layoutRef = useRef(layout)
124
127
  const backgroundColorRef = useRef(backgroundColor)
125
- const paddingPxRef = useRef(paddingPx)
128
+ const paddingXPxRef = useRef(paddingXPx)
129
+ const paddingYPxRef = useRef(paddingYPx)
126
130
  const borderRadiusPxRef = useRef(borderRadiusPx)
127
131
 
128
132
  useEffect(() => {
@@ -132,8 +136,11 @@ export function InsertLayoutDialog({
132
136
  backgroundColorRef.current = backgroundColor
133
137
  }, [backgroundColor])
134
138
  useEffect(() => {
135
- paddingPxRef.current = paddingPx
136
- }, [paddingPx])
139
+ paddingXPxRef.current = paddingXPx
140
+ }, [paddingXPx])
141
+ useEffect(() => {
142
+ paddingYPxRef.current = paddingYPx
143
+ }, [paddingYPx])
137
144
  useEffect(() => {
138
145
  borderRadiusPxRef.current = borderRadiusPx
139
146
  }, [borderRadiusPx])
@@ -143,10 +150,16 @@ export function InsertLayoutDialog({
143
150
  setBackgroundColor(value)
144
151
  }
145
152
 
146
- const onPaddingChange = (next: number) => {
153
+ const onPaddingXChange = (next: number) => {
147
154
  const value = Math.min(Math.max(next, 0), 64)
148
- paddingPxRef.current = value
149
- setPaddingPx(value)
155
+ paddingXPxRef.current = value
156
+ setPaddingXPx(value)
157
+ }
158
+
159
+ const onPaddingYChange = (next: number) => {
160
+ const value = Math.min(Math.max(next, 0), 64)
161
+ paddingYPxRef.current = value
162
+ setPaddingYPx(value)
150
163
  }
151
164
 
152
165
  const onBorderRadiusChange = (next: number) => {
@@ -160,7 +173,8 @@ export function InsertLayoutDialog({
160
173
  const values: LayoutDialogValues = {
161
174
  template: layoutRef.current,
162
175
  itemBackgroundColor: backgroundColorRef.current,
163
- itemPaddingPx: paddingPxRef.current,
176
+ itemPaddingXPx: paddingXPxRef.current,
177
+ itemPaddingYPx: paddingYPxRef.current,
164
178
  itemBorderRadiusPx: borderRadiusPxRef.current,
165
179
  }
166
180
  logger.info("[Layout] Submit dialog values", {
@@ -177,7 +191,7 @@ export function InsertLayoutDialog({
177
191
  }
178
192
 
179
193
  return (
180
- <>
194
+ <Flex direction="column" gap={4}>
181
195
  <Select onValueChange={setLayout} value={layout}>
182
196
  <SelectTrigger className="editor-input-lg editor-w-full">
183
197
  <SelectValue placeholder={buttonLabel} />
@@ -191,7 +205,7 @@ export function InsertLayoutDialog({
191
205
  </SelectContent>
192
206
  </Select>
193
207
  <div className="editor-layout-dialog-grid">
194
- <div className="editor-layout-dialog-group">
208
+ <Flex direction="column" gap={1.5}>
195
209
  <div className="editor-text-xs-muted">Background</div>
196
210
  <ColorPicker
197
211
  modal
@@ -227,48 +241,37 @@ export function InsertLayoutDialog({
227
241
  <ColorPickerPresets />
228
242
  </ColorPickerContent>
229
243
  </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"
244
+ </Flex>
245
+ <Flex direction="column" gap={1.5}>
246
+ <div className="editor-text-xs-muted">Padding X (px)</div>
247
+ <NumberInput
235
248
  min={0}
236
249
  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"
250
+ value={paddingXPx}
251
+ onValueChange={onPaddingXChange}
248
252
  />
249
- </div>
250
- <div className="editor-layout-dialog-group">
253
+ </Flex>
254
+ <Flex direction="column" gap={1.5}>
255
+ <div className="editor-text-xs-muted">Padding Y (px)</div>
256
+ <NumberInput
257
+ min={0}
258
+ max={64}
259
+ value={paddingYPx}
260
+ onValueChange={onPaddingYChange}
261
+ />
262
+ </Flex>
263
+ <Flex direction="column" gap={1.5}>
251
264
  <div className="editor-text-xs-muted">Border radius (px)</div>
252
- <Input
253
- type="number"
265
+ <NumberInput
254
266
  min={0}
255
267
  max={64}
256
- step={1}
257
268
  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"
269
+ onValueChange={onBorderRadiusChange}
267
270
  />
268
- </div>
271
+ </Flex>
269
272
  </div>
270
273
  <Button onClick={onClick}>{submitLabel}</Button>
271
- </>
274
+ </Flex>
272
275
  )
273
276
  }
274
277
 
@@ -339,29 +342,42 @@ export function LayoutPlugin(): JSX.Element | null {
339
342
  return match?.[1]?.trim()
340
343
  }
341
344
 
342
- const extractNumericStyle = (style: string, property: string): number | undefined => {
345
+ const extractNumericStyle = (style: string, property: string): number[] | undefined => {
343
346
  const value = extractStyleValue(style, property)
344
347
  if (!value) {
345
348
  return undefined
346
349
  }
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
350
+ // Remove !important and split by whitespace
351
+ const values = value.replace(/!important/gi, "").trim().split(/\s+/)
352
+ const parsedValues = values
353
+ .map((v) => {
354
+ const match = v.match(/^(\d+)px/i)
355
+ if (!match?.[1]) return null
356
+ const parsed = Number.parseInt(match[1], 10)
357
+ return Number.isFinite(parsed) ? parsed : null
358
+ })
359
+ .filter((v): v is number => v !== null)
360
+
361
+ if (parsedValues.length === 0) return undefined
362
+ return parsedValues
353
363
  }
354
364
 
355
365
  const buildLayoutItemStyle = ({
356
366
  itemBackgroundColor,
357
- itemPaddingPx,
367
+ itemPaddingXPx,
368
+ itemPaddingYPx,
358
369
  itemBorderRadiusPx,
359
370
  }: LayoutDialogValues): string => {
360
371
  const itemStyles: string[] = []
361
372
  if (itemBackgroundColor.trim()) {
362
373
  itemStyles.push(`background-color: ${itemBackgroundColor.trim()}`)
363
374
  }
364
- itemStyles.push(`padding: ${Math.min(Math.max(itemPaddingPx, 0), 64)}px`)
375
+ itemStyles.push(
376
+ `padding: ${Math.min(Math.max(itemPaddingYPx, 0), 64)}px ${Math.min(
377
+ Math.max(itemPaddingXPx, 0),
378
+ 64
379
+ )}px`
380
+ )
365
381
  itemStyles.push(
366
382
  `border-radius: ${Math.min(Math.max(itemBorderRadiusPx, 0), 64)}px`
367
383
  )
@@ -376,7 +392,10 @@ export function LayoutPlugin(): JSX.Element | null {
376
392
  }
377
393
 
378
394
  const background = values.itemBackgroundColor.trim()
379
- const padding = `${Math.min(Math.max(values.itemPaddingPx, 0), 64)}px`
395
+ const padding = `${Math.min(Math.max(values.itemPaddingYPx, 0), 64)}px ${Math.min(
396
+ Math.max(values.itemPaddingXPx, 0),
397
+ 64
398
+ )}px`
380
399
  const borderRadius = `${Math.min(Math.max(values.itemBorderRadiusPx, 0), 64)}px`
381
400
  if (background) {
382
401
  element.style.setProperty("background-color", background)
@@ -438,6 +457,9 @@ export function LayoutPlugin(): JSX.Element | null {
438
457
  }
439
458
 
440
459
  const style = layoutItem.getStyle()
460
+ const paddingValues = extractNumericStyle(style, "padding")
461
+ const borderRadiusValues = extractNumericStyle(style, "border-radius")
462
+
441
463
  payload = {
442
464
  containerKey: parentContainer.getKey(),
443
465
  layoutItemKey: layoutItem.getKey(),
@@ -445,8 +467,9 @@ export function LayoutPlugin(): JSX.Element | null {
445
467
  template: parentContainer.getTemplateColumns(),
446
468
  itemBackgroundColor:
447
469
  extractStyleValue(style, "background-color") ?? "#ffffff",
448
- itemPaddingPx: extractNumericStyle(style, "padding") ?? 12,
449
- itemBorderRadiusPx: extractNumericStyle(style, "border-radius") ?? 8,
470
+ itemPaddingXPx: paddingValues?.[1] ?? paddingValues?.[0] ?? 12,
471
+ itemPaddingYPx: paddingValues?.[0] ?? 12,
472
+ itemBorderRadiusPx: borderRadiusValues?.[0] ?? 8,
450
473
  },
451
474
  }
452
475
  logger.debug("[Layout] Resolved payload from target", payload)
@@ -566,12 +589,19 @@ export function LayoutPlugin(): JSX.Element | null {
566
589
  typeof payload === "string"
567
590
  ? undefined
568
591
  : payload.itemBackgroundColor?.trim()
569
- const itemPaddingPx =
592
+ const itemPaddingXPx =
593
+ typeof payload === "string"
594
+ ? undefined
595
+ : typeof payload.itemPaddingXPx === "number" &&
596
+ Number.isFinite(payload.itemPaddingXPx)
597
+ ? Math.min(Math.max(payload.itemPaddingXPx, 0), 64)
598
+ : undefined
599
+ const itemPaddingYPx =
570
600
  typeof payload === "string"
571
601
  ? undefined
572
- : typeof payload.itemPaddingPx === "number" &&
573
- Number.isFinite(payload.itemPaddingPx)
574
- ? Math.min(Math.max(payload.itemPaddingPx, 0), 64)
602
+ : typeof payload.itemPaddingYPx === "number" &&
603
+ Number.isFinite(payload.itemPaddingYPx)
604
+ ? Math.min(Math.max(payload.itemPaddingYPx, 0), 64)
575
605
  : undefined
576
606
  const itemBorderRadiusPx =
577
607
  typeof payload === "string"
@@ -584,7 +614,8 @@ export function LayoutPlugin(): JSX.Element | null {
584
614
  const itemStyle = buildLayoutItemStyle({
585
615
  template,
586
616
  itemBackgroundColor: itemBackgroundColor ?? "#ffffff",
587
- itemPaddingPx: itemPaddingPx ?? 12,
617
+ itemPaddingXPx: itemPaddingXPx ?? 12,
618
+ itemPaddingYPx: itemPaddingYPx ?? 12,
588
619
  itemBorderRadiusPx: itemBorderRadiusPx ?? 8,
589
620
  })
590
621
 
@@ -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
  }
@@ -121,6 +121,8 @@
121
121
  overflow-x: auto;
122
122
  flex-wrap: nowrap;
123
123
  border-top: $editor-border-width solid var(--border);
124
+ border-bottom-left-radius: 8px;
125
+ border-bottom-right-radius: 8px;
124
126
  padding: $editor-gap-1-5 $editor-gap-3;
125
127
  @include backdrop-blur($editor-dialog-overlay-blur * 2, color-mix(in srgb, var(--background), transparent 50%));
126
128
 
@@ -8,11 +8,11 @@
8
8
  @include flex-center;
9
9
  flex-wrap: wrap;
10
10
  gap: $editor-gap-1;
11
- border-bottom: $editor-border-width solid var(--border);
12
- border-top-left-radius: $editor-border-radius;
13
- border-top-right-radius: $editor-border-radius;
11
+ border-bottom: $editor-border-width solid var(--border) !important;
12
+ border-top-left-radius: $editor-border-radius !important;
13
+ border-top-right-radius: $editor-border-radius !important;
14
14
  @include backdrop-blur($editor-dialog-overlay-blur, rgba(255, 255, 255, 0.8));
15
- padding: $editor-gap-1;
15
+ padding: $editor-gap-2 !important;
16
16
  @include shadow-sm;
17
17
  width: 100%;
18
18
  overflow-x: visible;
@@ -23,7 +23,7 @@
23
23
  .editor-toolbar-group {
24
24
  @include flex-center;
25
25
  gap: $editor-gap-1;
26
- padding: $editor-gap-1;
26
+ padding: $editor-gap-1 !important;
27
27
  @include rounded-md;
28
28
  }
29
29
 
@@ -31,6 +31,6 @@
31
31
 
32
32
  .editor-toolbar-separator {
33
33
  height: $editor-icon-size-lg !important; // h-6 (standard separator height)
34
- margin-left: $editor-gap-1;
35
- margin-right: $editor-gap-1;
34
+ margin-left: $editor-gap-1 !important;
35
+ margin-right: $editor-gap-1 !important;
36
36
  }
@@ -17,6 +17,7 @@
17
17
  position: relative;
18
18
  padding: $editor-gap-2 $editor-gap-4;
19
19
  box-sizing: border-box; // Ensure consistent sizing
20
+ @include shadow-sm;
20
21
  @include editor-button-interactive;
21
22
 
22
23
  &:disabled {
@@ -53,7 +54,6 @@
53
54
  background-color: var(--primary);
54
55
  color: var(--primary-foreground);
55
56
  border-color: var(--primary);
56
- @include shadow-sm;
57
57
 
58
58
  &:hover {
59
59
  background-color: color-mix(in srgb, var(--primary), black 10%);
@@ -65,7 +65,6 @@
65
65
  background-color: var(--destructive);
66
66
  color: var(--destructive-foreground);
67
67
  border-color: var(--destructive);
68
- @include shadow-sm;
69
68
 
70
69
  &:hover {
71
70
  background-color: color-mix(in srgb, var(--destructive), black 10%);
@@ -114,11 +113,12 @@
114
113
  border: none;
115
114
  padding: 0;
116
115
  height: auto;
116
+ box-shadow: none !important;
117
117
 
118
118
  &:hover {
119
119
  text-decoration-line: underline;
120
120
  transform: none;
121
- box-shadow: none;
121
+ box-shadow: none !important;
122
122
  }
123
123
  }
124
124