@dsh-workbench/shared 0.1.7 → 0.1.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.
Files changed (64) hide show
  1. package/dist/api/dsh-client.d.ts +11 -0
  2. package/dist/components/Activity.css +69 -0
  3. package/dist/components/Activity.d.ts +23 -0
  4. package/dist/components/Activity.js +23 -0
  5. package/dist/components/ApprovalPlan.css +41 -0
  6. package/dist/components/ApprovalPlan.d.ts +13 -0
  7. package/dist/components/ApprovalPlan.js +11 -0
  8. package/dist/components/Card.css +20 -0
  9. package/dist/components/Card.d.ts +13 -0
  10. package/dist/components/Card.js +8 -0
  11. package/dist/components/Note.css +14 -0
  12. package/dist/components/Note.d.ts +8 -0
  13. package/dist/components/Note.js +6 -0
  14. package/dist/components/ResourceStates.css +5 -1
  15. package/dist/components/Rows.css +30 -0
  16. package/dist/components/Rows.d.ts +11 -0
  17. package/dist/components/Rows.js +10 -0
  18. package/dist/components/SettingsSection.css +26 -0
  19. package/dist/components/SettingsSection.d.ts +9 -0
  20. package/dist/components/SettingsSection.js +9 -0
  21. package/dist/components/Stack.css +7 -0
  22. package/dist/components/Stack.d.ts +6 -0
  23. package/dist/components/Stack.js +5 -0
  24. package/dist/components/StateBlock.css +36 -0
  25. package/dist/components/StateBlock.d.ts +11 -0
  26. package/dist/components/StateBlock.js +12 -0
  27. package/dist/components/icons.d.ts +1 -0
  28. package/dist/components/icons.js +4 -0
  29. package/dist/config/constants.d.ts +2 -0
  30. package/dist/config/constants.js +2 -0
  31. package/dist/i18n/en.js +5 -2
  32. package/dist/i18n/index.d.ts +6 -3
  33. package/dist/i18n/zh.d.ts +5 -2
  34. package/dist/i18n/zh.js +5 -2
  35. package/dist/index.d.ts +8 -0
  36. package/dist/index.js +8 -0
  37. package/dist/lib/react.d.ts +1 -0
  38. package/dist/lib/react.js +1 -0
  39. package/package.json +1 -1
  40. package/src/api/dsh-client.ts +13 -0
  41. package/src/components/Activity.css +69 -0
  42. package/src/components/Activity.tsx +76 -0
  43. package/src/components/ApprovalPlan.css +41 -0
  44. package/src/components/ApprovalPlan.tsx +33 -0
  45. package/src/components/Card.css +20 -0
  46. package/src/components/Card.tsx +28 -0
  47. package/src/components/Note.css +14 -0
  48. package/src/components/Note.tsx +14 -0
  49. package/src/components/ResourceStates.css +5 -1
  50. package/src/components/Rows.css +30 -0
  51. package/src/components/Rows.tsx +25 -0
  52. package/src/components/SettingsSection.css +26 -0
  53. package/src/components/SettingsSection.tsx +22 -0
  54. package/src/components/Stack.css +7 -0
  55. package/src/components/Stack.tsx +11 -0
  56. package/src/components/StateBlock.css +36 -0
  57. package/src/components/StateBlock.tsx +29 -0
  58. package/src/components/icons.tsx +16 -0
  59. package/src/config/constants.ts +4 -0
  60. package/src/i18n/en.ts +5 -2
  61. package/src/i18n/zh.ts +5 -2
  62. package/src/index.ts +8 -0
  63. package/src/lib/react.test.ts +2 -1
  64. package/src/lib/react.ts +1 -0
package/dist/i18n/zh.d.ts CHANGED
@@ -79,7 +79,7 @@ export declare const zh: {
79
79
  readonly 'panels.market.empty': "暂无可用模块";
80
80
  readonly 'panels.market.installedSection': "已装";
81
81
  readonly 'panels.market.moduleOutdated': "有新版";
82
- readonly 'panels.market.moduleRestartHint': "安装完成后可能需要重启才生效";
82
+ readonly 'panels.market.moduleRestartHint': "装好了但还没生效 —— 重启一次 dsh 就会出来";
83
83
  readonly 'panels.market.restartNeeded': "新版装好了,重启一次才生效。";
84
84
  readonly 'panels.market.foot': "装好后到那个项目的面板页勾选它,模块才会出现。";
85
85
  readonly 'panels.market.recheck': "重新检查更新";
@@ -275,13 +275,16 @@ export declare const zh: {
275
275
  readonly 'rightbar.label': "数据面板";
276
276
  readonly 'rightbar.expand': "展开数据面板";
277
277
  readonly 'rightbar.collapse': "收起数据面板";
278
+ readonly 'rightbar.column.label': "右侧栏";
279
+ readonly 'rightbar.column.workbench': "工作台面板";
280
+ readonly 'rightbar.column.dsh': "dsh 面板";
278
281
  readonly 'rightbar.refresh': "刷新";
279
282
  readonly 'rightbar.refreshing': "刷新中…";
280
283
  readonly 'rightbar.updatedAt': "更新于 {time}";
281
284
  readonly 'rightbar.noProject': "当前会话没有所属项目";
282
285
  readonly 'coding.notARepo.title': "这个项目不是 Coding 仓库";
283
286
  readonly 'error.unknown': "出错了";
284
- readonly 'board.title': "看板";
287
+ readonly 'board.title': "工作台面板";
285
288
  readonly 'panel.conversation': "对话";
286
289
  readonly 'panels.label': "全局面板";
287
290
  };
package/dist/i18n/zh.js CHANGED
@@ -79,7 +79,7 @@ export const zh = {
79
79
  'panels.market.empty': '暂无可用模块',
80
80
  'panels.market.installedSection': '已装',
81
81
  'panels.market.moduleOutdated': '有新版',
82
- 'panels.market.moduleRestartHint': '安装完成后可能需要重启才生效',
82
+ 'panels.market.moduleRestartHint': '装好了但还没生效 —— 重启一次 dsh 就会出来',
83
83
  'panels.market.restartNeeded': '新版装好了,重启一次才生效。',
84
84
  'panels.market.foot': '装好后到那个项目的面板页勾选它,模块才会出现。',
85
85
  'panels.market.recheck': '重新检查更新',
@@ -275,13 +275,16 @@ export const zh = {
275
275
  'rightbar.label': '数据面板',
276
276
  'rightbar.expand': '展开数据面板',
277
277
  'rightbar.collapse': '收起数据面板',
278
+ 'rightbar.column.label': '右侧栏',
279
+ 'rightbar.column.workbench': '工作台面板',
280
+ 'rightbar.column.dsh': 'dsh 面板',
278
281
  'rightbar.refresh': '刷新',
279
282
  'rightbar.refreshing': '刷新中…',
280
283
  'rightbar.updatedAt': '更新于 {time}',
281
284
  'rightbar.noProject': '当前会话没有所属项目',
282
285
  'coding.notARepo.title': '这个项目不是 Coding 仓库',
283
286
  'error.unknown': '出错了',
284
- 'board.title': '看板',
287
+ 'board.title': '工作台面板',
285
288
  'panel.conversation': '对话',
286
289
  'panels.label': '全局面板',
287
290
  };
package/dist/index.d.ts CHANGED
@@ -10,13 +10,21 @@ export * from './api/unit-board.js';
10
10
  export * from './api/unit.js';
11
11
  export * from './api/workbench-client.js';
12
12
  export * from './api/workbench-contract.js';
13
+ export * from './components/Activity.js';
13
14
  export * from './components/ApprovalDetail.js';
15
+ export * from './components/ApprovalPlan.js';
16
+ export * from './components/Card.js';
14
17
  export * from './components/CardHead.js';
15
18
  export * from './components/ChoiceGroup.js';
16
19
  export * from './components/LongTaskRow.js';
17
20
  export * from './components/MockStrip.js';
21
+ export * from './components/Note.js';
18
22
  export * from './components/ResourceStates.js';
23
+ export * from './components/Rows.js';
19
24
  export * from './components/SaveBar.js';
25
+ export * from './components/SettingsSection.js';
26
+ export * from './components/Stack.js';
27
+ export * from './components/StateBlock.js';
20
28
  export * from './components/TextField.js';
21
29
  export * from './components/board-module.js';
22
30
  export * from './components/icons.js';
package/dist/index.js CHANGED
@@ -10,13 +10,21 @@ export * from './api/unit-board.js';
10
10
  export * from './api/unit.js';
11
11
  export * from './api/workbench-client.js';
12
12
  export * from './api/workbench-contract.js';
13
+ export * from './components/Activity.js';
13
14
  export * from './components/ApprovalDetail.js';
15
+ export * from './components/ApprovalPlan.js';
16
+ export * from './components/Card.js';
14
17
  export * from './components/CardHead.js';
15
18
  export * from './components/ChoiceGroup.js';
16
19
  export * from './components/LongTaskRow.js';
17
20
  export * from './components/MockStrip.js';
21
+ export * from './components/Note.js';
18
22
  export * from './components/ResourceStates.js';
23
+ export * from './components/Rows.js';
19
24
  export * from './components/SaveBar.js';
25
+ export * from './components/SettingsSection.js';
26
+ export * from './components/Stack.js';
27
+ export * from './components/StateBlock.js';
20
28
  export * from './components/TextField.js';
21
29
  export * from './components/board-module.js';
22
30
  export * from './components/icons.js';
@@ -3,6 +3,7 @@ export declare const h: typeof ReactTypes.createElement;
3
3
  export declare const Fragment: ReactTypes.ExoticComponent<ReactTypes.FragmentProps>;
4
4
  export declare const useState: typeof ReactTypes.useState;
5
5
  export declare const useEffect: typeof ReactTypes.useEffect;
6
+ export declare const useLayoutEffect: typeof ReactTypes.useLayoutEffect;
6
7
  export declare const useMemo: typeof ReactTypes.useMemo;
7
8
  export declare const useCallback: typeof ReactTypes.useCallback;
8
9
  export declare const useRef: typeof ReactTypes.useRef;
package/dist/lib/react.js CHANGED
@@ -3,6 +3,7 @@ export const h = react.createElement;
3
3
  export const Fragment = react.Fragment;
4
4
  export const useState = react.useState;
5
5
  export const useEffect = react.useEffect;
6
+ export const useLayoutEffect = react.useLayoutEffect;
6
7
  export const useMemo = react.useMemo;
7
8
  export const useCallback = react.useCallback;
8
9
  export const useRef = react.useRef;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/shared",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "工作台与模块共享的纯代码与契约类型:类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进(不影响浏览器产物)。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -163,6 +163,19 @@ export interface DshSessionsService {
163
163
  scope(sessionId: string): unknown | undefined;
164
164
  }
165
165
 
166
+ export interface DshObservable<T> {
167
+ getSnapshot(): T;
168
+ subscribe(listener: () => void): () => void;
169
+ }
170
+
171
+ export interface DshSidebarRight {
172
+ readonly mounted: DshObservable<string | undefined>;
173
+ isExpanded(): boolean;
174
+ toggleExpanded(): void;
175
+ openResource(address: string, options?: unknown): void;
176
+ openTab(kind: string, options?: unknown): void;
177
+ }
178
+
166
179
  export interface DshClientContext {
167
180
  get<T = unknown>(name: string): T | undefined;
168
181
  provide(name: string, value: unknown): void;
@@ -0,0 +1,69 @@
1
+
2
+ .wb-activityBlock {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--wb-len-6);
6
+ padding-top: var(--wb-len-10);
7
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
8
+ }
9
+
10
+ .wb-activityBlock:first-child {
11
+ border-top: none;
12
+ }
13
+
14
+ .wb-activityBlockHead {
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: space-between;
18
+ gap: var(--wb-len-8);
19
+ }
20
+
21
+ .wb-activityLine {
22
+ display: flex;
23
+ align-items: center;
24
+ gap: var(--wb-len-6);
25
+ margin: 0;
26
+ font-size: var(--dsw-font-xxs-12-font-size);
27
+ line-height: var(--wb-line-18);
28
+ color: var(--dsw-alias-label-secondary);
29
+ }
30
+
31
+ .wb-activityLineText {
32
+ flex: none;
33
+ min-width: 0;
34
+ font-size: var(--dsw-font-xxs-12-font-size);
35
+ line-height: var(--wb-line-18);
36
+ overflow-wrap: anywhere;
37
+ white-space: pre-wrap;
38
+ max-height: var(--wb-len-72);
39
+ overflow-y: auto;
40
+ }
41
+
42
+ .wb-activityLineAt {
43
+ flex: none;
44
+ margin-left: auto;
45
+ font-size: var(--wb-font-10);
46
+ line-height: var(--wb-line-16);
47
+ font-variant-numeric: tabular-nums;
48
+ color: var(--dsw-alias-label-tertiary);
49
+ }
50
+
51
+ .wb-activityLine > .wb-activityLineAt,
52
+ .wb-activityLine > .wb-activityLineActions {
53
+ margin-left: auto;
54
+ }
55
+
56
+ .wb-activityLine > .wb-activityLineAt + .wb-activityLineActions {
57
+ margin-left: 0;
58
+ }
59
+
60
+ .wb-activityLineActions {
61
+ flex: none;
62
+ display: inline-flex;
63
+ align-items: center;
64
+ gap: var(--wb-len-6);
65
+ }
66
+
67
+ .wb-activityActionFailed {
68
+ color: var(--dsw-alias-state-error-primary);
69
+ }
@@ -0,0 +1,76 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { Button, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import { h } from '../lib/react.js';
4
+ import './Activity.css';
5
+
6
+ export interface ActivityBlockProps {
7
+ readonly head?: ReactNode | undefined;
8
+ readonly children?: ReactNode | undefined;
9
+ }
10
+
11
+ export function ActivityBlock({ head, children }: ActivityBlockProps) {
12
+ return (
13
+ <div className="wb-activityBlock">
14
+ {head === undefined ? null : <div className="wb-activityBlockHead">{head}</div>}
15
+ {children}
16
+ </div>
17
+ );
18
+ }
19
+
20
+ export interface ActivityLineProps {
21
+ readonly dot?: ReactNode | undefined;
22
+ readonly text: ReactNode;
23
+ readonly at?: ReactNode | undefined;
24
+ readonly actions?: ReactNode | undefined;
25
+ }
26
+
27
+ export function ActivityLine({ dot, text, at, actions }: ActivityLineProps) {
28
+ return (
29
+ <div className="wb-activityLine">
30
+ {dot}
31
+ <span className="wb-activityLineText">{text}</span>
32
+ {at === undefined ? null : <span className="wb-activityLineAt">{at}</span>}
33
+ {actions === undefined ? null : <span className="wb-activityLineActions">{actions}</span>}
34
+ </div>
35
+ );
36
+ }
37
+
38
+ export interface ActivityActionProps {
39
+ readonly label: string;
40
+ readonly hint?: string | undefined;
41
+ readonly icon: ReactNode;
42
+ readonly href?: string | undefined;
43
+ readonly onClick?: (() => void) | undefined;
44
+ readonly failed?: boolean | undefined;
45
+ }
46
+
47
+ export function ActivityAction({ label, hint, icon, href, onClick, failed }: ActivityActionProps) {
48
+ const tip = hint ?? label;
49
+ if (href !== undefined) {
50
+ return (
51
+ <a
52
+ className="wb-iconButton"
53
+ href={href}
54
+ target="_blank"
55
+ rel="noreferrer noopener"
56
+ title={tip}
57
+ aria-label={label}
58
+ >
59
+ {icon}
60
+ </a>
61
+ );
62
+ }
63
+ return (
64
+ <Tooltip side="bottom" align="end" gap={6} portal label={tip}>
65
+ <Button
66
+ type="button"
67
+ variant="ghost"
68
+ size="sm"
69
+ className={failed === true ? 'wb-iconButton wb-activityActionFailed' : 'wb-iconButton'}
70
+ aria-label={label}
71
+ icon={icon}
72
+ onClick={onClick}
73
+ />
74
+ </Tooltip>
75
+ );
76
+ }
@@ -0,0 +1,41 @@
1
+
2
+ .wb-approvalPlan {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--wb-len-6);
6
+ }
7
+ .wb-approvalHint {
8
+ margin: 0;
9
+ font-size: var(--dsw-font-xxs-12-font-size);
10
+ line-height: var(--wb-line-18);
11
+ color: var(--dsw-alias-label-secondary);
12
+ }
13
+ .wb-approvalRows {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: var(--wb-len-2);
17
+ margin: 0;
18
+ }
19
+ .wb-approvalRow {
20
+ display: flex;
21
+ align-items: baseline;
22
+ gap: var(--wb-len-8);
23
+ }
24
+ .wb-approvalLabel {
25
+ flex: none;
26
+ width: var(--wb-len-56);
27
+ font-size: var(--dsw-font-xxs-12-font-size);
28
+ line-height: var(--wb-line-18);
29
+ color: var(--dsw-alias-label-tertiary);
30
+ }
31
+ .wb-approvalValue {
32
+ margin: 0;
33
+ font-size: var(--dsw-font-xs-13-font-size);
34
+ line-height: var(--wb-line-18);
35
+ font-weight: 500;
36
+ color: var(--dsw-alias-label-primary);
37
+ overflow-wrap: anywhere;
38
+ }
39
+ .wb-approvalWarn {
40
+ color: var(--dsw-alias-label-secondary);
41
+ }
@@ -0,0 +1,33 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { h } from '../lib/react.js';
3
+ import './ApprovalPlan.css';
4
+
5
+ export interface ApprovalPlanRow {
6
+ readonly label: ReactNode;
7
+ readonly value: ReactNode;
8
+ }
9
+
10
+ export interface ApprovalPlanProps {
11
+ readonly rows: readonly ApprovalPlanRow[];
12
+ readonly hint?: ReactNode | undefined;
13
+ readonly warn?: ReactNode | undefined;
14
+ readonly children?: ReactNode | undefined;
15
+ }
16
+
17
+ export function ApprovalPlan({ rows, hint, warn, children }: ApprovalPlanProps) {
18
+ return (
19
+ <div className="wb-approvalPlan">
20
+ {hint === undefined ? null : <p className="wb-approvalHint">{hint}</p>}
21
+ <dl className="wb-approvalRows">
22
+ {rows.map((row, index) => (
23
+ <div className="wb-approvalRow" key={String(index)}>
24
+ <dt className="wb-approvalLabel">{row.label}</dt>
25
+ <dd className="wb-approvalValue">{row.value}</dd>
26
+ </div>
27
+ ))}
28
+ </dl>
29
+ {children}
30
+ {warn === undefined ? null : <p className="wb-approvalWarn">{warn}</p>}
31
+ </div>
32
+ );
33
+ }
@@ -0,0 +1,20 @@
1
+
2
+ .wb-card {
3
+ border: 0.5px solid var(--dsw-alias-border-l3);
4
+ border-radius: var(--dsw-radius-xl);
5
+ background: var(--dsw-alias-bg-layer-1);
6
+ overflow: hidden;
7
+ display: flex;
8
+ flex-direction: column;
9
+ flex: none;
10
+ }
11
+ .wb-cardBody {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: var(--wb-len-12);
15
+ padding: var(--wb-len-12);
16
+ }
17
+ .wb-cardBody > :not([data-wb-bleed]) {
18
+ padding-left: var(--wb-len-8);
19
+ padding-right: var(--wb-len-8);
20
+ }
@@ -0,0 +1,28 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import type { Translate } from '../api/dsh-client.js';
3
+ import { h } from '../lib/react.js';
4
+ import { CardHead } from './CardHead.js';
5
+ import './Card.css';
6
+
7
+ export interface CardProps {
8
+ readonly t: Translate;
9
+ readonly title: string;
10
+ readonly refreshing: boolean;
11
+ readonly onRefresh: () => void;
12
+ readonly meta?: ReactNode | undefined;
13
+ readonly head?: ReactNode | undefined;
14
+ readonly children?: ReactNode | undefined;
15
+ }
16
+
17
+ export function Card({ t, title, refreshing, onRefresh, meta, head, children }: CardProps) {
18
+ return (
19
+ <section className="wb-card">
20
+ {head === undefined ? (
21
+ <CardHead t={t} title={title} refreshing={refreshing} onRefresh={onRefresh} meta={meta} />
22
+ ) : (
23
+ head
24
+ )}
25
+ <div className="wb-cardBody">{children}</div>
26
+ </section>
27
+ );
28
+ }
@@ -0,0 +1,14 @@
1
+
2
+ .wb-note {
3
+ margin: 0;
4
+ font-size: var(--dsw-font-xxxs-11-font-size);
5
+ line-height: var(--wb-line-16);
6
+ color: var(--dsw-alias-label-tertiary);
7
+ }
8
+ .wb-problem {
9
+ margin: 0;
10
+ font-size: var(--dsw-font-xxxs-11-font-size);
11
+ line-height: var(--wb-line-16);
12
+ color: var(--dsw-alias-state-error-primary);
13
+ overflow-wrap: anywhere;
14
+ }
@@ -0,0 +1,14 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { h } from '../lib/react.js';
3
+ import './Note.css';
4
+
5
+ export interface NoteProps {
6
+ readonly tone?: 'muted' | 'problem';
7
+ readonly as?: 'p' | 'span';
8
+ readonly children?: ReactNode | undefined;
9
+ }
10
+
11
+ export function Note({ tone = 'muted', as, children }: NoteProps) {
12
+ const className = tone === 'problem' ? 'wb-problem' : 'wb-note';
13
+ return as === 'span' ? <span className={className}>{children}</span> : <p className={className}>{children}</p>;
14
+ }
@@ -108,4 +108,8 @@
108
108
  justify-content: center;
109
109
  gap: var(--wb-len-8);
110
110
  margin-top: var(--wb-len-2);
111
- }
111
+ }
112
+ @media (prefers-reduced-motion: reduce) {
113
+ .wb-skeletonBar {
114
+ animation: none;
115
+ }}
@@ -0,0 +1,30 @@
1
+
2
+ .wb-row:has(> [data-wb-dot]) {
3
+ grid-template-columns: 84px minmax(0, 1fr);
4
+ }
5
+ .wb-rows {
6
+ display: flex;
7
+ flex-direction: column;
8
+ }
9
+ .wb-row {
10
+ display: grid;
11
+ grid-template-columns: 56px minmax(0, 1fr);
12
+ align-items: baseline;
13
+ gap: var(--wb-len-8);
14
+ padding: var(--wb-len-4) 0;
15
+ }
16
+ .wb-row + .wb-row {
17
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
18
+ }
19
+ .wb-rowKey {
20
+ font-size: var(--dsw-font-xxxs-11-font-size);
21
+ line-height: var(--wb-line-16);
22
+ color: var(--dsw-alias-label-tertiary);
23
+ }
24
+ .wb-rowValue {
25
+ min-width: 0;
26
+ font-size: var(--dsw-font-xxs-12-font-size);
27
+ line-height: var(--wb-line-18);
28
+ color: var(--dsw-alias-label-primary);
29
+ overflow-wrap: anywhere;
30
+ }
@@ -0,0 +1,25 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { h } from '../lib/react.js';
3
+ import './Rows.css';
4
+
5
+ export interface RowsProps {
6
+ readonly children?: ReactNode | undefined;
7
+ }
8
+
9
+ export function Rows({ children }: RowsProps) {
10
+ return <div className="wb-rows">{children}</div>;
11
+ }
12
+
13
+ export interface RowProps {
14
+ readonly label: ReactNode;
15
+ readonly value: ReactNode;
16
+ }
17
+
18
+ export function Row({ label, value }: RowProps) {
19
+ return (
20
+ <div className="wb-row">
21
+ <span className="wb-rowKey">{label}</span>
22
+ <span className="wb-rowValue">{value}</span>
23
+ </div>
24
+ );
25
+ }
@@ -0,0 +1,26 @@
1
+
2
+ .wb-settings {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--wb-len-8);
6
+ padding: var(--wb-len-10);
7
+ border: 0.5px solid var(--dsw-alias-border-l2);
8
+ border-radius: var(--dsw-radius-md);
9
+ background: var(--dsw-alias-bg-layer-1);
10
+ }
11
+ .wb-settingsHead {
12
+ display: flex;
13
+ align-items: center;
14
+ gap: var(--wb-len-8);
15
+ }
16
+ .wb-settingsTitle {
17
+ flex: 1 1 auto;
18
+ min-width: 0;
19
+ overflow: hidden;
20
+ text-overflow: ellipsis;
21
+ white-space: nowrap;
22
+ font-size: var(--dsw-font-xxs-12-font-size);
23
+ line-height: var(--wb-line-18);
24
+ font-weight: 500;
25
+ color: var(--dsw-alias-label-primary);
26
+ }
@@ -0,0 +1,22 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { h } from '../lib/react.js';
3
+ import './SettingsSection.css';
4
+
5
+ export interface SettingsSectionProps {
6
+ readonly label: string;
7
+ readonly title: ReactNode;
8
+ readonly action?: ReactNode | undefined;
9
+ readonly children?: ReactNode | undefined;
10
+ }
11
+
12
+ export function SettingsSection({ label, title, action, children }: SettingsSectionProps) {
13
+ return (
14
+ <section className="wb-settings" role="group" aria-label={label}>
15
+ <header className="wb-settingsHead">
16
+ <span className="wb-settingsTitle">{title}</span>
17
+ {action}
18
+ </header>
19
+ {children}
20
+ </section>
21
+ );
22
+ }
@@ -0,0 +1,7 @@
1
+
2
+ .wb-stack {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--wb-len-10);
6
+ min-height: 0;
7
+ }
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { h } from '../lib/react.js';
3
+ import './Stack.css';
4
+
5
+ export interface StackProps {
6
+ readonly children?: ReactNode | undefined;
7
+ }
8
+
9
+ export function Stack({ children }: StackProps) {
10
+ return <div className="wb-stack">{children}</div>;
11
+ }
@@ -0,0 +1,36 @@
1
+
2
+ .wb-stateBlock {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--wb-len-6);
6
+ }
7
+ .wb-stateBlockTitle {
8
+ margin: 0;
9
+ display: flex;
10
+ align-items: center;
11
+ gap: var(--wb-len-6);
12
+ font-size: var(--dsw-font-xxs-12-font-size);
13
+ line-height: var(--wb-line-18);
14
+ color: var(--dsw-alias-label-primary);
15
+ }
16
+ .wb-stateBlockHint {
17
+ margin: 0;
18
+ font-size: var(--dsw-font-xxxs-11-font-size);
19
+ line-height: var(--wb-line-16);
20
+ color: var(--dsw-alias-label-tertiary);
21
+ }
22
+ .wb-stateBlockActions {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: var(--wb-len-8);
26
+ margin-top: var(--wb-len-2);
27
+ }
28
+ .wb-stateBlockResolving {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: var(--wb-len-8);
32
+ margin: 0;
33
+ font-size: var(--dsw-font-xxs-12-font-size);
34
+ line-height: var(--wb-line-18);
35
+ color: var(--dsw-alias-label-secondary);
36
+ }
@@ -0,0 +1,29 @@
1
+ import type { ReactNode } from '../lib/react.js';
2
+ import { h } from '../lib/react.js';
3
+ import './StateBlock.css';
4
+
5
+ export interface StateBlockProps {
6
+ readonly title?: ReactNode | undefined;
7
+ readonly dot?: ReactNode | undefined;
8
+ readonly hint?: ReactNode | undefined;
9
+ readonly actions?: ReactNode | undefined;
10
+ readonly resolving?: ReactNode | undefined;
11
+ readonly children?: ReactNode | undefined;
12
+ }
13
+
14
+ export function StateBlock({ title, dot, hint, actions, resolving, children }: StateBlockProps) {
15
+ return (
16
+ <div className="wb-stateBlock">
17
+ {title === undefined && dot === undefined ? null : (
18
+ <p className="wb-stateBlockTitle">
19
+ {dot}
20
+ {title}
21
+ </p>
22
+ )}
23
+ {resolving === undefined ? null : <p className="wb-stateBlockResolving">{resolving}</p>}
24
+ {hint === undefined ? null : <p className="wb-stateBlockHint">{hint}</p>}
25
+ {children}
26
+ {actions === undefined ? null : <div className="wb-stateBlockActions">{actions}</div>}
27
+ </div>
28
+ );
29
+ }