@octane-xplat/ui 0.2.1 → 0.3.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.
Files changed (94) hide show
  1. package/dist/native/octane-client-build.json +1 -1
  2. package/dist/native/ui.js +40 -19
  3. package/dist/native/ui10.js +19 -48
  4. package/dist/native/ui11.js +118 -56
  5. package/dist/native/ui12.js +114 -16
  6. package/dist/native/ui13.js +54 -18
  7. package/dist/native/ui14.js +76 -13
  8. package/dist/native/ui15.js +128 -18
  9. package/dist/native/ui16.js +48 -136
  10. package/dist/native/ui17.js +42 -19
  11. package/dist/native/ui18.js +50 -9
  12. package/dist/native/ui19.js +34 -12
  13. package/dist/native/ui2.js +10 -48
  14. package/dist/native/ui20.js +17 -0
  15. package/dist/native/ui21.js +93 -0
  16. package/dist/native/ui22.js +124 -0
  17. package/dist/native/ui23.js +103 -0
  18. package/dist/native/ui24.js +58 -0
  19. package/dist/native/ui25.js +19 -0
  20. package/dist/native/ui26.js +27 -0
  21. package/dist/native/ui27.js +35 -0
  22. package/dist/native/ui28.js +146 -0
  23. package/dist/native/ui29.js +28 -0
  24. package/dist/native/ui3.js +17 -20
  25. package/dist/native/ui30.js +35 -0
  26. package/dist/native/ui31.js +39 -0
  27. package/dist/native/ui32.js +70 -0
  28. package/dist/native/ui33.js +30 -0
  29. package/dist/native/ui34.js +10 -0
  30. package/dist/native/ui35.js +27 -0
  31. package/dist/native/ui36.js +34 -0
  32. package/dist/native/ui37.js +17 -0
  33. package/dist/native/ui38.js +68 -0
  34. package/dist/native/ui39.js +33 -0
  35. package/dist/native/ui4.js +21 -48
  36. package/dist/native/ui40.js +14 -0
  37. package/dist/native/ui41.js +104 -0
  38. package/dist/native/ui42.js +148 -0
  39. package/dist/native/ui43.js +22 -0
  40. package/dist/native/ui44.js +8 -0
  41. package/dist/native/ui5.js +70 -27
  42. package/dist/native/ui6.js +36 -20
  43. package/dist/native/ui7.js +24 -61
  44. package/dist/native/ui8.js +16 -18
  45. package/dist/native/ui9.js +16 -13
  46. package/dist/web/octane-client-build.json +1 -1
  47. package/dist/web/ui.js +40 -19
  48. package/dist/web/ui10.js +187 -31
  49. package/dist/web/ui11.js +419 -53
  50. package/dist/web/ui12.js +83 -15
  51. package/dist/web/ui13.js +107 -19
  52. package/dist/web/ui14.js +98 -18
  53. package/dist/web/ui15.js +83 -47
  54. package/dist/web/ui16.js +100 -93
  55. package/dist/web/ui17.js +36 -22
  56. package/dist/web/ui18.js +29 -15
  57. package/dist/web/ui19.js +9 -7
  58. package/dist/web/ui2.js +15 -103
  59. package/dist/web/ui20.js +114 -0
  60. package/dist/web/ui21.js +82 -0
  61. package/dist/web/ui22.js +68 -0
  62. package/dist/web/ui23.js +57 -0
  63. package/dist/web/ui24.js +16 -0
  64. package/dist/web/ui25.js +22 -0
  65. package/dist/web/ui26.js +39 -0
  66. package/dist/web/ui27.js +127 -0
  67. package/dist/web/ui28.js +112 -0
  68. package/dist/web/ui29.js +108 -0
  69. package/dist/web/ui3.js +19 -27
  70. package/dist/web/ui30.js +43 -0
  71. package/dist/web/ui31.js +42 -0
  72. package/dist/web/ui32.js +77 -0
  73. package/dist/web/ui33.js +43 -0
  74. package/dist/web/ui34.js +67 -0
  75. package/dist/web/ui35.js +9 -0
  76. package/dist/web/ui36.js +45 -0
  77. package/dist/web/ui37.js +47 -0
  78. package/dist/web/ui38.js +17 -0
  79. package/dist/web/ui39.js +100 -0
  80. package/dist/web/ui4.js +145 -17
  81. package/dist/web/ui40.js +41 -0
  82. package/dist/web/ui41.js +17 -0
  83. package/dist/web/ui42.js +9 -0
  84. package/dist/web/ui43.js +22 -0
  85. package/dist/web/ui44.js +8 -0
  86. package/dist/web/ui5.js +54 -52
  87. package/dist/web/ui6.js +43 -16
  88. package/dist/web/ui7.js +29 -46
  89. package/dist/web/ui8.js +29 -18
  90. package/dist/web/ui9.js +24 -16
  91. package/package.json +6 -3
  92. package/src/theme/tokens.css +166 -0
  93. package/types/index.d.ts +108 -1
  94. package/types/props.d.ts +333 -8
@@ -0,0 +1,68 @@
1
+ import { cx } from "./ui19.js";
2
+ import { __s, bag1, bag3, clone, componentSlot, createRoot, ifBlock, template } from "octane";
3
+ import { childTextHoleUpdate } from "octane/internal/client";
4
+ //#region src/toast.web.tsrx
5
+ var _t$0 = /* @__PURE__ */ template("<div class=\"vx-toast\"></div>");
6
+ function __then$0(__props, __s, __extra) {
7
+ const props = __extra[0];
8
+ let _b = __s.slots[0];
9
+ if (_b === void 0) {
10
+ let _m0;
11
+ const _root = clone(_t$0);
12
+ _m0 = _root;
13
+ _b = bag3(__s, _root, _m0, null, void 0);
14
+ }
15
+ {
16
+ const _v = props.content;
17
+ _b.b = childTextHoleUpdate(__s, 1, _b.a, _v, _b.b, _b.c);
18
+ _b.c = _v;
19
+ }
20
+ }
21
+ function __else$2(__props, __s, __extra) {
22
+ const Component = __extra[0].content;
23
+ let _b = __s.slots[0];
24
+ if (_b === void 0) {
25
+ let _m0;
26
+ const _root = clone(_t$0);
27
+ _m0 = _root;
28
+ _b = bag1(__s, _root, _m0);
29
+ }
30
+ componentSlot(__s, 1, _b.a, Component, {}, void 0, void 0, void 0, void 0, void 0, "c:1427a872");
31
+ }
32
+ var queue = [];
33
+ var active = false;
34
+ var ToastBody = /* @__PURE__ */ __s(function ToastBody(props, __s, __extra) {
35
+ const __block = __s.block;
36
+ ifBlock(__s, 0, __block.parentNode, typeof props.content === "string", __then$0, __else$2, __block.endMarker, [props]);
37
+ });
38
+ function applyWebProps(host, props) {
39
+ if (!props) return;
40
+ for (const [key, value] of Object.entries(props)) if (key.includes("-")) host.setAttribute(key, String(value));
41
+ else host[key] = value;
42
+ }
43
+ function showNext() {
44
+ if (active || queue.length === 0) return;
45
+ active = true;
46
+ const entry = queue.shift();
47
+ const host = document.createElement("div");
48
+ host.className = cx("vx-toast-host", entry.options.position === "top" ? "vx-toast-top" : "vx-toast-bottom");
49
+ applyWebProps(host, entry.options.web);
50
+ document.body.appendChild(host);
51
+ const root = createRoot(host);
52
+ root.render(ToastBody, { content: entry.content });
53
+ setTimeout(() => {
54
+ root.unmount();
55
+ host.remove();
56
+ active = false;
57
+ showNext();
58
+ }, Math.max(0, entry.options.duration ?? 3e3));
59
+ }
60
+ function showToast(content, options = {}) {
61
+ queue.push({
62
+ content,
63
+ options
64
+ });
65
+ showNext();
66
+ }
67
+ //#endregion
68
+ export { showToast };
@@ -0,0 +1,57 @@
1
+ import { hookSlots, useRef } from "octane";
2
+ //#region src/anim.web.tsrx
3
+ var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
4
+ function createAnimated(initial, prop) {
5
+ let el = null;
6
+ let current = initial;
7
+ let raf = 0;
8
+ const apply = (v) => {
9
+ current = v;
10
+ if (el) el.style.transform = `translateX(${v}px)`;
11
+ };
12
+ const run = (step) => {
13
+ cancelAnimationFrame(raf);
14
+ const start = Date.now();
15
+ const tick = () => {
16
+ const v = step(Date.now() - start);
17
+ if (v === null) return;
18
+ apply(v);
19
+ raf = requestAnimationFrame(tick);
20
+ };
21
+ raf = requestAnimationFrame(tick);
22
+ };
23
+ return {
24
+ get value() {
25
+ return current;
26
+ },
27
+ bind(e) {
28
+ el = e;
29
+ if (el) el.style.transform = `translateX(${current}px)`;
30
+ },
31
+ to(target, opts) {
32
+ const dur = opts?.duration ?? 300;
33
+ const from = current;
34
+ run((t) => t >= dur ? (apply(target), null) : from + (target - from) * (t / dur));
35
+ },
36
+ spring(target, opts) {
37
+ const damping = opts?.damping ?? 14, stiffness = opts?.stiffness ?? 120;
38
+ let v = 0, x = current;
39
+ run(() => {
40
+ const dt = 1 / 60;
41
+ v += (-stiffness * (x - target) - damping * v) * dt;
42
+ x += v * dt;
43
+ return Math.abs(v) < .5 && Math.abs(x - target) < .5 ? (apply(target), null) : x;
44
+ });
45
+ },
46
+ stop() {
47
+ cancelAnimationFrame(raf);
48
+ }
49
+ };
50
+ }
51
+ function useAnimation(initial = 0, prop = "translateX") {
52
+ const c = useRef(null, _h$0);
53
+ if (!c.current) c.current = createAnimated(initial, prop);
54
+ return c.current;
55
+ }
56
+ //#endregion
57
+ export { useAnimation };
@@ -0,0 +1,16 @@
1
+ import { hookSlots, useSyncExternalStore } from "octane";
2
+ //#region src/theme/colorScheme.web.tsrx
3
+ var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
4
+ function getColorScheme() {
5
+ return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
6
+ }
7
+ function subscribe(cb) {
8
+ const mq = matchMedia("(prefers-color-scheme: dark)");
9
+ mq.addEventListener("change", cb);
10
+ return () => mq.removeEventListener("change", cb);
11
+ }
12
+ function useColorScheme() {
13
+ return useSyncExternalStore(subscribe, getColorScheme, _h$0);
14
+ }
15
+ //#endregion
16
+ export { getColorScheme, useColorScheme };
@@ -0,0 +1,22 @@
1
+ import { componentSlot } from "octane";
2
+ //#region src/styled.web.tsrx
3
+ function styled(Base, def) {
4
+ function Styled(props, __s, __extra) {
5
+ const __block = __s.block;
6
+ const cls = [def.base];
7
+ const rest = { ...props };
8
+ for (const k of Object.keys(def.variants ?? {})) {
9
+ if (props[k]) cls.push(def.variants[k]);
10
+ delete rest[k];
11
+ }
12
+ if (props.className) cls.push(props.className);
13
+ if (__s.block.pending && !__s.block.crossRenderUpdate) return;
14
+ componentSlot(__s, 0, __block.parentNode, Base, {
15
+ ...rest,
16
+ "className": cls
17
+ }, __block.endMarker, void 0, void 0, true, void 0, "c:5d3d2b58");
18
+ }
19
+ return Styled;
20
+ }
21
+ //#endregion
22
+ export { styled };
@@ -0,0 +1,39 @@
1
+ import { applyEscapeProps } from "./ui2.js";
2
+ import { __s, bag6, clone, queueRefAttach, queueRefDetach, setStyle, template } from "octane";
3
+ import { childTextHoleUpdate, replaceRef, updateFreshClassName } from "octane/internal/client";
4
+ //#region src/Screen.web.tsrx
5
+ var _t$0 = /* @__PURE__ */ template("<div></div>");
6
+ var _rm$1 = [
7
+ "r",
8
+ "b",
9
+ "a"
10
+ ];
11
+ var Screen = /* @__PURE__ */ __s(function Screen(props, __s, __extra) {
12
+ let _b = __s.slots[0];
13
+ if (_b === void 0) {
14
+ let _m0, _m1;
15
+ const _root = clone(_t$0);
16
+ queueRefAttach(__s, _m1 = (e) => applyEscapeProps(e, props), _m0 = _root);
17
+ (__s.cleanups ??= []).push(() => _b && queueRefDetach(_b.b, _b.a));
18
+ _b = bag6(__s, _root, _m0, _m1, void 0, void 0, null, void 0);
19
+ __s.refFields = _rm$1;
20
+ } else {
21
+ const _r = (e) => applyEscapeProps(e, props);
22
+ if (_r !== _b.b) _b.b = replaceRef(__s, _b.b, _r, _b.a);
23
+ }
24
+ _b.c = updateFreshClassName(["vx-screen", props.className], _b.c, _b.a);
25
+ {
26
+ const _v = props.style;
27
+ if (_b.d !== _v) {
28
+ setStyle(_b.a, _v, _b.d);
29
+ _b.d = _v;
30
+ }
31
+ }
32
+ {
33
+ const _v = props.children;
34
+ _b.e = childTextHoleUpdate(__s, 1, _b.a, _v, _b.e, _b.f);
35
+ _b.f = _v;
36
+ }
37
+ });
38
+ //#endregion
39
+ export { Screen };
@@ -0,0 +1,127 @@
1
+ //#region src/route-table.ts
2
+ var EXT = /\.(tsrx|tsx|ts|mts|cts|js|mjs|cjs|jsx)$/;
3
+ var SUFFIX = /\.(web|native|ios|android)$/;
4
+ var PARAM = /^\[(.+)\]$/;
5
+ /** Component pick rule for route/layout modules: default export, then a
6
+ * `screen` named export, then a single function export. Route files use
7
+ * named exports (decision #13) — a lone component is unambiguous. */
8
+ function pick(mod, file) {
9
+ if (typeof mod?.default === "function") return mod.default;
10
+ if (typeof mod?.screen === "function") return mod.screen;
11
+ const fns = Object.keys(mod ?? {}).filter((k) => typeof mod[k] === "function");
12
+ if (fns.length === 1) return mod[fns[0]];
13
+ console.warn("[octane-xplat] route file " + file + (fns.length ? ` has ${fns.length} component-shaped exports (${fns.join(", ")}) — add a default or 'screen' export` : " has no component export") + " — skipped");
14
+ }
15
+ function deriveRouteManifest(files, prefer, dir = "app") {
16
+ const prefix = dir.replace(/^\.?\/?/, "").replace(/\/+$/, "") + "/";
17
+ const seen = /* @__PURE__ */ new Map();
18
+ const layoutRank = /* @__PURE__ */ new Map();
19
+ const layouts = {};
20
+ const warned = /* @__PURE__ */ new Set();
21
+ for (const key of Object.keys(files).sort()) {
22
+ let rel = key.replace(/^\.?\//, "");
23
+ if (rel.startsWith(prefix)) rel = rel.slice(prefix.length);
24
+ rel = rel.replace(EXT, "");
25
+ const parts = rel.split("/");
26
+ let base = parts[parts.length - 1];
27
+ const sm = SUFFIX.exec(base);
28
+ const suffix = sm?.[1];
29
+ if (sm) base = base.slice(0, base.length - sm[0].length);
30
+ if (suffix && !prefer.includes(suffix)) continue;
31
+ const rank = suffix ? prefer.indexOf(suffix) : prefer.length;
32
+ if (base === "_layout") {
33
+ const d = parts.slice(0, -1).join("/");
34
+ const prev = layoutRank.get(d);
35
+ if (prev !== void 0 && prev <= rank) continue;
36
+ const component = pick(files[key], key);
37
+ if (component) {
38
+ layouts[d] = component;
39
+ layoutRank.set(d, rank);
40
+ }
41
+ continue;
42
+ }
43
+ const segs = parts.slice(0, -1).concat(base);
44
+ if (segs[segs.length - 1] === "index") segs.pop();
45
+ const segments = segs.map((s) => {
46
+ const p = PARAM.exec(s);
47
+ return p ? ":" + p[1] : s;
48
+ });
49
+ const name = segments.join("/") || "index";
50
+ const meta = {
51
+ name,
52
+ segments,
53
+ params: segments.filter((s) => s.startsWith(":")).map((s) => s.slice(1)),
54
+ file: key
55
+ };
56
+ const prev = seen.get(name);
57
+ if (prev && prev.rank <= rank) {
58
+ if (prev.rank === rank && !warned.has(name)) {
59
+ warned.add(name);
60
+ console.warn(`[octane-xplat] route '${name}' is defined by both ${prev.meta.file} and ${key} — keeping ${prev.meta.file}`);
61
+ }
62
+ continue;
63
+ }
64
+ const component = pick(files[key], key);
65
+ if (component) seen.set(name, {
66
+ rank,
67
+ meta,
68
+ component
69
+ });
70
+ }
71
+ const screens = {};
72
+ const routes = [];
73
+ for (const { meta, component } of seen.values()) {
74
+ screens[meta.name] = component;
75
+ routes.push(meta);
76
+ }
77
+ routes.sort((a, b) => b.segments.reduce((n, s) => n + (s.startsWith(":") ? 1 : 2), 0) - a.segments.reduce((n, s) => n + (s.startsWith(":") ? 1 : 2), 0) || a.name.localeCompare(b.name));
78
+ return {
79
+ screens,
80
+ routes,
81
+ layouts
82
+ };
83
+ }
84
+ /** Match URL path segments against a manifest — returns the winning meta
85
+ * plus extracted params, or null. First hit wins (routes are pre-sorted
86
+ * by specificity). */
87
+ function matchRoute(routes, segs) {
88
+ for (const meta of routes) {
89
+ if (meta.segments.length !== segs.length) continue;
90
+ const params = {};
91
+ let ok = true;
92
+ for (let i = 0; i < segs.length; i++) {
93
+ const p = meta.segments[i];
94
+ if (p.startsWith(":")) params[p.slice(1)] = decodeURIComponent(segs[i]);
95
+ else if (p !== segs[i]) {
96
+ ok = false;
97
+ break;
98
+ }
99
+ }
100
+ if (ok) return {
101
+ meta,
102
+ params
103
+ };
104
+ }
105
+ return null;
106
+ }
107
+ /** Serialize a Route to a URL path (no origin): manifest routes substitute
108
+ * `:param` segments from params (leftover params → query string);
109
+ * non-manifest names keep the legacy `/<stack>/<name>?params` shape. */
110
+ function buildRoutePath(routes, r) {
111
+ const meta = routes.find((m) => m.name === r.name);
112
+ let segs;
113
+ let rest = r.params;
114
+ if (meta) {
115
+ segs = meta.segments.map((s) => {
116
+ if (!s.startsWith(":")) return s;
117
+ const v = r.params[s.slice(1)];
118
+ if (v === void 0) console.warn(`[octane-xplat] route '${r.name}' pushed without path param ${s}`);
119
+ return encodeURIComponent(String(v ?? ""));
120
+ });
121
+ rest = Object.fromEntries(Object.entries(r.params).filter(([k]) => !meta.params.includes(k)));
122
+ } else segs = [r.name];
123
+ const q = Object.entries(rest).map(([k, v]) => encodeURIComponent(k) + "=" + encodeURIComponent(String(v))).join("&");
124
+ return (((r.stack === "root" ? "" : "/" + r.stack) + "/" + segs.join("/")).replace(/\/+$/, "") || "/") + (q ? "?" + q : "");
125
+ }
126
+ //#endregion
127
+ export { buildRoutePath, deriveRouteManifest, matchRoute };
@@ -0,0 +1,112 @@
1
+ import { buildRoutePath, matchRoute } from "./ui27.js";
2
+ import { hookSlots, useSyncExternalStore } from "octane";
3
+ //#region src/route.web.ts
4
+ var screens = {};
5
+ var routes = [];
6
+ /** Register the app's name → screen table. On web the table feeds
7
+ * `screenFor` — the fallback outlet resolution in Tabs when no
8
+ * `resolveScreen` prop is given; on native `pushRoute` resolves
9
+ * `route.name` through it. `manifest` (from deriveRouteManifest) enables
10
+ * path-param matching — call once from the shared routes module. */
11
+ function registerScreens(table, manifest) {
12
+ screens = table;
13
+ routes = manifest ?? [];
14
+ if (current !== void 0) {
15
+ current = parse();
16
+ emit();
17
+ }
18
+ }
19
+ /** One-call registration for route-dir apps — screens + URL patterns +
20
+ * layouts all come from deriveRouteManifest. */
21
+ function registerRoutes(manifest) {
22
+ registerScreens(manifest.screens, manifest.routes);
23
+ }
24
+ function screenFor(name) {
25
+ return screens[name];
26
+ }
27
+ var listeners = /* @__PURE__ */ new Set();
28
+ var current;
29
+ function queryParams() {
30
+ const params = {};
31
+ new URLSearchParams(location.search).forEach((v, k) => params[k] = v);
32
+ return params;
33
+ }
34
+ function parse() {
35
+ const segs = location.pathname.split("/").filter(Boolean);
36
+ if (!segs.length) return null;
37
+ const query = queryParams();
38
+ const root = matchRoute(routes, segs);
39
+ if (root) return {
40
+ stack: "root",
41
+ name: root.meta.name,
42
+ params: {
43
+ ...query,
44
+ ...root.params
45
+ }
46
+ };
47
+ if (segs.length > 1) {
48
+ const named = matchRoute(routes, segs.slice(1));
49
+ if (named) return {
50
+ stack: segs[0],
51
+ name: named.meta.name,
52
+ params: {
53
+ ...query,
54
+ ...named.params
55
+ }
56
+ };
57
+ return {
58
+ stack: segs[0],
59
+ name: segs[1],
60
+ params: query
61
+ };
62
+ }
63
+ return {
64
+ stack: "root",
65
+ name: segs[0],
66
+ params: query
67
+ };
68
+ }
69
+ function read() {
70
+ if (current === void 0) current = parse();
71
+ return current;
72
+ }
73
+ function emit() {
74
+ listeners.forEach((l) => l());
75
+ }
76
+ function pushRoute(r) {
77
+ history.pushState(null, "", buildRoutePath(routes, r));
78
+ current = r;
79
+ emit();
80
+ }
81
+ /** Web history is one linear stack — back pops whatever route is current;
82
+ * per-stack pops aren't expressible, so `stack` is accepted for parity
83
+ * and ignored. */
84
+ function popRoute(_stack = "root") {
85
+ history.back();
86
+ }
87
+ window.addEventListener("popstate", () => {
88
+ current = parse();
89
+ emit();
90
+ });
91
+ /** Current route if it targets `stack`, else null. */
92
+ function routeFor(stack) {
93
+ const c = read();
94
+ return c && c.stack === stack ? c : null;
95
+ }
96
+ /** The route active at boot — for deep-link tab selection. */
97
+ function currentRoute() {
98
+ return read();
99
+ }
100
+ /** URL for a Route — Link's href and shareable-path helper. */
101
+ function hrefFor(r) {
102
+ return buildRoutePath(routes, r);
103
+ }
104
+ function useRoute(stack) {
105
+ return useSyncExternalStore((cb) => {
106
+ listeners.add(cb);
107
+ return () => listeners.delete(cb);
108
+ }, () => routeFor(stack), _h$0);
109
+ }
110
+ var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
111
+ //#endregion
112
+ export { currentRoute, hrefFor, popRoute, pushRoute, registerRoutes, registerScreens, routeFor, screenFor, useRoute };
@@ -0,0 +1,108 @@
1
+ import { screenFor, useRoute } from "./ui28.js";
2
+ import { __s, bag3, bag4, bag9, child, clone, createScopedValue, delegateEvents, forBlock, hookSlots, ifBlock, setEventHandler, setStyle, sibling, template, useState, withSlot } from "octane";
3
+ import { bindSignalAttribute, bindSignalChild, childTextHoleUpdate, createElementFromConfig, enableSignalBindings, updateFreshClassName } from "octane/internal/client";
4
+ //#region src/Tabs.web.tsrx
5
+ enableSignalBindings(1, true);
6
+ delegateEvents(["click"]);
7
+ var _t$0 = /* @__PURE__ */ template("<div class=\"vx-route\"></div>");
8
+ var _t$1 = /* @__PURE__ */ template("<button></button>");
9
+ var _t$2 = /* @__PURE__ */ template("<div><div class=\"vx-tabbar\"><!></div><div class=\"vx-tabpane\"></div></div>");
10
+ var _hs$ = /* @__PURE__ */ hookSlots(4);
11
+ var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
12
+ var _h$2 = /* @__PURE__ */ Symbol(_hs$ + 2);
13
+ function __then$0(__props, __s, __extra) {
14
+ const routed = __extra[4];
15
+ let _b = __s.slots[0];
16
+ if (_b === void 0) {
17
+ let _m0;
18
+ const _root = clone(_t$0);
19
+ _m0 = _root;
20
+ _b = bag3(__s, _root, _m0, null, void 0);
21
+ }
22
+ {
23
+ const _v = routed;
24
+ _b.b = childTextHoleUpdate(__s, 1, _b.a, _v, _b.b, _b.c);
25
+ _b.c = _v;
26
+ }
27
+ }
28
+ var _key$3 = (t) => t.title;
29
+ function __item$4(t, __s, __extra) {
30
+ const active = __extra[0];
31
+ const props = __extra[1];
32
+ const setInternal = __extra[2];
33
+ let _b = __s.slots[0];
34
+ if (_b === void 0) {
35
+ let _m1;
36
+ const _root = clone(_t$1);
37
+ _m1 = _root;
38
+ setEventHandler(_root, "$$click", () => {
39
+ const i = props.tabs.indexOf(t);
40
+ setInternal(i);
41
+ props.onSelectedIndexChanged?.(i);
42
+ });
43
+ _b = bag4(__s, _root, void 0, _m1, null, void 0);
44
+ } else setEventHandler(_b.b, "$$click", () => {
45
+ const i = props.tabs.indexOf(t);
46
+ setInternal(i);
47
+ props.onSelectedIndexChanged?.(i);
48
+ });
49
+ _b.a = updateFreshClassName(["vx-tab", active === props.tabs.indexOf(t) ? "active" : ""], _b.a, _b.b);
50
+ _b.e = bindSignalChild(__s, _b.e, 1, _b.b, t.title, "b:7ce48fd2", null, void 0, void 0, void 0, true);
51
+ }
52
+ function __else$2(__props, __s, __extra) {
53
+ const active = __extra[0];
54
+ const paneRoute = __extra[1];
55
+ const props = __extra[2];
56
+ const resolve = __extra[3];
57
+ const setInternal = __extra[5];
58
+ let _b = __s.slots[0];
59
+ if (_b === void 0) {
60
+ let _m1, _m4, _m5, _m6;
61
+ const _root = clone(_t$2);
62
+ _m1 = _root;
63
+ const _el0 = child(_root);
64
+ _m4 = _el0;
65
+ _m5 = child(_el0);
66
+ _m6 = sibling(_el0, 1);
67
+ _b = bag9(__s, _root, void 0, _m1, void 0, void 0, _m4, _m5, _m6, null, void 0);
68
+ }
69
+ _b.a = bindSignalAttribute(__s, _b.a, _b.b, "id", props.id, "b:7404e316", "attr");
70
+ _b.c = updateFreshClassName(["vx-tabs", props.className], _b.c, _b.b);
71
+ {
72
+ const _v = props.style;
73
+ if (_b.d !== _v) {
74
+ setStyle(_b.b, _v, _b.d);
75
+ _b.d = _v;
76
+ }
77
+ }
78
+ forBlock(__s, 1, _b.e, props.tabs, _key$3, __item$4, 26, [
79
+ active,
80
+ props,
81
+ setInternal
82
+ ], null, _b.f, true);
83
+ _b.j = bindSignalChild(__s, _b.j, 2, _b.g, (paneRoute ? resolve(paneRoute.name, paneRoute.params) : null) ?? props.tabs[active]?.render(), "b:a696350b", null, void 0, void 0, void 0, true);
84
+ }
85
+ var Tabs = /* @__PURE__ */ __s(function Tabs(props, __s, __extra) {
86
+ const __block = __s.block;
87
+ const [internal, setInternal] = useState(0, _hs$ + 0);
88
+ const active = props.selectedIndex ?? internal;
89
+ const rootRoute = withSlot(_h$1, useRoute, "root");
90
+ const paneRoute = withSlot(_h$2, useRoute, props.tabs[active]?.stack ?? "");
91
+ const resolve = (name, params) => {
92
+ if (props.resolveScreen) return props.resolveScreen(name, params);
93
+ const C = screenFor(name);
94
+ return C ? createScopedValue(() => createElementFromConfig("c:beeccfd6", C, { ...params })) : null;
95
+ };
96
+ const routed = rootRoute ? resolve(rootRoute.name, rootRoute.params) : null;
97
+ if (__s.block.pending && !__s.block.crossRenderUpdate) return;
98
+ ifBlock(__s, 0, __block.parentNode, routed, __then$0, __else$2, __block.endMarker, [
99
+ active,
100
+ paneRoute,
101
+ props,
102
+ resolve,
103
+ routed,
104
+ setInternal
105
+ ]);
106
+ });
107
+ //#endregion
108
+ export { Tabs };
package/dist/web/ui3.js CHANGED
@@ -1,28 +1,20 @@
1
- import { __s, bag5, clone, setStyle, template } from "octane";
2
- import { childTextHoleUpdate, updateFreshClassName } from "octane/internal/client";
3
- //#region src/Row.web.tsrx
4
- var _t$0 = /* @__PURE__ */ template("<div></div>");
5
- var Row = /* @__PURE__ */ __s(function Row(props, __s, __extra) {
6
- let _b = __s.slots[0];
7
- if (_b === void 0) {
8
- let _m1;
9
- const _root = clone(_t$0);
10
- _m1 = _root;
11
- _b = bag5(__s, _root, void 0, _m1, void 0, null, void 0);
12
- }
13
- _b.a = updateFreshClassName(["vx-row", props.className], _b.a, _b.b);
14
- {
15
- const _v = props.style;
16
- if (_b.c !== _v) {
17
- setStyle(_b.b, _v, _b.c);
18
- _b.c = _v;
19
- }
20
- }
21
- {
22
- const _v = props.children;
23
- _b.d = childTextHoleUpdate(__s, 1, _b.b, _v, _b.d, _b.e);
24
- _b.e = _v;
25
- }
26
- });
1
+ //#region src/layout-child.web.ts
2
+ /** Convert parent-layout metadata to CSS on the web leaf. Native's `dock`
3
+ * attribute has no CSS equivalent and is ignored on web. Grid indices are
4
+ * zero-based in the shared API, matching NativeScript. */
5
+ function layoutChildProps(props, baseStyle = props.style) {
6
+ const style = { ...baseStyle ?? {} };
7
+ if (props.row !== void 0) style.gridRow = `${props.row + 1} / span ${props.rowSpan ?? 1}`;
8
+ else if (props.rowSpan !== void 0) style.gridRow = `span ${props.rowSpan}`;
9
+ if (props.col !== void 0) style.gridColumn = `${props.col + 1} / span ${props.colSpan ?? 1}`;
10
+ else if (props.colSpan !== void 0) style.gridColumn = `span ${props.colSpan}`;
11
+ if (props.left !== void 0) style.left = props.left;
12
+ if (props.top !== void 0) style.top = props.top;
13
+ if (props.flexGrow !== void 0) style.flexGrow = props.flexGrow;
14
+ if (props.flexShrink !== void 0) style.flexShrink = props.flexShrink;
15
+ if (props.alignSelf !== void 0) style.alignSelf = props.alignSelf;
16
+ if (props.order !== void 0) style.order = props.order;
17
+ return { style };
18
+ }
27
19
  //#endregion
28
- export { Row };
20
+ export { layoutChildProps };
@@ -0,0 +1,43 @@
1
+ import { applyEscapeProps } from "./ui2.js";
2
+ import { __s, bag6, clone, delegateEvents, queueRefAttach, queueRefDetach, setEventHandler, setStyle, template } from "octane";
3
+ import { bindSignalAttribute, bindSignalChecked, enableSignalBindings, replaceRef, updateFreshClassName } from "octane/internal/client";
4
+ //#region src/Switch.web.tsrx
5
+ enableSignalBindings(1, true);
6
+ delegateEvents(["change"]);
7
+ var _t$0 = /* @__PURE__ */ template("<input type=\"checkbox\" data-octane-input=\"i:0400e5c1\"/>");
8
+ var _rm$0 = [
9
+ "r",
10
+ "b",
11
+ "a"
12
+ ];
13
+ var Switch = /* @__PURE__ */ __s(function Switch(props, __s, __extra) {
14
+ let _b = __s.slots[0];
15
+ if (_b === void 0) {
16
+ let _m0, _m1, _m5;
17
+ const _root = clone(_t$0);
18
+ queueRefAttach(__s, _m1 = (e) => applyEscapeProps(e, props), _m0 = _root);
19
+ (__s.cleanups ??= []).push(() => _b && queueRefDetach(_b.b, _b.a));
20
+ _m5 = bindSignalChecked(__s, void 0, _root, props.checked, "i:0400e5c1");
21
+ setEventHandler(_root, "$$change", (e) => props.onCheckedChange?.(e.target.checked));
22
+ _b = bag6(__s, _root, _m0, _m1, void 0, void 0, void 0, _m5);
23
+ __s.refFields = _rm$0;
24
+ } else {
25
+ {
26
+ const _r = (e) => applyEscapeProps(e, props);
27
+ if (_r !== _b.b) _b.b = replaceRef(__s, _b.b, _r, _b.a);
28
+ }
29
+ _b.f = bindSignalChecked(__s, _b.f, _b.a, props.checked, "i:0400e5c1");
30
+ setEventHandler(_b.a, "$$change", (e) => props.onCheckedChange?.(e.target.checked));
31
+ }
32
+ _b.c = bindSignalAttribute(__s, _b.c, _b.a, "id", props.id, "b:18b5d0ad", "attr");
33
+ _b.d = updateFreshClassName(["vx-switch", props.className], _b.d, _b.a);
34
+ {
35
+ const _v = props.style;
36
+ if (_b.e !== _v) {
37
+ setStyle(_b.a, _v, _b.e);
38
+ _b.e = _v;
39
+ }
40
+ }
41
+ });
42
+ //#endregion
43
+ export { Switch };