@inshapardaz/likhari-react 0.1.18 → 0.1.19-dev.182
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/EditorRoot.d.ts.map +1 -1
- package/dist/EditorRoot.js +6 -2
- package/dist/blocks/PoetryNode.d.ts +70 -0
- package/dist/blocks/PoetryNode.d.ts.map +1 -0
- package/dist/blocks/PoetryNode.js +198 -0
- package/dist/blocks/PoetryResizer.d.ts +11 -0
- package/dist/blocks/PoetryResizer.d.ts.map +1 -0
- package/dist/blocks/PoetryResizer.js +94 -0
- package/dist/blocks/poetryActions.d.ts +117 -0
- package/dist/blocks/poetryActions.d.ts.map +1 -0
- package/dist/blocks/poetryActions.js +481 -0
- package/dist/components/FindReplaceBar.d.ts +13 -0
- package/dist/components/FindReplaceBar.d.ts.map +1 -0
- package/dist/components/FindReplaceBar.js +72 -0
- package/dist/components/Toolbar.d.ts +4 -1
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +81 -9
- package/dist/find/findReplaceActions.d.ts +23 -0
- package/dist/find/findReplaceActions.d.ts.map +1 -0
- package/dist/find/findReplaceActions.js +81 -0
- package/dist/i18n/strings.d.ts +34 -1
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +99 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +2 -0
- package/dist/plugins/PoetryPlugin.d.ts +19 -0
- package/dist/plugins/PoetryPlugin.d.ts.map +1 -0
- package/dist/plugins/PoetryPlugin.js +54 -0
- package/dist/spellcheck/dictionaries/en/LICENSE.txt +347 -0
- package/dist/spellcheck/dictionaries/en/index.aff +205 -0
- package/dist/spellcheck/dictionaries/en/index.dic +49569 -0
- package/dist/spellcheck/spellDictionaries.d.ts +40 -0
- package/dist/spellcheck/spellDictionaries.d.ts.map +1 -0
- package/dist/spellcheck/spellDictionaries.js +62 -0
- package/dist/theme/editor.css +278 -0
- package/dist/theme/editorTheme.d.ts.map +1 -1
- package/dist/theme/editorTheme.js +1 -0
- package/package.json +8 -6
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Languages the spellchecker has a dictionary slot for. */
|
|
2
|
+
export type SpellLanguage = 'en' | 'ur' | 'pa-shahmukhi';
|
|
3
|
+
/** A Hunspell dictionary as the two text files every Hunspell dictionary ships with. */
|
|
4
|
+
export interface HunspellFiles {
|
|
5
|
+
/** Affix file: language, encoding, character rules. */
|
|
6
|
+
aff: string;
|
|
7
|
+
/** Dictionary file: one word per line, with optional affix flags. */
|
|
8
|
+
dic: string;
|
|
9
|
+
}
|
|
10
|
+
export interface Speller {
|
|
11
|
+
correct(word: string): boolean;
|
|
12
|
+
suggest(word: string): string[];
|
|
13
|
+
}
|
|
14
|
+
type Loader = () => Promise<HunspellFiles>;
|
|
15
|
+
/**
|
|
16
|
+
* Registers a dictionary for a language. Call once at startup with files you
|
|
17
|
+
* have licence to ship — e.g. the Urdu `.aff`/`.dic` pair — either as strings
|
|
18
|
+
* or as a loader that fetches them on demand. Registering again replaces the
|
|
19
|
+
* previous dictionary for that language.
|
|
20
|
+
*/
|
|
21
|
+
export declare function registerSpellDictionary(language: SpellLanguage, files: HunspellFiles | Loader): void;
|
|
22
|
+
/** Whether a dictionary is registered for the language. */
|
|
23
|
+
export declare function hasSpellDictionary(language: SpellLanguage): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* The speller for a language, loading its dictionary the first time it is
|
|
26
|
+
* asked for. Resolves to null when no dictionary is registered, so callers
|
|
27
|
+
* can skip spellchecking that language rather than flag every word.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getSpeller(language: SpellLanguage): Promise<Speller> | null;
|
|
30
|
+
/** A word in a text, with its position as character offsets. */
|
|
31
|
+
export interface WordSpan {
|
|
32
|
+
word: string;
|
|
33
|
+
start: number;
|
|
34
|
+
end: number;
|
|
35
|
+
}
|
|
36
|
+
export declare function wordsIn(text: string): WordSpan[];
|
|
37
|
+
/** The words in `text` the speller does not recognise. */
|
|
38
|
+
export declare function misspellingsIn(text: string, speller: Speller): WordSpan[];
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=spellDictionaries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spellDictionaries.d.ts","sourceRoot":"","sources":["../../src/spellcheck/spellDictionaries.ts"],"names":[],"mappings":"AAEA,4DAA4D;AAC5D,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC;AAEzD,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACjC;AAED,KAAK,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;AAmB3C;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAGpG;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAS3E;AAED,gEAAgE;AAChE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AASD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAMhD;AAED,0DAA0D;AAC1D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,EAAE,CAEzE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import nspell from 'nspell';
|
|
2
|
+
const loaders = new Map();
|
|
3
|
+
const spellers = new Map();
|
|
4
|
+
async function fetchText(url) {
|
|
5
|
+
const response = await fetch(url);
|
|
6
|
+
if (!response.ok)
|
|
7
|
+
throw new Error(`Spellcheck dictionary failed to load: ${url}`);
|
|
8
|
+
return response.text();
|
|
9
|
+
}
|
|
10
|
+
/** English ships with the editor: its files are fetched on first use. */
|
|
11
|
+
const englishLoader = async () => ({
|
|
12
|
+
aff: await fetchText(new URL('./dictionaries/en/index.aff', import.meta.url).href),
|
|
13
|
+
dic: await fetchText(new URL('./dictionaries/en/index.dic', import.meta.url).href),
|
|
14
|
+
});
|
|
15
|
+
loaders.set('en', englishLoader);
|
|
16
|
+
/**
|
|
17
|
+
* Registers a dictionary for a language. Call once at startup with files you
|
|
18
|
+
* have licence to ship — e.g. the Urdu `.aff`/`.dic` pair — either as strings
|
|
19
|
+
* or as a loader that fetches them on demand. Registering again replaces the
|
|
20
|
+
* previous dictionary for that language.
|
|
21
|
+
*/
|
|
22
|
+
export function registerSpellDictionary(language, files) {
|
|
23
|
+
loaders.set(language, typeof files === 'function' ? files : async () => files);
|
|
24
|
+
spellers.delete(language);
|
|
25
|
+
}
|
|
26
|
+
/** Whether a dictionary is registered for the language. */
|
|
27
|
+
export function hasSpellDictionary(language) {
|
|
28
|
+
return loaders.has(language);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The speller for a language, loading its dictionary the first time it is
|
|
32
|
+
* asked for. Resolves to null when no dictionary is registered, so callers
|
|
33
|
+
* can skip spellchecking that language rather than flag every word.
|
|
34
|
+
*/
|
|
35
|
+
export function getSpeller(language) {
|
|
36
|
+
const loader = loaders.get(language);
|
|
37
|
+
if (!loader)
|
|
38
|
+
return null;
|
|
39
|
+
let speller = spellers.get(language);
|
|
40
|
+
if (!speller) {
|
|
41
|
+
speller = loader().then(({ aff, dic }) => nspell(aff, dic));
|
|
42
|
+
spellers.set(language, speller);
|
|
43
|
+
}
|
|
44
|
+
return speller;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Letters and combining marks, with apostrophes inside a word kept. The
|
|
48
|
+
* Unicode classes cover Arabic-script letters and their diacritics, so Urdu
|
|
49
|
+
* and Shahmukhi words are found the same way English ones are.
|
|
50
|
+
*/
|
|
51
|
+
const WORD = /[\p{L}\p{M}]+(?:['’][\p{L}\p{M}]+)*/gu;
|
|
52
|
+
export function wordsIn(text) {
|
|
53
|
+
return [...text.matchAll(WORD)].map((match) => ({
|
|
54
|
+
word: match[0],
|
|
55
|
+
start: match.index ?? 0,
|
|
56
|
+
end: (match.index ?? 0) + match[0].length,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
/** The words in `text` the speller does not recognise. */
|
|
60
|
+
export function misspellingsIn(text, speller) {
|
|
61
|
+
return wordsIn(text).filter((span) => !speller.correct(span.word));
|
|
62
|
+
}
|
package/dist/theme/editor.css
CHANGED
|
@@ -160,6 +160,14 @@
|
|
|
160
160
|
/* Canvas — editor-ui-design-spec.md §4. flex: 1 1 auto + min-height: 0 lets
|
|
161
161
|
this pane absorb the root's height and scroll internally instead of the
|
|
162
162
|
editor (and the page around it) growing to fit the content. */
|
|
163
|
+
.likhari-canvas-frame {
|
|
164
|
+
position: relative;
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-direction: column;
|
|
167
|
+
flex: 1 1 auto;
|
|
168
|
+
min-height: 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
163
171
|
.likhari-canvas {
|
|
164
172
|
position: relative;
|
|
165
173
|
flex: 1 1 auto;
|
|
@@ -374,6 +382,169 @@
|
|
|
374
382
|
content: '[' counter(likhari-footnote-item) '] ';
|
|
375
383
|
}
|
|
376
384
|
|
|
385
|
+
/* Poetry couplets (lexical-editor-spec.md §4.11, editor-ui-design-spec.md §4).
|
|
386
|
+
Own type scale and spacing, distinct from body text — the .likhari-ltr/
|
|
387
|
+
.likhari-rtl per-block classes (above) already switch font-family for this
|
|
388
|
+
element same as any other block; these rules layer poetry's own size/
|
|
389
|
+
line-height/gap on top, combined with those same classes.
|
|
390
|
+
Capped width + auto margins read verse as a centered block on the page —
|
|
391
|
+
conventional poetry typesetting — rather than a full-width paragraph where
|
|
392
|
+
a short line just hugs the start edge regardless of its own text-align. */
|
|
393
|
+
.likhari-poetry {
|
|
394
|
+
box-sizing: border-box;
|
|
395
|
+
margin: 0 auto 1.4em auto;
|
|
396
|
+
max-width: 70%;
|
|
397
|
+
/* A visible boundary while editing, same affordance as a table's own
|
|
398
|
+
border — poetry couplets are a distinct structural block, not a plain
|
|
399
|
+
paragraph, and should read as one at a glance. */
|
|
400
|
+
border: 1px dashed var(--editor-line-strong);
|
|
401
|
+
border-radius: 6px;
|
|
402
|
+
padding: 10px 16px;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.likhari-poetry.likhari-ltr {
|
|
406
|
+
font-size: 15px;
|
|
407
|
+
line-height: 1.6;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.likhari-poetry.likhari-rtl {
|
|
411
|
+
font-size: 20px;
|
|
412
|
+
line-height: 2.1;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* Misra lines sit tight against each other within a couplet — the generic
|
|
416
|
+
.likhari-paragraph margin would otherwise add the same gap between a
|
|
417
|
+
couplet's own two lines as between separate couplets within the same
|
|
418
|
+
block, losing the pairing entirely. */
|
|
419
|
+
.likhari-poetry .likhari-paragraph {
|
|
420
|
+
margin: 0;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/* A poetry block is "one object with multiple couplets, add/remove like
|
|
424
|
+
table rows" — so couplet boundaries get the same visible divider as a
|
|
425
|
+
table's internal row borders, not just extra space. Every couplet but
|
|
426
|
+
the first (nth-child(odd), since each couplet is two paragraph
|
|
427
|
+
children — its first misra always lands on an odd position) gets a
|
|
428
|
+
border-top in place of the previous couplet's margin-bottom. */
|
|
429
|
+
.likhari-poetry--single .likhari-paragraph:nth-child(odd):not(:first-child) {
|
|
430
|
+
border-top: 1px dashed var(--editor-line-strong);
|
|
431
|
+
margin-top: var(--poetry-couplet-gap);
|
|
432
|
+
padding-top: calc(var(--poetry-couplet-gap) * 0.6);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.likhari-poetry--spacing-compact { --poetry-couplet-gap: 0.4em; }
|
|
436
|
+
.likhari-poetry--spacing-normal { --poetry-couplet-gap: 1em; }
|
|
437
|
+
.likhari-poetry--spacing-relaxed { --poetry-couplet-gap: 1.8em; }
|
|
438
|
+
.likhari-poetry--spacing-loose { --poetry-couplet-gap: 2.8em; }
|
|
439
|
+
|
|
440
|
+
.likhari-poetry--gutter-compact { --poetry-gutter: 8px; }
|
|
441
|
+
.likhari-poetry--gutter-normal { --poetry-gutter: 20px; }
|
|
442
|
+
.likhari-poetry--gutter-relaxed { --poetry-gutter: 32px; }
|
|
443
|
+
.likhari-poetry--gutter-loose { --poetry-gutter: 48px; }
|
|
444
|
+
|
|
445
|
+
.likhari-poetry--stagger-compact { --poetry-stagger-width: 50%; }
|
|
446
|
+
.likhari-poetry--stagger-normal { --poetry-stagger-width: 65%; }
|
|
447
|
+
.likhari-poetry--stagger-relaxed { --poetry-stagger-width: 75%; }
|
|
448
|
+
.likhari-poetry--stagger-loose { --poetry-stagger-width: 85%; }
|
|
449
|
+
|
|
450
|
+
/* Staggered: couplets are the same flat misra paragraphs as single column,
|
|
451
|
+
but each couplet's two misras are placed in a 65%-wide box that alternates
|
|
452
|
+
sides — the first couplet pushed to the start edge, the next to the end
|
|
453
|
+
edge, and so on. Logical properties keep the alternation mirrored for RTL. */
|
|
454
|
+
.likhari-poetry--staggered .likhari-paragraph {
|
|
455
|
+
width: var(--poetry-stagger-width, 65%);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.likhari-poetry--staggered .likhari-paragraph:nth-child(4n+1),
|
|
459
|
+
.likhari-poetry--staggered .likhari-paragraph:nth-child(4n+2) {
|
|
460
|
+
margin-inline-end: auto;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.likhari-poetry--staggered .likhari-paragraph:nth-child(4n+3),
|
|
464
|
+
.likhari-poetry--staggered .likhari-paragraph:nth-child(4n+4) {
|
|
465
|
+
margin-inline-start: auto;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.likhari-poetry--staggered .likhari-paragraph:nth-child(odd):not(:first-child) {
|
|
469
|
+
border-top: 1px dashed var(--editor-line-strong);
|
|
470
|
+
margin-top: var(--poetry-couplet-gap);
|
|
471
|
+
padding-top: calc(var(--poetry-couplet-gap) * 0.6);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.likhari-poetry--two-column .likhari-layout-container {
|
|
475
|
+
margin: 0;
|
|
476
|
+
/* No grid gap — the column divider sits exactly on the track boundary,
|
|
477
|
+
so spacing instead comes from matching padding on each side of it,
|
|
478
|
+
which keeps the gutter visually even on both sides of the line. */
|
|
479
|
+
gap: 0;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/* One row per couplet in two-column layout — same table-row-border
|
|
483
|
+
treatment as the single-column rule above, between couplets instead of
|
|
484
|
+
within one. */
|
|
485
|
+
.likhari-poetry--two-column .likhari-layout-container:not(:first-child) {
|
|
486
|
+
border-top: 1px dashed var(--editor-line-strong);
|
|
487
|
+
margin-top: var(--poetry-couplet-gap);
|
|
488
|
+
padding-top: calc(var(--poetry-couplet-gap) * 0.6);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.likhari-poetry--two-column .likhari-layout-item {
|
|
492
|
+
text-align: inherit;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/* A centered couplet: a two-column row holding one item (see poetryActions.ts's
|
|
496
|
+
$setCoupletCentered) — narrowed to the middle of the block, with no column
|
|
497
|
+
divider or gutter since there's only one column. */
|
|
498
|
+
.likhari-poetry--two-column > .likhari-layout-container:has(> .likhari-layout-item:only-child) {
|
|
499
|
+
width: 60%;
|
|
500
|
+
margin-inline: auto;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.likhari-poetry--two-column .likhari-layout-item:only-child {
|
|
504
|
+
padding-inline-end: 0;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.likhari-poetry--two-column .likhari-layout-item:first-child {
|
|
508
|
+
padding-inline-end: var(--poetry-gutter, 20px);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/* A visible divider between misra columns, same dashed language as the
|
|
512
|
+
couplet's own border — matches a table's internal cell borders. */
|
|
513
|
+
.likhari-poetry--two-column .likhari-layout-item:not(:first-child) {
|
|
514
|
+
border-inline-start: 1px dashed var(--editor-line-strong);
|
|
515
|
+
padding-inline-start: var(--poetry-gutter, 20px);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/* PoetryResizer.tsx's drag handle — portaled to a fixed position over the
|
|
519
|
+
active couplet's inline-end edge, so top/left are set inline per drag. */
|
|
520
|
+
.likhari-poetry-resize-handle {
|
|
521
|
+
position: fixed;
|
|
522
|
+
width: 10px;
|
|
523
|
+
/* Physical, not logical: PoetryResizer.tsx already computes `left` as the
|
|
524
|
+
couplet's actual edge in viewport coordinates for either direction, so
|
|
525
|
+
centering the handle on it must stay physical too. */
|
|
526
|
+
margin-left: -5px;
|
|
527
|
+
cursor: ew-resize;
|
|
528
|
+
touch-action: none;
|
|
529
|
+
z-index: 20;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
.likhari-poetry-resize-handle::before {
|
|
533
|
+
content: '';
|
|
534
|
+
display: block;
|
|
535
|
+
width: 3px;
|
|
536
|
+
height: 100%;
|
|
537
|
+
margin-inline: auto;
|
|
538
|
+
border-radius: 2px;
|
|
539
|
+
background: var(--editor-accent);
|
|
540
|
+
opacity: 0;
|
|
541
|
+
transition: opacity 0.1s ease;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.likhari-poetry-resize-handle:hover::before {
|
|
545
|
+
opacity: 0.6;
|
|
546
|
+
}
|
|
547
|
+
|
|
377
548
|
.likhari-table {
|
|
378
549
|
border-collapse: collapse;
|
|
379
550
|
margin: 1em 0;
|
|
@@ -592,3 +763,110 @@
|
|
|
592
763
|
outline: 2px solid var(--editor-accent);
|
|
593
764
|
outline-offset: 1px;
|
|
594
765
|
}
|
|
766
|
+
|
|
767
|
+
/* Floats over the top-right of the canvas, so it takes no space from the
|
|
768
|
+
toolbar or the page. */
|
|
769
|
+
.likhari-find-widget {
|
|
770
|
+
position: absolute;
|
|
771
|
+
z-index: 5;
|
|
772
|
+
top: 8px;
|
|
773
|
+
right: 16px;
|
|
774
|
+
display: flex;
|
|
775
|
+
flex-direction: column;
|
|
776
|
+
gap: 6px;
|
|
777
|
+
width: fit-content;
|
|
778
|
+
padding: 6px;
|
|
779
|
+
border: 1px solid var(--editor-line);
|
|
780
|
+
border-radius: 6px;
|
|
781
|
+
background: var(--editor-paper-dim);
|
|
782
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
|
783
|
+
font-size: 13px;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/* Both rows share one grid. Columns: chevron, input, then two narrow tracks
|
|
787
|
+
that hold either the match count (search row) or the two replace buttons
|
|
788
|
+
(replace row), then prev, next and close. */
|
|
789
|
+
.likhari-find-row {
|
|
790
|
+
display: grid;
|
|
791
|
+
grid-template-columns: 24px 180px 24px 24px 24px 24px 24px;
|
|
792
|
+
align-items: center;
|
|
793
|
+
column-gap: 4px;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
.likhari-find-replace-input {
|
|
797
|
+
grid-column: 2;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.likhari-find-status {
|
|
801
|
+
grid-column: 3 / span 2;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.likhari-find-prev {
|
|
805
|
+
grid-column: 5;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
.likhari-find-next {
|
|
809
|
+
grid-column: 6;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
.likhari-find-close {
|
|
813
|
+
grid-column: 7;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
.likhari-find-replace-one {
|
|
817
|
+
grid-column: 3;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
.likhari-find-replace-all {
|
|
821
|
+
grid-column: 4;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
.likhari-find-widget[dir='rtl'] {
|
|
825
|
+
right: auto;
|
|
826
|
+
left: 16px;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
.likhari-find-widget input {
|
|
830
|
+
width: 100%;
|
|
831
|
+
min-width: 0;
|
|
832
|
+
padding: 3px 6px;
|
|
833
|
+
border: 1px solid var(--editor-line);
|
|
834
|
+
border-radius: 4px;
|
|
835
|
+
background: var(--editor-paper);
|
|
836
|
+
color: inherit;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.likhari-find-widget button {
|
|
840
|
+
padding: 2px 8px;
|
|
841
|
+
border: 1px solid var(--editor-line);
|
|
842
|
+
border-radius: 4px;
|
|
843
|
+
background: transparent;
|
|
844
|
+
color: inherit;
|
|
845
|
+
cursor: pointer;
|
|
846
|
+
white-space: nowrap;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
.likhari-find-widget button:disabled {
|
|
850
|
+
opacity: 0.5;
|
|
851
|
+
cursor: default;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.likhari-find-widget .likhari-find-icon {
|
|
855
|
+
display: inline-flex;
|
|
856
|
+
align-items: center;
|
|
857
|
+
justify-content: center;
|
|
858
|
+
width: 24px;
|
|
859
|
+
height: 24px;
|
|
860
|
+
padding: 0;
|
|
861
|
+
border: none;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.likhari-find-icon-spacer {
|
|
865
|
+
display: block;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
.likhari-find-status {
|
|
869
|
+
text-align: end;
|
|
870
|
+
opacity: 0.8;
|
|
871
|
+
white-space: nowrap;
|
|
872
|
+
}
|
|
@@ -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,kBAgDzB,CAAC"}
|
|
@@ -45,6 +45,7 @@ export const editorTheme = {
|
|
|
45
45
|
footnoteReference: 'likhari-footnote-ref',
|
|
46
46
|
footnoteList: 'likhari-footnote-list',
|
|
47
47
|
footnoteItem: 'likhari-footnote-item',
|
|
48
|
+
poetry: 'likhari-poetry',
|
|
48
49
|
table: 'likhari-table',
|
|
49
50
|
tableRow: 'likhari-table-row',
|
|
50
51
|
tableCell: 'likhari-table-cell',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inshapardaz/likhari-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19-dev.182",
|
|
4
4
|
"description": "React implementation of the Likhari editor, built on @lexical/react.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,10 +29,12 @@
|
|
|
29
29
|
"*.css"
|
|
30
30
|
],
|
|
31
31
|
"scripts": {
|
|
32
|
-
"build": "tsc -p tsconfig.build.json && node ../../scripts/fix-esm-extensions.mjs ./dist && node ../../scripts/copy-assets.mjs src dist \"**/*.css\"",
|
|
32
|
+
"build": "tsc -p tsconfig.build.json && node ../../scripts/fix-esm-extensions.mjs ./dist && node ../../scripts/copy-assets.mjs src dist \"**/*.css\" && node ../../scripts/copy-assets.mjs src dist \"**/*.aff\" && node ../../scripts/copy-assets.mjs src dist \"**/*.dic\" && node ../../scripts/copy-assets.mjs src dist \"**/*.txt\"",
|
|
33
33
|
"prepublishOnly": "npm run build"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"@inshapardaz/likhari-converters": "^0.1.0",
|
|
37
|
+
"@inshapardaz/likhari-core": "^0.1.0",
|
|
36
38
|
"@lexical/link": "^0.20.0",
|
|
37
39
|
"@lexical/list": "^0.20.0",
|
|
38
40
|
"@lexical/react": "^0.20.0",
|
|
@@ -40,10 +42,9 @@
|
|
|
40
42
|
"@lexical/selection": "^0.20.0",
|
|
41
43
|
"@lexical/table": "^0.20.0",
|
|
42
44
|
"@lexical/utils": "^0.20.0",
|
|
43
|
-
"@inshapardaz/likhari-converters": "^0.1.0",
|
|
44
|
-
"@inshapardaz/likhari-core": "^0.1.0",
|
|
45
45
|
"@tabler/icons-react": "^3.46.0",
|
|
46
|
-
"lexical": "^0.20.0"
|
|
46
|
+
"lexical": "^0.20.0",
|
|
47
|
+
"nspell": "^2.1.5"
|
|
47
48
|
},
|
|
48
49
|
"peerDependencies": {
|
|
49
50
|
"@mantine/core": "^9.6.3",
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@mantine/core": "^9.6.3",
|
|
56
|
-
"@mantine/hooks": "^9.6.3"
|
|
57
|
+
"@mantine/hooks": "^9.6.3",
|
|
58
|
+
"@types/nspell": "^2.1.6"
|
|
57
59
|
}
|
|
58
60
|
}
|