sh3-core 0.10.2 → 0.10.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/dist/__test__/fixtures.js +1 -0
- package/dist/api.d.ts +2 -0
- package/dist/api.js +1 -0
- package/dist/conflicts/ConflictModal.svelte +131 -0
- package/dist/conflicts/ConflictModal.svelte.d.ts +19 -0
- package/dist/conflicts/DetailView.svelte +198 -0
- package/dist/conflicts/DetailView.svelte.d.ts +17 -0
- package/dist/conflicts/PromptView.svelte +55 -0
- package/dist/conflicts/PromptView.svelte.d.ts +9 -0
- package/dist/conflicts/adapter-documents.d.ts +3 -0
- package/dist/conflicts/adapter-documents.js +119 -0
- package/dist/conflicts/api.d.ts +108 -0
- package/dist/conflicts/api.js +33 -0
- package/dist/conflicts/most-recent.d.ts +3 -0
- package/dist/conflicts/most-recent.js +23 -0
- package/dist/conflicts/most-recent.test.d.ts +1 -0
- package/dist/conflicts/most-recent.test.js +45 -0
- package/dist/conflicts/renderer-registry.d.ts +7 -0
- package/dist/conflicts/renderer-registry.js +59 -0
- package/dist/conflicts/renderer-registry.test.d.ts +1 -0
- package/dist/conflicts/renderer-registry.test.js +124 -0
- package/dist/conflicts/renderers/MetaOnlyRenderer.svelte +73 -0
- package/dist/conflicts/renderers/MetaOnlyRenderer.svelte.d.ts +9 -0
- package/dist/conflicts/renderers/TextDiffRenderer.svelte +154 -0
- package/dist/conflicts/renderers/TextDiffRenderer.svelte.d.ts +9 -0
- package/dist/conflicts/renderers/index.d.ts +8 -0
- package/dist/conflicts/renderers/index.js +63 -0
- package/dist/conflicts/resolve-primitive.d.ts +2 -0
- package/dist/conflicts/resolve-primitive.js +55 -0
- package/dist/conflicts/shell-api.d.ts +2 -0
- package/dist/conflicts/shell-api.js +13 -0
- package/dist/documents/browse.d.ts +26 -0
- package/dist/documents/browse.js +16 -0
- package/dist/documents/browse.test.js +97 -0
- package/dist/documents/handle.js +5 -0
- package/dist/documents/handle.test.js +37 -0
- package/dist/documents/http-backend.d.ts +1 -0
- package/dist/documents/http-backend.js +9 -0
- package/dist/documents/http-backend.test.d.ts +1 -0
- package/dist/documents/http-backend.test.js +39 -0
- package/dist/documents/types.d.ts +14 -0
- package/dist/keys/ConsentDialog.svelte +1 -0
- package/dist/layout/LayoutRenderer.browser.test.js +78 -0
- package/dist/layout/LayoutRenderer.svelte +1 -0
- package/dist/layout/__screenshots__/LayoutRenderer.browser.test.ts/LayoutRenderer-browser---E-6-fixed-slots-freezes-the-handle-adjacent-to-a-fixed-pane--dblclick-does-not-collapse-1.png +0 -0
- package/dist/layout/__screenshots__/LayoutRenderer.browser.test.ts/LayoutRenderer-browser---E-6-fixed-slots-hides-the-collapse-widget-on-a-fixed-pane-1.png +0 -0
- package/dist/layout/types.d.ts +8 -0
- package/dist/primitives/ResizableSplitter.svelte +38 -3
- package/dist/primitives/ResizableSplitter.svelte.d.ts +7 -0
- package/dist/primitives/base.css +140 -1
- package/dist/shell-shard/InputLine.svelte +1 -0
- package/dist/shellRuntime.svelte.d.ts +3 -0
- package/dist/shellRuntime.svelte.js +2 -0
- package/dist/tokens.css +3 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
sizes,
|
|
29
29
|
pinned,
|
|
30
30
|
collapsed,
|
|
31
|
+
fixed,
|
|
31
32
|
count,
|
|
32
33
|
pane,
|
|
33
34
|
onResize,
|
|
@@ -46,6 +47,13 @@
|
|
|
46
47
|
pinned?: SizeMode[];
|
|
47
48
|
/** Per-pane collapsed state. Omitted entries default to false. */
|
|
48
49
|
collapsed?: boolean[];
|
|
50
|
+
/**
|
|
51
|
+
* Per-pane fixed flag. A fixed pane has no collapse widget and
|
|
52
|
+
* the handles on either side of it are frozen (non-interactive,
|
|
53
|
+
* rendered thinner). A non-fixed pane whose every neighbor is
|
|
54
|
+
* fixed also loses its collapse widget.
|
|
55
|
+
*/
|
|
56
|
+
fixed?: boolean[];
|
|
49
57
|
/** Number of panes — `sizes.length` should match. */
|
|
50
58
|
count: number;
|
|
51
59
|
/** Snippet invoked once per pane with the pane index. */
|
|
@@ -67,6 +75,15 @@
|
|
|
67
75
|
|
|
68
76
|
const modeOf = (i: number): SizeMode => pinned?.[i] ?? 'fr';
|
|
69
77
|
const isCollapsed = (i: number): boolean => collapsed?.[i] ?? false;
|
|
78
|
+
const isFixed = (i: number): boolean => fixed?.[i] ?? false;
|
|
79
|
+
const isHandleFrozen = (i: number): boolean => isFixed(i) || isFixed(i + 1);
|
|
80
|
+
|
|
81
|
+
function canCollapse(i: number): boolean {
|
|
82
|
+
if (isFixed(i)) return false;
|
|
83
|
+
const left = i > 0 ? !isFixed(i - 1) : false;
|
|
84
|
+
const right = i < count - 1 ? !isFixed(i + 1) : false;
|
|
85
|
+
return left || right;
|
|
86
|
+
}
|
|
70
87
|
|
|
71
88
|
/** CSS `flex` shorthand for pane i. */
|
|
72
89
|
function flexFor(i: number): string {
|
|
@@ -88,8 +105,9 @@
|
|
|
88
105
|
let drag: DragState | null = $state(null);
|
|
89
106
|
|
|
90
107
|
function beginDrag(e: PointerEvent, handleIndex: number) {
|
|
91
|
-
// Disable resize handles adjacent to collapsed panes.
|
|
108
|
+
// Disable resize handles adjacent to collapsed or fixed panes.
|
|
92
109
|
if (isCollapsed(handleIndex) || isCollapsed(handleIndex + 1)) return;
|
|
110
|
+
if (isHandleFrozen(handleIndex)) return;
|
|
93
111
|
|
|
94
112
|
e.preventDefault();
|
|
95
113
|
(e.target as HTMLElement).setPointerCapture(e.pointerId);
|
|
@@ -198,12 +216,13 @@
|
|
|
198
216
|
<span class="collapse-icon">{direction === 'horizontal' ? '▸' : '▾'}</span>
|
|
199
217
|
</button>
|
|
200
218
|
{:else}
|
|
201
|
-
{#if onCollapseToggle}
|
|
219
|
+
{#if onCollapseToggle && canCollapse(i)}
|
|
202
220
|
<button
|
|
203
221
|
type="button"
|
|
204
222
|
class="collapse-header expanded"
|
|
205
223
|
class:horizontal={direction === 'horizontal'}
|
|
206
224
|
class:vertical={direction === 'vertical'}
|
|
225
|
+
data-testid="collapse-toggle-{i}"
|
|
207
226
|
onclick={() => onCollapseToggle?.(i, true)}
|
|
208
227
|
aria-label="Collapse pane"
|
|
209
228
|
>
|
|
@@ -221,12 +240,17 @@
|
|
|
221
240
|
class="splitter-handle"
|
|
222
241
|
class:dragging={drag?.handleIndex === i}
|
|
223
242
|
class:disabled={isCollapsed(i) || isCollapsed(i + 1)}
|
|
243
|
+
class:frozen={isHandleFrozen(i)}
|
|
224
244
|
data-testid="splitter-handle-{i}"
|
|
225
245
|
onpointerdown={(e) => beginDrag(e, i)}
|
|
226
246
|
onpointermove={moveDrag}
|
|
227
247
|
onpointerup={endDrag}
|
|
228
248
|
onpointercancel={endDrag}
|
|
229
|
-
ondblclick={() =>
|
|
249
|
+
ondblclick={() => {
|
|
250
|
+
if (isHandleFrozen(i)) return;
|
|
251
|
+
if (!canCollapse(i) && !isCollapsed(i)) return;
|
|
252
|
+
onCollapseToggle?.(i, !isCollapsed(i));
|
|
253
|
+
}}
|
|
230
254
|
role="separator"
|
|
231
255
|
aria-orientation={direction === 'horizontal' ? 'vertical' : 'horizontal'}
|
|
232
256
|
></div>
|
|
@@ -323,6 +347,15 @@
|
|
|
323
347
|
cursor: default;
|
|
324
348
|
pointer-events: none;
|
|
325
349
|
}
|
|
350
|
+
.splitter-handle.frozen {
|
|
351
|
+
cursor: default;
|
|
352
|
+
pointer-events: none;
|
|
353
|
+
background: var(--shell-border);
|
|
354
|
+
opacity: 0.5;
|
|
355
|
+
}
|
|
356
|
+
.splitter-handle.frozen:hover {
|
|
357
|
+
background: var(--shell-border);
|
|
358
|
+
}
|
|
326
359
|
|
|
327
360
|
.horizontal > .splitter-handle {
|
|
328
361
|
width: 4px;
|
|
@@ -332,4 +365,6 @@
|
|
|
332
365
|
height: 4px;
|
|
333
366
|
cursor: row-resize;
|
|
334
367
|
}
|
|
368
|
+
.horizontal > .splitter-handle.frozen { width: 1px; }
|
|
369
|
+
.vertical > .splitter-handle.frozen { height: 1px; }
|
|
335
370
|
</style>
|
|
@@ -14,6 +14,13 @@ type $$ComponentProps = {
|
|
|
14
14
|
pinned?: SizeMode[];
|
|
15
15
|
/** Per-pane collapsed state. Omitted entries default to false. */
|
|
16
16
|
collapsed?: boolean[];
|
|
17
|
+
/**
|
|
18
|
+
* Per-pane fixed flag. A fixed pane has no collapse widget and
|
|
19
|
+
* the handles on either side of it are frozen (non-interactive,
|
|
20
|
+
* rendered thinner). A non-fixed pane whose every neighbor is
|
|
21
|
+
* fixed also loses its collapse widget.
|
|
22
|
+
*/
|
|
23
|
+
fixed?: boolean[];
|
|
17
24
|
/** Number of panes — `sizes.length` should match. */
|
|
18
25
|
count: number;
|
|
19
26
|
/** Snippet invoked once per pane with the pane index. */
|
package/dist/primitives/base.css
CHANGED
|
@@ -16,7 +16,7 @@ input[type="reset"],
|
|
|
16
16
|
.shell-base-button {
|
|
17
17
|
padding: 6px 14px;
|
|
18
18
|
background: var(--shell-accent, #6ea8fe);
|
|
19
|
-
color: #fff;
|
|
19
|
+
color: var(--shell-fg, #fff);
|
|
20
20
|
border: none;
|
|
21
21
|
border-radius: var(--shell-radius);
|
|
22
22
|
cursor: pointer;
|
|
@@ -40,3 +40,142 @@ input[type="reset"]:active,
|
|
|
40
40
|
.shell-base-button:active {
|
|
41
41
|
filter: brightness(0.92);
|
|
42
42
|
}
|
|
43
|
+
|
|
44
|
+
/* ── Text inputs ─────────────────────────────────────────────────────── */
|
|
45
|
+
|
|
46
|
+
input[type="text"],
|
|
47
|
+
input[type="email"],
|
|
48
|
+
input[type="password"],
|
|
49
|
+
input[type="search"],
|
|
50
|
+
input[type="url"],
|
|
51
|
+
input[type="tel"],
|
|
52
|
+
input[type="number"],
|
|
53
|
+
textarea,
|
|
54
|
+
.shell-base-input {
|
|
55
|
+
padding: var(--shell-pad-md) var(--shell-pad-lg);
|
|
56
|
+
background: var(--shell-input-bg);
|
|
57
|
+
color: var(--shell-fg);
|
|
58
|
+
border: 1px solid var(--shell-border);
|
|
59
|
+
border-radius: var(--shell-radius);
|
|
60
|
+
font-family: inherit;
|
|
61
|
+
font-size: 0.8125rem;
|
|
62
|
+
line-height: var(--shell-line);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
::placeholder { color: var(--shell-fg-muted); }
|
|
66
|
+
|
|
67
|
+
input:focus-visible,
|
|
68
|
+
textarea:focus-visible,
|
|
69
|
+
.shell-base-input:focus-visible {
|
|
70
|
+
border-color: var(--shell-input-border-focus);
|
|
71
|
+
box-shadow: var(--shell-focus-ring);
|
|
72
|
+
outline: none;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
input:disabled,
|
|
76
|
+
textarea:disabled,
|
|
77
|
+
.shell-base-input[aria-disabled="true"] {
|
|
78
|
+
opacity: 0.55;
|
|
79
|
+
cursor: not-allowed;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
textarea {
|
|
83
|
+
resize: vertical;
|
|
84
|
+
min-height: calc(var(--shell-line) * 3em);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* ── Checkbox & radio ────────────────────────────────────────────────── */
|
|
88
|
+
|
|
89
|
+
input[type="checkbox"].shell-base-check,
|
|
90
|
+
input[type="radio"].shell-base-radio {
|
|
91
|
+
appearance: none;
|
|
92
|
+
width: 14px;
|
|
93
|
+
height: 14px;
|
|
94
|
+
margin: 0;
|
|
95
|
+
background: var(--shell-input-bg);
|
|
96
|
+
border: 1px solid var(--shell-border);
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
display: inline-grid;
|
|
99
|
+
place-content: center;
|
|
100
|
+
flex-shrink: 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.shell-base-check { border-radius: var(--shell-radius-sm); }
|
|
104
|
+
.shell-base-radio { border-radius: 50%; }
|
|
105
|
+
|
|
106
|
+
.shell-base-check:checked,
|
|
107
|
+
.shell-base-radio:checked {
|
|
108
|
+
background: var(--shell-accent);
|
|
109
|
+
border-color: var(--shell-accent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.shell-base-check:checked::before {
|
|
113
|
+
content: "";
|
|
114
|
+
width: 8px;
|
|
115
|
+
height: 8px;
|
|
116
|
+
background: #fff;
|
|
117
|
+
clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 20%, 85% 8%, 38% 70%);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.shell-base-radio:checked::before {
|
|
121
|
+
content: "";
|
|
122
|
+
width: 6px;
|
|
123
|
+
height: 6px;
|
|
124
|
+
border-radius: 50%;
|
|
125
|
+
background: #fff;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.shell-base-check:focus-visible,
|
|
129
|
+
.shell-base-radio:focus-visible {
|
|
130
|
+
box-shadow: var(--shell-focus-ring);
|
|
131
|
+
outline: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.shell-base-check:disabled,
|
|
135
|
+
.shell-base-radio:disabled {
|
|
136
|
+
opacity: 0.55;
|
|
137
|
+
cursor: not-allowed;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* ── Switch ──────────────────────────────────────────────────────────── */
|
|
141
|
+
|
|
142
|
+
input[type="checkbox"].shell-base-switch {
|
|
143
|
+
appearance: none;
|
|
144
|
+
position: relative;
|
|
145
|
+
width: 28px;
|
|
146
|
+
height: 16px;
|
|
147
|
+
margin: 0;
|
|
148
|
+
background: var(--shell-border-strong);
|
|
149
|
+
border-radius: 999px;
|
|
150
|
+
cursor: pointer;
|
|
151
|
+
transition: background 120ms ease;
|
|
152
|
+
flex-shrink: 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.shell-base-switch::before {
|
|
156
|
+
content: "";
|
|
157
|
+
position: absolute;
|
|
158
|
+
top: 2px;
|
|
159
|
+
left: 2px;
|
|
160
|
+
width: 12px;
|
|
161
|
+
height: 12px;
|
|
162
|
+
background: var(--shell-fg);
|
|
163
|
+
border-radius: 50%;
|
|
164
|
+
transition: transform 120ms ease;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.shell-base-switch:checked { background: var(--shell-accent); }
|
|
168
|
+
.shell-base-switch:checked::before {
|
|
169
|
+
transform: translateX(12px);
|
|
170
|
+
background: #fff;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.shell-base-switch:focus-visible {
|
|
174
|
+
box-shadow: var(--shell-focus-ring);
|
|
175
|
+
outline: none;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.shell-base-switch:disabled {
|
|
179
|
+
opacity: 0.55;
|
|
180
|
+
cursor: not-allowed;
|
|
181
|
+
}
|
|
@@ -5,6 +5,7 @@ import { type PopupManager } from './overlays/popup';
|
|
|
5
5
|
import { type ToastManager } from './overlays/toast';
|
|
6
6
|
import { type FloatManager } from './overlays/float';
|
|
7
7
|
import { type PresetManager } from './overlays/presets';
|
|
8
|
+
import type { ConflictsApi } from './conflicts/api';
|
|
8
9
|
/**
|
|
9
10
|
* The process-wide shell singleton exposed to shards and the shell's own
|
|
10
11
|
* internal code. Provides state zone creation and overlay managers.
|
|
@@ -28,6 +29,8 @@ export interface Shell {
|
|
|
28
29
|
float: FloatManager;
|
|
29
30
|
/** Named layout presets per app. See overlays/presets.ts. */
|
|
30
31
|
presets: PresetManager;
|
|
32
|
+
/** Conflict manager view. Shell-owned modal for conflict arbitration. */
|
|
33
|
+
conflicts: ConflictsApi;
|
|
31
34
|
}
|
|
32
35
|
/** The process-wide shell instance. Framework-internal code uses this directly; shards receive a scoped view via `ShardContext`. */
|
|
33
36
|
export declare const shell: Shell;
|
|
@@ -20,6 +20,7 @@ import { popupManager } from './overlays/popup';
|
|
|
20
20
|
import { toastManager } from './overlays/toast';
|
|
21
21
|
import { floatManager } from './overlays/float';
|
|
22
22
|
import { presetManager } from './overlays/presets';
|
|
23
|
+
import { conflictsApi } from './conflicts/shell-api';
|
|
23
24
|
/** The process-wide shell instance. Framework-internal code uses this directly; shards receive a scoped view via `ShardContext`. */
|
|
24
25
|
export const shell = {
|
|
25
26
|
state: createStateZones,
|
|
@@ -28,4 +29,5 @@ export const shell = {
|
|
|
28
29
|
toast: toastManager,
|
|
29
30
|
float: floatManager,
|
|
30
31
|
presets: presetManager,
|
|
32
|
+
conflicts: conflictsApi,
|
|
31
33
|
};
|
package/dist/tokens.css
CHANGED
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
--shell-accent-muted: #3a5580;
|
|
34
34
|
|
|
35
35
|
/* Inputs */
|
|
36
|
-
--shell-input-bg:
|
|
36
|
+
--shell-input-bg: #2a2a2a;
|
|
37
|
+
--shell-input-border-focus: var(--shell-accent);
|
|
38
|
+
--shell-focus-ring: 0 0 0 2px color-mix(in srgb, var(--shell-accent) 40%, transparent);
|
|
37
39
|
|
|
38
40
|
/* Semantic */
|
|
39
41
|
--shell-error: #f87171;
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Auto-generated from package.json — do not edit manually. */
|
|
2
|
-
export declare const VERSION = "0.10.
|
|
2
|
+
export declare const VERSION = "0.10.5";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Auto-generated from package.json — do not edit manually. */
|
|
2
|
-
export const VERSION = '0.10.
|
|
2
|
+
export const VERSION = '0.10.5';
|