@lingxia/elements 0.10.0 → 0.12.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.
@@ -11,7 +11,6 @@ export interface NavigatorNativeAttrOptions {
11
11
  target?: NavigatorTarget;
12
12
  delta?: number;
13
13
  appId?: string;
14
- path?: string;
15
14
  query?: NavigatorQuery;
16
15
  envVersion?: NavigatorEnvVersion;
17
16
  targetVersion?: string;
@@ -41,8 +41,6 @@ export function buildNavigatorNativeAttrs(options, extraAttrs = {}) {
41
41
  result.target = options.target;
42
42
  if (options.appId)
43
43
  result["app-id"] = options.appId;
44
- if (options.path)
45
- result.path = options.path;
46
44
  if (options.query)
47
45
  result.query = JSON.stringify(options.query);
48
46
  if (options.envVersion)
@@ -13,7 +13,6 @@ export interface LxNavigatorEvent extends CustomEvent<LxNavigatorEventDetail> {
13
13
  export type LxNavigatorAttributes = {
14
14
  url?: string;
15
15
  page?: string;
16
- path?: string;
17
16
  query?: string;
18
17
  'open-type'?: NavigatorOpenType;
19
18
  target?: NavigatorTarget;
package/dist/navigator.js CHANGED
@@ -39,7 +39,6 @@ export class LxNavigatorElement extends HTMLElement {
39
39
  return [
40
40
  "url",
41
41
  "page",
42
- "path",
43
42
  "query",
44
43
  "open-type",
45
44
  "target",
@@ -162,6 +161,8 @@ export class LxNavigatorElement extends HTMLElement {
162
161
  e.preventDefault();
163
162
  const url = this.getAttribute('url') || '';
164
163
  const page = this.getAttribute('page');
164
+ // Read the removed attribute only to provide a forward-only runtime error
165
+ // for untyped HTML callers instead of silently ignoring it.
165
166
  const path = this.getAttribute('path');
166
167
  const query = this.getAttribute('query');
167
168
  const openType = (this.getAttribute('open-type') || 'navigate');
@@ -282,6 +283,9 @@ export class LxNavigatorElement extends HTMLElement {
282
283
  async performNavigation(options) {
283
284
  const url = options.url || '';
284
285
  const delta = Number.isFinite(options.delta) && options.delta > 0 ? options.delta : 1;
286
+ if (options.path !== null && options.path !== undefined) {
287
+ throw new Error('path is not supported; pass the configured page name in page');
288
+ }
285
289
  if (options.openType === 'tel') {
286
290
  if (!options.phoneNumber) {
287
291
  throw new Error('tel requires phone-number attribute');
@@ -290,12 +294,12 @@ export class LxNavigatorElement extends HTMLElement {
290
294
  return;
291
295
  }
292
296
  if (options.openType === 'exit') {
293
- await this.callHost('navigator.navigateBackLxApp');
297
+ await this.callHost('navigator.navigateBackApp');
294
298
  return;
295
299
  }
296
300
  if (options.openType === 'navigateBack') {
297
301
  if (options.target === 'lxapp') {
298
- await this.callHost('navigator.navigateBackLxApp');
302
+ await this.callHost('navigator.navigateBackApp');
299
303
  return;
300
304
  }
301
305
  if (options.target === 'browser') {
@@ -313,9 +317,9 @@ export class LxNavigatorElement extends HTMLElement {
313
317
  }
314
318
  if (options.target === 'lxapp') {
315
319
  if (!options.appId) {
316
- throw new Error('navigateToLxApp requires app-id');
320
+ throw new Error('navigateToApp requires app-id');
317
321
  }
318
- await this.callHost('navigator.navigateToLxApp', this.buildLxAppTarget(options));
322
+ await this.callHost('navigator.navigateToApp', this.buildLxAppTarget(options));
319
323
  return;
320
324
  }
321
325
  if (options.target === 'self' && /^https?:\/\//i.test(url)) {
@@ -327,7 +331,7 @@ export class LxNavigatorElement extends HTMLElement {
327
331
  }
328
332
  const target = this.buildPageTarget(options);
329
333
  if (!target) {
330
- throw new Error(`${options.openType} requires page or path`);
334
+ throw new Error(`${options.openType} requires page`);
331
335
  }
332
336
  switch (options.openType) {
333
337
  case 'navigate':
@@ -362,17 +366,13 @@ export class LxNavigatorElement extends HTMLElement {
362
366
  return parsed;
363
367
  }
364
368
  buildPageTarget(options) {
365
- var _a, _b;
369
+ var _a;
366
370
  const page = (_a = options.page) === null || _a === void 0 ? void 0 : _a.trim();
367
- const path = (_b = options.path) === null || _b === void 0 ? void 0 : _b.trim();
368
- if (page && path) {
369
- throw new Error('pass either page or path, not both');
370
- }
371
- if (!page && !path)
371
+ if (!page)
372
372
  return null;
373
373
  const query = this.readQuery(options.query);
374
374
  return {
375
- ...(page ? { page } : { path: path }),
375
+ page,
376
376
  ...(query ? { query } : {}),
377
377
  };
378
378
  }
package/dist/video.d.ts CHANGED
@@ -67,6 +67,8 @@ export declare class LxVideoElement extends HTMLElement {
67
67
  private attrObserver?;
68
68
  private resizeEventListener;
69
69
  private iOSScrollEventListener;
70
+ private scrollSettleFrame;
71
+ private containerScrollListener;
70
72
  private rawHandlers;
71
73
  private _pageBindings;
72
74
  private parseRotateValue;
package/dist/video.js CHANGED
@@ -25,6 +25,21 @@ export class LxVideoElement extends HTMLElement {
25
25
  this.iOSScrollEventListener = {
26
26
  handleEvent: () => this.boundUpdatePosition(),
27
27
  };
28
+ this.scrollSettleFrame = null;
29
+ // Scroll events do not bubble, so a plain window listener misses inner
30
+ // scroll containers; the capture phase sees them all. Any ancestor
31
+ // scrolling moves the element's document rect, so re-measure (coalesced
32
+ // to one update per frame; decide() dedups unchanged rects).
33
+ this.containerScrollListener = {
34
+ handleEvent: () => {
35
+ if (this.scrollSettleFrame !== null)
36
+ return;
37
+ this.scrollSettleFrame = requestAnimationFrame(() => {
38
+ this.scrollSettleFrame = null;
39
+ this.updatePosition();
40
+ });
41
+ },
42
+ };
28
43
  this.rawHandlers = {};
29
44
  this._pageBindings = {};
30
45
  }
@@ -538,6 +553,12 @@ export class LxVideoElement extends HTMLElement {
538
553
  if (isIOS()) {
539
554
  window.addEventListener("scroll", this.iOSScrollEventListener, { passive: true });
540
555
  }
556
+ else if (isWindows()) {
557
+ window.addEventListener("scroll", this.containerScrollListener, {
558
+ capture: true,
559
+ passive: true,
560
+ });
561
+ }
541
562
  if (isAndroid()) {
542
563
  this.removeLayoutInvalidationListener = addNativeComponentLayoutInvalidationListener(this.resizeEventListener);
543
564
  }
@@ -550,9 +571,16 @@ export class LxVideoElement extends HTMLElement {
550
571
  if (isIOS()) {
551
572
  window.removeEventListener("scroll", this.iOSScrollEventListener);
552
573
  }
574
+ else if (isWindows()) {
575
+ window.removeEventListener("scroll", this.containerScrollListener, { capture: true });
576
+ }
553
577
  (_a = this.removeLayoutInvalidationListener) === null || _a === void 0 ? void 0 : _a.call(this);
554
578
  this.removeLayoutInvalidationListener = undefined;
555
579
  this.stopSizeObserver();
580
+ if (this.scrollSettleFrame !== null) {
581
+ cancelAnimationFrame(this.scrollSettleFrame);
582
+ this.scrollSettleFrame = null;
583
+ }
556
584
  if (this.winSettleFrame !== null) {
557
585
  cancelAnimationFrame(this.winSettleFrame);
558
586
  this.winSettleFrame = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingxia/elements",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "private": false,
5
5
  "description": "LingXia custom elements — native-backed web components for LxApp pages",
6
6
  "type": "module",
@@ -38,7 +38,6 @@ export interface NavigatorNativeAttrOptions {
38
38
  target?: NavigatorTarget;
39
39
  delta?: number;
40
40
  appId?: string;
41
- path?: string;
42
41
  query?: NavigatorQuery;
43
42
  envVersion?: NavigatorEnvVersion;
44
43
  targetVersion?: string;
@@ -66,7 +65,6 @@ export function buildNavigatorNativeAttrs(
66
65
  if (options.page) result.page = options.page;
67
66
  if (options.target) result.target = options.target;
68
67
  if (options.appId) result["app-id"] = options.appId;
69
- if (options.path) result.path = options.path;
70
68
  if (options.query) result.query = JSON.stringify(options.query);
71
69
  if (options.envVersion) result["env-version"] = options.envVersion;
72
70
  if (options.targetVersion) result["target-version"] = options.targetVersion;
package/src/navigator.ts CHANGED
@@ -36,8 +36,7 @@ type LingXiaBridgeCall = {
36
36
  export type LxNavigatorAttributes = {
37
37
  // Navigation
38
38
  url?: string; // Browser URL for openUrl/browser target
39
- page?: string; // Named page in lxapp.json
40
- path?: string; // Raw page path, supports query string
39
+ page?: string; // Configured page name from lxapp.json; routes are unsupported
41
40
  query?: string; // JSON-encoded page query params
42
41
  'open-type'?: NavigatorOpenType; // Navigation type
43
42
  target?: NavigatorTarget; // Navigation target (auto-inferred if not specified)
@@ -85,7 +84,6 @@ export class LxNavigatorElement extends HTMLElement {
85
84
  return [
86
85
  "url",
87
86
  "page",
88
- "path",
89
87
  "query",
90
88
  "open-type",
91
89
  "target",
@@ -257,6 +255,8 @@ export class LxNavigatorElement extends HTMLElement {
257
255
 
258
256
  const url = this.getAttribute('url') || '';
259
257
  const page = this.getAttribute('page');
258
+ // Read the removed attribute only to provide a forward-only runtime error
259
+ // for untyped HTML callers instead of silently ignoring it.
260
260
  const path = this.getAttribute('path');
261
261
  const query = this.getAttribute('query');
262
262
  const openType = (this.getAttribute('open-type') || 'navigate') as NavigatorOpenType;
@@ -422,6 +422,10 @@ export class LxNavigatorElement extends HTMLElement {
422
422
  const url = options.url || '';
423
423
  const delta = Number.isFinite(options.delta) && options.delta > 0 ? options.delta : 1;
424
424
 
425
+ if (options.path !== null && options.path !== undefined) {
426
+ throw new Error('path is not supported; pass the configured page name in page');
427
+ }
428
+
425
429
  if (options.openType === 'tel') {
426
430
  if (!options.phoneNumber) {
427
431
  throw new Error('tel requires phone-number attribute');
@@ -431,13 +435,13 @@ export class LxNavigatorElement extends HTMLElement {
431
435
  }
432
436
 
433
437
  if (options.openType === 'exit') {
434
- await this.callHost('navigator.navigateBackLxApp');
438
+ await this.callHost('navigator.navigateBackApp');
435
439
  return;
436
440
  }
437
441
 
438
442
  if (options.openType === 'navigateBack') {
439
443
  if (options.target === 'lxapp') {
440
- await this.callHost('navigator.navigateBackLxApp');
444
+ await this.callHost('navigator.navigateBackApp');
441
445
  return;
442
446
  }
443
447
  if (options.target === 'browser') {
@@ -457,9 +461,9 @@ export class LxNavigatorElement extends HTMLElement {
457
461
 
458
462
  if (options.target === 'lxapp') {
459
463
  if (!options.appId) {
460
- throw new Error('navigateToLxApp requires app-id');
464
+ throw new Error('navigateToApp requires app-id');
461
465
  }
462
- await this.callHost('navigator.navigateToLxApp', this.buildLxAppTarget(options));
466
+ await this.callHost('navigator.navigateToApp', this.buildLxAppTarget(options));
463
467
  return;
464
468
  }
465
469
 
@@ -473,7 +477,7 @@ export class LxNavigatorElement extends HTMLElement {
473
477
 
474
478
  const target = this.buildPageTarget(options);
475
479
  if (!target) {
476
- throw new Error(`${options.openType} requires page or path`);
480
+ throw new Error(`${options.openType} requires page`);
477
481
  }
478
482
 
479
483
  switch (options.openType) {
@@ -511,18 +515,13 @@ export class LxNavigatorElement extends HTMLElement {
511
515
 
512
516
  private buildPageTarget(options: {
513
517
  page?: string | null;
514
- path?: string | null;
515
518
  query?: string | null;
516
- }): { page?: string; path?: string; query?: NavigatorQuery } | null {
519
+ }): { page: string; query?: NavigatorQuery } | null {
517
520
  const page = options.page?.trim();
518
- const path = options.path?.trim();
519
- if (page && path) {
520
- throw new Error('pass either page or path, not both');
521
- }
522
- if (!page && !path) return null;
521
+ if (!page) return null;
523
522
  const query = this.readQuery(options.query);
524
523
  return {
525
- ...(page ? { page } : { path: path! }),
524
+ page,
526
525
  ...(query ? { query } : {}),
527
526
  };
528
527
  }
@@ -530,7 +529,6 @@ export class LxNavigatorElement extends HTMLElement {
530
529
  private buildLxAppTarget(options: {
531
530
  appId?: string | null;
532
531
  page?: string | null;
533
- path?: string | null;
534
532
  query?: string | null;
535
533
  envVersion?: NavigatorEnvVersion | null;
536
534
  targetVersion?: string | null;
package/src/video.ts CHANGED
@@ -106,6 +106,20 @@ export class LxVideoElement extends HTMLElement {
106
106
  private iOSScrollEventListener: EventListenerObject = {
107
107
  handleEvent: () => this.boundUpdatePosition(),
108
108
  };
109
+ private scrollSettleFrame: number | null = null;
110
+ // Scroll events do not bubble, so a plain window listener misses inner
111
+ // scroll containers; the capture phase sees them all. Any ancestor
112
+ // scrolling moves the element's document rect, so re-measure (coalesced
113
+ // to one update per frame; decide() dedups unchanged rects).
114
+ private containerScrollListener: EventListenerObject = {
115
+ handleEvent: () => {
116
+ if (this.scrollSettleFrame !== null) return;
117
+ this.scrollSettleFrame = requestAnimationFrame(() => {
118
+ this.scrollSettleFrame = null;
119
+ this.updatePosition();
120
+ });
121
+ },
122
+ };
109
123
  private rawHandlers: Record<string, EventListenerOrEventListenerObject> = {};
110
124
  private _pageBindings: Record<string, string> = {};
111
125
 
@@ -641,6 +655,11 @@ export class LxVideoElement extends HTMLElement {
641
655
  window.addEventListener("resize", this.resizeEventListener);
642
656
  if (isIOS()) {
643
657
  window.addEventListener("scroll", this.iOSScrollEventListener, { passive: true });
658
+ } else if (isWindows()) {
659
+ window.addEventListener("scroll", this.containerScrollListener, {
660
+ capture: true,
661
+ passive: true,
662
+ });
644
663
  }
645
664
  if (isAndroid()) {
646
665
  this.removeLayoutInvalidationListener = addNativeComponentLayoutInvalidationListener(this.resizeEventListener);
@@ -653,10 +672,16 @@ export class LxVideoElement extends HTMLElement {
653
672
  window.removeEventListener("resize", this.resizeEventListener);
654
673
  if (isIOS()) {
655
674
  window.removeEventListener("scroll", this.iOSScrollEventListener);
675
+ } else if (isWindows()) {
676
+ window.removeEventListener("scroll", this.containerScrollListener, { capture: true });
656
677
  }
657
678
  this.removeLayoutInvalidationListener?.();
658
679
  this.removeLayoutInvalidationListener = undefined;
659
680
  this.stopSizeObserver();
681
+ if (this.scrollSettleFrame !== null) {
682
+ cancelAnimationFrame(this.scrollSettleFrame);
683
+ this.scrollSettleFrame = null;
684
+ }
660
685
  if (this.winSettleFrame !== null) {
661
686
  cancelAnimationFrame(this.winSettleFrame);
662
687
  this.winSettleFrame = null;