@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/select.tsx CHANGED
@@ -1,171 +1,171 @@
1
- import * as React from "react"
2
- import { createPortal } from "react-dom"
3
- import { cn } from "../lib/utils"
4
-
5
- interface SelectContextValue {
6
- value: string
7
- onValueChange?: (value: string) => void
8
- open: boolean
9
- setOpen: (open: boolean) => void
10
- triggerRef: React.RefObject<HTMLButtonElement | null>
11
- disabled?: boolean
12
- }
13
-
14
- const SelectContext = React.createContext<SelectContextValue | null>(null)
15
-
16
- export interface SelectProps {
17
- value: string
18
- onValueChange?: (value: string) => void
19
- children: React.ReactNode
20
- disabled?: boolean
21
- modal?: boolean
22
- }
23
-
24
- export function Select({ value, onValueChange, children, disabled }: SelectProps) {
25
- const [open, setOpen] = React.useState(false)
26
- const triggerRef = React.useRef<HTMLButtonElement>(null)
27
-
28
- const contextValue = React.useMemo(() => ({
29
- value, onValueChange, open, setOpen, triggerRef, disabled
30
- }), [value, onValueChange, open, setOpen, disabled])
31
-
32
- return (
33
- <SelectContext.Provider value={contextValue}>
34
- {children}
35
- </SelectContext.Provider>
36
- )
37
- }
38
-
39
- export interface SelectTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
40
- size?: "default" | "sm" | "lg" | "icon"
41
- }
42
-
43
- export function SelectTrigger({ className, children, size = "default", ...props }: SelectTriggerProps) {
44
- const context = React.useContext(SelectContext)
45
- if (!context) throw new Error("SelectTrigger must be used within Select")
46
-
47
- const { triggerRef, disabled, open, setOpen } = context
48
-
49
- return (
50
- <button
51
- ref={triggerRef}
52
- type="button"
53
- className={cn(
54
- "editor-select",
55
- size !== "default" && `editor-select--size-${size}`,
56
- className
57
- )}
58
- onClick={() => !disabled && setOpen(!open)}
59
- disabled={disabled || props.disabled}
60
- {...props}
61
- >
62
- {children}
63
- <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="editor-select-icon">
64
- <path d="M4.93179 5.43179C4.75605 5.60753 4.75605 5.89245 4.93179 6.06819C5.10753 6.24392 5.39245 6.24392 5.56819 6.06819L7.49999 4.13638L9.43179 6.06819C9.60753 6.24392 9.89245 6.24392 10.0682 6.06819C10.2439 5.89245 10.2439 5.60753 10.0682 5.43179L7.81819 3.18179C7.73379 3.0974 7.61933 3.04999 7.49999 3.04999C7.38064 3.04999 7.26618 3.0974 7.18179 3.18179L4.93179 5.43179ZM10.0682 9.56819C10.2439 9.39245 10.2439 9.10753 10.0682 8.93179C9.89245 8.75606 9.60753 8.75606 9.43179 8.93179L7.49999 10.8636L5.56819 8.93179C5.39245 8.75606 5.10753 8.75606 4.93179 8.93179C4.75605 9.10753 4.75605 9.39245 4.93179 9.56819L7.18179 11.8182C7.26618 11.9026 7.38064 11.95 7.49999 11.95C7.61933 11.95 7.73379 11.9026 7.81819 11.8182L10.0682 9.56819Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path>
65
- </svg>
66
- </button>
67
- )
68
- }
69
-
70
- export function SelectValue({ placeholder }: { placeholder?: string }) {
71
- const context = React.useContext(SelectContext)
72
- if (!context) throw new Error("SelectValue must be used within Select")
73
-
74
- return <span>{context.value || placeholder}</span>
75
- }
76
-
77
- export function SelectContent({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) {
78
- const context = React.useContext(SelectContext)
79
- const [position, setPosition] = React.useState({ top: 0, left: 0, width: 0 })
80
- const contentRef = React.useRef<HTMLDivElement>(null)
81
-
82
- React.useEffect(() => {
83
- if (context?.open && context.triggerRef.current) {
84
- const rect = context.triggerRef.current.getBoundingClientRect()
85
- setPosition({
86
- top: rect.bottom + window.scrollY + 4,
87
- left: rect.left + window.scrollX,
88
- width: rect.width
89
- })
90
-
91
- // Simple click outside for portal
92
- const handleClickOutside = (e: MouseEvent) => {
93
- if (contentRef.current && !contentRef.current.contains(e.target as Node) &&
94
- !context.triggerRef.current?.contains(e.target as Node)) {
95
- context.setOpen(false)
96
- }
97
- }
98
- document.addEventListener("mousedown", handleClickOutside)
99
- return () => document.removeEventListener("mousedown", handleClickOutside)
100
- }
101
- }, [context, context?.open, context?.triggerRef, context?.setOpen])
102
-
103
- if (!context?.open) return null
104
-
105
- return createPortal(
106
- <div
107
- ref={contentRef}
108
- className={cn("editor-popover-content", className)}
109
- style={{
110
- position: "absolute",
111
- top: position.top,
112
- left: position.left,
113
- minWidth: position.width,
114
- width: "auto", // allow wider
115
- padding: "4px",
116
- zIndex: 9999
117
- }}
118
- {...props}
119
- >
120
- {children}
121
- </div>,
122
- document.body
123
- )
124
- }
125
-
126
- export function SelectItem({ value, children, className, ...props }: React.HTMLAttributes<HTMLDivElement> & { value: string }) {
127
- const context = React.useContext(SelectContext)
128
- if (!context) throw new Error("SelectItem must be used within Select")
129
-
130
- const isSelected = context.value === value
131
-
132
- return (
133
- <div
134
- className={cn(
135
- "editor-select-item",
136
- className
137
- )}
138
- data-selected={isSelected}
139
- onClick={() => {
140
- context.onValueChange?.(value)
141
- context.setOpen(false)
142
- }}
143
- {...props}
144
- >
145
- {isSelected && (
146
- <span className="editor-select-item__check">
147
- <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="editor-icon-sm">
148
- <path d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path>
149
- </svg>
150
- </span>
151
- )}
152
- {children}
153
- </div>
154
- )
155
- }
156
-
157
- export function SelectGroup({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
158
- return (
159
- <div role="group" className={className} {...props}>
160
- {children}
161
- </div>
162
- )
163
- }
164
-
165
- export function SelectLabel({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
166
- return (
167
- <div className={cn("editor-select-label", className)} {...props}>
168
- {children}
169
- </div>
170
- )
171
- }
1
+ import * as React from "react"
2
+ import { createPortal } from "react-dom"
3
+ import { cn } from "../lib/utils"
4
+
5
+ interface SelectContextValue {
6
+ value: string
7
+ onValueChange?: (value: string) => void
8
+ open: boolean
9
+ setOpen: (open: boolean) => void
10
+ triggerRef: React.RefObject<HTMLButtonElement | null>
11
+ disabled?: boolean
12
+ }
13
+
14
+ const SelectContext = React.createContext<SelectContextValue | null>(null)
15
+
16
+ export interface SelectProps {
17
+ value: string
18
+ onValueChange?: (value: string) => void
19
+ children: React.ReactNode
20
+ disabled?: boolean
21
+ modal?: boolean
22
+ }
23
+
24
+ export function Select({ value, onValueChange, children, disabled }: SelectProps) {
25
+ const [open, setOpen] = React.useState(false)
26
+ const triggerRef = React.useRef<HTMLButtonElement>(null)
27
+
28
+ const contextValue = React.useMemo(() => ({
29
+ value, onValueChange, open, setOpen, triggerRef, disabled
30
+ }), [value, onValueChange, open, setOpen, disabled])
31
+
32
+ return (
33
+ <SelectContext.Provider value={contextValue}>
34
+ {children}
35
+ </SelectContext.Provider>
36
+ )
37
+ }
38
+
39
+ export interface SelectTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
40
+ size?: "default" | "sm" | "lg" | "icon"
41
+ }
42
+
43
+ export function SelectTrigger({ className, children, size = "default", ...props }: SelectTriggerProps) {
44
+ const context = React.useContext(SelectContext)
45
+ if (!context) throw new Error("SelectTrigger must be used within Select")
46
+
47
+ const { triggerRef, disabled, open, setOpen } = context
48
+
49
+ return (
50
+ <button
51
+ ref={triggerRef}
52
+ type="button"
53
+ className={cn(
54
+ "editor-select",
55
+ size !== "default" && `editor-select--size-${size}`,
56
+ className
57
+ )}
58
+ onClick={() => !disabled && setOpen(!open)}
59
+ disabled={disabled || props.disabled}
60
+ {...props}
61
+ >
62
+ {children}
63
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="editor-select-icon">
64
+ <path d="M4.93179 5.43179C4.75605 5.60753 4.75605 5.89245 4.93179 6.06819C5.10753 6.24392 5.39245 6.24392 5.56819 6.06819L7.49999 4.13638L9.43179 6.06819C9.60753 6.24392 9.89245 6.24392 10.0682 6.06819C10.2439 5.89245 10.2439 5.60753 10.0682 5.43179L7.81819 3.18179C7.73379 3.0974 7.61933 3.04999 7.49999 3.04999C7.38064 3.04999 7.26618 3.0974 7.18179 3.18179L4.93179 5.43179ZM10.0682 9.56819C10.2439 9.39245 10.2439 9.10753 10.0682 8.93179C9.89245 8.75606 9.60753 8.75606 9.43179 8.93179L7.49999 10.8636L5.56819 8.93179C5.39245 8.75606 5.10753 8.75606 4.93179 8.93179C4.75605 9.10753 4.75605 9.39245 4.93179 9.56819L7.18179 11.8182C7.26618 11.9026 7.38064 11.95 7.49999 11.95C7.61933 11.95 7.73379 11.9026 7.81819 11.8182L10.0682 9.56819Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path>
65
+ </svg>
66
+ </button>
67
+ )
68
+ }
69
+
70
+ export function SelectValue({ placeholder }: { placeholder?: string }) {
71
+ const context = React.useContext(SelectContext)
72
+ if (!context) throw new Error("SelectValue must be used within Select")
73
+
74
+ return <span>{context.value || placeholder}</span>
75
+ }
76
+
77
+ export function SelectContent({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) {
78
+ const context = React.useContext(SelectContext)
79
+ const [position, setPosition] = React.useState({ top: 0, left: 0, width: 0 })
80
+ const contentRef = React.useRef<HTMLDivElement>(null)
81
+
82
+ React.useEffect(() => {
83
+ if (context?.open && context.triggerRef.current) {
84
+ const rect = context.triggerRef.current.getBoundingClientRect()
85
+ setPosition({
86
+ top: rect.bottom + window.scrollY + 4,
87
+ left: rect.left + window.scrollX,
88
+ width: rect.width
89
+ })
90
+
91
+ // Simple click outside for portal
92
+ const handleClickOutside = (e: MouseEvent) => {
93
+ if (contentRef.current && !contentRef.current.contains(e.target as Node) &&
94
+ !context.triggerRef.current?.contains(e.target as Node)) {
95
+ context.setOpen(false)
96
+ }
97
+ }
98
+ document.addEventListener("mousedown", handleClickOutside)
99
+ return () => document.removeEventListener("mousedown", handleClickOutside)
100
+ }
101
+ }, [context, context?.open, context?.triggerRef, context?.setOpen])
102
+
103
+ if (!context?.open) return null
104
+
105
+ return createPortal(
106
+ <div
107
+ ref={contentRef}
108
+ className={cn("editor-popover-content", className)}
109
+ style={{
110
+ position: "absolute",
111
+ top: position.top,
112
+ left: position.left,
113
+ minWidth: position.width,
114
+ width: "auto", // allow wider
115
+ padding: "4px",
116
+ zIndex: 9999
117
+ }}
118
+ {...props}
119
+ >
120
+ {children}
121
+ </div>,
122
+ document.body
123
+ )
124
+ }
125
+
126
+ export function SelectItem({ value, children, className, ...props }: React.HTMLAttributes<HTMLDivElement> & { value: string }) {
127
+ const context = React.useContext(SelectContext)
128
+ if (!context) throw new Error("SelectItem must be used within Select")
129
+
130
+ const isSelected = context.value === value
131
+
132
+ return (
133
+ <div
134
+ className={cn(
135
+ "editor-select-item",
136
+ className
137
+ )}
138
+ data-selected={isSelected}
139
+ onClick={() => {
140
+ context.onValueChange?.(value)
141
+ context.setOpen(false)
142
+ }}
143
+ {...props}
144
+ >
145
+ {isSelected && (
146
+ <span className="editor-select-item__check">
147
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="editor-icon-sm">
148
+ <path d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path>
149
+ </svg>
150
+ </span>
151
+ )}
152
+ {children}
153
+ </div>
154
+ )
155
+ }
156
+
157
+ export function SelectGroup({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
158
+ return (
159
+ <div role="group" className={className} {...props}>
160
+ {children}
161
+ </div>
162
+ )
163
+ }
164
+
165
+ export function SelectLabel({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
166
+ return (
167
+ <div className={cn("editor-select-label", className)} {...props}>
168
+ {children}
169
+ </div>
170
+ )
171
+ }
@@ -1,20 +1,20 @@
1
- import * as React from "react"
2
- import { cn } from "../lib/utils"
3
-
4
- export const Separator = React.forwardRef<
5
- HTMLDivElement,
6
- React.HTMLAttributes<HTMLDivElement> & { orientation?: "horizontal" | "vertical" }
7
- >(({ className, orientation = "horizontal", ...props }, ref) => (
8
- <div
9
- ref={ref}
10
- role="separator"
11
- aria-orientation={orientation}
12
- className={cn(
13
- "editor-separator",
14
- `editor-separator--${orientation}`,
15
- className
16
- )}
17
- {...props}
18
- />
19
- ))
20
- Separator.displayName = "Separator"
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ export const Separator = React.forwardRef<
5
+ HTMLDivElement,
6
+ React.HTMLAttributes<HTMLDivElement> & { orientation?: "horizontal" | "vertical" }
7
+ >(({ className, orientation = "horizontal", ...props }, ref) => (
8
+ <div
9
+ ref={ref}
10
+ role="separator"
11
+ aria-orientation={orientation}
12
+ className={cn(
13
+ "editor-separator",
14
+ `editor-separator--${orientation}`,
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ ))
20
+ Separator.displayName = "Separator"
package/src/ui/slider.tsx CHANGED
@@ -1,14 +1,14 @@
1
- import * as React from "react"
2
- import { cn } from "../lib/utils"
3
-
4
- export const Slider = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
5
- ({ className, ...props }, ref) => (
6
- <input
7
- type="range"
8
- ref={ref}
9
- className={cn("editor-slider-input", className)}
10
- {...props}
11
- />
12
- )
13
- )
14
- Slider.displayName = "Slider"
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ export const Slider = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
5
+ ({ className, ...props }, ref) => (
6
+ <input
7
+ type="range"
8
+ ref={ref}
9
+ className={cn("editor-slider-input", className)}
10
+ {...props}
11
+ />
12
+ )
13
+ )
14
+ Slider.displayName = "Slider"
package/src/ui/slot.tsx CHANGED
@@ -1,3 +1,3 @@
1
- import { Slot as RadixSlot } from "@radix-ui/react-slot"
2
-
3
- export const Slot = RadixSlot
1
+ import { Slot as RadixSlot } from "@radix-ui/react-slot"
2
+
3
+ export const Slot = RadixSlot
package/src/ui/tabs.tsx CHANGED
@@ -1,87 +1,87 @@
1
- import * as React from "react"
2
- import { cn } from "../lib/utils"
3
-
4
- const TabsContext = React.createContext<{
5
- value: string
6
- onValueChange: (value: string) => void
7
- } | null>(null)
8
-
9
- export function Tabs({
10
- defaultValue,
11
- value: controlledValue,
12
- onValueChange,
13
- children,
14
- className,
15
- ...props
16
- }: {
17
- defaultValue?: string
18
- value?: string
19
- onValueChange?: (value: string) => void
20
- children: React.ReactNode
21
- className?: string
22
- }) {
23
- const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue || "")
24
- const value = controlledValue ?? uncontrolledValue
25
- const setValue = onValueChange ?? setUncontrolledValue
26
-
27
- return (
28
- <TabsContext.Provider value={{ value, onValueChange: setValue }}>
29
- <div className={cn(className)} {...props}>
30
- {children}
31
- </div>
32
- </TabsContext.Provider>
33
- )
34
- }
35
-
36
- export function TabsList({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) {
37
- return (
38
- <div
39
- className={cn(
40
- "editor-tabs-list",
41
- className
42
- )}
43
- {...props}
44
- >
45
- {children}
46
- </div>
47
- )
48
- }
49
-
50
- export function TabsTrigger({ value, className, children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement> & { value: string }) {
51
- const context = React.useContext(TabsContext)
52
- const isSelected = context?.value === value
53
-
54
- return (
55
- <button
56
- type="button"
57
- className={cn(
58
- "editor-tabs-trigger",
59
- className
60
- )}
61
- data-state={isSelected ? "active" : "inactive"}
62
- onClick={() => context?.onValueChange(value)}
63
- {...props}
64
- >
65
- {children}
66
- </button>
67
- )
68
- }
69
-
70
- export function TabsContent({ value, className, children, ...props }: React.HTMLAttributes<HTMLDivElement> & { value: string }) {
71
- const context = React.useContext(TabsContext)
72
- const isSelected = context?.value === value
73
-
74
- if (!isSelected) return null
75
-
76
- return (
77
- <div
78
- className={cn(
79
- "editor-tabs-content",
80
- className
81
- )}
82
- {...props}
83
- >
84
- {children}
85
- </div>
86
- )
87
- }
1
+ import * as React from "react"
2
+ import { cn } from "../lib/utils"
3
+
4
+ const TabsContext = React.createContext<{
5
+ value: string
6
+ onValueChange: (value: string) => void
7
+ } | null>(null)
8
+
9
+ export function Tabs({
10
+ defaultValue,
11
+ value: controlledValue,
12
+ onValueChange,
13
+ children,
14
+ className,
15
+ ...props
16
+ }: {
17
+ defaultValue?: string
18
+ value?: string
19
+ onValueChange?: (value: string) => void
20
+ children: React.ReactNode
21
+ className?: string
22
+ }) {
23
+ const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue || "")
24
+ const value = controlledValue ?? uncontrolledValue
25
+ const setValue = onValueChange ?? setUncontrolledValue
26
+
27
+ return (
28
+ <TabsContext.Provider value={{ value, onValueChange: setValue }}>
29
+ <div className={cn(className)} {...props}>
30
+ {children}
31
+ </div>
32
+ </TabsContext.Provider>
33
+ )
34
+ }
35
+
36
+ export function TabsList({ className, children, ...props }: React.HTMLAttributes<HTMLDivElement>) {
37
+ return (
38
+ <div
39
+ className={cn(
40
+ "editor-tabs-list",
41
+ className
42
+ )}
43
+ {...props}
44
+ >
45
+ {children}
46
+ </div>
47
+ )
48
+ }
49
+
50
+ export function TabsTrigger({ value, className, children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement> & { value: string }) {
51
+ const context = React.useContext(TabsContext)
52
+ const isSelected = context?.value === value
53
+
54
+ return (
55
+ <button
56
+ type="button"
57
+ className={cn(
58
+ "editor-tabs-trigger",
59
+ className
60
+ )}
61
+ data-state={isSelected ? "active" : "inactive"}
62
+ onClick={() => context?.onValueChange(value)}
63
+ {...props}
64
+ >
65
+ {children}
66
+ </button>
67
+ )
68
+ }
69
+
70
+ export function TabsContent({ value, className, children, ...props }: React.HTMLAttributes<HTMLDivElement> & { value: string }) {
71
+ const context = React.useContext(TabsContext)
72
+ const isSelected = context?.value === value
73
+
74
+ if (!isSelected) return null
75
+
76
+ return (
77
+ <div
78
+ className={cn(
79
+ "editor-tabs-content",
80
+ className
81
+ )}
82
+ {...props}
83
+ >
84
+ {children}
85
+ </div>
86
+ )
87
+ }