@inshapardaz/likhari-react 0.1.8 → 0.1.9-dev.96

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 (38) hide show
  1. package/dist/EditorRoot.d.ts +60 -0
  2. package/dist/EditorRoot.d.ts.map +1 -1
  3. package/dist/EditorRoot.js +183 -10
  4. package/dist/components/DraftRestore.d.ts +24 -0
  5. package/dist/components/DraftRestore.d.ts.map +1 -0
  6. package/dist/components/DraftRestore.js +61 -0
  7. package/dist/components/DraftsDialog.d.ts +25 -0
  8. package/dist/components/DraftsDialog.d.ts.map +1 -0
  9. package/dist/components/DraftsDialog.js +66 -0
  10. package/dist/components/LeaveDialog.d.ts +22 -0
  11. package/dist/components/LeaveDialog.d.ts.map +1 -0
  12. package/dist/components/LeaveDialog.js +15 -0
  13. package/dist/components/TableDialog.d.ts +17 -0
  14. package/dist/components/TableDialog.d.ts.map +1 -0
  15. package/dist/components/TableDialog.js +33 -0
  16. package/dist/components/Toolbar.d.ts +4 -1
  17. package/dist/components/Toolbar.d.ts.map +1 -1
  18. package/dist/components/Toolbar.js +110 -6
  19. package/dist/i18n/strings.d.ts +65 -2
  20. package/dist/i18n/strings.d.ts.map +1 -1
  21. package/dist/i18n/strings.js +168 -3
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/nodes.d.ts.map +1 -1
  25. package/dist/nodes.js +4 -0
  26. package/dist/persistence/draftStorage.d.ts +55 -0
  27. package/dist/persistence/draftStorage.d.ts.map +1 -0
  28. package/dist/persistence/draftStorage.js +198 -0
  29. package/dist/persistence/draftUi.d.ts +9 -0
  30. package/dist/persistence/draftUi.d.ts.map +1 -0
  31. package/dist/persistence/draftUi.js +23 -0
  32. package/dist/table/tableActions.d.ts +21 -0
  33. package/dist/table/tableActions.d.ts.map +1 -0
  34. package/dist/table/tableActions.js +71 -0
  35. package/dist/theme/editor.css +111 -0
  36. package/dist/theme/editorTheme.d.ts.map +1 -1
  37. package/dist/theme/editorTheme.js +5 -0
  38. package/package.json +2 -1
@@ -0,0 +1,71 @@
1
+ import { $deleteTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $getTableCellNodeFromLexicalNode, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $insertTableRow__EXPERIMENTAL, $isTableCellNode, $isTableSelection, } from '@lexical/table';
2
+ import { $getSelection, $isRangeSelection } from 'lexical';
3
+ /** Table cells the selection covers: the caret's own cell, or every cell of a
4
+ * multi-cell selection. Empty when the selection isn't in a table. */
5
+ function $selectedCells() {
6
+ const selection = $getSelection();
7
+ if ($isTableSelection(selection))
8
+ return selection.getNodes().filter($isTableCellNode);
9
+ if ($isRangeSelection(selection)) {
10
+ const cell = $getTableCellNodeFromLexicalNode(selection.anchor.getNode());
11
+ return cell ? [cell] : [];
12
+ }
13
+ return [];
14
+ }
15
+ /** How many rows and columns the selection spans (1 × 1 for a caret in a cell, 0 × 0 outside a table). */
16
+ export function $getTableSelectionSize() {
17
+ const cells = $selectedCells();
18
+ if (cells.length === 0)
19
+ return { rows: 0, columns: 0 };
20
+ const rows = cells.map($getTableRowIndexFromTableCellNode);
21
+ const columns = cells.map($getTableColumnIndexFromTableCellNode);
22
+ return {
23
+ rows: Math.max(...rows) - Math.min(...rows) + 1,
24
+ columns: Math.max(...columns) - Math.min(...columns) + 1,
25
+ };
26
+ }
27
+ /**
28
+ * Inserts as many rows as the selection spans, before its first row or after
29
+ * its last. Lexical's own insert works from the selection's focus cell and adds
30
+ * one row, so with several rows selected it would land mid-selection.
31
+ */
32
+ export function $insertTableRows(insertAfter) {
33
+ const cells = $selectedCells();
34
+ if (cells.length === 0)
35
+ return;
36
+ const rows = cells.map($getTableRowIndexFromTableCellNode);
37
+ const first = Math.min(...rows);
38
+ const last = Math.max(...rows);
39
+ // Park the caret in a cell on the edge row; every insert then lands right next to it.
40
+ cells[rows.indexOf(insertAfter ? last : first)].selectEnd();
41
+ for (let i = 0; i <= last - first; i++)
42
+ $insertTableRow__EXPERIMENTAL(insertAfter);
43
+ }
44
+ /** Like $insertTableRows, for columns. "Before" is the column index below the
45
+ * first selected one (the right-hand side in a right-to-left table). */
46
+ export function $insertTableColumns(insertAfter) {
47
+ const cells = $selectedCells();
48
+ if (cells.length === 0)
49
+ return;
50
+ const columns = cells.map($getTableColumnIndexFromTableCellNode);
51
+ const first = Math.min(...columns);
52
+ const last = Math.max(...columns);
53
+ cells[columns.indexOf(insertAfter ? last : first)].selectEnd();
54
+ for (let i = 0; i <= last - first; i++)
55
+ $insertTableColumn__EXPERIMENTAL(insertAfter);
56
+ }
57
+ /** Deletes every row the selection touches (Lexical handles a multi-cell selection). */
58
+ export function $deleteTableRows() {
59
+ $deleteTableRow__EXPERIMENTAL();
60
+ }
61
+ /** Deletes every column the selection touches. */
62
+ export function $deleteTableColumns() {
63
+ $deleteTableColumn__EXPERIMENTAL();
64
+ }
65
+ /** Removes the whole table the selection is in. */
66
+ export function $deleteTable() {
67
+ const selection = $getSelection();
68
+ const anchor = $isRangeSelection(selection) || $isTableSelection(selection) ? selection.anchor.getNode() : null;
69
+ if (anchor)
70
+ $getTableNodeFromLexicalNodeOrThrow(anchor).remove();
71
+ }
@@ -51,6 +51,12 @@
51
51
  pointer-events: none;
52
52
  }
53
53
 
54
+ /* pointer-events is inherited, so without this every menu, dropdown and dialog
55
+ portaled into the (pointer-transparent) anchor would be unclickable. */
56
+ .likhari-portal-target > * {
57
+ pointer-events: auto;
58
+ }
59
+
54
60
  .likhari-toolbar-group {
55
61
  display: flex;
56
62
  align-items: center;
@@ -253,6 +259,37 @@
253
259
  margin: 1.5em 0;
254
260
  }
255
261
 
262
+ /* Tables — cell merge/split is deliberately out of scope for now (a flagged
263
+ open risk, lexical-editor-spec.md §12 item 3, needing its own scope
264
+ decision); TablePlugin is configured with hasCellMerge={false} to keep
265
+ every table a plain grid until that's resolved. */
266
+ .likhari-table {
267
+ border-collapse: collapse;
268
+ margin: 1em 0;
269
+ width: 100%;
270
+ }
271
+
272
+ .likhari-table-row {
273
+ border-bottom: 1px solid var(--editor-line);
274
+ }
275
+
276
+ .likhari-table-cell {
277
+ border: 1px solid var(--editor-line);
278
+ padding: 6px 10px;
279
+ min-width: 72px;
280
+ vertical-align: top;
281
+ }
282
+
283
+ .likhari-table-cell-header {
284
+ background: var(--editor-paper-dim);
285
+ font-weight: 600;
286
+ text-align: start;
287
+ }
288
+
289
+ .likhari-table-cell-selected {
290
+ background: var(--editor-accent-soft);
291
+ }
292
+
256
293
  /* Images — block-level figure; the caption is static text (edited in the
257
294
  image's dialog), and a selected image gets a corner resize handle. */
258
295
  .likhari-image-block {
@@ -370,3 +407,77 @@
370
407
  text-overflow: ellipsis;
371
408
  white-space: nowrap;
372
409
  }
410
+
411
+ /* Restore-draft banner: a strip between the toolbar and the canvas. Uses the
412
+ editor's own tokens, so it follows the accent color and dark mode. */
413
+ .likhari-draft-banner {
414
+ display: flex;
415
+ flex-shrink: 0;
416
+ flex-wrap: wrap;
417
+ align-items: center;
418
+ gap: 8px 12px;
419
+ padding: 8px 12px;
420
+ background: var(--editor-accent-soft);
421
+ border-bottom: 1px solid var(--editor-line);
422
+ color: var(--editor-ink);
423
+ font-size: 13px;
424
+ }
425
+
426
+ .likhari-draft-banner-message {
427
+ display: flex;
428
+ flex: 1 1 240px;
429
+ align-items: center;
430
+ gap: 8px;
431
+ }
432
+
433
+ .likhari-draft-banner-message svg {
434
+ flex-shrink: 0;
435
+ color: var(--editor-accent);
436
+ }
437
+
438
+ .likhari-draft-banner-actions {
439
+ display: flex;
440
+ flex-wrap: wrap;
441
+ gap: 6px;
442
+ }
443
+
444
+ .likhari-draft-banner-button {
445
+ height: 28px;
446
+ padding: 0 12px;
447
+ border: 1px solid var(--editor-line-strong);
448
+ border-radius: 6px;
449
+ background: var(--editor-paper);
450
+ color: var(--editor-ink);
451
+ font: inherit;
452
+ font-weight: 500;
453
+ cursor: pointer;
454
+ }
455
+
456
+ .likhari-draft-banner-button:hover {
457
+ background: var(--editor-paper-dim);
458
+ }
459
+
460
+ .likhari-draft-banner-button[data-variant='primary'] {
461
+ border-color: var(--editor-accent);
462
+ background: var(--editor-accent);
463
+ color: var(--editor-paper);
464
+ }
465
+
466
+ .likhari-draft-banner-button[data-variant='primary']:hover {
467
+ filter: brightness(1.1);
468
+ }
469
+
470
+ .likhari-draft-banner-button[data-variant='danger'] {
471
+ border-color: transparent;
472
+ background: transparent;
473
+ color: var(--editor-danger);
474
+ }
475
+
476
+ .likhari-draft-banner-button[data-variant='danger']:hover {
477
+ background: var(--editor-paper-dim);
478
+ }
479
+
480
+ .likhari-draft-banner-button:focus-visible {
481
+ outline: 2px solid var(--editor-accent);
482
+ outline-offset: 1px;
483
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,kBA8BzB,CAAC"}
1
+ {"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,kBAmCzB,CAAC"}
@@ -33,4 +33,9 @@ export const editorTheme = {
33
33
  },
34
34
  hr: 'likhari-hr',
35
35
  image: 'likhari-image-block',
36
+ table: 'likhari-table',
37
+ tableRow: 'likhari-table-row',
38
+ tableCell: 'likhari-table-cell',
39
+ tableCellHeader: 'likhari-table-cell-header',
40
+ tableCellSelected: 'likhari-table-cell-selected',
36
41
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inshapardaz/likhari-react",
3
- "version": "0.1.8",
3
+ "version": "0.1.9-dev.96",
4
4
  "description": "React implementation of the Likhari editor, built on @lexical/react.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,6 +38,7 @@
38
38
  "@lexical/react": "^0.20.0",
39
39
  "@lexical/rich-text": "^0.20.0",
40
40
  "@lexical/selection": "^0.20.0",
41
+ "@lexical/table": "^0.20.0",
41
42
  "@lexical/utils": "^0.20.0",
42
43
  "@inshapardaz/likhari-converters": "^0.1.0",
43
44
  "@inshapardaz/likhari-core": "^0.1.0",