anentrypoint-design 0.0.155 → 0.0.157

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anentrypoint-design",
3
- "version": "0.0.155",
3
+ "version": "0.0.157",
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",
@@ -5,6 +5,7 @@
5
5
  import * as webjsx from '../../vendor/webjsx/index.js';
6
6
  import { renderMarkdownCached, highlightCodeBlockCached, initializeCachesEagerly, getCacheStats } from '../markdown-cache.js';
7
7
  import { register } from '../debug.js';
8
+ import { Icon } from './shell.js';
8
9
 
9
10
  const h = webjsx.createElement;
10
11
  let _stats = { messages: 0, lastKindCounts: {} };
@@ -171,10 +172,10 @@ export function ChatComposer({ value, onInput, onSend, onAttach, onEmoji, onMenu
171
172
  if (e.key === ';' && e.ctrlKey) { e.preventDefault(); onEmoji && onEmoji(e); }
172
173
  } }),
173
174
  h('div', { class: 'chat-composer-toolbar' },
174
- onAttach ? h('button', { class: 'composer-btn', onclick: (e) => { e.preventDefault(); onAttach(e); }, 'aria-label': 'attach file', title: 'attach file' }, '📎') : null,
175
- onEmoji ? h('button', { class: 'composer-btn', onclick: (e) => { e.preventDefault(); onEmoji(e); }, 'aria-label': 'emoji picker', title: 'emoji picker (Ctrl+;)' }, '😊') : null,
176
- onMenu ? h('button', { class: 'composer-btn', onclick: (e) => { e.preventDefault(); onMenu(e); }, 'aria-label': 'composer menu', title: 'more options' }, '') : null,
177
- h('button', { class: 'send', disabled: disabled || !(value && value.trim()), onclick: send, 'aria-label': 'send message', title: 'send message (Enter)' }, '')
175
+ onAttach ? h('button', { type: 'button', class: 'composer-btn', onclick: (e) => { e.preventDefault(); onAttach(e); }, 'aria-label': 'attach file', title: 'attach file' }, Icon('paperclip')) : null,
176
+ onEmoji ? h('button', { type: 'button', class: 'composer-btn', onclick: (e) => { e.preventDefault(); onEmoji(e); }, 'aria-label': 'emoji picker', title: 'emoji picker (Ctrl+;)' }, Icon('smile')) : null,
177
+ onMenu ? h('button', { type: 'button', class: 'composer-btn', onclick: (e) => { e.preventDefault(); onMenu(e); }, 'aria-label': 'composer menu', title: 'more options' }, Icon('more-horizontal')) : null,
178
+ h('button', { type: 'button', class: 'send', disabled: disabled || !(value && value.trim()), onclick: send, 'aria-label': 'send message', title: 'send message (Enter)' }, Icon('arrow-up'))
178
179
  )
179
180
  );
180
181
  }
@@ -223,6 +224,11 @@ export function Chat({ title = 'chat', sub, messages = [], composer, header } =
223
224
  h('span', { class: 'sub', 'aria-live': 'polite' }, String(messages.length).padStart(2, '0') + ' msgs')
224
225
  ),
225
226
  h('div', { class: 'chat-thread', ref: threadRef, role: 'log', 'aria-label': 'chat messages' },
227
+ messages.length === 0
228
+ ? h('div', { key: '_empty', class: 'chat-empty', role: 'status' },
229
+ h('p', { class: 'chat-empty-title' }, 'no messages yet'),
230
+ h('p', { class: 'chat-empty-sub' }, 'start the conversation'))
231
+ : null,
226
232
  ...messages.map((m, i) => ChatMessage({ ...m, key: m.key != null ? m.key : i }))
227
233
  ),
228
234
  composer || null
@@ -274,7 +274,7 @@ export function TextField({ label, value = '', type = 'text', placeholder = '',
274
274
  label != null ? h('span', { key: 'l', class: 'ds-field-label' }, label) : null,
275
275
  input,
276
276
  maxLength != null ? h('span', { key: 'c', class: 'ds-field-count' }, String(value.length) + '/' + maxLength) : null,
277
- hint != null ? h('span', { key: 'h', class: 'lede ds-field-hint' }, hint) : null
277
+ hint != null ? h('span', { key: 'h', class: 'ds-field-hint' }, hint) : null
278
278
  );
279
279
  }
280
280
 
@@ -294,7 +294,7 @@ export function Select({ label, value = '', options = [], onChange, name, key, p
294
294
  return h('label', { key, class: 'ds-field' },
295
295
  label != null ? h('span', { key: 'l', class: 'ds-field-label' }, label) : null,
296
296
  select,
297
- hint != null ? h('span', { key: 'h', class: 'lede ds-field-hint' }, hint) : null
297
+ hint != null ? h('span', { key: 'h', class: 'ds-field-hint' }, hint) : null
298
298
  );
299
299
  }
300
300
 
@@ -15,31 +15,35 @@ export function Chip({ tone = '', children }) {
15
15
  return h('span', { class: 'chip' + (tone ? ' tone-' + tone : '') }, children);
16
16
  }
17
17
 
18
- export function Btn({ href = '#', variant = 'default', children, onClick, 'aria-label': ariaLabel, primary, ghost, danger, disabled }) {
18
+ export function Btn({ href, variant = 'default', children, onClick, 'aria-label': ariaLabel, primary, ghost, danger, disabled }) {
19
19
  // Support legacy primary/ghost props for backward compatibility, but prefer variant
20
20
  const resolvedVariant = variant !== 'default' ? variant : (primary ? 'primary' : (ghost ? 'ghost' : (danger ? 'danger' : 'default')));
21
21
  const cls = (resolvedVariant === 'primary' ? 'btn-primary' : (resolvedVariant === 'ghost' ? 'btn-ghost' : (resolvedVariant === 'danger' ? 'btn-primary danger' : 'btn')))
22
22
  + (disabled ? ' is-disabled' : '');
23
- // Anchor with role=button needs explicit Space/Enter activation for keyboard parity with <button>.
24
- // Browsers fire click on Enter for anchors with href, but Space does nothing — and href="#"
25
- // synthesizes navigation if onclick doesn't preventDefault.
26
- const onkeydown = (e) => {
27
- if (disabled) { e.preventDefault(); return; }
28
- if (e.key === ' ' || (e.key === 'Enter' && (!href || href === '#'))) {
29
- e.preventDefault();
30
- if (onClick) onClick(e);
31
- }
32
- };
33
23
  const onclick = (e) => {
34
24
  if (disabled) { e.preventDefault(); return; }
35
25
  if (onClick) onClick(e);
36
26
  };
37
- return h('a', {
38
- class: cls, href, role: 'button',
39
- tabindex: disabled ? '-1' : '0',
40
- 'aria-label': ariaLabel || (typeof children === 'string' ? children : undefined),
41
- 'aria-disabled': disabled ? 'true' : null,
42
- onclick, onkeydown
27
+ const ariaName = ariaLabel || (typeof children === 'string' ? children : undefined);
28
+
29
+ // A real navigational href renders an anchor; everything else is an action
30
+ // button and renders a native <button> (correct semantics + keyboard
31
+ // activation for free, no role=button / href="#" scroll-jump hack).
32
+ const isLink = href != null && href !== '' && href !== '#';
33
+ if (isLink) {
34
+ return h('a', {
35
+ class: cls, href,
36
+ 'aria-label': ariaName,
37
+ 'aria-disabled': disabled ? 'true' : null,
38
+ tabindex: disabled ? '-1' : null,
39
+ onclick
40
+ }, children);
41
+ }
42
+ return h('button', {
43
+ type: 'button', class: cls,
44
+ disabled: disabled ? true : null,
45
+ 'aria-label': ariaName,
46
+ onclick
43
47
  }, children);
44
48
  }
45
49
 
@@ -59,10 +63,14 @@ export function Badge({ children, variant = 'default', tone = 'neutral' }) {
59
63
  return h('span', { class: 'ds-badge ds-badge-' + variant + ' tone-' + tone }, children);
60
64
  }
61
65
 
62
- export function Glyph({ children, color, size = 'base' }) {
66
+ export function Glyph({ children, color, size = 'base', label } = {}) {
63
67
  const fontSize = size === 'sm' ? '11px' : (size === 'lg' ? '16px' : '13px');
64
68
  const style = `font-size:${fontSize}` + (color ? `;color:${color}` : '');
65
- return h('span', { class: 'glyph', style }, children);
69
+ // Decorative by default (screen readers skip the glyph char). Pass `label`
70
+ // to expose an accessible name instead.
71
+ return h('span', label
72
+ ? { class: 'glyph', style, role: 'img', 'aria-label': label }
73
+ : { class: 'glyph', style, 'aria-hidden': 'true' }, children);
66
74
  }
67
75
 
68
76
  // Monochrome inline-SVG icons (stroke=currentColor) so chrome reads as one
@@ -77,7 +85,12 @@ const ICON_PATHS = {
77
85
  phone: '<path d="M5 4h3l2 5-2 1a11 11 0 0 0 5 5l1-2 5 2v3a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z"/>',
78
86
  members: '<circle cx="9" cy="8" r="3"/><path d="M3 20a6 6 0 0 1 12 0M16 6a3 3 0 0 1 0 6M21 20a6 6 0 0 0-4-5.7"/>',
79
87
  menu: '<path d="M4 6h16M4 12h16M4 18h16"/>',
80
- settings: '<circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M2 12h3M19 12h3M4.9 19.1 7 17M17 7l2.1-2.1"/>'
88
+ settings: '<circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M2 12h3M19 12h3M4.9 19.1 7 17M17 7l2.1-2.1"/>',
89
+ paperclip: '<path d="M21 11.5 12.5 20a5 5 0 0 1-7-7l8-8a3.5 3.5 0 0 1 5 5l-8 8a2 2 0 0 1-3-3l7.5-7.5"/>',
90
+ smile: '<circle cx="12" cy="12" r="9"/><path d="M8 14a4 4 0 0 0 8 0"/><path d="M9 9h.01M15 9h.01"/>',
91
+ 'more-horizontal': '<circle cx="5" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/>',
92
+ 'arrow-up': '<path d="M12 19V5M5 12l7-7 7 7"/>',
93
+ send: '<path d="M22 2 11 13M22 2l-7 20-4-9-9-4z"/>'
81
94
  };
82
95
  export function Icon(name, { size = 16 } = {}) {
83
96
  const inner = ICON_PATHS[name];
@@ -1,8 +1,8 @@
1
- @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
2
2
 
3
3
  :root {
4
- --ff-ui: 'Space Grotesk', system-ui, sans-serif;
5
- --ff-display: 'Space Grotesk', system-ui, sans-serif;
4
+ --ff-ui: 'Inter', system-ui, sans-serif;
5
+ --ff-display: 'Inter', system-ui, sans-serif;
6
6
  --ff-mono: 'JetBrains Mono', ui-monospace, monospace;
7
7
  --os-accent: var(--panel-accent, #3F8A4A);
8
8
  --os-accent-2: var(--panel-accent-2, #2B6B36);
@@ -23,8 +23,8 @@
23
23
  --os-bar-h-mobile: 52px;
24
24
  --os-rail-w: 64px;
25
25
  --os-tap: 44px;
26
- --os-font: var(--ff-ui, 'Space Grotesk', system-ui, sans-serif);
27
- --os-display: var(--ff-display, 'Space Grotesk', system-ui, sans-serif);
26
+ --os-font: var(--ff-ui, 'Inter', system-ui, sans-serif);
27
+ --os-display: var(--ff-display, 'Inter', system-ui, sans-serif);
28
28
  --os-mono: var(--ff-mono, 'JetBrains Mono', ui-monospace, monospace);
29
29
  }
30
30
 
@@ -464,7 +464,7 @@ html, body {
464
464
  * thebird theme preset (migrated from thebird's local thebird-brand.css
465
465
  * 2026-05-26). thebird ships ZERO design CSS — every rule below lives here
466
466
  * upstream and is delivered via the published package. Scoped to .ds-247420
467
- * (thebird's OS root carries that class). Brand identity: Space Grotesk +
467
+ * (thebird's OS root carries that class). Brand identity: Inter +
468
468
  * --paper #F5F0E4 + green accent #247420 + uniform 34px bars +
469
469
  * Windows-style right-side window controls.
470
470
  * ============================================================ */
@@ -472,9 +472,9 @@ html, body {
472
472
  --paper: #F5F0E4;
473
473
  }
474
474
  .ds-247420 {
475
- --ff-ui: 'Space Grotesk', system-ui, sans-serif !important;
476
- --ff-display: 'Space Grotesk', system-ui, sans-serif !important;
477
- --ff-prose: 'Space Grotesk', system-ui, sans-serif !important;
475
+ --ff-ui: 'Inter', system-ui, sans-serif !important;
476
+ --ff-display: 'Inter', system-ui, sans-serif !important;
477
+ --ff-prose: 'Inter', system-ui, sans-serif !important;
478
478
  --os-accent: #247420;
479
479
  /* uniform bar height: 22px button + 6px+6px padding = 34px */
480
480
  --os-bar-h: 34px !important;
@@ -538,7 +538,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
538
538
  border: 1px solid var(--os-accent, #247420);
539
539
  border-radius: 8px;
540
540
  z-index: 9600;
541
- font-family: var(--ff-ui, 'Space Grotesk', sans-serif);
541
+ font-family: var(--ff-ui, 'Inter', sans-serif);
542
542
  color: var(--os-fg, #fff);
543
543
  min-width: 280px;
544
544
  box-shadow: 0 12px 40px rgba(0,0,0,0.5);
@@ -555,19 +555,19 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
555
555
  color: var(--paper, #fff);
556
556
  }
557
557
 
558
- /* freddie-chat font family (upstream still ships Nunito; brand is Space Grotesk). */
558
+ /* freddie-chat font family (upstream still ships Nunito; brand is Inter). */
559
559
  .ds-247420 freddie-chat,
560
560
  .ds-247420 freddie-chat .chat-bubble,
561
561
  .ds-247420 freddie-chat .chat-meta,
562
562
  .ds-247420 freddie-chat .chat-head {
563
- font-family: var(--ff-ui, 'Space Grotesk', system-ui, sans-serif);
563
+ font-family: var(--ff-ui, 'Inter', system-ui, sans-serif);
564
564
  }
565
565
  .ds-247420 freddie-chat .chat-bubble pre,
566
566
  .ds-247420 freddie-chat .chat-bubble code {
567
567
  font-family: 'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace;
568
568
  }
569
569
  .ds-247420 freddie-chat .chat-head {
570
- font-family: var(--ff-display, 'Space Grotesk', system-ui, sans-serif);
570
+ font-family: var(--ff-display, 'Inter', system-ui, sans-serif);
571
571
  font-weight: 700;
572
572
  }
573
573