@octane-xplat/ui 0.2.1 → 0.4.0
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/README.md +46 -0
- package/dist/native/octane-client-build.json +1 -1
- package/dist/native/ui.js +52 -19
- package/dist/native/ui10.js +25 -45
- package/dist/native/ui11.js +52 -57
- package/dist/native/ui12.js +47 -16
- package/dist/native/ui13.js +24 -18
- package/dist/native/ui14.js +117 -12
- package/dist/native/ui15.js +78 -17
- package/dist/native/ui16.js +88 -115
- package/dist/native/ui17.js +29 -19
- package/dist/native/ui18.js +34 -12
- package/dist/native/ui19.js +244 -8
- package/dist/native/ui2.js +10 -48
- package/dist/native/ui20.js +28 -0
- package/dist/native/ui21.js +383 -0
- package/dist/native/ui22.js +36 -0
- package/dist/native/ui23.js +55 -0
- package/dist/native/ui24.js +83 -0
- package/dist/native/ui25.js +141 -0
- package/dist/native/ui26.js +12 -0
- package/dist/native/ui27.js +61 -0
- package/dist/native/ui28.js +40 -0
- package/dist/native/ui29.js +108 -0
- package/dist/native/ui3.js +17 -20
- package/dist/native/ui30.js +18 -0
- package/dist/native/ui31.js +58 -0
- package/dist/native/ui32.js +58 -0
- package/dist/native/ui33.js +38 -0
- package/dist/native/ui34.js +53 -0
- package/dist/native/ui35.js +105 -0
- package/dist/native/ui36.js +10 -0
- package/dist/native/ui37.js +44 -0
- package/dist/native/ui38.js +197 -0
- package/dist/native/ui39.js +105 -0
- package/dist/native/ui4.js +23 -48
- package/dist/native/ui40.js +58 -0
- package/dist/native/ui41.js +19 -0
- package/dist/native/ui42.js +8 -0
- package/dist/native/ui43.js +38 -0
- package/dist/native/ui44.js +267 -0
- package/dist/native/ui45.js +28 -0
- package/dist/native/ui46.js +35 -0
- package/dist/native/ui47.js +41 -0
- package/dist/native/ui48.js +72 -0
- package/dist/native/ui49.js +66 -0
- package/dist/native/ui5.js +37 -34
- package/dist/native/ui50.js +27 -0
- package/dist/native/ui51.js +13 -0
- package/dist/native/ui52.js +92 -0
- package/dist/native/ui53.js +34 -0
- package/dist/native/ui54.js +17 -0
- package/dist/native/ui55.js +156 -0
- package/dist/native/ui56.js +33 -0
- package/dist/native/ui57.js +14 -0
- package/dist/native/ui58.js +22 -0
- package/dist/native/ui59.js +8 -0
- package/dist/native/ui6.js +79 -20
- package/dist/native/ui60.js +108 -0
- package/dist/native/ui61.js +76 -0
- package/dist/native/ui7.js +44 -65
- package/dist/native/ui8.js +25 -17
- package/dist/native/ui9.js +24 -12
- package/dist/web/octane-client-build.json +1 -1
- package/dist/web/ui.js +51 -19
- package/dist/web/ui10.js +33 -30
- package/dist/web/ui11.js +40 -55
- package/dist/web/ui12.js +36 -15
- package/dist/web/ui13.js +212 -20
- package/dist/web/ui14.js +84 -14
- package/dist/web/ui15.js +425 -46
- package/dist/web/ui16.js +12 -93
- package/dist/web/ui17.js +246 -28
- package/dist/web/ui18.js +238 -15
- package/dist/web/ui19.js +36 -8
- package/dist/web/ui2.js +15 -103
- package/dist/web/ui20.js +85 -0
- package/dist/web/ui21.js +111 -0
- package/dist/web/ui22.js +108 -0
- package/dist/web/ui23.js +96 -0
- package/dist/web/ui24.js +32 -0
- package/dist/web/ui25.js +108 -0
- package/dist/web/ui26.js +45 -0
- package/dist/web/ui27.js +16 -0
- package/dist/web/ui28.js +11 -0
- package/dist/web/ui29.js +58 -0
- package/dist/web/ui3.js +30 -27
- package/dist/web/ui30.js +34 -0
- package/dist/web/ui31.js +123 -0
- package/dist/web/ui32.js +44 -0
- package/dist/web/ui33.js +159 -0
- package/dist/web/ui34.js +70 -0
- package/dist/web/ui35.js +57 -0
- package/dist/web/ui36.js +22 -0
- package/dist/web/ui37.js +7 -0
- package/dist/web/ui38.js +38 -0
- package/dist/web/ui39.js +154 -0
- package/dist/web/ui4.js +46 -24
- package/dist/web/ui40.js +43 -0
- package/dist/web/ui41.js +42 -0
- package/dist/web/ui42.js +76 -0
- package/dist/web/ui43.js +42 -0
- package/dist/web/ui44.js +62 -0
- package/dist/web/ui45.js +9 -0
- package/dist/web/ui46.js +45 -0
- package/dist/web/ui47.js +13 -0
- package/dist/web/ui48.js +63 -0
- package/dist/web/ui49.js +47 -0
- package/dist/web/ui5.js +158 -52
- package/dist/web/ui50.js +17 -0
- package/dist/web/ui51.js +149 -0
- package/dist/web/ui52.js +42 -0
- package/dist/web/ui53.js +17 -0
- package/dist/web/ui54.js +9 -0
- package/dist/web/ui55.js +22 -0
- package/dist/web/ui56.js +8 -0
- package/dist/web/ui57.js +44 -0
- package/dist/web/ui58.js +46 -0
- package/dist/web/ui6.js +85 -22
- package/dist/web/ui7.js +46 -41
- package/dist/web/ui8.js +28 -11
- package/dist/web/ui9.js +32 -13
- package/package.json +18 -6
- package/src/theme/tokens.css +444 -47
- package/types/index.d.ts +180 -29
- package/types/props.d.ts +553 -8
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { View } from "./ui6.js";
|
|
2
|
+
import { defineUniversalComponent, universalComponent, universalPlan, universalProps, universalValue } from "@nativescript-community/octane";
|
|
3
|
+
//#region src/ScrollBox.native.tsrx
|
|
4
|
+
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
5
|
+
"kind": "slot",
|
|
6
|
+
"slot": 0
|
|
7
|
+
});
|
|
8
|
+
var ScrollBox = defineUniversalComponent("nativescript", function ScrollBox(props) {
|
|
9
|
+
return universalValue(__octaneUniversalPlan0, [universalComponent("nativescript", View, universalProps([["spread", props]], props.children))]);
|
|
10
|
+
}, { "module": "@nativescript-community/octane" });
|
|
11
|
+
//#endregion
|
|
12
|
+
export { ScrollBox };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { cx } from "./ui2.js";
|
|
2
|
+
import { applyEscapeProps } from "./ui3.js";
|
|
3
|
+
import { glassClassOf, glassConfigOf } from "./ui4.js";
|
|
4
|
+
import { layoutChildProps } from "./ui5.js";
|
|
5
|
+
import { defineUniversalComponent, universalPlan, universalProps, universalValue } from "@nativescript-community/octane";
|
|
6
|
+
//#region src/ScrollView.native.tsrx
|
|
7
|
+
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
8
|
+
"kind": "host",
|
|
9
|
+
"type": "scrollview",
|
|
10
|
+
"propsSlot": 0,
|
|
11
|
+
"children": [{
|
|
12
|
+
"kind": "host",
|
|
13
|
+
"type": "flexboxlayout",
|
|
14
|
+
"bindings": [["flexDirection", 1]],
|
|
15
|
+
"children": [{
|
|
16
|
+
"kind": "slot",
|
|
17
|
+
"slot": 2
|
|
18
|
+
}]
|
|
19
|
+
}]
|
|
20
|
+
});
|
|
21
|
+
var ScrollView = defineUniversalComponent("nativescript", function ScrollView(props) {
|
|
22
|
+
return universalValue(__octaneUniversalPlan0, [
|
|
23
|
+
universalProps([
|
|
24
|
+
[
|
|
25
|
+
"set",
|
|
26
|
+
"ref",
|
|
27
|
+
(v) => applyEscapeProps(v, props)
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"set",
|
|
31
|
+
"id",
|
|
32
|
+
props.id
|
|
33
|
+
],
|
|
34
|
+
["spread", layoutChildProps(props)],
|
|
35
|
+
[
|
|
36
|
+
"set",
|
|
37
|
+
"className",
|
|
38
|
+
cx(glassClassOf(props.glass), props.className)
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
"set",
|
|
42
|
+
"style",
|
|
43
|
+
props.style
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
"set",
|
|
47
|
+
"iosGlassEffect",
|
|
48
|
+
glassConfigOf(props.glass)
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
"set",
|
|
52
|
+
"orientation",
|
|
53
|
+
props.horizontal ? "horizontal" : "vertical"
|
|
54
|
+
]
|
|
55
|
+
]),
|
|
56
|
+
props.horizontal ? "row" : "column",
|
|
57
|
+
props.children
|
|
58
|
+
]);
|
|
59
|
+
}, { "module": "@nativescript-community/octane" });
|
|
60
|
+
//#endregion
|
|
61
|
+
export { ScrollView };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { registerElement } from "@nativescript-community/octane";
|
|
2
|
+
import { SVGView } from "@nativescript-community/ui-svg";
|
|
3
|
+
//#region src/svg.native.ts
|
|
4
|
+
registerElement("svgview", SVGView);
|
|
5
|
+
var SVG_DATA_URI = /^data:image\/svg\+xml[;,]/i;
|
|
6
|
+
var SVG_PATH = /\.svg([?#].*)?$/i;
|
|
7
|
+
var EMPTY_SVG = "<svg xmlns=\"http://www.w3.org/2000/svg\"/>";
|
|
8
|
+
/** True when an `src` carries SVG: inline markup, an svg data URI, or an
|
|
9
|
+
* .svg path/URL. Anything else stays on the raster <image> path. */
|
|
10
|
+
function isSvgSrc(src) {
|
|
11
|
+
return src.trimStart().startsWith("<svg") || SVG_DATA_URI.test(src) || SVG_PATH.test(src);
|
|
12
|
+
}
|
|
13
|
+
/** Normalize an svg-shaped src into SVGView's grammar: file/resource paths and
|
|
14
|
+
* markup pass through, data URIs decode to markup, remote URLs fetch to
|
|
15
|
+
* markup (SVGView has no fetch of its own — it awaits promise srcs). */
|
|
16
|
+
function svgSource(src) {
|
|
17
|
+
if (SVG_DATA_URI.test(src)) {
|
|
18
|
+
const comma = src.indexOf(",");
|
|
19
|
+
const body = src.slice(comma + 1);
|
|
20
|
+
if (src.slice(0, comma).endsWith(";base64")) {
|
|
21
|
+
const atob = globalThis.atob;
|
|
22
|
+
if (!atob) return EMPTY_SVG;
|
|
23
|
+
return atob(body);
|
|
24
|
+
}
|
|
25
|
+
return decodeURIComponent(body);
|
|
26
|
+
}
|
|
27
|
+
if (/^https?:\/\//.test(src)) return fetch(src).then((r) => r.ok ? r.text() : EMPTY_SVG).catch(() => EMPTY_SVG);
|
|
28
|
+
return src;
|
|
29
|
+
}
|
|
30
|
+
/** IconGlyph → a full `<svg>` string for SVGView. `svg` path data gets a
|
|
31
|
+
* `<path>` with the requested fill; `markup` wraps inside a viewBox shell
|
|
32
|
+
* with `color`/`fill` set on the root so `currentColor` and default-fill
|
|
33
|
+
* children pick up the tint. */
|
|
34
|
+
function glyphSvgMarkup(glyph, color) {
|
|
35
|
+
const viewBox = glyph.viewBox ?? "0 0 24 24";
|
|
36
|
+
if (glyph.markup) return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}"${color ? ` color="${color}" fill="${color}"` : ""}>${glyph.markup}</svg>`;
|
|
37
|
+
if (glyph.svg) return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}"><path d="${glyph.svg}" fill="${color ?? "currentColor"}"/></svg>`;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { glyphSvgMarkup, isSvgSrc, svgSource };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { cx } from "./ui2.js";
|
|
2
|
+
import { applyEscapeProps } from "./ui3.js";
|
|
3
|
+
import { layoutChildProps } from "./ui5.js";
|
|
4
|
+
import { isSvgSrc, svgSource } from "./ui28.js";
|
|
5
|
+
import { defineUniversalComponent, hookSlots, universalIf, universalPlan, universalProps, universalValue, useMemo } from "@nativescript-community/octane";
|
|
6
|
+
import { ImageSource } from "@nativescript/core";
|
|
7
|
+
//#region src/Image.native.tsrx
|
|
8
|
+
var _hs$ = /* @__PURE__ */ hookSlots(2);
|
|
9
|
+
var _h$0 = /* @__PURE__ */ Symbol(_hs$);
|
|
10
|
+
var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
|
|
11
|
+
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
12
|
+
"kind": "host",
|
|
13
|
+
"type": "svgview",
|
|
14
|
+
"propsSlot": 0
|
|
15
|
+
});
|
|
16
|
+
var __octaneUniversalPlan1 = universalPlan("nativescript", {
|
|
17
|
+
"kind": "host",
|
|
18
|
+
"type": "image",
|
|
19
|
+
"propsSlot": 0
|
|
20
|
+
});
|
|
21
|
+
var __octaneUniversalPlan2 = universalPlan("nativescript", {
|
|
22
|
+
"kind": "slot",
|
|
23
|
+
"slot": 0
|
|
24
|
+
});
|
|
25
|
+
var Image = defineUniversalComponent("nativescript", function Image(props) {
|
|
26
|
+
const svg = useMemo(() => isSvgSrc(props.src) ? svgSource(props.src) : null, [props.src], _h$0);
|
|
27
|
+
const source = useMemo(() => {
|
|
28
|
+
const comma = props.src.indexOf(",");
|
|
29
|
+
if (props.src.startsWith("data:") && comma > 0 && props.src.slice(0, comma).endsWith(";base64")) return ImageSource.fromBase64Sync(props.src.slice(comma + 1));
|
|
30
|
+
return props.src;
|
|
31
|
+
}, [props.src], _h$1);
|
|
32
|
+
return universalValue(__octaneUniversalPlan2, [universalIf(svg != null, () => {
|
|
33
|
+
return universalValue(__octaneUniversalPlan0, [universalProps([
|
|
34
|
+
[
|
|
35
|
+
"set",
|
|
36
|
+
"ref",
|
|
37
|
+
(v) => applyEscapeProps(v, props)
|
|
38
|
+
],
|
|
39
|
+
[
|
|
40
|
+
"set",
|
|
41
|
+
"id",
|
|
42
|
+
props.id
|
|
43
|
+
],
|
|
44
|
+
["spread", layoutChildProps(props)],
|
|
45
|
+
[
|
|
46
|
+
"set",
|
|
47
|
+
"className",
|
|
48
|
+
cx(props.className)
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
"set",
|
|
52
|
+
"style",
|
|
53
|
+
props.style
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
"set",
|
|
57
|
+
"src",
|
|
58
|
+
svg
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"set",
|
|
62
|
+
"stretch",
|
|
63
|
+
"aspectFit"
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
"set",
|
|
67
|
+
"accessibilityLabel",
|
|
68
|
+
props.alt
|
|
69
|
+
]
|
|
70
|
+
])]);
|
|
71
|
+
}, () => {
|
|
72
|
+
return universalValue(__octaneUniversalPlan1, [universalProps([
|
|
73
|
+
[
|
|
74
|
+
"set",
|
|
75
|
+
"ref",
|
|
76
|
+
(v) => applyEscapeProps(v, props)
|
|
77
|
+
],
|
|
78
|
+
[
|
|
79
|
+
"set",
|
|
80
|
+
"id",
|
|
81
|
+
props.id
|
|
82
|
+
],
|
|
83
|
+
["spread", layoutChildProps(props)],
|
|
84
|
+
[
|
|
85
|
+
"set",
|
|
86
|
+
"className",
|
|
87
|
+
cx(props.className)
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
"set",
|
|
91
|
+
"style",
|
|
92
|
+
props.style
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
"set",
|
|
96
|
+
"src",
|
|
97
|
+
source
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
"set",
|
|
101
|
+
"accessibilityLabel",
|
|
102
|
+
props.alt
|
|
103
|
+
]
|
|
104
|
+
])]);
|
|
105
|
+
})]);
|
|
106
|
+
}, { "module": "@nativescript-community/octane" });
|
|
107
|
+
//#endregion
|
|
108
|
+
export { Image };
|
package/dist/native/ui3.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region src/
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
props.children
|
|
18
|
-
]);
|
|
19
|
-
}, { "module": "@nativescript-community/octane" });
|
|
1
|
+
import { isAndroid, isIOS } from "@nativescript/core";
|
|
2
|
+
//#region src/escape-props.native.ts
|
|
3
|
+
/** Apply only the active device's escape bag after the primitive's own props. */
|
|
4
|
+
function applyEscapeProps(view, props) {
|
|
5
|
+
if (!view) return;
|
|
6
|
+
const bag = isIOS ? props.ios : isAndroid ? props.android : void 0;
|
|
7
|
+
if (bag) Object.assign(view, bag);
|
|
8
|
+
}
|
|
9
|
+
/** NativeScript's AccessibilityState is a single enum value, unlike the
|
|
10
|
+
* web's independent ARIA booleans. Priority follows the strongest state. */
|
|
11
|
+
function nativeAccessibilityState(state) {
|
|
12
|
+
if (state?.disabled) return "disabled";
|
|
13
|
+
if (state?.selected) return "selected";
|
|
14
|
+
if (state?.checked === true) return "checked";
|
|
15
|
+
if (state?.checked === false) return "unchecked";
|
|
16
|
+
}
|
|
20
17
|
//#endregion
|
|
21
|
-
export {
|
|
18
|
+
export { applyEscapeProps, nativeAccessibilityState };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Application } from "@nativescript/core";
|
|
2
|
+
import { hookSlots, useSyncExternalStore } from "octane";
|
|
3
|
+
//#region src/theme/colorScheme.native.ts
|
|
4
|
+
function getColorScheme() {
|
|
5
|
+
return Application.primaryWindow?.systemAppearance?.() ?? Application.systemAppearance?.() ?? "light";
|
|
6
|
+
}
|
|
7
|
+
function subscribeSystemScheme(cb) {
|
|
8
|
+
const h = () => cb();
|
|
9
|
+
Application.on("systemAppearanceChanged", h);
|
|
10
|
+
return () => Application.off("systemAppearanceChanged", h);
|
|
11
|
+
}
|
|
12
|
+
/** Reactive system appearance — 'light' | 'dark', re-renders on OS change. */
|
|
13
|
+
function useColorScheme() {
|
|
14
|
+
return useSyncExternalStore(subscribeSystemScheme, getColorScheme, _h$0);
|
|
15
|
+
}
|
|
16
|
+
var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
|
|
17
|
+
//#endregion
|
|
18
|
+
export { getColorScheme, subscribeSystemScheme, useColorScheme };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { cx } from "./ui2.js";
|
|
2
|
+
import { getColorScheme, subscribeSystemScheme } from "./ui30.js";
|
|
3
|
+
import { hookSlots, useSyncExternalStore } from "octane";
|
|
4
|
+
//#region src/theme/theme-scheme.ts
|
|
5
|
+
var preference = "system";
|
|
6
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
var emit = () => listeners.forEach((l) => l());
|
|
8
|
+
/** App-level theme override. 'system' clears the override and follows the OS. */
|
|
9
|
+
function setThemePreference(p) {
|
|
10
|
+
if (p !== preference) {
|
|
11
|
+
preference = p;
|
|
12
|
+
emit();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function getThemePreference() {
|
|
16
|
+
return preference;
|
|
17
|
+
}
|
|
18
|
+
/** The effective scheme: explicit override if set, else system appearance. */
|
|
19
|
+
function getThemeScheme() {
|
|
20
|
+
return preference === "system" ? getColorScheme() : preference;
|
|
21
|
+
}
|
|
22
|
+
function subscribe(cb) {
|
|
23
|
+
listeners.add(cb);
|
|
24
|
+
const offSystem = subscribeSystemScheme(cb);
|
|
25
|
+
return () => {
|
|
26
|
+
listeners.delete(cb);
|
|
27
|
+
offSystem();
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Reactive effective scheme — re-renders on override or OS change. */
|
|
31
|
+
function useThemeScheme() {
|
|
32
|
+
return useSyncExternalStore(subscribe, getThemeScheme, _h$0);
|
|
33
|
+
}
|
|
34
|
+
/** Class string to stamp on independently-mounted roots (portal hosts,
|
|
35
|
+
* overlay/sheet/modal/toast containers): 'ns-dark dark' when effective
|
|
36
|
+
* dark, '' otherwise. Both names because tokens.css publishes both
|
|
37
|
+
* selectors and hosts may render either vocabulary. */
|
|
38
|
+
function themeSchemeClasses() {
|
|
39
|
+
return getThemeScheme() === "dark" ? "ns-dark dark" : "";
|
|
40
|
+
}
|
|
41
|
+
/** Subscribe imperative hosts to effective-scheme changes; returns an
|
|
42
|
+
* unsubscribe. Use for hosts that live outside any render cycle. */
|
|
43
|
+
function onThemeSchemeChange(cb) {
|
|
44
|
+
return subscribe(cb);
|
|
45
|
+
}
|
|
46
|
+
/** Stamp `base + themeSchemeClasses()` onto an imperative host (NS view or
|
|
47
|
+
* DOM element) and keep it live — returns an unsubscribe to call when the
|
|
48
|
+
* host closes. Works on both leaves since both honor `.className`. */
|
|
49
|
+
function applyThemeClasses(view, base) {
|
|
50
|
+
const apply = () => {
|
|
51
|
+
view.className = cx(base, themeSchemeClasses());
|
|
52
|
+
};
|
|
53
|
+
apply();
|
|
54
|
+
return onThemeSchemeChange(apply);
|
|
55
|
+
}
|
|
56
|
+
var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
|
|
57
|
+
//#endregion
|
|
58
|
+
export { applyThemeClasses, getThemePreference, getThemeScheme, onThemeSchemeChange, setThemePreference, themeSchemeClasses, useThemeScheme };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { applyThemeClasses } from "./ui31.js";
|
|
2
|
+
import { createNativeScriptRoot, defineUniversalComponent, hookSlots, universalPlan, universalValue, useEffect, useRef } from "@nativescript-community/octane";
|
|
3
|
+
import { Frame, GridLayout } from "@nativescript/core";
|
|
4
|
+
//#region src/Modal.native.tsrx
|
|
5
|
+
var _hs$ = /* @__PURE__ */ hookSlots(2);
|
|
6
|
+
var _h$0 = /* @__PURE__ */ Symbol(_hs$);
|
|
7
|
+
var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
|
|
8
|
+
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
9
|
+
"kind": "range",
|
|
10
|
+
"children": [{
|
|
11
|
+
"kind": "slot",
|
|
12
|
+
"slot": 0
|
|
13
|
+
}]
|
|
14
|
+
});
|
|
15
|
+
var __octaneUniversalPlan1 = universalPlan("nativescript", {
|
|
16
|
+
"kind": "range",
|
|
17
|
+
"children": []
|
|
18
|
+
});
|
|
19
|
+
var Panel = defineUniversalComponent("nativescript", function Panel(props) {
|
|
20
|
+
return universalValue(__octaneUniversalPlan0, [props.children]);
|
|
21
|
+
}, { "module": "@nativescript-community/octane" });
|
|
22
|
+
var Modal = defineUniversalComponent("nativescript", function Modal(props) {
|
|
23
|
+
const shown = useRef(null, _h$0);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (props.open && !shown.current) {
|
|
26
|
+
const presenter = Frame.topmost()?.currentPage ?? Frame.topmost();
|
|
27
|
+
if (!presenter) return;
|
|
28
|
+
const host = new GridLayout();
|
|
29
|
+
const unbindTheme = applyThemeClasses(host, "vx-modal-host");
|
|
30
|
+
const root = createNativeScriptRoot(host);
|
|
31
|
+
shown.current = {
|
|
32
|
+
host,
|
|
33
|
+
root,
|
|
34
|
+
unbindTheme
|
|
35
|
+
};
|
|
36
|
+
if (props.component) root.render(props.component, props.params ?? {});
|
|
37
|
+
else root.render(Panel, { children: props.children });
|
|
38
|
+
const fullscreen = props.presentation ? props.presentation === "fullscreen" : props.fullscreen ?? true;
|
|
39
|
+
presenter.showModal(host, {
|
|
40
|
+
context: {},
|
|
41
|
+
closeCallback: (result) => {
|
|
42
|
+
shown.current?.unbindTheme?.();
|
|
43
|
+
shown.current = null;
|
|
44
|
+
props.onClose?.(result);
|
|
45
|
+
},
|
|
46
|
+
fullscreen,
|
|
47
|
+
animated: true
|
|
48
|
+
});
|
|
49
|
+
} else if (!props.open && shown.current) {
|
|
50
|
+
const { host } = shown.current;
|
|
51
|
+
shown.current = null;
|
|
52
|
+
host.closeModal();
|
|
53
|
+
}
|
|
54
|
+
}, [props.open], _h$1);
|
|
55
|
+
return universalValue(__octaneUniversalPlan1, []);
|
|
56
|
+
}, { "module": "@nativescript-community/octane" });
|
|
57
|
+
//#endregion
|
|
58
|
+
export { Modal };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { applyThemeClasses } from "./ui31.js";
|
|
2
|
+
import { createNativeScriptRoot } from "@nativescript-community/octane";
|
|
3
|
+
import { Frame, GridLayout } from "@nativescript/core";
|
|
4
|
+
//#region src/modal-service.native.ts
|
|
5
|
+
/** Open a component in its own NativeScript modal root and resolve on close. */
|
|
6
|
+
var openModal = (Component, params, options = {}) => new Promise((resolve, reject) => {
|
|
7
|
+
const presenter = Frame.topmost()?.currentPage ?? Frame.topmost();
|
|
8
|
+
if (!presenter) {
|
|
9
|
+
reject(/* @__PURE__ */ new Error("Cannot open modal before a NativeScript page is active"));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const host = new GridLayout();
|
|
13
|
+
const unbindTheme = applyThemeClasses(host, "vx-modal-host");
|
|
14
|
+
const root = createNativeScriptRoot(host);
|
|
15
|
+
let finished = false;
|
|
16
|
+
const finish = (result) => {
|
|
17
|
+
if (finished) return;
|
|
18
|
+
finished = true;
|
|
19
|
+
unbindTheme();
|
|
20
|
+
root.unmount?.();
|
|
21
|
+
host.removeChildren?.();
|
|
22
|
+
resolve(result);
|
|
23
|
+
};
|
|
24
|
+
const close = (result) => host.closeModal(result);
|
|
25
|
+
root.render(Component, {
|
|
26
|
+
params,
|
|
27
|
+
close
|
|
28
|
+
});
|
|
29
|
+
const fullscreen = options.presentation ? options.presentation === "fullscreen" : options.fullscreen ?? true;
|
|
30
|
+
presenter.showModal(host, {
|
|
31
|
+
context: {},
|
|
32
|
+
closeCallback: finish,
|
|
33
|
+
fullscreen,
|
|
34
|
+
animated: options.animated ?? true
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export { openModal };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { RootLayout, getRootLayout } from "@nativescript/core";
|
|
2
|
+
//#region src/root-layout.native.ts
|
|
3
|
+
var registry = [];
|
|
4
|
+
/** Called by the Screen leaf's <rootlayout> onLoaded/onUnloaded. */
|
|
5
|
+
function registerRootLayout(rl) {
|
|
6
|
+
if (rl && !registry.includes(rl)) registry.push(rl);
|
|
7
|
+
}
|
|
8
|
+
function unregisterRootLayout(rl) {
|
|
9
|
+
const i = rl ? registry.indexOf(rl) : -1;
|
|
10
|
+
if (i >= 0) registry.splice(i, 1);
|
|
11
|
+
}
|
|
12
|
+
/** The most recently mounted rootlayout — the top of the push stack. For
|
|
13
|
+
* imperative services (toast, sheet) there is no invoking component to
|
|
14
|
+
* walk from; last-mounted is the pushed page when one exists. Caveat: tabs
|
|
15
|
+
* keep visited panes mounted — last is the newest, not the visible tab. */
|
|
16
|
+
function topRootLayout() {
|
|
17
|
+
return registry[registry.length - 1] ?? getRootLayout();
|
|
18
|
+
}
|
|
19
|
+
/** Resolve the RootLayout enclosing `view` by walking the native parent
|
|
20
|
+
* chain — the screen shell is a RootLayout (Screen.native), so the first
|
|
21
|
+
* RootLayout ancestor IS the current page's overlay host. Falls back to
|
|
22
|
+
* the top registry entry when the component renders outside any Screen. */
|
|
23
|
+
function rootLayoutFor(view) {
|
|
24
|
+
for (let v = view?.parent; v; v = v.parent) if (v instanceof RootLayout) return v;
|
|
25
|
+
return topRootLayout();
|
|
26
|
+
}
|
|
27
|
+
/** Search every registered rootlayout for a view by id — overlays/sheets/
|
|
28
|
+
* toasts land on different rootlayouts depending on which screen's shell
|
|
29
|
+
* mounted last. */
|
|
30
|
+
function findInRootLayouts(id) {
|
|
31
|
+
const walk = (view) => {
|
|
32
|
+
if (!view) return null;
|
|
33
|
+
if (view.id === id) return view;
|
|
34
|
+
let hit = null;
|
|
35
|
+
view.eachChildView?.((c) => {
|
|
36
|
+
const found = walk(c);
|
|
37
|
+
if (found) {
|
|
38
|
+
hit = found;
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
});
|
|
43
|
+
return hit;
|
|
44
|
+
};
|
|
45
|
+
for (let i = registry.length - 1; i >= 0; i--) {
|
|
46
|
+
const hit = walk(registry[i]);
|
|
47
|
+
if (hit) return hit;
|
|
48
|
+
}
|
|
49
|
+
const rl = getRootLayout();
|
|
50
|
+
return rl ? walk(rl) : null;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { findInRootLayouts, registerRootLayout, rootLayoutFor, topRootLayout, unregisterRootLayout };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { cx } from "./ui2.js";
|
|
2
|
+
import { applyThemeClasses } from "./ui31.js";
|
|
3
|
+
import { rootLayoutFor } from "./ui34.js";
|
|
4
|
+
import { createNativeScriptRoot, defineUniversalComponent, hookSlots, universalPlan, universalValue, useEffect, useRef } from "@nativescript-community/octane";
|
|
5
|
+
import { GridLayout, isAndroid, isIOS } from "@nativescript/core";
|
|
6
|
+
//#region src/Overlay.native.tsrx
|
|
7
|
+
var _hs$ = /* @__PURE__ */ hookSlots(4);
|
|
8
|
+
var _h$0 = /* @__PURE__ */ Symbol(_hs$);
|
|
9
|
+
var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
|
|
10
|
+
var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
|
|
11
|
+
var _h$3 = /* @__PURE__ */ Symbol(_hs$ + 3);
|
|
12
|
+
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
13
|
+
"kind": "range",
|
|
14
|
+
"children": [{
|
|
15
|
+
"kind": "slot",
|
|
16
|
+
"slot": 0
|
|
17
|
+
}]
|
|
18
|
+
});
|
|
19
|
+
var __octaneUniversalPlan1 = universalPlan("nativescript", {
|
|
20
|
+
"kind": "host",
|
|
21
|
+
"type": "stacklayout",
|
|
22
|
+
"bindings": [["ref", 0], ["style", 1]]
|
|
23
|
+
});
|
|
24
|
+
var OverlayBody = defineUniversalComponent("nativescript", function OverlayBody(props) {
|
|
25
|
+
return universalValue(__octaneUniversalPlan0, [props.children]);
|
|
26
|
+
}, { "module": "@nativescript-community/octane" });
|
|
27
|
+
var Overlay = defineUniversalComponent("nativescript", function Overlay(props) {
|
|
28
|
+
const shown = useRef(null, _h$0);
|
|
29
|
+
const hostView = useRef(null, _h$1);
|
|
30
|
+
const dismiss = useRef(props.onDismiss, _h$2);
|
|
31
|
+
dismiss.current = props.onDismiss;
|
|
32
|
+
const rootLayout = () => rootLayoutFor(hostView.current);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const current = shown.current;
|
|
35
|
+
if (!props.open) {
|
|
36
|
+
if (!current) return;
|
|
37
|
+
current.dismissOnClose = false;
|
|
38
|
+
shown.current = null;
|
|
39
|
+
const rl = rootLayout();
|
|
40
|
+
if (rl && rl?.hasChild?.(current.host)) rl.close(current.host).then(() => current.root.unmount?.(), (error) => {
|
|
41
|
+
console.error("[Overlay] close failed", error);
|
|
42
|
+
current.root.unmount?.();
|
|
43
|
+
});
|
|
44
|
+
else current.root.unmount?.();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (current) {
|
|
48
|
+
current.root.render(OverlayBody, { children: props.children });
|
|
49
|
+
current.unbindTheme = applyThemeClasses(current.host, cx("vx-overlay-host", props.className));
|
|
50
|
+
if (props.style) Object.assign(current.host.style, props.style);
|
|
51
|
+
Object.assign(current.host, isIOS ? props.ios : isAndroid ? props.android : void 0);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const rl = rootLayout();
|
|
55
|
+
if (!rl) return;
|
|
56
|
+
const host = new GridLayout();
|
|
57
|
+
const unbindTheme = applyThemeClasses(host, cx("vx-overlay-host", props.className));
|
|
58
|
+
host.horizontalAlignment = "stretch";
|
|
59
|
+
host.verticalAlignment = "stretch";
|
|
60
|
+
if (props.style) Object.assign(host.style, props.style);
|
|
61
|
+
Object.assign(host, isIOS ? props.ios : isAndroid ? props.android : void 0);
|
|
62
|
+
const root = createNativeScriptRoot(host);
|
|
63
|
+
const opened = {
|
|
64
|
+
host,
|
|
65
|
+
root,
|
|
66
|
+
dismissOnClose: true,
|
|
67
|
+
unbindTheme
|
|
68
|
+
};
|
|
69
|
+
shown.current = opened;
|
|
70
|
+
root.render(OverlayBody, { children: props.children });
|
|
71
|
+
host.on("closed", () => {
|
|
72
|
+
if (shown.current === opened) shown.current = null;
|
|
73
|
+
opened.unbindTheme?.();
|
|
74
|
+
root.unmount?.();
|
|
75
|
+
if (opened.dismissOnClose) dismiss.current?.();
|
|
76
|
+
});
|
|
77
|
+
const open = () => rl.open(host, props.shadeCover ? { shadeCover: {
|
|
78
|
+
opacity: .45,
|
|
79
|
+
color: "#000000",
|
|
80
|
+
tapToClose: true
|
|
81
|
+
} } : {}).catch((error) => {
|
|
82
|
+
if (shown.current === opened) shown.current = null;
|
|
83
|
+
console.error("[Overlay] open failed", error);
|
|
84
|
+
root.unmount?.();
|
|
85
|
+
});
|
|
86
|
+
if (rl.hasChild?.(host)) rl.close(host).then(open, (error) => console.error("[Overlay] stale host close failed", error));
|
|
87
|
+
else open();
|
|
88
|
+
}, [
|
|
89
|
+
props.open,
|
|
90
|
+
props.children,
|
|
91
|
+
props.shadeCover,
|
|
92
|
+
props.className,
|
|
93
|
+
props.style,
|
|
94
|
+
props.ios,
|
|
95
|
+
props.android
|
|
96
|
+
], _h$3);
|
|
97
|
+
return universalValue(__octaneUniversalPlan1, [(v) => {
|
|
98
|
+
hostView.current = v;
|
|
99
|
+
}, {
|
|
100
|
+
width: 0,
|
|
101
|
+
height: 0
|
|
102
|
+
}]);
|
|
103
|
+
}, { "module": "@nativescript-community/octane" });
|
|
104
|
+
//#endregion
|
|
105
|
+
export { Overlay };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { isAndroid, isIOS } from "@nativescript/core";
|
|
2
|
+
//#region src/platformProps.native.ts
|
|
3
|
+
/** Apply the matching native escape-hatch bag after the primitive's props. */
|
|
4
|
+
function applyNativeProps(el, props) {
|
|
5
|
+
if (!el) return;
|
|
6
|
+
const bag = isIOS ? props.ios : isAndroid ? props.android : void 0;
|
|
7
|
+
if (bag) Object.assign(el, bag);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { applyNativeProps };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/popover-position.ts
|
|
2
|
+
var opposite = {
|
|
3
|
+
top: "bottom",
|
|
4
|
+
bottom: "top",
|
|
5
|
+
left: "right",
|
|
6
|
+
right: "left"
|
|
7
|
+
};
|
|
8
|
+
/** Place beside the anchor, flip once when the requested side overflows, then clamp. */
|
|
9
|
+
function positionPopover(anchor, panel, viewport, requested = "bottom", gap = 8) {
|
|
10
|
+
const at = (placement) => {
|
|
11
|
+
switch (placement) {
|
|
12
|
+
case "top": return {
|
|
13
|
+
left: anchor.left,
|
|
14
|
+
top: anchor.top - panel.height - gap
|
|
15
|
+
};
|
|
16
|
+
case "bottom": return {
|
|
17
|
+
left: anchor.left,
|
|
18
|
+
top: anchor.top + anchor.height + gap
|
|
19
|
+
};
|
|
20
|
+
case "left": return {
|
|
21
|
+
left: anchor.left - panel.width - gap,
|
|
22
|
+
top: anchor.top
|
|
23
|
+
};
|
|
24
|
+
case "right": return {
|
|
25
|
+
left: anchor.left + anchor.width + gap,
|
|
26
|
+
top: anchor.top
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
throw new Error(`Unknown popover placement: ${placement}`);
|
|
30
|
+
};
|
|
31
|
+
const fits = (position) => position.left >= viewport.left && position.top >= viewport.top && position.left + panel.width <= viewport.left + viewport.width && position.top + panel.height <= viewport.top + viewport.height;
|
|
32
|
+
const preferred = at(requested);
|
|
33
|
+
const placement = fits(preferred) ? requested : opposite[requested];
|
|
34
|
+
const raw = placement === requested ? preferred : at(placement);
|
|
35
|
+
const maxLeft = Math.max(viewport.left, viewport.left + viewport.width - panel.width);
|
|
36
|
+
const maxTop = Math.max(viewport.top, viewport.top + viewport.height - panel.height);
|
|
37
|
+
return {
|
|
38
|
+
left: Math.min(maxLeft, Math.max(viewport.left, raw.left)),
|
|
39
|
+
top: Math.min(maxTop, Math.max(viewport.top, raw.top)),
|
|
40
|
+
placement
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { positionPopover };
|