anentrypoint-design 0.0.121 → 0.0.124

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.
Files changed (202) hide show
  1. package/README.md +253 -253
  2. package/app-shell.css +931 -594
  3. package/colors_and_type.css +226 -226
  4. package/community.css +817 -1222
  5. package/dist/247420.css +2202 -2084
  6. package/dist/247420.js +13 -13
  7. package/package.json +80 -80
  8. package/src/bootstrap.js +25 -25
  9. package/src/components/chat.js +199 -199
  10. package/src/components/community.js +190 -208
  11. package/src/components/content.js +269 -269
  12. package/src/components/editor-primitives.js +100 -0
  13. package/src/components/files-modals.js +107 -107
  14. package/src/components/files.js +118 -118
  15. package/src/components/freddie/helpers.js +50 -50
  16. package/src/components/freddie.js +33 -33
  17. package/src/components/shell.js +117 -117
  18. package/src/components/theme-toggle.js +70 -70
  19. package/src/components.js +59 -57
  20. package/src/debug.js +30 -30
  21. package/src/deck-stage.js +21 -21
  22. package/src/highlight.js +65 -32
  23. package/src/index.js +86 -86
  24. package/src/kits/os/about-app.js +52 -52
  25. package/src/kits/os/app-panes.css +152 -152
  26. package/src/kits/os/browser-app.js +58 -58
  27. package/src/kits/os/files-app.js +44 -44
  28. package/src/kits/os/freddie/helpers.js +59 -59
  29. package/src/kits/os/freddie/pages-chat.js +143 -143
  30. package/src/kits/os/freddie/pages-core.js +101 -101
  31. package/src/kits/os/freddie/pages-os.js +51 -51
  32. package/src/kits/os/freddie/pages-tools.js +183 -183
  33. package/src/kits/os/freddie/routes.js +24 -24
  34. package/src/kits/os/freddie-dashboard.css +51 -51
  35. package/src/kits/os/freddie-dashboard.js +101 -101
  36. package/src/kits/os/icons.js +17 -17
  37. package/src/kits/os/index.js +17 -17
  38. package/src/kits/os/launcher.css +61 -61
  39. package/src/kits/os/launcher.js +79 -79
  40. package/src/kits/os/monitor-app.js +34 -34
  41. package/src/kits/os/shell.js +214 -214
  42. package/src/kits/os/terminal-app.js +45 -45
  43. package/src/kits/os/theme.css +450 -450
  44. package/src/kits/os/validate.css +19 -19
  45. package/src/kits/os/validator-app.js +55 -55
  46. package/src/kits/os/wm.css +115 -115
  47. package/src/kits/os/wm.js +111 -111
  48. package/src/markdown.js +39 -39
  49. package/src/motion.js +35 -35
  50. package/src/page-html.js +196 -196
  51. package/src/styles.js +25 -25
  52. package/src/theme.js +99 -99
  53. package/src/web-components/ds-chat.js +116 -116
  54. package/dist/.nojekyll +0 -0
  55. package/dist/app-shell.css +0 -594
  56. package/dist/colors_and_type.css +0 -197
  57. package/dist/favicon.svg +0 -1
  58. package/dist/index.html +0 -308
  59. package/dist/preview/buttons.html +0 -28
  60. package/dist/preview/colors-core.html +0 -45
  61. package/dist/preview/colors-lore.html +0 -28
  62. package/dist/preview/colors-semantic.html +0 -34
  63. package/dist/preview/dateline.html +0 -19
  64. package/dist/preview/dropzone.html +0 -30
  65. package/dist/preview/file-grid.html +0 -19
  66. package/dist/preview/file-row.html +0 -20
  67. package/dist/preview/file-toolbar.html +0 -40
  68. package/dist/preview/file-viewer.html +0 -31
  69. package/dist/preview/header.html +0 -24
  70. package/dist/preview/icons-unicode.html +0 -26
  71. package/dist/preview/index-row.html +0 -25
  72. package/dist/preview/inputs.html +0 -22
  73. package/dist/preview/manifesto.html +0 -52
  74. package/dist/preview/motion-default.js +0 -106
  75. package/dist/preview/rules.html +0 -16
  76. package/dist/preview/spacing.html +0 -18
  77. package/dist/preview/stamps-lore.html +0 -20
  78. package/dist/preview/stamps.html +0 -14
  79. package/dist/preview/theme-ink.html +0 -15
  80. package/dist/preview/type-display.html +0 -16
  81. package/dist/preview/type-mono.html +0 -15
  82. package/dist/preview/type-prose.html +0 -11
  83. package/dist/preview/type-scale.html +0 -20
  84. package/dist/preview/wordmarks.html +0 -28
  85. package/dist/robots.txt +0 -8
  86. package/dist/site/content/globals/navigation.yaml +0 -5
  87. package/dist/site/content/globals/site.yaml +0 -16
  88. package/dist/site/content/pages/freddie.yaml +0 -88
  89. package/dist/site/content/pages/home.yaml +0 -190
  90. package/dist/site/theme.mjs +0 -368
  91. package/dist/sitemap.xml +0 -31
  92. package/dist/slides/deck-stage-overlay.js +0 -63
  93. package/dist/slides/deck-stage-state.js +0 -81
  94. package/dist/slides/deck-stage-style.js +0 -117
  95. package/dist/slides/deck-stage.js +0 -159
  96. package/dist/slides/index.html +0 -276
  97. package/dist/src/bootstrap.js +0 -25
  98. package/dist/src/components/chat.js +0 -199
  99. package/dist/src/components/community.js +0 -167
  100. package/dist/src/components/content.js +0 -213
  101. package/dist/src/components/files-modals.js +0 -107
  102. package/dist/src/components/files.js +0 -118
  103. package/dist/src/components/freddie/helpers.js +0 -50
  104. package/dist/src/components/freddie.js +0 -33
  105. package/dist/src/components/shell.js +0 -117
  106. package/dist/src/components/theme-toggle.js +0 -70
  107. package/dist/src/components.js +0 -52
  108. package/dist/src/debug.js +0 -30
  109. package/dist/src/deck-stage.js +0 -21
  110. package/dist/src/highlight.js +0 -32
  111. package/dist/src/index.js +0 -86
  112. package/dist/src/kits/os/about-app.js +0 -52
  113. package/dist/src/kits/os/app-panes.css +0 -152
  114. package/dist/src/kits/os/browser-app.js +0 -58
  115. package/dist/src/kits/os/files-app.js +0 -44
  116. package/dist/src/kits/os/freddie/helpers.js +0 -59
  117. package/dist/src/kits/os/freddie/pages-chat.js +0 -143
  118. package/dist/src/kits/os/freddie/pages-core.js +0 -101
  119. package/dist/src/kits/os/freddie/pages-os.js +0 -51
  120. package/dist/src/kits/os/freddie/pages-tools.js +0 -183
  121. package/dist/src/kits/os/freddie/routes.js +0 -24
  122. package/dist/src/kits/os/freddie-dashboard.css +0 -51
  123. package/dist/src/kits/os/freddie-dashboard.js +0 -101
  124. package/dist/src/kits/os/icons.js +0 -17
  125. package/dist/src/kits/os/index.js +0 -5
  126. package/dist/src/kits/os/launcher.css +0 -61
  127. package/dist/src/kits/os/launcher.js +0 -79
  128. package/dist/src/kits/os/monitor-app.js +0 -34
  129. package/dist/src/kits/os/shell.js +0 -214
  130. package/dist/src/kits/os/terminal-app.js +0 -45
  131. package/dist/src/kits/os/theme.css +0 -412
  132. package/dist/src/kits/os/validate.css +0 -19
  133. package/dist/src/kits/os/validator-app.js +0 -55
  134. package/dist/src/kits/os/wm.css +0 -115
  135. package/dist/src/kits/os/wm.js +0 -111
  136. package/dist/src/markdown.js +0 -39
  137. package/dist/src/motion.js +0 -35
  138. package/dist/src/page-html.js +0 -196
  139. package/dist/src/styles.js +0 -25
  140. package/dist/src/theme.js +0 -99
  141. package/dist/src/web-components/ds-chat.js +0 -45
  142. package/dist/ui_kits/aicat/README.md +0 -7
  143. package/dist/ui_kits/aicat/app.js +0 -156
  144. package/dist/ui_kits/aicat/index.html +0 -26
  145. package/dist/ui_kits/aicat/sample-square.png +0 -0
  146. package/dist/ui_kits/aicat/sample-svg.svg +0 -1
  147. package/dist/ui_kits/aicat/sample.pdf +0 -32
  148. package/dist/ui_kits/blog/README.md +0 -3
  149. package/dist/ui_kits/blog/index.html +0 -90
  150. package/dist/ui_kits/chat/README.md +0 -5
  151. package/dist/ui_kits/chat/app.js +0 -110
  152. package/dist/ui_kits/chat/index.html +0 -26
  153. package/dist/ui_kits/chat/sample-square.png +0 -0
  154. package/dist/ui_kits/chat/sample-svg.svg +0 -1
  155. package/dist/ui_kits/chat/sample.pdf +0 -32
  156. package/dist/ui_kits/community/app.js +0 -134
  157. package/dist/ui_kits/community/index.html +0 -24
  158. package/dist/ui_kits/dashboard/app.js +0 -92
  159. package/dist/ui_kits/dashboard/index.html +0 -26
  160. package/dist/ui_kits/docs/README.md +0 -3
  161. package/dist/ui_kits/docs/index.html +0 -123
  162. package/dist/ui_kits/error_404/app.js +0 -56
  163. package/dist/ui_kits/error_404/index.html +0 -26
  164. package/dist/ui_kits/file_browser/README.md +0 -48
  165. package/dist/ui_kits/file_browser/app.js +0 -231
  166. package/dist/ui_kits/file_browser/index.html +0 -33
  167. package/dist/ui_kits/gallery/app.js +0 -121
  168. package/dist/ui_kits/gallery/index.html +0 -26
  169. package/dist/ui_kits/homepage/README.md +0 -7
  170. package/dist/ui_kits/homepage/app.js +0 -167
  171. package/dist/ui_kits/homepage/index.html +0 -46
  172. package/dist/ui_kits/project_page/README.md +0 -3
  173. package/dist/ui_kits/project_page/app.js +0 -154
  174. package/dist/ui_kits/project_page/index.html +0 -45
  175. package/dist/ui_kits/search/app.js +0 -107
  176. package/dist/ui_kits/search/index.html +0 -26
  177. package/dist/ui_kits/settings/app.js +0 -133
  178. package/dist/ui_kits/settings/index.html +0 -26
  179. package/dist/ui_kits/signin/app.js +0 -115
  180. package/dist/ui_kits/signin/index.html +0 -26
  181. package/dist/ui_kits/slide_deck/app.js +0 -174
  182. package/dist/ui_kits/slide_deck/index.html +0 -26
  183. package/dist/ui_kits/system_primer/app.js +0 -152
  184. package/dist/ui_kits/system_primer/index.html +0 -26
  185. package/dist/ui_kits/terminal/app.js +0 -150
  186. package/dist/ui_kits/terminal/index.html +0 -26
  187. package/dist/vendor/webjsx/applyDiff.js +0 -182
  188. package/dist/vendor/webjsx/attributes.js +0 -154
  189. package/dist/vendor/webjsx/constants.js +0 -4
  190. package/dist/vendor/webjsx/createDOMElement.js +0 -52
  191. package/dist/vendor/webjsx/createElement.js +0 -75
  192. package/dist/vendor/webjsx/elementTags.js +0 -115
  193. package/dist/vendor/webjsx/factory.js +0 -6
  194. package/dist/vendor/webjsx/index.js +0 -6
  195. package/dist/vendor/webjsx/jsx-dev-runtime.js +0 -2
  196. package/dist/vendor/webjsx/jsx-runtime.js +0 -30
  197. package/dist/vendor/webjsx/jsx.js +0 -2
  198. package/dist/vendor/webjsx/package.json +0 -39
  199. package/dist/vendor/webjsx/renderSuspension.js +0 -25
  200. package/dist/vendor/webjsx/types.js +0 -5
  201. package/dist/vendor/webjsx/utils.js +0 -84
  202. package/src/components/overlays.js +0 -151
@@ -1,269 +1,269 @@
1
- // Content blocks: Panel, Row, RowLink, Section, Hero, Install, Receipt,
2
- // Changelog, WorksList, WritingList, Manifesto, Kpi, Table, HomeView,
3
- // ProjectView, Form. Pure factories.
4
-
5
- import * as webjsx from '../../vendor/webjsx/index.js';
6
- import { Btn, Heading, Lede, Dot } from './shell.js';
7
- const h = webjsx.createElement;
8
-
9
- export function Panel({ title, count, right, style = '', children, kind }) {
10
- const cls = 'panel' + (kind ? ' panel-' + kind : '');
11
- return h('div', { class: cls, style },
12
- title != null ? h('div', { class: 'panel-head' },
13
- h('span', {}, title),
14
- right != null ? right : (count != null ? h('span', {}, String(count)) : null)
15
- ) : null,
16
- h('div', { class: 'panel-body' }, ...(Array.isArray(children) ? children : [children]))
17
- );
18
- }
19
-
20
- export function Row({ code, title, sub, meta, active, onClick, key, style, href, kind, cols, leading, trailing, target }) {
21
- const isLink = kind === 'link' || (href != null && !onClick);
22
- const cls = 'row' + (active ? ' active' : '') + (cols ? ' row-grid' : '');
23
- const props = { key, class: cls, style: cols ? `${style ? style + ';' : ''}grid-template-columns:${cols}` : style };
24
- if (isLink) { props.href = href || '#'; if (target) props.target = target; }
25
- else if (onClick) { props.onclick = onClick; }
26
- return h(isLink ? 'a' : 'div', props,
27
- leading != null ? leading : (code != null ? h('span', { class: 'code' }, code) : null),
28
- h('span', { class: 'title' }, title, sub ? h('span', { class: 'sub' }, sub) : null),
29
- trailing != null ? trailing : (meta != null ? h('span', { class: 'meta' }, meta) : null));
30
- }
31
-
32
- export function RowLink({ code, title, sub, meta, href = '#', key, target }) {
33
- return Row({ code, title, sub, meta, href, kind: 'link', key, target });
34
- }
35
-
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 }) {
45
- return h('div', { class: 'ds-hero' },
46
- eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
47
- h('h1', { class: 'ds-hero-title' }, title),
48
- body ? h('p', { class: 'ds-hero-body' },
49
- body,
50
- accent ? h('span', { class: 'ds-hero-accent' }, ' ' + accent) : null
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,
53
- badge ? Panel({ title: badge, count: badgeCount, kind: 'inline', children: [] }) : null
54
- );
55
- }
56
-
57
- export function Install({ cmd, copied, onCopy }) {
58
- return h('div', { class: 'cli' },
59
- h('span', { class: 'prompt' }, '$'),
60
- h('span', { class: 'cmd' }, cmd),
61
- h('span', { class: 'copy', onclick: () => onCopy && onCopy(cmd) }, copied ? 'copied' : 'copy')
62
- );
63
- }
64
-
65
- export function Receipt({ rows = [] }) {
66
- return h('table', { class: 'kv' },
67
- h('tbody', {}, ...rows.map(([k, v], i) =>
68
- h('tr', { key: i }, h('td', {}, k), h('td', {}, v))
69
- ))
70
- );
71
- }
72
-
73
- export function Changelog({ entries = [] }) {
74
- return Panel({
75
- kind: 'wide',
76
- children: entries.map((e, i) =>
77
- h('div', { key: i, class: 'row ds-changelog-row' },
78
- h('span', { class: 'code' }, e.date),
79
- h('span', { class: 'ds-changelog-ver' }, e.ver),
80
- h('span', { class: 'title' }, e.msg)
81
- )
82
- )
83
- });
84
- }
85
-
86
- export function WorksList({ works = [], openedIndex = -1, onToggle }) {
87
- return Panel({
88
- children: works.map((w, i) => {
89
- const isOpen = openedIndex === i;
90
- return h('div', { key: i },
91
- Row({
92
- code: w.code,
93
- title: w.title, sub: w.sub,
94
- meta: w.meta + ' ' + (isOpen ? '−' : '+'),
95
- active: isOpen,
96
- onClick: () => onToggle && onToggle(isOpen ? -1 : i)
97
- }),
98
- isOpen ? h('div', { class: 'work-detail', 'data-work-index': String(i) },
99
- h('div', { class: 'ds-prose' },
100
- h('p', { class: 'ds-work-body' }, w.body)
101
- ),
102
- h('div', { class: 'ds-work-actions' },
103
- Btn({ primary: true, href: w.href || '#', children: 'open ↗' }),
104
- Btn({ href: w.source || '#', children: 'source' })
105
- )
106
- ) : null
107
- );
108
- })
109
- });
110
- }
111
-
112
- export function WritingList({ posts = [] }) {
113
- return Panel({
114
- children: posts.map((p, i) =>
115
- RowLink({ key: i, code: p.date, title: p.title, meta: p.tag, href: p.href || '#' })
116
- )
117
- });
118
- }
119
-
120
- export function Manifesto({ paragraphs = [], maxWidth }) {
121
- return h('div', {
122
- class: 'ds-prose ds-manifesto',
123
- 'data-max-width': maxWidth ? String(maxWidth) : null
124
- },
125
- ...paragraphs.map((p, i) => h('p', {
126
- key: i,
127
- class: 'ds-manifesto-para' + (p.dim ? ' dim' : '')
128
- }, p.text || p))
129
- );
130
- }
131
-
132
- export function Kpi({ items = [] }) {
133
- return h('div', { class: 'kpi' }, ...items.map(([n, l], i) =>
134
- h('div', { key: i, class: 'kpi-card' },
135
- h('div', { class: 'num' }, String(n)),
136
- h('div', { class: 'lbl' }, l))));
137
- }
138
-
139
- export function Table({ headers = [], rows = [], onRowClick, emptyText = 'nothing here yet' }) {
140
- if (!rows || rows.length === 0) return h('div', { class: 'empty' }, emptyText);
141
- return h('table', {},
142
- h('thead', {}, h('tr', {}, ...headers.map((hd, i) => h('th', { key: i }, hd)))),
143
- h('tbody', {}, ...rows.map((row, i) => h('tr', {
144
- key: i,
145
- class: onRowClick ? 'clickable' : '',
146
- onclick: onRowClick ? () => onRowClick(i) : null
147
- }, ...row.map((c, j) => h('td', { key: j }, c == null ? '' : (typeof c === 'object' ? c : String(c))))))));
148
- }
149
-
150
- export function HomeView({ state = {}, onNav, onToggleWork, works = [], posts = [], manifesto = [], currentlyShipping } = {}) {
151
- return [
152
- Hero({
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.'
157
- }),
158
- currentlyShipping ? Section({
159
- eyebrow: 'currently shipping',
160
- children: Panel({
161
- kind: 'wide',
162
- children: currentlyShipping.map((row, i) =>
163
- Row({
164
- key: i,
165
- code: Dot({ tone: row.live ? 'live' : 'idle' }),
166
- title: row.title, sub: row.sub, meta: row.meta
167
- })
168
- )
169
- })
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 } = {}) {
187
- return [
188
- h('div', { class: 'ds-prose' },
189
- Heading({ level: 1, children: project.name }),
190
- Lede({ children: project.tagline })
191
- ),
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();
205
- }
206
-
207
- export function PageHeader({ title, lede, eyebrow, right }) {
208
- return h('section', { class: 'ds-section' },
209
- eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
210
- title != null ? h('h1', {}, title) : null,
211
- lede != null ? h('p', { class: 'lede' }, lede) : null,
212
- right != null ? h('div', { class: 'ds-page-header-right' }, ...(Array.isArray(right) ? right : [right])) : null
213
- );
214
- }
215
-
216
- export function SearchInput({ value = '', placeholder = 'search…', onInput, onSubmit, name = 'q', key }) {
217
- return h('input', {
218
- key,
219
- type: 'search',
220
- name,
221
- class: 'ds-search-input',
222
- placeholder,
223
- value,
224
- oninput: onInput ? (e) => onInput(e.target.value, e) : null,
225
- onkeydown: onSubmit ? (e) => { if (e.key === 'Enter') onSubmit(e.target.value, e); } : null
226
- });
227
- }
228
-
229
- export function TextField({ label, value = '', type = 'text', placeholder = '', onInput, onChange, name, key, hint, multiline, rows = 4 }) {
230
- const input = multiline
231
- ? h('textarea', {
232
- key: 'i', name, rows, placeholder, value,
233
- oninput: onInput ? (e) => onInput(e.target.value, e) : null,
234
- onchange: onChange ? (e) => onChange(e.target.value, e) : null
235
- })
236
- : h('input', {
237
- key: 'i', type, name, placeholder, value,
238
- oninput: onInput ? (e) => onInput(e.target.value, e) : null,
239
- onchange: onChange ? (e) => onChange(e.target.value, e) : null
240
- });
241
- return h('label', { key, class: 'ds-field' },
242
- label != null ? h('span', { key: 'l', class: 'ds-field-label' }, label) : null,
243
- input,
244
- hint != null ? h('span', { key: 'h', class: 'lede ds-field-hint' }, hint) : null
245
- );
246
- }
247
-
248
- export function EventList({ items = [], emptyText = 'no events', rankPad = 3 }) {
249
- if (!items || !items.length) return h('p', { class: 'lede' }, emptyText);
250
- return h('section', { class: 'ds-section ds-event-list' },
251
- ...items.map((it, i) => Row({
252
- key: it.key || ('ev' + i),
253
- code: String(i + 1).padStart(rankPad, '0'),
254
- title: it.title || '(empty)',
255
- sub: it.sub || '',
256
- active: it.active,
257
- onClick: it.onClick,
258
- kind: it.kind
259
- }))
260
- );
261
- }
262
-
263
- export function Form({ fields = [], submit = 'submit', onSubmit }) {
264
- return h('form', { class: 'row-form', onsubmit: (ev) => { ev.preventDefault(); onSubmit && onSubmit(ev); } },
265
- ...fields.map((f, i) => f.kind === 'textarea'
266
- ? h('textarea', { key: i, name: f.name, placeholder: f.placeholder || '', rows: f.rows || 4 })
267
- : h('input', { key: i, name: f.name, type: f.type || 'text', placeholder: f.placeholder || '', value: f.value || '', required: f.required ? 'true' : null })),
268
- h('button', { type: 'submit', class: 'btn-primary' }, submit));
269
- }
1
+ // Content blocks: Panel, Row, RowLink, Section, Hero, Install, Receipt,
2
+ // Changelog, WorksList, WritingList, Manifesto, Kpi, Table, HomeView,
3
+ // ProjectView, Form. Pure factories.
4
+
5
+ import * as webjsx from '../../vendor/webjsx/index.js';
6
+ import { Btn, Heading, Lede, Dot } from './shell.js';
7
+ const h = webjsx.createElement;
8
+
9
+ export function Panel({ title, count, right, style = '', children, kind }) {
10
+ const cls = 'panel' + (kind ? ' panel-' + kind : '');
11
+ return h('div', { class: cls, style },
12
+ title != null ? h('div', { class: 'panel-head' },
13
+ h('span', {}, title),
14
+ right != null ? right : (count != null ? h('span', {}, String(count)) : null)
15
+ ) : null,
16
+ h('div', { class: 'panel-body' }, ...(Array.isArray(children) ? children : [children]))
17
+ );
18
+ }
19
+
20
+ export function Row({ code, title, sub, meta, active, onClick, key, style, href, kind, cols, leading, trailing, target }) {
21
+ const isLink = kind === 'link' || (href != null && !onClick);
22
+ const cls = 'row' + (active ? ' active' : '') + (cols ? ' row-grid' : '');
23
+ const props = { key, class: cls, style: cols ? `${style ? style + ';' : ''}grid-template-columns:${cols}` : style };
24
+ if (isLink) { props.href = href || '#'; if (target) props.target = target; }
25
+ else if (onClick) { props.onclick = onClick; }
26
+ return h(isLink ? 'a' : 'div', props,
27
+ leading != null ? leading : (code != null ? h('span', { class: 'code' }, code) : null),
28
+ h('span', { class: 'title' }, title, sub ? h('span', { class: 'sub' }, sub) : null),
29
+ trailing != null ? trailing : (meta != null ? h('span', { class: 'meta' }, meta) : null));
30
+ }
31
+
32
+ export function RowLink({ code, title, sub, meta, href = '#', key, target }) {
33
+ return Row({ code, title, sub, meta, href, kind: 'link', key, target });
34
+ }
35
+
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 }) {
45
+ return h('div', { class: 'ds-hero' },
46
+ eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
47
+ h('h1', { class: 'ds-hero-title' }, title),
48
+ body ? h('p', { class: 'ds-hero-body' },
49
+ body,
50
+ accent ? h('span', { class: 'ds-hero-accent' }, ' ' + accent) : null
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,
53
+ badge ? Panel({ title: badge, count: badgeCount, kind: 'inline', children: [] }) : null
54
+ );
55
+ }
56
+
57
+ export function Install({ cmd, copied, onCopy }) {
58
+ return h('div', { class: 'cli' },
59
+ h('span', { class: 'prompt' }, '$'),
60
+ h('span', { class: 'cmd' }, cmd),
61
+ h('span', { class: 'copy', onclick: () => onCopy && onCopy(cmd) }, copied ? 'copied' : 'copy')
62
+ );
63
+ }
64
+
65
+ export function Receipt({ rows = [] }) {
66
+ return h('table', { class: 'kv' },
67
+ h('tbody', {}, ...rows.map(([k, v], i) =>
68
+ h('tr', { key: i }, h('td', {}, k), h('td', {}, v))
69
+ ))
70
+ );
71
+ }
72
+
73
+ export function Changelog({ entries = [] }) {
74
+ return Panel({
75
+ kind: 'wide',
76
+ children: entries.map((e, i) =>
77
+ h('div', { key: i, class: 'row ds-changelog-row' },
78
+ h('span', { class: 'code' }, e.date),
79
+ h('span', { class: 'ds-changelog-ver' }, e.ver),
80
+ h('span', { class: 'title' }, e.msg)
81
+ )
82
+ )
83
+ });
84
+ }
85
+
86
+ export function WorksList({ works = [], openedIndex = -1, onToggle }) {
87
+ return Panel({
88
+ children: works.map((w, i) => {
89
+ const isOpen = openedIndex === i;
90
+ return h('div', { key: i },
91
+ Row({
92
+ code: w.code,
93
+ title: w.title, sub: w.sub,
94
+ meta: w.meta + ' ' + (isOpen ? '−' : '+'),
95
+ active: isOpen,
96
+ onClick: () => onToggle && onToggle(isOpen ? -1 : i)
97
+ }),
98
+ isOpen ? h('div', { class: 'work-detail', 'data-work-index': String(i) },
99
+ h('div', { class: 'ds-prose' },
100
+ h('p', { class: 'ds-work-body' }, w.body)
101
+ ),
102
+ h('div', { class: 'ds-work-actions' },
103
+ Btn({ primary: true, href: w.href || '#', children: 'open ↗' }),
104
+ Btn({ href: w.source || '#', children: 'source' })
105
+ )
106
+ ) : null
107
+ );
108
+ })
109
+ });
110
+ }
111
+
112
+ export function WritingList({ posts = [] }) {
113
+ return Panel({
114
+ children: posts.map((p, i) =>
115
+ RowLink({ key: i, code: p.date, title: p.title, meta: p.tag, href: p.href || '#' })
116
+ )
117
+ });
118
+ }
119
+
120
+ export function Manifesto({ paragraphs = [], maxWidth }) {
121
+ return h('div', {
122
+ class: 'ds-prose ds-manifesto',
123
+ 'data-max-width': maxWidth ? String(maxWidth) : null
124
+ },
125
+ ...paragraphs.map((p, i) => h('p', {
126
+ key: i,
127
+ class: 'ds-manifesto-para' + (p.dim ? ' dim' : '')
128
+ }, p.text || p))
129
+ );
130
+ }
131
+
132
+ export function Kpi({ items = [] }) {
133
+ return h('div', { class: 'kpi' }, ...items.map(([n, l], i) =>
134
+ h('div', { key: i, class: 'kpi-card' },
135
+ h('div', { class: 'num' }, String(n)),
136
+ h('div', { class: 'lbl' }, l))));
137
+ }
138
+
139
+ export function Table({ headers = [], rows = [], onRowClick, emptyText = 'nothing here yet' }) {
140
+ if (!rows || rows.length === 0) return h('div', { class: 'empty' }, emptyText);
141
+ return h('table', {},
142
+ h('thead', {}, h('tr', {}, ...headers.map((hd, i) => h('th', { key: i }, hd)))),
143
+ h('tbody', {}, ...rows.map((row, i) => h('tr', {
144
+ key: i,
145
+ class: onRowClick ? 'clickable' : '',
146
+ onclick: onRowClick ? () => onRowClick(i) : null
147
+ }, ...row.map((c, j) => h('td', { key: j }, c == null ? '' : (typeof c === 'object' ? c : String(c))))))));
148
+ }
149
+
150
+ export function HomeView({ state = {}, onNav, onToggleWork, works = [], posts = [], manifesto = [], currentlyShipping } = {}) {
151
+ return [
152
+ Hero({
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.'
157
+ }),
158
+ currentlyShipping ? Section({
159
+ eyebrow: 'currently shipping',
160
+ children: Panel({
161
+ kind: 'wide',
162
+ children: currentlyShipping.map((row, i) =>
163
+ Row({
164
+ key: i,
165
+ code: Dot({ tone: row.live ? 'live' : 'idle' }),
166
+ title: row.title, sub: row.sub, meta: row.meta
167
+ })
168
+ )
169
+ })
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 } = {}) {
187
+ return [
188
+ h('div', { class: 'ds-prose' },
189
+ Heading({ level: 1, children: project.name }),
190
+ Lede({ children: project.tagline })
191
+ ),
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();
205
+ }
206
+
207
+ export function PageHeader({ title, lede, eyebrow, right }) {
208
+ return h('section', { class: 'ds-section' },
209
+ eyebrow ? h('span', { class: 'eyebrow' }, eyebrow) : null,
210
+ title != null ? h('h1', {}, title) : null,
211
+ lede != null ? h('p', { class: 'lede' }, lede) : null,
212
+ right != null ? h('div', { class: 'ds-page-header-right' }, ...(Array.isArray(right) ? right : [right])) : null
213
+ );
214
+ }
215
+
216
+ export function SearchInput({ value = '', placeholder = 'search…', onInput, onSubmit, name = 'q', key }) {
217
+ return h('input', {
218
+ key,
219
+ type: 'search',
220
+ name,
221
+ class: 'ds-search-input',
222
+ placeholder,
223
+ value,
224
+ oninput: onInput ? (e) => onInput(e.target.value, e) : null,
225
+ onkeydown: onSubmit ? (e) => { if (e.key === 'Enter') onSubmit(e.target.value, e); } : null
226
+ });
227
+ }
228
+
229
+ export function TextField({ label, value = '', type = 'text', placeholder = '', onInput, onChange, name, key, hint, multiline, rows = 4 }) {
230
+ const input = multiline
231
+ ? h('textarea', {
232
+ key: 'i', name, rows, placeholder, value,
233
+ oninput: onInput ? (e) => onInput(e.target.value, e) : null,
234
+ onchange: onChange ? (e) => onChange(e.target.value, e) : null
235
+ })
236
+ : h('input', {
237
+ key: 'i', type, name, placeholder, value,
238
+ oninput: onInput ? (e) => onInput(e.target.value, e) : null,
239
+ onchange: onChange ? (e) => onChange(e.target.value, e) : null
240
+ });
241
+ return h('label', { key, class: 'ds-field' },
242
+ label != null ? h('span', { key: 'l', class: 'ds-field-label' }, label) : null,
243
+ input,
244
+ hint != null ? h('span', { key: 'h', class: 'lede ds-field-hint' }, hint) : null
245
+ );
246
+ }
247
+
248
+ export function EventList({ items = [], emptyText = 'no events', rankPad = 3 }) {
249
+ if (!items || !items.length) return h('p', { class: 'lede' }, emptyText);
250
+ return h('section', { class: 'ds-section ds-event-list' },
251
+ ...items.map((it, i) => Row({
252
+ key: it.key || ('ev' + i),
253
+ code: String(i + 1).padStart(rankPad, '0'),
254
+ title: it.title || '(empty)',
255
+ sub: it.sub || '',
256
+ active: it.active,
257
+ onClick: it.onClick,
258
+ kind: it.kind
259
+ }))
260
+ );
261
+ }
262
+
263
+ export function Form({ fields = [], submit = 'submit', onSubmit }) {
264
+ return h('form', { class: 'row-form', onsubmit: (ev) => { ev.preventDefault(); onSubmit && onSubmit(ev); } },
265
+ ...fields.map((f, i) => f.kind === 'textarea'
266
+ ? h('textarea', { key: i, name: f.name, placeholder: f.placeholder || '', rows: f.rows || 4 })
267
+ : h('input', { key: i, name: f.name, type: f.type || 'text', placeholder: f.placeholder || '', value: f.value || '', required: f.required ? 'true' : null })),
268
+ h('button', { type: 'submit', class: 'btn-primary' }, submit));
269
+ }
@@ -0,0 +1,100 @@
1
+ // Editor primitives — generic chrome for in-engine editors, inspectors,
2
+ // IDEs, debug HUDs. Pure factories, h-based, theme-token driven. All
3
+ // visuals route through CSS classes defined in editor-primitives.css;
4
+ // no hex/rgba literals appear in this file. Theme switching happens
5
+ // via the kit's data-theme attribute on the .ds-247420 scope root.
6
+
7
+ import * as webjsx from '../../vendor/webjsx/index.js';
8
+ const h = webjsx.createElement;
9
+
10
+ function kids(c) { return c == null ? [] : (Array.isArray(c) ? c : [c]); }
11
+
12
+ export function Toolbar({ leading = [], trailing = [], dense = false, children } = {}) {
13
+ const cls = 'ds-ep-toolbar' + (dense ? ' dense' : '');
14
+ return h('div', { class: cls, role: 'toolbar' },
15
+ h('div', { class: 'ds-ep-toolbar-leading' }, ...kids(leading)),
16
+ children != null ? h('div', { class: 'ds-ep-toolbar-center' }, ...kids(children)) : null,
17
+ h('div', { class: 'ds-ep-toolbar-trailing' }, ...kids(trailing))
18
+ );
19
+ }
20
+
21
+ export function Tabs({ items = [], active, onChange, children } = {}) {
22
+ return h('div', { class: 'ds-ep-tabs' },
23
+ h('div', { class: 'ds-ep-tabs-head', role: 'tablist' },
24
+ ...items.map((it) => h('button', {
25
+ key: it.id,
26
+ type: 'button',
27
+ class: 'ds-ep-tab' + (it.id === active ? ' active' : ''),
28
+ role: 'tab',
29
+ 'aria-selected': it.id === active ? 'true' : 'false',
30
+ onclick: () => onChange && onChange(it.id)
31
+ }, it.label))
32
+ ),
33
+ h('div', { class: 'ds-ep-tabs-body', role: 'tabpanel' }, ...kids(children))
34
+ );
35
+ }
36
+
37
+ export function TreeView({ children } = {}) {
38
+ return h('div', { class: 'ds-ep-tree', role: 'tree' }, ...kids(children));
39
+ }
40
+
41
+ export function TreeItem({ label, glyph, tag, depth = 0, selected = false, expanded = false, onSelect, onToggle, children } = {}) {
42
+ const hasKids = children != null;
43
+ return h('div', {
44
+ class: 'ds-ep-tree-item' + (selected ? ' selected' : ''),
45
+ role: 'treeitem',
46
+ 'aria-selected': selected ? 'true' : 'false',
47
+ 'aria-expanded': hasKids ? String(!!expanded) : null
48
+ },
49
+ h('div', {
50
+ class: 'ds-ep-tree-row',
51
+ style: 'padding-left:' + (depth * 12 + 6) + 'px',
52
+ onclick: () => onSelect && onSelect()
53
+ },
54
+ h('span', {
55
+ class: 'ds-ep-tree-twist' + (expanded ? ' open' : ''),
56
+ onclick: (e) => { e.stopPropagation(); if (hasKids && onToggle) onToggle(); }
57
+ }, hasKids ? '▸' : ''),
58
+ glyph != null ? h('span', { class: 'ds-ep-tree-glyph' }, glyph) : null,
59
+ h('span', { class: 'ds-ep-tree-label' }, label),
60
+ tag != null ? h('span', { class: 'ds-ep-tree-tag' }, tag) : null
61
+ ),
62
+ hasKids && expanded ? h('div', { class: 'ds-ep-tree-children', role: 'group' }, ...kids(children)) : null
63
+ );
64
+ }
65
+
66
+ export function PropertyGrid({ children } = {}) {
67
+ return h('div', { class: 'ds-ep-propgrid', role: 'group' }, ...kids(children));
68
+ }
69
+
70
+ export function PropertyField({ label, hint, inline = false, children } = {}) {
71
+ return h('label', { class: 'ds-ep-propfield' + (inline ? ' inline' : '') },
72
+ h('span', { class: 'ds-ep-propfield-label' }, label),
73
+ h('span', { class: 'ds-ep-propfield-value' }, ...kids(children)),
74
+ hint != null ? h('span', { class: 'ds-ep-propfield-hint' }, hint) : null
75
+ );
76
+ }
77
+
78
+ export function Dock({ top, left, right, bottom, center } = {}) {
79
+ return h('div', { class: 'ds-ep-dock' },
80
+ top != null ? h('div', { class: 'ds-ep-dock-top' }, ...kids(top)) : null,
81
+ left != null ? h('div', { class: 'ds-ep-dock-left' }, ...kids(left)) : null,
82
+ h('div', { class: 'ds-ep-dock-center' }, ...kids(center)),
83
+ right != null ? h('div', { class: 'ds-ep-dock-right' }, ...kids(right)) : null,
84
+ bottom != null ? h('div', { class: 'ds-ep-dock-bottom' }, ...kids(bottom)) : null
85
+ );
86
+ }
87
+
88
+ export function IconButtonGroup({ items = [], value, onChange, dense = false } = {}) {
89
+ return h('div', { class: 'ds-ep-btngrp' + (dense ? ' dense' : ''), role: 'group' },
90
+ ...items.map((it) => h('button', {
91
+ key: it.id,
92
+ type: 'button',
93
+ class: 'ds-ep-btngrp-btn' + (it.id === value ? ' active' : ''),
94
+ title: it.title || it.label || it.id,
95
+ 'aria-pressed': it.id === value ? 'true' : 'false',
96
+ disabled: it.disabled ? 'disabled' : null,
97
+ onclick: () => { if (!it.disabled && onChange) onChange(it.id); }
98
+ }, it.glyph != null ? it.glyph : it.label))
99
+ );
100
+ }