@octane-xplat/pager 0.14.0 → 0.16.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.
@@ -1,334 +0,0 @@
1
- import { applyWebProps } from "./platformProps.web.js";
2
- import { layoutChildProps } from "./layout-child.web.js";
3
- import { bag4, bagOf, child, clone, drainFrag, forBlock, hookSlots, ifBlock, markDangerouslySetInnerHTMLChildren, snapshotSpread, template, useEffect, useRef } from "octane";
4
- import { bindSignalChild, bindSignalHostPropSources, enableSignalBindings, setAriaAttributeIfChanged } from "octane/internal/client";
5
- //#region src/Pager.web.tsrx
6
- enableSignalBindings(1, true);
7
- var _t$0 = /* @__PURE__ */ template("<div class=\"vx-pager-page\" role=\"group\" aria-roledescription=\"slide\"></div>");
8
- var _t$1 = /* @__PURE__ */ template("<div><!></div>");
9
- var _t$2 = /* @__PURE__ */ template("<!>", 0, 1);
10
- var _hs$ = /* @__PURE__ */ hookSlots(8);
11
- var _key$1 = (item, i) => i;
12
- function __item$2(item, __s, __extra) {
13
- const __block = __s.block;
14
- const props = __extra[0];
15
- const i = __block.itemIndex;
16
- let _b = __s.slots[0];
17
- if (_b === void 0) {
18
- const _root = clone(_t$0);
19
- _b = bag4(__s, _root, void 0, _root, null, __s);
20
- }
21
- _b.a = setAriaAttributeIfChanged(`${i + 1} of ${props.items.length}`, _b.a, _b.b, "aria-label");
22
- _b.e = bindSignalChild(__s, _b.e, 1, _b.b, props.renderItem(item, i), "b:a193c343", null, void 0, void 0, void 0, true);
23
- }
24
- var _rm$5 = [
25
- "s",
26
- "p",
27
- "o"
28
- ];
29
- function __then$0(__props, __s, __extra) {
30
- const host = __extra[0];
31
- const props = __extra[1];
32
- let _b = __s.slots[0];
33
- if (_b === void 0) {
34
- let _m0, _m1, _m2, _m3, _m4, _m5, _m6, _m7, _m8, _m9, _m10, _m11, _m12, _m13, _m15, _m16;
35
- const _root = clone(_t$1);
36
- _m0 = (el) => {
37
- host.current = el;
38
- applyWebProps(el, props.web);
39
- };
40
- _m1 = props.id;
41
- _m2 = ["vx-pager", props.className];
42
- _m3 = snapshotSpread(layoutChildProps(props));
43
- _m4 = props.accessibilityRole ?? "group";
44
- _m5 = "carousel";
45
- _m6 = props.accessibilityLabel;
46
- _m7 = props.accessible === false ? true : void 0;
47
- _m8 = props.accessibilityHint;
48
- _m9 = props.accessibilityValue;
49
- _m10 = props.accessibilityState?.disabled;
50
- _m11 = props.accessibilityState?.selected;
51
- _m12 = props.accessibilityState?.checked;
52
- _m13 = props.accessibilityLiveRegion === "none" ? "off" : props.accessibilityLiveRegion;
53
- _m15 = bindSignalHostPropSources(__s, void 0, _root, [
54
- [
55
- false,
56
- "ref",
57
- _m0
58
- ],
59
- [
60
- false,
61
- "id",
62
- _m1
63
- ],
64
- [
65
- false,
66
- "className",
67
- _m2
68
- ],
69
- [true, _m3],
70
- [
71
- false,
72
- "role",
73
- _m4
74
- ],
75
- [
76
- false,
77
- "aria-roledescription",
78
- _m5
79
- ],
80
- [
81
- false,
82
- "aria-label",
83
- _m6
84
- ],
85
- [
86
- false,
87
- "aria-hidden",
88
- _m7
89
- ],
90
- [
91
- false,
92
- "aria-description",
93
- _m8
94
- ],
95
- [
96
- false,
97
- "aria-valuetext",
98
- _m9
99
- ],
100
- [
101
- false,
102
- "aria-disabled",
103
- _m10
104
- ],
105
- [
106
- false,
107
- "aria-selected",
108
- _m11
109
- ],
110
- [
111
- false,
112
- "aria-checked",
113
- _m12
114
- ],
115
- [
116
- false,
117
- "aria-live",
118
- _m13
119
- ]
120
- ], "b:452923c1", true);
121
- markDangerouslySetInnerHTMLChildren(_root);
122
- _m16 = child(_root);
123
- _b = bagOf(__s, _root, {
124
- a: _m0,
125
- b: _m1,
126
- c: _m2,
127
- d: _m3,
128
- e: _m4,
129
- f: _m5,
130
- g: _m6,
131
- h: _m7,
132
- i: _m8,
133
- j: _m9,
134
- k: _m10,
135
- l: _m11,
136
- m: _m12,
137
- n: _m13,
138
- o: _root,
139
- p: _m15,
140
- q: _m16
141
- });
142
- __s.refFields = _rm$5;
143
- } else {
144
- {
145
- const _v = (el) => {
146
- host.current = el;
147
- applyWebProps(el, props.web);
148
- };
149
- if (_b.a !== _v) _b.a = _v;
150
- }
151
- {
152
- const _v = props.id;
153
- if (_b.b !== _v) _b.b = _v;
154
- }
155
- {
156
- const _v = ["vx-pager", props.className];
157
- if (_b.c !== _v) _b.c = _v;
158
- }
159
- _b.d = snapshotSpread(layoutChildProps(props));
160
- {
161
- const _v = props.accessibilityRole ?? "group";
162
- if (_b.e !== _v) _b.e = _v;
163
- }
164
- {
165
- const _v = "carousel";
166
- if (_b.f !== _v) _b.f = _v;
167
- }
168
- {
169
- const _v = props.accessibilityLabel;
170
- if (_b.g !== _v) _b.g = _v;
171
- }
172
- {
173
- const _v = props.accessible === false ? true : void 0;
174
- if (_b.h !== _v) _b.h = _v;
175
- }
176
- {
177
- const _v = props.accessibilityHint;
178
- if (_b.i !== _v) _b.i = _v;
179
- }
180
- {
181
- const _v = props.accessibilityValue;
182
- if (_b.j !== _v) _b.j = _v;
183
- }
184
- {
185
- const _v = props.accessibilityState?.disabled;
186
- if (_b.k !== _v) _b.k = _v;
187
- }
188
- {
189
- const _v = props.accessibilityState?.selected;
190
- if (_b.l !== _v) _b.l = _v;
191
- }
192
- {
193
- const _v = props.accessibilityState?.checked;
194
- if (_b.m !== _v) _b.m = _v;
195
- }
196
- {
197
- const _v = props.accessibilityLiveRegion === "none" ? "off" : props.accessibilityLiveRegion;
198
- if (_b.n !== _v) _b.n = _v;
199
- }
200
- _b.p = bindSignalHostPropSources(__s, _b.p, _b.o, [
201
- [
202
- false,
203
- "ref",
204
- _b.a
205
- ],
206
- [
207
- false,
208
- "id",
209
- _b.b
210
- ],
211
- [
212
- false,
213
- "className",
214
- _b.c
215
- ],
216
- [true, _b.d],
217
- [
218
- false,
219
- "role",
220
- _b.e
221
- ],
222
- [
223
- false,
224
- "aria-roledescription",
225
- _b.f
226
- ],
227
- [
228
- false,
229
- "aria-label",
230
- _b.g
231
- ],
232
- [
233
- false,
234
- "aria-hidden",
235
- _b.h
236
- ],
237
- [
238
- false,
239
- "aria-description",
240
- _b.i
241
- ],
242
- [
243
- false,
244
- "aria-valuetext",
245
- _b.j
246
- ],
247
- [
248
- false,
249
- "aria-disabled",
250
- _b.k
251
- ],
252
- [
253
- false,
254
- "aria-selected",
255
- _b.l
256
- ],
257
- [
258
- false,
259
- "aria-checked",
260
- _b.m
261
- ],
262
- [
263
- false,
264
- "aria-live",
265
- _b.n
266
- ]
267
- ], "b:452923c1", true);
268
- }
269
- forBlock(__s, 1, _b.o, props.items, _key$1, __item$2, 50, [props], null, _b.q, true, "f3hircj");
270
- }
271
- function __else$6(__props, __s, __extra) {
272
- const __block = __s.block;
273
- const props = __extra[1];
274
- let _b = __s.slots[0];
275
- if (_b === void 0) {
276
- let _m0, _m1;
277
- const _root = clone(_t$2);
278
- _m0 = __block.parentNode;
279
- _m1 = child(_root);
280
- drainFrag(_root, __block.parentNode, __block.endMarker);
281
- _b = bag4(__s, null, _m0, _m1, null, __s);
282
- }
283
- _b.e = bindSignalChild(__s, _b.e, 1, _b.a, props.renderEmpty?.(), "b:8f0f2972", _b.b, true, void 0, true);
284
- }
285
- var Pager = function Pager(props, __s, __extra) {
286
- const __block = __s.block;
287
- const host = useRef(null, _hs$ + 0);
288
- const latest = useRef(props, _hs$ + 1);
289
- const current = useRef(props.page ?? props.defaultPage ?? 0, _hs$ + 2);
290
- const settle = useRef(null, _hs$ + 3);
291
- useEffect(() => {
292
- latest.current = props;
293
- }, [props], _hs$ + 4);
294
- useEffect(() => {
295
- const el = host.current;
296
- if (!el) return;
297
- const onScroll = () => {
298
- if (settle.current !== null) clearTimeout(settle.current);
299
- settle.current = setTimeout(() => {
300
- settle.current = null;
301
- const el2 = host.current;
302
- if (!el2 || el2.clientWidth === 0) return;
303
- const max = Math.max(latest.current.items.length - 1, 0);
304
- const next = Math.max(0, Math.min(max, Math.round(el2.scrollLeft / el2.clientWidth)));
305
- if (next !== current.current) {
306
- current.current = next;
307
- latest.current.onPageChange?.(next);
308
- }
309
- }, 90);
310
- };
311
- el.addEventListener("scroll", onScroll, { passive: true });
312
- return () => {
313
- el.removeEventListener("scroll", onScroll);
314
- if (settle.current !== null) clearTimeout(settle.current);
315
- };
316
- }, [], _hs$ + 5);
317
- useEffect(() => {
318
- const el = host.current;
319
- if (!el || current.current <= 0) return;
320
- el.scrollLeft = current.current * el.clientWidth;
321
- }, [], _hs$ + 6);
322
- useEffect(() => {
323
- const el = host.current;
324
- if (!el || props.page === void 0 || props.page === current.current) return;
325
- current.current = props.page;
326
- el.scrollTo({
327
- left: props.page * el.clientWidth,
328
- behavior: "smooth"
329
- });
330
- }, [props.page], _hs$ + 7);
331
- ifBlock(__s, 0, __block.parentNode, props.items.length > 0, __then$0, __else$6, __block.endMarker, [host, props], 2);
332
- };
333
- //#endregion
334
- export { Pager };
package/dist/web/index.js DELETED
@@ -1,2 +0,0 @@
1
- import { Pager } from "./Pager.web.tsrx.js";
2
- export { Pager };
@@ -1,47 +0,0 @@
1
- //#region src/layout-child.web.ts
2
- /** The shared contract is "numbers are dips" (RN semantics), but octane's DOM
3
- * renderer keeps React's unitless list — lineHeight is unitless there, so
4
- * `style={{lineHeight: 40}}` would render a 40× multiplier instead of 40px.
5
- * lineHeight is the one unitless-in-React prop that is a length in the
6
- * shared vocabulary; force the px suffix. */
7
- function normStyle(style) {
8
- if (style && typeof style.lineHeight === "number") return {
9
- ...style,
10
- lineHeight: style.lineHeight + "px"
11
- };
12
- return style;
13
- }
14
- var FLEX_JUSTIFY = {
15
- start: "flex-start",
16
- end: "flex-end"
17
- };
18
- var FLEX_ALIGN = {
19
- start: "flex-start",
20
- end: "flex-end"
21
- };
22
- /** Convert parent-layout metadata to CSS on the web leaf. Native's `dock`
23
- * attribute has no CSS equivalent and is ignored on web. Grid indices are
24
- * zero-based in the shared API, matching NativeScript. */
25
- function layoutChildProps(props, baseStyle = props.style) {
26
- const style = { ...normStyle(baseStyle) };
27
- if (props.row !== void 0) style.gridRow = `${props.row + 1} / span ${props.rowSpan ?? 1}`;
28
- else if (props.rowSpan !== void 0) style.gridRow = `span ${props.rowSpan}`;
29
- if (props.col !== void 0) style.gridColumn = `${props.col + 1} / span ${props.colSpan ?? 1}`;
30
- else if (props.colSpan !== void 0) style.gridColumn = `span ${props.colSpan}`;
31
- if (props.left !== void 0) style.left = props.left;
32
- if (props.top !== void 0) style.top = props.top;
33
- if (props.flexGrow !== void 0) style.flexGrow = props.flexGrow;
34
- if (props.flexShrink !== void 0) style.flexShrink = props.flexShrink;
35
- if (props.alignSelf !== void 0) style.alignSelf = props.alignSelf;
36
- if (props.order !== void 0) style.order = props.order;
37
- if (props.justifyContent !== void 0) style.justifyContent = FLEX_JUSTIFY[props.justifyContent] ?? props.justifyContent;
38
- if (props.alignItems !== void 0) style.alignItems = FLEX_ALIGN[props.alignItems] ?? props.alignItems;
39
- if (props.flexWrap !== void 0) style.flexWrap = props.flexWrap === true ? "wrap" : props.flexWrap === false ? "nowrap" : props.flexWrap;
40
- if (props.gap !== void 0) style.gap = props.gap;
41
- if (props.rowGap !== void 0) style.rowGap = props.rowGap;
42
- if (props.columnGap !== void 0) style.columnGap = props.columnGap;
43
- if (typeof style.lineHeight === "number") style.lineHeight = style.lineHeight + "px";
44
- return { style };
45
- }
46
- //#endregion
47
- export { layoutChildProps, normStyle };
@@ -1,8 +0,0 @@
1
- {
2
- "version": 1,
3
- "buildId": "a4e920b0-d311-42b3-ad90-36799b27d84f",
4
- "mode": "production",
5
- "capabilities": {
6
- "independentHydration": false
7
- }
8
- }
@@ -1,9 +0,0 @@
1
- //#region src/platformProps.web.ts
2
- /** Apply a web escape-hatch bag after the primitive's standard props. */
3
- function applyWebProps(el, props) {
4
- if (!el || !props) return;
5
- for (const [name, value] of Object.entries(props)) if (name.includes("-")) el.setAttribute(name, String(value));
6
- else el[name] = value;
7
- }
8
- //#endregion
9
- export { applyWebProps };
@@ -1,83 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { act, createRoot } from 'octane';
4
- import { Pager } from './Pager.web.tsrx';
5
-
6
- // jsdom has no layout — clientWidth is always 0 — so the leaf's scroll math
7
- // is exercised against a stubbed page width. scrollTo is unimplemented in
8
- // jsdom; the stub records controlled-page writes.
9
-
10
- const items = ['a', 'b', 'c'];
11
- const renderItem = (item: string) => <span class="pg">{item}</span>;
12
-
13
- function mount(extra: any = {}) {
14
- const el = document.createElement('div');
15
- document.body.appendChild(el);
16
- const root = createRoot(el);
17
- act(() => root.render(<Pager items={items} renderItem={renderItem} {...extra} />));
18
- const pager = el.querySelector('.vx-pager') as any;
19
- Object.defineProperty(pager, 'clientWidth', { value: 100, configurable: true });
20
- pager.scrollTo = vi.fn((opts: any) => {
21
- pager.scrollLeft = opts.left;
22
- pager.dispatchEvent(new Event('scroll'));
23
- });
24
-
25
- return { el, root, pager };
26
- }
27
-
28
- describe('Pager (web leaf)', () => {
29
- afterEach(() => {
30
- vi.useRealTimers();
31
- });
32
-
33
- it('renders one snap page per item, plus renderEmpty', () => {
34
- const { el, root, pager } = mount();
35
- expect(pager.className).toContain('vx-pager');
36
- expect(el.querySelectorAll('.vx-pager-page')).toHaveLength(3);
37
- expect(el.querySelectorAll('.pg')).toHaveLength(3);
38
- root.unmount();
39
- el.remove();
40
- });
41
-
42
- it('fires onPageChange once the scroll settles', () => {
43
- vi.useFakeTimers();
44
- const onPageChange = vi.fn();
45
- const { el, root, pager } = mount({ onPageChange });
46
- pager.scrollLeft = 200;
47
- pager.dispatchEvent(new Event('scroll'));
48
- vi.advanceTimersByTime(200);
49
- expect(onPageChange).toHaveBeenCalledTimes(1);
50
- expect(onPageChange).toHaveBeenCalledWith(2);
51
- root.unmount();
52
- el.remove();
53
- });
54
-
55
- it('suppresses the echo of its own controlled writes', () => {
56
- vi.useFakeTimers();
57
- const onPageChange = vi.fn();
58
- const el = document.createElement('div');
59
- document.body.appendChild(el);
60
- const root = createRoot(el);
61
- const set = { page: 0 };
62
- function Host() @{
63
- <Pager items={items} renderItem={renderItem} page={set.page} onPageChange={onPageChange} />;
64
- }
65
-
66
- act(() => root.render(<Host />));
67
- const pager = el.querySelector('.vx-pager') as any;
68
- Object.defineProperty(pager, 'clientWidth', { value: 100, configurable: true });
69
- pager.scrollTo = vi.fn((opts: any) => {
70
- pager.scrollLeft = opts.left;
71
- pager.dispatchEvent(new Event('scroll'));
72
- });
73
-
74
- set.page = 1;
75
- act(() => root.render(<Host />));
76
- expect(pager.scrollTo).toHaveBeenCalledWith({ left: 100, behavior: 'smooth' });
77
- vi.advanceTimersByTime(200);
78
- // The programmatic scroll must not report back as a user swipe.
79
- expect(onPageChange).not.toHaveBeenCalled();
80
- root.unmount();
81
- el.remove();
82
- });
83
- });
package/src/cx.mobile.ts DELETED
@@ -1,9 +0,0 @@
1
- /** Native renderers now normalize the declarative `className` prop, but
2
- * imperative `view.className` writes still need a pre-joined string — NS
3
- * splits on ' ' only. Native leaves keep normalizing through cx() before
4
- * handing className to an intrinsic so both paths accept the same values.
5
- * (The DOM renderer already flattens arrays, so web leaves don't need
6
- * this.) */
7
- export function cx(...parts: any[]): string {
8
- return parts.flat(Infinity).filter(Boolean).join(' ')
9
- }