@dennisrongo/dsh-todo 0.3.0 → 0.4.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/README.md +5 -0
- package/lib/client.js +44 -36
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# @dennisrongo/dsh-todo
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@dennisrongo/dsh-todo)
|
|
4
|
+
|
|
5
|
+
**npm:** [`@dennisrongo/dsh-todo`](https://www.npmjs.com/package/@dennisrongo/dsh-todo) ·
|
|
6
|
+
**source:** [dennisrongo/dsh-plugins](https://github.com/dennisrongo/dsh-plugins/tree/main/plugins/dsh-todo)
|
|
7
|
+
|
|
3
8
|
A todo list for the [DeepSeek Harness](https://github.com/deepseek-ai) (dsh) web UI.
|
|
4
9
|
|
|
5
10
|
Registers into the additive `conversation.view` slot — the conversation view
|
package/lib/client.js
CHANGED
|
@@ -92,17 +92,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
92
92
|
else: left unset it renders as a LIGHT popup while the option text inherits
|
|
93
93
|
the shell near-white label colour, i.e. white-on-white and unreadable.
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
@media (prefers-color-scheme: dark) {
|
|
104
|
-
.dshtd, .dshtd-modal, .dshtd-modal-backdrop { color-scheme: dark; }
|
|
105
|
-
}
|
|
95
|
+
This used to key off the prefers-color-scheme query, on the premise that the
|
|
96
|
+
shell "publishes its theme as CSS VARIABLES and never sets a color-scheme".
|
|
97
|
+
That premise was wrong: ui-layout's ThemePresenter sets
|
|
98
|
+
documentElement.style.colorScheme from the resolved theme on every change,
|
|
99
|
+
and color-scheme inherits \u2014 so native controls already follow the APP's
|
|
100
|
+
light/dark, including in the modal, which portals to document.body but is
|
|
101
|
+
still a descendant of <html>. Keying off the OS instead meant a light theme
|
|
102
|
+
on a dark-mode machine rendered dark popups. Nothing is needed here now.
|
|
106
103
|
|
|
107
104
|
/* ---- header ---- */
|
|
108
105
|
.dshtd-head {
|
|
@@ -143,13 +140,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
143
140
|
padding: 8px 12px;
|
|
144
141
|
}
|
|
145
142
|
.dshtd-add::placeholder { color: var(--td-caption); }
|
|
146
|
-
.dshtd-add:focus { outline: none; border-color: var(--dsw-alias-
|
|
143
|
+
.dshtd-add:focus { outline: none; border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
147
144
|
.dshtd-addbtn {
|
|
148
145
|
flex: none; border: 1px solid var(--td-border); border-radius: 8px;
|
|
149
146
|
background: var(--td-hover); color: var(--td-primary); font: inherit; font-weight: 500;
|
|
150
147
|
padding: 8px 16px; cursor: pointer;
|
|
151
148
|
}
|
|
152
|
-
.dshtd-addbtn:hover:not(:disabled) { border-color: var(--dsw-alias-
|
|
149
|
+
.dshtd-addbtn:hover:not(:disabled) { border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
153
150
|
.dshtd-addbtn:disabled { opacity: 0.4; cursor: default; }
|
|
154
151
|
|
|
155
152
|
/* ---- list ---- */
|
|
@@ -201,7 +198,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
201
198
|
}
|
|
202
199
|
.dshtd-edit {
|
|
203
200
|
flex: 1 1 auto; min-width: 0;
|
|
204
|
-
border: 1px solid var(--dsw-alias-
|
|
201
|
+
border: 1px solid var(--dsw-alias-brand-primary, #6b7280); border-radius: 6px;
|
|
205
202
|
background: transparent; color: var(--td-primary); font: inherit; padding: 3px 8px;
|
|
206
203
|
}
|
|
207
204
|
.dshtd-edit:focus { outline: none; }
|
|
@@ -234,8 +231,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
234
231
|
/* Priority reads as a rank, so only the urgent bands get colour \u2014 colouring all
|
|
235
232
|
four would make the list a rainbow and hide the two that matter. */
|
|
236
233
|
.dshtd-chip.p0 { color: var(--td-danger); border-color: currentColor; font-weight: 500; }
|
|
237
|
-
.dshtd-chip.p1 { color: var(--dsw-alias-state-
|
|
238
|
-
.dshtd-chip.rel { color: var(--dsw-alias-state-
|
|
234
|
+
.dshtd-chip.p1 { color: var(--dsw-alias-state-warn-primary, #f59e0b); border-color: currentColor; }
|
|
235
|
+
.dshtd-chip.rel { color: var(--dsw-alias-state-business-primary, #60a5fa); border-color: currentColor; }
|
|
239
236
|
|
|
240
237
|
/* Status pill doubles as the status control, so it is a real button. */
|
|
241
238
|
.dshtd-status {
|
|
@@ -244,8 +241,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
244
241
|
font: inherit; font-size: 12px; line-height: 20px; color: var(--td-caption);
|
|
245
242
|
cursor: pointer; appearance: none;
|
|
246
243
|
}
|
|
247
|
-
.dshtd-status:hover { color: var(--td-primary); border-color: var(--dsw-alias-
|
|
248
|
-
.dshtd-status.s-in-progress { color: var(--dsw-alias-state-
|
|
244
|
+
.dshtd-status:hover { color: var(--td-primary); border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
245
|
+
.dshtd-status.s-in-progress { color: var(--dsw-alias-state-business-primary, #60a5fa); border-color: currentColor; }
|
|
249
246
|
.dshtd-status.s-blocked { color: var(--td-danger); border-color: currentColor; }
|
|
250
247
|
.dshtd-status.s-done { color: var(--td-accent); border-color: currentColor; }
|
|
251
248
|
|
|
@@ -273,7 +270,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
273
270
|
border: 1px solid var(--td-border); border-radius: 6px; background: transparent;
|
|
274
271
|
color: var(--td-secondary); font: inherit; font-size: 14px; line-height: 22px; padding: 6px 8px;
|
|
275
272
|
}
|
|
276
|
-
.dshtd-desc:focus { outline: none; border-color: var(--dsw-alias-
|
|
273
|
+
.dshtd-desc:focus { outline: none; border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
277
274
|
.dshtd-fields { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
278
275
|
.dshtd-field { display: flex; align-items: center; gap: 6px; font-size: 12px; line-height: 18px; color: var(--td-caption); }
|
|
279
276
|
.dshtd-input {
|
|
@@ -281,24 +278,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
281
278
|
color: var(--td-primary); font: inherit; font-size: 12px; line-height: 18px;
|
|
282
279
|
padding: 3px 8px; min-width: 0; width: 130px;
|
|
283
280
|
}
|
|
284
|
-
.dshtd-input:focus { outline: none; border-color: var(--dsw-alias-
|
|
281
|
+
.dshtd-input:focus { outline: none; border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
285
282
|
.dshtd-select {
|
|
286
283
|
border: 1px solid var(--td-border); border-radius: 6px; background: transparent;
|
|
287
284
|
color: var(--td-primary); font: inherit; font-size: 12px; line-height: 18px; padding: 3px 6px;
|
|
288
285
|
}
|
|
289
286
|
|
|
290
287
|
/* Option rows get an explicit pair on the platforms that honour it (Windows and
|
|
291
|
-
Linux Chromium paint them; macOS ignores it and defers to color-scheme
|
|
288
|
+
Linux Chromium paint them; macOS ignores it and defers to color-scheme,
|
|
289
|
+
which ui-layout already sets on <html> from the resolved theme).
|
|
292
290
|
|
|
293
|
-
|
|
294
|
-
declarations paint a
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
291
|
+
Gated on the APP's palette, not the OS query it used to use: applied
|
|
292
|
+
unconditionally these declarations paint a dark popup under a light theme,
|
|
293
|
+
and keyed to the OS query they did exactly that whenever the theme and the
|
|
294
|
+
OS disagreed. body[data-ds-dark-theme] is what ThemePresenter
|
|
295
|
+
actually toggles, so this now follows the theme the user picked. */
|
|
296
|
+
body[data-ds-dark-theme] .dshtd-select option,
|
|
297
|
+
body[data-ds-dark-theme] .dshtd-status option {
|
|
298
|
+
background: var(--dsw-alias-bg-layer-1, #1b1d21);
|
|
299
|
+
color: var(--dsw-alias-label-primary, #f9fafb);
|
|
302
300
|
}
|
|
303
301
|
|
|
304
302
|
/* ---- task modal ----
|
|
@@ -345,14 +343,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
345
343
|
padding: 4px 8px;
|
|
346
344
|
}
|
|
347
345
|
.dshtd-modal-title:hover { border-color: var(--td-border); }
|
|
348
|
-
.dshtd-modal-title:focus { outline: none; border-color: var(--dsw-alias-
|
|
346
|
+
.dshtd-modal-title:focus { outline: none; border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
349
347
|
.dshtd-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; }
|
|
350
348
|
.dshtd-modal-desc {
|
|
351
349
|
width: 100%; min-height: 160px; resize: vertical;
|
|
352
350
|
border: 1px solid var(--td-border); border-radius: 8px; background: transparent;
|
|
353
351
|
color: var(--td-secondary); font: inherit; font-size: 14px; line-height: 22px; padding: 8px 10px;
|
|
354
352
|
}
|
|
355
|
-
.dshtd-modal-desc:focus { outline: none; border-color: var(--dsw-alias-
|
|
353
|
+
.dshtd-modal-desc:focus { outline: none; border-color: var(--dsw-alias-brand-primary, #6b7280); }
|
|
356
354
|
.dshtd-modal-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
|
|
357
355
|
.dshtd-modal-label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; line-height: 18px; color: var(--td-caption); }
|
|
358
356
|
.dshtd-modal-foot {
|
|
@@ -393,16 +391,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
393
391
|
padding: 6px 14px; cursor: pointer;
|
|
394
392
|
}
|
|
395
393
|
.dshtd-btn:hover { background: var(--td-hover); }
|
|
396
|
-
.dshtd-btn:focus-visible { outline: 2px solid var(--dsw-alias-
|
|
394
|
+
.dshtd-btn:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary, #6b7280); outline-offset: 1px; }
|
|
397
395
|
/* The destructive action is the one that looks destructive; Cancel stays quiet
|
|
398
396
|
so the safe choice is never the visually louder one. */
|
|
399
397
|
.dshtd-btn.danger { border-color: var(--td-danger); color: var(--td-danger); }
|
|
400
|
-
.dshtd-btn.danger:hover { background: var(--td-danger); color: var(--dsw-alias-label-
|
|
398
|
+
.dshtd-btn.danger:hover { background: var(--td-danger); color: var(--dsw-alias-label-primary-foreground, #fff); }
|
|
399
|
+
/* The shell's own filled primary, token for token, so a confirm action here
|
|
400
|
+
reads as the same control as one in Settings rather than a bespoke link.
|
|
401
|
+
Both tokens follow the active theme AND the accent axis. */
|
|
402
|
+
.dshtd-btn.primary {
|
|
403
|
+
background: var(--dsw-alias-button-primary-fill, #f9fafb);
|
|
404
|
+
border-color: transparent;
|
|
405
|
+
color: var(--dsw-alias-label-primary-foreground, #0f1115);
|
|
406
|
+
font-weight: 500;
|
|
407
|
+
}
|
|
408
|
+
.dshtd-btn.primary:hover { background: var(--dsw-alias-button-primary-hover, #e1e5ee); }
|
|
401
409
|
|
|
402
410
|
/* Overdue is the one state worth colouring in the list: it is the thing a
|
|
403
411
|
standup escalates. Due-today is warned, not alarmed. */
|
|
404
412
|
.dshtd-chip.due-over { color: var(--td-danger); border-color: currentColor; font-weight: 500; }
|
|
405
|
-
.dshtd-chip.due-today { color: var(--dsw-alias-state-
|
|
413
|
+
.dshtd-chip.due-today { color: var(--dsw-alias-state-warn-primary, #f59e0b); border-color: currentColor; }
|
|
406
414
|
|
|
407
415
|
/* ---- toolbar (group-by) ---- */
|
|
408
416
|
.dshtd-tools { flex: none; display: flex; align-items: center; gap: 6px; padding: 0 20px 10px; }
|
|
@@ -431,7 +439,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
431
439
|
@media (prefers-reduced-motion: reduce) {
|
|
432
440
|
.dshtd-progress > i, .dshtd-rowbtns { transition: none; }
|
|
433
441
|
}
|
|
434
|
-
`,gp=!1;function Mg(){if(gp)return;gp=!0;let e=document.createElement("style");e.dataset.plugin="@dennisrongo/dsh-todo",e.textContent=Vg,document.head.appendChild(e)}function le({path:e}){return(0,m.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:(0,m.jsx)("path",{d:e})})}var Q={check:"M3.5 8.5l3 3 6-6",restore:"M3 8a5 5 0 1 0 1.6-3.68M3 2.5v3h3",close:"M4 4l8 8M12 4l-8 8",up:"M8 12.5v-9M4.5 7L8 3.5 11.5 7",down:"M8 3.5v9M4.5 9L8 12.5 11.5 9",archive:"M2.5 5.5h11M3.5 5.5v7h9v-7M6.5 8.5h3",expand:"M6 4l4 4-4 4",collapse:"M4 6l4 4 4-4"};function Up({pending:e,onClose:r}){let i=E.default.useRef(null),o=E.default.useRef(null);E.default.useEffect(()=>{let a=document.activeElement;return o.current?.focus(),()=>a?.focus?.()},[]);let t=()=>{e.onConfirm(),r()};return(0,su.createPortal)((0,m.jsx)("div",{className:"dshtd-modal-backdrop",onClick:r,onKeyDown:a=>{if(a.stopPropagation(),a.key==="Escape"){a.preventDefault(),r();return}if(a.key!=="Tab")return;let c=i.current?.querySelectorAll("button");if(!c||c.length===0)return;let u=c[0],s=c[c.length-1];a.shiftKey&&document.activeElement===u?(a.preventDefault(),s.focus()):!a.shiftKey&&document.activeElement===s&&(a.preventDefault(),u.focus())},children:(0,m.jsxs)("div",{className:"dshtd-modal dshtd-confirm",role:"alertdialog","aria-modal":"true","aria-label":e.title,tabIndex:-1,ref:i,onClick:a=>a.stopPropagation(),children:[(0,m.jsxs)("div",{className:"dshtd-confirm-body",children:[(0,m.jsx)("span",{className:"dshtd-confirm-title",children:e.title}),(0,m.jsx)("span",{className:"dshtd-confirm-text",children:e.message}),e.subject?(0,m.jsx)("span",{className:"dshtd-confirm-subject",children:e.subject}):null]}),(0,m.jsxs)("div",{className:"dshtd-confirm-foot",children:[(0,m.jsx)("button",{className:"dshtd-btn",ref:o,onClick:r,children:"Cancel"}),(0,m.jsx)("button",{className:"dshtd-btn danger",onClick:t,children:e.confirmLabel})]})]})}),document.body)}function Op({item:e,store:r,onClose:i,knownReleases:o,knownSprints:t}){let[n,a]=E.default.useState(e.title),[c,u]=E.default.useState(e.description??""),s=E.default.useRef(null),l=E.default.useCallback(()=>{let g=vt(n),I=Vn(c);r.update(k=>{let P=k;return g&&g!==e.title&&(P=ee(P,e.id,{title:g})),I!==(e.description??"")&&(P=ee(P,e.id,{description:I})),P})},[n,c,e,r]),f=E.default.useCallback(()=>{l(),i()},[l,i]);E.default.useEffect(()=>{let g=document.activeElement;return s.current?.focus(),()=>g?.focus?.()},[]);let b=g=>{if(g.stopPropagation(),g.key==="Escape"){g.preventDefault(),f();return}if(g.key!=="Tab")return;let I=s.current?.querySelectorAll('button, input, textarea, select, [tabindex]:not([tabindex="-1"])');if(!I||I.length===0)return;let k=I[0],P=I[I.length-1];g.shiftKey&&document.activeElement===k?(g.preventDefault(),P.focus()):!g.shiftKey&&document.activeElement===P&&(g.preventDefault(),k.focus())},v=Kn(e);return(0,su.createPortal)((0,m.jsx)("div",{className:"dshtd-modal-backdrop",onClick:f,onKeyDown:b,children:(0,m.jsxs)("div",{className:"dshtd-modal",role:"dialog","aria-modal":"true","aria-label":`Task: ${e.title}`,tabIndex:-1,ref:s,onClick:g=>g.stopPropagation(),children:[(0,m.jsxs)("div",{className:"dshtd-modal-head",children:[(0,m.jsx)("input",{className:"dshtd-modal-title",value:n,"aria-label":"Task title",onChange:g=>a(g.target.value),onBlur:()=>{let g=vt(n);!g||g===e.title||r.update(I=>ee(I,e.id,{title:g}))}}),(0,m.jsx)("button",{className:"dshtd-icon",title:"Close","aria-label":"Close task details",onClick:f,children:(0,m.jsx)(le,{path:Q.close})})]}),(0,m.jsxs)("div",{className:"dshtd-modal-body",children:[(0,m.jsx)("textarea",{className:"dshtd-modal-desc",value:c,placeholder:"Description \u2014 acceptance criteria, repro steps, links\u2026","aria-label":"Task description",onChange:g=>u(g.target.value),onBlur:()=>{let g=Vn(c);g!==(e.description??"")&&r.update(I=>ee(I,e.id,{description:g}))}}),(0,m.jsxs)("div",{className:"dshtd-modal-grid",children:[(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Status",(0,m.jsx)("select",{className:"dshtd-select",value:e.status,onChange:g=>r.update(I=>Wn(I,e.id,g.target.value)),children:Ze.map(g=>(0,m.jsx)("option",{value:g,children:Bn[g]},g))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Priority",(0,m.jsx)("select",{className:"dshtd-select",value:e.priority,onChange:g=>r.update(I=>uu(I,e.id,g.target.value)),children:gt.map(g=>(0,m.jsx)("option",{value:g,children:Qt[g]},g))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Release",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-releases",defaultValue:e.release??"",placeholder:"v1.2.0",onBlur:g=>r.update(I=>ee(I,e.id,{release:g.target.value}))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Sprint",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-sprints",defaultValue:e.sprint??"",placeholder:"Sprint 24",onBlur:g=>r.update(I=>ee(I,e.id,{sprint:g.target.value}))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Due date",(0,m.jsx)("input",{className:"dshtd-input",type:"date",defaultValue:e.dueDate??"",onChange:g=>r.update(I=>ee(I,e.id,{dueDate:g.target.value}))})]})]}),(0,m.jsx)("datalist",{id:"dshtd-releases",children:o.map(g=>(0,m.jsx)("option",{value:g},g))}),(0,m.jsx)("datalist",{id:"dshtd-sprints",children:t.map(g=>(0,m.jsx)("option",{value:g},g))})]}),(0,m.jsxs)("div",{className:"dshtd-modal-foot",children:[(0,m.jsxs)("span",{children:["Created ",Ht(e.createdAt)," ago",e.completedAt?` \xB7 completed ${Ht(e.completedAt)} ago`:"",v?" \xB7 overdue":""]}),(0,m.jsx)("button",{className:"dshtd-link",onClick:f,children:"Done"})]})]})}),document.body)}function Kg({item:e,store:r}){return(0,m.jsx)("select",{className:`dshtd-status s-${e.status}`,value:e.status,"aria-label":`Status of "${e.title}"`,title:"Change status",onClick:i=>i.stopPropagation(),onChange:i=>r.update(o=>Wn(o,e.id,i.target.value)),children:Ze.map(i=>(0,m.jsx)("option",{value:i,children:Bn[i]},i))})}function Gg({item:e,index:r,total:i,store:o,knownReleases:t,knownSprints:n,onOpen:a,onDelete:c}){let[u,s]=E.default.useState(!1),[l,f]=E.default.useState(e.title),[b,v]=E.default.useState(!1),g=q(e),I=ie(e),k=()=>{let P=vt(l);s(!1),!(!P||P===e.title)&&o.update(Ee=>ee(Ee,e.id,{title:P}))};return g?(0,m.jsxs)("li",{className:"dshtd-row archived",children:[(0,m.jsx)("span",{className:"dshtd-badge","aria-hidden":"true",children:(0,m.jsx)(le,{path:Q.check})}),(0,m.jsx)("span",{className:"dshtd-text",children:e.title}),e.release?(0,m.jsx)("span",{className:"dshtd-chip rel",children:e.release}):null,(0,m.jsx)("span",{className:"dshtd-age",title:"When this was archived",children:Ht(e.archivedAt??0)}),(0,m.jsxs)("span",{className:"dshtd-rowbtns",children:[(0,m.jsx)("button",{className:"dshtd-icon",title:"Restore to the active list","aria-label":`Restore "${e.title}"`,onClick:()=>o.update(P=>_p(P,e.id)),children:(0,m.jsx)(le,{path:Q.restore})}),(0,m.jsx)("button",{className:"dshtd-icon danger",title:"Delete permanently","aria-label":`Permanently delete "${e.title}"`,onClick:c,children:(0,m.jsx)(le,{path:Q.close})})]})]}):(0,m.jsxs)("li",{className:"dshtd-item",children:[(0,m.jsxs)("div",{className:`dshtd-row${I?" done":""}`,children:[(0,m.jsx)("input",{type:"checkbox",className:"dshtd-check",checked:I,"aria-label":I?`Mark "${e.title}" as not done`:`Mark "${e.title}" as done`,onChange:()=>o.update(P=>xp(P,e.id))}),u?(0,m.jsx)("input",{className:"dshtd-edit",value:l,autoFocus:!0,"aria-label":"Edit task title",onChange:P=>f(P.target.value),onBlur:k,onKeyDown:P=>{P.stopPropagation(),P.key==="Enter"?(P.preventDefault(),k()):P.key==="Escape"&&(P.preventDefault(),f(e.title),s(!1))}}):(0,m.jsx)("span",{className:"dshtd-text",title:"Click to open \xB7 double-click to rename inline",onClick:a,onDoubleClick:P=>{P.stopPropagation(),f(e.title),s(!0)},children:e.title}),u?null:(0,m.jsxs)("span",{className:"dshtd-chips",children:[e.priority!==Fn?(0,m.jsx)("span",{className:`dshtd-chip ${e.priority}`,title:Qt[e.priority],children:e.priority.toUpperCase()}):null,e.release?(0,m.jsx)("span",{className:"dshtd-chip rel",title:`Release ${e.release}`,children:e.release}):null,e.sprint?(0,m.jsx)("span",{className:"dshtd-chip",title:`Sprint ${e.sprint}`,children:e.sprint}):null,e.dueDate?(0,m.jsx)("span",{className:`dshtd-chip${Kn(e)?" due-over":Pp(e)?" due-today":""}`,title:`Due ${e.dueDate}${Kn(e)?" \u2014 overdue":""}`,children:jp(e.dueDate)}):null,(0,m.jsx)(Kg,{item:e,store:o})]}),(0,m.jsxs)("span",{className:"dshtd-rowbtns",children:[(0,m.jsx)("button",{className:"dshtd-icon",title:b?"Hide details":"Show details","aria-label":`${b?"Hide":"Show"} details for "${e.title}"`,"aria-expanded":b,onClick:()=>v(P=>!P),children:(0,m.jsx)(le,{path:b?Q.collapse:Q.expand})}),(0,m.jsx)("button",{className:"dshtd-icon",title:"Move up","aria-label":`Move "${e.title}" up`,disabled:r===0,onClick:()=>o.update(P=>au(P,e.id,-1)),children:(0,m.jsx)(le,{path:Q.up})}),(0,m.jsx)("button",{className:"dshtd-icon",title:"Move down","aria-label":`Move "${e.title}" down`,disabled:r===i-1,onClick:()=>o.update(P=>au(P,e.id,1)),children:(0,m.jsx)(le,{path:Q.down})}),I?(0,m.jsx)("button",{className:"dshtd-icon",title:"Archive","aria-label":`Archive "${e.title}"`,onClick:()=>o.update(P=>yp(P,e.id)),children:(0,m.jsx)(le,{path:Q.archive})}):null,(0,m.jsx)("button",{className:"dshtd-icon danger",title:"Delete","aria-label":`Delete "${e.title}"`,onClick:c,children:(0,m.jsx)(le,{path:Q.close})})]})]}),b?(0,m.jsx)(Bg,{item:e,store:o,knownReleases:t,knownSprints:n}):null]})}function Bg({item:e,store:r,knownReleases:i,knownSprints:o}){let[t,n]=E.default.useState(e.description??""),[a,c]=E.default.useState(e.release??""),[u,s]=E.default.useState(e.sprint??"");return(0,m.jsxs)("div",{className:"dshtd-detail",children:[(0,m.jsx)("textarea",{className:"dshtd-desc",value:t,placeholder:"Description \u2014 acceptance criteria, repro steps, links\u2026","aria-label":`Description of "${e.title}"`,onChange:l=>n(l.target.value),onKeyDown:l=>l.stopPropagation(),onBlur:()=>{let l=Vn(t);l!==(e.description??"")&&r.update(f=>ee(f,e.id,{description:l}))}}),(0,m.jsxs)("div",{className:"dshtd-fields",children:[(0,m.jsxs)("label",{className:"dshtd-field",children:["Release",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-releases",value:a,placeholder:"v1.2.0",onChange:l=>c(l.target.value),onKeyDown:l=>l.stopPropagation(),onBlur:()=>{(ze(a)??"")!==(e.release??"")&&r.update(l=>ee(l,e.id,{release:a}))}})]}),(0,m.jsxs)("label",{className:"dshtd-field",children:["Sprint",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-sprints",value:u,placeholder:"Sprint 24",onChange:l=>s(l.target.value),onKeyDown:l=>l.stopPropagation(),onBlur:()=>{(ze(u)??"")!==(e.sprint??"")&&r.update(l=>ee(l,e.id,{sprint:u}))}})]}),(0,m.jsxs)("label",{className:"dshtd-field",children:["Priority",(0,m.jsx)("select",{className:"dshtd-select",value:e.priority,onChange:l=>r.update(f=>uu(f,e.id,l.target.value)),children:gt.map(l=>(0,m.jsx)("option",{value:l,children:Qt[l]},l))})]}),(0,m.jsxs)("span",{className:"dshtd-field",children:["Created ",Ht(e.createdAt)," ago"]})]}),(0,m.jsx)("datalist",{id:"dshtd-releases",children:i.map(l=>(0,m.jsx)("option",{value:l},l))}),(0,m.jsx)("datalist",{id:"dshtd-sprints",children:o.map(l=>(0,m.jsx)("option",{value:l},l))})]})}var Wg=[{id:"all",label:"All"},{id:"open",label:"Open"},{id:"in-progress",label:"In Progress"},{id:"blocked",label:"Blocked"},{id:"backlog",label:"Backlog"},{id:"done",label:"Done"},{id:"archived",label:"Archive"}],Xg=[{id:"none",label:"None"},{id:"status",label:"Status"},{id:"release",label:"Release"},{id:"sprint",label:"Sprint"},{id:"priority",label:"Priority"}];function qg(e,r,i){return r==="all"?i.total:r==="open"?i.open:r==="archived"?i.archived:ht(e).filter(o=>o.status===r).length}function Np({store:e}){let[r,i]=E.default.useState("all"),[o,t]=E.default.useState("none"),[n,a]=E.default.useState(""),[c,u]=E.default.useState({}),[s,l]=E.default.useState(null),[f,b]=E.default.useState(null);E.default.useEffect(()=>{Mg()},[]),E.default.useEffect(()=>{e&&e.ensure()},[e]);let v=E.default.useSyncExternalStore(e?e.subscribe:Hg,e?e.getSnapshot:vp,e?e.getSnapshot:vp);if(!e)return(0,m.jsx)("div",{className:"dshtd",children:(0,m.jsxs)("div",{className:"dshtd-empty",children:[(0,m.jsx)("b",{children:"No workspace yet"}),"Todos are stored per workspace. Open or create one to start a list."]})});let g=v.items,I=()=>{let w=vt(n);w&&(e.update(te=>[...te,bp(w)]),a(""),r!=="all"&&r!=="open"&&r!=="todo"&&i("all"))},k=$p(g),P=ht(g),Ee=Ip(g,r),Y=wp(Ee,o),Z=cu(g,"release"),R=cu(g,"sprint"),$t=s===null?void 0:g.find(w=>w.id===s),er=w=>{let te=q(w);b({title:te?"Delete permanently":"Delete task",message:te?"This removes the task from the archive for good. This cannot be undone.":"This deletes the task outright. Archiving keeps it recoverable instead.",subject:w.title,confirmLabel:"Delete",onConfirm:()=>e.update(qn=>qn.filter(Ae=>Ae.id!==w.id))})};return(0,m.jsxs)("div",{className:"dshtd",children:[(0,m.jsxs)("div",{className:"dshtd-head",children:[(0,m.jsx)("span",{className:"dshtd-title",children:"Todo"}),(0,m.jsx)("span",{className:"dshtd-progress",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":k.percent,"aria-label":"Todo completion",children:(0,m.jsx)("i",{style:{width:`${k.percent}%`}})}),(0,m.jsxs)("span",{className:"dshtd-score",children:[k.done,"/",k.total," done",k.inProgress>0?` \xB7 ${k.inProgress} in progress`:"",k.blocked>0?` \xB7 ${k.blocked} blocked`:""]})]}),(0,m.jsx)("div",{className:"dshtd-filters",role:"group","aria-label":"Filter todos",children:Wg.map(w=>{let te=qg(g,w.id,k);return te===0&&w.id!=="all"&&w.id!=="open"?null:(0,m.jsxs)("button",{className:"dshtd-filter","aria-pressed":r===w.id,onClick:()=>i(w.id),children:[w.label,w.id!=="all"&&te>0?` (${te})`:null]},w.id)})}),(0,m.jsxs)("div",{className:"dshtd-tools",children:[(0,m.jsx)("label",{htmlFor:"dshtd-groupby",children:"Group by"}),(0,m.jsx)("select",{id:"dshtd-groupby",className:"dshtd-select",value:o,onChange:w=>t(w.target.value),children:Xg.map(w=>(0,m.jsx)("option",{value:w.id,children:w.label},w.id))})]}),(0,m.jsxs)("div",{className:"dshtd-addrow",children:[(0,m.jsx)("input",{className:"dshtd-add",value:n,placeholder:"What needs doing?","aria-label":"Add a todo",disabled:v.status!=="ready",onChange:w=>a(w.target.value),onKeyDown:w=>{w.stopPropagation(),w.key==="Enter"?(w.preventDefault(),I()):w.key==="Escape"&&(w.preventDefault(),a(""))}}),(0,m.jsx)("button",{className:"dshtd-addbtn",disabled:!vt(n)||v.status!=="ready",onClick:I,children:"Add"})]}),(0,m.jsx)("div",{className:"dshtd-scroll",children:v.status==="loading"?(0,m.jsx)("div",{className:"dshtd-empty",children:"Loading\u2026"}):v.status==="error"?(0,m.jsxs)("div",{className:"dshtd-empty",children:[(0,m.jsx)("b",{children:"Couldn't load todos"}),v.error]}):Ee.length===0?(0,m.jsx)("div",{className:"dshtd-empty",children:r==="archived"?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"Nothing archived yet"}),"Check items off, then use \u201CArchive completed\u201D to file them away. Archived items stay here until you delete them."]}):k.total===0?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"No tasks yet"}),"Add your first one above \u2014 this list belongs to the current workspace."]}):r==="open"?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"All done \u{1F389}"}),"Nothing open right now."]}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"Nothing here"}),"No tasks match this filter."]})}):Y.map(w=>{let te=w.items.filter(ie).length,qn=w.items.length===0?0:Math.round(te/w.items.length*100),Ae=c[w.key]===!0;return(0,m.jsxs)("section",{className:"dshtd-group",children:[o!=="none"?(0,m.jsxs)("button",{className:"dshtd-ghead","aria-expanded":!Ae,onClick:()=>u(Ie=>({...Ie,[w.key]:!Ae})),children:[(0,m.jsx)(le,{path:Ae?Q.expand:Q.collapse}),w.label,(0,m.jsxs)("span",{className:"dshtd-gcount",children:[te,"/",w.items.length]}),(0,m.jsx)("span",{className:"dshtd-gbar","aria-hidden":"true",children:(0,m.jsx)("i",{style:{width:`${qn}%`}})})]}):null,Ae?null:(0,m.jsx)("ul",{className:"dshtd-list",children:w.items.map(Ie=>(0,m.jsx)(Gg,{item:Ie,index:P.indexOf(Ie),total:P.length,store:e,knownReleases:Z,knownSprints:R,onOpen:()=>l(Ie.id),onDelete:()=>er(Ie)},Ie.id))})]},w.key)})}),(0,m.jsxs)("div",{className:"dshtd-foot",children:[(0,m.jsxs)("span",{children:[k.open," open \xB7 ",k.done," done",k.archived>0?` \xB7 ${k.archived} archived`:null,v.saving?(0,m.jsx)("span",{className:"dshtd-state",children:" \xB7 saving\u2026"}):null,v.error&&v.status==="ready"?(0,m.jsxs)("span",{className:"dshtd-state err",children:[" \xB7 ",v.error]}):null]}),r==="archived"?k.archived>0?(0,m.jsx)("button",{className:"dshtd-link danger",title:"Permanently delete every archived item",onClick:()=>b({title:"Delete archived tasks",message:`Permanently delete ${k.archived} archived ${k.archived===1?"task":"tasks"}? This cannot be undone.`,confirmLabel:"Delete all",onConfirm:()=>e.update(zp)}),children:"Delete archived"}):null:k.done>0?(0,m.jsx)("button",{className:"dshtd-link",title:"Move completed items to the archive \u2014 they stay recoverable",onClick:()=>e.update(kp),children:"Archive completed"}):null]}),$t?(0,m.jsx)(Op,{item:$t,store:e,onClose:()=>l(null),knownReleases:Z,knownSprints:R}):null,f?(0,m.jsx)(Up,{pending:f,onClose:()=>b(null)}):null]})}var Yg={items:[],status:"ready",error:null,saving:!1},Hg=()=>()=>{},vp=()=>Yg;function Qg(e){let r=new Map,i=e;e.effect(()=>{let o=!1,t;return i.remote.$mount(tu).then(n=>{if(o)return void n();t=n}).catch(n=>{console.error("dsh-todo: failed to mount host remote",n)}),()=>{o=!0,r.clear(),t?.()}},"dsh-todo: mount host remote"),e.effect(()=>{let o=i.inject(["remote.dshTodo","workspaces","slots"],t=>{let n=t;n.slots.inject("conversation.view",()=>n.slots.register({name:"conversation.view",id:"todo",order:20,label:()=>"Todo",inject:a=>{let c=n.workspaces.list.getSnapshot().items,u=Tp(c,a);if(u===void 0)return{store:null};let s=r.get(u);return s===void 0&&(s=new Gn(n.remote.dshTodo,u),r.set(u,s)),{store:s}}},Np))});return()=>{o.dispose()}},"dsh-todo: conversation.view registration")}
|
|
442
|
+
`,gp=!1;function Mg(){if(gp)return;gp=!0;let e=document.createElement("style");e.dataset.plugin="@dennisrongo/dsh-todo",e.textContent=Vg,document.head.appendChild(e)}function le({path:e}){return(0,m.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:(0,m.jsx)("path",{d:e})})}var Q={check:"M3.5 8.5l3 3 6-6",restore:"M3 8a5 5 0 1 0 1.6-3.68M3 2.5v3h3",close:"M4 4l8 8M12 4l-8 8",up:"M8 12.5v-9M4.5 7L8 3.5 11.5 7",down:"M8 3.5v9M4.5 9L8 12.5 11.5 9",archive:"M2.5 5.5h11M3.5 5.5v7h9v-7M6.5 8.5h3",expand:"M6 4l4 4-4 4",collapse:"M4 6l4 4 4-4"};function Up({pending:e,onClose:r}){let i=E.default.useRef(null),o=E.default.useRef(null);E.default.useEffect(()=>{let a=document.activeElement;return o.current?.focus(),()=>a?.focus?.()},[]);let t=()=>{e.onConfirm(),r()};return(0,su.createPortal)((0,m.jsx)("div",{className:"dshtd-modal-backdrop",onClick:r,onKeyDown:a=>{if(a.stopPropagation(),a.key==="Escape"){a.preventDefault(),r();return}if(a.key!=="Tab")return;let c=i.current?.querySelectorAll("button");if(!c||c.length===0)return;let u=c[0],s=c[c.length-1];a.shiftKey&&document.activeElement===u?(a.preventDefault(),s.focus()):!a.shiftKey&&document.activeElement===s&&(a.preventDefault(),u.focus())},children:(0,m.jsxs)("div",{className:"dshtd-modal dshtd-confirm",role:"alertdialog","aria-modal":"true","aria-label":e.title,tabIndex:-1,ref:i,onClick:a=>a.stopPropagation(),children:[(0,m.jsxs)("div",{className:"dshtd-confirm-body",children:[(0,m.jsx)("span",{className:"dshtd-confirm-title",children:e.title}),(0,m.jsx)("span",{className:"dshtd-confirm-text",children:e.message}),e.subject?(0,m.jsx)("span",{className:"dshtd-confirm-subject",children:e.subject}):null]}),(0,m.jsxs)("div",{className:"dshtd-confirm-foot",children:[(0,m.jsx)("button",{className:"dshtd-btn",ref:o,onClick:r,children:"Cancel"}),(0,m.jsx)("button",{className:"dshtd-btn danger",onClick:t,children:e.confirmLabel})]})]})}),document.body)}function Op({item:e,store:r,onClose:i,knownReleases:o,knownSprints:t}){let[n,a]=E.default.useState(e.title),[c,u]=E.default.useState(e.description??""),s=E.default.useRef(null),l=E.default.useCallback(()=>{let g=vt(n),I=Vn(c);r.update(k=>{let P=k;return g&&g!==e.title&&(P=ee(P,e.id,{title:g})),I!==(e.description??"")&&(P=ee(P,e.id,{description:I})),P})},[n,c,e,r]),f=E.default.useCallback(()=>{l(),i()},[l,i]);E.default.useEffect(()=>{let g=document.activeElement;return s.current?.focus(),()=>g?.focus?.()},[]);let b=g=>{if(g.stopPropagation(),g.key==="Escape"){g.preventDefault(),f();return}if(g.key!=="Tab")return;let I=s.current?.querySelectorAll('button, input, textarea, select, [tabindex]:not([tabindex="-1"])');if(!I||I.length===0)return;let k=I[0],P=I[I.length-1];g.shiftKey&&document.activeElement===k?(g.preventDefault(),P.focus()):!g.shiftKey&&document.activeElement===P&&(g.preventDefault(),k.focus())},v=Kn(e);return(0,su.createPortal)((0,m.jsx)("div",{className:"dshtd-modal-backdrop",onClick:f,onKeyDown:b,children:(0,m.jsxs)("div",{className:"dshtd-modal",role:"dialog","aria-modal":"true","aria-label":`Task: ${e.title}`,tabIndex:-1,ref:s,onClick:g=>g.stopPropagation(),children:[(0,m.jsxs)("div",{className:"dshtd-modal-head",children:[(0,m.jsx)("input",{className:"dshtd-modal-title",value:n,"aria-label":"Task title",onChange:g=>a(g.target.value),onBlur:()=>{let g=vt(n);!g||g===e.title||r.update(I=>ee(I,e.id,{title:g}))}}),(0,m.jsx)("button",{className:"dshtd-icon",title:"Close","aria-label":"Close task details",onClick:f,children:(0,m.jsx)(le,{path:Q.close})})]}),(0,m.jsxs)("div",{className:"dshtd-modal-body",children:[(0,m.jsx)("textarea",{className:"dshtd-modal-desc",value:c,placeholder:"Description \u2014 acceptance criteria, repro steps, links\u2026","aria-label":"Task description",onChange:g=>u(g.target.value),onBlur:()=>{let g=Vn(c);g!==(e.description??"")&&r.update(I=>ee(I,e.id,{description:g}))}}),(0,m.jsxs)("div",{className:"dshtd-modal-grid",children:[(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Status",(0,m.jsx)("select",{className:"dshtd-select",value:e.status,onChange:g=>r.update(I=>Wn(I,e.id,g.target.value)),children:Ze.map(g=>(0,m.jsx)("option",{value:g,children:Bn[g]},g))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Priority",(0,m.jsx)("select",{className:"dshtd-select",value:e.priority,onChange:g=>r.update(I=>uu(I,e.id,g.target.value)),children:gt.map(g=>(0,m.jsx)("option",{value:g,children:Qt[g]},g))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Release",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-releases",defaultValue:e.release??"",placeholder:"v1.2.0",onBlur:g=>r.update(I=>ee(I,e.id,{release:g.target.value}))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Sprint",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-sprints",defaultValue:e.sprint??"",placeholder:"Sprint 24",onBlur:g=>r.update(I=>ee(I,e.id,{sprint:g.target.value}))})]}),(0,m.jsxs)("label",{className:"dshtd-modal-label",children:["Due date",(0,m.jsx)("input",{className:"dshtd-input",type:"date",defaultValue:e.dueDate??"",onChange:g=>r.update(I=>ee(I,e.id,{dueDate:g.target.value}))})]})]}),(0,m.jsx)("datalist",{id:"dshtd-releases",children:o.map(g=>(0,m.jsx)("option",{value:g},g))}),(0,m.jsx)("datalist",{id:"dshtd-sprints",children:t.map(g=>(0,m.jsx)("option",{value:g},g))})]}),(0,m.jsxs)("div",{className:"dshtd-modal-foot",children:[(0,m.jsxs)("span",{children:["Created ",Ht(e.createdAt)," ago",e.completedAt?` \xB7 completed ${Ht(e.completedAt)} ago`:"",v?" \xB7 overdue":""]}),(0,m.jsx)("button",{className:"dshtd-btn primary",onClick:f,children:"Done"})]})]})}),document.body)}function Kg({item:e,store:r}){return(0,m.jsx)("select",{className:`dshtd-status s-${e.status}`,value:e.status,"aria-label":`Status of "${e.title}"`,title:"Change status",onClick:i=>i.stopPropagation(),onChange:i=>r.update(o=>Wn(o,e.id,i.target.value)),children:Ze.map(i=>(0,m.jsx)("option",{value:i,children:Bn[i]},i))})}function Gg({item:e,index:r,total:i,store:o,knownReleases:t,knownSprints:n,onOpen:a,onDelete:c}){let[u,s]=E.default.useState(!1),[l,f]=E.default.useState(e.title),[b,v]=E.default.useState(!1),g=q(e),I=ie(e),k=()=>{let P=vt(l);s(!1),!(!P||P===e.title)&&o.update(Ee=>ee(Ee,e.id,{title:P}))};return g?(0,m.jsxs)("li",{className:"dshtd-row archived",children:[(0,m.jsx)("span",{className:"dshtd-badge","aria-hidden":"true",children:(0,m.jsx)(le,{path:Q.check})}),(0,m.jsx)("span",{className:"dshtd-text",children:e.title}),e.release?(0,m.jsx)("span",{className:"dshtd-chip rel",children:e.release}):null,(0,m.jsx)("span",{className:"dshtd-age",title:"When this was archived",children:Ht(e.archivedAt??0)}),(0,m.jsxs)("span",{className:"dshtd-rowbtns",children:[(0,m.jsx)("button",{className:"dshtd-icon",title:"Restore to the active list","aria-label":`Restore "${e.title}"`,onClick:()=>o.update(P=>_p(P,e.id)),children:(0,m.jsx)(le,{path:Q.restore})}),(0,m.jsx)("button",{className:"dshtd-icon danger",title:"Delete permanently","aria-label":`Permanently delete "${e.title}"`,onClick:c,children:(0,m.jsx)(le,{path:Q.close})})]})]}):(0,m.jsxs)("li",{className:"dshtd-item",children:[(0,m.jsxs)("div",{className:`dshtd-row${I?" done":""}`,children:[(0,m.jsx)("input",{type:"checkbox",className:"dshtd-check",checked:I,"aria-label":I?`Mark "${e.title}" as not done`:`Mark "${e.title}" as done`,onChange:()=>o.update(P=>xp(P,e.id))}),u?(0,m.jsx)("input",{className:"dshtd-edit",value:l,autoFocus:!0,"aria-label":"Edit task title",onChange:P=>f(P.target.value),onBlur:k,onKeyDown:P=>{P.stopPropagation(),P.key==="Enter"?(P.preventDefault(),k()):P.key==="Escape"&&(P.preventDefault(),f(e.title),s(!1))}}):(0,m.jsx)("span",{className:"dshtd-text",title:"Click to open \xB7 double-click to rename inline",onClick:a,onDoubleClick:P=>{P.stopPropagation(),f(e.title),s(!0)},children:e.title}),u?null:(0,m.jsxs)("span",{className:"dshtd-chips",children:[e.priority!==Fn?(0,m.jsx)("span",{className:`dshtd-chip ${e.priority}`,title:Qt[e.priority],children:e.priority.toUpperCase()}):null,e.release?(0,m.jsx)("span",{className:"dshtd-chip rel",title:`Release ${e.release}`,children:e.release}):null,e.sprint?(0,m.jsx)("span",{className:"dshtd-chip",title:`Sprint ${e.sprint}`,children:e.sprint}):null,e.dueDate?(0,m.jsx)("span",{className:`dshtd-chip${Kn(e)?" due-over":Pp(e)?" due-today":""}`,title:`Due ${e.dueDate}${Kn(e)?" \u2014 overdue":""}`,children:jp(e.dueDate)}):null,(0,m.jsx)(Kg,{item:e,store:o})]}),(0,m.jsxs)("span",{className:"dshtd-rowbtns",children:[(0,m.jsx)("button",{className:"dshtd-icon",title:b?"Hide details":"Show details","aria-label":`${b?"Hide":"Show"} details for "${e.title}"`,"aria-expanded":b,onClick:()=>v(P=>!P),children:(0,m.jsx)(le,{path:b?Q.collapse:Q.expand})}),(0,m.jsx)("button",{className:"dshtd-icon",title:"Move up","aria-label":`Move "${e.title}" up`,disabled:r===0,onClick:()=>o.update(P=>au(P,e.id,-1)),children:(0,m.jsx)(le,{path:Q.up})}),(0,m.jsx)("button",{className:"dshtd-icon",title:"Move down","aria-label":`Move "${e.title}" down`,disabled:r===i-1,onClick:()=>o.update(P=>au(P,e.id,1)),children:(0,m.jsx)(le,{path:Q.down})}),I?(0,m.jsx)("button",{className:"dshtd-icon",title:"Archive","aria-label":`Archive "${e.title}"`,onClick:()=>o.update(P=>yp(P,e.id)),children:(0,m.jsx)(le,{path:Q.archive})}):null,(0,m.jsx)("button",{className:"dshtd-icon danger",title:"Delete","aria-label":`Delete "${e.title}"`,onClick:c,children:(0,m.jsx)(le,{path:Q.close})})]})]}),b?(0,m.jsx)(Bg,{item:e,store:o,knownReleases:t,knownSprints:n}):null]})}function Bg({item:e,store:r,knownReleases:i,knownSprints:o}){let[t,n]=E.default.useState(e.description??""),[a,c]=E.default.useState(e.release??""),[u,s]=E.default.useState(e.sprint??"");return(0,m.jsxs)("div",{className:"dshtd-detail",children:[(0,m.jsx)("textarea",{className:"dshtd-desc",value:t,placeholder:"Description \u2014 acceptance criteria, repro steps, links\u2026","aria-label":`Description of "${e.title}"`,onChange:l=>n(l.target.value),onKeyDown:l=>l.stopPropagation(),onBlur:()=>{let l=Vn(t);l!==(e.description??"")&&r.update(f=>ee(f,e.id,{description:l}))}}),(0,m.jsxs)("div",{className:"dshtd-fields",children:[(0,m.jsxs)("label",{className:"dshtd-field",children:["Release",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-releases",value:a,placeholder:"v1.2.0",onChange:l=>c(l.target.value),onKeyDown:l=>l.stopPropagation(),onBlur:()=>{(ze(a)??"")!==(e.release??"")&&r.update(l=>ee(l,e.id,{release:a}))}})]}),(0,m.jsxs)("label",{className:"dshtd-field",children:["Sprint",(0,m.jsx)("input",{className:"dshtd-input",list:"dshtd-sprints",value:u,placeholder:"Sprint 24",onChange:l=>s(l.target.value),onKeyDown:l=>l.stopPropagation(),onBlur:()=>{(ze(u)??"")!==(e.sprint??"")&&r.update(l=>ee(l,e.id,{sprint:u}))}})]}),(0,m.jsxs)("label",{className:"dshtd-field",children:["Priority",(0,m.jsx)("select",{className:"dshtd-select",value:e.priority,onChange:l=>r.update(f=>uu(f,e.id,l.target.value)),children:gt.map(l=>(0,m.jsx)("option",{value:l,children:Qt[l]},l))})]}),(0,m.jsxs)("span",{className:"dshtd-field",children:["Created ",Ht(e.createdAt)," ago"]})]}),(0,m.jsx)("datalist",{id:"dshtd-releases",children:i.map(l=>(0,m.jsx)("option",{value:l},l))}),(0,m.jsx)("datalist",{id:"dshtd-sprints",children:o.map(l=>(0,m.jsx)("option",{value:l},l))})]})}var Wg=[{id:"all",label:"All"},{id:"open",label:"Open"},{id:"in-progress",label:"In Progress"},{id:"blocked",label:"Blocked"},{id:"backlog",label:"Backlog"},{id:"done",label:"Done"},{id:"archived",label:"Archive"}],Xg=[{id:"none",label:"None"},{id:"status",label:"Status"},{id:"release",label:"Release"},{id:"sprint",label:"Sprint"},{id:"priority",label:"Priority"}];function qg(e,r,i){return r==="all"?i.total:r==="open"?i.open:r==="archived"?i.archived:ht(e).filter(o=>o.status===r).length}function Np({store:e}){let[r,i]=E.default.useState("all"),[o,t]=E.default.useState("none"),[n,a]=E.default.useState(""),[c,u]=E.default.useState({}),[s,l]=E.default.useState(null),[f,b]=E.default.useState(null);E.default.useEffect(()=>{Mg()},[]),E.default.useEffect(()=>{e&&e.ensure()},[e]);let v=E.default.useSyncExternalStore(e?e.subscribe:Hg,e?e.getSnapshot:vp,e?e.getSnapshot:vp);if(!e)return(0,m.jsx)("div",{className:"dshtd",children:(0,m.jsxs)("div",{className:"dshtd-empty",children:[(0,m.jsx)("b",{children:"No workspace yet"}),"Todos are stored per workspace. Open or create one to start a list."]})});let g=v.items,I=()=>{let w=vt(n);w&&(e.update(te=>[...te,bp(w)]),a(""),r!=="all"&&r!=="open"&&r!=="todo"&&i("all"))},k=$p(g),P=ht(g),Ee=Ip(g,r),Y=wp(Ee,o),Z=cu(g,"release"),R=cu(g,"sprint"),$t=s===null?void 0:g.find(w=>w.id===s),er=w=>{let te=q(w);b({title:te?"Delete permanently":"Delete task",message:te?"This removes the task from the archive for good. This cannot be undone.":"This deletes the task outright. Archiving keeps it recoverable instead.",subject:w.title,confirmLabel:"Delete",onConfirm:()=>e.update(qn=>qn.filter(Ae=>Ae.id!==w.id))})};return(0,m.jsxs)("div",{className:"dshtd",children:[(0,m.jsxs)("div",{className:"dshtd-head",children:[(0,m.jsx)("span",{className:"dshtd-title",children:"Todo"}),(0,m.jsx)("span",{className:"dshtd-progress",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":k.percent,"aria-label":"Todo completion",children:(0,m.jsx)("i",{style:{width:`${k.percent}%`}})}),(0,m.jsxs)("span",{className:"dshtd-score",children:[k.done,"/",k.total," done",k.inProgress>0?` \xB7 ${k.inProgress} in progress`:"",k.blocked>0?` \xB7 ${k.blocked} blocked`:""]})]}),(0,m.jsx)("div",{className:"dshtd-filters",role:"group","aria-label":"Filter todos",children:Wg.map(w=>{let te=qg(g,w.id,k);return te===0&&w.id!=="all"&&w.id!=="open"?null:(0,m.jsxs)("button",{className:"dshtd-filter","aria-pressed":r===w.id,onClick:()=>i(w.id),children:[w.label,w.id!=="all"&&te>0?` (${te})`:null]},w.id)})}),(0,m.jsxs)("div",{className:"dshtd-tools",children:[(0,m.jsx)("label",{htmlFor:"dshtd-groupby",children:"Group by"}),(0,m.jsx)("select",{id:"dshtd-groupby",className:"dshtd-select",value:o,onChange:w=>t(w.target.value),children:Xg.map(w=>(0,m.jsx)("option",{value:w.id,children:w.label},w.id))})]}),(0,m.jsxs)("div",{className:"dshtd-addrow",children:[(0,m.jsx)("input",{className:"dshtd-add",value:n,placeholder:"What needs doing?","aria-label":"Add a todo",disabled:v.status!=="ready",onChange:w=>a(w.target.value),onKeyDown:w=>{w.stopPropagation(),w.key==="Enter"?(w.preventDefault(),I()):w.key==="Escape"&&(w.preventDefault(),a(""))}}),(0,m.jsx)("button",{className:"dshtd-addbtn",disabled:!vt(n)||v.status!=="ready",onClick:I,children:"Add"})]}),(0,m.jsx)("div",{className:"dshtd-scroll",children:v.status==="loading"?(0,m.jsx)("div",{className:"dshtd-empty",children:"Loading\u2026"}):v.status==="error"?(0,m.jsxs)("div",{className:"dshtd-empty",children:[(0,m.jsx)("b",{children:"Couldn't load todos"}),v.error]}):Ee.length===0?(0,m.jsx)("div",{className:"dshtd-empty",children:r==="archived"?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"Nothing archived yet"}),"Check items off, then use \u201CArchive completed\u201D to file them away. Archived items stay here until you delete them."]}):k.total===0?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"No tasks yet"}),"Add your first one above \u2014 this list belongs to the current workspace."]}):r==="open"?(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"All done \u{1F389}"}),"Nothing open right now."]}):(0,m.jsxs)(m.Fragment,{children:[(0,m.jsx)("b",{children:"Nothing here"}),"No tasks match this filter."]})}):Y.map(w=>{let te=w.items.filter(ie).length,qn=w.items.length===0?0:Math.round(te/w.items.length*100),Ae=c[w.key]===!0;return(0,m.jsxs)("section",{className:"dshtd-group",children:[o!=="none"?(0,m.jsxs)("button",{className:"dshtd-ghead","aria-expanded":!Ae,onClick:()=>u(Ie=>({...Ie,[w.key]:!Ae})),children:[(0,m.jsx)(le,{path:Ae?Q.expand:Q.collapse}),w.label,(0,m.jsxs)("span",{className:"dshtd-gcount",children:[te,"/",w.items.length]}),(0,m.jsx)("span",{className:"dshtd-gbar","aria-hidden":"true",children:(0,m.jsx)("i",{style:{width:`${qn}%`}})})]}):null,Ae?null:(0,m.jsx)("ul",{className:"dshtd-list",children:w.items.map(Ie=>(0,m.jsx)(Gg,{item:Ie,index:P.indexOf(Ie),total:P.length,store:e,knownReleases:Z,knownSprints:R,onOpen:()=>l(Ie.id),onDelete:()=>er(Ie)},Ie.id))})]},w.key)})}),(0,m.jsxs)("div",{className:"dshtd-foot",children:[(0,m.jsxs)("span",{children:[k.open," open \xB7 ",k.done," done",k.archived>0?` \xB7 ${k.archived} archived`:null,v.saving?(0,m.jsx)("span",{className:"dshtd-state",children:" \xB7 saving\u2026"}):null,v.error&&v.status==="ready"?(0,m.jsxs)("span",{className:"dshtd-state err",children:[" \xB7 ",v.error]}):null]}),r==="archived"?k.archived>0?(0,m.jsx)("button",{className:"dshtd-link danger",title:"Permanently delete every archived item",onClick:()=>b({title:"Delete archived tasks",message:`Permanently delete ${k.archived} archived ${k.archived===1?"task":"tasks"}? This cannot be undone.`,confirmLabel:"Delete all",onConfirm:()=>e.update(zp)}),children:"Delete archived"}):null:k.done>0?(0,m.jsx)("button",{className:"dshtd-link",title:"Move completed items to the archive \u2014 they stay recoverable",onClick:()=>e.update(kp),children:"Archive completed"}):null]}),$t?(0,m.jsx)(Op,{item:$t,store:e,onClose:()=>l(null),knownReleases:Z,knownSprints:R}):null,f?(0,m.jsx)(Up,{pending:f,onClose:()=>b(null)}):null]})}var Yg={items:[],status:"ready",error:null,saving:!1},Hg=()=>()=>{},vp=()=>Yg;function Qg(e){let r=new Map,i=e;e.effect(()=>{let o=!1,t;return i.remote.$mount(tu).then(n=>{if(o)return void n();t=n}).catch(n=>{console.error("dsh-todo: failed to mount host remote",n)}),()=>{o=!0,r.clear(),t?.()}},"dsh-todo: mount host remote"),e.effect(()=>{let o=i.inject(["remote.dshTodo","workspaces","slots"],t=>{let n=t;n.slots.inject("conversation.view",()=>n.slots.register({name:"conversation.view",id:"todo",order:20,label:()=>"Todo",inject:a=>{let c=n.workspaces.list.getSnapshot().items,u=Tp(c,a);if(u===void 0)return{store:null};let s=r.get(u);return s===void 0&&(s=new Gn(n.remote.dshTodo,u),r.set(u,s)),{store:s}}},Np))});return()=>{o.dispose()}},"dsh-todo: conversation.view registration")}
|
|
435
443
|
|
|
436
444
|
return module.exports;
|
|
437
445
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dennisrongo/dsh-todo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Todo list for DeepSeek Harness (dsh) — a per-workspace task list persisted on disk by the host",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "node build/build.mjs",
|
|
36
36
|
"typecheck": "tsc --noEmit",
|
|
37
|
-
"test": "node test/smoke.mjs && node test/cli.test.mjs",
|
|
37
|
+
"test": "node build/build.mjs && node test/smoke.mjs && node test/cli.test.mjs",
|
|
38
38
|
"test:icons": "node test/icon-probe.mjs",
|
|
39
39
|
"test:modal": "node test/modal-probe.mjs",
|
|
40
40
|
"test:cli": "node test/cli.test.mjs"
|