tetrons 2.2.1 → 2.2.3

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 (42) hide show
  1. package/dist/app/layout.d.ts +1 -1
  2. package/dist/app/{layout.jsx → layout.js} +2 -5
  3. package/dist/app/page.d.ts +2 -2
  4. package/dist/app/page.js +6 -0
  5. package/dist/components/tetrons/EditorContent.d.ts +1 -2
  6. package/dist/components/tetrons/{EditorContent.jsx → EditorContent.js} +2 -24
  7. package/dist/components/tetrons/{ResizableImageComponent.jsx → ResizableImageComponent.js} +10 -12
  8. package/dist/components/tetrons/{ResizableVideoComponent.jsx → ResizableVideoComponent.js} +7 -8
  9. package/dist/components/tetrons/toolbar/ActionGroup.d.ts +1 -2
  10. package/dist/components/tetrons/toolbar/{ActionGroup.jsx → ActionGroup.js} +18 -39
  11. package/dist/components/tetrons/toolbar/ClipboardGroup.d.ts +1 -2
  12. package/dist/components/tetrons/toolbar/ClipboardGroup.js +31 -0
  13. package/dist/components/tetrons/toolbar/FileGroup.d.ts +1 -2
  14. package/dist/components/tetrons/toolbar/{FileGroup.jsx → FileGroup.js} +3 -6
  15. package/dist/components/tetrons/toolbar/FontStyleGroup.d.ts +1 -2
  16. package/dist/components/tetrons/toolbar/FontStyleGroup.js +63 -0
  17. package/dist/components/tetrons/toolbar/InsertGroup.d.ts +1 -2
  18. package/dist/components/tetrons/toolbar/InsertGroup.js +138 -0
  19. package/dist/components/tetrons/toolbar/ListAlignGroup.d.ts +1 -2
  20. package/dist/components/tetrons/toolbar/ListAlignGroup.js +7 -0
  21. package/dist/components/tetrons/toolbar/MiscGroup.d.ts +1 -2
  22. package/dist/components/tetrons/toolbar/MiscGroup.js +25 -0
  23. package/dist/components/tetrons/toolbar/TableContextMenu.d.ts +1 -2
  24. package/dist/components/tetrons/toolbar/{TableContextMenu.jsx → TableContextMenu.js} +3 -21
  25. package/dist/components/tetrons/toolbar/TetronsToolbar.d.ts +1 -2
  26. package/dist/components/tetrons/toolbar/{TetronsToolbar.jsx → TetronsToolbar.js} +2 -16
  27. package/dist/components/tetrons/toolbar/ToolbarButton.js +7 -0
  28. package/dist/index.d.mts +2 -2
  29. package/dist/index.js +1 -0
  30. package/dist/index.mjs +731 -638
  31. package/dist/styles/styles/tetrons.css +371 -0
  32. package/dist/styles/tetrons.css +371 -0
  33. package/package.json +7 -4
  34. package/dist/app/page.jsx +0 -8
  35. package/dist/components/tetrons/toolbar/ClipboardGroup.jsx +0 -36
  36. package/dist/components/tetrons/toolbar/FontStyleGroup.jsx +0 -104
  37. package/dist/components/tetrons/toolbar/InsertGroup.jsx +0 -162
  38. package/dist/components/tetrons/toolbar/ListAlignGroup.jsx +0 -16
  39. package/dist/components/tetrons/toolbar/MiscGroup.jsx +0 -31
  40. package/dist/components/tetrons/toolbar/ToolbarButton.jsx +0 -8
  41. /package/dist/components/UI/{Button.jsx → Button.js} +0 -0
  42. /package/dist/components/UI/{Dropdown.jsx → Dropdown.js} +0 -0
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "tetrons",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "A Next.js project written in TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "dev": "next dev --turbo",
9
- "build": "tsup src/index.ts --format esm,cjs --dts --out-dir dist",
9
+ "build": "tsup src/index.ts --format esm,cjs --dts --out-dir dist && copyfiles -u 1 src/styles/*.css dist/styles",
10
10
  "start": "next start",
11
11
  "lint": "next lint"
12
12
  },
@@ -42,6 +42,7 @@
42
42
  "@types/node": "^20",
43
43
  "@types/react": "^19",
44
44
  "@types/react-dom": "^19",
45
+ "copyfiles": "^2.4.1",
45
46
  "eslint": "^9",
46
47
  "eslint-config-next": "^15.3.2",
47
48
  "tailwindcss": "^4",
@@ -65,10 +66,12 @@
65
66
  "import": "./dist/index.js",
66
67
  "require": "./dist/index.js",
67
68
  "types": "./dist/index.d.ts"
68
- }
69
+ },
70
+ "./style.css": "./dist/styles/tetrons.css"
69
71
  },
70
72
  "files": [
71
- "dist"
73
+ "dist",
74
+ "dist/styles/tetrons.css"
72
75
  ],
73
76
  "bugs": {
74
77
  "url": "https://github.com/your-repo/tetrons/issues"
package/dist/app/page.jsx DELETED
@@ -1,8 +0,0 @@
1
- import EditorContent from "../components/tetrons/EditorContent";
2
- export default function Home() {
3
- return (<main className="flex flex-col h-screen overflow-hidden">
4
- <div className="flex-1 overflow-auto flex flex-col">
5
- <EditorContent />
6
- </div>
7
- </main>);
8
- }
@@ -1,36 +0,0 @@
1
- import { MdContentPaste, MdContentCut, MdContentCopy, MdFormatPaint, } from "react-icons/md";
2
- import React from "react";
3
- import ToolbarButton from "./ToolbarButton";
4
- export default function ClipboardGroup({ editor }) {
5
- return (<div className="flex gap-1 border-r pr-3">
6
- <ToolbarButton icon={MdContentPaste} title="Paste" onClick={async () => {
7
- try {
8
- const text = await navigator.clipboard.readText();
9
- editor.chain().focus().insertContent(text).run();
10
- }
11
- catch (error) {
12
- console.error("Failed to read clipboard contents:", error);
13
- }
14
- }}/>
15
- <ToolbarButton icon={MdContentCut} title="Cut" onClick={() => {
16
- const { from, to } = editor.state.selection;
17
- if (from === to)
18
- return;
19
- const selectedText = editor.state.doc.textBetween(from, to);
20
- navigator.clipboard.writeText(selectedText).then(() => {
21
- editor.chain().focus().deleteRange({ from, to }).run();
22
- });
23
- }}/>
24
- <ToolbarButton icon={MdContentCopy} title="Copy" onClick={() => {
25
- const { from, to } = editor.state.selection;
26
- if (from === to)
27
- return;
28
- const selectedText = editor.state.doc.textBetween(from, to);
29
- navigator.clipboard.writeText(selectedText);
30
- }}/>
31
- <ToolbarButton icon={MdFormatPaint} title="Format Painter" onClick={() => {
32
- const currentMarks = editor.getAttributes("textStyle");
33
- localStorage.setItem("formatPainter", JSON.stringify(currentMarks));
34
- }}/>
35
- </div>);
36
- }
@@ -1,104 +0,0 @@
1
- "use client";
2
- import { MdFormatBold, MdFormatItalic, MdFormatUnderlined, MdStrikethroughS, MdSubscript, MdSuperscript, MdFormatClear, MdFormatPaint, } from "react-icons/md";
3
- import { ImTextColor } from "react-icons/im";
4
- import { BiSolidColorFill } from "react-icons/bi";
5
- import ToolbarButton from "./ToolbarButton";
6
- import React, { useEffect, useState } from "react";
7
- export default function FontStyleGroup({ editor }) {
8
- const [textColor, setTextColor] = useState("#000000");
9
- const [highlightColor, setHighlightColor] = useState("#ffff00");
10
- const [fontFamily, setFontFamily] = useState("Arial");
11
- const [fontSize, setFontSize] = useState("16px");
12
- useEffect(() => {
13
- if (!editor)
14
- return;
15
- const updateStates = () => {
16
- var _a, _b, _c;
17
- const highlight = editor.getAttributes("highlight");
18
- setHighlightColor((highlight === null || highlight === void 0 ? void 0 : highlight.color) || "#ffff00");
19
- const color = (_a = editor.getAttributes("textStyle")) === null || _a === void 0 ? void 0 : _a.color;
20
- setTextColor(color || "#000000");
21
- const fontAttr = ((_b = editor.getAttributes("fontFamily")) === null || _b === void 0 ? void 0 : _b.font) || "Arial";
22
- setFontFamily(fontAttr);
23
- const sizeAttr = ((_c = editor.getAttributes("fontSize")) === null || _c === void 0 ? void 0 : _c.size) || "16px";
24
- setFontSize(sizeAttr);
25
- };
26
- updateStates();
27
- editor.on("selectionUpdate", updateStates);
28
- editor.on("transaction", updateStates);
29
- return () => {
30
- editor.off("selectionUpdate", updateStates);
31
- editor.off("transaction", updateStates);
32
- };
33
- }, [editor]);
34
- return (<div className="flex gap-1 border-r pr-3 items-center">
35
- <select title="Font Family" className="text-sm border rounded px-1 py-0.5 mr-2" value={fontFamily} onChange={(e) => {
36
- const value = e.target.value;
37
- setFontFamily(value);
38
- editor.chain().focus().setFontFamily(value).run();
39
- }}>
40
- <option value="Arial">Arial</option>
41
- <option value="Georgia">Georgia</option>
42
- <option value="Times New Roman">Times New Roman</option>
43
- <option value="Courier New">Courier New</option>
44
- <option value="Verdana">Verdana</option>
45
- </select>
46
-
47
- <select title="Font Size" className="text-sm border rounded px-1 py-0.5 mr-2" value={fontSize} onChange={(e) => {
48
- const value = e.target.value;
49
- setFontSize(value);
50
- editor.chain().focus().setFontSize(value).run();
51
- }}>
52
- <option value="12px">12</option>
53
- <option value="14px">14</option>
54
- <option value="16px">16</option>
55
- <option value="18px">18</option>
56
- <option value="24px">24</option>
57
- <option value="36px">36</option>
58
- <option value="48px">48</option>
59
- <option value="64px">64</option>
60
- <option value="72px">72</option>
61
- </select>
62
-
63
- <ToolbarButton icon={MdFormatBold} label="Bold" onClick={() => editor.chain().focus().toggleBold().run()} isActive={editor.isActive("bold")}/>
64
- <ToolbarButton icon={MdFormatItalic} label="Italic" onClick={() => editor.chain().focus().toggleItalic().run()} isActive={editor.isActive("italic")}/>
65
- <ToolbarButton icon={MdFormatUnderlined} label="Underline" onClick={() => editor.chain().focus().toggleUnderline().run()} isActive={editor.isActive("underline")}/>
66
- <ToolbarButton icon={MdStrikethroughS} label="Strikethrough" onClick={() => editor.chain().focus().toggleStrike().run()} isActive={editor.isActive("strike")}/>
67
- <ToolbarButton icon={MdSubscript} label="Subscript" onClick={() => editor.chain().focus().toggleSubscript().run()} isActive={editor.isActive("subscript")}/>
68
- <ToolbarButton icon={MdSuperscript} label="Superscript" onClick={() => editor.chain().focus().toggleSuperscript().run()} isActive={editor.isActive("superscript")}/>
69
-
70
- <label title="Font Color" aria-label="Font Color" className="relative w-8 h-8 flex items-center justify-center cursor-pointer color-label" style={{ "--indicator-color": textColor }}>
71
- <ImTextColor size={20} className="text-gray-700"/>
72
- <div className="color-indicator"/>
73
- <input type="color" value={textColor} onChange={(e) => {
74
- const color = e.target.value;
75
- setTextColor(color);
76
- editor.chain().focus().setColor(color).run();
77
- }} className="absolute inset-0 opacity-0 cursor-pointer"/>
78
- </label>
79
-
80
- <label title="Highlight Color" aria-label="Highlight Color" className="relative w-8 h-8 flex items-center justify-center cursor-pointer color-label" style={{ "--indicator-color": highlightColor }}>
81
- <BiSolidColorFill size={20} className="text-gray-700"/>
82
- <div className="color-indicator"/>
83
- <input type="color" value={highlightColor} onChange={(e) => {
84
- const color = e.target.value;
85
- setHighlightColor(color);
86
- editor.chain().focus().setHighlight({ color }).run();
87
- }} className="absolute inset-0 opacity-0 cursor-pointer"/>
88
- </label>
89
-
90
- <ToolbarButton icon={MdFormatClear} label="Clear Formatting" onClick={() => editor.chain().focus().unsetAllMarks().run()}/>
91
- <ToolbarButton icon={MdFormatPaint} label="Apply Painter Format" onClick={() => {
92
- const format = JSON.parse(localStorage.getItem("formatPainter") || "{}");
93
- if (format.color)
94
- editor.chain().focus().setColor(format.color).run();
95
- if (format.backgroundColor) {
96
- editor
97
- .chain()
98
- .focus()
99
- .setHighlight({ color: format.backgroundColor })
100
- .run();
101
- }
102
- }}/>
103
- </div>);
104
- }
@@ -1,162 +0,0 @@
1
- "use client";
2
- import React, { useRef, useState } from "react";
3
- import { MdTableChart, MdInsertPhoto, MdInsertLink, MdInsertComment, MdInsertEmoticon, MdHorizontalRule, MdVideoLibrary, MdOutlineOndemandVideo, } from "react-icons/md";
4
- import ToolbarButton from "./ToolbarButton";
5
- import Picker from "@emoji-mart/react";
6
- export default function InsertGroup({ editor }) {
7
- const [showTableGrid, setShowTableGrid] = useState(false);
8
- const [selectedRows, setSelectedRows] = useState(1);
9
- const [selectedCols, setSelectedCols] = useState(1);
10
- const imageInputRef = useRef(null);
11
- const videoInputRef = useRef(null);
12
- const [showPicker, setShowPicker] = useState(false);
13
- const addEmoji = (emoji) => {
14
- editor.chain().focus().insertContent(emoji.native).run();
15
- setShowPicker(false);
16
- };
17
- const handleTableCellHover = (row, col) => {
18
- setSelectedRows(row);
19
- setSelectedCols(col);
20
- };
21
- const handleTableInsert = (rows, cols) => {
22
- editor
23
- .chain()
24
- .focus()
25
- .insertTable({
26
- rows: rows || 1,
27
- cols: cols || 1,
28
- withHeaderRow: true,
29
- })
30
- .run();
31
- setShowTableGrid(false);
32
- setSelectedRows(1);
33
- setSelectedCols(1);
34
- };
35
- const handleImageUpload = (e) => {
36
- var _a;
37
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
38
- if (file) {
39
- const reader = new FileReader();
40
- reader.onload = () => {
41
- editor
42
- .chain()
43
- .focus()
44
- .setImage({ src: reader.result })
45
- .run();
46
- };
47
- reader.readAsDataURL(file);
48
- }
49
- };
50
- const handleVideoUpload = (e) => {
51
- var _a;
52
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
53
- if (file) {
54
- const reader = new FileReader();
55
- reader.onload = () => {
56
- editor
57
- .chain()
58
- .focus()
59
- .setVideo({ src: reader.result, controls: true })
60
- .run();
61
- };
62
- reader.readAsDataURL(file);
63
- }
64
- };
65
- function normalizeEmbedUrl(url) {
66
- try {
67
- const u = new URL(url);
68
- const hostname = u.hostname.replace("www.", "").toLowerCase();
69
- if (hostname === "youtube.com" || hostname === "youtu.be") {
70
- let videoId = u.searchParams.get("v");
71
- if (!videoId && hostname === "youtu.be") {
72
- videoId = u.pathname.slice(1);
73
- }
74
- if (videoId) {
75
- return `https://www.youtube.com/embed/${videoId}`;
76
- }
77
- }
78
- if (hostname === "vimeo.com") {
79
- const videoId = u.pathname.split("/")[1];
80
- if (videoId) {
81
- return `https://player.vimeo.com/video/${videoId}`;
82
- }
83
- }
84
- if (hostname === "google.com" ||
85
- hostname === "maps.google.com" ||
86
- hostname === "goo.gl") {
87
- if (url.includes("/maps/embed")) {
88
- return url;
89
- }
90
- return url.replace("/maps/", "/maps/embed/");
91
- }
92
- return url;
93
- }
94
- catch (_a) {
95
- return url;
96
- }
97
- }
98
- return (<div className="flex gap-1 border-r pr-3 relative">
99
- <input type="file" accept="image/*" ref={imageInputRef} className="hidden" onChange={handleImageUpload} aria-label="Upload Image" title="Upload Image"/>
100
- <input type="file" accept="video/*" ref={videoInputRef} className="hidden" onChange={handleVideoUpload} aria-label="Upload Video" title="Upload Video"/>
101
-
102
- <ToolbarButton icon={MdTableChart} label="Insert Table" onClick={() => setShowTableGrid(!showTableGrid)}/>
103
- {showTableGrid && (<div className="absolute top-10 left-0 bg-white border rounded shadow p-2 z-20" onMouseLeave={() => setShowTableGrid(false)}>
104
- <div className="grid grid-cols-10 gap-[1px]">
105
- {[...Array(10)].map((_, row) => [...Array(10)].map((_, col) => {
106
- const isSelected = row < selectedRows && col < selectedCols;
107
- return (<div key={`${row}-${col}`} className={`w-5 h-5 border cursor-pointer ${isSelected ? "bg-blue-500" : "bg-gray-100"}`} onMouseEnter={() => handleTableCellHover(row + 1, col + 1)} onClick={() => handleTableInsert(row + 1, col + 1)}/>);
108
- }))}
109
- </div>
110
- <div className="text-sm mt-2 text-center text-gray-600">
111
- {selectedRows} x {selectedCols}
112
- </div>
113
- </div>)}
114
-
115
- <ToolbarButton icon={MdInsertPhoto} label="Insert Image" onClick={() => { var _a; return (_a = imageInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }}/>
116
- <ToolbarButton icon={MdVideoLibrary} label="Insert Video" onClick={() => { var _a; return (_a = videoInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }}/>
117
- <ToolbarButton icon={MdInsertLink} label="Insert Link" onClick={() => {
118
- const url = prompt("Enter URL");
119
- if (url)
120
- editor
121
- .chain()
122
- .focus()
123
- .extendMarkRange("link")
124
- .setLink({ href: url })
125
- .run();
126
- }}/>
127
- <ToolbarButton icon={MdInsertComment} label="Insert Comment" onClick={() => {
128
- const comment = prompt("Enter your comment");
129
- if (comment &&
130
- editor.can().chain().focus().setComment(comment).run()) {
131
- editor.chain().focus().setComment(comment).run();
132
- }
133
- else {
134
- console.warn("Cannot apply comment — maybe no selection?");
135
- }
136
- }}/>
137
- <div className="relative">
138
- <ToolbarButton icon={MdInsertEmoticon} label="Emoji" onClick={() => setShowPicker(!showPicker)}/>
139
- {showPicker && (<div className="absolute z-50 top-10 left-0">
140
- <Picker onEmojiSelect={addEmoji} theme="auto" emoji="point_up" showPreview={false} showSkinTones={true} emojiTooltip={true}/>
141
- </div>)}
142
- </div>
143
- <ToolbarButton icon={MdHorizontalRule} label="Horizontal Line" onClick={() => editor.chain().focus().setHorizontalRule().run()}/>
144
- <ToolbarButton icon={MdOutlineOndemandVideo} label="Embed" onClick={() => {
145
- const url = prompt("Enter embed URL (YouTube, Vimeo, Google Maps, etc.)");
146
- if (!url)
147
- return;
148
- const embedUrl = normalizeEmbedUrl(url);
149
- const width = prompt("Enter width in pixels", "560");
150
- const height = prompt("Enter height in pixels", "315");
151
- editor
152
- .chain()
153
- .focus()
154
- .setEmbed({
155
- src: embedUrl,
156
- width: width ? parseInt(width) : 560,
157
- height: height ? parseInt(height) : 315,
158
- })
159
- .run();
160
- }}/>
161
- </div>);
162
- }
@@ -1,16 +0,0 @@
1
- "use client";
2
- import React from "react";
3
- import { MdFormatListBulleted, MdFormatListNumbered, MdFormatIndentDecrease, MdFormatIndentIncrease, MdFormatAlignLeft, MdFormatAlignCenter, MdFormatAlignRight, MdFormatAlignJustify, } from "react-icons/md";
4
- import ToolbarButton from "./ToolbarButton";
5
- export default function ListAlignGroup({ editor }) {
6
- return (<div className="flex gap-1 border-r pr-3">
7
- <ToolbarButton icon={MdFormatListBulleted} title="Bulleted List" onClick={() => editor.chain().focus().toggleBulletList().run()} disabled={!editor.can().toggleBulletList()}/>
8
- <ToolbarButton icon={MdFormatListNumbered} title="Numbered List" onClick={() => editor.chain().focus().toggleOrderedList().run()} disabled={!editor.can().toggleOrderedList()}/>
9
- <ToolbarButton icon={MdFormatIndentIncrease} title="Increase Indent" onClick={() => editor.chain().focus().sinkListItem("listItem").run()} disabled={!editor.can().sinkListItem("listItem")}/>
10
- <ToolbarButton icon={MdFormatIndentDecrease} title="Decrease Indent" onClick={() => editor.chain().focus().liftListItem("listItem").run()} disabled={!editor.can().liftListItem("listItem")}/>
11
- <ToolbarButton icon={MdFormatAlignLeft} title="Align Left" onClick={() => editor.chain().focus().setTextAlign("left").run()} disabled={!editor.can().setTextAlign("left")}/>
12
- <ToolbarButton icon={MdFormatAlignCenter} title="Align Center" onClick={() => editor.chain().focus().setTextAlign("center").run()} disabled={!editor.can().setTextAlign("center")}/>
13
- <ToolbarButton icon={MdFormatAlignRight} title="Align Right" onClick={() => editor.chain().focus().setTextAlign("right").run()} disabled={!editor.can().setTextAlign("right")}/>
14
- <ToolbarButton icon={MdFormatAlignJustify} title="Justify" onClick={() => editor.chain().focus().setTextAlign("justify").run()} disabled={!editor.can().setTextAlign("justify")}/>
15
- </div>);
16
- }
@@ -1,31 +0,0 @@
1
- import React from "react";
2
- import { MdUndo, MdRedo, MdRefresh, MdVisibility, MdCode, } from "react-icons/md";
3
- import ToolbarButton from "./ToolbarButton";
4
- export default function MiscGroup({ editor }) {
5
- const handlePreview = () => {
6
- const html = editor.getHTML();
7
- const previewWindow = window.open("", "_blank");
8
- if (previewWindow) {
9
- previewWindow.document.open();
10
- previewWindow.document.write(`
11
- <html>
12
- <head>
13
- <title>Preview</title>
14
- <style>
15
- body { font-family: sans-serif; padding: 2rem; line-height: 1.6; }
16
- </style>
17
- </head>
18
- <body>${html}</body>
19
- </html>
20
- `);
21
- previewWindow.document.close();
22
- }
23
- };
24
- return (<div className="flex gap-1 items-center border-r pr-3">
25
- <ToolbarButton icon={MdUndo} label="Undo" onClick={() => editor.chain().focus().undo().run()} disabled={!editor.can().undo()}/>
26
- <ToolbarButton icon={MdRedo} label="Redo" onClick={() => editor.chain().focus().redo().run()} disabled={!editor.can().redo()}/>
27
- <ToolbarButton icon={MdRefresh} label="Reset Formatting" onClick={() => editor.chain().focus().unsetAllMarks().clearNodes().run()}/>
28
- <ToolbarButton icon={MdCode} label="Toggle Code Block" onClick={() => editor.chain().focus().toggleCodeBlock().run()} isActive={editor.isActive("codeBlock")}/>
29
- <ToolbarButton icon={MdVisibility} label="Preview" onClick={handlePreview}/>
30
- </div>);
31
- }
@@ -1,8 +0,0 @@
1
- import React from "react";
2
- const ToolbarButton = React.forwardRef(({ icon: Icon, onClick, disabled = false, title, label, isActive = false }, ref) => {
3
- return (<button type="button" ref={ref} onClick={onClick} disabled={disabled} title={title !== null && title !== void 0 ? title : label} aria-label={title !== null && title !== void 0 ? title : label} className={`p-2 rounded hover:bg-gray-200 disabled:opacity-50 disabled:cursor-not-allowed ${isActive ? "bg-gray-300" : ""}`}>
4
- <Icon size={20}/>
5
- </button>);
6
- });
7
- ToolbarButton.displayName = "ToolbarButton";
8
- export default ToolbarButton;
File without changes