@blotch/angular-lynx 22.2.9 → 22.2.10
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.
- package/README.md +2 -0
- package/fesm2022/blotch-angular-lynx.mjs +1054 -138
- package/fesm2022/blotch-angular-lynx.mjs.map +1 -1
- package/package.json +1 -1
- package/types/blotch-angular-lynx.d.ts +479 -89
|
@@ -1571,99 +1571,323 @@ const takePageHandOver = () => {
|
|
|
1571
1571
|
handingOverPage = false;
|
|
1572
1572
|
return handing;
|
|
1573
1573
|
};
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1574
|
+
var LynxEvent = class {
|
|
1575
|
+
static NONE = 0;
|
|
1576
|
+
static CAPTURING_PHASE = 1;
|
|
1577
|
+
static AT_TARGET = 2;
|
|
1578
|
+
static BUBBLING_PHASE = 3;
|
|
1579
|
+
type;
|
|
1580
|
+
bubbles;
|
|
1581
|
+
cancelable;
|
|
1582
|
+
composed;
|
|
1583
|
+
timeStamp = Date.now();
|
|
1584
|
+
isTrusted = false;
|
|
1585
|
+
target = null;
|
|
1586
|
+
currentTarget = null;
|
|
1587
|
+
eventPhase = 0;
|
|
1588
|
+
defaultPrevented = false;
|
|
1589
|
+
cancelBubble = false;
|
|
1590
|
+
constructor(type, init = {}) {
|
|
1591
|
+
this.type = String(type);
|
|
1592
|
+
this.bubbles = !!init.bubbles;
|
|
1593
|
+
this.cancelable = !!init.cancelable;
|
|
1594
|
+
this.composed = !!init.composed;
|
|
1595
|
+
}
|
|
1596
|
+
get srcElement() {
|
|
1597
|
+
return this.target;
|
|
1598
|
+
}
|
|
1599
|
+
preventDefault() {
|
|
1600
|
+
if (this.cancelable) this.defaultPrevented = true;
|
|
1601
|
+
}
|
|
1602
|
+
stopPropagation() {
|
|
1603
|
+
this.cancelBubble = true;
|
|
1604
|
+
}
|
|
1605
|
+
stopImmediatePropagation() {
|
|
1606
|
+
this.cancelBubble = true;
|
|
1607
|
+
}
|
|
1608
|
+
composedPath() {
|
|
1609
|
+
return this.currentTarget ? [this.currentTarget] : [];
|
|
1610
|
+
}
|
|
1584
1611
|
};
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1612
|
+
var LynxCustomEvent = class extends LynxEvent {
|
|
1613
|
+
detail;
|
|
1614
|
+
constructor(type, init = {}) {
|
|
1615
|
+
super(type, init);
|
|
1616
|
+
this.detail = init.detail ?? null;
|
|
1589
1617
|
}
|
|
1590
|
-
deferredCallbacks.push(callback);
|
|
1591
1618
|
};
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1619
|
+
const installEventClasses = (target) => {
|
|
1620
|
+
if (typeof target["Event"] === "undefined") target["Event"] = LynxEvent;
|
|
1621
|
+
if (typeof target["CustomEvent"] === "undefined") target["CustomEvent"] = LynxCustomEvent;
|
|
1595
1622
|
};
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1598
|
-
const DASHARRAY_DECLARATION = /(^|[;"'\s])stroke-dasharray\s*:\s*([^;"']*);?/g;
|
|
1599
|
-
const DASH_LENGTH = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(?:px)?$/i;
|
|
1600
|
-
const normalizeDashArray = (value) => {
|
|
1601
|
-
const tokens = value.trim().split(/[\s,]+/).filter((token) => token.length > 0);
|
|
1602
|
-
if (tokens.length === 0 || !tokens.every((t) => DASH_LENGTH.test(t))) return null;
|
|
1603
|
-
return tokens.map((token) => token.replace(/px$/i, "")).join(" ");
|
|
1623
|
+
const createEvent = (type) => {
|
|
1624
|
+
return new (globalThis.Event ?? LynxEvent)(type);
|
|
1604
1625
|
};
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
return normalized === null ? before : `${before}stroke-dasharray:${normalized};`;
|
|
1626
|
+
const captureOf = (options) => typeof options === "boolean" ? options : !!options?.capture;
|
|
1627
|
+
const setEventProperty = (event, name, value) => {
|
|
1628
|
+
Object.defineProperty(event, name, {
|
|
1629
|
+
value,
|
|
1630
|
+
writable: true,
|
|
1631
|
+
configurable: true,
|
|
1632
|
+
enumerable: true
|
|
1613
1633
|
});
|
|
1614
1634
|
};
|
|
1615
|
-
const
|
|
1616
|
-
const
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
right: left + width,
|
|
1625
|
-
bottom: top + height
|
|
1626
|
-
};
|
|
1627
|
-
return {
|
|
1628
|
-
...box,
|
|
1629
|
-
toJSON: () => ({ ...box })
|
|
1630
|
-
};
|
|
1635
|
+
const withProperties = (event, values, run) => {
|
|
1636
|
+
const saved = Object.keys(values).map((name) => [name, Object.getOwnPropertyDescriptor(event, name)]);
|
|
1637
|
+
for (const [name, value] of Object.entries(values)) setEventProperty(event, name, value);
|
|
1638
|
+
try {
|
|
1639
|
+
run();
|
|
1640
|
+
} finally {
|
|
1641
|
+
for (const [name, descriptor] of saved) if (descriptor) Object.defineProperty(event, name, descriptor);
|
|
1642
|
+
else delete event[name];
|
|
1643
|
+
}
|
|
1631
1644
|
};
|
|
1632
|
-
var
|
|
1633
|
-
#
|
|
1634
|
-
#
|
|
1635
|
-
#
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1645
|
+
var GlobalEventTarget = class {
|
|
1646
|
+
#entries = /* @__PURE__ */ new Map();
|
|
1647
|
+
#owner;
|
|
1648
|
+
#onTypesChange = () => {};
|
|
1649
|
+
constructor(owner) {
|
|
1650
|
+
this.#owner = owner ?? this;
|
|
1651
|
+
}
|
|
1652
|
+
set onTypesChange(callback) {
|
|
1653
|
+
this.#onTypesChange = callback;
|
|
1654
|
+
}
|
|
1655
|
+
addEventListener(type, callback, options) {
|
|
1656
|
+
if (!callback) return;
|
|
1657
|
+
const capture = captureOf(options);
|
|
1658
|
+
const signal = typeof options === "object" ? options.signal : void 0;
|
|
1659
|
+
if (signal?.aborted) return;
|
|
1660
|
+
const list = this.#entries.get(type) ?? [];
|
|
1661
|
+
if (list.some((e) => e.callback === callback && e.capture === capture)) return;
|
|
1662
|
+
const entry = {
|
|
1663
|
+
callback,
|
|
1664
|
+
capture,
|
|
1665
|
+
once: typeof options === "object" && !!options.once,
|
|
1666
|
+
unlinkSignal: null
|
|
1667
|
+
};
|
|
1668
|
+
if (signal) {
|
|
1669
|
+
const abort = () => this.#remove(type, entry);
|
|
1670
|
+
signal.addEventListener("abort", abort);
|
|
1671
|
+
entry.unlinkSignal = () => signal.removeEventListener?.("abort", abort);
|
|
1672
|
+
}
|
|
1673
|
+
list.push(entry);
|
|
1674
|
+
this.#entries.set(type, list);
|
|
1675
|
+
if (list.length === 1) this.#onTypesChange();
|
|
1639
1676
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
this.#
|
|
1643
|
-
this.#
|
|
1644
|
-
|
|
1645
|
-
|
|
1677
|
+
removeEventListener(type, callback, options) {
|
|
1678
|
+
const capture = captureOf(options);
|
|
1679
|
+
const entry = this.#entries.get(type)?.find((e) => e.callback === callback && e.capture === capture);
|
|
1680
|
+
if (entry) this.#remove(type, entry);
|
|
1681
|
+
}
|
|
1682
|
+
dispatchEvent(event) {
|
|
1683
|
+
return dispatchThrough(event, this.#owner, [this]);
|
|
1684
|
+
}
|
|
1685
|
+
get types() {
|
|
1686
|
+
return [...this.#entries.keys()];
|
|
1687
|
+
}
|
|
1688
|
+
hasListeners(type) {
|
|
1689
|
+
return this.#entries.has(type);
|
|
1690
|
+
}
|
|
1691
|
+
get owner() {
|
|
1692
|
+
return this.#owner;
|
|
1693
|
+
}
|
|
1694
|
+
invoke(type, event, phase, state) {
|
|
1695
|
+
const list = this.#entries.get(type);
|
|
1696
|
+
if (!list) return;
|
|
1697
|
+
const ordered = phase === 2 ? [...list.filter((e) => e.capture), ...list.filter((e) => !e.capture)] : list.filter((e) => e.capture === (phase === 1));
|
|
1698
|
+
withProperties(event, {
|
|
1699
|
+
currentTarget: this.#owner,
|
|
1700
|
+
eventPhase: phase
|
|
1701
|
+
}, () => this.#run(type, ordered, event, state));
|
|
1702
|
+
}
|
|
1703
|
+
#run(type, entries, event, state) {
|
|
1704
|
+
for (const entry of entries) {
|
|
1705
|
+
if (!this.#entries.get(type)?.includes(entry)) continue;
|
|
1706
|
+
if (entry.once) this.#remove(type, entry);
|
|
1707
|
+
try {
|
|
1708
|
+
if (typeof entry.callback === "function") entry.callback.call(this.#owner, event);
|
|
1709
|
+
else entry.callback.handleEvent(event);
|
|
1710
|
+
} catch (error) {
|
|
1711
|
+
queueMicrotask(() => {
|
|
1712
|
+
throw error;
|
|
1713
|
+
});
|
|
1714
|
+
}
|
|
1715
|
+
if (state.stoppedImmediately) break;
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
#remove(type, entry) {
|
|
1719
|
+
const list = this.#entries.get(type);
|
|
1720
|
+
const index = list?.indexOf(entry) ?? -1;
|
|
1721
|
+
if (!list || index < 0) return;
|
|
1722
|
+
list.splice(index, 1);
|
|
1723
|
+
entry.unlinkSignal?.();
|
|
1724
|
+
if (list.length > 0) return;
|
|
1725
|
+
this.#entries.delete(type);
|
|
1726
|
+
this.#onTypesChange();
|
|
1727
|
+
}
|
|
1728
|
+
};
|
|
1729
|
+
var PathDispatch = class {
|
|
1730
|
+
#event;
|
|
1731
|
+
#target;
|
|
1732
|
+
#path;
|
|
1733
|
+
#type;
|
|
1734
|
+
#state;
|
|
1735
|
+
constructor(event, target, path, type = event.type) {
|
|
1736
|
+
this.#event = event;
|
|
1737
|
+
this.#target = target;
|
|
1738
|
+
this.#path = path;
|
|
1739
|
+
this.#type = type;
|
|
1740
|
+
if (event.target == null) setEventProperty(event, "target", target);
|
|
1741
|
+
this.#state = {
|
|
1742
|
+
stopped: false,
|
|
1743
|
+
stoppedImmediately: false
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
#tracking(run) {
|
|
1747
|
+
const event = this.#event;
|
|
1748
|
+
const state = this.#state;
|
|
1749
|
+
const stop = event.stopPropagation;
|
|
1750
|
+
const stopImmediately = event.stopImmediatePropagation;
|
|
1751
|
+
withProperties(event, {
|
|
1752
|
+
stopPropagation: () => {
|
|
1753
|
+
state.stopped = true;
|
|
1754
|
+
stop.call(event);
|
|
1755
|
+
},
|
|
1756
|
+
stopImmediatePropagation: () => {
|
|
1757
|
+
state.stopped = true;
|
|
1758
|
+
state.stoppedImmediately = true;
|
|
1759
|
+
stopImmediately.call(event);
|
|
1760
|
+
}
|
|
1761
|
+
}, run);
|
|
1762
|
+
}
|
|
1763
|
+
#phaseOf(index, outerPhase) {
|
|
1764
|
+
return this.#path[index].owner === this.#target ? 2 : outerPhase;
|
|
1765
|
+
}
|
|
1766
|
+
capture() {
|
|
1767
|
+
this.#tracking(() => {
|
|
1768
|
+
for (let i = this.#path.length - 1; i >= 0; i--) {
|
|
1769
|
+
if (this.#state.stopped) return;
|
|
1770
|
+
const phase = this.#phaseOf(i, 1);
|
|
1771
|
+
if (phase === 2) continue;
|
|
1772
|
+
this.#path[i].invoke(this.#type, this.#event, phase, this.#state);
|
|
1773
|
+
}
|
|
1646
1774
|
});
|
|
1647
|
-
|
|
1648
|
-
|
|
1775
|
+
}
|
|
1776
|
+
bubble() {
|
|
1777
|
+
const bubbles = this.#event.bubbles !== false;
|
|
1778
|
+
this.#tracking(() => {
|
|
1779
|
+
for (let i = 0; i < this.#path.length; i++) {
|
|
1780
|
+
if (this.#state.stopped) return;
|
|
1781
|
+
const phase = this.#phaseOf(i, 3);
|
|
1782
|
+
if (phase === 2 || bubbles) this.#path[i].invoke(this.#type, this.#event, phase, this.#state);
|
|
1783
|
+
}
|
|
1649
1784
|
});
|
|
1785
|
+
return !this.#event.defaultPrevented;
|
|
1650
1786
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1787
|
+
};
|
|
1788
|
+
const dispatchThrough = (event, target, path) => {
|
|
1789
|
+
const dispatch = new PathDispatch(event, target, path);
|
|
1790
|
+
dispatch.capture();
|
|
1791
|
+
return dispatch.bubble();
|
|
1792
|
+
};
|
|
1793
|
+
var LynxGlobalDocument = class extends GlobalEventTarget {
|
|
1794
|
+
#events;
|
|
1795
|
+
constructor(events) {
|
|
1796
|
+
super();
|
|
1797
|
+
this.#events = events;
|
|
1655
1798
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1799
|
+
get defaultView() {
|
|
1800
|
+
return this.#events.window.owner;
|
|
1801
|
+
}
|
|
1802
|
+
get body() {
|
|
1803
|
+
return this.#events.page;
|
|
1804
|
+
}
|
|
1805
|
+
getElementById(_id) {
|
|
1806
|
+
return null;
|
|
1807
|
+
}
|
|
1808
|
+
querySelector(_selector) {
|
|
1809
|
+
return null;
|
|
1810
|
+
}
|
|
1811
|
+
querySelectorAll(_selector) {
|
|
1812
|
+
return [];
|
|
1813
|
+
}
|
|
1814
|
+
dispatchEvent(event) {
|
|
1815
|
+
return dispatchThrough(event, this, [this, this.#events.window]);
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
const screenViewport = () => {
|
|
1819
|
+
const info = globalThis.lynx?.SystemInfo ?? globalThis.SystemInfo;
|
|
1820
|
+
const ratio = info?.pixelRatio ?? 1;
|
|
1821
|
+
return {
|
|
1822
|
+
width: (info?.pixelWidth ?? 0) / ratio,
|
|
1823
|
+
height: (info?.pixelHeight ?? 0) / ratio
|
|
1824
|
+
};
|
|
1825
|
+
};
|
|
1826
|
+
var GlobalEvents = class {
|
|
1827
|
+
window;
|
|
1828
|
+
document;
|
|
1829
|
+
#source;
|
|
1830
|
+
#page = null;
|
|
1831
|
+
#lookup = () => void 0;
|
|
1832
|
+
#size = null;
|
|
1833
|
+
#pending = [];
|
|
1834
|
+
constructor(windowObject, createSource) {
|
|
1835
|
+
this.window = new GlobalEventTarget(windowObject);
|
|
1836
|
+
this.document = new LynxGlobalDocument(this);
|
|
1837
|
+
this.#source = createSource(this);
|
|
1838
|
+
this.window.onTypesChange = () => this.#sync();
|
|
1839
|
+
this.document.onTypesChange = () => this.#sync();
|
|
1840
|
+
}
|
|
1841
|
+
attach(page, lookup) {
|
|
1842
|
+
this.#page = page;
|
|
1843
|
+
this.#lookup = lookup;
|
|
1844
|
+
this.#sync();
|
|
1845
|
+
}
|
|
1846
|
+
get page() {
|
|
1847
|
+
return this.#page;
|
|
1848
|
+
}
|
|
1849
|
+
get viewport() {
|
|
1850
|
+
return this.#source.viewport?.() ?? this.#size;
|
|
1851
|
+
}
|
|
1852
|
+
hasListeners(type) {
|
|
1853
|
+
return this.document.hasListeners(type) || this.window.hasListeners(type);
|
|
1854
|
+
}
|
|
1855
|
+
targetFor(uniqueId) {
|
|
1856
|
+
return (uniqueId === void 0 ? void 0 : this.#lookup(uniqueId)) ?? this.#page ?? this.document;
|
|
1857
|
+
}
|
|
1858
|
+
early(key, deliveries) {
|
|
1859
|
+
const dispatches = deliveries.map(({ type, event, target }) => new PathDispatch(event, target, [this.document, this.window], type));
|
|
1860
|
+
for (const dispatch of dispatches) dispatch.capture();
|
|
1861
|
+
const pending = {
|
|
1862
|
+
key,
|
|
1863
|
+
dispatches
|
|
1662
1864
|
};
|
|
1663
|
-
|
|
1664
|
-
this
|
|
1665
|
-
|
|
1666
|
-
|
|
1865
|
+
this.#pending.push(pending);
|
|
1866
|
+
setTimeout(() => this.#finish(pending), 0);
|
|
1867
|
+
}
|
|
1868
|
+
late(key) {
|
|
1869
|
+
const pending = this.#pending.find((p) => p.key === key);
|
|
1870
|
+
if (pending) this.#finish(pending);
|
|
1871
|
+
}
|
|
1872
|
+
finishPending() {
|
|
1873
|
+
for (const pending of this.#pending.slice()) this.#finish(pending);
|
|
1874
|
+
}
|
|
1875
|
+
resized(size) {
|
|
1876
|
+
const before = this.#size ?? screenViewport();
|
|
1877
|
+
this.#size = size;
|
|
1878
|
+
if (before.width === size.width && before.height === size.height) return;
|
|
1879
|
+
if (!this.window.hasListeners("resize")) return;
|
|
1880
|
+
dispatchThrough(createEvent("resize"), this.window.owner, [this.window]);
|
|
1881
|
+
}
|
|
1882
|
+
#finish(pending) {
|
|
1883
|
+
const index = this.#pending.indexOf(pending);
|
|
1884
|
+
if (index < 0) return;
|
|
1885
|
+
this.#pending.splice(index, 1);
|
|
1886
|
+
for (const dispatch of pending.dispatches) dispatch.bubble();
|
|
1887
|
+
}
|
|
1888
|
+
#sync() {
|
|
1889
|
+
const types = /* @__PURE__ */ new Set([...this.document.types, ...this.window.types]);
|
|
1890
|
+
this.#source.sync(this.#page, types);
|
|
1667
1891
|
}
|
|
1668
1892
|
};
|
|
1669
1893
|
const POINTER_EVENT_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -1678,6 +1902,8 @@ const POINTER_EVENT_NAMES = /* @__PURE__ */ new Set([
|
|
|
1678
1902
|
"gotpointercapture",
|
|
1679
1903
|
"lostpointercapture"
|
|
1680
1904
|
]);
|
|
1905
|
+
const MAX_TOUCH_NUMBER = 65535;
|
|
1906
|
+
const pointerIdOf = (touch) => touch.identifier >= 0 && touch.identifier <= MAX_TOUCH_NUMBER ? touch.identifier : 0;
|
|
1681
1907
|
var LynxPointerEvent = class {
|
|
1682
1908
|
type;
|
|
1683
1909
|
pointerId;
|
|
@@ -1829,49 +2055,410 @@ var PointerEventSource = class {
|
|
|
1829
2055
|
}
|
|
1830
2056
|
#onStart(event) {
|
|
1831
2057
|
for (const touch of event.changedTouches ?? []) {
|
|
2058
|
+
const id = pointerIdOf(touch);
|
|
1832
2059
|
const offset = this.#offset(event, touch);
|
|
1833
|
-
this.#down.set(
|
|
1834
|
-
this.#primary ??=
|
|
2060
|
+
this.#down.set(id, offset);
|
|
2061
|
+
this.#primary ??= id;
|
|
1835
2062
|
this.lastOffset = offset;
|
|
1836
|
-
this.#fire("pointerover",
|
|
1837
|
-
this.#fire("pointerenter",
|
|
1838
|
-
this.#fire("pointerdown",
|
|
2063
|
+
this.#fire("pointerover", id, touch, event, offset);
|
|
2064
|
+
this.#fire("pointerenter", id, touch, event, offset);
|
|
2065
|
+
this.#fire("pointerdown", id, touch, event, offset);
|
|
1839
2066
|
}
|
|
1840
2067
|
}
|
|
1841
2068
|
#onMove(event) {
|
|
1842
2069
|
for (const touch of event.changedTouches ?? []) {
|
|
1843
|
-
|
|
2070
|
+
const id = pointerIdOf(touch);
|
|
2071
|
+
if (!this.#down.has(id)) continue;
|
|
1844
2072
|
const offset = this.#offset(event, touch);
|
|
1845
|
-
this.#down.set(
|
|
2073
|
+
this.#down.set(id, offset);
|
|
1846
2074
|
this.lastOffset = offset;
|
|
1847
|
-
this.#fire("pointermove",
|
|
2075
|
+
this.#fire("pointermove", id, touch, event, offset);
|
|
1848
2076
|
}
|
|
1849
2077
|
}
|
|
1850
2078
|
#onEnd(event, canceled) {
|
|
1851
2079
|
for (const touch of event.changedTouches ?? []) {
|
|
1852
|
-
|
|
1853
|
-
|
|
2080
|
+
const id = pointerIdOf(touch);
|
|
2081
|
+
if (!this.#down.has(id)) continue;
|
|
2082
|
+
const offset = canceled ? this.#down.get(id) : this.#offset(event, touch);
|
|
1854
2083
|
this.lastOffset = offset;
|
|
1855
|
-
this.#fire(canceled ? "pointercancel" : "pointerup",
|
|
1856
|
-
if (this.#captured.delete(
|
|
1857
|
-
this.#fire("pointerout",
|
|
1858
|
-
this.#fire("pointerleave",
|
|
1859
|
-
this.#down.delete(
|
|
1860
|
-
if (this.#primary ===
|
|
2084
|
+
this.#fire(canceled ? "pointercancel" : "pointerup", id, touch, event, offset);
|
|
2085
|
+
if (this.#captured.delete(id)) this.#fire("lostpointercapture", id, touch, event, offset);
|
|
2086
|
+
this.#fire("pointerout", id, touch, event, offset);
|
|
2087
|
+
this.#fire("pointerleave", id, touch, event, offset);
|
|
2088
|
+
this.#down.delete(id);
|
|
2089
|
+
if (this.#primary === id) this.#primary = null;
|
|
1861
2090
|
}
|
|
1862
2091
|
}
|
|
1863
2092
|
#fire(type, pointerId, touch, event, offset) {
|
|
1864
2093
|
const listeners = this.#listeners.get(type);
|
|
1865
2094
|
if (!listeners) return;
|
|
1866
2095
|
const position = offset ?? this.#down.get(pointerId);
|
|
1867
|
-
const
|
|
1868
|
-
|
|
2096
|
+
const pointerEvent = pointerEventFor(type, {
|
|
2097
|
+
pointerId,
|
|
2098
|
+
isPrimary: this.#primary === null || this.#primary === pointerId,
|
|
2099
|
+
...position
|
|
2100
|
+
}, touch, event?.timestamp, this.#host.eventTarget);
|
|
1869
2101
|
for (const listener of listeners.slice()) {
|
|
1870
2102
|
listener(pointerEvent);
|
|
1871
2103
|
if (pointerEvent.immediatePropagationStopped) break;
|
|
1872
2104
|
}
|
|
1873
2105
|
}
|
|
1874
2106
|
};
|
|
2107
|
+
const pointerEventFor = (type, pointer, touch, timeStamp, target) => {
|
|
2108
|
+
const pressed = type === "pointerdown" || type === "pointermove" || type === "pointerover" ? 1 : 0;
|
|
2109
|
+
return new LynxPointerEvent(type, pointer.pointerId, pointer.isPrimary, touch?.clientX ?? touch?.pageX ?? 0, touch?.clientY ?? touch?.pageY ?? 0, touch?.pageX ?? 0, touch?.pageY ?? 0, pointer.offsetX, pointer.offsetY, type === "pointermove" ? -1 : 0, pressed, pressed ? .5 : 0, timeStamp ?? Date.now(), target);
|
|
2110
|
+
};
|
|
2111
|
+
const TOUCH_EVENTS = [
|
|
2112
|
+
"touchstart",
|
|
2113
|
+
"touchmove",
|
|
2114
|
+
"touchend",
|
|
2115
|
+
"touchcancel"
|
|
2116
|
+
];
|
|
2117
|
+
const POINTER_EVENTS = /* @__PURE__ */ new Set([
|
|
2118
|
+
"pointerover",
|
|
2119
|
+
"pointerdown",
|
|
2120
|
+
"pointermove",
|
|
2121
|
+
"pointerup",
|
|
2122
|
+
"pointercancel",
|
|
2123
|
+
"pointerout"
|
|
2124
|
+
]);
|
|
2125
|
+
const POINTERS_FOR = {
|
|
2126
|
+
touchstart: ["pointerover", "pointerdown"],
|
|
2127
|
+
touchmove: ["pointermove"],
|
|
2128
|
+
touchend: ["pointerup", "pointerout"],
|
|
2129
|
+
touchcancel: ["pointercancel", "pointerout"]
|
|
2130
|
+
};
|
|
2131
|
+
const sizeOf$1 = (event) => {
|
|
2132
|
+
const size = Array.isArray(event.detail) ? event.detail[1] : void 0;
|
|
2133
|
+
if (!Array.isArray(size) || size.length < 2) return null;
|
|
2134
|
+
return {
|
|
2135
|
+
width: Number(size[0]),
|
|
2136
|
+
height: Number(size[1])
|
|
2137
|
+
};
|
|
2138
|
+
};
|
|
2139
|
+
var NativeScreenSource = class {
|
|
2140
|
+
#events;
|
|
2141
|
+
#page = null;
|
|
2142
|
+
#listening = /* @__PURE__ */ new Map();
|
|
2143
|
+
#down = /* @__PURE__ */ new Set();
|
|
2144
|
+
#primary = null;
|
|
2145
|
+
constructor(events) {
|
|
2146
|
+
this.#events = events;
|
|
2147
|
+
}
|
|
2148
|
+
sync(page, types) {
|
|
2149
|
+
if (page !== this.#page) {
|
|
2150
|
+
this.#stop([...this.#listening.keys()]);
|
|
2151
|
+
this.#page = page;
|
|
2152
|
+
}
|
|
2153
|
+
if (!page) return;
|
|
2154
|
+
const wanted = /* @__PURE__ */ new Set(["resize"]);
|
|
2155
|
+
if ([...types].some((t) => POINTER_EVENTS.has(t) || TOUCH_EVENTS.includes(t))) for (const name of TOUCH_EVENTS) wanted.add(name);
|
|
2156
|
+
if (types.has("click")) wanted.add("tap");
|
|
2157
|
+
this.#stop([...this.#listening.keys()].filter((n) => !wanted.has(n)));
|
|
2158
|
+
for (const name of wanted) if (!this.#listening.has(name)) this.#listening.set(name, this.#listen(page, name));
|
|
2159
|
+
}
|
|
2160
|
+
#listen(page, name) {
|
|
2161
|
+
if (name === "resize") return page.addEventListener("bindresize", (event) => {
|
|
2162
|
+
const size = sizeOf$1(event);
|
|
2163
|
+
if (size) this.#events.resized(size);
|
|
2164
|
+
});
|
|
2165
|
+
const stopEarly = page.addEventListener(`global-bind${name}`, (event) => this.#begin(name, event));
|
|
2166
|
+
const stopLate = page.addTrailingEventListener(`bind${name}`, () => this.#events.late(name));
|
|
2167
|
+
return () => {
|
|
2168
|
+
stopEarly();
|
|
2169
|
+
stopLate();
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
#stop(names) {
|
|
2173
|
+
for (const name of names) {
|
|
2174
|
+
this.#listening.get(name)?.();
|
|
2175
|
+
this.#listening.delete(name);
|
|
2176
|
+
if (name === "touchstart") {
|
|
2177
|
+
this.#down.clear();
|
|
2178
|
+
this.#primary = null;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
#begin(name, event) {
|
|
2183
|
+
this.#events.finishPending();
|
|
2184
|
+
const target = this.#events.targetFor(event.target?.uid);
|
|
2185
|
+
const deliveries = name === "tap" ? [{
|
|
2186
|
+
type: "click",
|
|
2187
|
+
event,
|
|
2188
|
+
target
|
|
2189
|
+
}] : [...this.#pointers(name, event, target), {
|
|
2190
|
+
type: name,
|
|
2191
|
+
event,
|
|
2192
|
+
target
|
|
2193
|
+
}];
|
|
2194
|
+
this.#events.early(name, deliveries.filter((d) => this.#events.hasListeners(d.type)));
|
|
2195
|
+
}
|
|
2196
|
+
#pointers(name, event, target) {
|
|
2197
|
+
const deliveries = [];
|
|
2198
|
+
for (const touch of event.changedTouches ?? []) {
|
|
2199
|
+
const id = pointerIdOf(touch);
|
|
2200
|
+
if (name === "touchstart") {
|
|
2201
|
+
this.#down.add(id);
|
|
2202
|
+
this.#primary ??= id;
|
|
2203
|
+
} else if (!this.#down.has(id)) continue;
|
|
2204
|
+
for (const type of POINTERS_FOR[name]) deliveries.push({
|
|
2205
|
+
type,
|
|
2206
|
+
event: this.#pointerEvent(type, touch, event, target),
|
|
2207
|
+
target
|
|
2208
|
+
});
|
|
2209
|
+
if (name === "touchend" || name === "touchcancel") {
|
|
2210
|
+
this.#down.delete(id);
|
|
2211
|
+
if (this.#primary === id) this.#primary = null;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
return deliveries;
|
|
2215
|
+
}
|
|
2216
|
+
#pointerEvent(type, touch, event, target) {
|
|
2217
|
+
return pointerEventFor(type, {
|
|
2218
|
+
pointerId: pointerIdOf(touch),
|
|
2219
|
+
isPrimary: this.#primary === pointerIdOf(touch),
|
|
2220
|
+
offsetX: touch.x ?? 0,
|
|
2221
|
+
offsetY: touch.y ?? 0
|
|
2222
|
+
}, touch, event.timestamp, target);
|
|
2223
|
+
}
|
|
2224
|
+
};
|
|
2225
|
+
const KEY_EVENTS = /* @__PURE__ */ new Set([
|
|
2226
|
+
"keydown",
|
|
2227
|
+
"keyup",
|
|
2228
|
+
"keypress"
|
|
2229
|
+
]);
|
|
2230
|
+
var WebScreenSource = class {
|
|
2231
|
+
#events;
|
|
2232
|
+
#page = null;
|
|
2233
|
+
#listening = /* @__PURE__ */ new Map();
|
|
2234
|
+
constructor(events) {
|
|
2235
|
+
this.#events = events;
|
|
2236
|
+
}
|
|
2237
|
+
sync(page, types) {
|
|
2238
|
+
if (page !== this.#page) {
|
|
2239
|
+
this.#stop([...this.#listening.keys()]);
|
|
2240
|
+
this.#page = page;
|
|
2241
|
+
}
|
|
2242
|
+
const scope = this.#scope();
|
|
2243
|
+
if (!scope) return;
|
|
2244
|
+
this.#stop([...this.#listening.keys()].filter((t) => !types.has(t)));
|
|
2245
|
+
for (const type of types) {
|
|
2246
|
+
if (this.#listening.has(type)) continue;
|
|
2247
|
+
this.#listening.set(type, type === "resize" ? this.#observeSize(scope.box) : this.#listen(scope, type));
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
viewport() {
|
|
2251
|
+
const rect = this.#scope()?.box.getBoundingClientRect();
|
|
2252
|
+
return rect ? {
|
|
2253
|
+
width: rect.width,
|
|
2254
|
+
height: rect.height
|
|
2255
|
+
} : null;
|
|
2256
|
+
}
|
|
2257
|
+
#scope() {
|
|
2258
|
+
const inside = globalThis.frameElement ?? this.#page?.element;
|
|
2259
|
+
if (!inside) return null;
|
|
2260
|
+
const root = inside.getRootNode();
|
|
2261
|
+
return {
|
|
2262
|
+
root,
|
|
2263
|
+
box: root.host ?? inside
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
#listen({ root, box }, type) {
|
|
2267
|
+
const target = KEY_EVENTS.has(type) ? box.ownerDocument : root;
|
|
2268
|
+
const begin = (event) => this.#events.early(event, [{
|
|
2269
|
+
type,
|
|
2270
|
+
event,
|
|
2271
|
+
target: event.target
|
|
2272
|
+
}]);
|
|
2273
|
+
const end = (event) => this.#events.late(event);
|
|
2274
|
+
target.addEventListener(type, begin, true);
|
|
2275
|
+
target.addEventListener(type, end);
|
|
2276
|
+
return () => {
|
|
2277
|
+
target.removeEventListener(type, begin, true);
|
|
2278
|
+
target.removeEventListener(type, end);
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
#observeSize(box) {
|
|
2282
|
+
const view = box.ownerDocument.defaultView;
|
|
2283
|
+
let last = null;
|
|
2284
|
+
const observer = new view.ResizeObserver(() => {
|
|
2285
|
+
const size = this.viewport();
|
|
2286
|
+
if (last && last.width === size.width && last.height === size.height) return;
|
|
2287
|
+
const first = last === null;
|
|
2288
|
+
last = size;
|
|
2289
|
+
if (!first) this.#events.resized(size);
|
|
2290
|
+
});
|
|
2291
|
+
observer.observe(box);
|
|
2292
|
+
return () => observer.disconnect();
|
|
2293
|
+
}
|
|
2294
|
+
#stop(types) {
|
|
2295
|
+
for (const type of types) {
|
|
2296
|
+
this.#listening.get(type)();
|
|
2297
|
+
this.#listening.delete(type);
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
};
|
|
2301
|
+
const SCREEN_EVENTS = /* @__PURE__ */ new Set([
|
|
2302
|
+
"pointerover",
|
|
2303
|
+
"pointerdown",
|
|
2304
|
+
"pointermove",
|
|
2305
|
+
"pointerup",
|
|
2306
|
+
"pointercancel",
|
|
2307
|
+
"pointerout",
|
|
2308
|
+
"touchstart",
|
|
2309
|
+
"touchmove",
|
|
2310
|
+
"touchend",
|
|
2311
|
+
"touchcancel",
|
|
2312
|
+
"mousedown",
|
|
2313
|
+
"mousemove",
|
|
2314
|
+
"mouseup",
|
|
2315
|
+
"click",
|
|
2316
|
+
"dblclick",
|
|
2317
|
+
"contextmenu",
|
|
2318
|
+
"wheel",
|
|
2319
|
+
"keydown",
|
|
2320
|
+
"keyup",
|
|
2321
|
+
"keypress",
|
|
2322
|
+
"resize"
|
|
2323
|
+
]);
|
|
2324
|
+
const INSTALLED = Symbol.for("@blotch/angular-lynx/global-window");
|
|
2325
|
+
const isBrowserWindow = (target) => typeof target["document"]?.nodeType === "number";
|
|
2326
|
+
const installGlobalWindow = (target, events) => {
|
|
2327
|
+
if (target[INSTALLED]) return;
|
|
2328
|
+
target[INSTALLED] = true;
|
|
2329
|
+
installEventClasses(target);
|
|
2330
|
+
const own = events.window;
|
|
2331
|
+
const browser = isBrowserWindow(target);
|
|
2332
|
+
const original = {
|
|
2333
|
+
add: target["addEventListener"],
|
|
2334
|
+
remove: target["removeEventListener"],
|
|
2335
|
+
dispatch: target["dispatchEvent"]
|
|
2336
|
+
};
|
|
2337
|
+
const ours = (type) => !browser || SCREEN_EVENTS.has(type);
|
|
2338
|
+
target["addEventListener"] = (type, listener, options) => {
|
|
2339
|
+
if (ours(type)) own.addEventListener(type, listener, options);
|
|
2340
|
+
else original.add.call(target, type, listener, options);
|
|
2341
|
+
};
|
|
2342
|
+
target["removeEventListener"] = (type, listener, options) => {
|
|
2343
|
+
if (ours(type)) own.removeEventListener(type, listener, options);
|
|
2344
|
+
else original.remove.call(target, type, listener, options);
|
|
2345
|
+
};
|
|
2346
|
+
target["dispatchEvent"] = (event) => ours(event.type) ? dispatchThrough(event, target, [own]) : original.dispatch.call(target, event);
|
|
2347
|
+
if (browser && !__WEB__) return;
|
|
2348
|
+
for (const [name, axis] of [["innerWidth", "width"], ["innerHeight", "height"]]) Object.defineProperty(target, name, {
|
|
2349
|
+
get: () => (events.viewport ?? screenViewport())[axis],
|
|
2350
|
+
configurable: true,
|
|
2351
|
+
enumerable: true
|
|
2352
|
+
});
|
|
2353
|
+
};
|
|
2354
|
+
const installGlobalDocument = (target, events) => {
|
|
2355
|
+
if (typeof target["document"]?.nodeType === "number") return;
|
|
2356
|
+
target["document"] = events.document;
|
|
2357
|
+
};
|
|
2358
|
+
const KEY = Symbol.for("@blotch/angular-lynx/global-events");
|
|
2359
|
+
const globalEvents = () => {
|
|
2360
|
+
const store = globalThis;
|
|
2361
|
+
store[KEY] ??= new GlobalEvents(globalThis, (events) => __WEB__ ? new WebScreenSource(events) : new NativeScreenSource(events));
|
|
2362
|
+
return store[KEY];
|
|
2363
|
+
};
|
|
2364
|
+
let firstRenderPending = true;
|
|
2365
|
+
const deferredCallbacks = [];
|
|
2366
|
+
const isFirstRenderPending = () => firstRenderPending;
|
|
2367
|
+
const markFirstRenderComplete = () => {
|
|
2368
|
+
firstRenderPending = false;
|
|
2369
|
+
if (deferredCallbacks.length === 0) return;
|
|
2370
|
+
const callbacks = deferredCallbacks.splice(0);
|
|
2371
|
+
setTimeout(() => {
|
|
2372
|
+
for (const callback of callbacks) callback();
|
|
2373
|
+
}, 0);
|
|
2374
|
+
};
|
|
2375
|
+
const runAfterFirstRender = (callback) => {
|
|
2376
|
+
if (!firstRenderPending) {
|
|
2377
|
+
callback();
|
|
2378
|
+
return;
|
|
2379
|
+
}
|
|
2380
|
+
deferredCallbacks.push(callback);
|
|
2381
|
+
};
|
|
2382
|
+
let insideChangeDetection = false;
|
|
2383
|
+
const setInsideChangeDetection = (value) => {
|
|
2384
|
+
insideChangeDetection = value;
|
|
2385
|
+
};
|
|
2386
|
+
const isInsideChangeDetection = () => insideChangeDetection;
|
|
2387
|
+
const DASHARRAY_ATTRIBUTE = /(\s)stroke-dasharray\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
2388
|
+
const DASHARRAY_DECLARATION = /(^|[;"'\s])stroke-dasharray\s*:\s*([^;"']*);?/g;
|
|
2389
|
+
const DASH_LENGTH = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(?:px)?$/i;
|
|
2390
|
+
const normalizeDashArray = (value) => {
|
|
2391
|
+
const tokens = value.trim().split(/[\s,]+/).filter((token) => token.length > 0);
|
|
2392
|
+
if (tokens.length === 0 || !tokens.every((t) => DASH_LENGTH.test(t))) return null;
|
|
2393
|
+
return tokens.map((token) => token.replace(/px$/i, "")).join(" ");
|
|
2394
|
+
};
|
|
2395
|
+
const sanitizeSvgContent = (content) => {
|
|
2396
|
+
if (!content.includes("stroke-dasharray")) return content;
|
|
2397
|
+
return content.replace(DASHARRAY_ATTRIBUTE, (_match, space, double, single) => {
|
|
2398
|
+
const normalized = normalizeDashArray(double ?? single);
|
|
2399
|
+
return normalized === null ? "" : `${space}stroke-dasharray="${normalized}"`;
|
|
2400
|
+
}).replace(DASHARRAY_DECLARATION, (_match, before, value) => {
|
|
2401
|
+
const normalized = normalizeDashArray(value);
|
|
2402
|
+
return normalized === null ? before : `${before}stroke-dasharray:${normalized};`;
|
|
2403
|
+
});
|
|
2404
|
+
};
|
|
2405
|
+
const toDOMRect = (rect) => {
|
|
2406
|
+
const { left = 0, top = 0, width = 0, height = 0 } = rect ?? {};
|
|
2407
|
+
const box = {
|
|
2408
|
+
x: left,
|
|
2409
|
+
y: top,
|
|
2410
|
+
width,
|
|
2411
|
+
height,
|
|
2412
|
+
top,
|
|
2413
|
+
left,
|
|
2414
|
+
right: left + width,
|
|
2415
|
+
bottom: top + height
|
|
2416
|
+
};
|
|
2417
|
+
return {
|
|
2418
|
+
...box,
|
|
2419
|
+
toJSON: () => ({ ...box })
|
|
2420
|
+
};
|
|
2421
|
+
};
|
|
2422
|
+
const measureLayout = (element, callback) => {
|
|
2423
|
+
__InvokeUIMethod(element, "boundingClientRect", {}, (result) => callback(result?.code === 0 && result.data ? result.data : null));
|
|
2424
|
+
};
|
|
2425
|
+
var LayoutTracker = class {
|
|
2426
|
+
#host;
|
|
2427
|
+
#observers = /* @__PURE__ */ new Set();
|
|
2428
|
+
#listening = false;
|
|
2429
|
+
rect = null;
|
|
2430
|
+
constructor(host) {
|
|
2431
|
+
this.#host = host;
|
|
2432
|
+
}
|
|
2433
|
+
start() {
|
|
2434
|
+
if (this.#listening) return;
|
|
2435
|
+
this.#listening = true;
|
|
2436
|
+
this.#host.listen("bindlayoutchange", (event) => {
|
|
2437
|
+
const detail = event?.detail;
|
|
2438
|
+
if (detail && typeof detail.width === "number") this.#update(detail);
|
|
2439
|
+
});
|
|
2440
|
+
this.#host.measure((rect) => {
|
|
2441
|
+
if (rect && !this.rect) this.#update(rect);
|
|
2442
|
+
});
|
|
2443
|
+
}
|
|
2444
|
+
observe(observer) {
|
|
2445
|
+
this.start();
|
|
2446
|
+
this.#observers.add(observer);
|
|
2447
|
+
return () => this.#observers.delete(observer);
|
|
2448
|
+
}
|
|
2449
|
+
#update(detail) {
|
|
2450
|
+
const rect = {
|
|
2451
|
+
left: detail.left,
|
|
2452
|
+
top: detail.top,
|
|
2453
|
+
width: detail.width,
|
|
2454
|
+
height: detail.height
|
|
2455
|
+
};
|
|
2456
|
+
const old = this.rect;
|
|
2457
|
+
this.rect = rect;
|
|
2458
|
+
if (old && old.left === rect.left && old.top === rect.top && old.width === rect.width && old.height === rect.height) return;
|
|
2459
|
+
for (const observer of Array.from(this.#observers)) observer(rect);
|
|
2460
|
+
}
|
|
2461
|
+
};
|
|
1875
2462
|
const LONG_PRESS_SLOP = 10;
|
|
1876
2463
|
const TAP_GRACE = 300;
|
|
1877
2464
|
let tapsDropped = false;
|
|
@@ -1927,6 +2514,20 @@ var WebLongPress = class {
|
|
|
1927
2514
|
this.#timer = void 0;
|
|
1928
2515
|
}
|
|
1929
2516
|
};
|
|
2517
|
+
const seconds = (value) => Number.isFinite(value) ? value : 0;
|
|
2518
|
+
const webVideoDetail = (eventName, video) => {
|
|
2519
|
+
switch (eventName) {
|
|
2520
|
+
case "timeupdate": return {
|
|
2521
|
+
current: seconds(video.currentTime),
|
|
2522
|
+
duration: seconds(video.duration)
|
|
2523
|
+
};
|
|
2524
|
+
case "error": return {
|
|
2525
|
+
errorCode: video.error?.code ?? 0,
|
|
2526
|
+
errorMsg: video.error?.message ?? ""
|
|
2527
|
+
};
|
|
2528
|
+
default: return;
|
|
2529
|
+
}
|
|
2530
|
+
};
|
|
1930
2531
|
const EVENT_PREFIXES = [
|
|
1931
2532
|
["capture-bind", "capture-bindEvent"],
|
|
1932
2533
|
["capture-catch", "capture-catchEvent"],
|
|
@@ -2032,6 +2633,9 @@ var LynxElement = class {
|
|
|
2032
2633
|
static #canonicalFor(ref) {
|
|
2033
2634
|
return _a.#byNativeId.get(__GetElementUniqueID(ref)) ?? new _a(ref);
|
|
2034
2635
|
}
|
|
2636
|
+
static byUniqueId(uniqueId) {
|
|
2637
|
+
return _a.#byNativeId.get(uniqueId);
|
|
2638
|
+
}
|
|
2035
2639
|
constructor(element) {
|
|
2036
2640
|
this.#nativeRef = element;
|
|
2037
2641
|
_a.#byNativeId.set(__GetElementUniqueID(element), this);
|
|
@@ -2040,6 +2644,9 @@ var LynxElement = class {
|
|
|
2040
2644
|
const id = __GetElementUniqueID(this.#nativeRef);
|
|
2041
2645
|
if (_a.#byNativeId.get(id) === this) _a.#byNativeId.delete(id);
|
|
2042
2646
|
}
|
|
2647
|
+
get ownerDocument() {
|
|
2648
|
+
return globalEvents().document;
|
|
2649
|
+
}
|
|
2043
2650
|
setProperty(name, value) {
|
|
2044
2651
|
this.setAttribute(name, value);
|
|
2045
2652
|
}
|
|
@@ -2384,10 +2991,19 @@ var LynxElement = class {
|
|
|
2384
2991
|
const parsed = parseEventName(name);
|
|
2385
2992
|
if (!parsed) return () => {};
|
|
2386
2993
|
if (__WEB__ && parsed.eventName === "longpress") this.#listenForWebLongPress();
|
|
2387
|
-
|
|
2994
|
+
return this.#add({
|
|
2388
2995
|
...parsed,
|
|
2389
2996
|
listener: cb
|
|
2390
|
-
};
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
addTrailingEventListener(name, cb) {
|
|
3000
|
+
return this.#add({
|
|
3001
|
+
...parseEventName(name),
|
|
3002
|
+
listener: cb,
|
|
3003
|
+
trailing: true
|
|
3004
|
+
});
|
|
3005
|
+
}
|
|
3006
|
+
#add(entry) {
|
|
2391
3007
|
this.#listeners.push(entry);
|
|
2392
3008
|
this.#syncNativeHandler(entry);
|
|
2393
3009
|
return () => this.#removeListener(entry);
|
|
@@ -2454,7 +3070,7 @@ var LynxElement = class {
|
|
|
2454
3070
|
#layoutTracker() {
|
|
2455
3071
|
this.#layout ??= new LayoutTracker({
|
|
2456
3072
|
listen: (event, listener) => this.addEventListener(event, listener),
|
|
2457
|
-
measure: (callback) =>
|
|
3073
|
+
measure: (callback) => measureLayout(this.element, callback)
|
|
2458
3074
|
});
|
|
2459
3075
|
return this.#layout;
|
|
2460
3076
|
}
|
|
@@ -2511,7 +3127,8 @@ var LynxElement = class {
|
|
|
2511
3127
|
}
|
|
2512
3128
|
#listenersLike(entry) {
|
|
2513
3129
|
const key = nativeEventKey(entry.eventType, entry.eventName);
|
|
2514
|
-
|
|
3130
|
+
const like = this.#listeners.filter((other) => nativeEventKey(other.eventType, other.eventName) === key);
|
|
3131
|
+
return [...like.filter((other) => !other.trailing), ...like.filter((other) => other.trailing)];
|
|
2515
3132
|
}
|
|
2516
3133
|
#syncNativeHandler(entry) {
|
|
2517
3134
|
const key = nativeEventKey(entry.eventType, entry.eventName);
|
|
@@ -2519,6 +3136,7 @@ var LynxElement = class {
|
|
|
2519
3136
|
const current = this.#nativeHandlers.get(key);
|
|
2520
3137
|
const eventType = listeners.length ? combinedEventType(listeners) : null;
|
|
2521
3138
|
if (current?.eventType === eventType) return;
|
|
3139
|
+
scheduleSettleFlush();
|
|
2522
3140
|
if (current) {
|
|
2523
3141
|
__AddEvent(this.element, current.eventType, entry.eventName, void 0);
|
|
2524
3142
|
this.#nativeHandlers.delete(key);
|
|
@@ -2542,6 +3160,10 @@ var LynxElement = class {
|
|
|
2542
3160
|
if (typeof event.stopImmediatePropagation !== "function") event.stopImmediatePropagation = () => {};
|
|
2543
3161
|
}
|
|
2544
3162
|
if (__WEB__ && entry.eventName === "tap" && dropsTap()) return void 0;
|
|
3163
|
+
if (__WEB__ && this.tagName === "video" && event && typeof event === "object") {
|
|
3164
|
+
const detail = webVideoDetail(entry.eventName, this.element);
|
|
3165
|
+
if (detail) event.detail = detail;
|
|
3166
|
+
}
|
|
2545
3167
|
const pointer = __WEB__ ? this.#webPointer : this.#pointerEvents?.lastOffset;
|
|
2546
3168
|
if (pointer && entry.eventName === "tap" && event && typeof event === "object" && event.offsetX === void 0) {
|
|
2547
3169
|
event.offsetX = pointer.offsetX;
|
|
@@ -9210,6 +9832,7 @@ var LynxDocument = class {
|
|
|
9210
9832
|
if (isAndroid()) __SetID(pageElement, ANDROID_BLUR_CAPTURE_TARGET);
|
|
9211
9833
|
this.#pageId = __GetElementUniqueID(pageElement);
|
|
9212
9834
|
setPageElementRef(pageElement);
|
|
9835
|
+
globalEvents().attach(this.page, (id) => LynxElement.byUniqueId(id));
|
|
9213
9836
|
return this.page;
|
|
9214
9837
|
}
|
|
9215
9838
|
createElement(name, value) {
|
|
@@ -9278,6 +9901,7 @@ var LynxHydrateDocument = class {
|
|
|
9278
9901
|
page.tagName = "page";
|
|
9279
9902
|
page.isRootPageElement = true;
|
|
9280
9903
|
this.#page = page;
|
|
9904
|
+
globalEvents().attach(page, (id) => LynxElement.byUniqueId(id));
|
|
9281
9905
|
return page;
|
|
9282
9906
|
}
|
|
9283
9907
|
createElement(tag, value) {
|
|
@@ -9306,7 +9930,48 @@ var LynxHydrateDocument = class {
|
|
|
9306
9930
|
this.#page?.appendChild(newChild);
|
|
9307
9931
|
}
|
|
9308
9932
|
};
|
|
9933
|
+
const LYNX_ELEMENT_TAGS = /* @__PURE__ */ new Set([
|
|
9934
|
+
"page",
|
|
9935
|
+
"view",
|
|
9936
|
+
"text",
|
|
9937
|
+
"raw-text",
|
|
9938
|
+
"inline-truncation",
|
|
9939
|
+
"image",
|
|
9940
|
+
"scroll-view",
|
|
9941
|
+
"list",
|
|
9942
|
+
"list-item",
|
|
9943
|
+
"block",
|
|
9944
|
+
"if",
|
|
9945
|
+
"for",
|
|
9946
|
+
"frame",
|
|
9947
|
+
"input",
|
|
9948
|
+
"textarea",
|
|
9949
|
+
"overlay",
|
|
9950
|
+
"svg",
|
|
9951
|
+
"viewpager",
|
|
9952
|
+
"viewpager-item",
|
|
9953
|
+
"refresh",
|
|
9954
|
+
"refresh-header",
|
|
9955
|
+
"title-bar-view",
|
|
9956
|
+
"scroll-coordinator",
|
|
9957
|
+
"scroll-coordinator-header",
|
|
9958
|
+
"scroll-coordinator-toolbar",
|
|
9959
|
+
"scroll-coordinator-slot",
|
|
9960
|
+
"scroll-coordinator-slot-drag",
|
|
9961
|
+
"blur-view",
|
|
9962
|
+
"webview",
|
|
9963
|
+
"video",
|
|
9964
|
+
"cover-view",
|
|
9965
|
+
"canvas",
|
|
9966
|
+
"comment"
|
|
9967
|
+
]);
|
|
9968
|
+
const tagClassOf = (tag) => `_ngtag-${tag.toLowerCase()}`;
|
|
9969
|
+
const tagClassFor = (tag) => LYNX_ELEMENT_TAGS.has(tag) ? null : tagClassOf(tag);
|
|
9309
9970
|
const collapseWhitespace = (value) => value.replace(/[ \t\n\r\f\v]+/g, " ");
|
|
9971
|
+
const markTag = (element, tag) => {
|
|
9972
|
+
const tagClass = tagClassFor(tag);
|
|
9973
|
+
if (tagClass) element.addScopeClass(tagClass);
|
|
9974
|
+
};
|
|
9310
9975
|
var LynxRenderer = class {
|
|
9311
9976
|
#document;
|
|
9312
9977
|
#data = {};
|
|
@@ -9318,7 +9983,9 @@ var LynxRenderer = class {
|
|
|
9318
9983
|
}
|
|
9319
9984
|
destroy() {}
|
|
9320
9985
|
createElement(name, _namespace) {
|
|
9321
|
-
|
|
9986
|
+
const element = this.#document.createElement(name);
|
|
9987
|
+
markTag(element, name);
|
|
9988
|
+
return element;
|
|
9322
9989
|
}
|
|
9323
9990
|
createComment(_value) {
|
|
9324
9991
|
return this.#document.createComment();
|
|
@@ -9376,10 +10043,18 @@ var LynxRenderer = class {
|
|
|
9376
10043
|
setValue(node, value) {
|
|
9377
10044
|
node.setAttribute("text", collapseWhitespace(value));
|
|
9378
10045
|
}
|
|
9379
|
-
listen(target, eventName, callback,
|
|
9380
|
-
|
|
10046
|
+
listen(target, eventName, callback, options) {
|
|
10047
|
+
const resolved = typeof target === "string" ? globalTarget(target, eventName) : target;
|
|
10048
|
+
const remove = resolved.addEventListener(eventName, callback, options);
|
|
10049
|
+
return typeof remove === "function" ? remove : () => resolved.removeEventListener(eventName, callback, options);
|
|
9381
10050
|
}
|
|
9382
10051
|
};
|
|
10052
|
+
const globalTarget = (name, eventName) => {
|
|
10053
|
+
const document = globalEvents().document;
|
|
10054
|
+
const target = name === "window" ? document.defaultView : name === "document" ? document : name === "body" ? document.body : null;
|
|
10055
|
+
if (!target) throw new Error(`Unsupported event target ${name} for event ${eventName}`);
|
|
10056
|
+
return target;
|
|
10057
|
+
};
|
|
9383
10058
|
var EmulatedLynxRenderer = class extends LynxRenderer {
|
|
9384
10059
|
#contentClass;
|
|
9385
10060
|
#hostClass;
|
|
@@ -9482,10 +10157,7 @@ const provideRenderer = () => {
|
|
|
9482
10157
|
},
|
|
9483
10158
|
{
|
|
9484
10159
|
provide: DOCUMENT,
|
|
9485
|
-
|
|
9486
|
-
getElementById: () => null,
|
|
9487
|
-
defaultView: globalThis
|
|
9488
|
-
}
|
|
10160
|
+
useFactory: () => globalEvents().document
|
|
9489
10161
|
},
|
|
9490
10162
|
{
|
|
9491
10163
|
provide: APP_BASE_HREF,
|
|
@@ -10649,7 +11321,7 @@ var LynxImageElement = class {
|
|
|
10649
11321
|
for (const listener of Array.from(this.#listeners.get(type) ?? [])) listener.call(this, event);
|
|
10650
11322
|
}
|
|
10651
11323
|
};
|
|
10652
|
-
const isLynxElement = (value) => typeof value === "object" && value !== null && typeof value.observeLayout === "function" && "element" in value;
|
|
11324
|
+
const isLynxElement$1 = (value) => typeof value === "object" && value !== null && typeof value.observeLayout === "function" && "element" in value;
|
|
10653
11325
|
const installCanvasGlobals = (target) => {
|
|
10654
11326
|
const install = (name, value) => {
|
|
10655
11327
|
if (typeof target[name] === "undefined") target[name] = value;
|
|
@@ -10683,7 +11355,7 @@ const installCanvasGlobals = (target) => {
|
|
|
10683
11355
|
if (typeof nativeGetComputedStyle !== "function") target["getComputedStyle"] = Object.assign(() => emptyComputedStyle(), { forLynxElements: true });
|
|
10684
11356
|
else if (!nativeGetComputedStyle.forLynxElements) {
|
|
10685
11357
|
const wrapped = (element, pseudo) => {
|
|
10686
|
-
if (!isLynxElement(element)) return nativeGetComputedStyle.call(target, element, pseudo);
|
|
11358
|
+
if (!isLynxElement$1(element)) return nativeGetComputedStyle.call(target, element, pseudo);
|
|
10687
11359
|
const node = element.element;
|
|
10688
11360
|
const view = node.ownerDocument?.defaultView;
|
|
10689
11361
|
return view ? view.getComputedStyle(node, pseudo) : emptyComputedStyle();
|
|
@@ -10735,7 +11407,7 @@ const sizeOf = (width, height) => [{
|
|
|
10735
11407
|
inlineSize: width,
|
|
10736
11408
|
blockSize: height
|
|
10737
11409
|
}];
|
|
10738
|
-
const entryFor = (target, rect) => {
|
|
11410
|
+
const entryFor$1 = (target, rect) => {
|
|
10739
11411
|
const ratio = pixelRatio();
|
|
10740
11412
|
return {
|
|
10741
11413
|
target,
|
|
@@ -10758,13 +11430,13 @@ var LynxResizeObserver = class {
|
|
|
10758
11430
|
this.#callback = callback;
|
|
10759
11431
|
}
|
|
10760
11432
|
observe(target) {
|
|
10761
|
-
if (!isLynxElement(target)) throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': the target is not an element");
|
|
11433
|
+
if (!isLynxElement$1(target)) throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': the target is not an element");
|
|
10762
11434
|
if (this.#observed.has(target)) return;
|
|
10763
11435
|
let last = null;
|
|
10764
11436
|
const notify = (rect) => {
|
|
10765
11437
|
if (last && last.width === rect.width && last.height === rect.height) return;
|
|
10766
11438
|
last = rect;
|
|
10767
|
-
this.#callback([entryFor(target, rect)], this);
|
|
11439
|
+
this.#callback([entryFor$1(target, rect)], this);
|
|
10768
11440
|
};
|
|
10769
11441
|
this.#observed.set(target, target.observeLayout(notify));
|
|
10770
11442
|
const rect = target.layoutRect;
|
|
@@ -10773,7 +11445,7 @@ var LynxResizeObserver = class {
|
|
|
10773
11445
|
});
|
|
10774
11446
|
}
|
|
10775
11447
|
unobserve(target) {
|
|
10776
|
-
if (!isLynxElement(target)) return;
|
|
11448
|
+
if (!isLynxElement$1(target)) return;
|
|
10777
11449
|
this.#observed.get(target)?.();
|
|
10778
11450
|
this.#observed.delete(target);
|
|
10779
11451
|
}
|
|
@@ -10803,12 +11475,12 @@ const wrapResizeObserver = (NativeResizeObserver) => {
|
|
|
10803
11475
|
});
|
|
10804
11476
|
}
|
|
10805
11477
|
observe(target, options) {
|
|
10806
|
-
const node = isLynxElement(target) ? target.element : target;
|
|
10807
|
-
if (isLynxElement(target)) this.#targets.set(node, target);
|
|
11478
|
+
const node = isLynxElement$1(target) ? target.element : target;
|
|
11479
|
+
if (isLynxElement$1(target)) this.#targets.set(node, target);
|
|
10808
11480
|
this.#observer.observe(node, options);
|
|
10809
11481
|
}
|
|
10810
11482
|
unobserve(target) {
|
|
10811
|
-
const node = isLynxElement(target) ? target.element : target;
|
|
11483
|
+
const node = isLynxElement$1(target) ? target.element : target;
|
|
10812
11484
|
this.#targets.delete(node);
|
|
10813
11485
|
this.#observer.unobserve(node);
|
|
10814
11486
|
}
|
|
@@ -10818,6 +11490,238 @@ const wrapResizeObserver = (NativeResizeObserver) => {
|
|
|
10818
11490
|
}
|
|
10819
11491
|
};
|
|
10820
11492
|
};
|
|
11493
|
+
const isLynxElement = (value) => typeof value === "object" && value !== null && "element" in value && typeof value.addEventListener === "function" && typeof value.observeLayout === "function" && typeof value.parentNode === "function";
|
|
11494
|
+
const SCROLL_CONTAINERS = /* @__PURE__ */ new Set([
|
|
11495
|
+
"scroll-view",
|
|
11496
|
+
"list",
|
|
11497
|
+
"viewpager",
|
|
11498
|
+
"scroll-coordinator"
|
|
11499
|
+
]);
|
|
11500
|
+
const measure = (element) => new Promise((resolve) => measureLayout(element.element, resolve));
|
|
11501
|
+
const measureGeometry = async (target) => {
|
|
11502
|
+
const scrollContainers = [];
|
|
11503
|
+
let top = target;
|
|
11504
|
+
while (!top.isRootPageElement) {
|
|
11505
|
+
const parent = top.parentNode();
|
|
11506
|
+
if (!parent) break;
|
|
11507
|
+
if (SCROLL_CONTAINERS.has(parent.tagName)) scrollContainers.push(parent);
|
|
11508
|
+
top = parent;
|
|
11509
|
+
}
|
|
11510
|
+
const page = top.isRootPageElement ? top : null;
|
|
11511
|
+
const [box, root, ...scrollBoxes] = await Promise.all([
|
|
11512
|
+
measure(target),
|
|
11513
|
+
page ? measure(page) : null,
|
|
11514
|
+
...scrollContainers.map(measure)
|
|
11515
|
+
]);
|
|
11516
|
+
return {
|
|
11517
|
+
box: box ?? null,
|
|
11518
|
+
root: root ?? null,
|
|
11519
|
+
scrollContainers: scrollBoxes
|
|
11520
|
+
};
|
|
11521
|
+
};
|
|
11522
|
+
const intersect = (a, b) => {
|
|
11523
|
+
const left = Math.max(a.left, b.left);
|
|
11524
|
+
const top = Math.max(a.top, b.top);
|
|
11525
|
+
const right = Math.min(a.left + a.width, b.left + b.width);
|
|
11526
|
+
const bottom = Math.min(a.top + a.height, b.top + b.height);
|
|
11527
|
+
return right > left && bottom > top ? {
|
|
11528
|
+
left,
|
|
11529
|
+
top,
|
|
11530
|
+
width: right - left,
|
|
11531
|
+
height: bottom - top
|
|
11532
|
+
} : null;
|
|
11533
|
+
};
|
|
11534
|
+
const visiblePart = ({ box, root, scrollContainers }) => {
|
|
11535
|
+
let visible = box;
|
|
11536
|
+
for (const clip of [root, ...scrollContainers]) visible = visible && clip ? intersect(visible, clip) : null;
|
|
11537
|
+
return visible;
|
|
11538
|
+
};
|
|
11539
|
+
const area = (rect) => rect.width * rect.height;
|
|
11540
|
+
const entryFor = (target, geometry, exposed) => {
|
|
11541
|
+
const visible = visiblePart(geometry);
|
|
11542
|
+
const isIntersecting = exposed ?? visible !== null;
|
|
11543
|
+
const { box } = geometry;
|
|
11544
|
+
let intersectionRatio = 0;
|
|
11545
|
+
if (isIntersecting) intersectionRatio = !box || area(box) === 0 ? 1 : visible ? area(visible) / area(box) : 0;
|
|
11546
|
+
return {
|
|
11547
|
+
target,
|
|
11548
|
+
time: performance.now(),
|
|
11549
|
+
rootBounds: geometry.root ? toDOMRect(geometry.root) : null,
|
|
11550
|
+
boundingClientRect: toDOMRect(box),
|
|
11551
|
+
intersectionRect: toDOMRect(isIntersecting ? visible : null),
|
|
11552
|
+
intersectionRatio,
|
|
11553
|
+
isIntersecting
|
|
11554
|
+
};
|
|
11555
|
+
};
|
|
11556
|
+
const thresholdsOf = (threshold) => {
|
|
11557
|
+
const given = threshold === void 0 ? [] : Array.isArray(threshold) ? threshold.map(Number) : [Number(threshold)];
|
|
11558
|
+
for (const value of given) if (!(value >= 0 && value <= 1)) throw new RangeError("Failed to construct 'IntersectionObserver': Threshold values must be numbers between 0 and 1");
|
|
11559
|
+
return Object.freeze(given.length ? given.sort((a, b) => a - b) : [0]);
|
|
11560
|
+
};
|
|
11561
|
+
const rootMarginOf = (margin) => {
|
|
11562
|
+
const tokens = String(margin ?? "").trim().split(/\s+/).filter(Boolean);
|
|
11563
|
+
if (tokens.length > 4) throw invalidRootMargin();
|
|
11564
|
+
const [top = "0px", right = top, bottom = top, left = right] = tokens.map((token) => {
|
|
11565
|
+
const match = /^(-?(?:\d+\.?\d*|\.\d+))(px|%)?$/.exec(token);
|
|
11566
|
+
if (!match || !match[2] && Number(match[1]) !== 0) throw invalidRootMargin();
|
|
11567
|
+
return match[2] ? token : "0px";
|
|
11568
|
+
});
|
|
11569
|
+
return `${top} ${right} ${bottom} ${left}`;
|
|
11570
|
+
};
|
|
11571
|
+
const invalidRootMargin = () => /* @__PURE__ */ new SyntaxError("Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.");
|
|
11572
|
+
const DEFAULT_ROOT_MARGIN = "0px 0px 0px 0px";
|
|
11573
|
+
let warnedOfOptions = false;
|
|
11574
|
+
const warnOfOptions = (observer) => {
|
|
11575
|
+
if (warnedOfOptions) return;
|
|
11576
|
+
const ignored = [
|
|
11577
|
+
observer.root !== null && "root",
|
|
11578
|
+
observer.rootMargin !== DEFAULT_ROOT_MARGIN && "rootMargin",
|
|
11579
|
+
(observer.thresholds.length !== 1 || observer.thresholds[0] !== 0) && "threshold"
|
|
11580
|
+
].filter(Boolean);
|
|
11581
|
+
if (!ignored.length) return;
|
|
11582
|
+
warnedOfOptions = true;
|
|
11583
|
+
console.warn(`[angular-lynx] IntersectionObserver on Lynx reports when an element comes into view and when it leaves, inside its scroll containers and the screen. It ignores ${ignored.join(", ")} for now.`);
|
|
11584
|
+
};
|
|
11585
|
+
var LynxIntersectionObserver = class {
|
|
11586
|
+
static forLynxElements = true;
|
|
11587
|
+
root;
|
|
11588
|
+
rootMargin;
|
|
11589
|
+
thresholds;
|
|
11590
|
+
#callback;
|
|
11591
|
+
#observed = /* @__PURE__ */ new Map();
|
|
11592
|
+
#records = [];
|
|
11593
|
+
#delivering = false;
|
|
11594
|
+
constructor(callback, options = {}) {
|
|
11595
|
+
if (typeof callback !== "function") throw new TypeError("Failed to construct 'IntersectionObserver': parameter 1 is not of type 'Function'.");
|
|
11596
|
+
this.#callback = callback;
|
|
11597
|
+
const root = options.root;
|
|
11598
|
+
this.root = root === void 0 || root === globalThis.document ? null : root;
|
|
11599
|
+
this.rootMargin = rootMarginOf(options.rootMargin);
|
|
11600
|
+
this.thresholds = thresholdsOf(options.threshold);
|
|
11601
|
+
warnOfOptions(this);
|
|
11602
|
+
}
|
|
11603
|
+
observe(target) {
|
|
11604
|
+
if (!isLynxElement(target)) throw new TypeError("Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'.");
|
|
11605
|
+
if (this.#observed.has(target)) return;
|
|
11606
|
+
const stopAppear = target.addEventListener("binduiappear", () => {
|
|
11607
|
+
this.#report(target, observation, true);
|
|
11608
|
+
});
|
|
11609
|
+
const stopDisappear = target.addEventListener("binduidisappear", () => {
|
|
11610
|
+
this.#report(target, observation, false);
|
|
11611
|
+
});
|
|
11612
|
+
let laidOut = false;
|
|
11613
|
+
const first = () => {
|
|
11614
|
+
if (laidOut) return;
|
|
11615
|
+
laidOut = true;
|
|
11616
|
+
stopLayout();
|
|
11617
|
+
this.#report(target, observation, null);
|
|
11618
|
+
};
|
|
11619
|
+
const stopLayout = target.observeLayout(first);
|
|
11620
|
+
const observation = {
|
|
11621
|
+
stop: () => {
|
|
11622
|
+
stopAppear();
|
|
11623
|
+
stopDisappear();
|
|
11624
|
+
stopLayout();
|
|
11625
|
+
},
|
|
11626
|
+
intersecting: null,
|
|
11627
|
+
events: 0
|
|
11628
|
+
};
|
|
11629
|
+
this.#observed.set(target, observation);
|
|
11630
|
+
if (target.layoutRect) queueMicrotask(first);
|
|
11631
|
+
}
|
|
11632
|
+
unobserve(target) {
|
|
11633
|
+
const observation = this.#observed.get(target);
|
|
11634
|
+
if (!observation) return;
|
|
11635
|
+
observation.stop();
|
|
11636
|
+
this.#observed.delete(target);
|
|
11637
|
+
this.#records = this.#records.filter((entry) => entry.target !== target);
|
|
11638
|
+
}
|
|
11639
|
+
disconnect() {
|
|
11640
|
+
for (const observation of this.#observed.values()) observation.stop();
|
|
11641
|
+
this.#observed.clear();
|
|
11642
|
+
this.#records = [];
|
|
11643
|
+
}
|
|
11644
|
+
takeRecords() {
|
|
11645
|
+
return this.#records.splice(0);
|
|
11646
|
+
}
|
|
11647
|
+
async #report(target, observation, exposed) {
|
|
11648
|
+
const event = exposed === null ? 0 : ++observation.events;
|
|
11649
|
+
const geometry = await measureGeometry(target);
|
|
11650
|
+
if (this.#observed.get(target) !== observation) return;
|
|
11651
|
+
if (observation.events !== event) return;
|
|
11652
|
+
const entry = entryFor(target, geometry, exposed);
|
|
11653
|
+
if (entry.isIntersecting === observation.intersecting) return;
|
|
11654
|
+
observation.intersecting = entry.isIntersecting;
|
|
11655
|
+
this.#records.push(entry);
|
|
11656
|
+
this.#deliverSoon();
|
|
11657
|
+
}
|
|
11658
|
+
#deliverSoon() {
|
|
11659
|
+
if (this.#delivering) return;
|
|
11660
|
+
this.#delivering = true;
|
|
11661
|
+
queueMicrotask(() => {
|
|
11662
|
+
this.#delivering = false;
|
|
11663
|
+
const records = this.takeRecords();
|
|
11664
|
+
if (records.length) this.#callback.call(this, records, this);
|
|
11665
|
+
});
|
|
11666
|
+
}
|
|
11667
|
+
};
|
|
11668
|
+
const wrapIntersectionObserver = (NativeIntersectionObserver) => {
|
|
11669
|
+
const toNode = (value) => isLynxElement(value) ? value.element : value;
|
|
11670
|
+
return class LynxWebIntersectionObserver {
|
|
11671
|
+
static forLynxElements = true;
|
|
11672
|
+
root;
|
|
11673
|
+
#observer;
|
|
11674
|
+
#targets = /* @__PURE__ */ new Map();
|
|
11675
|
+
constructor(callback, options) {
|
|
11676
|
+
this.root = options?.root ?? null;
|
|
11677
|
+
this.#observer = new NativeIntersectionObserver((entries) => callback(entries.map((entry) => this.#entry(entry)), this), options && {
|
|
11678
|
+
...options,
|
|
11679
|
+
root: toNode(options.root)
|
|
11680
|
+
});
|
|
11681
|
+
}
|
|
11682
|
+
get rootMargin() {
|
|
11683
|
+
return this.#observer.rootMargin;
|
|
11684
|
+
}
|
|
11685
|
+
get thresholds() {
|
|
11686
|
+
return this.#observer.thresholds;
|
|
11687
|
+
}
|
|
11688
|
+
observe(target) {
|
|
11689
|
+
const node = toNode(target);
|
|
11690
|
+
if (node !== target) this.#targets.set(node, target);
|
|
11691
|
+
this.#observer.observe(node);
|
|
11692
|
+
}
|
|
11693
|
+
unobserve(target) {
|
|
11694
|
+
const node = toNode(target);
|
|
11695
|
+
this.#targets.delete(node);
|
|
11696
|
+
this.#observer.unobserve(node);
|
|
11697
|
+
}
|
|
11698
|
+
disconnect() {
|
|
11699
|
+
this.#targets.clear();
|
|
11700
|
+
this.#observer.disconnect();
|
|
11701
|
+
}
|
|
11702
|
+
takeRecords() {
|
|
11703
|
+
return this.#observer.takeRecords().map((entry) => this.#entry(entry));
|
|
11704
|
+
}
|
|
11705
|
+
#entry(entry) {
|
|
11706
|
+
const target = this.#targets.get(entry.target);
|
|
11707
|
+
if (!target) return entry;
|
|
11708
|
+
return {
|
|
11709
|
+
target,
|
|
11710
|
+
time: entry.time,
|
|
11711
|
+
rootBounds: entry.rootBounds,
|
|
11712
|
+
boundingClientRect: entry.boundingClientRect,
|
|
11713
|
+
intersectionRect: entry.intersectionRect,
|
|
11714
|
+
intersectionRatio: entry.intersectionRatio,
|
|
11715
|
+
isIntersecting: entry.isIntersecting
|
|
11716
|
+
};
|
|
11717
|
+
}
|
|
11718
|
+
};
|
|
11719
|
+
};
|
|
11720
|
+
const installIntersectionObserver = (target) => {
|
|
11721
|
+
const native = target["IntersectionObserver"];
|
|
11722
|
+
if (typeof native === "undefined") target["IntersectionObserver"] = LynxIntersectionObserver;
|
|
11723
|
+
else if (!native.forLynxElements) target["IntersectionObserver"] = wrapIntersectionObserver(native);
|
|
11724
|
+
};
|
|
10821
11725
|
const readBundledAsset = (url) => {
|
|
10822
11726
|
const lynxGlobal = globalThis.lynx;
|
|
10823
11727
|
if (typeof lynxGlobal?.module !== "function") return null;
|
|
@@ -11055,9 +11959,20 @@ const parseUrl$1 = (input) => {
|
|
|
11055
11959
|
try {
|
|
11056
11960
|
return new URL(input).href;
|
|
11057
11961
|
} catch {
|
|
11058
|
-
throw new TypeError(`Failed to parse URL from ${input}. Lynx has no page URL to resolve a relative URL against, so
|
|
11962
|
+
throw new TypeError(`Failed to parse URL from ${input}. Lynx has no page URL to resolve a relative URL against, so this needs an absolute URL.`);
|
|
11059
11963
|
}
|
|
11060
11964
|
};
|
|
11965
|
+
const isRelative = (url) => !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url);
|
|
11966
|
+
const PLACEHOLDER_BASE = "http://placeholder.invalid/";
|
|
11967
|
+
const parseRequestUrl = (input) => {
|
|
11968
|
+
if (!isRelative(input)) return parseUrl$1(input);
|
|
11969
|
+
try {
|
|
11970
|
+
new URL(input, PLACEHOLDER_BASE);
|
|
11971
|
+
} catch {
|
|
11972
|
+
throw new TypeError(`Failed to parse URL from ${input}.`);
|
|
11973
|
+
}
|
|
11974
|
+
return input;
|
|
11975
|
+
};
|
|
11061
11976
|
const DEFAULT_OPTIONS = {
|
|
11062
11977
|
cache: "default",
|
|
11063
11978
|
credentials: "same-origin",
|
|
@@ -11096,7 +12011,7 @@ var LynxRequest = class LynxRequest extends LynxBody {
|
|
|
11096
12011
|
};
|
|
11097
12012
|
if (source !== null && (upper === "GET" || upper === "HEAD")) throw new TypeError("Failed to construct 'Request': Request with GET/HEAD method cannot have body.");
|
|
11098
12013
|
super(source);
|
|
11099
|
-
this.url = base ? base.url :
|
|
12014
|
+
this.url = base ? base.url : parseRequestUrl(String(input));
|
|
11100
12015
|
this.method = normalizedMethod;
|
|
11101
12016
|
this.headers = new LynxHeaders(init.headers ?? base?.headers);
|
|
11102
12017
|
if (type !== null && !this.headers.has("content-type")) this.headers.set("content-type", type);
|
|
@@ -11215,21 +12130,18 @@ var LynxResponse = class LynxResponse extends LynxBody {
|
|
|
11215
12130
|
}
|
|
11216
12131
|
};
|
|
11217
12132
|
let nextFetchId = 0;
|
|
11218
|
-
const
|
|
11219
|
-
const
|
|
11220
|
-
if (
|
|
11221
|
-
if (init?.method && init.method.toUpperCase() !== "GET") return null;
|
|
11222
|
-
const bytes = readBundledAsset(input);
|
|
11223
|
-
if (!bytes) return null;
|
|
12133
|
+
const bundledResponse = (request) => {
|
|
12134
|
+
const bytes = request.method === "GET" ? readBundledAsset(request.url) : null;
|
|
12135
|
+
if (!bytes) return /* @__PURE__ */ new TypeError(`Failed to fetch ${request.url}. Lynx has no page URL to resolve a relative URL against: only a GET of a file the app bundles can use one, and other requests need an absolute URL.`);
|
|
11224
12136
|
return new LynxResponse(new ExtractedBody(bytes), {
|
|
11225
12137
|
status: 200,
|
|
11226
12138
|
statusText: "OK",
|
|
11227
12139
|
headers: {
|
|
11228
|
-
"content-type": typeOfAsset(
|
|
12140
|
+
"content-type": typeOfAsset(request.url),
|
|
11229
12141
|
"content-length": String(bytes.byteLength)
|
|
11230
12142
|
}
|
|
11231
12143
|
}, {
|
|
11232
|
-
url:
|
|
12144
|
+
url: request.url,
|
|
11233
12145
|
redirected: false,
|
|
11234
12146
|
type: "basic"
|
|
11235
12147
|
});
|
|
@@ -11267,18 +12179,13 @@ const localResponse = (url) => {
|
|
|
11267
12179
|
return null;
|
|
11268
12180
|
};
|
|
11269
12181
|
const relayFetch = (input, init) => new Promise((resolve, reject) => {
|
|
11270
|
-
const bundled = bundledResponse(input, init);
|
|
11271
|
-
if (bundled) {
|
|
11272
|
-
resolve(bundled);
|
|
11273
|
-
return;
|
|
11274
|
-
}
|
|
11275
12182
|
const request = new LynxRequest(input, init);
|
|
11276
12183
|
const { signal } = request;
|
|
11277
12184
|
if (signal.aborted) {
|
|
11278
12185
|
reject(signal.reason);
|
|
11279
12186
|
return;
|
|
11280
12187
|
}
|
|
11281
|
-
const local = localResponse(request.url);
|
|
12188
|
+
const local = isRelative(request.url) ? bundledResponse(request) : localResponse(request.url);
|
|
11282
12189
|
if (local) {
|
|
11283
12190
|
if (local instanceof LynxResponse) resolve(local);
|
|
11284
12191
|
else reject(local);
|
|
@@ -12327,18 +13234,24 @@ if (typeof Node === "undefined") try {
|
|
|
12327
13234
|
});
|
|
12328
13235
|
globalThis.Node = LynxNode;
|
|
12329
13236
|
} catch {}
|
|
12330
|
-
if (
|
|
13237
|
+
if (isMainThread()) installGlobalDocument(globalThis, globalEvents());
|
|
13238
|
+
else if (typeof document === "undefined") globalThis.document = {
|
|
12331
13239
|
defaultView: globalThis,
|
|
12332
13240
|
querySelector: () => null
|
|
12333
13241
|
};
|
|
12334
13242
|
try {
|
|
12335
13243
|
if (typeof window === "undefined") globalThis.window = globalThis;
|
|
12336
|
-
} catch {
|
|
13244
|
+
} catch {
|
|
13245
|
+
if (__WEB__) window = globalThis;
|
|
13246
|
+
}
|
|
12337
13247
|
try {
|
|
12338
13248
|
if (typeof navigator === "undefined") globalThis.navigator = { userAgent: "" };
|
|
12339
13249
|
} catch {}
|
|
12340
|
-
if (
|
|
12341
|
-
|
|
13250
|
+
if (isMainThread()) installGlobalWindow(globalThis, globalEvents());
|
|
13251
|
+
else {
|
|
13252
|
+
if (typeof globalThis.addEventListener !== "function") globalThis.addEventListener = () => {};
|
|
13253
|
+
if (typeof globalThis.removeEventListener !== "function") globalThis.removeEventListener = () => {};
|
|
13254
|
+
}
|
|
12342
13255
|
if (typeof globalThis.setTimeout !== "function" && typeof lynx !== "undefined") {
|
|
12343
13256
|
const _lynx = lynx;
|
|
12344
13257
|
globalThis.setTimeout = _lynx.setTimeout;
|
|
@@ -12355,7 +13268,10 @@ if (typeof globalThis.requestIdleCallback !== "function" || typeof globalThis.ca
|
|
|
12355
13268
|
}), 0);
|
|
12356
13269
|
globalThis.cancelIdleCallback = (id) => clearTimeout(id);
|
|
12357
13270
|
}
|
|
12358
|
-
if (isMainThread())
|
|
13271
|
+
if (isMainThread()) {
|
|
13272
|
+
installCanvasGlobals(globalThis);
|
|
13273
|
+
installIntersectionObserver(globalThis);
|
|
13274
|
+
}
|
|
12359
13275
|
var Opcode;
|
|
12360
13276
|
(function(Opcode) {
|
|
12361
13277
|
Opcode[Opcode["Begin"] = 0] = "Begin";
|