anentrypoint-design 0.0.44 → 0.0.46

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.44",
3
+ "version": "0.0.46",
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",
@@ -8,4 +8,6 @@ export const icons = {
8
8
  about: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 8v.01M11 12h1v5h1"/></svg>',
9
9
  apps: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>',
10
10
  plus: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>',
11
+ home: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>',
12
+ close: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 6l12 12M18 6l-12 12"/></svg>',
11
13
  };
@@ -2,11 +2,11 @@ import { icons } from './icons.js';
2
2
 
3
3
  const THEME_CSS_URL = new URL('./theme.css', import.meta.url).href;
4
4
 
5
- function ensureCss() {
5
+ function ensureCss(href) {
6
6
  if (document.querySelector('link[data-os-theme]')) return;
7
7
  const l = document.createElement('link');
8
8
  l.rel = 'stylesheet';
9
- l.href = THEME_CSS_URL;
9
+ l.href = href || THEME_CSS_URL;
10
10
  l.dataset.osTheme = '1';
11
11
  document.head.appendChild(l);
12
12
  }
@@ -21,6 +21,7 @@ function ic(svg) {
21
21
  function makeBtn(svg, label, role) {
22
22
  const b = document.createElement('button');
23
23
  b.className = 'os-btn';
24
+ b.type = 'button';
24
25
  if (role) b.dataset.role = role;
25
26
  if (svg) b.append(ic(svg));
26
27
  if (label) b.append(Object.assign(document.createElement('span'), { textContent: label }));
@@ -30,26 +31,18 @@ function makeBtn(svg, label, role) {
30
31
  export function createDesktopShell({ root = document.body, wm, registry, brand = 'desktop', themeUrl, onNewInstance, autoBoot = false } = {}) {
31
32
  if (!wm) throw new Error('createDesktopShell: wm is required');
32
33
  if (!registry) throw new Error('createDesktopShell: registry is required');
33
- if (themeUrl) {
34
- if (!document.querySelector('link[data-os-theme]')) {
35
- const l = document.createElement('link');
36
- l.rel = 'stylesheet';
37
- l.href = themeUrl;
38
- l.dataset.osTheme = '1';
39
- document.head.appendChild(l);
40
- }
41
- } else {
42
- ensureCss();
43
- }
34
+ ensureCss(themeUrl);
44
35
 
45
36
  const osRoot = document.createElement('div');
46
37
  osRoot.className = 'os-root';
47
- osRoot.style.cssText = 'position:fixed;inset:0;display:flex;flex-direction:column;pointer-events:none;z-index:8000';
48
38
  root.appendChild(osRoot);
49
39
 
50
40
  const menubar = document.createElement('div');
51
41
  menubar.className = 'os-menubar';
52
42
 
43
+ const homeBtn = makeBtn(icons.home, '', 'home');
44
+ homeBtn.title = 'apps';
45
+
53
46
  const brandEl = document.createElement('span');
54
47
  brandEl.className = 'os-brand';
55
48
  brandEl.textContent = brand;
@@ -59,75 +52,87 @@ export function createDesktopShell({ root = document.body, wm, registry, brand =
59
52
 
60
53
  const instSwitch = document.createElement('div');
61
54
  instSwitch.className = 'os-instances';
62
- instSwitch.style.cssText = 'display:flex;gap:6px;margin-left:8px';
63
55
 
64
56
  const spacer = document.createElement('div');
65
- spacer.style.cssText = 'flex:1';
57
+ spacer.className = 'os-spacer';
66
58
 
67
59
  const tray = document.createElement('div');
68
- tray.style.cssText = 'display:flex;align-items:center;gap:6px';
60
+ tray.className = 'os-tray';
69
61
  const clock = document.createElement('span');
70
62
  clock.className = 'os-clock';
71
63
  tray.appendChild(clock);
72
64
 
73
- menubar.append(brandEl, appsBtn);
65
+ menubar.append(homeBtn, brandEl, appsBtn);
74
66
  if (newInstBtn) menubar.append(newInstBtn);
75
67
  menubar.append(instSwitch, spacer, tray);
76
68
 
77
69
  const appsMenu = document.createElement('div');
78
70
  appsMenu.className = 'os-menu';
79
- appsMenu.style.cssText = 'position:absolute;display:none;flex-direction:column;pointer-events:auto';
80
71
 
81
72
  const sideRail = document.createElement('div');
82
73
  sideRail.className = 'os-side-rail';
83
74
 
84
- const sheet = document.createElement('div');
85
- sheet.className = 'os-mobile-sheet';
86
- const sheetHandle = document.createElement('div');
87
- sheetHandle.className = 'os-mobile-handle';
88
- const sheetGrid = document.createElement('div');
89
- sheetGrid.className = 'os-mobile-grid';
90
- sheet.append(sheetHandle, sheetGrid);
91
- sheet.addEventListener('click', e => {
92
- if (e.target === sheet || e.target === sheetHandle) sheet.classList.toggle('open');
93
- });
75
+ const drawer = document.createElement('div');
76
+ drawer.className = 'os-drawer';
77
+ drawer.setAttribute('aria-hidden', 'true');
78
+ const drawerHeader = document.createElement('div');
79
+ drawerHeader.className = 'os-drawer-head';
80
+ const drawerTitle = document.createElement('span');
81
+ drawerTitle.className = 'os-drawer-title';
82
+ drawerTitle.textContent = 'apps';
83
+ const drawerClose = document.createElement('button');
84
+ drawerClose.className = 'os-drawer-close';
85
+ drawerClose.type = 'button';
86
+ drawerClose.append(ic(icons.close));
87
+ drawerHeader.append(drawerTitle, drawerClose);
88
+ const drawerGrid = document.createElement('div');
89
+ drawerGrid.className = 'os-drawer-grid';
90
+ drawer.append(drawerHeader, drawerGrid);
94
91
 
95
92
  const apps = typeof registry.list === 'function' ? registry.list() : [...registry.values()];
96
93
 
97
94
  for (const app of apps) {
98
95
  const iconSvg = app.icon || icons[app.id] || '';
99
96
  const menuBtn = makeBtn(iconSvg, app.name);
100
- menuBtn.addEventListener('click', () => { appsMenu.style.display = 'none'; openApp(app.id); });
97
+ menuBtn.addEventListener('click', () => { closeMenu(); openApp(app.id); });
101
98
  appsMenu.appendChild(menuBtn);
102
99
 
103
100
  const railBtn = document.createElement('button');
104
101
  railBtn.className = 'os-rail-btn';
102
+ railBtn.type = 'button';
105
103
  railBtn.title = app.name;
106
104
  railBtn.append(ic(iconSvg));
107
105
  railBtn.addEventListener('click', () => openApp(app.id));
108
106
  sideRail.appendChild(railBtn);
109
107
 
110
108
  const tile = document.createElement('button');
111
- tile.className = 'os-mobile-tile';
109
+ tile.className = 'os-drawer-tile';
110
+ tile.type = 'button';
112
111
  tile.append(ic(iconSvg), Object.assign(document.createElement('span'), { className: 'lbl', textContent: app.name }));
113
- tile.addEventListener('click', () => { sheet.classList.remove('open'); openApp(app.id); });
114
- sheetGrid.appendChild(tile);
112
+ tile.addEventListener('click', () => { closeDrawer(); openApp(app.id); });
113
+ drawerGrid.appendChild(tile);
115
114
  }
116
115
 
117
116
  const taskbar = document.createElement('div');
118
117
  taskbar.className = 'os-taskbar';
119
- taskbar.style.cssText = 'margin-top:auto;display:flex;align-items:center;gap:6px;flex-wrap:wrap';
120
118
 
121
119
  osRoot.append(menubar, appsMenu, taskbar);
122
- document.body.appendChild(sideRail);
123
- document.body.appendChild(sheet);
120
+ document.body.append(sideRail, drawer);
124
121
 
125
- appsBtn.addEventListener('click', e => {
126
- e.stopPropagation();
127
- appsMenu.style.display = appsMenu.style.display === 'flex' ? 'none' : 'flex';
128
- });
122
+ function openMenu() { appsMenu.classList.add('open'); }
123
+ function closeMenu() { appsMenu.classList.remove('open'); }
124
+ function openDrawer() { drawer.classList.add('open'); drawer.setAttribute('aria-hidden', 'false'); }
125
+ function closeDrawer() { drawer.classList.remove('open'); drawer.setAttribute('aria-hidden', 'true'); }
126
+
127
+ appsBtn.addEventListener('click', e => { e.stopPropagation(); appsMenu.classList.toggle('open'); });
128
+ homeBtn.addEventListener('click', e => { e.stopPropagation(); drawer.classList.contains('open') ? closeDrawer() : openDrawer(); });
129
+ drawerClose.addEventListener('click', closeDrawer);
130
+ drawer.addEventListener('click', e => { if (e.target === drawer) closeDrawer(); });
129
131
  document.addEventListener('click', e => {
130
- if (!appsMenu.contains(e.target) && !appsBtn.contains(e.target)) appsMenu.style.display = 'none';
132
+ if (!appsMenu.contains(e.target) && !appsBtn.contains(e.target)) closeMenu();
133
+ });
134
+ document.addEventListener('keydown', e => {
135
+ if (e.key === 'Escape') { closeMenu(); closeDrawer(); }
131
136
  });
132
137
 
133
138
  function tickClock() { clock.textContent = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); }
@@ -142,7 +147,9 @@ export function createDesktopShell({ root = document.body, wm, registry, brand =
142
147
  for (const w of wm.list()) {
143
148
  const t = document.createElement('button');
144
149
  t.className = 'os-task' + (w.focused ? ' focused' : '');
150
+ t.type = 'button';
145
151
  t.textContent = w.title;
152
+ t.dataset.winId = w.id;
146
153
  t.addEventListener('click', () => wm.focus(w.id));
147
154
  taskbar.appendChild(t);
148
155
  }
@@ -170,9 +177,9 @@ export function createDesktopShell({ root = document.body, wm, registry, brand =
170
177
 
171
178
  const api = {
172
179
  wm, registry, openApp, setContext, refreshTaskbar,
173
- toggleSheet() { sheet.classList.toggle('open'); },
174
- elements: { osRoot, menubar, taskbar, appsMenu, sideRail, sheet, instSwitch },
175
- dispose() { clearInterval(clockTimer); clearInterval(taskTimer); osRoot.remove(); sideRail.remove(); sheet.remove(); },
180
+ openDrawer, closeDrawer, openMenu, closeMenu,
181
+ elements: { osRoot, menubar, taskbar, appsMenu, sideRail, drawer, instSwitch, homeBtn, appsBtn },
182
+ dispose() { clearInterval(clockTimer); clearInterval(taskTimer); osRoot.remove(); sideRail.remove(); drawer.remove(); },
176
183
  };
177
184
 
178
185
  if (autoBoot && typeof autoBoot === 'string') openApp(autoBoot);
@@ -205,54 +205,74 @@ html, body {
205
205
  .os-rail-btn .ic { color: var(--os-accent); display: inline-flex; }
206
206
  .os-rail-btn .ic svg { width: 22px; height: 22px; fill: none; stroke: currentColor; }
207
207
 
208
- .os-mobile-sheet {
208
+ .os-drawer {
209
209
  position: fixed;
210
- left: 0; right: 0; bottom: 0;
211
- background: var(--os-bg-1);
212
- border-top: 1px solid var(--os-bg-3);
213
- border-radius: 14px 14px 0 0;
214
- padding: 8px 12px env(safe-area-inset-bottom, 12px);
215
- transform: translateY(calc(100% - 56px));
216
- transition: transform 220ms cubic-bezier(0.22, 0.8, 0.34, 1.0);
210
+ inset: 0;
211
+ background: var(--os-bg-0);
217
212
  z-index: 9700;
218
213
  pointer-events: auto;
219
214
  display: none;
220
215
  flex-direction: column;
221
- gap: 8px;
222
- max-height: 70vh;
223
- box-shadow: none;
216
+ opacity: 0;
217
+ transform: translateY(8px);
218
+ transition: opacity 180ms ease, transform 180ms ease;
219
+ padding-top: env(safe-area-inset-top, 0);
220
+ padding-bottom: env(safe-area-inset-bottom, 0);
224
221
  }
225
- .os-mobile-sheet.open { transform: translateY(0); }
226
- .os-mobile-handle {
227
- width: 44px; height: 4px;
228
- border-radius: 999px;
229
- background: var(--os-bg-3);
230
- margin: 6px auto 4px;
222
+ .os-drawer.open { display: flex; opacity: 1; transform: translateY(0); }
223
+ .os-drawer-head {
224
+ display: flex; align-items: center; justify-content: space-between;
225
+ padding: 12px 16px;
226
+ border-bottom: 1px solid var(--os-bg-3);
227
+ height: 56px;
228
+ box-sizing: border-box;
231
229
  }
232
- .os-mobile-grid {
230
+ .os-drawer-title { color: var(--os-fg); font: 17px var(--os-font); font-weight: 600; }
231
+ .os-drawer-close {
232
+ width: 44px; height: 44px;
233
+ border: none; background: transparent;
234
+ color: var(--os-fg-2);
235
+ cursor: pointer;
236
+ display: flex; align-items: center; justify-content: center;
237
+ border-radius: var(--os-radius-sm);
238
+ outline: none;
239
+ }
240
+ .os-drawer-close:hover { background: var(--os-bg-2); color: var(--os-fg); }
241
+ .os-drawer-close .ic svg { width: 22px; height: 22px; fill: none; stroke: currentColor; }
242
+ .os-drawer-grid {
233
243
  display: grid;
234
- grid-template-columns: repeat(4, 1fr);
235
- gap: 8px;
244
+ grid-template-columns: repeat(3, 1fr);
245
+ gap: 12px;
246
+ padding: 16px;
236
247
  overflow-y: auto;
237
- padding: 6px 4px 12px;
248
+ flex: 1;
249
+ align-content: start;
238
250
  }
239
- .os-mobile-tile {
240
- display: flex; flex-direction: column; align-items: center; gap: 6px;
241
- padding: 12px 6px;
242
- border-radius: var(--os-radius);
243
- background: var(--os-bg-2);
251
+ .os-drawer-tile {
252
+ display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
253
+ padding: 16px 8px;
254
+ background: var(--os-bg-1);
244
255
  border: none;
245
256
  color: var(--os-fg);
246
- font: 11px var(--os-font);
247
- min-height: var(--os-tap);
257
+ font: 13px var(--os-font);
258
+ min-height: 96px;
248
259
  cursor: pointer;
249
260
  transition: background 100ms ease;
250
261
  outline: none;
262
+ border-radius: var(--os-radius);
251
263
  }
252
- .os-mobile-tile:active { background: var(--os-accent-soft); }
253
- .os-mobile-tile .ic { color: var(--os-accent); display: inline-flex; width: 28px; height: 28px; }
254
- .os-mobile-tile .ic svg { width: 28px; height: 28px; fill: none; stroke: currentColor; }
255
- .os-mobile-tile .lbl { color: var(--os-fg-2); }
264
+ .os-drawer-tile:active { background: var(--os-accent-soft); }
265
+ .os-drawer-tile .ic { color: var(--os-accent); display: inline-flex; }
266
+ .os-drawer-tile .ic svg { width: 32px; height: 32px; fill: none; stroke: currentColor; }
267
+ .os-drawer-tile .lbl { color: var(--os-fg); font-weight: 500; }
268
+
269
+ .os-spacer { flex: 1 1 auto; }
270
+ .os-tray { display: flex; align-items: center; gap: 6px; }
271
+ .os-instances { display: flex; gap: 6px; margin-left: 8px; }
272
+ .os-menubar [data-role="home"] { display: none; }
273
+ .os-root { position: fixed; inset: 0; display: flex; flex-direction: column; pointer-events: none; z-index: 8000; }
274
+ .os-menubar, .os-taskbar { pointer-events: auto; flex: 0 0 auto; }
275
+ .wm-root { top: var(--os-bar-h) !important; bottom: var(--os-bar-h) !important; inset: var(--os-bar-h) 0 var(--os-bar-h) 0 !important; }
256
276
 
257
277
  .app-pane { padding: 14px; font: 13px var(--os-font); color: var(--os-fg); line-height: 1.55; overflow: auto; height: 100%; box-sizing: border-box; }
258
278
  .app-pane h2 { margin: 0 0 10px 0; color: var(--os-fg); font-size: 16px; font-weight: 600; }
@@ -281,17 +301,63 @@ html, body {
281
301
 
282
302
  @media (max-width: 767px) {
283
303
  :root { --os-bar-h: var(--os-bar-h-mobile); }
284
- .os-mobile-sheet { display: flex; }
285
- .os-menubar { font-size: 14px; padding: 0 8px; }
286
- .os-menubar .os-btn { min-height: var(--os-tap); padding: 8px 10px; }
304
+ body { overscroll-behavior: none; }
305
+ .os-menubar [data-role="home"] { display: inline-flex; min-width: var(--os-tap); min-height: var(--os-tap); padding: 0 12px; }
306
+ .os-menubar [data-role="home"] .ic svg { width: 22px; height: 22px; }
307
+ .os-menubar { font-size: 14px; padding: 0 8px; padding-top: env(safe-area-inset-top, 0); height: calc(var(--os-bar-h) + env(safe-area-inset-top, 0)); }
287
308
  .os-menubar [data-role="apps"] { display: none; }
288
- .os-menubar [data-role="add"] { min-width: var(--os-tap); }
289
- .os-menubar .os-instances { gap: 4px; }
309
+ .os-menubar .os-brand { font-size: 13px; margin-right: 6px; }
310
+ .os-menubar [data-role="add"] { display: none; }
311
+ .os-menubar .os-instances { display: none; }
290
312
  .os-clock { display: none; }
291
- .os-taskbar { padding: 4px 8px 64px; gap: 4px; overflow-x: auto; flex-wrap: nowrap; }
292
- .os-task { flex: 0 0 auto; min-height: 36px; max-width: 140px; padding: 8px 10px; }
293
- .wm-win { border-radius: 0 !important; }
294
- .wm-bar { padding: 10px 12px !important; }
295
- .wm-btn { width: 16px !important; height: 16px !important; }
296
- .os-menu { left: 8px; right: 8px; min-width: 0; }
313
+ .os-taskbar {
314
+ padding: 6px 8px calc(6px + env(safe-area-inset-bottom, 0));
315
+ gap: 6px;
316
+ overflow-x: auto;
317
+ overflow-y: hidden;
318
+ flex-wrap: nowrap;
319
+ scroll-snap-type: x proximity;
320
+ height: calc(var(--os-bar-h) + env(safe-area-inset-bottom, 0));
321
+ align-items: center;
322
+ }
323
+ .os-taskbar::-webkit-scrollbar { display: none; }
324
+ .os-task {
325
+ flex: 0 0 auto;
326
+ min-width: 120px;
327
+ min-height: 44px;
328
+ max-width: none;
329
+ padding: 10px 14px;
330
+ scroll-snap-align: start;
331
+ border-left: 3px solid transparent;
332
+ font-size: 13px;
333
+ }
334
+ .os-task.focused { border-left-color: var(--os-accent); background: var(--os-bg-2); }
335
+ .os-side-rail { display: none !important; }
336
+ .os-menu { left: 8px; right: 8px; min-width: 0; top: calc(var(--os-bar-h) + env(safe-area-inset-top, 0) + 4px); }
337
+ .wm-root {
338
+ top: calc(var(--os-bar-h) + env(safe-area-inset-top, 0)) !important;
339
+ bottom: calc(var(--os-bar-h) + env(safe-area-inset-bottom, 0)) !important;
340
+ inset: calc(var(--os-bar-h) + env(safe-area-inset-top, 0)) 0 calc(var(--os-bar-h) + env(safe-area-inset-bottom, 0)) 0 !important;
341
+ }
342
+ .wm-win {
343
+ position: absolute !important;
344
+ left: 0 !important; top: 0 !important;
345
+ width: 100% !important; height: 100% !important;
346
+ border: none !important;
347
+ border-radius: 0 !important;
348
+ box-shadow: none !important;
349
+ }
350
+ .wm-bar {
351
+ padding: 6px 10px !important;
352
+ height: 36px !important;
353
+ gap: 6px !important;
354
+ cursor: default !important;
355
+ touch-action: pan-y !important;
356
+ pointer-events: none;
357
+ }
358
+ .wm-bar .wm-title { pointer-events: auto; font-size: 13px !important; }
359
+ .wm-bar .wm-btns { pointer-events: auto; }
360
+ .wm-btns .wm-btn:nth-child(1), .wm-btns .wm-btn:nth-child(2) { display: none !important; }
361
+ .wm-btns .wm-btn:nth-child(3) { width: 44px !important; height: 44px !important; border-radius: 50% !important; }
362
+ .wm-resize { display: none !important; }
297
363
  }