tetrons 2.2.0 → 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.
- package/dist/app/layout.d.ts +0 -1
- package/dist/app/page.d.ts +1 -1
- package/dist/app/page.jsx +1 -0
- package/dist/components/tetrons/EditorContent.jsx +8 -10
- package/dist/components/tetrons/toolbar/ActionGroup.jsx +12 -10
- package/dist/components/tetrons/toolbar/ClipboardGroup.jsx +1 -1
- package/dist/components/tetrons/toolbar/FileGroup.jsx +1 -1
- package/dist/components/tetrons/toolbar/FontStyleGroup.jsx +9 -9
- package/dist/components/tetrons/toolbar/InsertGroup.jsx +10 -9
- package/dist/components/tetrons/toolbar/ListAlignGroup.jsx +1 -1
- package/dist/components/tetrons/toolbar/MiscGroup.jsx +1 -1
- package/dist/components/tetrons/toolbar/TetronsToolbar.jsx +4 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +89 -116
- package/dist/styles/tetrons.css +329 -0
- package/package.json +3 -2
package/dist/app/layout.d.ts
CHANGED
package/dist/app/page.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import "../styles/tetrons.css";
|
|
2
2
|
export default function Home(): import("react").JSX.Element;
|
package/dist/app/page.jsx
CHANGED
|
@@ -133,28 +133,26 @@ export default function EditorContent() {
|
|
|
133
133
|
setCurrentVersionIndex(index);
|
|
134
134
|
}
|
|
135
135
|
};
|
|
136
|
-
return (<div className="
|
|
137
|
-
<div className="
|
|
138
|
-
<button onClick={saveVersion} disabled={!editor} className="
|
|
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="
|
|
143
|
-
{versions.length === 0 && (<span className="
|
|
144
|
-
{versions.map((_, idx) => (<button key={idx} onClick={() => restoreVersion(idx)} className={`
|
|
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="
|
|
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="
|
|
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
|
|
28
|
+
const style = element.style;
|
|
29
|
+
const currentZoom = parseFloat(style.zoom || "1");
|
|
29
30
|
const next = Math.min(currentZoom + 0.1, 2);
|
|
30
|
-
|
|
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
|
|
37
|
+
const style = element.style;
|
|
38
|
+
const currentZoom = parseFloat(style.zoom || "1");
|
|
37
39
|
const next = Math.max(currentZoom - 0.1, 0.5);
|
|
38
|
-
|
|
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="
|
|
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="
|
|
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="
|
|
145
|
+
{dropdownOpen && (<div className="export-dropdown">
|
|
144
146
|
<button type="button" onClick={() => {
|
|
145
147
|
setDropdownOpen(false);
|
|
146
148
|
handleDownloadPDF();
|
|
147
|
-
}}
|
|
149
|
+
}}>
|
|
148
150
|
Export as PDF
|
|
149
151
|
</button>
|
|
150
152
|
<button type="button" onClick={() => {
|
|
151
153
|
setDropdownOpen(false);
|
|
152
154
|
handleDownloadHTML();
|
|
153
|
-
}}
|
|
155
|
+
}}>
|
|
154
156
|
Export as HTML
|
|
155
157
|
</button>
|
|
156
158
|
<button type="button" onClick={() => {
|
|
157
159
|
setDropdownOpen(false);
|
|
158
160
|
handleDownloadDOCX();
|
|
159
|
-
}}
|
|
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="
|
|
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="
|
|
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="
|
|
35
|
-
<select title="Font Family"
|
|
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"
|
|
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="
|
|
71
|
-
<ImTextColor size={20}
|
|
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
|
-
}}
|
|
77
|
+
}}/>
|
|
78
78
|
</label>
|
|
79
79
|
|
|
80
|
-
<label title="Highlight Color" aria-label="Highlight Color" className="
|
|
81
|
-
<BiSolidColorFill size={20}
|
|
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
|
-
}}
|
|
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="
|
|
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="
|
|
104
|
-
<div className="grid
|
|
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={`
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
31
|
-
<div className="
|
|
32
|
-
<input type="checkbox" id="autoSave" checked={autoSave} onChange={(e) => setAutoSave(e.target.checked)}
|
|
33
|
-
<label htmlFor="autoSave"
|
|
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
package/dist/index.js
CHANGED
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
|
-
"
|
|
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
|
-
|
|
14511
|
-
|
|
14512
|
-
"aria-
|
|
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(
|
|
14515
|
-
/* @__PURE__ */ React2.createElement(
|
|
14516
|
-
|
|
14517
|
-
|
|
14518
|
-
|
|
14519
|
-
"button",
|
|
14520
|
-
{
|
|
14521
|
-
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
|
|
14529
|
-
|
|
14530
|
-
|
|
14531
|
-
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
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: "
|
|
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: "
|
|
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: "
|
|
14742
|
+
className: "color-label",
|
|
14760
14743
|
style: { "--indicator-color": textColor }
|
|
14761
14744
|
},
|
|
14762
|
-
/* @__PURE__ */ React4.createElement(ImTextColor, { size: 20
|
|
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: "
|
|
14764
|
+
className: "color-label",
|
|
14783
14765
|
style: { "--indicator-color": highlightColor }
|
|
14784
14766
|
},
|
|
14785
|
-
/* @__PURE__ */ React4.createElement(BiSolidColorFill, { size: 20
|
|
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: "
|
|
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: "
|
|
14926
|
+
className: "table-grid-popup",
|
|
14946
14927
|
onMouseLeave: () => setShowTableGrid(false)
|
|
14947
14928
|
},
|
|
14948
|
-
/* @__PURE__ */ React5.createElement("div", { className: "grid
|
|
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: `
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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
|
-
"
|
|
15213
|
+
return /* @__PURE__ */ React8.createElement("div", { className: "file-group", role: "group", "aria-label": "File actions" }, /* @__PURE__ */ React8.createElement(
|
|
15214
|
+
"input",
|
|
15233
15215
|
{
|
|
15234
|
-
|
|
15235
|
-
|
|
15236
|
-
|
|
15237
|
-
|
|
15238
|
-
|
|
15239
|
-
"
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
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: "
|
|
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"
|
|
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: "
|
|
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: "
|
|
17161
|
+
className: "editor-save-btn"
|
|
17190
17162
|
},
|
|
17191
17163
|
"Save Version"
|
|
17192
|
-
), /* @__PURE__ */ React13.createElement("div", { className: "
|
|
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: `
|
|
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: "
|
|
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: "
|
|
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.
|
|
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"
|