mnfst 0.5.123 → 0.5.125
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.code.js +3 -1
- package/lib/manifest.css +77 -16
- package/lib/manifest.data.js +9 -38
- package/lib/manifest.dropdowns.js +4 -2
- package/lib/manifest.form.css +77 -16
- package/lib/manifest.integrity.json +6 -6
- package/lib/manifest.js +82 -31
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.tabs.js +101 -88
- package/lib/manifest.tooltips.js +18 -3
- package/package.json +1 -1
package/lib/manifest.code.js
CHANGED
|
@@ -714,8 +714,10 @@ async function setupCodeGroup(group) {
|
|
|
714
714
|
// That way the tablist can have its own overflow-x scrolling (when
|
|
715
715
|
// there are too many tabs to fit) without dragging sibling header
|
|
716
716
|
// content into the scroll region. CSS targets the inner element via
|
|
717
|
-
// [role="tablist"]
|
|
717
|
+
// [role="tablist"]. The unstyle class opts out of the generic tab
|
|
718
|
+
// bar styling in manifest.form.css; manifest.code.css styles it.
|
|
718
719
|
tablist = document.createElement('div');
|
|
720
|
+
tablist.className = 'unstyle';
|
|
719
721
|
tablist.setAttribute('role', 'tablist');
|
|
720
722
|
tablist.setAttribute('aria-label', 'Code examples');
|
|
721
723
|
header.appendChild(tablist);
|
package/lib/manifest.css
CHANGED
|
@@ -2360,8 +2360,9 @@
|
|
|
2360
2360
|
|
|
2361
2361
|
@layer components {
|
|
2362
2362
|
|
|
2363
|
-
/* Group
|
|
2364
|
-
:where([role=group]:has(button, input, select)
|
|
2363
|
+
/* Group & tab bar wrappers */
|
|
2364
|
+
:where([role=group]:has(button, [role=button], input, select),
|
|
2365
|
+
[role=tablist]:not(:has(>:not(button, a, [role=button], [role=tab], template)))):not(.unstyle) {
|
|
2365
2366
|
display: flex;
|
|
2366
2367
|
flex-flow: row nowrap;
|
|
2367
2368
|
align-items: center;
|
|
@@ -2378,20 +2379,6 @@
|
|
|
2378
2379
|
}
|
|
2379
2380
|
}
|
|
2380
2381
|
|
|
2381
|
-
&>*:first-child {
|
|
2382
|
-
border-start-end-radius: 0;
|
|
2383
|
-
border-end-end-radius: 0
|
|
2384
|
-
}
|
|
2385
|
-
|
|
2386
|
-
&>*:not(:first-child):not(:last-child) {
|
|
2387
|
-
border-radius: 0
|
|
2388
|
-
}
|
|
2389
|
-
|
|
2390
|
-
&>*:last-child {
|
|
2391
|
-
border-start-start-radius: 0;
|
|
2392
|
-
border-end-start-radius: 0
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
2382
|
&.even>* {
|
|
2396
2383
|
flex-shrink: initial;
|
|
2397
2384
|
width: 100%
|
|
@@ -2400,6 +2387,80 @@
|
|
|
2400
2387
|
& input {
|
|
2401
2388
|
width: fit-content
|
|
2402
2389
|
}
|
|
2390
|
+
|
|
2391
|
+
/* Groups connect children with shared borders */
|
|
2392
|
+
&:where([role=group]) {
|
|
2393
|
+
|
|
2394
|
+
&>*:first-child {
|
|
2395
|
+
border-start-end-radius: 0;
|
|
2396
|
+
border-end-end-radius: 0
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
&>*:not(:first-child):not(:last-child) {
|
|
2400
|
+
border-radius: 0
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
&>*:last-child {
|
|
2404
|
+
border-start-start-radius: 0;
|
|
2405
|
+
border-end-start-radius: 0
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
/* Tab bar track */
|
|
2410
|
+
&[role=tablist] {
|
|
2411
|
+
position: relative;
|
|
2412
|
+
isolation: isolate;
|
|
2413
|
+
gap: calc(var(--spacing, 0.25rem) * 0.5);
|
|
2414
|
+
height: var(--spacing-field-height, calc(var(--spacing) * 9));
|
|
2415
|
+
padding: calc(var(--spacing, 0.25rem) / 2);
|
|
2416
|
+
background-color: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent));
|
|
2417
|
+
border-radius: var(--radius, 0.5rem);
|
|
2418
|
+
anchor-scope: --selected-tab;
|
|
2419
|
+
|
|
2420
|
+
/* Concentric corners */
|
|
2421
|
+
&>* {
|
|
2422
|
+
height: 100%;
|
|
2423
|
+
background-color: transparent;
|
|
2424
|
+
border-radius: max(calc(var(--radius, 0.5rem) - var(--spacing, 0.25rem) / 2), 0px);
|
|
2425
|
+
|
|
2426
|
+
&:hover:not(.selected, [aria-selected=true], [aria-current]) {
|
|
2427
|
+
background-color: color-mix(in oklch, var(--color-field-surface-hover, oklch(37.1% 0 0)) 40%, transparent)
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
/* Selected tab */
|
|
2432
|
+
&>:is(.selected, [aria-selected=true], [aria-current]) {
|
|
2433
|
+
background-color: color-mix(in oklch, var(--color-field-surface, color-mix(oklch(20.5% 0 0) 10%, transparent)) 75%, var(--color-field-inverse, oklch(43.9% 0 0)));
|
|
2434
|
+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
/* Background slider for selected tab) */
|
|
2438
|
+
@supports (anchor-scope: --tab) {
|
|
2439
|
+
|
|
2440
|
+
&>:is(.selected, [aria-selected=true], [aria-current]) {
|
|
2441
|
+
/* --co-anchor lets inline anchor-name writers (e.g. tooltips) compose with the slider anchor */
|
|
2442
|
+
anchor-name: --selected-tab;
|
|
2443
|
+
--co-anchor: --selected-tab;
|
|
2444
|
+
background-color: transparent;
|
|
2445
|
+
box-shadow: none;
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
&:has(>:is(.selected, [aria-selected=true], [aria-current]))::before {
|
|
2449
|
+
content: "";
|
|
2450
|
+
position: absolute;
|
|
2451
|
+
z-index: -1;
|
|
2452
|
+
position-anchor: --selected-tab;
|
|
2453
|
+
top: anchor(top);
|
|
2454
|
+
left: anchor(left);
|
|
2455
|
+
width: anchor-size(width);
|
|
2456
|
+
height: anchor-size(height);
|
|
2457
|
+
background-color: color-mix(in oklch, var(--color-field-surface, color-mix(oklch(20.5% 0 0) 10%, transparent)) 75%, var(--color-field-inverse, oklch(43.9% 0 0)));
|
|
2458
|
+
border-radius: max(calc(var(--radius, 0.5rem) - var(--spacing, 0.25rem) / 2), 0px);
|
|
2459
|
+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
2460
|
+
transition: all 0.15s ease-in-out;
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2403
2464
|
}
|
|
2404
2465
|
|
|
2405
2466
|
:where(form):not(.unstyle) {
|
package/lib/manifest.data.js
CHANGED
|
@@ -10177,49 +10177,27 @@ function registerFilesDirective() {
|
|
|
10177
10177
|
let cleanupCallbacks = [];
|
|
10178
10178
|
let watchCreated = false; // Track if watch has been created to prevent duplicates
|
|
10179
10179
|
|
|
10180
|
-
// CRITICAL: Always create a NEW isolated x-data scope for this directive element
|
|
10181
|
-
// This ensures complete isolation - each directive instance has its own scope
|
|
10182
|
-
// We MUST do this even if a parent scope exists, to prevent property conflicts
|
|
10183
10180
|
const directiveInstanceId = `directive-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
10184
10181
|
|
|
10185
|
-
//
|
|
10186
|
-
//
|
|
10182
|
+
// Isolated reactive scope for this directive instance. Alpine never
|
|
10183
|
+
// re-reads x-data attributes on initialized elements, so editing the
|
|
10184
|
+
// attribute would resolve $data(el) to the ANCESTOR scope and pollute
|
|
10185
|
+
// it — addScopeToNode attaches a fresh scope layer to this node.
|
|
10187
10186
|
const isolatedData = Alpine.reactive({
|
|
10188
10187
|
files: [],
|
|
10189
10188
|
loadingFiles: false,
|
|
10190
10189
|
filesError: null
|
|
10191
10190
|
});
|
|
10191
|
+
const removeIsolatedScope = Alpine.addScopeToNode(el, isolatedData);
|
|
10192
|
+
cleanupCallbacks.push(removeIsolatedScope);
|
|
10192
10193
|
|
|
10193
|
-
//
|
|
10194
|
-
//
|
|
10195
|
-
el
|
|
10196
|
-
|
|
10197
|
-
// Get the scope AFTER setting x-data (Alpine creates it when x-data is set)
|
|
10198
|
-
let scope;
|
|
10199
|
-
try {
|
|
10200
|
-
scope = Alpine.$data(el);
|
|
10201
|
-
} catch (e) {
|
|
10202
|
-
// If Alpine hasn't initialized yet, create scope manually
|
|
10203
|
-
scope = {};
|
|
10204
|
-
Alpine.initTree(el);
|
|
10205
|
-
scope = Alpine.$data(el);
|
|
10206
|
-
}
|
|
10207
|
-
|
|
10208
|
-
// CRITICAL: Directly assign properties to the scope object
|
|
10209
|
-
// Since this is a NEW isolated scope, we can safely assign directly without conflicts
|
|
10210
|
-
scope.files = isolatedData.files;
|
|
10211
|
-
scope.loadingFiles = isolatedData.loadingFiles;
|
|
10212
|
-
scope.filesError = isolatedData.filesError;
|
|
10194
|
+
// Merged scope view: writes to files/loadingFiles/filesError land on
|
|
10195
|
+
// isolatedData (top of stack), magics like $watch resolve from ancestors
|
|
10196
|
+
const scope = Alpine.$data(el);
|
|
10213
10197
|
|
|
10214
10198
|
// Store reference in WeakMap for access in closures
|
|
10215
10199
|
dataFilesNamespaces.set(el, isolatedData);
|
|
10216
10200
|
|
|
10217
|
-
// DIAGNOSTIC: Log scope identity and element info
|
|
10218
|
-
const scopeId = `scope-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
10219
|
-
scope._debugScopeId = scopeId;
|
|
10220
|
-
scope._debugDirectiveId = directiveInstanceId;
|
|
10221
|
-
scope._debugElement = el;
|
|
10222
|
-
|
|
10223
10201
|
// Initialize local references
|
|
10224
10202
|
files = isolatedData.files;
|
|
10225
10203
|
loadingFiles = isolatedData.loadingFiles;
|
|
@@ -10584,7 +10562,6 @@ function registerFilesDirective() {
|
|
|
10584
10562
|
watchCreated = true; // Mark watch as created to prevent duplicates
|
|
10585
10563
|
const projectId = currentProjectId; // Capture project ID for closure
|
|
10586
10564
|
let isProcessing = false; // Guard against multiple simultaneous updates
|
|
10587
|
-
let isInitializing = true; // Skip first evaluation (initialization)
|
|
10588
10565
|
|
|
10589
10566
|
// Initialize lastFileIds with current value from the store to prevent false positives
|
|
10590
10567
|
const store = Alpine.store('data');
|
|
@@ -10616,12 +10593,6 @@ function registerFilesDirective() {
|
|
|
10616
10593
|
return JSON.stringify(currentProject.fileIds || []);
|
|
10617
10594
|
},
|
|
10618
10595
|
(currentFileIdsJson) => {
|
|
10619
|
-
// Skip first evaluation (initialization) - we already loaded files above
|
|
10620
|
-
if (isInitializing) {
|
|
10621
|
-
isInitializing = false;
|
|
10622
|
-
return;
|
|
10623
|
-
}
|
|
10624
|
-
|
|
10625
10596
|
// Guard against processing multiple updates simultaneously
|
|
10626
10597
|
if (isProcessing) {
|
|
10627
10598
|
return;
|
|
@@ -10,11 +10,13 @@ document.addEventListener('pointerdown', () => { lastInputModality = 'mouse'; },
|
|
|
10
10
|
|
|
11
11
|
// Initialize plugin when either DOM is ready or Alpine is ready
|
|
12
12
|
function initializeDropdownPlugin() {
|
|
13
|
-
// Ensure Alpine.js context exists for directives to work
|
|
13
|
+
// Ensure Alpine.js context exists for directives to work. Keep the scope
|
|
14
|
+
// empty — seeding properties here collides with author state and the
|
|
15
|
+
// tabs plugin's page-level `tab` property.
|
|
14
16
|
function ensureAlpineContext() {
|
|
15
17
|
const body = document.body;
|
|
16
18
|
if (!body.hasAttribute('x-data')) {
|
|
17
|
-
body.setAttribute('x-data', '{
|
|
19
|
+
body.setAttribute('x-data', '{}');
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
|
package/lib/manifest.form.css
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
@layer components {
|
|
4
4
|
|
|
5
|
-
/* Group
|
|
6
|
-
:where([role=group]:has(button, input, select)
|
|
5
|
+
/* Group & tab bar wrappers */
|
|
6
|
+
:where([role=group]:has(button, [role=button], input, select),
|
|
7
|
+
[role=tablist]:not(:has(>:not(button, a, [role=button], [role=tab], template)))):not(.unstyle) {
|
|
7
8
|
display: flex;
|
|
8
9
|
flex-flow: row nowrap;
|
|
9
10
|
align-items: center;
|
|
@@ -20,20 +21,6 @@
|
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
&>*:first-child {
|
|
24
|
-
border-start-end-radius: 0;
|
|
25
|
-
border-end-end-radius: 0
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
&>*:not(:first-child):not(:last-child) {
|
|
29
|
-
border-radius: 0
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
&>*:last-child {
|
|
33
|
-
border-start-start-radius: 0;
|
|
34
|
-
border-end-start-radius: 0
|
|
35
|
-
}
|
|
36
|
-
|
|
37
24
|
&.even>* {
|
|
38
25
|
flex-shrink: initial;
|
|
39
26
|
width: 100%
|
|
@@ -42,6 +29,80 @@
|
|
|
42
29
|
& input {
|
|
43
30
|
width: fit-content
|
|
44
31
|
}
|
|
32
|
+
|
|
33
|
+
/* Groups connect children with shared borders */
|
|
34
|
+
&:where([role=group]) {
|
|
35
|
+
|
|
36
|
+
&>*:first-child {
|
|
37
|
+
border-start-end-radius: 0;
|
|
38
|
+
border-end-end-radius: 0
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&>*:not(:first-child):not(:last-child) {
|
|
42
|
+
border-radius: 0
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&>*:last-child {
|
|
46
|
+
border-start-start-radius: 0;
|
|
47
|
+
border-end-start-radius: 0
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Tab bar track */
|
|
52
|
+
&[role=tablist] {
|
|
53
|
+
position: relative;
|
|
54
|
+
isolation: isolate;
|
|
55
|
+
gap: calc(var(--spacing, 0.25rem) * 0.5);
|
|
56
|
+
height: var(--spacing-field-height, calc(var(--spacing) * 9));
|
|
57
|
+
padding: calc(var(--spacing, 0.25rem) / 2);
|
|
58
|
+
background-color: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent));
|
|
59
|
+
border-radius: var(--radius, 0.5rem);
|
|
60
|
+
anchor-scope: --selected-tab;
|
|
61
|
+
|
|
62
|
+
/* Concentric corners */
|
|
63
|
+
&>* {
|
|
64
|
+
height: 100%;
|
|
65
|
+
background-color: transparent;
|
|
66
|
+
border-radius: max(calc(var(--radius, 0.5rem) - var(--spacing, 0.25rem) / 2), 0px);
|
|
67
|
+
|
|
68
|
+
&:hover:not(.selected, [aria-selected=true], [aria-current]) {
|
|
69
|
+
background-color: color-mix(in oklch, var(--color-field-surface-hover, oklch(37.1% 0 0)) 40%, transparent)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Selected tab */
|
|
74
|
+
&>:is(.selected, [aria-selected=true], [aria-current]) {
|
|
75
|
+
background-color: color-mix(in oklch, var(--color-field-surface, color-mix(oklch(20.5% 0 0) 10%, transparent)) 75%, var(--color-field-inverse, oklch(43.9% 0 0)));
|
|
76
|
+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Background slider for selected tab) */
|
|
80
|
+
@supports (anchor-scope: --tab) {
|
|
81
|
+
|
|
82
|
+
&>:is(.selected, [aria-selected=true], [aria-current]) {
|
|
83
|
+
/* --co-anchor lets inline anchor-name writers (e.g. tooltips) compose with the slider anchor */
|
|
84
|
+
anchor-name: --selected-tab;
|
|
85
|
+
--co-anchor: --selected-tab;
|
|
86
|
+
background-color: transparent;
|
|
87
|
+
box-shadow: none;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&:has(>:is(.selected, [aria-selected=true], [aria-current]))::before {
|
|
91
|
+
content: "";
|
|
92
|
+
position: absolute;
|
|
93
|
+
z-index: -1;
|
|
94
|
+
position-anchor: --selected-tab;
|
|
95
|
+
top: anchor(top);
|
|
96
|
+
left: anchor(left);
|
|
97
|
+
width: anchor-size(width);
|
|
98
|
+
height: anchor-size(height);
|
|
99
|
+
background-color: color-mix(in oklch, var(--color-field-surface, color-mix(oklch(20.5% 0 0) 10%, transparent)) 75%, var(--color-field-inverse, oklch(43.9% 0 0)));
|
|
100
|
+
border-radius: max(calc(var(--radius, 0.5rem) - var(--spacing, 0.25rem) / 2), 0px);
|
|
101
|
+
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
102
|
+
transition: all 0.15s ease-in-out;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
45
106
|
}
|
|
46
107
|
|
|
47
108
|
:where(form):not(.unstyle) {
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"manifest.appwrite.data.js": "sha384-00ulLT+GAIuPHA/rRT9p98vYlsyDzkyKXtg86BDQ6FGQa5vVVN+W6kuforniBAsz",
|
|
4
4
|
"manifest.appwrite.presence.js": "sha384-uxRpx9/Jj0kGtklH5QmUlAzD3zdSvFRfK6bcJQqxl+Bsf5tOo4zgwqJTQgtZoHQP",
|
|
5
5
|
"manifest.charts.js": "sha384-k4nJoXhwjdAg2LzM8uLsE8SMGDczYnUee1kR7OCzBOcX2N5UQ1v78Pndv9JrvCqq",
|
|
6
|
-
"manifest.code.js": "sha384-
|
|
6
|
+
"manifest.code.js": "sha384-nP6DncLx/UuJtloyVKMCOXwIBAq32DshTb/Lc0vVRBWX7kSbxiBnY5aEyqqvK8Kg",
|
|
7
7
|
"manifest.color.js": "sha384-Z9G/lzt0vVMxjz4wkPuGG1X9mmQAJR15aOoGX3ephf7r2wnlUWet5GLgkUMtT4vt",
|
|
8
8
|
"manifest.colorpicker.js": "sha384-Wqz0ZIbeIi7KarqqqSLsQk+7E/fMaKhb32hrq5/eWzX1yjqMrpPZKH8y+jZ3mfg+",
|
|
9
9
|
"manifest.components.js": "sha384-73CB1A+LAGfNexkd7aT69APFSHMzix8irse9uzOkYehHHio4px3oR8JHJeaMH+jI",
|
|
10
|
-
"manifest.data.js": "sha384-
|
|
10
|
+
"manifest.data.js": "sha384-PZiaRsDV4nnRGvmT8y2jEZV+BolcEZGJXbMJU75YqWGXI8b3y/L93zhhllovf4Go",
|
|
11
11
|
"manifest.datepicker.js": "sha384-ZKSSEm04AoMBpra/R0guKGUrLMMqmo3nqPvVb2b3akfDQeirPfYTHOMzAw+6KIGE",
|
|
12
|
-
"manifest.dropdowns.js": "sha384-
|
|
12
|
+
"manifest.dropdowns.js": "sha384-PFn6K1PCD3ict0j7yN25EH4EhMfpRsfR51B0GJB75jM9J7NlXquJkbY6s7SxXlib",
|
|
13
13
|
"manifest.export.js": "sha384-RsTGzsPCBw3yO4+TdAGd4F+o3FnzUNlqnMBqtnn/kUfv7axpzRdPc2AnsExV/93c",
|
|
14
14
|
"manifest.icons.js": "sha384-uOkboYrovjCpl22eey3Jaxpey+pOnot5NDnRRumcRxiR7IOVaRh1i20gYnWXR5dW",
|
|
15
15
|
"manifest.localization.js": "sha384-M3HRb2Ma8PemfFeqq9rgWgw/+Vdb/8d5LGW2MFbVsXaWUPqr/mPuxWtl5Pv8wolL",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
21
21
|
"manifest.status.js": "sha384-7cEl+Nh729ncqy5GtRYMqo5R4d257QPsoFm/hx9Znp9uV/D85pjxVzQ1fhiD+sO6",
|
|
22
22
|
"manifest.svg.js": "sha384-wPfasscODIO6pyMFNIqZ7/C12cR4QYDnVl/wYNhwBO7gFNBGrhimNzL18VTpMPIL",
|
|
23
|
-
"manifest.tabs.js": "sha384-
|
|
23
|
+
"manifest.tabs.js": "sha384-7Kb1EHIbqh1NOl8J1NMp087lcF1gVmwm55QNM3s7JamV6sYiH/WZbdnknAZFtsfW",
|
|
24
24
|
"manifest.tailwind.js": "sha384-aHLvl2oSuUgy06VaBqhhByn5wWxqvnqxw6KCwehakKUS00F/s/Nb62umeASS6Y4P",
|
|
25
25
|
"manifest.toasts.js": "sha384-ytd5rDbax/Ou9z23uedFXPZbxDPsk2E/pxCTq4WLvfv+os1qTI6kELp0kPp07g24",
|
|
26
|
-
"manifest.tooltips.js": "sha384-
|
|
26
|
+
"manifest.tooltips.js": "sha384-59szmOO26KgSq3ea//8LKy+pUzO1SkRUREjCmAUN4KVI5UTX/lKkJnJaIU888M/B",
|
|
27
27
|
"manifest.url.parameters.js": "sha384-FIufiClqDx1rJpU/QUc9z/D43qClQ6Qm8rBahipbJl9BDHUvhrOsUDegmTWW7Tuf",
|
|
28
28
|
"manifest.utilities.js": "sha384-+cS3BJdncunt8zYHWzGQMcNzr70GLRWkjUNavoTYj0566qStZkqVRB6BfTOlkBEJ",
|
|
29
|
-
"manifest.js": "sha384-
|
|
29
|
+
"manifest.js": "sha384-cAO4OK7ec8QQUhy3xd8MlFR0XPde+3LZHMrgTKs30tgxt3vXCJDL4ysZ7JUAroV4"
|
|
30
30
|
}
|
package/lib/manifest.js
CHANGED
|
@@ -38,15 +38,6 @@
|
|
|
38
38
|
const prerenderMeta = document.querySelector('meta[name="manifest:prerendered"]');
|
|
39
39
|
if (!prerenderMeta || prerenderMeta.getAttribute('content') === '0') return;
|
|
40
40
|
|
|
41
|
-
// Remove baked x-for/x-if clones the prerender kept for crawlers. Their
|
|
42
|
-
// <template> is still live, so Alpine re-renders the list/conditional on
|
|
43
|
-
// boot; dropping the baked copies first (before Alpine runs) avoids a
|
|
44
|
-
// duplicate render. data-hydrate islands keep their baked DOM.
|
|
45
|
-
document.querySelectorAll('[data-mnfst-prerender-clone]').forEach((el) => {
|
|
46
|
-
if (el.closest && el.closest('[data-hydrate]')) return;
|
|
47
|
-
el.remove();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
41
|
const blob = document.getElementById('__manifest_hydrate__');
|
|
51
42
|
if (!blob) return;
|
|
52
43
|
let entries;
|
|
@@ -149,6 +140,31 @@
|
|
|
149
140
|
blob.remove();
|
|
150
141
|
}
|
|
151
142
|
|
|
143
|
+
/*
|
|
144
|
+
* Remove baked x-for/x-if clones the prerender kept for crawlers. Their
|
|
145
|
+
* <template> is still live, so Alpine re-renders the list/conditional on
|
|
146
|
+
* boot; dropping the baked copies first avoids a duplicate render.
|
|
147
|
+
* data-hydrate islands keep their baked DOM.
|
|
148
|
+
*
|
|
149
|
+
* Deliberately NOT part of hydratePrerenderedPage(): this wipe is
|
|
150
|
+
* destructive, so it runs at the last safe moment — `alpine:init`, which
|
|
151
|
+
* Alpine dispatches after its script has arrived and executed but BEFORE
|
|
152
|
+
* it walks the DOM and re-renders x-for/x-if from their live templates.
|
|
153
|
+
* If Alpine never arrives (CDN failure, offline), the listener never
|
|
154
|
+
* fires and the page keeps its complete baked content instead of losing
|
|
155
|
+
* the clones with nothing to re-render them.
|
|
156
|
+
*/
|
|
157
|
+
function removePrerenderClones() {
|
|
158
|
+
if (typeof document === 'undefined' || !document.querySelectorAll) return;
|
|
159
|
+
document.querySelectorAll('[data-mnfst-prerender-clone]').forEach((el) => {
|
|
160
|
+
if (el.closest && el.closest('[data-hydrate]')) return;
|
|
161
|
+
el.remove();
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (typeof document !== 'undefined') {
|
|
165
|
+
document.addEventListener('alpine:init', removePrerenderClones, { once: true });
|
|
166
|
+
}
|
|
167
|
+
|
|
152
168
|
// Run hydration BEFORE Alpine's deferred script executes.
|
|
153
169
|
//
|
|
154
170
|
// Timing: `<script defer>` runs AFTER HTML parsing finishes but BEFORE
|
|
@@ -284,32 +300,67 @@
|
|
|
284
300
|
return `https://cdn.jsdelivr.net/npm/alpinejs@${dataAlpine}/dist/cdn.min.js`;
|
|
285
301
|
}
|
|
286
302
|
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
303
|
+
// Has DOMContentLoaded already fired? readyState alone can't tell:
|
|
304
|
+
// 'interactive' covers both "deferred scripts still running" (DCL pending)
|
|
305
|
+
// and "DCL done, subresources still loading". Disambiguate via the
|
|
306
|
+
// navigation timing entry, which records the event the moment it runs.
|
|
307
|
+
function domContentLoadedFired() {
|
|
308
|
+
if (document.readyState === 'complete') return true;
|
|
309
|
+
if (document.readyState === 'loading') return false;
|
|
310
|
+
try {
|
|
311
|
+
const nav = performance.getEntriesByType('navigation')[0];
|
|
312
|
+
if (nav) return nav.domContentLoadedEventEnd > 0;
|
|
313
|
+
} catch (_) { /* fall through */ }
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
299
316
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (
|
|
317
|
+
// Run fn once the document's deferred scripts have all executed (i.e. at
|
|
318
|
+
// or after DOMContentLoaded). The window 'load' listener is a belt-and-
|
|
319
|
+
// braces fallback for environments where the navigation entry is missing.
|
|
320
|
+
function whenDomReady(fn) {
|
|
321
|
+
if (domContentLoadedFired()) {
|
|
322
|
+
fn();
|
|
305
323
|
return;
|
|
306
324
|
}
|
|
325
|
+
let done = false;
|
|
326
|
+
const run = () => { if (!done) { done = true; fn(); } };
|
|
327
|
+
document.addEventListener('DOMContentLoaded', run, { once: true });
|
|
328
|
+
window.addEventListener('load', run, { once: true });
|
|
329
|
+
}
|
|
307
330
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
331
|
+
// Load Alpine.js from CDN. Called by the loader AFTER all plugin scripts
|
|
332
|
+
// have finished loading and registered their directives/magics.
|
|
333
|
+
//
|
|
334
|
+
// Gated on DOMContentLoaded: the page's own deferred scripts register
|
|
335
|
+
// x-data components and magics via `alpine:init`, and the defer queue
|
|
336
|
+
// spins the event loop while a script is still in flight — so on a warm
|
|
337
|
+
// cache an injected Alpine script can load and EXECUTE between two
|
|
338
|
+
// deferred scripts, firing `alpine:init` before the page's registrations
|
|
339
|
+
// exist. Waiting for DCL (which fires only after every deferred script
|
|
340
|
+
// has run) makes the ordering deterministic. In the common cold-cache
|
|
341
|
+
// case DCL has long passed by the time the plugin loads settle, so the
|
|
342
|
+
// gate adds no delay.
|
|
343
|
+
function loadAlpine(alpineUrl = ALPINE_CDN_URL) {
|
|
344
|
+
whenDomReady(() => {
|
|
345
|
+
// Fast check: Alpine already initialized
|
|
346
|
+
if (window.Alpine) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Fallback: if an existing Alpine <script> tag is already in the DOM
|
|
351
|
+
// (e.g. the fixture explicitly added one), wait for it — don't inject
|
|
352
|
+
// a second copy.
|
|
353
|
+
const existingAlpine = document.querySelector('script[src*="alpinejs"]');
|
|
354
|
+
if (existingAlpine) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const script = document.createElement('script');
|
|
359
|
+
script.src = alpineUrl;
|
|
360
|
+
// No `defer` — we're past plugin registration and past DCL, so
|
|
361
|
+
// Alpine should load and execute as soon as it arrives.
|
|
362
|
+
document.head.appendChild(script);
|
|
363
|
+
});
|
|
313
364
|
}
|
|
314
365
|
|
|
315
366
|
// Add a script tag to the head and wait for it to load and execute
|