@deepseek-ai/dsh-client-ui-primitives 0.1.6-alpha.2 → 0.1.7-alpha.1
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.i18n.yaml +2 -2
- package/README.md +25 -11
- package/README.zh.md +25 -11
- package/lib/ConnectionIndicator.module.css +1 -10
- package/lib/HoverCard.module.css +27 -0
- package/lib/Menu.module.css +68 -48
- package/lib/Modal.module.css +6 -2
- package/lib/OnboardingSurface.module.css +1 -2
- package/lib/PathLabel.module.css +28 -0
- package/lib/RiskConfirmation.module.css +1 -1
- package/lib/SegmentedControl.module.css +76 -0
- package/lib/SegmentedTabs.module.css +55 -0
- package/lib/StateDot.module.css +64 -37
- package/lib/TerminalBlock.module.css +13 -6
- package/lib/TextShimmer.module.css +27 -0
- package/lib/Toast.module.css +31 -2
- package/lib/Tooltip.module.css +12 -0
- package/lib/index.js +5418 -2739
- package/lib/markdown/MarkdownText.module.css +1 -1
- package/lib/settings-form/SettingsForm.module.css +53 -0
- package/lib/settings-form/fields.module.css +145 -0
- package/lib/types/ConfigField.d.ts +33 -0
- package/lib/types/DisclosureRow.d.ts +4 -1
- package/lib/types/HoverCard.d.ts +14 -4
- package/lib/types/LinkIcon.d.ts +15 -30
- package/lib/types/Menu.d.ts +50 -5
- package/lib/types/PathLabel.d.ts +13 -0
- package/lib/types/PermissionIcon.d.ts +39 -0
- package/lib/types/ReferenceIcon.d.ts +12 -7
- package/lib/types/SegmentedControl.d.ts +35 -0
- package/lib/types/SegmentedTabs.d.ts +26 -0
- package/lib/types/SiteGlyph.d.ts +1 -1
- package/lib/types/StateDot.d.ts +6 -4
- package/lib/types/TerminalBlock.d.ts +15 -3
- package/lib/types/TextShimmer.d.ts +13 -0
- package/lib/types/Toast.d.ts +19 -2
- package/lib/types/Tooltip.d.ts +12 -2
- package/lib/types/code-file-types.d.ts +1 -1
- package/lib/types/code-highlighting.d.ts +19 -0
- package/lib/types/icons/index.d.ts +376 -195
- package/lib/types/icons/props.d.ts +1 -1
- package/lib/types/icons/shared-artwork.d.ts +36 -0
- package/lib/types/index.d.ts +21 -4
- package/lib/types/overlay-top-margin.d.ts +14 -0
- package/lib/types/plugin-artwork.d.ts +17 -0
- package/lib/types/settings-form/SettingsForm.d.ts +46 -0
- package/lib/types/settings-form/fields.d.ts +69 -0
- package/lib/types/settings-form/form-model.d.ts +214 -0
- package/lib/types/useAnchoredMaxHeight.d.ts +4 -1
- package/lib/types/useAnchoredPosition.d.ts +3 -1
- package/package.json +5 -3
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* The track is the same translucent fill the hover state uses, so it reads as
|
|
2
|
+
* a place rather than a second button; the one raised part is the indicator,
|
|
3
|
+
* a white pill that slides under the selected segment. Its stroke rides inside
|
|
4
|
+
* the soft elevation shadow (border: 0), the way every elevated surface draws
|
|
5
|
+
* its edge, so the elevation gate keeps it off the alias-border set.
|
|
6
|
+
*
|
|
7
|
+
* Segments are equal-width grid tracks sized to the widest label, which is
|
|
8
|
+
* what lets one indicator be placed arithmetically: the tablist carries the
|
|
9
|
+
* segment count and the selected index as custom properties, and the indicator
|
|
10
|
+
* derives its width and offset from them instead of measuring the DOM. */
|
|
11
|
+
.control {
|
|
12
|
+
position: relative;
|
|
13
|
+
display: inline-grid;
|
|
14
|
+
grid-auto-flow: column;
|
|
15
|
+
grid-auto-columns: 1fr;
|
|
16
|
+
gap: 2px;
|
|
17
|
+
padding: 3px;
|
|
18
|
+
border-radius: 9px;
|
|
19
|
+
background: var(--dsw-alias-interactive-bg-hover);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.indicator {
|
|
23
|
+
position: absolute;
|
|
24
|
+
top: 3px;
|
|
25
|
+
left: 3px;
|
|
26
|
+
width: calc((100% - 6px - 2px * (var(--dsh-segment-count) - 1)) / var(--dsh-segment-count));
|
|
27
|
+
height: calc(100% - 6px);
|
|
28
|
+
border: 0;
|
|
29
|
+
border-radius: 7px;
|
|
30
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
31
|
+
box-shadow: var(--dsw-elevation-soft);
|
|
32
|
+
transform: translateX(calc(var(--dsh-segment-index) * (100% + 2px)));
|
|
33
|
+
transition: transform 160ms ease;
|
|
34
|
+
pointer-events: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.tab {
|
|
38
|
+
box-sizing: border-box;
|
|
39
|
+
position: relative;
|
|
40
|
+
z-index: 1;
|
|
41
|
+
height: 28px;
|
|
42
|
+
padding: 0 16px;
|
|
43
|
+
border: 0;
|
|
44
|
+
border-radius: 7px;
|
|
45
|
+
background: transparent;
|
|
46
|
+
color: var(--dsw-alias-label-secondary);
|
|
47
|
+
font: inherit;
|
|
48
|
+
font-size: 13px;
|
|
49
|
+
line-height: 20px;
|
|
50
|
+
font-weight: 500;
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
transition: color 120ms ease;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.tab:hover:not(:disabled),
|
|
57
|
+
.tab[aria-selected='true'] {
|
|
58
|
+
color: var(--dsw-alias-label-primary);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.tab:disabled {
|
|
62
|
+
cursor: default;
|
|
63
|
+
opacity: 0.4;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.tab:focus-visible {
|
|
67
|
+
outline: 2px solid var(--dsw-alias-brand-primary);
|
|
68
|
+
outline-offset: -2px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@media (prefers-reduced-motion: reduce) {
|
|
72
|
+
.indicator,
|
|
73
|
+
.tab {
|
|
74
|
+
transition: none;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
.tabs {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: grid;
|
|
4
|
+
padding: 4px;
|
|
5
|
+
border-radius: 12px;
|
|
6
|
+
background: var(--dsw-alias-bg-module-platform);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.indicator {
|
|
10
|
+
position: absolute;
|
|
11
|
+
inset: 4px auto 4px 4px;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
border: 0.5px solid var(--dsw-alias-border-l3);
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
16
|
+
transition: transform 180ms ease;
|
|
17
|
+
pointer-events: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.tab {
|
|
21
|
+
position: relative;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
height: 34px;
|
|
24
|
+
padding: 0 12px;
|
|
25
|
+
border-radius: 8px;
|
|
26
|
+
font-size: 14px;
|
|
27
|
+
line-height: 20px;
|
|
28
|
+
background: transparent;
|
|
29
|
+
color: var(--dsw-alias-label-secondary);
|
|
30
|
+
transition: color 180ms ease;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.tab:hover,
|
|
34
|
+
.tab[aria-selected='true'] {
|
|
35
|
+
background: transparent;
|
|
36
|
+
color: var(--dsw-alias-label-primary);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.tab[aria-selected='true'] {
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.tab:focus-visible {
|
|
44
|
+
outline: none;
|
|
45
|
+
text-decoration: underline;
|
|
46
|
+
text-decoration-thickness: 1px;
|
|
47
|
+
text-underline-offset: 4px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@media (prefers-reduced-motion: reduce) {
|
|
51
|
+
.indicator,
|
|
52
|
+
.tab {
|
|
53
|
+
transition: none;
|
|
54
|
+
}
|
|
55
|
+
}
|
package/lib/StateDot.module.css
CHANGED
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* not this 450) — component-level var pinned to the static scale instead. */
|
|
3
|
-
.dot,
|
|
4
|
-
.matrix {
|
|
5
|
-
--dsh-state-ongoing: var(--dsw-static-deepseek-450);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/* Solid states: same-color halo via a 0.10-opacity outer layer (::before)
|
|
9
|
-
* with a 6/10-scale solid core. Layer color rides currentColor set per state. */
|
|
1
|
+
/* Solid states keep the 10px layout slot but paint one 6px currentColor core. */
|
|
10
2
|
.dot {
|
|
11
3
|
position: relative;
|
|
12
4
|
display: inline-block;
|
|
13
5
|
flex: none;
|
|
14
6
|
}
|
|
15
7
|
|
|
16
|
-
.dot::before {
|
|
17
|
-
content: '';
|
|
18
|
-
position: absolute;
|
|
19
|
-
inset: 0;
|
|
20
|
-
border-radius: 50%;
|
|
21
|
-
corner-shape: round;
|
|
22
|
-
background: currentColor;
|
|
23
|
-
opacity: 0.1;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
8
|
.dot::after {
|
|
27
9
|
content: '';
|
|
28
10
|
position: absolute;
|
|
@@ -44,30 +26,75 @@
|
|
|
44
26
|
color: var(--dsw-alias-state-error-primary);
|
|
45
27
|
}
|
|
46
28
|
|
|
47
|
-
/* Idle is the absence of activity
|
|
48
|
-
* tertiary label color so it recedes beside the three outcome colors. */
|
|
29
|
+
/* Idle is the absence of activity and uses the theme's neutral state step. */
|
|
49
30
|
.dot[data-state='idle'] {
|
|
50
|
-
color: var(--dsw-alias-
|
|
31
|
+
color: var(--dsw-alias-state-idle-primary);
|
|
51
32
|
}
|
|
52
33
|
|
|
53
|
-
/*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
|
|
57
|
-
.matrix {
|
|
34
|
+
/* Ongoing is the sole non-dot state: a quiet full ring sits behind a centered
|
|
35
|
+
* breathing arc while the complete glyph rotates continuously. Both animations
|
|
36
|
+
* share one 1.5s period so pinning their start times aligns them together. */
|
|
37
|
+
.spinner {
|
|
58
38
|
flex: none;
|
|
59
|
-
color: var(--
|
|
39
|
+
color: var(--dsw-alias-label-tertiary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.spinnerMotion {
|
|
43
|
+
transform-origin: center;
|
|
44
|
+
animation: dsh-state-dot-spin 1.5s linear infinite;
|
|
60
45
|
}
|
|
61
46
|
|
|
62
|
-
.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
47
|
+
.spinnerTrack,
|
|
48
|
+
.spinnerArc {
|
|
49
|
+
fill: none;
|
|
50
|
+
stroke: currentColor;
|
|
51
|
+
stroke-width: 2;
|
|
52
|
+
stroke-linecap: round;
|
|
66
53
|
}
|
|
67
54
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
12.5%, 24.9% { opacity: 0.6; }
|
|
71
|
-
25%, 37.4% { opacity: 0.35; }
|
|
72
|
-
37.5%, 100% { opacity: 0.15; }
|
|
55
|
+
.spinnerTrack {
|
|
56
|
+
opacity: 0.25;
|
|
73
57
|
}
|
|
58
|
+
|
|
59
|
+
.spinnerArc {
|
|
60
|
+
stroke-dasharray: 12 150;
|
|
61
|
+
animation: dsh-state-dot-dash 1.5s ease-in-out infinite;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@keyframes dsh-state-dot-spin {
|
|
65
|
+
to { transform: rotate(360deg); }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@keyframes dsh-state-dot-dash {
|
|
69
|
+
0% {
|
|
70
|
+
stroke-dasharray: 12 150;
|
|
71
|
+
stroke-dashoffset: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
50% {
|
|
75
|
+
stroke-dasharray: 24 150;
|
|
76
|
+
stroke-dashoffset: -6;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
100% {
|
|
80
|
+
stroke-dasharray: 12 150;
|
|
81
|
+
stroke-dashoffset: 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (prefers-reduced-motion: reduce) {
|
|
86
|
+
.spinnerMotion,
|
|
87
|
+
.spinnerArc {
|
|
88
|
+
animation: none;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.spinnerArc {
|
|
92
|
+
stroke-dasharray: 18 150;
|
|
93
|
+
stroke-dashoffset: -3;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.step { display: inline-flex; flex: none; align-items: center; justify-content: center; box-sizing: border-box; border-radius: 50%; corner-shape: round; border: 1.5px solid var(--dsw-alias-label-tertiary); color: var(--dsw-alias-label-primary-foreground); }
|
|
98
|
+
.step[data-state='done'] { border-color: var(--dsw-alias-state-success-primary); background: var(--dsw-alias-state-success-primary); }
|
|
99
|
+
.step[data-state='error'] { border-color: var(--dsw-alias-state-error-primary); background: var(--dsw-alias-state-error-primary); }
|
|
100
|
+
.step[data-state='warning'] { border-color: var(--dsw-alias-state-warn-primary); }
|
|
@@ -110,15 +110,18 @@
|
|
|
110
110
|
color: var(--dsw-alias-label-tertiary);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
/* `pre`, not `nowrap`: the prompt row renders the command verbatim,
|
|
114
|
-
`nowrap`
|
|
115
|
-
continuation.
|
|
113
|
+
/* Default `pre`, not `nowrap`: the prompt row renders the command verbatim,
|
|
114
|
+
and `nowrap` would collapse the repeated spaces, tabs, and alignment of an
|
|
115
|
+
indented continuation. Hosts opt into wrapping long commands by rebinding
|
|
116
|
+
the variable to `pre-wrap`; the ellipsis then simply never engages, and
|
|
117
|
+
overflow-wrap is inert while white-space stays `pre`. */
|
|
116
118
|
.command {
|
|
117
119
|
min-width: 0;
|
|
118
120
|
color: var(--dsw-alias-label-primary);
|
|
119
121
|
overflow: hidden;
|
|
120
122
|
text-overflow: ellipsis;
|
|
121
|
-
white-space: pre;
|
|
123
|
+
white-space: var(--dsl-terminal-command-whitespace, pre);
|
|
124
|
+
overflow-wrap: anywhere;
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
/* Capped to the prompt's line height (Pill's own 24px height would exceed a
|
|
@@ -176,10 +179,14 @@
|
|
|
176
179
|
margin: 6px;
|
|
177
180
|
}
|
|
178
181
|
|
|
179
|
-
/*
|
|
182
|
+
/* Default `pre`: alignment is the payload of terminal output. Hosts opt
|
|
183
|
+
into wrapping long lines by rebinding the variable to `pre-wrap`, which
|
|
184
|
+
also keeps the output region from ever scrolling sideways; overflow-wrap
|
|
185
|
+
is inert while white-space stays `pre`. */
|
|
180
186
|
.line {
|
|
181
187
|
min-height: var(--dsl-terminal-line-height);
|
|
182
|
-
white-space: pre;
|
|
188
|
+
white-space: var(--dsl-terminal-line-whitespace, pre);
|
|
189
|
+
overflow-wrap: anywhere;
|
|
183
190
|
}
|
|
184
191
|
|
|
185
192
|
.expand {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.root[data-text-shimmer] {
|
|
2
|
+
background-image: linear-gradient(
|
|
3
|
+
90deg,
|
|
4
|
+
currentColor calc(50% - var(--dsh-text-shimmer-spread)),
|
|
5
|
+
color-mix(in oklab, currentColor 50%, transparent),
|
|
6
|
+
currentColor calc(50% + var(--dsh-text-shimmer-spread))
|
|
7
|
+
);
|
|
8
|
+
background-position: 100% center;
|
|
9
|
+
background-repeat: no-repeat;
|
|
10
|
+
background-size: 250% 100%;
|
|
11
|
+
background-clip: text;
|
|
12
|
+
-webkit-background-clip: text;
|
|
13
|
+
-webkit-text-fill-color: transparent;
|
|
14
|
+
animation: dsh-text-shimmer 1.5s cubic-bezier(0.33, 0, 0.67, 1) infinite;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@keyframes dsh-text-shimmer {
|
|
18
|
+
66.6667%, 100% { background-position: 0% center; }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@media (prefers-reduced-motion: reduce) {
|
|
22
|
+
.root[data-text-shimmer] {
|
|
23
|
+
background-image: none;
|
|
24
|
+
-webkit-text-fill-color: currentColor;
|
|
25
|
+
animation: none;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/lib/Toast.module.css
CHANGED
|
@@ -23,8 +23,11 @@
|
|
|
23
23
|
max-width: min(640px, calc(100vw - 48px));
|
|
24
24
|
padding: 12px 16px;
|
|
25
25
|
border-radius: 14px;
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
/* The design platform's toast surface is dark in BOTH themes (bluish-800
|
|
27
|
+
light / bluish-750 dark), so the label and the action text below stay
|
|
28
|
+
fixed instead of flipping with the theme. */
|
|
29
|
+
background: var(--dsw-alias-toast-bg);
|
|
30
|
+
color: var(--dsw-static-neutral-bluish-00);
|
|
28
31
|
font-size: 14px;
|
|
29
32
|
line-height: 22px;
|
|
30
33
|
box-shadow: var(--dsw-shadow-lv3);
|
|
@@ -41,10 +44,35 @@
|
|
|
41
44
|
color: var(--dsw-alias-state-warn-label);
|
|
42
45
|
}
|
|
43
46
|
|
|
47
|
+
.icon.success {
|
|
48
|
+
color: var(--dsw-alias-state-success-primary);
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
.text {
|
|
45
52
|
min-width: 0;
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
.action {
|
|
56
|
+
display: inline;
|
|
57
|
+
padding: 0;
|
|
58
|
+
border: 0;
|
|
59
|
+
background: none;
|
|
60
|
+
/* deepseek-400, brightened at the designer's request, reads as the action
|
|
61
|
+
against the always-dark toast surface without an underline. */
|
|
62
|
+
color: var(--dsw-static-deepseek-400);
|
|
63
|
+
font: inherit;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
/* Breathing room where the action text meets the surrounding copy. */
|
|
66
|
+
margin-inline: 3px;
|
|
67
|
+
/* The banner surface stays click-through (`pointer-events: none` above);
|
|
68
|
+
only its action text takes the pointer. */
|
|
69
|
+
pointer-events: auto;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.action:hover {
|
|
73
|
+
opacity: 0.8;
|
|
74
|
+
}
|
|
75
|
+
|
|
48
76
|
@keyframes dsh-toast-in {
|
|
49
77
|
from {
|
|
50
78
|
opacity: 0;
|
|
@@ -60,6 +88,7 @@
|
|
|
60
88
|
@keyframes dsh-toast-fade {
|
|
61
89
|
to {
|
|
62
90
|
opacity: 0;
|
|
91
|
+
visibility: hidden;
|
|
63
92
|
}
|
|
64
93
|
}
|
|
65
94
|
|
package/lib/Tooltip.module.css
CHANGED
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
animation: tooltip-in 150ms var(--ds-ease-in-out);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.bubble[data-portal] { z-index: 1100; }
|
|
23
|
+
|
|
22
24
|
.bubble[data-side='right'] {
|
|
23
25
|
transform: translateY(-50%);
|
|
24
26
|
}
|
|
@@ -31,6 +33,16 @@
|
|
|
31
33
|
transform: translate(-50%, -100%);
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
/* End alignment: `left` carries the anchor's right edge, so the bubble sits
|
|
37
|
+
fully left of it instead of centering. */
|
|
38
|
+
.bubble[data-side='bottom'][data-align='end'] {
|
|
39
|
+
transform: translateX(-100%);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.bubble[data-side='top'][data-align='end'] {
|
|
43
|
+
transform: translate(-100%, -100%);
|
|
44
|
+
}
|
|
45
|
+
|
|
34
46
|
@keyframes tooltip-in {
|
|
35
47
|
from { opacity: 0; }
|
|
36
48
|
}
|