@37signals/lexxy 0.1.26-beta → 0.1.27-beta
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 +1 -1
- package/dist/lexxy.esm.js +38 -33
- package/dist/stylesheets/lexxy-editor.css +24 -104
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ A modern rich text editor for Rails.
|
|
|
23
23
|
Add this line to your application's Gemfile:
|
|
24
24
|
|
|
25
25
|
```ruby
|
|
26
|
-
gem 'lexxy', '~> 0.1.
|
|
26
|
+
gem 'lexxy', '~> 0.1.26.beta' # Need to specify the version since it's a pre-release
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
And then execute:
|
package/dist/lexxy.esm.js
CHANGED
|
@@ -15,7 +15,7 @@ import { $isListNode, $isListItemNode, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORD
|
|
|
15
15
|
import { $isQuoteNode, $isHeadingNode, $createQuoteNode, $createHeadingNode, QuoteNode, HeadingNode, registerRichText } from '@lexical/rich-text';
|
|
16
16
|
import { $isCodeNode, CodeNode, normalizeCodeLang, CodeHighlightNode, registerCodeHighlighting, CODE_LANGUAGE_FRIENDLY_NAME_MAP } from '@lexical/code';
|
|
17
17
|
import { $isLinkNode, $createAutoLinkNode, $toggleLink, $createLinkNode, LinkNode, AutoLinkNode } from '@lexical/link';
|
|
18
|
-
import { $getTableCellNodeFromLexicalNode, INSERT_TABLE_COMMAND, $insertTableRowAtSelection, $insertTableColumnAtSelection, $deleteTableRowAtSelection, $deleteTableColumnAtSelection, $findTableNode,
|
|
18
|
+
import { $getTableCellNodeFromLexicalNode, INSERT_TABLE_COMMAND, $insertTableRowAtSelection, $insertTableColumnAtSelection, $deleteTableRowAtSelection, $deleteTableColumnAtSelection, $findTableNode, TableCellNode, TableNode, TableRowNode, registerTablePlugin, registerTableSelectionObserver, setScrollableTablesActive, $getTableRowIndexFromTableCellNode, $getTableColumnIndexFromTableCellNode, $getElementForTableNode, $isTableCellNode, TableCellHeaderStates } from '@lexical/table';
|
|
19
19
|
import { $generateNodesFromDOM, $generateHtmlFromNodes } from '@lexical/html';
|
|
20
20
|
import { registerMarkdownShortcuts, TRANSFORMERS } from '@lexical/markdown';
|
|
21
21
|
import { createEmptyHistoryState, registerHistory } from '@lexical/history';
|
|
@@ -1645,26 +1645,19 @@ class Selection {
|
|
|
1645
1645
|
this.#containEditorFocus();
|
|
1646
1646
|
}
|
|
1647
1647
|
|
|
1648
|
-
clear() {
|
|
1649
|
-
this.current = null;
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
1648
|
set current(selection) {
|
|
1653
|
-
|
|
1654
|
-
this
|
|
1655
|
-
|
|
1656
|
-
this.#syncSelectedClasses();
|
|
1657
|
-
});
|
|
1658
|
-
} else {
|
|
1659
|
-
this.editor.update(() => {
|
|
1660
|
-
this.#syncSelectedClasses();
|
|
1661
|
-
this._current = null;
|
|
1662
|
-
});
|
|
1663
|
-
}
|
|
1649
|
+
this.editor.update(() => {
|
|
1650
|
+
this.#syncSelectedClasses();
|
|
1651
|
+
});
|
|
1664
1652
|
}
|
|
1665
1653
|
|
|
1666
|
-
get
|
|
1667
|
-
|
|
1654
|
+
get hasNodeSelection() {
|
|
1655
|
+
let result = false;
|
|
1656
|
+
this.editor.getEditorState().read(() => {
|
|
1657
|
+
const selection = $getSelection();
|
|
1658
|
+
result = selection !== null && $isNodeSelection(selection);
|
|
1659
|
+
});
|
|
1660
|
+
return result
|
|
1668
1661
|
}
|
|
1669
1662
|
|
|
1670
1663
|
get cursorPosition() {
|
|
@@ -1857,18 +1850,18 @@ class Selection {
|
|
|
1857
1850
|
}
|
|
1858
1851
|
|
|
1859
1852
|
get #currentlySelectedKeys() {
|
|
1860
|
-
if (this.
|
|
1853
|
+
if (this.currentlySelectedKeys) { return this.currentlySelectedKeys }
|
|
1861
1854
|
|
|
1862
|
-
this.
|
|
1855
|
+
this.currentlySelectedKeys = new Set();
|
|
1863
1856
|
|
|
1864
1857
|
const selection = $getSelection();
|
|
1865
1858
|
if (selection && $isNodeSelection(selection)) {
|
|
1866
1859
|
for (const node of selection.getNodes()) {
|
|
1867
|
-
this.
|
|
1860
|
+
this.currentlySelectedKeys.add(node.getKey());
|
|
1868
1861
|
}
|
|
1869
1862
|
}
|
|
1870
1863
|
|
|
1871
|
-
return this.
|
|
1864
|
+
return this.currentlySelectedKeys
|
|
1872
1865
|
}
|
|
1873
1866
|
|
|
1874
1867
|
#processSelectionChangeCommands() {
|
|
@@ -1998,7 +1991,7 @@ class Selection {
|
|
|
1998
1991
|
this.#highlightNewItems();
|
|
1999
1992
|
|
|
2000
1993
|
this.previouslySelectedKeys = this.#currentlySelectedKeys;
|
|
2001
|
-
this.
|
|
1994
|
+
this.currentlySelectedKeys = null;
|
|
2002
1995
|
}
|
|
2003
1996
|
|
|
2004
1997
|
#clearPreviouslyHighlightedItems() {
|
|
@@ -2020,7 +2013,7 @@ class Selection {
|
|
|
2020
2013
|
}
|
|
2021
2014
|
|
|
2022
2015
|
async #selectPreviousNode() {
|
|
2023
|
-
if (this.
|
|
2016
|
+
if (this.hasNodeSelection) {
|
|
2024
2017
|
await this.#withCurrentNode((currentNode) => currentNode.selectPrevious());
|
|
2025
2018
|
} else {
|
|
2026
2019
|
this.#selectInLexical(this.nodeBeforeCursor);
|
|
@@ -2028,7 +2021,7 @@ class Selection {
|
|
|
2028
2021
|
}
|
|
2029
2022
|
|
|
2030
2023
|
async #selectNextNode() {
|
|
2031
|
-
if (this.
|
|
2024
|
+
if (this.hasNodeSelection) {
|
|
2032
2025
|
await this.#withCurrentNode((currentNode) => currentNode.selectNext(0, 0));
|
|
2033
2026
|
} else {
|
|
2034
2027
|
this.#selectInLexical(this.nodeAfterCursor);
|
|
@@ -2036,7 +2029,7 @@ class Selection {
|
|
|
2036
2029
|
}
|
|
2037
2030
|
|
|
2038
2031
|
async #selectPreviousTopLevelNode() {
|
|
2039
|
-
if (this.
|
|
2032
|
+
if (this.hasNodeSelection) {
|
|
2040
2033
|
await this.#withCurrentNode((currentNode) => currentNode.selectPrevious());
|
|
2041
2034
|
} else {
|
|
2042
2035
|
this.#selectInLexical(this.topLevelNodeBeforeCursor);
|
|
@@ -2044,7 +2037,7 @@ class Selection {
|
|
|
2044
2037
|
}
|
|
2045
2038
|
|
|
2046
2039
|
async #selectNextTopLevelNode() {
|
|
2047
|
-
if (this.
|
|
2040
|
+
if (this.hasNodeSelection) {
|
|
2048
2041
|
await this.#withCurrentNode((currentNode) => currentNode.selectNext(0, 0));
|
|
2049
2042
|
} else {
|
|
2050
2043
|
this.#selectInLexical(this.topLevelNodeAfterCursor);
|
|
@@ -2053,10 +2046,9 @@ class Selection {
|
|
|
2053
2046
|
|
|
2054
2047
|
async #withCurrentNode(fn) {
|
|
2055
2048
|
await nextFrame();
|
|
2056
|
-
if (this.
|
|
2049
|
+
if (this.hasNodeSelection) {
|
|
2057
2050
|
this.editor.update(() => {
|
|
2058
|
-
|
|
2059
|
-
fn(this.current.getNodes()[0]);
|
|
2051
|
+
fn($getSelection().getNodes()[0]);
|
|
2060
2052
|
this.editor.focus();
|
|
2061
2053
|
});
|
|
2062
2054
|
}
|
|
@@ -2301,6 +2293,17 @@ class Selection {
|
|
|
2301
2293
|
}
|
|
2302
2294
|
}
|
|
2303
2295
|
|
|
2296
|
+
// Prevent the hardcoded background color
|
|
2297
|
+
// A background color value is set by Lexical if background is null:
|
|
2298
|
+
// https://github.com/facebook/lexical/blob/5bbbe849bd229e1db0e7b536e6a919520ada7bb2/packages/lexical-table/src/LexicalTableCellNode.ts#L187
|
|
2299
|
+
function registerHeaderBackgroundTransform(editor) {
|
|
2300
|
+
return editor.registerNodeTransform(TableCellNode, (node) => {
|
|
2301
|
+
if (node.getBackgroundColor() === null) {
|
|
2302
|
+
node.setBackgroundColor("");
|
|
2303
|
+
}
|
|
2304
|
+
})
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2304
2307
|
class CustomActionTextAttachmentNode extends DecoratorNode {
|
|
2305
2308
|
static getType() {
|
|
2306
2309
|
return "custom_action_text_attachment"
|
|
@@ -2949,8 +2952,8 @@ class Contents {
|
|
|
2949
2952
|
let focusNode = null;
|
|
2950
2953
|
|
|
2951
2954
|
this.editor.update(() => {
|
|
2952
|
-
if (
|
|
2953
|
-
const nodesToRemove =
|
|
2955
|
+
if (this.#selection.hasNodeSelection) {
|
|
2956
|
+
const nodesToRemove = $getSelection().getNodes();
|
|
2954
2957
|
if (nodesToRemove.length === 0) return
|
|
2955
2958
|
|
|
2956
2959
|
focusNode = this.#findAdjacentNodeTo(nodesToRemove);
|
|
@@ -2962,7 +2965,6 @@ class Contents {
|
|
|
2962
2965
|
|
|
2963
2966
|
this.editor.update(() => {
|
|
2964
2967
|
this.#selectAfterDeletion(focusNode);
|
|
2965
|
-
this.#selection.clear();
|
|
2966
2968
|
this.editor.focus();
|
|
2967
2969
|
});
|
|
2968
2970
|
}
|
|
@@ -3988,6 +3990,8 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
3988
3990
|
registerTablePlugin(this.editor);
|
|
3989
3991
|
this.tableHandler = createElement("lexxy-table-handler");
|
|
3990
3992
|
this.append(this.tableHandler);
|
|
3993
|
+
|
|
3994
|
+
this.#addUnregisterHandler(registerHeaderBackgroundTransform(this.editor));
|
|
3991
3995
|
}
|
|
3992
3996
|
|
|
3993
3997
|
#registerCodeHiglightingComponents() {
|
|
@@ -4556,6 +4560,7 @@ class TableHandler extends HTMLElement {
|
|
|
4556
4560
|
const container = createElement("details", {
|
|
4557
4561
|
className: "lexxy-table-control lexxy-table-control__more-menu"
|
|
4558
4562
|
});
|
|
4563
|
+
container.setAttribute("name", "lexxy-dropdown");
|
|
4559
4564
|
|
|
4560
4565
|
container.tabIndex = -1;
|
|
4561
4566
|
|
|
@@ -54,15 +54,17 @@
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
table {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
th, td {
|
|
58
|
+
&.table-cell--selected {
|
|
59
|
+
background-color: var(--lexxy-color-table-cell-selected-bg);
|
|
60
|
+
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
&.lexxy-content__table-cell--selected {
|
|
63
|
+
background-color: var(--lexxy-color-table-cell-selected-bg);
|
|
64
|
+
border-color: var(--lexxy-color-table-cell-selected-border);
|
|
65
|
+
}
|
|
64
66
|
}
|
|
65
|
-
|
|
67
|
+
|
|
66
68
|
&.lexxy-content__table--selection {
|
|
67
69
|
::selection {
|
|
68
70
|
background: transparent;
|
|
@@ -376,69 +378,6 @@
|
|
|
376
378
|
}
|
|
377
379
|
}
|
|
378
380
|
|
|
379
|
-
/* Table dropdown
|
|
380
|
-
/* -------------------------------------------------------------------------- */
|
|
381
|
-
|
|
382
|
-
:where(lexxy-table-dropdown) {
|
|
383
|
-
display: flex;
|
|
384
|
-
flex-direction: column;
|
|
385
|
-
gap: 1ch;
|
|
386
|
-
|
|
387
|
-
.lexxy-editor__table-create {
|
|
388
|
-
display: flex;
|
|
389
|
-
flex-direction: column;
|
|
390
|
-
flex-wrap: wrap;
|
|
391
|
-
gap: 0;
|
|
392
|
-
|
|
393
|
-
.lexxy-editor__table-buttons {
|
|
394
|
-
background-color: var(--lexxy-color-ink-lighter);
|
|
395
|
-
display: flex;
|
|
396
|
-
flex-direction: column;
|
|
397
|
-
gap: 1px;
|
|
398
|
-
padding: 1px;
|
|
399
|
-
|
|
400
|
-
div {
|
|
401
|
-
display: flex;
|
|
402
|
-
flex-direction: row;
|
|
403
|
-
gap: 1px;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
button {
|
|
407
|
-
aspect-ratio: 1.5 / 1;
|
|
408
|
-
border: 0;
|
|
409
|
-
border-radius: 0;
|
|
410
|
-
color: var(--lexxy-color-ink);
|
|
411
|
-
font-family: var(--lexxy-font-base);
|
|
412
|
-
font-size: var(--lexxy-text-small);
|
|
413
|
-
font-weight: normal;
|
|
414
|
-
inline-size: 4ch;
|
|
415
|
-
margin: 0;
|
|
416
|
-
|
|
417
|
-
&.active {
|
|
418
|
-
background-color: var(--lexxy-color-ink-lightest);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
label {
|
|
424
|
-
align-items: center;
|
|
425
|
-
display: flex;
|
|
426
|
-
gap: 0.5ch;
|
|
427
|
-
padding: 0.5ch 0;
|
|
428
|
-
margin-block-start: 1ch;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
&:has(input[type="checkbox"]:checked) {
|
|
432
|
-
.lexxy-editor__table-buttons {
|
|
433
|
-
div:first-child button,
|
|
434
|
-
button:first-child {
|
|
435
|
-
filter: brightness(0.95);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
381
|
/* Table handle buttons
|
|
443
382
|
/* -------------------------------------------------------------------------- */
|
|
444
383
|
|
|
@@ -453,7 +392,7 @@
|
|
|
453
392
|
line-height: 1;
|
|
454
393
|
position: absolute;
|
|
455
394
|
transform: translate(-50%, -120%);
|
|
456
|
-
z-index:
|
|
395
|
+
z-index: 2;
|
|
457
396
|
|
|
458
397
|
.lexxy-table-control {
|
|
459
398
|
align-items: center;
|
|
@@ -465,7 +404,8 @@
|
|
|
465
404
|
padding: 2px;
|
|
466
405
|
white-space: nowrap;
|
|
467
406
|
|
|
468
|
-
button
|
|
407
|
+
button,
|
|
408
|
+
summary {
|
|
469
409
|
aspect-ratio: 1 / 1;
|
|
470
410
|
align-items: center;
|
|
471
411
|
background-color: transparent;
|
|
@@ -477,14 +417,24 @@
|
|
|
477
417
|
font-weight: bold;
|
|
478
418
|
justify-content: center;
|
|
479
419
|
line-height: 1;
|
|
420
|
+
list-style: none;
|
|
480
421
|
min-block-size: var(--button-size);
|
|
481
422
|
min-inline-size: var(--button-size);
|
|
482
423
|
padding: 0;
|
|
424
|
+
user-select: none;
|
|
425
|
+
-webkit-user-select: none;
|
|
483
426
|
|
|
484
427
|
&:hover {
|
|
485
428
|
background-color: var(--lexxy-color-ink-medium);
|
|
486
429
|
}
|
|
487
430
|
|
|
431
|
+
&:focus,
|
|
432
|
+
&:focus-visible {
|
|
433
|
+
background-color: var(--lexxy-color-ink-medium);
|
|
434
|
+
outline: var(--lexxy-focus-ring-size) solid var(--lexxy-focus-ring-color);
|
|
435
|
+
outline-offset: var(--lexxy-focus-ring-offset);
|
|
436
|
+
}
|
|
437
|
+
|
|
488
438
|
svg {
|
|
489
439
|
block-size: 1em;
|
|
490
440
|
inline-size: 1em;
|
|
@@ -495,47 +445,17 @@
|
|
|
495
445
|
display: none;
|
|
496
446
|
}
|
|
497
447
|
}
|
|
498
|
-
|
|
499
|
-
button,
|
|
500
|
-
summary {
|
|
501
|
-
&:focus,
|
|
502
|
-
&:focus-visible {
|
|
503
|
-
background-color: var(--lexxy-color-ink-medium);
|
|
504
|
-
outline: var(--lexxy-focus-ring-size) solid var(--lexxy-focus-ring-color);
|
|
505
|
-
outline-offset: var(--lexxy-focus-ring-offset);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
448
|
}
|
|
509
449
|
|
|
510
450
|
.lexxy-table-control__more-menu {
|
|
511
451
|
gap: 0;
|
|
512
|
-
padding:
|
|
452
|
+
padding: 0.25ch;
|
|
513
453
|
position: relative;
|
|
514
454
|
|
|
515
455
|
summary {
|
|
516
|
-
aspect-ratio: 1 / 1;
|
|
517
|
-
align-items: center;
|
|
518
|
-
background: transparent;
|
|
519
|
-
border-radius: var(--lexxy-radius);
|
|
520
|
-
border: 0;
|
|
521
|
-
box-sizing: border-box;
|
|
522
|
-
display: flex;
|
|
523
|
-
font-size: inherit;
|
|
524
|
-
justify-content: center;
|
|
525
|
-
list-style: none;
|
|
526
|
-
min-block-size: var(--button-size);
|
|
527
|
-
min-inline-size: var(--button-size);
|
|
528
|
-
padding: 0;
|
|
529
|
-
user-select: none;
|
|
530
|
-
-webkit-user-select: none;
|
|
531
|
-
|
|
532
456
|
&::-webkit-details-marker {
|
|
533
457
|
display: none;
|
|
534
458
|
}
|
|
535
|
-
|
|
536
|
-
&:hover {
|
|
537
|
-
background: var(--lexxy-color-ink-medium);
|
|
538
|
-
}
|
|
539
459
|
}
|
|
540
460
|
|
|
541
461
|
.lexxy-table-control__more-menu-details {
|
|
@@ -552,7 +472,7 @@
|
|
|
552
472
|
border-radius: 0.75ch;
|
|
553
473
|
display: flex;
|
|
554
474
|
flex-direction: column;
|
|
555
|
-
padding:
|
|
475
|
+
padding: 0.25ch;
|
|
556
476
|
}
|
|
557
477
|
|
|
558
478
|
button {
|