anentrypoint-design 0.0.185 → 0.0.186

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.185",
3
+ "version": "0.0.186",
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",
@@ -24,7 +24,7 @@ const threadRef = (msgCount) => makeThreadAutoScroll(() => msgCount);
24
24
 
25
25
  // The agent picker: agent-then-model, not a flat model list. Unavailable agents
26
26
  // are disabled (unless installable via npx). Ordering is the host's concern.
27
- function AgentControls({ agents, selectedAgent, models, selectedModel, busy, status,
27
+ function AgentControls({ agents, selectedAgent, models, selectedModel, busy, status, modelsLoading,
28
28
  onSelectAgent, onSelectModel, onNewChat, onStop }) {
29
29
  const agentOptions = (agents || []).map((a) => ({
30
30
  value: a.id,
@@ -38,13 +38,17 @@ function AgentControls({ agents, selectedAgent, models, selectedModel, busy, sta
38
38
  title: 'Select agent', options: agentOptions,
39
39
  onChange: (v) => onSelectAgent && onSelectAgent(v),
40
40
  }),
41
+ // While models load for a freshly-picked agent, show a disabled "loading…"
42
+ // placeholder so the picker doesn't vanish then reappear (a layout flash).
41
43
  showModels
42
44
  ? Select({
43
45
  key: 'modelsel', value: selectedModel, placeholder: '— model —',
44
46
  title: 'Select model', options: (models || []).map((m) => ({ value: m.id, label: m.name || m.id })),
45
47
  onChange: (v) => onSelectModel && onSelectModel(v),
46
48
  })
47
- : null,
49
+ : (modelsLoading
50
+ ? Select({ key: 'modelsel', value: '', placeholder: 'loading models…', title: 'Loading models', disabled: true, options: [] })
51
+ : null),
48
52
  busy
49
53
  ? Btn({ key: 'stop', onClick: () => onStop && onStop(), children: 'stop', title: 'Stop streaming' })
50
54
  : Btn({ key: 'new', onClick: () => onNewChat && onNewChat(), children: 'new', title: 'New chat' }),
@@ -81,7 +85,7 @@ function CwdBar({ cwd, editing, draft, onEdit, onSave, onCancel, onClear, onDraf
81
85
  // onCwdEdit/onCwdSave/onCwdCancel/onCwdClear/onCwdDraft
82
86
  export function AgentChat(props = {}) {
83
87
  const {
84
- agents = [], selectedAgent = '', models = [], selectedModel = '',
88
+ agents = [], selectedAgent = '', models = [], selectedModel = '', modelsLoading = false,
85
89
  messages = [], busy = false, draft = '', status, banners = [],
86
90
  cwd = '', cwdEditing = false, cwdDraft,
87
91
  agentName, placeholder,
@@ -97,6 +101,9 @@ export function AgentChat(props = {}) {
97
101
  const isStreaming = busy && i === lastIdx && isAssistant;
98
102
  const hasParts = Array.isArray(m.parts) && m.parts.length > 0;
99
103
  const emptyStreaming = isStreaming && !m.content && !hasParts;
104
+ // A finished assistant message with no content and no parts is an empty
105
+ // shell (e.g. an aborted turn) — render nothing rather than a blank bubble.
106
+ if (!isStreaming && isAssistant && !m.content && !hasParts) return null;
100
107
  const parts = [];
101
108
  if (m.content) parts.push({ kind: isAssistant ? 'md' : 'text', text: m.content });
102
109
  if (hasParts) for (const p of m.parts) parts.push({ kind: 'text', text: p });
@@ -120,7 +127,7 @@ export function AgentChat(props = {}) {
120
127
  });
121
128
 
122
129
  return h('div', { class: 'agentchat' },
123
- AgentControls({ agents, selectedAgent, models, selectedModel, busy, status,
130
+ AgentControls({ agents, selectedAgent, models, selectedModel, busy, status, modelsLoading,
124
131
  onSelectAgent, onSelectModel, onNewChat, onStop }),
125
132
  CwdBar({ cwd, editing: cwdEditing, draft: cwdDraft,
126
133
  onEdit: onCwdEdit, onSave: onCwdSave, onCancel: onCwdCancel, onClear: onCwdClear, onDraft: onCwdDraft }),
@@ -130,7 +137,7 @@ export function AgentChat(props = {}) {
130
137
  h('span', { class: 'agentchat-sub', 'aria-live': 'polite' },
131
138
  busy ? 'streaming…' : (messages.length ? messages.length + (messages.length === 1 ? ' message' : ' messages') : ''))),
132
139
  h('div', { class: 'agentchat-thread', ref: threadRef(messages.length), role: 'log', 'aria-label': 'conversation' },
133
- ...rows),
140
+ ...rows.filter(Boolean)),
134
141
  composer,
135
142
  );
136
143
  }
@@ -20,19 +20,25 @@ export function Panel({ title, count, right, style = '', children, kind }) {
20
20
  // Card — semantic alias of Panel; behaves identically.
21
21
  export const Card = Panel;
22
22
 
23
- export function Row({ code, title, sub, meta, active, state = 'default', onClick, key, style, href, kind, cols, leading, trailing, target, selected }) {
23
+ export function Row({ code, rank, title, sub, meta, active, state = 'default', onClick, key, style, href, kind, cols, leading, trailing, target, selected, rail }) {
24
+ // `rank` is an alias for `code` (the leading monospace index); callers use
25
+ // either name. `rail` renders a thin colour bar at the row's leading edge as
26
+ // a status indicator (tone: green | purple | flame | <any token>).
27
+ const codeVal = code != null ? code : rank;
24
28
  // Support legacy active/selected props for backward compatibility
25
29
  const isActive = state === 'active' || (state === 'default' && (active || selected));
26
30
  const isLink = kind === 'link' || (href != null && !onClick);
27
31
  const isButton = !isLink && !!onClick;
28
32
  const stateCls = state === 'disabled' ? ' row-state-disabled' : (state === 'error' ? ' row-state-error' : '');
29
- const cls = 'row' + (isActive ? ' active' : '') + stateCls + (cols ? ' row-grid' : '');
33
+ const cls = 'row' + (isActive ? ' active' : '') + stateCls + (cols ? ' row-grid' : '') + (rail ? ' rail-' + rail : '');
34
+ const isDisabled = state === 'disabled';
30
35
  const props = { key, class: cls, style: cols ? `${style ? style + ';' : ''}grid-template-columns:${cols}` : style };
31
36
  if (isLink) {
32
37
  props.href = href || '#';
33
38
  if (target) props.target = target;
34
- } else if (isButton) {
39
+ } else if (isButton && !isDisabled) {
35
40
  // Clickable div needs button semantics + keyboard activation for a11y parity.
41
+ // A disabled row is inert: no click, no button role, no tab stop.
36
42
  props.onclick = onClick;
37
43
  props.role = 'button';
38
44
  props.tabindex = '0';
@@ -40,9 +46,10 @@ export function Row({ code, title, sub, meta, active, state = 'default', onClick
40
46
  if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick(e); }
41
47
  };
42
48
  }
49
+ if (isDisabled) props['aria-disabled'] = 'true';
43
50
  if (isActive && (isLink || isButton)) props['aria-current'] = isActive ? 'page' : null;
44
51
  return h(isLink ? 'a' : 'div', props,
45
- leading != null ? leading : (code != null ? h('span', { class: 'code' }, code) : null),
52
+ leading != null ? leading : (codeVal != null ? h('span', { class: 'code' }, codeVal) : null),
46
53
  h('span', { class: 'title' }, title, sub ? h('span', { class: 'sub' }, sub) : null),
47
54
  trailing != null ? trailing : (meta != null ? h('span', { class: 'meta' }, meta) : null));
48
55
  }