mnfst 0.5.171 → 0.5.173
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 +125 -16
- package/lib/manifest.datepicker.css +21 -4
- package/lib/manifest.dropdown.css +12 -10
- package/lib/manifest.form.css +1 -1
- 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),
|
|
@@ -2326,28 +2332,45 @@
|
|
|
2326
2332
|
justify-content: space-between;
|
|
2327
2333
|
gap: 0.25rem;
|
|
2328
2334
|
width: 100%;
|
|
2335
|
+
contain: inline-size;
|
|
2329
2336
|
padding: 0.5rem 0;
|
|
2330
2337
|
border-top: 1px solid var(--color-line, color-mix(oklch(20.5% 0 0) 10%, transparent));
|
|
2331
2338
|
|
|
2332
2339
|
/* Today | Clear buttons */
|
|
2333
|
-
|
|
2334
|
-
width: fit-content
|
|
2340
|
+
&>button {
|
|
2341
|
+
width: fit-content;
|
|
2342
|
+
background: transparent;
|
|
2343
|
+
color: var(--color-content-neutral, oklch(43.9% 0 0));
|
|
2344
|
+
|
|
2345
|
+
&:hover {
|
|
2346
|
+
background: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent));
|
|
2347
|
+
color: var(--color-content-stark, oklch(20.5% 0 0))
|
|
2348
|
+
}
|
|
2335
2349
|
}
|
|
2336
2350
|
|
|
2337
2351
|
/* Preset chips */
|
|
2338
2352
|
&>div {
|
|
2339
2353
|
flex: 1;
|
|
2354
|
+
min-width: 0;
|
|
2340
2355
|
display: flex;
|
|
2341
|
-
flex-
|
|
2356
|
+
flex-wrap: nowrap;
|
|
2342
2357
|
align-items: center;
|
|
2343
|
-
justify-content: center;
|
|
2358
|
+
justify-content: safe center;
|
|
2344
2359
|
gap: 0.25rem;
|
|
2360
|
+
overflow-x: auto;
|
|
2361
|
+
scrollbar-width: none;
|
|
2362
|
+
|
|
2363
|
+
&::-webkit-scrollbar {
|
|
2364
|
+
display: none
|
|
2365
|
+
}
|
|
2345
2366
|
|
|
2346
2367
|
& button {
|
|
2368
|
+
flex: 0 0 auto;
|
|
2347
2369
|
height: auto;
|
|
2348
2370
|
min-height: 0;
|
|
2349
2371
|
padding: 0.25rem 0.625rem;
|
|
2350
2372
|
font-size: 0.75rem;
|
|
2373
|
+
white-space: nowrap;
|
|
2351
2374
|
background: var(--color-field-surface, color-mix(oklch(20.5% 0 0) 10%, transparent));
|
|
2352
2375
|
color: var(--color-content-stark, oklch(20.5% 0 0));
|
|
2353
2376
|
border: none;
|
|
@@ -2640,6 +2663,63 @@
|
|
|
2640
2663
|
}
|
|
2641
2664
|
}
|
|
2642
2665
|
|
|
2666
|
+
/* Manifest Dock */
|
|
2667
|
+
|
|
2668
|
+
@layer components {
|
|
2669
|
+
|
|
2670
|
+
/* Fixed bottom navigation bar. Best practice: <nav dock aria-label="Primary">.
|
|
2671
|
+
Physics (fixed + safe-area + item layout) baked in; skin is themeable via
|
|
2672
|
+
the --dock-* variables. Edge-to-edge by default; set --dock-inset (+ radius)
|
|
2673
|
+
to float it. */
|
|
2674
|
+
:where([dock]) {
|
|
2675
|
+
position: fixed;
|
|
2676
|
+
z-index: 40;
|
|
2677
|
+
inset-inline: var(--dock-inset, 0px);
|
|
2678
|
+
bottom: var(--dock-inset, 0px);
|
|
2679
|
+
display: flex;
|
|
2680
|
+
align-items: stretch;
|
|
2681
|
+
justify-content: space-around;
|
|
2682
|
+
gap: var(--dock-gap, 0px);
|
|
2683
|
+
/* Clear the home indicator in both modes: total bottom clearance == --safe-bottom */
|
|
2684
|
+
padding-bottom: max(calc(var(--safe-bottom, 0px) - var(--dock-inset, 0px)), 0px);
|
|
2685
|
+
background: var(--dock-surface, var(--color-surface-1, oklch(96.7% 0 0)));
|
|
2686
|
+
border-top: var(--dock-border-top, 1px solid var(--color-line, color-mix(in oklch, currentColor 11%, transparent)));
|
|
2687
|
+
border-radius: var(--dock-radius, 0px);
|
|
2688
|
+
box-shadow: var(--dock-shadow, none)
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
/* Dock items */
|
|
2692
|
+
:where([dock] > a, [dock] > button) {
|
|
2693
|
+
flex: 1 1 0;
|
|
2694
|
+
display: flex;
|
|
2695
|
+
flex-direction: column;
|
|
2696
|
+
align-items: center;
|
|
2697
|
+
justify-content: center;
|
|
2698
|
+
gap: 0.125rem;
|
|
2699
|
+
min-height: 3.25rem;
|
|
2700
|
+
padding: 0.375rem 0.25rem;
|
|
2701
|
+
background: transparent;
|
|
2702
|
+
color: var(--color-content-subtle, oklch(55.6% 0 0));
|
|
2703
|
+
font-size: 0.6875rem;
|
|
2704
|
+
line-height: 1.1;
|
|
2705
|
+
text-decoration: none
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
/* Dock icons */
|
|
2709
|
+
:where([dock] :is([x-icon], svg, img)) {
|
|
2710
|
+
width: 1.375rem;
|
|
2711
|
+
height: 1.375rem;
|
|
2712
|
+
font-size: 1.375rem
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
/* Active item — a hook, not a look (bind :aria-current="$route === '/x' ? 'page' : null') */
|
|
2716
|
+
[dock] > a[aria-current="page"],
|
|
2717
|
+
[dock] > button[aria-current="page"],
|
|
2718
|
+
[dock] > .selected {
|
|
2719
|
+
color: var(--color-content-stark, oklch(14.5% 0 0))
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2643
2723
|
/* Manifest Dropdowns */
|
|
2644
2724
|
[popover]:not(.unstyle):not(:popover-open) {
|
|
2645
2725
|
display: none;
|
|
@@ -2669,8 +2749,8 @@
|
|
|
2669
2749
|
transform-origin: top center;
|
|
2670
2750
|
overflow-x: hidden;
|
|
2671
2751
|
|
|
2672
|
-
/* Options */
|
|
2673
|
-
& :where(li, a, button, [role=button], label):not(.unstyle) {
|
|
2752
|
+
/* Options (labels only when flat items — field wrappers keep form layout) */
|
|
2753
|
+
& :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
2754
|
display: inline-flex;
|
|
2675
2755
|
justify-content: start;
|
|
2676
2756
|
align-items: center;
|
|
@@ -2730,13 +2810,14 @@
|
|
|
2730
2810
|
background-color: var(--color-line, color-mix(oklch(20.5% 0 0) 10%, transparent))
|
|
2731
2811
|
}
|
|
2732
2812
|
|
|
2733
|
-
/* Labels */
|
|
2734
|
-
& label {
|
|
2813
|
+
/* Labels (not inner field-surface wrappers) */
|
|
2814
|
+
& label:not(.unstyle):not(:has(> input[type=search], > input[type=file], > button[command="--copy"])) {
|
|
2735
2815
|
padding-inline-start: 0.5rem;
|
|
2736
2816
|
padding-inline-end: 0.5rem;
|
|
2737
2817
|
cursor: default;
|
|
2738
2818
|
|
|
2739
|
-
&:hover
|
|
2819
|
+
&:hover,
|
|
2820
|
+
&:active {
|
|
2740
2821
|
background-color: transparent
|
|
2741
2822
|
}
|
|
2742
2823
|
|
|
@@ -2745,8 +2826,9 @@
|
|
|
2745
2826
|
}
|
|
2746
2827
|
}
|
|
2747
2828
|
|
|
2748
|
-
/* Inputs and textareas */
|
|
2749
|
-
|
|
2829
|
+
/* Inputs and textareas placed as direct items */
|
|
2830
|
+
&>:where(input, textarea),
|
|
2831
|
+
& :where(li)>:where(input, textarea) {
|
|
2750
2832
|
flex-shrink: 0;
|
|
2751
2833
|
|
|
2752
2834
|
&:not(:first-child) {
|
|
@@ -2774,12 +2856,12 @@
|
|
|
2774
2856
|
}
|
|
2775
2857
|
|
|
2776
2858
|
/* Dark theme */
|
|
2777
|
-
:where(.dark menu[popover]) :where(li, a, button, label):hover {
|
|
2859
|
+
: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
2860
|
background-color: var(--color-field-surface-hover, color-mix(oklch(20.5% 0 0) 15%, transparent))
|
|
2779
2861
|
}
|
|
2780
2862
|
|
|
2781
|
-
/* Nested menu alignment */
|
|
2782
|
-
:where(menu menu):where(:not(.unstyle)) {
|
|
2863
|
+
/* Nested menu alignment (not combobox listboxes, which anchor to their field) */
|
|
2864
|
+
:where(menu menu:not([role=listbox])):where(:not(.unstyle)) {
|
|
2783
2865
|
position-area: span-end end;
|
|
2784
2866
|
margin: 0 var(--spacing-popover-offset, 0.5rem)
|
|
2785
2867
|
}
|
|
@@ -3099,7 +3181,7 @@
|
|
|
3099
3181
|
z-index: 1
|
|
3100
3182
|
}
|
|
3101
3183
|
|
|
3102
|
-
/* Equal-width children
|
|
3184
|
+
/* Equal-width children */
|
|
3103
3185
|
&.even>* {
|
|
3104
3186
|
flex-shrink: initial;
|
|
3105
3187
|
width: 100%
|
|
@@ -5649,4 +5731,31 @@
|
|
|
5649
5731
|
html[data-os="ios"] .no-ios { display: none !important }
|
|
5650
5732
|
html[data-os="android"] .no-android { display: none !important }
|
|
5651
5733
|
html[data-os="macos"] .no-apple, html[data-os="ios"] .no-apple { display: none !important }
|
|
5734
|
+
|
|
5735
|
+
/* Visibility — connectivity & container (html[data-*] set by the $device signal) */
|
|
5736
|
+
html:not([data-online="false"]) .offline-only { display: none !important }
|
|
5737
|
+
html[data-online="false"] .online-only { display: none !important }
|
|
5738
|
+
html:not([data-standalone]) .standalone-only { display: none !important }
|
|
5739
|
+
html:not([data-native]) .native-only { display: none !important }
|
|
5740
|
+
html[data-native] .web-only { display: none !important }
|
|
5741
|
+
|
|
5742
|
+
/* Safe-area padding (var --safe-* is 0 unless viewport-fit=cover on a notched screen) */
|
|
5743
|
+
:where(.pt-safe) { padding-top: var(--safe-top) }
|
|
5744
|
+
:where(.pr-safe) { padding-right: var(--safe-right) }
|
|
5745
|
+
:where(.pb-safe) { padding-bottom: var(--safe-bottom) }
|
|
5746
|
+
:where(.pl-safe) { padding-left: var(--safe-left) }
|
|
5747
|
+
:where(.px-safe) { padding-left: var(--safe-left); padding-right: var(--safe-right) }
|
|
5748
|
+
:where(.py-safe) { padding-top: var(--safe-top); padding-bottom: var(--safe-bottom) }
|
|
5749
|
+
:where(.p-safe) { padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left) }
|
|
5750
|
+
|
|
5751
|
+
/* Dynamic viewport height (avoids the mobile 100vh browser-chrome jump) */
|
|
5752
|
+
:where(.min-h-dvh) { min-height: 100dvh }
|
|
5753
|
+
:where(.h-dvh) { height: 100dvh }
|
|
5754
|
+
|
|
5755
|
+
/* Native — suppress web tells (opt-in) */
|
|
5756
|
+
:where(.no-callout) { -webkit-touch-callout: none }
|
|
5757
|
+
:where(.no-select) { -webkit-user-select: none; user-select: none }
|
|
5758
|
+
:where(.no-tap-zoom) { touch-action: manipulation }
|
|
5759
|
+
:where(.no-overscroll) { overscroll-behavior: none }
|
|
5760
|
+
:where(.no-overscroll-y) { overscroll-behavior-y: none }
|
|
5652
5761
|
}
|
|
@@ -373,28 +373,45 @@
|
|
|
373
373
|
justify-content: space-between;
|
|
374
374
|
gap: 0.25rem;
|
|
375
375
|
width: 100%;
|
|
376
|
+
contain: inline-size;
|
|
376
377
|
padding: 0.5rem 0;
|
|
377
378
|
border-top: 1px solid var(--color-line, color-mix(oklch(20.5% 0 0) 10%, transparent));
|
|
378
379
|
|
|
379
380
|
/* Today | Clear buttons */
|
|
380
|
-
|
|
381
|
-
width: fit-content
|
|
381
|
+
&>button {
|
|
382
|
+
width: fit-content;
|
|
383
|
+
background: transparent;
|
|
384
|
+
color: var(--color-content-neutral, oklch(43.9% 0 0));
|
|
385
|
+
|
|
386
|
+
&:hover {
|
|
387
|
+
background: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent));
|
|
388
|
+
color: var(--color-content-stark, oklch(20.5% 0 0))
|
|
389
|
+
}
|
|
382
390
|
}
|
|
383
391
|
|
|
384
392
|
/* Preset chips */
|
|
385
393
|
&>div {
|
|
386
394
|
flex: 1;
|
|
395
|
+
min-width: 0;
|
|
387
396
|
display: flex;
|
|
388
|
-
flex-
|
|
397
|
+
flex-wrap: nowrap;
|
|
389
398
|
align-items: center;
|
|
390
|
-
justify-content: center;
|
|
399
|
+
justify-content: safe center;
|
|
391
400
|
gap: 0.25rem;
|
|
401
|
+
overflow-x: auto;
|
|
402
|
+
scrollbar-width: none;
|
|
403
|
+
|
|
404
|
+
&::-webkit-scrollbar {
|
|
405
|
+
display: none
|
|
406
|
+
}
|
|
392
407
|
|
|
393
408
|
& button {
|
|
409
|
+
flex: 0 0 auto;
|
|
394
410
|
height: auto;
|
|
395
411
|
min-height: 0;
|
|
396
412
|
padding: 0.25rem 0.625rem;
|
|
397
413
|
font-size: 0.75rem;
|
|
414
|
+
white-space: nowrap;
|
|
398
415
|
background: var(--color-field-surface, color-mix(oklch(20.5% 0 0) 10%, transparent));
|
|
399
416
|
color: var(--color-content-stark, oklch(20.5% 0 0));
|
|
400
417
|
border: none;
|
|
@@ -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
|
}
|
package/lib/manifest.form.css
CHANGED
|
@@ -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 => {
|