anentrypoint-design 0.0.158 โ†’ 0.0.161

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.158",
3
+ "version": "0.0.161",
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",
@@ -37,7 +37,8 @@ export function ServerRail({ servers = [], activeId, onSelect, onAdd } = {}) {
37
37
  }
38
38
 
39
39
  export function ChannelItem({ id, name, type = 'text', active, voiceActive, voiceConnecting, badge, draggable, actions = [], participants = [], onClick, onContext } = {}) {
40
- const icon = type === 'voice' ? '๐Ÿ”Š' : type === 'forum' ? 'โ—ป' : type === 'threaded' ? 'โ—‰' : type === 'announcement' ? '๐Ÿ“ฃ' : type === 'page' ? '๐Ÿ“„' : type === 'thread' ? '๐Ÿงต' : '#';
40
+ const ICON_FOR = { voice: 'speaker', forum: 'forum', threaded: 'thread', announcement: 'megaphone', page: 'page', thread: 'thread', text: 'hash' };
41
+ const icon = Icon(ICON_FOR[type] || 'hash', { size: 15 });
41
42
  const handleActionClick = (a, e) => { e.stopPropagation(); a.onClick && a.onClick(id, e); };
42
43
  return h('div', { class: 'cm-channel-item-wrap', 'data-channel-wrap': id },
43
44
  h('div', {
@@ -238,13 +239,17 @@ export function VoiceStrip({ channelName, status, muted, deafened, onMute, onDea
238
239
  );
239
240
  }
240
241
 
241
- export function MobileHeader({ title, onMenu, onMembers } = {}) {
242
+ export function MobileHeader({ title, channelType, channelName, onMenu, onMembers } = {}) {
243
+ const ICON_FOR = { voice: 'speaker', forum: 'forum', threaded: 'thread', announcement: 'megaphone', page: 'page', thread: 'thread', text: 'hash' };
244
+ const titleNode = channelType
245
+ ? [Icon(ICON_FOR[channelType] || 'hash', { size: 16 }), ' ' + (channelName || '')]
246
+ : [title || ''];
242
247
  return h('div', { class: 'cm-mobile-header', role: 'banner' },
243
248
  h('button', {
244
249
  class: 'cm-mh-btn', type: 'button', onclick: onMenu,
245
250
  title: 'Menu', 'aria-label': 'open navigation menu'
246
251
  }, Icon('menu')),
247
- h('span', { class: 'cm-mh-title' }, title || ''),
252
+ h('span', { class: 'cm-mh-title' }, ...titleNode),
248
253
  h('button', {
249
254
  class: 'cm-mh-btn', type: 'button', onclick: onMembers,
250
255
  title: 'Members', 'aria-label': 'show members'
@@ -90,7 +90,12 @@ const ICON_PATHS = {
90
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
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
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"/>'
93
+ send: '<path d="M22 2 11 13M22 2l-7 20-4-9-9-4z"/>',
94
+ hash: '<path d="M4 9h16M4 15h16M10 3 8 21M16 3l-2 18"/>',
95
+ megaphone: '<path d="M3 11v2a1 1 0 0 0 1 1h2l5 4V6L6 10H4a1 1 0 0 0-1 1z"/><path d="M15 8a4 4 0 0 1 0 8M18 5a8 8 0 0 1 0 14"/>',
96
+ forum: '<path d="M4 5h13a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H9l-4 3v-3H4a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1z"/>',
97
+ page: '<path d="M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/><path d="M14 3v5h5M8 13h8M8 17h6"/>',
98
+ thread: '<path d="M5 6h14M5 11h14M5 16h8"/><circle cx="17" cy="17" r="3"/>'
94
99
  };
95
100
  export function Icon(name, { size = 16 } = {}) {
96
101
  const inner = ICON_PATHS[name];
@@ -108,9 +113,9 @@ export function Topbar({ brand = '247420', leaf = '', items = [], active = '', o
108
113
  return h('header', { class: 'app-topbar', role: 'banner' },
109
114
  Brand({ name: brand, leaf }),
110
115
  search ? h('label', { class: 'app-search' },
111
- h('span', { class: 'icon', 'aria-hidden': 'true' }, 'โŒ•'),
116
+ h('span', { class: 'icon', 'aria-hidden': 'true' }, 'search'),
112
117
  h('input', { type: 'search', placeholder: search, 'aria-label': `search ${search}` })
113
- ) : h('span', {}),
118
+ ) : null,
114
119
  h('nav', { 'aria-label': 'main navigation' }, ...items.map(([label, href]) => {
115
120
  const cleanLabel = String(label).replace(' โ†—', '');
116
121
  return h('a', {
@@ -189,6 +194,14 @@ function toggleSide(open) {
189
194
  export function AppShell({ topbar, crumb, side, main, status, narrow } = {}) {
190
195
  const hasSide = Boolean(side);
191
196
  const sideNode = hasSide ? side : h('aside', { class: 'app-side', 'aria-hidden': 'true' });
197
+ // Topbar and crumb used to stack as two separate chrome bars โ€” a "double
198
+ // title bar". When both are present, fold them into one sticky row:
199
+ // brand + nav (topbar) and breadcrumb + right slot (crumb) share a single
200
+ // band so the chrome reads as one bar, not two. Either prop alone still
201
+ // renders on its own (consumers that pass only a topbar are unaffected).
202
+ const chrome = (topbar && crumb)
203
+ ? h('div', { class: 'app-chrome' }, topbar, crumb)
204
+ : (topbar || crumb || null);
192
205
  return h('div', { class: 'app' },
193
206
  h('a', { href: '#app-main', class: 'skip-link' }, 'skip to main content'),
194
207
  hasSide ? h('button', {
@@ -196,8 +209,7 @@ export function AppShell({ topbar, crumb, side, main, status, narrow } = {}) {
196
209
  'aria-label': 'toggle navigation', 'aria-expanded': 'false', 'aria-controls': 'app-main',
197
210
  onclick: () => toggleSide(),
198
211
  }, Icon('menu')) : null,
199
- topbar || null,
200
- crumb || null,
212
+ chrome,
201
213
  h('div', { class: 'app-body' + (hasSide ? '' : ' no-side') },
202
214
  h('div', { class: 'app-side-scrim', 'aria-hidden': 'true', onclick: () => toggleSide(false) }),
203
215
  h('div', { class: 'app-side-shell', onclick: (e) => { if (e.target.closest('a')) toggleSide(false); } }, sideNode),