@dsh-workbench/shared 0.1.2 → 0.1.4

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 (99) hide show
  1. package/dist/api/host-write.d.ts +1 -0
  2. package/dist/api/host-write.js +7 -1
  3. package/dist/api/workbench-contract.d.ts +1 -1
  4. package/dist/components/ApprovalDetail.css +4 -0
  5. package/dist/components/ApprovalDetail.d.ts +1 -0
  6. package/dist/components/ApprovalDetail.js +5 -1
  7. package/dist/components/CardHead.css +92 -0
  8. package/dist/components/CardHead.d.ts +1 -0
  9. package/dist/components/CardHead.js +9 -7
  10. package/dist/components/ChoiceGroup.css +75 -0
  11. package/dist/components/ChoiceGroup.d.ts +1 -0
  12. package/dist/components/ChoiceGroup.js +1 -0
  13. package/dist/components/LongTaskRow.css +53 -0
  14. package/dist/components/LongTaskRow.d.ts +3 -0
  15. package/dist/components/LongTaskRow.js +11 -11
  16. package/dist/components/MockStrip.css +39 -0
  17. package/dist/components/MockStrip.d.ts +1 -0
  18. package/dist/components/MockStrip.js +1 -0
  19. package/dist/components/ResourceStates.css +111 -0
  20. package/dist/components/ResourceStates.d.ts +2 -1
  21. package/dist/components/ResourceStates.js +1 -0
  22. package/dist/components/SaveBar.css +7 -0
  23. package/dist/components/SaveBar.d.ts +1 -0
  24. package/dist/components/SaveBar.js +4 -2
  25. package/dist/components/TextField.css +22 -0
  26. package/dist/components/TextField.d.ts +6 -0
  27. package/dist/components/TextField.js +5 -0
  28. package/dist/components/icons.d.ts +0 -12
  29. package/dist/components/icons.js +0 -61
  30. package/dist/host/http.js +5 -29
  31. package/dist/host/provision.d.ts +18 -1
  32. package/dist/host/provision.js +73 -0
  33. package/dist/host.d.ts +8 -0
  34. package/dist/host.js +8 -0
  35. package/dist/i18n/en.js +126 -1
  36. package/dist/i18n/index.d.ts +129 -4
  37. package/dist/i18n/zh.d.ts +128 -3
  38. package/dist/i18n/zh.js +128 -3
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +1 -1
  41. package/package.json +5 -3
  42. package/src/api/__tests__/host-write.test.ts +20 -0
  43. package/src/api/host-write.ts +17 -3
  44. package/src/api/workbench-contract.ts +5 -1
  45. package/src/components/ApprovalDetail.css +4 -0
  46. package/src/components/ApprovalDetail.tsx +11 -1
  47. package/src/components/CardHead.css +92 -0
  48. package/src/components/CardHead.tsx +43 -31
  49. package/src/components/ChoiceGroup.css +75 -0
  50. package/src/components/ChoiceGroup.tsx +1 -0
  51. package/src/components/LongTaskRow.css +53 -0
  52. package/src/components/LongTaskRow.tsx +52 -13
  53. package/src/components/MockStrip.css +39 -0
  54. package/src/components/MockStrip.tsx +1 -0
  55. package/src/components/ResourceStates.css +111 -0
  56. package/src/components/ResourceStates.tsx +2 -1
  57. package/src/components/SaveBar.css +7 -0
  58. package/src/components/SaveBar.tsx +8 -5
  59. package/src/components/TextField.css +22 -0
  60. package/src/components/TextField.tsx +17 -0
  61. package/src/components/icons.tsx +0 -164
  62. package/src/host/__tests__/provision.test.ts +90 -0
  63. package/src/host/http.ts +5 -33
  64. package/src/host/provision.ts +87 -0
  65. package/src/host.ts +8 -0
  66. package/src/i18n/en.ts +127 -1
  67. package/src/i18n/zh.ts +128 -4
  68. package/src/index.ts +1 -1
  69. package/dist/components/StateDot.d.ts +0 -5
  70. package/dist/components/StateDot.js +0 -10
  71. package/dist/host/__tests__/fakes.d.ts +0 -41
  72. package/dist/host/__tests__/fakes.js +0 -76
  73. package/dist/host/__tests__/preflight-fixtures.d.ts +0 -19
  74. package/dist/host/__tests__/preflight-fixtures.js +0 -47
  75. package/dist/host/context-inject.d.ts +0 -24
  76. package/dist/host/context-inject.js +0 -74
  77. package/dist/host/events.d.ts +0 -9
  78. package/dist/host/events.js +0 -70
  79. package/dist/host/mount-units.d.ts +0 -52
  80. package/dist/host/mount-units.js +0 -186
  81. package/dist/host/preflight.d.ts +0 -58
  82. package/dist/host/preflight.js +0 -233
  83. package/dist/host/probe-cache.d.ts +0 -6
  84. package/dist/host/probe-cache.js +0 -19
  85. package/dist/host/probe-libs.d.ts +0 -45
  86. package/dist/host/probe-libs.js +0 -61
  87. package/dist/host/probe-units.d.ts +0 -17
  88. package/dist/host/probe-units.js +0 -102
  89. package/dist/host/probe-verdict.d.ts +0 -7
  90. package/dist/host/probe-verdict.js +0 -143
  91. package/dist/host/tool-scope.d.ts +0 -32
  92. package/dist/host/tool-scope.js +0 -84
  93. package/dist/host/unit-readiness.d.ts +0 -7
  94. package/dist/host/unit-readiness.js +0 -5
  95. package/dist/host/unit-registry.d.ts +0 -9
  96. package/dist/host/unit-registry.js +0 -33
  97. package/dist/host/version-range.d.ts +0 -2
  98. package/dist/host/version-range.js +0 -73
  99. package/src/components/StateDot.tsx +0 -31
@@ -8,5 +8,6 @@ export type WriteOutcome<T> = {
8
8
  readonly ok: false;
9
9
  readonly message: string;
10
10
  readonly detail?: string;
11
+ readonly helpUrl?: string;
11
12
  };
12
13
  export declare function writeOutcomeOf<T>(response: ApiResponse<T> | null, networkText: string): WriteOutcome<T>;
@@ -11,7 +11,13 @@ export function writeOutcomeOf(response, networkText) {
11
11
  const own = typeof box.error?.message === 'string' && box.error.message !== '' ? box.error.message : undefined;
12
12
  const fallback = typeof box.text === 'string' && box.text !== '' ? box.text : networkText;
13
13
  const detail = typeof box.error?.detail === 'string' ? box.error.detail : undefined;
14
- return { ok: false, message: own ?? fallback, ...(detail === undefined ? {} : { detail }) };
14
+ const helpUrl = typeof box.error?.helpUrl === 'string' && box.error.helpUrl !== '' ? box.error.helpUrl : undefined;
15
+ return {
16
+ ok: false,
17
+ message: own ?? fallback,
18
+ ...(detail === undefined ? {} : { detail }),
19
+ ...(helpUrl === undefined ? {} : { helpUrl }),
20
+ };
15
21
  }
16
22
  return { ok: true, value: response };
17
23
  }
@@ -1,5 +1,5 @@
1
1
  import type { PluginRelease } from '../api/unit.js';
2
- export type ProvisionAction = 'install' | 'update' | 'uninstall' | 'update-dependency';
2
+ export type ProvisionAction = 'install' | 'update' | 'uninstall' | 'update-dependency' | 'install-bundle' | 'update-bundle' | 'remove-bundle' | 'cancel-install';
3
3
  export interface PluginStatePayload {
4
4
  readonly name: string;
5
5
  readonly status: 'ok' | 'outdated' | 'missing';
@@ -0,0 +1,4 @@
1
+
2
+ .wb-approvalCommand {
3
+ max-width: 100%;
4
+ }
@@ -1,5 +1,6 @@
1
1
  import type { Translate } from '../api/dsh-client.js';
2
2
  import type { UnitClientFace } from '../components/board-module.js';
3
+ import './ApprovalDetail.css';
3
4
  interface ToolCallRoot {
4
5
  readonly callId?: string;
5
6
  readonly name?: string;
@@ -1,4 +1,6 @@
1
1
  import { h } from '../lib/react.js';
2
+ import { CodeBlock } from '@deepseek-ai/dsh-client-ui-primitives';
3
+ import './ApprovalDetail.css';
2
4
  function callOf(snapshot, callId) {
3
5
  if (callId === undefined)
4
6
  return undefined;
@@ -29,5 +31,7 @@ export function ApprovalDetail(props) {
29
31
  const owner = (props.units ?? []).find((face) => face.approval?.tools.includes(input.tool) === true);
30
32
  if (owner?.approval !== undefined)
31
33
  return h(owner.approval.render, { input: input, t: t });
32
- return command === '' ? null : h("code", { className: "wb-approvalCommand" }, command);
34
+ if (command === '')
35
+ return null;
36
+ return (h(CodeBlock, { code: command, className: "wb-approvalCommand", copyLabel: t('blocker.copy'), copiedLabel: t('env.copied') }));
33
37
  }
@@ -0,0 +1,92 @@
1
+
2
+ .wb-cardHead {
3
+ display: flex;
4
+ align-items: center;
5
+ gap: var(--wb-len-6);
6
+ flex: none;
7
+ padding: var(--wb-len-8) var(--wb-len-10) var(--wb-len-8) var(--wb-len-20);
8
+ border-bottom: 0.5px solid var(--dsw-alias-border-l2);
9
+ background: var(--dsw-alias-bg-layer-2);
10
+ }
11
+
12
+ .wb-cardTitle {
13
+ margin: 0;
14
+ font-size: var(--dsw-font-xxs-12-font-size);
15
+ line-height: var(--wb-line-18);
16
+ font-weight: 600;
17
+ color: var(--dsw-alias-label-secondary);
18
+ }
19
+
20
+ .wb-cardMeta {
21
+ font-size: var(--dsw-font-xxxs-11-font-size);
22
+ line-height: var(--wb-line-16);
23
+ color: var(--dsw-alias-label-tertiary);
24
+ min-width: 0;
25
+ overflow: hidden;
26
+ text-overflow: ellipsis;
27
+ white-space: nowrap;
28
+ }
29
+
30
+ .wb-cardMeta::before {
31
+ content: '\00b7';
32
+ margin-right: var(--wb-len-6);
33
+ color: var(--dsw-alias-label-tertiary);
34
+ }
35
+
36
+ .wb-cardOpen {
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ box-sizing: border-box;
41
+ margin-left: auto;
42
+ flex: none;
43
+ width: var(--wb-len-22);
44
+ height: var(--wb-len-22);
45
+ padding: var(--wb-len-4);
46
+ border-radius: var(--wb-radius-6);
47
+ color: var(--dsw-alias-label-tertiary);
48
+ }
49
+
50
+ .wb-cardOpen ~ .wb-cardRefresh {
51
+ margin-left: 0;
52
+ }
53
+
54
+ .wb-cardOpen:hover {
55
+ color: var(--dsw-alias-label-primary);
56
+ }
57
+
58
+ .wb-cardRefresh {
59
+ margin-left: auto;
60
+ flex: none;
61
+ width: var(--wb-len-22);
62
+ height: var(--wb-len-22);
63
+ padding: var(--wb-len-4);
64
+ border-radius: var(--wb-radius-6);
65
+ color: var(--dsw-alias-label-tertiary);
66
+ }
67
+
68
+ .wb-cardRefresh:hover:not(:disabled) {
69
+ color: var(--dsw-alias-label-primary);
70
+ }
71
+
72
+ .wb-cardRefresh:disabled {
73
+ cursor: default;
74
+ opacity: 1;
75
+ }
76
+
77
+ .wb-cardGear {
78
+ flex: none;
79
+ width: var(--wb-len-22);
80
+ height: var(--wb-len-22);
81
+ padding: var(--wb-len-3);
82
+ border-radius: var(--wb-radius-6);
83
+ color: var(--dsw-alias-label-tertiary);
84
+ }
85
+
86
+ .wb-cardGear:hover:not(:disabled) {
87
+ color: var(--dsw-alias-label-primary);
88
+ }
89
+
90
+ .wb-cardRefresh.wb-spinning svg {
91
+ animation: wb-spin var(--wb-dur-0-9) linear infinite;
92
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from '../lib/react.js';
2
2
  import type { Translate } from '../api/dsh-client.js';
3
+ import './CardHead.css';
3
4
  export interface CardHeadProps {
4
5
  readonly t: Translate;
5
6
  readonly title: string;
@@ -1,14 +1,16 @@
1
- import { IconRefresh, IconRightUp, IconSettings } from '../components/icons.js';
1
+ import { Button, IconRefreshOutlineRegular, IconRightUpOutlineRegular, IconSettingsOutlineRegular, Tooltip, } from '@deepseek-ai/dsh-client-ui-primitives';
2
2
  import { h } from '../lib/react.js';
3
+ import './CardHead.css';
3
4
  export function CardHead({ t, title, meta, refreshing, onRefresh, gear, gearOpen, onToggleGear, platformHref, platform, platformTitle, }) {
4
5
  const refreshLabel = refreshing ? t('rightbar.refreshing') : t('rightbar.refresh');
5
6
  return (h("header", { className: "wb-cardHead" },
6
7
  h("h2", { className: "wb-cardTitle" }, title),
7
8
  meta === undefined ? null : h("span", { className: "wb-cardMeta" }, meta),
8
- platformHref === undefined || platform === undefined ? null : (h("a", { className: "wb-iconButton wb-cardOpen", href: platformHref, target: "_blank", rel: "noreferrer noopener", title: platformTitle ?? platform, "aria-label": platform },
9
- h(IconRightUp, { size: 14 }))),
10
- h("button", { type: "button", className: `wb-iconButton wb-cardRefresh${refreshing ? ' wb-spinning' : ''}`, "aria-label": refreshLabel, title: refreshLabel, disabled: refreshing, onClick: onRefresh },
11
- h(IconRefresh, { size: 14 })),
12
- gear === undefined || onToggleGear === undefined ? null : (h("button", { type: "button", className: `wb-iconButton wb-cardGear${gearOpen === true ? ' wb-iconButtonActive' : ''}`, "aria-label": gear, "aria-expanded": gearOpen === true, title: gear, onClick: onToggleGear },
13
- h(IconSettings, { size: 15 })))));
9
+ platformHref === undefined || platform === undefined ? null : (h(Tooltip, { label: platformTitle ?? platform },
10
+ h("a", { className: "wb-iconButton wb-cardOpen", href: platformHref, target: "_blank", rel: "noreferrer noopener", "aria-label": platform },
11
+ h(IconRightUpOutlineRegular, { size: 14 })))),
12
+ h(Tooltip, { label: refreshLabel },
13
+ h(Button, { type: "button", size: "sm", variant: "ghost", className: `wb-cardRefresh${refreshing ? ' wb-spinning' : ''}`, "aria-label": refreshLabel, disabled: refreshing, icon: h(IconRefreshOutlineRegular, { size: 14 }), onClick: onRefresh })),
14
+ gear === undefined || onToggleGear === undefined ? null : (h(Tooltip, { label: gear },
15
+ h(Button, { type: "button", size: "sm", variant: "ghost", className: `wb-cardGear${gearOpen === true ? ' wb-iconButtonActive' : ''}`, "aria-label": gear, "aria-expanded": gearOpen === true, icon: h(IconSettingsOutlineRegular, { size: 15 }), onClick: onToggleGear })))));
14
16
  }
@@ -0,0 +1,75 @@
1
+
2
+ .wb-choiceMenu {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--wb-len-2);
6
+ padding: var(--wb-len-4);
7
+ border: 0.5px solid var(--dsw-alias-border-l3);
8
+ border-radius: var(--dsw-radius-md);
9
+ background: transparent;
10
+ }
11
+
12
+ .wb-choiceOption {
13
+ display: flex;
14
+ align-items: center;
15
+ gap: var(--wb-len-6);
16
+ min-height: var(--wb-len-30);
17
+ padding: var(--wb-len-6) var(--wb-len-8);
18
+ border-radius: var(--dsw-radius-md);
19
+ cursor: pointer;
20
+ font-size: var(--dsw-font-xs-13-font-size);
21
+ line-height: var(--wb-line-20);
22
+ color: var(--dsw-alias-label-primary);
23
+ }
24
+
25
+ .wb-choiceOption:hover {
26
+ background: var(--dsw-alias-interactive-bg-hover);
27
+ }
28
+
29
+ .wb-choiceLabel {
30
+ flex: 1;
31
+ min-width: 0;
32
+ overflow: hidden;
33
+ text-overflow: ellipsis;
34
+ white-space: nowrap;
35
+ }
36
+
37
+ .wb-radio {
38
+ appearance: none;
39
+ -webkit-appearance: none;
40
+ flex: none;
41
+ box-sizing: border-box;
42
+ width: var(--wb-len-12);
43
+ height: var(--wb-len-12);
44
+ margin: 0;
45
+ border: 1px solid var(--dsw-alias-border-l3);
46
+ border-radius: 50%;
47
+ corner-shape: round;
48
+ background-color: transparent;
49
+ cursor: pointer;
50
+ transition:
51
+ background-color var(--wb-dur-0-12) ease, border-color var(--wb-dur-0-12) ease;
52
+ }
53
+
54
+ .wb-radio:not(:checked):hover {
55
+ border-color: var(--dsw-alias-label-tertiary);
56
+ }
57
+
58
+ .wb-radio:checked {
59
+ border-color: var(--dsw-alias-brand-primary);
60
+ background-image: radial-gradient(
61
+ circle at center,
62
+ var(--dsw-alias-brand-primary) 0 3px,
63
+ transparent 3px
64
+ );
65
+ }
66
+
67
+ .wb-radio:disabled {
68
+ cursor: default;
69
+ opacity: 0.5;
70
+ }
71
+
72
+ .wb-radio:focus-visible {
73
+ outline: var(--dsw-focus-ring-width, var(--wb-len-2)) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));
74
+ outline-offset: 2px;
75
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode } from '../lib/react.js';
2
+ import './ChoiceGroup.css';
2
3
  export interface ChoiceGroupOption {
3
4
  readonly value: string;
4
5
  readonly label: ReactNode;
@@ -1,4 +1,5 @@
1
1
  import { Fragment, h } from '../lib/react.js';
2
+ import './ChoiceGroup.css';
2
3
  export function ChoiceGroup({ label, name, value, options, disabled, onChange }) {
3
4
  return (h("div", { className: "wb-choiceMenu", role: "radiogroup", "aria-label": label }, options.map((option) => (h(Fragment, { key: option.value },
4
5
  h("label", { className: "wb-choiceOption" },
@@ -0,0 +1,53 @@
1
+
2
+ .wb-longTask {
3
+ padding-top: var(--wb-len-12);
4
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: var(--wb-len-2);
8
+ }
9
+
10
+ .wb-longTaskHead {
11
+ display: flex;
12
+ align-items: center;
13
+ gap: var(--wb-len-6);
14
+ margin: 0;
15
+ }
16
+
17
+ .wb-longTaskLink {
18
+ flex: none;
19
+ display: inline-flex;
20
+ align-items: center;
21
+ gap: var(--wb-len-2);
22
+ text-decoration: none;
23
+ white-space: nowrap;
24
+ }
25
+
26
+ .wb-longTaskHeadline {
27
+ margin: 0;
28
+ font-size: var(--dsw-font-xxs-12-font-size);
29
+ line-height: var(--wb-line-18);
30
+ white-space: pre-wrap;
31
+ overflow-wrap: anywhere;
32
+ color: var(--dsw-alias-label-secondary);
33
+ }
34
+
35
+ .wb-longTaskProblem {
36
+ margin: 0;
37
+ font-size: var(--dsw-font-xxxs-11-font-size);
38
+ line-height: var(--wb-line-16);
39
+ color: var(--dsw-alias-state-error-primary);
40
+ overflow-wrap: anywhere;
41
+ }
42
+
43
+ .wb-longTaskDump {
44
+ margin: var(--wb-len-2) 0 0;
45
+ font-size: var(--dsw-font-xxxs-11-font-size);
46
+ color: var(--dsw-alias-label-tertiary);
47
+ }
48
+
49
+ .wb-longTaskDump pre {
50
+ margin: var(--wb-len-4) 0 0;
51
+ max-height: var(--wb-len-220);
52
+ overflow: auto;
53
+ }
@@ -1,4 +1,5 @@
1
1
  import { type LongTaskStatus } from '../api/long-task.js';
2
+ import './LongTaskRow.css';
2
3
  export interface LongTaskRowLink {
3
4
  readonly href: string;
4
5
  readonly text: string;
@@ -12,5 +13,7 @@ export interface LongTaskRowProps {
12
13
  readonly raw?: string | undefined;
13
14
  readonly stepsTitle?: string | undefined;
14
15
  readonly rawTitle?: string | undefined;
16
+ readonly copyLabel?: string | undefined;
17
+ readonly copiedLabel?: string | undefined;
15
18
  }
16
19
  export declare function LongTaskRow(props: LongTaskRowProps): JSX.Element;
@@ -1,13 +1,15 @@
1
1
  import { longTaskDot } from '../api/long-task.js';
2
- import { Fragment, h } from '../lib/react.js';
3
- import { IconRightUp } from './icons.js';
4
- import { StateDot } from './StateDot.js';
2
+ import { Fragment, h, useState } from '../lib/react.js';
3
+ import { CodeBlock, DisclosureRow, IconCodeOutlineRegular, IconFlatListOutlineRegular, IconRightUpOutlineRegular, StateDot, } from '@deepseek-ai/dsh-client-ui-primitives';
4
+ import './LongTaskRow.css';
5
5
  function RowLink({ href, text }) {
6
- return (h("a", { className: "wb-linkButton wb-longTaskLink", href: href, target: "_blank", rel: "noreferrer noopener" },
6
+ return (h("a", { className: "wb-longTaskLink", href: href, target: "_blank", rel: "noreferrer noopener" },
7
7
  text,
8
- h(IconRightUp, { size: 12 })));
8
+ h(IconRightUpOutlineRegular, { size: 12 })));
9
9
  }
10
10
  export function LongTaskRow(props) {
11
+ const [stepsOpen, setStepsOpen] = useState(false);
12
+ const [rawOpen, setRawOpen] = useState(false);
11
13
  const failed = props.status === 'failed';
12
14
  const problem = props.problem ?? '';
13
15
  const raw = (props.raw ?? '').trim();
@@ -19,10 +21,8 @@ export function LongTaskRow(props) {
19
21
  (props.links ?? []).map((link) => (h(RowLink, { href: link.href, key: `${link.text}@${link.href}`, text: link.text })))),
20
22
  problem === '' ? null : h("p", { className: "wb-longTaskProblem" }, problem),
21
23
  !failed ? null : (h(Fragment, null,
22
- steps.length === 0 || props.stepsTitle === undefined ? null : (h("details", { className: "wb-longTaskDump" },
23
- h("summary", null, props.stepsTitle),
24
- h("pre", null, steps.join('\n')))),
25
- raw === '' || props.rawTitle === undefined ? null : (h("details", { className: "wb-longTaskDump" },
26
- h("summary", null, props.rawTitle),
27
- h("pre", null, raw)))))));
24
+ steps.length === 0 || props.stepsTitle === undefined ? null : (h(DisclosureRow, { className: "wb-longTaskDump", icon: h(IconFlatListOutlineRegular, { size: 14 }), title: props.stepsTitle, open: stepsOpen, expandable: true, expandOnRowClick: true, previewChevron: true, onToggle: () => setStepsOpen(!stepsOpen) },
25
+ h(CodeBlock, { code: steps.join('\n'), className: "wb-longTaskDump", showHeader: props.copyLabel !== undefined, copyLabel: props.copyLabel ?? '', copiedLabel: props.copiedLabel ?? '' }))),
26
+ raw === '' || props.rawTitle === undefined ? null : (h(DisclosureRow, { className: "wb-longTaskDump", icon: h(IconCodeOutlineRegular, { size: 14 }), title: props.rawTitle, open: rawOpen, expandable: true, expandOnRowClick: true, previewChevron: true, onToggle: () => setRawOpen(!rawOpen) },
27
+ h(CodeBlock, { code: raw, className: "wb-longTaskDump", showHeader: props.copyLabel !== undefined, copyLabel: props.copyLabel ?? '', copiedLabel: props.copiedLabel ?? '' })))))));
28
28
  }
@@ -0,0 +1,39 @@
1
+
2
+ .wb-mockStrip {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ gap: var(--wb-len-4);
6
+ padding: var(--wb-len-8) var(--wb-len-12);
7
+ border-bottom: 0.5px solid var(--dsw-alias-border-l2);
8
+ flex: none;
9
+ }
10
+
11
+ .wb-mockNote {
12
+ flex: 1 0 100%;
13
+ font-size: var(--wb-font-10);
14
+ line-height: var(--wb-line-14);
15
+ color: var(--dsw-alias-label-tertiary);
16
+ }
17
+
18
+ .wb-mockChip {
19
+ flex: none;
20
+ padding: var(--wb-len-2) var(--wb-len-7);
21
+ border: 0.5px solid var(--dsw-alias-border-l2);
22
+ border-radius: var(--wb-radius-pill);
23
+ corner-shape: round;
24
+ background: transparent;
25
+ font-size: var(--wb-font-10);
26
+ line-height: var(--wb-line-14);
27
+ color: var(--dsw-alias-label-secondary);
28
+ cursor: pointer;
29
+ }
30
+
31
+ .wb-mockChip:hover {
32
+ color: var(--dsw-alias-label-primary);
33
+ }
34
+
35
+ .wb-mockChipOn {
36
+ border-color: transparent;
37
+ background: var(--dsw-alias-brand-primary);
38
+ color: var(--dsw-alias-label-primary-foreground);
39
+ }
@@ -1,3 +1,4 @@
1
+ import './MockStrip.css';
1
2
  export declare function MockStrip({ mocks, index, onPick, note, real, }: {
2
3
  readonly mocks: readonly {
3
4
  readonly id: string;
@@ -1,4 +1,5 @@
1
1
  import { h } from '../lib/react.js';
2
+ import './MockStrip.css';
2
3
  export function MockStrip({ mocks, index, onPick, note, real, }) {
3
4
  return (h("div", { className: "wb-mockStrip" },
4
5
  h("span", { className: "wb-mockNote" }, note ?? '夹具:只切状态,不发请求'),
@@ -0,0 +1,111 @@
1
+
2
+ .wb-centered.wb-centeredCompact {
3
+ flex: none;
4
+ min-height: 0;
5
+ gap: var(--wb-len-8);
6
+ padding: var(--wb-len-20) var(--wb-len-16);
7
+ }
8
+
9
+ .wb-centered.wb-centeredCompact .wb-centeredHero {
10
+ margin-bottom: var(--wb-len-4);
11
+ }
12
+
13
+ .wb-skeleton {
14
+ display: flex;
15
+ flex-direction: column;
16
+ }
17
+
18
+ .wb-skeletonRow {
19
+ display: flex;
20
+ flex-direction: column;
21
+ gap: var(--wb-len-8);
22
+ padding: var(--wb-len-8);
23
+ border-radius: var(--dsw-radius-md);
24
+ }
25
+
26
+ .wb-skeletonRow + .wb-skeletonRow::before {
27
+ content: '';
28
+ align-self: stretch;
29
+ height: var(--wb-len-0-5);
30
+ margin: 0 var(--wb-len-8) var(--wb-len-neg-0-5);
31
+ background: var(--dsw-alias-border-l2);
32
+ }
33
+
34
+ .wb-skeletonBar {
35
+ display: block;
36
+ height: var(--wb-len-13);
37
+ border-radius: var(--dsw-radius-xs);
38
+ background: var(--dsw-alias-bg-skeleton);
39
+ animation: wb-skeleton-pulse var(--wb-dur-1-4) var(--ds-ease-in-out) infinite;
40
+ }
41
+
42
+ .wb-skeletonBarTitle {
43
+ width: 62%;
44
+ }
45
+
46
+ .wb-skeletonBarMeta {
47
+ width: 32%;
48
+ height: var(--wb-len-10);
49
+ }
50
+
51
+ .wb-skeletonRow:nth-child(2n) .wb-skeletonBarTitle {
52
+ width: 74%;
53
+ }
54
+
55
+ .wb-skeletonRow:nth-child(3n) .wb-skeletonBarTitle {
56
+ width: 52%;
57
+ }
58
+
59
+ @keyframes wb-skeleton-pulse {
60
+ 50% {
61
+ opacity: 0.45;
62
+ }
63
+ }
64
+
65
+ .wb-centered {
66
+ box-sizing: border-box;
67
+ display: flex;
68
+ flex-direction: column;
69
+ justify-content: center;
70
+ align-items: center;
71
+ gap: var(--wb-len-14);
72
+ flex: 1;
73
+ min-height: var(--wb-len-240);
74
+ padding: 0 var(--wb-len-24) var(--wb-len-24);
75
+ text-align: center;
76
+ }
77
+
78
+ .wb-centeredHero {
79
+ display: flex;
80
+ margin-bottom: var(--wb-len-16);
81
+ color: var(--dsw-alias-label-dimmed);
82
+ }
83
+
84
+ .wb-centeredTitle {
85
+ font-size: var(--dsw-font-s-14-font-size);
86
+ line-height: var(--wb-line-22);
87
+ color: var(--dsw-alias-label-primary);
88
+ }
89
+
90
+ .wb-centeredHint {
91
+ max-width: var(--wb-len-300);
92
+ font-size: var(--dsw-font-xxs-12-font-size);
93
+ line-height: var(--wb-line-18);
94
+ color: var(--dsw-alias-label-tertiary);
95
+ }
96
+
97
+ .wb-centeredDetail {
98
+ max-width: var(--wb-len-320);
99
+ font-family: var(--ds-font-family-code, monospace);
100
+ font-size: var(--dsw-font-xxxs-11-font-size);
101
+ line-height: var(--wb-line-16);
102
+ color: var(--dsw-alias-label-dimmed);
103
+ word-break: break-all;
104
+ }
105
+
106
+ .wb-centeredAction {
107
+ display: flex;
108
+ justify-content: center;
109
+ gap: var(--wb-len-8);
110
+ margin-top: var(--wb-len-2);
111
+ }
@@ -1,10 +1,11 @@
1
1
  import type { ReactNode } from 'react';
2
+ import './ResourceStates.css';
2
3
  export declare function SkeletonRows({ rows }: {
3
4
  rows?: number;
4
5
  }): JSX.Element;
5
6
  export interface CenteredStateProps {
6
7
  icon: ReactNode;
7
- title: string;
8
+ title: ReactNode;
8
9
  hint?: string;
9
10
  detail?: string;
10
11
  action?: ReactNode;
@@ -1,4 +1,5 @@
1
1
  import { h } from '../lib/react.js';
2
+ import './ResourceStates.css';
2
3
  export function SkeletonRows({ rows = 4 }) {
3
4
  return (h("div", { className: "wb-skeleton", "aria-hidden": "true" }, Array.from({ length: rows }, (_, index) => (h("span", { key: index, className: "wb-skeletonRow" },
4
5
  h("span", { className: "wb-skeletonBar wb-skeletonBarTitle" }),
@@ -0,0 +1,7 @@
1
+
2
+ .wb-formActions {
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: flex-end;
6
+ gap: var(--wb-len-8);
7
+ }
@@ -1,3 +1,4 @@
1
+ import './SaveBar.css';
1
2
  export interface SaveBarProps {
2
3
  readonly busy: boolean;
3
4
  readonly disabled?: boolean | undefined;
@@ -1,6 +1,8 @@
1
+ import { Button } from '@deepseek-ai/dsh-client-ui-primitives';
1
2
  import { h } from '../lib/react.js';
3
+ import './SaveBar.css';
2
4
  export function SaveBar({ busy, disabled, labels, onCancel, onSave }) {
3
5
  return (h("div", { className: "wb-formActions" },
4
- h("button", { type: "button", className: "wb-linkButton", onClick: onCancel, disabled: busy }, labels.cancel),
5
- h("button", { type: "button", className: "wb-primaryButton", onClick: onSave, disabled: busy || disabled === true }, busy ? labels.saving : labels.save)));
6
+ h(Button, { type: "button", size: "sm", variant: "ghost", onClick: onCancel, disabled: busy }, labels.cancel),
7
+ h(Button, { type: "button", size: "sm", variant: "primary", onClick: onSave, disabled: busy || disabled === true }, busy ? labels.saving : labels.save)));
6
8
  }
@@ -0,0 +1,22 @@
1
+ .wb-textField {
2
+ box-sizing: border-box;
3
+ border: 0.5px solid var(--dsw-alias-border-l4);
4
+ border-radius: var(--dsw-radius-md);
5
+ background: var(--dsw-alias-bg-layer-3);
6
+ font: var(--dsw-font-xs-13);
7
+ color: var(--dsw-alias-label-primary);
8
+ outline: none;
9
+ }
10
+
11
+ .wb-textField:focus {
12
+ border-color: var(--dsw-alias-state-business-primary);
13
+ box-shadow: inset 0 0 0 0.5px var(--dsw-alias-state-business-primary);
14
+ }
15
+
16
+ .wb-textField[aria-invalid='true'] {
17
+ border-color: var(--dsw-alias-state-error-primary);
18
+ }
19
+
20
+ .wb-textField[aria-invalid='true']:focus {
21
+ box-shadow: inset 0 0 0 0.5px var(--dsw-alias-state-error-primary);
22
+ }
@@ -0,0 +1,6 @@
1
+ import type { InputHTMLAttributes } from 'react';
2
+ import './TextField.css';
3
+ export interface TextFieldProps extends InputHTMLAttributes<HTMLInputElement> {
4
+ readonly invalid?: boolean;
5
+ }
6
+ export declare function TextField({ invalid, className, ...rest }: TextFieldProps): JSX.Element;
@@ -0,0 +1,5 @@
1
+ import './TextField.css';
2
+ import { h } from '../lib/react.js';
3
+ export function TextField({ invalid = false, className, ...rest }) {
4
+ return (h("input", { ...rest, className: className === undefined ? 'wb-textField' : `wb-textField ${className}`, "aria-invalid": invalid || undefined }));
5
+ }
@@ -1,18 +1,6 @@
1
1
  export interface IconProps {
2
2
  size?: number;
3
3
  }
4
- export declare function IconPanelLeft({ size }: IconProps): JSX.Element;
5
- export declare function IconFolder({ size }: IconProps): JSX.Element;
6
- export declare function IconFolderOpen({ size }: IconProps): JSX.Element;
7
- export declare function IconChevronDown({ size }: IconProps): JSX.Element;
8
- export declare function IconPlus({ size }: IconProps): JSX.Element;
9
- export declare function IconEllipsis({ size }: IconProps): JSX.Element;
10
- export declare function IconSettings({ size }: IconProps): JSX.Element;
11
- export declare function IconPin({ size }: IconProps): JSX.Element;
12
- export declare function IconCheck({ size }: IconProps): JSX.Element;
13
- export declare function IconNewChat({ size }: IconProps): JSX.Element;
14
- export declare function IconRefresh({ size }: IconProps): JSX.Element;
15
- export declare function IconRightUp({ size }: IconProps): JSX.Element;
16
4
  export declare function IconConversation({ size }: IconProps): JSX.Element;
17
5
  export declare function IconBrandMark({ size }: IconProps): JSX.Element;
18
6
  export declare function IconModules({ size }: IconProps): JSX.Element;