@panyam/tsappkit 0.6.0 → 0.6.2
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 +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +82 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +82 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/page/IslandPage.ts +30 -1
- package/src/page/mount.ts +28 -7
- package/src/page/overlay.ts +63 -0
package/dist/index.mjs
CHANGED
|
@@ -1429,16 +1429,20 @@ function lazy(load) {
|
|
|
1429
1429
|
}
|
|
1430
1430
|
function mountIslands(spec, registry, findSlot, context, bus, log, options = {}) {
|
|
1431
1431
|
const out = [];
|
|
1432
|
+
const skip = (island, reason, message2) => {
|
|
1433
|
+
log(message2);
|
|
1434
|
+
options.onSkip?.(island, reason);
|
|
1435
|
+
};
|
|
1432
1436
|
let ctx;
|
|
1433
1437
|
for (const island of spec.islands) {
|
|
1434
1438
|
const entry = Object.prototype.hasOwnProperty.call(registry, island.name) ? registry[island.name] : void 0;
|
|
1435
1439
|
if (!entry) {
|
|
1436
|
-
|
|
1440
|
+
skip(island, "not in the registry", `page spec: no island called "${island.name}" in this page's registry`);
|
|
1437
1441
|
continue;
|
|
1438
1442
|
}
|
|
1439
1443
|
const el = findSlot(island.slot);
|
|
1440
1444
|
if (el === null) {
|
|
1441
|
-
|
|
1445
|
+
skip(island, "no slot", `page spec: island "${island.name}" wants slot "${island.slot}", which isn't on the page`);
|
|
1442
1446
|
continue;
|
|
1443
1447
|
}
|
|
1444
1448
|
const build = (factory) => {
|
|
@@ -1446,14 +1450,16 @@ function mountIslands(spec, registry, findSlot, context, bus, log, options = {})
|
|
|
1446
1450
|
ctx ?? (ctx = context());
|
|
1447
1451
|
return factory(el, island, ctx, bus);
|
|
1448
1452
|
} catch (err) {
|
|
1449
|
-
|
|
1453
|
+
skip(island, "factory threw", `page spec: island "${island.name}" failed to mount: ${message(err)}`);
|
|
1450
1454
|
return void 0;
|
|
1451
1455
|
}
|
|
1452
1456
|
};
|
|
1453
1457
|
const mountLate = () => {
|
|
1454
1458
|
const late = (factory) => {
|
|
1455
1459
|
const c2 = build(factory);
|
|
1456
|
-
if (c2
|
|
1460
|
+
if (c2 === void 0) return;
|
|
1461
|
+
options.onMount?.(c2, island, el);
|
|
1462
|
+
options.onLateMount?.(c2, island);
|
|
1457
1463
|
};
|
|
1458
1464
|
if (typeof entry === "function") {
|
|
1459
1465
|
late(entry);
|
|
@@ -1463,9 +1469,9 @@ function mountIslands(spec, registry, findSlot, context, bus, log, options = {})
|
|
|
1463
1469
|
(m) => {
|
|
1464
1470
|
const factory = typeof m === "function" ? m : m?.default;
|
|
1465
1471
|
if (typeof factory === "function") late(factory);
|
|
1466
|
-
else
|
|
1472
|
+
else skip(island, "no factory", `page spec: island "${island.name}" loaded, but its module has no factory (a default export or the function itself)`);
|
|
1467
1473
|
},
|
|
1468
|
-
(err) =>
|
|
1474
|
+
(err) => skip(island, "failed to load", `page spec: island "${island.name}" failed to load: ${message(err)}`)
|
|
1469
1475
|
);
|
|
1470
1476
|
};
|
|
1471
1477
|
const strategy = parseLoad(island.load);
|
|
@@ -1481,7 +1487,10 @@ function mountIslands(spec, registry, findSlot, context, bus, log, options = {})
|
|
|
1481
1487
|
continue;
|
|
1482
1488
|
}
|
|
1483
1489
|
const c = build(entry);
|
|
1484
|
-
if (c !== void 0)
|
|
1490
|
+
if (c !== void 0) {
|
|
1491
|
+
out.push(c);
|
|
1492
|
+
options.onMount?.(c, island, el);
|
|
1493
|
+
}
|
|
1485
1494
|
}
|
|
1486
1495
|
return out;
|
|
1487
1496
|
}
|
|
@@ -1489,6 +1498,48 @@ function message(err) {
|
|
|
1489
1498
|
return err instanceof Error ? err.message : String(err);
|
|
1490
1499
|
}
|
|
1491
1500
|
|
|
1501
|
+
// src/page/overlay.ts
|
|
1502
|
+
var STYLE_ID = "island-overlay-style";
|
|
1503
|
+
var CSS = `
|
|
1504
|
+
[data-island-debug] { position: relative; outline: 2px dashed #1565c0; outline-offset: -2px; }
|
|
1505
|
+
[data-island-debug]::after {
|
|
1506
|
+
content: attr(data-island-debug); position: absolute; top: 0; right: 0; z-index: 2147483647;
|
|
1507
|
+
font: 11px/1.4 ui-monospace, monospace; padding: 1px 6px; background: #1565c0; color: #fff; pointer-events: none;
|
|
1508
|
+
}
|
|
1509
|
+
[data-island-state="mounted"] { outline-color: #2e7d32; }
|
|
1510
|
+
[data-island-state="mounted"]::after { background: #2e7d32; }
|
|
1511
|
+
[data-island-state="failed"] { outline-color: #c62828; }
|
|
1512
|
+
[data-island-state="failed"]::after { background: #c62828; }
|
|
1513
|
+
`;
|
|
1514
|
+
var IslandOverlay = class {
|
|
1515
|
+
constructor(doc = document, now = () => performance.now()) {
|
|
1516
|
+
this.doc = doc;
|
|
1517
|
+
this.now = now;
|
|
1518
|
+
if (!doc.getElementById(STYLE_ID)) {
|
|
1519
|
+
const style = doc.createElement("style");
|
|
1520
|
+
style.id = STYLE_ID;
|
|
1521
|
+
style.textContent = CSS;
|
|
1522
|
+
doc.head.appendChild(style);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
/** The island has a slot and hasn't mounted yet. */
|
|
1526
|
+
waiting(island, el) {
|
|
1527
|
+
this.label(island, el, "waiting", "waiting");
|
|
1528
|
+
}
|
|
1529
|
+
/** The island has just mounted. */
|
|
1530
|
+
mounted(island, el) {
|
|
1531
|
+
this.label(island, el, "mounted", `mounted ${Math.round(this.now())} ms`);
|
|
1532
|
+
}
|
|
1533
|
+
/** The island won't mount, for `reason`. */
|
|
1534
|
+
failed(island, el, reason) {
|
|
1535
|
+
this.label(island, el, "failed", reason);
|
|
1536
|
+
}
|
|
1537
|
+
label(island, el, state, text) {
|
|
1538
|
+
el.dataset.islandState = state;
|
|
1539
|
+
el.dataset.islandDebug = [island.name, island.slot, island.load || "eager", text].join(" \xB7 ");
|
|
1540
|
+
}
|
|
1541
|
+
};
|
|
1542
|
+
|
|
1492
1543
|
// src/page/spec.ts
|
|
1493
1544
|
var SPEC_ELEMENT_ID = "page-spec";
|
|
1494
1545
|
var SLOT = /^[a-z][a-z0-9-]*$/;
|
|
@@ -1541,10 +1592,18 @@ var IslandPage = class extends BasePage {
|
|
|
1541
1592
|
console.warn(`page spec: no readable #${SPEC_ELEMENT_ID} on this page, so nothing is mounted`);
|
|
1542
1593
|
return [];
|
|
1543
1594
|
}
|
|
1595
|
+
const findSlot = (slot) => document.querySelector(`[data-slot="${slot}"]`);
|
|
1596
|
+
const overlay = this.showIslandOverlay() ? new IslandOverlay() : void 0;
|
|
1597
|
+
if (overlay) {
|
|
1598
|
+
for (const island of spec.islands) {
|
|
1599
|
+
const el = findSlot(island.slot);
|
|
1600
|
+
if (el) overlay.waiting(island, el);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1544
1603
|
return mountIslands(
|
|
1545
1604
|
spec,
|
|
1546
1605
|
this.registry(),
|
|
1547
|
-
|
|
1606
|
+
findSlot,
|
|
1548
1607
|
() => this.makeContext(spec),
|
|
1549
1608
|
this.eventBus,
|
|
1550
1609
|
(message2) => console.warn(message2),
|
|
@@ -1552,10 +1611,23 @@ var IslandPage = class extends BasePage {
|
|
|
1552
1611
|
defer: (island, el, mount) => this.scheduleLoad(parseLoad(island.load) ?? { kind: "eager" }, el, mount),
|
|
1553
1612
|
onLateMount: (component, island) => {
|
|
1554
1613
|
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
|
-
}
|
|
1614
|
+
},
|
|
1615
|
+
onMount: overlay && ((_c, island, el) => overlay.mounted(island, el)),
|
|
1616
|
+
onSkip: overlay && ((island, reason) => {
|
|
1617
|
+
const el = findSlot(island.slot);
|
|
1618
|
+
if (el) overlay.failed(island, el, reason);
|
|
1619
|
+
})
|
|
1556
1620
|
}
|
|
1557
1621
|
);
|
|
1558
1622
|
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Whether to draw the island overlay. The default is true when the URL has
|
|
1625
|
+
* an `islands` query parameter (`/game?islands`); a subclass can tie it to
|
|
1626
|
+
* its own debug setting instead.
|
|
1627
|
+
*/
|
|
1628
|
+
showIslandOverlay() {
|
|
1629
|
+
return new URLSearchParams(window.location.search).has("islands");
|
|
1630
|
+
}
|
|
1559
1631
|
/**
|
|
1560
1632
|
* Waits for `strategy` and then calls `mount`. Defaults to scheduleMount
|
|
1561
1633
|
* against the window; a subclass or test can replace how the waiting is done.
|
|
@@ -1907,6 +1979,6 @@ var KeyboardShortcutManager = class {
|
|
|
1907
1979
|
}
|
|
1908
1980
|
};
|
|
1909
1981
|
|
|
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 };
|
|
1982
|
+
export { BaseComponent, BasePage, ComponentEventTypes, EventBus, IslandOverlay, IslandPage, KeyboardShortcutManager, KeyboardState, LifecycleController, LifecycleEventTypes, MobileBottomDrawer, Modal, SPEC_ELEMENT_ID, SplashScreen, TemplateLoader, ThemeManager, ToastManager, hasModifierKeys, isInInputContext, lazy, mountIslands, parseLoad, readSpec, scheduleMount, shouldIgnoreShortcut };
|
|
1911
1983
|
//# sourceMappingURL=index.mjs.map
|
|
1912
1984
|
//# sourceMappingURL=index.mjs.map
|