@inshapardaz/likhari-react 0.1.18-dev.152 → 0.1.18-dev.154
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/PoetryCoupletNode.d.ts +36 -0
- package/dist/blocks/PoetryCoupletNode.d.ts.map +1 -0
- package/dist/blocks/PoetryCoupletNode.js +85 -0
- package/dist/blocks/PoetryNode.d.ts +13 -12
- package/dist/blocks/PoetryNode.d.ts.map +1 -1
- package/dist/blocks/PoetryNode.js +15 -14
- package/dist/blocks/poetryActions.d.ts +34 -16
- package/dist/blocks/poetryActions.d.ts.map +1 -1
- package/dist/blocks/poetryActions.js +126 -70
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +25 -10
- package/dist/i18n/strings.d.ts +3 -0
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +9 -0
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +2 -0
- package/dist/plugins/PoetryPlugin.d.ts.map +1 -1
- package/dist/plugins/PoetryPlugin.js +3 -2
- package/dist/theme/editor.css +50 -17
- package/dist/theme/editorTheme.d.ts.map +1 -1
- package/dist/theme/editorTheme.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type DOMConversionMap, type DOMExportOutput, type EditorConfig, type LexicalNode, type NodeKey, type SerializedElementNode, type Spread, ElementNode } from 'lexical';
|
|
2
|
+
export type SerializedPoetryCoupletNode = Spread<{
|
|
3
|
+
centered: boolean;
|
|
4
|
+
}, SerializedElementNode>;
|
|
5
|
+
/**
|
|
6
|
+
* One couplet's two misra lines, wrapped so each couplet can carry its own
|
|
7
|
+
* rendering override independent of its PoetryBlockNode's overall layout —
|
|
8
|
+
* currently just `centered` (a narrower box, centered on the page, instead
|
|
9
|
+
* of the block's default width): "two columns with a couplet that is
|
|
10
|
+
* single, aligned centered" mixes LayoutContainerNode rows (two-column
|
|
11
|
+
* couplets) with centered PoetryCoupletNodes in the same block, each
|
|
12
|
+
* couplet choosing independently.
|
|
13
|
+
*
|
|
14
|
+
* Used for single-column and alternating block layouts; a two-column
|
|
15
|
+
* couplet uses LayoutContainerNode instead (its own two-item row already
|
|
16
|
+
* gives it a natural per-couplet box, so it doesn't need this wrapper).
|
|
17
|
+
*/
|
|
18
|
+
export declare class PoetryCoupletNode extends ElementNode {
|
|
19
|
+
__centered: boolean;
|
|
20
|
+
constructor(centered?: boolean, key?: NodeKey);
|
|
21
|
+
static getType(): string;
|
|
22
|
+
static clone(node: PoetryCoupletNode): PoetryCoupletNode;
|
|
23
|
+
getCentered(): boolean;
|
|
24
|
+
setCentered(centered: boolean): this;
|
|
25
|
+
static importJSON(serializedNode: SerializedPoetryCoupletNode): PoetryCoupletNode;
|
|
26
|
+
exportJSON(): SerializedPoetryCoupletNode;
|
|
27
|
+
static importDOM(): DOMConversionMap | null;
|
|
28
|
+
exportDOM(): DOMExportOutput;
|
|
29
|
+
createDOM(config: EditorConfig): HTMLElement;
|
|
30
|
+
updateDOM(prevNode: PoetryCoupletNode, dom: HTMLElement, config: EditorConfig): boolean;
|
|
31
|
+
canBeEmpty(): false;
|
|
32
|
+
canIndent(): false;
|
|
33
|
+
}
|
|
34
|
+
export declare function $createPoetryCoupletNode(centered?: boolean): PoetryCoupletNode;
|
|
35
|
+
export declare function $isPoetryCoupletNode(node: LexicalNode | null | undefined): node is PoetryCoupletNode;
|
|
36
|
+
//# sourceMappingURL=PoetryCoupletNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PoetryCoupletNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryCoupletNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,2BAA2B,GAAG,MAAM,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,EAAE,qBAAqB,CAAC,CAAC;AAE/F;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,UAAU,EAAE,OAAO,CAAC;gBAER,QAAQ,UAAQ,EAAE,GAAG,CAAC,EAAE,OAAO;IAK3C,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,GAAG,iBAAiB;IAIxD,WAAW,IAAI,OAAO;IAItB,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAMpC,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,2BAA2B,GAAG,iBAAiB;IAIjF,UAAU,IAAI,2BAA2B;IAIzC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAU3C,SAAS,IAAI,eAAe;IAO5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAQ5C,SAAS,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO;IAQvF,UAAU,IAAI,KAAK;IAInB,SAAS,IAAI,KAAK;CAGnB;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,UAAQ,GAAG,iBAAiB,CAE5E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,iBAAiB,CAEpG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { addClassNamesToElement } from '@lexical/utils';
|
|
2
|
+
import { $applyNodeReplacement, ElementNode, } from 'lexical';
|
|
3
|
+
/**
|
|
4
|
+
* One couplet's two misra lines, wrapped so each couplet can carry its own
|
|
5
|
+
* rendering override independent of its PoetryBlockNode's overall layout —
|
|
6
|
+
* currently just `centered` (a narrower box, centered on the page, instead
|
|
7
|
+
* of the block's default width): "two columns with a couplet that is
|
|
8
|
+
* single, aligned centered" mixes LayoutContainerNode rows (two-column
|
|
9
|
+
* couplets) with centered PoetryCoupletNodes in the same block, each
|
|
10
|
+
* couplet choosing independently.
|
|
11
|
+
*
|
|
12
|
+
* Used for single-column and alternating block layouts; a two-column
|
|
13
|
+
* couplet uses LayoutContainerNode instead (its own two-item row already
|
|
14
|
+
* gives it a natural per-couplet box, so it doesn't need this wrapper).
|
|
15
|
+
*/
|
|
16
|
+
export class PoetryCoupletNode extends ElementNode {
|
|
17
|
+
constructor(centered = false, key) {
|
|
18
|
+
super(key);
|
|
19
|
+
this.__centered = centered;
|
|
20
|
+
}
|
|
21
|
+
static getType() {
|
|
22
|
+
return 'poetry-couplet';
|
|
23
|
+
}
|
|
24
|
+
static clone(node) {
|
|
25
|
+
return new PoetryCoupletNode(node.__centered, node.__key);
|
|
26
|
+
}
|
|
27
|
+
getCentered() {
|
|
28
|
+
return this.getLatest().__centered;
|
|
29
|
+
}
|
|
30
|
+
setCentered(centered) {
|
|
31
|
+
const writable = this.getWritable();
|
|
32
|
+
writable.__centered = centered;
|
|
33
|
+
return writable;
|
|
34
|
+
}
|
|
35
|
+
static importJSON(serializedNode) {
|
|
36
|
+
return $createPoetryCoupletNode(serializedNode.centered);
|
|
37
|
+
}
|
|
38
|
+
exportJSON() {
|
|
39
|
+
return { ...super.exportJSON(), type: 'poetry-couplet', version: 1, centered: this.getCentered() };
|
|
40
|
+
}
|
|
41
|
+
static importDOM() {
|
|
42
|
+
return {
|
|
43
|
+
div: (domNode) => {
|
|
44
|
+
if (!domNode.hasAttribute('data-likhari-poetry-couplet'))
|
|
45
|
+
return null;
|
|
46
|
+
const centered = domNode.getAttribute('data-likhari-poetry-couplet-centered') === 'true';
|
|
47
|
+
return { conversion: () => ({ node: $createPoetryCoupletNode(centered) }), priority: 2 };
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
exportDOM() {
|
|
52
|
+
const element = document.createElement('div');
|
|
53
|
+
element.setAttribute('data-likhari-poetry-couplet', '');
|
|
54
|
+
if (this.getCentered())
|
|
55
|
+
element.setAttribute('data-likhari-poetry-couplet-centered', 'true');
|
|
56
|
+
return { element };
|
|
57
|
+
}
|
|
58
|
+
createDOM(config) {
|
|
59
|
+
const element = document.createElement('div');
|
|
60
|
+
const base = config.theme.poetryCouplet ?? 'likhari-poetry-couplet';
|
|
61
|
+
addClassNamesToElement(element, base);
|
|
62
|
+
if (this.__centered)
|
|
63
|
+
element.classList.add(`${base}--centered`);
|
|
64
|
+
return element;
|
|
65
|
+
}
|
|
66
|
+
updateDOM(prevNode, dom, config) {
|
|
67
|
+
if (prevNode.__centered !== this.__centered) {
|
|
68
|
+
const base = config.theme.poetryCouplet ?? 'likhari-poetry-couplet';
|
|
69
|
+
dom.classList.toggle(`${base}--centered`, this.__centered);
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
canBeEmpty() {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
canIndent() {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export function $createPoetryCoupletNode(centered = false) {
|
|
81
|
+
return $applyNodeReplacement(new PoetryCoupletNode(centered));
|
|
82
|
+
}
|
|
83
|
+
export function $isPoetryCoupletNode(node) {
|
|
84
|
+
return node instanceof PoetryCoupletNode;
|
|
85
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DOMConversionMap, type DOMExportOutput, type EditorConfig, type LexicalNode, type NodeKey, type SerializedElementNode, type Spread, ElementNode } from 'lexical';
|
|
2
|
-
export type PoetryLayout = 'single' | 'two-column';
|
|
2
|
+
export type PoetryLayout = 'single' | 'two-column' | 'alternating';
|
|
3
3
|
export type PoetryAlign = 'justify' | 'left' | 'right' | 'start';
|
|
4
4
|
export type SerializedPoetryBlockNode = Spread<{
|
|
5
5
|
layout: PoetryLayout;
|
|
@@ -7,17 +7,18 @@ export type SerializedPoetryBlockNode = Spread<{
|
|
|
7
7
|
width?: number;
|
|
8
8
|
}, SerializedElementNode>;
|
|
9
9
|
/**
|
|
10
|
-
* A poetry *section*: one or more couplets (two-line verse units)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* restructured/grown
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
10
|
+
* A poetry *section*: one or more couplets (two-line verse units), each
|
|
11
|
+
* wrapped as either a PoetryCoupletNode (single-column/alternating — see
|
|
12
|
+
* that file) or a LayoutContainerNode row (two-column, built on the
|
|
13
|
+
* columns primitive, §4.9) — see blocks/poetryActions.ts's $getCouplets
|
|
14
|
+
* for how a block's children (a free mix of either wrapper, per couplet)
|
|
15
|
+
* are read, and $setPoetryLayout/$exitPoetryOnEnter for how they're
|
|
16
|
+
* restructured/grown. `layout` is this block's *default* for couplets
|
|
17
|
+
* appended to it (a PoetryCoupletNode can still individually override to
|
|
18
|
+
* "centered" regardless); `align` applies to the whole section. Both
|
|
19
|
+
* mutate in place via poetryActions so converting a section between
|
|
20
|
+
* layouts doesn't lose selection/undo coherence. One extensible primitive
|
|
21
|
+
* in place of four fixed templates, per requirements doc §4.11.
|
|
21
22
|
*/
|
|
22
23
|
export declare class PoetryBlockNode extends ElementNode {
|
|
23
24
|
__layout: PoetryLayout;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PoetryNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"PoetryNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PoetryNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,qBAAqB,EAC1B,KAAK,MAAM,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,aAAa,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAwBjE,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,qBAAqB,CAAC,CAAC;AAEpI;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB;8DAC0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEL,MAAM,GAAE,YAAuB,EAAE,KAAK,GAAE,WAAuB,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO;IAO1G,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe;IAIpD,SAAS,IAAI,YAAY;IAIzB,QAAQ,IAAI,WAAW;IAIvB,QAAQ,IAAI,MAAM,GAAG,SAAS;IAI9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAMzC;;gEAE4D;IAC5D,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAM9C,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMlC,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,yBAAyB,GAAG,eAAe;IAI7E,UAAU,IAAI,yBAAyB;IAYvC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAe3C,SAAS,IAAI,eAAe;IAW5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAa5C,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO;IAerF,UAAU,IAAI,KAAK;IAInB,YAAY,IAAI,OAAO;CAGxB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,YAAuB,EAAE,KAAK,GAAE,WAAuB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,CAEvI;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,eAAe,CAEhG"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { addClassNamesToElement } from '@lexical/utils';
|
|
2
2
|
import { $applyNodeReplacement, ElementNode, } from 'lexical';
|
|
3
|
-
const VALID_LAYOUTS = new Set(['single', 'two-column']);
|
|
3
|
+
const VALID_LAYOUTS = new Set(['single', 'two-column', 'alternating']);
|
|
4
4
|
const VALID_ALIGNS = new Set(['justify', 'left', 'right', 'start']);
|
|
5
5
|
/** `text-align: justify` only stretches a line that actually wraps — a
|
|
6
6
|
* misra short enough to fit on one line would otherwise just sit at its own
|
|
@@ -22,17 +22,18 @@ function applyWidthStyle(element, width) {
|
|
|
22
22
|
element.style.maxWidth = `${width}px`;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* A poetry *section*: one or more couplets (two-line verse units)
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* restructured/grown
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
25
|
+
* A poetry *section*: one or more couplets (two-line verse units), each
|
|
26
|
+
* wrapped as either a PoetryCoupletNode (single-column/alternating — see
|
|
27
|
+
* that file) or a LayoutContainerNode row (two-column, built on the
|
|
28
|
+
* columns primitive, §4.9) — see blocks/poetryActions.ts's $getCouplets
|
|
29
|
+
* for how a block's children (a free mix of either wrapper, per couplet)
|
|
30
|
+
* are read, and $setPoetryLayout/$exitPoetryOnEnter for how they're
|
|
31
|
+
* restructured/grown. `layout` is this block's *default* for couplets
|
|
32
|
+
* appended to it (a PoetryCoupletNode can still individually override to
|
|
33
|
+
* "centered" regardless); `align` applies to the whole section. Both
|
|
34
|
+
* mutate in place via poetryActions so converting a section between
|
|
35
|
+
* layouts doesn't lose selection/undo coherence. One extensible primitive
|
|
36
|
+
* in place of four fixed templates, per requirements doc §4.11.
|
|
36
37
|
*/
|
|
37
38
|
export class PoetryBlockNode extends ElementNode {
|
|
38
39
|
constructor(layout = 'single', align = 'justify', width, key) {
|
|
@@ -42,7 +43,7 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
42
43
|
this.__width = width;
|
|
43
44
|
}
|
|
44
45
|
static getType() {
|
|
45
|
-
return 'poetry-
|
|
46
|
+
return 'poetry-block';
|
|
46
47
|
}
|
|
47
48
|
static clone(node) {
|
|
48
49
|
return new PoetryBlockNode(node.__layout, node.__align, node.__width, node.__key);
|
|
@@ -81,7 +82,7 @@ export class PoetryBlockNode extends ElementNode {
|
|
|
81
82
|
const width = this.getWidth();
|
|
82
83
|
return {
|
|
83
84
|
...super.exportJSON(),
|
|
84
|
-
type: 'poetry-
|
|
85
|
+
type: 'poetry-block',
|
|
85
86
|
version: 1,
|
|
86
87
|
layout: this.getLayout(),
|
|
87
88
|
align: this.getAlign(),
|
|
@@ -3,12 +3,13 @@ import { type PoetryAlign, type PoetryLayout, type PoetryBlockNode } from './Poe
|
|
|
3
3
|
/** One couplet's two misra paragraphs, in order. */
|
|
4
4
|
export type Couplet = [ParagraphNode, ParagraphNode];
|
|
5
5
|
/**
|
|
6
|
-
* A poetry block
|
|
7
|
-
* (single-column
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* A poetry block's children are a free mix, per couplet, of either a
|
|
7
|
+
* PoetryCoupletNode (single-column/alternating, optionally `centered`) or a
|
|
8
|
+
* LayoutContainerNode row (two-column) — "two columns with a couplet that
|
|
9
|
+
* is single, aligned centered" means exactly this: some couplets two-column,
|
|
10
|
+
* others centered singles, in the same block. This walks that mixed
|
|
11
|
+
* structure and returns each couplet as a misra pair, in document order —
|
|
12
|
+
* the one place that knows how to read either wrapper, so nothing else does.
|
|
12
13
|
*/
|
|
13
14
|
export declare function $getCouplets(node: PoetryBlockNode): Couplet[];
|
|
14
15
|
/** Every misra in the block, flattened across all its couplets — for
|
|
@@ -18,14 +19,33 @@ export declare function $getMisraParagraphs(node: PoetryBlockNode): ParagraphNod
|
|
|
18
19
|
/** The PoetryBlockNode the current selection is inside, or null. */
|
|
19
20
|
export declare function $getPoetryBlockFromSelection(): PoetryBlockNode | null;
|
|
20
21
|
/**
|
|
21
|
-
* Converts every couplet in the block between
|
|
22
|
-
*
|
|
23
|
-
* pulls each couplet's two misra
|
|
24
|
-
* currently holds them and rebuilds the
|
|
25
|
-
* paragraph nodes, preserving couplet order
|
|
26
|
-
*
|
|
22
|
+
* Converts every couplet in the block between two-column (built on the
|
|
23
|
+
* columns primitive, §4.9) and single-column/alternating (a
|
|
24
|
+
* PoetryCoupletNode per couplet) — pulls each couplet's two misra
|
|
25
|
+
* paragraphs out of whichever shape currently holds them and rebuilds the
|
|
26
|
+
* other shape around the same paragraph nodes, preserving couplet order
|
|
27
|
+
* (and dropping any individual 'centered' override, which only applies to
|
|
28
|
+
* the non-two-column shape), so content, selection and undo history all
|
|
29
|
+
* survive the conversion. Switching between 'single' and 'alternating' is
|
|
30
|
+
* purely an attribute change (both use the same PoetryCoupletNode
|
|
31
|
+
* structure) — no restructuring needed.
|
|
27
32
|
*/
|
|
28
33
|
export declare function $setPoetryLayout(node: PoetryBlockNode, layout: PoetryLayout): void;
|
|
34
|
+
/**
|
|
35
|
+
* Sets whether the couplet the selection is inside renders as a narrower,
|
|
36
|
+
* centered box ("single, aligned centered") instead of the block's default
|
|
37
|
+
* width — independent of the block's own layout. A two-column couplet is
|
|
38
|
+
* converted into a PoetryCoupletNode first (its two columns stacked into
|
|
39
|
+
* two lines), since "centered" only applies to that shape; a couplet
|
|
40
|
+
* that's already a PoetryCoupletNode just has its flag flipped. Returns
|
|
41
|
+
* false when the selection isn't inside a couplet.
|
|
42
|
+
*/
|
|
43
|
+
export declare function $setCoupletCentered(centered: boolean): boolean;
|
|
44
|
+
/** Whether the couplet the selection is inside is currently centered —
|
|
45
|
+
* always false for a two-column couplet, since that override only applies
|
|
46
|
+
* to the PoetryCoupletNode shape. Null when the selection isn't inside a
|
|
47
|
+
* couplet at all (vs. inside one that just isn't centered). */
|
|
48
|
+
export declare function $getCoupletCenteredFromSelection(): boolean | null;
|
|
29
49
|
/** A block at the very end of the document would otherwise leave no
|
|
30
50
|
* editable block to click or arrow down into — appends one empty paragraph
|
|
31
51
|
* if the block doesn't already have a next sibling. Idempotent: once a
|
|
@@ -37,10 +57,8 @@ export declare function $ensureTrailingParagraph(node: PoetryBlockNode): void;
|
|
|
37
57
|
/**
|
|
38
58
|
* Inserts a poetry couplet at the caret. If the caret is already inside a
|
|
39
59
|
* poetry block, appends a new couplet to *that* block (in its existing
|
|
40
|
-
* layout
|
|
41
|
-
*
|
|
42
|
-
* not chosen per couplet) and focuses its first misra. Otherwise creates a
|
|
43
|
-
* new block (in `layout`/`align`) with one couplet, after the selection's
|
|
60
|
+
* default layout) and focuses its first misra. Otherwise creates a new
|
|
61
|
+
* block (in `layout`/`align`) with one couplet, after the selection's
|
|
44
62
|
* top-level element.
|
|
45
63
|
*/
|
|
46
64
|
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,EAA4F,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"poetryActions.d.ts","sourceRoot":"","sources":["../../src/blocks/poetryActions.ts"],"names":[],"mappings":"AACA,OAAO,EAA4F,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAGvI,OAAO,EAA8C,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAErI,oDAAoD;AACpD,MAAM,MAAM,OAAO,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,EAAE,CAc7D;AAED;;6CAE6C;AAC7C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,EAAE,CAE1E;AAED,oEAAoE;AACpE,wBAAgB,4BAA4B,IAAI,eAAe,GAAG,IAAI,CAKrE;AAyCD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CA8BlF;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CA4B9D;AAED;;;+DAG+D;AAC/D,wBAAgB,gCAAgC,IAAI,OAAO,GAAG,IAAI,CAYjE;AAED;;;;;;qDAMqD;AACrD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAmBtF;AAED;;;;wCAIwC;AACxC,wBAAgB,oBAAoB,IAAI,OAAO,CAkB9C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CA8BlD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAyC5C"}
|
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import { $findMatchingParent } from '@lexical/utils';
|
|
2
2
|
import { $createParagraphNode, $getSelection, $isElementNode, $isParagraphNode, $isRangeSelection } from 'lexical';
|
|
3
3
|
import { $createLayoutContainerNode, $createLayoutItemNode, $isLayoutContainerNode, $isLayoutItemNode } from './LayoutNode.js';
|
|
4
|
+
import { $createPoetryCoupletNode, $isPoetryCoupletNode } from './PoetryCoupletNode.js';
|
|
4
5
|
import { $createPoetryBlockNode, $isPoetryBlockNode } from './PoetryNode.js';
|
|
5
6
|
/**
|
|
6
|
-
* A poetry block
|
|
7
|
-
* (single-column
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* A poetry block's children are a free mix, per couplet, of either a
|
|
8
|
+
* PoetryCoupletNode (single-column/alternating, optionally `centered`) or a
|
|
9
|
+
* LayoutContainerNode row (two-column) — "two columns with a couplet that
|
|
10
|
+
* is single, aligned centered" means exactly this: some couplets two-column,
|
|
11
|
+
* others centered singles, in the same block. This walks that mixed
|
|
12
|
+
* structure and returns each couplet as a misra pair, in document order —
|
|
13
|
+
* the one place that knows how to read either wrapper, so nothing else does.
|
|
12
14
|
*/
|
|
13
15
|
export function $getCouplets(node) {
|
|
14
|
-
if (node.getLayout() === 'single') {
|
|
15
|
-
const paragraphs = node.getChildren().filter($isParagraphNode);
|
|
16
|
-
const couplets = [];
|
|
17
|
-
for (let i = 0; i + 1 < paragraphs.length; i += 2)
|
|
18
|
-
couplets.push([paragraphs[i], paragraphs[i + 1]]);
|
|
19
|
-
return couplets;
|
|
20
|
-
}
|
|
21
|
-
const containers = node.getChildren().filter($isLayoutContainerNode);
|
|
22
16
|
const couplets = [];
|
|
23
|
-
for (const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
for (const child of node.getChildren()) {
|
|
18
|
+
if ($isPoetryCoupletNode(child)) {
|
|
19
|
+
const [a, b] = child.getChildren().filter($isParagraphNode);
|
|
20
|
+
if (a && b)
|
|
21
|
+
couplets.push([a, b]);
|
|
22
|
+
}
|
|
23
|
+
else if ($isLayoutContainerNode(child)) {
|
|
24
|
+
const items = child.getChildren().filter($isLayoutItemNode);
|
|
25
|
+
const a = items[0]?.getFirstChild();
|
|
26
|
+
const b = items[1]?.getFirstChild();
|
|
27
|
+
if ($isParagraphNode(a) && $isParagraphNode(b))
|
|
28
|
+
couplets.push([a, b]);
|
|
29
|
+
}
|
|
29
30
|
}
|
|
30
31
|
return couplets;
|
|
31
32
|
}
|
|
@@ -55,30 +56,53 @@ function $findCoupletPosition(couplets, target) {
|
|
|
55
56
|
}
|
|
56
57
|
return null;
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
+
/** A couplet's own wrapper node (PoetryCoupletNode or LayoutContainerNode) —
|
|
60
|
+
* every couplet has exactly one, so removing/replacing a couplet means
|
|
61
|
+
* operating on this, not on its misra paragraphs individually. */
|
|
62
|
+
function $findCoupletWrapper(misra) {
|
|
63
|
+
return $findMatchingParent(misra, (n) => $isPoetryCoupletNode(n) || $isLayoutContainerNode(n));
|
|
64
|
+
}
|
|
65
|
+
/** Appends a new couplet to the block, in its default layout (two-column
|
|
66
|
+
* for a 'two-column' block, a plain PoetryCoupletNode otherwise) unless
|
|
67
|
+
* `twoColumn` is given explicitly. */
|
|
68
|
+
function $appendCoupletTo(node, twoColumn) {
|
|
59
69
|
const misraA = $createParagraphNode();
|
|
60
70
|
const misraB = $createParagraphNode();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
71
|
+
const useTwoColumn = twoColumn ?? node.getLayout() === 'two-column';
|
|
72
|
+
if (useTwoColumn) {
|
|
65
73
|
const container = $createLayoutContainerNode('repeat(2, 1fr)');
|
|
66
74
|
container.append($createLayoutItemNode().append(misraA), $createLayoutItemNode().append(misraB));
|
|
67
75
|
node.append(container);
|
|
68
76
|
}
|
|
77
|
+
else {
|
|
78
|
+
node.append($createPoetryCoupletNode().append(misraA, misraB));
|
|
79
|
+
}
|
|
69
80
|
return [misraA, misraB];
|
|
70
81
|
}
|
|
71
82
|
/**
|
|
72
|
-
* Converts every couplet in the block between
|
|
73
|
-
*
|
|
74
|
-
* pulls each couplet's two misra
|
|
75
|
-
* currently holds them and rebuilds the
|
|
76
|
-
* paragraph nodes, preserving couplet order
|
|
77
|
-
*
|
|
83
|
+
* Converts every couplet in the block between two-column (built on the
|
|
84
|
+
* columns primitive, §4.9) and single-column/alternating (a
|
|
85
|
+
* PoetryCoupletNode per couplet) — pulls each couplet's two misra
|
|
86
|
+
* paragraphs out of whichever shape currently holds them and rebuilds the
|
|
87
|
+
* other shape around the same paragraph nodes, preserving couplet order
|
|
88
|
+
* (and dropping any individual 'centered' override, which only applies to
|
|
89
|
+
* the non-two-column shape), so content, selection and undo history all
|
|
90
|
+
* survive the conversion. Switching between 'single' and 'alternating' is
|
|
91
|
+
* purely an attribute change (both use the same PoetryCoupletNode
|
|
92
|
+
* structure) — no restructuring needed.
|
|
78
93
|
*/
|
|
79
94
|
export function $setPoetryLayout(node, layout) {
|
|
80
|
-
|
|
95
|
+
const from = node.getLayout();
|
|
96
|
+
if (from === layout)
|
|
97
|
+
return;
|
|
98
|
+
const fromTwoColumn = from === 'two-column';
|
|
99
|
+
const toTwoColumn = layout === 'two-column';
|
|
100
|
+
if (fromTwoColumn === toTwoColumn) {
|
|
101
|
+
// Both 'single' and 'alternating' share the same PoetryCoupletNode
|
|
102
|
+
// structure — just relabel the block.
|
|
103
|
+
node.setLayoutAttribute(layout);
|
|
81
104
|
return;
|
|
105
|
+
}
|
|
82
106
|
const couplets = $getCouplets(node);
|
|
83
107
|
for (const [a, b] of couplets) {
|
|
84
108
|
a.remove();
|
|
@@ -86,19 +110,74 @@ export function $setPoetryLayout(node, layout) {
|
|
|
86
110
|
}
|
|
87
111
|
for (const leftover of node.getChildren())
|
|
88
112
|
leftover.remove();
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
node.append(a, b);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
for (const [a, b] of couplets) {
|
|
113
|
+
for (const [a, b] of couplets) {
|
|
114
|
+
if (toTwoColumn) {
|
|
95
115
|
const container = $createLayoutContainerNode('repeat(2, 1fr)');
|
|
96
116
|
container.append($createLayoutItemNode().append(a), $createLayoutItemNode().append(b));
|
|
97
117
|
node.append(container);
|
|
98
118
|
}
|
|
119
|
+
else {
|
|
120
|
+
node.append($createPoetryCoupletNode().append(a, b));
|
|
121
|
+
}
|
|
99
122
|
}
|
|
100
123
|
node.setLayoutAttribute(layout);
|
|
101
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Sets whether the couplet the selection is inside renders as a narrower,
|
|
127
|
+
* centered box ("single, aligned centered") instead of the block's default
|
|
128
|
+
* width — independent of the block's own layout. A two-column couplet is
|
|
129
|
+
* converted into a PoetryCoupletNode first (its two columns stacked into
|
|
130
|
+
* two lines), since "centered" only applies to that shape; a couplet
|
|
131
|
+
* that's already a PoetryCoupletNode just has its flag flipped. Returns
|
|
132
|
+
* false when the selection isn't inside a couplet.
|
|
133
|
+
*/
|
|
134
|
+
export function $setCoupletCentered(centered) {
|
|
135
|
+
const block = $getPoetryBlockFromSelection();
|
|
136
|
+
if (!block)
|
|
137
|
+
return false;
|
|
138
|
+
const selection = $getSelection();
|
|
139
|
+
if (!$isRangeSelection(selection))
|
|
140
|
+
return false;
|
|
141
|
+
const couplets = $getCouplets(block);
|
|
142
|
+
const position = $findCoupletPosition(couplets, selection.anchor.getNode());
|
|
143
|
+
if (!position)
|
|
144
|
+
return false;
|
|
145
|
+
const [a, b] = couplets[position.coupletIndex];
|
|
146
|
+
const wrapper = $findCoupletWrapper(a);
|
|
147
|
+
if (!wrapper)
|
|
148
|
+
return false;
|
|
149
|
+
if ($isPoetryCoupletNode(wrapper)) {
|
|
150
|
+
wrapper.setCentered(centered);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
// A two-column couplet: stack its two columns into a centered pair,
|
|
154
|
+
// replacing the LayoutContainerNode row with a PoetryCoupletNode in the
|
|
155
|
+
// same position.
|
|
156
|
+
a.remove();
|
|
157
|
+
b.remove();
|
|
158
|
+
const coupletNode = $createPoetryCoupletNode(centered).append(a, b);
|
|
159
|
+
wrapper.insertAfter(coupletNode);
|
|
160
|
+
wrapper.remove();
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
/** Whether the couplet the selection is inside is currently centered —
|
|
164
|
+
* always false for a two-column couplet, since that override only applies
|
|
165
|
+
* to the PoetryCoupletNode shape. Null when the selection isn't inside a
|
|
166
|
+
* couplet at all (vs. inside one that just isn't centered). */
|
|
167
|
+
export function $getCoupletCenteredFromSelection() {
|
|
168
|
+
const block = $getPoetryBlockFromSelection();
|
|
169
|
+
if (!block)
|
|
170
|
+
return null;
|
|
171
|
+
const selection = $getSelection();
|
|
172
|
+
if (!$isRangeSelection(selection))
|
|
173
|
+
return null;
|
|
174
|
+
const couplets = $getCouplets(block);
|
|
175
|
+
const position = $findCoupletPosition(couplets, selection.anchor.getNode());
|
|
176
|
+
if (!position)
|
|
177
|
+
return null;
|
|
178
|
+
const wrapper = $findCoupletWrapper(couplets[position.coupletIndex][0]);
|
|
179
|
+
return $isPoetryCoupletNode(wrapper) ? wrapper.getCentered() : false;
|
|
180
|
+
}
|
|
102
181
|
/** A block at the very end of the document would otherwise leave no
|
|
103
182
|
* editable block to click or arrow down into — appends one empty paragraph
|
|
104
183
|
* if the block doesn't already have a next sibling. Idempotent: once a
|
|
@@ -113,10 +192,8 @@ export function $ensureTrailingParagraph(node) {
|
|
|
113
192
|
/**
|
|
114
193
|
* Inserts a poetry couplet at the caret. If the caret is already inside a
|
|
115
194
|
* poetry block, appends a new couplet to *that* block (in its existing
|
|
116
|
-
* layout
|
|
117
|
-
*
|
|
118
|
-
* not chosen per couplet) and focuses its first misra. Otherwise creates a
|
|
119
|
-
* new block (in `layout`/`align`) with one couplet, after the selection's
|
|
195
|
+
* default layout) and focuses its first misra. Otherwise creates a new
|
|
196
|
+
* block (in `layout`/`align`) with one couplet, after the selection's
|
|
120
197
|
* top-level element.
|
|
121
198
|
*/
|
|
122
199
|
export function $insertPoetryCouplet(layout, align) {
|
|
@@ -131,7 +208,7 @@ export function $insertPoetryCouplet(layout, align) {
|
|
|
131
208
|
}
|
|
132
209
|
const anchorTopLevel = selection.anchor.getNode().getTopLevelElementOrThrow();
|
|
133
210
|
const node = $createPoetryBlockNode(layout, align);
|
|
134
|
-
const [misraA] = $appendCoupletTo(node);
|
|
211
|
+
const [misraA] = $appendCoupletTo(node, layout === 'two-column');
|
|
135
212
|
anchorTopLevel.insertAfter(node);
|
|
136
213
|
$ensureTrailingParagraph(node);
|
|
137
214
|
misraA.selectStart();
|
|
@@ -157,14 +234,7 @@ export function $deletePoetryCouplet() {
|
|
|
157
234
|
block.remove();
|
|
158
235
|
return true;
|
|
159
236
|
}
|
|
160
|
-
|
|
161
|
-
const container = $findMatchingParent(a, $isLayoutContainerNode);
|
|
162
|
-
if (container)
|
|
163
|
-
container.remove();
|
|
164
|
-
else {
|
|
165
|
-
a.remove();
|
|
166
|
-
b.remove();
|
|
167
|
-
}
|
|
237
|
+
$findCoupletWrapper(target[0])?.remove();
|
|
168
238
|
return true;
|
|
169
239
|
}
|
|
170
240
|
/**
|
|
@@ -190,12 +260,11 @@ export function $deletePoetryOnBackspace() {
|
|
|
190
260
|
const position = $findCoupletPosition(couplets, anchorNode);
|
|
191
261
|
if (!position || position.misraIndex !== 0)
|
|
192
262
|
return false;
|
|
193
|
-
const [
|
|
263
|
+
const [a, b] = couplets[position.coupletIndex];
|
|
194
264
|
const anchor = selection.anchor;
|
|
195
|
-
const isAtStart = anchor.key ===
|
|
265
|
+
const isAtStart = anchor.key === a.getKey() && anchor.offset === 0;
|
|
196
266
|
if (!isAtStart)
|
|
197
267
|
return false;
|
|
198
|
-
const [a, b] = couplets[position.coupletIndex];
|
|
199
268
|
if (!a.isEmpty() || !b.isEmpty())
|
|
200
269
|
return false;
|
|
201
270
|
if (couplets.length <= 1) {
|
|
@@ -205,13 +274,7 @@ export function $deletePoetryOnBackspace() {
|
|
|
205
274
|
previous.selectEnd();
|
|
206
275
|
return true;
|
|
207
276
|
}
|
|
208
|
-
|
|
209
|
-
if (container)
|
|
210
|
-
container.remove();
|
|
211
|
-
else {
|
|
212
|
-
a.remove();
|
|
213
|
-
b.remove();
|
|
214
|
-
}
|
|
277
|
+
$findCoupletWrapper(a)?.remove();
|
|
215
278
|
const remaining = $getCouplets(block);
|
|
216
279
|
const previousCouplet = remaining[position.coupletIndex - 1] ?? remaining[0];
|
|
217
280
|
previousCouplet?.[1].selectEnd();
|
|
@@ -252,15 +315,8 @@ export function $exitPoetryOnEnter() {
|
|
|
252
315
|
// Drop the couplet we ourselves auto-created on the previous Enter —
|
|
253
316
|
// unless it's the block's only couplet, in which case leave the
|
|
254
317
|
// section as the user's (empty) content rather than deleting it.
|
|
255
|
-
if (couplets.length > 1)
|
|
256
|
-
|
|
257
|
-
if (container)
|
|
258
|
-
container.remove();
|
|
259
|
-
else {
|
|
260
|
-
a.remove();
|
|
261
|
-
b.remove();
|
|
262
|
-
}
|
|
263
|
-
}
|
|
318
|
+
if (couplets.length > 1)
|
|
319
|
+
$findCoupletWrapper(a)?.remove();
|
|
264
320
|
const existingNext = block.getNextSibling();
|
|
265
321
|
const paragraph = $isParagraphNode(existingNext) ? existingNext : $createParagraphNode();
|
|
266
322
|
if (paragraph !== existingNext)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AAuEA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AA0fvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,EAAE,YAAY,+BA0kCxJ"}
|
|
@@ -15,7 +15,7 @@ import { INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
|
15
15
|
import { INSERT_LAYOUT_COMMAND } from '../blocks/LayoutNode.js';
|
|
16
16
|
import { INSERT_FOOTNOTE_COMMAND } from '../blocks/FootnoteNode.js';
|
|
17
17
|
import { $isPoetryBlockNode } from '../blocks/PoetryNode.js';
|
|
18
|
-
import { $deletePoetryCouplet, $getPoetryBlockFromSelection, $setPoetryLayout } from '../blocks/poetryActions.js';
|
|
18
|
+
import { $deletePoetryCouplet, $getCoupletCenteredFromSelection, $getPoetryBlockFromSelection, $setCoupletCentered, $setPoetryLayout, } from '../blocks/poetryActions.js';
|
|
19
19
|
import { INSERT_POETRY_COUPLET_COMMAND } from '../plugins/PoetryPlugin.js';
|
|
20
20
|
import { TableDialog } from './TableDialog.js';
|
|
21
21
|
import { LayoutDialog } from './LayoutDialog.js';
|
|
@@ -29,7 +29,7 @@ import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fo
|
|
|
29
29
|
import { setStyleProperty } from '../utils/style.js';
|
|
30
30
|
import { useStrings } from '../i18n/useStrings.js';
|
|
31
31
|
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
32
|
-
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconArrowMergeBoth, IconArrowsSplit2, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconColumns, IconColumns1, IconColumns2, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconTable, IconTableMinus, IconTrash, IconTableOptions, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
32
|
+
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconArrowMergeBoth, IconArrowsSplit2, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconColumns, IconArrowsShuffle, IconColumns1, IconColumns2, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconTable, IconTableMinus, IconTrash, IconTableOptions, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
33
33
|
/** Sentinel for "no inline style": Lexical returns the default it is given when
|
|
34
34
|
* the selection has none, so this tells "unstyled" (show the canvas default)
|
|
35
35
|
* apart from "styled with a value the dropdown doesn't list" (show nothing). */
|
|
@@ -51,6 +51,7 @@ const INITIAL_STATE = {
|
|
|
51
51
|
inPoetry: false,
|
|
52
52
|
poetryLayout: 'single',
|
|
53
53
|
poetryAlign: 'justify',
|
|
54
|
+
coupletCentered: false,
|
|
54
55
|
canUndo: false,
|
|
55
56
|
canRedo: false,
|
|
56
57
|
};
|
|
@@ -162,10 +163,13 @@ function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canU
|
|
|
162
163
|
};
|
|
163
164
|
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconRowInsertTop, manyRows ? t.insertRowsBefore : t.insertRowBefore, () => $insertTableRows(false)), item(IconRowInsertBottom, manyRows ? t.insertRowsAfter : t.insertRowAfter, () => $insertTableRows(true)), item(rtl ? IconColumnInsertRight : IconColumnInsertLeft, manyColumns ? t.insertColumnsBefore : t.insertColumnBefore, () => $insertTableColumns(false)), item(rtl ? IconColumnInsertLeft : IconColumnInsertRight, manyColumns ? t.insertColumnsAfter : t.insertColumnAfter, () => $insertTableColumns(true)), (canMergeCells || canUnmergeCell) && _jsx(Menu.Divider, {}), canMergeCells && item(IconArrowMergeBoth, t.mergeCells, $mergeTableCells), canUnmergeCell && item(IconArrowsSplit2, t.unmergeCell, $unmergeTableCell), _jsx(Menu.Divider, {}), item(IconRowRemove, manyRows ? t.deleteRows : t.deleteRow, $deleteTableRows), item(IconColumnRemove, manyColumns ? t.deleteColumns : t.deleteColumn, $deleteTableColumns), item(IconTableMinus, t.deleteTable, $deleteTable, 'red')] }));
|
|
164
165
|
}
|
|
165
|
-
/** The poetry couplet menu's contents — layout (single/two-column
|
|
166
|
-
* literal alignment
|
|
167
|
-
* "set per CoupletNode, not inherited from a document-wide
|
|
168
|
-
|
|
166
|
+
/** The poetry couplet menu's contents — block layout (single/two-column/
|
|
167
|
+
* alternating), literal alignment (both per-block overrides, requirements
|
|
168
|
+
* doc §4.11: "set per CoupletNode, not inherited from a document-wide
|
|
169
|
+
* setting"), and a per-couplet "centered" toggle independent of either —
|
|
170
|
+
* "two columns with a couplet that is single, aligned centered" mixes a
|
|
171
|
+
* centered couplet into an otherwise two-column block. */
|
|
172
|
+
function PoetryMenuItems({ strings, alignIcons, layout, align, centered, onAction, }) {
|
|
169
173
|
const t = strings.poetryMenu;
|
|
170
174
|
const a = strings.toolbar.alignOptions;
|
|
171
175
|
const item = (icon, label, action, active = false, color) => {
|
|
@@ -180,7 +184,7 @@ function PoetryMenuItems({ strings, alignIcons, layout, align, onAction, }) {
|
|
|
180
184
|
const setAlign = (next) => () => {
|
|
181
185
|
$getPoetryBlockFromSelection()?.setAlign(next);
|
|
182
186
|
};
|
|
183
|
-
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconColumns1, t.singleColumn, setLayout('single'), layout === 'single'), item(IconColumns2, t.twoColumn, setLayout('two-column'), layout === 'two-column'), _jsx(Menu.Divider, {}), item(alignIcons.justify ?? IconAlignJustified, a.justify, setAlign('justify'), align === 'justify'), item(alignIcons.start ?? IconAlignLeft, a.start, setAlign('start'), align === 'start'), item(IconAlignLeft, a.left, setAlign('left'), align === 'left'), item(IconAlignRight, a.right, setAlign('right'), align === 'right'), _jsx(Menu.Divider, {}), item(IconTrash, t.deleteCouplet, $deletePoetryCouplet, false, 'red')] }));
|
|
187
|
+
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconColumns1, t.singleColumn, setLayout('single'), layout === 'single'), item(IconColumns2, t.twoColumn, setLayout('two-column'), layout === 'two-column'), item(IconArrowsShuffle, t.alternating, setLayout('alternating'), layout === 'alternating'), _jsx(Menu.Divider, {}), item(alignIcons.justify ?? IconAlignJustified, a.justify, setAlign('justify'), align === 'justify'), item(alignIcons.start ?? IconAlignLeft, a.start, setAlign('start'), align === 'start'), item(IconAlignLeft, a.left, setAlign('left'), align === 'left'), item(IconAlignRight, a.right, setAlign('right'), align === 'right'), _jsx(Menu.Divider, {}), item(IconAlignCenter, centered ? t.uncenterCouplet : t.centerCouplet, () => $setCoupletCentered(!centered)), _jsx(Menu.Divider, {}), item(IconTrash, t.deleteCouplet, $deletePoetryCouplet, false, 'red')] }));
|
|
184
188
|
}
|
|
185
189
|
export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en', drafts }) {
|
|
186
190
|
const [editor] = useLexicalComposerContext();
|
|
@@ -206,7 +210,16 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
206
210
|
if ($isTableSelection(selection)) {
|
|
207
211
|
const { rows, columns } = $getTableSelectionSize();
|
|
208
212
|
const canMergeCells = $canMergeSelectedCells();
|
|
209
|
-
setState((s) => ({
|
|
213
|
+
setState((s) => ({
|
|
214
|
+
...s,
|
|
215
|
+
inTable: true,
|
|
216
|
+
tableRows: rows,
|
|
217
|
+
tableColumns: columns,
|
|
218
|
+
canMergeCells,
|
|
219
|
+
canUnmergeCell: false,
|
|
220
|
+
inPoetry: false,
|
|
221
|
+
coupletCentered: false,
|
|
222
|
+
}));
|
|
210
223
|
return;
|
|
211
224
|
}
|
|
212
225
|
if (!$isRangeSelection(selection))
|
|
@@ -243,6 +256,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
243
256
|
const elementFormat = ($isElementNode(element) ? element.getFormatType() : 'start') || 'start';
|
|
244
257
|
const poetryLayout = poetryBlock?.getLayout();
|
|
245
258
|
const poetryAlign = poetryBlock?.getAlign();
|
|
259
|
+
const coupletCentered = $getCoupletCenteredFromSelection();
|
|
246
260
|
setState((s) => ({
|
|
247
261
|
...s,
|
|
248
262
|
blockType,
|
|
@@ -261,6 +275,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
261
275
|
inPoetry: poetryBlock !== null,
|
|
262
276
|
poetryLayout: poetryLayout ?? s.poetryLayout,
|
|
263
277
|
poetryAlign: poetryAlign ?? s.poetryAlign,
|
|
278
|
+
coupletCentered: coupletCentered ?? false,
|
|
264
279
|
}));
|
|
265
280
|
});
|
|
266
281
|
}, [editor]);
|
|
@@ -806,7 +821,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
806
821
|
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
|
|
807
822
|
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.blocks.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_COMMAND, undefined) })), config.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.columns && _jsx(ToolbarButton, { icon: IconColumns, title: strings.toolbar.insertColumns, onClick: openLayoutDialog }), config.footnotes && (_jsx(ToolbarButton, { icon: IconNumber1Small, title: strings.toolbar.insertFootnote, onClick: () => editor.dispatchCommand(INSERT_FOOTNOTE_COMMAND, undefined) })), config.blocks.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.poetry.enabled && locale !== 'en' && (_jsx(ToolbarButton, { icon: IconFeather, title: strings.toolbar.insertPoetryCouplet, onClick: () => editor.dispatchCommand(INSERT_POETRY_COUPLET_COMMAND, { layout: config.poetry.defaultLayout, align: 'justify' }) }))] }, "stubInsert")),
|
|
808
823
|
config.tables && state.inTable && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.tableOptions, title: strings.toolbar.tableOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconTableOptions, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] }) }, "tableActions")),
|
|
809
|
-
config.poetry.enabled && state.inPoetry && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.poetryOptions, title: strings.toolbar.poetryOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign, onAction: runMenuAction }) })] }) }, "poetryActions")),
|
|
824
|
+
config.poetry.enabled && state.inPoetry && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.poetryOptions, title: strings.toolbar.poetryOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign, centered: state.coupletCentered, onAction: runMenuAction }) })] }) }, "poetryActions")),
|
|
810
825
|
showLanguageGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [config.language.autocorrect && _jsx(StubButton, { icon: IconWand, title: strings.toolbar.autocorrect, comingSoon: strings.toolbar.comingSoon }), config.language.textCleanup && _jsx(StubButton, { icon: IconSparkles, title: strings.toolbar.textCleanup, comingSoon: strings.toolbar.comingSoon }), config.language.spellCheck && _jsx(StubButton, { icon: IconAbc, title: strings.toolbar.spellChecker, comingSoon: strings.toolbar.comingSoon })] }, "language")),
|
|
811
826
|
];
|
|
812
827
|
return (_jsxs("div", { className: "likhari-toolbar", role: "toolbar", "aria-label": strings.toolbar.ariaLabel, ref: toolbarContainerRef, children: [fixedGroups, movableGroups
|
|
@@ -825,7 +840,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
825
840
|
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: tableContext?.x ?? -9999, top: tableContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: tableContext?.rows ?? 1, columns: tableContext?.columns ?? 1, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] })), config.poetry.enabled && (_jsxs(Menu, { opened: poetryContext !== null, onChange: (opened) => {
|
|
826
841
|
if (!opened)
|
|
827
842
|
setPoetryContext(null);
|
|
828
|
-
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: poetryContext?.x ?? -9999, top: poetryContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign, onAction: runMenuAction }) })] })), _jsxs("div", { "aria-hidden": "true", ref: toolbarMeasureRef, style: {
|
|
843
|
+
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: poetryContext?.x ?? -9999, top: poetryContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, alignIcons: ALIGN_ICONS, layout: state.poetryLayout, align: state.poetryAlign, centered: state.coupletCentered, onAction: runMenuAction }) })] })), _jsxs("div", { "aria-hidden": "true", ref: toolbarMeasureRef, style: {
|
|
829
844
|
position: 'absolute',
|
|
830
845
|
visibility: 'hidden',
|
|
831
846
|
pointerEvents: 'none',
|
package/dist/i18n/strings.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n/strings.js
CHANGED
|
@@ -125,6 +125,9 @@ const en = {
|
|
|
125
125
|
menuLabel: 'Poetry',
|
|
126
126
|
singleColumn: 'Single column',
|
|
127
127
|
twoColumn: 'Two column',
|
|
128
|
+
alternating: 'Alternating',
|
|
129
|
+
centerCouplet: 'Center this couplet',
|
|
130
|
+
uncenterCouplet: 'Un-center this couplet',
|
|
128
131
|
deleteCouplet: 'Delete couplet',
|
|
129
132
|
},
|
|
130
133
|
link: {
|
|
@@ -333,6 +336,9 @@ const ur = {
|
|
|
333
336
|
menuLabel: 'شاعری',
|
|
334
337
|
singleColumn: 'ایک کالم',
|
|
335
338
|
twoColumn: 'دو کالم',
|
|
339
|
+
alternating: 'باری باری',
|
|
340
|
+
centerCouplet: 'یہ شعر وسط میں رکھیں',
|
|
341
|
+
uncenterCouplet: 'وسط میں رکھنا ختم کریں',
|
|
336
342
|
deleteCouplet: 'شعر حذف کریں',
|
|
337
343
|
},
|
|
338
344
|
link: {
|
|
@@ -541,6 +547,9 @@ const paShahmukhi = {
|
|
|
541
547
|
menuLabel: 'شاعری',
|
|
542
548
|
singleColumn: 'اک کالم',
|
|
543
549
|
twoColumn: 'دو کالم',
|
|
550
|
+
alternating: 'واری واری',
|
|
551
|
+
centerCouplet: 'ایہ شعر وچکار رکھو',
|
|
552
|
+
uncenterCouplet: 'وچکار رکھنا بند کرو',
|
|
544
553
|
deleteCouplet: 'شعر مٹاؤ',
|
|
545
554
|
},
|
|
546
555
|
link: {
|
package/dist/nodes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAclD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAmB5C,CAAC"}
|
package/dist/nodes.js
CHANGED
|
@@ -9,6 +9,7 @@ import { LayoutContainerNode, LayoutItemNode } from './blocks/LayoutNode.js';
|
|
|
9
9
|
import { FootnoteReferenceNode } from './blocks/FootnoteNode.js';
|
|
10
10
|
import { FootnoteItemNode, FootnoteListNode } from './blocks/FootnoteListNode.js';
|
|
11
11
|
import { PoetryBlockNode } from './blocks/PoetryNode.js';
|
|
12
|
+
import { PoetryCoupletNode } from './blocks/PoetryCoupletNode.js';
|
|
12
13
|
/**
|
|
13
14
|
* Node types registered on the editor at construction time. Per
|
|
14
15
|
* editor-architecture-design.md §2, node registration cannot be conditional
|
|
@@ -36,4 +37,5 @@ export const EDITOR_NODES = [
|
|
|
36
37
|
FootnoteListNode,
|
|
37
38
|
FootnoteItemNode,
|
|
38
39
|
PoetryBlockNode,
|
|
40
|
+
PoetryCoupletNode,
|
|
39
41
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAIjB,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;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,SA4C3B"}
|
|
@@ -3,6 +3,7 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
|
|
|
3
3
|
import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, createCommand, } from 'lexical';
|
|
4
4
|
import { mergeRegister } from '@lexical/utils';
|
|
5
5
|
import { LayoutContainerNode, LayoutItemNode } from '../blocks/LayoutNode.js';
|
|
6
|
+
import { PoetryCoupletNode } from '../blocks/PoetryCoupletNode.js';
|
|
6
7
|
import { PoetryBlockNode } from '../blocks/PoetryNode.js';
|
|
7
8
|
import { $deletePoetryOnBackspace, $ensureTrailingParagraph, $exitPoetryOnEnter, $insertPoetryCouplet } from '../blocks/poetryActions.js';
|
|
8
9
|
export const INSERT_POETRY_COUPLET_COMMAND = createCommand('INSERT_POETRY_COUPLET_COMMAND');
|
|
@@ -21,8 +22,8 @@ export const INSERT_POETRY_COUPLET_COMMAND = createCommand('INSERT_POETRY_COUPLE
|
|
|
21
22
|
export function PoetryPlugin() {
|
|
22
23
|
const [editor] = useLexicalComposerContext();
|
|
23
24
|
useEffect(() => {
|
|
24
|
-
if (!editor.hasNodes([PoetryBlockNode, LayoutContainerNode, LayoutItemNode])) {
|
|
25
|
-
throw new Error('PoetryPlugin: PoetryBlockNode (and the columns nodes
|
|
25
|
+
if (!editor.hasNodes([PoetryBlockNode, PoetryCoupletNode, LayoutContainerNode, LayoutItemNode])) {
|
|
26
|
+
throw new Error('PoetryPlugin: PoetryBlockNode/PoetryCoupletNode (and the columns nodes two-column composes) not registered on the editor');
|
|
26
27
|
}
|
|
27
28
|
return mergeRegister(editor.registerCommand(INSERT_POETRY_COUPLET_COMMAND, ({ layout, align }) => $insertPoetryCouplet(layout, align), COMMAND_PRIORITY_EDITOR), editor.registerNodeTransform(PoetryBlockNode, (node) => {
|
|
28
29
|
if (node.getChildrenSize() === 0) {
|
package/dist/theme/editor.css
CHANGED
|
@@ -407,42 +407,75 @@
|
|
|
407
407
|
/* Misra lines sit tight against each other within a couplet — the generic
|
|
408
408
|
.likhari-paragraph margin would otherwise add the same gap between a
|
|
409
409
|
couplet's own two lines as between separate couplets within the same
|
|
410
|
-
block, losing the pairing entirely.
|
|
411
|
-
|
|
412
|
-
|
|
410
|
+
block, losing the pairing entirely. A block's children are a free mix of
|
|
411
|
+
.likhari-poetry-couplet (single-column/alternating/centered) and
|
|
412
|
+
.likhari-layout-container (two-column) — one wrapper box per couplet,
|
|
413
|
+
regardless of type — so "extra space after every couplet" is just
|
|
414
|
+
margin-bottom on every non-last couplet of either kind. */
|
|
413
415
|
.likhari-poetry .likhari-paragraph {
|
|
414
416
|
margin: 0;
|
|
415
417
|
}
|
|
416
418
|
|
|
417
|
-
.likhari-poetry
|
|
419
|
+
.likhari-poetry > .likhari-poetry-couplet:not(:last-child),
|
|
420
|
+
.likhari-poetry > .likhari-layout-container:not(:last-child) {
|
|
418
421
|
margin-bottom: 1em;
|
|
419
422
|
}
|
|
420
423
|
|
|
421
|
-
.likhari-poetry
|
|
422
|
-
|
|
423
|
-
/* No grid gap — the divider below sits exactly on the track boundary, so
|
|
424
|
-
spacing instead comes from matching padding on each side of it, which
|
|
425
|
-
keeps the gutter visually even on both sides of the line. */
|
|
426
|
-
gap: 0;
|
|
424
|
+
.likhari-poetry-couplet {
|
|
425
|
+
box-sizing: border-box;
|
|
427
426
|
}
|
|
428
427
|
|
|
429
|
-
/*
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
428
|
+
/* "Two columns with a couplet that is single, aligned centered": a couplet
|
|
429
|
+
can individually override to a narrower, page-centered box regardless of
|
|
430
|
+
the block's own layout — the same capped-width + auto-margin centering
|
|
431
|
+
.likhari-poetry itself uses, scoped to just this one couplet. */
|
|
432
|
+
.likhari-poetry-couplet--centered {
|
|
433
|
+
width: fit-content;
|
|
434
|
+
max-width: 70%;
|
|
435
|
+
margin-inline: auto;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/* "Aligned alternative": every couplet is the same fixed width, but
|
|
439
|
+
consecutive couplets alternate which edge they're pinned to — since both
|
|
440
|
+
widths overlap past the midpoint, the couplets visually stagger with
|
|
441
|
+
some overlap toward the center, rather than all stacking flush to one
|
|
442
|
+
side or centered identically. */
|
|
443
|
+
.likhari-poetry--alternating .likhari-poetry-couplet {
|
|
444
|
+
width: 65%;
|
|
445
|
+
max-width: none;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.likhari-poetry--alternating .likhari-poetry-couplet:nth-of-type(odd) {
|
|
449
|
+
margin-inline-end: auto;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.likhari-poetry--alternating .likhari-poetry-couplet:nth-of-type(even) {
|
|
453
|
+
margin-inline-start: auto;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/* Only inside a poetry block's own two-column couplets: no block margin
|
|
457
|
+
(the generic .likhari-layout-container rule's margin is for a
|
|
458
|
+
stand-alone Columns insert, not one couplet of several in a poetry
|
|
459
|
+
block — spacing between couplets is the margin-bottom rule above
|
|
460
|
+
instead) and no grid gap — the divider below sits exactly on the track
|
|
461
|
+
boundary, so spacing instead comes from matching padding on each side
|
|
462
|
+
of it, which keeps the gutter visually even on both sides of the line. */
|
|
463
|
+
.likhari-poetry > .likhari-layout-container {
|
|
464
|
+
margin: 0;
|
|
465
|
+
gap: 0;
|
|
433
466
|
}
|
|
434
467
|
|
|
435
|
-
.likhari-poetry
|
|
468
|
+
.likhari-poetry .likhari-layout-item {
|
|
436
469
|
text-align: inherit;
|
|
437
470
|
}
|
|
438
471
|
|
|
439
|
-
.likhari-poetry
|
|
472
|
+
.likhari-poetry .likhari-layout-item:first-child {
|
|
440
473
|
padding-inline-end: 20px;
|
|
441
474
|
}
|
|
442
475
|
|
|
443
476
|
/* A visible divider between misra columns, same dashed language as the
|
|
444
477
|
couplet's own border — matches a table's internal cell borders. */
|
|
445
|
-
.likhari-poetry
|
|
478
|
+
.likhari-poetry .likhari-layout-item:not(:first-child) {
|
|
446
479
|
border-inline-start: 1px dashed var(--editor-line-strong);
|
|
447
480
|
padding-inline-start: 20px;
|
|
448
481
|
}
|
|
@@ -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,
|
|
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,kBAiDzB,CAAC"}
|
|
@@ -46,6 +46,7 @@ export const editorTheme = {
|
|
|
46
46
|
footnoteList: 'likhari-footnote-list',
|
|
47
47
|
footnoteItem: 'likhari-footnote-item',
|
|
48
48
|
poetry: 'likhari-poetry',
|
|
49
|
+
poetryCouplet: 'likhari-poetry-couplet',
|
|
49
50
|
table: 'likhari-table',
|
|
50
51
|
tableRow: 'likhari-table-row',
|
|
51
52
|
tableCell: 'likhari-table-cell',
|