anentrypoint-design 0.0.118 → 0.0.121

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.118",
3
+ "version": "0.0.121",
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",
@@ -78,15 +78,28 @@ export function ChannelCategory({ id, name, channels = [], collapsed, activeId,
78
78
  );
79
79
  }
80
80
 
81
- export function VoiceUser({ identity, speaking, color } = {}) {
81
+ export function VoiceUser({ identity, speaking, color, quality, videoStream } = {}) {
82
82
  const initial = (identity || '?').slice(0, 1).toUpperCase();
83
+ const q = quality || null;
84
+ const videoRef = videoStream ? (el) => {
85
+ if (el && el.srcObject !== videoStream) el.srcObject = videoStream;
86
+ } : null;
83
87
  return h('div', { class: 'cm-voice-user' + (speaking ? ' speaking' : '') },
84
- h('div', { class: 'cm-voice-user-avatar', style: color ? `background:${color}` : '' }, initial),
88
+ h('div', { class: 'cm-voice-user-avatar', style: color ? `background:${color}` : '' },
89
+ videoStream ? h('video', {
90
+ class: 'cm-voice-user-video',
91
+ autoplay: true,
92
+ muted: true,
93
+ playsinline: true,
94
+ ref: videoRef
95
+ }) : initial,
96
+ q ? h('span', { class: `cm-voice-user-quality q-${q}`, title: `Connection: ${q}` }) : null
97
+ ),
85
98
  h('span', { class: 'cm-voice-user-name' }, identity)
86
99
  );
87
100
  }
88
101
 
89
- export function UserPanel({ name, tag, color, muted, deafened, onMute, onDeafen, onSettings } = {}) {
102
+ export function UserPanel({ name, tag, color, muted, deafened, onMute, onDeafen, onSettings, extraButtons = [] } = {}) {
90
103
  const initial = (name || '?').slice(0, 1).toUpperCase();
91
104
  return h('div', { class: 'cm-user-panel' },
92
105
  h('div', { class: 'cm-user-avatar', style: color ? `background:${color}` : '' },
@@ -98,6 +111,11 @@ export function UserPanel({ name, tag, color, muted, deafened, onMute, onDeafen,
98
111
  tag ? h('div', { class: 'cm-user-tag' }, tag) : null
99
112
  ),
100
113
  h('div', { class: 'cm-user-controls' },
114
+ ...extraButtons.map(b => h('button', {
115
+ class: 'cm-user-btn extra' + (b.active ? ' active' : ''),
116
+ onclick: b.onClick,
117
+ title: b.title || ''
118
+ }, b.icon || '·')),
101
119
  h('button', { class: 'cm-user-btn' + (muted ? ' muted' : ''), onclick: onMute, title: muted ? 'Unmute' : 'Mute' }, muted ? '🔇' : '🎤'),
102
120
  h('button', { class: 'cm-user-btn' + (deafened ? ' deafened' : ''), onclick: onDeafen, title: deafened ? 'Undeafen' : 'Deafen' }, deafened ? '🔕' : '🎧'),
103
121
  h('button', { class: 'cm-user-btn', onclick: onSettings, title: 'Settings' }, '⚙')
@@ -204,6 +204,62 @@ export function ProjectView({ project = {}, copied, onCopy } = {}) {
204
204
  ].filter(Boolean).flat();
205
205
  }
206
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
+
207
263
  export function Form({ fields = [], submit = 'submit', onSubmit }) {
208
264
  return h('form', { class: 'row-form', onsubmit: (ev) => { ev.preventDefault(); onSubmit && onSubmit(ev); } },
209
265
  ...fields.map((f, i) => f.kind === 'textarea'
@@ -0,0 +1,151 @@
1
+ // Overlay surface — toast, banner, mobile header, drawer, boot splash,
2
+ // context menu, command palette, emoji picker, reply bar.
3
+ // All factories: props → vnode. No internal state, no lifecycle (refs OK).
4
+
5
+ import * as webjsx from '../../vendor/webjsx/index.js';
6
+ const h = webjsx.createElement;
7
+
8
+ export function Toast({ message, tone = 'info', visible } = {}) {
9
+ if (!visible) return null;
10
+ return h('div', { class: `cm-toast tone-${tone}`, role: 'status' },
11
+ h('span', { class: 'cm-toast-msg' }, message || '')
12
+ );
13
+ }
14
+
15
+ export function Banner({ tone = 'info', message, action, onAction, visible, dismissable, onDismiss } = {}) {
16
+ if (!visible) return null;
17
+ return h('div', { class: `cm-banner tone-${tone}`, role: 'alert' },
18
+ h('span', { class: 'cm-banner-msg' }, message || ''),
19
+ action ? h('button', {
20
+ class: 'cm-banner-action',
21
+ onclick: onAction,
22
+ title: action.label || ''
23
+ }, action.icon ? h('span', { class: 'cm-banner-action-icon' }, action.icon) : null, action.label || '') : null,
24
+ dismissable ? h('button', { class: 'cm-banner-dismiss', onclick: onDismiss, title: 'Dismiss' }, '✕') : null
25
+ );
26
+ }
27
+
28
+ export function MobileHeader({ title, onMenu, onMembers } = {}) {
29
+ return h('div', { class: 'cm-mobile-header' },
30
+ h('button', { class: 'cm-mh-btn', onclick: onMenu, title: 'Menu' }, '☰'),
31
+ h('span', { class: 'cm-mh-title' }, title || ''),
32
+ h('button', { class: 'cm-mh-btn', onclick: onMembers, title: 'Members' }, '👥')
33
+ );
34
+ }
35
+
36
+ export function DrawerOverlay({ open, onClose, children, side = 'left' } = {}) {
37
+ if (!open) return null;
38
+ return h('div', { class: 'cm-drawer-overlay' },
39
+ h('div', { class: 'cm-drawer-backdrop', onclick: onClose }),
40
+ h('div', {
41
+ class: `cm-drawer-content side-${side}`,
42
+ onclick: (e) => e.stopPropagation()
43
+ }, ...(Array.isArray(children) ? children : [children]))
44
+ );
45
+ }
46
+
47
+ export function BootOverlay({ progress = 0, phase, error, visible } = {}) {
48
+ if (!visible) return null;
49
+ const pct = Math.max(0, Math.min(1, progress)) * 100;
50
+ return h('div', { class: 'cm-boot-overlay', role: 'dialog' },
51
+ h('div', { class: 'cm-boot-spinner' }),
52
+ h('div', { class: 'cm-boot-phase' }, phase || 'Loading…'),
53
+ h('div', { class: 'cm-boot-progress' },
54
+ h('div', { class: 'cm-boot-bar', style: `width:${pct}%` })
55
+ ),
56
+ error ? h('div', { class: 'cm-boot-error' }, String(error)) : null
57
+ );
58
+ }
59
+
60
+ export function ContextMenu({ items = [], x = 0, y = 0, open, onClose } = {}) {
61
+ if (!open) return null;
62
+ return h('div', {
63
+ class: 'cm-context-menu',
64
+ style: `left:${x}px;top:${y}px`,
65
+ onclick: (e) => e.stopPropagation()
66
+ },
67
+ h('div', { class: 'cm-cm-list' },
68
+ ...items.map(it => it.separator
69
+ ? h('div', { class: 'cm-cm-sep', key: it.id || 'sep' })
70
+ : h('button', {
71
+ class: 'cm-cm-item' + (it.danger ? ' danger' : ''),
72
+ 'data-id': it.id || '',
73
+ onclick: (e) => { e.stopPropagation(); it.onClick && it.onClick(e); onClose && onClose(); }
74
+ },
75
+ it.icon ? h('span', { class: 'cm-cm-icon' }, it.icon) : null,
76
+ h('span', { class: 'cm-cm-label' }, it.label || '')
77
+ )
78
+ )
79
+ )
80
+ );
81
+ }
82
+
83
+ export function CommandPalette({ items = [], query = '', onQuery, onSelect, open, onClose } = {}) {
84
+ if (!open) return null;
85
+ return h('div', { class: 'cm-command-palette-wrap' },
86
+ h('div', { class: 'cm-command-palette-backdrop', onclick: onClose }),
87
+ h('div', { class: 'cm-command-palette', onclick: (e) => e.stopPropagation() },
88
+ h('input', {
89
+ class: 'cm-cp-input',
90
+ type: 'text',
91
+ placeholder: 'Type a command…',
92
+ value: query,
93
+ oninput: (e) => onQuery && onQuery(e.target.value),
94
+ autofocus: true
95
+ }),
96
+ h('div', { class: 'cm-cp-list' },
97
+ ...items.map((it, i) => h('button', {
98
+ class: 'cm-cp-item' + (it.selected ? ' selected' : ''),
99
+ 'data-id': it.id || '',
100
+ onclick: () => onSelect && onSelect(it, i)
101
+ },
102
+ it.icon ? h('span', { class: 'cm-cp-icon' }, it.icon) : null,
103
+ h('span', { class: 'cm-cp-label' }, it.label || ''),
104
+ it.hint ? h('span', { class: 'cm-cp-hint' }, it.hint) : null
105
+ ))
106
+ )
107
+ )
108
+ );
109
+ }
110
+
111
+ const DEFAULT_EMOJI_CATEGORIES = [
112
+ { id: 'smileys', name: 'Smileys', emojis: ['😀','😃','😄','😁','😆','😅','🤣','😂','🙂','🙃','😉','😊','😇','🥰','😍','🤩','😘','😗','😚','😙','🥲','😋','😛','😜','🤪','😝','🤑','🤗','🤭','🤫'] },
113
+ { id: 'hearts', name: 'Hearts', emojis: ['❤️','🧡','💛','💚','💙','💜','🖤','🤍','🤎','💔','❣️','💕','💞','💓','💗','💖','💘','💝','💟','♥️','💌','💋','💍','💎','🌹','🌷','🌻','🌸','🌺','💐'] },
114
+ { id: 'animals', name: 'Animals', emojis: ['🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔','🐧','🐦','🐤','🦆','🦅','🦉','🦇','🐺','🐗','🐴','🦄','🐝','🐛','🦋'] },
115
+ { id: 'food', name: 'Food', emojis: ['🍏','🍎','🍐','🍊','🍋','🍌','🍉','🍇','🍓','🫐','🍈','🍒','🍑','🥭','🍍','🥥','🥝','🍅','🍆','🥑','🥦','🥬','🥒','🌶️','🌽','🥕','🧄','🧅','🥔','🍞'] },
116
+ { id: 'activities', name: 'Activities', emojis: ['⚽','🏀','🏈','⚾','🥎','🎾','🏐','🏉','🎱','🪀','🏓','🏸','🥅','🏒','🏑','🥍','🏏','🪃','⛳','🪁','🏹','🎣','🤿','🥊','🥋','🎽','🛹','🛼','🛷','⛸️'] },
117
+ { id: 'symbols', name: 'Symbols', emojis: ['✅','❌','⭕','🚫','♻️','✳️','❇️','⚠️','🔱','⚜️','🔰','✴️','🆚','🆗','🆙','🆒','🆕','🆓','0️⃣','1️⃣','2️⃣','3️⃣','4️⃣','5️⃣','6️⃣','7️⃣','8️⃣','9️⃣','🔟','💯'] }
118
+ ];
119
+
120
+ export function EmojiPicker({ recent = [], categories, onSelect, onClose, open } = {}) {
121
+ if (!open) return null;
122
+ const cats = categories && categories.length ? categories : DEFAULT_EMOJI_CATEGORIES;
123
+ return h('div', { class: 'cm-emoji-picker', onclick: (e) => e.stopPropagation() },
124
+ h('input', { class: 'cm-ep-search', type: 'text', placeholder: 'Search emoji…' }),
125
+ h('div', { class: 'cm-ep-grid' },
126
+ recent.length ? h('div', { class: 'cm-ep-category' }, 'Recent') : null,
127
+ ...recent.map((e, i) => h('button', {
128
+ class: 'cm-ep-btn', key: 'r' + i,
129
+ onclick: () => onSelect && onSelect(e)
130
+ }, e)),
131
+ ...cats.flatMap(cat => [
132
+ h('div', { class: 'cm-ep-category', key: 'c-' + cat.id }, cat.name),
133
+ ...cat.emojis.map((e, i) => h('button', {
134
+ class: 'cm-ep-btn', key: cat.id + '-' + i,
135
+ onclick: () => onSelect && onSelect(e)
136
+ }, e))
137
+ ])
138
+ )
139
+ );
140
+ }
141
+
142
+ export function ReplyBar({ quotedMessage, quotedAuthor, onCancel } = {}) {
143
+ return h('div', { class: 'cm-reply-bar' },
144
+ h('div', { class: 'cm-rb-quote' },
145
+ h('span', { class: 'cm-rb-label' }, 'Replying to '),
146
+ h('span', { class: 'cm-rb-author' }, quotedAuthor || ''),
147
+ h('span', { class: 'cm-rb-msg' }, quotedMessage ? ': ' + String(quotedMessage).slice(0, 80) : '')
148
+ ),
149
+ h('button', { class: 'cm-rb-cancel', onclick: onCancel, title: 'Cancel reply' }, '✕')
150
+ );
151
+ }
package/src/components.js CHANGED
@@ -12,8 +12,8 @@ export {
12
12
  export {
13
13
  Panel, Row, RowLink,
14
14
  Hero, Install, Receipt, Changelog,
15
- WorksList, WritingList, Manifesto, Section,
16
- Kpi, Table,
15
+ WorksList, WritingList, Manifesto, Section, PageHeader,
16
+ Kpi, Table, SearchInput, TextField, EventList,
17
17
  HomeView, ProjectView, Form
18
18
  } from './components/content.js';
19
19
 
@@ -44,6 +44,11 @@ export {
44
44
 
45
45
  export { ThemeToggle } from './components/theme-toggle.js';
46
46
 
47
+ export {
48
+ Toast, Banner, MobileHeader, DrawerOverlay, BootOverlay,
49
+ ContextMenu, CommandPalette, EmojiPicker, ReplyBar
50
+ } from './components/overlays.js';
51
+
47
52
  export {
48
53
  FREDDIE_PAGES,
49
54
  home, chat, voice, sessions, projects, agents, analytics,