mnfst 0.5.145 → 0.5.147
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/manifest.combobox.css +208 -0
- package/lib/manifest.combobox.js +570 -0
- package/lib/manifest.components.js +152 -0
- package/lib/manifest.css +209 -0
- package/lib/manifest.integrity.json +4 -2
- package/lib/manifest.js +2 -0
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.virtual.js +319 -0
- package/package.json +1 -1
|
@@ -799,6 +799,158 @@ window.ManifestComponentsMutation = {
|
|
|
799
799
|
}
|
|
800
800
|
};
|
|
801
801
|
|
|
802
|
+
// Components — route-level prefetch.
|
|
803
|
+
//
|
|
804
|
+
// Two enhancements that run on top of the existing on-encounter loader:
|
|
805
|
+
//
|
|
806
|
+
// 1. Parallel batch on route change. When manifest:route-change fires,
|
|
807
|
+
// scan the [x-route] subtrees that match the new route and call
|
|
808
|
+
// loadComponent() on every <x-*> tag inside them. The loader
|
|
809
|
+
// deduplicates fetches, so calling it for components that the
|
|
810
|
+
// regular swapping logic is already mounting is harmless — but
|
|
811
|
+
// pre-issuing in parallel saves 50–200 ms vs. one-by-one fetches.
|
|
812
|
+
//
|
|
813
|
+
// 2. Prefetch on hover. When the pointer enters an internal <a href>,
|
|
814
|
+
// derive the target pathname, find the [x-route] subtree(s) that
|
|
815
|
+
// would match it, and prefetch their components. By the time the
|
|
816
|
+
// user clicks the link, the components are warm in the loader's
|
|
817
|
+
// cache and navigation feels instant.
|
|
818
|
+
//
|
|
819
|
+
// Both phases require zero author configuration. Manifest auto-discovers
|
|
820
|
+
// what to prefetch from the existing [x-route] DOM structure.
|
|
821
|
+
|
|
822
|
+
(function () {
|
|
823
|
+
'use strict';
|
|
824
|
+
|
|
825
|
+
// <x-*> tag pattern — lowercase, hyphenated.
|
|
826
|
+
const TAG_RE = /^x-[a-z][a-z0-9-]*$/;
|
|
827
|
+
|
|
828
|
+
// Framework-provided web components (registered by Manifest plugins
|
|
829
|
+
// themselves, not as project components in manifest.json). Skip these
|
|
830
|
+
// when scanning for project components to prefetch.
|
|
831
|
+
const FRAMEWORK_TAGS = new Set(['code', 'code-group']);
|
|
832
|
+
|
|
833
|
+
// Anchors we've already issued a hover-prefetch for. WeakSet so DOM
|
|
834
|
+
// garbage-collects naturally as elements leave the tree.
|
|
835
|
+
const prefetchedAnchors = new WeakSet();
|
|
836
|
+
|
|
837
|
+
function loader() { return window.ManifestComponentsLoader; }
|
|
838
|
+
|
|
839
|
+
// Match a single route pattern against a normalized pathname (no
|
|
840
|
+
// leading/trailing slashes, '/' represented as '/'). Mirrors the
|
|
841
|
+
// router visibility logic so prefetch targets the same subtrees.
|
|
842
|
+
function routeMatches(routeValue, pathname) {
|
|
843
|
+
const pieces = String(routeValue || '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
844
|
+
let matched = false;
|
|
845
|
+
let negated = false;
|
|
846
|
+
for (const piece of pieces) {
|
|
847
|
+
if (piece === '!*') continue; // catch-all only handled by visibility plugin
|
|
848
|
+
if (piece.startsWith('!')) {
|
|
849
|
+
if (piece.slice(1) === pathname) negated = true;
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
if (piece.startsWith('=')) {
|
|
853
|
+
if (piece.slice(1) === pathname) matched = true;
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
if (piece.endsWith('/*')) {
|
|
857
|
+
const prefix = piece.slice(0, -2);
|
|
858
|
+
if (pathname === prefix || pathname.startsWith(prefix + '/')) matched = true;
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
if (piece === pathname) { matched = true; continue; }
|
|
862
|
+
if (pathname.startsWith(piece + '/')) matched = true;
|
|
863
|
+
}
|
|
864
|
+
return matched && !negated;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
function findRouteSubtrees(pathname) {
|
|
868
|
+
const normalized = (pathname || '/') === '/' ? '/' : pathname.replace(/^\/|\/$/g, '');
|
|
869
|
+
const out = [];
|
|
870
|
+
document.querySelectorAll('[x-route]').forEach((el) => {
|
|
871
|
+
const value = el.getAttribute('x-route') || '';
|
|
872
|
+
if (routeMatches(value, normalized)) out.push(el);
|
|
873
|
+
});
|
|
874
|
+
return out;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
function discoverComponentNames(root) {
|
|
878
|
+
const names = new Set();
|
|
879
|
+
if (!root || !root.querySelectorAll) return names;
|
|
880
|
+
// querySelectorAll('*') is the fastest path for "every descendant".
|
|
881
|
+
// We filter by tag name in JS — there's no CSS selector for "tag
|
|
882
|
+
// name starts with x-". A page typically has a few thousand nodes,
|
|
883
|
+
// which scans in well under a millisecond.
|
|
884
|
+
root.querySelectorAll('*').forEach((el) => {
|
|
885
|
+
const tag = el.tagName.toLowerCase();
|
|
886
|
+
if (!tag.startsWith('x-') || !TAG_RE.test(tag)) return;
|
|
887
|
+
const name = tag.slice(2);
|
|
888
|
+
if (!FRAMEWORK_TAGS.has(name)) names.add(name);
|
|
889
|
+
});
|
|
890
|
+
return names;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function prefetchForRoute(pathname) {
|
|
894
|
+
const L = loader();
|
|
895
|
+
if (!L || typeof L.loadComponent !== 'function') return;
|
|
896
|
+
const subtrees = findRouteSubtrees(pathname);
|
|
897
|
+
if (!subtrees.length) return;
|
|
898
|
+
const names = new Set();
|
|
899
|
+
for (const subtree of subtrees) {
|
|
900
|
+
discoverComponentNames(subtree).forEach((n) => names.add(n));
|
|
901
|
+
}
|
|
902
|
+
names.forEach((name) => {
|
|
903
|
+
try { L.loadComponent(name); } catch { /* swallow — dedup is internal */ }
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function hrefToPathname(href) {
|
|
908
|
+
if (!href) return null;
|
|
909
|
+
if (/^(#|mailto:|tel:|javascript:)/i.test(href)) return null;
|
|
910
|
+
try {
|
|
911
|
+
const url = new URL(href, window.location.href);
|
|
912
|
+
if (url.origin !== window.location.origin) return null;
|
|
913
|
+
return url.pathname || '/';
|
|
914
|
+
} catch {
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
function initialize() {
|
|
920
|
+
// 1) Parallel batch on route change.
|
|
921
|
+
window.addEventListener('manifest:route-change', (event) => {
|
|
922
|
+
const detail = (event && event.detail) || {};
|
|
923
|
+
const path = detail.normalizedPath || detail.to || '/';
|
|
924
|
+
const pathname = String(path).startsWith('/') ? String(path) : '/' + String(path);
|
|
925
|
+
prefetchForRoute(pathname);
|
|
926
|
+
});
|
|
927
|
+
|
|
928
|
+
// 2) Hover prefetch. Use pointerover (bubbles) and check the closest
|
|
929
|
+
// anchor on each event so we get a single trigger per anchor entry
|
|
930
|
+
// without needing pointerenter (which doesn't bubble). Dedup via
|
|
931
|
+
// a WeakSet so repeat moves within the anchor don't re-scan.
|
|
932
|
+
document.addEventListener('pointerover', (e) => {
|
|
933
|
+
if (!e.target || !e.target.closest) return;
|
|
934
|
+
const a = e.target.closest('a[href]');
|
|
935
|
+
if (!a || prefetchedAnchors.has(a)) return;
|
|
936
|
+
// Author opt-out: `data-no-prefetch` skips this anchor.
|
|
937
|
+
if (a.hasAttribute('data-no-prefetch')) return;
|
|
938
|
+
const href = a.getAttribute('href');
|
|
939
|
+
const pathname = hrefToPathname(href);
|
|
940
|
+
if (!pathname) return;
|
|
941
|
+
prefetchedAnchors.add(a);
|
|
942
|
+
prefetchForRoute(pathname);
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
if (document.readyState === 'loading') {
|
|
947
|
+
document.addEventListener('DOMContentLoaded', initialize);
|
|
948
|
+
} else {
|
|
949
|
+
initialize();
|
|
950
|
+
}
|
|
951
|
+
})();
|
|
952
|
+
|
|
953
|
+
|
|
802
954
|
// Main initialization for Manifest Components
|
|
803
955
|
async function initializeComponents() {
|
|
804
956
|
// Registry.initialize() may fetch manifest.json (async) when the loader
|
package/lib/manifest.css
CHANGED
|
@@ -1456,6 +1456,215 @@
|
|
|
1456
1456
|
}
|
|
1457
1457
|
}
|
|
1458
1458
|
|
|
1459
|
+
/* Manifest Combobox */
|
|
1460
|
+
|
|
1461
|
+
@layer components {
|
|
1462
|
+
|
|
1463
|
+
/* Field shell — inherits input tokens so it reads as a normal field */
|
|
1464
|
+
:where(.combobox):not(.unstyle) {
|
|
1465
|
+
display: flex;
|
|
1466
|
+
flex-wrap: wrap;
|
|
1467
|
+
align-items: center;
|
|
1468
|
+
gap: var(--spacing, 0.25rem);
|
|
1469
|
+
width: 100%;
|
|
1470
|
+
max-width: 100%;
|
|
1471
|
+
min-height: var(--spacing-field-height, 2.25rem);
|
|
1472
|
+
padding: calc(var(--spacing, 0.25rem) * 1.25) var(--spacing-field-padding, 0.625rem);
|
|
1473
|
+
color: var(--color-field-inverse, oklch(43.9% 0 0));
|
|
1474
|
+
background-color: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent));
|
|
1475
|
+
border-radius: var(--radius, 0.5rem);
|
|
1476
|
+
transition: var(--transition);
|
|
1477
|
+
cursor: text;
|
|
1478
|
+
|
|
1479
|
+
&:hover:has(> :where(input:not([type=hidden]), textarea, button):not([hidden])) {
|
|
1480
|
+
background-color: var(--color-field-surface-hover, color-mix(in oklch, oklch(20.5% 0 0) 15%, transparent))
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
&:not(:has(> :where(input:not([type=hidden]), textarea, button):not([hidden]))) {
|
|
1484
|
+
cursor: default
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
&:focus-within {
|
|
1488
|
+
background-color: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent));
|
|
1489
|
+
box-shadow: 0 0 0 2px color-mix(in oklch, var(--color-content-stark, oklch(43.9% 0 0)) 30%, transparent)
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
&:has(.combobox-chip) {
|
|
1493
|
+
padding-inline: calc(var(--spacing, 0.25rem) * 1.25)
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
&:has(> :where(input, textarea):disabled) {
|
|
1497
|
+
opacity: .5;
|
|
1498
|
+
pointer-events: none
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
/* Inner typing surface */
|
|
1502
|
+
&> :where(input:not([type=hidden]), textarea) {
|
|
1503
|
+
flex: 1 0 auto;
|
|
1504
|
+
width: auto;
|
|
1505
|
+
min-width: 7rem;
|
|
1506
|
+
height: auto;
|
|
1507
|
+
margin: 0;
|
|
1508
|
+
padding: 0;
|
|
1509
|
+
color: inherit;
|
|
1510
|
+
background: transparent;
|
|
1511
|
+
field-sizing: content;
|
|
1512
|
+
|
|
1513
|
+
&:hover,
|
|
1514
|
+
&:focus-visible {
|
|
1515
|
+
background: transparent;
|
|
1516
|
+
box-shadow: none
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
&>textarea {
|
|
1521
|
+
resize: none
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/* Chips */
|
|
1526
|
+
:where(.combobox-chip):not(.unstyle) {
|
|
1527
|
+
display: inline-flex;
|
|
1528
|
+
align-items: center;
|
|
1529
|
+
gap: var(--spacing, 0.25rem);
|
|
1530
|
+
max-width: 100%;
|
|
1531
|
+
height: calc(var(--spacing-field-height, 2.25rem) - var(--spacing, 0.25rem) * 2.5);
|
|
1532
|
+
padding-inline-start: calc(var(--spacing, 0.25rem) * 2);
|
|
1533
|
+
font-size: 0.875rem;
|
|
1534
|
+
color: var(--color-content-stark, oklch(43.9% 0 0));
|
|
1535
|
+
background-color: var(--color-popover-surface, oklch(100% 0 0));
|
|
1536
|
+
border-radius: calc(var(--radius, 0.5rem) * 0.7);
|
|
1537
|
+
overflow: hidden;
|
|
1538
|
+
user-select: none;
|
|
1539
|
+
|
|
1540
|
+
/* Label */
|
|
1541
|
+
&>span {
|
|
1542
|
+
overflow: hidden;
|
|
1543
|
+
text-overflow: ellipsis;
|
|
1544
|
+
white-space: nowrap
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
/* Remove button */
|
|
1548
|
+
&>button {
|
|
1549
|
+
display: inline-flex;
|
|
1550
|
+
align-items: center;
|
|
1551
|
+
justify-content: center;
|
|
1552
|
+
min-width: 0;
|
|
1553
|
+
height: 100%;
|
|
1554
|
+
aspect-ratio: 1 / 1;
|
|
1555
|
+
padding: 0;
|
|
1556
|
+
font-size: 1em;
|
|
1557
|
+
line-height: 1;
|
|
1558
|
+
color: var(--color-content-neutral, oklch(43.9% 0 0));
|
|
1559
|
+
background: transparent;
|
|
1560
|
+
border-radius: 0;
|
|
1561
|
+
cursor: pointer;
|
|
1562
|
+
|
|
1563
|
+
&:hover {
|
|
1564
|
+
color: var(--color-content-stark, oklch(43.9% 0 0));
|
|
1565
|
+
background: color-mix(in oklch, var(--color-content-stark, oklch(43.9% 0 0)) 12%, transparent)
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
/* Failed validation */
|
|
1570
|
+
&[aria-invalid="true"] {
|
|
1571
|
+
color: var(--color-negative-inverse, oklch(44.4% 0.177 26.899));
|
|
1572
|
+
background-color: var(--color-negative-surface, oklch(80.8% 0.114 19.571))
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
/* Trigger (editor:none button mode) — transparent; the shell is the field.
|
|
1577
|
+
Fills the row like the input editor, with a select-style caret. */
|
|
1578
|
+
:where(.combobox) > button:not(.unstyle) {
|
|
1579
|
+
flex: 1 1 auto;
|
|
1580
|
+
align-self: stretch;
|
|
1581
|
+
min-width: 7rem;
|
|
1582
|
+
justify-content: flex-start;
|
|
1583
|
+
gap: var(--spacing, 0.25rem);
|
|
1584
|
+
height: auto;
|
|
1585
|
+
min-height: calc(var(--spacing-field-height, 2.25rem) - var(--spacing, 0.25rem) * 2.5);
|
|
1586
|
+
padding: 0;
|
|
1587
|
+
color: inherit;
|
|
1588
|
+
background: transparent;
|
|
1589
|
+
cursor: pointer;
|
|
1590
|
+
|
|
1591
|
+
&:hover {
|
|
1592
|
+
background: transparent
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
/* Caret */
|
|
1596
|
+
&::after {
|
|
1597
|
+
content: '';
|
|
1598
|
+
flex: none;
|
|
1599
|
+
width: 1em;
|
|
1600
|
+
height: 1em;
|
|
1601
|
+
margin-inline-start: auto;
|
|
1602
|
+
background-color: var(--color-content-subtle, oklch(55.6% 0 0));
|
|
1603
|
+
mask: var(--icon-chevron-down, url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m6 9 6 6 6-6'/%3E%3C/svg%3E")) center / contain no-repeat
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
/* Button-only field (no chips): the button IS the field — it fills the whole
|
|
1608
|
+
wrapper and carries the padding, so the entire area is the click target. */
|
|
1609
|
+
:where(.combobox):has(> button:not(.unstyle)):not(:has(.combobox-chip)) {
|
|
1610
|
+
padding: 0;
|
|
1611
|
+
|
|
1612
|
+
&>button:not(.unstyle) {
|
|
1613
|
+
min-height: var(--spacing-field-height, 2.25rem);
|
|
1614
|
+
padding: calc(var(--spacing, 0.25rem) * 1.25) var(--spacing-field-padding, 0.625rem)
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/* Listbox — base look comes from menu[popover]; these are combobox-only extras */
|
|
1619
|
+
:where(menu[role=listbox]):not(.unstyle) {
|
|
1620
|
+
|
|
1621
|
+
/* Active descendant (mirrors hover) */
|
|
1622
|
+
& :where([role=option][aria-current="true"]) {
|
|
1623
|
+
color: var(--color-field-inverse, oklch(43.9% 0 0));
|
|
1624
|
+
background-color: var(--color-field-surface, color-mix(in oklch, oklch(20.5% 0 0) 10%, transparent))
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
/* Filtered out */
|
|
1628
|
+
& :where([role=option][hidden]) {
|
|
1629
|
+
display: none
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
/* Selected (multiple) */
|
|
1633
|
+
& :where([role=option][aria-selected="true"]) {
|
|
1634
|
+
font-weight: 600
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
/* "Add …" create row */
|
|
1638
|
+
& :where(.combobox-create) {
|
|
1639
|
+
color: var(--color-content-neutral, oklch(43.9% 0 0))
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
/* Empty state */
|
|
1643
|
+
& :where(.combobox-empty) {
|
|
1644
|
+
padding: 0.5rem;
|
|
1645
|
+
color: var(--color-content-subtle, oklch(55.6% 0 0));
|
|
1646
|
+
cursor: default;
|
|
1647
|
+
|
|
1648
|
+
&:hover {
|
|
1649
|
+
background: transparent
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
/* Screen-reader-only live region */
|
|
1655
|
+
:where(.combobox)> :where([role=status]) {
|
|
1656
|
+
position: absolute;
|
|
1657
|
+
width: 1px;
|
|
1658
|
+
height: 1px;
|
|
1659
|
+
margin: -1px;
|
|
1660
|
+
padding: 0;
|
|
1661
|
+
overflow: hidden;
|
|
1662
|
+
clip: rect(0 0 0 0);
|
|
1663
|
+
white-space: nowrap;
|
|
1664
|
+
border: 0
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1459
1668
|
/* Manifest Date Picker */
|
|
1460
1669
|
|
|
1461
1670
|
@layer utilities {
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"manifest.code.js": "sha384-nP6DncLx/UuJtloyVKMCOXwIBAq32DshTb/Lc0vVRBWX7kSbxiBnY5aEyqqvK8Kg",
|
|
7
7
|
"manifest.color.js": "sha384-6Rv3LxyTcZNjrhtayQfqRdCx0uSZ4BiEbgEI98I62eTvp8Aw7LBIoNJ0Je1oktwL",
|
|
8
8
|
"manifest.colorpicker.js": "sha384-Wqz0ZIbeIi7KarqqqSLsQk+7E/fMaKhb32hrq5/eWzX1yjqMrpPZKH8y+jZ3mfg+",
|
|
9
|
-
"manifest.
|
|
9
|
+
"manifest.combobox.js": "sha384-AEEtOVCcoGgCyKPbZSzKtRhz8G4VbE8BD5LC/urGqzxjMXNP9NrExeWrENXHCLsg",
|
|
10
|
+
"manifest.components.js": "sha384-mzPFoM0vqL9dnTVLMN3OrmO+KCgSqGknM1fd7bM1xzYeCco5OaZi56IMR5RS5oad",
|
|
10
11
|
"manifest.data.js": "sha384-bCYTYyAYNVkg5pSwGcoe07Dgf5B7JDN7GtOIQdS+BtrBStQwvjZtskiQ38Bncvrf",
|
|
11
12
|
"manifest.datepicker.js": "sha384-NEb/H4vuR3CFtRcodHsm3jJjrcYW2JMpDlQKlgwTrzpMMTcDkFKYXzAYJD0gZ7Ov",
|
|
12
13
|
"manifest.dropdowns.js": "sha384-a2j9Z1LWolyZANlfeBc1aIFQ0kf0UDeOZ8TetulYbpRS6T/zaD/OWSMGvz+gRehX",
|
|
@@ -26,5 +27,6 @@
|
|
|
26
27
|
"manifest.tooltips.js": "sha384-ADzAx9D0HWq2b46mvNG05iOwPmEWdiFZNpEOXONSbBxs4xj1B/bzNL7S3x2R9cS1",
|
|
27
28
|
"manifest.url.parameters.js": "sha384-FIufiClqDx1rJpU/QUc9z/D43qClQ6Qm8rBahipbJl9BDHUvhrOsUDegmTWW7Tuf",
|
|
28
29
|
"manifest.utilities.js": "sha384-HWyVkjQoDRlWFKDBQw4RQOYODkBcU72NHW6l1p4bhQv1RtN0/XtnjwIb+lQK6+zv",
|
|
29
|
-
"manifest.js": "sha384-
|
|
30
|
+
"manifest.virtual.js": "sha384-J2+MpRskVH39R2DmHUib2bItuGsvSLEhPM+83iznrdfQFMZ63Ea6xwLeCsG04jOl",
|
|
31
|
+
"manifest.js": "sha384-IsNGBIHGuUF5ABO58nkkZJQq1Ilt0wIsz+X2qR5hx4cGEhZez7GCmB8rAowJmrHS"
|
|
30
32
|
}
|
package/lib/manifest.js
CHANGED