@dsh-plugin/dsh-ui-components 0.0.1 → 0.1.0-dev.43616582648

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.
Files changed (65) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +21 -21
  3. package/README.md +136 -136
  4. package/README.zh_CN.md +136 -136
  5. package/docs/tokens.md +67 -67
  6. package/lib/basic/form.js +49 -49
  7. package/lib/basic/styles.js +391 -391
  8. package/lib/composites/styles.js +427 -427
  9. package/lib/data/styles.js +257 -257
  10. package/lib/display/styles.js +310 -310
  11. package/lib/feedback/styles.js +228 -228
  12. package/lib/foundation/bridge.js +203 -203
  13. package/lib/navigation/styles.js +417 -417
  14. package/package.json +104 -104
  15. package/scripts/check-size.mjs +69 -69
  16. package/scripts/dump-npm-latest.mjs +59 -59
  17. package/scripts/gen-host-tokens.mjs +61 -61
  18. package/scripts/gen-icons.mjs +188 -178
  19. package/scripts/verify-no-literal-colors.mjs +63 -63
  20. package/scripts/verify-tokens.mjs +135 -135
  21. package/src/basic/button.tsx +76 -76
  22. package/src/basic/form.tsx +187 -187
  23. package/src/basic/icon-button.tsx +66 -66
  24. package/src/basic/index.ts +38 -38
  25. package/src/basic/input.tsx +140 -140
  26. package/src/basic/select.tsx +120 -120
  27. package/src/basic/styles.ts +412 -412
  28. package/src/basic/toggle.tsx +116 -116
  29. package/src/composites/data-view.tsx +189 -189
  30. package/src/composites/index.ts +11 -11
  31. package/src/composites/indicator.tsx +90 -90
  32. package/src/composites/menu-select.tsx +230 -230
  33. package/src/composites/panel.tsx +72 -72
  34. package/src/composites/settings.tsx +80 -80
  35. package/src/composites/styles.ts +450 -450
  36. package/src/data/collection.tsx +71 -71
  37. package/src/data/index.ts +39 -39
  38. package/src/data/info.tsx +89 -89
  39. package/src/data/picker.tsx +113 -113
  40. package/src/data/styles.ts +278 -278
  41. package/src/display/container.tsx +67 -67
  42. package/src/display/feedback.tsx +92 -92
  43. package/src/display/index.ts +44 -44
  44. package/src/display/label.tsx +165 -165
  45. package/src/display/overlay.tsx +103 -103
  46. package/src/display/styles.ts +332 -332
  47. package/src/feedback/global.tsx +110 -110
  48. package/src/feedback/index.ts +19 -19
  49. package/src/feedback/inline.tsx +50 -50
  50. package/src/feedback/panel.tsx +93 -93
  51. package/src/feedback/styles.ts +250 -250
  52. package/src/foundation/bridge.ts +318 -318
  53. package/src/foundation/icons.tsx +315 -315
  54. package/src/foundation/index.ts +33 -33
  55. package/src/foundation/palette.ts +153 -153
  56. package/src/foundation/provider.tsx +62 -62
  57. package/src/foundation/style.ts +63 -63
  58. package/src/foundation/tokens.ts +62 -62
  59. package/src/index.ts +18 -18
  60. package/src/navigation/hierarchy.tsx +82 -82
  61. package/src/navigation/index.ts +21 -21
  62. package/src/navigation/indicator.tsx +125 -125
  63. package/src/navigation/menu.tsx +94 -94
  64. package/src/navigation/segmented.tsx +136 -136
  65. package/src/navigation/styles.ts +438 -438
@@ -1,116 +1,116 @@
1
- /**
2
- * 开关类控件:复选框、单选框、开关。
3
- *
4
- * 三者都沿用 Arco 的受控与非受控语义,因此 `checked` / `defaultChecked` /
5
- * `onChange` 的行为与原生表单一致。勾选状态的配色由桥接样式表改指 DSH 的
6
- * 品牌色令牌。
7
- *
8
- * @module @dsh-plugin/dsh-ui-components/basic/toggle
9
- */
10
- import * as React from 'react'
11
- import { Arco } from '@dsh-plugin/dsh-loader/client'
12
- import { injectBasicStyles } from './styles.js'
13
-
14
- /** {@link Checkbox} 的 props。 */
15
- export type CheckboxProps = Omit<React.ComponentPropsWithoutRef<typeof Arco.Checkbox>, 'children'> & {
16
- /** 勾选框右侧的文字。 */
17
- label?: React.ReactNode
18
- }
19
-
20
- /**
21
- * 一个复选框。
22
- *
23
- * @param props - 见 {@link CheckboxProps}。
24
- * @returns 复选框元素。
25
- */
26
- export function Checkbox({ label, ...rest }: CheckboxProps): React.ReactElement {
27
- injectBasicStyles()
28
- return <Arco.Checkbox {...rest}>{label}</Arco.Checkbox>
29
- }
30
-
31
- /** {@link CheckboxGroup} 的 props。 */
32
- export type CheckboxGroupProps = React.ComponentPropsWithoutRef<typeof Arco.Checkbox.Group>
33
-
34
- /**
35
- * 一组复选框。
36
- *
37
- * @param props - 见 {@link CheckboxGroupProps}。
38
- * @returns 复选框组元素。
39
- */
40
- export function CheckboxGroup(props: CheckboxGroupProps): React.ReactElement {
41
- injectBasicStyles()
42
- return <Arco.Checkbox.Group {...props} />
43
- }
44
-
45
- /** {@link Radio} 的 props。 */
46
- export type RadioProps = Omit<React.ComponentPropsWithoutRef<typeof Arco.Radio>, 'children'> & {
47
- /** 单选框右侧的文字。 */
48
- label?: React.ReactNode
49
- }
50
-
51
- /**
52
- * 一个单选框。
53
- *
54
- * @param props - 见 {@link RadioProps}。
55
- * @returns 单选框元素。
56
- */
57
- export function Radio({ label, ...rest }: RadioProps): React.ReactElement {
58
- injectBasicStyles()
59
- return <Arco.Radio {...rest}>{label}</Arco.Radio>
60
- }
61
-
62
- /** {@link RadioGroup} 的 props。 */
63
- export type RadioGroupProps = React.ComponentPropsWithoutRef<typeof Arco.Radio.Group>
64
-
65
- /**
66
- * 一组单选框,`onChange` 回调选中的 value。
67
- *
68
- * @param props - 见 {@link RadioGroupProps}。
69
- * @returns 单选框组元素。
70
- */
71
- export function RadioGroup(props: RadioGroupProps): React.ReactElement {
72
- injectBasicStyles()
73
- return <Arco.Radio.Group {...props} />
74
- }
75
-
76
- /** {@link Switch} 的 props。 */
77
- export type SwitchProps = React.ComponentPropsWithoutRef<typeof Arco.Switch>
78
-
79
- /**
80
- * 一个开关,用于即时生效的设置项。
81
- *
82
- * @param props - 见 {@link SwitchProps}。
83
- * @returns 开关元素。
84
- */
85
- export function Switch(props: SwitchProps): React.ReactElement {
86
- injectBasicStyles()
87
- return <Arco.Switch {...props} />
88
- }
89
-
90
- /** {@link Slider} 的 props。 */
91
- export type SliderProps = React.ComponentPropsWithoutRef<typeof Arco.Slider>
92
-
93
- /**
94
- * 一个滑块。
95
- *
96
- * @param props - 见 {@link SliderProps}。
97
- * @returns 滑块元素。
98
- */
99
- export function Slider(props: SliderProps): React.ReactElement {
100
- injectBasicStyles()
101
- return <Arco.Slider {...props} />
102
- }
103
-
104
- /** {@link Rate} 的 props。 */
105
- export type RateProps = React.ComponentPropsWithoutRef<typeof Arco.Rate>
106
-
107
- /**
108
- * 一个评分控件。
109
- *
110
- * @param props - 见 {@link RateProps}。
111
- * @returns 评分元素。
112
- */
113
- export function Rate(props: RateProps): React.ReactElement {
114
- injectBasicStyles()
115
- return <Arco.Rate {...props} />
116
- }
1
+ /**
2
+ * 开关类控件:复选框、单选框、开关。
3
+ *
4
+ * 三者都沿用 Arco 的受控与非受控语义,因此 `checked` / `defaultChecked` /
5
+ * `onChange` 的行为与原生表单一致。勾选状态的配色由桥接样式表改指 DSH 的
6
+ * 品牌色令牌。
7
+ *
8
+ * @module @dsh-plugin/dsh-ui-components/basic/toggle
9
+ */
10
+ import * as React from 'react'
11
+ import { Arco } from '@dsh-plugin/dsh-loader/client'
12
+ import { injectBasicStyles } from './styles.js'
13
+
14
+ /** {@link Checkbox} 的 props。 */
15
+ export type CheckboxProps = Omit<React.ComponentPropsWithoutRef<typeof Arco.Checkbox>, 'children'> & {
16
+ /** 勾选框右侧的文字。 */
17
+ label?: React.ReactNode
18
+ }
19
+
20
+ /**
21
+ * 一个复选框。
22
+ *
23
+ * @param props - 见 {@link CheckboxProps}。
24
+ * @returns 复选框元素。
25
+ */
26
+ export function Checkbox({ label, ...rest }: CheckboxProps): React.ReactElement {
27
+ injectBasicStyles()
28
+ return <Arco.Checkbox {...rest}>{label}</Arco.Checkbox>
29
+ }
30
+
31
+ /** {@link CheckboxGroup} 的 props。 */
32
+ export type CheckboxGroupProps = React.ComponentPropsWithoutRef<typeof Arco.Checkbox.Group>
33
+
34
+ /**
35
+ * 一组复选框。
36
+ *
37
+ * @param props - 见 {@link CheckboxGroupProps}。
38
+ * @returns 复选框组元素。
39
+ */
40
+ export function CheckboxGroup(props: CheckboxGroupProps): React.ReactElement {
41
+ injectBasicStyles()
42
+ return <Arco.Checkbox.Group {...props} />
43
+ }
44
+
45
+ /** {@link Radio} 的 props。 */
46
+ export type RadioProps = Omit<React.ComponentPropsWithoutRef<typeof Arco.Radio>, 'children'> & {
47
+ /** 单选框右侧的文字。 */
48
+ label?: React.ReactNode
49
+ }
50
+
51
+ /**
52
+ * 一个单选框。
53
+ *
54
+ * @param props - 见 {@link RadioProps}。
55
+ * @returns 单选框元素。
56
+ */
57
+ export function Radio({ label, ...rest }: RadioProps): React.ReactElement {
58
+ injectBasicStyles()
59
+ return <Arco.Radio {...rest}>{label}</Arco.Radio>
60
+ }
61
+
62
+ /** {@link RadioGroup} 的 props。 */
63
+ export type RadioGroupProps = React.ComponentPropsWithoutRef<typeof Arco.Radio.Group>
64
+
65
+ /**
66
+ * 一组单选框,`onChange` 回调选中的 value。
67
+ *
68
+ * @param props - 见 {@link RadioGroupProps}。
69
+ * @returns 单选框组元素。
70
+ */
71
+ export function RadioGroup(props: RadioGroupProps): React.ReactElement {
72
+ injectBasicStyles()
73
+ return <Arco.Radio.Group {...props} />
74
+ }
75
+
76
+ /** {@link Switch} 的 props。 */
77
+ export type SwitchProps = React.ComponentPropsWithoutRef<typeof Arco.Switch>
78
+
79
+ /**
80
+ * 一个开关,用于即时生效的设置项。
81
+ *
82
+ * @param props - 见 {@link SwitchProps}。
83
+ * @returns 开关元素。
84
+ */
85
+ export function Switch(props: SwitchProps): React.ReactElement {
86
+ injectBasicStyles()
87
+ return <Arco.Switch {...props} />
88
+ }
89
+
90
+ /** {@link Slider} 的 props。 */
91
+ export type SliderProps = React.ComponentPropsWithoutRef<typeof Arco.Slider>
92
+
93
+ /**
94
+ * 一个滑块。
95
+ *
96
+ * @param props - 见 {@link SliderProps}。
97
+ * @returns 滑块元素。
98
+ */
99
+ export function Slider(props: SliderProps): React.ReactElement {
100
+ injectBasicStyles()
101
+ return <Arco.Slider {...props} />
102
+ }
103
+
104
+ /** {@link Rate} 的 props。 */
105
+ export type RateProps = React.ComponentPropsWithoutRef<typeof Arco.Rate>
106
+
107
+ /**
108
+ * 一个评分控件。
109
+ *
110
+ * @param props - 见 {@link RateProps}。
111
+ * @returns 评分元素。
112
+ */
113
+ export function Rate(props: RateProps): React.ReactElement {
114
+ injectBasicStyles()
115
+ return <Arco.Rate {...props} />
116
+ }
@@ -1,189 +1,189 @@
1
- /**
2
- * JSON 树与代码块外壳。
3
- *
4
- * `JsonTree` 用于只读查看工具入参与结果,配色走宿主自己的 JSON 配色令牌;
5
- * `CodeBlockShell` 提供语言标签、右侧操作区与等宽内容区,供插件包裹自己的
6
- * 高亮结果。
7
- *
8
- * @module @dsh-plugin/dsh-ui-components/composites/data-view
9
- */
10
- import * as React from 'react'
11
- import { cx } from '../foundation/style.js'
12
- import { Icon } from '../foundation/icons.js'
13
- import { injectCompositeStyles } from './styles.js'
14
-
15
- /** {@link JsonTree} 的 props。 */
16
- export interface JsonTreeProps {
17
- /** 要展示的值,可以是任意可 JSON 化的数据。 */
18
- value: unknown
19
- /** 根节点的初始展开状态,默认展开。 */
20
- defaultExpanded?: boolean
21
- /** 追加类名。 */
22
- className?: string
23
- }
24
-
25
- /** 一个值的渲染种类。 */
26
- type JsonKind = 'object' | 'array' | 'string' | 'number' | 'boolean' | 'null'
27
-
28
- /**
29
- * 判断一个值的渲染种类。
30
- *
31
- * @param value - 任意值。
32
- * @returns 渲染种类。
33
- */
34
- function kindOf(value: unknown): JsonKind {
35
- if (value === null) return 'null'
36
- if (Array.isArray(value)) return 'array'
37
- const type = typeof value
38
- if (type === 'object') return 'object'
39
- if (type === 'number') return 'number'
40
- if (type === 'boolean') return 'boolean'
41
- return 'string'
42
- }
43
-
44
- /** 一个节点。 */
45
- interface JsonNodeProps {
46
- /** 键名;根节点省略。 */
47
- name?: string
48
- /** 值。 */
49
- value: unknown
50
- /** 是否是最后一个同级节点,决定尾逗号。 */
51
- last: boolean
52
- /** 初始是否展开。 */
53
- defaultExpanded: boolean
54
- /** 缩进层级,仅用于渲染。 */
55
- depth: number
56
- }
57
-
58
- /**
59
- * 渲染一个 JSON 节点。
60
- *
61
- * @param props - 见 {@link JsonNodeProps}。
62
- * @returns 节点元素。
63
- */
64
- function JsonNode({ name, value, last, defaultExpanded, depth }: JsonNodeProps): React.ReactElement {
65
- const kind = kindOf(value)
66
- const expandable = kind === 'object' || kind === 'array'
67
- const [expanded, setExpanded] = React.useState(defaultExpanded || depth < 1)
68
- const suffix = last ? '' : ','
69
- const keyPart = name === undefined ? null : <span className="dsh-json-tree__key">{name}: </span>
70
-
71
- if (!expandable) {
72
- const text = kind === 'string' ? JSON.stringify(value) : String(value)
73
- const className =
74
- kind === 'string'
75
- ? 'dsh-json-tree__string'
76
- : kind === 'number'
77
- ? 'dsh-json-tree__number'
78
- : 'dsh-json-tree__keyword'
79
- return (
80
- <div className="dsh-json-tree__row" style={{ paddingLeft: depth * 12 }}>
81
- <span style={{ width: 14, flex: 'none' }} />
82
- {keyPart}
83
- <span className={className}>{text}</span>
84
- <span className="dsh-json-tree__punct">{suffix}</span>
85
- </div>
86
- )
87
- }
88
-
89
- const entries = kind === 'array'
90
- ? (value as unknown[]).map((item, index) => [String(index), item] as const)
91
- : Object.entries(value as Record<string, unknown>)
92
- const open = kind === 'array' ? '[' : '{'
93
- const close = kind === 'array' ? ']' : '}'
94
-
95
- return (
96
- <div>
97
- <div className="dsh-json-tree__row" style={{ paddingLeft: depth * 12 }}>
98
- <button
99
- type="button"
100
- className="dsh-json-tree__toggle"
101
- aria-expanded={expanded}
102
- aria-label={expanded ? '收起' : '展开'}
103
- onClick={() => setExpanded(previous => !previous)}
104
- >
105
- <Icon name={expanded ? 'ChevronDown' : 'ChevronRight'} size={10} />
106
- </button>
107
- {keyPart}
108
- <span className="dsh-json-tree__punct">{open}</span>
109
- {expanded ? null : (
110
- <>
111
- <span className="dsh-json-tree__summary">{` ${entries.length} 项 `}</span>
112
- <span className="dsh-json-tree__punct">{close}{suffix}</span>
113
- </>
114
- )}
115
- </div>
116
- {expanded ? (
117
- <>
118
- <div className="dsh-json-tree__children">
119
- {entries.map(([key, item], index) => (
120
- <JsonNode
121
- key={key}
122
- name={kind === 'array' ? undefined : key}
123
- value={item}
124
- last={index === entries.length - 1}
125
- defaultExpanded={defaultExpanded}
126
- depth={depth + 1}
127
- />
128
- ))}
129
- </div>
130
- {/* 闭合括号属于当前层,必须与开括号同级缩进;放进子容器会多缩一层。 */}
131
- <div className="dsh-json-tree__row" style={{ paddingLeft: depth * 12 }}>
132
- <span style={{ width: 14, flex: 'none' }} />
133
- <span className="dsh-json-tree__punct">{close}{suffix}</span>
134
- </div>
135
- </>
136
- ) : null}
137
- </div>
138
- )
139
- }
140
-
141
- /**
142
- * 只读 JSON 树。
143
- *
144
- * @param props - 见 {@link JsonTreeProps}。
145
- * @returns JSON 树元素。
146
- */
147
- export function JsonTree({ value, defaultExpanded = false, className }: JsonTreeProps): React.ReactElement {
148
- injectCompositeStyles()
149
- return (
150
- <div className={cx('dsh-json-tree', className)}>
151
- <JsonNode value={value} last defaultExpanded={defaultExpanded} depth={0} />
152
- </div>
153
- )
154
- }
155
-
156
- /** {@link CodeBlockShell} 的 props。 */
157
- export interface CodeBlockShellProps {
158
- /** 语言标签,显示在横幅左侧。 */
159
- language?: string
160
- /** 横幅右侧的操作。 */
161
- actions?: React.ReactNode
162
- /** 代码内容,通常是 `<pre>` 或高亮后的节点。 */
163
- children?: React.ReactNode
164
- /** 追加类名。 */
165
- className?: string
166
- }
167
-
168
- /**
169
- * 代码块外壳:横幅加等宽内容区。
170
- *
171
- * @param props - 见 {@link CodeBlockShellProps}。
172
- * @returns 代码块元素。
173
- */
174
- export function CodeBlockShell({ language, actions, children, className }: CodeBlockShellProps): React.ReactElement {
175
- injectCompositeStyles()
176
- return (
177
- <div className={cx('dsh-code-shell', className)}>
178
- {language === undefined && actions === undefined
179
- ? null
180
- : (
181
- <div className="dsh-code-shell__banner">
182
- <span className="dsh-code-shell__lang">{language}</span>
183
- {actions === undefined ? null : <span className="dsh-code-shell__actions">{actions}</span>}
184
- </div>
185
- )}
186
- <div className="dsh-code-shell__body">{children}</div>
187
- </div>
188
- )
189
- }
1
+ /**
2
+ * JSON 树与代码块外壳。
3
+ *
4
+ * `JsonTree` 用于只读查看工具入参与结果,配色走宿主自己的 JSON 配色令牌;
5
+ * `CodeBlockShell` 提供语言标签、右侧操作区与等宽内容区,供插件包裹自己的
6
+ * 高亮结果。
7
+ *
8
+ * @module @dsh-plugin/dsh-ui-components/composites/data-view
9
+ */
10
+ import * as React from 'react'
11
+ import { cx } from '../foundation/style.js'
12
+ import { Icon } from '../foundation/icons.js'
13
+ import { injectCompositeStyles } from './styles.js'
14
+
15
+ /** {@link JsonTree} 的 props。 */
16
+ export interface JsonTreeProps {
17
+ /** 要展示的值,可以是任意可 JSON 化的数据。 */
18
+ value: unknown
19
+ /** 根节点的初始展开状态,默认展开。 */
20
+ defaultExpanded?: boolean
21
+ /** 追加类名。 */
22
+ className?: string
23
+ }
24
+
25
+ /** 一个值的渲染种类。 */
26
+ type JsonKind = 'object' | 'array' | 'string' | 'number' | 'boolean' | 'null'
27
+
28
+ /**
29
+ * 判断一个值的渲染种类。
30
+ *
31
+ * @param value - 任意值。
32
+ * @returns 渲染种类。
33
+ */
34
+ function kindOf(value: unknown): JsonKind {
35
+ if (value === null) return 'null'
36
+ if (Array.isArray(value)) return 'array'
37
+ const type = typeof value
38
+ if (type === 'object') return 'object'
39
+ if (type === 'number') return 'number'
40
+ if (type === 'boolean') return 'boolean'
41
+ return 'string'
42
+ }
43
+
44
+ /** 一个节点。 */
45
+ interface JsonNodeProps {
46
+ /** 键名;根节点省略。 */
47
+ name?: string
48
+ /** 值。 */
49
+ value: unknown
50
+ /** 是否是最后一个同级节点,决定尾逗号。 */
51
+ last: boolean
52
+ /** 初始是否展开。 */
53
+ defaultExpanded: boolean
54
+ /** 缩进层级,仅用于渲染。 */
55
+ depth: number
56
+ }
57
+
58
+ /**
59
+ * 渲染一个 JSON 节点。
60
+ *
61
+ * @param props - 见 {@link JsonNodeProps}。
62
+ * @returns 节点元素。
63
+ */
64
+ function JsonNode({ name, value, last, defaultExpanded, depth }: JsonNodeProps): React.ReactElement {
65
+ const kind = kindOf(value)
66
+ const expandable = kind === 'object' || kind === 'array'
67
+ const [expanded, setExpanded] = React.useState(defaultExpanded || depth < 1)
68
+ const suffix = last ? '' : ','
69
+ const keyPart = name === undefined ? null : <span className="dsh-json-tree__key">{name}: </span>
70
+
71
+ if (!expandable) {
72
+ const text = kind === 'string' ? JSON.stringify(value) : String(value)
73
+ const className =
74
+ kind === 'string'
75
+ ? 'dsh-json-tree__string'
76
+ : kind === 'number'
77
+ ? 'dsh-json-tree__number'
78
+ : 'dsh-json-tree__keyword'
79
+ return (
80
+ <div className="dsh-json-tree__row" style={{ paddingLeft: depth * 12 }}>
81
+ <span style={{ width: 14, flex: 'none' }} />
82
+ {keyPart}
83
+ <span className={className}>{text}</span>
84
+ <span className="dsh-json-tree__punct">{suffix}</span>
85
+ </div>
86
+ )
87
+ }
88
+
89
+ const entries = kind === 'array'
90
+ ? (value as unknown[]).map((item, index) => [String(index), item] as const)
91
+ : Object.entries(value as Record<string, unknown>)
92
+ const open = kind === 'array' ? '[' : '{'
93
+ const close = kind === 'array' ? ']' : '}'
94
+
95
+ return (
96
+ <div>
97
+ <div className="dsh-json-tree__row" style={{ paddingLeft: depth * 12 }}>
98
+ <button
99
+ type="button"
100
+ className="dsh-json-tree__toggle"
101
+ aria-expanded={expanded}
102
+ aria-label={expanded ? '收起' : '展开'}
103
+ onClick={() => setExpanded(previous => !previous)}
104
+ >
105
+ <Icon name={expanded ? 'ChevronDown' : 'ChevronRight'} size={10} />
106
+ </button>
107
+ {keyPart}
108
+ <span className="dsh-json-tree__punct">{open}</span>
109
+ {expanded ? null : (
110
+ <>
111
+ <span className="dsh-json-tree__summary">{` ${entries.length} 项 `}</span>
112
+ <span className="dsh-json-tree__punct">{close}{suffix}</span>
113
+ </>
114
+ )}
115
+ </div>
116
+ {expanded ? (
117
+ <>
118
+ <div className="dsh-json-tree__children">
119
+ {entries.map(([key, item], index) => (
120
+ <JsonNode
121
+ key={key}
122
+ name={kind === 'array' ? undefined : key}
123
+ value={item}
124
+ last={index === entries.length - 1}
125
+ defaultExpanded={defaultExpanded}
126
+ depth={depth + 1}
127
+ />
128
+ ))}
129
+ </div>
130
+ {/* 闭合括号属于当前层,必须与开括号同级缩进;放进子容器会多缩一层。 */}
131
+ <div className="dsh-json-tree__row" style={{ paddingLeft: depth * 12 }}>
132
+ <span style={{ width: 14, flex: 'none' }} />
133
+ <span className="dsh-json-tree__punct">{close}{suffix}</span>
134
+ </div>
135
+ </>
136
+ ) : null}
137
+ </div>
138
+ )
139
+ }
140
+
141
+ /**
142
+ * 只读 JSON 树。
143
+ *
144
+ * @param props - 见 {@link JsonTreeProps}。
145
+ * @returns JSON 树元素。
146
+ */
147
+ export function JsonTree({ value, defaultExpanded = false, className }: JsonTreeProps): React.ReactElement {
148
+ injectCompositeStyles()
149
+ return (
150
+ <div className={cx('dsh-json-tree', className)}>
151
+ <JsonNode value={value} last defaultExpanded={defaultExpanded} depth={0} />
152
+ </div>
153
+ )
154
+ }
155
+
156
+ /** {@link CodeBlockShell} 的 props。 */
157
+ export interface CodeBlockShellProps {
158
+ /** 语言标签,显示在横幅左侧。 */
159
+ language?: string
160
+ /** 横幅右侧的操作。 */
161
+ actions?: React.ReactNode
162
+ /** 代码内容,通常是 `<pre>` 或高亮后的节点。 */
163
+ children?: React.ReactNode
164
+ /** 追加类名。 */
165
+ className?: string
166
+ }
167
+
168
+ /**
169
+ * 代码块外壳:横幅加等宽内容区。
170
+ *
171
+ * @param props - 见 {@link CodeBlockShellProps}。
172
+ * @returns 代码块元素。
173
+ */
174
+ export function CodeBlockShell({ language, actions, children, className }: CodeBlockShellProps): React.ReactElement {
175
+ injectCompositeStyles()
176
+ return (
177
+ <div className={cx('dsh-code-shell', className)}>
178
+ {language === undefined && actions === undefined
179
+ ? null
180
+ : (
181
+ <div className="dsh-code-shell__banner">
182
+ <span className="dsh-code-shell__lang">{language}</span>
183
+ {actions === undefined ? null : <span className="dsh-code-shell__actions">{actions}</span>}
184
+ </div>
185
+ )}
186
+ <div className="dsh-code-shell__body">{children}</div>
187
+ </div>
188
+ )
189
+ }
@@ -1,11 +1,11 @@
1
- /**
2
- * DSH 专属组合件出口。
3
- *
4
- * @module @dsh-plugin/dsh-ui-components/composites
5
- */
6
- export { SettingsCard, SettingsRow, type SettingsCardProps, type SettingsRowProps } from './settings.js'
7
- export { PanelShell, type PanelShellProps } from './panel.js'
8
- export { MenuSelect, type MenuSelectOption, type MenuSelectProps } from './menu-select.js'
9
- export { CodeBlockShell, JsonTree, type CodeBlockShellProps, type JsonTreeProps } from './data-view.js'
10
- export { FileTypeBadge, StatusLine, type FileTypeBadgeProps, type StatusLineProps } from './indicator.js'
11
- export { COMPOSITES_CSS, injectCompositeStyles } from './styles.js'
1
+ /**
2
+ * DSH 专属组合件出口。
3
+ *
4
+ * @module @dsh-plugin/dsh-ui-components/composites
5
+ */
6
+ export { SettingsCard, SettingsRow, type SettingsCardProps, type SettingsRowProps } from './settings.js'
7
+ export { PanelShell, type PanelShellProps } from './panel.js'
8
+ export { MenuSelect, type MenuSelectOption, type MenuSelectProps } from './menu-select.js'
9
+ export { CodeBlockShell, JsonTree, type CodeBlockShellProps, type JsonTreeProps } from './data-view.js'
10
+ export { FileTypeBadge, StatusLine, type FileTypeBadgeProps, type StatusLineProps } from './indicator.js'
11
+ export { COMPOSITES_CSS, injectCompositeStyles } from './styles.js'