mnfst 0.5.171 → 0.5.172
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.charts.js +10 -4
- package/lib/manifest.combobox.js +28 -13
- package/lib/manifest.css +103 -11
- package/lib/manifest.dropdown.css +12 -10
- package/lib/manifest.integrity.json +5 -4
- package/lib/manifest.js +18 -3
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.native.js +484 -0
- package/lib/manifest.schema.json +5 -0
- package/lib/manifest.utilities.css +27 -0
- package/lib/manifest.utilities.js +78 -1
- package/package.json +1 -1
package/lib/manifest.charts.js
CHANGED
|
@@ -649,25 +649,31 @@
|
|
|
649
649
|
const thickness = Math.max(8, r * 0.22);
|
|
650
650
|
const cx = width / 2, cy = Math.max(PAD, (height - (r + labelBand)) / 2) + r;
|
|
651
651
|
const g = svg('g', { transform: `translate(${cx},${cy})` }, root);
|
|
652
|
-
|
|
652
|
+
// Bands are drawn with square (butt) ends so zone/value joins stay flush;
|
|
653
|
+
// the whole dial is then clipped to a single rounded full-sweep arc, so
|
|
654
|
+
// only its two outer corners are rounded — not each interior segment.
|
|
655
|
+
const arc = d3.arc().innerRadius(r - thickness).outerRadius(r);
|
|
656
|
+
const clipId = 'mnfst-gauge-' + (++_uid);
|
|
657
|
+
svg('path', { d: d3.arc().innerRadius(r - thickness).outerRadius(r).cornerRadius(cssRadius(state.el))({ startAngle: START, endAngle: END }) }, svg('clipPath', { id: clipId }, svg('defs', null, root)));
|
|
658
|
+
const ring = svg('g', { 'clip-path': `url(#${clipId})` }, g);
|
|
653
659
|
|
|
654
660
|
// Track, or threshold zone bands when `zones` is given.
|
|
655
661
|
if (Array.isArray(cfg.zones) && cfg.zones.length) {
|
|
656
662
|
let from = min;
|
|
657
663
|
cfg.zones.forEach((z, i) => {
|
|
658
664
|
const to = num(z.to, max);
|
|
659
|
-
svg('path', { class: 'gauge-track', d: arc({ startAngle: scale(from), endAngle: scale(to) }), style: `--color-chart-color:${z.color || seriesColorVar(i)}`, opacity: 0.35 },
|
|
665
|
+
svg('path', { class: 'gauge-track', d: arc({ startAngle: scale(from), endAngle: scale(to) }), style: `--color-chart-color:${z.color || seriesColorVar(i)}`, opacity: 0.35 }, ring);
|
|
660
666
|
from = to;
|
|
661
667
|
});
|
|
662
668
|
} else {
|
|
663
|
-
svg('path', { class: 'gauge-track', d: arc({ startAngle: START, endAngle: END }) },
|
|
669
|
+
svg('path', { class: 'gauge-track', d: arc({ startAngle: START, endAngle: END }) }, ring);
|
|
664
670
|
}
|
|
665
671
|
|
|
666
672
|
// Value arc — final geometry set unconditionally, so a background tab that
|
|
667
673
|
// skips the fade reveal still renders correctly.
|
|
668
674
|
const color = (cfg.series[0] && cfg.series[0].color) || 'var(--color-chart-1)';
|
|
669
675
|
const valueAngle = scale(value);
|
|
670
|
-
const vArc = svg('path', { class: 'gauge-value', d: arc({ startAngle: START, endAngle: valueAngle }), style: `--color-chart-color:${color}` },
|
|
676
|
+
const vArc = svg('path', { class: 'gauge-value', d: arc({ startAngle: START, endAngle: valueAngle }), style: `--color-chart-color:${color}` }, ring);
|
|
671
677
|
applyTip(vArc, (cfg.title ? cfg.title + ': ' : '') + value + unit, cfg);
|
|
672
678
|
animate(vArc, [{ opacity: 0 }, { opacity: 1 }], { duration: 500 });
|
|
673
679
|
|
package/lib/manifest.combobox.js
CHANGED
|
@@ -67,22 +67,34 @@ function initializeComboboxPlugin() {
|
|
|
67
67
|
const rand = () => Math.random().toString(36).slice(2, 9);
|
|
68
68
|
const ui = () => window.ManifestUI ? window.ManifestUI.resolve('combobox', UI_FALLBACK) : UI_FALLBACK;
|
|
69
69
|
|
|
70
|
+
// Alpine binding attributes — never carried onto combobox-owned clones
|
|
71
|
+
const isBinding = (n) => n[0] === ':' || n[0] === '@' || n.indexOf('x-') === 0;
|
|
72
|
+
|
|
70
73
|
// Read options from a source element (datalist/select → option, menu → li)
|
|
71
74
|
function readOptions(src) {
|
|
72
75
|
if (!src) return [];
|
|
73
76
|
if (src.tagName === 'MENU') {
|
|
74
|
-
return Array.from(src.querySelectorAll('li')).map(li =>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.
|
|
85
|
-
|
|
77
|
+
return Array.from(src.querySelectorAll('li')).map(li => {
|
|
78
|
+
// The clone is a rendered snapshot: strip Alpine bindings (x-/:/@) from the
|
|
79
|
+
// WHOLE subtree, not just the row — they reference the source's x-for scope
|
|
80
|
+
// and would throw when Alpine walks the combobox-owned copy. The computed
|
|
81
|
+
// results (style, class, text) are already baked in and survive.
|
|
82
|
+
const copy = li.cloneNode(true);
|
|
83
|
+
copy.querySelectorAll('*').forEach(n => {
|
|
84
|
+
Array.from(n.attributes).forEach(a => { if (isBinding(a.name)) n.removeAttribute(a.name); });
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
value: li.dataset.value != null ? li.dataset.value : li.textContent.trim(),
|
|
88
|
+
label: li.dataset.label || li.textContent.trim(),
|
|
89
|
+
pattern: li.dataset.pattern || null,
|
|
90
|
+
locked: li.hasAttribute('data-locked'),
|
|
91
|
+
html: copy.innerHTML,
|
|
92
|
+
// Carry the row's own attributes into the option, minus combobox-managed ones.
|
|
93
|
+
attrs: Array.from(li.attributes)
|
|
94
|
+
.filter(a => { const n = a.name; return n !== 'role' && n !== 'id' && n !== 'aria-selected' && !isBinding(n); })
|
|
95
|
+
.map(a => [a.name, a.value])
|
|
96
|
+
};
|
|
97
|
+
});
|
|
86
98
|
}
|
|
87
99
|
return Array.from(src.querySelectorAll('option')).map(o => ({
|
|
88
100
|
value: o.value || o.textContent.trim(),
|
|
@@ -308,7 +320,10 @@ function initializeComboboxPlugin() {
|
|
|
308
320
|
// stays a data layer x-for/$x can own (reread below mirrors it), the combobox
|
|
309
321
|
// owns the listbox. readOptions keeps each row's innerHTML, preserving markup.
|
|
310
322
|
menu = document.createElement('menu');
|
|
311
|
-
|
|
323
|
+
menu.setAttribute('x-ignore', ''); // plugin-owned rows — Alpine must never walk them
|
|
324
|
+
// Nearest popover host, so an outer auto popover isn't light-dismissed
|
|
325
|
+
// by listbox clicks; body otherwise (out of overflow contexts either way).
|
|
326
|
+
(el.closest('[popover]') || document.body).appendChild(menu);
|
|
312
327
|
generatedMenu = menu; // tracked so cleanup() can remove it on re-render
|
|
313
328
|
if (src) src.style.setProperty('display', 'none', 'important');
|
|
314
329
|
menu.setAttribute('popover', 'manual');
|
package/lib/manifest.css
CHANGED
|
@@ -28,7 +28,13 @@
|
|
|
28
28
|
overflow-wrap: break-word;
|
|
29
29
|
-moz-tab-size: 4;
|
|
30
30
|
-o-tab-size: 4;
|
|
31
|
-
tab-size: 4
|
|
31
|
+
tab-size: 4;
|
|
32
|
+
|
|
33
|
+
/* Device safe-area insets (0 unless viewport-fit=cover on a notched screen) */
|
|
34
|
+
--safe-top: env(safe-area-inset-top, 0px);
|
|
35
|
+
--safe-right: env(safe-area-inset-right, 0px);
|
|
36
|
+
--safe-bottom: env(safe-area-inset-bottom, 0px);
|
|
37
|
+
--safe-left: env(safe-area-inset-left, 0px)
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
:where(html),
|
|
@@ -2640,6 +2646,63 @@
|
|
|
2640
2646
|
}
|
|
2641
2647
|
}
|
|
2642
2648
|
|
|
2649
|
+
/* Manifest Dock */
|
|
2650
|
+
|
|
2651
|
+
@layer components {
|
|
2652
|
+
|
|
2653
|
+
/* Fixed bottom navigation bar. Best practice: <nav dock aria-label="Primary">.
|
|
2654
|
+
Physics (fixed + safe-area + item layout) baked in; skin is themeable via
|
|
2655
|
+
the --dock-* variables. Edge-to-edge by default; set --dock-inset (+ radius)
|
|
2656
|
+
to float it. */
|
|
2657
|
+
:where([dock]) {
|
|
2658
|
+
position: fixed;
|
|
2659
|
+
z-index: 40;
|
|
2660
|
+
inset-inline: var(--dock-inset, 0px);
|
|
2661
|
+
bottom: var(--dock-inset, 0px);
|
|
2662
|
+
display: flex;
|
|
2663
|
+
align-items: stretch;
|
|
2664
|
+
justify-content: space-around;
|
|
2665
|
+
gap: var(--dock-gap, 0px);
|
|
2666
|
+
/* Clear the home indicator in both modes: total bottom clearance == --safe-bottom */
|
|
2667
|
+
padding-bottom: max(calc(var(--safe-bottom, 0px) - var(--dock-inset, 0px)), 0px);
|
|
2668
|
+
background: var(--dock-surface, var(--color-surface-1, oklch(96.7% 0 0)));
|
|
2669
|
+
border-top: var(--dock-border-top, 1px solid var(--color-line, color-mix(in oklch, currentColor 11%, transparent)));
|
|
2670
|
+
border-radius: var(--dock-radius, 0px);
|
|
2671
|
+
box-shadow: var(--dock-shadow, none)
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
/* Dock items */
|
|
2675
|
+
:where([dock] > a, [dock] > button) {
|
|
2676
|
+
flex: 1 1 0;
|
|
2677
|
+
display: flex;
|
|
2678
|
+
flex-direction: column;
|
|
2679
|
+
align-items: center;
|
|
2680
|
+
justify-content: center;
|
|
2681
|
+
gap: 0.125rem;
|
|
2682
|
+
min-height: 3.25rem;
|
|
2683
|
+
padding: 0.375rem 0.25rem;
|
|
2684
|
+
background: transparent;
|
|
2685
|
+
color: var(--color-content-subtle, oklch(55.6% 0 0));
|
|
2686
|
+
font-size: 0.6875rem;
|
|
2687
|
+
line-height: 1.1;
|
|
2688
|
+
text-decoration: none
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
/* Dock icons */
|
|
2692
|
+
:where([dock] :is([x-icon], svg, img)) {
|
|
2693
|
+
width: 1.375rem;
|
|
2694
|
+
height: 1.375rem;
|
|
2695
|
+
font-size: 1.375rem
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
/* Active item — a hook, not a look (bind :aria-current="$route === '/x' ? 'page' : null') */
|
|
2699
|
+
[dock] > a[aria-current="page"],
|
|
2700
|
+
[dock] > button[aria-current="page"],
|
|
2701
|
+
[dock] > .selected {
|
|
2702
|
+
color: var(--color-content-stark, oklch(14.5% 0 0))
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2643
2706
|
/* Manifest Dropdowns */
|
|
2644
2707
|
[popover]:not(.unstyle):not(:popover-open) {
|
|
2645
2708
|
display: none;
|
|
@@ -2669,8 +2732,8 @@
|
|
|
2669
2732
|
transform-origin: top center;
|
|
2670
2733
|
overflow-x: hidden;
|
|
2671
2734
|
|
|
2672
|
-
/* Options */
|
|
2673
|
-
& :where(li, a, button, [role=button], label):not(.unstyle) {
|
|
2735
|
+
/* Options (labels only when flat items — field wrappers keep form layout) */
|
|
2736
|
+
& :where(li, a, button, [role=button], label:not(:has(input:not([type=checkbox], [type=radio], [type=hidden]), select, textarea, .combobox, .label, label))):not(.unstyle) {
|
|
2674
2737
|
display: inline-flex;
|
|
2675
2738
|
justify-content: start;
|
|
2676
2739
|
align-items: center;
|
|
@@ -2730,13 +2793,14 @@
|
|
|
2730
2793
|
background-color: var(--color-line, color-mix(oklch(20.5% 0 0) 10%, transparent))
|
|
2731
2794
|
}
|
|
2732
2795
|
|
|
2733
|
-
/* Labels */
|
|
2734
|
-
& label {
|
|
2796
|
+
/* Labels (not inner field-surface wrappers) */
|
|
2797
|
+
& label:not(.unstyle):not(:has(> input[type=search], > input[type=file], > button[command="--copy"])) {
|
|
2735
2798
|
padding-inline-start: 0.5rem;
|
|
2736
2799
|
padding-inline-end: 0.5rem;
|
|
2737
2800
|
cursor: default;
|
|
2738
2801
|
|
|
2739
|
-
&:hover
|
|
2802
|
+
&:hover,
|
|
2803
|
+
&:active {
|
|
2740
2804
|
background-color: transparent
|
|
2741
2805
|
}
|
|
2742
2806
|
|
|
@@ -2745,8 +2809,9 @@
|
|
|
2745
2809
|
}
|
|
2746
2810
|
}
|
|
2747
2811
|
|
|
2748
|
-
/* Inputs and textareas */
|
|
2749
|
-
|
|
2812
|
+
/* Inputs and textareas placed as direct items */
|
|
2813
|
+
&>:where(input, textarea),
|
|
2814
|
+
& :where(li)>:where(input, textarea) {
|
|
2750
2815
|
flex-shrink: 0;
|
|
2751
2816
|
|
|
2752
2817
|
&:not(:first-child) {
|
|
@@ -2774,12 +2839,12 @@
|
|
|
2774
2839
|
}
|
|
2775
2840
|
|
|
2776
2841
|
/* Dark theme */
|
|
2777
|
-
:where(.dark menu[popover]) :where(li, a, button, label):hover {
|
|
2842
|
+
:where(.dark menu[popover]) :where(li, a, button, label:not(:has(input:not([type=checkbox], [type=radio], [type=hidden]), select, textarea, .combobox, .label, label))):hover {
|
|
2778
2843
|
background-color: var(--color-field-surface-hover, color-mix(oklch(20.5% 0 0) 15%, transparent))
|
|
2779
2844
|
}
|
|
2780
2845
|
|
|
2781
|
-
/* Nested menu alignment */
|
|
2782
|
-
:where(menu menu):where(:not(.unstyle)) {
|
|
2846
|
+
/* Nested menu alignment (not combobox listboxes, which anchor to their field) */
|
|
2847
|
+
:where(menu menu:not([role=listbox])):where(:not(.unstyle)) {
|
|
2783
2848
|
position-area: span-end end;
|
|
2784
2849
|
margin: 0 var(--spacing-popover-offset, 0.5rem)
|
|
2785
2850
|
}
|
|
@@ -5649,4 +5714,31 @@
|
|
|
5649
5714
|
html[data-os="ios"] .no-ios { display: none !important }
|
|
5650
5715
|
html[data-os="android"] .no-android { display: none !important }
|
|
5651
5716
|
html[data-os="macos"] .no-apple, html[data-os="ios"] .no-apple { display: none !important }
|
|
5717
|
+
|
|
5718
|
+
/* Visibility — connectivity & container (html[data-*] set by the $device signal) */
|
|
5719
|
+
html:not([data-online="false"]) .offline-only { display: none !important }
|
|
5720
|
+
html[data-online="false"] .online-only { display: none !important }
|
|
5721
|
+
html:not([data-standalone]) .standalone-only { display: none !important }
|
|
5722
|
+
html:not([data-native]) .native-only { display: none !important }
|
|
5723
|
+
html[data-native] .web-only { display: none !important }
|
|
5724
|
+
|
|
5725
|
+
/* Safe-area padding (var --safe-* is 0 unless viewport-fit=cover on a notched screen) */
|
|
5726
|
+
:where(.pt-safe) { padding-top: var(--safe-top) }
|
|
5727
|
+
:where(.pr-safe) { padding-right: var(--safe-right) }
|
|
5728
|
+
:where(.pb-safe) { padding-bottom: var(--safe-bottom) }
|
|
5729
|
+
:where(.pl-safe) { padding-left: var(--safe-left) }
|
|
5730
|
+
:where(.px-safe) { padding-left: var(--safe-left); padding-right: var(--safe-right) }
|
|
5731
|
+
:where(.py-safe) { padding-top: var(--safe-top); padding-bottom: var(--safe-bottom) }
|
|
5732
|
+
:where(.p-safe) { padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left) }
|
|
5733
|
+
|
|
5734
|
+
/* Dynamic viewport height (avoids the mobile 100vh browser-chrome jump) */
|
|
5735
|
+
:where(.min-h-dvh) { min-height: 100dvh }
|
|
5736
|
+
:where(.h-dvh) { height: 100dvh }
|
|
5737
|
+
|
|
5738
|
+
/* Native — suppress web tells (opt-in) */
|
|
5739
|
+
:where(.no-callout) { -webkit-touch-callout: none }
|
|
5740
|
+
:where(.no-select) { -webkit-user-select: none; user-select: none }
|
|
5741
|
+
:where(.no-tap-zoom) { touch-action: manipulation }
|
|
5742
|
+
:where(.no-overscroll) { overscroll-behavior: none }
|
|
5743
|
+
:where(.no-overscroll-y) { overscroll-behavior-y: none }
|
|
5652
5744
|
}
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
transform-origin: top center;
|
|
46
46
|
overflow-x: hidden;
|
|
47
47
|
|
|
48
|
-
/* Options */
|
|
49
|
-
& :where(li, a, button, [role=button], label):not(.unstyle) {
|
|
48
|
+
/* Options (labels only when flat items — field wrappers keep form layout) */
|
|
49
|
+
& :where(li, a, button, [role=button], label:not(:has(input:not([type=checkbox], [type=radio], [type=hidden]), select, textarea, .combobox, .label, label))):not(.unstyle) {
|
|
50
50
|
display: inline-flex;
|
|
51
51
|
justify-content: start;
|
|
52
52
|
align-items: center;
|
|
@@ -106,13 +106,14 @@
|
|
|
106
106
|
background-color: var(--color-line, color-mix(oklch(20.5% 0 0) 10%, transparent))
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
/* Labels */
|
|
110
|
-
& label {
|
|
109
|
+
/* Labels (not inner field-surface wrappers) */
|
|
110
|
+
& label:not(.unstyle):not(:has(> input[type=search], > input[type=file], > button[command="--copy"])) {
|
|
111
111
|
padding-inline-start: 0.5rem;
|
|
112
112
|
padding-inline-end: 0.5rem;
|
|
113
113
|
cursor: default;
|
|
114
114
|
|
|
115
|
-
&:hover
|
|
115
|
+
&:hover,
|
|
116
|
+
&:active {
|
|
116
117
|
background-color: transparent
|
|
117
118
|
}
|
|
118
119
|
|
|
@@ -121,8 +122,9 @@
|
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
/* Inputs and textareas */
|
|
125
|
-
|
|
125
|
+
/* Inputs and textareas placed as direct items */
|
|
126
|
+
&>:where(input, textarea),
|
|
127
|
+
& :where(li)>:where(input, textarea) {
|
|
126
128
|
flex-shrink: 0;
|
|
127
129
|
|
|
128
130
|
&:not(:first-child) {
|
|
@@ -150,12 +152,12 @@
|
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
/* Dark theme */
|
|
153
|
-
:where(.dark menu[popover]) :where(li, a, button, label):hover {
|
|
155
|
+
:where(.dark menu[popover]) :where(li, a, button, label:not(:has(input:not([type=checkbox], [type=radio], [type=hidden]), select, textarea, .combobox, .label, label))):hover {
|
|
154
156
|
background-color: var(--color-field-surface-hover, color-mix(oklch(20.5% 0 0) 15%, transparent))
|
|
155
157
|
}
|
|
156
158
|
|
|
157
|
-
/* Nested menu alignment */
|
|
158
|
-
:where(menu menu):where(:not(.unstyle)) {
|
|
159
|
+
/* Nested menu alignment (not combobox listboxes, which anchor to their field) */
|
|
160
|
+
:where(menu menu:not([role=listbox])):where(:not(.unstyle)) {
|
|
159
161
|
position-area: span-end end;
|
|
160
162
|
margin: 0 var(--spacing-popover-offset, 0.5rem)
|
|
161
163
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-mHMJ2sVgZ82AdmLXK6ZyUpkWyX6KOtmIf5P/ribCUb2ejtvu/lwMhB68IgAcy9po",
|
|
3
3
|
"manifest.appwrite.data.js": "sha384-KFKVo5TQESLJB7wgk+C8Zb/sAl43QAMdioWW3tQRWYq5umfdpGCZ5Hld9y9f6/Np",
|
|
4
4
|
"manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
|
|
5
|
-
"manifest.charts.js": "sha384-
|
|
5
|
+
"manifest.charts.js": "sha384-qQrjhWkIDi4oU5uQrpy8DdlMjY+gfiivBuX6mssNiFdkawgkVBvKneGgp+nd3PYJ",
|
|
6
6
|
"manifest.chat.js": "sha384-3+eva9YYz5DrdS3DeRGw9oXH/CreuYX+ZHHtYP25vmnYDHiEpFf9nEGLvwSHBXjz",
|
|
7
7
|
"manifest.code.js": "sha384-G3MNfvQRWWY+gm4SGGrSsgQbDeil9MP+ON2DTk6Rcq9Nsex8woHMDt5EJHrFH0Nj",
|
|
8
8
|
"manifest.color.js": "sha384-6Rv3LxyTcZNjrhtayQfqRdCx0uSZ4BiEbgEI98I62eTvp8Aw7LBIoNJ0Je1oktwL",
|
|
9
9
|
"manifest.colorpicker.js": "sha384-N5ezEwgKrDodV4YdURxhdyZKmg1n/QhqvmAC4SEG03mw1pEAZAA8Gphp+NLAOxts",
|
|
10
|
-
"manifest.combobox.js": "sha384-
|
|
10
|
+
"manifest.combobox.js": "sha384-iJpm6Ufqrmm+zdl1YjPUeBkv60gMUxxe/P4Da9rNBuLyo04wkijU7KHxS/W7IG3Q",
|
|
11
11
|
"manifest.components.js": "sha384-eZDib+RFdwd9mOUdi6o53eNS0LBlEEkZPDegxtkAcE+GrGIFxsuB4O0ymfixGNfM",
|
|
12
12
|
"manifest.data.js": "sha384-3lLvGnqcQr4Ium80MdaQTr8RytjVbs5rnxd0q41BF3ppcoQccMFAcvgFSyZP/0sl",
|
|
13
13
|
"manifest.datepicker.js": "sha384-e6rJI0BxuE+AyI96/u6XoeOstsxLuQTO6+wYSr6rm2aKhOP2APM2xJqTz//0v4Pw",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"manifest.icons.js": "sha384-kKOINpX70YzNO3FvkV6umrmO3f0KIu0DNbwB+ej55a7y/lhU7v/myQtXL0bwCTbt",
|
|
17
17
|
"manifest.localization.js": "sha384-MUetuW8PllIM+9JDMw/tx+qGem8t+ZUN5WZpycsTDKtz+LaX4DJehsfh/YZt9J7L",
|
|
18
18
|
"manifest.markdown.js": "sha384-qlhYOzX0nl8HzuaiMVTkIhsma9mv3PlEvHO2S0AzshgmIcdZFvth6/sbHPCe5Zwr",
|
|
19
|
+
"manifest.native.js": "sha384-4WfuciRjqrfDLpHXp91AKQUTt8FDHaupSuVErRgdeaeoHf5d1CfHWqBd/aCOduDk",
|
|
19
20
|
"manifest.payments.js": "sha384-vhG1ZL3wGzb0vt0ygJJQF3jVQumMuvc2smGjYezuyQ+auN+MN9HY2k5NW2bdClxl",
|
|
20
21
|
"manifest.resize.js": "sha384-S3v4RAJoA77LUH6MddYG9bx//dZX//up7XWeH69Ql2ge3bVHgC6mR/CJBe6y4nQI",
|
|
21
22
|
"manifest.router.js": "sha384-oV0lwFkeevEWjRCC/VV2OzkjNdE70owBz+pwKqZzx5bqbx5/1PORW+ndCClEqSgS",
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
"manifest.toasts.js": "sha384-ytd5rDbax/Ou9z23uedFXPZbxDPsk2E/pxCTq4WLvfv+os1qTI6kELp0kPp07g24",
|
|
28
29
|
"manifest.tooltips.js": "sha384-HeJ0BGK3ebut1t8lm+MGeUUxd1pOZDyX8e6HFLsa4kAiRL+LwGDr67ckkRqv7to1",
|
|
29
30
|
"manifest.url.parameters.js": "sha384-FIufiClqDx1rJpU/QUc9z/D43qClQ6Qm8rBahipbJl9BDHUvhrOsUDegmTWW7Tuf",
|
|
30
|
-
"manifest.utilities.js": "sha384-
|
|
31
|
+
"manifest.utilities.js": "sha384-yLEqEbd1FncqswrtrcTO7KrIEK4iP0ZvqCi64XLI7D77/L0YiJbjLdLGGg6l7rgN",
|
|
31
32
|
"manifest.virtual.js": "sha384-c194pXD0Ld48QJ+HPVNibvbn54/ETJRuYhUOWesEBjtOIQcQMIKo0DnCyQMvDlLg",
|
|
32
|
-
"manifest.js": "sha384-
|
|
33
|
+
"manifest.js": "sha384-FLz68HEE8hEVLlAsoAX2+5cWBrhS5+B24rdJy5obXtP5U5bJKCswjbIQL8MpDUFZ"
|
|
33
34
|
}
|
package/lib/manifest.js
CHANGED
|
@@ -265,7 +265,8 @@
|
|
|
265
265
|
// Plugin dependencies: plugins that require other plugins to be loaded first
|
|
266
266
|
const PLUGIN_DEPENDENCIES = {
|
|
267
267
|
'appwrite-data': ['data'],
|
|
268
|
-
'appwrite-presences': ['data', 'appwrite-auth']
|
|
268
|
+
'appwrite-presences': ['data', 'appwrite-auth'],
|
|
269
|
+
'native': ['utilities']
|
|
269
270
|
};
|
|
270
271
|
|
|
271
272
|
// Derive default plugin list from manifest (only load data/localization/components when manifest needs them)
|
|
@@ -488,6 +489,14 @@
|
|
|
488
489
|
return [];
|
|
489
490
|
}
|
|
490
491
|
|
|
492
|
+
// Detect the native umbrella plugin. Auto-loaded inside a Capacitor container
|
|
493
|
+
// (window.Capacitor present) or when a `native` config block opts in on the web.
|
|
494
|
+
function detectNativePlugins(manifest) {
|
|
495
|
+
if (typeof window !== 'undefined' && window.Capacitor) return ['native'];
|
|
496
|
+
if (manifest && typeof manifest === 'object' && manifest.native && typeof manifest.native === 'object') return ['native'];
|
|
497
|
+
return [];
|
|
498
|
+
}
|
|
499
|
+
|
|
491
500
|
// Parse data attributes
|
|
492
501
|
function parseDataAttributes() {
|
|
493
502
|
// Try to get current script first, then fall back to querySelector
|
|
@@ -560,7 +569,7 @@
|
|
|
560
569
|
// Expose API
|
|
561
570
|
window.Manifest = {
|
|
562
571
|
loadPlugin: function (pluginName, version = DEFAULT_VERSION) {
|
|
563
|
-
const allPlugins = [...AVAILABLE_PLUGINS, ...APPWRITE_PLUGINS, 'payments', 'chat'];
|
|
572
|
+
const allPlugins = [...AVAILABLE_PLUGINS, ...APPWRITE_PLUGINS, 'payments', 'chat', 'native'];
|
|
564
573
|
if (!allPlugins.includes(pluginName)) {
|
|
565
574
|
console.warn(`[Manifest Loader] Unknown plugin: ${pluginName}`);
|
|
566
575
|
return Promise.reject(new Error(`Unknown plugin: ${pluginName}`));
|
|
@@ -654,12 +663,18 @@
|
|
|
654
663
|
const appwritePlugins = detectAppwritePlugins(manifest);
|
|
655
664
|
const paymentsPlugins = detectPaymentsPlugins(manifest);
|
|
656
665
|
const chatPlugins = detectChatPlugins(manifest);
|
|
657
|
-
|
|
666
|
+
const nativePlugins = detectNativePlugins(manifest);
|
|
667
|
+
pluginsToLoad = resolveDependencies([...corePlugins, ...appwritePlugins, ...paymentsPlugins, ...chatPlugins, ...nativePlugins]);
|
|
658
668
|
} else {
|
|
659
669
|
const needsManifest = config.plugins.some(p => MANIFEST_DEPENDENT_PLUGINS.includes(p));
|
|
660
670
|
if (needsManifest) {
|
|
661
671
|
manifestPromise = fetch(manifestUrl).then(r => r.ok ? r.json() : null).catch(() => null);
|
|
662
672
|
}
|
|
673
|
+
// Inside a Capacitor container, ensure the native umbrella loads even on
|
|
674
|
+
// the explicit data-plugins path (matches the derive-path auto-inject).
|
|
675
|
+
if (typeof window !== 'undefined' && window.Capacitor && !pluginsToLoad.includes('native')) {
|
|
676
|
+
pluginsToLoad = resolveDependencies([...pluginsToLoad, 'native']);
|
|
677
|
+
}
|
|
663
678
|
}
|
|
664
679
|
|
|
665
680
|
const pluginPromises = pluginsToLoad.map(pluginName => {
|