tetrons 2.2.1 → 2.2.2

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.
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import type { Metadata } from "next";
3
2
  import "./globals.css";
4
3
  export declare const metadata: Metadata;
@@ -1,2 +1,2 @@
1
- /// <reference types="react" />
1
+ import "../styles/tetrons.css";
2
2
  export default function Home(): import("react").JSX.Element;
package/dist/app/page.jsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import EditorContent from "../components/tetrons/EditorContent";
2
+ import "../styles/tetrons.css";
2
3
  export default function Home() {
3
4
  return (<main className="flex flex-col h-screen overflow-hidden">
4
5
  <div className="flex-1 overflow-auto flex flex-col">
@@ -133,28 +133,26 @@ export default function EditorContent() {
133
133
  setCurrentVersionIndex(index);
134
134
  }
135
135
  };
136
- return (<div className="flex flex-col h-full">
137
- <div className="p-2 border-b border-gray-300 bg-gray-50 flex flex-wrap items-center gap-3">
138
- <button onClick={saveVersion} disabled={!editor} className="px-3 py-1 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50">
136
+ return (<div className="editor-container">
137
+ <div className="editor-toolbar">
138
+ <button type="button" onClick={saveVersion} disabled={!editor} className="editor-save-btn">
139
139
  Save Version
140
140
  </button>
141
141
 
142
- <div className="flex items-center gap-2 overflow-x-auto max-w-full">
143
- {versions.length === 0 && (<span className="text-gray-500 text-sm">No saved versions</span>)}
144
- {versions.map((_, idx) => (<button key={idx} onClick={() => restoreVersion(idx)} className={`px-2 py-1 rounded border ${idx === currentVersionIndex
145
- ? "border-blue-600 font-semibold text-blue-600"
146
- : "border-gray-300 text-gray-700 hover:border-gray-600"}`} title={`Restore Version ${idx + 1}`}>
142
+ <div className="editor-versions-wrapper">
143
+ {versions.length === 0 && (<span className="editor-no-versions">No saved versions</span>)}
144
+ {versions.map((_, idx) => (<button type="button" key={idx} onClick={() => restoreVersion(idx)} className={`editor-version-btn ${idx === currentVersionIndex ? "active" : ""}`} title={`Restore Version ${idx + 1}`}>
147
145
  {`V${idx + 1}`}
148
146
  </button>))}
149
147
  </div>
150
148
  </div>
151
149
 
152
150
  {editor && <TetronsToolbar editor={editor}/>}
153
- <div ref={wrapperRef} className="flex-grow p-4 md:p-6 bg-white border border-gray-300 rounded shadow-sm overflow-auto min-h-0 prose relative" onClick={handleEditorClick}>
151
+ <div ref={wrapperRef} className="editor-content-wrapper" onClick={handleEditorClick}>
154
152
  {editor ? (<>
155
153
  <TiptapEditorContent editor={editor}/>
156
154
  {editor && <TableContextMenu editor={editor}/>}
157
- </>) : (<div className="text-gray-500">Loading editor...</div>)}
155
+ </>) : (<div className="editor-loading">Loading editor...</div>)}
158
156
  </div>
159
157
  </div>);
160
158
  }
@@ -25,17 +25,19 @@ export default function ActionGroup({ editor }) {
25
25
  const zoomIn = () => {
26
26
  const element = document.querySelector(".ProseMirror");
27
27
  if (element) {
28
- const currentZoom = parseFloat(element.style.zoom || "1");
28
+ const style = element.style;
29
+ const currentZoom = parseFloat(style.zoom || "1");
29
30
  const next = Math.min(currentZoom + 0.1, 2);
30
- element.style.zoom = next.toString();
31
+ style.zoom = next.toString();
31
32
  }
32
33
  };
33
34
  const zoomOut = () => {
34
35
  const element = document.querySelector(".ProseMirror");
35
36
  if (element) {
36
- const currentZoom = parseFloat(element.style.zoom || "1");
37
+ const style = element.style;
38
+ const currentZoom = parseFloat(style.zoom || "1");
37
39
  const next = Math.max(currentZoom - 0.1, 0.5);
38
- element.style.zoom = next.toString();
40
+ style.zoom = next.toString();
39
41
  }
40
42
  };
41
43
  const handlePrint = () => {
@@ -128,35 +130,35 @@ export default function ActionGroup({ editor }) {
128
130
  link.click();
129
131
  document.body.removeChild(link);
130
132
  };
131
- return (<div className="relative flex items-center gap-1" role="group" aria-label="Editor actions">
133
+ return (<div className="action-group" role="group" aria-label="Editor actions">
132
134
  <ToolbarButton icon={MdZoomIn} onClick={zoomIn} title="Zoom In"/>
133
135
  <ToolbarButton icon={MdZoomOut} onClick={zoomOut} title="Zoom Out"/>
134
136
  <ToolbarButton icon={MdPrint} onClick={handlePrint} title="Print"/>
135
137
  <ToolbarButton icon={MdSave} onClick={handleSave} title="Save"/>
136
138
 
137
139
  <div className="relative" ref={dropdownRef}>
138
- <button type="button" onClick={() => setDropdownOpen((open) => !open)} aria-haspopup="menu" aria-expanded={dropdownOpen ? "true" : "false"} className="flex items-center gap-1 px-2 py-1 rounded hover:bg-gray-100 focus:outline-none" title="Export">
140
+ <button type="button" onClick={() => setDropdownOpen((open) => !open)} aria-haspopup="menu" aria-expanded={dropdownOpen ? "true" : "false"} className="export-button" title="Export">
139
141
  <MdDownload />
140
142
  <span className="text-sm"></span>
141
143
  </button>
142
144
 
143
- {dropdownOpen && (<div className="absolute z-10 mt-2 w-40 bg-white border rounded shadow-md">
145
+ {dropdownOpen && (<div className="export-dropdown">
144
146
  <button type="button" onClick={() => {
145
147
  setDropdownOpen(false);
146
148
  handleDownloadPDF();
147
- }} className="w-full text-left px-4 py-2 hover:bg-gray-100">
149
+ }}>
148
150
  Export as PDF
149
151
  </button>
150
152
  <button type="button" onClick={() => {
151
153
  setDropdownOpen(false);
152
154
  handleDownloadHTML();
153
- }} className="w-full text-left px-4 py-2 hover:bg-gray-100">
155
+ }}>
154
156
  Export as HTML
155
157
  </button>
156
158
  <button type="button" onClick={() => {
157
159
  setDropdownOpen(false);
158
160
  handleDownloadDOCX();
159
- }} className="w-full text-left px-4 py-2 hover:bg-gray-100">
161
+ }}>
160
162
  Export as DOCX
161
163
  </button>
162
164
  </div>)}
@@ -2,7 +2,7 @@ import { MdContentPaste, MdContentCut, MdContentCopy, MdFormatPaint, } from "rea
2
2
  import React from "react";
3
3
  import ToolbarButton from "./ToolbarButton";
4
4
  export default function ClipboardGroup({ editor }) {
5
- return (<div className="flex gap-1 border-r pr-3">
5
+ return (<div className="clipboard-group">
6
6
  <ToolbarButton icon={MdContentPaste} title="Paste" onClick={async () => {
7
7
  try {
8
8
  const text = await navigator.clipboard.readText();
@@ -32,7 +32,7 @@ export default function FileGroup({ editor }) {
32
32
  e.target.value = "";
33
33
  }
34
34
  };
35
- return (<div className="flex items-center gap-1 border-r pr-3" role="group" aria-label="File actions">
35
+ return (<div className="file-group" role="group" aria-label="File actions">
36
36
  <input type="file" accept=".json" ref={fileInputRef} onChange={handleFileChange} className="hidden" aria-label="Open JSON file"/>
37
37
  <ToolbarButton icon={VscNewFile} onClick={handleNew} title="New"/>
38
38
  <ToolbarButton icon={FaRegFolderOpen} onClick={handleOpen} title="Open File"/>
@@ -31,8 +31,8 @@ export default function FontStyleGroup({ editor }) {
31
31
  editor.off("transaction", updateStates);
32
32
  };
33
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) => {
34
+ return (<div className="font-style-group">
35
+ <select title="Font Family" value={fontFamily} onChange={(e) => {
36
36
  const value = e.target.value;
37
37
  setFontFamily(value);
38
38
  editor.chain().focus().setFontFamily(value).run();
@@ -44,7 +44,7 @@ export default function FontStyleGroup({ editor }) {
44
44
  <option value="Verdana">Verdana</option>
45
45
  </select>
46
46
 
47
- <select title="Font Size" className="text-sm border rounded px-1 py-0.5 mr-2" value={fontSize} onChange={(e) => {
47
+ <select title="Font Size" value={fontSize} onChange={(e) => {
48
48
  const value = e.target.value;
49
49
  setFontSize(value);
50
50
  editor.chain().focus().setFontSize(value).run();
@@ -67,24 +67,24 @@ export default function FontStyleGroup({ editor }) {
67
67
  <ToolbarButton icon={MdSubscript} label="Subscript" onClick={() => editor.chain().focus().toggleSubscript().run()} isActive={editor.isActive("subscript")}/>
68
68
  <ToolbarButton icon={MdSuperscript} label="Superscript" onClick={() => editor.chain().focus().toggleSuperscript().run()} isActive={editor.isActive("superscript")}/>
69
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"/>
70
+ <label title="Font Color" aria-label="Font Color" className="color-label" style={{ "--indicator-color": textColor }}>
71
+ <ImTextColor size={20}/>
72
72
  <div className="color-indicator"/>
73
73
  <input type="color" value={textColor} onChange={(e) => {
74
74
  const color = e.target.value;
75
75
  setTextColor(color);
76
76
  editor.chain().focus().setColor(color).run();
77
- }} className="absolute inset-0 opacity-0 cursor-pointer"/>
77
+ }}/>
78
78
  </label>
79
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"/>
80
+ <label title="Highlight Color" aria-label="Highlight Color" className="color-label" style={{ "--indicator-color": highlightColor }}>
81
+ <BiSolidColorFill size={20}/>
82
82
  <div className="color-indicator"/>
83
83
  <input type="color" value={highlightColor} onChange={(e) => {
84
84
  const color = e.target.value;
85
85
  setHighlightColor(color);
86
86
  editor.chain().focus().setHighlight({ color }).run();
87
- }} className="absolute inset-0 opacity-0 cursor-pointer"/>
87
+ }}/>
88
88
  </label>
89
89
 
90
90
  <ToolbarButton icon={MdFormatClear} label="Clear Formatting" onClick={() => editor.chain().focus().unsetAllMarks().run()}/>
@@ -95,19 +95,19 @@ export default function InsertGroup({ editor }) {
95
95
  return url;
96
96
  }
97
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"/>
98
+ return (<div className="insert-group">
99
+ <input type="file" accept="image/*" ref={imageInputRef} className="hidden-input" onChange={handleImageUpload} aria-label="Upload Image" title="Upload Image"/>
100
+ <input type="file" accept="video/*" ref={videoInputRef} className="hidden-input" onChange={handleVideoUpload} aria-label="Upload Video" title="Upload Video"/>
101
101
 
102
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]">
103
+ {showTableGrid && (<div className="table-grid-popup" onMouseLeave={() => setShowTableGrid(false)}>
104
+ <div className="table-grid">
105
105
  {[...Array(10)].map((_, row) => [...Array(10)].map((_, col) => {
106
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)}/>);
107
+ return (<div key={`${row}-${col}`} className={`table-grid-cell ${isSelected ? "selected" : ""}`} onMouseEnter={() => handleTableCellHover(row + 1, col + 1)} onClick={() => handleTableInsert(row + 1, col + 1)}/>);
108
108
  }))}
109
109
  </div>
110
- <div className="text-sm mt-2 text-center text-gray-600">
110
+ <div className="table-grid-label">
111
111
  {selectedRows} x {selectedCols}
112
112
  </div>
113
113
  </div>)}
@@ -116,13 +116,14 @@ export default function InsertGroup({ editor }) {
116
116
  <ToolbarButton icon={MdVideoLibrary} label="Insert Video" onClick={() => { var _a; return (_a = videoInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }}/>
117
117
  <ToolbarButton icon={MdInsertLink} label="Insert Link" onClick={() => {
118
118
  const url = prompt("Enter URL");
119
- if (url)
119
+ if (url) {
120
120
  editor
121
121
  .chain()
122
122
  .focus()
123
123
  .extendMarkRange("link")
124
124
  .setLink({ href: url })
125
125
  .run();
126
+ }
126
127
  }}/>
127
128
  <ToolbarButton icon={MdInsertComment} label="Insert Comment" onClick={() => {
128
129
  const comment = prompt("Enter your comment");
@@ -136,7 +137,7 @@ export default function InsertGroup({ editor }) {
136
137
  }}/>
137
138
  <div className="relative">
138
139
  <ToolbarButton icon={MdInsertEmoticon} label="Emoji" onClick={() => setShowPicker(!showPicker)}/>
139
- {showPicker && (<div className="absolute z-50 top-10 left-0">
140
+ {showPicker && (<div className="emoji-picker">
140
141
  <Picker onEmojiSelect={addEmoji} theme="auto" emoji="point_up" showPreview={false} showSkinTones={true} emojiTooltip={true}/>
141
142
  </div>)}
142
143
  </div>
@@ -3,7 +3,7 @@ import React from "react";
3
3
  import { MdFormatListBulleted, MdFormatListNumbered, MdFormatIndentDecrease, MdFormatIndentIncrease, MdFormatAlignLeft, MdFormatAlignCenter, MdFormatAlignRight, MdFormatAlignJustify, } from "react-icons/md";
4
4
  import ToolbarButton from "./ToolbarButton";
5
5
  export default function ListAlignGroup({ editor }) {
6
- return (<div className="flex gap-1 border-r pr-3">
6
+ return (<div className="list-align-group">
7
7
  <ToolbarButton icon={MdFormatListBulleted} title="Bulleted List" onClick={() => editor.chain().focus().toggleBulletList().run()} disabled={!editor.can().toggleBulletList()}/>
8
8
  <ToolbarButton icon={MdFormatListNumbered} title="Numbered List" onClick={() => editor.chain().focus().toggleOrderedList().run()} disabled={!editor.can().toggleOrderedList()}/>
9
9
  <ToolbarButton icon={MdFormatIndentIncrease} title="Increase Indent" onClick={() => editor.chain().focus().sinkListItem("listItem").run()} disabled={!editor.can().sinkListItem("listItem")}/>
@@ -21,7 +21,7 @@ export default function MiscGroup({ editor }) {
21
21
  previewWindow.document.close();
22
22
  }
23
23
  };
24
- return (<div className="flex gap-1 items-center border-r pr-3">
24
+ return (<div className="misc-group">
25
25
  <ToolbarButton icon={MdUndo} label="Undo" onClick={() => editor.chain().focus().undo().run()} disabled={!editor.can().undo()}/>
26
26
  <ToolbarButton icon={MdRedo} label="Redo" onClick={() => editor.chain().focus().redo().run()} disabled={!editor.can().redo()}/>
27
27
  <ToolbarButton icon={MdRefresh} label="Reset Formatting" onClick={() => editor.chain().focus().unsetAllMarks().clearNodes().run()}/>
@@ -27,12 +27,10 @@ export default function TetronsToolbar({ editor }) {
27
27
  editor.off("update", handleUpdate);
28
28
  };
29
29
  }, [autoSave, editor]);
30
- return (<div className="flex flex-wrap items-center gap-4 p-3 border-b bg-white shadow-sm relative z-10">
31
- <div className="flex items-center gap-2 border-r pr-3">
32
- <input type="checkbox" id="autoSave" checked={autoSave} onChange={(e) => setAutoSave(e.target.checked)} className="w-4 h-4"/>
33
- <label htmlFor="autoSave" className="text-sm select-none">
34
- Auto Save
35
- </label>
30
+ return (<div className="tetrons-toolbar">
31
+ <div className="group">
32
+ <input type="checkbox" id="autoSave" checked={autoSave} onChange={(e) => setAutoSave(e.target.checked)}/>
33
+ <label htmlFor="autoSave">Auto Save</label>
36
34
  </div>
37
35
 
38
36
  <FileGroup editor={editor}/>
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as EditorContent } from "./components/tetrons/EditorContent";
2
+ import "./styles/tetrons.css";
2
3
  import EditorContent from "./components/tetrons/EditorContent";
3
4
  export default EditorContent;
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as EditorContent } from "./components/tetrons/EditorContent";
2
+ import "./styles/tetrons.css";
2
3
  import EditorContent from "./components/tetrons/EditorContent";
3
4
  export default EditorContent;
package/dist/index.mjs CHANGED
@@ -14504,64 +14504,49 @@ function ActionGroup({ editor }) {
14504
14504
  link.click();
14505
14505
  document.body.removeChild(link);
14506
14506
  };
14507
- return /* @__PURE__ */ React2.createElement(
14508
- "div",
14507
+ return /* @__PURE__ */ React2.createElement("div", { className: "action-group", role: "group", "aria-label": "Editor actions" }, /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdZoomIn, onClick: zoomIn, title: "Zoom In" }), /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdZoomOut, onClick: zoomOut, title: "Zoom Out" }), /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdPrint, onClick: handlePrint, title: "Print" }), /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdSave, onClick: handleSave, title: "Save" }), /* @__PURE__ */ React2.createElement("div", { className: "relative", ref: dropdownRef }, /* @__PURE__ */ React2.createElement(
14508
+ "button",
14509
14509
  {
14510
- className: "relative flex items-center gap-1",
14511
- role: "group",
14512
- "aria-label": "Editor actions"
14510
+ type: "button",
14511
+ onClick: () => setDropdownOpen((open) => !open),
14512
+ "aria-haspopup": "menu",
14513
+ "aria-expanded": dropdownOpen ? "true" : "false",
14514
+ className: "export-button",
14515
+ title: "Export"
14513
14516
  },
14514
- /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdZoomIn, onClick: zoomIn, title: "Zoom In" }),
14515
- /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdZoomOut, onClick: zoomOut, title: "Zoom Out" }),
14516
- /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdPrint, onClick: handlePrint, title: "Print" }),
14517
- /* @__PURE__ */ React2.createElement(ToolbarButton_default, { icon: MdSave, onClick: handleSave, title: "Save" }),
14518
- /* @__PURE__ */ React2.createElement("div", { className: "relative", ref: dropdownRef }, /* @__PURE__ */ React2.createElement(
14519
- "button",
14520
- {
14521
- type: "button",
14522
- onClick: () => setDropdownOpen((open) => !open),
14523
- "aria-haspopup": "menu",
14524
- "aria-expanded": dropdownOpen ? "true" : "false",
14525
- className: "flex items-center gap-1 px-2 py-1 rounded hover:bg-gray-100 focus:outline-none",
14526
- title: "Export"
14527
- },
14528
- /* @__PURE__ */ React2.createElement(MdDownload, null),
14529
- /* @__PURE__ */ React2.createElement("span", { className: "text-sm" })
14530
- ), dropdownOpen && /* @__PURE__ */ React2.createElement("div", { className: "absolute z-10 mt-2 w-40 bg-white border rounded shadow-md" }, /* @__PURE__ */ React2.createElement(
14531
- "button",
14532
- {
14533
- type: "button",
14534
- onClick: () => {
14535
- setDropdownOpen(false);
14536
- handleDownloadPDF();
14537
- },
14538
- className: "w-full text-left px-4 py-2 hover:bg-gray-100"
14539
- },
14540
- "Export as PDF"
14541
- ), /* @__PURE__ */ React2.createElement(
14542
- "button",
14543
- {
14544
- type: "button",
14545
- onClick: () => {
14546
- setDropdownOpen(false);
14547
- handleDownloadHTML();
14548
- },
14549
- className: "w-full text-left px-4 py-2 hover:bg-gray-100"
14550
- },
14551
- "Export as HTML"
14552
- ), /* @__PURE__ */ React2.createElement(
14553
- "button",
14554
- {
14555
- type: "button",
14556
- onClick: () => {
14557
- setDropdownOpen(false);
14558
- handleDownloadDOCX();
14559
- },
14560
- className: "w-full text-left px-4 py-2 hover:bg-gray-100"
14561
- },
14562
- "Export as DOCX"
14563
- )))
14564
- );
14517
+ /* @__PURE__ */ React2.createElement(MdDownload, null),
14518
+ /* @__PURE__ */ React2.createElement("span", { className: "text-sm" })
14519
+ ), dropdownOpen && /* @__PURE__ */ React2.createElement("div", { className: "export-dropdown" }, /* @__PURE__ */ React2.createElement(
14520
+ "button",
14521
+ {
14522
+ type: "button",
14523
+ onClick: () => {
14524
+ setDropdownOpen(false);
14525
+ handleDownloadPDF();
14526
+ }
14527
+ },
14528
+ "Export as PDF"
14529
+ ), /* @__PURE__ */ React2.createElement(
14530
+ "button",
14531
+ {
14532
+ type: "button",
14533
+ onClick: () => {
14534
+ setDropdownOpen(false);
14535
+ handleDownloadHTML();
14536
+ }
14537
+ },
14538
+ "Export as HTML"
14539
+ ), /* @__PURE__ */ React2.createElement(
14540
+ "button",
14541
+ {
14542
+ type: "button",
14543
+ onClick: () => {
14544
+ setDropdownOpen(false);
14545
+ handleDownloadDOCX();
14546
+ }
14547
+ },
14548
+ "Export as DOCX"
14549
+ ))));
14565
14550
  }
14566
14551
 
14567
14552
  // src/components/tetrons/toolbar/ClipboardGroup.tsx
@@ -14573,7 +14558,7 @@ import {
14573
14558
  } from "react-icons/md";
14574
14559
  import React3 from "react";
14575
14560
  function ClipboardGroup({ editor }) {
14576
- return /* @__PURE__ */ React3.createElement("div", { className: "flex gap-1 border-r pr-3" }, /* @__PURE__ */ React3.createElement(
14561
+ return /* @__PURE__ */ React3.createElement("div", { className: "clipboard-group" }, /* @__PURE__ */ React3.createElement(
14577
14562
  ToolbarButton_default,
14578
14563
  {
14579
14564
  icon: MdContentPaste,
@@ -14665,11 +14650,10 @@ function FontStyleGroup({ editor }) {
14665
14650
  editor.off("transaction", updateStates);
14666
14651
  };
14667
14652
  }, [editor]);
14668
- return /* @__PURE__ */ React4.createElement("div", { className: "flex gap-1 border-r pr-3 items-center" }, /* @__PURE__ */ React4.createElement(
14653
+ return /* @__PURE__ */ React4.createElement("div", { className: "font-style-group" }, /* @__PURE__ */ React4.createElement(
14669
14654
  "select",
14670
14655
  {
14671
14656
  title: "Font Family",
14672
- className: "text-sm border rounded px-1 py-0.5 mr-2",
14673
14657
  value: fontFamily,
14674
14658
  onChange: (e) => {
14675
14659
  const value = e.target.value;
@@ -14686,7 +14670,6 @@ function FontStyleGroup({ editor }) {
14686
14670
  "select",
14687
14671
  {
14688
14672
  title: "Font Size",
14689
- className: "text-sm border rounded px-1 py-0.5 mr-2",
14690
14673
  value: fontSize,
14691
14674
  onChange: (e) => {
14692
14675
  const value = e.target.value;
@@ -14756,10 +14739,10 @@ function FontStyleGroup({ editor }) {
14756
14739
  {
14757
14740
  title: "Font Color",
14758
14741
  "aria-label": "Font Color",
14759
- className: "relative w-8 h-8 flex items-center justify-center cursor-pointer color-label",
14742
+ className: "color-label",
14760
14743
  style: { "--indicator-color": textColor }
14761
14744
  },
14762
- /* @__PURE__ */ React4.createElement(ImTextColor, { size: 20, className: "text-gray-700" }),
14745
+ /* @__PURE__ */ React4.createElement(ImTextColor, { size: 20 }),
14763
14746
  /* @__PURE__ */ React4.createElement("div", { className: "color-indicator" }),
14764
14747
  /* @__PURE__ */ React4.createElement(
14765
14748
  "input",
@@ -14770,8 +14753,7 @@ function FontStyleGroup({ editor }) {
14770
14753
  const color = e.target.value;
14771
14754
  setTextColor(color);
14772
14755
  editor.chain().focus().setColor(color).run();
14773
- },
14774
- className: "absolute inset-0 opacity-0 cursor-pointer"
14756
+ }
14775
14757
  }
14776
14758
  )
14777
14759
  ), /* @__PURE__ */ React4.createElement(
@@ -14779,10 +14761,10 @@ function FontStyleGroup({ editor }) {
14779
14761
  {
14780
14762
  title: "Highlight Color",
14781
14763
  "aria-label": "Highlight Color",
14782
- className: "relative w-8 h-8 flex items-center justify-center cursor-pointer color-label",
14764
+ className: "color-label",
14783
14765
  style: { "--indicator-color": highlightColor }
14784
14766
  },
14785
- /* @__PURE__ */ React4.createElement(BiSolidColorFill, { size: 20, className: "text-gray-700" }),
14767
+ /* @__PURE__ */ React4.createElement(BiSolidColorFill, { size: 20 }),
14786
14768
  /* @__PURE__ */ React4.createElement("div", { className: "color-indicator" }),
14787
14769
  /* @__PURE__ */ React4.createElement(
14788
14770
  "input",
@@ -14793,8 +14775,7 @@ function FontStyleGroup({ editor }) {
14793
14775
  const color = e.target.value;
14794
14776
  setHighlightColor(color);
14795
14777
  editor.chain().focus().setHighlight({ color }).run();
14796
- },
14797
- className: "absolute inset-0 opacity-0 cursor-pointer"
14778
+ }
14798
14779
  }
14799
14780
  )
14800
14781
  ), /* @__PURE__ */ React4.createElement(
@@ -14910,13 +14891,13 @@ function InsertGroup({ editor }) {
14910
14891
  return url;
14911
14892
  }
14912
14893
  }
14913
- return /* @__PURE__ */ React5.createElement("div", { className: "flex gap-1 border-r pr-3 relative" }, /* @__PURE__ */ React5.createElement(
14894
+ return /* @__PURE__ */ React5.createElement("div", { className: "insert-group" }, /* @__PURE__ */ React5.createElement(
14914
14895
  "input",
14915
14896
  {
14916
14897
  type: "file",
14917
14898
  accept: "image/*",
14918
14899
  ref: imageInputRef,
14919
- className: "hidden",
14900
+ className: "hidden-input",
14920
14901
  onChange: handleImageUpload,
14921
14902
  "aria-label": "Upload Image",
14922
14903
  title: "Upload Image"
@@ -14927,7 +14908,7 @@ function InsertGroup({ editor }) {
14927
14908
  type: "file",
14928
14909
  accept: "video/*",
14929
14910
  ref: videoInputRef,
14930
- className: "hidden",
14911
+ className: "hidden-input",
14931
14912
  onChange: handleVideoUpload,
14932
14913
  "aria-label": "Upload Video",
14933
14914
  title: "Upload Video"
@@ -14942,24 +14923,24 @@ function InsertGroup({ editor }) {
14942
14923
  ), showTableGrid && /* @__PURE__ */ React5.createElement(
14943
14924
  "div",
14944
14925
  {
14945
- className: "absolute top-10 left-0 bg-white border rounded shadow p-2 z-20",
14926
+ className: "table-grid-popup",
14946
14927
  onMouseLeave: () => setShowTableGrid(false)
14947
14928
  },
14948
- /* @__PURE__ */ React5.createElement("div", { className: "grid grid-cols-10 gap-[1px]" }, [...Array(10)].map(
14929
+ /* @__PURE__ */ React5.createElement("div", { className: "table-grid" }, [...Array(10)].map(
14949
14930
  (_, row) => [...Array(10)].map((_2, col) => {
14950
14931
  const isSelected = row < selectedRows && col < selectedCols;
14951
14932
  return /* @__PURE__ */ React5.createElement(
14952
14933
  "div",
14953
14934
  {
14954
14935
  key: `${row}-${col}`,
14955
- className: `w-5 h-5 border cursor-pointer ${isSelected ? "bg-blue-500" : "bg-gray-100"}`,
14936
+ className: `table-grid-cell ${isSelected ? "selected" : ""}`,
14956
14937
  onMouseEnter: () => handleTableCellHover(row + 1, col + 1),
14957
14938
  onClick: () => handleTableInsert(row + 1, col + 1)
14958
14939
  }
14959
14940
  );
14960
14941
  })
14961
14942
  )),
14962
- /* @__PURE__ */ React5.createElement("div", { className: "text-sm mt-2 text-center text-gray-600" }, selectedRows, " x ", selectedCols)
14943
+ /* @__PURE__ */ React5.createElement("div", { className: "table-grid-label" }, selectedRows, " x ", selectedCols)
14963
14944
  ), /* @__PURE__ */ React5.createElement(
14964
14945
  ToolbarButton_default,
14965
14946
  {
@@ -14981,8 +14962,9 @@ function InsertGroup({ editor }) {
14981
14962
  label: "Insert Link",
14982
14963
  onClick: () => {
14983
14964
  const url = prompt("Enter URL");
14984
- if (url)
14965
+ if (url) {
14985
14966
  editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
14967
+ }
14986
14968
  }
14987
14969
  }
14988
14970
  ), /* @__PURE__ */ React5.createElement(
@@ -15006,7 +14988,7 @@ function InsertGroup({ editor }) {
15006
14988
  label: "Emoji",
15007
14989
  onClick: () => setShowPicker(!showPicker)
15008
14990
  }
15009
- ), showPicker && /* @__PURE__ */ React5.createElement("div", { className: "absolute z-50 top-10 left-0" }, /* @__PURE__ */ React5.createElement(
14991
+ ), showPicker && /* @__PURE__ */ React5.createElement("div", { className: "emoji-picker" }, /* @__PURE__ */ React5.createElement(
15010
14992
  Picker,
15011
14993
  {
15012
14994
  onEmojiSelect: addEmoji,
@@ -15059,7 +15041,7 @@ import {
15059
15041
  MdFormatAlignJustify
15060
15042
  } from "react-icons/md";
15061
15043
  function ListAlignGroup({ editor }) {
15062
- return /* @__PURE__ */ React6.createElement("div", { className: "flex gap-1 border-r pr-3" }, /* @__PURE__ */ React6.createElement(
15044
+ return /* @__PURE__ */ React6.createElement("div", { className: "list-align-group" }, /* @__PURE__ */ React6.createElement(
15063
15045
  ToolbarButton_default,
15064
15046
  {
15065
15047
  icon: MdFormatListBulleted,
@@ -15155,7 +15137,7 @@ function MiscGroup({ editor }) {
15155
15137
  previewWindow.document.close();
15156
15138
  }
15157
15139
  };
15158
- return /* @__PURE__ */ React7.createElement("div", { className: "flex gap-1 items-center border-r pr-3" }, /* @__PURE__ */ React7.createElement(
15140
+ return /* @__PURE__ */ React7.createElement("div", { className: "misc-group" }, /* @__PURE__ */ React7.createElement(
15159
15141
  ToolbarButton_default,
15160
15142
  {
15161
15143
  icon: MdUndo,
@@ -15228,34 +15210,24 @@ function FileGroup({ editor }) {
15228
15210
  e.target.value = "";
15229
15211
  }
15230
15212
  };
15231
- return /* @__PURE__ */ React8.createElement(
15232
- "div",
15213
+ return /* @__PURE__ */ React8.createElement("div", { className: "file-group", role: "group", "aria-label": "File actions" }, /* @__PURE__ */ React8.createElement(
15214
+ "input",
15233
15215
  {
15234
- className: "flex items-center gap-1 border-r pr-3",
15235
- role: "group",
15236
- "aria-label": "File actions"
15237
- },
15238
- /* @__PURE__ */ React8.createElement(
15239
- "input",
15240
- {
15241
- type: "file",
15242
- accept: ".json",
15243
- ref: fileInputRef,
15244
- onChange: handleFileChange,
15245
- className: "hidden",
15246
- "aria-label": "Open JSON file"
15247
- }
15248
- ),
15249
- /* @__PURE__ */ React8.createElement(ToolbarButton_default, { icon: VscNewFile, onClick: handleNew, title: "New" }),
15250
- /* @__PURE__ */ React8.createElement(
15251
- ToolbarButton_default,
15252
- {
15253
- icon: FaRegFolderOpen,
15254
- onClick: handleOpen,
15255
- title: "Open File"
15256
- }
15257
- )
15258
- );
15216
+ type: "file",
15217
+ accept: ".json",
15218
+ ref: fileInputRef,
15219
+ onChange: handleFileChange,
15220
+ className: "hidden",
15221
+ "aria-label": "Open JSON file"
15222
+ }
15223
+ ), /* @__PURE__ */ React8.createElement(ToolbarButton_default, { icon: VscNewFile, onClick: handleNew, title: "New" }), /* @__PURE__ */ React8.createElement(
15224
+ ToolbarButton_default,
15225
+ {
15226
+ icon: FaRegFolderOpen,
15227
+ onClick: handleOpen,
15228
+ title: "Open File"
15229
+ }
15230
+ ));
15259
15231
  }
15260
15232
 
15261
15233
  // src/components/tetrons/toolbar/TetronsToolbar.tsx
@@ -15277,16 +15249,15 @@ function TetronsToolbar({ editor }) {
15277
15249
  editor.off("update", handleUpdate);
15278
15250
  };
15279
15251
  }, [autoSave, editor]);
15280
- return /* @__PURE__ */ React9.createElement("div", { className: "flex flex-wrap items-center gap-4 p-3 border-b bg-white shadow-sm relative z-10" }, /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-2 border-r pr-3" }, /* @__PURE__ */ React9.createElement(
15252
+ return /* @__PURE__ */ React9.createElement("div", { className: "tetrons-toolbar" }, /* @__PURE__ */ React9.createElement("div", { className: "group" }, /* @__PURE__ */ React9.createElement(
15281
15253
  "input",
15282
15254
  {
15283
15255
  type: "checkbox",
15284
15256
  id: "autoSave",
15285
15257
  checked: autoSave,
15286
- onChange: (e) => setAutoSave(e.target.checked),
15287
- className: "w-4 h-4"
15258
+ onChange: (e) => setAutoSave(e.target.checked)
15288
15259
  }
15289
- ), /* @__PURE__ */ React9.createElement("label", { htmlFor: "autoSave", className: "text-sm select-none" }, "Auto Save")), /* @__PURE__ */ React9.createElement(FileGroup, { editor }), /* @__PURE__ */ React9.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React9.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React9.createElement(ListAlignGroup, { editor }), /* @__PURE__ */ React9.createElement(InsertGroup, { editor }), /* @__PURE__ */ React9.createElement(MiscGroup, { editor }), /* @__PURE__ */ React9.createElement(ActionGroup, { editor }));
15260
+ ), /* @__PURE__ */ React9.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), /* @__PURE__ */ React9.createElement(FileGroup, { editor }), /* @__PURE__ */ React9.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React9.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React9.createElement(ListAlignGroup, { editor }), /* @__PURE__ */ React9.createElement(InsertGroup, { editor }), /* @__PURE__ */ React9.createElement(MiscGroup, { editor }), /* @__PURE__ */ React9.createElement(ActionGroup, { editor }));
15290
15261
  }
15291
15262
 
15292
15263
  // src/components/tetrons/ResizableImage.ts
@@ -17181,20 +17152,22 @@ function EditorContent() {
17181
17152
  setCurrentVersionIndex(index);
17182
17153
  }
17183
17154
  };
17184
- return /* @__PURE__ */ React13.createElement("div", { className: "flex flex-col h-full" }, /* @__PURE__ */ React13.createElement("div", { className: "p-2 border-b border-gray-300 bg-gray-50 flex flex-wrap items-center gap-3" }, /* @__PURE__ */ React13.createElement(
17155
+ return /* @__PURE__ */ React13.createElement("div", { className: "editor-container" }, /* @__PURE__ */ React13.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React13.createElement(
17185
17156
  "button",
17186
17157
  {
17158
+ type: "button",
17187
17159
  onClick: saveVersion,
17188
17160
  disabled: !editor,
17189
- className: "px-3 py-1 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50"
17161
+ className: "editor-save-btn"
17190
17162
  },
17191
17163
  "Save Version"
17192
- ), /* @__PURE__ */ React13.createElement("div", { className: "flex items-center gap-2 overflow-x-auto max-w-full" }, versions.length === 0 && /* @__PURE__ */ React13.createElement("span", { className: "text-gray-500 text-sm" }, "No saved versions"), versions.map((_, idx) => /* @__PURE__ */ React13.createElement(
17164
+ ), /* @__PURE__ */ React13.createElement("div", { className: "editor-versions-wrapper" }, versions.length === 0 && /* @__PURE__ */ React13.createElement("span", { className: "editor-no-versions" }, "No saved versions"), versions.map((_, idx) => /* @__PURE__ */ React13.createElement(
17193
17165
  "button",
17194
17166
  {
17167
+ type: "button",
17195
17168
  key: idx,
17196
17169
  onClick: () => restoreVersion(idx),
17197
- className: `px-2 py-1 rounded border ${idx === currentVersionIndex ? "border-blue-600 font-semibold text-blue-600" : "border-gray-300 text-gray-700 hover:border-gray-600"}`,
17170
+ className: `editor-version-btn ${idx === currentVersionIndex ? "active" : ""}`,
17198
17171
  title: `Restore Version ${idx + 1}`
17199
17172
  },
17200
17173
  `V${idx + 1}`
@@ -17202,10 +17175,10 @@ function EditorContent() {
17202
17175
  "div",
17203
17176
  {
17204
17177
  ref: wrapperRef,
17205
- className: "flex-grow p-4 md:p-6 bg-white border border-gray-300 rounded shadow-sm overflow-auto min-h-0 prose relative",
17178
+ className: "editor-content-wrapper",
17206
17179
  onClick: handleEditorClick
17207
17180
  },
17208
- editor ? /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(TiptapEditorContent, { editor }), editor && /* @__PURE__ */ React13.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ React13.createElement("div", { className: "text-gray-500" }, "Loading editor...")
17181
+ editor ? /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(TiptapEditorContent, { editor }), editor && /* @__PURE__ */ React13.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ React13.createElement("div", { className: "editor-loading" }, "Loading editor...")
17209
17182
  ));
17210
17183
  }
17211
17184
 
@@ -0,0 +1,329 @@
1
+ .editor-container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+ }
6
+
7
+ .editor-toolbar {
8
+ padding: 0.5rem;
9
+ border-bottom: 1px solid #d1d5db;
10
+ background-color: #f9fafb;
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+ align-items: center;
14
+ gap: 0.75rem;
15
+ }
16
+
17
+ .editor-save-btn {
18
+ padding: 0.25rem 0.75rem;
19
+ background-color: #2563eb;
20
+ color: white;
21
+ border-radius: 0.375rem;
22
+ transition: background-color 0.2s;
23
+ }
24
+
25
+ .editor-save-btn:hover {
26
+ background-color: #1d4ed8;
27
+ }
28
+
29
+ .editor-save-btn:disabled {
30
+ opacity: 0.5;
31
+ cursor: not-allowed;
32
+ }
33
+
34
+ .editor-version-btn {
35
+ padding: 0.25rem 0.5rem;
36
+ border: 1px solid #d1d5db;
37
+ color: #374151;
38
+ border-radius: 0.375rem;
39
+ font-size: 0.875rem;
40
+ white-space: nowrap;
41
+ transition: all 0.2s;
42
+ background: none;
43
+ }
44
+
45
+ .editor-version-btn:hover {
46
+ border-color: #4b5563;
47
+ }
48
+
49
+ .editor-version-btn.active {
50
+ border-color: #2563eb;
51
+ color: #2563eb;
52
+ font-weight: 600;
53
+ }
54
+
55
+ .editor-content-wrapper {
56
+ flex-grow: 1;
57
+ padding: 1.5rem;
58
+ background-color: white;
59
+ border: 1px solid #d1d5db;
60
+ border-radius: 0.5rem;
61
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
62
+ overflow: auto;
63
+ position: relative;
64
+ min-height: 0;
65
+ }
66
+
67
+ .editor-loading {
68
+ color: #6b7280;
69
+ font-size: 0.875rem;
70
+ text-align: center;
71
+ padding: 1rem;
72
+ }
73
+
74
+ .editor-content-wrapper .ProseMirror {
75
+ outline: none;
76
+ min-height: 300px;
77
+ font-size: 1rem;
78
+ line-height: 1.75;
79
+ }
80
+
81
+ .editor-content-wrapper .ProseMirror[data-placeholder]:empty::before {
82
+ content: attr(data-placeholder);
83
+ color: #9ca3af;
84
+ float: left;
85
+ height: 0;
86
+ pointer-events: none;
87
+ }
88
+
89
+ .ProseMirror pre {
90
+ background: #f3f4f6;
91
+ padding: 1rem;
92
+ border-radius: 0.375rem;
93
+ font-family: monospace;
94
+ font-size: 0.875rem;
95
+ overflow-x: auto;
96
+ }
97
+
98
+ .editor-versions-wrapper {
99
+ display: flex;
100
+ align-items: center;
101
+ gap: 0.5rem;
102
+ overflow-x: auto;
103
+ max-width: 100%;
104
+ }
105
+
106
+ .editor-no-versions {
107
+ color: #6b7280;
108
+ font-size: 0.875rem;
109
+ }
110
+
111
+ .tetrons-toolbar {
112
+ display: flex;
113
+ flex-wrap: wrap;
114
+ align-items: center;
115
+ gap: 1rem;
116
+ padding: 0.75rem;
117
+ border-bottom: 1px solid #e5e7eb;
118
+ background-color: white;
119
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
120
+ position: relative;
121
+ z-index: 10;
122
+ }
123
+
124
+ .tetrons-toolbar .group {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 0.5rem;
128
+ border-right: 1px solid #e5e7eb;
129
+ padding-right: 0.75rem;
130
+ }
131
+
132
+ .tetrons-toolbar input[type="checkbox"] {
133
+ width: 1rem;
134
+ height: 1rem;
135
+ }
136
+
137
+ .tetrons-toolbar label {
138
+ font-size: 0.875rem;
139
+ user-select: none;
140
+ -webkit-user-select: none;
141
+ }
142
+
143
+ .misc-group {
144
+ display: flex;
145
+ gap: 0.25rem;
146
+ align-items: center;
147
+ border-right: 1px solid #e5e7eb;
148
+ padding-right: 0.75rem;
149
+ }
150
+
151
+ .list-align-group {
152
+ display: flex;
153
+ gap: 0.25rem;
154
+ border-right: 1px solid #e5e7eb;
155
+ padding-right: 0.75rem;
156
+ align-items: center;
157
+ }
158
+
159
+ .insert-group {
160
+ display: flex;
161
+ gap: 0.25rem;
162
+ border-right: 1px solid #e5e7eb;
163
+ padding-right: 0.75rem;
164
+ position: relative;
165
+ align-items: center;
166
+ }
167
+
168
+ .table-grid-popup {
169
+ position: absolute;
170
+ top: 2.5rem;
171
+ left: 0;
172
+ background-color: white;
173
+ border: 1px solid #d1d5db;
174
+ border-radius: 0.25rem;
175
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
176
+ padding: 0.5rem;
177
+ z-index: 20;
178
+ }
179
+
180
+ .table-grid {
181
+ display: grid;
182
+ grid-template-columns: repeat(10, 1fr);
183
+ gap: 1px;
184
+ }
185
+
186
+ .table-grid-cell {
187
+ width: 1.25rem;
188
+ height: 1.25rem;
189
+ border: 1px solid #d1d5db;
190
+ background-color: #f3f4f6;
191
+ cursor: pointer;
192
+ }
193
+
194
+ .table-grid-cell.selected {
195
+ background-color: #3b82f6;
196
+ }
197
+
198
+ .table-grid-label {
199
+ margin-top: 0.5rem;
200
+ font-size: 0.75rem;
201
+ text-align: center;
202
+ color: #6b7280;
203
+ }
204
+
205
+ .hidden-input {
206
+ display: none;
207
+ }
208
+
209
+ .emoji-picker {
210
+ position: absolute;
211
+ top: 2.5rem;
212
+ left: 0;
213
+ z-index: 50;
214
+ }
215
+
216
+ .font-style-group {
217
+ display: flex;
218
+ gap: 0.25rem;
219
+ border-right: 1px solid #e5e7eb;
220
+ padding-right: 0.75rem;
221
+ align-items: center;
222
+ }
223
+
224
+ .font-style-group select {
225
+ font-size: 0.875rem;
226
+ border: 1px solid #d1d5db;
227
+ border-radius: 0.25rem;
228
+ padding: 0.125rem 0.25rem;
229
+ margin-right: 0.5rem;
230
+ }
231
+
232
+ .color-label {
233
+ position: relative;
234
+ width: 2rem;
235
+ height: 2rem;
236
+ display: flex;
237
+ justify-content: center;
238
+ align-items: center;
239
+ cursor: pointer;
240
+ }
241
+
242
+ .color-indicator {
243
+ content: "";
244
+ position: absolute;
245
+ bottom: 2px;
246
+ left: 50%;
247
+ transform: translateX(-50%);
248
+ width: 12px;
249
+ height: 4px;
250
+ background-color: var(--indicator-color, #000000);
251
+ border-radius: 2px;
252
+ pointer-events: none;
253
+ }
254
+
255
+ .color-label input[type="color"] {
256
+ position: absolute;
257
+ inset: 0;
258
+ opacity: 0;
259
+ cursor: pointer;
260
+ }
261
+
262
+ .file-group {
263
+ display: flex;
264
+ align-items: center;
265
+ gap: 0.25rem;
266
+ border-right: 1px solid #e5e7eb;
267
+ padding-right: 0.75rem;
268
+ }
269
+
270
+ .file-group input[type="file"] {
271
+ display: none;
272
+ }
273
+
274
+ .clipboard-group {
275
+ display: flex;
276
+ gap: 0.25rem;
277
+ border-right: 1px solid #e5e7eb;
278
+ padding-right: 0.75rem;
279
+ }
280
+
281
+ .action-group {
282
+ position: relative;
283
+ display: flex;
284
+ align-items: center;
285
+ gap: 0.25rem;
286
+ }
287
+
288
+ .export-button {
289
+ display: flex;
290
+ align-items: center;
291
+ gap: 0.25rem;
292
+ padding: 0.25rem 0.5rem;
293
+ border-radius: 0.25rem;
294
+ background: transparent;
295
+ cursor: pointer;
296
+ }
297
+
298
+ .export-button:hover {
299
+ background-color: #f3f4f6;
300
+ }
301
+
302
+ .export-button:focus {
303
+ outline: none;
304
+ }
305
+
306
+ .export-dropdown {
307
+ position: absolute;
308
+ z-index: 10;
309
+ margin-top: 0.5rem;
310
+ width: 10rem;
311
+ background-color: #fff;
312
+ border: 1px solid #e5e7eb;
313
+ border-radius: 0.25rem;
314
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
315
+ }
316
+
317
+ .export-dropdown button {
318
+ width: 100%;
319
+ text-align: left;
320
+ padding: 0.5rem 1rem;
321
+ background: none;
322
+ border: none;
323
+ font-size: 0.875rem;
324
+ cursor: pointer;
325
+ }
326
+
327
+ .export-dropdown button:hover {
328
+ background-color: #f3f4f6;
329
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tetrons",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "A Next.js project written in TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -68,7 +68,8 @@
68
68
  }
69
69
  },
70
70
  "files": [
71
- "dist"
71
+ "dist",
72
+ "dist/styles/tetrons.css"
72
73
  ],
73
74
  "bugs": {
74
75
  "url": "https://github.com/your-repo/tetrons/issues"