anentrypoint-design 0.0.198 → 0.0.200

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.
@@ -140,7 +140,11 @@ const ICON_PATHS = {
140
140
  folder: '<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',
141
141
  upload: '<path d="M12 16V4M7 9l5-5 5 5"/><path d="M5 20h14"/>',
142
142
  download: '<path d="M12 4v12M7 11l5 5 5-5"/><path d="M5 20h14"/>',
143
- 'corner-up-left': '<path d="M9 14 4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 5 5v6"/>'
143
+ 'corner-up-left': '<path d="M9 14 4 9l5-5"/><path d="M4 9h11a5 5 0 0 1 5 5v6"/>',
144
+ // clipboard/copy — for the per-block code copy + message copy action, so the
145
+ // copy affordance reads as copy, not the lined-document `page` glyph.
146
+ copy: '<rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h8"/>',
147
+ clipboard: '<rect x="8" y="4" width="8" height="4" rx="1"/><path d="M8 6H6a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-2"/>'
144
148
  };
145
149
  // Raw-DOM consumers (no webjsx render in scope) need the SVG as a markup string
146
150
  // rather than an h() vnode. Same path table, same viewBox/stroke contract as
@@ -355,15 +359,21 @@ function wsCollapsed(which, fallback) {
355
359
  export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narrow,
356
360
  railCollapsed = false, paneCollapsed = false,
357
361
  railLabel = 'workspace navigation',
358
- paneLabel = 'context' } = {}) {
362
+ paneLabel = 'context', stableFrame = false } = {}) {
359
363
  const hasSessions = Boolean(sessions);
360
364
  const hasPane = Boolean(pane);
365
+ // Stable frame: keep the pane grid TRACK present even when this tab has no
366
+ // pane, so the shell does not re-flow its column count (4/3/2) on every tab
367
+ // switch - the loudest "separate pages" tell. The track collapses to width 0
368
+ // (ws-pane-collapsed) instead of being removed (ws-no-pane), so chat/history/
369
+ // files/live/settings all keep the same column geometry.
370
+ const keepPaneTrack = stableFrame && !hasPane;
361
371
  const railIsCollapsed = wsCollapsed('rail', railCollapsed);
362
372
  const paneIsCollapsed = hasPane ? wsCollapsed('pane', paneCollapsed) : true;
363
373
  const shellCls = 'ws-shell'
364
374
  + (railIsCollapsed ? ' ws-rail-collapsed' : '')
365
- + (hasPane ? '' : ' ws-no-pane')
366
- + (hasPane && paneIsCollapsed ? ' ws-pane-collapsed' : '')
375
+ + ((hasPane || keepPaneTrack) ? '' : ' ws-no-pane')
376
+ + (((hasPane && paneIsCollapsed) || keepPaneTrack) ? ' ws-pane-collapsed' : '')
367
377
  + (hasSessions ? '' : ' ws-no-sessions')
368
378
  + (narrow ? ' narrow' : '');
369
379
  return h('div', { class: shellCls },
package/src/components.js CHANGED
@@ -35,13 +35,13 @@ export { ContextPane } from './components/context-pane.js';
35
35
 
36
36
  export {
37
37
  fileGlyph, fmtFileSize,
38
- FileIcon, FileRow, FileGrid, FileSkeleton, sortFiles, FileToolbar,
38
+ FileIcon, FileRow, FileGrid, FileSkeleton, sortFiles, FileToolbar, RootsPicker,
39
39
  DropZone, UploadProgress, EmptyState, BreadcrumbPath
40
40
  } from './components/files.js';
41
41
 
42
42
  export {
43
43
  ConfirmDialog, PromptDialog,
44
- FilePreviewMedia, FilePreviewCode, FilePreviewText, FileViewer
44
+ FilePreviewMedia, FilePreviewCode, FilePreviewText, FileViewer, FilePreviewPane
45
45
  } from './components/files-modals.js';
46
46
 
47
47
  export {
@@ -182,3 +182,13 @@
182
182
  border: none;
183
183
  background: var(--os-bg-0);
184
184
  }
185
+
186
+ /* Touch tap-target floor for the browser pane toolbar. The back/forward/reload
187
+ * buttons and the URL field are 28px by default (no @media anywhere), below the
188
+ * 44px touch minimum on tablets and phones. Lift them on coarse pointers and
189
+ * grow the bar so the controls fit with breathing room. */
190
+ @media (hover: none), (pointer: coarse) {
191
+ .browser-app-bar { min-height: 52px; padding: 6px var(--space-2); }
192
+ .browser-app-btn { min-height: var(--os-tap, 44px); height: var(--os-tap, 44px); min-width: var(--os-tap, 44px); }
193
+ .browser-app-url { height: var(--os-tap, 44px); }
194
+ }
@@ -1347,3 +1347,139 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1347
1347
  font-size: 11px;
1348
1348
  padding: 2px 8px;
1349
1349
  }
1350
+
1351
+ /* ============================================================
1352
+ * thebird RESPONSIVE PERFECTION layer (desk / tablet / mobile).
1353
+ * Appended LAST so .ds-247420-scoped rules here win source order over the
1354
+ * earlier brand overrides (.ds-247420 .wm-root{inset:0!important} at the
1355
+ * "bars overlay" block, .ds-247420 .wm-bar{height:34px!important}, the
1356
+ * unconditional .ds-247420 .os-instances{display:flex}) that were silently
1357
+ * defeating the @media(max-width:767px)/(768-1023px) contracts. Every rule
1358
+ * below is a measured fix for a confirmed responsive-audit finding.
1359
+ *
1360
+ * View classes: desktop >1023px (free-float windows, full menubar);
1361
+ * tablet 768..1023px (side-rail, wm-root left-offset); mobile <=767px AND
1362
+ * short landscape phones (full-screen windows, collapsed menubar, bottom
1363
+ * scroll-snap taskbar). Touch sizing is driven by (pointer:coarse) so it
1364
+ * also covers the landscape-phone band that width-only queries miss.
1365
+ * ============================================================ */
1366
+
1367
+ /* --- mobile bar height: the kit intends a touch-friendly 52px; the brand
1368
+ * layer pinned --os-bar-h-mobile to 34px which left no room for 44px tap
1369
+ * targets in the bar. Restore 52px on mobile/touch. --- */
1370
+ @media (max-width: 767px), (max-height: 500px) and (orientation: landscape) {
1371
+ .ds-247420 { --os-bar-h-mobile: 52px !important; --os-bar-h: 52px !important; }
1372
+ }
1373
+
1374
+ /* --- mobile + landscape-phone full-screen windows. The earlier
1375
+ * .ds-247420 .wm-root{inset:0!important} forced windows over the bars so the
1376
+ * titlebar close button landed under the menubar (occluded, untappable) and
1377
+ * window content underlapped the taskbar. Re-assert the bar-inset at scoped
1378
+ * specificity so windows sit BETWEEN the bars. --- */
1379
+ @media (max-width: 767px), (max-height: 500px) and (orientation: landscape) {
1380
+ .ds-247420 .wm-root {
1381
+ top: calc(var(--os-bar-h) + env(safe-area-inset-top, 0px)) !important;
1382
+ bottom: calc(var(--os-bar-h) + env(safe-area-inset-bottom, 0px)) !important;
1383
+ inset: calc(var(--os-bar-h) + env(safe-area-inset-top, 0px)) 0
1384
+ calc(var(--os-bar-h) + env(safe-area-inset-bottom, 0px)) 0 !important;
1385
+ }
1386
+ .ds-247420 .wm-win {
1387
+ position: absolute !important;
1388
+ left: 0 !important; top: 0 !important;
1389
+ width: 100% !important; height: 100% !important;
1390
+ border: none !important; border-radius: 0 !important; box-shadow: none !important;
1391
+ }
1392
+ /* titlebar must host a 44px close button -> 44px bar (beats the 34px brand clamp) */
1393
+ .ds-247420 .wm-bar {
1394
+ height: 44px !important; min-height: 44px !important;
1395
+ padding: 0 10px !important; align-items: center !important;
1396
+ pointer-events: none;
1397
+ }
1398
+ .ds-247420 .wm-bar .wm-title { pointer-events: auto; }
1399
+ .ds-247420 .wm-bar .wm-btns { pointer-events: auto; }
1400
+ /* hide min+max on mobile full-screen; keep close at 44x44 fully inside the bar */
1401
+ .ds-247420 .wm-btns .wm-btn:nth-child(1),
1402
+ .ds-247420 .wm-btns .wm-btn:nth-child(2) { display: none !important; }
1403
+ .ds-247420 .wm-btns .wm-btn:nth-child(3) {
1404
+ width: 44px !important; height: 44px !important;
1405
+ border-radius: var(--r-1, 6px) !important;
1406
+ background: var(--os-bg-3) !important; color: var(--os-fg) !important;
1407
+ }
1408
+ .ds-247420 .wm-resize { display: none !important; }
1409
+ /* collapse the menubar workspace cluster on mobile (the unconditional
1410
+ * .ds-247420 .os-instances{display:flex} otherwise leaves it visible) */
1411
+ .ds-247420 .os-menubar .os-instances,
1412
+ .ds-247420 .os-instances { display: none !important; }
1413
+ .ds-247420 .os-menubar [data-role="add"],
1414
+ .ds-247420 .tb-sess-add { display: none !important; }
1415
+ }
1416
+
1417
+ /* --- landscape-phone (short + wide + touch): also hide the side-rail that the
1418
+ * 768-1023 tablet band would otherwise show, and force the mobile menubar. --- */
1419
+ @media (max-height: 500px) and (orientation: landscape) and (pointer: coarse) {
1420
+ .ds-247420 .os-side-rail { display: none !important; }
1421
+ }
1422
+
1423
+ /* --- tablet (768..1023): the side-rail offset for .wm-root was defeated by
1424
+ * the scoped inset:0; re-assert it at scoped specificity using the inset
1425
+ * shorthand so it actually wins. --- */
1426
+ @media (min-width: 768px) and (max-width: 1023px) {
1427
+ .ds-247420 .wm-root {
1428
+ left: var(--os-rail-w) !important;
1429
+ inset: 0 0 0 var(--os-rail-w) !important;
1430
+ }
1431
+ }
1432
+
1433
+ /* --- universal touch tap-target floor (pointer:coarse covers tablets AND
1434
+ * landscape phones that width-only queries miss). Every interactive control
1435
+ * the audit measured below 44px is lifted to the --os-tap (44px) token. --- */
1436
+ @media (pointer: coarse) {
1437
+ /* window chrome */
1438
+ .ds-247420 .wm-btns .wm-btn { min-width: var(--os-tap, 44px); min-height: var(--os-tap, 44px); }
1439
+ .ds-247420 .wm-resize { width: var(--os-tap, 44px); height: var(--os-tap, 44px); }
1440
+ /* taskbar tasks (also widen and snap on the whole touch band, not mobile-only) */
1441
+ .ds-247420 .os-task {
1442
+ min-height: var(--os-tap, 44px); min-width: 120px;
1443
+ padding: 10px 14px; scroll-snap-align: start;
1444
+ }
1445
+ .ds-247420 .os-taskbar { scroll-snap-type: x proximity; }
1446
+ /* menubar workspace controls (when shown on tablet) */
1447
+ .ds-247420 .os-menubar .tb-sess-x { min-width: var(--os-tap, 44px); min-height: var(--os-tap, 44px); }
1448
+ .ds-247420 .tb-sess-chip { min-height: var(--os-tap, 44px); }
1449
+ .ds-247420 .tb-sess-add { min-height: var(--os-tap, 44px); }
1450
+ /* modal controls */
1451
+ .ds-247420 .tb-sess-modal-input { height: var(--os-tap, 44px); min-height: var(--os-tap, 44px); }
1452
+ .ds-247420 .tb-sess-modal-btn { min-height: var(--os-tap, 44px); }
1453
+ .ds-247420 .tb-sess-modal-x { min-width: var(--os-tap, 44px); min-height: var(--os-tap, 44px); }
1454
+ /* files-app rows + per-row actions */
1455
+ .ds-247420 .fsb-row { min-height: var(--os-tap, 44px); }
1456
+ .ds-247420 .fsb-act {
1457
+ min-width: var(--os-tap, 44px); min-height: var(--os-tap, 44px);
1458
+ display: inline-flex; align-items: center; justify-content: center;
1459
+ }
1460
+ /* chat composer controls */
1461
+ .ds-247420 .chat-composer .send { width: var(--os-tap, 44px); height: var(--os-tap, 44px); }
1462
+ .ds-247420 .cc-toggle { min-height: var(--os-tap, 44px); }
1463
+ }
1464
+
1465
+ /* --- files-app row actions must reveal on coarse pointers too (the existing
1466
+ * trigger keyed only on hover:none, which fails on hybrid touch+hover
1467
+ * tablets that also report a hover-capable pointer). --- */
1468
+ @media (hover: none), (pointer: coarse) {
1469
+ .ds-247420 .fsb-actions { opacity: 1; }
1470
+ }
1471
+
1472
+ /* --- modals: a content-tall card had no max-height and the overlay did not
1473
+ * scroll, so the footer (primary action) was stranded off-canvas. Cap the
1474
+ * card to the visible viewport, scroll the body, honor safe-area. --- */
1475
+ .ds-247420 .tb-sess-overlay {
1476
+ overflow-y: auto;
1477
+ padding: max(12px, env(safe-area-inset-top, 0px)) max(12px, env(safe-area-inset-right, 0px))
1478
+ max(12px, env(safe-area-inset-bottom, 0px)) max(12px, env(safe-area-inset-left, 0px));
1479
+ }
1480
+ .ds-247420 .tb-sess-modal { max-height: calc(100svh - 24px); display: flex; flex-direction: column; }
1481
+ .ds-247420 .tb-sess-modal-body { overflow-y: auto; min-height: 0; }
1482
+
1483
+ /* --- browser-pane: the generic .app-pane 16px prose padding stranded the
1484
+ * iframe 16px on every side; the browser pane is full-bleed. --- */
1485
+ .ds-247420 .app-pane.browser-app { padding: 0 !important; }