@dsh-workbench/shared 0.2.12 → 0.2.14

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 (53) hide show
  1. package/dist/components/ChoiceGroup.css +53 -3
  2. package/dist/components/ChoiceGroup.d.ts +5 -0
  3. package/dist/components/ChoiceGroup.js +15 -5
  4. package/dist/components/FormActions.css +13 -0
  5. package/dist/components/FormActions.d.ts +15 -0
  6. package/dist/components/FormActions.js +38 -0
  7. package/dist/components/FormRows.css +69 -0
  8. package/dist/components/FormRows.d.ts +14 -0
  9. package/dist/components/FormRows.js +11 -0
  10. package/dist/components/SaveBar.d.ts +0 -1
  11. package/dist/components/SaveBar.js +13 -5
  12. package/dist/components/SelectField.css +12 -4
  13. package/dist/components/SelectField.d.ts +1 -0
  14. package/dist/components/SelectField.js +9 -7
  15. package/dist/components/Spinner.css +6 -0
  16. package/dist/components/Spinner.d.ts +6 -0
  17. package/dist/components/Spinner.js +7 -0
  18. package/dist/components/TextField.css +2 -2
  19. package/dist/host.d.ts +3 -3
  20. package/dist/host.js +3 -3
  21. package/dist/i18n/en.js +9 -0
  22. package/dist/i18n/index.d.ts +10 -1
  23. package/dist/i18n/zh.d.ts +9 -0
  24. package/dist/i18n/zh.js +9 -0
  25. package/dist/index.d.ts +8 -4
  26. package/dist/index.js +8 -4
  27. package/dist/lib/form-problem.d.ts +2 -0
  28. package/dist/lib/form-problem.js +20 -0
  29. package/package.json +2 -1
  30. package/src/components/ChoiceGroup.css +53 -3
  31. package/src/components/ChoiceGroup.test.tsx +88 -0
  32. package/src/components/ChoiceGroup.tsx +70 -28
  33. package/src/components/FormActions.css +13 -0
  34. package/src/components/FormActions.test.tsx +157 -0
  35. package/src/components/FormActions.tsx +75 -0
  36. package/src/components/FormRows.css +69 -0
  37. package/src/components/FormRows.test.tsx +138 -0
  38. package/src/components/FormRows.tsx +39 -0
  39. package/src/components/SaveBar.tsx +14 -18
  40. package/src/components/SelectField.css +12 -4
  41. package/src/components/SelectField.test.tsx +20 -2
  42. package/src/components/SelectField.tsx +11 -3
  43. package/src/components/Spinner.css +6 -0
  44. package/src/components/Spinner.test.tsx +35 -0
  45. package/src/components/Spinner.tsx +19 -0
  46. package/src/components/TextField.css +2 -2
  47. package/src/host.ts +3 -3
  48. package/src/i18n/en.ts +9 -0
  49. package/src/i18n/zh.ts +9 -0
  50. package/src/index.ts +8 -4
  51. package/src/lib/form-problem.test.ts +76 -0
  52. package/src/lib/form-problem.ts +22 -0
  53. package/src/components/SaveBar.css +0 -7
@@ -47,6 +47,15 @@ export declare const dictionaries: {
47
47
  readonly 'status.completed': "已完成";
48
48
  readonly 'status.subagentsRunning.one': "{n} 个子代理运行中";
49
49
  readonly 'status.subagentsRunning.other': "{n} 个子代理运行中";
50
+ readonly 'project.attention.warning.one': "1 个会话在等你点头";
51
+ readonly 'project.attention.warning.other': "{n} 个会话在等你点头";
52
+ readonly 'project.attention.running.one': "1 个会话在跑";
53
+ readonly 'project.attention.running.other': "{n} 个会话在跑";
54
+ readonly 'project.attention.done.one': "1 个会话跑完没看";
55
+ readonly 'project.attention.done.other': "{n} 个会话跑完没看";
56
+ readonly 'project.attention.state.warning': "待审批";
57
+ readonly 'project.attention.state.running': "在跑";
58
+ readonly 'project.attention.state.done': "新消息";
50
59
  readonly 'hover.copied': "已复制";
51
60
  readonly 'time.now': "刚刚";
52
61
  readonly 'time.minutes': "{n} 分钟前";
@@ -400,7 +409,7 @@ export declare const dictionaries: {
400
409
  readonly 'configSync.emptyProviders': "工作台还没有任何模型供应商 —— 去「配置同步」从某个 profile 把 llm- 那几行搬过来,或自己去「模型」里配。";
401
410
  readonly 'configSync.failed': "同步没成功,再试一次。";
402
411
  };
403
- en: Record<"time.now" | "time.ago" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.dep.failed" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.swapSlow" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.localMark" | "panels.market.localHint" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.moduleOutdated" | "panels.market.moduleRefused" | "panels.market.moduleRefusedDetail" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.workbenchName" | "panels.market.workbenchLocal" | "panels.market.pluginKeptInUse" | "panels.market.pluginKeptUnsure" | "panels.market.pluginKeptHeld" | "panels.market.pluginKeptUnnamed" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.classifying" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed", string>;
412
+ en: Record<"time.now" | "time.ago" | "time.minutes" | "time.hours" | "time.days" | "blocker.retry" | "blocker.copy" | "blocker.unknown.title" | "blocker.login.go" | "blocker.login.titleGeneric" | "blocker.login.title" | "blocker.login.manual" | "blocker.login.hint" | "blocker.forbidden.open" | "blocker.forbidden.titleGeneric" | "blocker.forbidden.title" | "blocker.forbidden.hint" | "blocker.timeout.hint" | "blocker.exec.hint" | "blocker.fix.install" | "blocker.fix.update" | "blocker.market.open" | "env.unit.failed" | "env.unit.failedHint" | "env.unit.missingPlugin" | "env.unit.hint" | "env.unit.missingCommands" | "env.unit.missingCommandsHint" | "env.unit.unchecked" | "env.unit.uncheckedHint" | "brand.name" | "toggle.open" | "toggle.collapse" | "project.label" | "workspace.section" | "project.none" | "project.empty" | "project.add" | "project.add.busy" | "project.add.failed" | "project.search.label" | "project.search.placeholder" | "project.search.empty" | "project.group.workspaces" | "project.group.defaultWorkspace" | "project.group.workshop" | "project.rename.row" | "project.rename.current" | "project.rename.title" | "project.rename.description" | "project.rename.field" | "project.rename.placeholder" | "project.rename.hint" | "project.rename.save" | "project.rename.saving" | "project.rename.cancel" | "project.rename.failed" | "session.new" | "session.new.label" | "session.empty" | "session.noProject" | "session.list.label" | "session.copy" | "session.pinned" | "session.actions" | "status.idle" | "status.running" | "status.waitingApproval" | "status.planReview" | "status.waitingAnswer" | "status.compact.approval" | "status.compact.planReview" | "status.compact.answer" | "status.completed" | "status.subagentsRunning.one" | "status.subagentsRunning.other" | "project.attention.warning.one" | "project.attention.warning.other" | "project.attention.running.one" | "project.attention.running.other" | "project.attention.done.one" | "project.attention.done.other" | "project.attention.state.warning" | "project.attention.state.running" | "project.attention.state.done" | "hover.copied" | "time.short.minutes" | "time.short.hours" | "time.short.days" | "time.short.months" | "time.short.years" | "panels.title" | "panels.groupBoardless" | "panels.groupPlugins" | "panels.market.defaultHint" | "panels.market.defaultLabel" | "panels.market.defaultLocked" | "panels.followAll" | "panels.followAllConfirmTitle" | "panels.followAllConfirmDetail" | "panels.followAllConfirmAck" | "panels.followAllConfirmYes" | "panels.followAllConfirmNo" | "panels.enabled" | "panels.disabled" | "panels.choose" | "panels.buildModule" | "panels.failed" | "panels.dragHint" | "panels.unknownStep" | "panels.labelWithHint" | "panels.dep.failed" | "panels.dep.missingPlugin" | "panels.dep.missingCommands" | "panels.dep.unchecked" | "panels.tab.modules" | "panels.tab.market" | "panels.browseMarket" | "panels.noneInstalled" | "panels.noneInstalledHint" | "panels.market.installed" | "panels.market.notActive" | "panels.market.notUsable" | "panels.market.broken" | "panels.market.hasNew" | "panels.market.missing" | "panels.market.unchecked" | "panels.market.checking" | "panels.market.sectionInstalled" | "panels.market.sectionPending" | "panels.market.sectionShared" | "panels.market.sharedUsedBy" | "panels.market.listSeparator" | "panels.market.sharedMissing" | "panels.market.sharedOutdated" | "panels.market.sharedUnsatisfied" | "panels.market.sharedOk" | "panels.market.versionArrow" | "panels.market.lead" | "panels.market.install" | "panels.market.update" | "panels.market.swapSlow" | "panels.market.uninstall" | "panels.market.uninstallLabel" | "panels.market.installing" | "panels.market.updating" | "panels.market.uninstalling" | "panels.market.confirmUninstallTitle" | "panels.market.confirmUninstallDetail" | "panels.market.confirmUninstallAck" | "panels.market.confirmYes" | "panels.market.confirmNo" | "panels.market.failed" | "panels.market.needEnv" | "panels.market.needCommands" | "panels.market.localMark" | "panels.market.localHint" | "panels.market.noSource" | "panels.market.badSource" | "panels.market.empty" | "panels.market.sectionPlugins" | "panels.market.moduleOutdated" | "panels.market.moduleRefused" | "panels.market.moduleRefusedDetail" | "panels.market.moduleRestartHint" | "panels.market.pendingRestart" | "panels.market.workbenchName" | "panels.market.workbenchLocal" | "panels.market.pluginKeptInUse" | "panels.market.pluginKeptUnsure" | "panels.market.pluginKeptHeld" | "panels.market.pluginKeptUnnamed" | "panels.market.pluginBroken" | "panels.market.restartNeeded" | "panels.market.foot" | "panels.market.recheck" | "panels.market.checkUpdates" | "panels.market.checkedAt" | "panels.market.justNow" | "panels.market.minutesAgo" | "panels.market.hoursAgo" | "panels.market.add.description" | "panels.market.add.specPlaceholder" | "panels.market.add.guideToggle" | "panels.market.add.guideHide" | "panels.market.add.guideIdTitle" | "panels.market.add.guideIdExample" | "panels.market.add.guideIdHint" | "panels.market.add.guideGitTitle" | "panels.market.add.guideGitExample" | "panels.market.add.guideGitHint" | "panels.market.add.guidePathTitle" | "panels.market.add.guidePathExample" | "panels.market.add.guidePathHint" | "panels.market.add.guideExampleLabel" | "panels.market.add.guideFill" | "panels.market.add.guideSafety" | "panels.market.add.registryLegend" | "panels.market.add.registryOfficial" | "panels.market.add.registryMirror" | "panels.market.add.registryWithHost" | "panels.market.add.registryToggle" | "panels.market.add.installVersion" | "panels.market.add.registryDefault" | "panels.market.add.registryCustom" | "panels.market.add.registryCustomPlaceholder" | "panels.market.add.registryCustomHint" | "panels.market.add.registryCustomInvalid" | "panels.market.add.run" | "panels.market.add.edit" | "panels.market.add.changeRegistry" | "panels.market.add.installingTitle" | "panels.market.add.installedTitle" | "panels.market.add.failedTitle" | "panels.market.add.cancelledTitle" | "panels.market.add.failureNetworkHost" | "panels.market.add.problemInvalid" | "panels.market.add.problemInstalled" | "panels.market.add.problemNotFound" | "panels.market.add.problemNotPackage" | "panels.market.add.problemNotBundle" | "panels.market.add.problemNotWorkbenchModule" | "panels.market.add.problemNotModuleOrPlugin" | "panels.market.add.failureNotModuleOrPlugin" | "panels.market.add.installedPlugin" | "panels.market.add.pluginPreview" | "panels.market.add.pluginAlias" | "panels.market.add.problemNetwork" | "panels.market.add.problemUnknown" | "panels.market.add.failureNetwork" | "panels.market.add.failureNotFound" | "panels.market.add.failureNoMatchingVersion" | "panels.market.add.failureDiskFull" | "panels.market.add.failurePermission" | "panels.market.add.failureBuildBlocked" | "panels.market.add.failureIntegrity" | "panels.market.add.failureTimeout" | "panels.market.add.failurePnpmMissing" | "panels.market.add.failureInstalled" | "panels.market.add.failureGeneric" | "panels.market.add.approveTitle" | "panels.market.add.approveCaution" | "panels.market.add.approveRun" | "panels.market.add.restart" | "panels.market.add.tookEffect" | "panels.market.add.details" | "panels.market.add.open" | "panels.market.add.title" | "panels.market.add.intro" | "panels.market.add.specLabel" | "panels.market.add.specHint" | "panels.market.add.exampleTitle" | "panels.market.add.exampleFill" | "panels.market.add.registryLabel" | "panels.market.add.registryProfile" | "panels.market.add.registryPnpm" | "panels.market.add.check" | "panels.market.add.checking" | "panels.market.add.classifying" | "panels.market.add.change" | "panels.market.add.previewTitle" | "panels.market.add.fieldName" | "panels.market.add.fieldVersion" | "panels.market.add.fieldDescription" | "panels.market.add.fieldSource" | "panels.market.add.install" | "panels.market.add.installing" | "panels.market.add.cancel" | "panels.market.add.close" | "panels.market.add.retry" | "panels.market.add.changeSource" | "panels.market.add.approveBuilds" | "panels.market.add.approveHint" | "panels.market.add.doneApplied" | "panels.market.add.doneRestart" | "panels.market.add.restartWhy" | "panels.market.add.restartWhy.no-hmr" | "panels.market.add.restartWhy.package-moved" | "panels.market.add.restartWhy.host-module" | "panels.market.add.restartWhy.unmanaged-plugin" | "panels.market.add.restartWhy.module-comparison" | "panels.market.add.cancelled" | "panels.market.add.failed" | "panels.market.add.removed" | "panels.market.add.supplyPending" | "panels.market.add.supplyFailed" | "panels.market.add.notModule" | "panels.market.add.removedRestart" | "panels.market.add.remove" | "panels.market.add.problem.invalidSpec" | "panels.market.add.problem.alreadyInstalled" | "panels.market.add.problem.notFound" | "panels.market.add.problem.notAPackage" | "panels.market.add.problem.notABundle" | "panels.market.add.problem.network" | "panels.market.add.problem.unknown" | "panels.market.add.reason.invalidSpec" | "panels.market.add.reason.incompatible" | "panels.market.add.reason.notBundle" | "panels.market.add.reason.notRemovable" | "panels.market.add.reason.bundleInUse" | "panels.market.add.reason.stopProfile" | "panels.market.add.reason.staleApproval" | "panels.market.add.reason.operationError" | "panels.market.add.reason.buildBlocked" | "panels.market.add.reason.pnpmMissing" | "panels.market.add.reason.noMatchingVersion" | "panels.market.add.reason.diskFull" | "panels.market.add.reason.permission" | "panels.market.add.reason.integrity" | "panels.market.add.reason.timeout" | "panels.market.add.reason.network" | "panels.market.add.reason.notFound" | "panels.market.add.reason.unknown" | "blocker.fix.running" | "blocker.fix.failed" | "blocker.retry.running" | "panels.reading" | "panels.cardBroken" | "panels.cardRetry" | "panels.empty" | "panels.emptyHint" | "env.title" | "env.checking" | "env.installing" | "env.failed" | "env.elapsed" | "env.stepFailed.install" | "env.stepFailed.path" | "env.stepFailed.shell" | "env.bridge.ok" | "env.bridge.short" | "env.bridge.why" | "env.bridge.daemon" | "env.bridge.extension" | "env.bridge.extensionLink" | "env.bridge.profile" | "env.bridge.stale" | "env.bridge.unknown" | "env.fix.title" | "env.fix.why" | "env.fix.whyPath" | "env.fix.whyShell" | "env.fix.step" | "env.fix.stepPath" | "env.fix.stepShell" | "env.fix.permission" | "env.fix.network" | "env.fix.details" | "env.retry" | "env.copyCommand" | "env.copied" | "env.step.opencli" | "env.step.codingPlugin" | "env.step.bridge" | "env.step.warm" | "env.warm.done" | "env.warm.short" | "rightbar.label" | "rightbar.expand" | "rightbar.collapse" | "rightbar.column.label" | "rightbar.column.workbench" | "rightbar.column.dsh" | "rightbar.refresh" | "rightbar.refreshing" | "rightbar.updatedAt" | "rightbar.noProject" | "rightbar.openPlatform" | "coding.notARepo.title" | "error.unknown" | "board.title" | "panel.conversation" | "panels.label" | "configSync.nav" | "configSync.lead" | "configSync.source" | "configSync.sourceBroken" | "configSync.sourceRows" | "configSync.sourceDead" | "configSync.refresh" | "configSync.loading" | "configSync.readHint" | "configSync.tag.new" | "configSync.tag.differs" | "configSync.conflictNote" | "configSync.code.lang" | "configSync.code.copy" | "configSync.code.copied" | "configSync.code.wrap" | "configSync.code.unwrap" | "configSync.code.collapse" | "configSync.code.collapseAria" | "configSync.code.expandAria" | "configSync.code.expand" | "configSync.missing" | "configSync.apply" | "configSync.applyNone" | "configSync.applying" | "configSync.applied" | "configSync.appliedIds" | "configSync.skippedIds" | "configSync.nothing" | "configSync.unreadable" | "configSync.noSource" | "configSync.emptyProviders" | "configSync.failed", string>;
404
413
  };
405
414
  export type { WorkbenchMessages };
406
415
  export interface Dictionaries {
package/dist/i18n/zh.d.ts CHANGED
@@ -45,6 +45,15 @@ export declare const zh: {
45
45
  readonly 'status.completed': "已完成";
46
46
  readonly 'status.subagentsRunning.one': "{n} 个子代理运行中";
47
47
  readonly 'status.subagentsRunning.other': "{n} 个子代理运行中";
48
+ readonly 'project.attention.warning.one': "1 个会话在等你点头";
49
+ readonly 'project.attention.warning.other': "{n} 个会话在等你点头";
50
+ readonly 'project.attention.running.one': "1 个会话在跑";
51
+ readonly 'project.attention.running.other': "{n} 个会话在跑";
52
+ readonly 'project.attention.done.one': "1 个会话跑完没看";
53
+ readonly 'project.attention.done.other': "{n} 个会话跑完没看";
54
+ readonly 'project.attention.state.warning': "待审批";
55
+ readonly 'project.attention.state.running': "在跑";
56
+ readonly 'project.attention.state.done': "新消息";
48
57
  readonly 'hover.copied': "已复制";
49
58
  readonly 'time.now': "刚刚";
50
59
  readonly 'time.minutes': "{n} 分钟前";
package/dist/i18n/zh.js CHANGED
@@ -45,6 +45,15 @@ export const zh = {
45
45
  'status.completed': '已完成',
46
46
  'status.subagentsRunning.one': '{n} 个子代理运行中',
47
47
  'status.subagentsRunning.other': '{n} 个子代理运行中',
48
+ 'project.attention.warning.one': '1 个会话在等你点头',
49
+ 'project.attention.warning.other': '{n} 个会话在等你点头',
50
+ 'project.attention.running.one': '1 个会话在跑',
51
+ 'project.attention.running.other': '{n} 个会话在跑',
52
+ 'project.attention.done.one': '1 个会话跑完没看',
53
+ 'project.attention.done.other': '{n} 个会话跑完没看',
54
+ 'project.attention.state.warning': '待审批',
55
+ 'project.attention.state.running': '在跑',
56
+ 'project.attention.state.done': '新消息',
48
57
  'hover.copied': '已复制',
49
58
  'time.now': '刚刚',
50
59
  'time.minutes': '{n} 分钟前',
package/dist/index.d.ts CHANGED
@@ -7,8 +7,8 @@ export * from './api/facts.js';
7
7
  export * from './api/host-write.js';
8
8
  export * from './api/long-task.js';
9
9
  export * from './api/unit-board.js';
10
- export * from './api/unit.js';
11
10
  export * from './api/unit-declaration.js';
11
+ export * from './api/unit.js';
12
12
  export * from './api/workbench-client.js';
13
13
  export * from './api/workbench-contract.js';
14
14
  export * from './components/Activity.js';
@@ -19,18 +19,21 @@ export * from './components/CardAnchor.js';
19
19
  export * from './components/CardBoundary.js';
20
20
  export * from './components/CardHead.js';
21
21
  export * from './components/ChoiceGroup.js';
22
+ export * from './components/Field.js';
23
+ export * from './components/FormActions.js';
24
+ export * from './components/FormRows.js';
25
+ export * from './components/Link.js';
22
26
  export * from './components/LongTaskRow.js';
23
27
  export * from './components/Note.js';
24
28
  export * from './components/ResourceStates.js';
25
29
  export * from './components/Rows.js';
26
30
  export * from './components/SaveBar.js';
27
- export * from './components/SettingsSection.js';
28
31
  export * from './components/SelectField.js';
32
+ export * from './components/SettingsSection.js';
33
+ export * from './components/Spinner.js';
29
34
  export * from './components/Stack.js';
30
35
  export * from './components/StateBlock.js';
31
36
  export * from './components/TextField.js';
32
- export * from './components/Field.js';
33
- export * from './components/Link.js';
34
37
  export * from './components/board-module.js';
35
38
  export * from './components/icons.js';
36
39
  export * from './config/constants.js';
@@ -41,6 +44,7 @@ export * from './i18n/merge.js';
41
44
  export * from './i18n/zh.js';
42
45
  export * from './lib/blocker-action.js';
43
46
  export * from './lib/busy.js';
47
+ export * from './lib/form-problem.js';
44
48
  export * from './lib/panel-state.js';
45
49
  export * from './lib/react.js';
46
50
  export * from './lib/text.js';
package/dist/index.js CHANGED
@@ -7,8 +7,8 @@ export * from './api/facts.js';
7
7
  export * from './api/host-write.js';
8
8
  export * from './api/long-task.js';
9
9
  export * from './api/unit-board.js';
10
- export * from './api/unit.js';
11
10
  export * from './api/unit-declaration.js';
11
+ export * from './api/unit.js';
12
12
  export * from './api/workbench-client.js';
13
13
  export * from './api/workbench-contract.js';
14
14
  export * from './components/Activity.js';
@@ -19,18 +19,21 @@ export * from './components/CardAnchor.js';
19
19
  export * from './components/CardBoundary.js';
20
20
  export * from './components/CardHead.js';
21
21
  export * from './components/ChoiceGroup.js';
22
+ export * from './components/Field.js';
23
+ export * from './components/FormActions.js';
24
+ export * from './components/FormRows.js';
25
+ export * from './components/Link.js';
22
26
  export * from './components/LongTaskRow.js';
23
27
  export * from './components/Note.js';
24
28
  export * from './components/ResourceStates.js';
25
29
  export * from './components/Rows.js';
26
30
  export * from './components/SaveBar.js';
27
- export * from './components/SettingsSection.js';
28
31
  export * from './components/SelectField.js';
32
+ export * from './components/SettingsSection.js';
33
+ export * from './components/Spinner.js';
29
34
  export * from './components/Stack.js';
30
35
  export * from './components/StateBlock.js';
31
36
  export * from './components/TextField.js';
32
- export * from './components/Field.js';
33
- export * from './components/Link.js';
34
37
  export * from './components/board-module.js';
35
38
  export * from './components/icons.js';
36
39
  export * from './config/constants.js';
@@ -41,6 +44,7 @@ export * from './i18n/merge.js';
41
44
  export * from './i18n/zh.js';
42
45
  export * from './lib/blocker-action.js';
43
46
  export * from './lib/busy.js';
47
+ export * from './lib/form-problem.js';
44
48
  export * from './lib/panel-state.js';
45
49
  export * from './lib/react.js';
46
50
  export * from './lib/text.js';
@@ -0,0 +1,2 @@
1
+ export declare function firstProblemOf(root: ParentNode): Element | null;
2
+ export declare function revealFirstProblem(root: ParentNode): boolean;
@@ -0,0 +1,20 @@
1
+ const PROBLEM_SELECTOR = '[data-wb-problem]';
2
+ const FOCUSABLE_SELECTOR = [
3
+ 'input:not([disabled])',
4
+ 'select:not([disabled])',
5
+ 'textarea:not([disabled])',
6
+ 'button:not([disabled])',
7
+ 'a[href]',
8
+ '[tabindex]:not([tabindex="-1"])',
9
+ ].join(', ');
10
+ export function firstProblemOf(root) {
11
+ return root.querySelector(PROBLEM_SELECTOR);
12
+ }
13
+ export function revealFirstProblem(root) {
14
+ const problem = firstProblemOf(root);
15
+ if (problem === null)
16
+ return false;
17
+ problem.scrollIntoView?.({ block: 'nearest' });
18
+ problem.querySelector(FOCUSABLE_SELECTOR)?.focus?.();
19
+ return true;
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/shared",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "工作台与模块共享的纯代码与契约类型:类型、纯逻辑、哑组件、平台解析。宿主侧的东西从 /host 进(不影响浏览器产物)。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,6 +43,7 @@
43
43
  "typecheck": "tsc --noEmit",
44
44
  "test": "vitest run",
45
45
  "coverage": "vitest run --coverage",
46
+ "barrels": "node scripts/barrels.mjs",
46
47
  "selfcheck": "node scripts/check-state.mjs",
47
48
  "arch:report": "arch-guard --report-only",
48
49
  "arch": "arch-guard"
@@ -3,10 +3,13 @@
3
3
  display: flex;
4
4
  flex-direction: column;
5
5
  gap: var(--wb-len-2);
6
+ background: transparent;
7
+ }
8
+
9
+ .wb-choiceMenu[data-variant='boxed'] {
6
10
  padding: var(--wb-len-4);
7
11
  border: 0.5px solid var(--dsw-alias-border-l3);
8
12
  border-radius: var(--dsw-radius-md);
9
- background: transparent;
10
13
  }
11
14
 
12
15
  .wb-choiceOption {
@@ -14,8 +17,8 @@
14
17
  display: flex;
15
18
  align-items: center;
16
19
  gap: var(--wb-len-6);
17
- min-height: var(--wb-len-30);
18
- padding: var(--wb-len-6) var(--wb-len-8);
20
+ min-height: var(--wb-len-28);
21
+ padding: var(--wb-len-4) var(--wb-len-8);
19
22
  border-radius: var(--dsw-radius-md);
20
23
  cursor: pointer;
21
24
  font-size: var(--dsw-font-xs-13-font-size);
@@ -87,12 +90,59 @@
87
90
 
88
91
  .wb-choiceLabel {
89
92
  flex: 1;
93
+ min-width: 0;
94
+ display: flex;
95
+ flex-direction: column;
96
+ overflow: hidden;
97
+ }
98
+
99
+ .wb-choiceLabelText {
100
+ overflow: hidden;
101
+ text-overflow: ellipsis;
102
+ white-space: nowrap;
103
+ }
104
+
105
+ .wb-choiceLabel:has(.wb-choiceDescription) .wb-choiceLabelText {
106
+ overflow: visible;
107
+ white-space: normal;
108
+ overflow-wrap: anywhere;
109
+ }
110
+
111
+ .wb-choiceDescription {
112
+ font-size: var(--dsw-font-xxs-12-font-size);
113
+ line-height: var(--wb-line-18);
114
+ color: var(--dsw-alias-label-tertiary);
115
+ overflow-wrap: anywhere;
116
+ }
117
+
118
+ .wb-choiceLoading {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: var(--wb-len-6);
122
+ min-height: var(--wb-len-28);
123
+ padding: var(--wb-len-4) var(--wb-len-8);
124
+ font-size: var(--dsw-font-xs-13-font-size);
125
+ line-height: var(--wb-line-20);
126
+ color: var(--dsw-alias-label-secondary);
127
+ }
128
+
129
+ .wb-choiceLoadingText {
90
130
  min-width: 0;
91
131
  overflow: hidden;
92
132
  text-overflow: ellipsis;
93
133
  white-space: nowrap;
94
134
  }
95
135
 
136
+ .wb-choiceEmpty {
137
+ display: flex;
138
+ align-items: center;
139
+ min-height: var(--wb-len-28);
140
+ padding: var(--wb-len-4) var(--wb-len-8);
141
+ font-size: var(--dsw-font-xs-13-font-size);
142
+ line-height: var(--wb-line-20);
143
+ color: var(--dsw-alias-label-tertiary);
144
+ }
145
+
96
146
  .wb-radio {
97
147
  appearance: none;
98
148
  -webkit-appearance: none;
@@ -195,6 +195,94 @@ describe('ChoiceGroup:单选照旧,多选是新加的那条路', () => {
195
195
  expect(inputs.every((one) => one.props['disabled'] === true)).toBe(true);
196
196
  });
197
197
 
198
+ it('★ loading:不画选项,画一行 Spinner + loadingText', () => {
199
+ const element = ChoiceGroup({
200
+ label: '环境',
201
+ name: 'env',
202
+ value: '',
203
+ options: OPTIONS,
204
+ loading: true,
205
+ loadingText: '正在读环境…',
206
+ onChange: () => {},
207
+ });
208
+ const tree = treeOf(element);
209
+ const loading = tree.find((one) => one.props['className'] === 'wb-choiceLoading');
210
+
211
+ expect(inputsOf(element)).toHaveLength(0);
212
+ expect(tree.some((one) => one.props['className'] === 'wb-choiceOption')).toBe(false);
213
+ expect(
214
+ treeOf(loading?.props['children']).some(
215
+ (one) => one.props['className'] === 'wb-spinner',
216
+ ),
217
+ ).toBe(true);
218
+ expect(
219
+ treeOf(loading?.props['children']).some(
220
+ (one) => one.props['children'] === '正在读环境…',
221
+ ),
222
+ ).toBe(true);
223
+ });
224
+
225
+ it('★ 没得选且不 loading:画 emptyText 那句,不画选项', () => {
226
+ const element = ChoiceGroup({
227
+ label: '环境',
228
+ name: 'env',
229
+ value: '',
230
+ options: [],
231
+ emptyText: '这个工作区还没绑定环境',
232
+ onChange: () => {},
233
+ });
234
+
235
+ expect(inputsOf(element)).toHaveLength(0);
236
+ expect(
237
+ treeOf(element).find((one) => one.props['className'] === 'wb-choiceEmpty')
238
+ ?.props['children'],
239
+ ).toBe('这个工作区还没绑定环境');
240
+ });
241
+
242
+ it('★ variant 落在菜单上:ghost 写 data-variant=ghost,默认是 boxed', () => {
243
+ const menuOf = (variant?: 'boxed' | 'ghost') =>
244
+ treeOf(
245
+ ChoiceGroup({
246
+ label: '环境',
247
+ name: 'env',
248
+ value: 'tencent-test',
249
+ options: OPTIONS,
250
+ ...(variant === undefined ? {} : { variant }),
251
+ onChange: () => {},
252
+ }),
253
+ ).find((one) => one.props['className'] === 'wb-choiceMenu');
254
+
255
+ expect(menuOf('ghost')?.props['data-variant']).toBe('ghost');
256
+ expect(menuOf(undefined)?.props['data-variant']).toBe('boxed');
257
+ });
258
+
259
+ it('★ description 画在 label 下面第二行', () => {
260
+ const element = ChoiceGroup({
261
+ label: '环境',
262
+ name: 'env',
263
+ value: 'tencent-test',
264
+ options: [
265
+ { value: 'tencent-test', label: '腾讯云 · 测试', description: '走的是测试账号' },
266
+ { value: 'tencent-prod', label: '腾讯云 · 生产' },
267
+ ],
268
+ onChange: () => {},
269
+ });
270
+ const labels = treeOf(element).filter(
271
+ (one) => one.props['className'] === 'wb-choiceLabel',
272
+ );
273
+ const descriptions = treeOf(element).filter(
274
+ (one) => one.props['className'] === 'wb-choiceDescription',
275
+ );
276
+
277
+ expect(descriptions).toHaveLength(1);
278
+ expect(descriptions[0]?.props['children']).toBe('走的是测试账号');
279
+ expect(
280
+ treeOf(labels[0]?.props['children']).some(
281
+ (one) => one.props['className'] === 'wb-choiceDescription',
282
+ ),
283
+ ).toBe(true);
284
+ });
285
+
198
286
  it('Fragment 还是 React 自己的(别把 key 语义换掉)', () => {
199
287
  expect(Fragment).toBeDefined();
200
288
  });
@@ -1,11 +1,13 @@
1
1
  import type { ReactNode } from '../lib/react.js';
2
2
  import { Fragment, h } from '../lib/react.js';
3
3
  import { IconCheckOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives';
4
+ import { Spinner } from './Spinner.js';
4
5
  import './ChoiceGroup.css';
5
6
 
6
7
  export interface ChoiceGroupOption {
7
8
  readonly value: string;
8
9
  readonly label: ReactNode;
10
+ readonly description?: ReactNode | undefined;
9
11
  }
10
12
 
11
13
  interface ChoiceGroupCommon {
@@ -13,6 +15,10 @@ interface ChoiceGroupCommon {
13
15
  readonly name: string;
14
16
  readonly options: readonly ChoiceGroupOption[];
15
17
  readonly disabled?: boolean | undefined;
18
+ readonly variant?: 'boxed' | 'ghost' | undefined;
19
+ readonly loading?: boolean | undefined;
20
+ readonly loadingText?: ReactNode | undefined;
21
+ readonly emptyText?: ReactNode | undefined;
16
22
  }
17
23
 
18
24
  export interface ChoiceGroupSingleProps extends ChoiceGroupCommon {
@@ -40,42 +46,66 @@ function ChoiceMenu(input: {
40
46
  readonly options: readonly ChoiceGroupOption[];
41
47
  readonly disabled: boolean;
42
48
  readonly multi: boolean;
49
+ readonly variant: 'boxed' | 'ghost';
50
+ readonly loading: boolean;
51
+ readonly loadingText: ReactNode | undefined;
52
+ readonly emptyText: ReactNode | undefined;
43
53
  readonly rowOf: (value: string) => ChoiceRowState;
44
54
  }) {
55
+ const body = input.loading ? (
56
+ <span className="wb-choiceLoading" role="status">
57
+ <Spinner size={14} />
58
+ <span className="wb-choiceLoadingText">{input.loadingText ?? '…'}</span>
59
+ </span>
60
+ ) : input.options.length === 0 ? (
61
+ input.emptyText === undefined ? null : (
62
+ <span className="wb-choiceEmpty">{input.emptyText}</span>
63
+ )
64
+ ) : (
65
+ input.options.map((option) => {
66
+ const row = input.rowOf(option.value);
67
+ return (
68
+ <Fragment key={option.value}>
69
+ <label
70
+ className={`wb-choiceOption${row.checked ? ' wb-choiceOptionOn' : ''}`}
71
+ >
72
+ <input
73
+ className={input.multi ? 'wb-checkbox' : 'wb-radio'}
74
+ type={input.multi ? 'checkbox' : 'radio'}
75
+ name={input.name}
76
+ checked={row.checked}
77
+ disabled={input.disabled}
78
+ onChange={row.onSelect}
79
+ />
80
+ {input.multi ? (
81
+ <span
82
+ className="wb-checkboxBox"
83
+ aria-hidden="true"
84
+ >
85
+ {row.checked ? <IconCheckOutlineRegular size={12} /> : null}
86
+ </span>
87
+ ) : null}
88
+ <span className="wb-choiceLabel">
89
+ <span className="wb-choiceLabelText">{option.label}</span>
90
+ {option.description === undefined ? null : (
91
+ <span className="wb-choiceDescription">{option.description}</span>
92
+ )}
93
+ </span>
94
+ </label>
95
+ </Fragment>
96
+ );
97
+ })
98
+ );
99
+
45
100
  return (
46
101
  <div
47
102
  className="wb-choiceMenu"
103
+ data-variant={input.variant}
48
104
  role={input.multi ? 'group' : 'radiogroup'}
49
105
  aria-label={input.label}
106
+ aria-busy={input.loading ? true : undefined}
50
107
  >
51
- {input.options.map((option) => {
52
- const row = input.rowOf(option.value);
53
- return (
54
- <Fragment key={option.value}>
55
- <label
56
- className={`wb-choiceOption${row.checked ? ' wb-choiceOptionOn' : ''}`}
57
- >
58
- <input
59
- className={input.multi ? 'wb-checkbox' : 'wb-radio'}
60
- type={input.multi ? 'checkbox' : 'radio'}
61
- name={input.name}
62
- checked={row.checked}
63
- disabled={input.disabled}
64
- onChange={row.onSelect}
65
- />
66
- {input.multi ? (
67
- <span
68
- className="wb-checkboxBox"
69
- aria-hidden="true"
70
- >
71
- {row.checked ? <IconCheckOutlineRegular size={12} /> : null}
72
- </span>
73
- ) : null}
74
- <span className="wb-choiceLabel">{option.label}</span>
75
- </label>
76
- </Fragment>
77
- );
78
- })}
108
+ {body}
79
109
  </div>
80
110
  );
81
111
  }
@@ -86,6 +116,10 @@ export function ChoiceGroup(props: ChoiceGroupProps) {
86
116
  name: props.name,
87
117
  options: props.options,
88
118
  disabled: props.disabled === true,
119
+ variant: props.variant ?? 'boxed',
120
+ loading: props.loading === true,
121
+ loadingText: props.loadingText,
122
+ emptyText: props.emptyText,
89
123
  };
90
124
 
91
125
  if (props.multi === true) {
@@ -98,6 +132,10 @@ export function ChoiceGroup(props: ChoiceGroupProps) {
98
132
  options={common.options}
99
133
  disabled={common.disabled}
100
134
  multi={true}
135
+ variant={common.variant}
136
+ loading={common.loading}
137
+ loadingText={common.loadingText}
138
+ emptyText={common.emptyText}
101
139
  rowOf={(value) => ({
102
140
  checked: values.includes(value),
103
141
  onSelect: () => {
@@ -121,6 +159,10 @@ export function ChoiceGroup(props: ChoiceGroupProps) {
121
159
  options={common.options}
122
160
  disabled={common.disabled}
123
161
  multi={false}
162
+ variant={common.variant}
163
+ loading={common.loading}
164
+ loadingText={common.loadingText}
165
+ emptyText={common.emptyText}
124
166
  rowOf={(option) => ({
125
167
  checked: option === value,
126
168
  onSelect: () => {
@@ -0,0 +1,13 @@
1
+ .wb-formActions {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ align-items: center;
5
+ justify-content: flex-end;
6
+ gap: var(--wb-len-8);
7
+ }
8
+
9
+ .wb-formActionDanger {
10
+ color: var(--dsw-alias-state-error-primary);
11
+ border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 30%, transparent);
12
+ --dsw-alias-interactive-bg-hover: color-mix(in srgb, var(--dsw-alias-state-error-primary) 8%, transparent);
13
+ }