dsh-better-workspace 0.11.1 → 0.11.2
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/dsh.plugin.json +1 -1
- package/package.json +1 -1
- package/src/client.js +40 -58
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-better-workspace",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"description": "侧边栏工作区层级树:名称中的 / 即虚拟分组(web/前端 · web/后端),添加工作区的目录流附所属分组弹窗,重命名即时重排层级,可新建空分组。Hierarchy tree for the DSH sidebar workspace list.",
|
|
6
6
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-better-workspace",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "DSH web plugin: a hierarchical workspace tree for the sidebar. Workspace titles containing \"/\" group into virtual folders (web/前端 · web/后端); the add-workspace directory flow gains a parent-group popup; renames re-derive the tree; a new-folder button creates empty levels.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/client.js
CHANGED
|
@@ -2699,16 +2699,16 @@ window.__ModuleLoader__.load({
|
|
|
2699
2699
|
'.bw-row-icon{flex:none;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary,#9a9a9a)}',
|
|
2700
2700
|
'.bw-chevron{flex:none;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary,#9a9a9a);transition:transform .15s ease}',
|
|
2701
2701
|
'.bw-chevron-open{transform:rotate(90deg)}',
|
|
2702
|
-
//
|
|
2703
|
-
//
|
|
2704
|
-
//
|
|
2702
|
+
// overflow:hidden (needed for the ellipsis) clips the outline: 3px of
|
|
2703
|
+
// padding covers the widest rim (2px at the top of the slider). margin
|
|
2704
|
+
// cancels it, so text still starts and truncates where it did.
|
|
2705
2705
|
'.bw-row-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:3px;margin:-3px}',
|
|
2706
2706
|
'.bw-row-count{flex:none;font-size:11px;color:var(--dsw-alias-label-quaternary,#8a8a8a)}',
|
|
2707
2707
|
'.bw-row-time{flex:none;font-size:11px;color:var(--dsw-alias-label-quaternary,#8a8a8a)}',
|
|
2708
|
-
// The
|
|
2709
|
-
//
|
|
2710
|
-
//
|
|
2711
|
-
'.bw-row-count,.bw-row-time{text-
|
|
2708
|
+
// The outline is inherited from the row: the 11px meta column (session
|
|
2709
|
+
// count / relative time) opts out — stroked meta text outshines the title
|
|
2710
|
+
// it is supposed to support.
|
|
2711
|
+
'.bw-row-count,.bw-row-time{-webkit-text-stroke-width:0}',
|
|
2712
2712
|
'.bw-schedule-badge{flex:none;display:inline-flex;align-items:center;color:var(--dsw-alias-label-tertiary,#9a9a9a);margin:0 6px}',
|
|
2713
2713
|
'.bw-row-actions{flex:none;display:none;align-items:center;gap:2px}',
|
|
2714
2714
|
'.bw-row:hover .bw-row-actions{display:flex}',
|
|
@@ -2790,10 +2790,7 @@ window.__ModuleLoader__.load({
|
|
|
2790
2790
|
'.bw-pulse{animation:bw-breathe 1.8s ease-in-out infinite}',
|
|
2791
2791
|
'@keyframes bw-breathe{0%,100%{filter:drop-shadow(0 0 1px var(--bw-pulse-color));opacity:.55}50%{filter:drop-shadow(0 0 6px var(--bw-pulse-color));opacity:1}}',
|
|
2792
2792
|
'.bw-pulse-text{animation:bw-breathe-text 1.8s ease-in-out infinite}',
|
|
2793
|
-
|
|
2794
|
-
// in --bw-stroke-shadow (set by rowStyleOf, comma-terminated) and the empty
|
|
2795
|
-
// fallback keeps a row without an outline breathing exactly as before.
|
|
2796
|
-
'@keyframes bw-breathe-text{0%,100%{text-shadow:var(--bw-stroke-shadow,) 0 0 1px var(--bw-pulse-color);opacity:.65}50%{text-shadow:var(--bw-stroke-shadow,) 0 0 7px var(--bw-pulse-color);opacity:1}}',
|
|
2793
|
+
'@keyframes bw-breathe-text{0%,100%{text-shadow:0 0 1px var(--bw-pulse-color);opacity:.65}50%{text-shadow:0 0 7px var(--bw-pulse-color);opacity:1}}',
|
|
2797
2794
|
'.bw-sync-modes{display:flex;gap:6px;margin-top:8px}',
|
|
2798
2795
|
'.bw-sync-mode{flex:1;padding:5px 10px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2,rgba(127,127,127,.3));background:transparent;color:var(--dsw-alias-label-secondary,#b8b8b8);cursor:pointer;font-size:12px}',
|
|
2799
2796
|
'.bw-sync-mode-on{border-color:var(--dsw-alias-brand-primary,#5b8def);color:var(--dsw-alias-label-primary,#e6e6e6);background:var(--dsw-alias-bg-layer-2,rgba(127,127,127,.12))}',
|
|
@@ -3259,7 +3256,9 @@ window.__ModuleLoader__.load({
|
|
|
3259
3256
|
// and returns the opposite pole; rows without a custom color inherit
|
|
3260
3257
|
// --bw-stroke-color, sampled from the live computed style (see the sampler
|
|
3261
3258
|
// in BetterBrowser) so a palette flip needs no React render.
|
|
3262
|
-
|
|
3259
|
+
// The slider is the rim the eye actually sees (0.5..2px). strokeStyleOf
|
|
3260
|
+
// paints twice that because paint-order hides the inner half of the band.
|
|
3261
|
+
const STROKE_MAX = 2
|
|
3263
3262
|
// The outline color defaults to a plain gray: it reads on light and dark
|
|
3264
3263
|
// backgrounds alike without shouting like pure black/white. "auto" derives
|
|
3265
3264
|
// the contrasting pole from the font color instead.
|
|
@@ -3334,33 +3333,26 @@ window.__ModuleLoader__.load({
|
|
|
3334
3333
|
}
|
|
3335
3334
|
return colorToRgb(picked) ? picked : DEFAULT_APPEARANCE.strokeColor
|
|
3336
3335
|
}
|
|
3337
|
-
//
|
|
3338
|
-
//
|
|
3339
|
-
//
|
|
3340
|
-
//
|
|
3341
|
-
//
|
|
3342
|
-
//
|
|
3343
|
-
// edge reads as pale and uneven — the "jagged" outline.
|
|
3336
|
+
// paint-order keeps the stroke UNDER the fill so the glyph does not thin out
|
|
3337
|
+
// — the whole point of an outer outline. The price is half the band:
|
|
3338
|
+
// -webkit-text-stroke centres it on the outline and the fill covers the inner
|
|
3339
|
+
// half, so the painted width must be TWICE the rim the slider promises.
|
|
3340
|
+
// Painting the configured value (0.10.x) left a 0.5px rim that antialiasing
|
|
3341
|
+
// blended away into a pale, uneven edge.
|
|
3344
3342
|
//
|
|
3345
|
-
//
|
|
3346
|
-
//
|
|
3347
|
-
//
|
|
3348
|
-
//
|
|
3349
|
-
//
|
|
3350
|
-
//
|
|
3351
|
-
const
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
}
|
|
3359
|
-
const strokeShadowsOf = (appearance) => {
|
|
3360
|
-
if (!appearance || appearance.stroke === false) return []
|
|
3361
|
-
const color = strokeColorOf(appearance)
|
|
3362
|
-
const offset = strokeOffsetOf(appearance)
|
|
3363
|
-
return STROKE_DIRECTIONS.map(([dx, dy]) => (dx * offset) + 'px ' + (dy * offset) + 'px ' + color)
|
|
3343
|
+
// 0.11.1 replaced this with eight offset glyph copies. It measured better and
|
|
3344
|
+
// looked worse: eight directions are only four diagonal samples, so every
|
|
3345
|
+
// slope and curve came out as a string of detached blocks instead of a filled
|
|
3346
|
+
// rim. A geometric stroke is continuous by construction — it really is a path
|
|
3347
|
+
// stroke — so the answer is to give it enough width to survive antialiasing,
|
|
3348
|
+
// not to fake it out of copies.
|
|
3349
|
+
const strokeStyleOf = (appearance) => {
|
|
3350
|
+
if (!appearance || appearance.stroke === false) return null
|
|
3351
|
+
return {
|
|
3352
|
+
WebkitTextStrokeWidth: clampStrokeWidth(appearance.strokeWidth) * 2 + 'px',
|
|
3353
|
+
WebkitTextStrokeColor: strokeColorOf(appearance),
|
|
3354
|
+
paintOrder: 'stroke fill',
|
|
3355
|
+
}
|
|
3364
3356
|
}
|
|
3365
3357
|
|
|
3366
3358
|
function FolderRow({ node, depth, expanded, onToggle, onContextMenu, dropInto, dragEvents, custStyle, iconMode, pulse, t }) {
|
|
@@ -3383,7 +3375,7 @@ window.__ModuleLoader__.load({
|
|
|
3383
3375
|
E('span', { className: cls('bw-chevron', expanded && 'bw-chevron-open') }, icon('IconTriangleRightFill14', 14)),
|
|
3384
3376
|
E('span', { className: 'bw-row-icon' }, iconChild),
|
|
3385
3377
|
// A row that already carries a custom label glow breathes in sync.
|
|
3386
|
-
E('span', { className: cls('bw-row-label', pulse && custStyle && custStyle
|
|
3378
|
+
E('span', { className: cls('bw-row-label', pulse && custStyle && custStyle.textShadow && 'bw-pulse-text') }, node.name),
|
|
3387
3379
|
total > 0 ? E('span', { className: 'bw-row-count' }, String(total)) : null,
|
|
3388
3380
|
)
|
|
3389
3381
|
}
|
|
@@ -3404,7 +3396,7 @@ window.__ModuleLoader__.load({
|
|
|
3404
3396
|
},
|
|
3405
3397
|
E('span', { className: cls('bw-chevron', sessionsOpen && 'bw-chevron-open') }, icon('IconTriangleRightFill14', 14)),
|
|
3406
3398
|
E('span', { className: 'bw-row-icon' }, iconChild),
|
|
3407
|
-
E('span', { className: cls('bw-row-label', pulse && custStyle && custStyle
|
|
3399
|
+
E('span', { className: cls('bw-row-label', pulse && custStyle && custStyle.textShadow && 'bw-pulse-text'), title: workspace.title || workspace.leaf }, workspace.leaf),
|
|
3408
3400
|
count > 0 ? E('span', { className: 'bw-row-count' }, String(count)) : null,
|
|
3409
3401
|
E('span', { className: 'bw-row-actions', onClick: (e) => e.stopPropagation() },
|
|
3410
3402
|
E('button', { type: 'button', className: 'bw-icon-btn', 'aria-label': t('session.new'), onClick: (e) => { e.stopPropagation(); onStart() } }, icon('IconPlusOutline16')),
|
|
@@ -3591,7 +3583,7 @@ window.__ModuleLoader__.load({
|
|
|
3591
3583
|
next[index] = n
|
|
3592
3584
|
patch({ color: rgbToHex(next[0], next[1], next[2]) })
|
|
3593
3585
|
}
|
|
3594
|
-
const previewShadows =
|
|
3586
|
+
const previewShadows = []
|
|
3595
3587
|
if (glow > 0 && color) previewShadows.push('0 0 ' + glow + 'px ' + color)
|
|
3596
3588
|
if (shadow) previewShadows.push('1px 1px 2px rgba(0,0,0,.85)')
|
|
3597
3589
|
// The preview must show the REAL outline: with no custom color the pole
|
|
@@ -3611,6 +3603,7 @@ window.__ModuleLoader__.load({
|
|
|
3611
3603
|
const poll = setInterval(sample, 1500)
|
|
3612
3604
|
return () => clearInterval(poll)
|
|
3613
3605
|
}, [color, stroke])
|
|
3606
|
+
const previewStroke = strokeStyleOf(appearance)
|
|
3614
3607
|
return E('div', { className: 'bw-appearance' },
|
|
3615
3608
|
E('div', { className: 'bw-field' },
|
|
3616
3609
|
t('custom.color'),
|
|
@@ -3751,6 +3744,7 @@ window.__ModuleLoader__.load({
|
|
|
3751
3744
|
color: color || undefined,
|
|
3752
3745
|
fontWeight: weight > 0 ? weight : undefined,
|
|
3753
3746
|
textShadow: previewShadows.length > 0 ? previewShadows.join(',') : undefined,
|
|
3747
|
+
...(previewStroke || null),
|
|
3754
3748
|
},
|
|
3755
3749
|
},
|
|
3756
3750
|
allowIcon ? E('span', { className: 'bw-preview-icon' }, iconOf(iconMode, true)) : null,
|
|
@@ -4177,27 +4171,15 @@ window.__ModuleLoader__.load({
|
|
|
4177
4171
|
const glow = Number(appearance.glow) || 0
|
|
4178
4172
|
const weight = Number(appearance.weight) || 0
|
|
4179
4173
|
const shadow = appearance.shadow === true
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
const halos = []
|
|
4184
|
-
if (glow > 0 && color) halos.push('0 0 ' + glow + 'px ' + color)
|
|
4185
|
-
if (shadow) halos.push('1px 1px 2px rgba(0,0,0,.85)')
|
|
4186
|
-
const shadows = outline.concat(halos)
|
|
4174
|
+
const shadows = []
|
|
4175
|
+
if (glow > 0 && color) shadows.push('0 0 ' + glow + 'px ' + color)
|
|
4176
|
+
if (shadow) shadows.push('1px 1px 2px rgba(0,0,0,.85)')
|
|
4187
4177
|
const style = {}
|
|
4188
4178
|
if (color) style.color = color
|
|
4189
4179
|
if (weight > 0) style.fontWeight = weight
|
|
4190
4180
|
if (shadows.length > 0) style.textShadow = shadows.join(',')
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
// load-bearing — the pulse keyframes append the halo after it.
|
|
4194
|
-
if (outline.length > 0) style['--bw-stroke-shadow'] = outline.join(',') + ','
|
|
4195
|
-
// Meta text (session count / relative time) opts out of the rim but keeps
|
|
4196
|
-
// the halo, which it can only read from here.
|
|
4197
|
-
if (halos.length > 0) style['--bw-glow-shadow'] = halos.join(',')
|
|
4198
|
-
// The label breathes its text only when the row actually carries a halo;
|
|
4199
|
-
// a rim alone is not a reason to pulse.
|
|
4200
|
-
if (halos.length > 0) style['--bw-text-glow'] = '1'
|
|
4181
|
+
const stroke = strokeStyleOf(appearance)
|
|
4182
|
+
if (stroke) Object.assign(style, stroke)
|
|
4201
4183
|
return Object.keys(style).length > 0 ? style : null
|
|
4202
4184
|
}
|
|
4203
4185
|
const keyOf = (kind, payload) => {
|