anentrypoint-design 0.0.102 → 0.0.104
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 +464 -2005
- package/colors_and_type.css +148 -619
- package/dist/247420.css +592 -2748
- package/dist/247420.js +23 -62
- package/package.json +22 -23
- package/src/bootstrap.js +5 -18
- package/src/components/chat.js +15 -15
- package/src/components/community.js +9 -7
- package/src/components/content.js +71 -54
- package/src/components/files-modals.js +4 -2
- package/src/components/files.js +6 -14
- package/src/components/freddie/helpers.js +38 -77
- package/src/components/freddie.js +32 -16
- package/src/components/shell.js +22 -15
- package/src/components.js +7 -3
- package/src/debug.js +21 -30
- package/src/deck-stage.js +10 -6
- package/src/highlight.js +25 -11
- package/src/index.js +31 -7
- package/src/{desktop → kits/os}/freddie/helpers.js +1 -1
- package/src/{desktop → kits/os}/freddie/pages-chat.js +2 -2
- package/src/{desktop → kits/os}/freddie/pages-core.js +2 -2
- package/src/{desktop → kits/os}/freddie/pages-os.js +1 -1
- package/src/{desktop → kits/os}/freddie/pages-tools.js +2 -2
- package/src/{desktop → kits/os}/freddie-dashboard.js +2 -2
- package/src/markdown.js +27 -49
- package/src/motion.js +30 -17
- package/src/page-html.js +18 -116
- package/src/styles.js +14 -22
- package/src/web-components/ds-chat.js +26 -56
- package/dist/247420.app.js +0 -5
- package/dist/fonts/archivo_v25_k3k6o8UDI-1M0wlSV9XAw6lQkqWY8Q82sJaRE-NWIDdgffTT0zRp8A.ttf +0 -0
- package/dist/fonts/archivo_v25_k3k6o8UDI-1M0wlSV9XAw6lQkqWY8Q82sJaRE-NWIDdgffTT6jRp8A.ttf +0 -0
- package/dist/fonts/archivo_v25_k3k6o8UDI-1M0wlSV9XAw6lQkqWY8Q82sJaRE-NWIDdgffTTBjNp8A.ttf +0 -0
- package/dist/fonts/archivo_v25_k3k6o8UDI-1M0wlSV9XAw6lQkqWY8Q82sJaRE-NWIDdgffTTNDNp8A.ttf +0 -0
- package/dist/fonts/archivo_v25_k3k6o8UDI-1M0wlSV9XAw6lQkqWY8Q82sJaRE-NWIDdgffTTnTRp8A.ttf +0 -0
- package/dist/fonts/archivo_v25_k3k6o8UDI-1M0wlSV9XAw6lQkqWY8Q82sJaRE-NWIDdgffTTtDRp8A.ttf +0 -0
- package/dist/fonts/archivonarrow_v35_tss5ApVBdCYD5Q7hcxTE1ArZ0Zz8oY2KRmwvKhhv8laKpA.ttf +0 -0
- package/dist/fonts/archivonarrow_v35_tss5ApVBdCYD5Q7hcxTE1ArZ0Zz8oY2KRmwvKhhvHlGKpA.ttf +0 -0
- package/dist/fonts/archivonarrow_v35_tss5ApVBdCYD5Q7hcxTE1ArZ0Zz8oY2KRmwvKhhvLFGKpA.ttf +0 -0
- package/dist/fonts/archivonarrow_v35_tss5ApVBdCYD5Q7hcxTE1ArZ0Zz8oY2KRmwvKhhvy1aKpA.ttf +0 -0
- package/dist/fonts/jetbrainsmono_v24_tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8-qxjPQ.ttf +0 -0
- package/dist/fonts/jetbrainsmono_v24_tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8FqtjPQ.ttf +0 -0
- package/dist/fonts/jetbrainsmono_v24_tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8L6tjPQ.ttf +0 -0
- package/dist/fonts/jetbrainsmono_v24_tDbY2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKxjPQ.ttf +0 -0
- package/dist/fonts/jetbrainsmono_v24_tDba2o-flEEny0FZhsfKu5WU4xD-IQ-PuZJJXxfpAO-LflOQ.ttf +0 -0
- package/dist/fonts/jetbrainsmono_v24_tDba2o-flEEny0FZhsfKu5WU4xD-IQ-PuZJJXxfpAO9seVOQ.ttf +0 -0
- package/dist/fonts/spacegrotesk_v22_V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj42Vksj.ttf +0 -0
- package/dist/fonts/spacegrotesk_v22_V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj4PVksj.ttf +0 -0
- package/dist/fonts/spacegrotesk_v22_V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj7aUUsj.ttf +0 -0
- package/dist/fonts/spacegrotesk_v22_V8mQoQDjQSkFtoMM3T6r8E7mF71Q-gOoraIAEj7oUUsj.ttf +0 -0
- package/src/app.js +0 -156
- package/src/components/freddie/pages-chains.js +0 -168
- package/src/components/freddie/pages-chat.js +0 -122
- package/src/components/freddie/pages-config-edit.js +0 -174
- package/src/components/freddie/pages-config.js +0 -193
- package/src/components/freddie/pages-core.js +0 -170
- package/src/components/freddie/pages-runtime.js +0 -69
- package/src/components/freddie/pages-voice.js +0 -109
- package/src/web-components/freddie-chat.js +0 -34
- /package/src/{desktop → kits/os}/about-app.js +0 -0
- /package/src/{desktop → kits/os}/app-panes.css +0 -0
- /package/src/{desktop → kits/os}/browser-app.js +0 -0
- /package/src/{desktop → kits/os}/files-app.js +0 -0
- /package/src/{desktop → kits/os}/freddie/routes.js +0 -0
- /package/src/{desktop → kits/os}/freddie-dashboard.css +0 -0
- /package/src/{desktop → kits/os}/icons.js +0 -0
- /package/src/{desktop → kits/os}/index.js +0 -0
- /package/src/{desktop → kits/os}/launcher.css +0 -0
- /package/src/{desktop → kits/os}/launcher.js +0 -0
- /package/src/{desktop → kits/os}/monitor-app.js +0 -0
- /package/src/{desktop → kits/os}/shell.js +0 -0
- /package/src/{desktop → kits/os}/terminal-app.js +0 -0
- /package/src/{desktop → kits/os}/theme.css +0 -0
- /package/src/{desktop → kits/os}/validate.css +0 -0
- /package/src/{desktop → kits/os}/validator-app.js +0 -0
- /package/src/{desktop → kits/os}/wm.css +0 -0
- /package/src/{desktop → kits/os}/wm.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.104",
|
|
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",
|
|
@@ -10,38 +10,37 @@
|
|
|
10
10
|
"import": "./dist/247420.js",
|
|
11
11
|
"default": "./dist/247420.js"
|
|
12
12
|
},
|
|
13
|
-
"./app": "./dist/247420.app.js",
|
|
14
13
|
"./css": "./dist/247420.css",
|
|
15
|
-
"./
|
|
16
|
-
"import": "./src/
|
|
17
|
-
"default": "./src/
|
|
14
|
+
"./kits/os": {
|
|
15
|
+
"import": "./src/kits/os/index.js",
|
|
16
|
+
"default": "./src/kits/os/index.js"
|
|
18
17
|
},
|
|
19
|
-
"./
|
|
20
|
-
"./
|
|
21
|
-
"./
|
|
22
|
-
"./
|
|
23
|
-
"./
|
|
24
|
-
"./
|
|
25
|
-
"./
|
|
26
|
-
"./
|
|
27
|
-
"./
|
|
28
|
-
"./
|
|
29
|
-
"./
|
|
30
|
-
"./
|
|
31
|
-
"./
|
|
32
|
-
"./
|
|
33
|
-
"./
|
|
34
|
-
"./
|
|
35
|
-
"./
|
|
18
|
+
"./kits/os/theme.css": "./src/kits/os/theme.css",
|
|
19
|
+
"./kits/os/wm.css": "./src/kits/os/wm.css",
|
|
20
|
+
"./kits/os/wm.js": "./src/kits/os/wm.js",
|
|
21
|
+
"./kits/os/launcher.js": "./src/kits/os/launcher.js",
|
|
22
|
+
"./kits/os/launcher.css": "./src/kits/os/launcher.css",
|
|
23
|
+
"./kits/os/validate.css": "./src/kits/os/validate.css",
|
|
24
|
+
"./kits/os/icons.js": "./src/kits/os/icons.js",
|
|
25
|
+
"./kits/os/shell.js": "./src/kits/os/shell.js",
|
|
26
|
+
"./kits/os/freddie-dashboard.js": "./src/kits/os/freddie-dashboard.js",
|
|
27
|
+
"./kits/os/freddie-dashboard.css": "./src/kits/os/freddie-dashboard.css",
|
|
28
|
+
"./kits/os/files-app.js": "./src/kits/os/files-app.js",
|
|
29
|
+
"./kits/os/monitor-app.js": "./src/kits/os/monitor-app.js",
|
|
30
|
+
"./kits/os/about-app.js": "./src/kits/os/about-app.js",
|
|
31
|
+
"./kits/os/terminal-app.js": "./src/kits/os/terminal-app.js",
|
|
32
|
+
"./kits/os/browser-app.js": "./src/kits/os/browser-app.js",
|
|
33
|
+
"./kits/os/validator-app.js": "./src/kits/os/validator-app.js",
|
|
34
|
+
"./kits/os/app-panes.css": "./src/kits/os/app-panes.css",
|
|
36
35
|
"./colors_and_type.css": "./colors_and_type.css",
|
|
37
36
|
"./app-shell.css": "./app-shell.css",
|
|
37
|
+
"./system.css": "./system.css",
|
|
38
38
|
"./page-html": {
|
|
39
39
|
"import": "./src/page-html.js",
|
|
40
40
|
"default": "./src/page-html.js"
|
|
41
41
|
},
|
|
42
42
|
"./src/page-html.js": "./src/page-html.js",
|
|
43
43
|
"./web-components/ds-chat.js": "./src/web-components/ds-chat.js",
|
|
44
|
-
"./web-components/freddie-chat.js": "./src/web-components/freddie-chat.js",
|
|
45
44
|
"./package.json": "./package.json"
|
|
46
45
|
},
|
|
47
46
|
"files": [
|
package/src/bootstrap.js
CHANGED
|
@@ -1,28 +1,15 @@
|
|
|
1
|
+
// mountKit — single entry every ui_kit uses. Installs motion, runs
|
|
2
|
+
// applyDiff, registers a debug snapshot.
|
|
3
|
+
|
|
1
4
|
import * as webjsx from '../vendor/webjsx/index.js';
|
|
2
5
|
import * as motion from './motion.js';
|
|
3
6
|
import { register } from './debug.js';
|
|
4
7
|
|
|
5
|
-
const ANIMATE_HREF = 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css';
|
|
6
|
-
const PRISM_CSS = 'https://cdn.jsdelivr.net/npm/prismjs@1.30.0/themes/prism-tomorrow.min.css';
|
|
7
|
-
|
|
8
|
-
export function ensureCdnLink(id, href) {
|
|
9
|
-
if (document.getElementById(id)) return;
|
|
10
|
-
const link = document.createElement('link');
|
|
11
|
-
link.id = id;
|
|
12
|
-
link.rel = 'stylesheet';
|
|
13
|
-
link.href = href;
|
|
14
|
-
document.head.appendChild(link);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function ensureMotionCss() { ensureCdnLink('animate-style-cdn', ANIMATE_HREF); }
|
|
18
|
-
export function ensurePrismCss() { ensureCdnLink('prism-style-cdn', PRISM_CSS); }
|
|
19
|
-
|
|
20
8
|
export function mountKit({ root, view, screen, animateOnMount = true } = {}) {
|
|
21
9
|
if (!root) throw new Error('mountKit: root required');
|
|
22
10
|
if (typeof view !== 'function') throw new Error('mountKit: view fn required');
|
|
23
|
-
if (screen) document.body.dataset.screenLabel = screen;
|
|
24
|
-
|
|
25
|
-
ensurePrismCss();
|
|
11
|
+
if (screen && typeof document !== 'undefined') document.body.dataset.screenLabel = screen;
|
|
12
|
+
motion.installMotion();
|
|
26
13
|
let scheduled = false;
|
|
27
14
|
const render = () => {
|
|
28
15
|
scheduled = false;
|
package/src/components/chat.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
// Chat surface — matches upstream signatures (parts, typing, reactions,
|
|
2
|
+
// receipts, aicat). Pure factories — props in, vnode out.
|
|
3
|
+
// Includes ChatMessage, ChatComposer, Chat, AICat, AICatPortrait.
|
|
4
|
+
|
|
1
5
|
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
2
6
|
import { renderMarkdown, ensureReady as ensureMarkdownReady } from '../markdown.js';
|
|
3
7
|
import { highlightAllUnder, ensurePrism } from '../highlight.js';
|
|
4
8
|
import { register } from '../debug.js';
|
|
5
9
|
|
|
6
10
|
const h = webjsx.createElement;
|
|
7
|
-
|
|
8
11
|
let _stats = { messages: 0, lastKindCounts: {} };
|
|
9
12
|
|
|
10
13
|
export function fmtBytes(n) {
|
|
@@ -15,6 +18,7 @@ export function fmtBytes(n) {
|
|
|
15
18
|
return (n / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
|
|
16
19
|
}
|
|
17
20
|
|
|
21
|
+
// Inline-only markdown subset; safe for chat bubbles.
|
|
18
22
|
export function renderInline(text) {
|
|
19
23
|
if (text == null) return [];
|
|
20
24
|
const out = [];
|
|
@@ -66,38 +70,34 @@ function CodeNode(p) {
|
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
const PART_RENDERERS = {
|
|
69
|
-
text:
|
|
70
|
-
md:
|
|
71
|
-
code:
|
|
73
|
+
text: (p) => h('div', { class: 'chat-bubble' }, ...renderInline(p.text || '')),
|
|
74
|
+
md: (p) => MdNode(p),
|
|
75
|
+
code: (p) => CodeNode(p),
|
|
72
76
|
image: (p) => h('a', { class: 'chat-image', href: p.href || p.src, target: '_blank', rel: 'noopener' },
|
|
73
77
|
h('img', { src: p.src, alt: p.alt || '', loading: 'lazy' }),
|
|
74
|
-
p.caption ? h('span', { class: 'cap' }, p.caption) : null
|
|
75
|
-
),
|
|
76
|
-
pdf: (p) => h('div', { class: 'chat-pdf' },
|
|
78
|
+
p.caption ? h('span', { class: 'cap' }, p.caption) : null),
|
|
79
|
+
pdf: (p) => h('div', { class: 'chat-pdf' },
|
|
77
80
|
h('div', { class: 'chat-pdf-head' },
|
|
78
81
|
h('span', { class: 'glyph' }, '▤'),
|
|
79
82
|
h('span', { class: 'name' }, p.name || 'document.pdf'),
|
|
80
83
|
p.size != null ? h('span', { class: 'size' }, fmtBytes(p.size)) : null,
|
|
81
84
|
h('a', { class: 'open', href: p.src, target: '_blank', rel: 'noopener' }, 'open ↗')
|
|
82
85
|
),
|
|
83
|
-
h('embed', { src: p.src, type: 'application/pdf' })
|
|
84
|
-
),
|
|
85
|
-
file: (p) => h('a', { class: 'chat-file', href: p.src, target: '_blank', rel: 'noopener', download: p.name || true },
|
|
86
|
+
h('embed', { src: p.src, type: 'application/pdf' })),
|
|
87
|
+
file: (p) => h('a', { class: 'chat-file', href: p.src, target: '_blank', rel: 'noopener', download: p.name || true },
|
|
86
88
|
h('span', { class: 'glyph' }, fileGlyph(p.name)),
|
|
87
89
|
h('span', { class: 'meta' },
|
|
88
90
|
h('span', { class: 'name' }, p.name || 'attachment'),
|
|
89
91
|
h('span', { class: 'size' }, [p.kindLabel || (p.name || '').split('.').pop().toUpperCase(), p.size != null ? fmtBytes(p.size) : null].filter(Boolean).join(' · '))
|
|
90
92
|
),
|
|
91
|
-
h('span', { class: 'go' }, '↓')
|
|
92
|
-
),
|
|
93
|
-
link: (p) => h('a', { class: 'chat-link', href: p.href, target: '_blank', rel: 'noopener' },
|
|
93
|
+
h('span', { class: 'go' }, '↓')),
|
|
94
|
+
link: (p) => h('a', { class: 'chat-link', href: p.href, target: '_blank', rel: 'noopener' },
|
|
94
95
|
p.thumb ? h('img', { class: 'thumb', src: p.thumb, alt: '' }) : null,
|
|
95
96
|
h('span', { class: 'meta' },
|
|
96
97
|
h('span', { class: 'host' }, p.host || (() => { try { return new URL(p.href).host; } catch { return ''; } })()),
|
|
97
98
|
h('span', { class: 'title' }, p.title || p.href),
|
|
98
99
|
p.desc ? h('span', { class: 'desc' }, p.desc) : null
|
|
99
|
-
)
|
|
100
|
-
)
|
|
100
|
+
))
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
function renderPart(p, key) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Community surface — matches upstream signatures.
|
|
2
|
+
|
|
1
3
|
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
2
4
|
const h = webjsx.createElement;
|
|
3
5
|
|
|
@@ -14,7 +16,7 @@ export function ServerRail({ servers = [], activeId, onSelect, onAdd } = {}) {
|
|
|
14
16
|
return h('div', { class: 'cm-server-rail' },
|
|
15
17
|
h('a', { class: 'cm-server-back', href: '../', title: 'Back' }, '◰'),
|
|
16
18
|
h('div', { class: 'cm-server-sep' }),
|
|
17
|
-
...servers.map(s => ServerIcon({ ...s, active: s.id === activeId, onClick: () => onSelect
|
|
19
|
+
...servers.map(s => ServerIcon({ ...s, active: s.id === activeId, onClick: () => onSelect && onSelect(s.id) })),
|
|
18
20
|
onAdd ? h('button', { class: 'cm-server-add', onclick: onAdd, title: 'Add server' }, '+') : null
|
|
19
21
|
);
|
|
20
22
|
}
|
|
@@ -25,7 +27,7 @@ export function ChannelItem({ id, name, type = 'text', active, voiceActive, onCl
|
|
|
25
27
|
class: 'cm-channel-item' + (active ? ' active' : '') + (voiceActive ? ' voice-active' : ''),
|
|
26
28
|
'data-id': id,
|
|
27
29
|
onclick: onClick,
|
|
28
|
-
oncontextmenu: (e) => { e.preventDefault(); onContext
|
|
30
|
+
oncontextmenu: (e) => { e.preventDefault(); onContext && onContext(id, e.clientX, e.clientY); }
|
|
29
31
|
},
|
|
30
32
|
h('span', { class: 'cm-ch-icon' }, icon),
|
|
31
33
|
h('span', { class: 'cm-ch-name' }, name)
|
|
@@ -36,7 +38,7 @@ export function ChannelCategory({ id, name, channels = [], collapsed, activeId,
|
|
|
36
38
|
return h('div', { class: 'cm-channel-category' },
|
|
37
39
|
h('div', {
|
|
38
40
|
class: 'cm-category-header' + (collapsed ? ' collapsed' : ''),
|
|
39
|
-
onclick: () => onToggle
|
|
41
|
+
onclick: () => onToggle && onToggle(id)
|
|
40
42
|
},
|
|
41
43
|
h('svg', { class: 'cm-cat-arrow', viewBox: '0 0 24 24' }, h('path', { d: 'M7 10l5 5 5-5z' })),
|
|
42
44
|
h('span', { class: 'cm-cat-name' }, name),
|
|
@@ -46,7 +48,7 @@ export function ChannelCategory({ id, name, channels = [], collapsed, activeId,
|
|
|
46
48
|
...channels.map(c => ChannelItem({
|
|
47
49
|
...c,
|
|
48
50
|
active: c.id === activeId,
|
|
49
|
-
onClick: () => onChannelClick
|
|
51
|
+
onClick: () => onChannelClick && onChannelClick(c),
|
|
50
52
|
onContext: onChannelContext
|
|
51
53
|
}))
|
|
52
54
|
)
|
|
@@ -80,10 +82,10 @@ export function UserPanel({ name, tag, color, muted, deafened, onMute, onDeafen,
|
|
|
80
82
|
);
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
export function ChannelSidebar({ serverName, channels = [], categories = [], activeId, collapsedCats
|
|
85
|
+
export function ChannelSidebar({ serverName, channels = [], categories = [], activeId, collapsedCats, onChannelClick, onCategoryToggle, onAddChannel, onChannelContext, userPanelProps } = {}) {
|
|
86
|
+
const collapsed = collapsedCats || new Set();
|
|
84
87
|
const uncategorized = channels.filter(c => !c.categoryId || !categories.find(cat => cat.id === c.categoryId));
|
|
85
88
|
const sorted = [...categories].sort((a, b) => (a.position || 0) - (b.position || 0));
|
|
86
|
-
|
|
87
89
|
return h('div', { class: 'cm-channel-sidebar' },
|
|
88
90
|
h('div', { class: 'cm-server-header' },
|
|
89
91
|
h('span', { class: 'cm-server-header-name' }, serverName || 'Server'),
|
|
@@ -93,7 +95,7 @@ export function ChannelSidebar({ serverName, channels = [], categories = [], act
|
|
|
93
95
|
id: cat.id,
|
|
94
96
|
name: cat.name,
|
|
95
97
|
channels: channels.filter(c => c.categoryId === cat.id).sort((a, b) => (a.position || 0) - (b.position || 0)),
|
|
96
|
-
collapsed:
|
|
98
|
+
collapsed: collapsed.has && collapsed.has(cat.id),
|
|
97
99
|
activeId,
|
|
98
100
|
onToggle: onCategoryToggle,
|
|
99
101
|
onAddChannel,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// Content blocks: Panel, Row, RowLink, Section, Hero, Install, Receipt,
|
|
2
|
+
// Changelog, WorksList, WritingList, Manifesto, Kpi, Table, HomeView,
|
|
3
|
+
// ProjectView, Form. Pure factories.
|
|
4
|
+
|
|
1
5
|
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
2
|
-
import { Btn, Heading, Lede } from './shell.js';
|
|
6
|
+
import { Btn, Heading, Lede, Dot } from './shell.js';
|
|
3
7
|
const h = webjsx.createElement;
|
|
4
8
|
|
|
5
9
|
export function Panel({ title, count, right, style = '', children, kind }) {
|
|
@@ -29,13 +33,23 @@ export function RowLink({ code, title, sub, meta, href = '#', key, target }) {
|
|
|
29
33
|
return Row({ code, title, sub, meta, href, kind: 'link', key, target });
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
export function
|
|
36
|
+
export function Section({ title, eyebrow, children }) {
|
|
37
|
+
return h('section', { class: 'ds-section' },
|
|
38
|
+
eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
|
|
39
|
+
title ? h('h3', {}, title) : null,
|
|
40
|
+
...(Array.isArray(children) ? children : [children])
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function Hero({ eyebrow, title, body, accent, badge, badgeCount, actions }) {
|
|
33
45
|
return h('div', { class: 'ds-hero' },
|
|
46
|
+
eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
|
|
34
47
|
h('h1', { class: 'ds-hero-title' }, title),
|
|
35
48
|
body ? h('p', { class: 'ds-hero-body' },
|
|
36
49
|
body,
|
|
37
50
|
accent ? h('span', { class: 'ds-hero-accent' }, ' ' + accent) : null
|
|
38
51
|
) : null,
|
|
52
|
+
actions ? h('div', { class: 'ds-hero-actions', style: 'display:flex;gap:10px;flex-wrap:wrap;margin-top:8px' }, ...(Array.isArray(actions) ? actions : [actions])) : null,
|
|
39
53
|
badge ? Panel({ title: badge, count: badgeCount, kind: 'inline', children: [] }) : null
|
|
40
54
|
);
|
|
41
55
|
}
|
|
@@ -71,21 +85,17 @@ export function Changelog({ entries = [] }) {
|
|
|
71
85
|
|
|
72
86
|
export function WorksList({ works = [], openedIndex = -1, onToggle }) {
|
|
73
87
|
return Panel({
|
|
74
|
-
title: `works · ${String(works.length).padStart(2, '0')} of ~${works.length}`,
|
|
75
|
-
right: h('a', { class: 'ds-link-accent', href: 'https://github.com/AnEntrypoint' }, 'all repos ↗'),
|
|
76
88
|
children: works.map((w, i) => {
|
|
77
89
|
const isOpen = openedIndex === i;
|
|
78
90
|
return h('div', { key: i },
|
|
79
91
|
Row({
|
|
80
|
-
code: w.code,
|
|
92
|
+
code: w.code,
|
|
93
|
+
title: w.title, sub: w.sub,
|
|
81
94
|
meta: w.meta + ' ' + (isOpen ? '−' : '+'),
|
|
82
95
|
active: isOpen,
|
|
83
96
|
onClick: () => onToggle && onToggle(isOpen ? -1 : i)
|
|
84
97
|
}),
|
|
85
|
-
isOpen ? h('div', {
|
|
86
|
-
class: 'work-detail',
|
|
87
|
-
'data-work-index': String(i)
|
|
88
|
-
},
|
|
98
|
+
isOpen ? h('div', { class: 'work-detail', 'data-work-index': String(i) },
|
|
89
99
|
h('div', { class: 'ds-prose' },
|
|
90
100
|
h('p', { class: 'ds-work-body' }, w.body)
|
|
91
101
|
),
|
|
@@ -102,7 +112,7 @@ export function WorksList({ works = [], openedIndex = -1, onToggle }) {
|
|
|
102
112
|
export function WritingList({ posts = [] }) {
|
|
103
113
|
return Panel({
|
|
104
114
|
children: posts.map((p, i) =>
|
|
105
|
-
RowLink({ key: i, code: p.date, title: p.title, meta:
|
|
115
|
+
RowLink({ key: i, code: p.date, title: p.title, meta: p.tag, href: p.href || '#' })
|
|
106
116
|
)
|
|
107
117
|
});
|
|
108
118
|
}
|
|
@@ -120,77 +130,84 @@ export function Manifesto({ paragraphs = [], maxWidth }) {
|
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
export function Kpi({ items = [] }) {
|
|
123
|
-
return h('div', { class: 'kpi' }, ...items.map(([n, l]) =>
|
|
124
|
-
h('div', { class: 'kpi-card' },
|
|
133
|
+
return h('div', { class: 'kpi' }, ...items.map(([n, l], i) =>
|
|
134
|
+
h('div', { key: i, class: 'kpi-card' },
|
|
125
135
|
h('div', { class: 'num' }, String(n)),
|
|
126
136
|
h('div', { class: 'lbl' }, l))));
|
|
127
137
|
}
|
|
128
138
|
|
|
129
|
-
export function Table({ headers = [], rows = [], onRowClick, emptyText = '
|
|
130
|
-
if (!rows || rows.length === 0) {
|
|
131
|
-
return h('div', { class: 'empty' }, emptyText);
|
|
132
|
-
}
|
|
139
|
+
export function Table({ headers = [], rows = [], onRowClick, emptyText = 'nothing here yet' }) {
|
|
140
|
+
if (!rows || rows.length === 0) return h('div', { class: 'empty' }, emptyText);
|
|
133
141
|
return h('table', {},
|
|
134
|
-
h('thead', {}, h('tr', {}, ...headers.map(hd => h('th', {}, hd)))),
|
|
142
|
+
h('thead', {}, h('tr', {}, ...headers.map((hd, i) => h('th', { key: i }, hd)))),
|
|
135
143
|
h('tbody', {}, ...rows.map((row, i) => h('tr', {
|
|
144
|
+
key: i,
|
|
136
145
|
class: onRowClick ? 'clickable' : '',
|
|
137
146
|
onclick: onRowClick ? () => onRowClick(i) : null
|
|
138
|
-
}, ...row.map(c => h('td', {}, c == null ? '' : (typeof c === 'object' ? c : String(c))))))));
|
|
147
|
+
}, ...row.map((c, j) => h('td', { key: j }, c == null ? '' : (typeof c === 'object' ? c : String(c))))))));
|
|
139
148
|
}
|
|
140
149
|
|
|
141
|
-
export function
|
|
142
|
-
return h('div', { class: 'ds-section' },
|
|
143
|
-
title ? h('h3', {}, title) : null,
|
|
144
|
-
...(Array.isArray(children) ? children : [children])
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function HomeView({ state, onNav, onToggleWork, works, posts, manifesto, currentlyShipping }) {
|
|
150
|
+
export function HomeView({ state = {}, onNav, onToggleWork, works = [], posts = [], manifesto = [], currentlyShipping } = {}) {
|
|
149
151
|
return [
|
|
150
152
|
Hero({
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
eyebrow: 'an entrypoint',
|
|
154
|
+
title: 'Small, weird, useful tools — built in public.',
|
|
155
|
+
body: '247420 is a creative collective of eight, scattered across three timezones. We have been shipping open-source tools for the web since 2018.',
|
|
156
|
+
accent: 'Some become the future. Most don\'t. That\'s the deal.'
|
|
154
157
|
}),
|
|
155
|
-
currentlyShipping ?
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
kind: 'inline',
|
|
158
|
+
currentlyShipping ? Section({
|
|
159
|
+
eyebrow: 'currently shipping',
|
|
160
|
+
children: Panel({
|
|
161
|
+
kind: 'wide',
|
|
160
162
|
children: currentlyShipping.map((row, i) =>
|
|
161
163
|
Row({
|
|
162
164
|
key: i,
|
|
163
|
-
code:
|
|
165
|
+
code: Dot({ tone: row.live ? 'live' : 'idle' }),
|
|
164
166
|
title: row.title, sub: row.sub, meta: row.meta
|
|
165
167
|
})
|
|
166
168
|
)
|
|
167
169
|
})
|
|
168
|
-
) : null,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
}) : null,
|
|
171
|
+
works.length ? Section({
|
|
172
|
+
eyebrow: 'works', title: 'Everything else.',
|
|
173
|
+
children: WorksList({ works, openedIndex: state.opened ?? -1, onToggle: onToggleWork })
|
|
174
|
+
}) : null,
|
|
175
|
+
posts.length ? Section({
|
|
176
|
+
eyebrow: 'writing', title: 'When we have something to say.',
|
|
177
|
+
children: WritingList({ posts })
|
|
178
|
+
}) : null,
|
|
179
|
+
manifesto.length ? Section({
|
|
180
|
+
eyebrow: 'who\'s here', title: 'Eight people, three timezones, one ongoing conversation.',
|
|
181
|
+
children: Manifesto({ paragraphs: manifesto })
|
|
182
|
+
}) : null
|
|
183
|
+
].filter(Boolean);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function ProjectView({ project = {}, copied, onCopy } = {}) {
|
|
176
187
|
return [
|
|
177
188
|
h('div', { class: 'ds-prose' },
|
|
178
189
|
Heading({ level: 1, children: project.name }),
|
|
179
190
|
Lede({ children: project.tagline })
|
|
180
191
|
),
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
192
|
+
project.install ? [
|
|
193
|
+
Heading({ level: 3, children: 'install' }),
|
|
194
|
+
Install({ cmd: project.install, copied, onCopy }),
|
|
195
|
+
] : null,
|
|
196
|
+
project.receipt ? [
|
|
197
|
+
Heading({ level: 3, children: 'by the numbers' }),
|
|
198
|
+
Receipt({ rows: project.receipt }),
|
|
199
|
+
] : null,
|
|
200
|
+
project.changelog ? [
|
|
201
|
+
Heading({ level: 3, children: 'recent releases' }),
|
|
202
|
+
Changelog({ entries: project.changelog })
|
|
203
|
+
] : null
|
|
204
|
+
].filter(Boolean).flat();
|
|
188
205
|
}
|
|
189
206
|
|
|
190
207
|
export function Form({ fields = [], submit = 'submit', onSubmit }) {
|
|
191
|
-
return h('form', { class: 'row-form', onsubmit: ev => { ev.preventDefault(); onSubmit && onSubmit(ev); } },
|
|
192
|
-
...fields.map(f => f.kind === 'textarea'
|
|
193
|
-
? h('textarea', { name: f.name, placeholder: f.placeholder || '', rows: f.rows || 4 })
|
|
194
|
-
: h('input', { name: f.name, type: f.type || 'text', placeholder: f.placeholder || '', value: f.value || '', required: f.required ? 'true' : null })),
|
|
208
|
+
return h('form', { class: 'row-form', onsubmit: (ev) => { ev.preventDefault(); onSubmit && onSubmit(ev); } },
|
|
209
|
+
...fields.map((f, i) => f.kind === 'textarea'
|
|
210
|
+
? h('textarea', { key: i, name: f.name, placeholder: f.placeholder || '', rows: f.rows || 4 })
|
|
211
|
+
: h('input', { key: i, name: f.name, type: f.type || 'text', placeholder: f.placeholder || '', value: f.value || '', required: f.required ? 'true' : null })),
|
|
195
212
|
h('button', { type: 'submit', class: 'btn-primary' }, submit));
|
|
196
213
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// File modals — matches upstream signatures + class names.
|
|
2
|
+
|
|
1
3
|
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
2
4
|
import { Btn } from './shell.js';
|
|
3
5
|
import { fileGlyph, fmtFileSize } from './files.js';
|
|
@@ -22,7 +24,7 @@ export function ConfirmDialog({ title = 'confirm', message, confirmLabel = 'conf
|
|
|
22
24
|
h('div', { class: 'ds-modal-actions' },
|
|
23
25
|
Btn({ onClick: onCancel, children: cancelLabel }),
|
|
24
26
|
h('button', {
|
|
25
|
-
class: destructive ? 'btn-
|
|
27
|
+
class: destructive ? 'btn-primary danger' : 'btn-primary',
|
|
26
28
|
onclick: onConfirm
|
|
27
29
|
}, confirmLabel)
|
|
28
30
|
)
|
|
@@ -52,7 +54,7 @@ export function PromptDialog({ title = 'name', value = '', placeholder = '', con
|
|
|
52
54
|
),
|
|
53
55
|
h('div', { class: 'ds-modal-actions' },
|
|
54
56
|
Btn({ onClick: onCancel, children: cancelLabel }),
|
|
55
|
-
h('button', { class: 'btn-
|
|
57
|
+
h('button', { class: 'btn-primary', onclick: () => onConfirm && onConfirm(value) }, confirmLabel)
|
|
56
58
|
)
|
|
57
59
|
]
|
|
58
60
|
});
|
package/src/components/files.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
// File primitives — matches upstream signatures.
|
|
2
|
+
|
|
1
3
|
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
2
|
-
import { Btn
|
|
4
|
+
import { Btn } from './shell.js';
|
|
3
5
|
const h = webjsx.createElement;
|
|
4
6
|
|
|
5
7
|
const FILE_TYPES = ['dir', 'image', 'video', 'audio', 'code', 'text', 'archive', 'document', 'symlink', 'other'];
|
|
@@ -49,12 +51,7 @@ export function FileGrid({ files = [], onOpen, onAction, emptyText = 'no files h
|
|
|
49
51
|
return h('div', { class: 'ds-file-grid' },
|
|
50
52
|
...files.map((f, i) => FileRow({
|
|
51
53
|
key: f.path || f.name + i,
|
|
52
|
-
name: f.name,
|
|
53
|
-
type: f.type,
|
|
54
|
-
size: f.size,
|
|
55
|
-
modified: f.modified,
|
|
56
|
-
code: f.code,
|
|
57
|
-
active: f.active,
|
|
54
|
+
name: f.name, type: f.type, size: f.size, modified: f.modified, code: f.code, active: f.active,
|
|
58
55
|
onOpen: onOpen ? () => onOpen(f) : null,
|
|
59
56
|
onAction: onAction ? (act) => onAction(act, f) : null
|
|
60
57
|
}))
|
|
@@ -93,10 +90,7 @@ export function UploadProgress({ items = [] } = {}) {
|
|
|
93
90
|
},
|
|
94
91
|
h('span', { class: 'ds-upload-name' }, it.name),
|
|
95
92
|
h('span', { class: 'ds-upload-bar' },
|
|
96
|
-
h('span', {
|
|
97
|
-
class: 'ds-upload-fill',
|
|
98
|
-
'data-pct': String(Math.max(0, Math.min(100, it.pct || 0)))
|
|
99
|
-
})
|
|
93
|
+
h('span', { class: 'ds-upload-fill', 'data-pct': String(Math.max(0, Math.min(100, it.pct || 0))) })
|
|
100
94
|
),
|
|
101
95
|
h('span', { class: 'ds-upload-pct' }, (it.error ? 'err' : (it.done ? 'ok' : (it.pct || 0) + '%')))
|
|
102
96
|
))
|
|
@@ -111,9 +105,7 @@ export function EmptyState({ text = 'nothing here', glyph = '◌' } = {}) {
|
|
|
111
105
|
}
|
|
112
106
|
|
|
113
107
|
export function BreadcrumbPath({ segments = [], onNav, root = 'root' } = {}) {
|
|
114
|
-
const parts = [
|
|
115
|
-
h('button', { key: 'root', class: 'ds-crumb-seg', onclick: () => onNav && onNav(0) }, root)
|
|
116
|
-
];
|
|
108
|
+
const parts = [h('button', { key: 'root', class: 'ds-crumb-seg', onclick: () => onNav && onNav(0) }, root)];
|
|
117
109
|
segments.forEach((seg, i) => {
|
|
118
110
|
parts.push(h('span', { key: 'sep' + i, class: 'ds-crumb-sep' }, '›'));
|
|
119
111
|
parts.push(h('button', {
|