@lingxia/html 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/global.d.ts +2 -0
- package/dist/global.es2020.js +555 -56
- package/dist/global.es5.js +630 -64
- package/dist/global.js +5 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/page.d.ts +19 -0
- package/dist/page.js +20 -0
- package/package.json +4 -4
package/dist/global.es5.js
CHANGED
|
@@ -9,9 +9,55 @@ var __assign = (this && this.__assign) || function () {
|
|
|
9
9
|
};
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
23
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
49
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
50
|
+
if (ar || !(i in from)) {
|
|
51
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
52
|
+
ar[i] = from[i];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
56
|
+
};
|
|
12
57
|
var LingXiaPage = (function (exports) {
|
|
58
|
+
var _a;
|
|
13
59
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
14
|
-
//#region dist/
|
|
60
|
+
//#region ../lingxia-page-runtime/dist/shared/runtime.js
|
|
15
61
|
var snapshot = {};
|
|
16
62
|
var stateInfo = {
|
|
17
63
|
rev: -1,
|
|
@@ -19,7 +65,16 @@ var LingXiaPage = (function (exports) {
|
|
|
19
65
|
};
|
|
20
66
|
var subscribed = false;
|
|
21
67
|
var subscribeRetryTimer = null;
|
|
68
|
+
var snapshotRetryTimer = null;
|
|
69
|
+
var snapshotRetries = 0;
|
|
70
|
+
/**
|
|
71
|
+
* The host pushes a page's first state at bridge-ready, so the request is only
|
|
72
|
+
* a fallback: a few tries, backing off, then stop. A page with no Logic never
|
|
73
|
+
* answers, and must not be asked for the life of the page.
|
|
74
|
+
*/
|
|
75
|
+
var MAX_SNAPSHOT_RETRIES = 3;
|
|
22
76
|
var initialSnapshotResolved = false;
|
|
77
|
+
var actions = null;
|
|
23
78
|
var snapshotRequestInFlight = false;
|
|
24
79
|
var listeners = /* @__PURE__ */ new Set();
|
|
25
80
|
function notifyListeners() {
|
|
@@ -30,8 +85,28 @@ var LingXiaPage = (function (exports) {
|
|
|
30
85
|
catch (_a) { }
|
|
31
86
|
});
|
|
32
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* In a dev session the page data is frozen, so a View that writes to it fails
|
|
90
|
+
* at the write instead of drifting from Logic until the next update. Each
|
|
91
|
+
* push is a fresh copy, so nothing else holds these objects.
|
|
92
|
+
*/
|
|
93
|
+
function isDevSession() {
|
|
94
|
+
var _a;
|
|
95
|
+
return typeof window !== "undefined" && ((_a = window.__LX_BRIDGE_CFG) === null || _a === void 0 ? void 0 : _a.dev) === true;
|
|
96
|
+
}
|
|
97
|
+
function deepFreeze(value) {
|
|
98
|
+
if (!value || typeof value !== "object" || Object.isFrozen(value))
|
|
99
|
+
return;
|
|
100
|
+
Object.freeze(value);
|
|
101
|
+
for (var _i = 0, _a = Object.keys(value); _i < _a.length; _i++) {
|
|
102
|
+
var key = _a[_i];
|
|
103
|
+
deepFreeze(value[key]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
33
106
|
function updateSnapshot(next, info) {
|
|
34
107
|
snapshot = next && typeof next === "object" ? next : {};
|
|
108
|
+
if (isDevSession())
|
|
109
|
+
deepFreeze(snapshot);
|
|
35
110
|
stateInfo = info;
|
|
36
111
|
notifyListeners();
|
|
37
112
|
}
|
|
@@ -43,17 +118,35 @@ var LingXiaPage = (function (exports) {
|
|
|
43
118
|
ensurePageBridgeSubscription();
|
|
44
119
|
}, 10);
|
|
45
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Retry the snapshot request itself. The subscription is already in place, so
|
|
123
|
+
* retrying it (as this used to) returned at once and never asked again; the
|
|
124
|
+
* page then relied on the host's own push at bridge-ready.
|
|
125
|
+
*/
|
|
126
|
+
function scheduleSnapshotRetry() {
|
|
127
|
+
if (snapshotRetryTimer !== null || snapshotRetries >= MAX_SNAPSHOT_RETRIES)
|
|
128
|
+
return;
|
|
129
|
+
snapshotRetries += 1;
|
|
130
|
+
snapshotRetryTimer = setTimeout(function () {
|
|
131
|
+
snapshotRetryTimer = null;
|
|
132
|
+
requestInitialSnapshot(window.LingXiaBridge);
|
|
133
|
+
}, 250 * Math.pow(2, (snapshotRetries - 1)));
|
|
134
|
+
}
|
|
46
135
|
function requestInitialSnapshot(bridge) {
|
|
47
136
|
var _a;
|
|
137
|
+
if (stateInfo.rev >= 0)
|
|
138
|
+
initialSnapshotResolved = true;
|
|
48
139
|
if (initialSnapshotResolved || snapshotRequestInFlight)
|
|
49
140
|
return;
|
|
50
|
-
if (!((_a = bridge === null || bridge === void 0 ? void 0 : bridge.raw) === null || _a === void 0 ? void 0 : _a.call))
|
|
141
|
+
if (!((_a = bridge === null || bridge === void 0 ? void 0 : bridge.raw) === null || _a === void 0 ? void 0 : _a.call)) {
|
|
142
|
+
scheduleSnapshotRetry();
|
|
51
143
|
return;
|
|
144
|
+
}
|
|
52
145
|
snapshotRequestInFlight = true;
|
|
53
146
|
bridge.raw.call("state.getSnapshot", { scope: "page" }).then(function () {
|
|
54
147
|
initialSnapshotResolved = true;
|
|
55
148
|
}).catch(function () {
|
|
56
|
-
|
|
149
|
+
scheduleSnapshotRetry();
|
|
57
150
|
}).finally(function () {
|
|
58
151
|
snapshotRequestInFlight = false;
|
|
59
152
|
});
|
|
@@ -81,41 +174,68 @@ var LingXiaPage = (function (exports) {
|
|
|
81
174
|
listeners.delete(listener);
|
|
82
175
|
};
|
|
83
176
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return function () { };
|
|
177
|
+
/** Whether the page's first state has arrived. Flips once per document. */
|
|
178
|
+
function isPageReady() {
|
|
87
179
|
ensurePageBridgeSubscription();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
180
|
+
return stateInfo.rev >= 0;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Resolves once the page's first state has arrived — the host pushes it at
|
|
184
|
+
* bridge-ready, before `onLoad`, carrying `Page({ data })`'s defaults — so a
|
|
185
|
+
* page can mount with its data whole. With `timeoutMs`, rejects if Logic has
|
|
186
|
+
* not delivered it by then (it failed to load, or threw first); `null` waits
|
|
187
|
+
* without limit.
|
|
188
|
+
*/
|
|
189
|
+
function whenPageReady(options) {
|
|
190
|
+
if (options === void 0) { options = {}; }
|
|
191
|
+
if (isPageReady())
|
|
192
|
+
return Promise.resolve();
|
|
193
|
+
var timeoutMs = options.timeoutMs === void 0 ? 1e4 : options.timeoutMs;
|
|
194
|
+
return new Promise(function (resolve, reject) {
|
|
195
|
+
var timer = null;
|
|
196
|
+
var check = function () {
|
|
197
|
+
if (stateInfo.rev < 0)
|
|
198
|
+
return;
|
|
199
|
+
if (timer !== null)
|
|
200
|
+
clearTimeout(timer);
|
|
201
|
+
listeners.delete(check);
|
|
202
|
+
resolve();
|
|
203
|
+
};
|
|
204
|
+
if (timeoutMs !== null)
|
|
205
|
+
timer = setTimeout(function () {
|
|
206
|
+
listeners.delete(check);
|
|
207
|
+
reject(/* @__PURE__ */ new Error("Page Logic did not deliver the page state within ".concat(timeoutMs, " ms")));
|
|
208
|
+
}, timeoutMs);
|
|
209
|
+
listeners.add(check);
|
|
95
210
|
});
|
|
96
211
|
}
|
|
97
212
|
function getPageSnapshot() {
|
|
98
213
|
ensurePageBridgeSubscription();
|
|
99
214
|
return snapshot;
|
|
100
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* The page's actions: one object for the whole page, so it is a stable
|
|
218
|
+
* dependency. Built on first use — the page's action names arrive with its
|
|
219
|
+
* bridge metadata, after the page module has evaluated.
|
|
220
|
+
*/
|
|
101
221
|
function getPageActions() {
|
|
102
|
-
|
|
222
|
+
if (actions)
|
|
223
|
+
return actions;
|
|
103
224
|
var bridge = window.__pageBridge;
|
|
104
225
|
if (!(bridge === null || bridge === void 0 ? void 0 : bridge.__names))
|
|
105
|
-
|
|
226
|
+
throw new Error("Page actions are not ready. Read useLxPage() during component setup/render, or getPage() after pageReady(); pass actions into shared helpers.");
|
|
227
|
+
var built = {};
|
|
106
228
|
for (var _i = 0, _a = bridge.__names; _i < _a.length; _i++) {
|
|
107
229
|
var name = _a[_i];
|
|
108
230
|
if (typeof name !== "string")
|
|
109
231
|
continue;
|
|
110
232
|
var fn = getOrCreatePageAction(bridge, name);
|
|
111
233
|
if (typeof fn === "function")
|
|
112
|
-
|
|
234
|
+
built[name] = fn;
|
|
113
235
|
}
|
|
236
|
+
actions = built;
|
|
114
237
|
return actions;
|
|
115
238
|
}
|
|
116
|
-
function getPageStateInfo() {
|
|
117
|
-
return stateInfo;
|
|
118
|
-
}
|
|
119
239
|
function getOrCreatePageAction(bridge, name) {
|
|
120
240
|
var existing = bridge[name];
|
|
121
241
|
if (typeof existing === "function")
|
|
@@ -127,7 +247,9 @@ var LingXiaPage = (function (exports) {
|
|
|
127
247
|
function resolvePageActionMode(bridge, name) {
|
|
128
248
|
var _a;
|
|
129
249
|
var mode = (_a = bridge.__modes) === null || _a === void 0 ? void 0 : _a[name];
|
|
130
|
-
|
|
250
|
+
if (mode === "call" || mode === "stream")
|
|
251
|
+
return mode;
|
|
252
|
+
throw new Error("Invalid bridge mode for page action '".concat(name, "'; regenerate the page with the current CLI"));
|
|
131
253
|
}
|
|
132
254
|
function definePageBridgeAction(name, mode) {
|
|
133
255
|
function action() {
|
|
@@ -148,14 +270,14 @@ var LingXiaPage = (function (exports) {
|
|
|
148
270
|
return handle;
|
|
149
271
|
}
|
|
150
272
|
if (mode === "call") {
|
|
151
|
-
var promise = bridge
|
|
273
|
+
var promise = callUnaryPageAction(bridge, name, payload);
|
|
152
274
|
if (promise && typeof promise.catch === "function")
|
|
153
275
|
promise.catch(function (err) {
|
|
154
276
|
console.warn("[PageFunc] ".concat(name, " failed:"), err instanceof Error ? err.message : err);
|
|
155
277
|
});
|
|
156
278
|
return promise;
|
|
157
279
|
}
|
|
158
|
-
bridge.
|
|
280
|
+
throw new Error("Invalid bridge mode for page action '".concat(name, "'"));
|
|
159
281
|
}
|
|
160
282
|
Object.assign(action, {
|
|
161
283
|
__logicFunc: true,
|
|
@@ -164,35 +286,463 @@ var LingXiaPage = (function (exports) {
|
|
|
164
286
|
});
|
|
165
287
|
return action;
|
|
166
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* The one wire path of a unary action. It has no bridge deadline: an action
|
|
291
|
+
* may wait for a person or poll for minutes, and settles when Logic settles
|
|
292
|
+
* or the document goes away.
|
|
293
|
+
*/
|
|
294
|
+
function callUnaryPageAction(bridge_1, name_1, payload_1) {
|
|
295
|
+
return __awaiter(this, arguments, void 0, function (bridge, name, payload, dropWhenGone) {
|
|
296
|
+
var error_1;
|
|
297
|
+
if (dropWhenGone === void 0) { dropWhenGone = true; }
|
|
298
|
+
return __generator(this, function (_a) {
|
|
299
|
+
switch (_a.label) {
|
|
300
|
+
case 0:
|
|
301
|
+
if (!!isPageReady()) return [3 /*break*/, 2];
|
|
302
|
+
return [4 /*yield*/, whenPageReady({ timeoutMs: null })];
|
|
303
|
+
case 1:
|
|
304
|
+
_a.sent();
|
|
305
|
+
_a.label = 2;
|
|
306
|
+
case 2:
|
|
307
|
+
_a.trys.push([2, 4, , 5]);
|
|
308
|
+
return [4 /*yield*/, bridge.raw.call(name, payload, { timeoutMs: 0 })];
|
|
309
|
+
case 3: return [2 /*return*/, _a.sent()];
|
|
310
|
+
case 4:
|
|
311
|
+
error_1 = _a.sent();
|
|
312
|
+
if (dropWhenGone && (error_1 === null || error_1 === void 0 ? void 0 : error_1.code) === "BRIDGE_NOT_READY")
|
|
313
|
+
return [2 /*return*/, new Promise(function () { })];
|
|
314
|
+
throw error_1;
|
|
315
|
+
case 5: return [2 /*return*/];
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* A DOM or framework event, in this realm or another. A JSON payload never
|
|
322
|
+
* carries methods, so event methods tell the two apart.
|
|
323
|
+
*/
|
|
324
|
+
function isEventLike(value) {
|
|
325
|
+
if (typeof Event !== "undefined" && value instanceof Event)
|
|
326
|
+
return true;
|
|
327
|
+
if (!value || typeof value !== "object")
|
|
328
|
+
return false;
|
|
329
|
+
var event = value;
|
|
330
|
+
return typeof event.preventDefault === "function" && typeof event.stopPropagation === "function";
|
|
331
|
+
}
|
|
332
|
+
var PAGE_ACTIONS_NOT_READY = "PAGE_ACTIONS_NOT_READY";
|
|
333
|
+
function pageActionError(code, message) {
|
|
334
|
+
return Object.assign(new Error(message), { code: code });
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Automation entry (`PageDriver.action`): invoke one unary action of this
|
|
338
|
+
* page with a JSON payload, as the View would. The payload is passed as is —
|
|
339
|
+
* no DOM-event repackaging.
|
|
340
|
+
*/
|
|
341
|
+
function invokePageActionForAutomation(name, payload) {
|
|
342
|
+
var _a;
|
|
343
|
+
if (typeof name !== "string" || name === "")
|
|
344
|
+
return Promise.reject(pageActionError("BRIDGE_MALFORMED_MESSAGE", "Page action name must be a non-empty string"));
|
|
345
|
+
var metadata = window.__pageBridge;
|
|
346
|
+
var bridge = window.LingXiaBridge;
|
|
347
|
+
if (!Array.isArray(metadata === null || metadata === void 0 ? void 0 : metadata.__names) || !(bridge === null || bridge === void 0 ? void 0 : bridge.raw))
|
|
348
|
+
return Promise.reject(pageActionError(PAGE_ACTIONS_NOT_READY, "Page actions are not ready yet"));
|
|
349
|
+
if (!metadata.__names.includes(name)) {
|
|
350
|
+
var known = metadata.__names.length ? metadata.__names.join(", ") : "none";
|
|
351
|
+
return Promise.reject(pageActionError("BRIDGE_METHOD_NOT_FOUND", "'".concat(name, "' is not an action of this page (actions: ").concat(known, ")")));
|
|
352
|
+
}
|
|
353
|
+
if (((_a = metadata.__modes) === null || _a === void 0 ? void 0 : _a[name]) !== "call")
|
|
354
|
+
return Promise.reject(pageActionError("PAGE_ACTION_NOT_UNARY", "Page action '".concat(name, "' is a stream action; only unary actions can be invoked")));
|
|
355
|
+
return callUnaryPageAction(bridge, name, payload, false);
|
|
356
|
+
}
|
|
357
|
+
if (typeof window !== "undefined")
|
|
358
|
+
Object.defineProperty(window, "__lxInvokePageAction", {
|
|
359
|
+
value: invokePageActionForAutomation,
|
|
360
|
+
configurable: true
|
|
361
|
+
});
|
|
167
362
|
function filterPayload(name, args) {
|
|
168
363
|
var clean = [];
|
|
169
364
|
for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
|
|
170
365
|
var value = args_1[_i];
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
var maybeEvent = value;
|
|
179
|
-
if (maybeEvent && typeof maybeEvent === "object" && typeof maybeEvent.type === "string" && "detail" in maybeEvent) {
|
|
180
|
-
clean.push({
|
|
181
|
-
type: maybeEvent.type,
|
|
182
|
-
detail: maybeEvent.detail
|
|
183
|
-
});
|
|
366
|
+
if (isEventLike(value)) {
|
|
367
|
+
var event = value;
|
|
368
|
+
if (typeof event.type === "string" && "detail" in event)
|
|
369
|
+
clean.push({
|
|
370
|
+
type: event.type,
|
|
371
|
+
detail: event.detail
|
|
372
|
+
});
|
|
184
373
|
continue;
|
|
185
374
|
}
|
|
186
|
-
if (value instanceof Event)
|
|
187
|
-
continue;
|
|
188
|
-
if (value && typeof value === "object" && "stopPropagation" in value && typeof value.stopPropagation === "function")
|
|
189
|
-
continue;
|
|
190
375
|
clean.push(value);
|
|
191
376
|
}
|
|
192
377
|
if (clean.length > 1)
|
|
193
378
|
throw new Error("Page action '".concat(name, "' accepts at most one payload argument"));
|
|
194
379
|
return clean[0];
|
|
195
380
|
}
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region ../lingxia-bridge/dist/es2020/error.js
|
|
383
|
+
var ERROR_STYLES = "\n* { margin: 0; padding: 0; box-sizing: border-box; }\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #f5f5f7;\n color: #1d1d1f;\n padding: 20px;\n -webkit-font-smoothing: antialiased;\n}\n.lx-error {\n text-align: center;\n max-width: 400px;\n}\n.lx-error-code {\n font-size: 120px;\n font-weight: 700;\n color: #d1d1d6;\n line-height: 1;\n letter-spacing: -4px;\n}\n.lx-error-title {\n font-size: 21px;\n font-weight: 600;\n margin: 16px 0 8px;\n color: #1d1d1f;\n}\n.lx-error-desc {\n font-size: 15px;\n color: #86868b;\n line-height: 1.5;\n}\n.lx-error-path {\n display: inline-block;\n margin-top: 20px;\n padding: 10px 16px;\n background: rgba(0,0,0,0.04);\n border-radius: 8px;\n font-family: 'SF Mono', ui-monospace, Menlo, Monaco, monospace;\n font-size: 13px;\n color: #1d1d1f;\n word-break: break-all;\n max-width: 100%;\n}\n@media (prefers-color-scheme: dark) {\n body { background: #000; color: #f5f5f7; }\n .lx-error-code { color: #3a3a3c; }\n .lx-error-title { color: #f5f5f7; }\n .lx-error-desc { color: #86868b; }\n .lx-error-path { background: rgba(255,255,255,0.08); color: #f5f5f7; }\n}\n";
|
|
384
|
+
function escapeHtml(str) {
|
|
385
|
+
var div = document.createElement("div");
|
|
386
|
+
div.textContent = str;
|
|
387
|
+
return div.innerHTML;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* A page whose Logic has not delivered its first state in time — it failed to
|
|
391
|
+
* load, threw before the page could start, or is very slow. Shown over the page
|
|
392
|
+
* instead of a blank screen, naming the page; returns a function that removes
|
|
393
|
+
* it, for when the state does arrive after all.
|
|
394
|
+
*/
|
|
395
|
+
function renderPageFault(pagePath, reason) {
|
|
396
|
+
var styleEl = document.createElement("style");
|
|
397
|
+
styleEl.textContent = "\n.lx-page-fault { position: fixed; inset: 0; z-index: 2147483647; overflow: auto;\n background: #fff; color: #1d1d1f; }\n@media (prefers-color-scheme: dark) { .lx-page-fault { background: #000; color: #f5f5f7; } }\n".concat(ERROR_STYLES.replace(/\bbody\b/g, ".lx-page-fault"));
|
|
398
|
+
document.head.appendChild(styleEl);
|
|
399
|
+
var overlay = document.createElement("div");
|
|
400
|
+
overlay.className = "lx-page-fault";
|
|
401
|
+
overlay.setAttribute("role", "alert");
|
|
402
|
+
var container = document.createElement("div");
|
|
403
|
+
container.className = "lx-error";
|
|
404
|
+
var html = "<div class=\"lx-error-code\">Page</div>";
|
|
405
|
+
html += "<h1 class=\"lx-error-title\">".concat(escapeHtml("This page couldn't start"), "</h1>");
|
|
406
|
+
html += "<p class=\"lx-error-desc\">".concat(escapeHtml("Its Logic has not delivered the page state. Check the Logic log for an error."), "</p>");
|
|
407
|
+
if (pagePath)
|
|
408
|
+
html += "<div class=\"lx-error-path\">".concat(escapeHtml(pagePath), "</div>");
|
|
409
|
+
html += "<p class=\"lx-error-desc\" style=\"margin-top:12px\">".concat(escapeHtml(reason), "</p>");
|
|
410
|
+
container.innerHTML = html;
|
|
411
|
+
overlay.appendChild(container);
|
|
412
|
+
document.body.appendChild(overlay);
|
|
413
|
+
return function () {
|
|
414
|
+
overlay.remove();
|
|
415
|
+
styleEl.remove();
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
//#endregion
|
|
419
|
+
//#region ../lingxia-bridge/dist/es2020/runtime-env.js
|
|
420
|
+
var BRIDGE_CONFIG = typeof window !== "undefined" && window.__LX_BRIDGE_CFG || {};
|
|
421
|
+
/**
|
|
422
|
+
* One store per document, deliberately on `window`.
|
|
423
|
+
*
|
|
424
|
+
* This module is present twice in a page: once as the global bridge runtime
|
|
425
|
+
* the host injects, once bundled into the page's own JS. Module-local state
|
|
426
|
+
* would give each copy its own value — the host would push the change into
|
|
427
|
+
* whichever copy won the race to install the hook, and the other, which is the
|
|
428
|
+
* one the framework hooks read, would answer with the boot value forever.
|
|
429
|
+
*/
|
|
430
|
+
var fallbackStore$1 = {
|
|
431
|
+
value: ((_a = BRIDGE_CONFIG.displayLanguage) === null || _a === void 0 ? void 0 : _a.trim()) || "en-US",
|
|
432
|
+
listeners: /* @__PURE__ */ new Set()
|
|
433
|
+
};
|
|
434
|
+
function store$1() {
|
|
435
|
+
var _a;
|
|
436
|
+
if (typeof window === "undefined")
|
|
437
|
+
return fallbackStore$1;
|
|
438
|
+
if (!window.__lxDisplayLanguage)
|
|
439
|
+
window.__lxDisplayLanguage = {
|
|
440
|
+
value: ((_a = BRIDGE_CONFIG.displayLanguage) === null || _a === void 0 ? void 0 : _a.trim()) || "en-US",
|
|
441
|
+
listeners: /* @__PURE__ */ new Set()
|
|
442
|
+
};
|
|
443
|
+
return window.__lxDisplayLanguage;
|
|
444
|
+
}
|
|
445
|
+
/** Primary subtags of languages written right to left, for engines without `Intl.Locale#getTextInfo`. */
|
|
446
|
+
var RTL_LANGUAGES = /* @__PURE__ */ new Set([
|
|
447
|
+
"ar",
|
|
448
|
+
"ckb",
|
|
449
|
+
"dv",
|
|
450
|
+
"fa",
|
|
451
|
+
"he",
|
|
452
|
+
"ps",
|
|
453
|
+
"sd",
|
|
454
|
+
"ug",
|
|
455
|
+
"ur",
|
|
456
|
+
"yi"
|
|
457
|
+
]);
|
|
458
|
+
/** The writing direction of a BCP-47 tag. */
|
|
459
|
+
function textDirection(tag) {
|
|
460
|
+
try {
|
|
461
|
+
var locale = new Intl.Locale(tag);
|
|
462
|
+
var info = typeof locale.getTextInfo === "function" ? locale.getTextInfo() : locale.textInfo;
|
|
463
|
+
if ((info === null || info === void 0 ? void 0 : info.direction) === "rtl" || (info === null || info === void 0 ? void 0 : info.direction) === "ltr")
|
|
464
|
+
return info.direction;
|
|
465
|
+
}
|
|
466
|
+
catch (_a) { }
|
|
467
|
+
return RTL_LANGUAGES.has(tag.split(/[-_]/)[0].toLowerCase()) ? "rtl" : "ltr";
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* `lang` and `dir` on `<html>` follow the display language, so a page never
|
|
471
|
+
* sets either: CSS logical properties and `:dir()` just work.
|
|
472
|
+
*/
|
|
473
|
+
function stampDocumentLanguage() {
|
|
474
|
+
if (typeof document !== "undefined" && document.documentElement) {
|
|
475
|
+
var language = store$1().value;
|
|
476
|
+
document.documentElement.lang = language;
|
|
477
|
+
document.documentElement.dir = textDirection(language);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
stampDocumentLanguage();
|
|
481
|
+
/**
|
|
482
|
+
* Host entry point for a language the user changed while this document was
|
|
483
|
+
* open. Bootstrap alone would leave a live page in the language it started in,
|
|
484
|
+
* with the native chrome around it already switched.
|
|
485
|
+
*
|
|
486
|
+
* The host pushes each change once, and again — the current value — when a
|
|
487
|
+
* document's bridge reports ready, since a change made while it loaded found
|
|
488
|
+
* no hook to call. Those two can land in either order, so a push carries the
|
|
489
|
+
* host revision it took effect at and an older one never overwrites a newer
|
|
490
|
+
* one. A push without a revision applies as it always did.
|
|
491
|
+
*/
|
|
492
|
+
function applyDisplayLanguage(next, revision) {
|
|
493
|
+
var _a;
|
|
494
|
+
var normalized = typeof next === "string" ? next.trim() : "";
|
|
495
|
+
var current = store$1();
|
|
496
|
+
if (typeof revision === "number" && Number.isFinite(revision)) {
|
|
497
|
+
if (revision <= ((_a = current.revision) !== null && _a !== void 0 ? _a : 0))
|
|
498
|
+
return;
|
|
499
|
+
current.revision = revision;
|
|
500
|
+
}
|
|
501
|
+
if (!normalized || normalized === current.value)
|
|
502
|
+
return;
|
|
503
|
+
current.value = normalized;
|
|
504
|
+
stampDocumentLanguage();
|
|
505
|
+
for (var _i = 0, _b = __spreadArray([], current.listeners, true); _i < _b.length; _i++) {
|
|
506
|
+
var listener = _b[_i];
|
|
507
|
+
listener(normalized);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
if (typeof window !== "undefined" && !window.__lingxiaApplyDisplayLanguage)
|
|
511
|
+
Object.defineProperty(window, "__lingxiaApplyDisplayLanguage", {
|
|
512
|
+
configurable: false,
|
|
513
|
+
enumerable: false,
|
|
514
|
+
value: applyDisplayLanguage
|
|
515
|
+
});
|
|
516
|
+
function getDisplayLanguage() {
|
|
517
|
+
return store$1().value;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Subscribe to host display-language changes. Returns an unsubscribe.
|
|
521
|
+
*
|
|
522
|
+
* Change-only, so that this composes with `useSyncExternalStore`: the listener
|
|
523
|
+
* runs when the language changes, never on subscribe. Read the current value
|
|
524
|
+
* with `getDisplayLanguage()`. Logic's `lx.host.displayLanguage.watch` differs
|
|
525
|
+
* deliberately — it has no render loop to feed, so it delivers immediately.
|
|
526
|
+
*/
|
|
527
|
+
function subscribeDisplayLanguage(listener) {
|
|
528
|
+
var listeners = store$1().listeners;
|
|
529
|
+
listeners.add(listener);
|
|
530
|
+
return function () {
|
|
531
|
+
listeners.delete(listener);
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
function getPlatformOS() {
|
|
535
|
+
return BRIDGE_CONFIG.os || "unknown";
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Which kind of machine this is, mobile or desktop. Read through `isMobile()`
|
|
539
|
+
* and `isDesktop()`; the class itself is host vocabulary, not lxapp API.
|
|
540
|
+
*
|
|
541
|
+
* Fixed for the life of the document. A shipped host is one machine; the
|
|
542
|
+
* Runner re-serves the page when its simulated device changes class, so this
|
|
543
|
+
* never has to change under a page that is already rendering.
|
|
544
|
+
*
|
|
545
|
+
* Hosts from before this config key shipped send nothing, so fall back to the
|
|
546
|
+
* OS: every one of them is the machine it names.
|
|
547
|
+
*/
|
|
548
|
+
function hostClass() {
|
|
549
|
+
if (BRIDGE_CONFIG.hostClass === "mobile" || BRIDGE_CONFIG.hostClass === "desktop")
|
|
550
|
+
return BRIDGE_CONFIG.hostClass;
|
|
551
|
+
return BRIDGE_CONFIG.os === "macOS" || BRIDGE_CONFIG.os === "Windows" ? "desktop" : "mobile";
|
|
552
|
+
}
|
|
553
|
+
function isDesktop() {
|
|
554
|
+
return hostClass() === "desktop";
|
|
555
|
+
}
|
|
556
|
+
//#endregion
|
|
557
|
+
//#region ../lingxia-bridge/dist/es2020/surface-context.js
|
|
558
|
+
/** What a host that sends nothing — one older than this API — is taken to say. */
|
|
559
|
+
var UNREPORTED = {
|
|
560
|
+
sizeClass: "compact",
|
|
561
|
+
width: 0,
|
|
562
|
+
height: 0,
|
|
563
|
+
aside: false
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* One store per document, on `window`, for the same reason as the display
|
|
567
|
+
* language: the bridge module is present twice in a page, and the host must
|
|
568
|
+
* reach the copy the framework hooks read.
|
|
569
|
+
*/
|
|
570
|
+
function store() {
|
|
571
|
+
var _a;
|
|
572
|
+
if (typeof window === "undefined")
|
|
573
|
+
return fallbackStore;
|
|
574
|
+
if (!window.__lxSurfaceContext) {
|
|
575
|
+
var config = window.__LX_BRIDGE_CFG;
|
|
576
|
+
window.__lxSurfaceContext = {
|
|
577
|
+
value: (_a = parse(config === null || config === void 0 ? void 0 : config.surfaceContext)) !== null && _a !== void 0 ? _a : UNREPORTED,
|
|
578
|
+
revision: typeof (config === null || config === void 0 ? void 0 : config.surfaceContextRevision) === "number" ? config.surfaceContextRevision : 0,
|
|
579
|
+
listeners: /* @__PURE__ */ new Set()
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
return window.__lxSurfaceContext;
|
|
583
|
+
}
|
|
584
|
+
var fallbackStore = {
|
|
585
|
+
value: UNREPORTED,
|
|
586
|
+
revision: 0,
|
|
587
|
+
listeners: /* @__PURE__ */ new Set()
|
|
588
|
+
};
|
|
589
|
+
function parse(next) {
|
|
590
|
+
if (typeof next !== "object" || next === null)
|
|
591
|
+
return null;
|
|
592
|
+
var sizeClass = next.sizeClass, width = next.width, height = next.height, aside = next.aside;
|
|
593
|
+
if (sizeClass !== "compact" && sizeClass !== "regular")
|
|
594
|
+
return null;
|
|
595
|
+
if (typeof width !== "number" || typeof height !== "number")
|
|
596
|
+
return null;
|
|
597
|
+
return {
|
|
598
|
+
sizeClass: sizeClass,
|
|
599
|
+
width: width,
|
|
600
|
+
height: height,
|
|
601
|
+
aside: aside === true
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
function same$1(a, b) {
|
|
605
|
+
return a.sizeClass === b.sizeClass && a.width === b.width && a.height === b.height && a.aside === b.aside;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Host entry point: once the page's bridge is up, and on every change. Pushes
|
|
609
|
+
* can run out of order across host threads, so each carries a revision and an
|
|
610
|
+
* older one than the store holds is dropped.
|
|
611
|
+
*/
|
|
612
|
+
function applySurfaceContext(next, revision) {
|
|
613
|
+
var context = parse(next);
|
|
614
|
+
var current = store();
|
|
615
|
+
if (!context)
|
|
616
|
+
return;
|
|
617
|
+
if (typeof revision === "number") {
|
|
618
|
+
if (revision <= current.revision)
|
|
619
|
+
return;
|
|
620
|
+
current.revision = revision;
|
|
621
|
+
}
|
|
622
|
+
if (same$1(current.value, context))
|
|
623
|
+
return;
|
|
624
|
+
current.value = context;
|
|
625
|
+
for (var _i = 0, _a = __spreadArray([], current.listeners, true); _i < _a.length; _i++) {
|
|
626
|
+
var listener = _a[_i];
|
|
627
|
+
listener();
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (typeof window !== "undefined" && !window.__lingxiaApplySurfaceContext)
|
|
631
|
+
Object.defineProperty(window, "__lingxiaApplySurfaceContext", {
|
|
632
|
+
configurable: false,
|
|
633
|
+
enumerable: false,
|
|
634
|
+
value: applySurfaceContext
|
|
635
|
+
});
|
|
636
|
+
/**
|
|
637
|
+
* The lxapp's adaptive context. The host seeds it into every page before any
|
|
638
|
+
* script runs and pushes each change, so there is always a value; a host older
|
|
639
|
+
* than this API reports `compact` with a 0×0 viewport.
|
|
640
|
+
*/
|
|
641
|
+
function getSurfaceContext() {
|
|
642
|
+
return store().value;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Follow the adaptive context. Change-only, like `subscribeDisplayLanguage`,
|
|
646
|
+
* so it composes with `useSyncExternalStore`. Returns an unsubscribe.
|
|
647
|
+
*/
|
|
648
|
+
function subscribeSurfaceContext(listener) {
|
|
649
|
+
var listeners = store().listeners;
|
|
650
|
+
listeners.add(listener);
|
|
651
|
+
return function () {
|
|
652
|
+
listeners.delete(listener);
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region ../lingxia-bridge/dist/es2020/host.js
|
|
657
|
+
var current = null;
|
|
658
|
+
function read() {
|
|
659
|
+
var surface = getSurfaceContext();
|
|
660
|
+
return {
|
|
661
|
+
sizeClass: surface.sizeClass,
|
|
662
|
+
aside: surface.aside,
|
|
663
|
+
displayLanguage: getDisplayLanguage(),
|
|
664
|
+
formFactor: isDesktop() ? "desktop" : "mobile",
|
|
665
|
+
os: getPlatformOS(),
|
|
666
|
+
runner: BRIDGE_CONFIG.runner === true
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
function same(a, b) {
|
|
670
|
+
return a.sizeClass === b.sizeClass && a.aside === b.aside && a.displayLanguage === b.displayLanguage && a.formFactor === b.formFactor && a.os === b.os && a.runner === b.runner;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* The host facts for this page. The same object is returned until a field
|
|
674
|
+
* changes, so it composes with `useSyncExternalStore` and with memoization.
|
|
675
|
+
*/
|
|
676
|
+
function getHost() {
|
|
677
|
+
var next = read();
|
|
678
|
+
if (current === null || !same(current, next))
|
|
679
|
+
current = next;
|
|
680
|
+
return current;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Follow the host facts. Change-only: the listener runs when a field of
|
|
684
|
+
* `getHost()` changes — not on subscribe, and not when only the viewport's
|
|
685
|
+
* size moves within its size class. Returns an unsubscribe.
|
|
686
|
+
*/
|
|
687
|
+
function subscribeHost(listener) {
|
|
688
|
+
var last = getHost();
|
|
689
|
+
var check = function () {
|
|
690
|
+
var next = getHost();
|
|
691
|
+
if (next === last)
|
|
692
|
+
return;
|
|
693
|
+
last = next;
|
|
694
|
+
listener();
|
|
695
|
+
};
|
|
696
|
+
var stopLanguage = subscribeDisplayLanguage(check);
|
|
697
|
+
var stopSurface = subscribeSurfaceContext(check);
|
|
698
|
+
return function () {
|
|
699
|
+
stopLanguage();
|
|
700
|
+
stopSurface();
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
//#endregion
|
|
704
|
+
//#region ../lingxia-page-runtime/dist/shared/startup.js
|
|
705
|
+
var pending;
|
|
706
|
+
/** Mount with complete initial data; a delayed startup stays recoverable. */
|
|
707
|
+
function waitForPageState() {
|
|
708
|
+
if (isPageReady())
|
|
709
|
+
return Promise.resolve();
|
|
710
|
+
return pending !== null && pending !== void 0 ? pending : (pending = wait().finally(function () {
|
|
711
|
+
pending = void 0;
|
|
712
|
+
}));
|
|
713
|
+
}
|
|
714
|
+
function wait() {
|
|
715
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
716
|
+
var delay, panel, timer;
|
|
717
|
+
var _a;
|
|
718
|
+
return __generator(this, function (_b) {
|
|
719
|
+
switch (_b.label) {
|
|
720
|
+
case 0:
|
|
721
|
+
delay = 1e4;
|
|
722
|
+
panel = {};
|
|
723
|
+
timer = setTimeout(function () {
|
|
724
|
+
var reason = "Page Logic has not delivered the page state after ".concat(delay, " ms");
|
|
725
|
+
console.error("[LingXia] ".concat(location.pathname, ": ").concat(reason));
|
|
726
|
+
panel.dismiss = renderPageFault(location.pathname, reason);
|
|
727
|
+
}, delay);
|
|
728
|
+
_b.label = 1;
|
|
729
|
+
case 1:
|
|
730
|
+
_b.trys.push([1, , 3, 4]);
|
|
731
|
+
return [4 /*yield*/, whenPageReady({ timeoutMs: null })];
|
|
732
|
+
case 2:
|
|
733
|
+
_b.sent();
|
|
734
|
+
return [3 /*break*/, 4];
|
|
735
|
+
case 3:
|
|
736
|
+
clearTimeout(timer);
|
|
737
|
+
(_a = panel.dismiss) === null || _a === void 0 ? void 0 : _a.call(panel);
|
|
738
|
+
return [7 /*endfinally*/];
|
|
739
|
+
case 4: return [2 /*return*/];
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
//#endregion
|
|
745
|
+
//#region ../lingxia-page-runtime/dist/page-chrome.js
|
|
196
746
|
var initialLayout = Object.freeze({
|
|
197
747
|
revision: 0,
|
|
198
748
|
topInset: 0,
|
|
@@ -208,24 +758,18 @@ var LingXiaPage = (function (exports) {
|
|
|
208
758
|
root === null || root === void 0 ? void 0 : root.style.setProperty("--lx-page-chrome-top-inset", "".concat(layout.topInset, "px"));
|
|
209
759
|
root === null || root === void 0 ? void 0 : root.style.setProperty("--lx-page-chrome-bottom-inset", "".concat(layout.bottomInset, "px"));
|
|
210
760
|
root === null || root === void 0 ? void 0 : root.style.setProperty("--lx-page-chrome-capsule-inline-end-inset", "".concat(layout.capsuleInlineEndInset, "px"));
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
installPageChromeRuntime();
|
|
224
|
-
var handleChange = function (event) {
|
|
225
|
-
listener(event.detail);
|
|
226
|
-
};
|
|
227
|
-
window.addEventListener("lxpagechromechange", handleChange);
|
|
228
|
-
return function () { return window.removeEventListener("lxpagechromechange", handleChange); };
|
|
761
|
+
var capsule = layout.capsuleRect;
|
|
762
|
+
for (var _i = 0, _a = [
|
|
763
|
+
"top",
|
|
764
|
+
"right",
|
|
765
|
+
"bottom",
|
|
766
|
+
"left",
|
|
767
|
+
"width",
|
|
768
|
+
"height"
|
|
769
|
+
]; _i < _a.length; _i++) {
|
|
770
|
+
var edge = _a[_i];
|
|
771
|
+
root === null || root === void 0 ? void 0 : root.style.setProperty("--lx-page-chrome-capsule-".concat(edge), "".concat(capsule ? capsule[edge] : 0, "px"));
|
|
772
|
+
}
|
|
229
773
|
}
|
|
230
774
|
/** Ensure browser previews have the same synchronous contract as native pages. */
|
|
231
775
|
function installPageChromeRuntime() {
|
|
@@ -264,12 +808,34 @@ var LingXiaPage = (function (exports) {
|
|
|
264
808
|
}
|
|
265
809
|
installPageChromeRuntime();
|
|
266
810
|
//#endregion
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
811
|
+
//#region dist/page.js
|
|
812
|
+
/**
|
|
813
|
+
* Resolves once the first state arrives. By default a delayed startup shows
|
|
814
|
+
* a fault panel and keeps waiting, just like React/Vue. An explicit timeout
|
|
815
|
+
* rejects instead; `null` waits without the panel. Await before `getPage()`.
|
|
816
|
+
*/
|
|
817
|
+
function pageReady(options) {
|
|
818
|
+
return (options === null || options === void 0 ? void 0 : options.timeoutMs) === void 0 ? waitForPageState() : whenPageReady(options);
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* This page's Logic state and actions — `this.data` and the page's methods.
|
|
822
|
+
* `data` is readonly: Logic owns it (in a dev session a write throws).
|
|
823
|
+
*/
|
|
824
|
+
function getPage() {
|
|
825
|
+
return {
|
|
826
|
+
data: getPageSnapshot(),
|
|
827
|
+
actions: getPageActions()
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
/** Follow the page's state. Change-only; read it with `getPage()`. Returns an unsubscribe. */
|
|
831
|
+
function subscribePage(listener) {
|
|
832
|
+
return subscribePageSnapshot(listener);
|
|
833
|
+
}
|
|
834
|
+
//#endregion
|
|
835
|
+
exports.getHost = getHost;
|
|
836
|
+
exports.getPage = getPage;
|
|
837
|
+
exports.pageReady = pageReady;
|
|
838
|
+
exports.subscribeHost = subscribeHost;
|
|
839
|
+
exports.subscribePage = subscribePage;
|
|
274
840
|
return exports;
|
|
275
841
|
})({});
|