@panyam/tsappkit 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +113 -11
- package/dist/index.d.ts +113 -11
- package/dist/index.js +133 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +4 -2
- package/src/page/IslandPage.ts +25 -0
- package/src/page/load.ts +86 -0
- package/src/page/mount.ts +105 -16
- package/src/page/spec.ts +7 -0
package/dist/index.mjs
CHANGED
|
@@ -255,9 +255,9 @@ var BaseComponent = class {
|
|
|
255
255
|
/**
|
|
256
256
|
* Log messages with component identification
|
|
257
257
|
*/
|
|
258
|
-
log(
|
|
258
|
+
log(message2, data = null) {
|
|
259
259
|
if (this.debugMode) {
|
|
260
|
-
console.log(`[${this.componentId}] ${
|
|
260
|
+
console.log(`[${this.componentId}] ${message2}`, data);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
@@ -435,16 +435,16 @@ var LifecycleController = class {
|
|
|
435
435
|
/**
|
|
436
436
|
* Log message if debug logging is enabled
|
|
437
437
|
*/
|
|
438
|
-
log(
|
|
438
|
+
log(message2, ...args) {
|
|
439
439
|
if (this.config.enableDebugLogging) {
|
|
440
|
-
console.log(`[LifecycleController] ${
|
|
440
|
+
console.log(`[LifecycleController] ${message2}`, ...args);
|
|
441
441
|
}
|
|
442
442
|
}
|
|
443
443
|
/**
|
|
444
444
|
* Log error message
|
|
445
445
|
*/
|
|
446
|
-
logError(
|
|
447
|
-
console.error(`[LifecycleController] ${
|
|
446
|
+
logError(message2, error) {
|
|
447
|
+
console.error(`[LifecycleController] ${message2}`, error);
|
|
448
448
|
}
|
|
449
449
|
/**
|
|
450
450
|
* Get current status of all components
|
|
@@ -843,7 +843,7 @@ var _ToastManager = class _ToastManager {
|
|
|
843
843
|
* @param type Toast type for styling
|
|
844
844
|
* @param duration Duration in ms (default: 4000)
|
|
845
845
|
*/
|
|
846
|
-
showToast(title,
|
|
846
|
+
showToast(title, message2, type = "info", duration = 4e3) {
|
|
847
847
|
if (!this.container || !this.template) return "";
|
|
848
848
|
const id = `toast-${Date.now()}-${this.counter++}`;
|
|
849
849
|
const toast = this.template.cloneNode(true);
|
|
@@ -852,7 +852,7 @@ var _ToastManager = class _ToastManager {
|
|
|
852
852
|
const titleElement = toast.querySelector(".toast-title");
|
|
853
853
|
const messageElement = toast.querySelector(".toast-message");
|
|
854
854
|
if (titleElement) titleElement.textContent = title;
|
|
855
|
-
if (messageElement) messageElement.textContent =
|
|
855
|
+
if (messageElement) messageElement.textContent = message2;
|
|
856
856
|
const iconContainer = toast.querySelector(".flex-shrink-0");
|
|
857
857
|
if (iconContainer) {
|
|
858
858
|
iconContainer.innerHTML = "";
|
|
@@ -957,7 +957,7 @@ var SplashScreen = class {
|
|
|
957
957
|
/**
|
|
958
958
|
* Update the splash screen message (if it hasn't been dismissed yet)
|
|
959
959
|
*/
|
|
960
|
-
static updateMessage(title,
|
|
960
|
+
static updateMessage(title, message2) {
|
|
961
961
|
if (this.dismissed) {
|
|
962
962
|
return;
|
|
963
963
|
}
|
|
@@ -971,10 +971,10 @@ var SplashScreen = class {
|
|
|
971
971
|
titleEl.textContent = title;
|
|
972
972
|
}
|
|
973
973
|
}
|
|
974
|
-
if (
|
|
974
|
+
if (message2) {
|
|
975
975
|
const messageEl = splash.querySelector("[data-splash-message]");
|
|
976
976
|
if (messageEl) {
|
|
977
|
-
messageEl.textContent =
|
|
977
|
+
messageEl.textContent = message2;
|
|
978
978
|
}
|
|
979
979
|
}
|
|
980
980
|
}
|
|
@@ -1089,8 +1089,8 @@ var BasePage = class extends BaseComponent {
|
|
|
1089
1089
|
/**
|
|
1090
1090
|
* Show a toast notification
|
|
1091
1091
|
*/
|
|
1092
|
-
showToast(title,
|
|
1093
|
-
this.toastManager?.showToast(title,
|
|
1092
|
+
showToast(title, message2, type = "info", duration) {
|
|
1093
|
+
this.toastManager?.showToast(title, message2, type, duration);
|
|
1094
1094
|
}
|
|
1095
1095
|
/**
|
|
1096
1096
|
* Show a modal dialog
|
|
@@ -1371,13 +1371,68 @@ var MobileBottomDrawer = class extends BaseComponent {
|
|
|
1371
1371
|
}
|
|
1372
1372
|
};
|
|
1373
1373
|
|
|
1374
|
+
// src/page/load.ts
|
|
1375
|
+
function parseLoad(load) {
|
|
1376
|
+
switch (load ?? "") {
|
|
1377
|
+
case "":
|
|
1378
|
+
case "eager":
|
|
1379
|
+
return { kind: "eager" };
|
|
1380
|
+
case "idle":
|
|
1381
|
+
return { kind: "idle" };
|
|
1382
|
+
case "visible":
|
|
1383
|
+
return { kind: "visible" };
|
|
1384
|
+
}
|
|
1385
|
+
const query = load.startsWith("media:") ? load.slice("media:".length) : "";
|
|
1386
|
+
return query.trim() ? { kind: "media", query } : null;
|
|
1387
|
+
}
|
|
1388
|
+
function scheduleMount(strategy, el, mount, env = window) {
|
|
1389
|
+
switch (strategy.kind) {
|
|
1390
|
+
case "eager":
|
|
1391
|
+
mount();
|
|
1392
|
+
return;
|
|
1393
|
+
case "idle":
|
|
1394
|
+
if (env.requestIdleCallback) env.requestIdleCallback(mount);
|
|
1395
|
+
else env.setTimeout(mount, 1);
|
|
1396
|
+
return;
|
|
1397
|
+
case "visible": {
|
|
1398
|
+
let done = false;
|
|
1399
|
+
const observer = new env.IntersectionObserver((entries) => {
|
|
1400
|
+
if (done || !entries.some((e) => e.isIntersecting)) return;
|
|
1401
|
+
done = true;
|
|
1402
|
+
observer.disconnect();
|
|
1403
|
+
mount();
|
|
1404
|
+
});
|
|
1405
|
+
observer.observe(el);
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
case "media": {
|
|
1409
|
+
const mq = env.matchMedia(strategy.query);
|
|
1410
|
+
if (mq.matches) {
|
|
1411
|
+
mount();
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
const onChange = (e) => {
|
|
1415
|
+
if (!e.matches) return;
|
|
1416
|
+
mq.removeEventListener("change", onChange);
|
|
1417
|
+
mount();
|
|
1418
|
+
};
|
|
1419
|
+
mq.addEventListener("change", onChange);
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1374
1425
|
// src/page/mount.ts
|
|
1375
|
-
|
|
1426
|
+
var LAZY = /* @__PURE__ */ Symbol("lazy island");
|
|
1427
|
+
function lazy(load) {
|
|
1428
|
+
return { [LAZY]: load };
|
|
1429
|
+
}
|
|
1430
|
+
function mountIslands(spec, registry, findSlot, context, bus, log, options = {}) {
|
|
1376
1431
|
const out = [];
|
|
1377
1432
|
let ctx;
|
|
1378
1433
|
for (const island of spec.islands) {
|
|
1379
|
-
const
|
|
1380
|
-
if (!
|
|
1434
|
+
const entry = Object.prototype.hasOwnProperty.call(registry, island.name) ? registry[island.name] : void 0;
|
|
1435
|
+
if (!entry) {
|
|
1381
1436
|
log(`page spec: no island called "${island.name}" in this page's registry`);
|
|
1382
1437
|
continue;
|
|
1383
1438
|
}
|
|
@@ -1386,15 +1441,53 @@ function mountIslands(spec, registry, findSlot, context, bus, log) {
|
|
|
1386
1441
|
log(`page spec: island "${island.name}" wants slot "${island.slot}", which isn't on the page`);
|
|
1387
1442
|
continue;
|
|
1388
1443
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1444
|
+
const build = (factory) => {
|
|
1445
|
+
try {
|
|
1446
|
+
ctx ?? (ctx = context());
|
|
1447
|
+
return factory(el, island, ctx, bus);
|
|
1448
|
+
} catch (err) {
|
|
1449
|
+
log(`page spec: island "${island.name}" failed to mount: ${message(err)}`);
|
|
1450
|
+
return void 0;
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
const mountLate = () => {
|
|
1454
|
+
const late = (factory) => {
|
|
1455
|
+
const c2 = build(factory);
|
|
1456
|
+
if (c2 !== void 0) options.onLateMount?.(c2, island);
|
|
1457
|
+
};
|
|
1458
|
+
if (typeof entry === "function") {
|
|
1459
|
+
late(entry);
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
new Promise((resolve) => resolve(entry[LAZY]())).then(
|
|
1463
|
+
(m) => {
|
|
1464
|
+
const factory = typeof m === "function" ? m : m?.default;
|
|
1465
|
+
if (typeof factory === "function") late(factory);
|
|
1466
|
+
else log(`page spec: island "${island.name}" loaded, but its module has no factory (a default export or the function itself)`);
|
|
1467
|
+
},
|
|
1468
|
+
(err) => log(`page spec: island "${island.name}" failed to load: ${message(err)}`)
|
|
1469
|
+
);
|
|
1470
|
+
};
|
|
1471
|
+
const strategy = parseLoad(island.load);
|
|
1472
|
+
if (strategy === null) {
|
|
1473
|
+
log(`page spec: island "${island.name}" has load "${island.load}", which isn't eager, idle, visible or media:<query>; mounting it now`);
|
|
1474
|
+
}
|
|
1475
|
+
if (options.defer && strategy !== null && strategy.kind !== "eager") {
|
|
1476
|
+
options.defer(island, el, mountLate);
|
|
1477
|
+
continue;
|
|
1394
1478
|
}
|
|
1479
|
+
if (typeof entry !== "function") {
|
|
1480
|
+
mountLate();
|
|
1481
|
+
continue;
|
|
1482
|
+
}
|
|
1483
|
+
const c = build(entry);
|
|
1484
|
+
if (c !== void 0) out.push(c);
|
|
1395
1485
|
}
|
|
1396
1486
|
return out;
|
|
1397
1487
|
}
|
|
1488
|
+
function message(err) {
|
|
1489
|
+
return err instanceof Error ? err.message : String(err);
|
|
1490
|
+
}
|
|
1398
1491
|
|
|
1399
1492
|
// src/page/spec.ts
|
|
1400
1493
|
var SPEC_ELEMENT_ID = "page-spec";
|
|
@@ -1415,7 +1508,8 @@ function readSpec(text, extend) {
|
|
|
1415
1508
|
name: is.name,
|
|
1416
1509
|
slot: is.slot,
|
|
1417
1510
|
...typeof is.presentation === "string" && { presentation: is.presentation },
|
|
1418
|
-
config: isObject(is.config) ? is.config : {}
|
|
1511
|
+
config: isObject(is.config) ? is.config : {},
|
|
1512
|
+
...typeof is.load === "string" && { load: is.load }
|
|
1419
1513
|
});
|
|
1420
1514
|
}
|
|
1421
1515
|
const spec = { layout: raw.layout, islands };
|
|
@@ -1453,9 +1547,22 @@ var IslandPage = class extends BasePage {
|
|
|
1453
1547
|
(slot) => document.querySelector(`[data-slot="${slot}"]`),
|
|
1454
1548
|
() => this.makeContext(spec),
|
|
1455
1549
|
this.eventBus,
|
|
1456
|
-
(
|
|
1550
|
+
(message2) => console.warn(message2),
|
|
1551
|
+
{
|
|
1552
|
+
defer: (island, el, mount) => this.scheduleLoad(parseLoad(island.load) ?? { kind: "eager" }, el, mount),
|
|
1553
|
+
onLateMount: (component, island) => {
|
|
1554
|
+
new LifecycleController(this.eventBus, LifecycleController.DefaultConfig).initializeFromRoot(component).catch((err) => console.warn(`page spec: island "${island.name}" failed to start: ${err instanceof Error ? err.message : String(err)}`));
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1457
1557
|
);
|
|
1458
1558
|
}
|
|
1559
|
+
/**
|
|
1560
|
+
* Waits for `strategy` and then calls `mount`. Defaults to scheduleMount
|
|
1561
|
+
* against the window; a subclass or test can replace how the waiting is done.
|
|
1562
|
+
*/
|
|
1563
|
+
scheduleLoad(strategy, el, mount) {
|
|
1564
|
+
scheduleMount(strategy, el, mount);
|
|
1565
|
+
}
|
|
1459
1566
|
};
|
|
1460
1567
|
|
|
1461
1568
|
// src/DOMUtils.ts
|
|
@@ -1800,6 +1907,6 @@ var KeyboardShortcutManager = class {
|
|
|
1800
1907
|
}
|
|
1801
1908
|
};
|
|
1802
1909
|
|
|
1803
|
-
export { BaseComponent, BasePage, ComponentEventTypes, EventBus, IslandPage, KeyboardShortcutManager, KeyboardState, LifecycleController, LifecycleEventTypes, MobileBottomDrawer, Modal, SPEC_ELEMENT_ID, SplashScreen, TemplateLoader, ThemeManager, ToastManager, hasModifierKeys, isInInputContext, mountIslands, readSpec, shouldIgnoreShortcut };
|
|
1910
|
+
export { BaseComponent, BasePage, ComponentEventTypes, EventBus, IslandPage, KeyboardShortcutManager, KeyboardState, LifecycleController, LifecycleEventTypes, MobileBottomDrawer, Modal, SPEC_ELEMENT_ID, SplashScreen, TemplateLoader, ThemeManager, ToastManager, hasModifierKeys, isInInputContext, lazy, mountIslands, parseLoad, readSpec, scheduleMount, shouldIgnoreShortcut };
|
|
1804
1911
|
//# sourceMappingURL=index.mjs.map
|
|
1805
1912
|
//# sourceMappingURL=index.mjs.map
|