tetrons 2.2.2 → 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 (43) hide show
  1. package/dist/app/layout.d.ts +2 -1
  2. package/dist/app/{layout.jsx → layout.js} +2 -5
  3. package/dist/app/page.d.ts +1 -1
  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 -22
  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} +12 -35
  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 -14
  27. package/dist/components/tetrons/toolbar/ToolbarButton.js +7 -0
  28. package/dist/index.d.mts +2 -2
  29. package/dist/index.d.ts +0 -1
  30. package/dist/index.js +1 -1
  31. package/dist/index.mjs +749 -629
  32. package/dist/styles/styles/tetrons.css +371 -0
  33. package/dist/styles/tetrons.css +42 -0
  34. package/package.json +5 -3
  35. package/dist/app/page.jsx +0 -9
  36. package/dist/components/tetrons/toolbar/ClipboardGroup.jsx +0 -36
  37. package/dist/components/tetrons/toolbar/FontStyleGroup.jsx +0 -104
  38. package/dist/components/tetrons/toolbar/InsertGroup.jsx +0 -163
  39. package/dist/components/tetrons/toolbar/ListAlignGroup.jsx +0 -16
  40. package/dist/components/tetrons/toolbar/MiscGroup.jsx +0 -31
  41. package/dist/components/tetrons/toolbar/ToolbarButton.jsx +0 -8
  42. /package/dist/components/UI/{Button.jsx → Button.js} +0 -0
  43. /package/dist/components/UI/{Dropdown.jsx → Dropdown.js} +0 -0
@@ -0,0 +1,371 @@
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
+ }
330
+
331
+ .toolbar-button {
332
+ padding: 0.5rem;
333
+ border: none;
334
+ background-color: transparent;
335
+ border-radius: 0.375rem;
336
+ cursor: pointer;
337
+ display: flex;
338
+ align-items: center;
339
+ justify-content: center;
340
+ transition: background-color 0.2s ease;
341
+ }
342
+
343
+ .toolbar-button:hover {
344
+ background-color: #e5e7eb;
345
+ }
346
+
347
+ .toolbar-button.active {
348
+ background-color: #d1d5db;
349
+ }
350
+
351
+ .toolbar-button:disabled {
352
+ opacity: 0.5;
353
+ cursor: not-allowed;
354
+ }
355
+
356
+ .tableWrapper {
357
+ overflow-x: auto;
358
+ margin: 1rem 0;
359
+ }
360
+
361
+ .tableWrapper table {
362
+ width: 100%;
363
+ border-collapse: collapse;
364
+ }
365
+
366
+ .tableWrapper th,
367
+ .tableWrapper td {
368
+ border: 1px solid #d1d5db;
369
+ padding: 0.5rem;
370
+ text-align: left;
371
+ }
@@ -327,3 +327,45 @@
327
327
  .export-dropdown button:hover {
328
328
  background-color: #f3f4f6;
329
329
  }
330
+
331
+ .toolbar-button {
332
+ padding: 0.5rem;
333
+ border: none;
334
+ background-color: transparent;
335
+ border-radius: 0.375rem;
336
+ cursor: pointer;
337
+ display: flex;
338
+ align-items: center;
339
+ justify-content: center;
340
+ transition: background-color 0.2s ease;
341
+ }
342
+
343
+ .toolbar-button:hover {
344
+ background-color: #e5e7eb;
345
+ }
346
+
347
+ .toolbar-button.active {
348
+ background-color: #d1d5db;
349
+ }
350
+
351
+ .toolbar-button:disabled {
352
+ opacity: 0.5;
353
+ cursor: not-allowed;
354
+ }
355
+
356
+ .tableWrapper {
357
+ overflow-x: auto;
358
+ margin: 1rem 0;
359
+ }
360
+
361
+ .tableWrapper table {
362
+ width: 100%;
363
+ border-collapse: collapse;
364
+ }
365
+
366
+ .tableWrapper th,
367
+ .tableWrapper td {
368
+ border: 1px solid #d1d5db;
369
+ padding: 0.5rem;
370
+ text-align: left;
371
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "tetrons",
3
- "version": "2.2.2",
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,7 +66,8 @@
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
73
  "dist",
package/dist/app/page.jsx DELETED
@@ -1,9 +0,0 @@
1
- import EditorContent from "../components/tetrons/EditorContent";
2
- import "../styles/tetrons.css";
3
- export default function Home() {
4
- return (<main className="flex flex-col h-screen overflow-hidden">
5
- <div className="flex-1 overflow-auto flex flex-col">
6
- <EditorContent />
7
- </div>
8
- </main>);
9
- }
@@ -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="clipboard-group">
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="font-style-group">
35
- <select title="Font Family" 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" 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="color-label" style={{ "--indicator-color": textColor }}>
71
- <ImTextColor size={20}/>
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
- }}/>
78
- </label>
79
-
80
- <label title="Highlight Color" aria-label="Highlight Color" className="color-label" style={{ "--indicator-color": highlightColor }}>
81
- <BiSolidColorFill size={20}/>
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
- }}/>
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
- }