@inshapardaz/likhari-react 0.1.18-dev.132 → 0.1.18-dev.136
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/blocks/poetryActions.d.ts +8 -0
- package/dist/blocks/poetryActions.d.ts.map +1 -1
- package/dist/blocks/poetryActions.js +24 -3
- package/dist/plugins/PoetryPlugin.d.ts +3 -3
- package/dist/plugins/PoetryPlugin.d.ts.map +1 -1
- package/dist/plugins/PoetryPlugin.js +8 -5
- package/dist/theme/editor.css +7 -0
- package/package.json +1 -1
|
@@ -13,6 +13,14 @@ export declare function $getPoetryBlockFromSelection(): PoetryBlockNode | null;
|
|
|
13
13
|
* selection and undo history all survive the conversion.
|
|
14
14
|
*/
|
|
15
15
|
export declare function $setPoetryLayout(node: PoetryBlockNode, layout: PoetryLayout): void;
|
|
16
|
+
/** A couplet at the very end of the document would otherwise leave no
|
|
17
|
+
* editable block to click or arrow down into — appends one empty paragraph
|
|
18
|
+
* if the couplet doesn't already have a next sibling. Idempotent: once a
|
|
19
|
+
* sibling exists (that paragraph, or anything else), this is a no-op, so
|
|
20
|
+
* it's safe to call from both the insert command and a node transform that
|
|
21
|
+
* keeps the invariant even after later edits (e.g. deleting the trailing
|
|
22
|
+
* paragraph, or JSON content loaded without one). */
|
|
23
|
+
export declare function $ensureTrailingParagraph(node: PoetryBlockNode): void;
|
|
16
24
|
/** Inserts a new two-misra couplet after the selection's top-level block,
|
|
17
25
|
* in `layout`/`align`, and focuses its first misra. */
|
|
18
26
|
export declare function $insertPoetryCouplet(layout: PoetryLayout, align: PoetryAlign): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poetryActions.d.ts","sourceRoot":"","sources":["../../src/blocks/poetryActions.ts"],"names":[],"mappings":"AACA,OAAO,EAA4E,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAEvH,OAAO,EAA8C,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAErI;wCACwC;AACxC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,EAAE,CAW1E;AAED,oEAAoE;AACpE,wBAAgB,4BAA4B,IAAI,eAAe,GAAG,IAAI,CAKrE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAclF;AAED;uDACuD;AACvD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"poetryActions.d.ts","sourceRoot":"","sources":["../../src/blocks/poetryActions.ts"],"names":[],"mappings":"AACA,OAAO,EAA4E,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAEvH,OAAO,EAA8C,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAErI;wCACwC;AACxC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,EAAE,CAW1E;AAED,oEAAoE;AACpE,wBAAgB,4BAA4B,IAAI,eAAe,GAAG,IAAI,CAKrE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAclF;AAED;;;;;;qDAMqD;AACrD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAEpE;AAED;uDACuD;AACvD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAyBtF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAuB5C"}
|
|
@@ -52,13 +52,29 @@ export function $setPoetryLayout(node, layout) {
|
|
|
52
52
|
}
|
|
53
53
|
node.setLayoutAttribute(layout);
|
|
54
54
|
}
|
|
55
|
+
/** A couplet at the very end of the document would otherwise leave no
|
|
56
|
+
* editable block to click or arrow down into — appends one empty paragraph
|
|
57
|
+
* if the couplet doesn't already have a next sibling. Idempotent: once a
|
|
58
|
+
* sibling exists (that paragraph, or anything else), this is a no-op, so
|
|
59
|
+
* it's safe to call from both the insert command and a node transform that
|
|
60
|
+
* keeps the invariant even after later edits (e.g. deleting the trailing
|
|
61
|
+
* paragraph, or JSON content loaded without one). */
|
|
62
|
+
export function $ensureTrailingParagraph(node) {
|
|
63
|
+
if (node.getNextSibling() === null)
|
|
64
|
+
node.insertAfter($createParagraphNode());
|
|
65
|
+
}
|
|
55
66
|
/** Inserts a new two-misra couplet after the selection's top-level block,
|
|
56
67
|
* in `layout`/`align`, and focuses its first misra. */
|
|
57
68
|
export function $insertPoetryCouplet(layout, align) {
|
|
58
69
|
const selection = $getSelection();
|
|
59
70
|
if (!$isRangeSelection(selection))
|
|
60
71
|
return false;
|
|
61
|
-
|
|
72
|
+
// getTopLevelElement() stops at the nearest shadow root, and a
|
|
73
|
+
// PoetryBlockNode is one — so from inside an existing couplet it resolves
|
|
74
|
+
// to the misra paragraph itself, not the couplet. Without this check, a
|
|
75
|
+
// second insert lands as a sibling of that misra (nested inside the first
|
|
76
|
+
// couplet) instead of after the couplet as a whole.
|
|
77
|
+
const anchorTopLevel = $getPoetryBlockFromSelection() ?? selection.anchor.getNode().getTopLevelElementOrThrow();
|
|
62
78
|
const node = $createPoetryBlockNode(layout, align);
|
|
63
79
|
const misraA = $createParagraphNode();
|
|
64
80
|
const misraB = $createParagraphNode();
|
|
@@ -71,6 +87,7 @@ export function $insertPoetryCouplet(layout, align) {
|
|
|
71
87
|
node.append(container);
|
|
72
88
|
}
|
|
73
89
|
anchorTopLevel.insertAfter(node);
|
|
90
|
+
$ensureTrailingParagraph(node);
|
|
74
91
|
misraA.selectStart();
|
|
75
92
|
return true;
|
|
76
93
|
}
|
|
@@ -99,8 +116,12 @@ export function $exitPoetryOnEnter() {
|
|
|
99
116
|
const isAtEnd = lastDesc ? anchor.key === lastDesc.getKey() && anchor.offset === lastDesc.getTextContentSize() : anchor.key === lastMisra.getKey();
|
|
100
117
|
if (!isAtEnd)
|
|
101
118
|
return false;
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
// $ensureTrailingParagraph already guarantees one after every couplet —
|
|
120
|
+
// reuse it rather than stacking a new empty paragraph on repeated Enters.
|
|
121
|
+
const existing = couplet.getNextSibling();
|
|
122
|
+
const paragraph = $isParagraphNode(existing) ? existing : $createParagraphNode();
|
|
123
|
+
if (paragraph !== existing)
|
|
124
|
+
couplet.insertAfter(paragraph);
|
|
104
125
|
paragraph.select();
|
|
105
126
|
return true;
|
|
106
127
|
}
|
|
@@ -6,9 +6,9 @@ export declare const INSERT_POETRY_COUPLET_COMMAND: LexicalCommand<{
|
|
|
6
6
|
}>;
|
|
7
7
|
/**
|
|
8
8
|
* Registers INSERT_POETRY_COUPLET_COMMAND (mirrors LayoutPlugin/FootnotePlugin's
|
|
9
|
-
* shape)
|
|
10
|
-
* content
|
|
11
|
-
*
|
|
9
|
+
* shape); a node transform that removes a couplet left with no misra
|
|
10
|
+
* content (e.g. after undo/paste leaves it structurally empty) and keeps a
|
|
11
|
+
* trailing couplet always followed by an editable paragraph; and a
|
|
12
12
|
* KEY_ENTER_COMMAND handler (above RichTextPlugin's own, which would
|
|
13
13
|
* otherwise trap Enter inside the couplet — see poetryActions.ts) that lets
|
|
14
14
|
* Enter at the end of the last misra add a paragraph after the block.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoF,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAGhI,OAAO,EAAmB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG5F,eAAO,MAAM,6BAA6B,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAEtG,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoF,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAGhI,OAAO,EAAmB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG5F,eAAO,MAAM,6BAA6B,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAEtG,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,YAAY,SAmC3B"}
|
|
@@ -4,13 +4,13 @@ import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, KEY_ENTER_COMMAND, crea
|
|
|
4
4
|
import { mergeRegister } from '@lexical/utils';
|
|
5
5
|
import { LayoutContainerNode, LayoutItemNode } from '../blocks/LayoutNode.js';
|
|
6
6
|
import { PoetryBlockNode } from '../blocks/PoetryNode.js';
|
|
7
|
-
import { $exitPoetryOnEnter, $insertPoetryCouplet } from '../blocks/poetryActions.js';
|
|
7
|
+
import { $ensureTrailingParagraph, $exitPoetryOnEnter, $insertPoetryCouplet } from '../blocks/poetryActions.js';
|
|
8
8
|
export const INSERT_POETRY_COUPLET_COMMAND = createCommand('INSERT_POETRY_COUPLET_COMMAND');
|
|
9
9
|
/**
|
|
10
10
|
* Registers INSERT_POETRY_COUPLET_COMMAND (mirrors LayoutPlugin/FootnotePlugin's
|
|
11
|
-
* shape)
|
|
12
|
-
* content
|
|
13
|
-
*
|
|
11
|
+
* shape); a node transform that removes a couplet left with no misra
|
|
12
|
+
* content (e.g. after undo/paste leaves it structurally empty) and keeps a
|
|
13
|
+
* trailing couplet always followed by an editable paragraph; and a
|
|
14
14
|
* KEY_ENTER_COMMAND handler (above RichTextPlugin's own, which would
|
|
15
15
|
* otherwise trap Enter inside the couplet — see poetryActions.ts) that lets
|
|
16
16
|
* Enter at the end of the last misra add a paragraph after the block.
|
|
@@ -22,8 +22,11 @@ export function PoetryPlugin() {
|
|
|
22
22
|
throw new Error('PoetryPlugin: PoetryBlockNode (and the columns nodes it composes) not registered on the editor');
|
|
23
23
|
}
|
|
24
24
|
return mergeRegister(editor.registerCommand(INSERT_POETRY_COUPLET_COMMAND, ({ layout, align }) => $insertPoetryCouplet(layout, align), COMMAND_PRIORITY_EDITOR), editor.registerNodeTransform(PoetryBlockNode, (node) => {
|
|
25
|
-
if (node.getChildrenSize() === 0)
|
|
25
|
+
if (node.getChildrenSize() === 0) {
|
|
26
26
|
node.remove();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
$ensureTrailingParagraph(node);
|
|
27
30
|
}), editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
|
|
28
31
|
if (event?.shiftKey)
|
|
29
32
|
return false; // Shift+Enter stays a plain line break
|
package/dist/theme/editor.css
CHANGED
|
@@ -413,6 +413,13 @@
|
|
|
413
413
|
text-align: inherit;
|
|
414
414
|
}
|
|
415
415
|
|
|
416
|
+
/* A visible divider between misra columns, same dashed language as the
|
|
417
|
+
couplet's own border — matches a table's internal cell borders. */
|
|
418
|
+
.likhari-poetry--two-column .likhari-layout-item:not(:first-child) {
|
|
419
|
+
border-inline-start: 1px dashed var(--editor-line-strong);
|
|
420
|
+
padding-inline-start: 16px;
|
|
421
|
+
}
|
|
422
|
+
|
|
416
423
|
.likhari-table {
|
|
417
424
|
border-collapse: collapse;
|
|
418
425
|
margin: 1em 0;
|