anentrypoint-design 0.0.245 → 0.0.246
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/app-shell.css +10 -9
- package/dist/247420.css +15 -14
- package/dist/247420.js +17 -15
- package/dist/index.html +49 -38
- package/package.json +1 -1
- package/src/components/content.js +112 -0
- package/src/components.js +2 -2
- package/src/html-escape.js +31 -0
- package/src/index.js +8 -3
- package/src/markdown.js +7 -7
- package/src/page-html.js +17 -6
package/dist/index.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en" class="ds-247420" data-theme="auto">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
6
6
|
<title>design — 247420 design system</title>
|
|
7
7
|
<meta name="description" content="the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface." />
|
|
8
8
|
<meta name="keywords" content="design-system, tokens, 247420, anentrypoint" />
|
|
@@ -42,19 +42,27 @@
|
|
|
42
42
|
<meta name="twitter:creator" content="@AnEntrypoint" />
|
|
43
43
|
<meta name="twitter:image" content="https://anentrypoint.github.io/design/og-card.png" />
|
|
44
44
|
<meta name="twitter:image:alt" content="design" />
|
|
45
|
-
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ctext y='26' font-size='26'%3E%
|
|
46
|
-
<link rel="apple-touch-icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ctext y='26' font-size='26'%3E%
|
|
45
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ctext y='26' font-size='26'%3E%C2%B7%3C/text%3E%3C/svg%3E" />
|
|
46
|
+
<link rel="apple-touch-icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ctext y='26' font-size='26'%3E%C2%B7%3C/text%3E%3C/svg%3E" />
|
|
47
47
|
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"design","url":"https://anentrypoint.github.io/design","description":"the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface.","inLanguage":"en","publisher":{"@type":"Organization","name":"247420 / AnEntrypoint","url":"https://247420.xyz"}}</script>
|
|
48
48
|
<script type="importmap">{"imports":{"anentrypoint-design":"https://unpkg.com/anentrypoint-design@latest/dist/247420.js"}}</script>
|
|
49
49
|
<link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@latest/dist/247420.css">
|
|
50
50
|
<link rel="preconnect" href="https://unpkg.com" crossorigin>
|
|
51
51
|
<link rel="dns-prefetch" href="https://unpkg.com">
|
|
52
|
-
<style>html,body{margin:0;padding:0}body{background:var(--
|
|
52
|
+
<style>html,body{margin:0;padding:0}body{background:var(--bg,#F6F5F1);color:var(--fg,#131318);font-family:var(--ff-body,system-ui,sans-serif)}html:not(.ds-ready) body{visibility:hidden}html.ds-ready body{visibility:visible;animation:ds-fade-in .18s ease-out both}@keyframes ds-fade-in{from{opacity:0}to{opacity:1}}</style>
|
|
53
53
|
<noscript><style>html body{visibility:visible !important}</style></noscript>
|
|
54
54
|
</head>
|
|
55
55
|
<body>
|
|
56
56
|
<div id="app"></div>
|
|
57
|
-
<script type="application/json" id="__site__">{"site":{"title":"design","tagline":"247420 design system","description":"the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface.","repo":"https://github.com/AnEntrypoint/design","url":"https://anentrypoint.github.io/design","year":2026,"keywords":["design-system","tokens","247420","anentrypoint"],"accent_from":"#56d364","accent_to":"#79c0ff","glyph":"◰","code":"072","category":"web"},"nav":{"links":[{"label":247420,"href":"https://247420.xyz"},{"label":"GitHub","href":"https://github.com/AnEntrypoint"}]},"home":{"id":"home","title":"Home","hero":{"heading":"design","subheading":"247420 design system","body":"the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface.","badges":[{"label":"design-system"},{"label":"tokens"},{"label":"web"}],"ctas":[{"label":"GitHub","href":"https://github.com/AnEntrypoint/design","primary":true},{"label":"247420","href":"https://247420.xyz"}]},"sidebar":{"fab":{"label":"open","glyph":"✦","href":"./ui_kits/homepage/"},"bins":[{"glyph":"▣","label":"everything","href":"#all","count":23,"active":true},{"glyph":"★","label":"starred","href":"#starred","count":5},{"glyph":"◐","label":"shipped","href":"#shipped","count":12},{"glyph":"◌","label":"drafts","href":"#drafts","count":6}],"labels_group":"labels","labels":[{"glyph":"●","label":"ui kits","href":"#kits","count":4,"color":"var(--panel-accent)"},{"glyph":"●","label":"decks","href":"#decks","count":1,"color":"var(--mascot,#e0a200)"},{"glyph":"●","label":"previews","href":"#previews","count":20,"color":"var(--purple,#8856b3)"},{"glyph":"●","label":"docs","href":"#docs","count":3,"color":"var(--panel-text-3)"}],"more_group":"more","more":[{"glyph":"§","label":"readme","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"glyph":"§","label":"skill","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"glyph":"⌘","label":"tokens","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"glyph":"↗","label":"source","href":"https://github.com/AnEntrypoint/design"}]},"tabs":[{"glyph":"▣","label":"everything","href":"#all","active":true},{"glyph":"◎","label":"kits","href":"#kits"},{"glyph":"▰","label":"decks","href":"#decks"},{"glyph":"§","label":"previews","href":"#previews"}],"kits":{"heading":"ui kits","count":"14 surfaces","items":[{"code":"01","title":"homepage","sub":"marquee + works grid","desc":"editorial banner over a quiet shell","href":"./ui_kits/homepage/"},{"code":"02","title":"project page","sub":"hero · receipt · install · changelog","desc":"shippable case-study template","href":"./ui_kits/project_page/"},{"code":"03","title":"docs","sub":"long-form prose chrome","desc":"sidebar nav, mono headings, code blocks","href":"./ui_kits/docs/"},{"code":"04","title":"blog","sub":"dated index + reading view","desc":"typographic, no clutter","href":"./ui_kits/blog/"},{"code":"05","title":"chat","sub":"message thread + composer","desc":"pill bubbles, monospace timestamps, room sidebar","href":"./ui_kits/chat/"},{"code":"06","title":"aicat","sub":"ai assistant with cat persona","desc":"ascii portrait, thinking dots, mood-swapping face","href":"./ui_kits/aicat/"},{"code":"07","title":"file browser","sub":"rails by file type · drop · preview","desc":"static demo wired to fsbrowse — every file-row primitive in one surface","href":"./ui_kits/file_browser/"},{"code":"08","title":"dashboard","sub":"kpis · tables · receipts · changelog","desc":"every content primitive in one operations surface","href":"./ui_kits/dashboard/"},{"code":"09","title":"terminal","sub":"cli prompt · command lines · log view","desc":"five line kinds — cmt cmd out ok warn — over a tonal panel","href":"./ui_kits/terminal/"},{"code":"10","title":"settings","sub":"sectioned forms · toggles · save bar","desc":"every input primitive — fields, segmented buttons, danger panel","href":"./ui_kits/settings/"},{"code":"11","title":"signin","sub":"auth · providers · magic link","desc":"narrow shell + tone-on-tone form, no shadows, no spinners","href":"./ui_kits/signin/"},{"code":"12","title":"search","sub":"topbar query · faceted filters · rows","desc":"ranked results reuse the same RowLink primitive every list does","href":"./ui_kits/search/"},{"code":"13","title":"404","sub":"empty-state hero · suggested routes","desc":"narrow shell, oversized mono code, three CTAs","href":"./ui_kits/error_404/"},{"code":"14","title":"gallery","sub":"visual grid · tonal cards · lightbox","desc":"tiles share the panel tokens; lightbox reuses the same surface","href":"./ui_kits/gallery/"}]},"decks":{"heading":"decks","items":[{"code":"01","title":"deck template","sub":"16:9 stage with auto-fit","desc":"title, lede, code, comparison, manifesto","href":"./slides/"}]},"docs":{"heading":"docs","items":[{"code":"md","title":"readme","sub":"overview, manifesto, conventions","desc":"start here","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"code":"md","title":"skill","sub":"authoring rules for the agent","desc":"editorial · zine · surface modes","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"code":"css","title":"tokens","sub":"colors, type, panel surface tokens","desc":"canonical source of truth","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"}]},"previews":{"heading":"previews","base":"./preview/","items":["buttons","colors-core","colors-lore","colors-semantic","dateline","dropzone","file-grid","file-row","file-toolbar","file-viewer","header","icons-unicode","index-row","inputs","manifesto","rules","spacing","stamps","stamps-lore","theme-ink","type-display","type-mono","type-prose","type-scale","wordmarks"]},"file_browser":{"heading":"file browser","count":"primitives","items":[{"code":"fb","title":"file_browser kit","sub":"drop, list, preview, dialogs","desc":"the full surface, working with mock data","href":"./ui_kits/file_browser/","cta":"open kit ↗"},{"code":"fb","title":"FileRow","sub":"rail · icon · name · meta","desc":"data-file-type drives the rail color — never apply rail-* manually","href":"./preview/file-row.html","cta":"preview ↗"},{"code":"fb","title":"FileGrid","sub":"stack of rows in a panel","desc":"directories sort first; selected row gets the mint .active tone","href":"./preview/file-grid.html","cta":"preview ↗"},{"code":"fb","title":"DropZone","sub":"tonal upload target","desc":"swap to --panel-select on dragover; preventDefault on document, not just zone","href":"./preview/dropzone.html","cta":"preview ↗"},{"code":"fb","title":"FileViewer","sub":"modal preview · keyed head","desc":"head + body both carry data-file-type so rails propagate inside the modal","href":"./preview/file-viewer.html","cta":"preview ↗"},{"code":"fb","title":"FileToolbar","sub":"actions · breadcrumb · upload","desc":"left-aligned actions, right-aligned count; UploadProgress sits underneath","href":"./preview/file-toolbar.html","cta":"preview ↗"},{"code":"fb","title":"fsbrowse","sub":"Express + busboy backend","desc":"canonical real-world wiring — same SDK, real filesystem operations","href":"https://github.com/AnEntrypoint/fsbrowse","cta":"source ↗"}]},"quickstart":{"heading":"quick start","lines":[{"kind":"cmt","text":"# install via importmap (no bundler)"},{"kind":"cmd","text":"\u003cscript type='importmap'\u003e{\"imports\":{\"anentrypoint-design\":\"https://unpkg.com/anentrypoint-design@latest/dist/247420.js\"}}\u003c/script\u003e"},{"kind":"cmt","text":"# or clone the source"},{"kind":"cmd","text":"git clone https://github.com/AnEntrypoint/design.git"}]},"desktop_os":{"heading":"desktop os shell","count":"in-page wm","items":[{"code":"os","title":"createDesktopShell","sub":"menubar · apps launcher · taskbar · window manager","desc":"in-page desktop OS chrome — mount any app registry into a draggable wm","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/shell.js","cta":"shell.js ↗"},{"code":"os","title":"icons set","sub":"svg glyphs for menubar + taskbar","desc":"home, apps, search, settings — used by the shell and exposed for apps","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/icons.js","cta":"icons.js ↗"},{"code":"os","title":"theme.css","sub":"os chrome tokens · menubar · launcher · wm","desc":"scoped css module loaded by the shell — keeps desktop visuals isolated","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/theme.css","cta":"theme.css ↗"},{"code":"os","title":"import path","sub":"anentrypoint-design/desktop","desc":"subpath export; no bundler needed — pulls icons + createDesktopShell","href":"https://github.com/AnEntrypoint/design/blob/main/package.json","cta":"exports ↗"}]},"web_components":{"heading":"web components","count":"1 element","items":[{"code":"wc","title":"\u003cds-chat\u003e","sub":"auto-registers when the sdk loads in a browser","desc":"set el.messages = [...] or pass json via attribute; listen for 'send' event","href":"https://github.com/AnEntrypoint/design/blob/main/src/web-components/ds-chat.js","cta":"ds-chat.js ↗"},{"code":"wc","title":"registerChatElement","sub":"manual register helper","desc":"exported from the sdk root for ssr / late-mount when customElements is gated","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js","cta":"source ↗"}]},"api_exports":{"heading":"public api","count":"sdk surface","items":[{"code":"api","title":"h / applyDiff","sub":"webjsx createElement + diff","desc":"build vnodes with h(), render with applyDiff(root, [vnode]) — no jsx pragma needed","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js","cta":"index.js ↗"},{"code":"api","title":"installStyles / scope","sub":"ds-247420 css scope + bootstrap","desc":"installStyles() injects the prefixed css; scope = '.ds-247420' for selector composition","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js","cta":"styles.js ↗"},{"code":"api","title":"loadCss","sub":"fetch the bundled css string","desc":"useful for shadow roots or custom style injection paths","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js","cta":"styles.js ↗"},{"code":"api","title":"mount / mountKit","sub":"ds shell + ui_kit bootstrap","desc":"mount(root, viewFn) wires applyDiff + motion; mountKit({root,view,screen}) wires a kit","href":"https://github.com/AnEntrypoint/design/blob/main/src/bootstrap.js","cta":"bootstrap.js ↗"},{"code":"api","title":"registerDeckStage / getDeckStage","sub":"16:9 deck stage api","desc":"register custom deck stages and fetch the active stage for slide transitions","href":"https://github.com/AnEntrypoint/design/blob/main/src/deck-stage.js","cta":"deck-stage.js ↗"},{"code":"api","title":"renderMarkdown","sub":"marked v15 + dompurify lazy stack","desc":"lazy-loads marked + dompurify from jsdelivr; only xss gate for chat html","href":"https://github.com/AnEntrypoint/design/blob/main/src/markdown.js","cta":"markdown.js ↗"},{"code":"api","title":"ensurePrism / highlightAllUnder","sub":"prism core + per-language","desc":"injects prism on first use; CodeNode ref-callback highlights inside any subtree","href":"https://github.com/AnEntrypoint/design/blob/main/src/highlight.js","cta":"highlight.js ↗"},{"code":"api","title":"renderPageHtml","sub":"static page html template","desc":"shared head/body wrapper for kit pages — meta, importmap, ds-247420 scope","href":"https://github.com/AnEntrypoint/design/blob/main/src/page-html.js","cta":"page-html.js ↗"},{"code":"api","title":"components / motion / debug","sub":"namespaces from the default export","desc":"components.* are the C.* primitives; motion.animateTree, debug.window.__debug registry","href":"https://github.com/AnEntrypoint/design/blob/main/src/components.js","cta":"components.js ↗"}]},"features":{"heading":"why design","items":[{"name":"layered surfaces","desc":"panel-on-panel rhythm; loud content sits inside quiet chrome."},{"name":"monospace labels","desc":"mono only for codes/labels/CLI; sans for everything legible."},{"name":"indicator rails","desc":"color-coded inset rails for category separation, never borders."},{"name":"tokens-only","desc":"every surface, type ramp, accent driven by --panel-* / --fs-* tokens."}]},"examples":{"heading":"live examples","items":[{"name":"index shell","desc":"full navigation shell with tabs, filters, and row interactions.","href":"./index.html","cta":"open index"},{"name":"homepage kit","desc":"hero + works layout and updated readable type scale.","href":"./ui_kits/homepage/","cta":"open kit"},{"name":"project page kit","desc":"overview, install, receipt, and changelog template.","href":"./ui_kits/project_page/","cta":"open kit"},{"name":"docs kit","desc":"technical documentation layout with sidebar and prose.","href":"./ui_kits/docs/","cta":"open docs"},{"name":"blog kit","desc":"long-form writing layout tuned for readability.","href":"./ui_kits/blog/","cta":"open writing"},{"name":"chat kit","desc":"message thread + composer with pill bubbles and room sidebar.","href":"./ui_kits/chat/","cta":"open chat"},{"name":"aicat kit","desc":"ai assistant with cat persona — ascii portrait + mood face.","href":"./ui_kits/aicat/","cta":"open aicat"},{"name":"slide deck","desc":"16:9 deck stage with improved presenter controls text.","href":"./slides/","cta":"open slides"},{"name":"dashboard kit","desc":"kpis, tables, receipts, changelog — operations surface.","href":"./ui_kits/dashboard/","cta":"open dashboard"},{"name":"terminal kit","desc":"cli prompt, command lines, log viewer.","href":"./ui_kits/terminal/","cta":"open terminal"},{"name":"settings kit","desc":"sectioned forms, toggles, segmented buttons, save bar.","href":"./ui_kits/settings/","cta":"open settings"},{"name":"signin kit","desc":"auth panel, providers, magic link.","href":"./ui_kits/signin/","cta":"open signin"},{"name":"search kit","desc":"query bar, faceted filters, ranked results.","href":"./ui_kits/search/","cta":"open search"},{"name":"404 kit","desc":"empty-state hero with suggested routes.","href":"./ui_kits/error_404/","cta":"open 404"},{"name":"gallery kit","desc":"visual grid + lightbox over tonal cards.","href":"./ui_kits/gallery/","cta":"open gallery"},{"name":"preview samples","desc":"design previews and component samples.","href":"./preview/buttons.html","cta":"open previews"}]},"status_left":["main","• utf-8","• lf"],"status_right":["247420 / mmxxvi","• probably emerging"]}}</script>
|
|
57
|
+
<noscript>
|
|
58
|
+
<main class="ds-prose">
|
|
59
|
+
<h1>design — 247420 design system</h1>
|
|
60
|
+
<p>the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface.</p>
|
|
61
|
+
<nav><a href="https://247420.xyz">247420</a>
|
|
62
|
+
<a href="https://github.com/AnEntrypoint">GitHub</a></nav>
|
|
63
|
+
</main>
|
|
64
|
+
</noscript>
|
|
65
|
+
<script type="application/json" id="__site__">{"site":{"title":"design","tagline":"247420 design system","description":"the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface.","repo":"https://github.com/AnEntrypoint/design","url":"https://anentrypoint.github.io/design","year":2026,"keywords":["design-system","tokens","247420","anentrypoint"],"accent_from":"#247420","accent_to":"#3A9A34","glyph":"·","code":"072","category":"web"},"nav":{"links":[{"label":247420,"href":"https://247420.xyz"},{"label":"GitHub","href":"https://github.com/AnEntrypoint"}]},"home":{"id":"home","title":"Home","hero":{"heading":"design","subheading":"the 247420 design system","body":"acid editorial. oversized display type, one electric green, print texture over glow. every 247420 surface runs on it.","badges":[{"label":"design-system"},{"label":"tokens"},{"label":"web"}],"ctas":[{"label":"GitHub","href":"https://github.com/AnEntrypoint/design","primary":true},{"label":"247420","href":"https://247420.xyz"}]},"sidebar":{"fab":{"label":"open","glyph":"+","href":"./ui_kits/homepage/"},"bins":[{"label":"everything","href":"#all","count":23,"active":true},{"label":"pinned","href":"#kits","count":5},{"label":"shipped","href":"#previews","count":12},{"label":"drafts","href":"#decks","count":6}],"labels_group":"labels","labels":[{"label":"ui kits","href":"#kits","count":4,"color":"var(--panel-accent)"},{"label":"decks","href":"#decks","count":1,"color":"var(--mascot,#E84B8A)"},{"label":"previews","href":"#previews","count":20,"color":"var(--purple,#420247)"},{"label":"docs","href":"#docs","count":3,"color":"var(--panel-text-3)"}],"more_group":"more","more":[{"label":"readme","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"label":"skill","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"label":"tokens","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"label":"source","href":"https://github.com/AnEntrypoint/design"}]},"tabs":[{"label":"everything","href":"#all","active":true},{"label":"kits","href":"#kits"},{"label":"decks","href":"#decks"},{"label":"previews","href":"#previews"}],"kits":{"heading":"ui kits","count":"14 surfaces","items":[{"code":"01","title":"homepage","sub":"marquee + works grid","desc":"editorial banner over a quiet shell","href":"./ui_kits/homepage/"},{"code":"02","title":"project page","sub":"hero receipt install changelog","desc":"shippable case-study template","href":"./ui_kits/project_page/"},{"code":"03","title":"docs","sub":"long-form prose chrome","desc":"sidebar nav, mono headings, code blocks","href":"./ui_kits/docs/"},{"code":"04","title":"blog","sub":"dated index + reading view","desc":"typographic, no clutter","href":"./ui_kits/blog/"},{"code":"05","title":"chat","sub":"message thread + composer","desc":"pill bubbles, monospace timestamps, room sidebar","href":"./ui_kits/chat/"},{"code":"06","title":"aicat","sub":"ai assistant with cat persona","desc":"ascii portrait, thinking dots, mood-swapping face","href":"./ui_kits/aicat/"},{"code":"07","title":"file browser","sub":"rails by file type drop preview","desc":"static demo wired to fsbrowse — every file-row primitive in one surface","href":"./ui_kits/file_browser/"},{"code":"08","title":"dashboard","sub":"kpis tables receipts changelog","desc":"every content primitive in one operations surface","href":"./ui_kits/dashboard/"},{"code":"09","title":"terminal","sub":"cli prompt command lines log view","desc":"five line kinds (cmt cmd out ok warn) over a tonal panel","href":"./ui_kits/terminal/"},{"code":"10","title":"settings","sub":"sectioned forms toggles save bar","desc":"every input primitive — fields, segmented buttons, danger panel","href":"./ui_kits/settings/"},{"code":"11","title":"signin","sub":"auth providers magic link","desc":"narrow shell + tone-on-tone form, no shadows, no spinners","href":"./ui_kits/signin/"},{"code":"12","title":"search","sub":"topbar query faceted filters rows","desc":"ranked results reuse the same RowLink primitive every list does","href":"./ui_kits/search/"},{"code":"13","title":"404","sub":"empty-state hero suggested routes","desc":"narrow shell, oversized mono code, three CTAs","href":"./ui_kits/error_404/"},{"code":"14","title":"gallery","sub":"visual grid tonal cards lightbox","desc":"tiles share the panel tokens; lightbox reuses the same surface","href":"./ui_kits/gallery/"}]},"decks":{"heading":"decks","items":[{"code":"01","title":"deck template","sub":"16:9 stage with auto-fit","desc":"title, lede, code, comparison, manifesto","href":"./slides/"}]},"docs":{"heading":"docs","items":[{"code":"md","title":"readme","sub":"overview, manifesto, conventions","desc":"start here","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"code":"md","title":"skill","sub":"authoring rules for the agent","desc":"editorial zine surface modes","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"code":"css","title":"tokens","sub":"colors, type, panel surface tokens","desc":"canonical source of truth","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"}]},"previews":{"heading":"previews","base":"./preview/","items":["buttons","colors-core","colors-lore","colors-semantic","dateline","dropzone","file-grid","file-row","file-toolbar","file-viewer","header","icons-unicode","index-row","inputs","manifesto","rules","spacing","stamps","stamps-lore","theme-ink","type-display","type-mono","type-prose","type-scale","wordmarks"]},"file_browser":{"heading":"file browser","count":"primitives","items":[{"code":"fb","title":"file_browser kit","sub":"drop, list, preview, dialogs","desc":"the full surface, working with mock data","href":"./ui_kits/file_browser/","cta":"open kit"},{"code":"fb","title":"FileRow","sub":"rail icon name meta","desc":"data-file-type drives the rail color — never apply rail-* manually","href":"./preview/file-row.html","cta":"preview"},{"code":"fb","title":"FileGrid","sub":"stack of rows in a panel","desc":"directories sort first; selected row gets the mint .active tone","href":"./preview/file-grid.html","cta":"preview"},{"code":"fb","title":"DropZone","sub":"tonal upload target","desc":"swap to --panel-select on dragover; preventDefault on document, not just zone","href":"./preview/dropzone.html","cta":"preview"},{"code":"fb","title":"FileViewer","sub":"modal preview keyed head","desc":"head + body both carry data-file-type so rails propagate inside the modal","href":"./preview/file-viewer.html","cta":"preview"},{"code":"fb","title":"FileToolbar","sub":"actions breadcrumb upload","desc":"left-aligned actions, right-aligned count; UploadProgress sits underneath","href":"./preview/file-toolbar.html","cta":"preview"},{"code":"fb","title":"fsbrowse","sub":"Express + busboy backend","desc":"canonical real-world wiring — same SDK, real filesystem operations","href":"https://github.com/AnEntrypoint/fsbrowse","cta":"source"}]},"quickstart":{"heading":"quick start","lines":[{"kind":"cmt","text":"# install via importmap (no bundler)"},{"kind":"cmd","text":"\u003cscript type='importmap'\u003e{\"imports\":{\"anentrypoint-design\":\"https://unpkg.com/anentrypoint-design@latest/dist/247420.js\"}}\u003c/script\u003e"},{"kind":"cmt","text":"# or clone the source"},{"kind":"cmd","text":"git clone https://github.com/AnEntrypoint/design.git"}]},"desktop_os":{"heading":"desktop os shell","count":"in-page wm","items":[{"code":"os","title":"createDesktopShell","sub":"menubar apps launcher taskbar window manager","desc":"in-page desktop OS chrome — mount any app registry into a draggable wm","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/shell.js","cta":"shell.js"},{"code":"os","title":"icons set","sub":"svg glyphs for menubar + taskbar","desc":"home, apps, search, settings — used by the shell and exposed for apps","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/icons.js","cta":"icons.js"},{"code":"os","title":"theme.css","sub":"os chrome tokens menubar launcher wm","desc":"scoped css module loaded by the shell — keeps desktop visuals isolated","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/theme.css","cta":"theme.css"},{"code":"os","title":"import path","sub":"anentrypoint-design/desktop","desc":"subpath export; no bundler needed — pulls icons + createDesktopShell","href":"https://github.com/AnEntrypoint/design/blob/main/package.json","cta":"exports"}]},"web_components":{"heading":"web components","count":"1 element","items":[{"code":"wc","title":"\u003cds-chat\u003e","sub":"auto-registers when the sdk loads in a browser","desc":"set el.messages = [...] or pass json via attribute; listen for 'send' event","href":"https://github.com/AnEntrypoint/design/blob/main/src/web-components/ds-chat.js","cta":"ds-chat.js"},{"code":"wc","title":"registerChatElement","sub":"manual register helper","desc":"exported from the sdk root for ssr / late-mount when customElements is gated","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js","cta":"source"}]},"api_exports":{"heading":"public api","count":"sdk surface","items":[{"code":"api","title":"h / applyDiff","sub":"webjsx createElement + diff","desc":"build vnodes with h(), render with applyDiff(root, [vnode]) — no jsx pragma needed","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js","cta":"index.js"},{"code":"api","title":"installStyles / scope","sub":"ds-247420 css scope + bootstrap","desc":"installStyles() injects the prefixed css; scope = '.ds-247420' for selector composition","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js","cta":"styles.js"},{"code":"api","title":"loadCss","sub":"fetch the bundled css string","desc":"useful for shadow roots or custom style injection paths","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js","cta":"styles.js"},{"code":"api","title":"mount / mountKit","sub":"ds shell + ui_kit bootstrap","desc":"mount(root, viewFn) wires applyDiff + motion; mountKit({root,view,screen}) wires a kit","href":"https://github.com/AnEntrypoint/design/blob/main/src/bootstrap.js","cta":"bootstrap.js"},{"code":"api","title":"registerDeckStage / getDeckStage","sub":"16:9 deck stage api","desc":"register custom deck stages and fetch the active stage for slide transitions","href":"https://github.com/AnEntrypoint/design/blob/main/src/deck-stage.js","cta":"deck-stage.js"},{"code":"api","title":"renderMarkdown","sub":"marked v15 + dompurify lazy stack","desc":"lazy-loads marked + dompurify from jsdelivr; only xss gate for chat html","href":"https://github.com/AnEntrypoint/design/blob/main/src/markdown.js","cta":"markdown.js"},{"code":"api","title":"ensurePrism / highlightAllUnder","sub":"prism core + per-language","desc":"injects prism on first use; CodeNode ref-callback highlights inside any subtree","href":"https://github.com/AnEntrypoint/design/blob/main/src/highlight.js","cta":"highlight.js"},{"code":"api","title":"renderPageHtml","sub":"static page html template","desc":"shared head/body wrapper for kit pages — meta, importmap, ds-247420 scope","href":"https://github.com/AnEntrypoint/design/blob/main/src/page-html.js","cta":"page-html.js"},{"code":"api","title":"components / motion / debug","sub":"namespaces from the default export","desc":"components.* are the C.* primitives; motion.animateTree, debug.window.__debug registry","href":"https://github.com/AnEntrypoint/design/blob/main/src/components.js","cta":"components.js"}]},"features":{"heading":"why design","items":[{"name":"layered surfaces","desc":"panel-on-panel rhythm; loud content sits inside quiet chrome."},{"name":"monospace labels","desc":"mono only for codes/labels/CLI; sans for everything legible."},{"name":"indicator rails","desc":"color-coded inset rails for category separation, never borders."},{"name":"tokens-only","desc":"every surface, type ramp, accent driven by --panel-* / --fs-* tokens."}]},"examples":{"heading":"live examples","items":[{"name":"index shell","desc":"full navigation shell with tabs, filters, and row interactions.","href":"./index.html","cta":"open index"},{"name":"homepage kit","desc":"hero + works layout and updated readable type scale.","href":"./ui_kits/homepage/","cta":"open kit"},{"name":"project page kit","desc":"overview, install, receipt, and changelog template.","href":"./ui_kits/project_page/","cta":"open kit"},{"name":"docs kit","desc":"technical documentation layout with sidebar and prose.","href":"./ui_kits/docs/","cta":"open docs"},{"name":"blog kit","desc":"long-form writing layout tuned for readability.","href":"./ui_kits/blog/","cta":"open writing"},{"name":"chat kit","desc":"message thread + composer with pill bubbles and room sidebar.","href":"./ui_kits/chat/","cta":"open chat"},{"name":"aicat kit","desc":"ai assistant with cat persona — ascii portrait + mood face.","href":"./ui_kits/aicat/","cta":"open aicat"},{"name":"slide deck","desc":"16:9 deck stage with improved presenter controls text.","href":"./slides/","cta":"open slides"},{"name":"dashboard kit","desc":"kpis, tables, receipts, changelog — operations surface.","href":"./ui_kits/dashboard/","cta":"open dashboard"},{"name":"terminal kit","desc":"cli prompt, command lines, log viewer.","href":"./ui_kits/terminal/","cta":"open terminal"},{"name":"settings kit","desc":"sectioned forms, toggles, segmented buttons, save bar.","href":"./ui_kits/settings/","cta":"open settings"},{"name":"signin kit","desc":"auth panel, providers, magic link.","href":"./ui_kits/signin/","cta":"open signin"},{"name":"search kit","desc":"query bar, faceted filters, ranked results.","href":"./ui_kits/search/","cta":"open search"},{"name":"404 kit","desc":"empty-state hero with suggested routes.","href":"./ui_kits/error_404/","cta":"open 404"},{"name":"gallery kit","desc":"visual grid + lightbox over tonal cards.","href":"./ui_kits/gallery/","cta":"open gallery"},{"name":"preview samples","desc":"design previews and component samples.","href":"./preview/buttons.html","cta":"open previews"}]},"status_left":["main","utf-8","lf"],"status_right":["247420 · mmxxvi","probably emerging"]}}</script>
|
|
58
66
|
<script type="module">
|
|
59
67
|
import { h, applyDiff, installStyles, components as C, initTheme } from 'anentrypoint-design';
|
|
60
68
|
installStyles();
|
|
@@ -73,20 +81,18 @@ const { site, nav, home } = data;
|
|
|
73
81
|
function Hero() {
|
|
74
82
|
if (!home || !home.hero) return null;
|
|
75
83
|
const hero = home.hero;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
)
|
|
89
|
-
});
|
|
84
|
+
const actions = (hero.ctas && hero.ctas.length)
|
|
85
|
+
? hero.ctas.map((c, i) => C.Btn({ key: 'c' + i, href: c.href, primary: c.primary, children: c.label }))
|
|
86
|
+
: null;
|
|
87
|
+
// Editorial Hero — oversized display, asymmetric grid, print grain.
|
|
88
|
+
return h('div', { class: 'ds-grain ds-home-hero-wrap' },
|
|
89
|
+
C.Hero({
|
|
90
|
+
eyebrow: hero.subheading || site.tagline || null,
|
|
91
|
+
title: hero.heading || site.title,
|
|
92
|
+
body: hero.body || '',
|
|
93
|
+
actions
|
|
94
|
+
})
|
|
95
|
+
);
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
function rowsFromItems(items, prefix) {
|
|
@@ -95,7 +101,7 @@ function rowsFromItems(items, prefix) {
|
|
|
95
101
|
code: it.code || String(i + 1).padStart(2, '0'),
|
|
96
102
|
title: it.title || it.name,
|
|
97
103
|
sub: it.sub || it.desc || '',
|
|
98
|
-
meta: it.cta || it.meta || 'open
|
|
104
|
+
meta: it.cta || it.meta || 'open ->',
|
|
99
105
|
href: it.href || '#'
|
|
100
106
|
}));
|
|
101
107
|
}
|
|
@@ -103,9 +109,10 @@ function rowsFromItems(items, prefix) {
|
|
|
103
109
|
function Kits() {
|
|
104
110
|
if (!home.kits || !home.kits.items || !home.kits.items.length) return null;
|
|
105
111
|
return C.Panel({
|
|
112
|
+
id: 'kits',
|
|
106
113
|
title: home.kits.heading || 'ui kits',
|
|
107
114
|
count: home.kits.count || home.kits.items.length,
|
|
108
|
-
|
|
115
|
+
class: 'ds-home-panel',
|
|
109
116
|
children: rowsFromItems(home.kits.items, 'k')
|
|
110
117
|
});
|
|
111
118
|
}
|
|
@@ -113,8 +120,9 @@ function Kits() {
|
|
|
113
120
|
function Decks() {
|
|
114
121
|
if (!home.decks || !home.decks.items || !home.decks.items.length) return null;
|
|
115
122
|
return C.Panel({
|
|
123
|
+
id: 'decks',
|
|
116
124
|
title: home.decks.heading || 'decks',
|
|
117
|
-
|
|
125
|
+
class: 'ds-home-panel',
|
|
118
126
|
children: rowsFromItems(home.decks.items, 'd')
|
|
119
127
|
});
|
|
120
128
|
}
|
|
@@ -124,7 +132,7 @@ function FileBrowser() {
|
|
|
124
132
|
return C.Panel({
|
|
125
133
|
title: home.file_browser.heading || 'file browser',
|
|
126
134
|
count: home.file_browser.count || home.file_browser.items.length,
|
|
127
|
-
|
|
135
|
+
class: 'ds-home-panel',
|
|
128
136
|
children: rowsFromItems(home.file_browser.items, 'fb')
|
|
129
137
|
});
|
|
130
138
|
}
|
|
@@ -132,8 +140,9 @@ function FileBrowser() {
|
|
|
132
140
|
function Docs() {
|
|
133
141
|
if (!home.docs || !home.docs.items || !home.docs.items.length) return null;
|
|
134
142
|
return C.Panel({
|
|
143
|
+
id: 'docs',
|
|
135
144
|
title: home.docs.heading || 'docs',
|
|
136
|
-
|
|
145
|
+
class: 'ds-home-panel',
|
|
137
146
|
children: rowsFromItems(home.docs.items, 'doc')
|
|
138
147
|
});
|
|
139
148
|
}
|
|
@@ -146,13 +155,14 @@ function Previews() {
|
|
|
146
155
|
code: String(i + 1).padStart(2, '0'),
|
|
147
156
|
title: String(name).replace(/-/g, ' '),
|
|
148
157
|
sub: 'preview · ' + name + '.html',
|
|
149
|
-
meta: 'open
|
|
158
|
+
meta: 'open ->',
|
|
150
159
|
href: base + name + '.html'
|
|
151
160
|
}));
|
|
152
161
|
return C.Panel({
|
|
162
|
+
id: 'previews',
|
|
153
163
|
title: home.previews.heading || 'previews',
|
|
154
164
|
count: rows.length,
|
|
155
|
-
|
|
165
|
+
class: 'ds-home-panel',
|
|
156
166
|
children: rows
|
|
157
167
|
});
|
|
158
168
|
}
|
|
@@ -169,7 +179,7 @@ function Features() {
|
|
|
169
179
|
}));
|
|
170
180
|
return C.Panel({
|
|
171
181
|
title: home.features.heading || 'why design',
|
|
172
|
-
|
|
182
|
+
class: 'ds-home-panel',
|
|
173
183
|
children: rows
|
|
174
184
|
});
|
|
175
185
|
}
|
|
@@ -182,8 +192,8 @@ function Quickstart() {
|
|
|
182
192
|
));
|
|
183
193
|
return C.Panel({
|
|
184
194
|
title: home.quickstart.heading || 'quick start',
|
|
185
|
-
|
|
186
|
-
children: h('div', {
|
|
195
|
+
class: 'ds-home-panel',
|
|
196
|
+
children: h('div', { class: 'ds-quickstart' }, ...lineNodes)
|
|
187
197
|
});
|
|
188
198
|
}
|
|
189
199
|
|
|
@@ -192,7 +202,7 @@ function DesktopOS() {
|
|
|
192
202
|
return C.Panel({
|
|
193
203
|
title: home.desktop_os.heading || 'desktop os shell',
|
|
194
204
|
count: home.desktop_os.count || home.desktop_os.items.length,
|
|
195
|
-
|
|
205
|
+
class: 'ds-home-panel',
|
|
196
206
|
children: rowsFromItems(home.desktop_os.items, 'os')
|
|
197
207
|
});
|
|
198
208
|
}
|
|
@@ -202,7 +212,7 @@ function WebComponents() {
|
|
|
202
212
|
return C.Panel({
|
|
203
213
|
title: home.web_components.heading || 'web components',
|
|
204
214
|
count: home.web_components.count || home.web_components.items.length,
|
|
205
|
-
|
|
215
|
+
class: 'ds-home-panel',
|
|
206
216
|
children: rowsFromItems(home.web_components.items, 'wc')
|
|
207
217
|
});
|
|
208
218
|
}
|
|
@@ -212,7 +222,7 @@ function ApiExports() {
|
|
|
212
222
|
return C.Panel({
|
|
213
223
|
title: home.api_exports.heading || 'public api',
|
|
214
224
|
count: home.api_exports.count || home.api_exports.items.length,
|
|
215
|
-
|
|
225
|
+
class: 'ds-home-panel',
|
|
216
226
|
children: rowsFromItems(home.api_exports.items, 'api')
|
|
217
227
|
});
|
|
218
228
|
}
|
|
@@ -222,7 +232,7 @@ function Examples() {
|
|
|
222
232
|
return C.Panel({
|
|
223
233
|
title: home.examples.heading || 'live examples',
|
|
224
234
|
count: home.examples.items.length,
|
|
225
|
-
|
|
235
|
+
class: 'ds-home-panel',
|
|
226
236
|
children: rowsFromItems(home.examples.items, 'e')
|
|
227
237
|
});
|
|
228
238
|
}
|
|
@@ -233,7 +243,7 @@ function buildSide() {
|
|
|
233
243
|
if (sb.fab) {
|
|
234
244
|
sections.push({
|
|
235
245
|
group: 'open',
|
|
236
|
-
items: [{ glyph: sb.fab.glyph || '
|
|
246
|
+
items: [{ glyph: sb.fab.glyph || '+', label: sb.fab.label || 'open', href: sb.fab.href || '#' }]
|
|
237
247
|
});
|
|
238
248
|
}
|
|
239
249
|
if (sb.bins && sb.bins.length) {
|
|
@@ -250,7 +260,7 @@ function buildSide() {
|
|
|
250
260
|
|
|
251
261
|
function Tabs() {
|
|
252
262
|
if (!home.tabs || !home.tabs.length) return null;
|
|
253
|
-
return h('div', { class: 'tabs', role: 'tablist'
|
|
263
|
+
return h('div', { class: 'tabs ds-home-panel', role: 'tablist' },
|
|
254
264
|
...home.tabs.map((t, i) => h('a', {
|
|
255
265
|
key: 't' + i,
|
|
256
266
|
href: t.href || '#',
|
|
@@ -265,8 +275,8 @@ function Tabs() {
|
|
|
265
275
|
|
|
266
276
|
const navItems = (nav && nav.links ? nav.links : []).map(l => [String(l.label || ''), l.href]);
|
|
267
277
|
|
|
268
|
-
const statusLeft = home.status_left || ['main', '
|
|
269
|
-
const statusRight = home.status_right || ['247420
|
|
278
|
+
const statusLeft = home.status_left || ['main', '- utf-8', '- lf'];
|
|
279
|
+
const statusRight = home.status_right || ['247420 · mmxxvi', '- probably emerging'];
|
|
270
280
|
|
|
271
281
|
const App = C.AppShell({
|
|
272
282
|
topbar: C.Topbar({
|
|
@@ -276,8 +286,9 @@ const App = C.AppShell({
|
|
|
276
286
|
}),
|
|
277
287
|
crumb: C.Crumb({ trail: ['247420'], leaf: site.title || 'design' }),
|
|
278
288
|
side: buildSide(),
|
|
279
|
-
main: h('div', {},
|
|
289
|
+
main: h('div', { id: 'all' },
|
|
280
290
|
Hero(),
|
|
291
|
+
C.Marquee({ items: ['always open', '24 7 420', 'the creative department', 'shipping in public'], sep: '/' }),
|
|
281
292
|
Tabs(),
|
|
282
293
|
Kits(),
|
|
283
294
|
FileBrowser(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.246",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -120,6 +120,32 @@ export function RowLink({ code, title, sub, meta, href = '#', key, target }) {
|
|
|
120
120
|
return Row({ code, title, sub, meta, href, kind: 'link', key, target });
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
// PanelFromItems — the shared 'items[] -> RowLink wrapped in Panel' mapper
|
|
124
|
+
// every portfolio consumer theme.mjs (zellous/wireweave/thebird/247420) had
|
|
125
|
+
// hand-rolled identically: items.map((it,i) => RowLink({code, title, sub,
|
|
126
|
+
// meta, href})) inside a titled Panel. `keyPrefix` seeds each row's stable
|
|
127
|
+
// key (`${keyPrefix}${i}`), matching the consumer convention of a
|
|
128
|
+
// one-letter-per-section prefix (e.g. 'f' for features, 'm' for modules).
|
|
129
|
+
// Field aliasing mirrors the union of shapes actually hand-rolled downstream:
|
|
130
|
+
// title reads `title` then `name`; sub reads `sub` then `desc`; code falls
|
|
131
|
+
// back to a zero-padded 1-based index when the item carries none. `heading`/
|
|
132
|
+
// `count`/`style`/`kind` pass through to Panel unchanged.
|
|
133
|
+
export function PanelFromItems({ heading, items = [], keyPrefix = 'i', count, style, kind, emptyText } = {}) {
|
|
134
|
+
if (!items || !items.length) return emptyText != null ? h('div', { class: 'empty' }, emptyText) : null;
|
|
135
|
+
const rows = items.map((it, i) => {
|
|
136
|
+
const codeVal = it.code != null ? it.code : (it.rank != null ? it.rank : String(i + 1).padStart(2, '0'));
|
|
137
|
+
return RowLink({
|
|
138
|
+
key: keyPrefix + i,
|
|
139
|
+
code: codeVal,
|
|
140
|
+
title: it.title != null ? it.title : it.name,
|
|
141
|
+
sub: it.sub != null ? it.sub : (it.desc != null ? it.desc : ''),
|
|
142
|
+
meta: it.meta != null ? it.meta : '',
|
|
143
|
+
href: it.href || '#'
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
return Panel({ title: heading, count, style, kind, children: rows });
|
|
147
|
+
}
|
|
148
|
+
|
|
123
149
|
export function Section({ title, eyebrow, children, id }) {
|
|
124
150
|
return h('section', { class: 'ds-section', id: id || null },
|
|
125
151
|
eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
|
|
@@ -144,6 +170,66 @@ export function Hero({ eyebrow, title, body, accent, actions }) {
|
|
|
144
170
|
);
|
|
145
171
|
}
|
|
146
172
|
|
|
173
|
+
// HeroFromPageData — a single factory for the "hero block driven by a page-data
|
|
174
|
+
// object" shape that recurs, independently hand-rolled, across every flatspace
|
|
175
|
+
// consumer theme.mjs (heading/subheading/body/badges/ctas/install all read off
|
|
176
|
+
// a `hero` object parsed from the `__site__` JSON script tag). Consumers differ
|
|
177
|
+
// only in which fields their content YAML populates; this factory renders every
|
|
178
|
+
// field it is given and omits what is absent, so it is a drop-in for the
|
|
179
|
+
// narrowest (heading+body only) or richest (badges+ctas+install) hero shape
|
|
180
|
+
// alike. Returns null on a falsy `hero` so callers can write
|
|
181
|
+
// `HeroFromPageData(page.hero)` unconditionally, matching the existing
|
|
182
|
+
// `!home.hero ? null : ...` guard every hand-rolled version repeats.
|
|
183
|
+
//
|
|
184
|
+
// Shape: { heading, title, subheading, body, accent, badges, ctas, install }
|
|
185
|
+
// heading/title — hero <h1> text (heading wins if both given)
|
|
186
|
+
// subheading — a Lede-style standalone line above `body`
|
|
187
|
+
// body — the hero paragraph
|
|
188
|
+
// accent — a muted trailing aside appended to `body`
|
|
189
|
+
// badges — [{label, desc}] or [string], rendered as a stat strip
|
|
190
|
+
// ctas — [{label, href, primary}], rendered as Btn-equivalent links
|
|
191
|
+
// install — a single install command string, rendered as a `.cli` block
|
|
192
|
+
export function HeroFromPageData(hero) {
|
|
193
|
+
if (!hero) return null;
|
|
194
|
+
const heading = hero.heading || hero.title || '';
|
|
195
|
+
const badges = Array.isArray(hero.badges) ? hero.badges.filter(Boolean) : [];
|
|
196
|
+
const ctas = Array.isArray(hero.ctas) ? hero.ctas.filter(Boolean) : [];
|
|
197
|
+
const badgeRow = badges.length
|
|
198
|
+
? h('div', { class: 'ds-hero-stats' }, ...badges.map((b, i) =>
|
|
199
|
+
h('span', { key: 'hb' + i, class: 'ds-hero-stat' },
|
|
200
|
+
h('strong', { class: 'ds-hero-stat-n' }, String(b && b.label != null ? b.label : b)),
|
|
201
|
+
(b && b.desc) ? h('span', { class: 'ds-hero-stat-l' }, String(b.desc)) : null,
|
|
202
|
+
)))
|
|
203
|
+
: null;
|
|
204
|
+
const ctaRow = ctas.length
|
|
205
|
+
? h('div', { class: 'ds-hero-actions' }, ...ctas.map((c, i) =>
|
|
206
|
+
h('a', {
|
|
207
|
+
key: 'hc' + i,
|
|
208
|
+
class: (c.primary || i === 0) ? 'btn btn-accent' : 'btn btn-ghost',
|
|
209
|
+
href: c.href || '#',
|
|
210
|
+
}, c.label || c.cta || 'go')))
|
|
211
|
+
: null;
|
|
212
|
+
const installRow = hero.install
|
|
213
|
+
? h('div', { class: 'cli' },
|
|
214
|
+
h('span', { class: 'prompt' }, '$'),
|
|
215
|
+
h('span', { class: 'cmd' }, hero.install))
|
|
216
|
+
: null;
|
|
217
|
+
return h('div', { class: 'ds-hero' },
|
|
218
|
+
h('div', { class: 'ds-hero-head' },
|
|
219
|
+
hero.eyebrow ? h('span', { class: 'eyebrow' }, hero.eyebrow) : null,
|
|
220
|
+
h('h1', { class: 'ds-hero-title' }, heading)
|
|
221
|
+
),
|
|
222
|
+
hero.subheading ? h('p', { class: 'ds-hero-body lede' }, hero.subheading) : null,
|
|
223
|
+
hero.body ? h('p', { class: 'ds-hero-body' },
|
|
224
|
+
hero.body,
|
|
225
|
+
hero.accent ? h('span', { class: 'ds-hero-accent' }, ' ' + hero.accent) : null,
|
|
226
|
+
) : null,
|
|
227
|
+
installRow,
|
|
228
|
+
ctaRow,
|
|
229
|
+
badgeRow,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
147
233
|
export function Marquee({ items = [], sep = '/' }) {
|
|
148
234
|
// No items -> no ticker: an empty marquee still paints its border-block
|
|
149
235
|
// rules as an unexplained full-width stripe.
|
|
@@ -168,6 +254,32 @@ export function Install({ cmd, copied, onCopy }) {
|
|
|
168
254
|
);
|
|
169
255
|
}
|
|
170
256
|
|
|
257
|
+
// CliBlock — the shared 'quickstart.lines[] -> stacked CLI block' renderer
|
|
258
|
+
// every portfolio consumer theme.mjs (zellous/wireweave/247420) had hand-rolled
|
|
259
|
+
// identically: lines.map((l,i) => a div per line holding a prompt span ('$' or
|
|
260
|
+
// '#' for a comment line) and a cmd span, all wrapped in a Panel. This factory
|
|
261
|
+
// targets the multi-line `.cli` contract already defined in app-shell.css and
|
|
262
|
+
// gm-prose.css (`.cli` holding `.ds-cli-row` rows — each a prompt+cmd pair —
|
|
263
|
+
// and `.ds-cli-comment` comment rows). `lines` is [{kind, text}] where kind: 'cmt' renders a
|
|
264
|
+
// comment-only row (no prompt glyph); any other kind (or omitted) renders a
|
|
265
|
+
// command row prefixed '$'. `heading` titles the wrapping Panel ('quick start'
|
|
266
|
+
// default, matching every hand-rolled instance); pass `heading: null` to
|
|
267
|
+
// render the bare `.cli` block with no Panel chrome.
|
|
268
|
+
export function CliBlock({ lines = [], heading = 'quick start', className = '' } = {}) {
|
|
269
|
+
if (!lines || !lines.length) return null;
|
|
270
|
+
const rows = lines.map((l, i) => {
|
|
271
|
+
const isComment = l && l.kind === 'cmt';
|
|
272
|
+
const text = l && l.text != null ? l.text : '';
|
|
273
|
+
return isComment
|
|
274
|
+
? h('div', { key: 'q' + i, class: 'ds-cli-comment' }, text)
|
|
275
|
+
: h('div', { key: 'q' + i, class: 'ds-cli-row' },
|
|
276
|
+
h('span', { class: 'prompt' }, '$'),
|
|
277
|
+
h('span', { class: 'cmd' }, text));
|
|
278
|
+
});
|
|
279
|
+
const body = h('div', { class: 'cli' + (className ? ' ' + className : '') }, ...rows);
|
|
280
|
+
return heading == null ? body : Panel({ title: heading, children: body });
|
|
281
|
+
}
|
|
282
|
+
|
|
171
283
|
export function Receipt({ rows = [], emptyText = 'nothing here yet' }) {
|
|
172
284
|
if (!rows.length) return h('div', { class: 'empty' }, emptyText);
|
|
173
285
|
return h('table', { class: 'kv' },
|
package/src/components.js
CHANGED
|
@@ -11,8 +11,8 @@ export {
|
|
|
11
11
|
} from './components/shell.js';
|
|
12
12
|
|
|
13
13
|
export {
|
|
14
|
-
Panel, Card, Row, RowLink,
|
|
15
|
-
Hero, Marquee, Install, Receipt, Changelog,
|
|
14
|
+
Panel, Card, Row, RowLink, PanelFromItems,
|
|
15
|
+
Hero, HeroFromPageData, Marquee, Install, CliBlock, Receipt, Changelog,
|
|
16
16
|
WorksList, WritingList, Manifesto, Section, PageHeader,
|
|
17
17
|
Kpi, Table, SearchInput, TextField, Select, EventList,
|
|
18
18
|
HomeView, ProjectView, Form,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Single source of HTML/JSON escaping for the whole SDK and every static-site
|
|
2
|
+
// consumer that embeds SDK-produced markup or JSON into an HTML document.
|
|
3
|
+
// Exported from the SDK root so consumer theme.mjs files (this repo's own
|
|
4
|
+
// site/theme.mjs included) import these instead of pasting their own copy.
|
|
5
|
+
|
|
6
|
+
// Full HTML-entity escape (incl. quotes), safe in both text and attribute
|
|
7
|
+
// contexts.
|
|
8
|
+
export function escapeHtml(s) {
|
|
9
|
+
return String(s ?? '').replace(/[&<>"']/g, (c) => ({
|
|
10
|
+
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
|
11
|
+
})[c]);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// U+2028 LINE SEPARATOR / U+2029 PARAGRAPH SEPARATOR are valid JSON string
|
|
15
|
+
// contents but invalid raw JS string-literal contents, so they must be
|
|
16
|
+
// entity-escaped too before this can be safely embedded in an inline
|
|
17
|
+
// <script> block. Built from character codes rather than a literal
|
|
18
|
+
// character or bare regex literal so no raw U+2028/U+2029 byte has to
|
|
19
|
+
// survive on disk (some toolchains mangle/strip it), and so it never risks
|
|
20
|
+
// being parsed as a source-level line terminator.
|
|
21
|
+
const LINE_SEP_RE = new RegExp(String.fromCharCode(0x2028), 'g');
|
|
22
|
+
const PARA_SEP_RE = new RegExp(String.fromCharCode(0x2029), 'g');
|
|
23
|
+
|
|
24
|
+
// Safe to embed the result of JSON.stringify inside a <script type="...">
|
|
25
|
+
// block: escapes </script>-breaking sequences and the two line-terminator
|
|
26
|
+
// code points that are valid JSON but invalid raw JS string literals.
|
|
27
|
+
export function escapeJson(obj) {
|
|
28
|
+
return JSON.stringify(obj)
|
|
29
|
+
.replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026')
|
|
30
|
+
.replace(LINE_SEP_RE, '\\u2028').replace(PARA_SEP_RE, '\\u2029');
|
|
31
|
+
}
|
package/src/index.js
CHANGED
|
@@ -10,8 +10,11 @@ import * as components from './components.js';
|
|
|
10
10
|
import * as motion from './motion.js';
|
|
11
11
|
import * as debug from './debug.js';
|
|
12
12
|
import { renderMarkdown, ensureReady as ensureMarkdownReady } from './markdown.js';
|
|
13
|
+
import { escapeHtml, escapeJson } from './html-escape.js';
|
|
13
14
|
import { ensurePrism, highlightAllUnder } from './highlight.js';
|
|
14
15
|
import { renderPageHtml } from './page-html.js';
|
|
16
|
+
import { HeroFromPageData } from './components/content.js';
|
|
17
|
+
import { ThemeToggle } from './components/theme-toggle.js';
|
|
15
18
|
import { mountKit } from './bootstrap.js';
|
|
16
19
|
import * as theme from './theme.js';
|
|
17
20
|
import { registerChatElement, DsChat } from './web-components/ds-chat.js';
|
|
@@ -68,8 +71,9 @@ export {
|
|
|
68
71
|
ensurePrism, highlightAllUnder,
|
|
69
72
|
registerChatElement, DsChat,
|
|
70
73
|
registerFreddieChatElement, FreddieChat,
|
|
71
|
-
renderPageHtml,
|
|
72
|
-
|
|
74
|
+
renderPageHtml, HeroFromPageData,
|
|
75
|
+
escapeHtml, escapeJson,
|
|
76
|
+
theme, ThemeToggle
|
|
73
77
|
};
|
|
74
78
|
export { applyTheme, getTheme, resolvedTheme, onThemeChange, initTheme,
|
|
75
79
|
applyAccent, getAccent, applyDensity, getDensity } from './theme.js';
|
|
@@ -94,5 +98,6 @@ export default {
|
|
|
94
98
|
webjsx, loadCss, scope, installStyles, mount, h, applyDiff,
|
|
95
99
|
registerDeckStage, getDeckStage, Router, createRouter,
|
|
96
100
|
components, motion, debug, mountKit,
|
|
97
|
-
renderMarkdown, ensurePrism, registerChatElement, renderPageHtml
|
|
101
|
+
renderMarkdown, ensurePrism, registerChatElement, renderPageHtml, HeroFromPageData,
|
|
102
|
+
escapeHtml, escapeJson
|
|
98
103
|
};
|
package/src/markdown.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// if loading fails, we fall back to a simple escape-and-linebreak pass so
|
|
3
3
|
// the chat doesn't go blank.
|
|
4
4
|
|
|
5
|
+
import { escapeHtml } from './html-escape.js';
|
|
6
|
+
|
|
5
7
|
let _ready = null;
|
|
6
8
|
let _marked = null;
|
|
7
9
|
let _purify = null;
|
|
@@ -44,13 +46,11 @@ export async function ensureReady() {
|
|
|
44
46
|
return _ready;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
// The single HTML-entity escape for the whole SDK
|
|
48
|
-
// is safe in attribute contexts too).
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
})[c]);
|
|
53
|
-
}
|
|
49
|
+
// The single HTML-entity escape for the whole SDK now lives in html-escape.js
|
|
50
|
+
// (full set incl. quotes, so it is safe in attribute contexts too).
|
|
51
|
+
// Re-exported here for backward compatibility with existing importers of
|
|
52
|
+
// escapeHtml from this module. page-html.js re-exports this as `escape`.
|
|
53
|
+
export { escapeHtml };
|
|
54
54
|
|
|
55
55
|
export async function renderMarkdown(src) {
|
|
56
56
|
const ok = await ensureReady();
|