dsh-taskboard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +169 -0
- package/cordis.patch.yml +12 -0
- package/lib/client.js +2085 -0
- package/lib/host/execution.js +189 -0
- package/lib/host/execution.js.map +1 -0
- package/lib/host/protocol-text.js +37 -0
- package/lib/host/protocol-text.js.map +1 -0
- package/lib/host/routes.js +369 -0
- package/lib/host/routes.js.map +1 -0
- package/lib/host/scheduler.js +91 -0
- package/lib/host/scheduler.js.map +1 -0
- package/lib/host/sdk.js +145 -0
- package/lib/host/sdk.js.map +1 -0
- package/lib/host/store.js +112 -0
- package/lib/host/store.js.map +1 -0
- package/lib/host/tools.js +620 -0
- package/lib/host/tools.js.map +1 -0
- package/lib/index.js +91 -0
- package/lib/index.js.map +1 -0
- package/lib/invariant.js +22 -0
- package/lib/invariant.js.map +1 -0
- package/lib/shared/api.js +9 -0
- package/lib/shared/api.js.map +1 -0
- package/lib/shared/protocol.js +279 -0
- package/lib/shared/protocol.js.map +1 -0
- package/package.json +74 -0
- package/src/client/api.ts +90 -0
- package/src/client/board/NewTaskModal.tsx +8 -0
- package/src/client/board/TaskBoard.tsx +184 -0
- package/src/client/board/TaskCard.tsx +61 -0
- package/src/client/board/TaskDetail.tsx +210 -0
- package/src/client/board/TaskFormModal.tsx +257 -0
- package/src/client/board-mount.tsx +92 -0
- package/src/client/controller.ts +241 -0
- package/src/client/index.ts +87 -0
- package/src/client/sidebar-entry.ts +165 -0
- package/src/client/styles.ts +391 -0
- package/src/host/execution.ts +244 -0
- package/src/host/protocol-text.ts +37 -0
- package/src/host/routes.ts +387 -0
- package/src/host/scheduler.ts +107 -0
- package/src/host/sdk.ts +200 -0
- package/src/host/store.ts +139 -0
- package/src/host/tools.ts +631 -0
- package/src/index.ts +124 -0
- package/src/invariant.ts +22 -0
- package/src/shared/api.ts +98 -0
- package/src/shared/protocol.ts +475 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar entry injection — structure ported from the working dsh-web-ui
|
|
3
|
+
* family implementations (dsh-ssh / dsh-client-ui-task-board, verified live
|
|
4
|
+
* in this shell): scope to the sidebar root (the logoRow's parent), find the
|
|
5
|
+
* New Session button inside it (newSession class → first direct-child BUTTON
|
|
6
|
+
* → aria-label/text fallbacks), and insert the entry as a direct child of
|
|
7
|
+
* that root next to the logo row. A body-level MutationObserver waits for
|
|
8
|
+
* the shell and self-heals React re-renders; a slow timer covers shells that
|
|
9
|
+
* mount late without further mutations.
|
|
10
|
+
*
|
|
11
|
+
* The row is plain DOM (no React tree) so it can never disturb the shell's
|
|
12
|
+
* reconciliation; the board view it toggles is a separate React root mounted
|
|
13
|
+
* in the center column (see board-mount.tsx).
|
|
14
|
+
*
|
|
15
|
+
* @module dsh-taskboard/client/sidebar-entry
|
|
16
|
+
*/
|
|
17
|
+
import type { BoardController } from './controller.ts'
|
|
18
|
+
|
|
19
|
+
/** Stable data attribute identifying this entry row. */
|
|
20
|
+
export const ENTRY_SELECTOR = '[data-dsh-atb-entry]'
|
|
21
|
+
|
|
22
|
+
/** Inline icon (16px nav-icon look). */
|
|
23
|
+
const ICON = '<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="2.5" width="12" height="11" rx="1.5"/><path d="M2 6.5h12M6.5 6.5v7"/></svg>'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Find the sidebar shell root element, or undefined while not yet mounted.
|
|
27
|
+
* (Same as the working family plugins: sidebarCol pane → logoRow owner.)
|
|
28
|
+
*/
|
|
29
|
+
function sidebarRoot(): HTMLElement | undefined {
|
|
30
|
+
const column = document.querySelector<HTMLElement>('[data-pane="sidebar"], [class*="sidebarCol"]')
|
|
31
|
+
if (column === null) return undefined
|
|
32
|
+
const logoOwner = column.querySelector<HTMLElement>('[class*="logoRow"]')?.parentElement
|
|
33
|
+
return logoOwner ?? (column.firstElementChild as HTMLElement | undefined)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The New Session button: nested in the logo row on current shells, a direct
|
|
38
|
+
* child BUTTON on the real shell (the family plugins' fallback), with
|
|
39
|
+
* aria-label/text fallbacks for other shells.
|
|
40
|
+
*/
|
|
41
|
+
function newSessionButton(root: HTMLElement): HTMLButtonElement | undefined {
|
|
42
|
+
const nested = root.querySelector<HTMLButtonElement>('button[class*="newSession"]')
|
|
43
|
+
if (nested !== null) return nested
|
|
44
|
+
for (const child of root.children) {
|
|
45
|
+
if (child instanceof HTMLButtonElement) return child
|
|
46
|
+
}
|
|
47
|
+
const byAria = root.querySelector<HTMLButtonElement>(
|
|
48
|
+
'button[aria-label="新建会话"], button[aria-label="New Session"], button[aria-label*="新会话"], button[aria-label*="new session" i]',
|
|
49
|
+
)
|
|
50
|
+
if (byAria !== null) return byAria
|
|
51
|
+
const buttons = Array.from(root.querySelectorAll<HTMLButtonElement>('button'))
|
|
52
|
+
return buttons.find(button => /新会话|新建会话|new session/i.test(button.textContent ?? ''))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Build the entry row (a detached button; insert once the shell is up). */
|
|
56
|
+
function createEntry(controller: BoardController): HTMLButtonElement {
|
|
57
|
+
const entry = document.createElement('button')
|
|
58
|
+
entry.type = 'button'
|
|
59
|
+
entry.dataset.dshAtbEntry = ''
|
|
60
|
+
entry.className = 'dsh-atb-entry'
|
|
61
|
+
entry.setAttribute('aria-label', 'Agent 任务看板')
|
|
62
|
+
entry.innerHTML = `<span class="dsh-atb-entry-icon">${ICON}</span><span class="dsh-atb-entry-label">任务看板</span>`
|
|
63
|
+
entry.addEventListener('click', () => { controller.toggleBoard() })
|
|
64
|
+
return entry
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Re-insert the entry after the New Session row (before the browser region). */
|
|
68
|
+
function placeEntry(root: HTMLElement, entry: HTMLButtonElement): boolean {
|
|
69
|
+
const button = newSessionButton(root)
|
|
70
|
+
if (button === undefined) return false
|
|
71
|
+
if (entry.parentElement !== root) {
|
|
72
|
+
// Position relative to the family block (entries injected by sibling
|
|
73
|
+
// plugins), never relative to transient logoRow geometry: every family
|
|
74
|
+
// plugin that self-heals during a re-render then lands in the same
|
|
75
|
+
// relative order. No append-to-end fallback: appending at the end would
|
|
76
|
+
// randomly reorder the block after a shell re-render.
|
|
77
|
+
const row = button.closest('[class*="logoRow"]')
|
|
78
|
+
const base = (row !== null && row.parentElement === root) ? row : button
|
|
79
|
+
const family = Array.from(root.children).filter(
|
|
80
|
+
(el): el is HTMLElement => el instanceof HTMLElement && el.matches('[data-dsh-atb-entry], [data-dsh-taskboard-entry], [data-dsh-ssh-entry]'),
|
|
81
|
+
)
|
|
82
|
+
// taskboard sits before the whole family block.
|
|
83
|
+
const anchor = family.length > 0 ? (family[0] ?? null) : (base.nextElementSibling ?? null)
|
|
84
|
+
root.insertBefore(entry, anchor)
|
|
85
|
+
}
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Debug counters (window.__atbDebug) — evidence if the entry fails to appear. */
|
|
90
|
+
interface AtbDebug { attempts: number; found: boolean; placed: boolean }
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Mount the sidebar entry, waiting for the shell to render and self-healing
|
|
94
|
+
* on later React re-renders.
|
|
95
|
+
* @param controller - the board controller the entry toggles.
|
|
96
|
+
* @returns disposer removing the entry and its observers.
|
|
97
|
+
*/
|
|
98
|
+
export function mountSidebarEntry(controller: BoardController): () => void {
|
|
99
|
+
const entry = createEntry(controller)
|
|
100
|
+
const debug: AtbDebug = { attempts: 0, found: false, placed: false }
|
|
101
|
+
;(window as unknown as { __atbDebug?: AtbDebug }).__atbDebug = debug
|
|
102
|
+
let root: HTMLElement | undefined
|
|
103
|
+
let placed = false
|
|
104
|
+
|
|
105
|
+
const tryPlace = (): void => {
|
|
106
|
+
debug.attempts++
|
|
107
|
+
if (root !== undefined && !root.isConnected) {
|
|
108
|
+
rootObserver.disconnect()
|
|
109
|
+
root = undefined
|
|
110
|
+
placed = false
|
|
111
|
+
}
|
|
112
|
+
if (placed) {
|
|
113
|
+
if (document.body.contains(entry)) return
|
|
114
|
+
rootObserver.disconnect()
|
|
115
|
+
root = undefined
|
|
116
|
+
placed = false
|
|
117
|
+
}
|
|
118
|
+
root ??= sidebarRoot()
|
|
119
|
+
if (root === undefined) return
|
|
120
|
+
debug.found = newSessionButton(root) !== undefined
|
|
121
|
+
placed = placeEntry(root, entry)
|
|
122
|
+
debug.placed = placed
|
|
123
|
+
if (placed) {
|
|
124
|
+
rootObserver.observe(root, { childList: true, subtree: true })
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Body-level watcher as the whole-rebuild fallback.
|
|
129
|
+
const waitObserver = new MutationObserver(() => { tryPlace() })
|
|
130
|
+
waitObserver.observe(document.body, { childList: true, subtree: true })
|
|
131
|
+
|
|
132
|
+
// Self-heal: re-insert in the same frame when a re-render displaces the row.
|
|
133
|
+
const rootObserver = new MutationObserver(() => {
|
|
134
|
+
if (root === undefined || !root.isConnected) {
|
|
135
|
+
placed = false
|
|
136
|
+
tryPlace()
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
if (!root.contains(entry)) {
|
|
140
|
+
placed = placeEntry(root, entry)
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// Belt-and-braces: a late shell mount that triggers no further mutations
|
|
145
|
+
// still gets periodic retries (the family plugins rely on mutation traffic
|
|
146
|
+
// alone; the timer costs one cheap contains-check per tick once placed).
|
|
147
|
+
const retry = setInterval(() => { tryPlace() }, 2_000)
|
|
148
|
+
|
|
149
|
+
const syncActive = () => {
|
|
150
|
+
if (controller.getSnapshot().boardOpen) entry.dataset.active = 'true'
|
|
151
|
+
else delete entry.dataset.active
|
|
152
|
+
}
|
|
153
|
+
const unsubscribe = controller.subscribe(syncActive)
|
|
154
|
+
syncActive()
|
|
155
|
+
|
|
156
|
+
tryPlace()
|
|
157
|
+
|
|
158
|
+
return () => {
|
|
159
|
+
clearInterval(retry)
|
|
160
|
+
waitObserver.disconnect()
|
|
161
|
+
rootObserver.disconnect()
|
|
162
|
+
unsubscribe()
|
|
163
|
+
entry.remove()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board styles, injected as one global stylesheet with dsh-atb- prefixed
|
|
3
|
+
* classes. Colors ride the shell's --dsw-* design tokens where available so
|
|
4
|
+
* the board follows the active theme/skin; urgency accents are the fixed
|
|
5
|
+
* red/purple/blue of the protocol.
|
|
6
|
+
*
|
|
7
|
+
* @module dsh-taskboard/client/styles
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** The stylesheet text. */
|
|
11
|
+
export const STYLES = `
|
|
12
|
+
.dsh-atb-entry {
|
|
13
|
+
display: flex; align-items: center; gap: 8px;
|
|
14
|
+
width: calc(100% - 8px); margin: 2px 4px; padding: 6px 10px;
|
|
15
|
+
border: none; border-radius: 8px; background: transparent;
|
|
16
|
+
color: var(--dsw-text-secondary, inherit); font: inherit; font-size: 13px;
|
|
17
|
+
cursor: pointer; text-align: left;
|
|
18
|
+
}
|
|
19
|
+
.dsh-atb-entry:hover { background: var(--dsw-hover, rgba(128,128,128,.12)); color: var(--dsw-text-primary, inherit); }
|
|
20
|
+
.dsh-atb-entry[data-active="true"] { background: var(--dsw-active, rgba(128,128,128,.18)); color: var(--dsw-text-primary, inherit); font-weight: 500; }
|
|
21
|
+
.dsh-atb-entry svg { flex: none; }
|
|
22
|
+
|
|
23
|
+
html[data-dsh-atb-active] [data-pane="conversation"] > *:not([data-dsh-atb-view]) { display: none !important; }
|
|
24
|
+
.dsh-atb-view { display: none; }
|
|
25
|
+
html[data-dsh-atb-active] .dsh-atb-view { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
|
|
26
|
+
|
|
27
|
+
.dsh-atb-board { display: flex; flex-direction: column; height: 100%; min-height: 0; padding: 12px 16px; gap: 10px; box-sizing: border-box; }
|
|
28
|
+
.dsh-atb-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
29
|
+
.dsh-atb-title { font-size: 15px; font-weight: 600; margin: 0; }
|
|
30
|
+
.dsh-atb-count { font-size: 12px; color: var(--dsw-text-secondary, gray); }
|
|
31
|
+
.dsh-atb-spacer { flex: 1; }
|
|
32
|
+
.dsh-atb-select, .dsh-atb-input {
|
|
33
|
+
font: inherit; font-size: 12.5px; padding: 5px 8px; border-radius: 7px;
|
|
34
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.35));
|
|
35
|
+
background: var(--dsw-bg, transparent); color: inherit;
|
|
36
|
+
}
|
|
37
|
+
.dsh-atb-chip {
|
|
38
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
39
|
+
font-size: 12px; padding: 3px 9px; border-radius: 999px; cursor: pointer;
|
|
40
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.35));
|
|
41
|
+
background: transparent; color: var(--dsw-text-secondary, inherit);
|
|
42
|
+
}
|
|
43
|
+
.dsh-atb-chip[data-on="true"] { color: #fff; border-color: transparent; }
|
|
44
|
+
.dsh-atb-chip[data-urgency="urgent"][data-on="true"] { background: #e5484d; }
|
|
45
|
+
.dsh-atb-chip[data-urgency="normal"][data-on="true"] { background: #8e4ec6; }
|
|
46
|
+
.dsh-atb-chip[data-urgency="relaxed"][data-on="true"] { background: #3e63dd; }
|
|
47
|
+
.dsh-atb-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
|
|
48
|
+
.dsh-atb-dot[data-urgency="urgent"] { background: #e5484d; }
|
|
49
|
+
.dsh-atb-dot[data-urgency="normal"] { background: #8e4ec6; }
|
|
50
|
+
.dsh-atb-dot[data-urgency="relaxed"] { background: #3e63dd; }
|
|
51
|
+
|
|
52
|
+
.dsh-atb-btn {
|
|
53
|
+
font: inherit; font-size: 12.5px; padding: 5px 11px; border-radius: 7px; cursor: pointer;
|
|
54
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.35));
|
|
55
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.08)); color: inherit;
|
|
56
|
+
}
|
|
57
|
+
.dsh-atb-btn:hover { background: var(--dsw-hover, rgba(128,128,128,.18)); }
|
|
58
|
+
.dsh-atb-btn:disabled { opacity: .45; cursor: default; }
|
|
59
|
+
.dsh-atb-btn[data-primary="true"] { background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary, #1f2328)); border-color: transparent; color: var(--dsw-alias-label-primary-foreground, #fff); }
|
|
60
|
+
.dsh-atb-btn[data-danger="true"] { color: var(--dsw-alias-state-error-primary, #e5484d); border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary, #e5484d) 45%, transparent); }
|
|
61
|
+
|
|
62
|
+
.dsh-atb-columns { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 10px; flex: 1; min-height: 0; overflow-x: auto; }
|
|
63
|
+
|
|
64
|
+
.dsh-atb-detailpanel {
|
|
65
|
+
display: flex; flex-direction: column;
|
|
66
|
+
flex: none; max-height: 55%; min-height: 180px; overflow: hidden;
|
|
67
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.25)); border-radius: 12px;
|
|
68
|
+
background: var(--dsw-bg-panel, var(--dsw-bg-elevated, rgba(128,128,128,.05)));
|
|
69
|
+
padding: 10px 12px; box-shadow: 0 -4px 18px rgba(0,0,0,.12);
|
|
70
|
+
}
|
|
71
|
+
.dsh-atb-detailpanel .dsh-atb-detail { flex: 1; min-height: 0; }
|
|
72
|
+
.dsh-atb-column { display: flex; flex-direction: column; min-width: 200px; min-height: 0; border-radius: 10px; background: var(--dsw-bg-inset, rgba(128,128,128,.07)); padding: 8px; gap: 8px; }
|
|
73
|
+
.dsh-atb-colhead { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; padding: 2px 4px; }
|
|
74
|
+
.dsh-atb-colcount { font-size: 11px; font-weight: 400; color: var(--dsw-text-secondary, gray); }
|
|
75
|
+
.dsh-atb-cards { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; min-height: 0; flex: 1; padding: 2px; }
|
|
76
|
+
|
|
77
|
+
.dsh-atb-card {
|
|
78
|
+
position: relative; border-radius: 9px; padding: 8px 10px 8px 13px; cursor: pointer;
|
|
79
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.1));
|
|
80
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.25));
|
|
81
|
+
font-size: 13px; text-align: left; color: inherit; width: 100%; box-sizing: border-box;
|
|
82
|
+
}
|
|
83
|
+
.dsh-atb-card:hover { border-color: var(--dsw-border-strong, rgba(128,128,128,.55)); }
|
|
84
|
+
.dsh-atb-card[draggable="true"] { cursor: grab; }
|
|
85
|
+
.dsh-atb-card[data-dragging] { opacity: .45; }
|
|
86
|
+
.dsh-atb-column[data-dragover] { outline: 2px dashed var(--dsw-border-strong, rgba(128,128,128,.55)); outline-offset: -2px; background: var(--dsw-bg-hover, rgba(128,128,128,.12)); }
|
|
87
|
+
.dsh-atb-card::before {
|
|
88
|
+
content: ""; position: absolute; left: 4px; top: 6px; bottom: 6px; width: 3.5px; border-radius: 3px;
|
|
89
|
+
}
|
|
90
|
+
.dsh-atb-card[data-urgency="urgent"]::before { background: #e5484d; }
|
|
91
|
+
.dsh-atb-card[data-urgency="normal"]::before { background: #8e4ec6; }
|
|
92
|
+
.dsh-atb-card[data-urgency="relaxed"]::before { background: #3e63dd; }
|
|
93
|
+
.dsh-atb-card-title { font-weight: 550; line-height: 1.35; word-break: break-word; }
|
|
94
|
+
.dsh-atb-card-meta { display: flex; align-items: center; gap: 6px; margin-top: 5px; font-size: 11px; color: var(--dsw-text-secondary, gray); flex-wrap: wrap; }
|
|
95
|
+
.dsh-atb-badge { font-size: 10.5px; padding: 1px 6px; border-radius: 5px; background: rgba(128,128,128,.18); }
|
|
96
|
+
.dsh-atb-badge[data-kind="blocked"] { background: rgba(229,72,77,.18); color: #e5484d; }
|
|
97
|
+
.dsh-atb-badge[data-kind="scheduled"] { background: rgba(62,99,221,.16); color: #3e63dd; }
|
|
98
|
+
.dsh-atb-badge[data-kind="trashed"] { background: rgba(229,72,77,.14); color: #e5484d; text-decoration: line-through; }
|
|
99
|
+
.dsh-atb-badge[data-kind="done"] { background: rgba(46,160,67,.16); color: #2ea043; }
|
|
100
|
+
.dsh-atb-badge[data-kind="running"] { background: rgba(229,152,42,.16); color: #e69842; }
|
|
101
|
+
|
|
102
|
+
.dsh-atb-error { font-size: 12px; color: #e5484d; padding: 4px 8px; border-radius: 6px; background: rgba(229,72,77,.1); }
|
|
103
|
+
.dsh-atb-empty { font-size: 12px; color: var(--dsw-text-secondary, gray); padding: 10px 4px; }
|
|
104
|
+
|
|
105
|
+
/* ---------- detail pane (polished) ---------- */
|
|
106
|
+
.dsh-atb-detail {
|
|
107
|
+
display: flex; flex-direction: column; gap: 12px; overflow-y: auto; min-height: 0; flex: 1;
|
|
108
|
+
padding: 2px; position: relative;
|
|
109
|
+
}
|
|
110
|
+
.dsh-atb-detail::before {
|
|
111
|
+
content: ""; position: sticky; top: 0; height: 3px; border-radius: 3px; flex: none;
|
|
112
|
+
}
|
|
113
|
+
.dsh-atb-detail[data-urgency="urgent"]::before { background: linear-gradient(90deg, #e5484d, rgba(229,72,77,.15)); }
|
|
114
|
+
.dsh-atb-detail[data-urgency="normal"]::before { background: linear-gradient(90deg, #8e4ec6, rgba(142,78,198,.15)); }
|
|
115
|
+
.dsh-atb-detail[data-urgency="relaxed"]::before { background: linear-gradient(90deg, #3e63dd, rgba(62,99,221,.15)); }
|
|
116
|
+
|
|
117
|
+
.dsh-atb-detail-head { display: flex; align-items: flex-start; gap: 10px; }
|
|
118
|
+
.dsh-atb-detail-titlewrap { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
|
|
119
|
+
.dsh-atb-detail-titlebar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
120
|
+
.dsh-atb-detail-titlebar h3 { margin: 0; font-size: 15.5px; line-height: 1.35; word-break: break-word; }
|
|
121
|
+
.dsh-atb-detail-close {
|
|
122
|
+
flex: none; width: 26px; height: 26px; border-radius: 7px; border: none; cursor: pointer;
|
|
123
|
+
background: transparent; color: var(--dsw-text-secondary, gray); font-size: 13px; line-height: 1;
|
|
124
|
+
}
|
|
125
|
+
.dsh-atb-detail-close:hover { background: var(--dsw-hover, rgba(128,128,128,.18)); color: inherit; }
|
|
126
|
+
.dsh-atb-detail-topbtns { display: flex; align-items: center; gap: 6px; flex: none; }
|
|
127
|
+
.dsh-atb-detail-edit {
|
|
128
|
+
font: inherit; font-size: 12px; padding: 4px 10px; border-radius: 7px; cursor: pointer;
|
|
129
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.32));
|
|
130
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.07)); color: var(--dsw-text-secondary, inherit);
|
|
131
|
+
}
|
|
132
|
+
.dsh-atb-detail-edit:hover { border-color: var(--dsw-alias-brand-primary, #1f2328); color: var(--dsw-alias-label-primary, inherit); }
|
|
133
|
+
|
|
134
|
+
.dsh-atb-statuspill {
|
|
135
|
+
flex: none; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px; letter-spacing: .02em;
|
|
136
|
+
}
|
|
137
|
+
.dsh-atb-statuspill[data-status="backlog"] { background: rgba(128,128,128,.18); color: var(--dsw-text-secondary, #888); }
|
|
138
|
+
.dsh-atb-statuspill[data-status="todo"] { background: rgba(62,99,221,.15); color: #3e63dd; }
|
|
139
|
+
.dsh-atb-statuspill[data-status="in_progress"] { background: rgba(230,152,66,.16); color: #d9822b; }
|
|
140
|
+
.dsh-atb-statuspill[data-status="in_review"] { background: rgba(142,78,198,.16); color: #8e4ec6; }
|
|
141
|
+
.dsh-atb-statuspill[data-status="done"] { background: rgba(46,160,67,.16); color: #2ea043; }
|
|
142
|
+
.dsh-atb-statuspill[data-status="canceled"], .dsh-atb-statuspill[data-status="archived"] { background: rgba(128,128,128,.14); color: var(--dsw-text-secondary, #888); }
|
|
143
|
+
|
|
144
|
+
.dsh-atb-detail-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
145
|
+
.dsh-atb-chip2 {
|
|
146
|
+
display: inline-flex; align-items: center; gap: 4px; font-size: 11px; line-height: 1;
|
|
147
|
+
padding: 3px 8px; border-radius: 6px;
|
|
148
|
+
background: var(--dsw-bg-inset, rgba(128,128,128,.09)); color: var(--dsw-text-secondary, #999);
|
|
149
|
+
}
|
|
150
|
+
.dsh-atb-chip2-icon { font-size: 10.5px; opacity: .85; }
|
|
151
|
+
.dsh-atb-chip2[data-tone="urgent"] { background: rgba(229,72,77,.15); color: #e5484d; }
|
|
152
|
+
.dsh-atb-chip2[data-tone="normal"] { background: rgba(142,78,198,.14); color: #a06ce0; }
|
|
153
|
+
.dsh-atb-chip2[data-tone="relaxed"] { background: rgba(62,99,221,.13); color: #6d92e8; }
|
|
154
|
+
.dsh-atb-detail-sub { font-size: 11.5px; color: var(--dsw-text-secondary, gray); }
|
|
155
|
+
|
|
156
|
+
.dsh-atb-fieldcard {
|
|
157
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.22)); border-radius: 10px;
|
|
158
|
+
padding: 9px 11px; display: flex; flex-direction: column; gap: 5px;
|
|
159
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.06));
|
|
160
|
+
}
|
|
161
|
+
.dsh-atb-fieldcard-label {
|
|
162
|
+
font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
|
|
163
|
+
color: var(--dsw-text-secondary, gray);
|
|
164
|
+
}
|
|
165
|
+
.dsh-atb-fieldcard[data-kind="prompt"] .dsh-atb-fieldcard-label { color: #8e63c8; }
|
|
166
|
+
.dsh-atb-promptbox {
|
|
167
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
168
|
+
font-size: 12px; line-height: 1.55; white-space: pre-wrap; word-break: break-word;
|
|
169
|
+
background: var(--dsw-bg-inset, rgba(128,128,128,.08)); border-radius: 7px; padding: 8px 10px;
|
|
170
|
+
border: 1px dashed var(--dsw-border, rgba(128,128,128,.25));
|
|
171
|
+
}
|
|
172
|
+
.dsh-atb-desc { white-space: pre-wrap; word-break: break-word; font-size: 13px; line-height: 1.55; }
|
|
173
|
+
|
|
174
|
+
.dsh-atb-detail-actions { display: flex; flex-direction: column; gap: 8px; }
|
|
175
|
+
.dsh-atb-runbtn {
|
|
176
|
+
font: inherit; font-size: 13px; font-weight: 600; padding: 8px 14px; border-radius: 9px; cursor: pointer;
|
|
177
|
+
border: 1px solid transparent; background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary, #1f2328)); color: var(--dsw-alias-label-primary-foreground, #fff); text-align: center;
|
|
178
|
+
transition: filter .12s ease;
|
|
179
|
+
}
|
|
180
|
+
.dsh-atb-runbtn:hover { filter: brightness(1.1); }
|
|
181
|
+
.dsh-atb-movebtns { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
182
|
+
.dsh-atb-movebtn {
|
|
183
|
+
font: inherit; font-size: 12px; padding: 4px 11px; border-radius: 999px; cursor: pointer;
|
|
184
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.32));
|
|
185
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.07)); color: var(--dsw-text-secondary, inherit);
|
|
186
|
+
transition: border-color .12s ease, color .12s ease;
|
|
187
|
+
}
|
|
188
|
+
.dsh-atb-movebtn:hover { border-color: var(--dsw-border-strong, rgba(128,128,128,.6)); color: inherit; }
|
|
189
|
+
.dsh-atb-movebtn[data-to="done"] { border-color: rgba(46,160,67,.55); color: #2ea043; }
|
|
190
|
+
.dsh-atb-movebtn[data-to="done"]:hover { background: rgba(46,160,67,.12); }
|
|
191
|
+
.dsh-atb-movebtn[data-to="canceled"], .dsh-atb-movebtn[data-to="archived"] { opacity: .75; }
|
|
192
|
+
.dsh-atb-movebtn[data-to="blocked"] { border-color: rgba(229,72,77,.45); }
|
|
193
|
+
.dsh-atb-movebtn[data-to="blocked"]:hover { background: rgba(229,72,77,.1); }
|
|
194
|
+
.dsh-atb-confirm { display: inline-flex; align-items: center; gap: 6px; }
|
|
195
|
+
.dsh-atb-confirm-label { font-size: 11.5px; color: var(--dsw-text-secondary, gray); }
|
|
196
|
+
|
|
197
|
+
.dsh-atb-section { font-size: 13px; display: flex; flex-direction: column; gap: 7px; }
|
|
198
|
+
.dsh-atb-section h4 {
|
|
199
|
+
margin: 0; font-size: 11px; color: var(--dsw-text-secondary, gray);
|
|
200
|
+
text-transform: uppercase; letter-spacing: .05em; display: flex; align-items: center; gap: 6px;
|
|
201
|
+
}
|
|
202
|
+
.dsh-atb-count2 {
|
|
203
|
+
font-size: 10px; font-weight: 600; padding: 0 6px; border-radius: 999px; line-height: 16px;
|
|
204
|
+
background: var(--dsw-bg-inset, rgba(128,128,128,.14)); color: var(--dsw-text-secondary, gray);
|
|
205
|
+
}
|
|
206
|
+
.dsh-atb-empty2 { font-size: 12px; color: var(--dsw-text-secondary, gray); padding: 8px 0; }
|
|
207
|
+
|
|
208
|
+
.dsh-atb-commentlist { display: flex; flex-direction: column; gap: 8px; }
|
|
209
|
+
.dsh-atb-bubble { display: flex; gap: 8px; }
|
|
210
|
+
.dsh-atb-bubble-avatar {
|
|
211
|
+
flex: none; width: 26px; height: 26px; border-radius: 8px; display: flex; align-items: center; justify-content: center;
|
|
212
|
+
font-size: 13px; background: var(--dsw-bg-inset, rgba(128,128,128,.12));
|
|
213
|
+
}
|
|
214
|
+
.dsh-atb-bubble[data-from="agent"] .dsh-atb-bubble-avatar { background: rgba(142,78,198,.15); }
|
|
215
|
+
.dsh-atb-bubble-main {
|
|
216
|
+
flex: 1; min-width: 0; border-radius: 10px; padding: 6px 10px;
|
|
217
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.08));
|
|
218
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.18));
|
|
219
|
+
}
|
|
220
|
+
.dsh-atb-bubble[data-from="agent"] .dsh-atb-bubble-main { border-color: rgba(142,78,198,.3); background: rgba(142,78,198,.07); }
|
|
221
|
+
.dsh-atb-bubble-meta { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; }
|
|
222
|
+
.dsh-atb-bubble-meta b { font-size: 11.5px; font-weight: 600; color: var(--dsw-text-primary, inherit); }
|
|
223
|
+
.dsh-atb-bubble[data-from="agent"] .dsh-atb-bubble-meta b { color: #a06ce0; }
|
|
224
|
+
.dsh-atb-bubble-meta span { font-size: 10.5px; color: var(--dsw-text-secondary, gray); }
|
|
225
|
+
.dsh-atb-bubble-body { font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
|
|
226
|
+
|
|
227
|
+
.dsh-atb-composer { display: flex; gap: 7px; align-items: flex-end; margin-top: 2px; }
|
|
228
|
+
.dsh-atb-composer-input {
|
|
229
|
+
flex: 1; font: inherit; font-size: 12.5px; line-height: 1.5; padding: 7px 10px; border-radius: 9px;
|
|
230
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.32));
|
|
231
|
+
background: var(--dsw-bg, transparent); color: inherit; resize: vertical; min-height: 38px;
|
|
232
|
+
}
|
|
233
|
+
.dsh-atb-composer-input:focus { outline: none; border-color: var(--dsw-alias-brand-primary, #1f2328); }
|
|
234
|
+
.dsh-atb-composer-send {
|
|
235
|
+
flex: none; font: inherit; font-size: 12.5px; padding: 7px 14px; border-radius: 9px; cursor: pointer;
|
|
236
|
+
border: 1px solid transparent; background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary, #1f2328)); color: var(--dsw-alias-label-primary-foreground, #fff);
|
|
237
|
+
}
|
|
238
|
+
.dsh-atb-composer-send:disabled { opacity: .4; cursor: default; }
|
|
239
|
+
|
|
240
|
+
.dsh-atb-execlist { display: flex; flex-direction: column; gap: 5px; }
|
|
241
|
+
.dsh-atb-exec-row {
|
|
242
|
+
display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px;
|
|
243
|
+
padding: 5px 9px; border-radius: 8px;
|
|
244
|
+
background: var(--dsw-bg-elevated, rgba(128,128,128,.07));
|
|
245
|
+
border: 1px solid var(--dsw-border, rgba(128,128,128,.16));
|
|
246
|
+
}
|
|
247
|
+
.dsh-atb-exec-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: rgba(128,128,128,.5); }
|
|
248
|
+
.dsh-atb-exec-dot[data-outcome="succeeded"] { background: #2ea043; box-shadow: 0 0 0 3px rgba(46,160,67,.15); }
|
|
249
|
+
.dsh-atb-exec-dot[data-outcome="failed"] { background: #e5484d; box-shadow: 0 0 0 3px rgba(229,72,77,.15); }
|
|
250
|
+
.dsh-atb-exec-dot[data-outcome="running"] { background: #d9822b; box-shadow: 0 0 0 3px rgba(217,130,43,.18); animation: dsh-atb-pulse 1.6s ease-in-out infinite; }
|
|
251
|
+
@keyframes dsh-atb-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
|
|
252
|
+
.dsh-atb-exec-trigger { font-size: 11px; color: var(--dsw-text-secondary, gray); }
|
|
253
|
+
.dsh-atb-exec-outcome { font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 5px; }
|
|
254
|
+
.dsh-atb-exec-outcome[data-outcome="succeeded"] { background: rgba(46,160,67,.15); color: #2ea043; }
|
|
255
|
+
.dsh-atb-exec-outcome[data-outcome="failed"] { background: rgba(229,72,77,.14); color: #e5484d; }
|
|
256
|
+
.dsh-atb-exec-outcome[data-outcome="running"] { background: rgba(217,130,43,.15); color: #d9822b; }
|
|
257
|
+
.dsh-atb-exec-outcome[data-outcome="cancelled"] { background: rgba(128,128,128,.15); color: var(--dsw-text-secondary, gray); }
|
|
258
|
+
.dsh-atb-exec-time { font-size: 11px; color: var(--dsw-text-secondary, gray); }
|
|
259
|
+
.dsh-atb-exec-session { font-size: 11px; color: var(--dsw-text-secondary, gray); }
|
|
260
|
+
.dsh-atb-exec-error { flex-basis: 100%; font-size: 11px; color: #e5484d; word-break: break-all; }
|
|
261
|
+
|
|
262
|
+
.dsh-atb-dangerzone {
|
|
263
|
+
display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 8px;
|
|
264
|
+
border-top: 1px dashed var(--dsw-border, rgba(128,128,128,.25));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* ---------- task form modal (create + edit, polished) ---------- */
|
|
268
|
+
.dsh-atb-modal-backdrop {
|
|
269
|
+
position: fixed; inset: 0; z-index: 80;
|
|
270
|
+
background: var(--dsw-alias-bg-mask-drop, rgba(28,30,36,.4)); backdrop-filter: var(--dsw-mask-blur, blur(2px));
|
|
271
|
+
display: flex; align-items: center; justify-content: center;
|
|
272
|
+
animation: dsh-atb-fade .14s ease;
|
|
273
|
+
}
|
|
274
|
+
@keyframes dsh-atb-fade { from { opacity: 0; } }
|
|
275
|
+
.dsh-atb-modal {
|
|
276
|
+
width: min(560px, calc(100vw - 48px)); max-height: calc(100vh - 80px);
|
|
277
|
+
display: flex; flex-direction: column; overflow: hidden; border-radius: 14px;
|
|
278
|
+
background: var(--dsw-alias-bg-overlay, #fff); color: var(--dsw-alias-label-primary, inherit);
|
|
279
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.25));
|
|
280
|
+
box-shadow: var(--dsw-shadow-lv3, 0 12px 32px rgba(0,0,0,.18));
|
|
281
|
+
animation: dsh-atb-pop .16s ease;
|
|
282
|
+
}
|
|
283
|
+
@keyframes dsh-atb-pop { from { opacity: 0; transform: translateY(8px) scale(.98); } }
|
|
284
|
+
.dsh-atb-modal-head {
|
|
285
|
+
display: flex; align-items: center; gap: 10px;
|
|
286
|
+
padding: 13px 16px 11px; border-bottom: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.18));
|
|
287
|
+
}
|
|
288
|
+
.dsh-atb-modal-headicon {
|
|
289
|
+
flex: none; width: 30px; height: 30px; border-radius: 9px;
|
|
290
|
+
display: flex; align-items: center; justify-content: center;
|
|
291
|
+
font-size: 14px; background: var(--dsw-alias-brand-primary, #1f2328); color: var(--dsw-alias-label-primary-foreground, #fff);
|
|
292
|
+
}
|
|
293
|
+
.dsh-atb-modal-headtext { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
|
|
294
|
+
.dsh-atb-modal-headtext h3 { margin: 0; font-size: 15px; line-height: 1.3; }
|
|
295
|
+
.dsh-atb-modal-headtext p { margin: 0; font-size: 11.5px; color: var(--dsw-alias-label-secondary, gray); }
|
|
296
|
+
.dsh-atb-modal-close {
|
|
297
|
+
flex: none; width: 26px; height: 26px; border-radius: 7px; border: none; cursor: pointer;
|
|
298
|
+
background: transparent; color: var(--dsw-alias-label-tertiary, gray); font-size: 13px; line-height: 1;
|
|
299
|
+
}
|
|
300
|
+
.dsh-atb-modal-close:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,.18)); color: var(--dsw-alias-label-primary, inherit); }
|
|
301
|
+
|
|
302
|
+
.dsh-atb-modal-body {
|
|
303
|
+
padding: 13px 16px; overflow-y: auto;
|
|
304
|
+
display: grid; grid-template-columns: 1fr 1fr; gap: 11px 10px;
|
|
305
|
+
}
|
|
306
|
+
.dsh-atb-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
|
|
307
|
+
.dsh-atb-field[data-span="full"] { grid-column: 1 / -1; }
|
|
308
|
+
.dsh-atb-field-label {
|
|
309
|
+
display: flex; align-items: center; gap: 3px;
|
|
310
|
+
font-size: 11px; font-weight: 600; letter-spacing: .03em;
|
|
311
|
+
color: var(--dsw-alias-label-secondary, gray);
|
|
312
|
+
}
|
|
313
|
+
.dsh-atb-req { color: var(--dsw-alias-state-error-primary, #e5484d); font-style: normal; }
|
|
314
|
+
.dsh-atb-modal-body input, .dsh-atb-modal-body textarea, .dsh-atb-modal-body select {
|
|
315
|
+
font: inherit; font-size: 13px; padding: 7px 10px; border-radius: 8px;
|
|
316
|
+
width: 100%; box-sizing: border-box;
|
|
317
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.35));
|
|
318
|
+
background: var(--dsw-specific-input-major, transparent); color: var(--dsw-alias-label-primary, inherit);
|
|
319
|
+
transition: border-color .12s ease, box-shadow .12s ease;
|
|
320
|
+
}
|
|
321
|
+
.dsh-atb-modal-body textarea { min-height: 64px; resize: vertical; }
|
|
322
|
+
.dsh-atb-modal-body input:focus, .dsh-atb-modal-body textarea:focus, .dsh-atb-modal-body select:focus {
|
|
323
|
+
outline: none; border-color: var(--dsw-alias-brand-primary, #1f2328);
|
|
324
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsw-alias-brand-primary, #1f2328) 18%, transparent);
|
|
325
|
+
}
|
|
326
|
+
.dsh-atb-modal-body .dsh-atb-input-bad { border-color: var(--dsw-alias-state-error-primary, #e5484d); }
|
|
327
|
+
.dsh-atb-modal-body .dsh-atb-input-bad:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsw-alias-state-error-primary, #e5484d) 20%, transparent); }
|
|
328
|
+
|
|
329
|
+
.dsh-atb-urgency-picker { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
|
|
330
|
+
.dsh-atb-urgency-opt {
|
|
331
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
|
|
332
|
+
padding: 8px 10px; border-radius: 9px; cursor: pointer;
|
|
333
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.35));
|
|
334
|
+
background: transparent; color: inherit;
|
|
335
|
+
transition: border-color .12s ease, background .12s ease;
|
|
336
|
+
}
|
|
337
|
+
.dsh-atb-urgency-name { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; }
|
|
338
|
+
.dsh-atb-urgency-hint { font-size: 10.5px; color: var(--dsw-alias-label-tertiary, gray); }
|
|
339
|
+
.dsh-atb-urgency-opt:hover { border-color: var(--dsw-alias-label-tertiary, rgba(128,128,128,.6)); }
|
|
340
|
+
.dsh-atb-urgency-opt[data-on="true"][data-urgency="urgent"] { border-color: rgba(229,72,77,.65); background: rgba(229,72,77,.1); }
|
|
341
|
+
.dsh-atb-urgency-opt[data-on="true"][data-urgency="normal"] { border-color: rgba(142,78,198,.65); background: rgba(142,78,198,.1); }
|
|
342
|
+
.dsh-atb-urgency-opt[data-on="true"][data-urgency="relaxed"] { border-color: rgba(62,99,221,.65); background: rgba(62,99,221,.1); }
|
|
343
|
+
|
|
344
|
+
.dsh-atb-mode-picker { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }
|
|
345
|
+
.dsh-atb-mode-opt {
|
|
346
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
|
|
347
|
+
padding: 8px 10px; border-radius: 9px; cursor: pointer;
|
|
348
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.35));
|
|
349
|
+
background: transparent; color: inherit;
|
|
350
|
+
transition: border-color .12s ease, background .12s ease;
|
|
351
|
+
}
|
|
352
|
+
.dsh-atb-mode-name { font-size: 12.5px; font-weight: 600; }
|
|
353
|
+
.dsh-atb-mode-hint { font-size: 10.5px; color: var(--dsw-alias-label-tertiary, gray); }
|
|
354
|
+
.dsh-atb-mode-opt:hover { border-color: var(--dsw-alias-label-tertiary, rgba(128,128,128,.6)); }
|
|
355
|
+
.dsh-atb-mode-opt[data-on="true"] { border-color: var(--dsw-alias-brand-primary, #1f2328); background: color-mix(in srgb, var(--dsw-alias-brand-primary, #1f2328) 8%, transparent); }
|
|
356
|
+
|
|
357
|
+
.dsh-atb-cron-presets { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
|
|
358
|
+
.dsh-atb-cron-preset {
|
|
359
|
+
font: inherit; font-size: 11px; padding: 2px 9px; border-radius: 999px; cursor: pointer;
|
|
360
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.35));
|
|
361
|
+
background: transparent; color: var(--dsw-alias-label-secondary, inherit);
|
|
362
|
+
}
|
|
363
|
+
.dsh-atb-cron-preset:hover { border-color: var(--dsw-alias-label-tertiary, rgba(128,128,128,.6)); color: inherit; }
|
|
364
|
+
.dsh-atb-cron-preset[data-on="true"] { border-color: transparent; background: var(--dsw-alias-brand-primary, #1f2328); color: var(--dsw-alias-label-primary-foreground, #fff); }
|
|
365
|
+
.dsh-atb-cron-next { margin-left: auto; font-size: 11px; color: var(--dsw-alias-label-tertiary, gray); }
|
|
366
|
+
|
|
367
|
+
.dsh-atb-modal-foot {
|
|
368
|
+
display: flex; align-items: center; gap: 10px;
|
|
369
|
+
padding: 11px 16px; border-top: 1px solid var(--dsw-alias-border-l2, rgba(128,128,128,.18));
|
|
370
|
+
background: var(--dsw-alias-bg-layer-1, rgba(128,128,128,.04));
|
|
371
|
+
}
|
|
372
|
+
.dsh-atb-modal-hint { flex: 1; min-width: 0; font-size: 11.5px; color: var(--dsw-alias-label-tertiary, gray); }
|
|
373
|
+
.dsh-atb-modal-hint[data-tone="bad"] { color: var(--dsw-alias-state-error-primary, #e5484d); }
|
|
374
|
+
.dsh-atb-modal-footbtns { display: flex; gap: 8px; }
|
|
375
|
+
|
|
376
|
+
.dsh-atb-secondary { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
|
|
377
|
+
.dsh-atb-link { color: var(--dsw-alias-state-business-primary, #3e63dd); cursor: pointer; text-decoration: none; }
|
|
378
|
+
.dsh-atb-link:hover { text-decoration: underline; }
|
|
379
|
+
`
|
|
380
|
+
|
|
381
|
+
let injected = false
|
|
382
|
+
|
|
383
|
+
/** Inject the stylesheet once (idempotent). */
|
|
384
|
+
export function injectStyles(): void {
|
|
385
|
+
if (injected || typeof document === 'undefined') return
|
|
386
|
+
const style = document.createElement('style')
|
|
387
|
+
style.id = 'dsh-taskboard-styles'
|
|
388
|
+
style.textContent = STYLES
|
|
389
|
+
document.head.append(style)
|
|
390
|
+
injected = true
|
|
391
|
+
}
|