mnfst 0.5.220 → 0.5.222
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/lib/manifest.appwrite.data.js +1 -1
- package/lib/manifest.css +62 -79
- package/lib/manifest.data.js +1 -1
- package/lib/manifest.edit.css +22 -67
- package/lib/manifest.edit.js +50 -12
- package/lib/manifest.integrity.json +5 -5
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.sw.js +1 -1
- package/lib/manifest.text.edit.css +40 -12
- package/lib/manifest.text.edit.js +36 -2
- package/package.json +1 -1
|
@@ -9,13 +9,9 @@
|
|
|
9
9
|
@layer components {
|
|
10
10
|
|
|
11
11
|
:where([data-text-edit]) {
|
|
12
|
-
|
|
13
|
-
max-height: var(--text-edit-max-height, none);
|
|
12
|
+
position: relative;
|
|
14
13
|
overflow-y: auto;
|
|
15
|
-
|
|
16
|
-
background: var(--text-edit-background, var(--color-surface-1));
|
|
17
|
-
border: 1px solid var(--color-line);
|
|
18
|
-
border-radius: var(--radius);
|
|
14
|
+
max-height: var(--text-edit-max-height, none);
|
|
19
15
|
outline: none;
|
|
20
16
|
|
|
21
17
|
/* Page-level styling — set by .page controls, read back by $text.page.
|
|
@@ -26,19 +22,45 @@
|
|
|
26
22
|
text-align: var(--text-edit-align, start);
|
|
27
23
|
color: var(--text-edit-color, inherit);
|
|
28
24
|
|
|
29
|
-
&:focus {
|
|
30
|
-
border-color: var(--color-content-subtle);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
25
|
/* Flagged from script: :empty never matches the <br> a contenteditable
|
|
34
|
-
keeps, and the tag holding it is not predictable after a wipe.
|
|
26
|
+
keeps, and the tag holding it is not predictable after a wipe. The
|
|
27
|
+
placeholder OVERLAYS the first line (it is not a line of its own), so
|
|
28
|
+
the caret sits on top of it and nothing jumps when typing starts. */
|
|
35
29
|
&[data-text-edit-empty]::before {
|
|
36
30
|
content: attr(placeholder);
|
|
31
|
+
position: absolute;
|
|
32
|
+
inset-block-start: var(--text-edit-padding, 0.75rem);
|
|
33
|
+
inset-inline: var(--text-edit-padding, 0.75rem);
|
|
37
34
|
color: var(--color-content-subtle);
|
|
38
35
|
pointer-events: none;
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
38
|
|
|
39
|
+
/* An unstyled area has no field padding, so its placeholder hugs the line. */
|
|
40
|
+
:where([data-text-edit].unstyle)[data-text-edit-empty]::before {
|
|
41
|
+
inset-block-start: 0;
|
|
42
|
+
inset-inline: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* The FIELD look. `.unstyle` drops it so an area can sit seamlessly in a
|
|
46
|
+
page — a WYSIWYG document inherits its element's own type and colours;
|
|
47
|
+
everything above (caret custody, placeholder, commands) still works. */
|
|
48
|
+
:where([data-text-edit]:not(.unstyle)) {
|
|
49
|
+
min-height: var(--text-edit-min-height, 8rem);
|
|
50
|
+
padding: var(--text-edit-padding, 0.75rem);
|
|
51
|
+
background: var(--text-edit-background, var(--color-surface-1));
|
|
52
|
+
border: 1px solid var(--color-line);
|
|
53
|
+
border-radius: var(--radius);
|
|
54
|
+
|
|
55
|
+
/* Held while the area owns the editing session — a <select> or colour
|
|
56
|
+
control takes NATIVE focus by design, and the ring must not flicker
|
|
57
|
+
off while the writer is mid-command. */
|
|
58
|
+
&:focus,
|
|
59
|
+
&[data-text-edit-focused] {
|
|
60
|
+
border-color: var(--color-content-subtle);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
42
64
|
/* ---- Selection menu (x-text-edit-menu) ----
|
|
43
65
|
Positioned by the --text-edit-selection-* variables the plugin writes to
|
|
44
66
|
:root, so the default needs no script; restyle or reposition freely. */
|
|
@@ -49,7 +71,6 @@
|
|
|
49
71
|
left: var(--text-edit-selection-center);
|
|
50
72
|
top: var(--text-edit-selection-y);
|
|
51
73
|
transform: translate(-50%, calc(-100% - 0.5rem));
|
|
52
|
-
display: flex;
|
|
53
74
|
gap: 0.25rem;
|
|
54
75
|
align-items: center;
|
|
55
76
|
padding: 0.25rem;
|
|
@@ -59,6 +80,13 @@
|
|
|
59
80
|
box-shadow: 0 8px 30px rgb(0 0 0 / 0.2);
|
|
60
81
|
}
|
|
61
82
|
|
|
83
|
+
/* display only while OPEN: an author display on the base rule would beat
|
|
84
|
+
the UA's closed-popover display:none, leaving the menu floating fixed
|
|
85
|
+
over the page before any selection exists. */
|
|
86
|
+
:where([data-text-edit-menu]:popover-open) {
|
|
87
|
+
display: flex;
|
|
88
|
+
}
|
|
89
|
+
|
|
62
90
|
/* Without the Popover API the attribute is inert and the menu would render
|
|
63
91
|
permanently fixed on the page — hide it there; the bubble is progressive
|
|
64
92
|
enhancement. (In supporting browsers a closed popover is hidden natively.) */
|
|
@@ -389,15 +389,34 @@
|
|
|
389
389
|
Swapping the element outright covers every block tag, where formatBlock only
|
|
390
390
|
accepts a short list and disagrees between engines. */
|
|
391
391
|
function setBlock(tag) {
|
|
392
|
-
|
|
392
|
+
let b = blockEl(); if (!b) return;
|
|
393
393
|
const want = (b.tagName === tag.toUpperCase() ? 'p' : tag).toLowerCase();
|
|
394
394
|
if (b.tagName === want.toUpperCase()) return;
|
|
395
|
+
// A heading or quote cannot live inside a list — markdown has no
|
|
396
|
+
// <ul><h2> — so lift the item out of its list first, then retag.
|
|
397
|
+
// Retagging in place serialized to nothing: the content vanished.
|
|
398
|
+
// A NESTED item outdents to the top level first, or the lift would
|
|
399
|
+
// land the new block inside the outer <li>.
|
|
400
|
+
if (b.tagName === 'LI' && want !== 'li') {
|
|
401
|
+
const area = b.closest('[data-text-edit]');
|
|
402
|
+
for (let guard = 0; guard < 8; guard++) {
|
|
403
|
+
const list = b && b.tagName === 'LI' && b.closest('ul, ol');
|
|
404
|
+
if (!list || !list.parentElement || !list.parentElement.closest('li')) break;
|
|
405
|
+
indent(-1, area);
|
|
406
|
+
b = blockEl(); if (!b) return;
|
|
407
|
+
}
|
|
408
|
+
if (b.tagName === 'LI') { unwrapItem(b); b = blockEl(); if (!b) return; }
|
|
409
|
+
if (b.tagName === want.toUpperCase()) return;
|
|
410
|
+
}
|
|
395
411
|
const n = document.createElement(want);
|
|
396
412
|
n.setAttribute('style', b.getAttribute('style') || '');
|
|
397
413
|
if (!n.getAttribute('style')) n.removeAttribute('style');
|
|
398
414
|
const off = offsetIn(b);
|
|
399
415
|
while (b.firstChild) n.appendChild(b.firstChild);
|
|
400
416
|
b.replaceWith(n);
|
|
417
|
+
// A sublist that rode along out of a list item cannot live inside a
|
|
418
|
+
// heading or quote — it steps out right after the new block.
|
|
419
|
+
[...n.querySelectorAll(':scope > ul, :scope > ol')].reverse().forEach(l => n.after(l));
|
|
401
420
|
caretIn(n, off);
|
|
402
421
|
}
|
|
403
422
|
|
|
@@ -1641,6 +1660,7 @@
|
|
|
1641
1660
|
const was = area || lastFocused;
|
|
1642
1661
|
if (!area || area === lastFocused) lastFocused = null;
|
|
1643
1662
|
if (!was) return;
|
|
1663
|
+
was.removeAttribute('data-text-edit-focused');
|
|
1644
1664
|
was._selection = null;
|
|
1645
1665
|
was.removeAttribute('data-text-edit-selected');
|
|
1646
1666
|
document.documentElement.removeAttribute('data-text-edit-selected');
|
|
@@ -1697,6 +1717,13 @@
|
|
|
1697
1717
|
const spec = COMMANDS[id], cfg = area && area._te;
|
|
1698
1718
|
if (!spec || !cfg || cfg.mode === 'plain') return false;
|
|
1699
1719
|
const page = !!(ctrl && ctrl.page && spec.page);
|
|
1720
|
+
// The writer's caret is visibly in ANOTHER editable element (a plain
|
|
1721
|
+
// x-edit leaf, an input, someone else's contenteditable): acting now
|
|
1722
|
+
// would restore this area's old saved range and edit text the writer
|
|
1723
|
+
// can see is not selected. The control goes quiet instead. Page
|
|
1724
|
+
// commands write variables, never the selection — they stay live.
|
|
1725
|
+
const live = range();
|
|
1726
|
+
if (!page && live && !area.contains(live.startContainer) && editableElsewhere(live.startContainer)) return false;
|
|
1700
1727
|
if (cfg.minimal && spec.block && !page) return false;
|
|
1701
1728
|
if (cfg.mode !== 'html' && !spec.md && !page) return false;
|
|
1702
1729
|
if (page) return true; // writes to the area, needs no caret
|
|
@@ -1710,6 +1737,13 @@
|
|
|
1710
1737
|
const spec = COMMANDS[id]; if (!spec) return;
|
|
1711
1738
|
const page = !!(ctrl && ctrl.page && spec.page);
|
|
1712
1739
|
if (!page) {
|
|
1740
|
+
// Checked BEFORE restoring the saved range: if the writer's caret is
|
|
1741
|
+
// visibly in another editable element, restoring first would move the
|
|
1742
|
+
// selection back here and the command would edit text the writer can
|
|
1743
|
+
// see is not selected. (The reset blocks pointer clicks on disabled
|
|
1744
|
+
// controls; this covers keyboard activation.)
|
|
1745
|
+
const live = range();
|
|
1746
|
+
if (live && !area.contains(live.startContainer) && editableElsewhere(live.startContainer)) return;
|
|
1713
1747
|
restoreRange(area);
|
|
1714
1748
|
// If the caret could not be put in this area — it was never focused, or
|
|
1715
1749
|
// the saved range has gone stale — do nothing. Running anyway rewrites
|
|
@@ -2064,7 +2098,7 @@
|
|
|
2064
2098
|
if (a && el.contains(a)) e.preventDefault();
|
|
2065
2099
|
});
|
|
2066
2100
|
|
|
2067
|
-
el.addEventListener('focusin', () => { lastFocused = el; sync(); });
|
|
2101
|
+
el.addEventListener('focusin', () => { if (lastFocused && lastFocused !== el) release(lastFocused); lastFocused = el; el.setAttribute('data-text-edit-focused', ''); sync(); });
|
|
2068
2102
|
// Focus gone somewhere that is neither this area nor one of its controls.
|
|
2069
2103
|
el.addEventListener('focusout', (e) => {
|
|
2070
2104
|
if (keeps(el, e.relatedTarget || pointerTarget)) return;
|