@try-works/dsh-recursive-mode 0.1.10 → 0.1.12

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.
@@ -0,0 +1,397 @@
1
+ /**
2
+ * One-shot board/inspector stylesheet injection (run 15). The client bundle is a
3
+ * plain CJS closure with NO CSS pipeline (tsdown has no CSS handling), so we
4
+ * inject a single <style data-dsh-recursive> element into document.head and
5
+ * style via class names + the shell's --dsw-* theme tokens. That unlocks hover,
6
+ * grid layout, and light/dark/skin theme following — impossible with inline
7
+ * styles. Idempotent: guarded by document.querySelector, so every registration
8
+ * reuses the one element; the returned disposer removes it.
9
+ */
10
+
11
+ const BOARD_CSS = `
12
+ /* dsh-recursive board + inspector (theme-token driven, .rec-* scoped) */
13
+ .rec-board {
14
+ position: fixed;
15
+ inset: 0;
16
+ z-index: 9999;
17
+ background: var(--dsw-alias-bg-base);
18
+ color: var(--dsw-alias-label-primary);
19
+ font-family: var(--dsw-font-family);
20
+ display: flex;
21
+ flex-direction: column;
22
+ box-sizing: border-box;
23
+ padding: 14px 16px 16px;
24
+ gap: 12px;
25
+ pointer-events: auto;
26
+ overflow: hidden;
27
+ }
28
+
29
+ .rec-board-header {
30
+ display: flex;
31
+ align-items: center;
32
+ gap: 10px;
33
+ flex: none;
34
+ }
35
+
36
+ .rec-board-title {
37
+ margin: 0;
38
+ font-size: 16px;
39
+ font-weight: 700;
40
+ color: var(--dsw-alias-label-primary);
41
+ white-space: nowrap;
42
+ }
43
+
44
+ .rec-board-count {
45
+ flex: none;
46
+ font-size: 12px;
47
+ color: var(--dsw-alias-label-tertiary);
48
+ background: var(--dsw-alias-interactive-bg-hover);
49
+ border-radius: 999px;
50
+ padding: 1px 8px;
51
+ }
52
+
53
+ .rec-board-empty {
54
+ margin: 0;
55
+ padding: 40px;
56
+ text-align: center;
57
+ color: var(--dsw-alias-label-tertiary);
58
+ }
59
+
60
+ .rec-close {
61
+ position: absolute;
62
+ top: 14px;
63
+ right: 16px;
64
+ z-index: 1;
65
+ display: inline-flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ width: 26px;
69
+ height: 26px;
70
+ padding: 0;
71
+ background: transparent;
72
+ border: 1px solid var(--dsw-alias-border-l2);
73
+ border-radius: 6px;
74
+ color: var(--dsw-alias-label-secondary);
75
+ cursor: pointer;
76
+ font-size: 15px;
77
+ line-height: 1;
78
+ }
79
+
80
+ .rec-close:hover {
81
+ background: var(--dsw-alias-interactive-bg-hover);
82
+ color: var(--dsw-alias-label-primary);
83
+ }
84
+
85
+ .rec-columns {
86
+ display: grid;
87
+ grid-auto-flow: column;
88
+ grid-auto-columns: minmax(240px, 1fr);
89
+ gap: 12px;
90
+ flex: 1;
91
+ min-height: 0;
92
+ overflow-x: auto;
93
+ overflow-y: hidden;
94
+ overscroll-behavior-inline: contain;
95
+ padding-bottom: 6px;
96
+ scrollbar-color: var(--dsw-alias-border-l3) var(--dsw-alias-interactive-bg-hover);
97
+ scrollbar-width: thin;
98
+ }
99
+
100
+ .rec-columns::-webkit-scrollbar { height: 10px; }
101
+ .rec-columns::-webkit-scrollbar-track { background: var(--dsw-alias-interactive-bg-hover); border-radius: 999px; }
102
+ .rec-columns::-webkit-scrollbar-thumb { background: var(--dsw-alias-border-l3); background-clip: content-box; border: 2px solid transparent; border-radius: 999px; }
103
+ .rec-columns::-webkit-scrollbar-thumb:hover { background: var(--dsw-alias-border-l3); background-clip: content-box; }
104
+
105
+ .rec-column {
106
+ display: flex;
107
+ flex-direction: column;
108
+ min-height: 0;
109
+ background: var(--dsw-alias-bg-layer-2);
110
+ border: 1px solid var(--dsw-alias-border-l1);
111
+ border-radius: 12px;
112
+ overflow: hidden;
113
+ }
114
+
115
+ .rec-column-header {
116
+ display: flex;
117
+ align-items: center;
118
+ gap: 6px;
119
+ padding: 10px 12px;
120
+ flex: none;
121
+ }
122
+
123
+ .rec-column-title {
124
+ margin: 0;
125
+ flex: 1;
126
+ font-size: 13px;
127
+ font-weight: 700;
128
+ color: var(--dsw-alias-label-primary);
129
+ overflow: hidden;
130
+ text-overflow: ellipsis;
131
+ white-space: nowrap;
132
+ }
133
+
134
+ .rec-column-count {
135
+ flex: none;
136
+ font-size: 12px;
137
+ color: var(--dsw-alias-label-tertiary);
138
+ background: var(--dsw-alias-interactive-bg-hover);
139
+ border-radius: 999px;
140
+ padding: 1px 8px;
141
+ }
142
+
143
+ .rec-status-dot {
144
+ width: 8px;
145
+ height: 8px;
146
+ border-radius: 50%;
147
+ flex: none;
148
+ }
149
+
150
+ .rec-status-dot[data-status='new'] { background: var(--dsw-alias-label-tertiary); }
151
+ .rec-status-dot[data-status='active'] { background: var(--dsw-alias-state-business-primary); }
152
+ .rec-status-dot[data-status='paused'] { background: var(--dsw-alias-state-warn-primary); }
153
+ .rec-status-dot[data-status='blocked'] { background: var(--dsw-alias-state-error-primary); }
154
+ .rec-status-dot[data-status='complete'] { background: var(--dsw-alias-state-success-primary); }
155
+
156
+ .rec-cards {
157
+ display: flex;
158
+ flex-direction: column;
159
+ gap: 8px;
160
+ padding: 2px 8px 10px;
161
+ overflow-y: auto;
162
+ flex: 1;
163
+ min-height: 0;
164
+ }
165
+
166
+ .rec-column-empty {
167
+ padding: 24px 8px;
168
+ text-align: center;
169
+ font-size: 12px;
170
+ color: var(--dsw-alias-label-tertiary);
171
+ }
172
+
173
+ .rec-card {
174
+ display: flex;
175
+ flex-direction: column;
176
+ gap: 6px;
177
+ padding: 10px 12px;
178
+ text-align: left;
179
+ background: var(--dsw-alias-bg-base);
180
+ border: 1px solid var(--dsw-alias-border-l2);
181
+ border-radius: 10px;
182
+ cursor: pointer;
183
+ color: var(--dsw-alias-label-primary);
184
+ font-family: inherit;
185
+ transition: box-shadow 120ms ease, border-color 120ms ease, transform 120ms ease;
186
+ }
187
+
188
+ .rec-card:hover {
189
+ box-shadow: var(--dsw-shadow-lv2);
190
+ border-color: var(--dsw-alias-border-l3);
191
+ transform: translateY(-1px);
192
+ }
193
+
194
+ .rec-card:active {
195
+ box-shadow: var(--dsw-shadow-lv1);
196
+ transform: translateY(0);
197
+ }
198
+
199
+ .rec-card[data-state='active'] { border-color: var(--dsw-alias-state-business-primary); }
200
+ .rec-card[data-state='paused'] { border-color: var(--dsw-alias-state-warn-primary); }
201
+ .rec-card[data-state='blocked'] { border-color: var(--dsw-alias-state-error-primary); }
202
+ .rec-card[data-state='complete'] { border-color: var(--dsw-alias-state-success-primary); }
203
+
204
+ .rec-card-title {
205
+ font-size: 13px;
206
+ font-weight: 600;
207
+ line-height: 1.35;
208
+ overflow: hidden;
209
+ display: -webkit-box;
210
+ -webkit-line-clamp: 2;
211
+ -webkit-box-orient: vertical;
212
+ }
213
+
214
+ .rec-card-progress {
215
+ height: 6px;
216
+ background: var(--dsw-alias-interactive-bg-hover);
217
+ border-radius: 3px;
218
+ overflow: hidden;
219
+ }
220
+
221
+ .rec-card-progress-fill {
222
+ height: 100%;
223
+ background: var(--dsw-alias-state-business-primary);
224
+ }
225
+
226
+ .rec-card-meta {
227
+ display: flex;
228
+ align-items: center;
229
+ gap: 8px;
230
+ font-size: 11px;
231
+ color: var(--dsw-alias-label-tertiary);
232
+ }
233
+
234
+ .rec-card-phase {
235
+ flex: 1;
236
+ overflow: hidden;
237
+ text-overflow: ellipsis;
238
+ white-space: nowrap;
239
+ }
240
+
241
+ .rec-badge {
242
+ flex: none;
243
+ padding: 2px 10px;
244
+ font-size: 12px;
245
+ border-radius: 999px;
246
+ border: 1px solid var(--dsw-alias-border-l2);
247
+ color: var(--dsw-alias-label-secondary);
248
+ }
249
+
250
+ .rec-badge[data-status='active'] { color: var(--dsw-alias-state-business-primary); border-color: var(--dsw-alias-state-business-primary); }
251
+ .rec-badge[data-status='paused'] { color: var(--dsw-alias-state-warn-primary); border-color: var(--dsw-alias-state-warn-primary); }
252
+ .rec-badge[data-status='blocked'] { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }
253
+ .rec-badge[data-status='complete'] { color: var(--dsw-alias-state-success-primary); border-color: var(--dsw-alias-state-success-primary); }
254
+ .rec-badge[data-status='new'] { color: var(--dsw-alias-label-tertiary); }
255
+
256
+ .rec-badge-tamper {
257
+ color: var(--dsw-alias-state-error-primary);
258
+ border-color: var(--dsw-alias-state-error-primary);
259
+ }
260
+
261
+ /* inspector: centered modal-style detail */
262
+ .rec-inspector {
263
+ position: fixed;
264
+ inset: 0;
265
+ z-index: 9999;
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ background: var(--dsw-alias-bg-mask-1);
270
+ pointer-events: auto;
271
+ }
272
+
273
+ .rec-detail {
274
+ display: flex;
275
+ flex-direction: column;
276
+ width: min(640px, calc(100vw - 48px));
277
+ max-height: calc(100vh - 80px);
278
+ background: var(--dsw-alias-bg-base);
279
+ border: 1px solid var(--dsw-alias-border-l2);
280
+ border-radius: 14px;
281
+ box-shadow: var(--dsw-shadow-lv3);
282
+ color: var(--dsw-alias-label-primary);
283
+ overflow: hidden;
284
+ }
285
+
286
+ .rec-detail-header {
287
+ display: flex;
288
+ align-items: center;
289
+ gap: 10px;
290
+ padding: 14px 18px;
291
+ border-bottom: 1px solid var(--dsw-alias-separator-primary);
292
+ flex: none;
293
+ }
294
+
295
+ .rec-detail-title {
296
+ margin: 0;
297
+ flex: 1;
298
+ font-size: 15px;
299
+ font-weight: 700;
300
+ overflow-wrap: anywhere;
301
+ }
302
+
303
+ .rec-back {
304
+ display: inline-flex;
305
+ align-items: center;
306
+ gap: 4px;
307
+ padding: 5px 12px;
308
+ font-size: 12px;
309
+ color: var(--dsw-alias-label-primary);
310
+ background: transparent;
311
+ border: 1px solid var(--dsw-alias-border-l2);
312
+ border-radius: 8px;
313
+ cursor: pointer;
314
+ white-space: nowrap;
315
+ }
316
+
317
+ .rec-back:hover {
318
+ background: var(--dsw-alias-interactive-bg-hover);
319
+ }
320
+
321
+ .rec-detail-body {
322
+ padding: 14px 18px;
323
+ overflow-y: auto;
324
+ display: flex;
325
+ flex-direction: column;
326
+ gap: 16px;
327
+ flex: 1;
328
+ }
329
+
330
+ .rec-detail-section {
331
+ display: flex;
332
+ flex-direction: column;
333
+ gap: 6px;
334
+ }
335
+
336
+ .rec-detail-section h3 {
337
+ margin: 0;
338
+ font-size: 12px;
339
+ font-weight: 700;
340
+ color: var(--dsw-alias-label-tertiary);
341
+ }
342
+
343
+ .rec-phase-row {
344
+ display: flex;
345
+ align-items: center;
346
+ gap: 10px;
347
+ padding: 8px 10px;
348
+ border: 1px solid var(--dsw-alias-border-l1);
349
+ border-radius: 8px;
350
+ font-size: 13px;
351
+ }
352
+
353
+ .rec-phase-id {
354
+ min-width: 48px;
355
+ font-family: var(--dsw-font-markdown-code-block-small);
356
+ color: var(--dsw-alias-state-business-primary);
357
+ }
358
+
359
+ .rec-phase-name {
360
+ flex: 1;
361
+ color: var(--dsw-alias-label-primary);
362
+ overflow: hidden;
363
+ text-overflow: ellipsis;
364
+ white-space: nowrap;
365
+ }
366
+
367
+ .rec-lockhash {
368
+ font-family: var(--dsw-font-markdown-code-block-small);
369
+ font-size: 11px;
370
+ color: var(--dsw-alias-label-tertiary);
371
+ }
372
+
373
+ @media (prefers-reduced-motion: reduce) {
374
+ .rec-card, .rec-back, .rec-close { transition: none; }
375
+ }
376
+ `
377
+
378
+ /**
379
+ * Inject the board/inspector stylesheet once. Idempotent: if a <style
380
+ * data-dsh-recursive> already exists, returns a disposer that does nothing
381
+ * (the first injector owns the element). Returns a disposer that removes it.
382
+ */
383
+ export function injectBoardStyles(): () => void {
384
+ if (typeof document === 'undefined') return () => {}
385
+ const existing = document.querySelector('style[data-dsh-recursive]')
386
+ if (existing !== null) return () => {}
387
+ const style = document.createElement('style')
388
+ style.setAttribute('data-dsh-recursive', '')
389
+ style.textContent = BOARD_CSS
390
+ document.head.appendChild(style)
391
+ let disposed = false
392
+ return () => {
393
+ if (disposed) return
394
+ disposed = true
395
+ style.remove()
396
+ }
397
+ }