@manyducks.co/dolla 0.69.4 → 0.70.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/lib/app.d.ts +8 -3
- package/lib/index.js +152 -137
- package/lib/index.js.map +4 -4
- package/lib/routing.d.ts +4 -4
- package/lib/stores/language.d.ts +3 -2
- package/lib/stores/router.d.ts +1 -1
- package/lib/views/default-crash-page.d.ts +7 -0
- package/lib/views/default-view.d.ts +2 -0
- package/package.json +1 -1
package/lib/app.d.ts
CHANGED
|
@@ -49,13 +49,18 @@ export interface StoreRegistration<O = any> {
|
|
|
49
49
|
instance?: ReturnType<typeof initStore>;
|
|
50
50
|
}
|
|
51
51
|
interface ConfigureContext {
|
|
52
|
+
/**
|
|
53
|
+
* Returns the shared instance of `store`.
|
|
54
|
+
*/
|
|
55
|
+
getStore<T extends Store<any, any>>(store: T): ReturnType<T>;
|
|
56
|
+
/**
|
|
57
|
+
* Returns the shared instance of a built-in store.
|
|
58
|
+
*/
|
|
59
|
+
getStore<N extends keyof BuiltInStores>(name: N): BuiltInStores[N];
|
|
52
60
|
}
|
|
53
61
|
type ConfigureCallback = (ctx: ConfigureContext) => void | Promise<void>;
|
|
54
62
|
export interface IApp {
|
|
55
63
|
readonly isConnected: boolean;
|
|
56
|
-
/**
|
|
57
|
-
* Makes this store accessible from any other component in the app, except for stores registered before this one.
|
|
58
|
-
*/
|
|
59
64
|
/**
|
|
60
65
|
* Runs `callback` after app-level stores are connected to the app, but before views are connected to the DOM.
|
|
61
66
|
* Use this function to run async configuration code before displaying content to the user.
|
package/lib/index.js
CHANGED
|
@@ -2195,10 +2195,65 @@ function RenderStore(ctx) {
|
|
|
2195
2195
|
};
|
|
2196
2196
|
}
|
|
2197
2197
|
|
|
2198
|
-
// src/
|
|
2199
|
-
function
|
|
2198
|
+
// src/views/default-crash-page.ts
|
|
2199
|
+
function DefaultCrashPage({ message, error, componentName }) {
|
|
2200
|
+
return m(
|
|
2201
|
+
"div",
|
|
2202
|
+
{
|
|
2203
|
+
style: {
|
|
2204
|
+
backgroundColor: "#880000",
|
|
2205
|
+
color: "#fff",
|
|
2206
|
+
padding: "2rem",
|
|
2207
|
+
position: "fixed",
|
|
2208
|
+
inset: 0,
|
|
2209
|
+
fontSize: "20px"
|
|
2210
|
+
}
|
|
2211
|
+
},
|
|
2212
|
+
m("h1", { style: { marginBottom: "0.5rem" } }, "The app has crashed"),
|
|
2213
|
+
m(
|
|
2214
|
+
"p",
|
|
2215
|
+
{ style: { marginBottom: "0.25rem" } },
|
|
2216
|
+
m("span", { style: { fontFamily: "monospace" } }, componentName),
|
|
2217
|
+
" says:"
|
|
2218
|
+
),
|
|
2219
|
+
m(
|
|
2220
|
+
"blockquote",
|
|
2221
|
+
{
|
|
2222
|
+
style: {
|
|
2223
|
+
backgroundColor: "#991111",
|
|
2224
|
+
padding: "0.25em",
|
|
2225
|
+
borderRadius: "6px",
|
|
2226
|
+
fontFamily: "monospace",
|
|
2227
|
+
marginBottom: "1rem"
|
|
2228
|
+
}
|
|
2229
|
+
},
|
|
2230
|
+
m(
|
|
2231
|
+
"span",
|
|
2232
|
+
{
|
|
2233
|
+
style: {
|
|
2234
|
+
display: "inline-block",
|
|
2235
|
+
backgroundColor: "red",
|
|
2236
|
+
padding: "0.1em 0.4em",
|
|
2237
|
+
marginRight: "0.5em",
|
|
2238
|
+
borderRadius: "4px",
|
|
2239
|
+
fontSize: "0.9em",
|
|
2240
|
+
fontWeight: "bold"
|
|
2241
|
+
}
|
|
2242
|
+
},
|
|
2243
|
+
error.name
|
|
2244
|
+
),
|
|
2245
|
+
message
|
|
2246
|
+
),
|
|
2247
|
+
m("p", {}, "Please see the browser console for details.")
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// src/views/default-view.ts
|
|
2252
|
+
function DefaultView(_, ctx) {
|
|
2200
2253
|
return ctx.outlet();
|
|
2201
2254
|
}
|
|
2255
|
+
|
|
2256
|
+
// src/app.ts
|
|
2202
2257
|
function isAppOptions(value) {
|
|
2203
2258
|
return isObject(value);
|
|
2204
2259
|
}
|
|
@@ -2207,7 +2262,7 @@ function App(options) {
|
|
|
2207
2262
|
throw new TypeError(`App options must be an object. Got: ${options}`);
|
|
2208
2263
|
}
|
|
2209
2264
|
let isConnected = false;
|
|
2210
|
-
let mainView = m(options?.view ??
|
|
2265
|
+
let mainView = m(options?.view ?? DefaultView);
|
|
2211
2266
|
let configureCallback;
|
|
2212
2267
|
const settings = merge(
|
|
2213
2268
|
{
|
|
@@ -2290,14 +2345,42 @@ function App(options) {
|
|
|
2290
2345
|
if (configureCallback) {
|
|
2291
2346
|
await configureCallback({
|
|
2292
2347
|
// TODO: Add context methods
|
|
2348
|
+
getStore(store) {
|
|
2349
|
+
let name;
|
|
2350
|
+
if (typeof store === "string") {
|
|
2351
|
+
name = store;
|
|
2352
|
+
} else {
|
|
2353
|
+
name = store.name;
|
|
2354
|
+
}
|
|
2355
|
+
if (typeof store !== "string") {
|
|
2356
|
+
let ec = elementContext;
|
|
2357
|
+
while (ec) {
|
|
2358
|
+
if (ec.stores.has(store)) {
|
|
2359
|
+
return ec.stores.get(store)?.instance.exports;
|
|
2360
|
+
}
|
|
2361
|
+
ec = ec.parent;
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
if (appContext.stores.has(store)) {
|
|
2365
|
+
const _store = appContext.stores.get(store);
|
|
2366
|
+
if (!_store.instance) {
|
|
2367
|
+
appContext.crashCollector.crash({
|
|
2368
|
+
componentName: "@manyducks.co/dolla/App",
|
|
2369
|
+
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
return _store.instance.exports;
|
|
2373
|
+
}
|
|
2374
|
+
appContext.crashCollector.crash({
|
|
2375
|
+
componentName: "@manyducks.co/dolla/App",
|
|
2376
|
+
error: new Error(`Store '${name}' is not registered on this app.`)
|
|
2377
|
+
});
|
|
2378
|
+
}
|
|
2293
2379
|
});
|
|
2294
2380
|
}
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
resolve2();
|
|
2299
|
-
};
|
|
2300
|
-
done();
|
|
2381
|
+
appContext.rootView.connect(appContext.rootElement);
|
|
2382
|
+
isConnected = true;
|
|
2383
|
+
resolve2();
|
|
2301
2384
|
});
|
|
2302
2385
|
}
|
|
2303
2386
|
async function disconnect() {
|
|
@@ -2324,54 +2407,6 @@ function App(options) {
|
|
|
2324
2407
|
get isConnected() {
|
|
2325
2408
|
return isConnected;
|
|
2326
2409
|
},
|
|
2327
|
-
// language(tag: string, config: LanguageConfig) {
|
|
2328
|
-
// languages.set(tag, config);
|
|
2329
|
-
//
|
|
2330
|
-
// return app;
|
|
2331
|
-
// },
|
|
2332
|
-
//
|
|
2333
|
-
// setLanguage(tag: string, fallback?: string) {
|
|
2334
|
-
// if (tag === "auto") {
|
|
2335
|
-
// let tags = [];
|
|
2336
|
-
//
|
|
2337
|
-
// if (typeof navigator === "object") {
|
|
2338
|
-
// const nav = navigator as any;
|
|
2339
|
-
//
|
|
2340
|
-
// if (nav.languages?.length > 0) {
|
|
2341
|
-
// tags.push(...nav.languages);
|
|
2342
|
-
// } else if (nav.language) {
|
|
2343
|
-
// tags.push(nav.language);
|
|
2344
|
-
// } else if (nav.browserLanguage) {
|
|
2345
|
-
// tags.push(nav.browserLanguage);
|
|
2346
|
-
// } else if (nav.userLanguage) {
|
|
2347
|
-
// tags.push(nav.userLanguage);
|
|
2348
|
-
// }
|
|
2349
|
-
// }
|
|
2350
|
-
//
|
|
2351
|
-
// for (const tag of tags) {
|
|
2352
|
-
// if (languages.has(tag)) {
|
|
2353
|
-
// // Found a matching language.
|
|
2354
|
-
// currentLanguage = tag;
|
|
2355
|
-
// return this;
|
|
2356
|
-
// }
|
|
2357
|
-
// }
|
|
2358
|
-
//
|
|
2359
|
-
// if (!currentLanguage && fallback) {
|
|
2360
|
-
// if (languages.has(fallback)) {
|
|
2361
|
-
// currentLanguage = fallback;
|
|
2362
|
-
// }
|
|
2363
|
-
// }
|
|
2364
|
-
// } else {
|
|
2365
|
-
// // Tag is the actual tag to set.
|
|
2366
|
-
// if (languages.has(tag)) {
|
|
2367
|
-
// currentLanguage = tag;
|
|
2368
|
-
// } else {
|
|
2369
|
-
// throw new Error(`Language '${tag}' has not been added to this app yet.`);
|
|
2370
|
-
// }
|
|
2371
|
-
// }
|
|
2372
|
-
//
|
|
2373
|
-
// return app;
|
|
2374
|
-
// },
|
|
2375
2410
|
configure(callback) {
|
|
2376
2411
|
if (configureCallback !== void 0) {
|
|
2377
2412
|
debugChannel.warn(`Configure callback is already defined. Only the final configure call will take effect.`);
|
|
@@ -2382,57 +2417,6 @@ function App(options) {
|
|
|
2382
2417
|
};
|
|
2383
2418
|
return app;
|
|
2384
2419
|
}
|
|
2385
|
-
function DefaultCrashPage({ message, error, componentName }) {
|
|
2386
|
-
return m(
|
|
2387
|
-
"div",
|
|
2388
|
-
{
|
|
2389
|
-
style: {
|
|
2390
|
-
backgroundColor: "#880000",
|
|
2391
|
-
color: "#fff",
|
|
2392
|
-
padding: "2rem",
|
|
2393
|
-
position: "fixed",
|
|
2394
|
-
inset: 0,
|
|
2395
|
-
fontSize: "20px"
|
|
2396
|
-
}
|
|
2397
|
-
},
|
|
2398
|
-
m("h1", { style: { marginBottom: "0.5rem" } }, "The app has crashed"),
|
|
2399
|
-
m(
|
|
2400
|
-
"p",
|
|
2401
|
-
{ style: { marginBottom: "0.25rem" } },
|
|
2402
|
-
m("span", { style: { fontFamily: "monospace" } }, componentName),
|
|
2403
|
-
" says:"
|
|
2404
|
-
),
|
|
2405
|
-
m(
|
|
2406
|
-
"blockquote",
|
|
2407
|
-
{
|
|
2408
|
-
style: {
|
|
2409
|
-
backgroundColor: "#991111",
|
|
2410
|
-
padding: "0.25em",
|
|
2411
|
-
borderRadius: "6px",
|
|
2412
|
-
fontFamily: "monospace",
|
|
2413
|
-
marginBottom: "1rem"
|
|
2414
|
-
}
|
|
2415
|
-
},
|
|
2416
|
-
m(
|
|
2417
|
-
"span",
|
|
2418
|
-
{
|
|
2419
|
-
style: {
|
|
2420
|
-
display: "inline-block",
|
|
2421
|
-
backgroundColor: "red",
|
|
2422
|
-
padding: "0.1em 0.4em",
|
|
2423
|
-
marginRight: "0.5em",
|
|
2424
|
-
borderRadius: "4px",
|
|
2425
|
-
fontSize: "0.9em",
|
|
2426
|
-
fontWeight: "bold"
|
|
2427
|
-
}
|
|
2428
|
-
},
|
|
2429
|
-
error.name
|
|
2430
|
-
),
|
|
2431
|
-
message
|
|
2432
|
-
),
|
|
2433
|
-
m("p", {}, "Please see the browser console for details.")
|
|
2434
|
-
);
|
|
2435
|
-
}
|
|
2436
2420
|
|
|
2437
2421
|
// src/views/fragment.ts
|
|
2438
2422
|
function Fragment(_, ctx) {
|
|
@@ -3122,9 +3106,7 @@ function patternToFragments(pattern) {
|
|
|
3122
3106
|
const part = parts[i];
|
|
3123
3107
|
if (part === "*") {
|
|
3124
3108
|
if (i !== parts.length - 1) {
|
|
3125
|
-
throw new Error(
|
|
3126
|
-
`Wildcard must be at the end of a pattern. Received: ${pattern}`
|
|
3127
|
-
);
|
|
3109
|
+
throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);
|
|
3128
3110
|
}
|
|
3129
3111
|
fragments.push({
|
|
3130
3112
|
type: 3 /* Wildcard */,
|
|
@@ -3149,7 +3131,6 @@ function patternToFragments(pattern) {
|
|
|
3149
3131
|
}
|
|
3150
3132
|
|
|
3151
3133
|
// src/stores/router.ts
|
|
3152
|
-
var DefaultView = (_, ctx) => ctx.outlet();
|
|
3153
3134
|
function RouterStore(ctx) {
|
|
3154
3135
|
ctx.name = "dolla/router";
|
|
3155
3136
|
const { appContext, elementContext } = getStoreSecrets(ctx);
|
|
@@ -3488,37 +3469,71 @@ function LanguageStore(ctx) {
|
|
|
3488
3469
|
}
|
|
3489
3470
|
return template;
|
|
3490
3471
|
}
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3472
|
+
async function setLanguage(tag) {
|
|
3473
|
+
let realTag;
|
|
3474
|
+
if (tag === "auto") {
|
|
3475
|
+
let tags = [];
|
|
3476
|
+
if (typeof navigator === "object") {
|
|
3477
|
+
const nav = navigator;
|
|
3478
|
+
if (nav.languages?.length > 0) {
|
|
3479
|
+
tags.push(...nav.languages);
|
|
3480
|
+
} else if (nav.language) {
|
|
3481
|
+
tags.push(nav.language);
|
|
3482
|
+
} else if (nav.browserLanguage) {
|
|
3483
|
+
tags.push(nav.browserLanguage);
|
|
3484
|
+
} else if (nav.userLanguage) {
|
|
3485
|
+
tags.push(nav.userLanguage);
|
|
3486
|
+
}
|
|
3487
|
+
}
|
|
3488
|
+
for (const tag2 of tags) {
|
|
3489
|
+
if (languages.has(tag2)) {
|
|
3490
|
+
realTag = tag2;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
} else {
|
|
3494
|
+
if (languages.has(tag)) {
|
|
3495
|
+
realTag = tag;
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
if (realTag == null) {
|
|
3499
|
+
const firstLanguage = ctx.options.languages[0];
|
|
3500
|
+
if (firstLanguage) {
|
|
3501
|
+
realTag = firstLanguage.name;
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
if (!realTag || !languages.has(realTag)) {
|
|
3505
|
+
throw new Error(`Language '${tag}' is not configured for this app.`);
|
|
3506
|
+
}
|
|
3507
|
+
const lang = languages.get(realTag);
|
|
3508
|
+
try {
|
|
3509
|
+
const translation = await getTranslation(lang);
|
|
3498
3510
|
$$translation.set(translation);
|
|
3499
|
-
$$
|
|
3500
|
-
|
|
3511
|
+
$$language.set(realTag);
|
|
3512
|
+
ctx.info("set language to " + realTag);
|
|
3513
|
+
} catch (error) {
|
|
3514
|
+
if (error instanceof Error) {
|
|
3515
|
+
ctx.crash(error);
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3501
3518
|
}
|
|
3519
|
+
setLanguage(ctx.options.defaultLanguage ?? "auto").then(() => {
|
|
3520
|
+
$$isLoaded.set(true);
|
|
3521
|
+
});
|
|
3502
3522
|
return {
|
|
3523
|
+
loaded: new Promise((resolve2, reject) => {
|
|
3524
|
+
const stop = observe($$isLoaded, (isLoaded) => {
|
|
3525
|
+
if (isLoaded) {
|
|
3526
|
+
setTimeout(() => {
|
|
3527
|
+
stop();
|
|
3528
|
+
resolve2();
|
|
3529
|
+
}, 0);
|
|
3530
|
+
}
|
|
3531
|
+
});
|
|
3532
|
+
}),
|
|
3503
3533
|
$isLoaded: $($$isLoaded),
|
|
3504
3534
|
$currentLanguage: $($$language),
|
|
3505
3535
|
supportedLanguages: [...languages.keys()],
|
|
3506
|
-
|
|
3507
|
-
if (!languages.has(tag)) {
|
|
3508
|
-
throw new Error(`Language '${tag}' is not supported.`);
|
|
3509
|
-
}
|
|
3510
|
-
const lang = languages.get(tag);
|
|
3511
|
-
try {
|
|
3512
|
-
const translation = await getTranslation(lang);
|
|
3513
|
-
$$translation.set(translation);
|
|
3514
|
-
$$language.set(tag);
|
|
3515
|
-
ctx.info("set language to " + tag);
|
|
3516
|
-
} catch (error) {
|
|
3517
|
-
if (error instanceof Error) {
|
|
3518
|
-
ctx.crash(error);
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
},
|
|
3536
|
+
setLanguage,
|
|
3522
3537
|
/**
|
|
3523
3538
|
* Returns a Readable of the translated value.
|
|
3524
3539
|
|