@ai-matrx/canvas 0.5.2 → 0.6.0

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/dist/styles.css CHANGED
@@ -269,6 +269,14 @@
269
269
  gap: 0.125rem;
270
270
  }
271
271
 
272
+ /* A kind's own header controls: no gap of ours (tap buttons carry their own spacing). */
273
+ .mxc-kind-actions {
274
+ display: inline-flex;
275
+ align-items: center;
276
+ gap: 0;
277
+ min-width: 0;
278
+ }
279
+
272
280
  .mxc-pane-body {
273
281
  position: relative;
274
282
  flex: 1 1 auto;
@@ -395,6 +403,20 @@
395
403
 
396
404
  /* ── tabs ───────────────────────────────────────────────────────────────── */
397
405
 
406
+ /*
407
+ * THE STRIP takes what the header has: it is as wide as its tabs need (the
408
+ * leading slot after it has no basis), so "+" sits right after the last tab
409
+ * and only shrinks when the header runs out of room. Past the tabs' minimum
410
+ * the strip scrolls, and says so: the clipped edge fades and chevrons appear.
411
+ */
412
+ .mxc-tabstrip {
413
+ flex: 0 1 auto;
414
+ min-width: 0;
415
+ display: flex;
416
+ align-items: center;
417
+ gap: 0.125rem;
418
+ }
419
+
398
420
  .mxc-tabs {
399
421
  /* The tabs' offset parent, so "keep the active tab in view" measures in strip coordinates. */
400
422
  position: relative;
@@ -405,32 +427,50 @@
405
427
  gap: 0.125rem;
406
428
  overflow-x: auto;
407
429
  scrollbar-width: none;
430
+ --mxc-fade-start: 0px;
431
+ --mxc-fade-end: 0px;
408
432
  }
409
433
 
410
434
  .mxc-tabs::-webkit-scrollbar {
411
435
  display: none;
412
436
  }
413
437
 
438
+ /* Overflow cue: the clipped edge(s) fade out. */
439
+ .mxc-tabstrip[data-overflow-start] > .mxc-tabs {
440
+ --mxc-fade-start: 1.5rem;
441
+ }
442
+
443
+ .mxc-tabstrip[data-overflow-end] > .mxc-tabs {
444
+ --mxc-fade-end: 1.5rem;
445
+ }
446
+
447
+ .mxc-tabstrip[data-overflow] > .mxc-tabs {
448
+ -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--mxc-fade-start), #000 calc(100% - var(--mxc-fade-end)), transparent 100%);
449
+ mask-image: linear-gradient(to right, transparent 0, #000 var(--mxc-fade-start), #000 calc(100% - var(--mxc-fade-end)), transparent 100%);
450
+ }
451
+
452
+ .mxc-tabs-scroll {
453
+ flex: none;
454
+ }
455
+
414
456
  /*
415
457
  * TAB DENSITY (Claude Code / Codex): 12.5px text, a 14px icon, 6px side
416
- * padding. Tabs shrink evenly from 8rem to a 4.5rem floor, then the strip
417
- * scrolls (a tab is never squeezed to three letters). A background tab
418
- * narrower than 6rem drops its icon so its name keeps the room. The active
419
- * tab keeps icon + ~10 letters + its close.
420
- * The close button is OVERLAID on the tab's end and costs no width while
421
- * hidden; shown (hover, active, focus) the title fades under it.
458
+ * padding. A tab is as wide as its name (up to 12rem); tabs shrink evenly
459
+ * only when the header is out of room, to a 4.5rem floor (a tab is never
460
+ * squeezed to three letters), then the strip scrolls. The active tab keeps
461
+ * icon + ~10 letters. Every tab reserves the room of its close, so a name is
462
+ * never under the button; the close shows on hover, the active tab and focus.
422
463
  */
423
464
  .mxc-tab {
424
465
  position: relative;
425
- flex: 1 1 8rem;
466
+ flex: 0 1 auto;
426
467
  min-width: 4.5rem;
427
468
  max-width: 12rem;
428
- container: mxc-tab / inline-size;
429
469
  display: flex;
430
470
  align-items: center;
431
471
  gap: 0.3125rem;
432
472
  height: 1.625rem;
433
- padding: 0 0.375rem;
473
+ padding: 0 1.375rem 0 0.375rem;
434
474
  border-radius: 0.375rem;
435
475
  font-size: 0.78125rem;
436
476
  line-height: 1rem;
@@ -441,6 +481,11 @@
441
481
  box-sizing: border-box;
442
482
  }
443
483
 
484
+ /* A tab without a close (BrowserTabs with no onClose) keeps even padding. */
485
+ .mxc-tab:not(:has(> .mxc-tab-close)) {
486
+ padding-right: 0.375rem;
487
+ }
488
+
444
489
  .mxc-tab[data-active] {
445
490
  min-width: min(7.5rem, 100%);
446
491
  background: var(--mxc-tab-active-bg);
@@ -472,12 +517,6 @@
472
517
  opacity: 0.75;
473
518
  }
474
519
 
475
- @container mxc-tab (max-width: 6rem) {
476
- .mxc-tab:not([data-active]) .mxc-tab-icon {
477
- display: none;
478
- }
479
- }
480
-
481
520
  .mxc-tab-icon svg,
482
521
  .mxc-favicon {
483
522
  width: 0.875rem;
@@ -489,26 +528,13 @@
489
528
  }
490
529
 
491
530
  .mxc-tab-title {
492
- flex: 1 1 auto;
531
+ flex: 0 1 auto;
493
532
  min-width: 0;
494
533
  overflow: hidden;
495
- text-overflow: clip;
534
+ text-overflow: ellipsis;
496
535
  white-space: nowrap;
497
536
  }
498
537
 
499
- /* The close shows: the title's end fades out from under it. */
500
- .mxc-tab:hover .mxc-tab-title,
501
- .mxc-tab[data-active] .mxc-tab-title,
502
- .mxc-tab:focus-within .mxc-tab-title {
503
- -webkit-mask-image: linear-gradient(to left, transparent 1.125rem, #000 1.875rem);
504
- mask-image: linear-gradient(to left, transparent 1.125rem, #000 1.875rem);
505
- }
506
-
507
- .mxc-tab:not(:hover):not([data-active]):not(:focus-within) .mxc-tab-title {
508
- -webkit-mask-image: linear-gradient(to left, transparent 0, #000 0.75rem);
509
- mask-image: linear-gradient(to left, transparent 0, #000 0.75rem);
510
- }
511
-
512
538
  .mxc-tab-note {
513
539
  flex: none;
514
540
  font-size: 0.6875rem;
@@ -746,6 +772,9 @@
746
772
  }
747
773
 
748
774
  .mxc-launcher-item {
775
+ /* A double-click must never select the label (or the new tab under it). */
776
+ user-select: none;
777
+ -webkit-user-select: none;
749
778
  display: flex;
750
779
  align-items: center;
751
780
  gap: 0.5rem;
@@ -46,11 +46,24 @@ interface CanvasHistoryEntry {
46
46
  readonly key: string;
47
47
  readonly title: string | null;
48
48
  readonly data: CanvasJson;
49
+ /**
50
+ * The body this content had (its item's `instance`). Back and a navigate to
51
+ * a kept step reuse it, so the SAME live body comes back (a typed draft, a
52
+ * scroll position) while the layer still holds it mounted.
53
+ */
54
+ readonly instance?: string | undefined;
49
55
  }
50
56
  /** The built-in "New tab" item: the launcher, shown as a tab. Never registered as a kind. */
51
57
  declare const CANVAS_LAUNCHER_KIND = "canvas.launcher";
52
58
  /** How many steps Back can go in one tab. Older entries fall off. */
53
59
  declare const CANVAS_HISTORY_LIMIT = 50;
60
+ /**
61
+ * How many earlier contents of one tab keep their body MOUNTED (hidden), in
62
+ * each direction: the newest steps Back reaches, and the contents Back left
63
+ * (`CanvasItem.kept`). Older steps still work — their body mounts fresh.
64
+ * Only closing the tab disposes the kept bodies.
65
+ */
66
+ declare const CANVAS_KEEP_ALIVE_DEPTH = 5;
54
67
  interface CanvasItem {
55
68
  readonly id: CanvasItemId;
56
69
  /** Registered kind id (see `registerCanvasKind`). */
@@ -64,6 +77,13 @@ interface CanvasItem {
64
77
  readonly updatedAt: number;
65
78
  /** Earlier contents of this tab, oldest first (navigate in place). Absent = no Back. */
66
79
  readonly history?: readonly CanvasHistoryEntry[] | undefined;
80
+ /**
81
+ * Contents this tab showed that Back has stepped away from (newest last, at
82
+ * most CANVAS_KEEP_ALIVE_DEPTH). Navigating to one again brings back its
83
+ * live body instead of a new one: "+" → Quick Chat → type → Back → Quick
84
+ * Chat finds the draft.
85
+ */
86
+ readonly kept?: readonly CanvasHistoryEntry[] | undefined;
67
87
  /**
68
88
  * The mounted body's identity. Minted when the item is created and kept by
69
89
  * `rekey`, so a draft that receives its durable id keeps its live body.
@@ -661,6 +681,12 @@ interface CanvasPresentation {
661
681
  /** How many panes the window's canvas shows right now. */
662
682
  readonly paneCount: number;
663
683
  }
684
+ /**
685
+ * THE phone breakpoint: a viewport at most this wide (CSS px) is a phone —
686
+ * the canvas is a full-screen layer and presents ONE pane at a time. Same
687
+ * number as styles.css `@media (max-width: 767px)`.
688
+ */
689
+ declare const CANVAS_PHONE_MAX_WIDTH = 767;
664
690
  /** Under this width (px) a body is narrow. */
665
691
  declare const CANVAS_NARROW_WIDTH = 480;
666
692
  declare function canvasOrientation(width: number, height: number): CanvasPresentationOrientation;
@@ -706,4 +732,4 @@ interface ToggleKindInput {
706
732
  /** Returns what the item is after the click. */
707
733
  declare function toggleKind(controller: CanvasController, input: ToggleKindInput): CanvasKindVisibility;
708
734
 
709
- export { canvasPresentation as $, type CanvasErrorSink as A, type CanvasKeyValueStore as B, type CanvasItemId as C, type CanvasKindVisibility as D, type CanvasLayoutRules as E, type CanvasNavigateInput as F, type CanvasOpenInput as G, type CanvasOpenTarget as H, type CanvasOrientation as I, type CanvasPersistencePort as J, type CanvasPreferredTarget as K, type CanvasPresentation as L, type CanvasPresentationOrientation as M, type CanvasRect as N, type CanvasSessionAttachReason as O, type CanvasSessionDetachReason as P, type CanvasSessionEvent as Q, type CanvasSessionHooks as R, type CanvasSplitId as S, type CanvasWindowCloseMode as T, type CanvasWindowFrame as U, type CanvasWindowPorts as V, type ReduxStoreLike as W, type ToggleKindInput as X, bindCanvasToReduxStore as Y, canvasActions as Z, canvasOrientation as _, type CanvasWindowId as a, canvasReducer as a0, canvasWindowFrame as a1, canvasWindowOfPane as a2, clampDraggedCanvasWidth as a3, consoleCanvasErrorSink as a4, createCanvasController as a5, createCanvasStore as a6, createInitialCanvasState as a7, createKeyValueCanvasPersistence as a8, createLocalStorageCanvasPersistence as a9, defaultCanvasWidth as aa, fitCanvasWidth as ab, foldCanvasWindows as ac, isCanvasAction as ad, listCanvasWindowIds as ae, preferredFlowDirection as af, resolveCanvasLayoutRules as ag, sanitizeCanvasSnapshot as ah, selectCanvasKindVisibility as ai, shouldStackSplit as aj, toPersistableSnapshot as ak, toggleKind as al, type CanvasJson as b, type CanvasLayoutNode as c, type CanvasPaneId as d, type CanvasStoreBinding as e, type CanvasState as f, type CanvasAction as g, type CanvasController as h, type CanvasItem as i, type CanvasExtraWindow as j, type CanvasHistoryEntry as k, type CanvasPane as l, canvasWindowOfItem as m, CANVAS_DEFAULT_KEY as n, CANVAS_DEFAULT_WIDTH as o, CANVAS_DESKTOP_LAYOUT_RULES as p, CANVAS_HISTORY_LIMIT as q, CANVAS_LAUNCHER_KIND as r, CANVAS_MAIN_WINDOW as s, CANVAS_MIN_SPLIT_FRACTION as t, CANVAS_MIN_WIDTH as u, CANVAS_NARROW_WIDTH as v, CANVAS_STORAGE_KEY as w, CANVAS_WEB_LAYOUT_RULES as x, type CanvasControllerOptions as y, type CanvasErrorReport as z };
735
+ export { canvasActions as $, type CanvasControllerOptions as A, type CanvasErrorReport as B, type CanvasItemId as C, type CanvasErrorSink as D, type CanvasKeyValueStore as E, type CanvasKindVisibility as F, type CanvasLayoutRules as G, type CanvasNavigateInput as H, type CanvasOpenInput as I, type CanvasOpenTarget as J, type CanvasOrientation as K, type CanvasPersistencePort as L, type CanvasPreferredTarget as M, type CanvasPresentation as N, type CanvasPresentationOrientation as O, type CanvasRect as P, type CanvasSessionAttachReason as Q, type CanvasSessionDetachReason as R, type CanvasSessionEvent as S, type CanvasSessionHooks as T, type CanvasSplitId as U, type CanvasWindowCloseMode as V, type CanvasWindowFrame as W, type CanvasWindowPorts as X, type ReduxStoreLike as Y, type ToggleKindInput as Z, bindCanvasToReduxStore as _, type CanvasWindowId as a, canvasOrientation as a0, canvasPresentation as a1, canvasReducer as a2, canvasWindowFrame as a3, canvasWindowOfPane as a4, clampDraggedCanvasWidth as a5, consoleCanvasErrorSink as a6, createCanvasController as a7, createCanvasStore as a8, createInitialCanvasState as a9, createKeyValueCanvasPersistence as aa, createLocalStorageCanvasPersistence as ab, defaultCanvasWidth as ac, fitCanvasWidth as ad, foldCanvasWindows as ae, isCanvasAction as af, listCanvasWindowIds as ag, preferredFlowDirection as ah, resolveCanvasLayoutRules as ai, sanitizeCanvasSnapshot as aj, selectCanvasKindVisibility as ak, shouldStackSplit as al, toPersistableSnapshot as am, toggleKind as an, type CanvasJson as b, type CanvasLayoutNode as c, type CanvasPaneId as d, type CanvasStoreBinding as e, type CanvasState as f, type CanvasAction as g, type CanvasController as h, type CanvasItem as i, type CanvasExtraWindow as j, type CanvasHistoryEntry as k, type CanvasPane as l, canvasWindowOfItem as m, CANVAS_DEFAULT_KEY as n, CANVAS_DEFAULT_WIDTH as o, CANVAS_DESKTOP_LAYOUT_RULES as p, CANVAS_HISTORY_LIMIT as q, CANVAS_KEEP_ALIVE_DEPTH as r, CANVAS_LAUNCHER_KIND as s, CANVAS_MAIN_WINDOW as t, CANVAS_MIN_SPLIT_FRACTION as u, CANVAS_MIN_WIDTH as v, CANVAS_NARROW_WIDTH as w, CANVAS_PHONE_MAX_WIDTH as x, CANVAS_STORAGE_KEY as y, CANVAS_WEB_LAYOUT_RULES as z };
@@ -46,11 +46,24 @@ interface CanvasHistoryEntry {
46
46
  readonly key: string;
47
47
  readonly title: string | null;
48
48
  readonly data: CanvasJson;
49
+ /**
50
+ * The body this content had (its item's `instance`). Back and a navigate to
51
+ * a kept step reuse it, so the SAME live body comes back (a typed draft, a
52
+ * scroll position) while the layer still holds it mounted.
53
+ */
54
+ readonly instance?: string | undefined;
49
55
  }
50
56
  /** The built-in "New tab" item: the launcher, shown as a tab. Never registered as a kind. */
51
57
  declare const CANVAS_LAUNCHER_KIND = "canvas.launcher";
52
58
  /** How many steps Back can go in one tab. Older entries fall off. */
53
59
  declare const CANVAS_HISTORY_LIMIT = 50;
60
+ /**
61
+ * How many earlier contents of one tab keep their body MOUNTED (hidden), in
62
+ * each direction: the newest steps Back reaches, and the contents Back left
63
+ * (`CanvasItem.kept`). Older steps still work — their body mounts fresh.
64
+ * Only closing the tab disposes the kept bodies.
65
+ */
66
+ declare const CANVAS_KEEP_ALIVE_DEPTH = 5;
54
67
  interface CanvasItem {
55
68
  readonly id: CanvasItemId;
56
69
  /** Registered kind id (see `registerCanvasKind`). */
@@ -64,6 +77,13 @@ interface CanvasItem {
64
77
  readonly updatedAt: number;
65
78
  /** Earlier contents of this tab, oldest first (navigate in place). Absent = no Back. */
66
79
  readonly history?: readonly CanvasHistoryEntry[] | undefined;
80
+ /**
81
+ * Contents this tab showed that Back has stepped away from (newest last, at
82
+ * most CANVAS_KEEP_ALIVE_DEPTH). Navigating to one again brings back its
83
+ * live body instead of a new one: "+" → Quick Chat → type → Back → Quick
84
+ * Chat finds the draft.
85
+ */
86
+ readonly kept?: readonly CanvasHistoryEntry[] | undefined;
67
87
  /**
68
88
  * The mounted body's identity. Minted when the item is created and kept by
69
89
  * `rekey`, so a draft that receives its durable id keeps its live body.
@@ -661,6 +681,12 @@ interface CanvasPresentation {
661
681
  /** How many panes the window's canvas shows right now. */
662
682
  readonly paneCount: number;
663
683
  }
684
+ /**
685
+ * THE phone breakpoint: a viewport at most this wide (CSS px) is a phone —
686
+ * the canvas is a full-screen layer and presents ONE pane at a time. Same
687
+ * number as styles.css `@media (max-width: 767px)`.
688
+ */
689
+ declare const CANVAS_PHONE_MAX_WIDTH = 767;
664
690
  /** Under this width (px) a body is narrow. */
665
691
  declare const CANVAS_NARROW_WIDTH = 480;
666
692
  declare function canvasOrientation(width: number, height: number): CanvasPresentationOrientation;
@@ -706,4 +732,4 @@ interface ToggleKindInput {
706
732
  /** Returns what the item is after the click. */
707
733
  declare function toggleKind(controller: CanvasController, input: ToggleKindInput): CanvasKindVisibility;
708
734
 
709
- export { canvasPresentation as $, type CanvasErrorSink as A, type CanvasKeyValueStore as B, type CanvasItemId as C, type CanvasKindVisibility as D, type CanvasLayoutRules as E, type CanvasNavigateInput as F, type CanvasOpenInput as G, type CanvasOpenTarget as H, type CanvasOrientation as I, type CanvasPersistencePort as J, type CanvasPreferredTarget as K, type CanvasPresentation as L, type CanvasPresentationOrientation as M, type CanvasRect as N, type CanvasSessionAttachReason as O, type CanvasSessionDetachReason as P, type CanvasSessionEvent as Q, type CanvasSessionHooks as R, type CanvasSplitId as S, type CanvasWindowCloseMode as T, type CanvasWindowFrame as U, type CanvasWindowPorts as V, type ReduxStoreLike as W, type ToggleKindInput as X, bindCanvasToReduxStore as Y, canvasActions as Z, canvasOrientation as _, type CanvasWindowId as a, canvasReducer as a0, canvasWindowFrame as a1, canvasWindowOfPane as a2, clampDraggedCanvasWidth as a3, consoleCanvasErrorSink as a4, createCanvasController as a5, createCanvasStore as a6, createInitialCanvasState as a7, createKeyValueCanvasPersistence as a8, createLocalStorageCanvasPersistence as a9, defaultCanvasWidth as aa, fitCanvasWidth as ab, foldCanvasWindows as ac, isCanvasAction as ad, listCanvasWindowIds as ae, preferredFlowDirection as af, resolveCanvasLayoutRules as ag, sanitizeCanvasSnapshot as ah, selectCanvasKindVisibility as ai, shouldStackSplit as aj, toPersistableSnapshot as ak, toggleKind as al, type CanvasJson as b, type CanvasLayoutNode as c, type CanvasPaneId as d, type CanvasStoreBinding as e, type CanvasState as f, type CanvasAction as g, type CanvasController as h, type CanvasItem as i, type CanvasExtraWindow as j, type CanvasHistoryEntry as k, type CanvasPane as l, canvasWindowOfItem as m, CANVAS_DEFAULT_KEY as n, CANVAS_DEFAULT_WIDTH as o, CANVAS_DESKTOP_LAYOUT_RULES as p, CANVAS_HISTORY_LIMIT as q, CANVAS_LAUNCHER_KIND as r, CANVAS_MAIN_WINDOW as s, CANVAS_MIN_SPLIT_FRACTION as t, CANVAS_MIN_WIDTH as u, CANVAS_NARROW_WIDTH as v, CANVAS_STORAGE_KEY as w, CANVAS_WEB_LAYOUT_RULES as x, type CanvasControllerOptions as y, type CanvasErrorReport as z };
735
+ export { canvasActions as $, type CanvasControllerOptions as A, type CanvasErrorReport as B, type CanvasItemId as C, type CanvasErrorSink as D, type CanvasKeyValueStore as E, type CanvasKindVisibility as F, type CanvasLayoutRules as G, type CanvasNavigateInput as H, type CanvasOpenInput as I, type CanvasOpenTarget as J, type CanvasOrientation as K, type CanvasPersistencePort as L, type CanvasPreferredTarget as M, type CanvasPresentation as N, type CanvasPresentationOrientation as O, type CanvasRect as P, type CanvasSessionAttachReason as Q, type CanvasSessionDetachReason as R, type CanvasSessionEvent as S, type CanvasSessionHooks as T, type CanvasSplitId as U, type CanvasWindowCloseMode as V, type CanvasWindowFrame as W, type CanvasWindowPorts as X, type ReduxStoreLike as Y, type ToggleKindInput as Z, bindCanvasToReduxStore as _, type CanvasWindowId as a, canvasOrientation as a0, canvasPresentation as a1, canvasReducer as a2, canvasWindowFrame as a3, canvasWindowOfPane as a4, clampDraggedCanvasWidth as a5, consoleCanvasErrorSink as a6, createCanvasController as a7, createCanvasStore as a8, createInitialCanvasState as a9, createKeyValueCanvasPersistence as aa, createLocalStorageCanvasPersistence as ab, defaultCanvasWidth as ac, fitCanvasWidth as ad, foldCanvasWindows as ae, isCanvasAction as af, listCanvasWindowIds as ag, preferredFlowDirection as ah, resolveCanvasLayoutRules as ai, sanitizeCanvasSnapshot as aj, selectCanvasKindVisibility as ak, shouldStackSplit as al, toPersistableSnapshot as am, toggleKind as an, type CanvasJson as b, type CanvasLayoutNode as c, type CanvasPaneId as d, type CanvasStoreBinding as e, type CanvasState as f, type CanvasAction as g, type CanvasController as h, type CanvasItem as i, type CanvasExtraWindow as j, type CanvasHistoryEntry as k, type CanvasPane as l, canvasWindowOfItem as m, CANVAS_DEFAULT_KEY as n, CANVAS_DEFAULT_WIDTH as o, CANVAS_DESKTOP_LAYOUT_RULES as p, CANVAS_HISTORY_LIMIT as q, CANVAS_KEEP_ALIVE_DEPTH as r, CANVAS_LAUNCHER_KIND as s, CANVAS_MAIN_WINDOW as t, CANVAS_MIN_SPLIT_FRACTION as u, CANVAS_MIN_WIDTH as v, CANVAS_NARROW_WIDTH as w, CANVAS_PHONE_MAX_WIDTH as x, CANVAS_STORAGE_KEY as y, CANVAS_WEB_LAYOUT_RULES as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/canvas",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "The AI Matrx canvas: a docked right-hand column with split panes, tabs, full screen, a kind registry, Redux-compatible state and persistence.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",