smartrte-react 0.1.10 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -330,15 +330,13 @@ The editor comes with built-in styles. You can customize the appearance by wrapp
330
330
 
331
331
  - Node.js 18+
332
332
  - pnpm 9.10.0+
333
- - Rust (for WASM compilation)
334
- - wasm-pack
335
333
 
336
334
  ### Setting Up Development Environment
337
335
 
338
336
  1. **Clone the repository**
339
337
 
340
338
  ```bash
341
- git clone https://github.com/yourusername/smart-rte.git
339
+ git clone https://github.com/ayush1852017/smart-rte.git
342
340
  cd smart-rte
343
341
  ```
344
342
 
@@ -351,13 +349,7 @@ pnpm install
351
349
  3. **Build the project**
352
350
 
353
351
  ```bash
354
- # Build WASM core
355
- pnpm build:wasm
356
-
357
352
  # Build TypeScript packages
358
- pnpm build:ts
359
-
360
- # Or build everything
361
353
  pnpm build
362
354
  ```
363
355
 
@@ -376,19 +368,17 @@ The playground will be available at `http://localhost:5173`
376
368
  ```
377
369
  smart-rte/
378
370
  ├── packages/
379
- ├── react/ # Main React package (smartrte-react)
380
- ├── src/
381
- ├── components/
382
- │ │ ├── ClassicEditor.tsx # Main editor component
383
- │ │ └── MediaManager.tsx # Media management component
384
- └── index.ts
385
- ├── playground/ # Development playground
386
- └── package.json
387
- ├── core-wasm/ # WASM bindings
388
- └── classic-embed/ # Standalone bundle
389
- ├── rust/ # Rust core
390
- │ └── smart_rte_core/
391
- ├── apps/ # Example applications
371
+ └── react/ # Main React package (smartrte-react)
372
+ ├── src/
373
+ │ ├── components/
374
+ │ │ ├── ClassicEditor.tsx # Main editor component
375
+ │ │ └── MediaManager.tsx # Media management component
376
+ │ └── index.ts
377
+ ├── playground/ # Development playground
378
+ └── package.json
379
+ ├── dart/ # Flutter/Dart packages
380
+ ├── smartrte_flutter/ # Flutter WebView integration
381
+ │ └── example_app/ # Flutter example
392
382
  └── package.json
393
383
  ```
394
384
 
@@ -455,7 +445,7 @@ We welcome contributions! Here's how you can help:
455
445
 
456
446
  ### Reporting Bugs
457
447
 
458
- 1. Check if the bug has already been reported in [Issues](https://github.com/yourusername/smart-rte/issues)
448
+ 1. Check if the bug has already been reported in [Issues](https://github.com/ayush1852017/smart-rte/issues)
459
449
  2. If not, create a new issue with:
460
450
  - Clear title and description
461
451
  - Steps to reproduce
@@ -465,7 +455,7 @@ We welcome contributions! Here's how you can help:
465
455
 
466
456
  ### Suggesting Features
467
457
 
468
- 1. Check [existing feature requests](https://github.com/yourusername/smart-rte/issues?q=is%3Aissue+label%3Aenhancement)
458
+ 1. Check [existing feature requests](https://github.com/ayush1852017/smart-rte/issues?q=is%3Aissue+label%3Aenhancement)
469
459
  2. Create a new issue with:
470
460
  - Clear description of the feature
471
461
  - Use cases
@@ -611,20 +601,20 @@ SOFTWARE.
611
601
 
612
602
  - **Smart RTE Team** - Initial work and maintenance
613
603
 
614
- See the list of [contributors](https://github.com/yourusername/smart-rte/contributors) who participated in this project.
604
+ See the list of [contributors](https://github.com/ayush1852017/smart-rte/contributors) who participated in this project.
615
605
 
616
606
  ## 🙏 Acknowledgments
617
607
 
618
608
  - [KaTeX](https://katex.org/) - For mathematical formula rendering
619
609
  - [React](https://reactjs.org/) - The UI library
620
610
  - [Vite](https://vitejs.dev/) - Build tool
621
- - All our amazing [contributors](https://github.com/yourusername/smart-rte/contributors)
611
+ - All our amazing [contributors](https://github.com/ayush1852017/smart-rte/contributors)
622
612
 
623
613
  ## 📞 Support
624
614
 
625
615
  - **Documentation:** You're reading it! 📖
626
- - **Issues:** [GitHub Issues](https://github.com/yourusername/smart-rte/issues)
627
- - **Discussions:** [GitHub Discussions](https://github.com/yourusername/smart-rte/discussions)
616
+ - **Issues:** [GitHub Issues](https://github.com/ayush1852017/smart-rte/issues)
617
+ - **Discussions:** [GitHub Discussions](https://github.com/ayush1852017/smart-rte/discussions)
628
618
  - **Twitter:** [@smartrte](https://twitter.com/smartrte) (if applicable)
629
619
 
630
620
  ## 🗺️ Roadmap
@@ -658,9 +648,7 @@ See the list of [contributors](https://github.com/yourusername/smart-rte/contrib
658
648
 
659
649
  ## 🔗 Related Packages
660
650
 
661
- - **@smartrte/classic-embed** - Standalone script-tag bundle
662
- - **smartrte-flutter** - Flutter/Dart implementation
663
- - **smart-rte-core** - Rust core library
651
+ - **smartrte-flutter** - Flutter/Dart WebView implementation
664
652
 
665
653
  ## 💡 Tips & Best Practices
666
654
 
@@ -696,4 +684,4 @@ See the list of [contributors](https://github.com/yourusername/smart-rte/contrib
696
684
 
697
685
  **Happy Editing! 🎉**
698
686
 
699
- If you find this package useful, please consider giving it a ⭐ on [GitHub](https://github.com/yourusername/smart-rte)!
687
+ If you find this package useful, please consider giving it a ⭐ on [GitHub](https://github.com/ayush1852017/smart-rte)!
@@ -11,6 +11,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
11
11
  const [imageOverlay, setImageOverlay] = useState(null);
12
12
  const resizingRef = useRef(null);
13
13
  const draggedImageRef = useRef(null);
14
+ const tableResizeRef = useRef(null);
14
15
  const [showTableDialog, setShowTableDialog] = useState(false);
15
16
  const [tableRows, setTableRows] = useState(3);
16
17
  const [tableCols, setTableCols] = useState(3);
@@ -194,6 +195,124 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
194
195
  window.removeEventListener("resize", onResize);
195
196
  };
196
197
  }, []);
198
+ // Table resize event listeners
199
+ useEffect(() => {
200
+ const el = editableRef.current;
201
+ if (!el)
202
+ return;
203
+ addTableResizeHandles();
204
+ const onMouseDown = (e) => {
205
+ if (!table)
206
+ return;
207
+ const target = e.target;
208
+ if (target.tagName === 'TD' || target.tagName === 'TH') {
209
+ const rect = target.getBoundingClientRect();
210
+ const rightEdge = rect.right;
211
+ const clickX = e.clientX;
212
+ if (Math.abs(clickX - rightEdge) < 5) {
213
+ e.preventDefault();
214
+ const tableElem = target.closest('table');
215
+ const colIndex = parseInt(target.getAttribute('data-col-index') || '0', 10);
216
+ if (tableElem) {
217
+ startColumnResize(tableElem, colIndex, e.clientX);
218
+ }
219
+ return;
220
+ }
221
+ const bottomEdge = rect.bottom;
222
+ const clickY = e.clientY;
223
+ if (Math.abs(clickY - bottomEdge) < 5) {
224
+ e.preventDefault();
225
+ const tableElem = target.closest('table');
226
+ const row = target.closest('tr');
227
+ if (tableElem && row) {
228
+ const rowIndex = parseInt(row.getAttribute('data-row-index') || '0', 10);
229
+ startRowResize(tableElem, rowIndex, e.clientY);
230
+ }
231
+ return;
232
+ }
233
+ }
234
+ };
235
+ const onMouseMove = (e) => {
236
+ if (tableResizeRef.current) {
237
+ handleTableResizeMove(e);
238
+ return;
239
+ }
240
+ if (!table)
241
+ return;
242
+ const target = e.target;
243
+ if (target.tagName === 'TD' || target.tagName === 'TH') {
244
+ const rect = target.getBoundingClientRect();
245
+ const clickX = e.clientX;
246
+ const clickY = e.clientY;
247
+ if (Math.abs(clickX - rect.right) < 5) {
248
+ el.style.cursor = 'col-resize';
249
+ return;
250
+ }
251
+ if (Math.abs(clickY - rect.bottom) < 5) {
252
+ el.style.cursor = 'row-resize';
253
+ return;
254
+ }
255
+ if (el.style.cursor === 'col-resize' || el.style.cursor === 'row-resize') {
256
+ el.style.cursor = '';
257
+ }
258
+ }
259
+ };
260
+ const onMouseUp = () => {
261
+ handleTableResizeEnd();
262
+ };
263
+ const onTouchStart = (e) => {
264
+ if (!table)
265
+ return;
266
+ const target = e.target;
267
+ if (target.tagName === 'TD' || target.tagName === 'TH') {
268
+ const rect = target.getBoundingClientRect();
269
+ const touch = e.touches[0];
270
+ const clickX = touch.clientX;
271
+ const clickY = touch.clientY;
272
+ if (Math.abs(clickX - rect.right) < 15) {
273
+ e.preventDefault();
274
+ const tableElem = target.closest('table');
275
+ const colIndex = parseInt(target.getAttribute('data-col-index') || '0', 10);
276
+ if (tableElem) {
277
+ startColumnResize(tableElem, colIndex, clickX);
278
+ }
279
+ return;
280
+ }
281
+ if (Math.abs(clickY - rect.bottom) < 15) {
282
+ e.preventDefault();
283
+ const tableElem = target.closest('table');
284
+ const row = target.closest('tr');
285
+ if (tableElem && row) {
286
+ const rowIndex = parseInt(row.getAttribute('data-row-index') || '0', 10);
287
+ startRowResize(tableElem, rowIndex, clickY);
288
+ }
289
+ return;
290
+ }
291
+ }
292
+ };
293
+ const onTouchMove = (e) => {
294
+ if (tableResizeRef.current) {
295
+ handleTableResizeMove(e);
296
+ }
297
+ };
298
+ const onTouchEnd = () => {
299
+ handleTableResizeEnd();
300
+ };
301
+ el.addEventListener('mousedown', onMouseDown);
302
+ window.addEventListener('mousemove', onMouseMove);
303
+ window.addEventListener('mouseup', onMouseUp);
304
+ el.addEventListener('touchstart', onTouchStart, { passive: false });
305
+ window.addEventListener('touchmove', onTouchMove, { passive: false });
306
+ window.addEventListener('touchend', onTouchEnd);
307
+ return () => {
308
+ el.removeEventListener('mousedown', onMouseDown);
309
+ window.removeEventListener('mousemove', onMouseMove);
310
+ window.removeEventListener('mouseup', onMouseUp);
311
+ el.removeEventListener('touchstart', onTouchStart);
312
+ window.removeEventListener('touchmove', onTouchMove);
313
+ window.removeEventListener('touchend', onTouchEnd);
314
+ };
315
+ }, [table]);
197
316
  const insertImageAtSelection = (src) => {
198
317
  try {
199
318
  const host = editableRef.current;
@@ -400,6 +519,20 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
400
519
  if (!node || !range)
401
520
  return;
402
521
  range.insertNode(node);
522
+ // Add resize handles to the new table
523
+ if (node instanceof HTMLTableElement) {
524
+ const tbody = node.querySelector('tbody');
525
+ if (tbody) {
526
+ const rows = Array.from(tbody.querySelectorAll('tr'));
527
+ rows.forEach((row, index) => {
528
+ row.setAttribute('data-row-index', String(index));
529
+ const cells = cellsOfRow(row);
530
+ cells.forEach((cell, cellIndex) => {
531
+ cell.setAttribute('data-col-index', String(cellIndex));
532
+ });
533
+ });
534
+ }
535
+ }
403
536
  // Move caret into first cell
404
537
  const firstCell = node.querySelector("td,th");
405
538
  if (firstCell)
@@ -741,6 +874,123 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
741
874
  applyToggle(fallbackCell);
742
875
  }
743
876
  };
877
+ // Table column and row resizing functions
878
+ const getColumnCells = (table, colIndex) => {
879
+ const tbody = table.querySelector('tbody');
880
+ if (!tbody)
881
+ return [];
882
+ const cells = [];
883
+ const rows = Array.from(tbody.querySelectorAll('tr'));
884
+ rows.forEach(row => {
885
+ const rowCells = cellsOfRow(row);
886
+ if (rowCells[colIndex]) {
887
+ cells.push(rowCells[colIndex]);
888
+ }
889
+ });
890
+ return cells;
891
+ };
892
+ const startColumnResize = (table, colIndex, clientX) => {
893
+ const cells = getColumnCells(table, colIndex);
894
+ if (cells.length === 0)
895
+ return;
896
+ const firstCell = cells[0];
897
+ const currentWidth = firstCell.offsetWidth;
898
+ tableResizeRef.current = {
899
+ type: 'column',
900
+ table,
901
+ index: colIndex,
902
+ startPos: clientX,
903
+ startSize: currentWidth,
904
+ cells,
905
+ };
906
+ document.body.style.cursor = 'col-resize';
907
+ document.body.style.userSelect = 'none';
908
+ };
909
+ const startRowResize = (table, rowIndex, clientY) => {
910
+ const tbody = table.querySelector('tbody');
911
+ if (!tbody)
912
+ return;
913
+ const rows = Array.from(tbody.querySelectorAll('tr'));
914
+ const row = rows[rowIndex];
915
+ if (!row)
916
+ return;
917
+ const cells = cellsOfRow(row);
918
+ const currentHeight = row.offsetHeight;
919
+ tableResizeRef.current = {
920
+ type: 'row',
921
+ table,
922
+ index: rowIndex,
923
+ startPos: clientY,
924
+ startSize: currentHeight,
925
+ cells,
926
+ };
927
+ document.body.style.cursor = 'row-resize';
928
+ document.body.style.userSelect = 'none';
929
+ };
930
+ const handleTableResizeMove = (e) => {
931
+ const resize = tableResizeRef.current;
932
+ if (!resize)
933
+ return;
934
+ e.preventDefault();
935
+ const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
936
+ const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;
937
+ if (resize.type === 'column') {
938
+ const delta = clientX - resize.startPos;
939
+ const newWidth = Math.max(60, resize.startSize + delta);
940
+ resize.cells.forEach(cell => {
941
+ cell.style.width = `${newWidth}px`;
942
+ cell.style.minWidth = `${newWidth}px`;
943
+ cell.style.maxWidth = `${newWidth}px`;
944
+ });
945
+ }
946
+ else if (resize.type === 'row') {
947
+ const delta = clientY - resize.startPos;
948
+ const newHeight = Math.max(30, resize.startSize + delta);
949
+ const tbody = resize.table.querySelector('tbody');
950
+ if (tbody) {
951
+ const rows = Array.from(tbody.querySelectorAll('tr'));
952
+ const row = rows[resize.index];
953
+ if (row) {
954
+ row.style.height = `${newHeight}px`;
955
+ resize.cells.forEach(cell => {
956
+ cell.style.height = `${newHeight}px`;
957
+ });
958
+ }
959
+ }
960
+ }
961
+ };
962
+ const handleTableResizeEnd = () => {
963
+ if (tableResizeRef.current) {
964
+ tableResizeRef.current = null;
965
+ document.body.style.cursor = '';
966
+ document.body.style.userSelect = '';
967
+ handleInput();
968
+ }
969
+ };
970
+ const addTableResizeHandles = () => {
971
+ if (!table)
972
+ return;
973
+ const el = editableRef.current;
974
+ if (!el)
975
+ return;
976
+ const tables = el.querySelectorAll('table');
977
+ tables.forEach(tableElem => {
978
+ const tbody = tableElem.querySelector('tbody');
979
+ if (!tbody)
980
+ return;
981
+ const firstRow = tbody.querySelector('tr');
982
+ if (firstRow) {
983
+ const cells = cellsOfRow(firstRow);
984
+ cells.forEach((cell, index) => {
985
+ cell.setAttribute('data-col-index', String(index));
986
+ });
987
+ }
988
+ const rows = Array.from(tbody.querySelectorAll('tr'));
989
+ rows.forEach((row, index) => {
990
+ row.setAttribute('data-row-index', String(index));
991
+ });
992
+ });
993
+ };
744
994
  return (_jsxs("div", { style: { border: "1px solid #ddd", borderRadius: 6 }, children: [_jsxs("div", { style: {
745
995
  display: "flex",
746
996
  flexWrap: "wrap",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smartrte-react",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "description": "A powerful, feature-rich Rich Text Editor for React with support for tables, mathematical formulas (LaTeX/KaTeX), and media management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,6 +38,16 @@
38
38
  },
39
39
  "author": "Smart RTE Contributors",
40
40
  "license": "MIT",
41
+ "scripts": {
42
+ "build": "tsc -p tsconfig.json",
43
+ "prepublishOnly": "pnpm run build",
44
+ "dev": "pnpm build",
45
+ "lint": "eslint . || true",
46
+ "test": "vitest run || true",
47
+ "storybook": "storybook dev -p 6006",
48
+ "build-storybook": "storybook build",
49
+ "e2e": "playwright test || true"
50
+ },
41
51
  "publishConfig": {
42
52
  "access": "public"
43
53
  },
@@ -59,16 +69,5 @@
59
69
  "@playwright/test": "^1.48.2",
60
70
  "react": "18.3.1",
61
71
  "react-dom": "18.3.1"
62
- },
63
- "scripts": {
64
- "build": "tsc -p tsconfig.json",
65
- "build:embed": "vite build",
66
- "build:all": "pnpm run build && pnpm run build:embed",
67
- "dev": "pnpm build",
68
- "lint": "eslint . || true",
69
- "test": "vitest run || true",
70
- "storybook": "storybook dev -p 6006",
71
- "build-storybook": "storybook build",
72
- "e2e": "playwright test || true"
73
72
  }
74
- }
73
+ }