@ai-matrx/canvas 0.5.3 → 0.6.1
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/CHANGELOG.md +27 -0
- package/README.md +6 -0
- package/dist/index.cjs +45 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +45 -9
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +247 -59
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +251 -62
- package/dist/react.js.map +1 -1
- package/dist/styles.css +66 -27
- package/dist/{toggleKind-BD78LnMB.d.cts → toggleKind-DhDmWExm.d.cts} +27 -1
- package/dist/{toggleKind-BD78LnMB.d.ts → toggleKind-DhDmWExm.d.ts} +27 -1
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -258,12 +258,14 @@
|
|
|
258
258
|
gap: 0.125rem;
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
/* Nothing leading: no box and no gap of its own — the tabs keep that room; the actions still sit at the end. */
|
|
261
262
|
.mxc-pane-leading:empty {
|
|
262
|
-
|
|
263
|
+
display: none;
|
|
263
264
|
}
|
|
264
265
|
|
|
265
266
|
.mxc-pane-actions {
|
|
266
267
|
flex: none;
|
|
268
|
+
margin-left: auto;
|
|
267
269
|
display: flex;
|
|
268
270
|
align-items: center;
|
|
269
271
|
gap: 0.125rem;
|
|
@@ -403,40 +405,74 @@
|
|
|
403
405
|
|
|
404
406
|
/* ── tabs ───────────────────────────────────────────────────────────────── */
|
|
405
407
|
|
|
408
|
+
/*
|
|
409
|
+
* THE STRIP takes the header's free width (flex 1): its tabs are laid out in
|
|
410
|
+
* real room, never in the strip's own intrinsic size — browsers undercount a
|
|
411
|
+
* row of text tabs by a few px each, which cut every name ("Quic", "Messa").
|
|
412
|
+
* Past the tabs' minimum the strip scrolls, and says so: the clipped edge
|
|
413
|
+
* fades and chevrons appear.
|
|
414
|
+
*/
|
|
415
|
+
.mxc-tabstrip {
|
|
416
|
+
flex: 1 1 auto;
|
|
417
|
+
min-width: 0;
|
|
418
|
+
display: flex;
|
|
419
|
+
align-items: center;
|
|
420
|
+
gap: 0.125rem;
|
|
421
|
+
}
|
|
422
|
+
|
|
406
423
|
.mxc-tabs {
|
|
407
424
|
/* The tabs' offset parent, so "keep the active tab in view" measures in strip coordinates. */
|
|
408
425
|
position: relative;
|
|
409
|
-
flex:
|
|
426
|
+
flex: 1 1 auto;
|
|
410
427
|
min-width: 0;
|
|
411
428
|
display: flex;
|
|
412
429
|
align-items: center;
|
|
413
430
|
gap: 0.125rem;
|
|
414
431
|
overflow-x: auto;
|
|
415
432
|
scrollbar-width: none;
|
|
433
|
+
--mxc-fade-start: 0px;
|
|
434
|
+
--mxc-fade-end: 0px;
|
|
416
435
|
}
|
|
417
436
|
|
|
418
437
|
.mxc-tabs::-webkit-scrollbar {
|
|
419
438
|
display: none;
|
|
420
439
|
}
|
|
421
440
|
|
|
441
|
+
/* Overflow cue: the clipped edge(s) fade out. */
|
|
442
|
+
.mxc-tabstrip[data-overflow-start] > .mxc-tabs {
|
|
443
|
+
--mxc-fade-start: 1.5rem;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.mxc-tabstrip[data-overflow-end] > .mxc-tabs {
|
|
447
|
+
--mxc-fade-end: 1.5rem;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.mxc-tabstrip[data-overflow] > .mxc-tabs {
|
|
451
|
+
-webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--mxc-fade-start), #000 calc(100% - var(--mxc-fade-end)), transparent 100%);
|
|
452
|
+
mask-image: linear-gradient(to right, transparent 0, #000 var(--mxc-fade-start), #000 calc(100% - var(--mxc-fade-end)), transparent 100%);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.mxc-tabs-scroll {
|
|
456
|
+
flex: none;
|
|
457
|
+
}
|
|
458
|
+
|
|
422
459
|
/*
|
|
423
460
|
* TAB DENSITY (Claude Code / Codex): 12.5px text, a 14px icon, 6px side
|
|
424
|
-
* padding.
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
461
|
+
* padding. A tab is as wide as its name (up to 12rem); tabs shrink evenly
|
|
462
|
+
* only when the header is out of room, to a 4.5rem floor (a tab is never
|
|
463
|
+
* squeezed to three letters), then the strip scrolls. The active tab keeps
|
|
464
|
+
* icon + ~10 letters and reserves the room of its (always shown) close, so
|
|
465
|
+
* its name is never under the button. A background tab's close costs no
|
|
466
|
+
* width: on hover it is overlaid and the name's end fades under it.
|
|
430
467
|
*/
|
|
431
468
|
.mxc-tab {
|
|
432
469
|
position: relative;
|
|
433
|
-
flex:
|
|
470
|
+
flex: 0 1 auto;
|
|
434
471
|
min-width: 4.5rem;
|
|
435
472
|
max-width: 12rem;
|
|
436
|
-
container: mxc-tab / inline-size;
|
|
437
473
|
display: flex;
|
|
438
474
|
align-items: center;
|
|
439
|
-
gap: 0.
|
|
475
|
+
gap: 0.25rem;
|
|
440
476
|
height: 1.625rem;
|
|
441
477
|
padding: 0 0.375rem;
|
|
442
478
|
border-radius: 0.375rem;
|
|
@@ -449,6 +485,11 @@
|
|
|
449
485
|
box-sizing: border-box;
|
|
450
486
|
}
|
|
451
487
|
|
|
488
|
+
/* The active tab always shows its close: its room is reserved. */
|
|
489
|
+
.mxc-tab[data-active]:has(> .mxc-tab-close) {
|
|
490
|
+
padding-right: 1.25rem;
|
|
491
|
+
}
|
|
492
|
+
|
|
452
493
|
.mxc-tab[data-active] {
|
|
453
494
|
min-width: min(7.5rem, 100%);
|
|
454
495
|
background: var(--mxc-tab-active-bg);
|
|
@@ -480,12 +521,6 @@
|
|
|
480
521
|
opacity: 0.75;
|
|
481
522
|
}
|
|
482
523
|
|
|
483
|
-
@container mxc-tab (max-width: 6rem) {
|
|
484
|
-
.mxc-tab:not([data-active]) .mxc-tab-icon {
|
|
485
|
-
display: none;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
524
|
.mxc-tab-icon svg,
|
|
490
525
|
.mxc-favicon {
|
|
491
526
|
width: 0.875rem;
|
|
@@ -497,26 +532,27 @@
|
|
|
497
532
|
}
|
|
498
533
|
|
|
499
534
|
.mxc-tab-title {
|
|
500
|
-
flex:
|
|
535
|
+
flex: 0 1 auto;
|
|
501
536
|
min-width: 0;
|
|
502
537
|
overflow: hidden;
|
|
538
|
+
/* Never an ellipsis: system fonts overflow their intrinsic width by a fraction of a pixel. */
|
|
503
539
|
text-overflow: clip;
|
|
504
540
|
white-space: nowrap;
|
|
505
541
|
}
|
|
506
542
|
|
|
507
|
-
/*
|
|
508
|
-
.mxc-tab
|
|
509
|
-
.mxc-tab[data-active] .mxc-tab-title,
|
|
510
|
-
.mxc-tab:focus-within .mxc-tab-title {
|
|
511
|
-
-webkit-mask-image: linear-gradient(to left, transparent 1.125rem, #000 1.875rem);
|
|
512
|
-
mask-image: linear-gradient(to left, transparent 1.125rem, #000 1.875rem);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
.mxc-tab:not(:hover):not([data-active]):not(:focus-within) .mxc-tab-title {
|
|
543
|
+
/* A name that is really cut (data-truncated, measured) fades at its end. */
|
|
544
|
+
.mxc-tab[data-truncated] .mxc-tab-title {
|
|
516
545
|
-webkit-mask-image: linear-gradient(to left, transparent 0, #000 0.75rem);
|
|
517
546
|
mask-image: linear-gradient(to left, transparent 0, #000 0.75rem);
|
|
518
547
|
}
|
|
519
548
|
|
|
549
|
+
/* A background tab's close is overlaid while shown: the name's end fades under it. */
|
|
550
|
+
.mxc-tab:not([data-active]):hover:has(> .mxc-tab-close) .mxc-tab-title,
|
|
551
|
+
.mxc-tab:not([data-active]):focus-within:has(> .mxc-tab-close) .mxc-tab-title {
|
|
552
|
+
-webkit-mask-image: linear-gradient(to left, transparent 1.125rem, #000 1.875rem);
|
|
553
|
+
mask-image: linear-gradient(to left, transparent 1.125rem, #000 1.875rem);
|
|
554
|
+
}
|
|
555
|
+
|
|
520
556
|
.mxc-tab-note {
|
|
521
557
|
flex: none;
|
|
522
558
|
font-size: 0.6875rem;
|
|
@@ -754,6 +790,9 @@
|
|
|
754
790
|
}
|
|
755
791
|
|
|
756
792
|
.mxc-launcher-item {
|
|
793
|
+
/* A double-click must never select the label (or the new tab under it). */
|
|
794
|
+
user-select: none;
|
|
795
|
+
-webkit-user-select: none;
|
|
757
796
|
display: flex;
|
|
758
797
|
align-items: center;
|
|
759
798
|
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 {
|
|
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 {
|
|
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.
|
|
3
|
+
"version": "0.6.1",
|
|
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",
|