@1agh/maude 1.4.3 → 1.4.5
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/apps/studio/api.ts +4 -0
- package/apps/studio/canvas-comment-mount.tsx +13 -1
- package/apps/studio/canvas-shell.tsx +62 -13
- package/apps/studio/canvas-source-memo.ts +39 -0
- package/apps/studio/canvas-text-patch.ts +117 -0
- package/apps/studio/client/app.jsx +105 -60
- package/apps/studio/client/file-tree.jsx +157 -0
- package/apps/studio/client/index.html +1 -1
- package/apps/studio/client/panels/DiffView.jsx +37 -8
- package/apps/studio/client/panels/GitPanel.jsx +2 -1
- package/apps/studio/client/panels/SourceConflictPanel.jsx +19 -17
- package/apps/studio/client/styles/3-shell-maude.css +21 -9
- package/apps/studio/client/styles/4-components.css +4 -2
- package/apps/studio/dist/client.bundle.js +1086 -1086
- package/apps/studio/dist/comment-mount.js +2 -2
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/hmr-broadcast.ts +59 -3
- package/apps/studio/http.ts +3 -0
- package/apps/studio/sync/accepted-cold-start.ts +35 -3
- package/apps/studio/sync/accepted-link.ts +165 -29
- package/apps/studio/sync/file-plane.ts +24 -1
- package/apps/studio/sync/index.ts +87 -17
- package/apps/studio/sync/journal-client.ts +9 -3
- package/apps/studio/sync/projection.ts +114 -11
- package/apps/studio/sync/remote-docs.ts +3 -2
- package/apps/studio/sync/source-recovery.ts +67 -0
- package/apps/studio/sync/status.ts +11 -3
- package/apps/studio/sync/transaction-client.ts +49 -4
- package/apps/studio/use-selection-set.tsx +9 -3
- package/apps/studio/use-undo-stack.tsx +22 -2
- package/apps/studio/whats-new.json +9 -0
- package/cli/lib/workspace-plan.mjs +10 -0
- package/package.json +8 -8
- package/plugins/design/templates/_shell.html +21 -0
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
//
|
|
13
13
|
// No hashes, epochs or lane names: "Your version" / "The project's version".
|
|
14
14
|
|
|
15
|
-
import { useEffect, useMemo,
|
|
15
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
16
|
+
import { useLinkDialogFocus } from '../share-dialog.jsx';
|
|
16
17
|
|
|
17
18
|
/** Line diff by longest common subsequence — bounded, for a canvas source. */
|
|
18
19
|
export function lineDiff(a, b, max = 2000) {
|
|
@@ -63,7 +64,7 @@ export default function SourceConflictPanel({ slug, onClose }) {
|
|
|
63
64
|
const [sides, setSides] = useState(null);
|
|
64
65
|
const [error, setError] = useState('');
|
|
65
66
|
const [busy, setBusy] = useState('');
|
|
66
|
-
const ref =
|
|
67
|
+
const ref = useLinkDialogFocus(onClose);
|
|
67
68
|
|
|
68
69
|
useEffect(() => {
|
|
69
70
|
let alive = true;
|
|
@@ -80,19 +81,6 @@ export default function SourceConflictPanel({ slug, onClose }) {
|
|
|
80
81
|
};
|
|
81
82
|
}, [slug]);
|
|
82
83
|
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
const prev = document.activeElement;
|
|
85
|
-
ref.current?.querySelector('button')?.focus();
|
|
86
|
-
const onKey = (e) => {
|
|
87
|
-
if (e.key === 'Escape') onClose();
|
|
88
|
-
};
|
|
89
|
-
document.addEventListener('keydown', onKey);
|
|
90
|
-
return () => {
|
|
91
|
-
document.removeEventListener('keydown', onKey);
|
|
92
|
-
prev?.focus?.();
|
|
93
|
-
};
|
|
94
|
-
}, [onClose]);
|
|
95
|
-
|
|
96
84
|
const rows = useMemo(() => (sides ? withContext(lineDiff(sides.mine ?? '', sides.theirs ?? '')) : []), [sides]);
|
|
97
85
|
|
|
98
86
|
async function choose(choice) {
|
|
@@ -120,8 +108,8 @@ export default function SourceConflictPanel({ slug, onClose }) {
|
|
|
120
108
|
<div className="gi-dialog scp-dialog" ref={ref} data-testid="source-conflict-panel">
|
|
121
109
|
<div className="tp-dialog-head">
|
|
122
110
|
<div>
|
|
123
|
-
<h2 id="scp-title">
|
|
124
|
-
<p>Your
|
|
111
|
+
<h2 id="scp-title">Review changes to {slug}</h2>
|
|
112
|
+
<p>Your draft has not been shared. Compare it with the project’s version before choosing what to keep.</p>
|
|
125
113
|
</div>
|
|
126
114
|
<button type="button" className="btn btn--ghost btn--sm" onClick={() => onClose()} aria-label="Close" data-testid="source-conflict-close">
|
|
127
115
|
×
|
|
@@ -129,6 +117,20 @@ export default function SourceConflictPanel({ slug, onClose }) {
|
|
|
129
117
|
</div>
|
|
130
118
|
{sides && (
|
|
131
119
|
<>
|
|
120
|
+
<div className="scp-recovery">
|
|
121
|
+
<details>
|
|
122
|
+
<summary>Original draft</summary>
|
|
123
|
+
{sides.original !== null && sides.original !== undefined ? (
|
|
124
|
+
<pre tabIndex={0} role="region" aria-label="Original draft" data-testid="source-conflict-original">{sides.original}</pre>
|
|
125
|
+
) : <p>The original draft is not available on this device.</p>}
|
|
126
|
+
</details>
|
|
127
|
+
<details>
|
|
128
|
+
<summary>Starting version</summary>
|
|
129
|
+
{sides.base !== null && sides.base !== undefined ? (
|
|
130
|
+
<pre tabIndex={0} role="region" aria-label="Starting version" data-testid="source-conflict-base">{sides.base}</pre>
|
|
131
|
+
) : <p>The version this draft started from is not known.</p>}
|
|
132
|
+
</details>
|
|
133
|
+
</div>
|
|
132
134
|
<div className="scp-legend" aria-hidden="true">
|
|
133
135
|
<span className="scp-key scp-key--mine">Your version</span>
|
|
134
136
|
<span className="scp-key scp-key--theirs">The project’s version</span>
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
.st-mb-file b { color: var(--fg-0); font-weight: 600; }
|
|
81
81
|
.st-mb-sep { width: 1px; height: 16px; background: var(--border-default); }
|
|
82
82
|
.st-mb-count { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); }
|
|
83
|
-
.st-mb-proj { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--
|
|
83
|
+
.st-mb-proj { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
|
|
84
84
|
.st-reportbug {
|
|
85
85
|
appearance: none; border: 0; background: transparent; cursor: pointer;
|
|
86
86
|
width: 26px; height: 26px; display: grid; place-items: center; border-radius: var(--radius-sm);
|
|
@@ -193,7 +193,7 @@
|
|
|
193
193
|
font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); z-index: 30;
|
|
194
194
|
}
|
|
195
195
|
.st-sb-slot { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; }
|
|
196
|
-
.st-sb-slot .lbl { color: var(--fg-
|
|
196
|
+
.st-sb-slot .lbl { color: var(--fg-2); text-transform: uppercase; letter-spacing: var(--tracking-wide); font-size: 10px; flex: none; }
|
|
197
197
|
.st-sb-slot .val { color: var(--fg-0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
198
198
|
.st-sb-slot + .st-sb-slot { padding-left: var(--space-4); border-left: 1px solid var(--border-subtle); }
|
|
199
199
|
.st-sb-active { font-weight: 500; }
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
|
|
226
226
|
/* The running release. Ambient, not a state to act on — so it sits at the same
|
|
227
227
|
weight as a slot label rather than at .val's foreground. No new tokens. */
|
|
228
|
-
.st-sb-version .val { color: var(--fg-
|
|
228
|
+
.st-sb-version .val { color: var(--fg-2); }
|
|
229
229
|
|
|
230
230
|
/* ═══ Task 4 — body row · sidebar · tree · rail ═══════════════════════════════ */
|
|
231
231
|
|
|
@@ -243,7 +243,7 @@
|
|
|
243
243
|
.st-dockslot > .st-rpanel,
|
|
244
244
|
.st-dockslot > .st-sidebar { flex: 1 1 auto; width: 100%; min-height: 0; }
|
|
245
245
|
.st-docktabs { display: flex; gap: 2px; padding: var(--space-2) var(--space-2) 0; border-bottom: 1px solid var(--border-subtle); background: var(--bg-1); flex: none; }
|
|
246
|
-
.st-docktab { appearance: none; border: 0; background: transparent; cursor: pointer; padding: var(--space-1) var(--space-3); border-radius: var(--radius-sm) var(--radius-sm) 0 0; color: var(--fg-
|
|
246
|
+
.st-docktab { appearance: none; border: 0; background: transparent; cursor: pointer; padding: var(--space-1) var(--space-3); border-radius: var(--radius-sm) var(--radius-sm) 0 0; color: var(--fg-2); font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); transition: color var(--dur-soft) var(--ease-out), background var(--dur-soft) var(--ease-out); }
|
|
247
247
|
.st-docktab:hover { color: var(--fg-1); background: var(--bg-2); }
|
|
248
248
|
.st-docktab.is-active { color: var(--fg-0); background: var(--bg-2); box-shadow: inset 0 -2px 0 var(--accent); }
|
|
249
249
|
.st-docktab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
@@ -308,8 +308,10 @@
|
|
|
308
308
|
accent language as .st-row.is-drop-target. */
|
|
309
309
|
.st-tree-sec-hd.is-drop-target { background: var(--accent-tint); color: var(--fg-0); box-shadow: inset 2px 0 0 var(--accent); }
|
|
310
310
|
.st-tree-sec-hd .st-sec-name { font-family: var(--font-mono); font-size: var(--type-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
|
|
311
|
+
/* --fg-2, not --fg-3: a 10px count is text, and --fg-3 is 3.0:1 on the
|
|
312
|
+
sidebar — below WCAG AA (axe on the cloud cell, F3 S19, 2026-09-24). */
|
|
311
313
|
.st-tree-sec-hd .st-pill {
|
|
312
|
-
margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--fg-
|
|
314
|
+
margin-left: auto; font-family: var(--font-mono); font-size: 10px; color: var(--fg-2);
|
|
313
315
|
padding: 0 6px; border: 1px solid var(--border-subtle); border-radius: var(--radius-pill);
|
|
314
316
|
}
|
|
315
317
|
.st-tree-empty { padding: var(--space-2) var(--space-5); color: var(--fg-3); font-size: var(--type-xs); font-style: italic; }
|
|
@@ -357,6 +359,8 @@
|
|
|
357
359
|
}
|
|
358
360
|
/* delete affordance — sibling of the row button (can't nest buttons). */
|
|
359
361
|
.st-row-wrap { position: relative; display: flex; align-items: center; }
|
|
362
|
+
.st-tree-item:focus-visible { outline: none; }
|
|
363
|
+
.st-tree-item:focus-visible > .st-row-wrap { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius-sm); }
|
|
360
364
|
.st-row-wrap .st-row { flex: 1; }
|
|
361
365
|
.st-row-del {
|
|
362
366
|
position: absolute; right: var(--space-2); top: 50%; transform: translateY(-50%);
|
|
@@ -564,6 +568,10 @@
|
|
|
564
568
|
.st-banner-close:hover { background: color-mix(in oklab, var(--fg-0) 12%, transparent); color: var(--fg-0); }
|
|
565
569
|
|
|
566
570
|
/* ─── Command palette (⌘K) ───────────────────────────────────────────────── */
|
|
571
|
+
/* The informational role notice sits BELOW a modal's scrim (9000): it covered
|
|
572
|
+
the preview dialog's own header (S19). Warnings and errors keep
|
|
573
|
+
.st-banner's 9100 and stay visible over a dialog. */
|
|
574
|
+
.st-banner.st-banner--info { z-index: 8990; }
|
|
567
575
|
.st-scrim { position: fixed; inset: 0; background: color-mix(in oklab, var(--bg-0) 62%, transparent); z-index: 9000; display: grid; place-items: start center; padding-top: 12vh; }
|
|
568
576
|
.st-palette {
|
|
569
577
|
width: 560px; max-width: 92vw; background: var(--bg-2); border: 1px solid var(--border-default);
|
|
@@ -1563,7 +1571,7 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
|
|
|
1563
1571
|
}
|
|
1564
1572
|
.st-skel-cap {
|
|
1565
1573
|
font-size: var(--type-xs); letter-spacing: var(--tracking-wide);
|
|
1566
|
-
text-transform: uppercase; color: var(--fg-
|
|
1574
|
+
text-transform: uppercase; color: var(--fg-2);
|
|
1567
1575
|
}
|
|
1568
1576
|
.skel {
|
|
1569
1577
|
display: block;
|
|
@@ -1744,7 +1752,7 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
|
|
|
1744
1752
|
.gp-panel-title { font-family: var(--font-display); font-weight: 600; font-size: var(--type-md); color: var(--fg-0); flex: none; }
|
|
1745
1753
|
.gp-count { font-family: var(--font-mono); font-size: var(--type-xs); font-weight: 600; padding: 1px var(--space-2); border-radius: var(--radius-pill); background: var(--accent-tint); color: var(--accent); border: 1px solid var(--accent-muted); white-space: nowrap; flex: none; }
|
|
1746
1754
|
.gp-spacer { flex: 1; min-width: var(--space-2); }
|
|
1747
|
-
.gp-draft { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-
|
|
1755
|
+
.gp-draft { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-1); display: inline-flex; align-items: center; gap: var(--space-1); padding: 1px var(--space-2); border: 1px solid var(--border-default); border-radius: var(--radius-sm); background: var(--bg-2); white-space: nowrap; min-width: 0; flex: 0 1 auto; }
|
|
1748
1756
|
.gp-draft b { color: var(--fg-0); font-weight: 600; overflow: hidden; text-overflow: ellipsis; max-width: 90px; }
|
|
1749
1757
|
.gp-draft .gp-sep { color: var(--fg-3); }
|
|
1750
1758
|
.gp-x { appearance: none; border: none; background: transparent; color: var(--fg-2); font-size: 16px; line-height: 1; cursor: pointer; padding: 2px 5px; border-radius: var(--radius-xs); }
|
|
@@ -2263,7 +2271,7 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
|
|
|
2263
2271
|
.dv-zoom-btn:hover { background: var(--bg-3); color: var(--fg-0); }
|
|
2264
2272
|
.dv-zoom-val { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); min-width: 44px; text-align: center; cursor: pointer; appearance: none; border: none; background: transparent; }
|
|
2265
2273
|
.dv-zoom-val:hover { color: var(--fg-0); }
|
|
2266
|
-
.dv-zoom-sync { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-
|
|
2274
|
+
.dv-zoom-sync { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); padding-left: var(--space-2); border-left: 1px solid var(--border-subtle); margin-left: var(--space-1); }
|
|
2267
2275
|
|
|
2268
2276
|
/* overlay / slider compare (shares the locked view; frozen layers for the wipe) */
|
|
2269
2277
|
.dv-overlay { --dv-split: 52%; position: relative; flex: 1; min-height: 0; margin: 0 auto; width: 100%; max-width: 900px; background: var(--bg-0); border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }
|
|
@@ -2639,7 +2647,11 @@ body.st-scrubbing, body.st-scrubbing * { cursor: ew-resize !important; user-sele
|
|
|
2639
2647
|
.sp-ai-held { display: flex; flex-direction: column; gap: var(--space-2); }
|
|
2640
2648
|
.sp-ai-actions { display: flex; gap: var(--space-2); }
|
|
2641
2649
|
/* ── SourceConflictPanel (plan T28) — two versions, line by line. ── */
|
|
2642
|
-
.gi-dialog.scp-dialog { width: min(760px, 94vw); max-height: min(820px, 90vh); overflow:
|
|
2650
|
+
.gi-dialog.scp-dialog { width: min(760px, 94vw); max-height: min(820px, 90vh); overflow: auto; display: flex; flex-direction: column; padding: var(--space-6); gap: var(--space-4); }
|
|
2651
|
+
.scp-recovery { display: grid; gap: var(--space-2); font-size: var(--type-xs); color: var(--fg-1); }
|
|
2652
|
+
.scp-recovery summary { cursor: pointer; padding: var(--space-2) 0; }
|
|
2653
|
+
.scp-recovery pre { margin: 0; padding: var(--space-3); max-height: 160px; overflow: auto; border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-1); font: var(--type-xs)/1.55 var(--font-mono); }
|
|
2654
|
+
.scp-recovery summary:focus-visible, .scp-recovery pre:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
2643
2655
|
.scp-legend { display: flex; gap: var(--space-4); font-size: var(--type-xs); color: var(--fg-2); }
|
|
2644
2656
|
.scp-key::before { content: ''; display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: var(--space-2); vertical-align: -1px; }
|
|
2645
2657
|
.scp-key--mine::before { background: color-mix(in oklch, var(--status-warn) 45%, transparent); }
|
|
@@ -1614,7 +1614,9 @@
|
|
|
1614
1614
|
position: fixed;
|
|
1615
1615
|
left: 16px;
|
|
1616
1616
|
bottom: 16px;
|
|
1617
|
-
|
|
1617
|
+
/* below a modal's scrim (.st-scrim 9000): it sat on top of the history
|
|
1618
|
+
preview dialog (S19). */
|
|
1619
|
+
z-index: 8990;
|
|
1618
1620
|
display: flex;
|
|
1619
1621
|
align-items: center;
|
|
1620
1622
|
gap: 12px;
|
|
@@ -2030,7 +2032,7 @@
|
|
|
2030
2032
|
.st-cloudwho-out {
|
|
2031
2033
|
font: inherit;
|
|
2032
2034
|
font-size: 12px;
|
|
2033
|
-
color: var(--u-fg-
|
|
2035
|
+
color: var(--u-fg-2);
|
|
2034
2036
|
background: none;
|
|
2035
2037
|
border: 0;
|
|
2036
2038
|
cursor: pointer;
|