@stonecrop/desktop 0.35.0 → 0.38.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/README.md CHANGED
@@ -160,7 +160,7 @@ Three things are adjustable, for the cases that genuinely differ between applica
160
160
 
161
161
  `args` is an opaque JSON array: nothing validates it, so both ends of your own stack have to agree. A backend taking positional `[recordId, data]` supplies `buildArgs` to say so.
162
162
 
163
- Resolving a record's identity and keying it into HST are deliberately **not** adjustable. That rule is declared on the doctype and re-derived server-side by the adapter, and every host that re-derived it client-side got it wrong. If you dispatch through `Stonecrop.dispatchAction` directly instead of using this composable, that method still files the returned record under the settled identity, so you cannot store it under the wrong key by accident. What you lose is the stale-key cleanup and the route-follow, which need the id you dispatched.
163
+ Resolving a record's identity and keying it into HST are deliberately **not** adjustable. That rule is declared on the doctype and re-derived server-side by the adapter, and every host that re-derived it client-side got it wrong. If you dispatch through `Stonecrop.dispatchAction` directly instead of using this composable, that method still files the result's `record` (the server's read of the record after the action) under the settled identity, so you cannot store it under the wrong key by accident. What you lose is the stale-key cleanup and the route-follow, which need the id you dispatched.
164
164
 
165
165
  Do not copy form data into HST before dispatching. Desktop already hands you the current form snapshot in `payload.data`, and an unsaved record has no HST node to write to.
166
166
 
@@ -1,4 +1,74 @@
1
1
 
2
+ .command-search[data-v-2ec3bd14] {
3
+ display: flex;
4
+ flex-direction: column;
5
+ min-height: 0;
6
+ background-color: var(--sc-form-background);
7
+ }
8
+ .command-search--embedded[data-v-2ec3bd14] {
9
+ flex: 1;
10
+ }
11
+ .command-search-header[data-v-2ec3bd14] {
12
+ display: flex;
13
+ border-bottom: 1px solid var(--sc-gray-20);
14
+ padding: 12px;
15
+ flex-shrink: 0;
16
+ }
17
+ .command-search-input[data-v-2ec3bd14] {
18
+ flex: 1;
19
+ box-sizing: border-box;
20
+ width: 100%;
21
+ border: 1px solid var(--sc-input-border-color);
22
+ border-radius: var(--sc-border-radius);
23
+ outline: none;
24
+ font-size: 0.95rem;
25
+ font-family: var(--sc-font-family);
26
+ padding: 8px 10px;
27
+ background-color: var(--sc-input-field-background);
28
+ color: var(--sc-gray-80);
29
+ }
30
+ .command-search-input[data-v-2ec3bd14]:focus-visible {
31
+ border-color: var(--sc-input-active-border-color);
32
+ outline: 2px solid var(--sc-primary-color);
33
+ outline-offset: 1px;
34
+ }
35
+ .command-search-results[data-v-2ec3bd14] {
36
+ overflow-y: auto;
37
+ flex: 1;
38
+ min-height: 0;
39
+ }
40
+ .command-search-result[data-v-2ec3bd14] {
41
+ padding: 10px 12px;
42
+ cursor: pointer;
43
+ border-bottom: 1px solid var(--sc-gray-10);
44
+ }
45
+ .command-search-result[data-v-2ec3bd14]:hover,
46
+ .command-search-result.selected[data-v-2ec3bd14] {
47
+ background-color: var(--sc-row-hover-color);
48
+ }
49
+ .command-search-result.selected[data-v-2ec3bd14] {
50
+ background-color: var(--sc-color-changed);
51
+ }
52
+ .command-search-result-title[data-v-2ec3bd14] {
53
+ font-weight: 500;
54
+ margin-bottom: 2px;
55
+ color: var(--sc-gray-80);
56
+ font-size: 0.9rem;
57
+ }
58
+ .command-search-result-content[data-v-2ec3bd14] {
59
+ font-size: 0.8rem;
60
+ color: var(--sc-input-label-color);
61
+ white-space: nowrap;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ }
65
+ .command-search-no-results[data-v-2ec3bd14] {
66
+ padding: 16px 12px;
67
+ text-align: center;
68
+ color: var(--sc-input-label-color);
69
+ font-size: 0.9rem;
70
+ }
71
+
2
72
  .fade-enter-active,
3
73
  .fade-leave-active {
4
74
  transition: opacity 0.2s ease;
@@ -31,89 +101,59 @@
31
101
  display: flex;
32
102
  flex-direction: column;
33
103
  }
34
- .command-palette-header {
104
+
105
+ .action-set__rail[data-v-8ca97265] {
106
+ position: fixed;
107
+ right: var(--sc-action-set-tile-gap);
108
+ z-index: 1002;
35
109
  display: flex;
36
- border-bottom: 1px solid var(--sc-gray-10);
37
- padding: 12px;
38
- }
39
- .command-palette-input {
40
- flex: 1;
41
- border: none;
42
- outline: none;
43
- font-size: 16px;
44
- padding: 8px 12px;
45
- background-color: transparent;
46
- }
47
- .command-palette-close {
48
- background: transparent;
49
- border: none;
50
- font-size: 24px;
51
- cursor: pointer;
52
- color: var(--sc-input-label-color);
53
- padding: 0 8px;
54
- }
55
- .command-palette-close:hover {
56
- color: var(--sc-gray-80);
57
- }
58
- .command-palette-results {
59
- overflow-y: auto;
60
- max-height: 60vh;
61
- }
62
- .command-palette-result {
63
- padding: 12px 16px;
64
- cursor: pointer;
65
- border-bottom: 1px solid var(--sc-gray-10);
66
- }
67
- .command-palette-result:hover,
68
- .command-palette-result.selected {
69
- background-color: var(--sc-row-hover-color);
110
+ flex-direction: column;
111
+ align-items: stretch;
112
+ visibility: hidden;
113
+ pointer-events: none;
70
114
  }
71
- .command-palette-result.selected {
72
- background-color: var(--sc-color-changed);
115
+ .action-set__rail--layout-ready[data-v-8ca97265] {
116
+ visibility: visible;
117
+ pointer-events: auto;
73
118
  }
74
- .result-title {
75
- font-weight: 500;
76
- margin-bottom: 4px;
77
- color: var(--sc-gray-80);
119
+ .action-set__rail--drawer-open[data-v-8ca97265] {
120
+ right: calc(var(--sc-action-set-drawer-width) + var(--sc-action-set-tile-gap));
78
121
  }
79
- .result-content {
80
- font-size: 14px;
81
- color: var(--sc-input-label-color);
82
- white-space: nowrap;
83
- overflow: hidden;
84
- text-overflow: ellipsis;
122
+ .action-set__drag-handle[data-v-8ca97265] {
123
+ box-sizing: border-box;
124
+ width: 100%;
125
+ height: 10px;
126
+ padding: 0;
127
+ border: 1px solid var(--sc-gray-20);
128
+ border-bottom: none;
129
+ border-radius: 0;
130
+ background: var(--sc-gray-5);
131
+ cursor: ns-resize;
132
+ flex-shrink: 0;
85
133
  }
86
- .command-palette-no-results {
87
- padding: 20px 16px;
88
- text-align: center;
89
- color: var(--sc-input-label-color);
134
+ .action-set__drag-handle[data-v-8ca97265]::before {
135
+ content: '';
136
+ display: block;
137
+ width: 1.25rem;
138
+ height: 2px;
139
+ margin: 3px auto 0;
140
+ background: var(--sc-gray-50);
141
+ box-shadow: 0 4px 0 var(--sc-gray-50);
90
142
  }
91
-
92
- .action-set[data-v-40295597] {
93
- /* Right offset + tile column width + gap: the strip the drawer keeps clear for the tile column. */
94
- --action-set-rail-inset: calc(10px + 2.75rem + 18px + 8px);
95
- position: fixed;
96
- top: var(--sc-action-set-offset-top);
97
- right: 10px;
98
- z-index: 1001;
99
- display: flex;
100
- flex-direction: row-reverse;
101
- align-items: flex-start;
102
- gap: 0;
143
+ .action-set__drag-handle[data-v-8ca97265]:focus-visible {
144
+ outline: 2px solid var(--sc-primary-color);
145
+ outline-offset: 1px;
103
146
  }
104
-
105
- /* Positioned above the drawer, which is a later sibling in the same stacking context. */
106
- .action-set__tile[data-v-40295597] {
107
- position: relative;
108
- z-index: 1;
147
+ .action-set__tile[data-v-8ca97265] {
109
148
  display: flex;
110
149
  flex-direction: column;
111
- align-items: center;
112
- padding: 8px;
150
+ align-items: stretch;
151
+ gap: 4px;
152
+ padding: 4px;
113
153
  background: var(--sc-form-background);
114
154
  border: 1px solid var(--sc-gray-20);
115
155
  }
116
- .action-set__toggle[data-v-40295597] {
156
+ .action-set__toggle[data-v-8ca97265] {
117
157
  display: flex;
118
158
  align-items: center;
119
159
  justify-content: center;
@@ -130,28 +170,27 @@
130
170
  transition: transform 0.2s ease-in-out;
131
171
  }
132
172
  @media (prefers-reduced-motion: reduce) {
133
- .action-set__toggle[data-v-40295597] {
173
+ .action-set__toggle[data-v-8ca97265] {
134
174
  transition: none;
135
175
  }
136
176
  }
137
- .action-set__toggle--expanded[data-v-40295597] {
177
+ .action-set__toggle--expanded[data-v-8ca97265] {
138
178
  transform: rotate(45deg);
139
179
  }
140
- .action-set__toggle[data-v-40295597]:focus-visible,
141
- .action-set__item[data-v-40295597]:focus-visible,
142
- .action-set__drawer-close[data-v-40295597]:focus-visible,
143
- .action-set__actions-list-item[data-v-40295597]:focus-visible {
180
+ .action-set__toggle[data-v-8ca97265]:focus-visible,
181
+ .action-set__item[data-v-8ca97265]:focus-visible,
182
+ .action-set__drawer-close[data-v-8ca97265]:focus-visible,
183
+ .action-set__actions-list-item[data-v-8ca97265]:focus-visible {
144
184
  outline: 2px solid var(--sc-primary-color);
145
185
  outline-offset: 2px;
146
186
  }
147
- .action-set__item[data-v-40295597] {
187
+ .action-set__item[data-v-8ca97265] {
148
188
  position: relative;
149
189
  display: flex;
150
190
  align-items: center;
151
191
  justify-content: center;
152
192
  width: 2.75rem;
153
193
  height: 2.75rem;
154
- margin-top: 8px;
155
194
  padding: 0;
156
195
  border: 1px solid var(--sc-gray-20);
157
196
  background: transparent;
@@ -159,22 +198,22 @@
159
198
  font-family: var(--sc-font-family);
160
199
  color: var(--sc-gray-80);
161
200
  }
162
- .action-set__item[data-v-40295597]:hover,
163
- .action-set__item--active[data-v-40295597] {
201
+ .action-set__item[data-v-8ca97265]:hover,
202
+ .action-set__item--active[data-v-8ca97265] {
164
203
  background: var(--sc-btn-hover);
165
204
  }
166
- .action-set__item-icon[data-v-40295597] {
205
+ .action-set__item-icon[data-v-8ca97265] {
167
206
  display: block;
168
207
  width: 1rem;
169
208
  height: 1rem;
170
209
  flex-shrink: 0;
171
210
  }
172
- .action-set__item-fallback[data-v-40295597] {
211
+ .action-set__item-fallback[data-v-8ca97265] {
173
212
  font-size: 0.85rem;
174
213
  font-weight: 600;
175
214
  line-height: 1;
176
215
  }
177
- .action-set__item-badge[data-v-40295597] {
216
+ .action-set__item-badge[data-v-8ca97265] {
178
217
  position: absolute;
179
218
  top: 2px;
180
219
  right: 2px;
@@ -190,54 +229,71 @@
190
229
  text-align: center;
191
230
  pointer-events: none;
192
231
  }
193
- .action-set__drawer[data-v-40295597] {
232
+
233
+ /* Drawer flush to viewport right; workspace margin is drawer width minus 1px overlap (see Desktop.vue). */
234
+ .action-set__drawer[data-v-8ca97265] {
194
235
  position: fixed;
195
236
  top: 0;
196
237
  right: 0;
197
238
  bottom: 0;
198
239
  box-sizing: border-box;
199
240
  width: var(--sc-action-set-drawer-width);
200
- padding-right: var(--action-set-rail-inset);
201
- background: var(--sc-form-background);
202
- border-left: 1px solid var(--sc-gray-20);
241
+ border-left: none;
242
+ box-shadow: none;
243
+ /* Divider as background fill — inset box-shadow can read as a full-height lane beside the seam in Firefox. */
244
+ background: linear-gradient(
245
+ to right,
246
+ var(--sc-gray-20) 0,
247
+ var(--sc-gray-20) 1px,
248
+ var(--sc-form-background) 1px,
249
+ var(--sc-form-background) 100%
250
+ );
203
251
  display: flex;
204
252
  flex-direction: column;
205
- z-index: 0;
253
+ z-index: 1001;
206
254
  }
207
- .action-set__drawer-header[data-v-40295597] {
255
+ .action-set__drawer-header[data-v-8ca97265] {
208
256
  display: flex;
209
257
  align-items: center;
210
258
  justify-content: flex-end;
211
- padding: 8px 12px;
259
+ padding: 4px 8px;
212
260
  flex-shrink: 0;
213
261
  }
214
- .action-set__drawer-close[data-v-40295597] {
262
+ .action-set__drawer-close[data-v-8ca97265] {
215
263
  flex-shrink: 0;
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: center;
216
267
  border: none;
217
268
  background: transparent;
218
269
  font-size: 1.25rem;
219
270
  line-height: 1;
220
271
  cursor: pointer;
221
272
  color: var(--sc-gray-60);
222
- padding: 0.5rem;
223
- min-width: 2.75rem;
224
- min-height: 2.75rem;
273
+ padding: 0;
274
+ width: 2.75rem;
275
+ height: 2.75rem;
225
276
  }
226
- .action-set__drawer-body[data-v-40295597] {
277
+ .action-set__drawer-body[data-v-8ca97265] {
227
278
  flex: 1;
228
279
  min-height: 0;
229
280
  overflow: auto;
281
+ display: flex;
282
+ flex-direction: column;
283
+ }
284
+ .action-set__drawer-body[data-v-8ca97265]:not(:has(.command-search)) {
285
+ padding: 0 12px 16px;
230
286
  }
231
- .action-set__drawer-empty[data-v-40295597] {
287
+ .action-set__drawer-empty[data-v-8ca97265] {
232
288
  padding: 16px 12px;
233
289
  margin: 0;
234
290
  color: var(--sc-gray-60);
235
291
  font-style: italic;
236
292
  }
237
- .action-set__actions-list[data-v-40295597] {
238
- padding: 8px;
293
+ .action-set__actions-list[data-v-8ca97265] {
294
+ padding: 0;
239
295
  }
240
- .action-set__actions-list-item[data-v-40295597] {
296
+ .action-set__actions-list-item[data-v-8ca97265] {
241
297
  display: block;
242
298
  box-sizing: border-box;
243
299
  width: 100%;
@@ -253,22 +309,22 @@
253
309
  text-decoration: none;
254
310
  cursor: pointer;
255
311
  }
256
- .action-set__actions-list-item[data-v-40295597]:hover {
312
+ .action-set__actions-list-item[data-v-8ca97265]:hover {
257
313
  background: var(--sc-btn-hover);
258
314
  }
259
- .action-set__actions-list-item[data-v-40295597]:disabled {
315
+ .action-set__actions-list-item[data-v-8ca97265]:disabled {
260
316
  opacity: 0.5;
261
317
  cursor: not-allowed;
262
318
  }
263
- .action-set__actions-list-item--nested[data-v-40295597] {
319
+ .action-set__actions-list-item--nested[data-v-8ca97265] {
264
320
  margin-left: 0;
265
321
  width: 100%;
266
322
  font-weight: 400;
267
323
  }
268
- .action-set__actions-group[data-v-40295597] {
324
+ .action-set__actions-group[data-v-8ca97265] {
269
325
  margin-bottom: 8px;
270
326
  }
271
- .action-set__actions-group-label[data-v-40295597] {
327
+ .action-set__actions-group-label[data-v-8ca97265] {
272
328
  margin: 4px 0 6px;
273
329
  padding: 0 2px;
274
330
  font-family: var(--sc-font-family);
@@ -278,7 +334,7 @@
278
334
  text-transform: uppercase;
279
335
  color: var(--sc-gray-60);
280
336
  }
281
- .action-set__actions-empty[data-v-40295597] {
337
+ .action-set__actions-empty[data-v-8ca97265] {
282
338
  padding: 16px 12px;
283
339
  margin: 0;
284
340
  color: var(--sc-gray-60);
@@ -432,7 +488,7 @@ a[data-v-cdbbd2a0]:focus-visible,
432
488
  flex-shrink: 0;
433
489
  }
434
490
 
435
- .desktop[data-v-378bae6b] {
491
+ .desktop[data-v-9ccbbb36] {
436
492
  position: relative;
437
493
  height: 100%;
438
494
  display: flex;
@@ -440,7 +496,7 @@ a[data-v-cdbbd2a0]:focus-visible,
440
496
  min-height: 0;
441
497
  overflow: hidden;
442
498
  }
443
- .desktop__workspace[data-v-378bae6b] {
499
+ .desktop__workspace[data-v-9ccbbb36] {
444
500
  display: flex;
445
501
  flex: 1;
446
502
  min-height: 0;
@@ -448,28 +504,38 @@ a[data-v-cdbbd2a0]:focus-visible,
448
504
  margin-right: 0;
449
505
  transition: margin-right 0.25s ease-out;
450
506
  }
451
- .desktop--action-set-open .desktop__workspace[data-v-378bae6b] {
452
- margin-right: var(--sc-action-set-drawer-width);
507
+
508
+ /* Pull workspace 1px under the drawer so Firefox does not leave a hairline at the seam. */
509
+ .desktop--action-set-open .desktop__workspace[data-v-9ccbbb36] {
510
+ margin-right: calc(var(--sc-action-set-drawer-width) - 1px);
453
511
  }
454
512
 
455
513
  /* SheetNav is fixed to the viewport, so the workspace margin does not move it clear of the drawer. */
456
- .desktop__sheetnav[data-v-378bae6b] {
514
+ .desktop__sheetnav[data-v-9ccbbb36] {
457
515
  transition: right 0.25s ease-out;
458
516
  }
459
- .desktop--action-set-open .desktop__sheetnav[data-v-378bae6b] {
517
+ .desktop--action-set-open .desktop__sheetnav[data-v-9ccbbb36] {
460
518
  right: var(--sc-action-set-drawer-width);
461
519
  }
462
- .desktop__main[data-v-378bae6b] {
520
+ .desktop__main[data-v-9ccbbb36] {
463
521
  flex: 1;
464
522
  min-width: 0;
465
523
  min-height: 0;
466
524
  overflow: auto;
525
+ /* Keep the scroll track left of the fixed tile column (drawer open shifts workspace instead). */
526
+ padding-right: calc(var(--sc-action-set-rail-width) + var(--sc-action-set-tile-gap));
527
+ scrollbar-gutter: stable;
528
+ }
529
+ .desktop--action-set-open .desktop__main[data-v-9ccbbb36] {
530
+ padding-right: 0;
531
+ /* Stable gutter reserves a column in Firefox; release it when the drawer owns the right edge. */
532
+ scrollbar-gutter: auto;
467
533
  }
468
- .desktop--preview-open .desktop__main[data-v-378bae6b] {
534
+ .desktop--preview-open .desktop__main[data-v-9ccbbb36] {
469
535
  flex: 0 0 calc(50% - 10px);
470
536
  max-width: calc(50% - 10px);
471
537
  }
472
- .desktop__preview[data-v-378bae6b] {
538
+ .desktop__preview[data-v-9ccbbb36] {
473
539
  flex: 0 0 50%;
474
540
  max-width: 50%;
475
541
  min-width: 0;
@@ -480,7 +546,7 @@ a[data-v-cdbbd2a0]:focus-visible,
480
546
  background: var(--sc-form-background);
481
547
  overflow: hidden;
482
548
  }
483
- .desktop__preview-header[data-v-378bae6b] {
549
+ .desktop__preview-header[data-v-9ccbbb36] {
484
550
  display: flex;
485
551
  justify-content: flex-end;
486
552
  align-items: center;
@@ -489,7 +555,7 @@ a[data-v-cdbbd2a0]:focus-visible,
489
555
  border-bottom: 1px solid var(--sc-gray-20);
490
556
  flex-shrink: 0;
491
557
  }
492
- .desktop__preview-close[data-v-378bae6b] {
558
+ .desktop__preview-close[data-v-9ccbbb36] {
493
559
  border: none;
494
560
  background: transparent;
495
561
  font-size: 1.25rem;
@@ -497,12 +563,12 @@ a[data-v-cdbbd2a0]:focus-visible,
497
563
  cursor: pointer;
498
564
  color: var(--sc-gray-60);
499
565
  }
500
- .desktop__preview-body[data-v-378bae6b] {
566
+ .desktop__preview-body[data-v-9ccbbb36] {
501
567
  flex: 1;
502
568
  min-height: 0;
503
569
  overflow: auto;
504
570
  }
505
- .loading[data-v-378bae6b] {
571
+ .loading[data-v-9ccbbb36] {
506
572
  display: flex;
507
573
  align-items: center;
508
574
  justify-content: center;