@linxin666/dsh-client-ui-task-board 0.3.11 → 0.3.13

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.
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Board view mounting (dsh-task-board wrapper).
3
+ *
4
+ * The single-occupant takeover lifecycle — container injection into the
5
+ * center column, sibling eviction, remount resilience, sidebar click-out —
6
+ * lives exactly once in shared/client/panel-mount-core.ts (synced copy); this
7
+ * wrapper supplies the board tree, view dataset key, CSS module, and the html
8
+ * attribute names. Those names are pinned by board.module.css, skins, and the
9
+ * semantic attributes contract.
10
+ */
1
11
  import type { BoardController } from '../core/controller.ts';
2
12
  import type { LocaleRefreshSource } from './sidebar-entry.ts';
3
13
  /** The injected board container (kept in the DOM, hidden when inactive). */
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Center-column panel takeover lifecycle.
3
+ *
4
+ * The `conversation` slot is single-occupant (ui-conversation) and external
5
+ * plugins cannot declare slots, so a family panel takes over the center
6
+ * column at the DOM level: a container is appended inside the center column
7
+ * (`[class*="centerCol"]`, the 0.1.0-rc.6+ AppFrame layout; previously
8
+ * `[data-pane="conversation"]` on older shells — the mount selector keeps
9
+ * both, ssh #243 / task-board #107) as an extra trailing child React never
10
+ * manages, and a stylesheet rule hides the conversation content while the
11
+ * panel is active. Toggling is a data attribute on <html> — no React
12
+ * involvement, so the conversation subtree underneath stays mounted and
13
+ * stateful.
14
+ *
15
+ * Consuming plugins keep a thin wrapper that supplies the panel tree,
16
+ * container attribute names, and stylesheet class; those names are pinned by
17
+ * each package's CSS, skins, and the semantic-attributes contract. The
18
+ * sidebar row toggling the panel shares its core the same way
19
+ * (shared/client/sidebar-entry-core.ts, synced copy).
20
+ */
21
+ import { type Root } from 'react-dom/client';
22
+ /** Options for mountCenterPanel; dsh-ssh mount.tsx and dsh-task-board board-mount.tsx are the canonical consumers. */
23
+ export interface CenterPanelMountOptions {
24
+ /** Render the panel React tree into a root (initial mount, remount, locale refresh). */
25
+ render: (root: Root) => void;
26
+ /** dataset key of the injected container's view attribute, e.g. `dshSshView` for `data-dsh-ssh-view`. */
27
+ viewDatasetKey: string;
28
+ /** value of the container's L2 `data-dsh-plugin` semantic attribute. */
29
+ pluginName: string;
30
+ /** stylesheet class applied to the injected container. */
31
+ viewClassName: string;
32
+ /** <html> attribute set while this panel is active. */
33
+ activeAttribute: string;
34
+ /** the sibling panel's active attribute, removed from <html> when this panel opens. */
35
+ siblingActiveAttribute: string;
36
+ /** detail value this panel broadcasts on the cross-plugin activation event. */
37
+ panelName: string;
38
+ /** sibling detail value whose activation closes this panel. */
39
+ siblingPanelName: string;
40
+ /** open flag of the owning controller. */
41
+ isOpen: () => boolean;
42
+ /** close the panel, handing the center column back to the conversation. */
43
+ close: () => void;
44
+ /** subscribe to the owning controller's open-state changes; returns an unsubscriber. */
45
+ subscribe: (listener: () => void) => () => void;
46
+ /** locale-change source; when given, re-renders an open panel on a Language switch. */
47
+ locale?: {
48
+ subscribe(listener: () => void): () => void;
49
+ };
50
+ }
51
+ /**
52
+ * Mount a family panel into the center column and bind its visibility to the
53
+ * owning controller's open state.
54
+ * @returns disposer unmounting the tree and restoring the column.
55
+ */
56
+ export declare function mountCenterPanel(options: CenterPanelMountOptions): () => void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@linxin666/dsh-client-ui-task-board",
3
3
  "description": "Host-authoritative task board for the DSH Web GUI with real session execution, Host cron scheduling, and optional cross-platform idle-sleep protection; mounted without DSH source changes.",
4
- "version": "0.3.11",
4
+ "version": "0.3.13",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "dsh": {
25
25
  "engines": {
26
- "dsh": ">=0.1.2-alpha.3"
26
+ "dsh": ">=0.1.2-alpha.4"
27
27
  },
28
28
  "bundle": {
29
29
  "patch": "./cordis.patch.yml"
@@ -48,23 +48,23 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@deepseek-ai/cordis": "^4.0.2",
51
- "@deepseek-ai/dsh-agent": "^0.1.2-alpha.3",
52
- "@deepseek-ai/dsh-agent-presets": "^0.1.2-alpha.3",
53
- "@deepseek-ai/dsh-api-gateway": "^0.1.2-alpha.3",
54
- "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.3",
55
- "@deepseek-ai/dsh-workspace": "^0.1.2-alpha.3",
56
- "@deepseek-ai/dsh-api-session-controller": "^0.1.2-alpha.3",
57
- "@deepseek-ai/dsh-api-workspace-controller": "^0.1.2-alpha.3",
58
- "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.3",
59
- "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.3",
60
- "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.3",
61
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.3",
62
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.3",
63
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.3",
64
- "@deepseek-ai/dsh-commands": "^0.1.2-alpha.3",
65
- "@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.3",
66
- "@deepseek-ai/dsh-settings": "^0.1.2-alpha.3",
67
- "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.3",
51
+ "@deepseek-ai/dsh-agent": "^0.1.2-alpha.4",
52
+ "@deepseek-ai/dsh-agent-presets": "^0.1.2-alpha.4",
53
+ "@deepseek-ai/dsh-api-gateway": "^0.1.2-alpha.4",
54
+ "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.4",
55
+ "@deepseek-ai/dsh-workspace": "^0.1.2-alpha.4",
56
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.2-alpha.4",
57
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.1.2-alpha.4",
58
+ "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.4",
59
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.4",
60
+ "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.4",
61
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.4",
62
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.4",
63
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.4",
64
+ "@deepseek-ai/dsh-commands": "^0.1.2-alpha.4",
65
+ "@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.4",
66
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.4",
67
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.4",
68
68
  "@types/node": "^22.20.0",
69
69
  "@types/react": "~18.3.1",
70
70
  "@types/react-dom": "^18.3.5",
@@ -1,39 +1,22 @@
1
1
  /**
2
- * Board view mounting.
2
+ * Board view mounting (dsh-task-board wrapper).
3
3
  *
4
- * The `conversation` slot is single-occupant (ui-conversation) and external
5
- * plugins cannot declare slots, so the board takes over the center column at
6
- * the DOM level: a container is appended inside the center column
7
- * (`[class*="centerCol"]`, the dsh 0.1.0-rc.6 AppFrame layout; previously
8
- * `[data-pane="conversation"]` on older shells — the mount selector keeps both)
9
- * as an extra trailing child
10
- * React never manages, and a stylesheet
11
- * rule hides the conversation content while the board is active. Toggling is
12
- * a data attribute on <html> — no React involvement, so the conversation
13
- * subtree underneath stays mounted and stateful.
4
+ * The single-occupant takeover lifecycle — container injection into the
5
+ * center column, sibling eviction, remount resilience, sidebar click-out —
6
+ * lives exactly once in shared/client/panel-mount-core.ts (synced copy); this
7
+ * wrapper supplies the board tree, view dataset key, CSS module, and the html
8
+ * attribute names. Those names are pinned by board.module.css, skins, and the
9
+ * semantic attributes contract.
14
10
  */
15
- import { createRoot, type Root } from 'react-dom/client'
16
11
  import type { BoardController } from '../core/controller.ts'
17
12
  import { TaskBoard } from './board/TaskBoard.tsx'
13
+ import { mountCenterPanel } from './panel-mount-core.ts'
18
14
  import type { LocaleRefreshSource } from './sidebar-entry.ts'
19
15
  import css from './board.module.css'
20
16
 
21
17
  /** The injected board container (kept in the DOM, hidden when inactive). */
22
18
  export const BOARD_VIEW_SELECTOR = '[data-dsh-taskboard-view]'
23
19
 
24
- const CONVERSATION_COLUMN_SELECTOR = '[data-pane="conversation"], [class*="centerCol"]'
25
- const ACTIVE_ATTR = 'data-dsh-taskboard-active'
26
- /** The sibling panel's activation attribute (ssh), removed when this panel opens. */
27
- const OTHER_ACTIVE_ATTR = 'data-dsh-ssh-active'
28
- /** Cross-plugin activation event; detail is the activating panel name. */
29
- const ACTIVATE_EVENT = 'dsh-panel-activate'
30
- const PANEL_NAME = 'taskboard'
31
-
32
- /** Find the center column, or undefined while the frame is not mounted. */
33
- function conversationColumn(): HTMLElement | undefined {
34
- return document.querySelector<HTMLElement>(CONVERSATION_COLUMN_SELECTOR) ?? undefined
35
- }
36
-
37
20
  /**
38
21
  * Mount the board React tree into the center column and bind its visibility
39
22
  * to the controller's boardOpen state.
@@ -43,83 +26,18 @@ function conversationColumn(): HTMLElement | undefined {
43
26
  * @returns disposer unmounting the tree and restoring the column.
44
27
  */
45
28
  export function mountBoard(controller: BoardController, locale?: LocaleRefreshSource): () => void {
46
- let root: Root | undefined
47
- let container: HTMLDivElement | undefined
48
- let unsubscribeLocale: (() => void) | undefined
49
- try {
50
- unsubscribeLocale = locale?.subscribe(() => {
51
- if (root !== undefined) root.render(<TaskBoard controller={controller} />)
52
- })
53
- } catch { /* locale service absent: the board follows its next natural re-render */ }
54
-
55
- const ensure = (): void => {
56
- if (container !== undefined) {
57
- if (container.isConnected) return
58
- root?.unmount()
59
- root = undefined
60
- container.remove()
61
- container = undefined
62
- }
63
- const column = conversationColumn()
64
- if (column === undefined) return
65
- container = document.createElement('div')
66
- container.dataset.dshTaskboardView = ''
67
- container.dataset.dshPlugin = 'task-board'
68
- container.className = css.boardView
69
- column.appendChild(container)
70
- root = createRoot(container)
71
- root.render(<TaskBoard controller={controller} />)
72
- }
73
-
74
- // The frame mounts after boot settlement; watch for the column's arrival.
75
- const waitObserver = new MutationObserver(() => { ensure() })
76
- waitObserver.observe(document.body, { childList: true, subtree: true })
77
-
78
- const applyActive = (): void => {
79
- if (controller.getSnapshot().boardOpen) {
80
- // Single-occupant center column: opening this panel must evict the
81
- // sibling panel (ssh), both its html attribute and its controller
82
- // state, otherwise the two panels' visibility rules fight and the
83
- // second click appears dead.
84
- document.documentElement.removeAttribute(OTHER_ACTIVE_ATTR)
85
- document.documentElement.setAttribute(ACTIVE_ATTR, '')
86
- document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: PANEL_NAME }))
87
- } else {
88
- document.documentElement.removeAttribute(ACTIVE_ATTR)
89
- }
90
- }
91
- const onOtherActivate = (event: Event): void => {
92
- if ((event as CustomEvent).detail === 'ssh' && controller.getSnapshot().boardOpen) {
93
- controller.closeBoard()
94
- }
95
- }
96
- // Jump out on sidebar context clicks: clicking a session/workspace row
97
- // (including the already-current one, which produces no session-change
98
- // event) hands the center column back to the conversation. Capture phase,
99
- // so the panel closes before the shell processes the click.
100
- const SIDEBAR_ROW_SELECTOR = '[class*="sessionRow"], [class*="projectRow"], [class*="searchResultRow"], [class*="searchResultWorkspace"], [class*="newSession"]'
101
- const onClickSidebarRow = (event: MouseEvent): void => {
102
- if (!controller.getSnapshot().boardOpen) return
103
- const target = event.target as HTMLElement | null
104
- if (target === null) return
105
- if (target.closest(SIDEBAR_ROW_SELECTOR) !== null) controller.closeBoard()
106
- }
107
- document.addEventListener('click', onClickSidebarRow, true)
108
- document.addEventListener(ACTIVATE_EVENT, onOtherActivate)
109
- const unsubscribe = controller.subscribe(applyActive)
110
- applyActive()
111
- ensure()
112
-
113
- return () => {
114
- document.removeEventListener('click', onClickSidebarRow, true)
115
- document.removeEventListener(ACTIVATE_EVENT, onOtherActivate)
116
- waitObserver.disconnect()
117
- unsubscribe()
118
- unsubscribeLocale?.()
119
- document.documentElement.removeAttribute(ACTIVE_ATTR)
120
- root?.unmount()
121
- root = undefined
122
- container?.remove()
123
- container = undefined
124
- }
29
+ return mountCenterPanel({
30
+ render: root => root.render(<TaskBoard controller={controller} />),
31
+ viewDatasetKey: 'dshTaskboardView',
32
+ pluginName: 'task-board',
33
+ viewClassName: css.boardView,
34
+ activeAttribute: 'data-dsh-taskboard-active',
35
+ siblingActiveAttribute: 'data-dsh-ssh-active',
36
+ panelName: 'taskboard',
37
+ siblingPanelName: 'ssh',
38
+ isOpen: () => controller.getSnapshot().boardOpen,
39
+ close: () => controller.closeBoard(),
40
+ subscribe: listener => controller.subscribe(listener),
41
+ locale,
42
+ })
125
43
  }
@@ -0,0 +1,147 @@
1
+ // Generated by scripts/sync-shared.mjs from shared/client/panel-mount-core.ts. Do not edit this copy; edit the shared source and run "node scripts/sync-shared.mjs".
2
+ /**
3
+ * Center-column panel takeover lifecycle.
4
+ *
5
+ * The `conversation` slot is single-occupant (ui-conversation) and external
6
+ * plugins cannot declare slots, so a family panel takes over the center
7
+ * column at the DOM level: a container is appended inside the center column
8
+ * (`[class*="centerCol"]`, the 0.1.0-rc.6+ AppFrame layout; previously
9
+ * `[data-pane="conversation"]` on older shells — the mount selector keeps
10
+ * both, ssh #243 / task-board #107) as an extra trailing child React never
11
+ * manages, and a stylesheet rule hides the conversation content while the
12
+ * panel is active. Toggling is a data attribute on <html> — no React
13
+ * involvement, so the conversation subtree underneath stays mounted and
14
+ * stateful.
15
+ *
16
+ * Consuming plugins keep a thin wrapper that supplies the panel tree,
17
+ * container attribute names, and stylesheet class; those names are pinned by
18
+ * each package's CSS, skins, and the semantic-attributes contract. The
19
+ * sidebar row toggling the panel shares its core the same way
20
+ * (shared/client/sidebar-entry-core.ts, synced copy).
21
+ */
22
+ import { createRoot, type Root } from 'react-dom/client'
23
+
24
+ /** Options for mountCenterPanel; dsh-ssh mount.tsx and dsh-task-board board-mount.tsx are the canonical consumers. */
25
+ export interface CenterPanelMountOptions {
26
+ /** Render the panel React tree into a root (initial mount, remount, locale refresh). */
27
+ render: (root: Root) => void
28
+ /** dataset key of the injected container's view attribute, e.g. `dshSshView` for `data-dsh-ssh-view`. */
29
+ viewDatasetKey: string
30
+ /** value of the container's L2 `data-dsh-plugin` semantic attribute. */
31
+ pluginName: string
32
+ /** stylesheet class applied to the injected container. */
33
+ viewClassName: string
34
+ /** <html> attribute set while this panel is active. */
35
+ activeAttribute: string
36
+ /** the sibling panel's active attribute, removed from <html> when this panel opens. */
37
+ siblingActiveAttribute: string
38
+ /** detail value this panel broadcasts on the cross-plugin activation event. */
39
+ panelName: string
40
+ /** sibling detail value whose activation closes this panel. */
41
+ siblingPanelName: string
42
+ /** open flag of the owning controller. */
43
+ isOpen: () => boolean
44
+ /** close the panel, handing the center column back to the conversation. */
45
+ close: () => void
46
+ /** subscribe to the owning controller's open-state changes; returns an unsubscriber. */
47
+ subscribe: (listener: () => void) => () => void
48
+ /** locale-change source; when given, re-renders an open panel on a Language switch. */
49
+ locale?: { subscribe(listener: () => void): () => void }
50
+ }
51
+
52
+ const CONVERSATION_COLUMN_SELECTOR = '[data-pane="conversation"], [class*="centerCol"]'
53
+ /** Cross-plugin activation event; detail is the activating panel name. */
54
+ const ACTIVATE_EVENT = 'dsh-panel-activate'
55
+ // Sidebar rows whose clicks hand the center column back to the conversation
56
+ // (including the already-current row, which produces no session-change
57
+ // event). Capture phase, so the panel closes before the shell processes the
58
+ // click.
59
+ const SIDEBAR_ROW_SELECTOR = '[class*="sessionRow"], [class*="projectRow"], [class*="searchResultRow"], [class*="searchResultWorkspace"], [class*="newSession"]'
60
+
61
+ /** Find the center column, or undefined while the frame is not mounted. */
62
+ function conversationColumn(): HTMLElement | undefined {
63
+ return document.querySelector<HTMLElement>(CONVERSATION_COLUMN_SELECTOR) ?? undefined
64
+ }
65
+
66
+ /**
67
+ * Mount a family panel into the center column and bind its visibility to the
68
+ * owning controller's open state.
69
+ * @returns disposer unmounting the tree and restoring the column.
70
+ */
71
+ export function mountCenterPanel(options: CenterPanelMountOptions): () => void {
72
+ let root: Root | undefined
73
+ let container: HTMLDivElement | undefined
74
+ let unsubscribeLocale: (() => void) | undefined
75
+ try {
76
+ unsubscribeLocale = options.locale?.subscribe(() => {
77
+ if (root !== undefined) options.render(root)
78
+ })
79
+ } catch { /* locale service absent: the panel follows its next natural re-render */ }
80
+
81
+ const ensure = (): void => {
82
+ if (container !== undefined) {
83
+ if (container.isConnected) return
84
+ // The conversation pane was replaced; drop the stale tree and remount.
85
+ root?.unmount()
86
+ root = undefined
87
+ container.remove()
88
+ container = undefined
89
+ }
90
+ const column = conversationColumn()
91
+ if (column === undefined) return
92
+ container = document.createElement('div')
93
+ container.dataset[options.viewDatasetKey] = ''
94
+ container.dataset.dshPlugin = options.pluginName
95
+ container.className = options.viewClassName
96
+ column.appendChild(container)
97
+ root = createRoot(container)
98
+ options.render(root)
99
+ }
100
+
101
+ // The frame mounts after boot settlement; watch for the column's arrival.
102
+ const waitObserver = new MutationObserver(() => { ensure() })
103
+ waitObserver.observe(document.body, { childList: true, subtree: true })
104
+
105
+ const applyActive = (): void => {
106
+ if (options.isOpen()) {
107
+ // Single-occupant center column: opening this panel must evict the
108
+ // sibling panel, both its html attribute and its controller state,
109
+ // otherwise the two panels' visibility rules fight and the second
110
+ // click appears dead.
111
+ document.documentElement.removeAttribute(options.siblingActiveAttribute)
112
+ document.documentElement.setAttribute(options.activeAttribute, '')
113
+ document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: options.panelName }))
114
+ } else {
115
+ document.documentElement.removeAttribute(options.activeAttribute)
116
+ }
117
+ }
118
+ const onOtherActivate = (event: Event): void => {
119
+ if ((event as CustomEvent).detail === options.siblingPanelName && options.isOpen()) {
120
+ options.close()
121
+ }
122
+ }
123
+ const onClickSidebarRow = (event: MouseEvent): void => {
124
+ if (!options.isOpen()) return
125
+ const target = event.target as HTMLElement | null
126
+ if (target === null) return
127
+ if (target.closest(SIDEBAR_ROW_SELECTOR) !== null) options.close()
128
+ }
129
+ document.addEventListener('click', onClickSidebarRow, true)
130
+ document.addEventListener(ACTIVATE_EVENT, onOtherActivate)
131
+ const unsubscribe = options.subscribe(applyActive)
132
+ applyActive()
133
+ ensure()
134
+
135
+ return () => {
136
+ document.removeEventListener('click', onClickSidebarRow, true)
137
+ document.removeEventListener(ACTIVATE_EVENT, onOtherActivate)
138
+ waitObserver.disconnect()
139
+ unsubscribe()
140
+ unsubscribeLocale?.()
141
+ document.documentElement.removeAttribute(options.activeAttribute)
142
+ root?.unmount()
143
+ root = undefined
144
+ container?.remove()
145
+ container = undefined
146
+ }
147
+ }
@@ -72,7 +72,10 @@
72
72
  }
73
73
 
74
74
  .description {
75
- color: var(--dsw-alias-label-tertiary);
75
+ /* Secondary, not tertiary: skins whose tertiary token is tuned for large
76
+ print leave 12-13px hint text below readable contrast (orca-link #778399
77
+ on cream measures ~3.4:1). */
78
+ color: var(--dsw-alias-label-secondary);
76
79
  font-size: 13px;
77
80
  line-height: 1.5;
78
81
  }
@@ -106,7 +109,7 @@
106
109
  }
107
110
 
108
111
  .readOnly {
109
- color: var(--dsw-alias-label-tertiary);
112
+ color: var(--dsw-alias-label-secondary);
110
113
  margin: 12px 0 0;
111
114
  font-size: 12px;
112
115
  line-height: 1.5;
@@ -130,7 +133,10 @@
130
133
 
131
134
  .failed {
132
135
  min-width: 0;
133
- color: var(--dsw-alias-label-error);
136
+ /* The suite's error alias is state-error-primary; a label-error token does
137
+ not exist, so the var() would resolve to nothing and the message would
138
+ inherit the ink color, losing the failure signal. */
139
+ color: var(--dsw-alias-state-error-primary, #b42318);
134
140
  flex: 1;
135
141
  margin: 0;
136
142
  font-size: 12px;
@@ -278,7 +284,7 @@
278
284
  }
279
285
 
280
286
  .inputInvalid {
281
- border: 1px solid var(--dsw-alias-label-error);
287
+ border: 1px solid var(--dsw-alias-state-error-primary, #b42318);
282
288
  background: var(--dsw-alias-bg-layer-3);
283
289
  height: 34px;
284
290
  font: inherit;
@@ -290,9 +296,9 @@
290
296
  }
291
297
 
292
298
  .inputInvalid:focus-visible {
293
- outline: 2px solid var(--dsw-alias-label-error);
299
+ outline: 2px solid var(--dsw-alias-state-error-primary, #b42318);
294
300
  outline-offset: 1px;
295
- border-color: var(--dsw-alias-label-error);
301
+ border-color: var(--dsw-alias-state-error-primary, #b42318);
296
302
  }
297
303
 
298
304
  .selectWrap {
@@ -384,14 +390,14 @@
384
390
  }
385
391
 
386
392
  .invalid {
387
- color: var(--dsw-alias-label-error);
393
+ color: var(--dsw-alias-state-error-primary, #b42318);
388
394
  margin: 0;
389
395
  font-size: 12px;
390
396
  line-height: 1.5;
391
397
  }
392
398
 
393
399
  .hint {
394
- color: var(--dsw-alias-label-tertiary);
400
+ color: var(--dsw-alias-label-secondary);
395
401
  margin: 0;
396
402
  font-size: 12px;
397
403
  line-height: 1.5;