@manyducks.co/dolla 1.0.1 → 2.0.0-alpha.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/README.md +47 -23
- package/build.js +5 -5
- package/dist/fragment-s33qZBzz.js +1241 -0
- package/dist/fragment-s33qZBzz.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +1308 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.js +17 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/{lib/jsx → dist}/jsx-runtime.d.ts +3 -4
- package/dist/jsx-runtime.js +20 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/{lib → dist}/markup.d.ts +12 -13
- package/dist/modules/dolla.d.ts +87 -0
- package/dist/modules/http.d.ts +57 -0
- package/dist/modules/language.d.ts +41 -0
- package/{lib/stores → dist/modules}/render.d.ts +5 -6
- package/{lib/stores → dist/modules}/router.d.ts +37 -39
- package/{lib → dist}/nodes/cond.d.ts +1 -4
- package/{lib → dist}/nodes/html.d.ts +2 -5
- package/{lib → dist}/nodes/observer.d.ts +2 -5
- package/{lib → dist}/nodes/outlet.d.ts +1 -4
- package/{lib → dist}/nodes/portal.d.ts +1 -3
- package/{lib → dist}/nodes/repeat.d.ts +2 -5
- package/{lib → dist}/nodes/text.d.ts +1 -1
- package/{lib → dist}/signals.d.ts +37 -54
- package/{lib → dist}/types.d.ts +0 -8
- package/{lib → dist}/utils.d.ts +10 -0
- package/dist/view.d.ts +44 -0
- package/dist/views/default-crash-page.d.ts +8 -0
- package/notes/scratch.md +120 -0
- package/package.json +11 -12
- package/vite.config.js +27 -0
- package/lib/app.d.ts +0 -83
- package/lib/classes/CrashCollector.d.ts +0 -30
- package/lib/classes/DebugHub.d.ts +0 -61
- package/lib/classes/EventEmitter.d.ts +0 -44
- package/lib/index.d.ts +0 -21
- package/lib/index.js +0 -4176
- package/lib/index.js.map +0 -7
- package/lib/jsx/jsx-dev-runtime.d.ts +0 -3
- package/lib/jsx/jsx-dev-runtime.js +0 -20
- package/lib/jsx/jsx-dev-runtime.js.map +0 -7
- package/lib/jsx/jsx-runtime.js +0 -22
- package/lib/jsx/jsx-runtime.js.map +0 -7
- package/lib/signals.test.d.ts +0 -1
- package/lib/spring.d.ts +0 -0
- package/lib/state.d.ts +0 -103
- package/lib/store.d.ts +0 -59
- package/lib/stores/dialog.d.ts +0 -32
- package/lib/stores/document.d.ts +0 -11
- package/lib/stores/http.d.ts +0 -60
- package/lib/stores/language.d.ts +0 -36
- package/lib/testing/classes/MockHTTP.d.ts +0 -10
- package/lib/testing/index.d.ts +0 -4
- package/lib/testing/makeMockDOMNode.d.ts +0 -10
- package/lib/testing/makeMockFetch._test.d.ts +0 -1
- package/lib/testing/makeMockFetch.d.ts +0 -36
- package/lib/testing/makeMockFetch.test.d.ts +0 -1
- package/lib/testing/makeMockFetch.test_skip.d.ts +0 -1
- package/lib/testing/stores/dialog.d.ts +0 -6
- package/lib/testing/stores/http.d.ts +0 -13
- package/lib/testing/stores/page.d.ts +0 -7
- package/lib/testing/stores/router.d.ts +0 -12
- package/lib/testing/wrapStore._test.d.ts +0 -1
- package/lib/testing/wrapStore.d.ts +0 -8
- package/lib/testing/wrapStore.test.d.ts +0 -1
- package/lib/testing/wrapStore.test_skip.d.ts +0 -1
- package/lib/testing/wrapView.d.ts +0 -0
- package/lib/view.d.ts +0 -88
- package/lib/views/default-crash-page.d.ts +0 -7
- package/lib/views/store-scope.d.ts +0 -13
- /package/{lib → dist}/routing.d.ts +0 -0
- /package/{lib → dist}/routing.test.d.ts +0 -0
- /package/{lib → dist}/typeChecking.d.ts +0 -0
- /package/{lib → dist}/views/default-view.d.ts +0 -0
- /package/{lib → dist}/views/fragment.d.ts +0 -0
package/lib/index.js
DELETED
|
@@ -1,4176 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
24
|
-
mod
|
|
25
|
-
));
|
|
26
|
-
|
|
27
|
-
// node_modules/simple-color-hash/lib/index.js
|
|
28
|
-
var require_lib = __commonJS({
|
|
29
|
-
"node_modules/simple-color-hash/lib/index.js"(exports, module) {
|
|
30
|
-
"use strict";
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
var _slicedToArray = /* @__PURE__ */ function() {
|
|
33
|
-
function a(a2, b) {
|
|
34
|
-
var c = [], d = true, e = false, f = void 0;
|
|
35
|
-
try {
|
|
36
|
-
for (var g, h = a2[Symbol.iterator](); !(d = (g = h.next()).done) && (c.push(g.value), !(b && c.length === b)); d = true)
|
|
37
|
-
;
|
|
38
|
-
} catch (a3) {
|
|
39
|
-
e = true, f = a3;
|
|
40
|
-
} finally {
|
|
41
|
-
try {
|
|
42
|
-
!d && h["return"] && h["return"]();
|
|
43
|
-
} finally {
|
|
44
|
-
if (e)
|
|
45
|
-
throw f;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return c;
|
|
49
|
-
}
|
|
50
|
-
return function(b, c) {
|
|
51
|
-
if (Array.isArray(b))
|
|
52
|
-
return b;
|
|
53
|
-
if (Symbol.iterator in Object(b))
|
|
54
|
-
return a(b, c);
|
|
55
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
|
56
|
-
};
|
|
57
|
-
}();
|
|
58
|
-
var rgbToHex = function(a) {
|
|
59
|
-
return a.reduce(function(a2, b) {
|
|
60
|
-
return 16 > b ? a2 + "0" + b.toString(16) : a2 + b.toString(16);
|
|
61
|
-
}, "#");
|
|
62
|
-
};
|
|
63
|
-
var hslToRgb = function(a, b, c) {
|
|
64
|
-
var d = 0.5 > c ? c * (1 + b) : c + b - c * b, e = 2 * c - d, f = function(a2, b2, c2) {
|
|
65
|
-
var d2 = Math.round, e2 = 0 > c2 ? c2 + 1 : 1 < c2 ? c2 - 1 : c2;
|
|
66
|
-
return e2 = e2 < 1 / 6 ? a2 + 6 * (b2 - a2) * e2 : e2 < 1 / 2 ? b2 : e2 < 2 / 3 ? a2 + 6 * (b2 - a2) * (2 / 3 - e2) : a2, d2(255 * e2);
|
|
67
|
-
}, g = f(e, d, a + 1 / 3), h = f(e, d, a), i = f(e, d, a - 1 / 3);
|
|
68
|
-
return [g, h, i];
|
|
69
|
-
};
|
|
70
|
-
var hslGeneration = function(a, b, c, d) {
|
|
71
|
-
var e = a % 1007 / 1007, f = function(a2, b2, c2) {
|
|
72
|
-
return a2 * (c2 - b2) + b2;
|
|
73
|
-
}, g = f(e, b.min, b.max), h = f(e, c.min, c.max), i = f(e, d.max, d.min);
|
|
74
|
-
return [g, h, i];
|
|
75
|
-
};
|
|
76
|
-
var standardHashFunction = function(a) {
|
|
77
|
-
return a.split("").reduce(function(a2, b, c) {
|
|
78
|
-
return a2 * b.charCodeAt(0) * c + 1;
|
|
79
|
-
}, 1);
|
|
80
|
-
};
|
|
81
|
-
var generateColorHash = function(a) {
|
|
82
|
-
var b = a.str, c = a.hue, d = c === void 0 ? { min: 0, max: 360 } : c, e = a.sat, f = e === void 0 ? { min: 0.35, max: 0.65 } : e, g = a.light, h = g === void 0 ? { min: 0.3, max: 0.7 } : g, i = a.hashFunction, j = i === void 0 ? standardHashFunction : i, k = a.scheme, l = k === void 0 ? "hex" : k, m2 = hslGeneration(j(b), d, f, h), n = _slicedToArray(m2, 3), o = n[0], p = n[1], q = n[2], r = hslToRgb(o / 360, p, q), s = rgbToHex(r);
|
|
83
|
-
if ("hsl" === l)
|
|
84
|
-
return [o, p, q];
|
|
85
|
-
return "rgb" === l ? r : s;
|
|
86
|
-
};
|
|
87
|
-
exports.default = generateColorHash, module.exports = exports.default;
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// src/classes/CrashCollector.ts
|
|
92
|
-
var CrashCollector = class {
|
|
93
|
-
#errors = [];
|
|
94
|
-
#errorCallbacks = [];
|
|
95
|
-
/**
|
|
96
|
-
* Registers a callback to receive all errors that pass through the CrashCollector.
|
|
97
|
-
* Returns a function that cancels this listener when called.
|
|
98
|
-
*/
|
|
99
|
-
onError(callback) {
|
|
100
|
-
this.#errorCallbacks.push(callback);
|
|
101
|
-
return () => {
|
|
102
|
-
this.#errorCallbacks.splice(this.#errorCallbacks.indexOf(callback), 1);
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Reports an unrecoverable error that requires crashing the whole app.
|
|
107
|
-
*/
|
|
108
|
-
crash({ error, componentName }) {
|
|
109
|
-
const ctx = {
|
|
110
|
-
error,
|
|
111
|
-
severity: "crash",
|
|
112
|
-
componentName: componentName ?? "anonymous component"
|
|
113
|
-
};
|
|
114
|
-
this.#errors.push(ctx);
|
|
115
|
-
for (const callback of this.#errorCallbacks) {
|
|
116
|
-
callback(ctx);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Reports a recoverable error.
|
|
121
|
-
*/
|
|
122
|
-
error({ error, componentName }) {
|
|
123
|
-
const ctx = {
|
|
124
|
-
error,
|
|
125
|
-
severity: "error",
|
|
126
|
-
componentName: componentName ?? "anonymous component"
|
|
127
|
-
};
|
|
128
|
-
this.#errors.push(ctx);
|
|
129
|
-
for (const callback of this.#errorCallbacks) {
|
|
130
|
-
callback(ctx);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
// src/classes/DebugHub.ts
|
|
136
|
-
var import_simple_color_hash = __toESM(require_lib(), 1);
|
|
137
|
-
|
|
138
|
-
// src/typeChecking.ts
|
|
139
|
-
function typeOf(value) {
|
|
140
|
-
if (value === void 0) {
|
|
141
|
-
return "undefined";
|
|
142
|
-
}
|
|
143
|
-
if (value === null) {
|
|
144
|
-
return "null";
|
|
145
|
-
}
|
|
146
|
-
const type = typeof value;
|
|
147
|
-
switch (type) {
|
|
148
|
-
case "number":
|
|
149
|
-
if (isNaN(value)) {
|
|
150
|
-
return "NaN";
|
|
151
|
-
}
|
|
152
|
-
return "number";
|
|
153
|
-
case "function":
|
|
154
|
-
if (isClass(value)) {
|
|
155
|
-
return "class";
|
|
156
|
-
}
|
|
157
|
-
return type;
|
|
158
|
-
case "object":
|
|
159
|
-
if (isArray(value)) {
|
|
160
|
-
return "array";
|
|
161
|
-
}
|
|
162
|
-
if (isPromise(value)) {
|
|
163
|
-
return "promise";
|
|
164
|
-
}
|
|
165
|
-
return type;
|
|
166
|
-
default:
|
|
167
|
-
return type;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function isArray(value) {
|
|
171
|
-
return Array.isArray(value);
|
|
172
|
-
}
|
|
173
|
-
function isArrayOf(...args) {
|
|
174
|
-
const check = args[0];
|
|
175
|
-
const test = (value) => {
|
|
176
|
-
return isArray(value) && value.every((item) => check(item));
|
|
177
|
-
};
|
|
178
|
-
if (args.length < 2) {
|
|
179
|
-
return test;
|
|
180
|
-
} else {
|
|
181
|
-
return test(args[1]);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function assertArrayOf(...args) {
|
|
185
|
-
const check = args[0];
|
|
186
|
-
const message = isString(args[2]) ? args[2] : "Expected an array of valid items. Got type: %t, value: %v";
|
|
187
|
-
const test = (value) => {
|
|
188
|
-
if (isArray(value) && value.every((item) => check(item))) {
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
throw new TypeError(formatError(value, message));
|
|
192
|
-
};
|
|
193
|
-
if (args.length < 2) {
|
|
194
|
-
return test;
|
|
195
|
-
} else {
|
|
196
|
-
return test(args[1]);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
function isString(value) {
|
|
200
|
-
return typeof value === "string";
|
|
201
|
-
}
|
|
202
|
-
function assertString(value, errorMessage) {
|
|
203
|
-
if (isString(value)) {
|
|
204
|
-
return true;
|
|
205
|
-
}
|
|
206
|
-
throw new TypeError(formatError(value, errorMessage ?? "Expected a string. Got type: %t, value: %v"));
|
|
207
|
-
}
|
|
208
|
-
function isFunction(value) {
|
|
209
|
-
return typeof value === "function" && !isClass(value);
|
|
210
|
-
}
|
|
211
|
-
function assertFunction(value, errorMessage) {
|
|
212
|
-
if (isFunction(value)) {
|
|
213
|
-
return true;
|
|
214
|
-
}
|
|
215
|
-
throw new TypeError(formatError(value, errorMessage ?? "Expected a function. Got type: %t, value: %v"));
|
|
216
|
-
}
|
|
217
|
-
function isNumber(value) {
|
|
218
|
-
return typeof value === "number" && !isNaN(value);
|
|
219
|
-
}
|
|
220
|
-
function isPromise(value) {
|
|
221
|
-
if (value == null)
|
|
222
|
-
return false;
|
|
223
|
-
const obj = value;
|
|
224
|
-
return obj instanceof Promise || isFunction(obj.then) && isFunction(obj.catch) && isFunction(obj.finally);
|
|
225
|
-
}
|
|
226
|
-
function isClass(value) {
|
|
227
|
-
return typeof value === "function" && /^\s*class\s+/.test(value.toString());
|
|
228
|
-
}
|
|
229
|
-
function assertInstanceOf(...args) {
|
|
230
|
-
const constructor = args[0];
|
|
231
|
-
const errorMessage = isString(args[2]) ? args[2] : `Expected instance of ${constructor.name}. Got type: %t, value: %v`;
|
|
232
|
-
const test = (value) => {
|
|
233
|
-
if (value instanceof constructor) {
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
throw new TypeError(formatError(value, errorMessage));
|
|
237
|
-
};
|
|
238
|
-
if (args.length < 2) {
|
|
239
|
-
return test;
|
|
240
|
-
} else {
|
|
241
|
-
return test(args[1]);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
function isObject(value) {
|
|
245
|
-
return value != null && typeof value === "object" && !isArray(value);
|
|
246
|
-
}
|
|
247
|
-
function assertObject(value, errorMessage) {
|
|
248
|
-
if (isObject(value)) {
|
|
249
|
-
return true;
|
|
250
|
-
}
|
|
251
|
-
throw new TypeError(formatError(value, errorMessage ?? "Expected an object. Got type: %t, value: %v"));
|
|
252
|
-
}
|
|
253
|
-
function formatError(value, message) {
|
|
254
|
-
const typeName = typeOf(value);
|
|
255
|
-
const valueString = value?.toString?.() || String(value);
|
|
256
|
-
return message.replaceAll("%t", typeName).replaceAll("%v", valueString);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// src/classes/DebugHub.ts
|
|
260
|
-
var DebugHub = class {
|
|
261
|
-
#filter = "*,-dolla/*";
|
|
262
|
-
#matcher;
|
|
263
|
-
#console;
|
|
264
|
-
#options;
|
|
265
|
-
constructor(options, _console = getDefaultConsole()) {
|
|
266
|
-
if (options.filter) {
|
|
267
|
-
this.#filter = options.filter;
|
|
268
|
-
}
|
|
269
|
-
this.#matcher = makeMatcher(this.#filter);
|
|
270
|
-
this.#console = _console;
|
|
271
|
-
this.#options = options;
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Returns a debug channel labelled by `name`. Used for logging from components.
|
|
275
|
-
*/
|
|
276
|
-
channel(options) {
|
|
277
|
-
const _console = this.#console;
|
|
278
|
-
const hubOptions = this.#options;
|
|
279
|
-
const match = (value) => {
|
|
280
|
-
return this.#matcher(value);
|
|
281
|
-
};
|
|
282
|
-
return {
|
|
283
|
-
get info() {
|
|
284
|
-
const name = options.name;
|
|
285
|
-
if (hubOptions.info === false || isString(hubOptions.info) && hubOptions.info !== hubOptions.mode || !match(name)) {
|
|
286
|
-
return noOp;
|
|
287
|
-
} else {
|
|
288
|
-
let label = `%c${name}`;
|
|
289
|
-
if (options.id) {
|
|
290
|
-
label += ` %c[uid: %c${options.id}%c]`;
|
|
291
|
-
} else {
|
|
292
|
-
label += `%c%c%c`;
|
|
293
|
-
}
|
|
294
|
-
return _console.info.bind(
|
|
295
|
-
_console,
|
|
296
|
-
label,
|
|
297
|
-
`color:${hash(label)};font-weight:bold`,
|
|
298
|
-
`color:#777`,
|
|
299
|
-
`color:#aaa`,
|
|
300
|
-
`color:#777`
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
|
-
get log() {
|
|
305
|
-
const name = options.name;
|
|
306
|
-
if (hubOptions.log === false || isString(hubOptions.log) && hubOptions.log !== hubOptions.mode || !match(name)) {
|
|
307
|
-
return noOp;
|
|
308
|
-
} else {
|
|
309
|
-
let label = `%c${name}`;
|
|
310
|
-
if (options.id) {
|
|
311
|
-
label += ` %c[uid: %c${options.id}%c]`;
|
|
312
|
-
} else {
|
|
313
|
-
label += `%c%c%c`;
|
|
314
|
-
}
|
|
315
|
-
return _console.log.bind(
|
|
316
|
-
_console,
|
|
317
|
-
label,
|
|
318
|
-
`color:${hash(label)};font-weight:bold`,
|
|
319
|
-
`color:#777`,
|
|
320
|
-
`color:#aaa`,
|
|
321
|
-
`color:#777`
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
get warn() {
|
|
326
|
-
const name = options.name;
|
|
327
|
-
if (hubOptions.warn === false || isString(hubOptions.warn) && hubOptions.warn !== hubOptions.mode || !match(name)) {
|
|
328
|
-
return noOp;
|
|
329
|
-
} else {
|
|
330
|
-
let label = `%c${name}`;
|
|
331
|
-
if (options.id) {
|
|
332
|
-
label += ` %c[uid: %c${options.id}%c]`;
|
|
333
|
-
} else {
|
|
334
|
-
label += `%c%c%c`;
|
|
335
|
-
}
|
|
336
|
-
return _console.warn.bind(
|
|
337
|
-
_console,
|
|
338
|
-
label,
|
|
339
|
-
`color:${hash(label)};font-weight:bold`,
|
|
340
|
-
`color:#777`,
|
|
341
|
-
`color:#aaa`,
|
|
342
|
-
`color:#777`
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
},
|
|
346
|
-
get error() {
|
|
347
|
-
const name = options.name;
|
|
348
|
-
if (hubOptions.error === false || isString(hubOptions.error) && hubOptions.error !== hubOptions.mode || !match(name)) {
|
|
349
|
-
return noOp;
|
|
350
|
-
} else {
|
|
351
|
-
let label = `%c${name}`;
|
|
352
|
-
if (options.id) {
|
|
353
|
-
label += ` %c[uid: %c${options.id}%c]`;
|
|
354
|
-
} else {
|
|
355
|
-
label += `%c%c%c`;
|
|
356
|
-
}
|
|
357
|
-
return _console.error.bind(
|
|
358
|
-
_console,
|
|
359
|
-
label,
|
|
360
|
-
`color:${hash(label)};font-weight:bold`,
|
|
361
|
-
`color:#777`,
|
|
362
|
-
`color:#aaa`,
|
|
363
|
-
`color:#777`
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
get filter() {
|
|
370
|
-
return this.#filter;
|
|
371
|
-
}
|
|
372
|
-
set filter(pattern) {
|
|
373
|
-
this.#filter = pattern;
|
|
374
|
-
this.#matcher = makeMatcher(pattern);
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
function getDefaultConsole() {
|
|
378
|
-
if (typeof window !== "undefined" && window.console) {
|
|
379
|
-
return window.console;
|
|
380
|
-
}
|
|
381
|
-
if (typeof global !== "undefined" && global.console) {
|
|
382
|
-
return global.console;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
var noOp = () => {
|
|
386
|
-
};
|
|
387
|
-
function hash(value) {
|
|
388
|
-
return (0, import_simple_color_hash.default)({
|
|
389
|
-
str: value,
|
|
390
|
-
sat: { min: 0.35, max: 0.55 },
|
|
391
|
-
light: { min: 0.6, max: 0.6 }
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
function makeMatcher(pattern) {
|
|
395
|
-
if (pattern instanceof RegExp) {
|
|
396
|
-
return (value) => pattern.test(value);
|
|
397
|
-
}
|
|
398
|
-
const matchers = {
|
|
399
|
-
positive: [],
|
|
400
|
-
negative: []
|
|
401
|
-
};
|
|
402
|
-
const parts = pattern.split(",").map((p) => p.trim()).filter((p) => p !== "");
|
|
403
|
-
for (let part of parts) {
|
|
404
|
-
let section = "positive";
|
|
405
|
-
if (part.startsWith("-")) {
|
|
406
|
-
section = "negative";
|
|
407
|
-
part = part.slice(1);
|
|
408
|
-
}
|
|
409
|
-
if (part === "*") {
|
|
410
|
-
matchers[section].push(function() {
|
|
411
|
-
return true;
|
|
412
|
-
});
|
|
413
|
-
} else if (part.endsWith("*")) {
|
|
414
|
-
matchers[section].push(function(value) {
|
|
415
|
-
return value.startsWith(part.slice(0, part.length - 1));
|
|
416
|
-
});
|
|
417
|
-
} else {
|
|
418
|
-
matchers[section].push(function(value) {
|
|
419
|
-
return value === part;
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return function(name) {
|
|
424
|
-
const { positive, negative } = matchers;
|
|
425
|
-
if (negative.some((fn) => fn(name))) {
|
|
426
|
-
return false;
|
|
427
|
-
}
|
|
428
|
-
if (positive.length > 0 && !positive.some((fn) => fn(name))) {
|
|
429
|
-
return false;
|
|
430
|
-
}
|
|
431
|
-
return true;
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// src/nodes/cond.ts
|
|
436
|
-
var Conditional = class {
|
|
437
|
-
node;
|
|
438
|
-
endNode;
|
|
439
|
-
$predicate;
|
|
440
|
-
stopCallback;
|
|
441
|
-
thenContent;
|
|
442
|
-
elseContent;
|
|
443
|
-
connectedContent = [];
|
|
444
|
-
appContext;
|
|
445
|
-
elementContext;
|
|
446
|
-
initialUpdateHappened = false;
|
|
447
|
-
previousValue;
|
|
448
|
-
constructor(config) {
|
|
449
|
-
this.$predicate = config.$predicate;
|
|
450
|
-
this.thenContent = config.thenContent ? toMarkup(config.thenContent) : void 0;
|
|
451
|
-
this.elseContent = config.elseContent ? toMarkup(config.elseContent) : void 0;
|
|
452
|
-
this.appContext = config.appContext;
|
|
453
|
-
this.elementContext = config.elementContext;
|
|
454
|
-
if (this.appContext.mode === "development") {
|
|
455
|
-
this.node = document.createComment("Conditional");
|
|
456
|
-
this.endNode = document.createComment("/Conditional");
|
|
457
|
-
} else {
|
|
458
|
-
this.node = document.createTextNode("");
|
|
459
|
-
this.endNode = document.createTextNode("");
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
get connected() {
|
|
463
|
-
return this.node.parentNode != null;
|
|
464
|
-
}
|
|
465
|
-
connect(parent2, after) {
|
|
466
|
-
if (!this.connected) {
|
|
467
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
468
|
-
if (this.appContext.mode === "development") {
|
|
469
|
-
parent2.insertBefore(this.endNode, this.node.nextSibling);
|
|
470
|
-
}
|
|
471
|
-
this.stopCallback = this.$predicate.watch((value) => {
|
|
472
|
-
if (!this.initialUpdateHappened || value && !this.previousValue || !value && this.previousValue) {
|
|
473
|
-
this.update(value);
|
|
474
|
-
this.initialUpdateHappened = true;
|
|
475
|
-
this.previousValue = value;
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
disconnect() {
|
|
481
|
-
if (this.stopCallback) {
|
|
482
|
-
this.stopCallback();
|
|
483
|
-
this.stopCallback = void 0;
|
|
484
|
-
}
|
|
485
|
-
for (const handle of this.connectedContent) {
|
|
486
|
-
handle.disconnect();
|
|
487
|
-
}
|
|
488
|
-
this.connectedContent = [];
|
|
489
|
-
if (this.connected) {
|
|
490
|
-
this.node.parentNode?.removeChild(this.node);
|
|
491
|
-
this.endNode.parentNode?.removeChild(this.endNode);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
update(value) {
|
|
495
|
-
for (const handle of this.connectedContent) {
|
|
496
|
-
handle.disconnect();
|
|
497
|
-
}
|
|
498
|
-
this.connectedContent = [];
|
|
499
|
-
if (this.node.parentNode == null) {
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
if (value && this.thenContent) {
|
|
503
|
-
this.connectedContent = renderMarkupToDOM(this.thenContent, this);
|
|
504
|
-
} else if (!value && this.elseContent) {
|
|
505
|
-
this.connectedContent = renderMarkupToDOM(this.elseContent, this);
|
|
506
|
-
}
|
|
507
|
-
for (let i = 0; i < this.connectedContent.length; i++) {
|
|
508
|
-
const handle = this.connectedContent[i];
|
|
509
|
-
const previous = this.connectedContent[i - 1]?.node ?? this.node;
|
|
510
|
-
handle.connect(this.node.parentNode, previous);
|
|
511
|
-
}
|
|
512
|
-
if (this.appContext.mode === "development") {
|
|
513
|
-
this.node.textContent = `Conditional (${value ? "truthy" : "falsy"})`;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
async setChildren(children) {
|
|
517
|
-
}
|
|
518
|
-
};
|
|
519
|
-
|
|
520
|
-
// node_modules/nanoid/index.browser.js
|
|
521
|
-
var nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
|
|
522
|
-
byte &= 63;
|
|
523
|
-
if (byte < 36) {
|
|
524
|
-
id += byte.toString(36);
|
|
525
|
-
} else if (byte < 62) {
|
|
526
|
-
id += (byte - 26).toString(36).toUpperCase();
|
|
527
|
-
} else if (byte > 62) {
|
|
528
|
-
id += "-";
|
|
529
|
-
} else {
|
|
530
|
-
id += "_";
|
|
531
|
-
}
|
|
532
|
-
return id;
|
|
533
|
-
}, "");
|
|
534
|
-
|
|
535
|
-
// src/utils.ts
|
|
536
|
-
function isPlainObject(value) {
|
|
537
|
-
return value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.getPrototypeOf({});
|
|
538
|
-
}
|
|
539
|
-
function deepEqual(one, two) {
|
|
540
|
-
if (one === two) {
|
|
541
|
-
return true;
|
|
542
|
-
}
|
|
543
|
-
if (isSignal(one) || isSignal(two)) {
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
if (isPlainObject(one) && isPlainObject(two)) {
|
|
547
|
-
const keysOne = Object.keys(one);
|
|
548
|
-
const keysTwo = Object.keys(two);
|
|
549
|
-
if (keysOne.length !== keysTwo.length) {
|
|
550
|
-
return false;
|
|
551
|
-
}
|
|
552
|
-
for (const key in one) {
|
|
553
|
-
if (!deepEqual(one[key], two[key])) {
|
|
554
|
-
return false;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
return true;
|
|
558
|
-
}
|
|
559
|
-
if (Array.isArray(one) && Array.isArray(two)) {
|
|
560
|
-
if (one.length !== two.length) {
|
|
561
|
-
return false;
|
|
562
|
-
}
|
|
563
|
-
for (const index in one) {
|
|
564
|
-
if (!deepEqual(one[index], two[index])) {
|
|
565
|
-
return false;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
return true;
|
|
569
|
-
}
|
|
570
|
-
return one === two;
|
|
571
|
-
}
|
|
572
|
-
function merge(one, two) {
|
|
573
|
-
if (isObject(one)) {
|
|
574
|
-
if (!isObject(two)) {
|
|
575
|
-
return two;
|
|
576
|
-
}
|
|
577
|
-
const merged = Object.assign({}, one);
|
|
578
|
-
for (const key in two) {
|
|
579
|
-
merged[key] = merge(merged[key], two[key]);
|
|
580
|
-
}
|
|
581
|
-
return merged;
|
|
582
|
-
} else {
|
|
583
|
-
return two;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
function omit(keys, object) {
|
|
587
|
-
const process2 = (object2) => {
|
|
588
|
-
const newObject = {};
|
|
589
|
-
for (const key in object2) {
|
|
590
|
-
if (!keys.includes(key)) {
|
|
591
|
-
newObject[key] = object2[key];
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
return newObject;
|
|
595
|
-
};
|
|
596
|
-
if (object == null) {
|
|
597
|
-
return process2;
|
|
598
|
-
}
|
|
599
|
-
return process2(object);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// src/signals.ts
|
|
603
|
-
function isSignal(value) {
|
|
604
|
-
if (value == null || typeof value !== "object") {
|
|
605
|
-
return false;
|
|
606
|
-
}
|
|
607
|
-
if (typeof value["get"] !== "function") {
|
|
608
|
-
return false;
|
|
609
|
-
}
|
|
610
|
-
if (typeof value["watch"] !== "function") {
|
|
611
|
-
return false;
|
|
612
|
-
}
|
|
613
|
-
return true;
|
|
614
|
-
}
|
|
615
|
-
function isSettableSignal(value) {
|
|
616
|
-
if (value == null || typeof value !== "object") {
|
|
617
|
-
return false;
|
|
618
|
-
}
|
|
619
|
-
if (typeof value["set"] !== "function") {
|
|
620
|
-
return false;
|
|
621
|
-
}
|
|
622
|
-
if (typeof value["get"] !== "function") {
|
|
623
|
-
return false;
|
|
624
|
-
}
|
|
625
|
-
if (typeof value["watch"] !== "function") {
|
|
626
|
-
return false;
|
|
627
|
-
}
|
|
628
|
-
return true;
|
|
629
|
-
}
|
|
630
|
-
function designalify(value) {
|
|
631
|
-
if (isSignal(value)) {
|
|
632
|
-
return value.get();
|
|
633
|
-
} else {
|
|
634
|
-
return value;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
function signalify(value) {
|
|
638
|
-
if (isSignal(value)) {
|
|
639
|
-
return value;
|
|
640
|
-
} else {
|
|
641
|
-
return createStaticSignal(value);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
function signal(initialValue, options) {
|
|
645
|
-
return createSignal(initialValue, options);
|
|
646
|
-
}
|
|
647
|
-
signal.settable = createSettableSignal;
|
|
648
|
-
signal.toSettable = createSettableSignalFrom;
|
|
649
|
-
signal.createSetter = createSignalSetter;
|
|
650
|
-
function createSettableSignal(initialValue, options) {
|
|
651
|
-
const [$value, setValue] = signal(initialValue, options);
|
|
652
|
-
return {
|
|
653
|
-
get: $value.get,
|
|
654
|
-
watch: $value.watch,
|
|
655
|
-
set: setValue
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
function createSettableSignalFrom(signal2, setter) {
|
|
659
|
-
return {
|
|
660
|
-
get: signal2.get,
|
|
661
|
-
watch: signal2.watch,
|
|
662
|
-
set: setter
|
|
663
|
-
};
|
|
664
|
-
}
|
|
665
|
-
function createSignalSetter(signal2, callback) {
|
|
666
|
-
return function setValue(nextOrCallback) {
|
|
667
|
-
const previous = signal2.get();
|
|
668
|
-
let next;
|
|
669
|
-
if (typeof nextOrCallback === "function") {
|
|
670
|
-
next = nextOrCallback(previous);
|
|
671
|
-
} else {
|
|
672
|
-
next = nextOrCallback;
|
|
673
|
-
}
|
|
674
|
-
callback(next, previous);
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
function createStaticSignal(value) {
|
|
678
|
-
return {
|
|
679
|
-
get() {
|
|
680
|
-
return value;
|
|
681
|
-
},
|
|
682
|
-
watch(callback, options = {}) {
|
|
683
|
-
if (!options.lazy) {
|
|
684
|
-
callback(value);
|
|
685
|
-
}
|
|
686
|
-
return function stop() {
|
|
687
|
-
};
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
function createSignal(initialValue, options) {
|
|
692
|
-
let currentValue = initialValue;
|
|
693
|
-
let watchers = [];
|
|
694
|
-
function notify() {
|
|
695
|
-
for (const watcher of watchers) {
|
|
696
|
-
watcher(currentValue);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
function equal(next, previous) {
|
|
700
|
-
if (options?.equality) {
|
|
701
|
-
return options.equality(next, previous);
|
|
702
|
-
} else {
|
|
703
|
-
return deepEqual(next, previous);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
const $value = {
|
|
707
|
-
get() {
|
|
708
|
-
return designalify(currentValue);
|
|
709
|
-
},
|
|
710
|
-
watch(callback, options2) {
|
|
711
|
-
watchers.push(callback);
|
|
712
|
-
if (!options2?.lazy) {
|
|
713
|
-
callback($value.get());
|
|
714
|
-
}
|
|
715
|
-
return function stop() {
|
|
716
|
-
watchers.splice(watchers.indexOf(callback), 1);
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
};
|
|
720
|
-
function setValue(next) {
|
|
721
|
-
let value;
|
|
722
|
-
if (typeof next === "function") {
|
|
723
|
-
value = next(currentValue);
|
|
724
|
-
} else {
|
|
725
|
-
value = next;
|
|
726
|
-
}
|
|
727
|
-
if (!equal(value, currentValue)) {
|
|
728
|
-
currentValue = value;
|
|
729
|
-
notify();
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
return [$value, setValue];
|
|
733
|
-
}
|
|
734
|
-
var EMPTY = Symbol("EMPTY");
|
|
735
|
-
function derive(signals, fn, options) {
|
|
736
|
-
signals = signals.map((s) => {
|
|
737
|
-
if (isSignal(s)) {
|
|
738
|
-
return s;
|
|
739
|
-
} else {
|
|
740
|
-
return createStaticSignal(s);
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
let previousSourceValues = new Array(signals.length).fill(EMPTY, 0, signals.length);
|
|
744
|
-
let currentValue;
|
|
745
|
-
let watchers = [];
|
|
746
|
-
let watching = false;
|
|
747
|
-
let stoppers = [];
|
|
748
|
-
let stopWatchingCurrentValue;
|
|
749
|
-
let rawCurrentValue;
|
|
750
|
-
function notify(value = getCurrentValue()) {
|
|
751
|
-
for (const watcher of watchers) {
|
|
752
|
-
watcher(value);
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
function equal(next, previous) {
|
|
756
|
-
if (options?.equality) {
|
|
757
|
-
return options.equality(next, previous);
|
|
758
|
-
} else {
|
|
759
|
-
return deepEqual(next, previous);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
function update() {
|
|
763
|
-
const sourceValues = signals.map((s) => s.get());
|
|
764
|
-
for (let i = 0; i < signals.length; i++) {
|
|
765
|
-
if (!equal(sourceValues[i], previousSourceValues[i])) {
|
|
766
|
-
setCurrentValue(fn(...sourceValues));
|
|
767
|
-
previousSourceValues = sourceValues;
|
|
768
|
-
break;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
function getCurrentValue() {
|
|
773
|
-
if (!watching) {
|
|
774
|
-
update();
|
|
775
|
-
}
|
|
776
|
-
rawCurrentValue = designalify(currentValue);
|
|
777
|
-
return rawCurrentValue;
|
|
778
|
-
}
|
|
779
|
-
function setCurrentValue(value) {
|
|
780
|
-
if (value === currentValue) {
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
if (stopWatchingCurrentValue) {
|
|
784
|
-
stopWatchingCurrentValue();
|
|
785
|
-
stopWatchingCurrentValue = void 0;
|
|
786
|
-
}
|
|
787
|
-
currentValue = value;
|
|
788
|
-
rawCurrentValue = designalify(value);
|
|
789
|
-
if (isSignal(value)) {
|
|
790
|
-
if (watching) {
|
|
791
|
-
stopWatchingCurrentValue = value.watch((current) => {
|
|
792
|
-
const raw = designalify(current);
|
|
793
|
-
if (!equal(raw, rawCurrentValue)) {
|
|
794
|
-
rawCurrentValue = raw;
|
|
795
|
-
notify(raw);
|
|
796
|
-
}
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
function startWatchingSources() {
|
|
802
|
-
let startingSourceValues = [...previousSourceValues];
|
|
803
|
-
for (let i = 0; i < signals.length; i++) {
|
|
804
|
-
const signal2 = signals[i];
|
|
805
|
-
stoppers.push(
|
|
806
|
-
signal2.watch((next) => {
|
|
807
|
-
const previous = previousSourceValues[i];
|
|
808
|
-
previousSourceValues[i] = next;
|
|
809
|
-
if (watching && !equal(next, previous)) {
|
|
810
|
-
setCurrentValue(fn(...previousSourceValues));
|
|
811
|
-
notify(designalify(currentValue));
|
|
812
|
-
}
|
|
813
|
-
})
|
|
814
|
-
);
|
|
815
|
-
}
|
|
816
|
-
watching = true;
|
|
817
|
-
for (let i = 0; i < signals.length; i++) {
|
|
818
|
-
if (!equal(previousSourceValues[i], startingSourceValues[i])) {
|
|
819
|
-
setCurrentValue(fn(...previousSourceValues));
|
|
820
|
-
notify(designalify(currentValue));
|
|
821
|
-
break;
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
function stopWatchingSources() {
|
|
826
|
-
for (const stop of stoppers) {
|
|
827
|
-
stop();
|
|
828
|
-
}
|
|
829
|
-
stoppers = [];
|
|
830
|
-
if (stopWatchingCurrentValue) {
|
|
831
|
-
stopWatchingCurrentValue();
|
|
832
|
-
stopWatchingCurrentValue = void 0;
|
|
833
|
-
}
|
|
834
|
-
watching = false;
|
|
835
|
-
}
|
|
836
|
-
const $value = {
|
|
837
|
-
get() {
|
|
838
|
-
return getCurrentValue();
|
|
839
|
-
},
|
|
840
|
-
watch(callback, options2) {
|
|
841
|
-
if (!watching) {
|
|
842
|
-
startWatchingSources();
|
|
843
|
-
}
|
|
844
|
-
watchers.push(callback);
|
|
845
|
-
if (!options2?.lazy) {
|
|
846
|
-
callback(getCurrentValue());
|
|
847
|
-
}
|
|
848
|
-
return function stop() {
|
|
849
|
-
watchers.splice(watchers.indexOf(callback), 1);
|
|
850
|
-
if (watching && watchers.length === 0) {
|
|
851
|
-
stopWatchingSources();
|
|
852
|
-
}
|
|
853
|
-
};
|
|
854
|
-
}
|
|
855
|
-
};
|
|
856
|
-
return $value;
|
|
857
|
-
}
|
|
858
|
-
function watch(signals, fn) {
|
|
859
|
-
if (signals.length === 0) {
|
|
860
|
-
throw new TypeError(`Expected at least one signal.`);
|
|
861
|
-
}
|
|
862
|
-
if (signals.some((s) => !isSignal(s))) {
|
|
863
|
-
throw new TypeError(`All values must be signals`);
|
|
864
|
-
}
|
|
865
|
-
signals = signals.map((s) => {
|
|
866
|
-
if (isSignal(s)) {
|
|
867
|
-
return s;
|
|
868
|
-
} else {
|
|
869
|
-
return createStaticSignal(s);
|
|
870
|
-
}
|
|
871
|
-
});
|
|
872
|
-
if (signals.length > 1) {
|
|
873
|
-
return derive(signals, fn).watch(() => null);
|
|
874
|
-
} else {
|
|
875
|
-
return signals[0].watch(fn);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
// src/nodes/html.ts
|
|
880
|
-
var isCamelCaseEventName = (key) => /^on[A-Z]/.test(key);
|
|
881
|
-
var HTML = class {
|
|
882
|
-
node;
|
|
883
|
-
props;
|
|
884
|
-
children;
|
|
885
|
-
stopCallbacks = [];
|
|
886
|
-
appContext;
|
|
887
|
-
elementContext;
|
|
888
|
-
uniqueId = nanoid();
|
|
889
|
-
// Prevents 'onClickOutside' handlers from firing in the same cycle in which the element is connected.
|
|
890
|
-
canClickAway = false;
|
|
891
|
-
get connected() {
|
|
892
|
-
return this.node.parentNode != null;
|
|
893
|
-
}
|
|
894
|
-
constructor({ tag, props, children, appContext, elementContext }) {
|
|
895
|
-
elementContext = { ...elementContext };
|
|
896
|
-
if (tag.toLowerCase() === "svg") {
|
|
897
|
-
elementContext.isSVG = true;
|
|
898
|
-
}
|
|
899
|
-
if (elementContext.isSVG) {
|
|
900
|
-
this.node = document.createElementNS("http://www.w3.org/2000/svg", tag);
|
|
901
|
-
} else {
|
|
902
|
-
this.node = document.createElement(tag);
|
|
903
|
-
}
|
|
904
|
-
if (appContext.mode === "development") {
|
|
905
|
-
this.node.dataset.uniqueId = this.uniqueId;
|
|
906
|
-
}
|
|
907
|
-
if (props.ref) {
|
|
908
|
-
if (isRef(props.ref)) {
|
|
909
|
-
props.ref.node = this.node;
|
|
910
|
-
} else {
|
|
911
|
-
throw new Error("Expected ref to be a Ref object. Got: " + props.ref);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
this.props = {
|
|
915
|
-
...omit(["ref", "class", "className"], props),
|
|
916
|
-
class: props.className ?? props.class
|
|
917
|
-
};
|
|
918
|
-
this.children = children ? renderMarkupToDOM(children, { appContext, elementContext }) : [];
|
|
919
|
-
this.appContext = appContext;
|
|
920
|
-
this.elementContext = elementContext;
|
|
921
|
-
}
|
|
922
|
-
connect(parent2, after) {
|
|
923
|
-
if (parent2 == null) {
|
|
924
|
-
throw new Error(`HTML element requires a parent element as the first argument to connect. Got: ${parent2}`);
|
|
925
|
-
}
|
|
926
|
-
if (!this.connected) {
|
|
927
|
-
for (const child of this.children) {
|
|
928
|
-
child.connect(this.node);
|
|
929
|
-
}
|
|
930
|
-
this.applyProps(this.node, this.props);
|
|
931
|
-
if (this.props.style)
|
|
932
|
-
this.applyStyles(this.node, this.props.style, this.stopCallbacks);
|
|
933
|
-
if (this.props.class)
|
|
934
|
-
this.applyClasses(this.node, this.props.class, this.stopCallbacks);
|
|
935
|
-
}
|
|
936
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
937
|
-
setTimeout(() => {
|
|
938
|
-
this.canClickAway = true;
|
|
939
|
-
}, 0);
|
|
940
|
-
}
|
|
941
|
-
disconnect() {
|
|
942
|
-
if (this.connected) {
|
|
943
|
-
for (const child of this.children) {
|
|
944
|
-
child.disconnect();
|
|
945
|
-
}
|
|
946
|
-
this.node.parentNode?.removeChild(this.node);
|
|
947
|
-
this.canClickAway = false;
|
|
948
|
-
for (const stop of this.stopCallbacks) {
|
|
949
|
-
stop();
|
|
950
|
-
}
|
|
951
|
-
this.stopCallbacks = [];
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
setChildren(next) {
|
|
955
|
-
const current = this.children;
|
|
956
|
-
const patched = [];
|
|
957
|
-
const length = Math.max(current.length, next.length);
|
|
958
|
-
for (let i = 0; i < length; i++) {
|
|
959
|
-
if (!current[i] && next[i]) {
|
|
960
|
-
patched[i] = next[i];
|
|
961
|
-
patched[i].connect(this.node, patched[i - 1]?.node);
|
|
962
|
-
} else if (current[i] && !next[i]) {
|
|
963
|
-
current[i].disconnect();
|
|
964
|
-
} else if (current[i] != next[i]) {
|
|
965
|
-
patched[i] = next[i];
|
|
966
|
-
current[i].disconnect();
|
|
967
|
-
patched[i].connect(this.node, patched[i - 1]?.node);
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
this.children = patched;
|
|
971
|
-
}
|
|
972
|
-
getUpdateKey(type, value) {
|
|
973
|
-
return `${this.uniqueId}:${type}:${value}`;
|
|
974
|
-
}
|
|
975
|
-
applyProps(element, props) {
|
|
976
|
-
const render = this.appContext.stores.get("render").instance?.exports;
|
|
977
|
-
const attachProp = (value, callback, updateKey) => {
|
|
978
|
-
if (isSignal(value)) {
|
|
979
|
-
this.stopCallbacks.push(
|
|
980
|
-
value.watch((current) => {
|
|
981
|
-
render.update(() => {
|
|
982
|
-
callback(current);
|
|
983
|
-
}, updateKey);
|
|
984
|
-
})
|
|
985
|
-
);
|
|
986
|
-
} else {
|
|
987
|
-
render.update(() => {
|
|
988
|
-
callback(value);
|
|
989
|
-
}, updateKey);
|
|
990
|
-
}
|
|
991
|
-
};
|
|
992
|
-
for (const key in props) {
|
|
993
|
-
const value = props[key];
|
|
994
|
-
if (key === "attributes") {
|
|
995
|
-
const values = value;
|
|
996
|
-
for (const name in values) {
|
|
997
|
-
attachProp(
|
|
998
|
-
values[name],
|
|
999
|
-
(current) => {
|
|
1000
|
-
if (current == null) {
|
|
1001
|
-
element.removeAttribute(name);
|
|
1002
|
-
} else {
|
|
1003
|
-
element.setAttribute(name, String(current));
|
|
1004
|
-
}
|
|
1005
|
-
},
|
|
1006
|
-
this.getUpdateKey("attr", name)
|
|
1007
|
-
);
|
|
1008
|
-
}
|
|
1009
|
-
} else if (key === "eventListeners") {
|
|
1010
|
-
const values = value;
|
|
1011
|
-
for (const name in values) {
|
|
1012
|
-
const listener = isSignal(value) ? (e) => value.get()(e) : value;
|
|
1013
|
-
element.addEventListener(name, listener);
|
|
1014
|
-
this.stopCallbacks.push(() => {
|
|
1015
|
-
element.removeEventListener(name, listener);
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
} else if (key === "onClickOutside" || key === "onclickoutside") {
|
|
1019
|
-
const listener = (e) => {
|
|
1020
|
-
if (this.canClickAway && !element.contains(e.target)) {
|
|
1021
|
-
if (isSignal(value)) {
|
|
1022
|
-
value.get()(e);
|
|
1023
|
-
} else {
|
|
1024
|
-
value(e);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
};
|
|
1028
|
-
const options = { capture: true };
|
|
1029
|
-
window.addEventListener("click", listener, options);
|
|
1030
|
-
this.stopCallbacks.push(() => {
|
|
1031
|
-
window.removeEventListener("click", listener, options);
|
|
1032
|
-
});
|
|
1033
|
-
} else if (key === "$$value") {
|
|
1034
|
-
if (!isSettableSignal(value)) {
|
|
1035
|
-
throw new TypeError(`$$value attribute must be a settable signal. Got: ${value}`);
|
|
1036
|
-
}
|
|
1037
|
-
attachProp(
|
|
1038
|
-
value,
|
|
1039
|
-
(current) => {
|
|
1040
|
-
element.value = String(current);
|
|
1041
|
-
},
|
|
1042
|
-
this.getUpdateKey("attr", "value")
|
|
1043
|
-
);
|
|
1044
|
-
const listener = (e) => {
|
|
1045
|
-
const updated = toTypeOf(value.get(), e.currentTarget.value);
|
|
1046
|
-
value.set(updated);
|
|
1047
|
-
};
|
|
1048
|
-
element.addEventListener("input", listener);
|
|
1049
|
-
this.stopCallbacks.push(() => {
|
|
1050
|
-
element.removeEventListener("input", listener);
|
|
1051
|
-
});
|
|
1052
|
-
} else if (isCamelCaseEventName(key)) {
|
|
1053
|
-
const eventName = key.slice(2).toLowerCase();
|
|
1054
|
-
const listener = isSignal(value) ? (e) => value.get()(e) : value;
|
|
1055
|
-
element.addEventListener(eventName, listener);
|
|
1056
|
-
this.stopCallbacks.push(() => {
|
|
1057
|
-
element.removeEventListener(eventName, listener);
|
|
1058
|
-
});
|
|
1059
|
-
} else if (key.includes("-")) {
|
|
1060
|
-
attachProp(
|
|
1061
|
-
value,
|
|
1062
|
-
(current) => {
|
|
1063
|
-
if (current == null) {
|
|
1064
|
-
element.removeAttribute(key);
|
|
1065
|
-
} else {
|
|
1066
|
-
element.setAttribute(key, String(current));
|
|
1067
|
-
}
|
|
1068
|
-
},
|
|
1069
|
-
this.getUpdateKey("attr", key)
|
|
1070
|
-
);
|
|
1071
|
-
} else if (!privateProps.includes(key)) {
|
|
1072
|
-
if (this.elementContext.isSVG) {
|
|
1073
|
-
attachProp(
|
|
1074
|
-
value,
|
|
1075
|
-
(current) => {
|
|
1076
|
-
if (current != null) {
|
|
1077
|
-
element.setAttribute(key, String(props[key]));
|
|
1078
|
-
} else {
|
|
1079
|
-
element.removeAttribute(key);
|
|
1080
|
-
}
|
|
1081
|
-
},
|
|
1082
|
-
this.getUpdateKey("attr", key)
|
|
1083
|
-
);
|
|
1084
|
-
} else {
|
|
1085
|
-
switch (key) {
|
|
1086
|
-
case "contentEditable":
|
|
1087
|
-
case "value":
|
|
1088
|
-
attachProp(
|
|
1089
|
-
value,
|
|
1090
|
-
(current) => {
|
|
1091
|
-
element[key] = String(current);
|
|
1092
|
-
},
|
|
1093
|
-
this.getUpdateKey("prop", key)
|
|
1094
|
-
);
|
|
1095
|
-
break;
|
|
1096
|
-
case "for":
|
|
1097
|
-
attachProp(
|
|
1098
|
-
value,
|
|
1099
|
-
(current) => {
|
|
1100
|
-
element.htmlFor = current;
|
|
1101
|
-
},
|
|
1102
|
-
this.getUpdateKey("prop", "htmlFor")
|
|
1103
|
-
);
|
|
1104
|
-
break;
|
|
1105
|
-
case "checked":
|
|
1106
|
-
attachProp(
|
|
1107
|
-
value,
|
|
1108
|
-
(current) => {
|
|
1109
|
-
element.checked = current;
|
|
1110
|
-
if (current) {
|
|
1111
|
-
element.setAttribute("checked", "");
|
|
1112
|
-
} else {
|
|
1113
|
-
element.removeAttribute("checked");
|
|
1114
|
-
}
|
|
1115
|
-
},
|
|
1116
|
-
this.getUpdateKey("prop", "checked")
|
|
1117
|
-
);
|
|
1118
|
-
break;
|
|
1119
|
-
case "exportParts":
|
|
1120
|
-
case "part":
|
|
1121
|
-
case "translate":
|
|
1122
|
-
case "title": {
|
|
1123
|
-
const _key = key.toLowerCase();
|
|
1124
|
-
attachProp(
|
|
1125
|
-
value,
|
|
1126
|
-
(current) => {
|
|
1127
|
-
if (current == void 0) {
|
|
1128
|
-
element.removeAttribute(_key);
|
|
1129
|
-
} else {
|
|
1130
|
-
element.setAttribute(_key, String(current));
|
|
1131
|
-
}
|
|
1132
|
-
},
|
|
1133
|
-
this.getUpdateKey("attr", _key)
|
|
1134
|
-
);
|
|
1135
|
-
break;
|
|
1136
|
-
}
|
|
1137
|
-
case "autocomplete":
|
|
1138
|
-
case "autocapitalize":
|
|
1139
|
-
attachProp(
|
|
1140
|
-
value,
|
|
1141
|
-
(current) => {
|
|
1142
|
-
if (typeof current === "string") {
|
|
1143
|
-
element.autocomplete = current;
|
|
1144
|
-
} else if (current) {
|
|
1145
|
-
element.autocomplete = "on";
|
|
1146
|
-
} else {
|
|
1147
|
-
element.autocomplete = "off";
|
|
1148
|
-
}
|
|
1149
|
-
},
|
|
1150
|
-
this.getUpdateKey("prop", key)
|
|
1151
|
-
);
|
|
1152
|
-
break;
|
|
1153
|
-
default: {
|
|
1154
|
-
attachProp(
|
|
1155
|
-
value,
|
|
1156
|
-
(current) => {
|
|
1157
|
-
element[key] = current;
|
|
1158
|
-
},
|
|
1159
|
-
this.getUpdateKey("prop", key)
|
|
1160
|
-
);
|
|
1161
|
-
break;
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
applyStyles(element, styles, stopCallbacks) {
|
|
1169
|
-
const render = this.appContext.stores.get("render").instance?.exports;
|
|
1170
|
-
const propStopCallbacks = [];
|
|
1171
|
-
if (styles == void 0) {
|
|
1172
|
-
element.style.cssText = "";
|
|
1173
|
-
} else if (typeof styles === "string") {
|
|
1174
|
-
element.style.cssText = styles;
|
|
1175
|
-
} else if (isSignal(styles)) {
|
|
1176
|
-
let unapply;
|
|
1177
|
-
const stop = styles.watch((current) => {
|
|
1178
|
-
render.update(
|
|
1179
|
-
() => {
|
|
1180
|
-
if (isFunction(unapply)) {
|
|
1181
|
-
unapply();
|
|
1182
|
-
}
|
|
1183
|
-
element.style.cssText = "";
|
|
1184
|
-
unapply = this.applyStyles(element, current, stopCallbacks);
|
|
1185
|
-
},
|
|
1186
|
-
this.getUpdateKey("styles", "*")
|
|
1187
|
-
);
|
|
1188
|
-
});
|
|
1189
|
-
stopCallbacks.push(stop);
|
|
1190
|
-
propStopCallbacks.push(stop);
|
|
1191
|
-
} else if (isObject(styles)) {
|
|
1192
|
-
styles = styles;
|
|
1193
|
-
for (const key in styles) {
|
|
1194
|
-
const value = styles[key];
|
|
1195
|
-
const setProperty = key.startsWith("--") ? (key2, value2) => value2 == null ? element.style.removeProperty(key2) : element.style.setProperty(key2, value2) : (key2, value2) => element.style[key2] = value2 ?? "";
|
|
1196
|
-
if (isSignal(value)) {
|
|
1197
|
-
const stop = value.watch((current) => {
|
|
1198
|
-
render.update(
|
|
1199
|
-
() => {
|
|
1200
|
-
if (current != null) {
|
|
1201
|
-
setProperty(key, current);
|
|
1202
|
-
} else {
|
|
1203
|
-
element.style.removeProperty(key);
|
|
1204
|
-
}
|
|
1205
|
-
},
|
|
1206
|
-
this.getUpdateKey("style", key)
|
|
1207
|
-
);
|
|
1208
|
-
});
|
|
1209
|
-
stopCallbacks.push(stop);
|
|
1210
|
-
propStopCallbacks.push(stop);
|
|
1211
|
-
} else if (isString(value)) {
|
|
1212
|
-
setProperty(key, value);
|
|
1213
|
-
} else if (isNumber(value)) {
|
|
1214
|
-
setProperty(key, String(value));
|
|
1215
|
-
} else {
|
|
1216
|
-
throw new TypeError(`Style properties should be strings, $states or numbers. Got (${key}: ${value})`);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
} else {
|
|
1220
|
-
throw new TypeError(`Expected style property to be a string, $state, or object. Got: ${styles}`);
|
|
1221
|
-
}
|
|
1222
|
-
return function unapply() {
|
|
1223
|
-
for (const stop of propStopCallbacks) {
|
|
1224
|
-
stop();
|
|
1225
|
-
stopCallbacks.splice(stopCallbacks.indexOf(stop), 1);
|
|
1226
|
-
}
|
|
1227
|
-
};
|
|
1228
|
-
}
|
|
1229
|
-
applyClasses(element, classes, stopCallbacks) {
|
|
1230
|
-
const render = this.appContext.stores.get("render").instance?.exports;
|
|
1231
|
-
const classStopCallbacks = [];
|
|
1232
|
-
if (isSignal(classes)) {
|
|
1233
|
-
let unapply;
|
|
1234
|
-
const stop = classes.watch((current) => {
|
|
1235
|
-
render.update(
|
|
1236
|
-
() => {
|
|
1237
|
-
if (isFunction(unapply)) {
|
|
1238
|
-
unapply();
|
|
1239
|
-
}
|
|
1240
|
-
element.removeAttribute("class");
|
|
1241
|
-
unapply = this.applyClasses(element, current, stopCallbacks);
|
|
1242
|
-
},
|
|
1243
|
-
this.getUpdateKey("attr", "class")
|
|
1244
|
-
);
|
|
1245
|
-
});
|
|
1246
|
-
stopCallbacks.push(stop);
|
|
1247
|
-
classStopCallbacks.push(stop);
|
|
1248
|
-
} else {
|
|
1249
|
-
const mapped = getClassMap(classes);
|
|
1250
|
-
for (const name in mapped) {
|
|
1251
|
-
const value = mapped[name];
|
|
1252
|
-
if (isSignal(value)) {
|
|
1253
|
-
const stop = value.watch((current) => {
|
|
1254
|
-
render.update(() => {
|
|
1255
|
-
if (current) {
|
|
1256
|
-
element.classList.add(name);
|
|
1257
|
-
} else {
|
|
1258
|
-
element.classList.remove(name);
|
|
1259
|
-
}
|
|
1260
|
-
});
|
|
1261
|
-
});
|
|
1262
|
-
stopCallbacks.push(stop);
|
|
1263
|
-
classStopCallbacks.push(stop);
|
|
1264
|
-
} else if (value) {
|
|
1265
|
-
element.classList.add(name);
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
|
-
return function unapply() {
|
|
1270
|
-
for (const stop of classStopCallbacks) {
|
|
1271
|
-
stop();
|
|
1272
|
-
stopCallbacks.splice(stopCallbacks.indexOf(stop), 1);
|
|
1273
|
-
}
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1276
|
-
};
|
|
1277
|
-
function getClassMap(classes) {
|
|
1278
|
-
let mapped = {};
|
|
1279
|
-
if (isString(classes)) {
|
|
1280
|
-
const names = classes.split(" ");
|
|
1281
|
-
for (const name of names) {
|
|
1282
|
-
mapped[name] = true;
|
|
1283
|
-
}
|
|
1284
|
-
} else if (isObject(classes)) {
|
|
1285
|
-
Object.assign(mapped, classes);
|
|
1286
|
-
} else if (Array.isArray(classes)) {
|
|
1287
|
-
Array.from(classes).filter((item) => item != null).forEach((item) => {
|
|
1288
|
-
Object.assign(mapped, getClassMap(item));
|
|
1289
|
-
});
|
|
1290
|
-
}
|
|
1291
|
-
return mapped;
|
|
1292
|
-
}
|
|
1293
|
-
function toTypeOf(target, source) {
|
|
1294
|
-
const type = typeof target;
|
|
1295
|
-
if (type === "string") {
|
|
1296
|
-
return String(source);
|
|
1297
|
-
}
|
|
1298
|
-
if (type === "number") {
|
|
1299
|
-
return Number(source);
|
|
1300
|
-
}
|
|
1301
|
-
if (type === "boolean") {
|
|
1302
|
-
return Boolean(source);
|
|
1303
|
-
}
|
|
1304
|
-
return source;
|
|
1305
|
-
}
|
|
1306
|
-
var privateProps = ["ref", "children", "class", "style", "data"];
|
|
1307
|
-
|
|
1308
|
-
// src/nodes/observer.ts
|
|
1309
|
-
var Observer = class {
|
|
1310
|
-
node;
|
|
1311
|
-
endNode;
|
|
1312
|
-
connectedViews = [];
|
|
1313
|
-
renderFn;
|
|
1314
|
-
appContext;
|
|
1315
|
-
elementContext;
|
|
1316
|
-
observerControls;
|
|
1317
|
-
get connected() {
|
|
1318
|
-
return this.node.parentNode != null;
|
|
1319
|
-
}
|
|
1320
|
-
constructor({ signals, renderFn, appContext, elementContext }) {
|
|
1321
|
-
this.appContext = appContext;
|
|
1322
|
-
this.elementContext = elementContext;
|
|
1323
|
-
this.renderFn = renderFn;
|
|
1324
|
-
this.node = document.createComment("Observer");
|
|
1325
|
-
this.endNode = document.createComment("/Observer");
|
|
1326
|
-
let _stop;
|
|
1327
|
-
this.observerControls = {
|
|
1328
|
-
start: () => {
|
|
1329
|
-
if (_stop != null)
|
|
1330
|
-
return;
|
|
1331
|
-
_stop = watch(signals, (...values) => {
|
|
1332
|
-
const rendered = this.renderFn(...values);
|
|
1333
|
-
if (!isRenderable(rendered)) {
|
|
1334
|
-
console.error(rendered);
|
|
1335
|
-
throw new TypeError(
|
|
1336
|
-
`Observer received invalid value to render. Got type: ${typeOf(rendered)}, value: ${rendered}`
|
|
1337
|
-
);
|
|
1338
|
-
}
|
|
1339
|
-
if (Array.isArray(rendered)) {
|
|
1340
|
-
this.update(...rendered);
|
|
1341
|
-
} else {
|
|
1342
|
-
this.update(rendered);
|
|
1343
|
-
}
|
|
1344
|
-
});
|
|
1345
|
-
},
|
|
1346
|
-
stop: () => {
|
|
1347
|
-
if (_stop == null)
|
|
1348
|
-
return;
|
|
1349
|
-
_stop();
|
|
1350
|
-
_stop = void 0;
|
|
1351
|
-
}
|
|
1352
|
-
};
|
|
1353
|
-
}
|
|
1354
|
-
connect(parent2, after) {
|
|
1355
|
-
if (!this.connected) {
|
|
1356
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1357
|
-
this.observerControls.start();
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
disconnect() {
|
|
1361
|
-
this.observerControls.stop();
|
|
1362
|
-
if (this.connected) {
|
|
1363
|
-
this.cleanup();
|
|
1364
|
-
this.node.parentNode?.removeChild(this.node);
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
async setChildren() {
|
|
1368
|
-
console.warn("setChildren is not implemented for Dynamic");
|
|
1369
|
-
}
|
|
1370
|
-
cleanup() {
|
|
1371
|
-
while (this.connectedViews.length > 0) {
|
|
1372
|
-
this.connectedViews.pop()?.disconnect();
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
update(...children) {
|
|
1376
|
-
this.cleanup();
|
|
1377
|
-
if (children == null || !this.connected) {
|
|
1378
|
-
return;
|
|
1379
|
-
}
|
|
1380
|
-
const handles = children.map((c) => {
|
|
1381
|
-
if (isDOMHandle(c)) {
|
|
1382
|
-
return c;
|
|
1383
|
-
} else if (isMarkup(c)) {
|
|
1384
|
-
return getRenderHandle(renderMarkupToDOM(c, this));
|
|
1385
|
-
} else {
|
|
1386
|
-
return getRenderHandle(renderMarkupToDOM(toMarkup(c), this));
|
|
1387
|
-
}
|
|
1388
|
-
});
|
|
1389
|
-
for (const handle of handles) {
|
|
1390
|
-
const previous = this.connectedViews.at(-1)?.node || this.node;
|
|
1391
|
-
handle.connect(this.node.parentNode, previous);
|
|
1392
|
-
this.connectedViews.push(handle);
|
|
1393
|
-
}
|
|
1394
|
-
if (this.appContext.mode === "development") {
|
|
1395
|
-
const lastNode = this.connectedViews.at(-1)?.node;
|
|
1396
|
-
if (this.endNode.previousSibling !== lastNode) {
|
|
1397
|
-
this.node.parentNode.insertBefore(this.endNode, lastNode?.nextSibling ?? null);
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
};
|
|
1402
|
-
|
|
1403
|
-
// src/nodes/outlet.ts
|
|
1404
|
-
var Outlet = class {
|
|
1405
|
-
node;
|
|
1406
|
-
endNode;
|
|
1407
|
-
$children;
|
|
1408
|
-
stopCallback;
|
|
1409
|
-
connectedChildren = [];
|
|
1410
|
-
appContext;
|
|
1411
|
-
elementContext;
|
|
1412
|
-
constructor(config) {
|
|
1413
|
-
this.$children = config.$children;
|
|
1414
|
-
this.appContext = config.appContext;
|
|
1415
|
-
this.elementContext = config.elementContext;
|
|
1416
|
-
if (this.appContext.mode === "development") {
|
|
1417
|
-
this.node = document.createComment("Outlet");
|
|
1418
|
-
this.endNode = document.createComment("/Outlet");
|
|
1419
|
-
} else {
|
|
1420
|
-
this.node = document.createTextNode("");
|
|
1421
|
-
this.endNode = document.createTextNode("");
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
get connected() {
|
|
1425
|
-
return this.node?.parentNode != null;
|
|
1426
|
-
}
|
|
1427
|
-
connect(parent2, after) {
|
|
1428
|
-
if (!this.connected) {
|
|
1429
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1430
|
-
this.stopCallback = this.$children.watch((children) => {
|
|
1431
|
-
this.update(children);
|
|
1432
|
-
});
|
|
1433
|
-
}
|
|
1434
|
-
}
|
|
1435
|
-
disconnect() {
|
|
1436
|
-
if (this.stopCallback) {
|
|
1437
|
-
this.stopCallback();
|
|
1438
|
-
this.stopCallback = void 0;
|
|
1439
|
-
}
|
|
1440
|
-
if (this.connected) {
|
|
1441
|
-
for (const child of this.connectedChildren) {
|
|
1442
|
-
child.disconnect();
|
|
1443
|
-
}
|
|
1444
|
-
this.connectedChildren = [];
|
|
1445
|
-
this.endNode.parentNode?.removeChild(this.endNode);
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
update(newChildren) {
|
|
1449
|
-
for (const child of this.connectedChildren) {
|
|
1450
|
-
child.disconnect();
|
|
1451
|
-
}
|
|
1452
|
-
for (let i = 0; i < newChildren.length; i++) {
|
|
1453
|
-
const child = newChildren[i];
|
|
1454
|
-
const previous = i > 0 ? newChildren[i] : void 0;
|
|
1455
|
-
child.connect(this.node.parentElement, previous?.node);
|
|
1456
|
-
}
|
|
1457
|
-
this.connectedChildren = newChildren;
|
|
1458
|
-
if (this.appContext.mode === "development") {
|
|
1459
|
-
this.node.textContent = `Outlet (${newChildren.length} ${newChildren.length === 1 ? "child" : "children"})`;
|
|
1460
|
-
this.node.parentElement?.insertBefore(
|
|
1461
|
-
this.endNode,
|
|
1462
|
-
this.connectedChildren[this.connectedChildren.length - 1]?.node?.nextSibling ?? null
|
|
1463
|
-
);
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
setChildren(children) {
|
|
1467
|
-
throw new Error(`setChildren is not supported on Outlet`);
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
|
|
1471
|
-
// src/nodes/portal.ts
|
|
1472
|
-
var Portal = class {
|
|
1473
|
-
config;
|
|
1474
|
-
handle;
|
|
1475
|
-
get connected() {
|
|
1476
|
-
if (!this.handle) {
|
|
1477
|
-
return false;
|
|
1478
|
-
}
|
|
1479
|
-
return this.handle.connected;
|
|
1480
|
-
}
|
|
1481
|
-
constructor(config) {
|
|
1482
|
-
this.config = config;
|
|
1483
|
-
}
|
|
1484
|
-
connect(_parent, _after) {
|
|
1485
|
-
const { content, parent: parent2 } = this.config;
|
|
1486
|
-
if (isDOMHandle(content)) {
|
|
1487
|
-
this.handle = content;
|
|
1488
|
-
} else if (isMarkup(content)) {
|
|
1489
|
-
this.handle = getRenderHandle(renderMarkupToDOM(content, this.config));
|
|
1490
|
-
} else {
|
|
1491
|
-
this.handle = getRenderHandle(renderMarkupToDOM(toMarkup(content), this.config));
|
|
1492
|
-
}
|
|
1493
|
-
this.handle.connect(parent2);
|
|
1494
|
-
}
|
|
1495
|
-
disconnect() {
|
|
1496
|
-
if (this.handle?.connected) {
|
|
1497
|
-
this.handle.disconnect();
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
setChildren(children) {
|
|
1501
|
-
this.handle?.setChildren(children);
|
|
1502
|
-
}
|
|
1503
|
-
};
|
|
1504
|
-
|
|
1505
|
-
// src/view.ts
|
|
1506
|
-
var SECRETS = Symbol("VIEW_SECRETS");
|
|
1507
|
-
function getViewSecrets(ctx) {
|
|
1508
|
-
return ctx[SECRETS];
|
|
1509
|
-
}
|
|
1510
|
-
function initView(config) {
|
|
1511
|
-
const appContext = config.appContext;
|
|
1512
|
-
const elementContext = {
|
|
1513
|
-
...config.elementContext,
|
|
1514
|
-
stores: /* @__PURE__ */ new Map(),
|
|
1515
|
-
parent: config.elementContext
|
|
1516
|
-
};
|
|
1517
|
-
const [$children, setChildren] = signal(
|
|
1518
|
-
renderMarkupToDOM(config.children ?? [], { appContext, elementContext })
|
|
1519
|
-
);
|
|
1520
|
-
let isConnected = false;
|
|
1521
|
-
const stopObserverCallbacks = [];
|
|
1522
|
-
const connectedCallbacks = [];
|
|
1523
|
-
const disconnectedCallbacks = [];
|
|
1524
|
-
const beforeConnectCallbacks = [];
|
|
1525
|
-
const beforeDisconnectCallbacks = [];
|
|
1526
|
-
const uniqueId = nanoid();
|
|
1527
|
-
const ctx = {
|
|
1528
|
-
get uid() {
|
|
1529
|
-
return uniqueId;
|
|
1530
|
-
},
|
|
1531
|
-
name: config.view.name ?? "anonymous",
|
|
1532
|
-
getStore(store) {
|
|
1533
|
-
let name;
|
|
1534
|
-
if (typeof store === "string") {
|
|
1535
|
-
name = store;
|
|
1536
|
-
} else {
|
|
1537
|
-
name = store.name;
|
|
1538
|
-
}
|
|
1539
|
-
if (typeof store !== "string") {
|
|
1540
|
-
let ec = elementContext;
|
|
1541
|
-
while (ec) {
|
|
1542
|
-
if (ec.stores.has(store)) {
|
|
1543
|
-
return ec.stores.get(store)?.instance.exports;
|
|
1544
|
-
}
|
|
1545
|
-
ec = ec.parent;
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1548
|
-
if (appContext.stores.has(store)) {
|
|
1549
|
-
const _store = appContext.stores.get(store);
|
|
1550
|
-
if (!_store.instance) {
|
|
1551
|
-
appContext.crashCollector.crash({
|
|
1552
|
-
componentName: ctx.name,
|
|
1553
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
1554
|
-
});
|
|
1555
|
-
}
|
|
1556
|
-
return _store.instance.exports;
|
|
1557
|
-
}
|
|
1558
|
-
appContext.crashCollector.crash({
|
|
1559
|
-
componentName: ctx.name,
|
|
1560
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
1561
|
-
});
|
|
1562
|
-
},
|
|
1563
|
-
onConnected(callback) {
|
|
1564
|
-
connectedCallbacks.push(callback);
|
|
1565
|
-
},
|
|
1566
|
-
onDisconnected(callback) {
|
|
1567
|
-
disconnectedCallbacks.push(callback);
|
|
1568
|
-
},
|
|
1569
|
-
beforeConnect(callback) {
|
|
1570
|
-
beforeConnectCallbacks.push(callback);
|
|
1571
|
-
},
|
|
1572
|
-
beforeDisconnect(callback) {
|
|
1573
|
-
beforeDisconnectCallbacks.push(callback);
|
|
1574
|
-
},
|
|
1575
|
-
onMount(callback) {
|
|
1576
|
-
connectedCallbacks.push(callback);
|
|
1577
|
-
},
|
|
1578
|
-
onUnmount(callback) {
|
|
1579
|
-
disconnectedCallbacks.push(callback);
|
|
1580
|
-
},
|
|
1581
|
-
crash(error) {
|
|
1582
|
-
config.appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
1583
|
-
},
|
|
1584
|
-
watch(signals, callback) {
|
|
1585
|
-
if (isConnected) {
|
|
1586
|
-
const stop = watch(signals, callback);
|
|
1587
|
-
stopObserverCallbacks.push(stop);
|
|
1588
|
-
return stop;
|
|
1589
|
-
} else {
|
|
1590
|
-
let stop;
|
|
1591
|
-
let stopped = false;
|
|
1592
|
-
connectedCallbacks.push(() => {
|
|
1593
|
-
if (!stopped) {
|
|
1594
|
-
stop = watch(signals, callback);
|
|
1595
|
-
stopObserverCallbacks.push(stop);
|
|
1596
|
-
}
|
|
1597
|
-
});
|
|
1598
|
-
return function stop2() {
|
|
1599
|
-
if (stop2 != null) {
|
|
1600
|
-
stopped = true;
|
|
1601
|
-
stop2();
|
|
1602
|
-
}
|
|
1603
|
-
};
|
|
1604
|
-
}
|
|
1605
|
-
},
|
|
1606
|
-
outlet() {
|
|
1607
|
-
return m("$outlet", { $children });
|
|
1608
|
-
}
|
|
1609
|
-
};
|
|
1610
|
-
const debugChannel = appContext.debugHub.channel({
|
|
1611
|
-
get name() {
|
|
1612
|
-
return ctx.name;
|
|
1613
|
-
},
|
|
1614
|
-
get id() {
|
|
1615
|
-
return uniqueId;
|
|
1616
|
-
}
|
|
1617
|
-
});
|
|
1618
|
-
Object.defineProperties(ctx, Object.getOwnPropertyDescriptors(debugChannel));
|
|
1619
|
-
Object.defineProperty(ctx, SECRETS, {
|
|
1620
|
-
enumerable: false,
|
|
1621
|
-
configurable: false,
|
|
1622
|
-
value: {
|
|
1623
|
-
appContext,
|
|
1624
|
-
elementContext
|
|
1625
|
-
}
|
|
1626
|
-
});
|
|
1627
|
-
let rendered;
|
|
1628
|
-
function initialize() {
|
|
1629
|
-
let result;
|
|
1630
|
-
try {
|
|
1631
|
-
result = config.view(config.props, ctx);
|
|
1632
|
-
} catch (error) {
|
|
1633
|
-
if (error instanceof Error) {
|
|
1634
|
-
appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
1635
|
-
}
|
|
1636
|
-
throw error;
|
|
1637
|
-
}
|
|
1638
|
-
if (result instanceof Promise) {
|
|
1639
|
-
appContext.crashCollector.crash({
|
|
1640
|
-
error: new TypeError(`View function cannot return a Promise.`),
|
|
1641
|
-
componentName: ctx.name
|
|
1642
|
-
});
|
|
1643
|
-
}
|
|
1644
|
-
if (result === null) {
|
|
1645
|
-
} else if (result instanceof Node) {
|
|
1646
|
-
rendered = getRenderHandle(renderMarkupToDOM(m("$node", { value: result }), { appContext, elementContext }));
|
|
1647
|
-
} else if (isMarkup(result) || isArrayOf(isMarkup, result)) {
|
|
1648
|
-
rendered = getRenderHandle(renderMarkupToDOM(result, { appContext, elementContext }));
|
|
1649
|
-
} else if (isSignal(result)) {
|
|
1650
|
-
rendered = getRenderHandle(
|
|
1651
|
-
renderMarkupToDOM(m("$observer", { signals: [result], renderFn: (x) => x }), { appContext, elementContext })
|
|
1652
|
-
);
|
|
1653
|
-
} else {
|
|
1654
|
-
console.warn(result, config);
|
|
1655
|
-
appContext.crashCollector.crash({
|
|
1656
|
-
error: new TypeError(
|
|
1657
|
-
`Expected '${config.view.name}' function to return a DOM node, Markup element, Readable or null. Got: ${typeOf(result)}`
|
|
1658
|
-
),
|
|
1659
|
-
componentName: ctx.name
|
|
1660
|
-
});
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
const handle = {
|
|
1664
|
-
get node() {
|
|
1665
|
-
return rendered?.node;
|
|
1666
|
-
},
|
|
1667
|
-
get connected() {
|
|
1668
|
-
return isConnected;
|
|
1669
|
-
},
|
|
1670
|
-
connect(parent2, after) {
|
|
1671
|
-
const wasConnected = isConnected;
|
|
1672
|
-
if (!wasConnected) {
|
|
1673
|
-
initialize();
|
|
1674
|
-
while (beforeConnectCallbacks.length > 0) {
|
|
1675
|
-
const callback = beforeConnectCallbacks.shift();
|
|
1676
|
-
callback();
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
if (rendered) {
|
|
1680
|
-
rendered.connect(parent2, after);
|
|
1681
|
-
}
|
|
1682
|
-
if (!wasConnected) {
|
|
1683
|
-
isConnected = true;
|
|
1684
|
-
requestAnimationFrame(() => {
|
|
1685
|
-
while (connectedCallbacks.length > 0) {
|
|
1686
|
-
const callback = connectedCallbacks.shift();
|
|
1687
|
-
callback();
|
|
1688
|
-
}
|
|
1689
|
-
});
|
|
1690
|
-
}
|
|
1691
|
-
},
|
|
1692
|
-
disconnect() {
|
|
1693
|
-
while (beforeDisconnectCallbacks.length > 0) {
|
|
1694
|
-
const callback = beforeDisconnectCallbacks.shift();
|
|
1695
|
-
callback();
|
|
1696
|
-
}
|
|
1697
|
-
if (rendered) {
|
|
1698
|
-
rendered.disconnect();
|
|
1699
|
-
}
|
|
1700
|
-
isConnected = false;
|
|
1701
|
-
while (disconnectedCallbacks.length > 0) {
|
|
1702
|
-
const callback = disconnectedCallbacks.shift();
|
|
1703
|
-
callback();
|
|
1704
|
-
}
|
|
1705
|
-
while (stopObserverCallbacks.length > 0) {
|
|
1706
|
-
const callback = stopObserverCallbacks.shift();
|
|
1707
|
-
callback();
|
|
1708
|
-
}
|
|
1709
|
-
},
|
|
1710
|
-
async setChildren(children) {
|
|
1711
|
-
setChildren(children);
|
|
1712
|
-
}
|
|
1713
|
-
};
|
|
1714
|
-
return handle;
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
// src/nodes/repeat.ts
|
|
1718
|
-
var Repeat = class {
|
|
1719
|
-
node;
|
|
1720
|
-
endNode;
|
|
1721
|
-
$items;
|
|
1722
|
-
stopCallback;
|
|
1723
|
-
connectedItems = [];
|
|
1724
|
-
appContext;
|
|
1725
|
-
elementContext;
|
|
1726
|
-
renderFn;
|
|
1727
|
-
keyFn;
|
|
1728
|
-
get connected() {
|
|
1729
|
-
return this.node.parentNode != null;
|
|
1730
|
-
}
|
|
1731
|
-
constructor({ appContext, elementContext, $items, renderFn, keyFn }) {
|
|
1732
|
-
this.appContext = appContext;
|
|
1733
|
-
this.elementContext = elementContext;
|
|
1734
|
-
this.$items = $items;
|
|
1735
|
-
this.renderFn = renderFn;
|
|
1736
|
-
this.keyFn = keyFn;
|
|
1737
|
-
if (appContext.mode === "development") {
|
|
1738
|
-
this.node = document.createComment("Repeat");
|
|
1739
|
-
this.endNode = document.createComment("/Repeat");
|
|
1740
|
-
} else {
|
|
1741
|
-
this.node = document.createTextNode("");
|
|
1742
|
-
this.endNode = document.createTextNode("");
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
connect(parent2, after) {
|
|
1746
|
-
if (!this.connected) {
|
|
1747
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1748
|
-
this.stopCallback = this.$items.watch((value) => {
|
|
1749
|
-
this._update(Array.from(value));
|
|
1750
|
-
});
|
|
1751
|
-
}
|
|
1752
|
-
}
|
|
1753
|
-
disconnect() {
|
|
1754
|
-
if (this.stopCallback) {
|
|
1755
|
-
this.stopCallback();
|
|
1756
|
-
this.stopCallback = void 0;
|
|
1757
|
-
}
|
|
1758
|
-
if (this.connected) {
|
|
1759
|
-
this.node.parentNode?.removeChild(this.node);
|
|
1760
|
-
this.endNode.parentNode?.removeChild(this.endNode);
|
|
1761
|
-
}
|
|
1762
|
-
this._cleanup();
|
|
1763
|
-
}
|
|
1764
|
-
setChildren() {
|
|
1765
|
-
console.warn("setChildren is not implemented for repeat()");
|
|
1766
|
-
}
|
|
1767
|
-
_cleanup() {
|
|
1768
|
-
for (const item of this.connectedItems) {
|
|
1769
|
-
item.handle.disconnect();
|
|
1770
|
-
}
|
|
1771
|
-
this.connectedItems = [];
|
|
1772
|
-
}
|
|
1773
|
-
_update(value) {
|
|
1774
|
-
if (value.length === 0 || !this.connected) {
|
|
1775
|
-
return this._cleanup();
|
|
1776
|
-
}
|
|
1777
|
-
const potentialItems = [];
|
|
1778
|
-
let index = 0;
|
|
1779
|
-
for (const item of value) {
|
|
1780
|
-
potentialItems.push({
|
|
1781
|
-
key: this.keyFn(item, index),
|
|
1782
|
-
value: item,
|
|
1783
|
-
index: index++
|
|
1784
|
-
});
|
|
1785
|
-
}
|
|
1786
|
-
const newItems = [];
|
|
1787
|
-
for (const connected of this.connectedItems) {
|
|
1788
|
-
const potentialItem = potentialItems.find((p) => p.key === connected.key);
|
|
1789
|
-
if (!potentialItem) {
|
|
1790
|
-
connected.handle.disconnect();
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
for (const potential of potentialItems) {
|
|
1794
|
-
const connected = this.connectedItems.find((item) => item.key === potential.key);
|
|
1795
|
-
if (connected) {
|
|
1796
|
-
connected.setValue(potential.value);
|
|
1797
|
-
connected.setIndex(potential.index);
|
|
1798
|
-
newItems[potential.index] = connected;
|
|
1799
|
-
} else {
|
|
1800
|
-
const [$value, setValue] = signal(potential.value);
|
|
1801
|
-
const [$index, setIndex] = signal(potential.index);
|
|
1802
|
-
newItems[potential.index] = {
|
|
1803
|
-
key: potential.key,
|
|
1804
|
-
$value,
|
|
1805
|
-
setValue,
|
|
1806
|
-
$index,
|
|
1807
|
-
setIndex,
|
|
1808
|
-
handle: initView({
|
|
1809
|
-
view: RepeatItemView,
|
|
1810
|
-
appContext: this.appContext,
|
|
1811
|
-
elementContext: this.elementContext,
|
|
1812
|
-
props: { $value, $index, renderFn: this.renderFn }
|
|
1813
|
-
})
|
|
1814
|
-
};
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
for (let i = 0; i < newItems.length; i++) {
|
|
1818
|
-
const item = newItems[i];
|
|
1819
|
-
const previous = newItems[i - 1]?.handle.node ?? this.node;
|
|
1820
|
-
item.handle.connect(this.node.parentNode, previous);
|
|
1821
|
-
}
|
|
1822
|
-
this.connectedItems = newItems;
|
|
1823
|
-
if (this.appContext.mode === "development") {
|
|
1824
|
-
this.node.textContent = `Repeat (${newItems.length} item${newItems.length === 1 ? "" : "s"})`;
|
|
1825
|
-
const lastItem = newItems.at(-1)?.handle.node ?? this.node;
|
|
1826
|
-
this.node.parentNode?.insertBefore(this.endNode, lastItem.nextSibling);
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
};
|
|
1830
|
-
function RepeatItemView({ $value, $index, renderFn }, ctx) {
|
|
1831
|
-
return renderFn($value, $index, ctx);
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
// src/nodes/text.ts
|
|
1835
|
-
var Text = class {
|
|
1836
|
-
node = document.createTextNode("");
|
|
1837
|
-
value = "";
|
|
1838
|
-
stopCallback;
|
|
1839
|
-
get connected() {
|
|
1840
|
-
return this.node.parentNode != null;
|
|
1841
|
-
}
|
|
1842
|
-
constructor({ value }) {
|
|
1843
|
-
this.value = value;
|
|
1844
|
-
}
|
|
1845
|
-
async connect(parent2, after = null) {
|
|
1846
|
-
if (!this.connected) {
|
|
1847
|
-
if (isSignal(this.value)) {
|
|
1848
|
-
this.stopCallback = this.value.watch((value) => {
|
|
1849
|
-
this.update(value);
|
|
1850
|
-
});
|
|
1851
|
-
} else {
|
|
1852
|
-
this.update(this.value);
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1856
|
-
}
|
|
1857
|
-
async disconnect() {
|
|
1858
|
-
if (this.connected) {
|
|
1859
|
-
if (this.stopCallback) {
|
|
1860
|
-
this.stopCallback();
|
|
1861
|
-
this.stopCallback = void 0;
|
|
1862
|
-
}
|
|
1863
|
-
this.node.parentNode.removeChild(this.node);
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
update(value) {
|
|
1867
|
-
if (value != null) {
|
|
1868
|
-
this.node.textContent = value.toString();
|
|
1869
|
-
} else {
|
|
1870
|
-
this.node.textContent = "";
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
async setChildren() {
|
|
1874
|
-
}
|
|
1875
|
-
};
|
|
1876
|
-
|
|
1877
|
-
// src/markup.ts
|
|
1878
|
-
var MARKUP = Symbol("Markup");
|
|
1879
|
-
function isMarkup(value) {
|
|
1880
|
-
return isObject(value) && value[MARKUP] === true;
|
|
1881
|
-
}
|
|
1882
|
-
function isDOMHandle(value) {
|
|
1883
|
-
return isObject(value) && isFunction(value.connect) && isFunction(value.disconnect);
|
|
1884
|
-
}
|
|
1885
|
-
function toMarkup(renderables) {
|
|
1886
|
-
if (!isArray(renderables)) {
|
|
1887
|
-
renderables = [renderables];
|
|
1888
|
-
}
|
|
1889
|
-
return renderables.flat(Infinity).filter((x) => x !== null && x !== void 0 && x !== false).map((x) => {
|
|
1890
|
-
if (x instanceof Node) {
|
|
1891
|
-
return m("$node", { value: x });
|
|
1892
|
-
}
|
|
1893
|
-
if (isMarkup(x)) {
|
|
1894
|
-
return x;
|
|
1895
|
-
}
|
|
1896
|
-
if (isString(x) || isNumber(x)) {
|
|
1897
|
-
return m("$text", { value: x });
|
|
1898
|
-
}
|
|
1899
|
-
if (isSignal(x)) {
|
|
1900
|
-
return m("$observer", {
|
|
1901
|
-
signals: [x],
|
|
1902
|
-
renderFn: (x2) => x2
|
|
1903
|
-
});
|
|
1904
|
-
}
|
|
1905
|
-
console.error(x);
|
|
1906
|
-
throw new TypeError(`Unexpected child type. Got: ${x}`);
|
|
1907
|
-
});
|
|
1908
|
-
}
|
|
1909
|
-
function m(type, props, ...children) {
|
|
1910
|
-
if (props != null) {
|
|
1911
|
-
_assertPropTypes(props);
|
|
1912
|
-
}
|
|
1913
|
-
return {
|
|
1914
|
-
[MARKUP]: true,
|
|
1915
|
-
type,
|
|
1916
|
-
props,
|
|
1917
|
-
children: toMarkup(children)
|
|
1918
|
-
};
|
|
1919
|
-
}
|
|
1920
|
-
function _assertPropTypes(props) {
|
|
1921
|
-
if (props.ref) {
|
|
1922
|
-
if (!isRef(props.ref)) {
|
|
1923
|
-
console.warn(props.ref);
|
|
1924
|
-
throw new TypeError(`Prop 'ref' must be a Ref object. Got: ${props.ref}`);
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
for (const key in props) {
|
|
1928
|
-
if (key.startsWith("$$") && props[key] !== void 0) {
|
|
1929
|
-
if (!isSettableSignal(props[key])) {
|
|
1930
|
-
throw new TypeError(`Prop '${key}' is named as a SettableSignal but value is not. Got: ${props[key]}`);
|
|
1931
|
-
}
|
|
1932
|
-
} else if (key.startsWith("$") && props[key] !== void 0) {
|
|
1933
|
-
if (!isSignal(props[key])) {
|
|
1934
|
-
throw new TypeError(`Prop '${key}' is named as a Signal but value is not. Got: ${props[key]}`);
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
function cond(predicate, thenContent, elseContent) {
|
|
1940
|
-
const $predicate = signalify(predicate);
|
|
1941
|
-
return m("$cond", {
|
|
1942
|
-
$predicate,
|
|
1943
|
-
thenContent,
|
|
1944
|
-
elseContent
|
|
1945
|
-
});
|
|
1946
|
-
}
|
|
1947
|
-
function repeat(items, keyFn, renderFn) {
|
|
1948
|
-
const $items = signalify(items);
|
|
1949
|
-
return m("$repeat", { $items, keyFn, renderFn });
|
|
1950
|
-
}
|
|
1951
|
-
function portal(content, parent2) {
|
|
1952
|
-
return m("$portal", { content, parent: parent2 });
|
|
1953
|
-
}
|
|
1954
|
-
function ref() {
|
|
1955
|
-
const [$node, setNode] = signal();
|
|
1956
|
-
return {
|
|
1957
|
-
get: $node.get,
|
|
1958
|
-
watch: $node.watch,
|
|
1959
|
-
get node() {
|
|
1960
|
-
return $node.get();
|
|
1961
|
-
},
|
|
1962
|
-
set node(node) {
|
|
1963
|
-
setNode(node);
|
|
1964
|
-
}
|
|
1965
|
-
};
|
|
1966
|
-
}
|
|
1967
|
-
function isRef(value) {
|
|
1968
|
-
if (value == null || typeof value !== "object") {
|
|
1969
|
-
return false;
|
|
1970
|
-
}
|
|
1971
|
-
if (!value.hasOwnProperty("node")) {
|
|
1972
|
-
return false;
|
|
1973
|
-
}
|
|
1974
|
-
return true;
|
|
1975
|
-
}
|
|
1976
|
-
var NodeHandle = class {
|
|
1977
|
-
node;
|
|
1978
|
-
get connected() {
|
|
1979
|
-
return this.node.parentNode != null;
|
|
1980
|
-
}
|
|
1981
|
-
constructor(node) {
|
|
1982
|
-
this.node = node;
|
|
1983
|
-
}
|
|
1984
|
-
async connect(parent2, after) {
|
|
1985
|
-
parent2.insertBefore(this.node, after?.nextSibling ?? null);
|
|
1986
|
-
}
|
|
1987
|
-
async disconnect() {
|
|
1988
|
-
if (this.node.parentNode) {
|
|
1989
|
-
this.node.parentNode.removeChild(this.node);
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
async setChildren(children) {
|
|
1993
|
-
}
|
|
1994
|
-
};
|
|
1995
|
-
function renderMarkupToDOM(markup, ctx) {
|
|
1996
|
-
const items = isArray(markup) ? markup : [markup];
|
|
1997
|
-
return items.map((item) => {
|
|
1998
|
-
if (isFunction(item.type)) {
|
|
1999
|
-
return initView({
|
|
2000
|
-
view: item.type,
|
|
2001
|
-
props: item.props,
|
|
2002
|
-
children: item.children,
|
|
2003
|
-
appContext: ctx.appContext,
|
|
2004
|
-
elementContext: ctx.elementContext
|
|
2005
|
-
});
|
|
2006
|
-
} else if (isString(item.type)) {
|
|
2007
|
-
switch (item.type) {
|
|
2008
|
-
case "$node": {
|
|
2009
|
-
const attrs = item.props;
|
|
2010
|
-
return new NodeHandle(attrs.value);
|
|
2011
|
-
}
|
|
2012
|
-
case "$text": {
|
|
2013
|
-
const attrs = item.props;
|
|
2014
|
-
return new Text({
|
|
2015
|
-
value: attrs.value
|
|
2016
|
-
});
|
|
2017
|
-
}
|
|
2018
|
-
case "$cond": {
|
|
2019
|
-
const attrs = item.props;
|
|
2020
|
-
return new Conditional({
|
|
2021
|
-
$predicate: attrs.$predicate,
|
|
2022
|
-
thenContent: attrs.thenContent,
|
|
2023
|
-
elseContent: attrs.elseContent,
|
|
2024
|
-
appContext: ctx.appContext,
|
|
2025
|
-
elementContext: ctx.elementContext
|
|
2026
|
-
});
|
|
2027
|
-
}
|
|
2028
|
-
case "$repeat": {
|
|
2029
|
-
const attrs = item.props;
|
|
2030
|
-
return new Repeat({
|
|
2031
|
-
$items: attrs.$items,
|
|
2032
|
-
keyFn: attrs.keyFn,
|
|
2033
|
-
renderFn: attrs.renderFn,
|
|
2034
|
-
appContext: ctx.appContext,
|
|
2035
|
-
elementContext: ctx.elementContext
|
|
2036
|
-
});
|
|
2037
|
-
}
|
|
2038
|
-
case "$observer": {
|
|
2039
|
-
const attrs = item.props;
|
|
2040
|
-
return new Observer({
|
|
2041
|
-
signals: attrs.signals,
|
|
2042
|
-
renderFn: attrs.renderFn,
|
|
2043
|
-
appContext: ctx.appContext,
|
|
2044
|
-
elementContext: ctx.elementContext
|
|
2045
|
-
});
|
|
2046
|
-
}
|
|
2047
|
-
case "$outlet": {
|
|
2048
|
-
const attrs = item.props;
|
|
2049
|
-
return new Outlet({
|
|
2050
|
-
$children: attrs.$children,
|
|
2051
|
-
appContext: ctx.appContext,
|
|
2052
|
-
elementContext: ctx.elementContext
|
|
2053
|
-
});
|
|
2054
|
-
}
|
|
2055
|
-
case "$portal": {
|
|
2056
|
-
const attrs = item.props;
|
|
2057
|
-
return new Portal({
|
|
2058
|
-
content: attrs.content,
|
|
2059
|
-
parent: attrs.parent,
|
|
2060
|
-
appContext: ctx.appContext,
|
|
2061
|
-
elementContext: ctx.elementContext
|
|
2062
|
-
});
|
|
2063
|
-
}
|
|
2064
|
-
default:
|
|
2065
|
-
if (item.type.startsWith("$")) {
|
|
2066
|
-
throw new Error(`Unknown markup type: ${item.type}`);
|
|
2067
|
-
}
|
|
2068
|
-
return new HTML({
|
|
2069
|
-
tag: item.type,
|
|
2070
|
-
props: item.props,
|
|
2071
|
-
children: item.children,
|
|
2072
|
-
appContext: ctx.appContext,
|
|
2073
|
-
elementContext: ctx.elementContext
|
|
2074
|
-
});
|
|
2075
|
-
}
|
|
2076
|
-
} else {
|
|
2077
|
-
throw new TypeError(`Expected a string or view function. Got: ${item.type}`);
|
|
2078
|
-
}
|
|
2079
|
-
});
|
|
2080
|
-
}
|
|
2081
|
-
function getRenderHandle(handles) {
|
|
2082
|
-
if (handles.length === 1) {
|
|
2083
|
-
return handles[0];
|
|
2084
|
-
}
|
|
2085
|
-
const node = document.createComment("renderHandle");
|
|
2086
|
-
let isConnected = false;
|
|
2087
|
-
return {
|
|
2088
|
-
get node() {
|
|
2089
|
-
return node;
|
|
2090
|
-
},
|
|
2091
|
-
get connected() {
|
|
2092
|
-
return isConnected;
|
|
2093
|
-
},
|
|
2094
|
-
connect(parent2, after) {
|
|
2095
|
-
parent2.insertBefore(node, after ? after : null);
|
|
2096
|
-
for (const handle of handles) {
|
|
2097
|
-
const previous = handles[handles.length - 1]?.node ?? node;
|
|
2098
|
-
handle.connect(parent2, previous);
|
|
2099
|
-
}
|
|
2100
|
-
isConnected = true;
|
|
2101
|
-
},
|
|
2102
|
-
disconnect() {
|
|
2103
|
-
if (isConnected) {
|
|
2104
|
-
for (const handle of handles) {
|
|
2105
|
-
handle.disconnect();
|
|
2106
|
-
}
|
|
2107
|
-
node.remove();
|
|
2108
|
-
}
|
|
2109
|
-
isConnected = false;
|
|
2110
|
-
},
|
|
2111
|
-
setChildren() {
|
|
2112
|
-
throw new Error(`setChildren not supported on renderHandle`);
|
|
2113
|
-
}
|
|
2114
|
-
};
|
|
2115
|
-
}
|
|
2116
|
-
function isRenderable(value) {
|
|
2117
|
-
return value == null || value === false || typeof value === "string" || typeof value === "number" || isMarkup(value) || isSignal(value) || isArrayOf(isRenderable, value);
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
|
-
// src/store.ts
|
|
2121
|
-
var SECRETS2 = Symbol("STORE_SECRETS");
|
|
2122
|
-
function getStoreSecrets(c) {
|
|
2123
|
-
return c[SECRETS2];
|
|
2124
|
-
}
|
|
2125
|
-
function initStore(config) {
|
|
2126
|
-
const appContext = config.appContext;
|
|
2127
|
-
const elementContext = config.elementContext;
|
|
2128
|
-
let isConnected = false;
|
|
2129
|
-
const stopObserverCallbacks = [];
|
|
2130
|
-
const connectedCallbacks = [];
|
|
2131
|
-
const disconnectedCallbacks = [];
|
|
2132
|
-
const ctx = {
|
|
2133
|
-
name: config.store.name ?? "anonymous",
|
|
2134
|
-
options: config.options,
|
|
2135
|
-
getStore(store) {
|
|
2136
|
-
let name;
|
|
2137
|
-
if (typeof store === "string") {
|
|
2138
|
-
name = store;
|
|
2139
|
-
} else {
|
|
2140
|
-
name = store.name;
|
|
2141
|
-
}
|
|
2142
|
-
if (typeof store !== "string") {
|
|
2143
|
-
let ec = elementContext;
|
|
2144
|
-
while (ec) {
|
|
2145
|
-
if (ec.stores.has(store)) {
|
|
2146
|
-
return ec.stores.get(store)?.instance.exports;
|
|
2147
|
-
}
|
|
2148
|
-
ec = ec.parent;
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
if (appContext.stores.has(store)) {
|
|
2152
|
-
const _store = appContext.stores.get(store);
|
|
2153
|
-
if (!_store.instance) {
|
|
2154
|
-
appContext.crashCollector.crash({
|
|
2155
|
-
componentName: ctx.name,
|
|
2156
|
-
error: new Error(
|
|
2157
|
-
`Store '${name}' was accessed before it was set up. Make sure '${name}' is registered before components that access it.`
|
|
2158
|
-
)
|
|
2159
|
-
});
|
|
2160
|
-
}
|
|
2161
|
-
return _store.instance.exports;
|
|
2162
|
-
}
|
|
2163
|
-
appContext.crashCollector.crash({
|
|
2164
|
-
componentName: ctx.name,
|
|
2165
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
2166
|
-
});
|
|
2167
|
-
},
|
|
2168
|
-
onConnected(callback) {
|
|
2169
|
-
connectedCallbacks.push(callback);
|
|
2170
|
-
},
|
|
2171
|
-
onDisconnected(callback) {
|
|
2172
|
-
disconnectedCallbacks.push(callback);
|
|
2173
|
-
},
|
|
2174
|
-
crash(error) {
|
|
2175
|
-
config.appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
2176
|
-
},
|
|
2177
|
-
watch(signals, callback) {
|
|
2178
|
-
if (isConnected) {
|
|
2179
|
-
const stop = watch(signals, callback);
|
|
2180
|
-
stopObserverCallbacks.push(stop);
|
|
2181
|
-
return stop;
|
|
2182
|
-
} else {
|
|
2183
|
-
let stop;
|
|
2184
|
-
let stopped = false;
|
|
2185
|
-
connectedCallbacks.push(() => {
|
|
2186
|
-
if (!stopped) {
|
|
2187
|
-
stop = watch(signals, callback);
|
|
2188
|
-
stopObserverCallbacks.push(stop);
|
|
2189
|
-
}
|
|
2190
|
-
});
|
|
2191
|
-
return function() {
|
|
2192
|
-
if (stop != null) {
|
|
2193
|
-
stopped = true;
|
|
2194
|
-
stop();
|
|
2195
|
-
}
|
|
2196
|
-
};
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
};
|
|
2200
|
-
const debugChannel = appContext.debugHub.channel({
|
|
2201
|
-
get name() {
|
|
2202
|
-
return ctx.name;
|
|
2203
|
-
}
|
|
2204
|
-
});
|
|
2205
|
-
Object.defineProperties(ctx, Object.getOwnPropertyDescriptors(debugChannel));
|
|
2206
|
-
Object.defineProperty(ctx, SECRETS2, {
|
|
2207
|
-
enumerable: false,
|
|
2208
|
-
configurable: false,
|
|
2209
|
-
value: {
|
|
2210
|
-
appContext,
|
|
2211
|
-
elementContext
|
|
2212
|
-
}
|
|
2213
|
-
});
|
|
2214
|
-
let exports;
|
|
2215
|
-
return {
|
|
2216
|
-
get name() {
|
|
2217
|
-
return ctx.name;
|
|
2218
|
-
},
|
|
2219
|
-
get exports() {
|
|
2220
|
-
return exports;
|
|
2221
|
-
},
|
|
2222
|
-
setup() {
|
|
2223
|
-
let result;
|
|
2224
|
-
try {
|
|
2225
|
-
result = config.store(ctx);
|
|
2226
|
-
} catch (error) {
|
|
2227
|
-
if (error instanceof Error) {
|
|
2228
|
-
appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
2229
|
-
} else {
|
|
2230
|
-
throw error;
|
|
2231
|
-
}
|
|
2232
|
-
}
|
|
2233
|
-
if (result instanceof Promise) {
|
|
2234
|
-
appContext.crashCollector.crash({
|
|
2235
|
-
error: new TypeError(`Store function cannot return a Promise`),
|
|
2236
|
-
componentName: ctx.name
|
|
2237
|
-
});
|
|
2238
|
-
}
|
|
2239
|
-
if (!isObject(result)) {
|
|
2240
|
-
const error = new TypeError(`Expected ${ctx.name} function to return an object. Got: ${typeOf(result)}`);
|
|
2241
|
-
appContext.crashCollector.crash({ error, componentName: ctx.name });
|
|
2242
|
-
}
|
|
2243
|
-
exports = result;
|
|
2244
|
-
},
|
|
2245
|
-
connect() {
|
|
2246
|
-
while (connectedCallbacks.length > 0) {
|
|
2247
|
-
const callback = connectedCallbacks.shift();
|
|
2248
|
-
callback();
|
|
2249
|
-
}
|
|
2250
|
-
},
|
|
2251
|
-
disconnect() {
|
|
2252
|
-
while (disconnectedCallbacks.length > 0) {
|
|
2253
|
-
const callback = disconnectedCallbacks.shift();
|
|
2254
|
-
callback();
|
|
2255
|
-
}
|
|
2256
|
-
}
|
|
2257
|
-
};
|
|
2258
|
-
}
|
|
2259
|
-
|
|
2260
|
-
// src/stores/document.ts
|
|
2261
|
-
function DocumentStore(ctx) {
|
|
2262
|
-
ctx.name = "dolla/document";
|
|
2263
|
-
const [$title, setTitle] = signal(document.title);
|
|
2264
|
-
const [$visibility, setVisibility] = signal(document.visibilityState);
|
|
2265
|
-
const [$orientation, setOrientation] = signal("landscape");
|
|
2266
|
-
const [$colorScheme, setColorScheme] = signal("light");
|
|
2267
|
-
ctx.watch([$title], (current) => {
|
|
2268
|
-
document.title = current;
|
|
2269
|
-
});
|
|
2270
|
-
const onVisibilityChange = () => {
|
|
2271
|
-
setVisibility(document.visibilityState);
|
|
2272
|
-
};
|
|
2273
|
-
const onFocus = () => {
|
|
2274
|
-
setVisibility("visible");
|
|
2275
|
-
};
|
|
2276
|
-
const landscapeQuery = window.matchMedia("(orientation: landscape)");
|
|
2277
|
-
function onOrientationChange(e) {
|
|
2278
|
-
setOrientation(e.matches ? "landscape" : "portrait");
|
|
2279
|
-
}
|
|
2280
|
-
onOrientationChange(landscapeQuery);
|
|
2281
|
-
const colorSchemeQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
2282
|
-
function onColorChange(e) {
|
|
2283
|
-
setColorScheme(e.matches ? "dark" : "light");
|
|
2284
|
-
}
|
|
2285
|
-
onColorChange(colorSchemeQuery);
|
|
2286
|
-
ctx.onConnected(function() {
|
|
2287
|
-
landscapeQuery.addEventListener("change", onOrientationChange);
|
|
2288
|
-
colorSchemeQuery.addEventListener("change", onColorChange);
|
|
2289
|
-
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
2290
|
-
window.addEventListener("focus", onFocus);
|
|
2291
|
-
});
|
|
2292
|
-
ctx.onDisconnected(function() {
|
|
2293
|
-
landscapeQuery.removeEventListener("change", onOrientationChange);
|
|
2294
|
-
colorSchemeQuery.removeEventListener("change", onColorChange);
|
|
2295
|
-
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
2296
|
-
window.removeEventListener("focus", onFocus);
|
|
2297
|
-
});
|
|
2298
|
-
return {
|
|
2299
|
-
$title,
|
|
2300
|
-
setTitle,
|
|
2301
|
-
$visibility,
|
|
2302
|
-
$orientation,
|
|
2303
|
-
$colorScheme
|
|
2304
|
-
};
|
|
2305
|
-
}
|
|
2306
|
-
|
|
2307
|
-
// src/stores/render.ts
|
|
2308
|
-
function RenderStore(ctx) {
|
|
2309
|
-
ctx.name = "dolla/render";
|
|
2310
|
-
const keyedUpdates = /* @__PURE__ */ new Map();
|
|
2311
|
-
let unkeyedUpdates = [];
|
|
2312
|
-
let reads = [];
|
|
2313
|
-
let isUpdating = false;
|
|
2314
|
-
let isConnected = false;
|
|
2315
|
-
ctx.onConnected(() => {
|
|
2316
|
-
isConnected = true;
|
|
2317
|
-
});
|
|
2318
|
-
ctx.onDisconnected(() => {
|
|
2319
|
-
isConnected = false;
|
|
2320
|
-
});
|
|
2321
|
-
function runUpdates() {
|
|
2322
|
-
const totalQueued = keyedUpdates.size + unkeyedUpdates.length;
|
|
2323
|
-
if (!isConnected || totalQueued === 0) {
|
|
2324
|
-
isUpdating = false;
|
|
2325
|
-
}
|
|
2326
|
-
if (!isUpdating) {
|
|
2327
|
-
for (const callback of reads) {
|
|
2328
|
-
callback();
|
|
2329
|
-
}
|
|
2330
|
-
reads = [];
|
|
2331
|
-
return;
|
|
2332
|
-
}
|
|
2333
|
-
requestAnimationFrame(() => {
|
|
2334
|
-
ctx.info(`Batching ${keyedUpdates.size + unkeyedUpdates.length} queued DOM update(s).`);
|
|
2335
|
-
for (const callback of keyedUpdates.values()) {
|
|
2336
|
-
callback();
|
|
2337
|
-
}
|
|
2338
|
-
keyedUpdates.clear();
|
|
2339
|
-
for (const callback of unkeyedUpdates) {
|
|
2340
|
-
callback();
|
|
2341
|
-
}
|
|
2342
|
-
unkeyedUpdates = [];
|
|
2343
|
-
runUpdates();
|
|
2344
|
-
});
|
|
2345
|
-
}
|
|
2346
|
-
return {
|
|
2347
|
-
/**
|
|
2348
|
-
* Queues a callback to run in the next render batch.
|
|
2349
|
-
* Running your DOM mutations in update callbacks reduces layout thrashing.
|
|
2350
|
-
* Returns a Promise that resolves once the callback has run.
|
|
2351
|
-
*/
|
|
2352
|
-
update(callback, key) {
|
|
2353
|
-
return new Promise((resolve2) => {
|
|
2354
|
-
if (key) {
|
|
2355
|
-
keyedUpdates.set(key, () => {
|
|
2356
|
-
callback();
|
|
2357
|
-
resolve2();
|
|
2358
|
-
});
|
|
2359
|
-
} else {
|
|
2360
|
-
unkeyedUpdates.push(() => {
|
|
2361
|
-
callback();
|
|
2362
|
-
resolve2();
|
|
2363
|
-
});
|
|
2364
|
-
}
|
|
2365
|
-
if (!isUpdating && isConnected) {
|
|
2366
|
-
isUpdating = true;
|
|
2367
|
-
runUpdates();
|
|
2368
|
-
}
|
|
2369
|
-
});
|
|
2370
|
-
},
|
|
2371
|
-
/**
|
|
2372
|
-
* Queues a callback that reads DOM information to run after the next render batch,
|
|
2373
|
-
* ensuring all writes have been performed before reading.
|
|
2374
|
-
* Returns a Promise that resolves once the callback has run.
|
|
2375
|
-
*/
|
|
2376
|
-
read(callback) {
|
|
2377
|
-
return new Promise((resolve2) => {
|
|
2378
|
-
reads.push(() => {
|
|
2379
|
-
callback();
|
|
2380
|
-
resolve2();
|
|
2381
|
-
});
|
|
2382
|
-
if (!isUpdating && isConnected) {
|
|
2383
|
-
isUpdating = true;
|
|
2384
|
-
runUpdates();
|
|
2385
|
-
}
|
|
2386
|
-
});
|
|
2387
|
-
}
|
|
2388
|
-
};
|
|
2389
|
-
}
|
|
2390
|
-
|
|
2391
|
-
// src/views/default-crash-page.ts
|
|
2392
|
-
function DefaultCrashPage({ message, error, componentName }) {
|
|
2393
|
-
return m(
|
|
2394
|
-
"div",
|
|
2395
|
-
{
|
|
2396
|
-
style: {
|
|
2397
|
-
backgroundColor: "#880000",
|
|
2398
|
-
color: "#fff",
|
|
2399
|
-
padding: "2rem",
|
|
2400
|
-
position: "fixed",
|
|
2401
|
-
inset: 0,
|
|
2402
|
-
fontSize: "20px"
|
|
2403
|
-
}
|
|
2404
|
-
},
|
|
2405
|
-
m("h1", { style: { marginBottom: "0.5rem" } }, "The app has crashed"),
|
|
2406
|
-
m(
|
|
2407
|
-
"p",
|
|
2408
|
-
{ style: { marginBottom: "0.25rem" } },
|
|
2409
|
-
m("span", { style: { fontFamily: "monospace" } }, componentName),
|
|
2410
|
-
" says:"
|
|
2411
|
-
),
|
|
2412
|
-
m(
|
|
2413
|
-
"blockquote",
|
|
2414
|
-
{
|
|
2415
|
-
style: {
|
|
2416
|
-
backgroundColor: "#991111",
|
|
2417
|
-
padding: "0.25em",
|
|
2418
|
-
borderRadius: "6px",
|
|
2419
|
-
fontFamily: "monospace",
|
|
2420
|
-
marginBottom: "1rem"
|
|
2421
|
-
}
|
|
2422
|
-
},
|
|
2423
|
-
m(
|
|
2424
|
-
"span",
|
|
2425
|
-
{
|
|
2426
|
-
style: {
|
|
2427
|
-
display: "inline-block",
|
|
2428
|
-
backgroundColor: "red",
|
|
2429
|
-
padding: "0.1em 0.4em",
|
|
2430
|
-
marginRight: "0.5em",
|
|
2431
|
-
borderRadius: "4px",
|
|
2432
|
-
fontSize: "0.9em",
|
|
2433
|
-
fontWeight: "bold"
|
|
2434
|
-
}
|
|
2435
|
-
},
|
|
2436
|
-
error.name
|
|
2437
|
-
),
|
|
2438
|
-
message
|
|
2439
|
-
),
|
|
2440
|
-
m("p", {}, "Please see the browser console for details.")
|
|
2441
|
-
);
|
|
2442
|
-
}
|
|
2443
|
-
|
|
2444
|
-
// src/views/default-view.ts
|
|
2445
|
-
function DefaultView(_, ctx) {
|
|
2446
|
-
return ctx.outlet();
|
|
2447
|
-
}
|
|
2448
|
-
|
|
2449
|
-
// src/app.ts
|
|
2450
|
-
function isAppOptions(value) {
|
|
2451
|
-
return isObject(value);
|
|
2452
|
-
}
|
|
2453
|
-
function App(options) {
|
|
2454
|
-
if (options && !isAppOptions(options)) {
|
|
2455
|
-
throw new TypeError(`App options must be an object. Got: ${options}`);
|
|
2456
|
-
}
|
|
2457
|
-
let isConnected = false;
|
|
2458
|
-
let mainView = m(options?.view ?? DefaultView);
|
|
2459
|
-
let configureCallback;
|
|
2460
|
-
const settings = merge(
|
|
2461
|
-
{
|
|
2462
|
-
debug: {
|
|
2463
|
-
filter: "*,-dolla/*",
|
|
2464
|
-
log: "development",
|
|
2465
|
-
// Only print logs in development.
|
|
2466
|
-
warn: "development",
|
|
2467
|
-
// Only print warnings in development.
|
|
2468
|
-
error: true
|
|
2469
|
-
// Always print errors.
|
|
2470
|
-
},
|
|
2471
|
-
mode: "production"
|
|
2472
|
-
},
|
|
2473
|
-
options ?? {}
|
|
2474
|
-
);
|
|
2475
|
-
const stores = /* @__PURE__ */ new Map([
|
|
2476
|
-
["render", { store: RenderStore }],
|
|
2477
|
-
["document", { store: DocumentStore }]
|
|
2478
|
-
]);
|
|
2479
|
-
if (options?.stores) {
|
|
2480
|
-
for (const entry of options.stores) {
|
|
2481
|
-
assertFunction(entry.store, `Expected a store function. Got type: %t, value: %v`);
|
|
2482
|
-
stores.set(entry.store, entry);
|
|
2483
|
-
}
|
|
2484
|
-
}
|
|
2485
|
-
const crashCollector = new CrashCollector();
|
|
2486
|
-
const debugHub = new DebugHub({ ...settings.debug, crashCollector, mode: settings.mode });
|
|
2487
|
-
const debugChannel = debugHub.channel({ name: "dolla/App" });
|
|
2488
|
-
crashCollector.onError(async ({ error, severity, componentName }) => {
|
|
2489
|
-
if (severity === "crash") {
|
|
2490
|
-
await disconnect();
|
|
2491
|
-
const instance = initView({
|
|
2492
|
-
view: DefaultCrashPage,
|
|
2493
|
-
appContext,
|
|
2494
|
-
elementContext,
|
|
2495
|
-
props: {
|
|
2496
|
-
message: error.message,
|
|
2497
|
-
error,
|
|
2498
|
-
componentName
|
|
2499
|
-
}
|
|
2500
|
-
});
|
|
2501
|
-
instance.connect(appContext.rootElement);
|
|
2502
|
-
}
|
|
2503
|
-
});
|
|
2504
|
-
async function connect(selector) {
|
|
2505
|
-
return new Promise(async (resolve2) => {
|
|
2506
|
-
let element = null;
|
|
2507
|
-
if (isString(selector)) {
|
|
2508
|
-
element = document.querySelector(selector);
|
|
2509
|
-
assertInstanceOf(HTMLElement, element, `Selector string '${selector}' did not match any element.`);
|
|
2510
|
-
}
|
|
2511
|
-
assertInstanceOf(HTMLElement, element, "Expected a DOM node or a selector string. Got type: %t, value: %v");
|
|
2512
|
-
appContext.rootElement = element;
|
|
2513
|
-
appContext.rootView = initView({
|
|
2514
|
-
view: mainView.type,
|
|
2515
|
-
props: mainView.props,
|
|
2516
|
-
appContext,
|
|
2517
|
-
elementContext
|
|
2518
|
-
});
|
|
2519
|
-
for (let [key, item] of stores.entries()) {
|
|
2520
|
-
const { store, options: options2 } = item;
|
|
2521
|
-
const channelPrefix = isString(key) ? "dolla/store" : "store";
|
|
2522
|
-
const label = isString(key) ? key : store.name ?? "(anonymous)";
|
|
2523
|
-
const config = {
|
|
2524
|
-
store,
|
|
2525
|
-
appContext,
|
|
2526
|
-
elementContext,
|
|
2527
|
-
channelPrefix,
|
|
2528
|
-
label,
|
|
2529
|
-
options: options2 ?? {}
|
|
2530
|
-
};
|
|
2531
|
-
const instance = initStore(config);
|
|
2532
|
-
instance.setup();
|
|
2533
|
-
stores.set(key, { ...item, instance });
|
|
2534
|
-
}
|
|
2535
|
-
for (const { instance } of stores.values()) {
|
|
2536
|
-
instance.connect();
|
|
2537
|
-
}
|
|
2538
|
-
if (configureCallback) {
|
|
2539
|
-
await configureCallback({
|
|
2540
|
-
// TODO: Add context methods
|
|
2541
|
-
getStore(store) {
|
|
2542
|
-
let name;
|
|
2543
|
-
if (typeof store === "string") {
|
|
2544
|
-
name = store;
|
|
2545
|
-
} else {
|
|
2546
|
-
name = store.name;
|
|
2547
|
-
}
|
|
2548
|
-
if (typeof store !== "string") {
|
|
2549
|
-
let ec = elementContext;
|
|
2550
|
-
while (ec) {
|
|
2551
|
-
if (ec.stores.has(store)) {
|
|
2552
|
-
return ec.stores.get(store)?.instance.exports;
|
|
2553
|
-
}
|
|
2554
|
-
ec = ec.parent;
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
if (appContext.stores.has(store)) {
|
|
2558
|
-
const _store = appContext.stores.get(store);
|
|
2559
|
-
if (!_store.instance) {
|
|
2560
|
-
appContext.crashCollector.crash({
|
|
2561
|
-
componentName: "@manyducks.co/dolla/App",
|
|
2562
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
2563
|
-
});
|
|
2564
|
-
}
|
|
2565
|
-
return _store.instance.exports;
|
|
2566
|
-
}
|
|
2567
|
-
appContext.crashCollector.crash({
|
|
2568
|
-
componentName: "@manyducks.co/dolla/App",
|
|
2569
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
2570
|
-
});
|
|
2571
|
-
}
|
|
2572
|
-
});
|
|
2573
|
-
}
|
|
2574
|
-
appContext.rootView.connect(appContext.rootElement);
|
|
2575
|
-
isConnected = true;
|
|
2576
|
-
resolve2();
|
|
2577
|
-
});
|
|
2578
|
-
}
|
|
2579
|
-
async function disconnect() {
|
|
2580
|
-
if (isConnected) {
|
|
2581
|
-
appContext.rootView.disconnect();
|
|
2582
|
-
isConnected = false;
|
|
2583
|
-
for (const { instance } of stores.values()) {
|
|
2584
|
-
instance.disconnect();
|
|
2585
|
-
}
|
|
2586
|
-
}
|
|
2587
|
-
}
|
|
2588
|
-
const appContext = {
|
|
2589
|
-
crashCollector,
|
|
2590
|
-
debugHub,
|
|
2591
|
-
stores,
|
|
2592
|
-
mode: settings.mode ?? "production"
|
|
2593
|
-
};
|
|
2594
|
-
const elementContext = {
|
|
2595
|
-
stores: /* @__PURE__ */ new Map()
|
|
2596
|
-
};
|
|
2597
|
-
const app = {
|
|
2598
|
-
connect,
|
|
2599
|
-
disconnect,
|
|
2600
|
-
get isConnected() {
|
|
2601
|
-
return isConnected;
|
|
2602
|
-
},
|
|
2603
|
-
configure(callback) {
|
|
2604
|
-
if (configureCallback !== void 0) {
|
|
2605
|
-
debugChannel.warn(`Configure callback is already defined. Only the final configure call will take effect.`);
|
|
2606
|
-
}
|
|
2607
|
-
configureCallback = callback;
|
|
2608
|
-
return app;
|
|
2609
|
-
}
|
|
2610
|
-
};
|
|
2611
|
-
return app;
|
|
2612
|
-
}
|
|
2613
|
-
|
|
2614
|
-
// src/views/fragment.ts
|
|
2615
|
-
function Fragment(_, ctx) {
|
|
2616
|
-
return ctx.outlet();
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
|
-
// src/views/store-scope.ts
|
|
2620
|
-
function StoreScope(props, ctx) {
|
|
2621
|
-
const { appContext, elementContext } = getViewSecrets(ctx);
|
|
2622
|
-
const instances = [];
|
|
2623
|
-
for (const config of props.stores) {
|
|
2624
|
-
let store;
|
|
2625
|
-
let options;
|
|
2626
|
-
if (isFunction(config)) {
|
|
2627
|
-
store = config;
|
|
2628
|
-
} else {
|
|
2629
|
-
store = config.store;
|
|
2630
|
-
options = config.options;
|
|
2631
|
-
}
|
|
2632
|
-
const instance = initStore({
|
|
2633
|
-
store,
|
|
2634
|
-
options,
|
|
2635
|
-
appContext,
|
|
2636
|
-
elementContext
|
|
2637
|
-
});
|
|
2638
|
-
instance.setup();
|
|
2639
|
-
elementContext.stores.set(store, { store, options, instance });
|
|
2640
|
-
instances.push(instance);
|
|
2641
|
-
}
|
|
2642
|
-
ctx.beforeConnect(() => {
|
|
2643
|
-
for (const instance of instances) {
|
|
2644
|
-
instance.connect();
|
|
2645
|
-
}
|
|
2646
|
-
});
|
|
2647
|
-
ctx.onDisconnected(() => {
|
|
2648
|
-
for (const instance of instances) {
|
|
2649
|
-
instance.disconnect();
|
|
2650
|
-
}
|
|
2651
|
-
});
|
|
2652
|
-
return ctx.outlet();
|
|
2653
|
-
}
|
|
2654
|
-
|
|
2655
|
-
// node_modules/@babel/runtime/helpers/esm/extends.js
|
|
2656
|
-
function _extends() {
|
|
2657
|
-
_extends = Object.assign || function(target) {
|
|
2658
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
2659
|
-
var source = arguments[i];
|
|
2660
|
-
for (var key in source) {
|
|
2661
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
2662
|
-
target[key] = source[key];
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
}
|
|
2666
|
-
return target;
|
|
2667
|
-
};
|
|
2668
|
-
return _extends.apply(this, arguments);
|
|
2669
|
-
}
|
|
2670
|
-
|
|
2671
|
-
// node_modules/history/index.js
|
|
2672
|
-
var Action;
|
|
2673
|
-
(function(Action2) {
|
|
2674
|
-
Action2["Pop"] = "POP";
|
|
2675
|
-
Action2["Push"] = "PUSH";
|
|
2676
|
-
Action2["Replace"] = "REPLACE";
|
|
2677
|
-
})(Action || (Action = {}));
|
|
2678
|
-
var readOnly = true ? function(obj) {
|
|
2679
|
-
return Object.freeze(obj);
|
|
2680
|
-
} : function(obj) {
|
|
2681
|
-
return obj;
|
|
2682
|
-
};
|
|
2683
|
-
function warning(cond2, message) {
|
|
2684
|
-
if (!cond2) {
|
|
2685
|
-
if (typeof console !== "undefined")
|
|
2686
|
-
console.warn(message);
|
|
2687
|
-
try {
|
|
2688
|
-
throw new Error(message);
|
|
2689
|
-
} catch (e) {
|
|
2690
|
-
}
|
|
2691
|
-
}
|
|
2692
|
-
}
|
|
2693
|
-
var BeforeUnloadEventType = "beforeunload";
|
|
2694
|
-
var HashChangeEventType = "hashchange";
|
|
2695
|
-
var PopStateEventType = "popstate";
|
|
2696
|
-
function createBrowserHistory(options) {
|
|
2697
|
-
if (options === void 0) {
|
|
2698
|
-
options = {};
|
|
2699
|
-
}
|
|
2700
|
-
var _options = options, _options$window = _options.window, window2 = _options$window === void 0 ? document.defaultView : _options$window;
|
|
2701
|
-
var globalHistory = window2.history;
|
|
2702
|
-
function getIndexAndLocation() {
|
|
2703
|
-
var _window$location = window2.location, pathname = _window$location.pathname, search = _window$location.search, hash2 = _window$location.hash;
|
|
2704
|
-
var state = globalHistory.state || {};
|
|
2705
|
-
return [state.idx, readOnly({
|
|
2706
|
-
pathname,
|
|
2707
|
-
search,
|
|
2708
|
-
hash: hash2,
|
|
2709
|
-
state: state.usr || null,
|
|
2710
|
-
key: state.key || "default"
|
|
2711
|
-
})];
|
|
2712
|
-
}
|
|
2713
|
-
var blockedPopTx = null;
|
|
2714
|
-
function handlePop() {
|
|
2715
|
-
if (blockedPopTx) {
|
|
2716
|
-
blockers.call(blockedPopTx);
|
|
2717
|
-
blockedPopTx = null;
|
|
2718
|
-
} else {
|
|
2719
|
-
var nextAction = Action.Pop;
|
|
2720
|
-
var _getIndexAndLocation = getIndexAndLocation(), nextIndex = _getIndexAndLocation[0], nextLocation = _getIndexAndLocation[1];
|
|
2721
|
-
if (blockers.length) {
|
|
2722
|
-
if (nextIndex != null) {
|
|
2723
|
-
var delta = index - nextIndex;
|
|
2724
|
-
if (delta) {
|
|
2725
|
-
blockedPopTx = {
|
|
2726
|
-
action: nextAction,
|
|
2727
|
-
location: nextLocation,
|
|
2728
|
-
retry: function retry() {
|
|
2729
|
-
go(delta * -1);
|
|
2730
|
-
}
|
|
2731
|
-
};
|
|
2732
|
-
go(delta);
|
|
2733
|
-
}
|
|
2734
|
-
} else {
|
|
2735
|
-
true ? warning(
|
|
2736
|
-
false,
|
|
2737
|
-
// TODO: Write up a doc that explains our blocking strategy in
|
|
2738
|
-
// detail and link to it here so people can understand better what
|
|
2739
|
-
// is going on and how to avoid it.
|
|
2740
|
-
"You are trying to block a POP navigation to a location that was not created by the history library. The block will fail silently in production, but in general you should do all navigation with the history library (instead of using window.history.pushState directly) to avoid this situation."
|
|
2741
|
-
) : void 0;
|
|
2742
|
-
}
|
|
2743
|
-
} else {
|
|
2744
|
-
applyTx(nextAction);
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
}
|
|
2748
|
-
window2.addEventListener(PopStateEventType, handlePop);
|
|
2749
|
-
var action = Action.Pop;
|
|
2750
|
-
var _getIndexAndLocation2 = getIndexAndLocation(), index = _getIndexAndLocation2[0], location = _getIndexAndLocation2[1];
|
|
2751
|
-
var listeners = createEvents();
|
|
2752
|
-
var blockers = createEvents();
|
|
2753
|
-
if (index == null) {
|
|
2754
|
-
index = 0;
|
|
2755
|
-
globalHistory.replaceState(_extends({}, globalHistory.state, {
|
|
2756
|
-
idx: index
|
|
2757
|
-
}), "");
|
|
2758
|
-
}
|
|
2759
|
-
function createHref(to) {
|
|
2760
|
-
return typeof to === "string" ? to : createPath(to);
|
|
2761
|
-
}
|
|
2762
|
-
function getNextLocation(to, state) {
|
|
2763
|
-
if (state === void 0) {
|
|
2764
|
-
state = null;
|
|
2765
|
-
}
|
|
2766
|
-
return readOnly(_extends({
|
|
2767
|
-
pathname: location.pathname,
|
|
2768
|
-
hash: "",
|
|
2769
|
-
search: ""
|
|
2770
|
-
}, typeof to === "string" ? parsePath(to) : to, {
|
|
2771
|
-
state,
|
|
2772
|
-
key: createKey()
|
|
2773
|
-
}));
|
|
2774
|
-
}
|
|
2775
|
-
function getHistoryStateAndUrl(nextLocation, index2) {
|
|
2776
|
-
return [{
|
|
2777
|
-
usr: nextLocation.state,
|
|
2778
|
-
key: nextLocation.key,
|
|
2779
|
-
idx: index2
|
|
2780
|
-
}, createHref(nextLocation)];
|
|
2781
|
-
}
|
|
2782
|
-
function allowTx(action2, location2, retry) {
|
|
2783
|
-
return !blockers.length || (blockers.call({
|
|
2784
|
-
action: action2,
|
|
2785
|
-
location: location2,
|
|
2786
|
-
retry
|
|
2787
|
-
}), false);
|
|
2788
|
-
}
|
|
2789
|
-
function applyTx(nextAction) {
|
|
2790
|
-
action = nextAction;
|
|
2791
|
-
var _getIndexAndLocation3 = getIndexAndLocation();
|
|
2792
|
-
index = _getIndexAndLocation3[0];
|
|
2793
|
-
location = _getIndexAndLocation3[1];
|
|
2794
|
-
listeners.call({
|
|
2795
|
-
action,
|
|
2796
|
-
location
|
|
2797
|
-
});
|
|
2798
|
-
}
|
|
2799
|
-
function push(to, state) {
|
|
2800
|
-
var nextAction = Action.Push;
|
|
2801
|
-
var nextLocation = getNextLocation(to, state);
|
|
2802
|
-
function retry() {
|
|
2803
|
-
push(to, state);
|
|
2804
|
-
}
|
|
2805
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
2806
|
-
var _getHistoryStateAndUr = getHistoryStateAndUrl(nextLocation, index + 1), historyState = _getHistoryStateAndUr[0], url = _getHistoryStateAndUr[1];
|
|
2807
|
-
try {
|
|
2808
|
-
globalHistory.pushState(historyState, "", url);
|
|
2809
|
-
} catch (error) {
|
|
2810
|
-
window2.location.assign(url);
|
|
2811
|
-
}
|
|
2812
|
-
applyTx(nextAction);
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
function replace(to, state) {
|
|
2816
|
-
var nextAction = Action.Replace;
|
|
2817
|
-
var nextLocation = getNextLocation(to, state);
|
|
2818
|
-
function retry() {
|
|
2819
|
-
replace(to, state);
|
|
2820
|
-
}
|
|
2821
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
2822
|
-
var _getHistoryStateAndUr2 = getHistoryStateAndUrl(nextLocation, index), historyState = _getHistoryStateAndUr2[0], url = _getHistoryStateAndUr2[1];
|
|
2823
|
-
globalHistory.replaceState(historyState, "", url);
|
|
2824
|
-
applyTx(nextAction);
|
|
2825
|
-
}
|
|
2826
|
-
}
|
|
2827
|
-
function go(delta) {
|
|
2828
|
-
globalHistory.go(delta);
|
|
2829
|
-
}
|
|
2830
|
-
var history = {
|
|
2831
|
-
get action() {
|
|
2832
|
-
return action;
|
|
2833
|
-
},
|
|
2834
|
-
get location() {
|
|
2835
|
-
return location;
|
|
2836
|
-
},
|
|
2837
|
-
createHref,
|
|
2838
|
-
push,
|
|
2839
|
-
replace,
|
|
2840
|
-
go,
|
|
2841
|
-
back: function back() {
|
|
2842
|
-
go(-1);
|
|
2843
|
-
},
|
|
2844
|
-
forward: function forward() {
|
|
2845
|
-
go(1);
|
|
2846
|
-
},
|
|
2847
|
-
listen: function listen(listener) {
|
|
2848
|
-
return listeners.push(listener);
|
|
2849
|
-
},
|
|
2850
|
-
block: function block(blocker) {
|
|
2851
|
-
var unblock = blockers.push(blocker);
|
|
2852
|
-
if (blockers.length === 1) {
|
|
2853
|
-
window2.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
2854
|
-
}
|
|
2855
|
-
return function() {
|
|
2856
|
-
unblock();
|
|
2857
|
-
if (!blockers.length) {
|
|
2858
|
-
window2.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
2859
|
-
}
|
|
2860
|
-
};
|
|
2861
|
-
}
|
|
2862
|
-
};
|
|
2863
|
-
return history;
|
|
2864
|
-
}
|
|
2865
|
-
function createHashHistory(options) {
|
|
2866
|
-
if (options === void 0) {
|
|
2867
|
-
options = {};
|
|
2868
|
-
}
|
|
2869
|
-
var _options2 = options, _options2$window = _options2.window, window2 = _options2$window === void 0 ? document.defaultView : _options2$window;
|
|
2870
|
-
var globalHistory = window2.history;
|
|
2871
|
-
function getIndexAndLocation() {
|
|
2872
|
-
var _parsePath = parsePath(window2.location.hash.substr(1)), _parsePath$pathname = _parsePath.pathname, pathname = _parsePath$pathname === void 0 ? "/" : _parsePath$pathname, _parsePath$search = _parsePath.search, search = _parsePath$search === void 0 ? "" : _parsePath$search, _parsePath$hash = _parsePath.hash, hash2 = _parsePath$hash === void 0 ? "" : _parsePath$hash;
|
|
2873
|
-
var state = globalHistory.state || {};
|
|
2874
|
-
return [state.idx, readOnly({
|
|
2875
|
-
pathname,
|
|
2876
|
-
search,
|
|
2877
|
-
hash: hash2,
|
|
2878
|
-
state: state.usr || null,
|
|
2879
|
-
key: state.key || "default"
|
|
2880
|
-
})];
|
|
2881
|
-
}
|
|
2882
|
-
var blockedPopTx = null;
|
|
2883
|
-
function handlePop() {
|
|
2884
|
-
if (blockedPopTx) {
|
|
2885
|
-
blockers.call(blockedPopTx);
|
|
2886
|
-
blockedPopTx = null;
|
|
2887
|
-
} else {
|
|
2888
|
-
var nextAction = Action.Pop;
|
|
2889
|
-
var _getIndexAndLocation4 = getIndexAndLocation(), nextIndex = _getIndexAndLocation4[0], nextLocation = _getIndexAndLocation4[1];
|
|
2890
|
-
if (blockers.length) {
|
|
2891
|
-
if (nextIndex != null) {
|
|
2892
|
-
var delta = index - nextIndex;
|
|
2893
|
-
if (delta) {
|
|
2894
|
-
blockedPopTx = {
|
|
2895
|
-
action: nextAction,
|
|
2896
|
-
location: nextLocation,
|
|
2897
|
-
retry: function retry() {
|
|
2898
|
-
go(delta * -1);
|
|
2899
|
-
}
|
|
2900
|
-
};
|
|
2901
|
-
go(delta);
|
|
2902
|
-
}
|
|
2903
|
-
} else {
|
|
2904
|
-
true ? warning(
|
|
2905
|
-
false,
|
|
2906
|
-
// TODO: Write up a doc that explains our blocking strategy in
|
|
2907
|
-
// detail and link to it here so people can understand better
|
|
2908
|
-
// what is going on and how to avoid it.
|
|
2909
|
-
"You are trying to block a POP navigation to a location that was not created by the history library. The block will fail silently in production, but in general you should do all navigation with the history library (instead of using window.history.pushState directly) to avoid this situation."
|
|
2910
|
-
) : void 0;
|
|
2911
|
-
}
|
|
2912
|
-
} else {
|
|
2913
|
-
applyTx(nextAction);
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
}
|
|
2917
|
-
window2.addEventListener(PopStateEventType, handlePop);
|
|
2918
|
-
window2.addEventListener(HashChangeEventType, function() {
|
|
2919
|
-
var _getIndexAndLocation5 = getIndexAndLocation(), nextLocation = _getIndexAndLocation5[1];
|
|
2920
|
-
if (createPath(nextLocation) !== createPath(location)) {
|
|
2921
|
-
handlePop();
|
|
2922
|
-
}
|
|
2923
|
-
});
|
|
2924
|
-
var action = Action.Pop;
|
|
2925
|
-
var _getIndexAndLocation6 = getIndexAndLocation(), index = _getIndexAndLocation6[0], location = _getIndexAndLocation6[1];
|
|
2926
|
-
var listeners = createEvents();
|
|
2927
|
-
var blockers = createEvents();
|
|
2928
|
-
if (index == null) {
|
|
2929
|
-
index = 0;
|
|
2930
|
-
globalHistory.replaceState(_extends({}, globalHistory.state, {
|
|
2931
|
-
idx: index
|
|
2932
|
-
}), "");
|
|
2933
|
-
}
|
|
2934
|
-
function getBaseHref() {
|
|
2935
|
-
var base = document.querySelector("base");
|
|
2936
|
-
var href = "";
|
|
2937
|
-
if (base && base.getAttribute("href")) {
|
|
2938
|
-
var url = window2.location.href;
|
|
2939
|
-
var hashIndex = url.indexOf("#");
|
|
2940
|
-
href = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
2941
|
-
}
|
|
2942
|
-
return href;
|
|
2943
|
-
}
|
|
2944
|
-
function createHref(to) {
|
|
2945
|
-
return getBaseHref() + "#" + (typeof to === "string" ? to : createPath(to));
|
|
2946
|
-
}
|
|
2947
|
-
function getNextLocation(to, state) {
|
|
2948
|
-
if (state === void 0) {
|
|
2949
|
-
state = null;
|
|
2950
|
-
}
|
|
2951
|
-
return readOnly(_extends({
|
|
2952
|
-
pathname: location.pathname,
|
|
2953
|
-
hash: "",
|
|
2954
|
-
search: ""
|
|
2955
|
-
}, typeof to === "string" ? parsePath(to) : to, {
|
|
2956
|
-
state,
|
|
2957
|
-
key: createKey()
|
|
2958
|
-
}));
|
|
2959
|
-
}
|
|
2960
|
-
function getHistoryStateAndUrl(nextLocation, index2) {
|
|
2961
|
-
return [{
|
|
2962
|
-
usr: nextLocation.state,
|
|
2963
|
-
key: nextLocation.key,
|
|
2964
|
-
idx: index2
|
|
2965
|
-
}, createHref(nextLocation)];
|
|
2966
|
-
}
|
|
2967
|
-
function allowTx(action2, location2, retry) {
|
|
2968
|
-
return !blockers.length || (blockers.call({
|
|
2969
|
-
action: action2,
|
|
2970
|
-
location: location2,
|
|
2971
|
-
retry
|
|
2972
|
-
}), false);
|
|
2973
|
-
}
|
|
2974
|
-
function applyTx(nextAction) {
|
|
2975
|
-
action = nextAction;
|
|
2976
|
-
var _getIndexAndLocation7 = getIndexAndLocation();
|
|
2977
|
-
index = _getIndexAndLocation7[0];
|
|
2978
|
-
location = _getIndexAndLocation7[1];
|
|
2979
|
-
listeners.call({
|
|
2980
|
-
action,
|
|
2981
|
-
location
|
|
2982
|
-
});
|
|
2983
|
-
}
|
|
2984
|
-
function push(to, state) {
|
|
2985
|
-
var nextAction = Action.Push;
|
|
2986
|
-
var nextLocation = getNextLocation(to, state);
|
|
2987
|
-
function retry() {
|
|
2988
|
-
push(to, state);
|
|
2989
|
-
}
|
|
2990
|
-
true ? warning(nextLocation.pathname.charAt(0) === "/", "Relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")") : void 0;
|
|
2991
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
2992
|
-
var _getHistoryStateAndUr3 = getHistoryStateAndUrl(nextLocation, index + 1), historyState = _getHistoryStateAndUr3[0], url = _getHistoryStateAndUr3[1];
|
|
2993
|
-
try {
|
|
2994
|
-
globalHistory.pushState(historyState, "", url);
|
|
2995
|
-
} catch (error) {
|
|
2996
|
-
window2.location.assign(url);
|
|
2997
|
-
}
|
|
2998
|
-
applyTx(nextAction);
|
|
2999
|
-
}
|
|
3000
|
-
}
|
|
3001
|
-
function replace(to, state) {
|
|
3002
|
-
var nextAction = Action.Replace;
|
|
3003
|
-
var nextLocation = getNextLocation(to, state);
|
|
3004
|
-
function retry() {
|
|
3005
|
-
replace(to, state);
|
|
3006
|
-
}
|
|
3007
|
-
true ? warning(nextLocation.pathname.charAt(0) === "/", "Relative pathnames are not supported in hash history.replace(" + JSON.stringify(to) + ")") : void 0;
|
|
3008
|
-
if (allowTx(nextAction, nextLocation, retry)) {
|
|
3009
|
-
var _getHistoryStateAndUr4 = getHistoryStateAndUrl(nextLocation, index), historyState = _getHistoryStateAndUr4[0], url = _getHistoryStateAndUr4[1];
|
|
3010
|
-
globalHistory.replaceState(historyState, "", url);
|
|
3011
|
-
applyTx(nextAction);
|
|
3012
|
-
}
|
|
3013
|
-
}
|
|
3014
|
-
function go(delta) {
|
|
3015
|
-
globalHistory.go(delta);
|
|
3016
|
-
}
|
|
3017
|
-
var history = {
|
|
3018
|
-
get action() {
|
|
3019
|
-
return action;
|
|
3020
|
-
},
|
|
3021
|
-
get location() {
|
|
3022
|
-
return location;
|
|
3023
|
-
},
|
|
3024
|
-
createHref,
|
|
3025
|
-
push,
|
|
3026
|
-
replace,
|
|
3027
|
-
go,
|
|
3028
|
-
back: function back() {
|
|
3029
|
-
go(-1);
|
|
3030
|
-
},
|
|
3031
|
-
forward: function forward() {
|
|
3032
|
-
go(1);
|
|
3033
|
-
},
|
|
3034
|
-
listen: function listen(listener) {
|
|
3035
|
-
return listeners.push(listener);
|
|
3036
|
-
},
|
|
3037
|
-
block: function block(blocker) {
|
|
3038
|
-
var unblock = blockers.push(blocker);
|
|
3039
|
-
if (blockers.length === 1) {
|
|
3040
|
-
window2.addEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
3041
|
-
}
|
|
3042
|
-
return function() {
|
|
3043
|
-
unblock();
|
|
3044
|
-
if (!blockers.length) {
|
|
3045
|
-
window2.removeEventListener(BeforeUnloadEventType, promptBeforeUnload);
|
|
3046
|
-
}
|
|
3047
|
-
};
|
|
3048
|
-
}
|
|
3049
|
-
};
|
|
3050
|
-
return history;
|
|
3051
|
-
}
|
|
3052
|
-
function promptBeforeUnload(event) {
|
|
3053
|
-
event.preventDefault();
|
|
3054
|
-
event.returnValue = "";
|
|
3055
|
-
}
|
|
3056
|
-
function createEvents() {
|
|
3057
|
-
var handlers = [];
|
|
3058
|
-
return {
|
|
3059
|
-
get length() {
|
|
3060
|
-
return handlers.length;
|
|
3061
|
-
},
|
|
3062
|
-
push: function push(fn) {
|
|
3063
|
-
handlers.push(fn);
|
|
3064
|
-
return function() {
|
|
3065
|
-
handlers = handlers.filter(function(handler) {
|
|
3066
|
-
return handler !== fn;
|
|
3067
|
-
});
|
|
3068
|
-
};
|
|
3069
|
-
},
|
|
3070
|
-
call: function call(arg) {
|
|
3071
|
-
handlers.forEach(function(fn) {
|
|
3072
|
-
return fn && fn(arg);
|
|
3073
|
-
});
|
|
3074
|
-
}
|
|
3075
|
-
};
|
|
3076
|
-
}
|
|
3077
|
-
function createKey() {
|
|
3078
|
-
return Math.random().toString(36).substr(2, 8);
|
|
3079
|
-
}
|
|
3080
|
-
function createPath(_ref) {
|
|
3081
|
-
var _ref$pathname = _ref.pathname, pathname = _ref$pathname === void 0 ? "/" : _ref$pathname, _ref$search = _ref.search, search = _ref$search === void 0 ? "" : _ref$search, _ref$hash = _ref.hash, hash2 = _ref$hash === void 0 ? "" : _ref$hash;
|
|
3082
|
-
if (search && search !== "?")
|
|
3083
|
-
pathname += search.charAt(0) === "?" ? search : "?" + search;
|
|
3084
|
-
if (hash2 && hash2 !== "#")
|
|
3085
|
-
pathname += hash2.charAt(0) === "#" ? hash2 : "#" + hash2;
|
|
3086
|
-
return pathname;
|
|
3087
|
-
}
|
|
3088
|
-
function parsePath(path) {
|
|
3089
|
-
var parsedPath = {};
|
|
3090
|
-
if (path) {
|
|
3091
|
-
var hashIndex = path.indexOf("#");
|
|
3092
|
-
if (hashIndex >= 0) {
|
|
3093
|
-
parsedPath.hash = path.substr(hashIndex);
|
|
3094
|
-
path = path.substr(0, hashIndex);
|
|
3095
|
-
}
|
|
3096
|
-
var searchIndex = path.indexOf("?");
|
|
3097
|
-
if (searchIndex >= 0) {
|
|
3098
|
-
parsedPath.search = path.substr(searchIndex);
|
|
3099
|
-
path = path.substr(0, searchIndex);
|
|
3100
|
-
}
|
|
3101
|
-
if (path) {
|
|
3102
|
-
parsedPath.pathname = path;
|
|
3103
|
-
}
|
|
3104
|
-
}
|
|
3105
|
-
return parsedPath;
|
|
3106
|
-
}
|
|
3107
|
-
|
|
3108
|
-
// src/routing.ts
|
|
3109
|
-
function splitPath(path) {
|
|
3110
|
-
assertString(path, "Expected `path` to be a string. Got type: %t, value: %v");
|
|
3111
|
-
return path.split("/").map((f) => f.trim()).filter((f) => f !== "");
|
|
3112
|
-
}
|
|
3113
|
-
function joinPath(parts) {
|
|
3114
|
-
assertArrayOf(
|
|
3115
|
-
(part) => isFunction(part?.toString),
|
|
3116
|
-
parts,
|
|
3117
|
-
"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v"
|
|
3118
|
-
);
|
|
3119
|
-
parts = parts.filter((x) => x).flatMap(String);
|
|
3120
|
-
let joined = parts.shift()?.toString();
|
|
3121
|
-
if (joined) {
|
|
3122
|
-
for (const part of parts.map((p) => p.toString())) {
|
|
3123
|
-
if (part.startsWith(".")) {
|
|
3124
|
-
joined = resolvePath(joined, part);
|
|
3125
|
-
} else if (joined[joined.length - 1] !== "/") {
|
|
3126
|
-
if (part[0] !== "/") {
|
|
3127
|
-
joined += "/" + part;
|
|
3128
|
-
} else {
|
|
3129
|
-
joined += part;
|
|
3130
|
-
}
|
|
3131
|
-
} else {
|
|
3132
|
-
if (part[0] === "/") {
|
|
3133
|
-
joined += part.slice(1);
|
|
3134
|
-
} else {
|
|
3135
|
-
joined += part;
|
|
3136
|
-
}
|
|
3137
|
-
}
|
|
3138
|
-
}
|
|
3139
|
-
if (joined && joined !== "/" && joined.endsWith("/")) {
|
|
3140
|
-
joined = joined.slice(0, joined.length - 1);
|
|
3141
|
-
}
|
|
3142
|
-
}
|
|
3143
|
-
return joined ?? "";
|
|
3144
|
-
}
|
|
3145
|
-
function resolvePath(base, part) {
|
|
3146
|
-
assertString(base, "Expected `base` to be a string. Got type: %t, value: %v");
|
|
3147
|
-
if (part == null) {
|
|
3148
|
-
part = base;
|
|
3149
|
-
base = "";
|
|
3150
|
-
}
|
|
3151
|
-
if (part.startsWith("/")) {
|
|
3152
|
-
return part;
|
|
3153
|
-
}
|
|
3154
|
-
let resolved = base;
|
|
3155
|
-
while (true) {
|
|
3156
|
-
if (part.startsWith("..")) {
|
|
3157
|
-
for (let i = resolved.length; i > 0; --i) {
|
|
3158
|
-
if (resolved[i] === "/" || i === 0) {
|
|
3159
|
-
resolved = resolved.slice(0, i);
|
|
3160
|
-
part = part.replace(/^\.\.\/?/, "");
|
|
3161
|
-
break;
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
} else if (part.startsWith(".")) {
|
|
3165
|
-
part = part.replace(/^\.\/?/, "");
|
|
3166
|
-
} else {
|
|
3167
|
-
break;
|
|
3168
|
-
}
|
|
3169
|
-
}
|
|
3170
|
-
return joinPath([resolved, part]);
|
|
3171
|
-
}
|
|
3172
|
-
function parseQueryParams(query) {
|
|
3173
|
-
if (!query)
|
|
3174
|
-
return {};
|
|
3175
|
-
if (query.startsWith("?")) {
|
|
3176
|
-
query = query.slice(1);
|
|
3177
|
-
}
|
|
3178
|
-
const entries = query.split("&").filter((x) => x.trim() !== "").map((entry) => {
|
|
3179
|
-
const [key, value] = entry.split("=").map((x) => x.trim());
|
|
3180
|
-
if (value.toLowerCase() === "true") {
|
|
3181
|
-
return [key, true];
|
|
3182
|
-
}
|
|
3183
|
-
if (value.toLowerCase() === "false") {
|
|
3184
|
-
return [key, false];
|
|
3185
|
-
}
|
|
3186
|
-
if (!isNaN(Number(value))) {
|
|
3187
|
-
return [key, Number(value)];
|
|
3188
|
-
}
|
|
3189
|
-
return [key, value];
|
|
3190
|
-
});
|
|
3191
|
-
return Object.fromEntries(entries);
|
|
3192
|
-
}
|
|
3193
|
-
function matchRoutes(routes, url, options = {}) {
|
|
3194
|
-
const [path, query] = url.split("?");
|
|
3195
|
-
const parts = splitPath(path);
|
|
3196
|
-
routes:
|
|
3197
|
-
for (const route of routes) {
|
|
3198
|
-
const { fragments } = route;
|
|
3199
|
-
const hasWildcard = fragments[fragments.length - 1]?.type === 3 /* Wildcard */;
|
|
3200
|
-
if (!hasWildcard && fragments.length !== parts.length) {
|
|
3201
|
-
continue routes;
|
|
3202
|
-
}
|
|
3203
|
-
if (options.willMatch && !options.willMatch(route)) {
|
|
3204
|
-
continue routes;
|
|
3205
|
-
}
|
|
3206
|
-
const matched = [];
|
|
3207
|
-
fragments:
|
|
3208
|
-
for (let i = 0; i < fragments.length; i++) {
|
|
3209
|
-
const part = parts[i];
|
|
3210
|
-
const frag = fragments[i];
|
|
3211
|
-
if (part == null && frag.type !== 3 /* Wildcard */) {
|
|
3212
|
-
continue routes;
|
|
3213
|
-
}
|
|
3214
|
-
switch (frag.type) {
|
|
3215
|
-
case 1 /* Literal */:
|
|
3216
|
-
if (frag.name.toLowerCase() === part.toLowerCase()) {
|
|
3217
|
-
matched.push(frag);
|
|
3218
|
-
break;
|
|
3219
|
-
} else {
|
|
3220
|
-
continue routes;
|
|
3221
|
-
}
|
|
3222
|
-
case 2 /* Param */:
|
|
3223
|
-
matched.push({ ...frag, value: part });
|
|
3224
|
-
break;
|
|
3225
|
-
case 3 /* Wildcard */:
|
|
3226
|
-
matched.push({ ...frag, value: parts.slice(i).join("/") });
|
|
3227
|
-
break fragments;
|
|
3228
|
-
case 4 /* NumericParam */:
|
|
3229
|
-
if (!isNaN(Number(part))) {
|
|
3230
|
-
matched.push({ ...frag, value: Number(part) });
|
|
3231
|
-
break;
|
|
3232
|
-
} else {
|
|
3233
|
-
continue routes;
|
|
3234
|
-
}
|
|
3235
|
-
default:
|
|
3236
|
-
throw new Error(`Unknown fragment type: ${frag.type}`);
|
|
3237
|
-
}
|
|
3238
|
-
}
|
|
3239
|
-
const params = /* @__PURE__ */ Object.create(null);
|
|
3240
|
-
for (const frag of matched) {
|
|
3241
|
-
if (frag.type === 2 /* Param */) {
|
|
3242
|
-
params[frag.name] = decodeURIComponent(frag.value);
|
|
3243
|
-
}
|
|
3244
|
-
if (frag.type === 4 /* NumericParam */) {
|
|
3245
|
-
params[frag.name] = frag.value;
|
|
3246
|
-
}
|
|
3247
|
-
if (frag.type === 3 /* Wildcard */) {
|
|
3248
|
-
params.wildcard = "/" + decodeURIComponent(frag.value);
|
|
3249
|
-
}
|
|
3250
|
-
}
|
|
3251
|
-
return {
|
|
3252
|
-
path: "/" + matched.map((f) => f.value).join("/"),
|
|
3253
|
-
pattern: "/" + fragments.map((f) => {
|
|
3254
|
-
if (f.type === 2 /* Param */) {
|
|
3255
|
-
return `{${f.name}}`;
|
|
3256
|
-
}
|
|
3257
|
-
if (f.type === 4 /* NumericParam */) {
|
|
3258
|
-
return `{#${f.name}}`;
|
|
3259
|
-
}
|
|
3260
|
-
return f.name;
|
|
3261
|
-
}).join("/"),
|
|
3262
|
-
params,
|
|
3263
|
-
query: parseQueryParams(query),
|
|
3264
|
-
meta: route.meta
|
|
3265
|
-
};
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
function sortRoutes(routes) {
|
|
3269
|
-
const withoutParams = [];
|
|
3270
|
-
const withNumericParams = [];
|
|
3271
|
-
const withParams = [];
|
|
3272
|
-
const wildcard = [];
|
|
3273
|
-
for (const route of routes) {
|
|
3274
|
-
const { fragments } = route;
|
|
3275
|
-
if (fragments.some((f) => f.type === 3 /* Wildcard */)) {
|
|
3276
|
-
wildcard.push(route);
|
|
3277
|
-
} else if (fragments.some((f) => f.type === 4 /* NumericParam */)) {
|
|
3278
|
-
withNumericParams.push(route);
|
|
3279
|
-
} else if (fragments.some((f) => f.type === 2 /* Param */)) {
|
|
3280
|
-
withParams.push(route);
|
|
3281
|
-
} else {
|
|
3282
|
-
withoutParams.push(route);
|
|
3283
|
-
}
|
|
3284
|
-
}
|
|
3285
|
-
const bySizeDesc = (a, b) => {
|
|
3286
|
-
if (a.fragments.length > b.fragments.length) {
|
|
3287
|
-
return -1;
|
|
3288
|
-
} else {
|
|
3289
|
-
return 1;
|
|
3290
|
-
}
|
|
3291
|
-
};
|
|
3292
|
-
withoutParams.sort(bySizeDesc);
|
|
3293
|
-
withNumericParams.sort(bySizeDesc);
|
|
3294
|
-
withParams.sort(bySizeDesc);
|
|
3295
|
-
wildcard.sort(bySizeDesc);
|
|
3296
|
-
return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];
|
|
3297
|
-
}
|
|
3298
|
-
function patternToFragments(pattern) {
|
|
3299
|
-
const parts = splitPath(pattern);
|
|
3300
|
-
const fragments = [];
|
|
3301
|
-
for (let i = 0; i < parts.length; i++) {
|
|
3302
|
-
const part = parts[i];
|
|
3303
|
-
if (part === "*") {
|
|
3304
|
-
if (i !== parts.length - 1) {
|
|
3305
|
-
throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);
|
|
3306
|
-
}
|
|
3307
|
-
fragments.push({
|
|
3308
|
-
type: 3 /* Wildcard */,
|
|
3309
|
-
name: "*",
|
|
3310
|
-
value: null
|
|
3311
|
-
});
|
|
3312
|
-
} else if (part.at(0) === "{" && part.at(-1) === "}") {
|
|
3313
|
-
fragments.push({
|
|
3314
|
-
type: part[1] === "#" ? 4 /* NumericParam */ : 2 /* Param */,
|
|
3315
|
-
name: part[1] === "#" ? part.slice(2, -1) : part.slice(1, -1),
|
|
3316
|
-
value: null
|
|
3317
|
-
});
|
|
3318
|
-
} else {
|
|
3319
|
-
fragments.push({
|
|
3320
|
-
type: 1 /* Literal */,
|
|
3321
|
-
name: part,
|
|
3322
|
-
value: part
|
|
3323
|
-
});
|
|
3324
|
-
}
|
|
3325
|
-
}
|
|
3326
|
-
return fragments;
|
|
3327
|
-
}
|
|
3328
|
-
|
|
3329
|
-
// src/stores/router.ts
|
|
3330
|
-
function RouterStore(ctx) {
|
|
3331
|
-
ctx.name = "dolla/router";
|
|
3332
|
-
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
3333
|
-
const render = ctx.getStore("render");
|
|
3334
|
-
let history;
|
|
3335
|
-
if (ctx.options.history) {
|
|
3336
|
-
history = ctx.options.history;
|
|
3337
|
-
} else if (ctx.options.hash) {
|
|
3338
|
-
history = createHashHistory();
|
|
3339
|
-
} else {
|
|
3340
|
-
history = createBrowserHistory();
|
|
3341
|
-
}
|
|
3342
|
-
let layerId = 0;
|
|
3343
|
-
function prepareRoute(route, parents = [], layers = []) {
|
|
3344
|
-
if (!(typeof route === "object" && !Array.isArray(route)) || !(typeof route.path === "string")) {
|
|
3345
|
-
throw new TypeError(`Route configs must be objects with a 'path' string property. Got: ${route}`);
|
|
3346
|
-
}
|
|
3347
|
-
if (route.redirect && route.routes) {
|
|
3348
|
-
throw new Error(`Route cannot have both a 'redirect' and nested 'routes'.`);
|
|
3349
|
-
} else if (route.redirect && route.view) {
|
|
3350
|
-
throw new Error(`Route cannot have both a 'redirect' and a 'view'.`);
|
|
3351
|
-
} else if (!route.view && !route.routes && !route.redirect) {
|
|
3352
|
-
throw new Error(`Route must have a 'view', a 'redirect', or a set of nested 'routes'.`);
|
|
3353
|
-
}
|
|
3354
|
-
let parts = [];
|
|
3355
|
-
for (const parent2 of parents) {
|
|
3356
|
-
parts.push(...splitPath(parent2.path));
|
|
3357
|
-
}
|
|
3358
|
-
parts.push(...splitPath(route.path));
|
|
3359
|
-
if (parts[parts.length - 1] === "*") {
|
|
3360
|
-
parts.pop();
|
|
3361
|
-
}
|
|
3362
|
-
const routes2 = [];
|
|
3363
|
-
if (route.redirect) {
|
|
3364
|
-
let redirect = route.redirect;
|
|
3365
|
-
if (isString(redirect)) {
|
|
3366
|
-
redirect = resolvePath(joinPath(parts), redirect);
|
|
3367
|
-
if (!redirect.startsWith("/")) {
|
|
3368
|
-
redirect = "/" + redirect;
|
|
3369
|
-
}
|
|
3370
|
-
}
|
|
3371
|
-
routes2.push({
|
|
3372
|
-
pattern: "/" + joinPath([...parts, ...splitPath(route.path)]),
|
|
3373
|
-
meta: {
|
|
3374
|
-
redirect
|
|
3375
|
-
}
|
|
3376
|
-
});
|
|
3377
|
-
return routes2;
|
|
3378
|
-
}
|
|
3379
|
-
let view = DefaultView;
|
|
3380
|
-
if (typeof route.view === "function") {
|
|
3381
|
-
view = route.view;
|
|
3382
|
-
} else if (route.view) {
|
|
3383
|
-
throw new TypeError(`Route '${route.path}' expected a view function or undefined. Got: ${route.view}`);
|
|
3384
|
-
}
|
|
3385
|
-
const markup = m(view);
|
|
3386
|
-
const layer = { id: layerId++, markup };
|
|
3387
|
-
if (route.routes) {
|
|
3388
|
-
for (const subroute of route.routes) {
|
|
3389
|
-
routes2.push(...prepareRoute(subroute, [...parents, route], [...layers, layer]));
|
|
3390
|
-
}
|
|
3391
|
-
} else {
|
|
3392
|
-
routes2.push({
|
|
3393
|
-
pattern: parent ? joinPath([...parents.map((p) => p.path), route.path]) : route.path,
|
|
3394
|
-
meta: {
|
|
3395
|
-
pattern: route.path,
|
|
3396
|
-
layers: [...layers, layer],
|
|
3397
|
-
beforeMatch: route.beforeMatch
|
|
3398
|
-
}
|
|
3399
|
-
});
|
|
3400
|
-
}
|
|
3401
|
-
return routes2;
|
|
3402
|
-
}
|
|
3403
|
-
const routes = sortRoutes(
|
|
3404
|
-
ctx.options.routes.flatMap((route) => prepareRoute(route)).map((route) => ({
|
|
3405
|
-
pattern: route.pattern,
|
|
3406
|
-
meta: route.meta,
|
|
3407
|
-
fragments: patternToFragments(route.pattern)
|
|
3408
|
-
}))
|
|
3409
|
-
);
|
|
3410
|
-
for (const route of routes) {
|
|
3411
|
-
if (route.meta.redirect) {
|
|
3412
|
-
let redirectPath;
|
|
3413
|
-
if (isFunction(route.meta.redirect)) {
|
|
3414
|
-
} else if (isString(route.meta.redirect)) {
|
|
3415
|
-
redirectPath = route.meta.redirect;
|
|
3416
|
-
const match = matchRoutes(routes, redirectPath, {
|
|
3417
|
-
willMatch(r) {
|
|
3418
|
-
return r !== route;
|
|
3419
|
-
}
|
|
3420
|
-
});
|
|
3421
|
-
if (!match) {
|
|
3422
|
-
throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);
|
|
3423
|
-
}
|
|
3424
|
-
} else {
|
|
3425
|
-
throw new TypeError(`Expected a string or redirect function. Got: ${route.meta.redirect}`);
|
|
3426
|
-
}
|
|
3427
|
-
}
|
|
3428
|
-
}
|
|
3429
|
-
ctx.onConnected(() => {
|
|
3430
|
-
ctx.info("Routes registered:", routes);
|
|
3431
|
-
});
|
|
3432
|
-
const [$pattern, setPattern] = signal(null);
|
|
3433
|
-
const [$path, setPath] = signal("");
|
|
3434
|
-
const [$params, setParams] = signal({});
|
|
3435
|
-
const [$query, setQuery] = signal(parseQueryParams(window.location.search));
|
|
3436
|
-
ctx.watch([$query], (current) => {
|
|
3437
|
-
const params = new URLSearchParams();
|
|
3438
|
-
for (const key in current) {
|
|
3439
|
-
params.set(key, String(current[key]));
|
|
3440
|
-
}
|
|
3441
|
-
const search = "?" + params.toString();
|
|
3442
|
-
if (search != history.location.search) {
|
|
3443
|
-
history.replace({
|
|
3444
|
-
pathname: history.location.pathname,
|
|
3445
|
-
search
|
|
3446
|
-
});
|
|
3447
|
-
}
|
|
3448
|
-
});
|
|
3449
|
-
ctx.onConnected(() => {
|
|
3450
|
-
history.listen(onRouteChange);
|
|
3451
|
-
onRouteChange(history);
|
|
3452
|
-
ctx.info("Intercepting <a> clicks within root element:", appContext.rootElement);
|
|
3453
|
-
catchLinks(appContext.rootElement, (anchor) => {
|
|
3454
|
-
let href = anchor.getAttribute("href");
|
|
3455
|
-
ctx.info("Intercepted link click", anchor, href);
|
|
3456
|
-
if (!/^https?:\/\/|^\//.test(href)) {
|
|
3457
|
-
href = joinPath([history.location.pathname, href]);
|
|
3458
|
-
}
|
|
3459
|
-
history.push(href);
|
|
3460
|
-
});
|
|
3461
|
-
});
|
|
3462
|
-
let activeLayers = [];
|
|
3463
|
-
let lastQuery;
|
|
3464
|
-
const onRouteChange = async ({ location }) => {
|
|
3465
|
-
if (location.search !== lastQuery) {
|
|
3466
|
-
lastQuery = location.search;
|
|
3467
|
-
setQuery(parseQueryParams(location.search));
|
|
3468
|
-
}
|
|
3469
|
-
const matched = matchRoutes(routes, location.pathname);
|
|
3470
|
-
if (!matched) {
|
|
3471
|
-
setPattern(null);
|
|
3472
|
-
setPath(location.pathname);
|
|
3473
|
-
setParams({
|
|
3474
|
-
wildcard: location.pathname
|
|
3475
|
-
});
|
|
3476
|
-
return;
|
|
3477
|
-
}
|
|
3478
|
-
if (matched.meta.beforeMatch) {
|
|
3479
|
-
await matched.meta.beforeMatch({
|
|
3480
|
-
getStore(store) {
|
|
3481
|
-
let name;
|
|
3482
|
-
if (typeof store === "string") {
|
|
3483
|
-
name = store;
|
|
3484
|
-
} else {
|
|
3485
|
-
name = store.name;
|
|
3486
|
-
}
|
|
3487
|
-
if (typeof store !== "string") {
|
|
3488
|
-
let ec = elementContext;
|
|
3489
|
-
while (ec) {
|
|
3490
|
-
if (ec.stores.has(store)) {
|
|
3491
|
-
return ec.stores.get(store)?.instance.exports;
|
|
3492
|
-
}
|
|
3493
|
-
ec = ec.parent;
|
|
3494
|
-
}
|
|
3495
|
-
}
|
|
3496
|
-
if (appContext.stores.has(store)) {
|
|
3497
|
-
const _store = appContext.stores.get(store);
|
|
3498
|
-
if (!_store.instance) {
|
|
3499
|
-
appContext.crashCollector.crash({
|
|
3500
|
-
componentName: ctx.name,
|
|
3501
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
3502
|
-
});
|
|
3503
|
-
}
|
|
3504
|
-
return _store.instance.exports;
|
|
3505
|
-
}
|
|
3506
|
-
appContext.crashCollector.crash({
|
|
3507
|
-
componentName: ctx.name,
|
|
3508
|
-
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
3509
|
-
});
|
|
3510
|
-
},
|
|
3511
|
-
redirect: (path) => {
|
|
3512
|
-
throw new Error(`Redirect not yet implemented.`);
|
|
3513
|
-
}
|
|
3514
|
-
});
|
|
3515
|
-
}
|
|
3516
|
-
ctx.info(`Matched route: '${matched.pattern}' ('${matched.path}')`);
|
|
3517
|
-
if (matched.meta.redirect != null) {
|
|
3518
|
-
if (typeof matched.meta.redirect === "string") {
|
|
3519
|
-
const path = replaceParams(matched.meta.redirect, matched.params);
|
|
3520
|
-
ctx.info(`Redirecting to: '${path}'`);
|
|
3521
|
-
history.replace(path);
|
|
3522
|
-
} else if (typeof matched.meta.redirect === "function") {
|
|
3523
|
-
const redirectContext = {
|
|
3524
|
-
path: matched.path,
|
|
3525
|
-
pattern: matched.pattern,
|
|
3526
|
-
params: matched.params,
|
|
3527
|
-
query: matched.query
|
|
3528
|
-
};
|
|
3529
|
-
let path = await matched.meta.redirect(redirectContext);
|
|
3530
|
-
if (typeof path !== "string") {
|
|
3531
|
-
throw new Error(`Redirect function must return a path to redirect to.`);
|
|
3532
|
-
}
|
|
3533
|
-
if (!path.startsWith("/")) {
|
|
3534
|
-
path = resolvePath(matched.path, path);
|
|
3535
|
-
}
|
|
3536
|
-
ctx.info(`Redirecting to: '${path}'`);
|
|
3537
|
-
history.replace(path);
|
|
3538
|
-
} else {
|
|
3539
|
-
throw new TypeError(`Redirect must either be a path string or a function.`);
|
|
3540
|
-
}
|
|
3541
|
-
} else {
|
|
3542
|
-
setPath(matched.path);
|
|
3543
|
-
setParams(matched.params);
|
|
3544
|
-
if (matched.pattern !== $pattern.get()) {
|
|
3545
|
-
setPattern(matched.pattern);
|
|
3546
|
-
const layers = matched.meta.layers;
|
|
3547
|
-
for (let i = 0; i < layers.length; i++) {
|
|
3548
|
-
const matchedLayer = layers[i];
|
|
3549
|
-
const activeLayer = activeLayers[i];
|
|
3550
|
-
if (activeLayer?.id !== matchedLayer.id) {
|
|
3551
|
-
ctx.info(`Replacing layer @${i} (active ID: ${activeLayer?.id}, matched ID: ${matchedLayer.id})`);
|
|
3552
|
-
activeLayers = activeLayers.slice(0, i);
|
|
3553
|
-
const parentLayer = activeLayers[activeLayers.length - 1];
|
|
3554
|
-
const renderContext = { appContext, elementContext };
|
|
3555
|
-
const rendered = renderMarkupToDOM(matchedLayer.markup, renderContext);
|
|
3556
|
-
const handle = getRenderHandle(rendered);
|
|
3557
|
-
if (activeLayer && activeLayer.handle.connected) {
|
|
3558
|
-
activeLayer.handle.disconnect();
|
|
3559
|
-
}
|
|
3560
|
-
if (parentLayer) {
|
|
3561
|
-
parentLayer.handle.setChildren(rendered);
|
|
3562
|
-
} else {
|
|
3563
|
-
appContext.rootView.setChildren(rendered);
|
|
3564
|
-
}
|
|
3565
|
-
activeLayers.push({ id: matchedLayer.id, handle });
|
|
3566
|
-
}
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
};
|
|
3571
|
-
function navigate(path, options = {}) {
|
|
3572
|
-
let joined;
|
|
3573
|
-
if (Array.isArray(path)) {
|
|
3574
|
-
joined = joinPath(path);
|
|
3575
|
-
} else {
|
|
3576
|
-
joined = path.toString();
|
|
3577
|
-
}
|
|
3578
|
-
joined = resolvePath(history.location.pathname, joined);
|
|
3579
|
-
if (options.preserveQuery) {
|
|
3580
|
-
joined += history.location.search;
|
|
3581
|
-
}
|
|
3582
|
-
if (options.replace) {
|
|
3583
|
-
history.replace(joined);
|
|
3584
|
-
} else {
|
|
3585
|
-
history.push(joined);
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
|
-
return {
|
|
3589
|
-
/**
|
|
3590
|
-
* The currently matched route pattern, if any.
|
|
3591
|
-
*/
|
|
3592
|
-
$pattern,
|
|
3593
|
-
/**
|
|
3594
|
-
* The current URL path.
|
|
3595
|
-
*/
|
|
3596
|
-
$path,
|
|
3597
|
-
/**
|
|
3598
|
-
* The current named path params.
|
|
3599
|
-
*/
|
|
3600
|
-
$params,
|
|
3601
|
-
/**
|
|
3602
|
-
* The current query params. Changes to this object will be reflected in the URL.
|
|
3603
|
-
*/
|
|
3604
|
-
$query,
|
|
3605
|
-
setQuery,
|
|
3606
|
-
/**
|
|
3607
|
-
* Navigate backward. Pass a number of steps to hit the back button that many times.
|
|
3608
|
-
*/
|
|
3609
|
-
back(steps = 1) {
|
|
3610
|
-
history.go(-steps);
|
|
3611
|
-
},
|
|
3612
|
-
/**
|
|
3613
|
-
* Navigate forward. Pass a number of steps to hit the forward button that many times.
|
|
3614
|
-
*/
|
|
3615
|
-
forward(steps = 1) {
|
|
3616
|
-
history.go(steps);
|
|
3617
|
-
},
|
|
3618
|
-
/**
|
|
3619
|
-
* Navigates to another route.
|
|
3620
|
-
*
|
|
3621
|
-
* @example
|
|
3622
|
-
* navigate("/login"); // navigate to `/login`
|
|
3623
|
-
* navigate(["/users", 215], { replace: true }); // replace current history entry with `/users/215`
|
|
3624
|
-
*
|
|
3625
|
-
* @param args - One or more path segments optionally followed by an options object.
|
|
3626
|
-
*/
|
|
3627
|
-
navigate
|
|
3628
|
-
/**
|
|
3629
|
-
* Updates a query param in place.
|
|
3630
|
-
*/
|
|
3631
|
-
// updateQuery(key: string, value: string) {},
|
|
3632
|
-
/**
|
|
3633
|
-
* Updates a route param in place.
|
|
3634
|
-
*/
|
|
3635
|
-
// updateParam(key: string, value: string) {},
|
|
3636
|
-
};
|
|
3637
|
-
}
|
|
3638
|
-
var safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/;
|
|
3639
|
-
var protocolLink = /^[\w-_]+:/;
|
|
3640
|
-
function catchLinks(root, callback, _window = window) {
|
|
3641
|
-
function traverse(node) {
|
|
3642
|
-
if (!node || node === root) {
|
|
3643
|
-
return null;
|
|
3644
|
-
}
|
|
3645
|
-
if (node.localName !== "a" || node.href === void 0) {
|
|
3646
|
-
return traverse(node.parentNode);
|
|
3647
|
-
}
|
|
3648
|
-
return node;
|
|
3649
|
-
}
|
|
3650
|
-
function handler(e) {
|
|
3651
|
-
if (e.button && e.button !== 0 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) {
|
|
3652
|
-
return;
|
|
3653
|
-
}
|
|
3654
|
-
const anchor = traverse(e.target);
|
|
3655
|
-
if (!anchor) {
|
|
3656
|
-
return;
|
|
3657
|
-
}
|
|
3658
|
-
if (_window.location.protocol !== anchor.protocol || _window.location.hostname !== anchor.hostname || _window.location.port !== anchor.port || anchor.hasAttribute("data-router-ignore") || anchor.hasAttribute("download") || anchor.getAttribute("target") === "_blank" && safeExternalLink.test(anchor.getAttribute("rel")) || protocolLink.test(anchor.getAttribute("href"))) {
|
|
3659
|
-
return;
|
|
3660
|
-
}
|
|
3661
|
-
e.preventDefault();
|
|
3662
|
-
callback(anchor);
|
|
3663
|
-
}
|
|
3664
|
-
root.addEventListener("click", handler);
|
|
3665
|
-
return function cancel() {
|
|
3666
|
-
root.removeEventListener("click", handler);
|
|
3667
|
-
};
|
|
3668
|
-
}
|
|
3669
|
-
function replaceParams(path, params) {
|
|
3670
|
-
for (const key in params) {
|
|
3671
|
-
const value = params[key].toString();
|
|
3672
|
-
path = path.replace(`{${key}}`, value).replace(`{#${key}}`, value);
|
|
3673
|
-
}
|
|
3674
|
-
return path;
|
|
3675
|
-
}
|
|
3676
|
-
|
|
3677
|
-
// src/stores/language.ts
|
|
3678
|
-
function LanguageStore(ctx) {
|
|
3679
|
-
ctx.name = "dolla/language";
|
|
3680
|
-
const languages = /* @__PURE__ */ new Map();
|
|
3681
|
-
const cache = /* @__PURE__ */ new Map();
|
|
3682
|
-
ctx.options.languages.forEach((entry) => {
|
|
3683
|
-
languages.set(entry.name, entry);
|
|
3684
|
-
});
|
|
3685
|
-
ctx.info(
|
|
3686
|
-
`App supports ${languages.size} language${languages.size === 1 ? "" : "s"}: '${[...languages.keys()].join("', '")}'`
|
|
3687
|
-
);
|
|
3688
|
-
async function getTranslation(config) {
|
|
3689
|
-
if (!cache.has(config.name)) {
|
|
3690
|
-
let fn;
|
|
3691
|
-
if (isString(config.translations)) {
|
|
3692
|
-
fn = async () => {
|
|
3693
|
-
return fetch(config.translations).then((res) => res.json());
|
|
3694
|
-
};
|
|
3695
|
-
} else if (isFunction(config.translations)) {
|
|
3696
|
-
fn = async () => config.translations();
|
|
3697
|
-
} else if (isObject(config.translations)) {
|
|
3698
|
-
fn = async () => config.translations;
|
|
3699
|
-
} else {
|
|
3700
|
-
throw new TypeError(
|
|
3701
|
-
`Translation of '${config.name}' must be an object of translated strings, a path to an object of translated strings, a function that returns one, or an async function that resolves to one. Got type: ${typeOf(
|
|
3702
|
-
config.translations
|
|
3703
|
-
)}, value: ${config.translations}`
|
|
3704
|
-
);
|
|
3705
|
-
}
|
|
3706
|
-
try {
|
|
3707
|
-
const translation = await fn();
|
|
3708
|
-
assertObject(
|
|
3709
|
-
translation,
|
|
3710
|
-
`Expected '${config.name}' translations to resolve to an object. Got type: %t, value: %v`
|
|
3711
|
-
);
|
|
3712
|
-
cache.set(config.name, translation);
|
|
3713
|
-
} catch (err) {
|
|
3714
|
-
throw err;
|
|
3715
|
-
}
|
|
3716
|
-
}
|
|
3717
|
-
return cache.get(config.name);
|
|
3718
|
-
}
|
|
3719
|
-
const [$loaded, setLoaded] = signal(false);
|
|
3720
|
-
const [$language, _setLanguage] = signal();
|
|
3721
|
-
const [$translation, setTranslation] = signal();
|
|
3722
|
-
const [$noLanguageValue] = signal("[NO LANGUAGE SET]");
|
|
3723
|
-
const translationCache = [];
|
|
3724
|
-
function getCached(key, values) {
|
|
3725
|
-
for (const entry of translationCache) {
|
|
3726
|
-
if (entry[0] === key && deepEqual(entry[1], values)) {
|
|
3727
|
-
return entry[2];
|
|
3728
|
-
}
|
|
3729
|
-
}
|
|
3730
|
-
}
|
|
3731
|
-
function replaceMustaches(template, values) {
|
|
3732
|
-
for (const name in values) {
|
|
3733
|
-
template = template.replace(`{{${name}}}`, String(values[name]));
|
|
3734
|
-
}
|
|
3735
|
-
return template;
|
|
3736
|
-
}
|
|
3737
|
-
async function setLanguage(tag) {
|
|
3738
|
-
let realTag;
|
|
3739
|
-
if (tag === "auto") {
|
|
3740
|
-
let tags = [];
|
|
3741
|
-
if (typeof navigator === "object") {
|
|
3742
|
-
const nav = navigator;
|
|
3743
|
-
if (nav.languages?.length > 0) {
|
|
3744
|
-
tags.push(...nav.languages);
|
|
3745
|
-
} else if (nav.language) {
|
|
3746
|
-
tags.push(nav.language);
|
|
3747
|
-
} else if (nav.browserLanguage) {
|
|
3748
|
-
tags.push(nav.browserLanguage);
|
|
3749
|
-
} else if (nav.userLanguage) {
|
|
3750
|
-
tags.push(nav.userLanguage);
|
|
3751
|
-
}
|
|
3752
|
-
}
|
|
3753
|
-
for (const tag2 of tags) {
|
|
3754
|
-
if (languages.has(tag2)) {
|
|
3755
|
-
realTag = tag2;
|
|
3756
|
-
}
|
|
3757
|
-
}
|
|
3758
|
-
} else {
|
|
3759
|
-
if (languages.has(tag)) {
|
|
3760
|
-
realTag = tag;
|
|
3761
|
-
}
|
|
3762
|
-
}
|
|
3763
|
-
if (realTag == null) {
|
|
3764
|
-
const firstLanguage = ctx.options.languages[0];
|
|
3765
|
-
if (firstLanguage) {
|
|
3766
|
-
realTag = firstLanguage.name;
|
|
3767
|
-
}
|
|
3768
|
-
}
|
|
3769
|
-
if (!realTag || !languages.has(realTag)) {
|
|
3770
|
-
throw new Error(`Language '${tag}' is not configured for this app.`);
|
|
3771
|
-
}
|
|
3772
|
-
const lang = languages.get(realTag);
|
|
3773
|
-
try {
|
|
3774
|
-
const translation = await getTranslation(lang);
|
|
3775
|
-
setTranslation(translation);
|
|
3776
|
-
_setLanguage(realTag);
|
|
3777
|
-
ctx.info("set language to " + realTag);
|
|
3778
|
-
} catch (error) {
|
|
3779
|
-
if (error instanceof Error) {
|
|
3780
|
-
ctx.crash(error);
|
|
3781
|
-
}
|
|
3782
|
-
}
|
|
3783
|
-
}
|
|
3784
|
-
setLanguage(ctx.options.defaultLanguage ?? "auto").then(() => {
|
|
3785
|
-
setLoaded(true);
|
|
3786
|
-
});
|
|
3787
|
-
return {
|
|
3788
|
-
loaded: new Promise((resolve2, reject) => {
|
|
3789
|
-
const stop = $loaded.watch((isLoaded) => {
|
|
3790
|
-
if (isLoaded) {
|
|
3791
|
-
setTimeout(() => {
|
|
3792
|
-
stop();
|
|
3793
|
-
resolve2();
|
|
3794
|
-
}, 0);
|
|
3795
|
-
}
|
|
3796
|
-
});
|
|
3797
|
-
}),
|
|
3798
|
-
$isLoaded: $loaded,
|
|
3799
|
-
$currentLanguage: $language,
|
|
3800
|
-
supportedLanguages: [...languages.keys()],
|
|
3801
|
-
setLanguage,
|
|
3802
|
-
/**
|
|
3803
|
-
* Returns a Readable of the translated value.
|
|
3804
|
-
|
|
3805
|
-
* @param key - Key to the translated value.
|
|
3806
|
-
* @param values - A map of {{placeholder}} names and the values to replace them with.
|
|
3807
|
-
*/
|
|
3808
|
-
translate(key, values) {
|
|
3809
|
-
if (!$language.get()) {
|
|
3810
|
-
return $noLanguageValue;
|
|
3811
|
-
}
|
|
3812
|
-
const cached = getCached(key, values);
|
|
3813
|
-
if (cached) {
|
|
3814
|
-
return cached;
|
|
3815
|
-
}
|
|
3816
|
-
if (values) {
|
|
3817
|
-
const signalValues = {};
|
|
3818
|
-
for (const [key2, value] of Object.entries(values)) {
|
|
3819
|
-
if (isSignal(value)) {
|
|
3820
|
-
signalValues[key2] = value;
|
|
3821
|
-
}
|
|
3822
|
-
}
|
|
3823
|
-
const readableEntries = Object.entries(signalValues);
|
|
3824
|
-
if (readableEntries.length > 0) {
|
|
3825
|
-
const readables = readableEntries.map((x) => x[1]);
|
|
3826
|
-
const $merged = derive([$translation, ...readables], (t, ...entryValues) => {
|
|
3827
|
-
const entries = entryValues.map((_, i) => readableEntries[i]);
|
|
3828
|
-
const mergedValues = {
|
|
3829
|
-
...values
|
|
3830
|
-
};
|
|
3831
|
-
for (let i = 0; i < entries.length; i++) {
|
|
3832
|
-
const key2 = entries[i][0];
|
|
3833
|
-
mergedValues[key2] = entryValues[i];
|
|
3834
|
-
}
|
|
3835
|
-
const result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
3836
|
-
return replaceMustaches(result, mergedValues);
|
|
3837
|
-
});
|
|
3838
|
-
translationCache.push([key, values, $merged]);
|
|
3839
|
-
return $merged;
|
|
3840
|
-
}
|
|
3841
|
-
}
|
|
3842
|
-
const $replaced = derive([$translation], (t) => {
|
|
3843
|
-
let result = resolve(t, key) || `[NO TRANSLATION: ${key}]`;
|
|
3844
|
-
if (values) {
|
|
3845
|
-
result = replaceMustaches(result, values);
|
|
3846
|
-
}
|
|
3847
|
-
return result;
|
|
3848
|
-
});
|
|
3849
|
-
translationCache.push([key, values, $replaced]);
|
|
3850
|
-
return $replaced;
|
|
3851
|
-
}
|
|
3852
|
-
};
|
|
3853
|
-
}
|
|
3854
|
-
function resolve(object, key) {
|
|
3855
|
-
const parsed = String(key).split(/[\.\[\]]/).filter((part) => part.trim() !== "");
|
|
3856
|
-
let value = object;
|
|
3857
|
-
while (parsed.length > 0) {
|
|
3858
|
-
const part = parsed.shift();
|
|
3859
|
-
if (value != null) {
|
|
3860
|
-
value = value[part];
|
|
3861
|
-
} else {
|
|
3862
|
-
value = void 0;
|
|
3863
|
-
}
|
|
3864
|
-
}
|
|
3865
|
-
return value;
|
|
3866
|
-
}
|
|
3867
|
-
|
|
3868
|
-
// src/stores/http.ts
|
|
3869
|
-
function HTTPStore(ctx) {
|
|
3870
|
-
ctx.name = "dolla/http";
|
|
3871
|
-
const fetch2 = ctx.options.fetch ?? getDefaultFetch();
|
|
3872
|
-
const middleware = [];
|
|
3873
|
-
async function request(method, uri, options) {
|
|
3874
|
-
return makeRequest({ ...options, method, uri, middleware, fetch: fetch2 });
|
|
3875
|
-
}
|
|
3876
|
-
return {
|
|
3877
|
-
/**
|
|
3878
|
-
* Adds a new middleware that will apply to subsequent requests.
|
|
3879
|
-
* Returns a function to remove this middleware.
|
|
3880
|
-
*
|
|
3881
|
-
* @param middleware - A middleware function that will intercept requests.
|
|
3882
|
-
*/
|
|
3883
|
-
middleware(fn) {
|
|
3884
|
-
middleware.push(fn);
|
|
3885
|
-
return function remove() {
|
|
3886
|
-
middleware.splice(middleware.indexOf(fn), 1);
|
|
3887
|
-
};
|
|
3888
|
-
},
|
|
3889
|
-
async get(uri, options) {
|
|
3890
|
-
return request("get", uri, options);
|
|
3891
|
-
},
|
|
3892
|
-
async put(uri, options) {
|
|
3893
|
-
return request("put", uri, options);
|
|
3894
|
-
},
|
|
3895
|
-
async patch(uri, options) {
|
|
3896
|
-
return request("patch", uri, options);
|
|
3897
|
-
},
|
|
3898
|
-
async post(uri, options) {
|
|
3899
|
-
return request("post", uri, options);
|
|
3900
|
-
},
|
|
3901
|
-
async delete(uri, options) {
|
|
3902
|
-
return request("delete", uri, options);
|
|
3903
|
-
},
|
|
3904
|
-
async head(uri, options) {
|
|
3905
|
-
return request("head", uri, options);
|
|
3906
|
-
},
|
|
3907
|
-
async options(uri, options) {
|
|
3908
|
-
return request("options", uri, options);
|
|
3909
|
-
},
|
|
3910
|
-
async trace(uri, options) {
|
|
3911
|
-
return request("trace", uri, options);
|
|
3912
|
-
}
|
|
3913
|
-
};
|
|
3914
|
-
}
|
|
3915
|
-
function getDefaultFetch() {
|
|
3916
|
-
if (typeof window !== "undefined" && window.fetch) {
|
|
3917
|
-
return window.fetch.bind(window);
|
|
3918
|
-
}
|
|
3919
|
-
if (typeof global !== "undefined" && global.fetch) {
|
|
3920
|
-
return global.fetch.bind(global);
|
|
3921
|
-
}
|
|
3922
|
-
throw new Error("Running in neither browser nor node. Please run this app in one of the supported environments.");
|
|
3923
|
-
}
|
|
3924
|
-
var HTTPResponseError = class extends Error {
|
|
3925
|
-
response;
|
|
3926
|
-
constructor(response) {
|
|
3927
|
-
const { status, statusText, method, uri } = response;
|
|
3928
|
-
const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${uri})`;
|
|
3929
|
-
super(message);
|
|
3930
|
-
this.response = response;
|
|
3931
|
-
}
|
|
3932
|
-
};
|
|
3933
|
-
async function makeRequest(config) {
|
|
3934
|
-
const { headers, query, fetch: fetch2, middleware } = config;
|
|
3935
|
-
const request = {
|
|
3936
|
-
method: config.method,
|
|
3937
|
-
uri: config.uri,
|
|
3938
|
-
get sameOrigin() {
|
|
3939
|
-
return !request.uri.startsWith("http");
|
|
3940
|
-
},
|
|
3941
|
-
query: new URLSearchParams(),
|
|
3942
|
-
headers: new Headers(),
|
|
3943
|
-
body: config.body
|
|
3944
|
-
};
|
|
3945
|
-
if (headers) {
|
|
3946
|
-
if (headers instanceof Map || headers instanceof Headers) {
|
|
3947
|
-
headers.forEach((value, key) => {
|
|
3948
|
-
request.headers.set(key, value);
|
|
3949
|
-
});
|
|
3950
|
-
} else if (headers != null && typeof headers === "object" && !Array.isArray(headers)) {
|
|
3951
|
-
for (const name in headers) {
|
|
3952
|
-
const value = headers[name];
|
|
3953
|
-
if (value instanceof Date) {
|
|
3954
|
-
request.headers.set(name, value.toISOString());
|
|
3955
|
-
} else if (value != null) {
|
|
3956
|
-
request.headers.set(name, String(value));
|
|
3957
|
-
}
|
|
3958
|
-
}
|
|
3959
|
-
} else {
|
|
3960
|
-
throw new TypeError(`Unknown headers type. Got: ${headers}`);
|
|
3961
|
-
}
|
|
3962
|
-
}
|
|
3963
|
-
if (query) {
|
|
3964
|
-
if (query instanceof Map || query instanceof URLSearchParams) {
|
|
3965
|
-
query.forEach((value, key) => {
|
|
3966
|
-
request.query.set(key, value);
|
|
3967
|
-
});
|
|
3968
|
-
} else if (query != null && typeof query === "object" && !Array.isArray(query)) {
|
|
3969
|
-
for (const name in query) {
|
|
3970
|
-
const value = query[name];
|
|
3971
|
-
if (value instanceof Date) {
|
|
3972
|
-
request.query.set(name, value.toISOString());
|
|
3973
|
-
} else if (value != null) {
|
|
3974
|
-
request.query.set(name, String(value));
|
|
3975
|
-
}
|
|
3976
|
-
}
|
|
3977
|
-
} else {
|
|
3978
|
-
throw new TypeError(`Unknown query params type. Got: ${query}`);
|
|
3979
|
-
}
|
|
3980
|
-
}
|
|
3981
|
-
let response;
|
|
3982
|
-
const handler = async () => {
|
|
3983
|
-
const query2 = request.query.toString();
|
|
3984
|
-
const fullURL = query2.length > 0 ? request.uri + "?" + query2 : request.uri;
|
|
3985
|
-
let reqBody;
|
|
3986
|
-
if (!request.headers.has("content-type") && isObject(request.body)) {
|
|
3987
|
-
request.headers.set("content-type", "application/json");
|
|
3988
|
-
reqBody = JSON.stringify(request.body);
|
|
3989
|
-
} else {
|
|
3990
|
-
reqBody = request.body;
|
|
3991
|
-
}
|
|
3992
|
-
const fetched = await fetch2(fullURL, {
|
|
3993
|
-
method: request.method,
|
|
3994
|
-
headers: request.headers,
|
|
3995
|
-
body: reqBody
|
|
3996
|
-
});
|
|
3997
|
-
const headers2 = Object.fromEntries(fetched.headers.entries());
|
|
3998
|
-
const contentType = headers2["content-type"];
|
|
3999
|
-
let body;
|
|
4000
|
-
if (contentType?.includes("application/json")) {
|
|
4001
|
-
body = await fetched.json();
|
|
4002
|
-
} else if (contentType?.includes("application/x-www-form-urlencoded")) {
|
|
4003
|
-
body = await fetched.formData();
|
|
4004
|
-
} else {
|
|
4005
|
-
body = await fetched.text();
|
|
4006
|
-
}
|
|
4007
|
-
response = {
|
|
4008
|
-
method: request.method,
|
|
4009
|
-
uri: request.uri,
|
|
4010
|
-
status: fetched.status,
|
|
4011
|
-
statusText: fetched.statusText,
|
|
4012
|
-
headers: headers2,
|
|
4013
|
-
body
|
|
4014
|
-
};
|
|
4015
|
-
};
|
|
4016
|
-
if (middleware.length > 0) {
|
|
4017
|
-
const mount = (index = 0) => {
|
|
4018
|
-
const current = middleware[index];
|
|
4019
|
-
const next = middleware[index + 1] ? mount(index + 1) : handler;
|
|
4020
|
-
return async () => current(request, async () => {
|
|
4021
|
-
await next();
|
|
4022
|
-
return response;
|
|
4023
|
-
});
|
|
4024
|
-
};
|
|
4025
|
-
await mount()();
|
|
4026
|
-
} else {
|
|
4027
|
-
await handler();
|
|
4028
|
-
}
|
|
4029
|
-
if (response.status < 200 || response.status >= 400) {
|
|
4030
|
-
throw new HTTPResponseError(response);
|
|
4031
|
-
}
|
|
4032
|
-
return response;
|
|
4033
|
-
}
|
|
4034
|
-
|
|
4035
|
-
// src/stores/dialog.ts
|
|
4036
|
-
function DialogStore(ctx) {
|
|
4037
|
-
ctx.name = "dolla/dialog";
|
|
4038
|
-
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
4039
|
-
const render = ctx.getStore("render");
|
|
4040
|
-
const container = document.createElement("div");
|
|
4041
|
-
container.style.position = "fixed";
|
|
4042
|
-
container.style.top = "0";
|
|
4043
|
-
container.style.right = "0";
|
|
4044
|
-
container.style.bottom = "0";
|
|
4045
|
-
container.style.left = "0";
|
|
4046
|
-
container.style.zIndex = "99999";
|
|
4047
|
-
const [$dialogs, setDialogs] = signal([]);
|
|
4048
|
-
let activeDialogs = [];
|
|
4049
|
-
function dialogChangedCallback() {
|
|
4050
|
-
if (activeDialogs.length > 0) {
|
|
4051
|
-
if (!container.parentNode) {
|
|
4052
|
-
document.body.appendChild(container);
|
|
4053
|
-
}
|
|
4054
|
-
} else {
|
|
4055
|
-
if (container.parentNode) {
|
|
4056
|
-
document.body.removeChild(container);
|
|
4057
|
-
}
|
|
4058
|
-
}
|
|
4059
|
-
}
|
|
4060
|
-
ctx.watch([$dialogs], (dialogs) => {
|
|
4061
|
-
render.update(() => {
|
|
4062
|
-
let removed = [];
|
|
4063
|
-
let added = [];
|
|
4064
|
-
for (const dialog of activeDialogs) {
|
|
4065
|
-
if (!dialogs.includes(dialog)) {
|
|
4066
|
-
removed.push(dialog);
|
|
4067
|
-
}
|
|
4068
|
-
}
|
|
4069
|
-
for (const dialog of dialogs) {
|
|
4070
|
-
if (!activeDialogs.includes(dialog)) {
|
|
4071
|
-
added.push(dialog);
|
|
4072
|
-
}
|
|
4073
|
-
}
|
|
4074
|
-
for (const dialog of removed) {
|
|
4075
|
-
if (dialog.transitionOutCallback) {
|
|
4076
|
-
dialog.transitionOutCallback().then(() => {
|
|
4077
|
-
dialog.instance.disconnect();
|
|
4078
|
-
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
4079
|
-
dialogChangedCallback();
|
|
4080
|
-
});
|
|
4081
|
-
} else {
|
|
4082
|
-
dialog.instance.disconnect();
|
|
4083
|
-
activeDialogs.splice(activeDialogs.indexOf(dialog), 1);
|
|
4084
|
-
}
|
|
4085
|
-
}
|
|
4086
|
-
for (const dialog of added) {
|
|
4087
|
-
dialog.instance.connect(container);
|
|
4088
|
-
if (dialog.transitionInCallback) {
|
|
4089
|
-
dialog.transitionInCallback();
|
|
4090
|
-
}
|
|
4091
|
-
activeDialogs.push(dialog);
|
|
4092
|
-
}
|
|
4093
|
-
dialogChangedCallback();
|
|
4094
|
-
});
|
|
4095
|
-
});
|
|
4096
|
-
ctx.onDisconnected(() => {
|
|
4097
|
-
if (container.parentNode) {
|
|
4098
|
-
document.body.removeChild(container);
|
|
4099
|
-
}
|
|
4100
|
-
});
|
|
4101
|
-
function open(view, props) {
|
|
4102
|
-
const $$open = signal.settable(true);
|
|
4103
|
-
let dialog;
|
|
4104
|
-
let transitionInCallback;
|
|
4105
|
-
let transitionOutCallback;
|
|
4106
|
-
let instance = initView({
|
|
4107
|
-
view,
|
|
4108
|
-
appContext,
|
|
4109
|
-
elementContext,
|
|
4110
|
-
props: {
|
|
4111
|
-
...props,
|
|
4112
|
-
dialog: {
|
|
4113
|
-
$$open,
|
|
4114
|
-
transitionIn: (callback) => {
|
|
4115
|
-
transitionInCallback = callback;
|
|
4116
|
-
},
|
|
4117
|
-
transitionOut: (callback) => {
|
|
4118
|
-
transitionOutCallback = callback;
|
|
4119
|
-
}
|
|
4120
|
-
}
|
|
4121
|
-
}
|
|
4122
|
-
});
|
|
4123
|
-
dialog = {
|
|
4124
|
-
instance,
|
|
4125
|
-
// These must be getters because the fns passed to props aren't called until before connect.
|
|
4126
|
-
get transitionInCallback() {
|
|
4127
|
-
return transitionInCallback;
|
|
4128
|
-
},
|
|
4129
|
-
get transitionOutCallback() {
|
|
4130
|
-
return transitionOutCallback;
|
|
4131
|
-
}
|
|
4132
|
-
};
|
|
4133
|
-
setDialogs((current) => {
|
|
4134
|
-
return [...current, dialog];
|
|
4135
|
-
});
|
|
4136
|
-
const stopObserver = $$open.watch((value) => {
|
|
4137
|
-
if (!value) {
|
|
4138
|
-
closeDialog();
|
|
4139
|
-
}
|
|
4140
|
-
});
|
|
4141
|
-
function closeDialog() {
|
|
4142
|
-
setDialogs((current) => {
|
|
4143
|
-
return current.filter((x) => x !== dialog);
|
|
4144
|
-
});
|
|
4145
|
-
dialog = void 0;
|
|
4146
|
-
stopObserver();
|
|
4147
|
-
}
|
|
4148
|
-
return closeDialog;
|
|
4149
|
-
}
|
|
4150
|
-
return {
|
|
4151
|
-
open
|
|
4152
|
-
};
|
|
4153
|
-
}
|
|
4154
|
-
export {
|
|
4155
|
-
App,
|
|
4156
|
-
DialogStore,
|
|
4157
|
-
Fragment,
|
|
4158
|
-
HTTPStore,
|
|
4159
|
-
LanguageStore,
|
|
4160
|
-
RouterStore,
|
|
4161
|
-
StoreScope,
|
|
4162
|
-
cond,
|
|
4163
|
-
derive,
|
|
4164
|
-
designalify,
|
|
4165
|
-
isRef,
|
|
4166
|
-
isSettableSignal,
|
|
4167
|
-
isSignal,
|
|
4168
|
-
m,
|
|
4169
|
-
portal,
|
|
4170
|
-
ref,
|
|
4171
|
-
repeat,
|
|
4172
|
-
signal,
|
|
4173
|
-
signalify,
|
|
4174
|
-
watch
|
|
4175
|
-
};
|
|
4176
|
-
//# sourceMappingURL=index.js.map
|