@octane-xplat/ui 0.3.0 → 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.
Files changed (123) hide show
  1. package/README.md +46 -0
  2. package/dist/native/octane-client-build.json +1 -1
  3. package/dist/native/ui.js +52 -40
  4. package/dist/native/ui10.js +20 -11
  5. package/dist/native/ui11.js +42 -109
  6. package/dist/native/ui12.js +17 -84
  7. package/dist/native/ui13.js +11 -41
  8. package/dist/native/ui14.js +118 -76
  9. package/dist/native/ui15.js +43 -92
  10. package/dist/native/ui16.js +106 -45
  11. package/dist/native/ui17.js +29 -42
  12. package/dist/native/ui18.js +34 -53
  13. package/dist/native/ui19.js +246 -32
  14. package/dist/native/ui20.js +27 -16
  15. package/dist/native/ui21.js +376 -86
  16. package/dist/native/ui22.js +26 -114
  17. package/dist/native/ui23.js +49 -97
  18. package/dist/native/ui24.js +78 -53
  19. package/dist/native/ui25.js +138 -16
  20. package/dist/native/ui26.js +8 -23
  21. package/dist/native/ui27.js +60 -34
  22. package/dist/native/ui28.js +36 -142
  23. package/dist/native/ui29.js +101 -21
  24. package/dist/native/ui30.js +14 -31
  25. package/dist/native/ui31.js +55 -36
  26. package/dist/native/ui32.js +49 -61
  27. package/dist/native/ui33.js +36 -28
  28. package/dist/native/ui34.js +51 -8
  29. package/dist/native/ui35.js +98 -20
  30. package/dist/native/ui36.js +9 -33
  31. package/dist/native/ui37.js +42 -15
  32. package/dist/native/ui38.js +186 -57
  33. package/dist/native/ui39.js +96 -24
  34. package/dist/native/ui4.js +22 -20
  35. package/dist/native/ui40.js +57 -13
  36. package/dist/native/ui41.js +15 -100
  37. package/dist/native/ui42.js +6 -146
  38. package/dist/native/ui43.js +37 -21
  39. package/dist/native/ui44.js +265 -6
  40. package/dist/native/ui45.js +28 -0
  41. package/dist/native/ui46.js +35 -0
  42. package/dist/native/ui47.js +41 -0
  43. package/dist/native/ui48.js +72 -0
  44. package/dist/native/ui49.js +66 -0
  45. package/dist/native/ui5.js +37 -77
  46. package/dist/native/ui50.js +27 -0
  47. package/dist/native/ui51.js +13 -0
  48. package/dist/native/ui52.js +92 -0
  49. package/dist/native/ui53.js +34 -0
  50. package/dist/native/ui54.js +17 -0
  51. package/dist/native/ui55.js +156 -0
  52. package/dist/native/ui56.js +33 -0
  53. package/dist/native/ui57.js +14 -0
  54. package/dist/native/ui58.js +22 -0
  55. package/dist/native/ui59.js +8 -0
  56. package/dist/native/ui6.js +52 -9
  57. package/dist/native/ui60.js +108 -0
  58. package/dist/native/ui61.js +76 -0
  59. package/dist/native/ui7.js +42 -26
  60. package/dist/native/ui8.js +22 -12
  61. package/dist/native/ui9.js +18 -9
  62. package/dist/web/octane-client-build.json +1 -1
  63. package/dist/web/ui.js +51 -40
  64. package/dist/web/ui10.js +33 -186
  65. package/dist/web/ui11.js +28 -409
  66. package/dist/web/ui12.js +21 -68
  67. package/dist/web/ui13.js +201 -97
  68. package/dist/web/ui14.js +85 -95
  69. package/dist/web/ui15.js +368 -25
  70. package/dist/web/ui16.js +13 -101
  71. package/dist/web/ui17.js +246 -42
  72. package/dist/web/ui18.js +237 -28
  73. package/dist/web/ui19.js +36 -10
  74. package/dist/web/ui20.js +73 -102
  75. package/dist/web/ui21.js +102 -73
  76. package/dist/web/ui22.js +95 -55
  77. package/dist/web/ui23.js +94 -55
  78. package/dist/web/ui24.js +31 -15
  79. package/dist/web/ui25.js +105 -19
  80. package/dist/web/ui26.js +29 -23
  81. package/dist/web/ui27.js +12 -123
  82. package/dist/web/ui28.js +9 -110
  83. package/dist/web/ui29.js +52 -102
  84. package/dist/web/ui3.js +29 -18
  85. package/dist/web/ui30.js +32 -41
  86. package/dist/web/ui31.js +120 -39
  87. package/dist/web/ui32.js +41 -74
  88. package/dist/web/ui33.js +148 -32
  89. package/dist/web/ui34.js +54 -51
  90. package/dist/web/ui35.js +55 -7
  91. package/dist/web/ui36.js +18 -41
  92. package/dist/web/ui37.js +6 -46
  93. package/dist/web/ui38.js +37 -16
  94. package/dist/web/ui39.js +135 -81
  95. package/dist/web/ui4.js +46 -152
  96. package/dist/web/ui40.js +39 -37
  97. package/dist/web/ui41.js +41 -16
  98. package/dist/web/ui42.js +74 -7
  99. package/dist/web/ui43.js +40 -20
  100. package/dist/web/ui44.js +60 -6
  101. package/dist/web/ui45.js +9 -0
  102. package/dist/web/ui46.js +45 -0
  103. package/dist/web/ui47.js +13 -0
  104. package/dist/web/ui48.js +63 -0
  105. package/dist/web/ui49.js +47 -0
  106. package/dist/web/ui5.js +131 -27
  107. package/dist/web/ui50.js +17 -0
  108. package/dist/web/ui51.js +149 -0
  109. package/dist/web/ui52.js +42 -0
  110. package/dist/web/ui53.js +17 -0
  111. package/dist/web/ui54.js +9 -0
  112. package/dist/web/ui55.js +22 -0
  113. package/dist/web/ui56.js +8 -0
  114. package/dist/web/ui57.js +44 -0
  115. package/dist/web/ui58.js +46 -0
  116. package/dist/web/ui6.js +81 -45
  117. package/dist/web/ui7.js +43 -21
  118. package/dist/web/ui8.js +27 -21
  119. package/dist/web/ui9.js +29 -18
  120. package/package.json +13 -4
  121. package/src/theme/tokens.css +369 -138
  122. package/types/index.d.ts +102 -58
  123. package/types/props.d.ts +233 -13
package/dist/web/ui29.js CHANGED
@@ -1,108 +1,58 @@
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;
1
+ import { getColorScheme, subscribeSystemScheme } from "./ui27.js";
2
+ import { cx } from "./ui28.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();
26
13
  }
27
14
  }
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);
15
+ function getThemePreference() {
16
+ return preference;
51
17
  }
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);
18
+ /** The effective scheme: explicit override if set, else system appearance. */
19
+ function getThemeScheme() {
20
+ return preference === "system" ? getColorScheme() : preference;
84
21
  }
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;
22
+ function subscribe(cb) {
23
+ listeners.add(cb);
24
+ const offSystem = subscribeSystemScheme(cb);
25
+ return () => {
26
+ listeners.delete(cb);
27
+ offSystem();
95
28
  };
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
- });
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));
107
57
  //#endregion
108
- export { Tabs };
58
+ export { applyThemeClasses, getThemePreference, getThemeScheme, onThemeSchemeChange, setThemePreference, themeSchemeClasses, useThemeScheme };
package/dist/web/ui3.js CHANGED
@@ -1,20 +1,31 @@
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 };
1
+ //#region src/glass.ts
2
+ /** Normalize the `glass` surface prop into the config object handed to
3
+ * `iosGlassEffect` on native. Always returns an object — the upstream
4
+ * string shorthand silently drops `interactive` on the layout's update
5
+ * path, and an empty config defaults the variant to 'regular' here rather
6
+ * than upstream's own fallback. `false`/'none'/'identity' → no glass. */
7
+ function glassConfigOf(glass) {
8
+ if (!glass || glass === "none" || glass === "identity") return;
9
+ const c = typeof glass === "string" ? { variant: glass } : glass === true ? {} : glass;
10
+ if (c.variant === "none" || c.variant === "identity") return;
11
+ return {
12
+ variant: "regular",
13
+ ...c
14
+ };
15
+ }
16
+ /** `vx-glass` classes shared by web (real styling) and native (hook for
17
+ * app-supplied fallback CSS on non-glass OSes). */
18
+ function glassClassOf(glass) {
19
+ const c = glassConfigOf(glass);
20
+ if (!c) return;
21
+ return c.variant === "clear" ? "vx-glass vx-glass--clear" : "vx-glass";
22
+ }
23
+ /** Style merge for the web approximation — `tint` becomes the surface
24
+ * color (the class's translucent fallback is a weaker claim than an
25
+ * explicit inline value). Caller spreads result into its style object. */
26
+ function glassStyleOf(glass) {
27
+ const c = glassConfigOf(glass);
28
+ return c?.tint ? { backgroundColor: c.tint } : {};
18
29
  }
19
30
  //#endregion
20
- export { layoutChildProps };
31
+ export { glassClassOf, glassConfigOf, glassStyleOf };
package/dist/web/ui30.js CHANGED
@@ -1,43 +1,34 @@
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
- }
1
+ import { applyThemeClasses } from "./ui29.js";
2
+ import { createRoot } from "octane";
3
+ //#region src/modal-service.web.ts
4
+ /** Open a component in a document-level dialog and resolve with close(value). */
5
+ var openModal = (Component, params, options = {}) => new Promise((resolve) => {
6
+ const dialog = document.createElement("dialog");
7
+ dialog.className = options.presentation === "sheet" ? "vx-modal vx-modal--sheet" : options.presentation === "dialog" ? "vx-modal vx-modal--dialog" : options.presentation === "fullscreen" || !options.presentation && options.fullscreen ? "vx-modal vx-modal--fullscreen" : "vx-modal";
8
+ const unbindTheme = applyThemeClasses(dialog, dialog.className);
9
+ document.body.appendChild(dialog);
10
+ const root = createRoot(dialog);
11
+ let finished = false;
12
+ const finish = (result) => {
13
+ if (finished) return;
14
+ finished = true;
15
+ unbindTheme();
16
+ root.unmount();
17
+ dialog.remove();
18
+ resolve(result);
19
+ };
20
+ const close = (result) => {
21
+ if (finished) return;
22
+ if (dialog.open) dialog.close();
23
+ finish(result);
24
+ };
25
+ dialog.addEventListener("close", () => finish());
26
+ dialog.addEventListener("cancel", () => finish());
27
+ root.render(Component, {
28
+ params,
29
+ close
30
+ });
31
+ dialog.showModal();
41
32
  });
42
33
  //#endregion
43
- export { Switch };
34
+ export { openModal };
package/dist/web/ui31.js CHANGED
@@ -1,42 +1,123 @@
1
- import { hookSlots, useEffect, useState } from "octane";
2
- //#region src/safeAreaInsets.web.tsrx
3
- var _hs$ = /* @__PURE__ */ hookSlots(2);
4
- var _h$0 = /* @__PURE__ */ Symbol(_hs$);
5
- var _h$1 = /* @__PURE__ */ Symbol(_hs$ + 1);
6
- function measure() {
7
- if (!document.body) return {
8
- top: 0,
9
- right: 0,
10
- bottom: 0,
11
- left: 0
12
- };
13
- const probe = document.createElement("div");
14
- probe.style.cssText = "position:fixed;visibility:hidden;pointer-events:none;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);padding:constant(safe-area-inset-top) constant(safe-area-inset-right) constant(safe-area-inset-bottom) constant(safe-area-inset-left);";
15
- document.body.appendChild(probe);
16
- const style = getComputedStyle(probe);
17
- const insets = {
18
- top: parseFloat(style.paddingTop) || 0,
19
- right: parseFloat(style.paddingRight) || 0,
20
- bottom: parseFloat(style.paddingBottom) || 0,
21
- left: parseFloat(style.paddingLeft) || 0
22
- };
23
- probe.remove();
24
- return insets;
1
+ import { cx } from "./ui28.js";
2
+ import { useThemeScheme } from "./ui29.js";
3
+ import { bag1, bag2, bag9, child, clone, delegateEvents, drainFrag, hookSlots, ifBlock, markDangerouslySetInnerHTMLChildren, portal, setEventHandler, sibling, snapshotSpread, template, withSlot } from "octane";
4
+ import { bindSignalChild, bindSignalHostPropSources, enableSignalBindings } from "octane/internal/client";
5
+ //#region src/Overlay.web.tsrx
6
+ enableSignalBindings(1, true);
7
+ delegateEvents(["click"]);
8
+ var _t$0 = /* @__PURE__ */ template("<div class=\"vx-overlay-shade\"></div>");
9
+ var _t$1 = /* @__PURE__ */ template("<div><!><div class=\"vx-overlay-content\"></div></div>");
10
+ var _t$2 = /* @__PURE__ */ template("<!>", 0, 1);
11
+ var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(4));
12
+ function __then$2(__props, __s, __extra) {
13
+ const props = __extra[0];
14
+ let _b = __s.slots[0];
15
+ if (_b === void 0) {
16
+ let _m0;
17
+ const _root = clone(_t$0);
18
+ _m0 = _root;
19
+ setEventHandler(_root, "$$click", props.onDismiss);
20
+ _b = bag1(__s, _root, _m0);
21
+ } else setEventHandler(_b.a, "$$click", props.onDismiss);
25
22
  }
26
- function useSafeAreaInsets() {
27
- const [insets, setInsets] = useState({
28
- top: 0,
29
- right: 0,
30
- bottom: 0,
31
- left: 0
32
- }, _h$0);
33
- useEffect(() => {
34
- const update = () => setInsets(measure());
35
- update();
36
- window.addEventListener("resize", update);
37
- return () => window.removeEventListener("resize", update);
38
- }, [], _h$1);
39
- return insets;
23
+ var _rm$5 = [
24
+ "s",
25
+ "e",
26
+ "d"
27
+ ];
28
+ function __portal$1(__props, __s, __extra) {
29
+ const dark = __extra[0];
30
+ const props = __extra[1];
31
+ let _b = __s.slots[0];
32
+ if (_b === void 0) {
33
+ let _m0, _m1, _m2, _m3, _m4, _m5, _m6;
34
+ const _root = clone(_t$1);
35
+ _m0 = cx("vx-overlay", dark && "dark", props.className);
36
+ _m1 = {
37
+ ...props.style,
38
+ position: "fixed",
39
+ inset: 0
40
+ };
41
+ _m2 = snapshotSpread(props.web);
42
+ _m3 = _root;
43
+ _m4 = bindSignalHostPropSources(__s, void 0, _root, [
44
+ [
45
+ false,
46
+ "className",
47
+ _m0
48
+ ],
49
+ [
50
+ false,
51
+ "style",
52
+ _m1
53
+ ],
54
+ [true, _m2]
55
+ ], "b:843a5624", true);
56
+ const _el0 = sibling(child(_root), 1);
57
+ _m5 = _el0;
58
+ setEventHandler(_el0, "$$click", (event) => event.stopPropagation());
59
+ markDangerouslySetInnerHTMLChildren(_root);
60
+ _m6 = child(_root);
61
+ _b = bag9(__s, _root, _m0, _m1, _m2, _m3, _m4, _m5, _m6, null, void 0);
62
+ __s.refFields = _rm$5;
63
+ } else {
64
+ {
65
+ const _v = cx("vx-overlay", dark && "dark", props.className);
66
+ if (_b.a !== _v) _b.a = _v;
67
+ }
68
+ {
69
+ const _v = {
70
+ ...props.style,
71
+ position: "fixed",
72
+ inset: 0
73
+ };
74
+ if (_b.b !== _v) _b.b = _v;
75
+ }
76
+ _b.c = snapshotSpread(props.web);
77
+ _b.e = bindSignalHostPropSources(__s, _b.e, _b.d, [
78
+ [
79
+ false,
80
+ "className",
81
+ _b.a
82
+ ],
83
+ [
84
+ false,
85
+ "style",
86
+ _b.b
87
+ ],
88
+ [true, _b.c]
89
+ ], "b:843a5624", true);
90
+ setEventHandler(_b.f, "$$click", (event) => event.stopPropagation());
91
+ }
92
+ {
93
+ const __ifCondition = props.shadeCover;
94
+ ifBlock(__s, 1, _b.d, __ifCondition, __then$2, null, _b.g, __ifCondition ? [props] : void 0);
95
+ }
96
+ _b.j = bindSignalChild(__s, _b.j, 2, _b.f, props.children, "b:f597242e", null, void 0, void 0, void 0, true);
40
97
  }
98
+ function __then$0(__props, __s, __extra) {
99
+ const __block = __s.block;
100
+ const dark = __extra[0];
101
+ const props = __extra[1];
102
+ let _b = __s.slots[0];
103
+ if (_b === void 0) {
104
+ let _m0, _m1;
105
+ const _root = clone(_t$2);
106
+ _m0 = __block.parentNode;
107
+ _m1 = child(_root);
108
+ drainFrag(_root, __block.parentNode, __block.endMarker);
109
+ _b = bag2(__s, null, _m0, _m1);
110
+ }
111
+ portal(__s, 1, document.body, __portal$1, void 0, _b.a, [dark, props], void 0, _b.b);
112
+ }
113
+ var Overlay = function Overlay(props, __s, __extra) {
114
+ const __block = __s.block;
115
+ const dark = withSlot(_h$0, useThemeScheme) === "dark";
116
+ if (__s.block.pending && !__s.block.crossRenderUpdate) return;
117
+ {
118
+ const __ifCondition$ = props.open;
119
+ ifBlock(__s, 0, __block.parentNode, __ifCondition$, __then$0, null, __block.endMarker, __ifCondition$ ? [dark, props] : void 0);
120
+ }
121
+ };
41
122
  //#endregion
42
- export { useSafeAreaInsets };
123
+ export { Overlay };
package/dist/web/ui32.js CHANGED
@@ -1,77 +1,44 @@
1
- import { useSafeAreaInsets } from "./ui31.js";
2
- import { __s, bag11, clone, hookSlots, queueRefAttach, queueRefDetach, setStyle, setStyleProperty, template, withSlot } from "octane";
3
- import { canSplitStyleProperties, childTextHoleUpdate, replaceRef, styleObjectPrototype, updateFreshClassName } from "octane/internal/client";
4
- //#region src/SafeArea.web.tsrx
5
- var _t$0 = /* @__PURE__ */ template("<div></div>");
6
- var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
7
- var _rm$1 = [
8
- "r",
9
- "b",
10
- "a"
11
- ];
12
- function applyWebProps(node, bag) {
13
- if (!node || !bag) return;
14
- for (const [key, value] of Object.entries(bag)) if (key.includes("-")) node.setAttribute(key, String(value));
15
- else node[key] = value;
16
- }
17
- var SafeArea = /* @__PURE__ */ __s(function SafeArea(props, __s, __extra) {
18
- const insets = withSlot(_h$0, useSafeAreaInsets);
19
- if (__s.block.pending && !__s.block.crossRenderUpdate) return;
20
- let _b = __s.slots[0];
21
- if (_b === void 0) {
22
- let _m0, _m1;
23
- const _root = clone(_t$0);
24
- queueRefAttach(__s, _m1 = (node) => applyWebProps(node, props.web), _m0 = _root);
25
- (__s.cleanups ??= []).push(() => _b && queueRefDetach(_b.b, _b.a));
26
- _b = bag11(__s, _root, _m0, _m1, void 0, __s, void 0, void 0, void 0, void 0, void 0, null, void 0);
27
- __s.refFields = _rm$1;
28
- } else {
29
- const _r = (node) => applyWebProps(node, props.web);
30
- if (_r !== _b.b) _b.b = replaceRef(__s, _b.b, _r, _b.a);
31
- }
32
- _b.c = updateFreshClassName(["vx-safe-area", props.className], _b.c, _b.a);
33
- {
34
- const __styleSpread = { ...props.style };
35
- const __styleValue = insets.top;
36
- const __styleValue$ = insets.right;
37
- const __styleValue$2 = insets.bottom;
38
- const __styleValue$3 = insets.left;
39
- const __styleFull = "paddingTop" in __styleSpread || "paddingRight" in __styleSpread || "paddingBottom" in __styleSpread || "paddingLeft" in __styleSpread || !canSplitStyleProperties();
40
- if (_b.d === __s || __styleFull || _b.e) {
41
- const __styleObject = __styleFull && !("paddingTop" in styleObjectPrototype || "paddingRight" in styleObjectPrototype || "paddingBottom" in styleObjectPrototype || "paddingLeft" in styleObjectPrototype) ? (__styleSpread["paddingTop"] = __styleValue, __styleSpread["paddingRight"] = __styleValue$, __styleSpread["paddingBottom"] = __styleValue$2, __styleSpread["paddingLeft"] = __styleValue$3, __styleSpread) : {
42
- ...__styleSpread,
43
- "paddingTop": __styleValue,
44
- "paddingRight": __styleValue$,
45
- "paddingBottom": __styleValue$2,
46
- "paddingLeft": __styleValue$3
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
47
27
  };
48
- setStyle(_b.a, __styleObject, _b.d === __s ? void 0 : _b.e ? _b.d : {
49
- ..._b.d,
50
- "paddingTop": _b.f,
51
- "paddingRight": _b.g,
52
- "paddingBottom": _b.h,
53
- "paddingLeft": _b.i
54
- });
55
- _b.d = __styleFull ? __styleObject : __styleSpread;
56
- } else {
57
- setStyle(_b.a, __styleSpread, _b.d);
58
- if (_b.f !== __styleValue) setStyleProperty(_b.a, "paddingTop", __styleValue, "", _b.f);
59
- if (_b.g !== __styleValue$) setStyleProperty(_b.a, "paddingRight", __styleValue$, "", _b.g);
60
- if (_b.h !== __styleValue$2) setStyleProperty(_b.a, "paddingBottom", __styleValue$2, "", _b.h);
61
- if (_b.i !== __styleValue$3) setStyleProperty(_b.a, "paddingLeft", __styleValue$3, "", _b.i);
62
- _b.d = __styleSpread;
63
28
  }
64
- _b.e = __styleFull;
65
- _b.f = __styleValue;
66
- _b.g = __styleValue$;
67
- _b.h = __styleValue$2;
68
- _b.i = __styleValue$3;
69
- }
70
- {
71
- const _v = props.children;
72
- _b.j = childTextHoleUpdate(__s, 1, _b.a, _v, _b.j, _b.k);
73
- _b.k = _v;
74
- }
75
- });
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
+ }
76
43
  //#endregion
77
- export { SafeArea };
44
+ export { positionPopover };