@baack-software/baack-ts-tasks 0.0.0-stage → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +158 -2
  3. package/dist/activity.d.ts +20 -0
  4. package/dist/activity.d.ts.map +1 -0
  5. package/dist/activity.js +75 -0
  6. package/dist/activity.js.map +1 -0
  7. package/dist/blockers.d.ts +28 -0
  8. package/dist/blockers.d.ts.map +1 -0
  9. package/dist/blockers.js +134 -0
  10. package/dist/blockers.js.map +1 -0
  11. package/dist/conflicts.d.ts +50 -0
  12. package/dist/conflicts.d.ts.map +1 -0
  13. package/dist/conflicts.js +73 -0
  14. package/dist/conflicts.js.map +1 -0
  15. package/dist/draft.d.ts +45 -0
  16. package/dist/draft.d.ts.map +1 -0
  17. package/dist/draft.js +155 -0
  18. package/dist/draft.js.map +1 -0
  19. package/dist/errors.d.ts +30 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +37 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/index.d.ts +11 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +11 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/react/TaskActivity.d.ts +15 -0
  28. package/dist/react/TaskActivity.d.ts.map +1 -0
  29. package/dist/react/TaskActivity.js +60 -0
  30. package/dist/react/TaskActivity.js.map +1 -0
  31. package/dist/react/TaskBoard.d.ts +38 -0
  32. package/dist/react/TaskBoard.d.ts.map +1 -0
  33. package/dist/react/TaskBoard.js +85 -0
  34. package/dist/react/TaskBoard.js.map +1 -0
  35. package/dist/react/TaskConflicts.d.ts +26 -0
  36. package/dist/react/TaskConflicts.d.ts.map +1 -0
  37. package/dist/react/TaskConflicts.js +87 -0
  38. package/dist/react/TaskConflicts.js.map +1 -0
  39. package/dist/react/TaskCreateForm.d.ts +13 -0
  40. package/dist/react/TaskCreateForm.d.ts.map +1 -0
  41. package/dist/react/TaskCreateForm.js +68 -0
  42. package/dist/react/TaskCreateForm.js.map +1 -0
  43. package/dist/react/TaskEditor.d.ts +33 -0
  44. package/dist/react/TaskEditor.d.ts.map +1 -0
  45. package/dist/react/TaskEditor.js +172 -0
  46. package/dist/react/TaskEditor.js.map +1 -0
  47. package/dist/react/TaskFilters.d.ts +15 -0
  48. package/dist/react/TaskFilters.d.ts.map +1 -0
  49. package/dist/react/TaskFilters.js +48 -0
  50. package/dist/react/TaskFilters.js.map +1 -0
  51. package/dist/react/TaskView.d.ts +30 -0
  52. package/dist/react/TaskView.d.ts.map +1 -0
  53. package/dist/react/TaskView.js +108 -0
  54. package/dist/react/TaskView.js.map +1 -0
  55. package/dist/react/TasksAbout.d.ts +24 -0
  56. package/dist/react/TasksAbout.d.ts.map +1 -0
  57. package/dist/react/TasksAbout.js +82 -0
  58. package/dist/react/TasksAbout.js.map +1 -0
  59. package/dist/react/copy.d.ts +154 -0
  60. package/dist/react/copy.d.ts.map +1 -0
  61. package/dist/react/copy.js +173 -0
  62. package/dist/react/copy.js.map +1 -0
  63. package/dist/react/fields.d.ts +36 -0
  64. package/dist/react/fields.d.ts.map +1 -0
  65. package/dist/react/fields.js +21 -0
  66. package/dist/react/fields.js.map +1 -0
  67. package/dist/react/hooks.d.ts +9 -0
  68. package/dist/react/hooks.d.ts.map +1 -0
  69. package/dist/react/hooks.js +31 -0
  70. package/dist/react/hooks.js.map +1 -0
  71. package/dist/react/index.d.ts +13 -0
  72. package/dist/react/index.d.ts.map +1 -0
  73. package/dist/react/index.js +13 -0
  74. package/dist/react/index.js.map +1 -0
  75. package/dist/react/parts.d.ts +55 -0
  76. package/dist/react/parts.d.ts.map +1 -0
  77. package/dist/react/parts.js +92 -0
  78. package/dist/react/parts.js.map +1 -0
  79. package/dist/react/ui/alert.d.ts +11 -0
  80. package/dist/react/ui/alert.d.ts.map +1 -0
  81. package/dist/react/ui/alert.js +29 -0
  82. package/dist/react/ui/alert.js.map +1 -0
  83. package/dist/react/ui/avatar.d.ts +12 -0
  84. package/dist/react/ui/avatar.d.ts.map +1 -0
  85. package/dist/react/ui/avatar.js +24 -0
  86. package/dist/react/ui/avatar.js.map +1 -0
  87. package/dist/react/ui/badge.d.ts +10 -0
  88. package/dist/react/ui/badge.d.ts.map +1 -0
  89. package/dist/react/ui/badge.js +26 -0
  90. package/dist/react/ui/badge.js.map +1 -0
  91. package/dist/react/ui/button.d.ts +11 -0
  92. package/dist/react/ui/button.d.ts.map +1 -0
  93. package/dist/react/ui/button.js +37 -0
  94. package/dist/react/ui/button.js.map +1 -0
  95. package/dist/react/ui/card.d.ts +12 -0
  96. package/dist/react/ui/card.d.ts.map +1 -0
  97. package/dist/react/ui/card.js +26 -0
  98. package/dist/react/ui/card.js.map +1 -0
  99. package/dist/react/ui/input.d.ts +4 -0
  100. package/dist/react/ui/input.d.ts.map +1 -0
  101. package/dist/react/ui/input.js +8 -0
  102. package/dist/react/ui/input.js.map +1 -0
  103. package/dist/react/ui/label.d.ts +5 -0
  104. package/dist/react/ui/label.d.ts.map +1 -0
  105. package/dist/react/ui/label.js +10 -0
  106. package/dist/react/ui/label.js.map +1 -0
  107. package/dist/react/ui/radio-group.d.ts +6 -0
  108. package/dist/react/ui/radio-group.d.ts.map +1 -0
  109. package/dist/react/ui/radio-group.js +12 -0
  110. package/dist/react/ui/radio-group.js.map +1 -0
  111. package/dist/react/ui/select.d.ts +16 -0
  112. package/dist/react/ui/select.d.ts.map +1 -0
  113. package/dist/react/ui/select.js +37 -0
  114. package/dist/react/ui/select.js.map +1 -0
  115. package/dist/react/ui/separator.d.ts +5 -0
  116. package/dist/react/ui/separator.d.ts.map +1 -0
  117. package/dist/react/ui/separator.js +10 -0
  118. package/dist/react/ui/separator.js.map +1 -0
  119. package/dist/react/ui/sheet.d.ts +15 -0
  120. package/dist/react/ui/sheet.d.ts.map +1 -0
  121. package/dist/react/ui/sheet.js +38 -0
  122. package/dist/react/ui/sheet.js.map +1 -0
  123. package/dist/react/ui/skeleton.d.ts +3 -0
  124. package/dist/react/ui/skeleton.d.ts.map +1 -0
  125. package/dist/react/ui/skeleton.js +7 -0
  126. package/dist/react/ui/skeleton.js.map +1 -0
  127. package/dist/react/ui/table.d.ts +11 -0
  128. package/dist/react/ui/table.d.ts.map +1 -0
  129. package/dist/react/ui/table.js +29 -0
  130. package/dist/react/ui/table.js.map +1 -0
  131. package/dist/react/ui/tabs.d.ts +12 -0
  132. package/dist/react/ui/tabs.d.ts.map +1 -0
  133. package/dist/react/ui/tabs.js +31 -0
  134. package/dist/react/ui/tabs.js.map +1 -0
  135. package/dist/react/ui/textarea.d.ts +4 -0
  136. package/dist/react/ui/textarea.d.ts.map +1 -0
  137. package/dist/react/ui/textarea.js +8 -0
  138. package/dist/react/ui/textarea.js.map +1 -0
  139. package/dist/react/ui/toggle-group.d.ts +11 -0
  140. package/dist/react/ui/toggle-group.d.ts.map +1 -0
  141. package/dist/react/ui/toggle-group.js +25 -0
  142. package/dist/react/ui/toggle-group.js.map +1 -0
  143. package/dist/react/ui/toggle.d.ts +10 -0
  144. package/dist/react/ui/toggle.d.ts.map +1 -0
  145. package/dist/react/ui/toggle.js +27 -0
  146. package/dist/react/ui/toggle.js.map +1 -0
  147. package/dist/refs.d.ts +16 -0
  148. package/dist/refs.d.ts.map +1 -0
  149. package/dist/refs.js +43 -0
  150. package/dist/refs.js.map +1 -0
  151. package/dist/server/index.d.ts +4 -0
  152. package/dist/server/index.d.ts.map +1 -0
  153. package/dist/server/index.js +4 -0
  154. package/dist/server/index.js.map +1 -0
  155. package/dist/server/recipes.d.ts +39 -0
  156. package/dist/server/recipes.d.ts.map +1 -0
  157. package/dist/server/recipes.js +81 -0
  158. package/dist/server/recipes.js.map +1 -0
  159. package/dist/server/webhooks.d.ts +135 -0
  160. package/dist/server/webhooks.d.ts.map +1 -0
  161. package/dist/server/webhooks.js +243 -0
  162. package/dist/server/webhooks.js.map +1 -0
  163. package/dist/store.d.ts +124 -0
  164. package/dist/store.d.ts.map +1 -0
  165. package/dist/store.js +443 -0
  166. package/dist/store.js.map +1 -0
  167. package/dist/task-client.d.ts +137 -0
  168. package/dist/task-client.d.ts.map +1 -0
  169. package/dist/task-client.js +271 -0
  170. package/dist/task-client.js.map +1 -0
  171. package/dist/tasks.d.ts +84 -0
  172. package/dist/tasks.d.ts.map +1 -0
  173. package/dist/tasks.js +208 -0
  174. package/dist/tasks.js.map +1 -0
  175. package/dist/time.d.ts +15 -0
  176. package/dist/time.d.ts.map +1 -0
  177. package/dist/time.js +34 -0
  178. package/dist/time.js.map +1 -0
  179. package/dist/types.d.ts +74 -0
  180. package/dist/types.d.ts.map +1 -0
  181. package/dist/types.js +9 -0
  182. package/dist/types.js.map +1 -0
  183. package/package.json +101 -4
  184. package/src/activity.ts +86 -0
  185. package/src/blockers.ts +134 -0
  186. package/src/conflicts.ts +115 -0
  187. package/src/draft.ts +162 -0
  188. package/src/errors.ts +40 -0
  189. package/src/index.ts +10 -0
  190. package/src/react/TaskActivity.tsx +187 -0
  191. package/src/react/TaskBoard.tsx +264 -0
  192. package/src/react/TaskConflicts.tsx +217 -0
  193. package/src/react/TaskCreateForm.tsx +165 -0
  194. package/src/react/TaskEditor.tsx +485 -0
  195. package/src/react/TaskFilters.tsx +122 -0
  196. package/src/react/TaskView.tsx +291 -0
  197. package/src/react/TasksAbout.tsx +226 -0
  198. package/src/react/copy.tsx +253 -0
  199. package/src/react/fields.tsx +104 -0
  200. package/src/react/hooks.ts +41 -0
  201. package/src/react/index.ts +12 -0
  202. package/src/react/parts.tsx +176 -0
  203. package/src/react/ui/README.md +6 -0
  204. package/src/react/ui/alert.tsx +75 -0
  205. package/src/react/ui/avatar.tsx +109 -0
  206. package/src/react/ui/badge.tsx +48 -0
  207. package/src/react/ui/button.tsx +66 -0
  208. package/src/react/ui/card.tsx +102 -0
  209. package/src/react/ui/input.tsx +18 -0
  210. package/src/react/ui/label.tsx +23 -0
  211. package/src/react/ui/radio-group.tsx +41 -0
  212. package/src/react/ui/select.tsx +189 -0
  213. package/src/react/ui/separator.tsx +27 -0
  214. package/src/react/ui/sheet.tsx +145 -0
  215. package/src/react/ui/skeleton.tsx +13 -0
  216. package/src/react/ui/table.tsx +113 -0
  217. package/src/react/ui/tabs.tsx +89 -0
  218. package/src/react/ui/textarea.tsx +17 -0
  219. package/src/react/ui/toggle-group.tsx +89 -0
  220. package/src/react/ui/toggle.tsx +44 -0
  221. package/src/refs.ts +49 -0
  222. package/src/server/index.ts +3 -0
  223. package/src/server/recipes.ts +107 -0
  224. package/src/server/webhooks.ts +369 -0
  225. package/src/store.ts +538 -0
  226. package/src/task-client.ts +373 -0
  227. package/src/tasks.ts +263 -0
  228. package/src/time.ts +35 -0
  229. package/src/types.ts +101 -0
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useId } from 'react';
3
+ import { cn } from 'cn';
4
+ import { lookupFrom, openBlockers } from "../blockers.js";
5
+ import { groupByStage, groupByWorkflow, groupTasks, isOverdue, NONE_KEY, } from "../tasks.js";
6
+ import { parseTimestamp } from "../time.js";
7
+ import { priorityCopy, statusCopy, useCopy } from "./copy.js";
8
+ import { BlockedBadge, DueDate, nameOf, PersonAvatar, PriorityBadge, StatusBadge } from "./parts.js";
9
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./ui/table.js";
10
+ function useBlocked(directory) {
11
+ const lookup = lookupFrom(directory.tasks);
12
+ return (task) => openBlockers(task, lookup);
13
+ }
14
+ /** A task as a board card: priority, blocked, title, due date and assignee. Opens the task when chosen. */
15
+ export function TaskCard({ task, directory, selected, blockedBy, onOpen, id, now, }) {
16
+ const copy = useCopy();
17
+ const ids = useId();
18
+ const assignee = task.assignee ? { urn: task.assignee.urn, name: nameOf(directory, task.assignee) } : null;
19
+ const blockedTitle = blockedBy.map((urn) => copy('blocked_by', { name: nameOf(directory, { urn }) })).join(', ');
20
+ // The title names the card; the rest describes it, so screen readers hear the title first and the details after.
21
+ const details = [
22
+ copy(priorityCopy(task.priority)),
23
+ dueLabel(task, copy, now),
24
+ assignee ? `${copy('field_assignee')}: ${assignee.name}` : copy('option_unassigned'),
25
+ blockedTitle,
26
+ ]
27
+ .filter(Boolean)
28
+ .join(', ');
29
+ return (_jsxs("button", { type: "button", id: id, onClick: () => onOpen(task), "aria-current": selected ? 'true' : undefined, "aria-labelledby": `${ids}-title`, "aria-describedby": `${ids}-details`, className: cn('border-border bg-card hover:border-primary focus-visible:outline-primary w-full rounded-lg border p-2.5', 'text-left transition-colors focus-visible:outline-2', selected && 'border-primary ring-primary/30 ring-2'), children: [_jsxs("span", { "aria-hidden": "true", className: "flex flex-wrap items-center gap-1.5", children: [_jsx(PriorityBadge, { priority: task.priority }), blockedBy.length > 0 && _jsx(BlockedBadge, { title: blockedTitle })] }), _jsx("span", { id: `${ids}-title`, className: "mt-1.5 block text-[13px] leading-snug font-medium", children: task.title }), _jsxs("span", { "aria-hidden": "true", className: "mt-2 flex items-center justify-between gap-1", children: [_jsx(DueDate, { task: task, ...(now ? { now } : {}) }), _jsx(PersonAvatar, { person: assignee })] }), _jsx("span", { id: `${ids}-details`, className: "sr-only", children: details })] }));
30
+ }
31
+ /** The due date as words, for a screen reader: "Due 12 Oct, overdue", or "No due date". */
32
+ function dueLabel(task, copy, now) {
33
+ const due = parseTimestamp(task.dueTimestamp);
34
+ if (!due)
35
+ return copy('due_none');
36
+ const text = `${copy('field_due')} ${due.toLocaleDateString(undefined, { day: 'numeric', month: 'short' })}`;
37
+ return isOverdue(task, now) ? `${text}, ${copy('due_overdue')}` : text;
38
+ }
39
+ /** Tasks in columns by status, priority, assignee, project, workflow or workflow stage, each with its count. */
40
+ export function TaskBoard({ tasks, directory, selected, onOpen, itemId, now, groupBy = 'status', sort, hideEmpty = ['UNDEFINED'], workflow, }) {
41
+ const copy = useCopy();
42
+ const ids = useId();
43
+ const blocked = useBlocked(directory);
44
+ const grouped = groupBy === 'workflowStage' && workflow
45
+ ? groupByStage(tasks, workflow)
46
+ : groupBy === 'workflow'
47
+ ? groupByWorkflow(tasks, directory.workflows ?? [])
48
+ : groupTasks(tasks, groupBy);
49
+ const groups = [...grouped].filter(([key, group]) => group.length > 0 || !hideEmpty.includes(key));
50
+ const columnName = (key) => {
51
+ switch (groupBy) {
52
+ case 'status':
53
+ return copy(statusCopy(key));
54
+ case 'priority':
55
+ return copy(priorityCopy(key));
56
+ case 'assignee':
57
+ return key === NONE_KEY ? copy('option_unassigned') : nameOf(directory, { urn: key });
58
+ case 'project':
59
+ return key === NONE_KEY ? copy('option_no_project') : nameOf(directory, { urn: key });
60
+ case 'workflow':
61
+ return key === NONE_KEY
62
+ ? copy('option_no_workflow')
63
+ : (directory.workflows?.find((w) => w.urn === key)?.name ?? nameOf(directory, { urn: key }));
64
+ case 'workflowStage':
65
+ return key === NONE_KEY ? copy('option_no_stage') : nameOf(directory, { urn: key });
66
+ }
67
+ };
68
+ return (_jsx("div", { className: "relative grid auto-cols-[minmax(15rem,1fr)] grid-flow-col gap-3 overflow-x-auto pb-2", children: groups.map(([key, group], index) => {
69
+ const sorted = sort ? [...group].sort(sort) : group;
70
+ const name = columnName(key);
71
+ const count = group.length === 1 ? copy('tasks_count_one') : copy('tasks_count', { count: group.length });
72
+ return (_jsxs("section", { "aria-labelledby": `${ids}-column-${index}`, className: "bg-muted/50 rounded-xl p-2", children: [_jsxs("h3", { id: `${ids}-column-${index}`, "aria-label": `${name}, ${count}`, className: "text-muted-foreground mb-2 flex items-center justify-between px-1 text-xs font-semibold tracking-wide uppercase", children: [name, _jsx("span", { className: "bg-background text-foreground rounded-full px-1.5 text-[11px] tabular-nums", children: group.length })] }), _jsx("ul", { className: "space-y-2", children: sorted.map((task) => (_jsx("li", { children: _jsx(TaskCard, { task: task, directory: directory, selected: task.urn === selected, blockedBy: blocked(task), onOpen: onOpen, ...(itemId ? { id: itemId(task.urn) } : {}), ...(now ? { now } : {}) }) }, task.urn))) })] }, key));
73
+ }) }));
74
+ }
75
+ /** Tasks as table rows: title, status, priority, assignee, project and due date. The title opens the task. */
76
+ export function TaskTable({ tasks, directory, selected, onOpen, itemId, now }) {
77
+ const copy = useCopy();
78
+ const blocked = useBlocked(directory);
79
+ return (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: copy('field_title') }), _jsx(TableHead, { children: copy('field_status') }), _jsx(TableHead, { children: copy('field_priority') }), _jsx(TableHead, { children: copy('field_assignee') }), _jsx(TableHead, { children: copy('field_project') }), _jsx(TableHead, { children: copy('field_due') })] }) }), _jsx(TableBody, { children: tasks.map((task) => {
80
+ const assignee = task.assignee ? { urn: task.assignee.urn, name: nameOf(directory, task.assignee) } : null;
81
+ const blockers = blocked(task);
82
+ return (_jsxs(TableRow, { "data-state": task.urn === selected ? 'selected' : undefined, children: [_jsxs(TableCell, { className: "max-w-80 whitespace-normal", children: [_jsx("button", { type: "button", ...(itemId ? { id: itemId(task.urn) } : {}), onClick: () => onOpen(task), "aria-current": task.urn === selected ? 'true' : undefined, className: "hover:text-primary text-left font-medium hover:underline", children: task.title }), blockers.length > 0 && (_jsx("span", { className: "ml-2", children: _jsx(BlockedBadge, {}) }))] }), _jsx(TableCell, { children: _jsx(StatusBadge, { status: task.status }) }), _jsx(TableCell, { children: _jsx(PriorityBadge, { priority: task.priority }) }), _jsx(TableCell, { children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx(PersonAvatar, { person: assignee }), _jsx("span", { className: cn(!assignee && 'text-muted-foreground'), children: assignee?.name ?? copy('option_unassigned') })] }) }), _jsx(TableCell, { className: cn(!task.project && 'text-muted-foreground'), children: task.project ? nameOf(directory, task.project) : copy('option_no_project') }), _jsx(TableCell, { children: _jsx(DueDate, { task: task, ...(now ? { now } : {}) }) })] }, task.urn));
83
+ }) })] }));
84
+ }
85
+ //# sourceMappingURL=TaskBoard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskBoard.js","sourceRoot":"","sources":["../../src/react/TaskBoard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { ConflictChoices, TaskConflict, TaskField } from '../conflicts.ts';
2
+ import type { TaskListField } from '../types.ts';
3
+ import { type TaskCopyName } from './copy.tsx';
4
+ import { type TaskDirectory } from './parts.tsx';
5
+ /** The copy name of a field's label. */
6
+ export declare const fieldCopy: (field: TaskField | TaskListField) => TaskCopyName;
7
+ export interface TaskConflictsProps {
8
+ conflicts: readonly TaskConflict[];
9
+ directory: TaskDirectory;
10
+ /** Saves with the choices made. Fields left on "keep mine" are saved again; "use theirs" drops the change. */
11
+ onResolve: (choices: ConflictChoices) => void;
12
+ /** Keeps everything the other person saved, dropping this person's conflicting changes. */
13
+ onDiscard: () => void;
14
+ }
15
+ /**
16
+ * Shown when someone else changed the same fields while this person was editing: each field with both values, and a
17
+ * choice to keep mine or use theirs. Takes focus when it appears.
18
+ */
19
+ export declare function TaskConflicts({ conflicts, directory, onResolve, onDiscard }: TaskConflictsProps): import("react").JSX.Element;
20
+ export interface ChangedElsewhereProps {
21
+ fields: readonly (TaskField | TaskListField)[];
22
+ onDismiss?: (() => void) | undefined;
23
+ }
24
+ /** A note that someone else changed other fields while this person was editing, which were kept. */
25
+ export declare function ChangedElsewhere({ fields, onDismiss }: ChangedElsewhereProps): import("react").JSX.Element;
26
+ //# sourceMappingURL=TaskConflicts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskConflicts.d.ts","sourceRoot":"","sources":["../../src/react/TaskConflicts.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,EAAkB,MAAM,iBAAiB,CAAC;AAEhG,OAAO,KAAK,EAAO,aAAa,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAqC,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAuBzD,wCAAwC;AACxC,eAAO,MAAM,SAAS,GAAI,OAAO,SAAS,GAAG,aAAa,KAAG,YAAiC,CAAC;AAE/F,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IACnC,SAAS,EAAE,aAAa,CAAC;IACzB,8GAA8G;IAC9G,SAAS,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC9C,2FAA2F;IAC3F,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,kBAAkB,+BA4F/F;AAuDD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,CAAC,EAAE,CAAC;IAC/C,SAAS,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACtC;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,qBAAqB,+BAgB5E"}
@@ -0,0 +1,87 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useId, useRef, useState } from 'react';
3
+ import { TriangleAlert } from 'lucide-react';
4
+ import { cn } from 'cn';
5
+ import { parseTimestamp } from "../time.js";
6
+ import { priorityCopy, statusCopy, useCopy } from "./copy.js";
7
+ import { nameOf } from "./parts.js";
8
+ import { Alert, AlertDescription } from "./ui/alert.js";
9
+ import { Button } from "./ui/button.js";
10
+ import { Label } from "./ui/label.js";
11
+ import { RadioGroup, RadioGroupItem } from "./ui/radio-group.js";
12
+ const FIELD_COPY = {
13
+ title: 'field_title',
14
+ description: 'field_description',
15
+ status: 'field_status',
16
+ priority: 'field_priority',
17
+ dueTimestamp: 'field_due',
18
+ assignee: 'field_assignee',
19
+ project: 'field_project',
20
+ workflowStage: 'field_stage',
21
+ blockedBy: 'blockers_heading',
22
+ blocking: 'field_blocking',
23
+ associatedTasks: 'related_heading',
24
+ associatedEntities: 'related_heading',
25
+ associatedIdentities: 'related_heading',
26
+ associatedCompanies: 'related_heading',
27
+ };
28
+ /** The copy name of a field's label. */
29
+ export const fieldCopy = (field) => FIELD_COPY[field];
30
+ /**
31
+ * Shown when someone else changed the same fields while this person was editing: each field with both values, and a
32
+ * choice to keep mine or use theirs. Takes focus when it appears.
33
+ */
34
+ export function TaskConflicts({ conflicts, directory, onResolve, onDiscard }) {
35
+ const copy = useCopy();
36
+ const ids = useId();
37
+ const heading = useRef(null);
38
+ const [choices, setChoices] = useState({});
39
+ useEffect(() => {
40
+ setChoices({});
41
+ heading.current?.focus();
42
+ }, [conflicts]);
43
+ return (_jsxs("section", { role: "alertdialog", "aria-labelledby": `${ids}-heading`, "aria-describedby": `${ids}-intro`, className: "grid gap-3 rounded-lg border border-amber-500/50 bg-amber-500/5 p-3", children: [_jsxs("div", { className: "grid gap-1", children: [_jsxs("h3", { id: `${ids}-heading`, ref: heading, tabIndex: -1, className: "flex items-center gap-1.5 text-sm font-semibold outline-none", children: [_jsx(TriangleAlert, { "aria-hidden": "true", className: "size-4 text-amber-600 dark:text-amber-400" }), copy('conflict_heading')] }), _jsx("p", { id: `${ids}-intro`, className: "text-muted-foreground text-sm", children: copy('conflict_intro') })] }), conflicts.map((conflict) => {
44
+ const id = `${ids}-${conflict.field}`;
45
+ const choice = choices[conflict.field] ?? 'mine';
46
+ return (_jsxs("div", { className: "grid gap-1.5", children: [_jsx("p", { id: id, className: "text-xs font-semibold tracking-wide uppercase", children: copy(fieldCopy(conflict.field)) }), _jsx(RadioGroup, { "aria-labelledby": id, value: choice, onValueChange: (value) => setChoices({ ...choices, [conflict.field]: value }), className: "gap-1.5", children: ['mine', 'theirs'].map((side) => (_jsxs(Label, { htmlFor: `${id}-${side}`, className: cn('bg-card items-start gap-2.5 rounded-md border p-2 font-normal', choice === side && 'border-primary'), children: [_jsx(RadioGroupItem, { id: `${id}-${side}`, value: side, "aria-labelledby": `${id}-${side}-label`, "aria-describedby": `${id}-${side}-value`, className: "mt-0.5" }), _jsxs("span", { className: "grid min-w-0 gap-0.5", children: [_jsx("span", { id: `${id}-${side}-label`, className: "font-medium", children: copy(side === 'mine' ? 'conflict_mine' : 'conflict_theirs') }), _jsx(FieldValue, { id: `${id}-${side}-value`, field: conflict.field, value: conflict[side], directory: directory })] })] }, side))) })] }, conflict.field));
47
+ }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { size: "sm", onClick: () => onResolve(choices), children: copy('conflict_save') }), _jsx(Button, { size: "sm", variant: "ghost", onClick: onDiscard, children: copy('conflict_discard') })] })] }));
48
+ }
49
+ /** A field's value as the reader would say it: names for references, labels for status and priority. */
50
+ function FieldValue({ id, field, value, directory, }) {
51
+ const copy = useCopy();
52
+ const empty = value == null || value === '';
53
+ let text;
54
+ switch (field) {
55
+ case 'status':
56
+ text = empty ? copy('value_empty') : copy(statusCopy(value));
57
+ break;
58
+ case 'priority':
59
+ text = empty ? copy('value_empty') : copy(priorityCopy(value));
60
+ break;
61
+ case 'assignee':
62
+ text = empty ? copy('option_unassigned') : nameOf(directory, value);
63
+ break;
64
+ case 'project':
65
+ text = empty ? copy('option_no_project') : nameOf(directory, value);
66
+ break;
67
+ case 'workflowStage':
68
+ text = empty ? copy('value_empty') : nameOf(directory, value);
69
+ break;
70
+ case 'dueTimestamp': {
71
+ const due = parseTimestamp(value);
72
+ text = due ? due.toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }) : copy('due_none');
73
+ break;
74
+ }
75
+ default:
76
+ text = empty ? copy('value_empty') : value;
77
+ }
78
+ return (_jsx("span", { id: id, className: cn('text-muted-foreground text-sm break-words', field === 'description' && 'max-h-32 overflow-y-auto whitespace-pre-wrap', empty && 'italic'), children: text }));
79
+ }
80
+ /** A note that someone else changed other fields while this person was editing, which were kept. */
81
+ export function ChangedElsewhere({ fields, onDismiss }) {
82
+ const copy = useCopy();
83
+ const names = [...new Set(fields.map((field) => copy(fieldCopy(field))))];
84
+ const list = new Intl.ListFormat(undefined, { type: 'conjunction' }).format(names);
85
+ return (_jsx(Alert, { children: _jsxs(AlertDescription, { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsx("span", { children: copy('changed_elsewhere', { fields: list }) }), onDismiss && (_jsx(Button, { size: "xs", variant: "ghost", onClick: onDismiss, children: copy('changed_elsewhere_dismiss') }))] }) }));
86
+ }
87
+ //# sourceMappingURL=TaskConflicts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskConflicts.js","sourceRoot":"","sources":["../../src/react/TaskConflicts.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAqB,MAAM,WAAY,CAAC;AAClF,OAAO,EAAE,MAAM,EAAsB,MAAM,YAAa,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAgB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAiB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAsB,CAAC;AAElE,MAAM,UAAU,GAAoD;IAClE,KAAK,EAAE,aAAa;IACpB,WAAW,EAAE,mBAAmB;IAChC,MAAM,EAAE,cAAc;IACtB,QAAQ,EAAE,gBAAgB;IAC1B,YAAY,EAAE,WAAW;IACzB,QAAQ,EAAE,gBAAgB;IAC1B,OAAO,EAAE,eAAe;IACxB,aAAa,EAAE,aAAa;IAC5B,SAAS,EAAE,kBAAkB;IAC7B,QAAQ,EAAE,gBAAgB;IAC1B,eAAe,EAAE,iBAAiB;IAClC,kBAAkB,EAAE,iBAAiB;IACrC,oBAAoB,EAAE,iBAAiB;IACvC,mBAAmB,EAAE,iBAAiB;CACvC,CAAC;AAEF,wCAAwC;AACxC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAgC,EAAgB,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAW/F;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAsB;IAC9F,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;IACpB,MAAM,OAAO,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAkB,EAAE,CAAC,CAAC;IAE5D,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,EAAE,CAAC,CAAC;QACf,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhB,OAAO,CACL,mBACE,IAAI,EAAC,aAAa,qBACD,GAAG,GAAG,UAAU,sBACf,GAAG,GAAG,QAAQ,EAChC,SAAS,EAAC,qEAAqE,aAE/E,eAAK,SAAS,EAAC,YAAY,aACzB,cACE,EAAE,EAAE,GAAG,GAAG,UAAU,EACpB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,CAAC,CAAC,EACZ,SAAS,EAAC,8DAA8D,aAExE,KAAC,aAAa,mBAAa,MAAM,EAAC,SAAS,EAAC,2CAA2C,GAAG,EACzF,IAAI,CAAC,kBAAkB,CAAC,IACtB,EACL,YAAG,EAAE,EAAE,GAAG,GAAG,QAAQ,EAAE,SAAS,EAAC,+BAA+B,YAC7D,IAAI,CAAC,gBAAgB,CAAC,GACrB,IACA,EAEL,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC1B,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACtC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;gBACjD,OAAO,CACL,eAA0B,SAAS,EAAC,cAAc,aAChD,YAAG,EAAE,EAAE,EAAE,EAAE,SAAS,EAAC,+CAA+C,YACjE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAC9B,EACJ,KAAC,UAAU,uBACQ,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAA0B,EAAE,CAAC,EAClG,SAAS,EAAC,SAAS,YAEjB,CAAC,MAAM,EAAE,QAAQ,CAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAC3C,MAAC,KAAK,IAEJ,OAAO,EAAE,GAAG,EAAE,IAAI,IAAI,EAAE,EACxB,SAAS,EAAE,EAAE,CACX,+DAA+D,EAC/D,MAAM,KAAK,IAAI,IAAI,gBAAgB,CACpC,aAGD,KAAC,cAAc,IACb,EAAE,EAAE,GAAG,EAAE,IAAI,IAAI,EAAE,EACnB,KAAK,EAAE,IAAI,qBACM,GAAG,EAAE,IAAI,IAAI,QAAQ,sBACpB,GAAG,EAAE,IAAI,IAAI,QAAQ,EACvC,SAAS,EAAC,QAAQ,GAClB,EACF,gBAAM,SAAS,EAAC,sBAAsB,aACpC,eAAM,EAAE,EAAE,GAAG,EAAE,IAAI,IAAI,QAAQ,EAAE,SAAS,EAAC,aAAa,YACrD,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC,GACvD,EACP,KAAC,UAAU,IACT,EAAE,EAAE,GAAG,EAAE,IAAI,IAAI,QAAQ,EACzB,KAAK,EAAE,QAAQ,CAAC,KAAK,EACrB,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EACrB,SAAS,EAAE,SAAS,GACpB,IACG,KAzBF,IAAI,CA0BH,CACT,CAAC,GACS,KAxCL,QAAQ,CAAC,KAAK,CAyClB,CACP,CAAC;YACJ,CAAC,CAAC,EAEF,eAAK,SAAS,EAAC,sBAAsB,aACnC,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,YAChD,IAAI,CAAC,eAAe,CAAC,GACf,EACT,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAE,SAAS,YACjD,IAAI,CAAC,kBAAkB,CAAC,GAClB,IACL,IACE,CACX,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,SAAS,UAAU,CAAC,EAClB,EAAE,EACF,KAAK,EACL,KAAK,EACL,SAAS,GAMV;IACC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;IAC5C,IAAI,IAAY,CAAC;IACjB,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,QAAQ;YACX,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAmB,CAAC,CAAC,CAAC;YAC3E,MAAM;QACR,KAAK,UAAU;YACb,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,KAAqB,CAAC,CAAC,CAAC;YAC/E,MAAM;QACR,KAAK,UAAU;YACb,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAY,CAAC,CAAC;YAC3E,MAAM;QACR,KAAK,SAAS;YACZ,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAY,CAAC,CAAC;YAC3E,MAAM;QACR,KAAK,eAAe;YAClB,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAY,CAAC,CAAC;YACrE,MAAM;QACR,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,GAAG,GAAG,cAAc,CAAC,KAAkC,CAAC,CAAC;YAC/D,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3G,MAAM;QACR,CAAC;QACD;YACE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAE,KAAgB,CAAC;IAC3D,CAAC;IACD,OAAO,CACL,eACE,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,EAAE,CACX,2CAA2C,EAC3C,KAAK,KAAK,aAAa,IAAI,8CAA8C,EACzE,KAAK,IAAI,QAAQ,CAClB,YAEA,IAAI,GACA,CACR,CAAC;AACJ,CAAC;AAOD,oGAAoG;AACpG,MAAM,UAAU,gBAAgB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAyB;IAC3E,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnF,OAAO,CACL,KAAC,KAAK,cACJ,MAAC,gBAAgB,IAAC,SAAS,EAAC,mDAAmD,aAC7E,yBAAO,IAAI,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAQ,EACzD,SAAS,IAAI,CACZ,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAE,SAAS,YACjD,IAAI,CAAC,2BAA2B,CAAC,GAC3B,CACV,IACgB,GACb,CACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { DraftInput } from '../draft.ts';
2
+ import { type TaskDirectory } from './parts.tsx';
3
+ export type NewTask = Omit<DraftInput, 'owner'>;
4
+ export interface TaskCreateFormProps {
5
+ directory: TaskDirectory;
6
+ onCreate: (task: NewTask) => Promise<unknown>;
7
+ onCancel?: (() => void) | undefined;
8
+ /** Starting values, e.g. the project or assignee the view is filtered to. */
9
+ initial?: Partial<NewTask>;
10
+ }
11
+ /** A form for a new task: title (required), description, priority, assignee, project and due date. */
12
+ export declare function TaskCreateForm({ directory, onCreate, onCancel, initial }: TaskCreateFormProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=TaskCreateForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskCreateForm.d.ts","sourceRoot":"","sources":["../../src/react/TaskCreateForm.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAM/D,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACpC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5B;AAED,sGAAsG;AACtG,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,mBAAmB,+BA2I7F"}
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useId, useRef, useState } from 'react';
3
+ import { Plus, X } from 'lucide-react';
4
+ import { TASK_PRIORITIES } from "../tasks.js";
5
+ import { fromLocalInput } from "../time.js";
6
+ import { priorityCopy, useCopy } from "./copy.js";
7
+ import { ChoiceSelect, Field, NONE } from "./fields.js";
8
+ import { PersonAvatar } from "./parts.js";
9
+ import { Alert, AlertDescription } from "./ui/alert.js";
10
+ import { Button } from "./ui/button.js";
11
+ import { Input } from "./ui/input.js";
12
+ import { Textarea } from "./ui/textarea.js";
13
+ /** A form for a new task: title (required), description, priority, assignee, project and due date. */
14
+ export function TaskCreateForm({ directory, onCreate, onCancel, initial }) {
15
+ const copy = useCopy();
16
+ const ids = useId();
17
+ const title = useRef(null);
18
+ const [values, setValues] = useState({
19
+ title: initial?.title ?? '',
20
+ description: initial?.description ?? '',
21
+ priority: initial?.priority ?? 'NONE',
22
+ assignee: initial?.assignee?.urn ?? NONE,
23
+ project: initial?.project?.urn ?? NONE,
24
+ due: '',
25
+ });
26
+ const [sending, setSending] = useState(false);
27
+ const [failed, setFailed] = useState(false);
28
+ useEffect(() => title.current?.focus(), []);
29
+ const set = (key, value) => setValues((current) => ({ ...current, [key]: value }));
30
+ return (_jsxs("form", { "aria-labelledby": `${ids}-heading`, className: "grid gap-4", onSubmit: async (event) => {
31
+ event.preventDefault();
32
+ if (!values.title.trim())
33
+ return;
34
+ setSending(true);
35
+ setFailed(false);
36
+ const due = fromLocalInput(values.due);
37
+ try {
38
+ await onCreate({
39
+ ...initial,
40
+ title: values.title.trim(),
41
+ description: values.description,
42
+ priority: values.priority,
43
+ ...(values.assignee === NONE ? {} : { assignee: { urn: values.assignee } }),
44
+ ...(values.project === NONE ? {} : { project: { urn: values.project } }),
45
+ ...(due === undefined ? {} : { dueTimestamp: due }),
46
+ });
47
+ }
48
+ catch {
49
+ setFailed(true);
50
+ }
51
+ finally {
52
+ setSending(false);
53
+ }
54
+ }, children: [_jsxs("header", { className: "flex items-center justify-between gap-2", children: [_jsx("h2", { id: `${ids}-heading`, className: "text-lg font-bold", children: copy('create_heading') }), onCancel && (_jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: onCancel, "aria-label": copy('create_cancel'), children: _jsx(X, { "aria-hidden": "true" }) }))] }), failed && (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: copy('create_failed') }) })), _jsx(Field, { id: `${ids}-title`, label: copy('field_title'), children: _jsx(Input, { ref: title, id: `${ids}-title`, required: true, maxLength: 1024, value: values.title, onChange: (e) => set('title', e.target.value) }) }), _jsx(Field, { id: `${ids}-description`, label: copy('field_description'), children: _jsx(Textarea, { id: `${ids}-description`, rows: 4, value: values.description, onChange: (e) => set('description', e.target.value) }) }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Field, { id: `${ids}-priority`, label: copy('field_priority'), children: _jsx(ChoiceSelect, { id: `${ids}-priority`, value: values.priority, choices: [...TASK_PRIORITIES]
55
+ .reverse()
56
+ .map((priority) => ({ value: priority, label: copy(priorityCopy(priority)) })), onChange: (priority) => set('priority', priority) }) }), _jsx(Field, { id: `${ids}-due`, label: copy('field_due'), children: _jsx(Input, { id: `${ids}-due`, type: "datetime-local", className: "h-7 text-sm", value: values.due, onChange: (e) => set('due', e.target.value) }) }), _jsx(Field, { id: `${ids}-assignee`, label: copy('field_assignee'), children: _jsx(ChoiceSelect, { id: `${ids}-assignee`, value: values.assignee, choices: [
57
+ { value: NONE, label: copy('option_unassigned') },
58
+ ...directory.people.map((person) => ({
59
+ value: person.urn,
60
+ label: person.name,
61
+ icon: _jsx(PersonAvatar, { person: person }),
62
+ })),
63
+ ], onChange: (urn) => set('assignee', urn) }) }), _jsx(Field, { id: `${ids}-project`, label: copy('field_project'), children: _jsx(ChoiceSelect, { id: `${ids}-project`, value: values.project, choices: [
64
+ { value: NONE, label: copy('option_no_project') },
65
+ ...directory.projects.map((project) => ({ value: project.urn, label: project.name })),
66
+ ], onChange: (urn) => set('project', urn) }) })] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { type: "submit", disabled: !values.title.trim() || sending, children: [_jsx(Plus, { "aria-hidden": "true" }), copy('create_submit')] }), onCancel && (_jsx(Button, { type: "button", variant: "ghost", onClick: onCancel, children: copy('create_cancel') }))] })] }));
67
+ }
68
+ //# sourceMappingURL=TaskCreateForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskCreateForm.js","sourceRoot":"","sources":["../../src/react/TaskCreateForm.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { Task } from '@baack-software/baack-ts-client';
3
+ import { type TaskField } from '../conflicts.ts';
4
+ import type { TaskInput, TaskListField } from '../types.ts';
5
+ import { type TaskDirectory } from './parts.tsx';
6
+ export interface TaskEditorProps {
7
+ task: Task;
8
+ directory: TaskDirectory;
9
+ /**
10
+ * Sends a change. Rejections are shown in the editor. A `TaskConflictError` (from `TaskStore.update`, or
11
+ * `TaskClient.update` with `base: task`) opens a panel to choose, field by field, between this person's value and
12
+ * the other one; the choices are sent as another change. Without the store, update `task` to the error's `current`
13
+ * so that change is checked against what the person now sees.
14
+ */
15
+ onChange: (changes: TaskInput) => Promise<unknown>;
16
+ /** Fields someone else changed while this person was editing, shown as a note. */
17
+ changedElsewhere?: readonly (TaskField | TaskListField)[] | undefined;
18
+ onDismissChangedElsewhere?: (() => void) | undefined;
19
+ onDelete?: (() => Promise<unknown>) | undefined;
20
+ onClose?: (() => void) | undefined;
21
+ /** Shown while a change is being saved. */
22
+ saving?: boolean;
23
+ /** The activity log, usually a `TaskActivity`. */
24
+ activity?: ReactNode;
25
+ /** Focus the heading when the editor opens, for keyboard and screen reader users. Default true. */
26
+ focusOnOpen?: boolean;
27
+ }
28
+ /**
29
+ * Every field of a task, saved as it changes: selects at once, text when it loses focus. Blockers can be added
30
+ * and removed, related records are listed, and the activity log goes below.
31
+ */
32
+ export declare function TaskEditor({ task, directory, onChange, onDelete, onClose, saving, activity, focusOnOpen, changedElsewhere, onDismissChangedElsewhere, }: TaskEditorProps): import("react").JSX.Element;
33
+ //# sourceMappingURL=TaskEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskEditor.d.ts","sourceRoot":"","sources":["../../src/react/TaskEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,KAAK,EAAE,IAAI,EAA4B,MAAM,iCAAiC,CAAC;AAGtF,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAMtF,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5D,OAAO,EAA4D,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ3G,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,aAAa,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,CAAC,EAAE,GAAG,SAAS,CAAC;IACtE,yBAAyB,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,mGAAmG;IACnG,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,WAAkB,EAClB,gBAAgB,EAChB,yBAAyB,GAC1B,EAAE,eAAe,+BA0QjB"}
@@ -0,0 +1,172 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useId, useRef, useState } from 'react';
3
+ import { Building2, FileText, Link2, Trash2, UserRound, X } from 'lucide-react';
4
+ import { wouldCreateCycle } from "../blockers.js";
5
+ import { resolveConflicts } from "../conflicts.js";
6
+ import { isEmptyChange } from "../draft.js";
7
+ import { TaskConflictError } from "../errors.js";
8
+ import { withoutRef, withRef } from "../refs.js";
9
+ import { isOpen, TASK_PRIORITIES, TASK_STATUSES, workflowStages } from "../tasks.js";
10
+ import { fromLocalInput, toLocalInput } from "../time.js";
11
+ import { priorityCopy, statusCopy, useCopy } from "./copy.js";
12
+ import { ChoiceSelect, Field, NONE } from "./fields.js";
13
+ import { nameOf, PersonAvatar, StatusBadge, Timestamp } from "./parts.js";
14
+ import { Alert, AlertDescription } from "./ui/alert.js";
15
+ import { Button } from "./ui/button.js";
16
+ import { Input } from "./ui/input.js";
17
+ import { Separator } from "./ui/separator.js";
18
+ import { Textarea } from "./ui/textarea.js";
19
+ import { ChangedElsewhere, TaskConflicts } from "./TaskConflicts.js";
20
+ /**
21
+ * Every field of a task, saved as it changes: selects at once, text when it loses focus. Blockers can be added
22
+ * and removed, related records are listed, and the activity log goes below.
23
+ */
24
+ export function TaskEditor({ task, directory, onChange, onDelete, onClose, saving, activity, focusOnOpen = true, changedElsewhere, onDismissChangedElsewhere, }) {
25
+ const copy = useCopy();
26
+ const ids = useId();
27
+ const heading = useRef(null);
28
+ const [error, setError] = useState();
29
+ const [confirmDelete, setConfirmDelete] = useState(false);
30
+ const stages = (directory.workflows ?? []).flatMap((workflow) => workflow.stages ?? []);
31
+ const [conflict, setConflict] = useState();
32
+ useEffect(() => {
33
+ if (focusOnOpen)
34
+ heading.current?.focus();
35
+ setError(undefined);
36
+ setConfirmDelete(false);
37
+ setConflict(undefined);
38
+ }, [task.urn, focusOnOpen]);
39
+ const save = async (changes) => {
40
+ setError(undefined);
41
+ try {
42
+ await onChange(changes);
43
+ }
44
+ catch (failure) {
45
+ if (failure instanceof TaskConflictError) {
46
+ // Builds on a conflict already open, so choices cover every field this person changed.
47
+ setConflict((open) => ({
48
+ conflicts: [
49
+ ...(open?.conflicts.filter((c) => !failure.conflicts.some((f) => f.field === c.field)) ?? []),
50
+ ...failure.conflicts,
51
+ ],
52
+ changes: { ...open?.changes, ...changes },
53
+ }));
54
+ return;
55
+ }
56
+ const detail = failure instanceof Error && failure.name === 'TaskValidationError' ? failure.message : undefined;
57
+ setError(detail ? `${copy('editor_save_failed')} ${detail}` : copy('editor_save_failed'));
58
+ }
59
+ };
60
+ const others = directory.tasks.filter((t) => t.urn !== task.urn);
61
+ const blockerChoices = others.filter((t) => isOpen(t) &&
62
+ !task.blockedBy?.some((b) => b.urn === t.urn) &&
63
+ !wouldCreateCycle(directory.tasks, task.urn, t.urn));
64
+ return (_jsxs("article", { "aria-labelledby": `${ids}-heading`, className: "grid gap-4", children: [_jsxs("header", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-muted-foreground text-xs", children: copy('editor_label') }), _jsx("h2", { id: `${ids}-heading`, ref: heading, tabIndex: -1, className: "text-lg leading-snug font-bold break-words outline-none", children: task.title })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx("span", { "aria-live": "polite", className: "text-muted-foreground text-xs", children: saving ? copy('editor_saving') : '' }), onClose && (_jsx(Button, { variant: "ghost", size: "icon-sm", onClick: onClose, "aria-label": copy('editor_close'), children: _jsx(X, { "aria-hidden": "true" }) }))] })] }), error && (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })), conflict && (_jsx(TaskConflicts, { conflicts: conflict.conflicts, directory: directory, onResolve: (choices) => {
65
+ const resolved = resolveConflicts(conflict.changes, choices);
66
+ setConflict(undefined);
67
+ if (!isEmptyChange(resolved))
68
+ void save(resolved);
69
+ }, onDiscard: () => setConflict(undefined) })), changedElsewhere && changedElsewhere.length > 0 && (_jsx(ChangedElsewhere, { fields: changedElsewhere, onDismiss: onDismissChangedElsewhere })), _jsx(TextField, { id: `${ids}-title`, label: copy('field_title'), value: task.title, onCommit: (title) => save({ title }), required: true }, `title-${task.urn}`), _jsxs("div", { className: "grid grid-cols-2 gap-x-3 gap-y-3", children: [_jsx(Field, { id: `${ids}-status`, label: copy('field_status'), children: _jsx(ChoiceSelect, { id: `${ids}-status`, value: task.status, choices: TASK_STATUSES.map((status) => ({ value: status, label: copy(statusCopy(status)) })), onChange: (status) => save({ status: status }) }) }), _jsx(Field, { id: `${ids}-priority`, label: copy('field_priority'), children: _jsx(ChoiceSelect, { id: `${ids}-priority`, value: task.priority, choices: [...TASK_PRIORITIES]
70
+ .reverse()
71
+ .map((priority) => ({ value: priority, label: copy(priorityCopy(priority)) })), onChange: (priority) => save({ priority: priority }) }) }), _jsx(Field, { id: `${ids}-assignee`, label: copy('field_assignee'), children: _jsx(ChoiceSelect, { id: `${ids}-assignee`, value: task.assignee?.urn ?? NONE, choices: [
72
+ { value: NONE, label: copy('option_unassigned') },
73
+ ...withCurrent(directory.people, task.assignee, directory).map((person) => ({
74
+ value: person.urn,
75
+ label: person.name,
76
+ icon: _jsx(PersonAvatar, { person: person }),
77
+ })),
78
+ ], onChange: (urn) => save({ assignee: urn === NONE ? null : { urn } }) }) }), _jsx(Field, { id: `${ids}-project`, label: copy('field_project'), children: _jsx(ChoiceSelect, { id: `${ids}-project`, value: task.project?.urn ?? NONE, choices: [
79
+ { value: NONE, label: copy('option_no_project') },
80
+ ...withCurrent(directory.projects, task.project, directory).map((project) => ({
81
+ value: project.urn,
82
+ label: project.name,
83
+ })),
84
+ ], onChange: (urn) => save({ project: urn === NONE ? null : { urn } }) }) }), (directory.workflows?.length || task.workflowStage) && (_jsx(Field, { id: `${ids}-stage`, label: copy('field_stage'), children: _jsx(ChoiceSelect, { id: `${ids}-stage`, value: task.workflowStage?.urn ?? NONE, choices: [
85
+ { value: NONE, label: copy('option_no_stage') },
86
+ // A stage of a workflow the directory doesn't have still shows.
87
+ ...(task.workflowStage && !stages.some((stage) => stage.urn === task.workflowStage?.urn)
88
+ ? [{ value: task.workflowStage.urn, label: nameOf(directory, task.workflowStage) }]
89
+ : []),
90
+ ], groups: (directory.workflows ?? []).map((workflow) => ({
91
+ label: workflow.name,
92
+ choices: workflowStages(workflow).map((stage) => ({ value: stage.urn, label: stage.name })),
93
+ })), onChange: (urn) => save({ workflowStage: urn === NONE ? null : { urn } }) }) })), _jsx(DueField, { id: `${ids}-due`, task: task, onCommit: (dueTimestamp) => save({ dueTimestamp }) }, `due-${task.urn}`), _jsxs("div", { className: "text-muted-foreground grid content-end gap-1 pb-1 text-xs", children: [_jsx("span", { children: copy('field_updated') }), _jsx(Timestamp, { value: task.updatedTimestamp, className: "text-foreground" })] })] }), _jsx(TextField, { id: `${ids}-description`, label: copy('field_description'), value: task.description, onCommit: (description) => save({ description }), multiline: true }, `description-${task.urn}`), _jsxs("section", { "aria-labelledby": `${ids}-blockers`, className: "grid gap-2", children: [_jsx("h3", { id: `${ids}-blockers`, className: "text-xs font-semibold tracking-wide uppercase", children: copy('blockers_heading') }), (task.blockedBy?.length ?? 0) === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: copy('blockers_none') })) : (_jsx("ul", { className: "grid gap-1.5", children: task.blockedBy.map((blocker) => {
94
+ const known = directory.tasks.find((t) => t.urn === blocker.urn);
95
+ const name = nameOf(directory, blocker);
96
+ return (_jsxs("li", { className: "flex items-center gap-2 text-sm", children: [known && _jsx(StatusBadge, { status: known.status }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: name }), _jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": copy('blockers_remove', { name }), onClick: () => save({ blockedBy: withoutRef(task.blockedBy, blocker) }), children: _jsx(X, { "aria-hidden": "true" }) })] }, blocker.urn));
97
+ }) })), blockerChoices.length > 0 && (_jsx(ChoiceSelect, { value: NONE, label: copy('blockers_add'), choices: [
98
+ { value: NONE, label: copy('blockers_add') },
99
+ ...blockerChoices.map((t) => ({ value: t.urn, label: t.title })),
100
+ ], onChange: (urn) => urn !== NONE && save({ blockedBy: withRef(task.blockedBy, urn) }) }, `add-blocker-${task.blockedBy?.length ?? 0}`))] }), _jsx(Related, { task: task, directory: directory, onChange: save }), activity && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), activity] })), onDelete && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), confirmDelete ? (_jsxs("div", { role: "alertdialog", "aria-labelledby": `${ids}-delete`, className: "grid gap-2", children: [_jsx("p", { id: `${ids}-delete`, className: "text-sm", children: copy('task_delete_confirm') }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "destructive", size: "sm", onClick: () => onDelete().catch(() => setError(copy('editor_save_failed'))), children: [_jsx(Trash2, { "aria-hidden": "true" }), copy('task_delete')] }), _jsx(Button, { variant: "ghost", size: "sm", autoFocus: true, onClick: () => setConfirmDelete(false), children: copy('task_delete_cancel') })] })] })) : (_jsxs(Button, { variant: "ghost", size: "sm", className: "text-destructive justify-self-start", onClick: () => setConfirmDelete(true), children: [_jsx(Trash2, { "aria-hidden": "true" }), copy('task_delete')] }))] }))] }));
101
+ }
102
+ /** The directory's choices, plus the current value when the directory doesn't list it, so it still shows. */
103
+ function withCurrent(choices, current, directory) {
104
+ if (!current || choices.some((choice) => choice.urn === current.urn))
105
+ return choices;
106
+ return [...choices, { urn: current.urn, name: nameOf(directory, current) }];
107
+ }
108
+ /** A text input or textarea that saves when it loses focus (or on Enter for a single line), if the value changed. */
109
+ function TextField({ id, label, value, onCommit, multiline, required, }) {
110
+ const [draft, setDraft] = useState(value);
111
+ useEffect(() => setDraft(value), [value]);
112
+ const commit = () => {
113
+ if (draft === value)
114
+ return;
115
+ if (required && !draft.trim())
116
+ return setDraft(value);
117
+ onCommit(draft);
118
+ };
119
+ return (_jsx(Field, { id: id, label: label, children: multiline ? (_jsx(Textarea, { id: id, rows: 5, value: draft, onChange: (e) => setDraft(e.target.value), onBlur: commit })) : (_jsx(Input, { id: id, value: draft, required: required, onChange: (e) => setDraft(e.target.value), onBlur: commit, onKeyDown: (e) => {
120
+ if (e.key === 'Enter')
121
+ commit();
122
+ if (e.key === 'Escape')
123
+ setDraft(value);
124
+ } })) }));
125
+ }
126
+ function DueField({ id, task, onCommit }) {
127
+ const copy = useCopy();
128
+ const value = toLocalInput(task.dueTimestamp);
129
+ const [draft, setDraft] = useState(value);
130
+ useEffect(() => setDraft(value), [value]);
131
+ const commit = (next) => {
132
+ if (next === value)
133
+ return;
134
+ onCommit(fromLocalInput(next) ?? null);
135
+ };
136
+ return (_jsx(Field, { id: id, label: copy('field_due'), children: _jsx(Input, { id: id, type: "datetime-local", className: "h-7 text-sm", value: draft, onChange: (e) => setDraft(e.target.value), onBlur: (e) => commit(e.target.value) }) }));
137
+ }
138
+ /** The kinds of related item, in the order they're shown, with their icon and the heading for adding one. */
139
+ const ASSOCIATIONS = [
140
+ { field: 'associatedIdentities', Icon: UserRound, heading: 'related_people' },
141
+ { field: 'associatedCompanies', Icon: Building2, heading: 'related_companies' },
142
+ { field: 'associatedEntities', Icon: FileText, heading: 'related_entities' },
143
+ { field: 'associatedTasks', Icon: Link2, heading: 'related_tasks' },
144
+ ];
145
+ /** The people, companies, content and tasks the task is associated with, each removable, and a picker to add more. */
146
+ function Related({ task, directory, onChange, }) {
147
+ const copy = useCopy();
148
+ const ids = useId();
149
+ const items = ASSOCIATIONS.flatMap(({ field, Icon }) => (task[field] ?? []).map((item) => ({ field, item, Icon })));
150
+ const offered = {
151
+ associatedIdentities: directory.people,
152
+ associatedCompanies: directory.companies ?? [],
153
+ associatedEntities: directory.entities ?? [],
154
+ associatedTasks: directory.tasks.filter((t) => t.urn !== task.urn).map((t) => ({ urn: t.urn, name: t.title })),
155
+ };
156
+ const groups = ASSOCIATIONS.map(({ field, heading }) => ({
157
+ label: copy(heading),
158
+ choices: offered[field]
159
+ .filter((choice) => !(task[field] ?? []).some((item) => item.urn === choice.urn))
160
+ .map((choice) => ({ value: `${field} ${choice.urn}`, label: choice.name })),
161
+ }));
162
+ return (_jsxs("section", { "aria-labelledby": `${ids}-related`, className: "grid gap-2", children: [_jsx("h3", { id: `${ids}-related`, className: "text-xs font-semibold tracking-wide uppercase", children: copy('related_heading') }), items.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: copy('related_none') })) : (_jsx("ul", { className: "flex flex-wrap gap-1.5 text-xs", children: items.map(({ field, item, Icon }) => {
163
+ const name = nameOf(directory, item);
164
+ return (_jsxs("li", { className: "bg-muted inline-flex items-center gap-1 rounded py-0.5 ps-1.5 pe-0.5", children: [_jsx(Icon, { "aria-hidden": "true", className: "size-3" }), name, _jsx(Button, { variant: "ghost", size: "icon-xs", className: "size-5", "aria-label": copy('related_remove', { name }), onClick: () => onChange({ [field]: withoutRef(task[field], item) }), children: _jsx(X, { "aria-hidden": "true" }) })] }, `${field} ${item.urn}`));
165
+ }) })), groups.some((group) => group.choices.length > 0) && (_jsx(ChoiceSelect, { value: NONE, label: copy('related_add'), choices: [{ value: NONE, label: copy('related_add') }], groups: groups, onChange: (value) => {
166
+ if (value === NONE)
167
+ return;
168
+ const [field, urn] = value.split(' ');
169
+ onChange({ [field]: withRef(task[field], urn) });
170
+ } }, `add-related-${items.length}`))] }));
171
+ }
172
+ //# sourceMappingURL=TaskEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskEditor.js","sourceRoot":"","sources":["../../src/react/TaskEditor.tsx"],"names":[],"mappings":"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"}