@blotch/angular-lynx 22.2.9 → 22.2.11
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 +1306 -145
- package/fesm2022/blotch-angular-lynx.mjs.map +1 -1
- package/package.json +1 -1
- package/types/blotch-angular-lynx.d.ts +541 -92
|
@@ -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"],
|
|
@@ -1989,6 +2590,11 @@ const flushesBefore = (first, second) => {
|
|
|
1989
2590
|
const isIOS = () => {
|
|
1990
2591
|
return ((typeof lynx !== "undefined" ? lynx.SystemInfo : void 0) ?? (typeof SystemInfo !== "undefined" ? SystemInfo : void 0))?.platform === "iOS";
|
|
1991
2592
|
};
|
|
2593
|
+
const listenForScrollsFromTheStart = (element) => {
|
|
2594
|
+
if (__WEB__ || !isIOS()) return;
|
|
2595
|
+
element.addEventListener("bindscroll", ignoreScroll);
|
|
2596
|
+
};
|
|
2597
|
+
const ignoreScroll = () => {};
|
|
1992
2598
|
const insertHidesBlurView = (parent, child) => !__WEB__ && child.tagName === "blur-view" && parent.tagName !== "blur-view" && isIOS();
|
|
1993
2599
|
const isTextish = (el) => el.tagName === "text" || el.tagName === "raw-text";
|
|
1994
2600
|
var LynxElement = class {
|
|
@@ -2014,6 +2620,7 @@ var LynxElement = class {
|
|
|
2014
2620
|
#ownTraits = null;
|
|
2015
2621
|
#addedTraits = [];
|
|
2016
2622
|
#listeners = [];
|
|
2623
|
+
#heldEvents = /* @__PURE__ */ new Map();
|
|
2017
2624
|
#webLongPress = null;
|
|
2018
2625
|
#pointerEvents = null;
|
|
2019
2626
|
#webPointer = null;
|
|
@@ -2029,9 +2636,14 @@ var LynxElement = class {
|
|
|
2029
2636
|
static #pendingAttributeRemovals = /* @__PURE__ */ new Set();
|
|
2030
2637
|
#removedAttributes = /* @__PURE__ */ new Set();
|
|
2031
2638
|
static #byNativeId = /* @__PURE__ */ new Map();
|
|
2639
|
+
static #pendingReleases = /* @__PURE__ */ new Set();
|
|
2640
|
+
#destroyed = false;
|
|
2032
2641
|
static #canonicalFor(ref) {
|
|
2033
2642
|
return _a.#byNativeId.get(__GetElementUniqueID(ref)) ?? new _a(ref);
|
|
2034
2643
|
}
|
|
2644
|
+
static byUniqueId(uniqueId) {
|
|
2645
|
+
return _a.#byNativeId.get(uniqueId);
|
|
2646
|
+
}
|
|
2035
2647
|
constructor(element) {
|
|
2036
2648
|
this.#nativeRef = element;
|
|
2037
2649
|
_a.#byNativeId.set(__GetElementUniqueID(element), this);
|
|
@@ -2040,6 +2652,18 @@ var LynxElement = class {
|
|
|
2040
2652
|
const id = __GetElementUniqueID(this.#nativeRef);
|
|
2041
2653
|
if (_a.#byNativeId.get(id) === this) _a.#byNativeId.delete(id);
|
|
2042
2654
|
}
|
|
2655
|
+
markDestroyed() {
|
|
2656
|
+
if (this.isRootPageElement) return;
|
|
2657
|
+
this.#destroyed = true;
|
|
2658
|
+
_a.#pendingReleases.add(this);
|
|
2659
|
+
scheduleSettleFlush();
|
|
2660
|
+
}
|
|
2661
|
+
virtualChildren() {
|
|
2662
|
+
return [];
|
|
2663
|
+
}
|
|
2664
|
+
get ownerDocument() {
|
|
2665
|
+
return globalEvents().document;
|
|
2666
|
+
}
|
|
2043
2667
|
setProperty(name, value) {
|
|
2044
2668
|
this.setAttribute(name, value);
|
|
2045
2669
|
}
|
|
@@ -2155,6 +2779,7 @@ var LynxElement = class {
|
|
|
2155
2779
|
insertBefore(newChild, refChild) {
|
|
2156
2780
|
if (newChild.isRootPageElement) return;
|
|
2157
2781
|
newChild.#cancelPendingRemoval();
|
|
2782
|
+
newChild.#keepIfDestroyed();
|
|
2158
2783
|
newChild.#removeIfMoveWouldBeLost(this);
|
|
2159
2784
|
newChild.#recreateIfDead();
|
|
2160
2785
|
if (refChild == null) this.appendChild(newChild);
|
|
@@ -2176,6 +2801,7 @@ var LynxElement = class {
|
|
|
2176
2801
|
appendChild(newChild) {
|
|
2177
2802
|
if (newChild.isRootPageElement) return;
|
|
2178
2803
|
newChild.#cancelPendingRemoval();
|
|
2804
|
+
newChild.#keepIfDestroyed();
|
|
2179
2805
|
newChild.#removeIfMoveWouldBeLost(this);
|
|
2180
2806
|
newChild.#recreateIfDead();
|
|
2181
2807
|
if (wouldFormCycle(this.element, newChild.element)) return;
|
|
@@ -2234,10 +2860,18 @@ var LynxElement = class {
|
|
|
2234
2860
|
}
|
|
2235
2861
|
}
|
|
2236
2862
|
static commitPendingRemovals() {
|
|
2237
|
-
if (_a.#pendingRemovals.size
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2863
|
+
if (_a.#pendingRemovals.size > 0) {
|
|
2864
|
+
const items = [..._a.#pendingRemovals];
|
|
2865
|
+
_a.#pendingRemovals.clear();
|
|
2866
|
+
for (const el of items) el.#doRemove();
|
|
2867
|
+
}
|
|
2868
|
+
_a.#commitPendingReleases();
|
|
2869
|
+
}
|
|
2870
|
+
static #commitPendingReleases() {
|
|
2871
|
+
if (_a.#pendingReleases.size === 0) return;
|
|
2872
|
+
const elements = [..._a.#pendingReleases];
|
|
2873
|
+
_a.#pendingReleases.clear();
|
|
2874
|
+
for (const el of elements) if (el.#destroyed && !el.#jsParent && !el._virtualParent) el.#release();
|
|
2241
2875
|
}
|
|
2242
2876
|
static #enqueueTextNormalization(el) {
|
|
2243
2877
|
_a.#pendingTextNormalization.add(el);
|
|
@@ -2289,6 +2923,11 @@ var LynxElement = class {
|
|
|
2289
2923
|
#cancelPendingRemoval() {
|
|
2290
2924
|
_a.#pendingRemovals.delete(this);
|
|
2291
2925
|
}
|
|
2926
|
+
#keepIfDestroyed() {
|
|
2927
|
+
if (!this.#destroyed) return;
|
|
2928
|
+
this.#destroyed = false;
|
|
2929
|
+
_a.#pendingReleases.delete(this);
|
|
2930
|
+
}
|
|
2292
2931
|
#removeIfMoveWouldBeLost(newParent) {
|
|
2293
2932
|
if (__WEB__ || this.#paintingDead || this._virtualParent) return;
|
|
2294
2933
|
const oldParent = __GetParent(this.element);
|
|
@@ -2296,7 +2935,7 @@ var LynxElement = class {
|
|
|
2296
2935
|
if (flushesBefore(newParent.element, oldParent)) this.#doRemove();
|
|
2297
2936
|
}
|
|
2298
2937
|
#doRemove() {
|
|
2299
|
-
const parent = this.
|
|
2938
|
+
const parent = __GetParent(this.element);
|
|
2300
2939
|
if (!parent) return;
|
|
2301
2940
|
for (const anim of this.#activeAnimations) anim.cancel();
|
|
2302
2941
|
if (this.#activeAnimations.length > 0) {
|
|
@@ -2304,7 +2943,7 @@ var LynxElement = class {
|
|
|
2304
2943
|
__AddInlineStyle(this.element, "transform", null);
|
|
2305
2944
|
this.#activeAnimations.length = 0;
|
|
2306
2945
|
}
|
|
2307
|
-
__RemoveElement(parent
|
|
2946
|
+
__RemoveElement(parent, this.element);
|
|
2308
2947
|
const jsParent = this.#jsParent;
|
|
2309
2948
|
if (jsParent) {
|
|
2310
2949
|
const i = jsParent.#children.indexOf(this);
|
|
@@ -2314,6 +2953,15 @@ var LynxElement = class {
|
|
|
2314
2953
|
}
|
|
2315
2954
|
this.#markPaintingDead();
|
|
2316
2955
|
if (jsParent && isTextish(this)) _a.#enqueueTextNormalization(jsParent);
|
|
2956
|
+
if (this.#destroyed) this.#release();
|
|
2957
|
+
}
|
|
2958
|
+
#release() {
|
|
2959
|
+
this.#destroyed = false;
|
|
2960
|
+
this.#paintingDead = true;
|
|
2961
|
+
this.deregisterNative();
|
|
2962
|
+
for (const { eventType, eventName } of this.#nativeHandlers.values()) __AddEvent(this.element, eventType, eventName, void 0);
|
|
2963
|
+
for (const child of this.#children) child.#release();
|
|
2964
|
+
for (const child of this.virtualChildren()) child.#release();
|
|
2317
2965
|
}
|
|
2318
2966
|
#markPaintingDead() {
|
|
2319
2967
|
this.#paintingDead = true;
|
|
@@ -2384,10 +3032,19 @@ var LynxElement = class {
|
|
|
2384
3032
|
const parsed = parseEventName(name);
|
|
2385
3033
|
if (!parsed) return () => {};
|
|
2386
3034
|
if (__WEB__ && parsed.eventName === "longpress") this.#listenForWebLongPress();
|
|
2387
|
-
|
|
3035
|
+
return this.#add({
|
|
2388
3036
|
...parsed,
|
|
2389
3037
|
listener: cb
|
|
2390
|
-
};
|
|
3038
|
+
});
|
|
3039
|
+
}
|
|
3040
|
+
addTrailingEventListener(name, cb) {
|
|
3041
|
+
return this.#add({
|
|
3042
|
+
...parseEventName(name),
|
|
3043
|
+
listener: cb,
|
|
3044
|
+
trailing: true
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
#add(entry) {
|
|
2391
3048
|
this.#listeners.push(entry);
|
|
2392
3049
|
this.#syncNativeHandler(entry);
|
|
2393
3050
|
return () => this.#removeListener(entry);
|
|
@@ -2454,7 +3111,7 @@ var LynxElement = class {
|
|
|
2454
3111
|
#layoutTracker() {
|
|
2455
3112
|
this.#layout ??= new LayoutTracker({
|
|
2456
3113
|
listen: (event, listener) => this.addEventListener(event, listener),
|
|
2457
|
-
measure: (callback) =>
|
|
3114
|
+
measure: (callback) => measureLayout(this.element, callback)
|
|
2458
3115
|
});
|
|
2459
3116
|
return this.#layout;
|
|
2460
3117
|
}
|
|
@@ -2511,14 +3168,18 @@ var LynxElement = class {
|
|
|
2511
3168
|
}
|
|
2512
3169
|
#listenersLike(entry) {
|
|
2513
3170
|
const key = nativeEventKey(entry.eventType, entry.eventName);
|
|
2514
|
-
|
|
3171
|
+
const like = this.#listeners.filter((other) => nativeEventKey(other.eventType, other.eventName) === key);
|
|
3172
|
+
return [...like.filter((other) => !other.trailing), ...like.filter((other) => other.trailing)];
|
|
2515
3173
|
}
|
|
2516
3174
|
#syncNativeHandler(entry) {
|
|
2517
3175
|
const key = nativeEventKey(entry.eventType, entry.eventName);
|
|
3176
|
+
if (this.#heldEvents.has(key)) return;
|
|
2518
3177
|
const listeners = this.#listenersLike(entry);
|
|
2519
3178
|
const current = this.#nativeHandlers.get(key);
|
|
2520
3179
|
const eventType = listeners.length ? combinedEventType(listeners) : null;
|
|
2521
3180
|
if (current?.eventType === eventType) return;
|
|
3181
|
+
scheduleSettleFlush();
|
|
3182
|
+
this.#sendHandlersWithNextFlush();
|
|
2522
3183
|
if (current) {
|
|
2523
3184
|
__AddEvent(this.element, current.eventType, entry.eventName, void 0);
|
|
2524
3185
|
this.#nativeHandlers.delete(key);
|
|
@@ -2535,6 +3196,25 @@ var LynxElement = class {
|
|
|
2535
3196
|
value: handler.dispatch
|
|
2536
3197
|
});
|
|
2537
3198
|
}
|
|
3199
|
+
holdNativeEvent(eventName) {
|
|
3200
|
+
this.#heldEvents.set(eventName, (this.#heldEvents.get(eventName) ?? 0) + 1);
|
|
3201
|
+
this.#nativeHandlers.delete(eventName);
|
|
3202
|
+
}
|
|
3203
|
+
releaseNativeEvent(eventName) {
|
|
3204
|
+
const held = this.#heldEvents.get(eventName);
|
|
3205
|
+
if (held === void 0) return;
|
|
3206
|
+
if (held > 1) {
|
|
3207
|
+
this.#heldEvents.set(eventName, held - 1);
|
|
3208
|
+
return;
|
|
3209
|
+
}
|
|
3210
|
+
this.#heldEvents.delete(eventName);
|
|
3211
|
+
const entry = this.#listeners.find((listener) => listener.eventName === eventName && listener.eventType !== "global-bindEvent");
|
|
3212
|
+
if (entry) this.#syncNativeHandler(entry);
|
|
3213
|
+
}
|
|
3214
|
+
#sendHandlersWithNextFlush() {
|
|
3215
|
+
if (__WEB__) return;
|
|
3216
|
+
__SetDataset(this.element, { ...this.#dataset });
|
|
3217
|
+
}
|
|
2538
3218
|
#dispatch(entry, event) {
|
|
2539
3219
|
if (event && typeof event === "object") {
|
|
2540
3220
|
if (typeof event.stopPropagation !== "function") event.stopPropagation = () => {};
|
|
@@ -2542,6 +3222,10 @@ var LynxElement = class {
|
|
|
2542
3222
|
if (typeof event.stopImmediatePropagation !== "function") event.stopImmediatePropagation = () => {};
|
|
2543
3223
|
}
|
|
2544
3224
|
if (__WEB__ && entry.eventName === "tap" && dropsTap()) return void 0;
|
|
3225
|
+
if (__WEB__ && this.tagName === "video" && event && typeof event === "object") {
|
|
3226
|
+
const detail = webVideoDetail(entry.eventName, this.element);
|
|
3227
|
+
if (detail) event.detail = detail;
|
|
3228
|
+
}
|
|
2545
3229
|
const pointer = __WEB__ ? this.#webPointer : this.#pointerEvents?.lastOffset;
|
|
2546
3230
|
if (pointer && entry.eventName === "tap" && event && typeof event === "object" && event.offsetX === void 0) {
|
|
2547
3231
|
event.offsetX = pointer.offsetX;
|
|
@@ -2647,6 +3331,11 @@ var LynxListElement = class extends LynxElement {
|
|
|
2647
3331
|
}
|
|
2648
3332
|
return children;
|
|
2649
3333
|
}
|
|
3334
|
+
virtualChildren() {
|
|
3335
|
+
const children = [];
|
|
3336
|
+
for (let child = this.#firstVirtualChild; child; child = child._virtualNext) children.push(child);
|
|
3337
|
+
return children;
|
|
3338
|
+
}
|
|
2650
3339
|
getCommittedUIChildren() {
|
|
2651
3340
|
return this.#committedUIChildren;
|
|
2652
3341
|
}
|
|
@@ -5315,6 +6004,9 @@ const noHandler = () => ({
|
|
|
5315
6004
|
});
|
|
5316
6005
|
var LynxMainThreadEvent = class LynxMainThreadEvent {
|
|
5317
6006
|
#el = inject(ElementRef).nativeElement;
|
|
6007
|
+
get #host() {
|
|
6008
|
+
return this.#el;
|
|
6009
|
+
}
|
|
5318
6010
|
#registrations = /* @__PURE__ */ new Map();
|
|
5319
6011
|
mainThreadBindtap;
|
|
5320
6012
|
mainThreadCatchtap;
|
|
@@ -5359,9 +6051,13 @@ var LynxMainThreadEvent = class LynxMainThreadEvent {
|
|
|
5359
6051
|
__workletMap[workletId] = handle;
|
|
5360
6052
|
}
|
|
5361
6053
|
if (workletId === void 0) {
|
|
5362
|
-
if (this.#registrations.delete(inputName))
|
|
6054
|
+
if (this.#registrations.delete(inputName)) {
|
|
6055
|
+
__AddEvent(elementRef, eventType, eventName, noHandler());
|
|
6056
|
+
this.#host.releaseNativeEvent?.(eventName);
|
|
6057
|
+
}
|
|
5363
6058
|
continue;
|
|
5364
6059
|
}
|
|
6060
|
+
if (!this.#registrations.has(inputName)) this.#host.holdNativeEvent?.(eventName);
|
|
5365
6061
|
__AddEvent(elementRef, eventType, eventName, {
|
|
5366
6062
|
type: "worklet",
|
|
5367
6063
|
value: {
|
|
@@ -5377,6 +6073,7 @@ var LynxMainThreadEvent = class LynxMainThreadEvent {
|
|
|
5377
6073
|
if (!elementRef) return;
|
|
5378
6074
|
for (const [inputName, { eventType, eventName }] of this.#registrations) {
|
|
5379
6075
|
__AddEvent(elementRef, eventType, eventName, noHandler());
|
|
6076
|
+
this.#host.releaseNativeEvent?.(eventName);
|
|
5380
6077
|
this.#release(inputName);
|
|
5381
6078
|
}
|
|
5382
6079
|
this.#registrations.clear();
|
|
@@ -8971,6 +9668,7 @@ const CONTEXT_EVENTS = /* @__PURE__ */ new Set([
|
|
|
8971
9668
|
"webglcontextrestored",
|
|
8972
9669
|
"webglcontextcreationerror"
|
|
8973
9670
|
]);
|
|
9671
|
+
const contextFinalizer = typeof FinalizationRegistry === "function" ? new FinalizationRegistry((free) => free()) : null;
|
|
8974
9672
|
const kebab = (name) => name.startsWith("--") ? name : name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
8975
9673
|
const createStyle = (element) => {
|
|
8976
9674
|
return new Proxy({}, {
|
|
@@ -9080,6 +9778,7 @@ var LynxCanvasElement = class extends LynxElement {
|
|
|
9080
9778
|
return null;
|
|
9081
9779
|
}
|
|
9082
9780
|
this.#context = new LynxWebGL2RenderingContext(bridge, contextId, this, resolved);
|
|
9781
|
+
contextFinalizer?.register(this, () => bridge.destroy(contextId));
|
|
9083
9782
|
return this.#context;
|
|
9084
9783
|
}
|
|
9085
9784
|
addEventListener(name, cb) {
|
|
@@ -9210,6 +9909,7 @@ var LynxDocument = class {
|
|
|
9210
9909
|
if (isAndroid()) __SetID(pageElement, ANDROID_BLUR_CAPTURE_TARGET);
|
|
9211
9910
|
this.#pageId = __GetElementUniqueID(pageElement);
|
|
9212
9911
|
setPageElementRef(pageElement);
|
|
9912
|
+
globalEvents().attach(this.page, (id) => LynxElement.byUniqueId(id));
|
|
9213
9913
|
return this.page;
|
|
9214
9914
|
}
|
|
9215
9915
|
createElement(name, value) {
|
|
@@ -9217,7 +9917,11 @@ var LynxDocument = class {
|
|
|
9217
9917
|
/* v8 ignore next */
|
|
9218
9918
|
if (__PROFILE__) devStats.elementCreated++;
|
|
9219
9919
|
scheduleSettleFlush();
|
|
9220
|
-
if (tag === "list")
|
|
9920
|
+
if (tag === "list") {
|
|
9921
|
+
const list = createListElement(this.#pageId);
|
|
9922
|
+
listenForScrollsFromTheStart(list);
|
|
9923
|
+
return list;
|
|
9924
|
+
}
|
|
9221
9925
|
if (tag === "page") {
|
|
9222
9926
|
const result = createPageElement(this.page, this.#pageElementRequested);
|
|
9223
9927
|
this.#pageElementRequested = result.pageElementRequested;
|
|
@@ -9228,6 +9932,7 @@ var LynxDocument = class {
|
|
|
9228
9932
|
el.tagName = tag;
|
|
9229
9933
|
if (tag === "raw-text") el.setInitialText(value ?? "");
|
|
9230
9934
|
if (tag === "blur-view") el.updateBlurMaterial();
|
|
9935
|
+
if (tag === "scroll-view") listenForScrollsFromTheStart(el);
|
|
9231
9936
|
return el;
|
|
9232
9937
|
}
|
|
9233
9938
|
createText(value) {
|
|
@@ -9278,6 +9983,7 @@ var LynxHydrateDocument = class {
|
|
|
9278
9983
|
page.tagName = "page";
|
|
9279
9984
|
page.isRootPageElement = true;
|
|
9280
9985
|
this.#page = page;
|
|
9986
|
+
globalEvents().attach(page, (id) => LynxElement.byUniqueId(id));
|
|
9281
9987
|
return page;
|
|
9282
9988
|
}
|
|
9283
9989
|
createElement(tag, value) {
|
|
@@ -9306,7 +10012,48 @@ var LynxHydrateDocument = class {
|
|
|
9306
10012
|
this.#page?.appendChild(newChild);
|
|
9307
10013
|
}
|
|
9308
10014
|
};
|
|
10015
|
+
const LYNX_ELEMENT_TAGS = /* @__PURE__ */ new Set([
|
|
10016
|
+
"page",
|
|
10017
|
+
"view",
|
|
10018
|
+
"text",
|
|
10019
|
+
"raw-text",
|
|
10020
|
+
"inline-truncation",
|
|
10021
|
+
"image",
|
|
10022
|
+
"scroll-view",
|
|
10023
|
+
"list",
|
|
10024
|
+
"list-item",
|
|
10025
|
+
"block",
|
|
10026
|
+
"if",
|
|
10027
|
+
"for",
|
|
10028
|
+
"frame",
|
|
10029
|
+
"input",
|
|
10030
|
+
"textarea",
|
|
10031
|
+
"overlay",
|
|
10032
|
+
"svg",
|
|
10033
|
+
"viewpager",
|
|
10034
|
+
"viewpager-item",
|
|
10035
|
+
"refresh",
|
|
10036
|
+
"refresh-header",
|
|
10037
|
+
"title-bar-view",
|
|
10038
|
+
"scroll-coordinator",
|
|
10039
|
+
"scroll-coordinator-header",
|
|
10040
|
+
"scroll-coordinator-toolbar",
|
|
10041
|
+
"scroll-coordinator-slot",
|
|
10042
|
+
"scroll-coordinator-slot-drag",
|
|
10043
|
+
"blur-view",
|
|
10044
|
+
"webview",
|
|
10045
|
+
"video",
|
|
10046
|
+
"cover-view",
|
|
10047
|
+
"canvas",
|
|
10048
|
+
"comment"
|
|
10049
|
+
]);
|
|
10050
|
+
const tagClassOf = (tag) => `_ngtag-${tag.toLowerCase()}`;
|
|
10051
|
+
const tagClassFor = (tag) => LYNX_ELEMENT_TAGS.has(tag) ? null : tagClassOf(tag);
|
|
9309
10052
|
const collapseWhitespace = (value) => value.replace(/[ \t\n\r\f\v]+/g, " ");
|
|
10053
|
+
const markTag = (element, tag) => {
|
|
10054
|
+
const tagClass = tagClassFor(tag);
|
|
10055
|
+
if (tagClass) element.addScopeClass(tagClass);
|
|
10056
|
+
};
|
|
9310
10057
|
var LynxRenderer = class {
|
|
9311
10058
|
#document;
|
|
9312
10059
|
#data = {};
|
|
@@ -9318,7 +10065,9 @@ var LynxRenderer = class {
|
|
|
9318
10065
|
}
|
|
9319
10066
|
destroy() {}
|
|
9320
10067
|
createElement(name, _namespace) {
|
|
9321
|
-
|
|
10068
|
+
const element = this.#document.createElement(name);
|
|
10069
|
+
markTag(element, name);
|
|
10070
|
+
return element;
|
|
9322
10071
|
}
|
|
9323
10072
|
createComment(_value) {
|
|
9324
10073
|
return this.#document.createComment();
|
|
@@ -9327,7 +10076,7 @@ var LynxRenderer = class {
|
|
|
9327
10076
|
return this.#document.createText(collapseWhitespace(value));
|
|
9328
10077
|
}
|
|
9329
10078
|
destroyNode = (node) => {
|
|
9330
|
-
node.
|
|
10079
|
+
node.markDestroyed?.();
|
|
9331
10080
|
node.releaseContext?.();
|
|
9332
10081
|
};
|
|
9333
10082
|
appendChild(parent, newChild) {
|
|
@@ -9376,10 +10125,18 @@ var LynxRenderer = class {
|
|
|
9376
10125
|
setValue(node, value) {
|
|
9377
10126
|
node.setAttribute("text", collapseWhitespace(value));
|
|
9378
10127
|
}
|
|
9379
|
-
listen(target, eventName, callback,
|
|
9380
|
-
|
|
10128
|
+
listen(target, eventName, callback, options) {
|
|
10129
|
+
const resolved = typeof target === "string" ? globalTarget(target, eventName) : target;
|
|
10130
|
+
const remove = resolved.addEventListener(eventName, callback, options);
|
|
10131
|
+
return typeof remove === "function" ? remove : () => resolved.removeEventListener(eventName, callback, options);
|
|
9381
10132
|
}
|
|
9382
10133
|
};
|
|
10134
|
+
const globalTarget = (name, eventName) => {
|
|
10135
|
+
const document = globalEvents().document;
|
|
10136
|
+
const target = name === "window" ? document.defaultView : name === "document" ? document : name === "body" ? document.body : null;
|
|
10137
|
+
if (!target) throw new Error(`Unsupported event target ${name} for event ${eventName}`);
|
|
10138
|
+
return target;
|
|
10139
|
+
};
|
|
9383
10140
|
var EmulatedLynxRenderer = class extends LynxRenderer {
|
|
9384
10141
|
#contentClass;
|
|
9385
10142
|
#hostClass;
|
|
@@ -9482,10 +10239,7 @@ const provideRenderer = () => {
|
|
|
9482
10239
|
},
|
|
9483
10240
|
{
|
|
9484
10241
|
provide: DOCUMENT,
|
|
9485
|
-
|
|
9486
|
-
getElementById: () => null,
|
|
9487
|
-
defaultView: globalThis
|
|
9488
|
-
}
|
|
10242
|
+
useFactory: () => globalEvents().document
|
|
9489
10243
|
},
|
|
9490
10244
|
{
|
|
9491
10245
|
provide: APP_BASE_HREF,
|
|
@@ -10649,7 +11403,7 @@ var LynxImageElement = class {
|
|
|
10649
11403
|
for (const listener of Array.from(this.#listeners.get(type) ?? [])) listener.call(this, event);
|
|
10650
11404
|
}
|
|
10651
11405
|
};
|
|
10652
|
-
const isLynxElement = (value) => typeof value === "object" && value !== null && typeof value.observeLayout === "function" && "element" in value;
|
|
11406
|
+
const isLynxElement$1 = (value) => typeof value === "object" && value !== null && typeof value.observeLayout === "function" && "element" in value;
|
|
10653
11407
|
const installCanvasGlobals = (target) => {
|
|
10654
11408
|
const install = (name, value) => {
|
|
10655
11409
|
if (typeof target[name] === "undefined") target[name] = value;
|
|
@@ -10683,7 +11437,7 @@ const installCanvasGlobals = (target) => {
|
|
|
10683
11437
|
if (typeof nativeGetComputedStyle !== "function") target["getComputedStyle"] = Object.assign(() => emptyComputedStyle(), { forLynxElements: true });
|
|
10684
11438
|
else if (!nativeGetComputedStyle.forLynxElements) {
|
|
10685
11439
|
const wrapped = (element, pseudo) => {
|
|
10686
|
-
if (!isLynxElement(element)) return nativeGetComputedStyle.call(target, element, pseudo);
|
|
11440
|
+
if (!isLynxElement$1(element)) return nativeGetComputedStyle.call(target, element, pseudo);
|
|
10687
11441
|
const node = element.element;
|
|
10688
11442
|
const view = node.ownerDocument?.defaultView;
|
|
10689
11443
|
return view ? view.getComputedStyle(node, pseudo) : emptyComputedStyle();
|
|
@@ -10758,7 +11512,7 @@ var LynxResizeObserver = class {
|
|
|
10758
11512
|
this.#callback = callback;
|
|
10759
11513
|
}
|
|
10760
11514
|
observe(target) {
|
|
10761
|
-
if (!isLynxElement(target)) throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': the target is not an element");
|
|
11515
|
+
if (!isLynxElement$1(target)) throw new TypeError("Failed to execute 'observe' on 'ResizeObserver': the target is not an element");
|
|
10762
11516
|
if (this.#observed.has(target)) return;
|
|
10763
11517
|
let last = null;
|
|
10764
11518
|
const notify = (rect) => {
|
|
@@ -10773,7 +11527,7 @@ var LynxResizeObserver = class {
|
|
|
10773
11527
|
});
|
|
10774
11528
|
}
|
|
10775
11529
|
unobserve(target) {
|
|
10776
|
-
if (!isLynxElement(target)) return;
|
|
11530
|
+
if (!isLynxElement$1(target)) return;
|
|
10777
11531
|
this.#observed.get(target)?.();
|
|
10778
11532
|
this.#observed.delete(target);
|
|
10779
11533
|
}
|
|
@@ -10803,12 +11557,12 @@ const wrapResizeObserver = (NativeResizeObserver) => {
|
|
|
10803
11557
|
});
|
|
10804
11558
|
}
|
|
10805
11559
|
observe(target, options) {
|
|
10806
|
-
const node = isLynxElement(target) ? target.element : target;
|
|
10807
|
-
if (isLynxElement(target)) this.#targets.set(node, target);
|
|
11560
|
+
const node = isLynxElement$1(target) ? target.element : target;
|
|
11561
|
+
if (isLynxElement$1(target)) this.#targets.set(node, target);
|
|
10808
11562
|
this.#observer.observe(node, options);
|
|
10809
11563
|
}
|
|
10810
11564
|
unobserve(target) {
|
|
10811
|
-
const node = isLynxElement(target) ? target.element : target;
|
|
11565
|
+
const node = isLynxElement$1(target) ? target.element : target;
|
|
10812
11566
|
this.#targets.delete(node);
|
|
10813
11567
|
this.#observer.unobserve(node);
|
|
10814
11568
|
}
|
|
@@ -10818,6 +11572,401 @@ const wrapResizeObserver = (NativeResizeObserver) => {
|
|
|
10818
11572
|
}
|
|
10819
11573
|
};
|
|
10820
11574
|
};
|
|
11575
|
+
const isLynxElement = (value) => typeof value === "object" && value !== null && "element" in value && typeof value.addEventListener === "function" && typeof value.observeLayout === "function" && typeof value.parentNode === "function";
|
|
11576
|
+
const SCROLL_EVENTS = /* @__PURE__ */ new Map([
|
|
11577
|
+
["scroll-view", "bindscroll"],
|
|
11578
|
+
["list", "bindscroll"],
|
|
11579
|
+
["viewpager", "bindoffsetchange"],
|
|
11580
|
+
["scroll-coordinator", "bindoffset"]
|
|
11581
|
+
]);
|
|
11582
|
+
const measurements = /* @__PURE__ */ new Map();
|
|
11583
|
+
let sampleMeasurements = null;
|
|
11584
|
+
const measure = (element) => {
|
|
11585
|
+
const native = element.element;
|
|
11586
|
+
const shared = sampleMeasurements?.get(native) ?? measurements.get(native);
|
|
11587
|
+
if (shared) return shared;
|
|
11588
|
+
let answered = false;
|
|
11589
|
+
const rect = new Promise((resolve) => measureLayout(native, (box) => {
|
|
11590
|
+
answered = true;
|
|
11591
|
+
measurements.delete(native);
|
|
11592
|
+
resolve(box);
|
|
11593
|
+
}));
|
|
11594
|
+
sampleMeasurements?.set(native, rect);
|
|
11595
|
+
if (!answered) measurements.set(native, rect);
|
|
11596
|
+
return rect;
|
|
11597
|
+
};
|
|
11598
|
+
const measureGeometry = async (target, root) => {
|
|
11599
|
+
const scrollContainers = [];
|
|
11600
|
+
let top = target;
|
|
11601
|
+
let inRoot = false;
|
|
11602
|
+
while (!top.isRootPageElement) {
|
|
11603
|
+
const parent = top.parentNode();
|
|
11604
|
+
if (!parent) break;
|
|
11605
|
+
if (parent === root) {
|
|
11606
|
+
inRoot = true;
|
|
11607
|
+
break;
|
|
11608
|
+
}
|
|
11609
|
+
if (SCROLL_EVENTS.has(parent.tagName)) scrollContainers.push(parent);
|
|
11610
|
+
top = parent;
|
|
11611
|
+
}
|
|
11612
|
+
if (!root) inRoot = top.isRootPageElement === true;
|
|
11613
|
+
const rootElement = root ?? (inRoot ? top : null);
|
|
11614
|
+
const clips = inRoot ? scrollContainers : [];
|
|
11615
|
+
const [box, rootBox, ...scrollBoxes] = await Promise.all([
|
|
11616
|
+
measure(target),
|
|
11617
|
+
rootElement ? measure(rootElement) : null,
|
|
11618
|
+
...clips.map(measure)
|
|
11619
|
+
]);
|
|
11620
|
+
return {
|
|
11621
|
+
box: box ?? null,
|
|
11622
|
+
root: rootBox ?? null,
|
|
11623
|
+
inRoot,
|
|
11624
|
+
scrollContainers: scrollBoxes,
|
|
11625
|
+
scrolledBy: root && inRoot && SCROLL_EVENTS.has(root.tagName) ? [...clips, root] : clips
|
|
11626
|
+
};
|
|
11627
|
+
};
|
|
11628
|
+
const intersect = (a, b, touching) => {
|
|
11629
|
+
const left = Math.max(a.left, b.left);
|
|
11630
|
+
const top = Math.max(a.top, b.top);
|
|
11631
|
+
const right = Math.min(a.left + a.width, b.left + b.width);
|
|
11632
|
+
const bottom = Math.min(a.top + a.height, b.top + b.height);
|
|
11633
|
+
return (touching ? right >= left && bottom >= top : right > left && bottom > top) ? {
|
|
11634
|
+
left,
|
|
11635
|
+
top,
|
|
11636
|
+
width: right - left,
|
|
11637
|
+
height: bottom - top
|
|
11638
|
+
} : null;
|
|
11639
|
+
};
|
|
11640
|
+
const visiblePart = ({ box, root, scrollContainers }) => {
|
|
11641
|
+
let visible = box;
|
|
11642
|
+
for (const clip of [root, ...scrollContainers]) visible = visible && clip ? intersect(visible, clip, false) : null;
|
|
11643
|
+
return visible;
|
|
11644
|
+
};
|
|
11645
|
+
const area = (rect) => rect.width * rect.height;
|
|
11646
|
+
const exposureEntryFor = (target, geometry, exposed) => {
|
|
11647
|
+
const visible = visiblePart(geometry);
|
|
11648
|
+
const isIntersecting = exposed ?? visible !== null;
|
|
11649
|
+
const { box } = geometry;
|
|
11650
|
+
let intersectionRatio = 0;
|
|
11651
|
+
if (isIntersecting) intersectionRatio = !box || area(box) === 0 ? 1 : visible ? area(visible) / area(box) : 0;
|
|
11652
|
+
return {
|
|
11653
|
+
target,
|
|
11654
|
+
time: performance.now(),
|
|
11655
|
+
rootBounds: geometry.root ? toDOMRect(geometry.root) : null,
|
|
11656
|
+
boundingClientRect: toDOMRect(box),
|
|
11657
|
+
intersectionRect: toDOMRect(isIntersecting ? visible : null),
|
|
11658
|
+
intersectionRatio,
|
|
11659
|
+
isIntersecting
|
|
11660
|
+
};
|
|
11661
|
+
};
|
|
11662
|
+
const grow = (rect, margin) => {
|
|
11663
|
+
const [top, right, bottom, left] = margin.map((side, index) => side.percent ? side.value * (index % 2 ? rect.width : rect.height) / 100 : side.value);
|
|
11664
|
+
return {
|
|
11665
|
+
left: rect.left - left,
|
|
11666
|
+
top: rect.top - top,
|
|
11667
|
+
width: Math.max(rect.width + left + right, 0),
|
|
11668
|
+
height: Math.max(rect.height + top + bottom, 0)
|
|
11669
|
+
};
|
|
11670
|
+
};
|
|
11671
|
+
const thresholdIndexOf = (ratio, thresholds) => {
|
|
11672
|
+
let index = 0;
|
|
11673
|
+
while (index < thresholds.length && thresholds[index] <= ratio + 1e-6) index++;
|
|
11674
|
+
return index;
|
|
11675
|
+
};
|
|
11676
|
+
const measuredEntryFor = (target, geometry, margin, thresholds, exposed) => {
|
|
11677
|
+
const { box } = geometry;
|
|
11678
|
+
const rootBounds = geometry.root && grow(geometry.root, margin);
|
|
11679
|
+
let visible = null;
|
|
11680
|
+
let overlaps = false;
|
|
11681
|
+
let ratio = 0;
|
|
11682
|
+
if (!box) {
|
|
11683
|
+
overlaps = exposed === true;
|
|
11684
|
+
ratio = overlaps ? 1 : 0;
|
|
11685
|
+
} else if (geometry.inRoot && rootBounds) {
|
|
11686
|
+
visible = box;
|
|
11687
|
+
for (const clip of [...geometry.scrollContainers, rootBounds]) visible = visible && clip ? intersect(visible, clip, true) : null;
|
|
11688
|
+
if (visible) {
|
|
11689
|
+
overlaps = true;
|
|
11690
|
+
ratio = area(box) === 0 ? 1 : Math.min(area(visible) / area(box), 1);
|
|
11691
|
+
}
|
|
11692
|
+
}
|
|
11693
|
+
const index = overlaps ? thresholdIndexOf(ratio, thresholds) : 0;
|
|
11694
|
+
return {
|
|
11695
|
+
index,
|
|
11696
|
+
entry: {
|
|
11697
|
+
target,
|
|
11698
|
+
time: performance.now(),
|
|
11699
|
+
rootBounds: rootBounds ? toDOMRect(rootBounds) : null,
|
|
11700
|
+
boundingClientRect: toDOMRect(box),
|
|
11701
|
+
intersectionRect: toDOMRect(visible),
|
|
11702
|
+
intersectionRatio: ratio,
|
|
11703
|
+
isIntersecting: index > 0
|
|
11704
|
+
}
|
|
11705
|
+
};
|
|
11706
|
+
};
|
|
11707
|
+
const thresholdsOf = (threshold) => {
|
|
11708
|
+
const given = threshold === void 0 ? [] : Array.isArray(threshold) ? threshold.map(Number) : [Number(threshold)];
|
|
11709
|
+
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");
|
|
11710
|
+
return Object.freeze(given.length ? given.sort((a, b) => a - b) : [0]);
|
|
11711
|
+
};
|
|
11712
|
+
const rootMarginOf = (margin) => {
|
|
11713
|
+
const tokens = String(margin ?? "").trim().split(/\s+/).filter(Boolean);
|
|
11714
|
+
if (tokens.length > 4) throw invalidRootMargin();
|
|
11715
|
+
const [top = NO_MARGIN, right = top, bottom = top, left = right] = tokens.map((token) => {
|
|
11716
|
+
const match = /^(-?(?:\d+\.?\d*|\.\d+))(px|%)?$/.exec(token);
|
|
11717
|
+
if (!match || !match[2] && Number(match[1]) !== 0) throw invalidRootMargin();
|
|
11718
|
+
return match[2] ? {
|
|
11719
|
+
text: token,
|
|
11720
|
+
value: Number(match[1]),
|
|
11721
|
+
percent: match[2] === "%"
|
|
11722
|
+
} : NO_MARGIN;
|
|
11723
|
+
});
|
|
11724
|
+
return [
|
|
11725
|
+
top,
|
|
11726
|
+
right,
|
|
11727
|
+
bottom,
|
|
11728
|
+
left
|
|
11729
|
+
];
|
|
11730
|
+
};
|
|
11731
|
+
const NO_MARGIN = {
|
|
11732
|
+
text: "0px",
|
|
11733
|
+
value: 0,
|
|
11734
|
+
percent: false
|
|
11735
|
+
};
|
|
11736
|
+
const invalidRootMargin = () => /* @__PURE__ */ new SyntaxError("Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.");
|
|
11737
|
+
const SAMPLE_INTERVAL = 50;
|
|
11738
|
+
const SAMPLES_AFTER_SCROLL = 6;
|
|
11739
|
+
const scrolling = /* @__PURE__ */ new Map();
|
|
11740
|
+
let samplingTimer = null;
|
|
11741
|
+
const sampleWhileScrolling = (sample) => {
|
|
11742
|
+
scrolling.set(sample, SAMPLES_AFTER_SCROLL);
|
|
11743
|
+
if (samplingTimer === null) samplingTimer = setTimeout(sampleScrolling, SAMPLE_INTERVAL);
|
|
11744
|
+
};
|
|
11745
|
+
const sampleScrolling = () => {
|
|
11746
|
+
samplingTimer = null;
|
|
11747
|
+
sampleMeasurements = /* @__PURE__ */ new Map();
|
|
11748
|
+
for (const [sample, left] of Array.from(scrolling)) {
|
|
11749
|
+
if (left > 1) scrolling.set(sample, left - 1);
|
|
11750
|
+
else scrolling.delete(sample);
|
|
11751
|
+
sample();
|
|
11752
|
+
}
|
|
11753
|
+
sampleMeasurements = null;
|
|
11754
|
+
if (scrolling.size && samplingTimer === null) samplingTimer = setTimeout(sampleScrolling, SAMPLE_INTERVAL);
|
|
11755
|
+
};
|
|
11756
|
+
const stopSampling = (sample) => {
|
|
11757
|
+
scrolling.delete(sample);
|
|
11758
|
+
if (!scrolling.size && samplingTimer !== null) {
|
|
11759
|
+
clearTimeout(samplingTimer);
|
|
11760
|
+
samplingTimer = null;
|
|
11761
|
+
}
|
|
11762
|
+
};
|
|
11763
|
+
var LynxIntersectionObserver = class {
|
|
11764
|
+
static forLynxElements = true;
|
|
11765
|
+
root;
|
|
11766
|
+
rootMargin;
|
|
11767
|
+
thresholds;
|
|
11768
|
+
#callback;
|
|
11769
|
+
#root;
|
|
11770
|
+
#margin;
|
|
11771
|
+
#measures;
|
|
11772
|
+
#observed = /* @__PURE__ */ new Map();
|
|
11773
|
+
#records = [];
|
|
11774
|
+
#delivering = false;
|
|
11775
|
+
constructor(callback, options = {}) {
|
|
11776
|
+
if (typeof callback !== "function") throw new TypeError("Failed to construct 'IntersectionObserver': parameter 1 is not of type 'Function'.");
|
|
11777
|
+
this.#callback = callback;
|
|
11778
|
+
const root = options.root;
|
|
11779
|
+
if (root === void 0 || root === null || root === globalThis.document) this.#root = null;
|
|
11780
|
+
else if (isLynxElement(root)) this.#root = root;
|
|
11781
|
+
else throw new TypeError("Failed to construct 'IntersectionObserver': Failed to read the 'root' property from 'IntersectionObserverInit': The provided value is not of type '(Document or Element)'.");
|
|
11782
|
+
this.root = this.#root;
|
|
11783
|
+
this.#margin = rootMarginOf(options.rootMargin);
|
|
11784
|
+
this.rootMargin = this.#margin.map((side) => side.text).join(" ");
|
|
11785
|
+
this.thresholds = thresholdsOf(options.threshold);
|
|
11786
|
+
this.#measures = this.#root !== null || this.#margin.some((side) => side.value !== 0) || this.thresholds.length !== 1 || this.thresholds[0] !== 0;
|
|
11787
|
+
}
|
|
11788
|
+
observe(target) {
|
|
11789
|
+
if (!isLynxElement(target)) throw new TypeError("Failed to execute 'observe' on 'IntersectionObserver': parameter 1 is not of type 'Element'.");
|
|
11790
|
+
if (this.#observed.has(target)) return;
|
|
11791
|
+
const stopAppear = target.addEventListener("binduiappear", () => {
|
|
11792
|
+
this.#exposure(target, observation, true);
|
|
11793
|
+
});
|
|
11794
|
+
const stopDisappear = target.addEventListener("binduidisappear", () => {
|
|
11795
|
+
this.#exposure(target, observation, false);
|
|
11796
|
+
});
|
|
11797
|
+
let laidOut = false;
|
|
11798
|
+
const layout = () => {
|
|
11799
|
+
if (this.#measures) {
|
|
11800
|
+
observation.sample();
|
|
11801
|
+
return;
|
|
11802
|
+
}
|
|
11803
|
+
if (laidOut) return;
|
|
11804
|
+
laidOut = true;
|
|
11805
|
+
stopLayout();
|
|
11806
|
+
this.#report(target, observation, null);
|
|
11807
|
+
};
|
|
11808
|
+
const stopLayout = target.observeLayout(layout);
|
|
11809
|
+
const observation = {
|
|
11810
|
+
stop: () => {
|
|
11811
|
+
stopAppear();
|
|
11812
|
+
stopDisappear();
|
|
11813
|
+
stopLayout();
|
|
11814
|
+
for (const stopScroll of observation.scrollListeners.values()) stopScroll();
|
|
11815
|
+
observation.scrollListeners.clear();
|
|
11816
|
+
stopSampling(observation.sample);
|
|
11817
|
+
},
|
|
11818
|
+
index: null,
|
|
11819
|
+
exposed: null,
|
|
11820
|
+
events: 0,
|
|
11821
|
+
measuring: false,
|
|
11822
|
+
again: false,
|
|
11823
|
+
measured: false,
|
|
11824
|
+
scrollListeners: /* @__PURE__ */ new Map(),
|
|
11825
|
+
sample: () => this.#sample(target, observation)
|
|
11826
|
+
};
|
|
11827
|
+
this.#observed.set(target, observation);
|
|
11828
|
+
if (target.layoutRect) queueMicrotask(layout);
|
|
11829
|
+
}
|
|
11830
|
+
unobserve(target) {
|
|
11831
|
+
const observation = this.#observed.get(target);
|
|
11832
|
+
if (!observation) return;
|
|
11833
|
+
observation.stop();
|
|
11834
|
+
this.#observed.delete(target);
|
|
11835
|
+
this.#records = this.#records.filter((entry) => entry.target !== target);
|
|
11836
|
+
}
|
|
11837
|
+
disconnect() {
|
|
11838
|
+
for (const observation of this.#observed.values()) observation.stop();
|
|
11839
|
+
this.#observed.clear();
|
|
11840
|
+
this.#records = [];
|
|
11841
|
+
}
|
|
11842
|
+
takeRecords() {
|
|
11843
|
+
return this.#records.splice(0);
|
|
11844
|
+
}
|
|
11845
|
+
#exposure(target, observation, exposed) {
|
|
11846
|
+
observation.exposed = exposed;
|
|
11847
|
+
if (this.#measures) observation.sample();
|
|
11848
|
+
else this.#report(target, observation, exposed);
|
|
11849
|
+
}
|
|
11850
|
+
async #report(target, observation, exposed) {
|
|
11851
|
+
const event = exposed === null ? 0 : ++observation.events;
|
|
11852
|
+
const geometry = await measureGeometry(target, null);
|
|
11853
|
+
if (this.#observed.get(target) !== observation) return;
|
|
11854
|
+
if (observation.events !== event) return;
|
|
11855
|
+
const entry = exposureEntryFor(target, geometry, exposed);
|
|
11856
|
+
const index = entry.isIntersecting ? 1 : 0;
|
|
11857
|
+
if (index === observation.index) return;
|
|
11858
|
+
observation.index = index;
|
|
11859
|
+
this.#queue(entry);
|
|
11860
|
+
}
|
|
11861
|
+
#sample(target, observation) {
|
|
11862
|
+
if (this.#observed.get(target) !== observation) return;
|
|
11863
|
+
if (observation.measuring) {
|
|
11864
|
+
observation.again = true;
|
|
11865
|
+
return;
|
|
11866
|
+
}
|
|
11867
|
+
observation.measuring = true;
|
|
11868
|
+
measureGeometry(target, this.#root).then((geometry) => {
|
|
11869
|
+
observation.measuring = false;
|
|
11870
|
+
if (this.#observed.get(target) !== observation) return;
|
|
11871
|
+
this.#listenForScrolls(observation, geometry.scrolledBy);
|
|
11872
|
+
if (geometry.box) observation.measured = true;
|
|
11873
|
+
const { entry, index } = measuredEntryFor(target, geometry, this.#margin, this.thresholds, observation.measured ? null : observation.exposed);
|
|
11874
|
+
if (index !== observation.index) {
|
|
11875
|
+
observation.index = index;
|
|
11876
|
+
this.#queue(entry);
|
|
11877
|
+
}
|
|
11878
|
+
if (observation.again) {
|
|
11879
|
+
observation.again = false;
|
|
11880
|
+
observation.sample();
|
|
11881
|
+
}
|
|
11882
|
+
});
|
|
11883
|
+
}
|
|
11884
|
+
#listenForScrolls(observation, scrolledBy) {
|
|
11885
|
+
const current = new Set(scrolledBy);
|
|
11886
|
+
for (const [scroller, stopScroll] of observation.scrollListeners) {
|
|
11887
|
+
if (current.has(scroller)) continue;
|
|
11888
|
+
stopScroll();
|
|
11889
|
+
observation.scrollListeners.delete(scroller);
|
|
11890
|
+
}
|
|
11891
|
+
for (const scroller of scrolledBy) {
|
|
11892
|
+
if (observation.scrollListeners.has(scroller)) continue;
|
|
11893
|
+
const event = SCROLL_EVENTS.get(scroller.tagName);
|
|
11894
|
+
observation.scrollListeners.set(scroller, scroller.addEventListener(event, () => {
|
|
11895
|
+
sampleWhileScrolling(observation.sample);
|
|
11896
|
+
}));
|
|
11897
|
+
}
|
|
11898
|
+
}
|
|
11899
|
+
#queue(entry) {
|
|
11900
|
+
this.#records.push(entry);
|
|
11901
|
+
this.#deliverSoon();
|
|
11902
|
+
}
|
|
11903
|
+
#deliverSoon() {
|
|
11904
|
+
if (this.#delivering) return;
|
|
11905
|
+
this.#delivering = true;
|
|
11906
|
+
queueMicrotask(() => {
|
|
11907
|
+
this.#delivering = false;
|
|
11908
|
+
const records = this.takeRecords();
|
|
11909
|
+
if (records.length) this.#callback.call(this, records, this);
|
|
11910
|
+
});
|
|
11911
|
+
}
|
|
11912
|
+
};
|
|
11913
|
+
const wrapIntersectionObserver = (NativeIntersectionObserver) => {
|
|
11914
|
+
const toNode = (value) => isLynxElement(value) ? value.element : value;
|
|
11915
|
+
return class LynxWebIntersectionObserver {
|
|
11916
|
+
static forLynxElements = true;
|
|
11917
|
+
root;
|
|
11918
|
+
#observer;
|
|
11919
|
+
#targets = /* @__PURE__ */ new Map();
|
|
11920
|
+
constructor(callback, options) {
|
|
11921
|
+
this.root = options?.root ?? null;
|
|
11922
|
+
this.#observer = new NativeIntersectionObserver((entries) => callback(entries.map((entry) => this.#entry(entry)), this), options && {
|
|
11923
|
+
...options,
|
|
11924
|
+
root: toNode(options.root)
|
|
11925
|
+
});
|
|
11926
|
+
}
|
|
11927
|
+
get rootMargin() {
|
|
11928
|
+
return this.#observer.rootMargin;
|
|
11929
|
+
}
|
|
11930
|
+
get thresholds() {
|
|
11931
|
+
return this.#observer.thresholds;
|
|
11932
|
+
}
|
|
11933
|
+
observe(target) {
|
|
11934
|
+
const node = toNode(target);
|
|
11935
|
+
if (node !== target) this.#targets.set(node, target);
|
|
11936
|
+
this.#observer.observe(node);
|
|
11937
|
+
}
|
|
11938
|
+
unobserve(target) {
|
|
11939
|
+
const node = toNode(target);
|
|
11940
|
+
this.#targets.delete(node);
|
|
11941
|
+
this.#observer.unobserve(node);
|
|
11942
|
+
}
|
|
11943
|
+
disconnect() {
|
|
11944
|
+
this.#targets.clear();
|
|
11945
|
+
this.#observer.disconnect();
|
|
11946
|
+
}
|
|
11947
|
+
takeRecords() {
|
|
11948
|
+
return this.#observer.takeRecords().map((entry) => this.#entry(entry));
|
|
11949
|
+
}
|
|
11950
|
+
#entry(entry) {
|
|
11951
|
+
const target = this.#targets.get(entry.target);
|
|
11952
|
+
if (!target) return entry;
|
|
11953
|
+
return {
|
|
11954
|
+
target,
|
|
11955
|
+
time: entry.time,
|
|
11956
|
+
rootBounds: entry.rootBounds,
|
|
11957
|
+
boundingClientRect: entry.boundingClientRect,
|
|
11958
|
+
intersectionRect: entry.intersectionRect,
|
|
11959
|
+
intersectionRatio: entry.intersectionRatio,
|
|
11960
|
+
isIntersecting: entry.isIntersecting
|
|
11961
|
+
};
|
|
11962
|
+
}
|
|
11963
|
+
};
|
|
11964
|
+
};
|
|
11965
|
+
const installIntersectionObserver = (target) => {
|
|
11966
|
+
const native = target["IntersectionObserver"];
|
|
11967
|
+
if (typeof native === "undefined") target["IntersectionObserver"] = LynxIntersectionObserver;
|
|
11968
|
+
else if (!native.forLynxElements) target["IntersectionObserver"] = wrapIntersectionObserver(native);
|
|
11969
|
+
};
|
|
10821
11970
|
const readBundledAsset = (url) => {
|
|
10822
11971
|
const lynxGlobal = globalThis.lynx;
|
|
10823
11972
|
if (typeof lynxGlobal?.module !== "function") return null;
|
|
@@ -11055,8 +12204,19 @@ const parseUrl$1 = (input) => {
|
|
|
11055
12204
|
try {
|
|
11056
12205
|
return new URL(input).href;
|
|
11057
12206
|
} catch {
|
|
11058
|
-
throw new TypeError(`Failed to parse URL from ${input}. Lynx has no page URL to resolve a relative URL against, so
|
|
12207
|
+
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.`);
|
|
12208
|
+
}
|
|
12209
|
+
};
|
|
12210
|
+
const isRelative = (url) => !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url);
|
|
12211
|
+
const PLACEHOLDER_BASE = "http://placeholder.invalid/";
|
|
12212
|
+
const parseRequestUrl = (input) => {
|
|
12213
|
+
if (!isRelative(input)) return parseUrl$1(input);
|
|
12214
|
+
try {
|
|
12215
|
+
new URL(input, PLACEHOLDER_BASE);
|
|
12216
|
+
} catch {
|
|
12217
|
+
throw new TypeError(`Failed to parse URL from ${input}.`);
|
|
11059
12218
|
}
|
|
12219
|
+
return input;
|
|
11060
12220
|
};
|
|
11061
12221
|
const DEFAULT_OPTIONS = {
|
|
11062
12222
|
cache: "default",
|
|
@@ -11096,7 +12256,7 @@ var LynxRequest = class LynxRequest extends LynxBody {
|
|
|
11096
12256
|
};
|
|
11097
12257
|
if (source !== null && (upper === "GET" || upper === "HEAD")) throw new TypeError("Failed to construct 'Request': Request with GET/HEAD method cannot have body.");
|
|
11098
12258
|
super(source);
|
|
11099
|
-
this.url = base ? base.url :
|
|
12259
|
+
this.url = base ? base.url : parseRequestUrl(String(input));
|
|
11100
12260
|
this.method = normalizedMethod;
|
|
11101
12261
|
this.headers = new LynxHeaders(init.headers ?? base?.headers);
|
|
11102
12262
|
if (type !== null && !this.headers.has("content-type")) this.headers.set("content-type", type);
|
|
@@ -11215,21 +12375,18 @@ var LynxResponse = class LynxResponse extends LynxBody {
|
|
|
11215
12375
|
}
|
|
11216
12376
|
};
|
|
11217
12377
|
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;
|
|
12378
|
+
const bundledResponse = (request) => {
|
|
12379
|
+
const bytes = request.method === "GET" ? readBundledAsset(request.url) : null;
|
|
12380
|
+
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
12381
|
return new LynxResponse(new ExtractedBody(bytes), {
|
|
11225
12382
|
status: 200,
|
|
11226
12383
|
statusText: "OK",
|
|
11227
12384
|
headers: {
|
|
11228
|
-
"content-type": typeOfAsset(
|
|
12385
|
+
"content-type": typeOfAsset(request.url),
|
|
11229
12386
|
"content-length": String(bytes.byteLength)
|
|
11230
12387
|
}
|
|
11231
12388
|
}, {
|
|
11232
|
-
url:
|
|
12389
|
+
url: request.url,
|
|
11233
12390
|
redirected: false,
|
|
11234
12391
|
type: "basic"
|
|
11235
12392
|
});
|
|
@@ -11267,18 +12424,13 @@ const localResponse = (url) => {
|
|
|
11267
12424
|
return null;
|
|
11268
12425
|
};
|
|
11269
12426
|
const relayFetch = (input, init) => new Promise((resolve, reject) => {
|
|
11270
|
-
const bundled = bundledResponse(input, init);
|
|
11271
|
-
if (bundled) {
|
|
11272
|
-
resolve(bundled);
|
|
11273
|
-
return;
|
|
11274
|
-
}
|
|
11275
12427
|
const request = new LynxRequest(input, init);
|
|
11276
12428
|
const { signal } = request;
|
|
11277
12429
|
if (signal.aborted) {
|
|
11278
12430
|
reject(signal.reason);
|
|
11279
12431
|
return;
|
|
11280
12432
|
}
|
|
11281
|
-
const local = localResponse(request.url);
|
|
12433
|
+
const local = isRelative(request.url) ? bundledResponse(request) : localResponse(request.url);
|
|
11282
12434
|
if (local) {
|
|
11283
12435
|
if (local instanceof LynxResponse) resolve(local);
|
|
11284
12436
|
else reject(local);
|
|
@@ -12327,18 +13479,24 @@ if (typeof Node === "undefined") try {
|
|
|
12327
13479
|
});
|
|
12328
13480
|
globalThis.Node = LynxNode;
|
|
12329
13481
|
} catch {}
|
|
12330
|
-
if (
|
|
13482
|
+
if (isMainThread()) installGlobalDocument(globalThis, globalEvents());
|
|
13483
|
+
else if (typeof document === "undefined") globalThis.document = {
|
|
12331
13484
|
defaultView: globalThis,
|
|
12332
13485
|
querySelector: () => null
|
|
12333
13486
|
};
|
|
12334
13487
|
try {
|
|
12335
13488
|
if (typeof window === "undefined") globalThis.window = globalThis;
|
|
12336
|
-
} catch {
|
|
13489
|
+
} catch {
|
|
13490
|
+
if (__WEB__) window = globalThis;
|
|
13491
|
+
}
|
|
12337
13492
|
try {
|
|
12338
13493
|
if (typeof navigator === "undefined") globalThis.navigator = { userAgent: "" };
|
|
12339
13494
|
} catch {}
|
|
12340
|
-
if (
|
|
12341
|
-
|
|
13495
|
+
if (isMainThread()) installGlobalWindow(globalThis, globalEvents());
|
|
13496
|
+
else {
|
|
13497
|
+
if (typeof globalThis.addEventListener !== "function") globalThis.addEventListener = () => {};
|
|
13498
|
+
if (typeof globalThis.removeEventListener !== "function") globalThis.removeEventListener = () => {};
|
|
13499
|
+
}
|
|
12342
13500
|
if (typeof globalThis.setTimeout !== "function" && typeof lynx !== "undefined") {
|
|
12343
13501
|
const _lynx = lynx;
|
|
12344
13502
|
globalThis.setTimeout = _lynx.setTimeout;
|
|
@@ -12355,7 +13513,10 @@ if (typeof globalThis.requestIdleCallback !== "function" || typeof globalThis.ca
|
|
|
12355
13513
|
}), 0);
|
|
12356
13514
|
globalThis.cancelIdleCallback = (id) => clearTimeout(id);
|
|
12357
13515
|
}
|
|
12358
|
-
if (isMainThread())
|
|
13516
|
+
if (isMainThread()) {
|
|
13517
|
+
installCanvasGlobals(globalThis);
|
|
13518
|
+
installIntersectionObserver(globalThis);
|
|
13519
|
+
}
|
|
12359
13520
|
var Opcode;
|
|
12360
13521
|
(function(Opcode) {
|
|
12361
13522
|
Opcode[Opcode["Begin"] = 0] = "Begin";
|