@blotch/angular-lynx 22.2.3 → 22.2.4

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.
@@ -3,7 +3,7 @@ import { ApplicationRef, Component, DOCUMENT, DestroyRef, Directive, ElementRef,
3
3
  import { ReplaySubject, Subject, firstValueFrom } from "rxjs";
4
4
  import { APP_BASE_HREF, IMAGE_CONFIG, Location, LocationStrategy, PlatformLocation, getLocaleId } from "@angular/common";
5
5
  import { NG_VALUE_ACCESSOR } from "@angular/forms";
6
- import { provideRouter as provideRouter$1, withRouterConfig } from "@angular/router";
6
+ import { RouterLinkActive, provideRouter as provideRouter$1, withRouterConfig } from "@angular/router";
7
7
  import { bootstrapApplication as bootstrapApplication$1 } from "@angular/platform-browser";
8
8
  const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9
9
  const VALUES = new Map(Array.from(ALPHABET, (char, index) => [char, index]));
@@ -241,6 +241,7 @@ const handlers = {
241
241
  registerJSModule: (name, module) => {
242
242
  lynxApi("registerModule")(name, restoreFunctions(module));
243
243
  },
244
+ osVersion: () => typeof SystemInfo !== "undefined" ? SystemInfo.osVersion : void 0,
244
245
  fetch: (id, request) => fetchForMainThread(id, request),
245
246
  abortFetch: (id) => abortFetchForMainThread(id)
246
247
  };
@@ -512,6 +513,121 @@ i0.ɵɵngDeclareClassMetadata({
512
513
  args: [{ providedIn: "root" }]
513
514
  }]
514
515
  });
516
+ const initDataUpdates = new Subject();
517
+ const globalDataUpdates = new Subject();
518
+ const asRecord = (data) => typeof data === "object" && data !== null ? data : {};
519
+ const applyInitDataUpdate = (data, reset) => {
520
+ const host = lynx;
521
+ const next = {
522
+ ...reset ? {} : host.__initData,
523
+ ...asRecord(data)
524
+ };
525
+ host.__initData = next;
526
+ initDataUpdates.next(next);
527
+ return next;
528
+ };
529
+ const applyGlobalDataUpdate = (data) => {
530
+ const next = {
531
+ ...lynx.__globalProps,
532
+ ...asRecord(data)
533
+ };
534
+ lynx.__globalProps = next;
535
+ globalDataUpdates.next(next);
536
+ return next;
537
+ };
538
+ var LynxGlobalData = class LynxGlobalData {
539
+ globalData = signal(typeof lynx !== "undefined" && lynx.__globalProps || {}, ...ngDevMode ? [{ debugName: "globalData" }] : /* istanbul ignore next */ []);
540
+ constructor() {
541
+ const subscription = globalDataUpdates.subscribe((data) => this.globalData.set(data));
542
+ inject(DestroyRef).onDestroy(() => subscription.unsubscribe());
543
+ }
544
+ static ɵfac = i0.ɵɵngDeclareFactory({
545
+ minVersion: "12.0.0",
546
+ version: "22.2.1",
547
+ ngImport: i0,
548
+ type: LynxGlobalData,
549
+ deps: [],
550
+ target: i0.ɵɵFactoryTarget.Injectable
551
+ });
552
+ static ɵprov = i0.ɵɵngDeclareInjectable({
553
+ minVersion: "12.0.0",
554
+ version: "22.2.1",
555
+ ngImport: i0,
556
+ type: LynxGlobalData,
557
+ providedIn: "root"
558
+ });
559
+ };
560
+ i0.ɵɵngDeclareClassMetadata({
561
+ minVersion: "12.0.0",
562
+ version: "22.2.1",
563
+ ngImport: i0,
564
+ type: LynxGlobalData,
565
+ decorators: [{
566
+ type: Injectable,
567
+ args: [{ providedIn: "root" }]
568
+ }],
569
+ ctorParameters: () => []
570
+ });
571
+ const MEDIA_QUERIES = {
572
+ reduceMotion: "(prefers-reduced-motion: reduce)",
573
+ reduceTransparency: "(prefers-reduced-transparency: reduce)",
574
+ increaseContrast: "(prefers-contrast: more)"
575
+ };
576
+ const isOn = (data, setting) => data[setting] === true || data[setting] === "true";
577
+ const pageWindow = () => {
578
+ if (!__WEB__ || typeof __GetPageElement !== "function") return void 0;
579
+ return __GetPageElement()?.ownerDocument?.defaultView ?? void 0;
580
+ };
581
+ const watchMediaQueries = (destroyRef) => {
582
+ const win = pageWindow();
583
+ const signals = {};
584
+ for (const setting of Object.keys(MEDIA_QUERIES)) {
585
+ const query = typeof win?.matchMedia === "function" ? win.matchMedia(MEDIA_QUERIES[setting]) : void 0;
586
+ const matches = signal(query?.matches ?? false, ...ngDevMode ? [{ debugName: "matches" }] : /* istanbul ignore next */ []);
587
+ if (query) {
588
+ const update = () => matches.set(query.matches);
589
+ query.addEventListener("change", update);
590
+ destroyRef.onDestroy(() => query.removeEventListener("change", update));
591
+ }
592
+ signals[setting] = matches.asReadonly();
593
+ }
594
+ return signals;
595
+ };
596
+ var LynxAccessibilitySettings = class LynxAccessibilitySettings {
597
+ #globalData = inject(LynxGlobalData);
598
+ #media = watchMediaQueries(inject(DestroyRef));
599
+ reduceMotion = this.#setting("reduceMotion");
600
+ reduceTransparency = this.#setting("reduceTransparency");
601
+ increaseContrast = this.#setting("increaseContrast");
602
+ #setting(setting) {
603
+ return computed(() => isOn(this.#globalData.globalData(), setting) || this.#media[setting]());
604
+ }
605
+ static ɵfac = i0.ɵɵngDeclareFactory({
606
+ minVersion: "12.0.0",
607
+ version: "22.2.1",
608
+ ngImport: i0,
609
+ type: LynxAccessibilitySettings,
610
+ deps: [],
611
+ target: i0.ɵɵFactoryTarget.Injectable
612
+ });
613
+ static ɵprov = i0.ɵɵngDeclareInjectable({
614
+ minVersion: "12.0.0",
615
+ version: "22.2.1",
616
+ ngImport: i0,
617
+ type: LynxAccessibilitySettings,
618
+ providedIn: "root"
619
+ });
620
+ };
621
+ i0.ɵɵngDeclareClassMetadata({
622
+ minVersion: "12.0.0",
623
+ version: "22.2.1",
624
+ ngImport: i0,
625
+ type: LynxAccessibilitySettings,
626
+ decorators: [{
627
+ type: Injectable,
628
+ args: [{ providedIn: "root" }]
629
+ }]
630
+ });
515
631
  var LynxPerformance = class LynxPerformance {
516
632
  #perf = this.#resolve();
517
633
  #resolve() {
@@ -646,61 +762,6 @@ const registerDataProcessors = (definition) => {
646
762
  }
647
763
  };
648
764
  };
649
- const initDataUpdates = new Subject();
650
- const globalDataUpdates = new Subject();
651
- const asRecord = (data) => typeof data === "object" && data !== null ? data : {};
652
- const applyInitDataUpdate = (data, reset) => {
653
- const host = lynx;
654
- const next = {
655
- ...reset ? {} : host.__initData,
656
- ...asRecord(data)
657
- };
658
- host.__initData = next;
659
- initDataUpdates.next(next);
660
- return next;
661
- };
662
- const applyGlobalDataUpdate = (data) => {
663
- const next = {
664
- ...lynx.__globalProps,
665
- ...asRecord(data)
666
- };
667
- lynx.__globalProps = next;
668
- globalDataUpdates.next(next);
669
- return next;
670
- };
671
- var LynxGlobalData = class LynxGlobalData {
672
- globalData = signal(typeof lynx !== "undefined" && lynx.__globalProps || {}, ...ngDevMode ? [{ debugName: "globalData" }] : /* istanbul ignore next */ []);
673
- constructor() {
674
- const subscription = globalDataUpdates.subscribe((data) => this.globalData.set(data));
675
- inject(DestroyRef).onDestroy(() => subscription.unsubscribe());
676
- }
677
- static ɵfac = i0.ɵɵngDeclareFactory({
678
- minVersion: "12.0.0",
679
- version: "22.2.1",
680
- ngImport: i0,
681
- type: LynxGlobalData,
682
- deps: [],
683
- target: i0.ɵɵFactoryTarget.Injectable
684
- });
685
- static ɵprov = i0.ɵɵngDeclareInjectable({
686
- minVersion: "12.0.0",
687
- version: "22.2.1",
688
- ngImport: i0,
689
- type: LynxGlobalData,
690
- providedIn: "root"
691
- });
692
- };
693
- i0.ɵɵngDeclareClassMetadata({
694
- minVersion: "12.0.0",
695
- version: "22.2.1",
696
- ngImport: i0,
697
- type: LynxGlobalData,
698
- decorators: [{
699
- type: Injectable,
700
- args: [{ providedIn: "root" }]
701
- }],
702
- ctorParameters: () => []
703
- });
704
765
  var LynxInitData = class LynxInitData {
705
766
  initData = signal(typeof lynx !== "undefined" && lynx.__initData || {}, ...ngDevMode ? [{ debugName: "initData" }] : /* istanbul ignore next */ []);
706
767
  constructor() {
@@ -3304,6 +3365,43 @@ i0.ɵɵngDeclareClassMetadata({
3304
3365
  }]
3305
3366
  }]
3306
3367
  });
3368
+ const ROUTER_LINK_ACTIVE_CHANGE = new InjectionToken("router-link-active-change");
3369
+ var LynxRouterLinkActive = class LynxRouterLinkActive {
3370
+ constructor() {
3371
+ const activeChange = inject(ROUTER_LINK_ACTIVE_CHANGE, { optional: true })?.();
3372
+ if (!activeChange) return;
3373
+ const element = inject(ElementRef).nativeElement;
3374
+ const subscription = activeChange.subscribe((active) => element.setAccessibilityTrait("selected", active));
3375
+ inject(DestroyRef).onDestroy(() => subscription.unsubscribe());
3376
+ }
3377
+ static ɵfac = i0.ɵɵngDeclareFactory({
3378
+ minVersion: "12.0.0",
3379
+ version: "22.2.1",
3380
+ ngImport: i0,
3381
+ type: LynxRouterLinkActive,
3382
+ deps: [],
3383
+ target: i0.ɵɵFactoryTarget.Directive
3384
+ });
3385
+ static ɵdir = i0.ɵɵngDeclareDirective({
3386
+ minVersion: "14.0.0",
3387
+ version: "22.2.1",
3388
+ type: LynxRouterLinkActive,
3389
+ isStandalone: true,
3390
+ selector: "[routerLinkActive]",
3391
+ ngImport: i0
3392
+ });
3393
+ };
3394
+ i0.ɵɵngDeclareClassMetadata({
3395
+ minVersion: "12.0.0",
3396
+ version: "22.2.1",
3397
+ ngImport: i0,
3398
+ type: LynxRouterLinkActive,
3399
+ decorators: [{
3400
+ type: Directive,
3401
+ args: [{ selector: "[routerLinkActive]" }]
3402
+ }],
3403
+ ctorParameters: () => []
3404
+ });
3307
3405
  const LYNX_ELEMENTS = [
3308
3406
  LynxView,
3309
3407
  LynxText,
@@ -3335,7 +3433,8 @@ const LYNX_ELEMENTS = [
3335
3433
  LynxVideo,
3336
3434
  LynxWebView,
3337
3435
  LynxCoverView,
3338
- LynxTitleBarView
3436
+ LynxTitleBarView,
3437
+ LynxRouterLinkActive
3339
3438
  ];
3340
3439
  const LOG_EVENT = "__lynx_log__";
3341
3440
  const logUrl = () => __DEV__ && typeof __DEV_LOG_URL__ !== "undefined" ? __DEV_LOG_URL__ : "";
@@ -3942,12 +4041,21 @@ i0.ɵɵngDeclareClassMetadata({
3942
4041
  args: [{ providedIn: "root" }]
3943
4042
  }]
3944
4043
  });
4044
+ const hostOsVersion = () => {
4045
+ const value = typeof lynx !== "undefined" ? lynx.__globalProps?.["osVersion"] : void 0;
4046
+ return typeof value === "string" && value !== "" ? value : void 0;
4047
+ };
3945
4048
  var LynxSystemInfo = class LynxSystemInfo {
3946
4049
  #info;
4050
+ #osVersion = signal(void 0, ...ngDevMode ? [{ debugName: "#osVersion" }] : /* istanbul ignore next */ []);
3947
4051
  constructor() {
3948
4052
  const info = (typeof lynx !== "undefined" ? lynx.SystemInfo : void 0) ?? (typeof SystemInfo !== "undefined" ? SystemInfo : void 0);
3949
4053
  if (!info) throw new Error("SystemInfo is not available in this environment");
3950
4054
  this.#info = info;
4055
+ this.#osVersion.set(info.osVersion || hostOsVersion());
4056
+ if (this.#osVersion() === void 0 && isMainThread()) callOnBackground("osVersion").then((version) => {
4057
+ if (version) this.#osVersion.set(version);
4058
+ }, () => {});
3951
4059
  }
3952
4060
  get platform() {
3953
4061
  return this.#info.platform;
@@ -3956,7 +4064,7 @@ var LynxSystemInfo = class LynxSystemInfo {
3956
4064
  return this.#info.engineVersion;
3957
4065
  }
3958
4066
  get osVersion() {
3959
- return this.#info.osVersion;
4067
+ return this.#osVersion() ?? "";
3960
4068
  }
3961
4069
  get pixelWidth() {
3962
4070
  return this.#info.pixelWidth;
@@ -4673,7 +4781,7 @@ const isAndroid = () => {
4673
4781
  const createBlurViewElement = (pageId) => {
4674
4782
  const element = __CreateElement("blur-view", pageId);
4675
4783
  if (!__WEB__ && isAndroid()) __SetAttribute(element, "android-capture-target", ANDROID_BLUR_CAPTURE_TARGET);
4676
- if (__WEB__ && __MAIN_THREAD__) import("./blotch-angular-lynx-web-glass-8MFrhPz0.mjs").then(({ attachWebGlass }) => attachWebGlass(element)).catch(() => {});
4784
+ if (__WEB__ && __MAIN_THREAD__) import("./blotch-angular-lynx-web-glass-ciDHw7Bw.mjs").then(({ attachWebGlass }) => attachWebGlass(element)).catch(() => {});
4677
4785
  return element;
4678
4786
  };
4679
4787
  const createCommentElement = (pageId) => {
@@ -4884,6 +4992,61 @@ const sanitizeSvgContent = (content) => {
4884
4992
  return normalized === null ? before : `${before}stroke-dasharray:${normalized};`;
4885
4993
  });
4886
4994
  };
4995
+ const LONG_PRESS_SLOP = 10;
4996
+ const TAP_GRACE = 300;
4997
+ let tapsDropped = false;
4998
+ let longPresses = 0;
4999
+ const dropsTap = () => tapsDropped;
5000
+ const pointOf = (event) => {
5001
+ const { x = 0, y = 0 } = typeof event.detail === "object" && event.detail !== null ? event.detail : event;
5002
+ return {
5003
+ x,
5004
+ y
5005
+ };
5006
+ };
5007
+ var WebLongPress = class {
5008
+ #fire;
5009
+ #timer;
5010
+ #start = null;
5011
+ #fired = false;
5012
+ constructor(fire) {
5013
+ this.#fire = fire;
5014
+ }
5015
+ start = (event) => {
5016
+ if (event.button !== void 0 && event.button !== 0) return;
5017
+ this.#stop();
5018
+ this.#fired = false;
5019
+ const point = pointOf(event);
5020
+ this.#start = point;
5021
+ this.#timer = setTimeout(() => {
5022
+ this.#timer = void 0;
5023
+ this.#fired = true;
5024
+ longPresses++;
5025
+ tapsDropped = true;
5026
+ this.#fire(point);
5027
+ }, 500);
5028
+ };
5029
+ move = (event) => {
5030
+ if (!this.#start) return;
5031
+ const { x, y } = pointOf(event);
5032
+ if (Math.hypot(x - this.#start.x, y - this.#start.y) > LONG_PRESS_SLOP) this.#stop();
5033
+ };
5034
+ end = () => {
5035
+ this.#stop();
5036
+ this.#start = null;
5037
+ if (this.#fired) {
5038
+ this.#fired = false;
5039
+ const longPress = longPresses;
5040
+ setTimeout(() => {
5041
+ if (longPress === longPresses) tapsDropped = false;
5042
+ }, TAP_GRACE);
5043
+ }
5044
+ };
5045
+ #stop() {
5046
+ if (this.#timer !== void 0) clearTimeout(this.#timer);
5047
+ this.#timer = void 0;
5048
+ }
5049
+ };
4887
5050
  const EVENT_PREFIXES = [
4888
5051
  ["capture-bind", "capture-bindEvent"],
4889
5052
  ["capture-catch", "capture-catchEvent"],
@@ -4891,12 +5054,57 @@ const EVENT_PREFIXES = [
4891
5054
  ["catch", "catchEvent"],
4892
5055
  ["bind", "bindEvent"]
4893
5056
  ];
5057
+ const DOM_EVENT_ALIASES = /* @__PURE__ */ new Map([["click", "tap"]]);
4894
5058
  var _a;
5059
+ const nativeEventKey = (type, name) => type === "global-bindEvent" ? `global:${name}` : name;
5060
+ const combinedEventType = (listeners) => {
5061
+ if (listeners[0].eventType === "global-bindEvent") return "global-bindEvent";
5062
+ const capture = listeners.every((l) => l.eventType.startsWith("capture-"));
5063
+ const stops = listeners.some((l) => l.eventType.endsWith("catchEvent"));
5064
+ if (capture) return stops ? "capture-catchEvent" : "capture-bindEvent";
5065
+ return stops ? "catchEvent" : "bindEvent";
5066
+ };
5067
+ const parseEventName = (name) => {
5068
+ const alias = DOM_EVENT_ALIASES.get(name);
5069
+ if (alias) return {
5070
+ eventType: "bindEvent",
5071
+ eventName: alias
5072
+ };
5073
+ for (const [prefix, eventType] of EVENT_PREFIXES) if (name.startsWith(prefix)) return {
5074
+ eventType,
5075
+ eventName: name.slice(prefix.length)
5076
+ };
5077
+ };
5078
+ const withAddedTraits = (own, added) => {
5079
+ if (added.length === 0 || isAndroid()) return own;
5080
+ const traits = own == null ? [] : String(own).split(",").map((trait) => trait.trim()).filter((trait) => trait !== "" && trait !== "none");
5081
+ for (const trait of added) if (!traits.includes(trait)) traits.push(trait);
5082
+ return traits.join(",");
5083
+ };
4895
5084
  const wouldFormCycle = (parent, candidate) => {
4896
5085
  const candidateId = __GetElementUniqueID(candidate);
4897
5086
  for (let cur = parent; cur; cur = __GetParent(cur)) if (__GetElementUniqueID(cur) === candidateId) return true;
4898
5087
  return false;
4899
5088
  };
5089
+ const ancestry = (element) => {
5090
+ const path = [];
5091
+ for (let cur = element; cur; cur = __GetParent(cur)) path.push(cur);
5092
+ return path;
5093
+ };
5094
+ const flushesBefore = (first, second) => {
5095
+ const firstPath = ancestry(first);
5096
+ const secondPath = ancestry(second);
5097
+ const secondDepth = new Map(secondPath.map((element, depth) => [__GetElementUniqueID(element), depth]));
5098
+ for (let depth = 0; depth < firstPath.length; depth++) {
5099
+ const shared = secondDepth.get(__GetElementUniqueID(firstPath[depth]));
5100
+ if (shared === void 0) continue;
5101
+ if (depth === 0) return true;
5102
+ if (shared === 0) return false;
5103
+ const order = __GetChildren(firstPath[depth]).map((child) => __GetElementUniqueID(child));
5104
+ return order.indexOf(__GetElementUniqueID(firstPath[depth - 1])) < order.indexOf(__GetElementUniqueID(secondPath[shared - 1]));
5105
+ }
5106
+ return false;
5107
+ };
4900
5108
  const isTextish = (el) => el.tagName === "text" || el.tagName === "raw-text";
4901
5109
  var LynxElement = class {
4902
5110
  #nativeRef;
@@ -4917,7 +5125,11 @@ var LynxElement = class {
4917
5125
  #inlineStyleWhole = null;
4918
5126
  #inlineStyleKeys = /* @__PURE__ */ new Map();
4919
5127
  #runtimeStyle = "";
5128
+ #ownTraits = null;
5129
+ #addedTraits = [];
4920
5130
  #listeners = [];
5131
+ #webLongPress = null;
5132
+ #nativeHandlers = /* @__PURE__ */ new Map();
4921
5133
  #text;
4922
5134
  #rawText;
4923
5135
  #children = [];
@@ -4967,6 +5179,10 @@ var LynxElement = class {
4967
5179
  this.#dataset[key] = value;
4968
5180
  } else {
4969
5181
  if (this.tagName === "svg" && name === "content" && typeof value === "string") value = sanitizeSvgContent(value);
5182
+ if (name === "accessibility-traits") {
5183
+ this.#ownTraits = value ?? null;
5184
+ value = withAddedTraits(this.#ownTraits, this.#addedTraits);
5185
+ }
4970
5186
  __SetAttribute(this.element, name, value);
4971
5187
  if (value == null) this.#attrs.delete(name);
4972
5188
  else this.#attrs.set(name, value);
@@ -4982,6 +5198,11 @@ var LynxElement = class {
4982
5198
  updateBlurMaterial() {
4983
5199
  if (usesAndroidBlurMaterials()) this.#setRuntimeStyle(androidBlurMaterialStyle(this.#attrs));
4984
5200
  }
5201
+ setAccessibilityTrait(trait, on) {
5202
+ if (this.#addedTraits.includes(trait) === on) return;
5203
+ this.#addedTraits = on ? [...this.#addedTraits, trait] : this.#addedTraits.filter((added) => added !== trait);
5204
+ this.setAttribute("accessibility-traits", this.#ownTraits);
5205
+ }
4985
5206
  getAttribute(name) {
4986
5207
  return __GetAttributeByName(this.element, name);
4987
5208
  }
@@ -5013,6 +5234,7 @@ var LynxElement = class {
5013
5234
  insertBefore(newChild, refChild) {
5014
5235
  if (newChild.isRootPageElement) return;
5015
5236
  newChild.#cancelPendingRemoval();
5237
+ newChild.#removeIfMoveWouldBeLost(this);
5016
5238
  newChild.#recreateIfDead();
5017
5239
  if (refChild == null) this.appendChild(newChild);
5018
5240
  else {
@@ -5025,6 +5247,7 @@ var LynxElement = class {
5025
5247
  appendChild(newChild) {
5026
5248
  if (newChild.isRootPageElement) return;
5027
5249
  newChild.#cancelPendingRemoval();
5250
+ newChild.#removeIfMoveWouldBeLost(this);
5028
5251
  newChild.#recreateIfDead();
5029
5252
  if (wouldFormCycle(this.element, newChild.element)) return;
5030
5253
  __AppendElement(this.element, newChild.element);
@@ -5128,6 +5351,12 @@ var LynxElement = class {
5128
5351
  #cancelPendingRemoval() {
5129
5352
  _a.#pendingRemovals.delete(this);
5130
5353
  }
5354
+ #removeIfMoveWouldBeLost(newParent) {
5355
+ if (__WEB__ || this.#paintingDead || this._virtualParent) return;
5356
+ const oldParent = __GetParent(this.element);
5357
+ if (!oldParent || __GetElementUniqueID(oldParent) === __GetElementUniqueID(newParent.element)) return;
5358
+ if (flushesBefore(newParent.element, oldParent)) this.#doRemove();
5359
+ }
5131
5360
  #doRemove() {
5132
5361
  const parent = this.parentNode();
5133
5362
  if (!parent) return;
@@ -5173,9 +5402,9 @@ var LynxElement = class {
5173
5402
  const inlineStyle = this.#withRuntimeStyle(this.#inlineStyleWhole);
5174
5403
  if (inlineStyle != null) __SetInlineStyles(fresh, inlineStyle);
5175
5404
  for (const [key, value] of this.#inlineStyleKeys) __AddInlineStyle(fresh, key, value);
5176
- for (const { eventType, eventName, listener } of this.#listeners) __AddEvent(fresh, eventType, eventName, {
5405
+ for (const { eventType, eventName, dispatch } of this.#nativeHandlers.values()) __AddEvent(fresh, eventType, eventName, {
5177
5406
  type: "worklet",
5178
- value: listener
5407
+ value: dispatch
5179
5408
  });
5180
5409
  for (const child of this.#children) {
5181
5410
  child.#recreateSubtree();
@@ -5213,40 +5442,87 @@ var LynxElement = class {
5213
5442
  return anim;
5214
5443
  }
5215
5444
  addEventListener(name, cb) {
5216
- let eventName = "";
5217
- let eventType;
5218
- for (const [prefix, type] of EVENT_PREFIXES) if (name.startsWith(prefix)) {
5219
- eventName = name.slice(prefix.length);
5220
- eventType = type;
5221
- break;
5222
- }
5223
- if (!eventType) return () => {};
5224
- const listener = (event) => {
5225
- if (event && typeof event === "object") {
5226
- if (typeof event.stopPropagation !== "function") event.stopPropagation = () => {};
5227
- if (typeof event.preventDefault !== "function") event.preventDefault = () => {};
5228
- if (typeof event.stopImmediatePropagation !== "function") event.stopImmediatePropagation = () => {};
5229
- }
5230
- const result = cb(event);
5231
- scheduleSettleFlush();
5232
- return result;
5233
- };
5445
+ const parsed = parseEventName(name);
5446
+ if (!parsed) return () => {};
5447
+ if (__WEB__ && parsed.eventName === "longpress") this.#listenForWebLongPress();
5234
5448
  const entry = {
5235
- eventType,
5236
- eventName,
5237
- listener
5449
+ ...parsed,
5450
+ listener: cb
5238
5451
  };
5239
5452
  this.#listeners.push(entry);
5240
- __AddEvent(this.element, eventType, eventName, {
5241
- type: "worklet",
5242
- value: listener
5453
+ this.#syncNativeHandler(entry);
5454
+ return () => this.#removeListener(entry);
5455
+ }
5456
+ removeEventListener(name, cb) {
5457
+ const parsed = parseEventName(name);
5458
+ if (!parsed) return;
5459
+ const entry = this.#listeners.find((other) => other.listener === cb && other.eventType === parsed.eventType && other.eventName === parsed.eventName);
5460
+ if (entry) this.#removeListener(entry);
5461
+ }
5462
+ #listenForWebLongPress() {
5463
+ if (this.#webLongPress) return;
5464
+ const press = new WebLongPress((detail) => {
5465
+ const entry = this.#listeners.find((listener) => listener.eventName === "longpress");
5466
+ if (entry) this.#dispatch(entry, {
5467
+ type: "longpress",
5468
+ detail
5469
+ });
5243
5470
  });
5244
- return () => {
5245
- const i = this.#listeners.indexOf(entry);
5246
- /* v8 ignore next */
5247
- if (i >= 0) this.#listeners.splice(i, 1);
5248
- __AddEvent(this.element, eventType, eventName, void 0);
5471
+ this.#webLongPress = press;
5472
+ this.addEventListener("bindtouchstart", press.start);
5473
+ this.addEventListener("bindmousedown", press.start);
5474
+ this.addEventListener("bindtouchmove", press.move);
5475
+ this.addEventListener("bindmousemove", press.move);
5476
+ for (const end of [
5477
+ "touchend",
5478
+ "touchcancel",
5479
+ "mouseup",
5480
+ "mouseleave"
5481
+ ]) this.addEventListener(`bind${end}`, press.end);
5482
+ }
5483
+ #removeListener(entry) {
5484
+ const i = this.#listeners.indexOf(entry);
5485
+ if (i < 0) return;
5486
+ this.#listeners.splice(i, 1);
5487
+ this.#syncNativeHandler(entry);
5488
+ }
5489
+ #listenersLike(entry) {
5490
+ const key = nativeEventKey(entry.eventType, entry.eventName);
5491
+ return this.#listeners.filter((other) => nativeEventKey(other.eventType, other.eventName) === key);
5492
+ }
5493
+ #syncNativeHandler(entry) {
5494
+ const key = nativeEventKey(entry.eventType, entry.eventName);
5495
+ const listeners = this.#listenersLike(entry);
5496
+ const current = this.#nativeHandlers.get(key);
5497
+ const eventType = listeners.length ? combinedEventType(listeners) : null;
5498
+ if (current?.eventType === eventType) return;
5499
+ if (current) {
5500
+ __AddEvent(this.element, current.eventType, entry.eventName, void 0);
5501
+ this.#nativeHandlers.delete(key);
5502
+ }
5503
+ if (!eventType) return;
5504
+ const handler = {
5505
+ eventType,
5506
+ eventName: entry.eventName,
5507
+ dispatch: current?.dispatch ?? ((event) => this.#dispatch(entry, event))
5249
5508
  };
5509
+ this.#nativeHandlers.set(key, handler);
5510
+ __AddEvent(this.element, eventType, entry.eventName, {
5511
+ type: "worklet",
5512
+ value: handler.dispatch
5513
+ });
5514
+ }
5515
+ #dispatch(entry, event) {
5516
+ if (event && typeof event === "object") {
5517
+ if (typeof event.stopPropagation !== "function") event.stopPropagation = () => {};
5518
+ if (typeof event.preventDefault !== "function") event.preventDefault = () => {};
5519
+ if (typeof event.stopImmediatePropagation !== "function") event.stopImmediatePropagation = () => {};
5520
+ }
5521
+ if (__WEB__ && entry.eventName === "tap" && dropsTap()) return void 0;
5522
+ let result;
5523
+ for (const other of this.#listenersLike(entry)) if (this.#listeners.includes(other)) result = other.listener(event);
5524
+ scheduleSettleFlush();
5525
+ return result;
5250
5526
  }
5251
5527
  };
5252
5528
  _a = LynxElement;
@@ -6051,7 +6327,7 @@ var LynxBackButton = class LynxBackButton {
6051
6327
  Promise.resolve().then(() => shell?.setBackHandlerEnabled(enabled)).catch(() => hasShell = false);
6052
6328
  });
6053
6329
  const emitter = modules.getJSModule("GlobalEventEmitter");
6054
- Promise.resolve().then(() => emitter?.addListener(BACK_EVENT, () => setTimeout(() => location.back()))).catch(() => {});
6330
+ Promise.resolve().then(() => emitter?.addListener(BACK_EVENT, () => location.back())).catch(() => {});
6055
6331
  }
6056
6332
  static ɵfac = i0.ɵɵngDeclareFactory({
6057
6333
  minVersion: "12.0.0",
@@ -6091,7 +6367,14 @@ const provideRouter = (routes, ...features) => {
6091
6367
  useClass: LynxLocationStrategy
6092
6368
  },
6093
6369
  provideRouter$1(routes, withRouterConfig({ resolveNavigationPromiseOnError: true }), ...features),
6094
- provideEnvironmentInitializer(() => inject(LynxBackButton))
6370
+ provideEnvironmentInitializer(() => inject(LynxBackButton)),
6371
+ {
6372
+ provide: ROUTER_LINK_ACTIVE_CHANGE,
6373
+ useValue: () => inject(RouterLinkActive, {
6374
+ self: true,
6375
+ optional: true
6376
+ })?.isActiveChange ?? null
6377
+ }
6095
6378
  ]);
6096
6379
  };
6097
6380
  globalThis.__lynxLastError = "";
@@ -8079,6 +8362,6 @@ const bootstrapOnMainThread = async (rootComponent, options) => {
8079
8362
  if (__WEB__ && !wasHydrating) setTimeout(() => __FlushElementTree(), 0);
8080
8363
  return appRef;
8081
8364
  };
8082
- export { BaseGesture, ComposedGesture, ContinuousGesture, FlingDirection, FlingGesture, Gesture, GestureState, GestureStateManager, GestureType, LYNX_ELEMENTS, LYNX_FORM_ACCESSORS, LongPressGesture, LynxAccessibility, LynxAnimation, LynxBlock, LynxBlurView, LynxCoverView, LynxDevTools, LynxErrorHandler, LynxExposure, LynxFont, LynxFor, LynxFrame, LynxGestureDetector, LynxGlobalData, LynxGlobalExposure, LynxIf, LynxImage, LynxInitData, LynxInlineTruncation, LynxInput, LynxInputValueAccessor, LynxList, LynxListItem, LynxLocale, LynxLocationStrategy, LynxLogger, LynxMainThread, LynxMainThreadEvent, LynxNativeModule, LynxOverlay, LynxPerformance, LynxPlatformLocation, LynxPortal, LynxRefresh, LynxRefreshHeader, LynxResourcePrefetch, LynxRouteReuseStrategy, LynxSafeArea, LynxScrollCoordinator, LynxScrollCoordinatorHeader, LynxScrollCoordinatorSlot, LynxScrollCoordinatorSlotDrag, LynxScrollCoordinatorToolbar, LynxScrollView, LynxSessionStorage, LynxSvg, LynxSystemInfo, LynxText, LynxTextMeasure, LynxTextarea, LynxTextareaValueAccessor, LynxTheme, LynxTitleBarView, LynxTransition, LynxTransitionGroup, LynxVideo, LynxView, LynxViewPager, LynxViewPagerItem, LynxWebView, MainThreadElement, MainThreadRef, PanGesture, PinchGesture, PortalRef, RotationGesture, SAFE_AREA_INSET_BOTTOM, SAFE_AREA_INSET_LEFT, SAFE_AREA_INSET_RIGHT, SAFE_AREA_INSET_TOP, TapGesture, backgroundFn, bootstrapApplication, createMainThreadRef, getLynxAppLocale, loadLazyBundle, mainThreadFn, provideLocale, provideRenderer, provideRouter, registerDataProcessors, ɵhmrAccept, ɵstartBackgroundThread };
8365
+ export { BaseGesture, ComposedGesture, ContinuousGesture, FlingDirection, FlingGesture, Gesture, GestureState, GestureStateManager, GestureType, LYNX_ELEMENTS, LYNX_FORM_ACCESSORS, LongPressGesture, LynxAccessibility, LynxAccessibilitySettings, LynxAnimation, LynxBlock, LynxBlurView, LynxCoverView, LynxDevTools, LynxErrorHandler, LynxExposure, LynxFont, LynxFor, LynxFrame, LynxGestureDetector, LynxGlobalData, LynxGlobalExposure, LynxIf, LynxImage, LynxInitData, LynxInlineTruncation, LynxInput, LynxInputValueAccessor, LynxList, LynxListItem, LynxLocale, LynxLocationStrategy, LynxLogger, LynxMainThread, LynxMainThreadEvent, LynxNativeModule, LynxOverlay, LynxPerformance, LynxPlatformLocation, LynxPortal, LynxRefresh, LynxRefreshHeader, LynxResourcePrefetch, LynxRouteReuseStrategy, LynxRouterLinkActive, LynxSafeArea, LynxScrollCoordinator, LynxScrollCoordinatorHeader, LynxScrollCoordinatorSlot, LynxScrollCoordinatorSlotDrag, LynxScrollCoordinatorToolbar, LynxScrollView, LynxSessionStorage, LynxSvg, LynxSystemInfo, LynxText, LynxTextMeasure, LynxTextarea, LynxTextareaValueAccessor, LynxTheme, LynxTitleBarView, LynxTransition, LynxTransitionGroup, LynxVideo, LynxView, LynxViewPager, LynxViewPagerItem, LynxWebView, MainThreadElement, MainThreadRef, PanGesture, PinchGesture, PortalRef, RotationGesture, SAFE_AREA_INSET_BOTTOM, SAFE_AREA_INSET_LEFT, SAFE_AREA_INSET_RIGHT, SAFE_AREA_INSET_TOP, TapGesture, backgroundFn, bootstrapApplication, createMainThreadRef, getLynxAppLocale, loadLazyBundle, mainThreadFn, provideLocale, provideRenderer, provideRouter, registerDataProcessors, ɵhmrAccept, ɵstartBackgroundThread };
8083
8366
 
8084
8367
  //# sourceMappingURL=blotch-angular-lynx.mjs.map