youiyoux 0.1.2 → 0.1.4
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 +10 -0
- package/dist/chunks/{chunk-S7UV34H5.js → chunk-42YJX3W5.js} +1 -3
- package/dist/chunks/{chunk-FUB7B3VK.js → chunk-4BBYLTZX.js} +10 -10
- package/dist/chunks/chunk-52KOKYY6.js +8710 -0
- package/dist/chunks/chunk-FJZFCAL5.js +129 -0
- package/dist/chunks/chunk-FVVL5JCY.js +24 -0
- package/dist/chunks/{chunk-UHPK62Q5.js → chunk-M5XZWCPS.js} +240 -60
- package/dist/chunks/{chunk-ZLRFD5JI.js → chunk-NYDJYMID.js} +263 -16
- package/dist/chunks/{src-7ENJHYG4.js → chunk-RDTHHRZN.js} +319 -165
- package/dist/chunks/{chunk-E4HNK7VF.js → chunk-WNTS7ZO4.js} +1 -1
- package/dist/chunks/chunk-XAEMVEYX.js +188 -0
- package/dist/chunks/{chunk-CLNMVQZJ.js → chunk-YFCMTTXS.js} +708 -494
- package/dist/chunks/chunk-YJ7WMBTT.js +13761 -0
- package/dist/chunks/src-5IP4NGKT.js +115 -0
- package/dist/chunks/src-6CJR547Y.js +124 -0
- package/dist/chunks/{src-WQWYJ6IQ.js → src-BPETAFLW.js} +175 -76
- package/dist/chunks/{src-B742AYFC.js → src-LLV7IY6W.js} +55 -16
- package/dist/chunks/src-RHNZELGE.js +306 -0
- package/dist/chunks/{src-4KFNL3MY.js → src-SFKFERZ2.js} +18 -8
- package/dist/chunks/{src-VEHGMKYV.js → src-VL2ZYO6X.js} +4 -4
- package/dist/hub/assets/Badge-CUJUit4d.js +1 -0
- package/dist/hub/assets/CandidatePanel-CnbK4S0j.js +1 -0
- package/dist/hub/assets/CatalogScreen-B5OVL-AR.js +1 -0
- package/dist/hub/assets/ChangesScreen-GwGqJwxN.js +1 -0
- package/dist/hub/assets/CheatSheet-BLSOq-xa.js +1 -0
- package/dist/hub/assets/CodeBlock-CsiGFgvI.js +1 -0
- package/dist/hub/assets/CommandPalette-CAWQfdXJ.js +1 -0
- package/dist/hub/assets/CopyButton-DE8drl4P.js +1 -0
- package/dist/hub/assets/Disclosure-B1kTgPgk.js +1 -0
- package/dist/hub/assets/DiscoverScreen-Tl_Z6mgY.js +2 -0
- package/dist/hub/assets/DraftEditor-yIDapXTs.js +5 -0
- package/dist/hub/assets/Field-LwrJXoOs.js +1 -0
- package/dist/hub/assets/GapsScreen-DXZAlm6v.js +1 -0
- package/dist/hub/assets/HomeScreen-CEpiVhOa.js +1 -0
- package/dist/hub/assets/InventoryScreen-CEG3Pmw_.js +1 -0
- package/dist/hub/assets/KindIcon-BJ6bz-ny.js +1 -0
- package/dist/hub/assets/LibraryScreen-IaVnxrX9.js +1 -0
- package/dist/hub/assets/LicenceBadge-CLCUMMHE.js +1 -0
- package/dist/hub/assets/Opened-DJyf4Hnj.js +1 -0
- package/dist/hub/assets/Preview-C069zVMP.js +1 -0
- package/dist/hub/assets/RuleDetail-B4g2-TRe.js +3 -0
- package/dist/hub/assets/RulesScreen-CAaXIWjO.js +3 -0
- package/dist/hub/assets/ScreenImage-DcI7_G3O.js +1 -0
- package/dist/hub/assets/ScreensScreen-DwczCjZD.js +1 -0
- package/dist/hub/assets/SearchField-DaCpNAj6.js +1 -0
- package/dist/hub/assets/Section-BTnvUq_W.js +1 -0
- package/dist/hub/assets/Segmented-Dzi1x49S.js +1 -0
- package/dist/hub/assets/ServiceDown-Bv-BPXro.js +1 -0
- package/dist/hub/assets/SpecimenCapture-DlsjshVE.js +1 -0
- package/dist/hub/assets/Specimens-C-lHp7sr.js +2 -0
- package/dist/hub/assets/StackScreen-DkmELsqR.js +1 -0
- package/dist/hub/assets/StubScreens-Bt7lWLVK.js +1 -0
- package/dist/hub/assets/StyleScreen-tq1tbRBo.js +1 -0
- package/dist/hub/assets/Swatch-KDz4qxdM.js +1 -0
- package/dist/hub/assets/Tabs-1QQDS0I6.js +1 -0
- package/dist/hub/assets/TokenDetail-DvCw6GqC.js +1 -0
- package/dist/hub/assets/TokenValue-CsPRc2ai.js +1 -0
- package/dist/hub/assets/TokensScreen-DoENV8Xy.js +1 -0
- package/dist/hub/assets/arrow-right-DcbNDzqs.js +1 -0
- package/dist/hub/assets/bot-B3gC9oUR.js +1 -0
- package/dist/hub/assets/button-6mvMVtpb.js +1 -0
- package/dist/hub/assets/button.demo-DuU0DQbv.js +1 -0
- package/dist/hub/assets/card.demo-CufAxMAA.js +1 -0
- package/dist/hub/assets/chevron-down-CzN07vMi.js +1 -0
- package/dist/hub/assets/circle-alert-DT2LC4yf.js +1 -0
- package/dist/hub/assets/circle-check-DkwBMT62.js +1 -0
- package/dist/hub/assets/client-D7whEyep.js +1 -0
- package/dist/hub/assets/clsx-DB0hHKMi.js +1 -0
- package/dist/hub/assets/compass-BkKOZPYe.js +1 -0
- package/dist/hub/assets/contrast-BkNHUAPa.js +1 -0
- package/dist/hub/assets/createLucideIcon-CGDJWtKO.js +1 -0
- package/dist/hub/assets/discover-XjJEViwk.js +1 -0
- package/dist/hub/assets/dist-BYQYaPBV.js +1 -0
- package/dist/hub/assets/dist-Bk4srtDn.js +41 -0
- package/dist/hub/assets/dist-BogNzeK9.js +1 -0
- package/dist/hub/assets/dist-D0z7Bvsy.js +1 -0
- package/dist/hub/assets/download-BQI-Si9R.js +1 -0
- package/dist/hub/assets/engine-CMmt9yEz.js +1 -0
- package/dist/hub/assets/esm-NPpg23M8.js +1 -0
- package/dist/hub/assets/family-tiles-CyTdy_cP.js +1 -0
- package/dist/hub/assets/format-DxAYNTN_.js +1 -0
- package/dist/hub/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/hub/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/hub/assets/geist-latin-core-vkBVTr4s.woff2 +0 -0
- package/dist/hub/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/hub/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/hub/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/hub/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/hub/assets/geist-mono-latin-core-DccGGzmg.woff2 +0 -0
- package/dist/hub/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/hub/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/hub/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/hub/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/hub/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/hub/assets/git-pull-request-arrow-RqUUIRCU.js +1 -0
- package/dist/hub/assets/input.demo-238gqWpz.js +1 -0
- package/dist/hub/assets/inventory-BI8QBdar.js +1 -0
- package/dist/hub/assets/inventory-source-lZYzcA8O.js +1 -0
- package/dist/hub/assets/jsx-runtime-D6zNwnaE.js +9 -0
- package/dist/hub/assets/layers-DfzdK_wG.js +1 -0
- package/dist/hub/assets/layout-grid-xFY9L9Oc.js +1 -0
- package/dist/hub/assets/library-W5R8GwvG.js +1 -0
- package/dist/hub/assets/main-7snyIdoi.css +2 -0
- package/dist/hub/assets/main-B9CIkk5m.js +2 -0
- package/dist/hub/assets/minus-BDifFhOo.js +1 -0
- package/dist/hub/assets/monitor-X_lELkcU.js +1 -0
- package/dist/hub/assets/mouse-pointer-click-CVJ6hWg8.js +1 -0
- package/dist/hub/assets/paintbrush-DOkEgSTO.js +1 -0
- package/dist/hub/assets/plural-BbGQPQKA.js +1 -0
- package/dist/hub/assets/preview-BA8CPsKb.css +2 -0
- package/dist/hub/assets/preview-DUm13vr1.js +3 -0
- package/dist/hub/assets/protocol-caP6umNL.js +1 -0
- package/dist/hub/assets/react-DB-4Zxce.js +1 -0
- package/dist/hub/assets/shield-check-0ka0kQct.js +1 -0
- package/dist/hub/assets/trash-B7aEfJps.js +1 -0
- package/dist/hub/assets/triangle-alert-Dkdi9eDR.js +1 -0
- package/dist/hub/assets/try-live-zX3CSd3P.js +1 -0
- package/dist/hub/assets/utils-BoaXfs8y.js +1 -0
- package/dist/hub/assets/values-DzxR_TlI.js +1 -0
- package/dist/hub/assets/worker-Bh-wSp42.js +1 -0
- package/dist/hub/assets/workflow-jpV8wh-U.js +1 -0
- package/dist/hub/assets/x-MLbFVa4v.js +1 -0
- package/dist/hub/favicon.svg +1 -0
- package/dist/hub/index.html +35 -0
- package/dist/hub/kit/candidates.json +1 -0
- package/dist/hub/kit/chunks/chunk-2NYFUOIV.js +14 -0
- package/dist/hub/kit/chunks/chunk-DCANE7XH.js +1 -0
- package/dist/hub/kit/chunks/chunk-FTGHCY4I.js +14 -0
- package/dist/hub/kit/chunks/chunk-IBF3UTJF.js +33 -0
- package/dist/hub/kit/chunks/chunk-LLXY4VSH.js +1 -0
- package/dist/hub/kit/chunks/chunk-PUPZMW4P.js +14 -0
- package/dist/hub/kit/chunks/chunk-PWLNZQET.js +1 -0
- package/dist/hub/kit/chunks/chunk-ULXWVOKJ.js +1 -0
- package/dist/hub/kit/chunks/chunk-WM4BGGMK.js +1 -0
- package/dist/hub/kit/chunks/chunk-ZQUNRK72.js +1 -0
- package/dist/hub/kit/class-variance-authority.js +1 -0
- package/dist/hub/kit/clsx.js +1 -0
- package/dist/hub/kit/fonts/geist-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/hub/kit/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/hub/kit/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/hub/kit/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/dist/hub/kit/fonts/geist-vietnamese-wght-normal.woff2 +0 -0
- package/dist/hub/kit/frame.css.src +73 -0
- package/dist/hub/kit/frame.js +2 -0
- package/dist/hub/kit/lucide-react.js +1878 -0
- package/dist/hub/kit/preview.html +13 -0
- package/dist/hub/kit/radix-ui-react-dialog.js +41 -0
- package/dist/hub/kit/radix-ui-react-label.js +1 -0
- package/dist/hub/kit/radix-ui-react-separator.js +1 -0
- package/dist/hub/kit/radix-ui-react-slot.js +1 -0
- package/dist/hub/kit/radix-ui-react-switch.js +1 -0
- package/dist/hub/kit/radix-ui-react-tabs.js +1 -0
- package/dist/hub/kit/react-dom-client.js +1 -0
- package/dist/hub/kit/react-dom.js +1 -0
- package/dist/hub/kit/react-jsx-runtime.js +1 -0
- package/dist/hub/kit/react.js +1 -0
- package/dist/hub/kit/tailwind-merge.js +1 -0
- package/dist/hub/kit/tailwindcss/index.css +950 -0
- package/dist/hub/kit/tailwindcss/preflight.css +398 -0
- package/dist/hub/kit/tailwindcss/theme.css +510 -0
- package/dist/hub/kit/tailwindcss/utilities.css +1 -0
- package/dist/hub-demo/frame/button.demo.js +1 -0
- package/dist/hub-demo/frame/card.demo.js +1 -0
- package/dist/hub-demo/frame/demos.js +6 -0
- package/dist/hub-demo/frame/frame.css +770 -0
- package/dist/hub-demo/frame/input.demo.js +1 -0
- package/dist/hub-demo/preview/components/button.demo.tsx +47 -0
- package/dist/hub-demo/preview/components/button.tsx +31 -0
- package/dist/hub-demo/preview/components/card.demo.tsx +26 -0
- package/dist/hub-demo/preview/components/card.tsx +20 -0
- package/dist/hub-demo/preview/components/input.demo.tsx +39 -0
- package/dist/hub-demo/preview/components/input.tsx +19 -0
- package/dist/hub-demo/preview/components/utils.ts +5 -0
- package/dist/hub-demo/preview/system.css +161 -0
- package/dist/hub-demo/public/data/demo-app.usage.bedd9c82fe.json +1 -0
- package/dist/hub-demo/public/data/demo.catalog.a605de2281.json +1 -0
- package/dist/hub-demo/public/data/gaps.129a93538d.json +1 -0
- package/dist/hub-demo/public/data/inventory.165a4f6408.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.badge.ad0238784e.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.button.3249daff35.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.card.9ea88708ac.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.dialog.8b6574d93a.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.input.bdffb756a7.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.link-as-button.1ce7faa1f3.json +1 -0
- package/dist/hub-demo/public/data/inventory.console.tabs.813e694c44.json +1 -0
- package/dist/hub-demo/public/data/inventory.extras.e5d06c6ff4.json +1 -0
- package/dist/hub-demo/public/data/inventory.site.badge.047a68f644.json +1 -0
- package/dist/hub-demo/public/data/inventory.site.button.720938384e.json +1 -0
- package/dist/hub-demo/public/data/inventory.site.card.d8df5f6873.json +1 -0
- package/dist/hub-demo/public/data/inventory.site.link-as-button.9c1f8a55bf.json +1 -0
- package/dist/hub-demo/public/data/inventory.site.tabs.59bd0200b9.json +1 -0
- package/dist/hub-demo/public/data/manifest.json +39 -0
- package/dist/hub-demo/public/data/specimens.console.dark.046471907d.css +786 -0
- package/dist/hub-demo/public/data/specimens.console.light.aaffa2d213.css +786 -0
- package/dist/hub-demo/public/data/specimens.site.dark.94a6706908.css +92 -0
- package/dist/hub-demo/public/data/specimens.site.light.3ddbc8d28d.css +92 -0
- package/dist/hub-demo/public/previews/button.dark.webp +0 -0
- package/dist/hub-demo/public/previews/button.light.webp +0 -0
- package/dist/hub-demo/public/previews/card.dark.webp +0 -0
- package/dist/hub-demo/public/previews/card.light.webp +0 -0
- package/dist/hub-demo/public/previews/input.dark.webp +0 -0
- package/dist/hub-demo/public/previews/input.light.webp +0 -0
- package/dist/hub-previews.js +173 -0
- package/dist/hub-server.js +6329 -0
- package/dist/hub-snapshot.js +573 -0
- package/dist/schema/youi.gaps.schema.json +235 -0
- package/dist/schema/youi.request.schema.json +229 -0
- package/dist/tailwind-worker.js +3 -3
- package/dist/youi.js +10 -8
- package/dist/youiyoux.js +10 -8
- package/package.json +4 -4
- package/dist/chunks/chunk-3ZHGONNA.js +0 -21797
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* src/styles/ui.css */
|
|
2
|
+
/* The site's kit: one BEM block per element, modifiers with --. */
|
|
3
|
+
:root {
|
|
4
|
+
--ui-radius: 8px;
|
|
5
|
+
--ui-control-height: 32px;
|
|
6
|
+
--ui-space: 4px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ui-button {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
height: var(--ui-control-height);
|
|
13
|
+
padding: 0 calc(var(--ui-space) * 3);
|
|
14
|
+
border-radius: var(--ui-radius);
|
|
15
|
+
font-size: 0.875rem;
|
|
16
|
+
font-weight: 500;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.ui-button--sm {
|
|
20
|
+
height: 28px;
|
|
21
|
+
padding: 0 10px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ui-button:is(:hover, .youi-state-hover, .youi-state-hover *) {
|
|
25
|
+
background: #f4f4f5;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@media (max-width: 640px) {
|
|
29
|
+
.ui-button {
|
|
30
|
+
height: 40px;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ui-badge {
|
|
35
|
+
display: inline-flex;
|
|
36
|
+
height: 20px;
|
|
37
|
+
padding: 0 8px;
|
|
38
|
+
border-radius: 999px;
|
|
39
|
+
font-size: 12px;
|
|
40
|
+
font-weight: 500;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.ui-card {
|
|
44
|
+
padding: 24px;
|
|
45
|
+
border-radius: 12px;
|
|
46
|
+
border: 1px solid #e4e4e7;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ui-tabs {
|
|
50
|
+
display: flex;
|
|
51
|
+
gap: 4px;
|
|
52
|
+
padding: 4px;
|
|
53
|
+
border-radius: 10px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.ui-tab {
|
|
57
|
+
height: 28px;
|
|
58
|
+
padding: 0 12px;
|
|
59
|
+
border-radius: var(--ui-radius);
|
|
60
|
+
font-size: 14px;
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.ui-tab--active {
|
|
65
|
+
background: #fff;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* src/styles/marketing.css */
|
|
69
|
+
/* The marketing pages' own styles: a plain .badge, with no kit prefix. */
|
|
70
|
+
.badge {
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
height: 20px;
|
|
74
|
+
padding: 0 8px;
|
|
75
|
+
border-radius: 9999px;
|
|
76
|
+
font-size: 12px;
|
|
77
|
+
font-weight: 500;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.badge--muted {
|
|
81
|
+
opacity: 0.7;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Named like an element, but sets no shape: not a kit member. */
|
|
85
|
+
.tag-list {
|
|
86
|
+
display: flex;
|
|
87
|
+
gap: 8px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
:root { color-scheme: dark; }
|
|
91
|
+
|
|
92
|
+
/* youi-states: forced-state twins */
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* src/styles/ui.css */
|
|
2
|
+
/* The site's kit: one BEM block per element, modifiers with --. */
|
|
3
|
+
:root {
|
|
4
|
+
--ui-radius: 8px;
|
|
5
|
+
--ui-control-height: 32px;
|
|
6
|
+
--ui-space: 4px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ui-button {
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
height: var(--ui-control-height);
|
|
13
|
+
padding: 0 calc(var(--ui-space) * 3);
|
|
14
|
+
border-radius: var(--ui-radius);
|
|
15
|
+
font-size: 0.875rem;
|
|
16
|
+
font-weight: 500;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.ui-button--sm {
|
|
20
|
+
height: 28px;
|
|
21
|
+
padding: 0 10px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ui-button:is(:hover, .youi-state-hover, .youi-state-hover *) {
|
|
25
|
+
background: #f4f4f5;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@media (max-width: 640px) {
|
|
29
|
+
.ui-button {
|
|
30
|
+
height: 40px;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ui-badge {
|
|
35
|
+
display: inline-flex;
|
|
36
|
+
height: 20px;
|
|
37
|
+
padding: 0 8px;
|
|
38
|
+
border-radius: 999px;
|
|
39
|
+
font-size: 12px;
|
|
40
|
+
font-weight: 500;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.ui-card {
|
|
44
|
+
padding: 24px;
|
|
45
|
+
border-radius: 12px;
|
|
46
|
+
border: 1px solid #e4e4e7;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ui-tabs {
|
|
50
|
+
display: flex;
|
|
51
|
+
gap: 4px;
|
|
52
|
+
padding: 4px;
|
|
53
|
+
border-radius: 10px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.ui-tab {
|
|
57
|
+
height: 28px;
|
|
58
|
+
padding: 0 12px;
|
|
59
|
+
border-radius: var(--ui-radius);
|
|
60
|
+
font-size: 14px;
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.ui-tab--active {
|
|
65
|
+
background: #fff;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* src/styles/marketing.css */
|
|
69
|
+
/* The marketing pages' own styles: a plain .badge, with no kit prefix. */
|
|
70
|
+
.badge {
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
height: 20px;
|
|
74
|
+
padding: 0 8px;
|
|
75
|
+
border-radius: 9999px;
|
|
76
|
+
font-size: 12px;
|
|
77
|
+
font-weight: 500;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.badge--muted {
|
|
81
|
+
opacity: 0.7;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Named like an element, but sets no shape: not a kit member. */
|
|
85
|
+
.tag-list {
|
|
86
|
+
display: flex;
|
|
87
|
+
gap: 8px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
:root { color-scheme: light; }
|
|
91
|
+
|
|
92
|
+
/* youi-states: forced-state twins */
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __youiRequire } from "node:module"; import { dirname as __youiDir } from "node:path"; import { fileURLToPath as __youiPath } from "node:url"; const require = __youiRequire(import.meta.url); const __youiDirname = __youiDir(__youiPath(import.meta.url));
|
|
3
|
+
import {
|
|
4
|
+
launchBrowser
|
|
5
|
+
} from "./chunks/chunk-4BBYLTZX.js";
|
|
6
|
+
import {
|
|
7
|
+
discoverCacheDir,
|
|
8
|
+
loadIndex
|
|
9
|
+
} from "./chunks/chunk-M5XZWCPS.js";
|
|
10
|
+
import {
|
|
11
|
+
THUMBS_PATH,
|
|
12
|
+
THUMB_SCHEMES,
|
|
13
|
+
needsCapture,
|
|
14
|
+
prunePictures,
|
|
15
|
+
readThumbIndex,
|
|
16
|
+
selectCandidates,
|
|
17
|
+
thumbsDir,
|
|
18
|
+
writeThumbIndex
|
|
19
|
+
} from "./chunks/chunk-FJZFCAL5.js";
|
|
20
|
+
import "./chunks/chunk-XAEMVEYX.js";
|
|
21
|
+
import "./chunks/chunk-FVVL5JCY.js";
|
|
22
|
+
import "./chunks/chunk-NYDJYMID.js";
|
|
23
|
+
import "./chunks/chunk-WNTS7ZO4.js";
|
|
24
|
+
|
|
25
|
+
// ../../apps/web/scripts/capture-discover-thumbs.ts
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
import { mkdir, rename, writeFile } from "node:fs/promises";
|
|
28
|
+
import { join, resolve } from "node:path";
|
|
29
|
+
import { parseArgs } from "node:util";
|
|
30
|
+
var DRAW_TIMEOUT_MS = 9e4;
|
|
31
|
+
var SETTLE_MS = 300;
|
|
32
|
+
var INSET = 8;
|
|
33
|
+
var WEBP_QUALITY = 0.86;
|
|
34
|
+
var BLANK_SHARE = 2e-3;
|
|
35
|
+
var SCALE = 2;
|
|
36
|
+
async function writeBytes(file, bytes) {
|
|
37
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
38
|
+
await writeFile(temporary, bytes);
|
|
39
|
+
await rename(temporary, file);
|
|
40
|
+
}
|
|
41
|
+
async function webp(page, png) {
|
|
42
|
+
const { url, share } = await page.evaluate(
|
|
43
|
+
async ({ data, quality }) => {
|
|
44
|
+
const image = new Image();
|
|
45
|
+
image.src = `data:image/png;base64,${data}`;
|
|
46
|
+
await image.decode();
|
|
47
|
+
const canvas = document.createElement("canvas");
|
|
48
|
+
canvas.width = image.naturalWidth;
|
|
49
|
+
canvas.height = image.naturalHeight;
|
|
50
|
+
const context = canvas.getContext("2d");
|
|
51
|
+
context.drawImage(image, 0, 0);
|
|
52
|
+
const pixels = context.getImageData(0, 0, canvas.width, canvas.height).data;
|
|
53
|
+
let away = 0;
|
|
54
|
+
for (let i = 0; i < pixels.length; i += 4) if (Math.abs(pixels[i] - pixels[0]) + Math.abs(pixels[i + 1] - pixels[1]) + Math.abs(pixels[i + 2] - pixels[2]) > 24) away++;
|
|
55
|
+
return { url: canvas.toDataURL("image/webp", quality), share: away / (pixels.length / 4) };
|
|
56
|
+
},
|
|
57
|
+
{ data: png.toString("base64"), quality: WEBP_QUALITY }
|
|
58
|
+
);
|
|
59
|
+
if (!url.startsWith("data:image/webp;base64,")) throw new Error("this Chromium cannot encode WebP");
|
|
60
|
+
return { bytes: Buffer.from(url.slice("data:image/webp;base64,".length), "base64"), blank: share < BLANK_SHARE };
|
|
61
|
+
}
|
|
62
|
+
async function photograph(page, hub, id, project) {
|
|
63
|
+
await page.goto(`${hub}/discover/specimen?id=${encodeURIComponent(id)}&project=${encodeURIComponent(project)}`);
|
|
64
|
+
const settled = page.locator(`[data-capture="${id}"][data-capture-state="ready"] [data-capture-stage] iframe[data-placed], [data-capture-state="failed"]`).first();
|
|
65
|
+
try {
|
|
66
|
+
await settled.waitFor({ timeout: DRAW_TIMEOUT_MS });
|
|
67
|
+
await page.waitForFunction(() => document.querySelector('[data-capture-state="failed"]') || document.querySelectorAll("[data-capture-stage] iframe[data-placed]").length === 2, void 0, { timeout: DRAW_TIMEOUT_MS });
|
|
68
|
+
} catch {
|
|
69
|
+
return { status: "failed", reason: `It did not draw within ${DRAW_TIMEOUT_MS / 1e3}s` };
|
|
70
|
+
}
|
|
71
|
+
await page.waitForTimeout(SETTLE_MS);
|
|
72
|
+
const failed = page.locator('[data-capture-state="failed"]');
|
|
73
|
+
if (await failed.count()) return { status: "failed", reason: (await failed.first().getAttribute("data-capture-reason") ?? "It could not be drawn").replace(/\.$/, "") };
|
|
74
|
+
const shots = {};
|
|
75
|
+
let size = { width: 0, height: 0 };
|
|
76
|
+
for (const scheme of THUMB_SCHEMES) {
|
|
77
|
+
const box = await page.locator(`[data-capture-stage="${scheme}"]`).boundingBox();
|
|
78
|
+
if (!box) return { status: "failed", reason: "Its stage was not on the page" };
|
|
79
|
+
const clip = { x: box.x + INSET, y: box.y + INSET, width: box.width - 2 * INSET, height: box.height - 2 * INSET };
|
|
80
|
+
const shot = await webp(page, await page.screenshot({ clip }));
|
|
81
|
+
if (shot.blank) return { status: "failed", reason: "It draws nothing visible on its own (it may need data, a size or a parent)" };
|
|
82
|
+
shots[scheme] = shot.bytes;
|
|
83
|
+
size = { width: Math.round(clip.width * SCALE), height: Math.round(clip.height * SCALE) };
|
|
84
|
+
}
|
|
85
|
+
return { status: "drawn", light: shots.light, dark: shots.dark, ...size };
|
|
86
|
+
}
|
|
87
|
+
async function main() {
|
|
88
|
+
const { values } = parseArgs({ options: { hub: { type: "string" }, registry: { type: "string" }, role: { type: "string" }, limit: { type: "string" }, force: { type: "boolean", default: false }, cache: { type: "string" } } });
|
|
89
|
+
const hub = (values.hub ?? "http://localhost:5173").replace(/\/+$/, "");
|
|
90
|
+
const cache = resolve(discoverCacheDir(values.cache));
|
|
91
|
+
const limit = values.limit === void 0 ? null : Number(values.limit);
|
|
92
|
+
if (limit !== null && (!Number.isSafeInteger(limit) || limit <= 0)) throw new Error("--limit takes a whole number above 0");
|
|
93
|
+
const answer = await fetch(`${hub}${THUMBS_PATH}`).then(
|
|
94
|
+
async (res) => ({ ok: res.ok, body: await res.json().catch(() => null) }),
|
|
95
|
+
() => null
|
|
96
|
+
);
|
|
97
|
+
if (!answer) {
|
|
98
|
+
process.stderr.write(`\u2716 no hub answers at ${hub}: start one on your project with \`youiyoux ui --project <dir>\` (it says its port), then run this again
|
|
99
|
+
`);
|
|
100
|
+
return 1;
|
|
101
|
+
}
|
|
102
|
+
if (!answer.ok || !answer.body?.project) {
|
|
103
|
+
process.stderr.write(`\u2716 ${answer.body?.error ?? `the hub at ${hub} cannot serve Discover previews`}
|
|
104
|
+
`);
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
const project = answer.body.project;
|
|
108
|
+
const listings = selectCandidates((await loadIndex(cache)).entries, { registry: values.registry ?? null, role: values.role ?? null, limit });
|
|
109
|
+
let index = readThumbIndex(cache, project);
|
|
110
|
+
const todo = listings.filter((e) => needsCapture(index, e.id, e.provenance.sha256, values.force));
|
|
111
|
+
process.stdout.write(`Photographing ${todo.length} of ${listings.length} candidates in ${project}'s theme (${listings.length - todo.length} already current)
|
|
112
|
+
`);
|
|
113
|
+
const dir = thumbsDir(cache, project);
|
|
114
|
+
await mkdir(dir, { recursive: true });
|
|
115
|
+
const offsite = [];
|
|
116
|
+
const browser = await launchBrowser(process.env.YOUI_CHROMIUM, { purpose: { what: "Discover previews", command: "youiyoux discover previews" } });
|
|
117
|
+
let drawn = 0;
|
|
118
|
+
let failed = 0;
|
|
119
|
+
try {
|
|
120
|
+
const context = await browser.newContext({ viewport: { width: 1200, height: 800 }, deviceScaleFactor: SCALE, reducedMotion: "reduce" });
|
|
121
|
+
const host = new URL(hub).host;
|
|
122
|
+
await context.route("**/*", (route) => {
|
|
123
|
+
const url = new URL(route.request().url());
|
|
124
|
+
if (url.host === host || url.protocol === "data:" || url.protocol === "blob:" || url.protocol === "about:") return route.continue();
|
|
125
|
+
offsite.push(url.href);
|
|
126
|
+
return route.abort();
|
|
127
|
+
});
|
|
128
|
+
const page = await context.newPage();
|
|
129
|
+
for (const entry of todo) {
|
|
130
|
+
const sha = entry.provenance.sha256;
|
|
131
|
+
const outcome = await photograph(page, hub, entry.id, project);
|
|
132
|
+
const items = { ...index.items };
|
|
133
|
+
const failures = { ...index.failed };
|
|
134
|
+
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
135
|
+
if (outcome.status === "drawn") {
|
|
136
|
+
const key = createHash("sha256").update(outcome.light).update(outcome.dark).digest("hex").slice(0, 16);
|
|
137
|
+
await writeBytes(join(dir, `${key}.light.webp`), outcome.light);
|
|
138
|
+
await writeBytes(join(dir, `${key}.dark.webp`), outcome.dark);
|
|
139
|
+
items[entry.id] = { sha, key, width: outcome.width, height: outcome.height, capturedAt: at };
|
|
140
|
+
delete failures[entry.id];
|
|
141
|
+
drawn++;
|
|
142
|
+
process.stdout.write(` \u2713 ${entry.source.ref}
|
|
143
|
+
`);
|
|
144
|
+
} else {
|
|
145
|
+
delete items[entry.id];
|
|
146
|
+
failures[entry.id] = { sha, reason: outcome.reason, at };
|
|
147
|
+
failed++;
|
|
148
|
+
process.stdout.write(` \u2013 ${entry.source.ref}: ${outcome.reason}
|
|
149
|
+
`);
|
|
150
|
+
}
|
|
151
|
+
index = { ...index, items, failed: failures };
|
|
152
|
+
await writeThumbIndex(cache, index);
|
|
153
|
+
}
|
|
154
|
+
} finally {
|
|
155
|
+
await browser.close();
|
|
156
|
+
}
|
|
157
|
+
const current = new Map((await loadIndex(cache)).entries.map((e) => [e.id, e.provenance?.sha256]));
|
|
158
|
+
index = { ...index, items: Object.fromEntries(Object.entries(index.items).filter(([id, t]) => current.get(id) === t.sha)), failed: Object.fromEntries(Object.entries(index.failed).filter(([id, f]) => current.get(id) === f.sha)) };
|
|
159
|
+
await writeThumbIndex(cache, index);
|
|
160
|
+
const pruned = await prunePictures(cache, index);
|
|
161
|
+
process.stdout.write(`${drawn} photographed, ${failed} could not be drawn on their own${pruned ? `, ${pruned} old pictures removed` : ""} \u2192 ${dir}
|
|
162
|
+
`);
|
|
163
|
+
if (offsite.length) process.stdout.write(`${offsite.length} requests to other hosts were blocked (${[...new Set(offsite.map((u) => new URL(u).host))].slice(0, 5).join(", ")})
|
|
164
|
+
`);
|
|
165
|
+
process.stdout.write(`Next: open ${hub}/discover?view=gallery
|
|
166
|
+
`);
|
|
167
|
+
return 0;
|
|
168
|
+
}
|
|
169
|
+
process.exitCode = await main().catch((error) => {
|
|
170
|
+
process.stderr.write(`\u2716 ${error instanceof Error ? error.message : String(error)}
|
|
171
|
+
`);
|
|
172
|
+
return 1;
|
|
173
|
+
});
|