@thangph2146/lexical-editor 0.0.11 → 0.0.13

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 (46) hide show
  1. package/README.md +2 -1
  2. package/dist/editor-x/editor.cjs +280 -20
  3. package/dist/editor-x/editor.cjs.map +1 -1
  4. package/dist/editor-x/editor.css +27 -4
  5. package/dist/editor-x/editor.css.map +1 -1
  6. package/dist/editor-x/editor.js +281 -21
  7. package/dist/editor-x/editor.js.map +1 -1
  8. package/dist/index.cjs +292 -23
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.css +27 -4
  11. package/dist/index.css.map +1 -1
  12. package/dist/index.d.cts +26 -1
  13. package/dist/index.d.ts +26 -1
  14. package/dist/index.js +293 -24
  15. package/dist/index.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/components/lexical-editor.tsx +19 -6
  18. package/src/context/uploads-context.tsx +1 -0
  19. package/src/editor-ui/content-editable.tsx +18 -2
  20. package/src/editor-x/nodes.ts +2 -0
  21. package/src/nodes/download-link-node.tsx +118 -0
  22. package/src/plugins/floating-link-editor-plugin.tsx +338 -91
  23. package/src/themes/core/_tables.scss +0 -1
  24. package/src/themes/plugins/_floating-link-editor.scss +28 -2
  25. package/src/themes/ui-components/_button.scss +1 -1
  26. package/src/themes/ui-components/_flex.scss +1 -0
  27. package/src/ui/button-group.tsx +10 -10
  28. package/src/ui/button.tsx +38 -38
  29. package/src/ui/collapsible.tsx +67 -67
  30. package/src/ui/command.tsx +48 -48
  31. package/src/ui/dialog.tsx +146 -146
  32. package/src/ui/flex.tsx +45 -45
  33. package/src/ui/input.tsx +20 -20
  34. package/src/ui/label.tsx +20 -20
  35. package/src/ui/number-input.tsx +104 -104
  36. package/src/ui/popover.tsx +128 -128
  37. package/src/ui/scroll-area.tsx +17 -17
  38. package/src/ui/select.tsx +171 -171
  39. package/src/ui/separator.tsx +20 -20
  40. package/src/ui/slider.tsx +14 -14
  41. package/src/ui/slot.tsx +3 -3
  42. package/src/ui/tabs.tsx +87 -87
  43. package/src/ui/toggle-group.tsx +109 -109
  44. package/src/ui/toggle.tsx +28 -28
  45. package/src/ui/tooltip.tsx +28 -28
  46. package/src/ui/typography.tsx +44 -44
package/src/ui/dialog.tsx CHANGED
@@ -1,146 +1,146 @@
1
- import * as React from "react"
2
- import { createPortal } from "react-dom"
3
- import { cn } from "../lib/utils"
4
-
5
- interface DialogProps {
6
- open?: boolean
7
- onOpenChange?: (open: boolean) => void
8
- children: React.ReactNode
9
- }
10
-
11
- interface DialogContextValue {
12
- open: boolean
13
- onOpenChange: (open: boolean) => void
14
- }
15
-
16
- const DialogContext = React.createContext<DialogContextValue | null>(null)
17
-
18
- export function Dialog({ open = false, onOpenChange = () => {}, children }: DialogProps) {
19
- return (
20
- <DialogContext.Provider value={{ open, onOpenChange }}>
21
- {children}
22
- </DialogContext.Provider>
23
- )
24
- }
25
-
26
- export function DialogTrigger({ asChild, children, className, ...props }: React.HTMLAttributes<HTMLElement> & { asChild?: boolean, children: React.ReactNode }) {
27
- const context = React.useContext(DialogContext)
28
-
29
- const handleClick = (e: React.MouseEvent<HTMLElement>) => {
30
- context?.onOpenChange(true)
31
- if (React.isValidElement(children)) {
32
- (children as React.ReactElement<{ onClick?: React.MouseEventHandler<HTMLElement> }>).props.onClick?.(e)
33
- }
34
- }
35
-
36
- if (asChild && React.isValidElement(children)) {
37
- return React.cloneElement(children as React.ReactElement<React.HTMLAttributes<HTMLElement>>, {
38
- onClick: handleClick,
39
- ...props
40
- })
41
- }
42
-
43
- return (
44
- <button type="button" onClick={handleClick} className={className} {...props}>
45
- {children}
46
- </button>
47
- )
48
- }
49
-
50
- export function DialogClose({ asChild, children, className, ...props }: React.HTMLAttributes<HTMLElement> & { asChild?: boolean, children: React.ReactNode }) {
51
- const context = React.useContext(DialogContext)
52
-
53
- const handleClick = (e: React.MouseEvent<HTMLElement>) => {
54
- context?.onOpenChange(false)
55
- if (React.isValidElement(children)) {
56
- (children as React.ReactElement<{ onClick?: React.MouseEventHandler<HTMLElement> }>).props.onClick?.(e)
57
- }
58
- }
59
-
60
- if (asChild && React.isValidElement(children)) {
61
- return React.cloneElement(children as React.ReactElement<React.HTMLAttributes<HTMLElement>>, {
62
- onClick: handleClick,
63
- ...props
64
- })
65
- }
66
-
67
- return (
68
- <button type="button" onClick={handleClick} className={className} {...props}>
69
- {children}
70
- </button>
71
- )
72
- }
73
-
74
- export interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement> {
75
- disableOutsideClick?: boolean
76
- }
77
-
78
- export function DialogContent({ children, className, disableOutsideClick, ...props }: DialogContentProps) {
79
- const context = React.useContext(DialogContext)
80
- const [mounted, setMounted] = React.useState(false)
81
-
82
- React.useEffect(() => {
83
- setMounted(true)
84
- return () => setMounted(false)
85
- }, [])
86
-
87
- if (!mounted || !context?.open) return null
88
-
89
- const handleOverlayClick = (e: React.MouseEvent) => {
90
- if (e.target === e.currentTarget && !disableOutsideClick) {
91
- context.onOpenChange(false)
92
- }
93
- }
94
-
95
- const content = (
96
- <div
97
- className="editor-dialog-overlay"
98
- data-state="open"
99
- onClick={handleOverlayClick}
100
- >
101
- <div
102
- className={cn("editor-dialog-content", className)}
103
- data-state="open"
104
- {...props}
105
- >
106
- {children}
107
- <button
108
- type="button"
109
- className="editor-dialog-content__close"
110
- onClick={() => context.onOpenChange(false)}
111
- >
112
- <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="editor-icon-sm">
113
- <path d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path>
114
- </svg>
115
- <span className="editor-sr-only">Close</span>
116
- </button>
117
- </div>
118
- </div>
119
- )
120
-
121
- return createPortal(content, document.body)
122
- }
123
-
124
- export function DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
125
- return (
126
- <div className={cn("editor-dialog-header", className)} {...props} />
127
- )
128
- }
129
-
130
- export function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
131
- return (
132
- <div className={cn("editor-dialog-footer", className)} {...props} />
133
- )
134
- }
135
-
136
- export function DialogTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {
137
- return (
138
- <h3 className={cn("editor-dialog-header__title", className)} {...props} />
139
- )
140
- }
141
-
142
- export function DialogDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) {
143
- return (
144
- <p className={cn("editor-dialog-header__description", className)} {...props} />
145
- )
146
- }
1
+ import * as React from "react"
2
+ import { createPortal } from "react-dom"
3
+ import { cn } from "../lib/utils"
4
+
5
+ interface DialogProps {
6
+ open?: boolean
7
+ onOpenChange?: (open: boolean) => void
8
+ children: React.ReactNode
9
+ }
10
+
11
+ interface DialogContextValue {
12
+ open: boolean
13
+ onOpenChange: (open: boolean) => void
14
+ }
15
+
16
+ const DialogContext = React.createContext<DialogContextValue | null>(null)
17
+
18
+ export function Dialog({ open = false, onOpenChange = () => {}, children }: DialogProps) {
19
+ return (
20
+ <DialogContext.Provider value={{ open, onOpenChange }}>
21
+ {children}
22
+ </DialogContext.Provider>
23
+ )
24
+ }
25
+
26
+ export function DialogTrigger({ asChild, children, className, ...props }: React.HTMLAttributes<HTMLElement> & { asChild?: boolean, children: React.ReactNode }) {
27
+ const context = React.useContext(DialogContext)
28
+
29
+ const handleClick = (e: React.MouseEvent<HTMLElement>) => {
30
+ context?.onOpenChange(true)
31
+ if (React.isValidElement(children)) {
32
+ (children as React.ReactElement<{ onClick?: React.MouseEventHandler<HTMLElement> }>).props.onClick?.(e)
33
+ }
34
+ }
35
+
36
+ if (asChild && React.isValidElement(children)) {
37
+ return React.cloneElement(children as React.ReactElement<React.HTMLAttributes<HTMLElement>>, {
38
+ onClick: handleClick,
39
+ ...props
40
+ })
41
+ }
42
+
43
+ return (
44
+ <button type="button" onClick={handleClick} className={className} {...props}>
45
+ {children}
46
+ </button>
47
+ )
48
+ }
49
+
50
+ export function DialogClose({ asChild, children, className, ...props }: React.HTMLAttributes<HTMLElement> & { asChild?: boolean, children: React.ReactNode }) {
51
+ const context = React.useContext(DialogContext)
52
+
53
+ const handleClick = (e: React.MouseEvent<HTMLElement>) => {
54
+ context?.onOpenChange(false)
55
+ if (React.isValidElement(children)) {
56
+ (children as React.ReactElement<{ onClick?: React.MouseEventHandler<HTMLElement> }>).props.onClick?.(e)
57
+ }
58
+ }
59
+
60
+ if (asChild && React.isValidElement(children)) {
61
+ return React.cloneElement(children as React.ReactElement<React.HTMLAttributes<HTMLElement>>, {
62
+ onClick: handleClick,
63
+ ...props
64
+ })
65
+ }
66
+
67
+ return (
68
+ <button type="button" onClick={handleClick} className={className} {...props}>
69
+ {children}
70
+ </button>
71
+ )
72
+ }
73
+
74
+ export interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement> {
75
+ disableOutsideClick?: boolean
76
+ }
77
+
78
+ export function DialogContent({ children, className, disableOutsideClick, ...props }: DialogContentProps) {
79
+ const context = React.useContext(DialogContext)
80
+ const [mounted, setMounted] = React.useState(false)
81
+
82
+ React.useEffect(() => {
83
+ setMounted(true)
84
+ return () => setMounted(false)
85
+ }, [])
86
+
87
+ if (!mounted || !context?.open) return null
88
+
89
+ const handleOverlayClick = (e: React.MouseEvent) => {
90
+ if (e.target === e.currentTarget && !disableOutsideClick) {
91
+ context.onOpenChange(false)
92
+ }
93
+ }
94
+
95
+ const content = (
96
+ <div
97
+ className="editor-dialog-overlay"
98
+ data-state="open"
99
+ onClick={handleOverlayClick}
100
+ >
101
+ <div
102
+ className={cn("editor-dialog-content", className)}
103
+ data-state="open"
104
+ {...props}
105
+ >
106
+ {children}
107
+ <button
108
+ type="button"
109
+ className="editor-dialog-content__close"
110
+ onClick={() => context.onOpenChange(false)}
111
+ >
112
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="editor-icon-sm">
113
+ <path d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path>
114
+ </svg>
115
+ <span className="editor-sr-only">Close</span>
116
+ </button>
117
+ </div>
118
+ </div>
119
+ )
120
+
121
+ return createPortal(content, document.body)
122
+ }
123
+
124
+ export function DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
125
+ return (
126
+ <div className={cn("editor-dialog-header", className)} {...props} />
127
+ )
128
+ }
129
+
130
+ export function DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
131
+ return (
132
+ <div className={cn("editor-dialog-footer", className)} {...props} />
133
+ )
134
+ }
135
+
136
+ export function DialogTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {
137
+ return (
138
+ <h3 className={cn("editor-dialog-header__title", className)} {...props} />
139
+ )
140
+ }
141
+
142
+ export function DialogDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) {
143
+ return (
144
+ <p className={cn("editor-dialog-header__description", className)} {...props} />
145
+ )
146
+ }
package/src/ui/flex.tsx CHANGED
@@ -1,45 +1,45 @@
1
- import * as React from "react"
2
- import { cn } from "../lib/utils"
3
-
4
- export interface FlexProps extends React.HTMLAttributes<HTMLDivElement> {
5
- align?: "start" | "center" | "end" | "baseline" | "stretch"
6
- justify?: "start" | "center" | "end" | "between" | "around" | "evenly"
7
- direction?: "row" | "column" | "row-reverse" | "column-reverse"
8
- wrap?: "nowrap" | "wrap" | "wrap-reverse"
9
- gap?: number | string
10
- }
11
-
12
- export const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
13
- ({ className, align, justify, direction, wrap, gap, style, ...props }, ref) => {
14
- const isStandardGap =
15
- typeof gap === "number" && [0.5, 1, 1.5, 2, 3, 4, 5].includes(gap)
16
- const gapClass = isStandardGap
17
- ? `editor-gap-${gap.toString().replace(".", "-")}`
18
- : undefined
19
-
20
- const gapStyle =
21
- !isStandardGap && typeof gap === "number"
22
- ? { gap: `${gap * 0.25}rem` }
23
- : !isStandardGap && typeof gap !== "undefined"
24
- ? { gap }
25
- : undefined
26
-
27
- return (
28
- <div
29
- ref={ref}
30
- className={cn(
31
- "editor-flex",
32
- align && `editor-items-${align}`,
33
- justify && `editor-justify-${justify}`,
34
- direction && `editor-flex-${direction}`,
35
- wrap && `editor-flex-${wrap}`,
36
- gapClass,
37
- className
38
- )}
39
- style={{ ...gapStyle, ...style }}
40
- {...props}
41
- />
42
- )
43
- }
44
- )
45
- Flex.displayName = "Flex"
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ export interface FlexProps extends React.HTMLAttributes<HTMLDivElement> {
5
+ align?: "start" | "center" | "end" | "baseline" | "stretch"
6
+ justify?: "start" | "center" | "end" | "between" | "around" | "evenly"
7
+ direction?: "row" | "column" | "row-reverse" | "column-reverse"
8
+ wrap?: "nowrap" | "wrap" | "wrap-reverse"
9
+ gap?: number | string
10
+ }
11
+
12
+ export const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
13
+ ({ className, align, justify, direction, wrap, gap, style, ...props }, ref) => {
14
+ const isStandardGap =
15
+ typeof gap === "number" && [0.5, 1, 1.5, 2, 3, 4, 5].includes(gap)
16
+ const gapClass = isStandardGap
17
+ ? `editor-gap-${gap.toString().replace(".", "-")}`
18
+ : undefined
19
+
20
+ const gapStyle =
21
+ !isStandardGap && typeof gap === "number"
22
+ ? { gap: `${gap * 0.25}rem` }
23
+ : !isStandardGap && typeof gap !== "undefined"
24
+ ? { gap }
25
+ : undefined
26
+
27
+ return (
28
+ <div
29
+ ref={ref}
30
+ className={cn(
31
+ "editor-flex",
32
+ align && `editor-items-${align}`,
33
+ justify && `editor-justify-${justify}`,
34
+ direction && `editor-flex-${direction}`,
35
+ wrap && `editor-flex-${wrap}`,
36
+ gapClass,
37
+ className
38
+ )}
39
+ style={{ ...gapStyle, ...style }}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+ )
45
+ Flex.displayName = "Flex"
package/src/ui/input.tsx CHANGED
@@ -1,20 +1,20 @@
1
- import * as React from "react"
2
- import { cn } from "../lib/utils"
3
-
4
- export type InputProps = React.InputHTMLAttributes<HTMLInputElement>
5
-
6
- const Input = React.forwardRef<HTMLInputElement, InputProps>(
7
- ({ className, type, ...props }, ref) => {
8
- return (
9
- <input
10
- type={type}
11
- className={cn("editor-input", className)}
12
- ref={ref}
13
- {...props}
14
- />
15
- )
16
- }
17
- )
18
- Input.displayName = "Input"
19
-
20
- export { Input }
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ export type InputProps = React.InputHTMLAttributes<HTMLInputElement>
5
+
6
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(
7
+ ({ className, type, ...props }, ref) => {
8
+ return (
9
+ <input
10
+ type={type}
11
+ className={cn("editor-input", className)}
12
+ ref={ref}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+ )
18
+ Input.displayName = "Input"
19
+
20
+ export { Input }
package/src/ui/label.tsx CHANGED
@@ -1,20 +1,20 @@
1
- import * as React from "react"
2
- import { cn } from "../lib/utils"
3
-
4
- const Label = React.forwardRef<
5
- HTMLLabelElement,
6
- React.LabelHTMLAttributes<HTMLLabelElement>
7
- >(({ className, ...props }, ref) => (
8
- <label
9
- ref={ref}
10
- className={cn(
11
- "editor-label",
12
- props["aria-disabled"] && "editor-label--disabled",
13
- className
14
- )}
15
- {...props}
16
- />
17
- ))
18
- Label.displayName = "Label"
19
-
20
- export { Label }
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ const Label = React.forwardRef<
5
+ HTMLLabelElement,
6
+ React.LabelHTMLAttributes<HTMLLabelElement>
7
+ >(({ className, ...props }, ref) => (
8
+ <label
9
+ ref={ref}
10
+ className={cn(
11
+ "editor-label",
12
+ props["aria-disabled"] && "editor-label--disabled",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ ))
18
+ Label.displayName = "Label"
19
+
20
+ export { Label }