dsh-manage-session 0.2.3 → 0.4.8

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/package.json CHANGED
@@ -1,121 +1,125 @@
1
- {
2
- "name": "dsh-manage-session",
3
- "version": "0.2.3",
4
- "publishConfig": {
5
- "registry": "https://registry.npmjs.org",
6
- "access": "public",
7
- "tag": "dsh-0.1.2"
8
- },
9
- "description": "DSH Web 插件:会话管家 —— 会话历史文件(归档浏览与清理)与会话健康检查(体检 → 处方 → 出院),不碰会话日志、只做可逆处置",
10
- "keywords": [
11
- "deepseek-harness",
12
- "dsh",
13
- "dsh-plugin",
14
- "session",
15
- "archive",
16
- "health",
17
- "doctor"
18
- ],
19
- "repository": {
20
- "type": "git",
21
- "url": "git+https://github.com/drscrewdriver/dsh-manage-session.git"
22
- },
23
- "type": "module",
24
- "main": "lib/index.js",
25
- "types": "lib/index.d.ts",
26
- "exports": {
27
- ".": {
28
- "types": "./lib/index.d.ts",
29
- "default": "./lib/index.js"
30
- },
31
- "./client": {
32
- "default": "./lib/client.js"
33
- },
34
- "./cordis.patch.yml": "./cordis.patch.yml",
35
- "./package.json": "./package.json"
36
- },
37
- "dsh": {
38
- "bundle": {
39
- "patch": "./cordis.patch.yml"
40
- },
41
- "client": {
42
- "platform": "web",
43
- "inject": [
44
- "@deepseek-ai/dsh-client-locale",
45
- "@deepseek-ai/dsh-client-ui-settings",
46
- "@deepseek-ai/dsh-client-ui-settings-general"
47
- ]
48
- }
49
- },
50
- "scripts": {
51
- "build": "node -e \"require('fs').rmSync('lib',{recursive:true,force:true})\" && tsc -b && tsdown",
52
- "prepublishOnly": "npm run build",
53
- "typecheck": "tsc -b --pretty false",
54
- "test": "vitest run"
55
- },
56
- "files": [
57
- "lib/index.js",
58
- "lib/index.d.ts",
59
- "lib/client.js",
60
- "src",
61
- "cordis.patch.yml",
62
- "dsh.plugin.json",
63
- "screenshots.json",
64
- "README.md",
65
- "README.en.md",
66
- "README.ja.md",
67
- "README.ko.md",
68
- "INSTALL.md",
69
- "INSTALL.zh.md",
70
- "INSTALL.ja.md",
71
- "INSTALL.ko.md",
72
- "CHANGELOG.md",
73
- "CHANGELOG.ja.md",
74
- "CHANGELOG.ko.md",
75
- "LICENSE"
76
- ],
77
- "engines": {
78
- "node": ">=20",
79
- "dsh": ">=0.1.2-rc.1 <0.1.3-0"
80
- },
81
- "license": "MIT",
82
- "peerDependencies": {
83
- "@deepseek-ai/cordis": "^4.0.1",
84
- "@deepseek-ai/dsh-client-locale": ">=0.1.2-rc.1 <0.1.3-0",
85
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-rc.1 <0.1.3-0",
86
- "@deepseek-ai/dsh-client-ui-settings-general": ">=0.1.2-rc.1 <0.1.3-0",
87
- "@deepseek-ai/dsh-client-ui-slots": ">=0.0.1-rc.1 <0.1.0 || >=0.1.0-rc.1 <0.1.3-0",
88
- "@deepseek-ai/schemastery": "^3.18.1",
89
- "react": "^18.2.0"
90
- },
91
- "peerDependenciesMeta": {
92
- "@deepseek-ai/dsh-client-locale": {
93
- "optional": true
94
- },
95
- "@deepseek-ai/dsh-client-ui-settings": {
96
- "optional": true
97
- },
98
- "@deepseek-ai/dsh-client-ui-settings-general": {
99
- "optional": true
100
- },
101
- "@deepseek-ai/dsh-client-ui-slots": {
102
- "optional": true
103
- }
104
- },
105
- "devDependencies": {
106
- "@deepseek-ai/cordis": "^4.0.1",
107
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
108
- "@deepseek-ai/schemastery": "^3.18.1",
109
- "@types/node": "^24.0.0",
110
- "@types/react": "~18.3.1",
111
- "@types/react-dom": "^18.3.7",
112
- "cordis": "^4.0.0-rc.7",
113
- "react": "^18.2.0",
114
- "react-dom": "^18.2.0",
115
- "tsdown": "^0.22.2",
116
- "tsx": "^4.23.12",
117
- "typescript": "^5.6.0",
118
- "vite-tsconfig-paths": "^6.1.1",
119
- "vitest": "^4.1.1"
120
- }
121
- }
1
+ {
2
+ "name": "dsh-manage-session",
3
+ "version": "0.4.8",
4
+ "publishConfig": {
5
+ "tag": "dsh-0.1.7"
6
+ },
7
+ "description": "DSH Web 插件(DSH 0.1.5 专线):会话管家 —— 会话历史文件(归档浏览与清理)与会话健康检查(体检 → 处方 → 出院),不碰会话日志、只做可逆处置",
8
+ "keywords": [
9
+ "deepseek-harness",
10
+ "dsh",
11
+ "dsh-plugin",
12
+ "session",
13
+ "archive",
14
+ "health",
15
+ "doctor"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/drscrewdriver/dsh-manage-session.git"
20
+ },
21
+ "type": "module",
22
+ "main": "lib/index.js",
23
+ "types": "lib/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./lib/index.d.ts",
27
+ "default": "./lib/index.js"
28
+ },
29
+ "./client": {
30
+ "default": "./lib/client.js"
31
+ },
32
+ "./cordis.patch.yml": "./cordis.patch.yml",
33
+ "./package.json": "./package.json"
34
+ },
35
+ "dsh": {
36
+ "bundle": {
37
+ "patch": "./cordis.patch.yml"
38
+ },
39
+ "client": {
40
+ "platform": "web",
41
+ "inject": [
42
+ "@deepseek-ai/dsh-client-locale",
43
+ "@deepseek-ai/dsh-client-ui-settings",
44
+ "@deepseek-ai/dsh-client-ui-settings-general"
45
+ ]
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "node -e \"require('fs').rmSync('lib',{recursive:true,force:true})\" && tsc -b && tsdown",
50
+ "prepublishOnly": "npm run build",
51
+ "typecheck": "tsc -b --pretty false",
52
+ "test": "vitest run",
53
+ "release:015": "npm publish --tag dsh-0.1.5"
54
+ },
55
+ "files": [
56
+ "lib/index.js",
57
+ "lib/index.d.ts",
58
+ "lib/client.js",
59
+ "src",
60
+ "cordis.patch.yml",
61
+ "dsh.plugin.json",
62
+ "screenshots.json",
63
+ "README.md",
64
+ "README.en.md",
65
+ "README.ja.md",
66
+ "README.ko.md",
67
+ "INSTALL.md",
68
+ "INSTALL.zh.md",
69
+ "INSTALL.ja.md",
70
+ "INSTALL.ko.md",
71
+ "CHANGELOG.md",
72
+ "CHANGELOG.ja.md",
73
+ "CHANGELOG.ko.md",
74
+ "LICENSE"
75
+ ],
76
+ "engines": {
77
+ "node": ">=20",
78
+ "dsh": ">=0.1.7-rc.1 <0.1.8-0"
79
+ },
80
+ "license": "MIT",
81
+ "peerDependencies": {
82
+ "@deepseek-ai/cordis": "^4.0.1",
83
+ "@deepseek-ai/dsh-client-locale": ">=0.1.7-rc.1 <0.1.8-0",
84
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1 <0.1.8-0",
85
+ "@deepseek-ai/dsh-client-ui-settings-general": ">=0.1.7-rc.1 <0.1.8-0",
86
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.1 <0.1.8-0",
87
+ "@deepseek-ai/schemastery": "^3.18.4",
88
+ "react": "^18.2.0",
89
+ "@deepseek-ai/dsh-session": ">=0.1.7-rc.1 <0.1.8-0"
90
+ },
91
+ "peerDependenciesMeta": {
92
+ "@deepseek-ai/dsh-client-locale": {
93
+ "optional": true
94
+ },
95
+ "@deepseek-ai/dsh-client-ui-settings": {
96
+ "optional": true
97
+ },
98
+ "@deepseek-ai/dsh-client-ui-settings-general": {
99
+ "optional": true
100
+ },
101
+ "@deepseek-ai/dsh-client-ui-slots": {
102
+ "optional": true
103
+ },
104
+ "@deepseek-ai/dsh-session": {
105
+ "optional": true
106
+ }
107
+ },
108
+ "devDependencies": {
109
+ "@deepseek-ai/cordis": "^4.0.1",
110
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.1",
111
+ "@deepseek-ai/schemastery": "^3.18.4",
112
+ "@types/node": "^24.0.0",
113
+ "@types/react": "~18.3.1",
114
+ "@types/react-dom": "^18.3.7",
115
+ "cordis": "^4.0.0-rc.7",
116
+ "react": "^18.2.0",
117
+ "react-dom": "^18.2.0",
118
+ "tsdown": "^0.22.2",
119
+ "tsx": "^4.23.12",
120
+ "typescript": "^5.6.0",
121
+ "vite-tsconfig-paths": "^6.1.1",
122
+ "vitest": "^4.1.1",
123
+ "@deepseek-ai/dsh-session": "^0.1.7-rc.1"
124
+ }
125
+ }
package/screenshots.json CHANGED
@@ -1,3 +1,7 @@
1
1
  {
2
- "screenshots": []
2
+ "screenshots": [
3
+ "assets/left-sidebar.png",
4
+ "assets/archive.png",
5
+ "assets/doctor.png"
6
+ ]
3
7
  }
@@ -1,153 +1,150 @@
1
- /**
2
- * 设置卡(插件配置行):一个可折叠抽屉 —— 会话历史文件 / 健康检查。
3
- *
4
- * **chrome 必须自己渲染**:DSH 的「插件」设置分区(`dsh-client-ui-settings-plugins`)
5
- * 只做一件事——按 settings 命名空间分发 `settings.plugin.item`:
6
- *
7
- * renderSlot('settings.plugin.item', {}, { entryKey: ns })
8
- *
9
- * 它**不提供任何外壳**。所以卡片的标题、说明、展开/收起全归插件自己所有
10
- * (同分区里 search-index 等卡片都是这个形态)。早期版本只渲染了裸行,
11
- * 结果既与分区内其它插件的抽屉形态不一致,又让 `card.title` / `card.desc`
12
- * 变成定义了却没人渲染的死文案。
13
- *
14
- * 读写走 settingsScope 的显式 `set`(用户在控件上的直接操作,非隐式提交)。
15
- */
16
- import { createElement, useState, useSyncExternalStore, type JSX } from 'react'
17
- import { DEFAULT_CONFIG, type StewardConfig } from '../config.ts'
18
- import { translate, type LocaleKey } from './locales.ts'
19
-
20
- /** 卡片字典面。 */
21
- export type CardTranslate = (key: LocaleKey, params?: Record<string, unknown>) => string
22
-
23
- /** 设置 scope 面(结构化镜像,与 toggle 的 SwitchCardScope 同形状)。 */
24
- export interface StewardCardScope {
25
- getSnapshot(): {
26
- status: 'ready' | 'loading' | 'unavailable'
27
- value: StewardConfig | undefined
28
- revision?: number
29
- writable: boolean
30
- }
31
- subscribe(listener: () => void): () => void
32
- set(field: string, value: unknown): Promise<void>
33
- }
34
-
35
- /** 卡片入参。 */
36
- export interface StewardCardProps {
37
- t?: CardTranslate
38
- scope: StewardCardScope
39
- }
40
-
41
- /** 一行设置项。 */
42
- function Row(props: { title: string; desc?: string; control: JSX.Element }): JSX.Element {
43
- return createElement('div', { className: 'dss_setRow' }, [
44
- createElement('div', { key: 'text', className: 'dss_setText' }, [
45
- createElement('span', { key: 't', className: 'dss_setTitle' }, props.title),
46
- props.desc !== undefined && createElement('span', { key: 'd', className: 'dss_setDesc' }, props.desc),
47
- ]),
48
- createElement('div', { key: 'ctl' }, props.control),
49
- ])
50
- }
51
-
52
- /** 一个布尔开关(原生 checkbox 语义,样式由本插件 CSS 提供)。 */
53
- function Toggle(props: { checked: boolean; disabled?: boolean; onChange: (checked: boolean) => void }): JSX.Element {
54
- return createElement('label', { className: `dss_toggle${props.checked ? ' dss_toggleOn' : ''}` }, [
55
- createElement('input', {
56
- key: 'i',
57
- type: 'checkbox',
58
- checked: props.checked,
59
- disabled: props.disabled === true,
60
- onChange: (event: { target: { checked: boolean } }) => { props.onChange(event.target.checked) },
61
- }),
62
- createElement('span', { key: 's', className: 'dss_toggleTrack' }, createElement('span', { className: 'dss_toggleKnob' })),
63
- ])
64
- }
65
-
66
- /** 抽屉头:标题 + 说明 + chevron,整块可点。 */
67
- function Header(props: { t?: CardTranslate; open: boolean; onToggle: () => void }): JSX.Element {
68
- return createElement('button', {
69
- key: 'head',
70
- type: 'button',
71
- className: 'dss_setHead',
72
- 'aria-expanded': props.open,
73
- onClick: props.onToggle,
74
- }, [
75
- createElement('span', { key: 'text', className: 'dss_setHeadText' }, [
76
- createElement('span', { key: 't', className: 'dss_setCardTitle' }, translate(props.t, 'card.title')),
77
- createElement('span', { key: 'd', className: 'dss_setCardDesc' }, translate(props.t, 'card.desc')),
78
- ]),
79
- createElement('svg', {
80
- key: 'chev',
81
- className: 'dss_setChev',
82
- width: 16,
83
- height: 16,
84
- viewBox: '0 0 16 16',
85
- 'aria-hidden': true,
86
- }, createElement('path', {
87
- d: 'M4 6l4 4 4-4',
88
- fill: 'none',
89
- stroke: 'currentColor',
90
- strokeWidth: 1.5,
91
- strokeLinecap: 'round',
92
- strokeLinejoin: 'round',
93
- })),
94
- ])
95
- }
96
-
97
- /** 插件设置卡主体(抽屉)。默认收起,与「插件」分区内其它卡片一致。 */
98
- export function StewardSettingsCard({ t, scope }: StewardCardProps): JSX.Element {
99
- const snapshot = useSyncExternalStore(
100
- (listener) => scope.subscribe(listener),
101
- () => scope.getSnapshot(),
102
- )
103
- const [open, setOpen] = useState(false)
104
- const value: Partial<StewardConfig> = snapshot.value ?? {}
105
- const writable = snapshot.writable
106
-
107
- const rows: JSX.Element[] = []
108
- if (snapshot.status === 'unavailable') {
109
- // 拿不到设置服务:抽屉仍要在(否则这个插件在分区里彻底消失),只是里面说明原因。
110
- rows.push(createElement('div', { key: 'unavailable', className: 'dss_setDesc' }, translate(t, 'card.unavailable')))
111
- } else {
112
- rows.push(
113
- createElement(Row, {
114
- key: 'enabled',
115
- title: translate(t, 'card.enabled'),
116
- desc: translate(t, 'card.enabled.desc'),
117
- control: createElement(Toggle, {
118
- checked: value.enabled ?? DEFAULT_CONFIG.enabled,
119
- disabled: !writable,
120
- onChange: (checked) => { void scope.set('enabled', checked) },
121
- }),
122
- }),
123
- createElement(Row, {
124
- key: 'history',
125
- title: translate(t, 'card.history'),
126
- desc: translate(t, 'card.history.desc'),
127
- control: createElement(Toggle, {
128
- checked: value.historyFiles ?? DEFAULT_CONFIG.historyFiles,
129
- disabled: !writable,
130
- onChange: (checked) => { void scope.set('historyFiles', checked) },
131
- }),
132
- }),
133
- createElement(Row, {
134
- key: 'health',
135
- title: translate(t, 'card.health'),
136
- desc: translate(t, 'card.health.desc'),
137
- control: createElement(Toggle, {
138
- checked: value.healthCheck ?? DEFAULT_CONFIG.healthCheck,
139
- disabled: !writable,
140
- onChange: (checked) => { void scope.set('healthCheck', checked) },
141
- }),
142
- }),
143
- )
144
- if (!writable) rows.push(createElement('div', { key: 'ro', className: 'dss_setDesc' }, translate(t, 'card.readonly')))
145
- }
146
-
147
- return createElement('div', {
148
- className: `dss_setCard${open ? ' dss_setCardOpen' : ''}`,
149
- }, [
150
- createElement(Header, { key: 'head', t, open, onToggle: () => { setOpen(current => !current) } }),
151
- open && createElement('div', { key: 'body', className: 'dss_setBody' }, rows),
152
- ])
153
- }
1
+ /**
2
+ * 设置卡(插件配置行):一个可折叠抽屉 —— 会话历史文件 / 健康检查。
3
+ *
4
+ * **chrome 必须自己渲染**:宿主不为贡献卡提供任何外壳,标题、说明、
5
+ * 展开/收起全归插件自己所有。早期版本只渲染裸行,与同分区其它插件
6
+ * 的抽屉形态不一致,还让 `card.title` / `card.desc` 成为死文案。
7
+ *
8
+ * 读写走 configForms(`configForms.get(STEWARD_ENTRY_ID)`,以本插件 entry 为键;
9
+ * 旧宿主回退 settingsScope 绑定)的显式 `set`。0.1.7 起本卡挂在插件族共用
10
+ * 设置节(`dsh-family.tab`,dsh-thinking-levels 顶级「起子插件设置」节声明)里,
11
+ * 与同节其它抽屉一样默认展开。
12
+ */
13
+ import { createElement, useState, useSyncExternalStore, type JSX } from 'react'
14
+ import { DEFAULT_CONFIG, type StewardConfig } from '../config.ts'
15
+ import { translate, type LocaleKey } from './locales.ts'
16
+
17
+ /** 卡片字典面。 */
18
+ export type CardTranslate = (key: LocaleKey, params?: Record<string, unknown>) => string
19
+
20
+ /** 设置 scope 面(结构化镜像,与 toggle 的 SwitchCardScope 同形状)。 */
21
+ export interface StewardCardScope {
22
+ getSnapshot(): {
23
+ status: 'ready' | 'loading' | 'unavailable'
24
+ value: StewardConfig | undefined
25
+ revision?: number
26
+ writable: boolean
27
+ }
28
+ subscribe(listener: () => void): () => void
29
+ set(field: string, value: unknown): Promise<void>
30
+ }
31
+
32
+ /** 卡片入参。 */
33
+ export interface StewardCardProps {
34
+ t?: CardTranslate
35
+ scope: StewardCardScope
36
+ }
37
+
38
+ /** 一行设置项。 */
39
+ function Row(props: { title: string; desc?: string; control: JSX.Element }): JSX.Element {
40
+ return createElement('div', { className: 'dss_setRow' }, [
41
+ createElement('div', { key: 'text', className: 'dss_setText' }, [
42
+ createElement('span', { key: 't', className: 'dss_setTitle' }, props.title),
43
+ props.desc !== undefined && createElement('span', { key: 'd', className: 'dss_setDesc' }, props.desc),
44
+ ]),
45
+ createElement('div', { key: 'ctl' }, props.control),
46
+ ])
47
+ }
48
+
49
+ /** 一个布尔开关(原生 checkbox 语义,样式由本插件 CSS 提供)。 */
50
+ function Toggle(props: { checked: boolean; disabled?: boolean; onChange: (checked: boolean) => void }): JSX.Element {
51
+ return createElement('label', { className: `dss_toggle${props.checked ? ' dss_toggleOn' : ''}` }, [
52
+ createElement('input', {
53
+ key: 'i',
54
+ type: 'checkbox',
55
+ checked: props.checked,
56
+ disabled: props.disabled === true,
57
+ onChange: (event: { target: { checked: boolean } }) => { props.onChange(event.target.checked) },
58
+ }),
59
+ createElement('span', { key: 's', className: 'dss_toggleTrack' }, createElement('span', { className: 'dss_toggleKnob' })),
60
+ ])
61
+ }
62
+
63
+ /** 抽屉头:标题 + 说明 + chevron,整块可点。 */
64
+ function Header(props: { t?: CardTranslate; open: boolean; onToggle: () => void }): JSX.Element {
65
+ return createElement('button', {
66
+ key: 'head',
67
+ type: 'button',
68
+ className: 'dss_setHead',
69
+ 'aria-expanded': props.open,
70
+ onClick: props.onToggle,
71
+ }, [
72
+ createElement('span', { key: 'text', className: 'dss_setHeadText' }, [
73
+ createElement('span', { key: 't', className: 'dss_setCardTitle' }, translate(props.t, 'card.title')),
74
+ createElement('span', { key: 'd', className: 'dss_setCardDesc' }, translate(props.t, 'card.desc')),
75
+ ]),
76
+ createElement('svg', {
77
+ key: 'chev',
78
+ className: 'dss_setChev',
79
+ width: 16,
80
+ height: 16,
81
+ viewBox: '0 0 16 16',
82
+ 'aria-hidden': true,
83
+ }, createElement('path', {
84
+ d: 'M4 6l4 4 4-4',
85
+ fill: 'none',
86
+ stroke: 'currentColor',
87
+ strokeWidth: 1.5,
88
+ strokeLinecap: 'round',
89
+ strokeLinejoin: 'round',
90
+ })),
91
+ ])
92
+ }
93
+
94
+ /** 插件设置卡主体(抽屉)。默认展开,family 设置节内直接呈现完整面板。 */
95
+ export function StewardSettingsCard({ t, scope }: StewardCardProps): JSX.Element {
96
+ const snapshot = useSyncExternalStore(
97
+ (listener) => scope.subscribe(listener),
98
+ () => scope.getSnapshot(),
99
+ )
100
+ const [open, setOpen] = useState(true)
101
+ const value: Partial<StewardConfig> = snapshot.value ?? {}
102
+ const writable = snapshot.writable
103
+
104
+ const rows: JSX.Element[] = []
105
+ if (snapshot.status === 'unavailable') {
106
+ // 拿不到设置服务:抽屉仍要在(否则这个插件在分区里彻底消失),只是里面说明原因。
107
+ rows.push(createElement('div', { key: 'unavailable', className: 'dss_setDesc' }, translate(t, 'card.unavailable')))
108
+ } else {
109
+ rows.push(
110
+ createElement(Row, {
111
+ key: 'enabled',
112
+ title: translate(t, 'card.enabled'),
113
+ desc: translate(t, 'card.enabled.desc'),
114
+ control: createElement(Toggle, {
115
+ checked: value.enabled ?? DEFAULT_CONFIG.enabled,
116
+ disabled: !writable,
117
+ onChange: (checked) => { void scope.set('enabled', checked) },
118
+ }),
119
+ }),
120
+ createElement(Row, {
121
+ key: 'history',
122
+ title: translate(t, 'card.history'),
123
+ desc: translate(t, 'card.history.desc'),
124
+ control: createElement(Toggle, {
125
+ checked: value.historyFiles ?? DEFAULT_CONFIG.historyFiles,
126
+ disabled: !writable,
127
+ onChange: (checked) => { void scope.set('historyFiles', checked) },
128
+ }),
129
+ }),
130
+ createElement(Row, {
131
+ key: 'health',
132
+ title: translate(t, 'card.health'),
133
+ desc: translate(t, 'card.health.desc'),
134
+ control: createElement(Toggle, {
135
+ checked: value.healthCheck ?? DEFAULT_CONFIG.healthCheck,
136
+ disabled: !writable,
137
+ onChange: (checked) => { void scope.set('healthCheck', checked) },
138
+ }),
139
+ }),
140
+ )
141
+ if (!writable) rows.push(createElement('div', { key: 'ro', className: 'dss_setDesc' }, translate(t, 'card.readonly')))
142
+ }
143
+
144
+ return createElement('div', {
145
+ className: `dss_setCard${open ? ' dss_setCardOpen' : ''}`,
146
+ }, [
147
+ createElement(Header, { key: 'head', t, open, onToggle: () => { setOpen(current => !current) } }),
148
+ open && createElement('div', { key: 'body', className: 'dss_setBody' }, rows),
149
+ ])
150
+ }