@morlay/dsh-client-ui-primitives 0.0.7 → 0.0.9
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 +32 -9
- package/dist/client-DYp99CgT.mjs +3730 -0
- package/dist/client-uyVkC7mu.cjs +17197 -0
- package/dist/client.cjs +54 -0
- package/dist/client.d.cts +4 -0
- package/dist/client.d.mts +3 -11680
- package/dist/client.mjs +3 -4575
- package/dist/index-AMHtcyMt.d.mts +647 -0
- package/dist/index.cjs +54 -0
- package/dist/index.d.mts +4 -5
- package/dist/index.mjs +4 -5
- package/dist/reference-hchCWm3z.cjs +482 -0
- package/dist/reference.cjs +4 -0
- package/dist/reference.d.mts +3 -0
- package/dist/reference.mjs +1 -0
- package/package.json +31 -35
- package/src/client/controls/Bubble.module.css +17 -0
- package/src/client/controls/Bubble.tsx +17 -0
- package/src/client/controls/Button.module.css +10 -0
- package/src/client/controls/Button.tsx +29 -0
- package/src/client/controls/DisclosureRow.module.css +22 -0
- package/src/client/controls/DisclosureRow.tsx +20 -0
- package/src/client/controls/IconButton.module.css +50 -0
- package/src/client/controls/IconButton.tsx +47 -0
- package/src/client/controls/ModelRouteList.module.css +100 -0
- package/src/client/controls/ModelRouteList.tsx +118 -0
- package/src/client/controls/MultilineField.module.css +26 -0
- package/src/client/controls/MultilineField.tsx +19 -0
- package/src/client/controls/SearchSelect.module.css +34 -0
- package/src/client/controls/SearchSelect.tsx +138 -0
- package/src/client/controls/SeatButton.module.css +53 -0
- package/src/client/controls/SeatButton.tsx +39 -0
- package/src/client/controls/Spinner.module.css +18 -0
- package/src/client/controls/Spinner.tsx +14 -0
- package/src/client/controls/TagInput.module.css +105 -0
- package/src/client/controls/TagInput.tsx +152 -0
- package/src/client/controls/TimeLabel.module.css +16 -0
- package/src/client/controls/TimeLabel.tsx +15 -0
- package/src/client/controls/VisuallyHidden.module.css +9 -0
- package/src/client/controls/VisuallyHidden.tsx +16 -0
- package/src/client/controls/classes.ts +5 -0
- package/src/client/controls/index.ts +24 -0
- package/src/client/controls/tags.ts +24 -0
- package/src/client/index.ts +16 -2
- package/src/client/layout/Row.tsx +89 -0
- package/src/client/layout/Stack.tsx +82 -0
- package/src/client/layout/Text.tsx +61 -0
- package/src/client/layout/index.ts +16 -0
- package/src/client/layout/layout.module.css +217 -0
- package/src/client/layout/scales.ts +91 -0
- package/src/client/schema-form/Editor.tsx +65 -65
- package/src/client/schema-form/SchemaForm.tsx +9 -4
- package/src/client/schema-form/controller.ts +5 -2
- package/src/client/schema-form/geometry.ts +3 -0
- package/src/client/schema-form/index.ts +5 -0
- package/src/client/schema-form/schema-form.module.css +335 -0
- package/src/client/schema-form/testing/fake-scope.ts +0 -1
- package/src/client/schema-form/value.tsx +15 -9
- package/src/client/settings-form/SettingsFieldRow.module.css +93 -0
- package/src/client/settings-form/SettingsFieldRow.tsx +105 -0
- package/src/client/settings-form/index.ts +5 -18
- package/src/css-modules.d.ts +6 -0
- package/src/index.ts +6 -2
- package/src/reference-markdown.tsx +2 -6
- package/dist/rolldown-runtime-EAsCxrDo.mjs +0 -14
- package/locale/en.json +0 -6
- package/locale/zh.json +0 -6
- package/src/client/schema-form/styles.ts +0 -321
- package/src/client/settings-form/SettingsForm.styles.ts +0 -58
- package/src/client/settings-form/SettingsForm.tsx +0 -68
- package/src/client/settings-form/fields.styles.ts +0 -158
- package/src/client/settings-form/fields.tsx +0 -184
- package/src/client/settings-form/form-model.ts +0 -339
- package/src/client/styling/css.ts +0 -27
- package/src/client/styling/focus.ts +0 -9
- package/src/client/styling/index.ts +0 -6
- package/src/client/styling/styled.tsx +0 -54
- package/src/client/styling/styling.ts +0 -142
- package/src/client/styling/token.ts +0 -275
- package/src/client/styling/toolkit.ts +0 -37
- package/src/client/theme.generated.ts +0 -846
- package/src/client/theme.ts +0 -5
- /package/src/{client/markdown-text.ts → markdown-text.ts} +0 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/* 行式编辑器的样式:等宽、行号、语法色、悬停行为——全部消费官方 `--dsw-*` token。
|
|
2
|
+
几何只有一套:行高 22px、行内间距 6px、动作键 20px、折叠列 14px、行号列 32px,行与行之间不各自决定。 */
|
|
3
|
+
|
|
4
|
+
.editorRoot {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
width: 100%;
|
|
8
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
9
|
+
font-size: 14px;
|
|
10
|
+
line-height: 22px;
|
|
11
|
+
color: var(--dsw-alias-label-primary);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* 一行:行号 + 折进 + 行内容。悬停给一层浅底。 */
|
|
15
|
+
.lineRow {
|
|
16
|
+
display: flex;
|
|
17
|
+
/* 顶部对齐:行里出现输入框或多行值时,内容不跟着上下跳。 */
|
|
18
|
+
align-items: flex-start;
|
|
19
|
+
gap: 6px;
|
|
20
|
+
min-height: 22px;
|
|
21
|
+
padding-right: 8px;
|
|
22
|
+
white-space: nowrap;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.lineRow:hover {
|
|
26
|
+
background: var(--dsw-alias-bg-layer-2);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* 选中一行(点行号):整行留一层底色,便于对着行号找内容。 */
|
|
30
|
+
.lineRow[data-selected="true"] {
|
|
31
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* 本页改过还没保存:左边一道强调色,和「已经存进用户层」的浅灰区分开。 */
|
|
35
|
+
.lineRow[data-dirty="true"] {
|
|
36
|
+
box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.lineRow[data-overridden="true"] {
|
|
40
|
+
box-shadow: inset 2px 0 0 var(--dsw-elevation-stroke-color);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* 改过的字段名用强调色(存没存看左边那道条);出错时红优先。 */
|
|
44
|
+
.lineRow[data-dirty="true"] [data-role="key"] {
|
|
45
|
+
color: var(--dsw-alias-brand-primary);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.lineRow[data-overridden="true"] [data-role="key"] {
|
|
49
|
+
color: var(--dsw-alias-brand-primary);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* 有问题的行:半透明红底 + 左侧一道实红条,字段名与注释位那句都是红字。 */
|
|
53
|
+
.lineRow[data-invalid="true"] {
|
|
54
|
+
background: color-mix(in srgb, var(--dsw-alias-state-error-secondary) 12%, transparent);
|
|
55
|
+
box-shadow: inset 2px 0 0 var(--dsw-alias-state-error-primary);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.lineRow[data-invalid="true"] [data-role="key"] {
|
|
59
|
+
color: var(--dsw-alias-state-error-primary);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* 行内的行为按钮(撤回 / 恢复默认 / 复制 / 移除):平时透明,悬停这一行才显形。 */
|
|
63
|
+
.lineRow:hover [data-role="actions"] {
|
|
64
|
+
opacity: 1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* 一行的内容区:**缩进只作用在这里**——行号列固定在左边,缩进不推它。 */
|
|
68
|
+
.lineBody {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: 6px;
|
|
72
|
+
flex: 1;
|
|
73
|
+
min-width: 0;
|
|
74
|
+
min-height: 22px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* 行号列:右对齐、不可选、淡色。 */
|
|
78
|
+
.lineNumber {
|
|
79
|
+
flex: none;
|
|
80
|
+
width: 32px;
|
|
81
|
+
line-height: 22px;
|
|
82
|
+
text-align: right;
|
|
83
|
+
color: var(--dsw-alias-label-caption);
|
|
84
|
+
user-select: none;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* 折叠 chevron(官方箭头图标,尺寸与别的行内图标同源)。 */
|
|
89
|
+
.lineFold {
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
flex: none;
|
|
94
|
+
width: 14px;
|
|
95
|
+
height: 22px;
|
|
96
|
+
padding: 0;
|
|
97
|
+
border: 0;
|
|
98
|
+
background: none;
|
|
99
|
+
color: var(--dsw-alias-label-caption);
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.lineFold:hover {
|
|
104
|
+
color: var(--dsw-alias-label-secondary);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* 叶子行的折叠占位(保持列对齐)。 */
|
|
108
|
+
.lineFoldSpacer {
|
|
109
|
+
flex: none;
|
|
110
|
+
width: 14px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* 键名(配置键原样;数组下标淡一些)。 */
|
|
114
|
+
.lineKey {
|
|
115
|
+
flex: none;
|
|
116
|
+
color: var(--dsw-alias-label-primary);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.lineKey[data-index="true"] {
|
|
120
|
+
color: var(--dsw-alias-label-caption);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* 结构符与标点(`{` `}` `[` `]` `:`)。 */
|
|
124
|
+
.lineToken {
|
|
125
|
+
flex: none;
|
|
126
|
+
color: var(--dsw-alias-label-caption);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* 值(token):字符串 / 数字 / 布尔各有语法色。
|
|
130
|
+
**必须是块级盒**:`overflow` / `text-overflow` 对 inline 盒不生效,inline 的 token 无论多长都不会截断,
|
|
131
|
+
只会把行撑宽。 */
|
|
132
|
+
.lineValue {
|
|
133
|
+
display: block;
|
|
134
|
+
min-width: 0;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
text-overflow: ellipsis;
|
|
137
|
+
cursor: text;
|
|
138
|
+
color: var(--dsw-alias-state-business-primary);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.lineValue[data-tone="number"] {
|
|
142
|
+
color: var(--dsw-alias-state-warn-primary);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.lineValue[data-tone="boolean"] {
|
|
146
|
+
color: var(--dsw-alias-state-success-primary);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.lineValue[data-tone="empty"] {
|
|
150
|
+
color: var(--dsw-alias-label-caption);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* 值在行里的位置(字段槽的宿主):键名与结构符都是 `flex: none`,它是行里**唯一可收缩**的那一项。
|
|
154
|
+
不生长:短值保持自然宽度,长值才收缩到行尾并自己截断。 */
|
|
155
|
+
.valueSlot {
|
|
156
|
+
display: block;
|
|
157
|
+
flex: 0 1 auto;
|
|
158
|
+
min-width: 0;
|
|
159
|
+
overflow: hidden;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* 值上的下拉触发:**它自己就是值的呈现**(不再是「值 + 一个下拉」两遍),点开才出菜单。 */
|
|
163
|
+
.valueTrigger {
|
|
164
|
+
display: inline-flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
gap: 2px;
|
|
167
|
+
min-width: 0;
|
|
168
|
+
padding: 0;
|
|
169
|
+
border: 0;
|
|
170
|
+
background: none;
|
|
171
|
+
font: inherit;
|
|
172
|
+
text-align: left;
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
color: var(--dsw-alias-label-caption);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.valueTrigger:disabled {
|
|
178
|
+
cursor: default;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.valueTrigger:focus-visible {
|
|
182
|
+
outline: none;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* 行内输入的外壳:官方 `Input` 压到与值同一行高,并**吃掉剩下的宽度**。
|
|
186
|
+
行内编辑与容器闭合行的添加输入共用它——两处的输入框因此长得一模一样。 */
|
|
187
|
+
.compactInput {
|
|
188
|
+
display: inline-flex;
|
|
189
|
+
flex: 1 1 auto;
|
|
190
|
+
min-width: 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.compactInput > span {
|
|
194
|
+
width: 100%;
|
|
195
|
+
height: 22px;
|
|
196
|
+
padding: 0 6px;
|
|
197
|
+
border-radius: 4px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.compactInput input {
|
|
201
|
+
font-size: 14px;
|
|
202
|
+
line-height: 22px;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* 多行值的行内输入:官方没有多行原子,所以这里用同一套观感的字段壳(同边框、同圆角、同焦点色),
|
|
206
|
+
高度跟着内容长、宽度同样撑满剩下的位置。 */
|
|
207
|
+
.compactTextField {
|
|
208
|
+
display: inline-flex;
|
|
209
|
+
flex: 1 1 auto;
|
|
210
|
+
min-width: 0;
|
|
211
|
+
padding: 0 6px;
|
|
212
|
+
border-radius: 4px;
|
|
213
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
214
|
+
/* 细线走 theme 的描边(0.5px 与颜色都由 token 给)。 */
|
|
215
|
+
border: 0;
|
|
216
|
+
box-shadow: 0 0 0 0.5px var(--dsw-elevation-stroke-color);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.compactTextField:focus-within {
|
|
220
|
+
--dsw-elevation-stroke-color: var(--dsw-alias-brand-primary);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.compactTextField > textarea {
|
|
224
|
+
flex: 1;
|
|
225
|
+
width: 100%;
|
|
226
|
+
min-height: 20px;
|
|
227
|
+
max-height: 240px;
|
|
228
|
+
padding: 0;
|
|
229
|
+
border: 0;
|
|
230
|
+
outline: none;
|
|
231
|
+
background: transparent;
|
|
232
|
+
resize: none;
|
|
233
|
+
field-sizing: content;
|
|
234
|
+
font-family: inherit;
|
|
235
|
+
font-size: 14px;
|
|
236
|
+
line-height: 22px;
|
|
237
|
+
color: var(--dsw-alias-label-primary);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* 行内注释(schema 说明与业务文案):比配置值小一档、tertiary 色,占满这一行剩下的宽度,长了就截断——
|
|
241
|
+
**真的被截断时**才由官方 `Tooltip` 给全文。 */
|
|
242
|
+
.lineComment {
|
|
243
|
+
flex: 1 1 auto;
|
|
244
|
+
min-width: 0;
|
|
245
|
+
overflow: hidden;
|
|
246
|
+
text-overflow: ellipsis;
|
|
247
|
+
color: var(--dsw-alias-label-tertiary);
|
|
248
|
+
font-family: inherit;
|
|
249
|
+
font-size: 12px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* 行内的校验消息(与注释放同一档字号):可收缩、自己截断、**截断了**才由官方 `Tooltip` 给全文。
|
|
253
|
+
`flex: 0 1 auto`(不生长):短消息别铺满整行,添加入口那一行里也不跟输入框抢剩下的宽度。 */
|
|
254
|
+
.lineInvalid {
|
|
255
|
+
flex: 0 1 auto;
|
|
256
|
+
min-width: 0;
|
|
257
|
+
overflow: hidden;
|
|
258
|
+
text-overflow: ellipsis;
|
|
259
|
+
color: var(--dsw-alias-state-error-primary);
|
|
260
|
+
font-family: inherit;
|
|
261
|
+
font-size: 12px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* 行尾的动作组:方形图标键(默认透明,悬停时显形,显形规则写在行上)。 */
|
|
265
|
+
.lineActions {
|
|
266
|
+
display: inline-flex;
|
|
267
|
+
align-items: center;
|
|
268
|
+
gap: 4px;
|
|
269
|
+
flex: none;
|
|
270
|
+
opacity: 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.lineActions > button {
|
|
274
|
+
display: inline-flex;
|
|
275
|
+
align-items: center;
|
|
276
|
+
justify-content: center;
|
|
277
|
+
width: 20px;
|
|
278
|
+
height: 20px;
|
|
279
|
+
padding: 0;
|
|
280
|
+
border: 0;
|
|
281
|
+
border-radius: 4px;
|
|
282
|
+
background: none;
|
|
283
|
+
color: var(--dsw-alias-label-secondary);
|
|
284
|
+
cursor: pointer;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.lineActions > button:hover {
|
|
288
|
+
background: var(--dsw-alias-bg-layer-3);
|
|
289
|
+
color: var(--dsw-alias-label-primary);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.lineActions > button:disabled {
|
|
293
|
+
cursor: not-allowed;
|
|
294
|
+
color: var(--dsw-alias-label-dimmed);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/* 编辑态的两个按钮常显,而且**要有底色与描边**:行底色上只有淡色图标是看不见的,
|
|
298
|
+
所以这里给实体按钮(theme 的描边 + 一层底),确认用成功档、取消用中性档。 */
|
|
299
|
+
.hoverActions[data-editing="true"] {
|
|
300
|
+
opacity: 1;
|
|
301
|
+
gap: 6px;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.hoverActions[data-editing="true"] > button {
|
|
305
|
+
box-shadow: 0 0 0 0.5px var(--dsw-elevation-stroke-color);
|
|
306
|
+
background: var(--dsw-alias-bg-layer-1);
|
|
307
|
+
color: var(--dsw-alias-label-primary);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.hoverActions[data-editing="true"] > button:first-of-type {
|
|
311
|
+
color: var(--dsw-alias-state-success-primary);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* 添加输入:**跟在容器的闭合括号同一行**(菜单锚在它上面),宽度吃掉剩下的位置。 */
|
|
315
|
+
.addWrap {
|
|
316
|
+
position: relative;
|
|
317
|
+
display: inline-flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
gap: 6px;
|
|
320
|
+
flex: 1 1 auto;
|
|
321
|
+
min-width: 0;
|
|
322
|
+
margin-left: 6px;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.addWrap[data-invalid="true"] input {
|
|
326
|
+
border-color: var(--dsw-alias-state-error-primary);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* 一行说明(不可用 / 没有可生成项时用)。 */
|
|
330
|
+
.hint {
|
|
331
|
+
margin: 0;
|
|
332
|
+
font-size: 12px;
|
|
333
|
+
line-height: 1.5;
|
|
334
|
+
color: var(--dsw-alias-label-tertiary);
|
|
335
|
+
}
|
|
@@ -7,7 +7,8 @@ import { useState, type ReactNode } from "react";
|
|
|
7
7
|
import { IconChevronDownOutlineRegular, Menu } from "@deepseek-ai/dsh-client-ui-primitives";
|
|
8
8
|
import type { SelectOption } from "./hints.ts";
|
|
9
9
|
import type { SchemaFieldOwnerProps } from "./slot-contract.ts";
|
|
10
|
-
import { ICON_SIZE
|
|
10
|
+
import { ICON_SIZE } from "./geometry.ts";
|
|
11
|
+
import css from "./schema-form.module.css";
|
|
11
12
|
import { TruncatedTooltip } from "./TruncatedTooltip.tsx";
|
|
12
13
|
|
|
13
14
|
// 编辑态文本:字符串就是原文(换行照旧),其余按 JSON 写。
|
|
@@ -46,18 +47,21 @@ export function InlineValue({ owner }: { owner: SchemaFieldOwnerProps }): ReactN
|
|
|
46
47
|
// secret 不回显值:这里显示的是「已配置」的 `••••••`,它不会截断,`owner.hint` 也不是「被截断文本的全文」
|
|
47
48
|
// ——按行内浮层的口径它不该弹气泡,所以回到非侵入的原行为:挂原生 `title`。
|
|
48
49
|
return (
|
|
49
|
-
<
|
|
50
|
+
<span className={css.lineValue} data-tone="empty" title={owner.hint}>
|
|
50
51
|
{owner.secretConfigured ? "••••••" : ""}
|
|
51
|
-
</
|
|
52
|
+
</span>
|
|
52
53
|
);
|
|
53
54
|
}
|
|
54
55
|
// 值长了会在行里截断(值槽可收缩):确实截断时整份内容由官方 `Tooltip` 承载,放得下就不挂。
|
|
55
56
|
const text = tokenText(owner.value);
|
|
56
57
|
return (
|
|
57
58
|
<TruncatedTooltip label={text}>
|
|
58
|
-
<
|
|
59
|
+
<span
|
|
60
|
+
className={css.lineValue}
|
|
61
|
+
data-tone={owner.node.readOnly === null ? tokenTone(owner.value) : "empty"}
|
|
62
|
+
>
|
|
59
63
|
{text}
|
|
60
|
-
</
|
|
64
|
+
</span>
|
|
61
65
|
</TruncatedTooltip>
|
|
62
66
|
);
|
|
63
67
|
}
|
|
@@ -101,7 +105,8 @@ function OptionSelect({
|
|
|
101
105
|
setOpen(false);
|
|
102
106
|
}}
|
|
103
107
|
anchor={
|
|
104
|
-
<
|
|
108
|
+
<button
|
|
109
|
+
className={css.valueTrigger}
|
|
105
110
|
type="button"
|
|
106
111
|
disabled={owner.disabled}
|
|
107
112
|
aria-label={owner.label}
|
|
@@ -109,13 +114,14 @@ function OptionSelect({
|
|
|
109
114
|
setOpen(true);
|
|
110
115
|
}}
|
|
111
116
|
>
|
|
112
|
-
<
|
|
117
|
+
<span
|
|
118
|
+
className={css.lineValue}
|
|
113
119
|
data-tone={current === undefined ? tokenTone(owner.value) : tokenTone(current.value)}
|
|
114
120
|
>
|
|
115
121
|
{label}
|
|
116
|
-
</
|
|
122
|
+
</span>
|
|
117
123
|
<IconChevronDownOutlineRegular size={ICON_SIZE} />
|
|
118
|
-
</
|
|
124
|
+
</button>
|
|
119
125
|
}
|
|
120
126
|
/>
|
|
121
127
|
);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* 字段行(`SettingsFieldRow`):官方 `SettingsValueField` 的留白口径(上下各 12px),分隔线由调用方按
|
|
2
|
+
「不是这一组的第一个字段」显式声明——两种排法与官方控件的留白因此完全一致。 */
|
|
3
|
+
.row {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.row[data-divider="true"] {
|
|
9
|
+
border-top: 0.5px solid var(--dsw-alias-border-l2);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* 上下排(输入类):标签 / 控件 / 说明同列。 */
|
|
13
|
+
.body {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: 6px;
|
|
17
|
+
padding: 12px 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* 右置排(切换类):左列标签与说明,控件贴最右。 */
|
|
21
|
+
.inline {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: row;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: space-between;
|
|
26
|
+
gap: 16px;
|
|
27
|
+
padding: 12px 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.text {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: 2px;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.label {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 8px;
|
|
41
|
+
font-size: 13px;
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
line-height: 1.5;
|
|
44
|
+
color: var(--dsw-alias-label-primary);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* 覆盖标记(「已覆盖」):照官方 badge 的 neutral 那一档。 */
|
|
48
|
+
.badge {
|
|
49
|
+
display: inline-flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
padding: 1px 8px;
|
|
52
|
+
border-radius: 999px;
|
|
53
|
+
corner-shape: round;
|
|
54
|
+
font-size: 11px;
|
|
55
|
+
line-height: 17px;
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
color: var(--dsw-alias-label-secondary);
|
|
58
|
+
background: var(--dsw-alias-bg-module-platform);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* 恢复默认的入口:文字按钮,没有边框与底色。 */
|
|
62
|
+
.reset {
|
|
63
|
+
padding: 0;
|
|
64
|
+
border: none;
|
|
65
|
+
background: none;
|
|
66
|
+
font: inherit;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
line-height: 1.5;
|
|
69
|
+
color: var(--dsw-alias-label-secondary);
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.reset:hover:not(:disabled) {
|
|
74
|
+
color: var(--dsw-alias-label-primary);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.reset:disabled {
|
|
78
|
+
cursor: default;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.hint {
|
|
82
|
+
margin: 0;
|
|
83
|
+
font-size: 12px;
|
|
84
|
+
line-height: 1.5;
|
|
85
|
+
color: var(--dsw-alias-label-tertiary);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.invalid {
|
|
89
|
+
margin: 0;
|
|
90
|
+
font-size: 12px;
|
|
91
|
+
line-height: 1.5;
|
|
92
|
+
color: var(--dsw-alias-state-error-primary);
|
|
93
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// 字段行:设置面上"一个字段"的容器——标签、控件、说明、非法提示与"已覆盖"徽标都由它摆位置。
|
|
2
|
+
// 两种排法按控件的宽度选:输入类(stack)是标签 / 控件 / 说明同列,切换类(inline)把控件贴最右。
|
|
3
|
+
// 留白与分隔线的口径与官方 `SettingsValueField` 一致(上下各 12px、相邻 0.5px 细线)。
|
|
4
|
+
|
|
5
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
6
|
+
import { classes } from "../controls/classes.ts";
|
|
7
|
+
import css from "./SettingsFieldRow.module.css";
|
|
8
|
+
|
|
9
|
+
export interface SettingsFieldRowProps extends Omit<
|
|
10
|
+
HTMLAttributes<HTMLDivElement>,
|
|
11
|
+
"children" | "color"
|
|
12
|
+
> {
|
|
13
|
+
// 字段名。
|
|
14
|
+
label: string;
|
|
15
|
+
// 字段下面那句说明("这一项到底管什么")。
|
|
16
|
+
hint: string;
|
|
17
|
+
// 控件的摆法:`stack`(同列,输入类,缺省)或 `inline`(控件贴右,切换类)。
|
|
18
|
+
layout?: "stack" | "inline";
|
|
19
|
+
// 与上一个字段之间画一条细分隔线(这一组里不是第一个字段时为 true)。
|
|
20
|
+
divider?: boolean;
|
|
21
|
+
// 字段被用户层覆盖时的徽标文案;不给就不显示。
|
|
22
|
+
overriddenLabel?: string;
|
|
23
|
+
// 恢复默认的入口:给了它与 `resetLabel` 才显示(覆盖用户层那一项)。
|
|
24
|
+
resetLabel?: string;
|
|
25
|
+
onReset?: () => void;
|
|
26
|
+
// 非法提示;不给就只说合法的那些。
|
|
27
|
+
invalid?: string;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function SettingsFieldRow({
|
|
32
|
+
label,
|
|
33
|
+
hint,
|
|
34
|
+
layout = "stack",
|
|
35
|
+
divider = false,
|
|
36
|
+
overriddenLabel,
|
|
37
|
+
resetLabel,
|
|
38
|
+
onReset,
|
|
39
|
+
invalid,
|
|
40
|
+
children,
|
|
41
|
+
className,
|
|
42
|
+
...rest
|
|
43
|
+
}: SettingsFieldRowProps): ReactNode {
|
|
44
|
+
const labelNode = (
|
|
45
|
+
<span className={css.label}>
|
|
46
|
+
{label}
|
|
47
|
+
{overriddenLabel === undefined ? null : (
|
|
48
|
+
<>
|
|
49
|
+
<span className={css.badge}>{overriddenLabel}</span>
|
|
50
|
+
{resetLabel === undefined || onReset === undefined ? null : (
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
className={css.reset}
|
|
54
|
+
onClick={() => {
|
|
55
|
+
onReset();
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
{resetLabel}
|
|
59
|
+
</button>
|
|
60
|
+
)}
|
|
61
|
+
</>
|
|
62
|
+
)}
|
|
63
|
+
</span>
|
|
64
|
+
);
|
|
65
|
+
const invalidNode =
|
|
66
|
+
invalid === undefined ? null : (
|
|
67
|
+
<p className={css.invalid} role="alert">
|
|
68
|
+
{invalid}
|
|
69
|
+
</p>
|
|
70
|
+
);
|
|
71
|
+
if (layout === "inline") {
|
|
72
|
+
return (
|
|
73
|
+
<div
|
|
74
|
+
className={classes(css.row, className)}
|
|
75
|
+
data-role="field-row"
|
|
76
|
+
data-divider={divider ? "true" : "false"}
|
|
77
|
+
{...rest}
|
|
78
|
+
>
|
|
79
|
+
<div className={css.inline}>
|
|
80
|
+
<div className={css.text}>
|
|
81
|
+
{labelNode}
|
|
82
|
+
<p className={css.hint}>{hint}</p>
|
|
83
|
+
</div>
|
|
84
|
+
{children}
|
|
85
|
+
</div>
|
|
86
|
+
{invalidNode}
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return (
|
|
91
|
+
<div
|
|
92
|
+
className={classes(css.row, className)}
|
|
93
|
+
data-role="field-row"
|
|
94
|
+
data-divider={divider ? "true" : "false"}
|
|
95
|
+
{...rest}
|
|
96
|
+
>
|
|
97
|
+
<div className={css.body}>
|
|
98
|
+
{labelNode}
|
|
99
|
+
{children}
|
|
100
|
+
<p className={css.hint}>{hint}</p>
|
|
101
|
+
</div>
|
|
102
|
+
{invalidNode}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -1,19 +1,6 @@
|
|
|
1
|
-
// 设置表单原语的 client
|
|
2
|
-
//
|
|
1
|
+
// 设置表单原语的 client 出口:**直接用上游那份**(同名同形的 `SettingsForm` / 两个字段控件 / 表单模型,样式
|
|
2
|
+
// 本来就是上游的 `.module.css`),这里只留本包自造的那一个字段行——上游的 `SettingsValueField` 摆不下
|
|
3
|
+
// 「标签 + 控件 + 说明 + 覆盖标记」这一整行。
|
|
3
4
|
|
|
4
|
-
export {
|
|
5
|
-
export type {
|
|
6
|
-
SettingsFieldSpec,
|
|
7
|
-
SettingsFieldState,
|
|
8
|
-
SettingsFieldWrite,
|
|
9
|
-
SettingsFormActions,
|
|
10
|
-
SettingsFormPathOp,
|
|
11
|
-
SettingsFormScope,
|
|
12
|
-
SettingsFormScopeSnapshot,
|
|
13
|
-
SettingsFormShell,
|
|
14
|
-
SettingsSecretSpec,
|
|
15
|
-
} from "./form-model.ts";
|
|
16
|
-
export { SettingsSecretField, SettingsValueField } from "./fields.tsx";
|
|
17
|
-
export type { SettingsFieldProps } from "./fields.tsx";
|
|
18
|
-
export { SettingsForm } from "./SettingsForm.tsx";
|
|
19
|
-
export type { SettingsFormLabels, SettingsFormProps } from "./SettingsForm.tsx";
|
|
5
|
+
export { SettingsFieldRow } from "./SettingsFieldRow.tsx";
|
|
6
|
+
export type { SettingsFieldRowProps } from "./SettingsFieldRow.tsx";
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 引用解析的 host 侧工具。
|
|
3
|
+
*
|
|
4
|
+
* 本包是**普通库**(UI 原语 + 引用解析),不是 cordis 插件包:没有 `./client` 那类"浏览器半"出口,
|
|
5
|
+
* 默认出口就是库本体(浏览器组件),这里只留 host 侧也用得着的那部分。
|
|
6
|
+
*/
|
|
1
7
|
export { findReferences, parseReferenceToken } from "./reference.ts";
|
|
2
8
|
export type { Reference, ReferenceSpan } from "./reference.ts";
|
|
3
|
-
|
|
4
|
-
export function apply(): void {}
|
|
@@ -13,12 +13,8 @@
|
|
|
13
13
|
// 因此 `code-review` 这种没有路径特征的 skill 也能稳定成 chip、而普通 inline code 不会。
|
|
14
14
|
|
|
15
15
|
import { memo, useMemo } from "react";
|
|
16
|
-
import { MarkdownText } from "./
|
|
17
|
-
import type {
|
|
18
|
-
MarkdownFileMentions,
|
|
19
|
-
MarkdownLabels,
|
|
20
|
-
MarkdownPathImages,
|
|
21
|
-
} from "./client/markdown-text.ts";
|
|
16
|
+
import { MarkdownText } from "./markdown-text.ts";
|
|
17
|
+
import type { MarkdownFileMentions, MarkdownLabels, MarkdownPathImages } from "./markdown-text.ts";
|
|
22
18
|
import {
|
|
23
19
|
findReferences,
|
|
24
20
|
formatReference,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
|
-
var __exportAll = (all, no_symbols) => {
|
|
5
|
-
let target = {};
|
|
6
|
-
for (var name in all) __defProp(target, name, {
|
|
7
|
-
get: all[name],
|
|
8
|
-
enumerable: true
|
|
9
|
-
});
|
|
10
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
11
|
-
return target;
|
|
12
|
-
};
|
|
13
|
-
//#endregion
|
|
14
|
-
export { __exportAll as n, __commonJSMin as t };
|
package/locale/en.json
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"meta": {
|
|
3
|
-
"title": "UI Primitives",
|
|
4
|
-
"description": "The shared base for the conversation UI and the settings pages: the css-in-js styling layer, the reference parser and renderer (one source shared with the host), the staged settings-form primitives forked from upstream, and the schema-generated row config pages (field-slot injection). Inlined by the client rows that use it, not an assembly row."
|
|
5
|
-
}
|
|
6
|
-
}
|