@burdenoff/planmagnet-fe-sdk 2026.704.3 → 2026.704.4
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/dist/index.d.ts +31 -5
- package/dist/index.js +89 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -271,8 +271,9 @@ interface BoardColumn {
|
|
|
271
271
|
}
|
|
272
272
|
/**
|
|
273
273
|
* The default, ordered board columns. Product-agnostic — no farm semantics.
|
|
274
|
-
*
|
|
275
|
-
*
|
|
274
|
+
* Covers every TaskStatus so a task can never be "orphaned" off the board
|
|
275
|
+
* (a CANCELLED item has a home). Callers can trim/reorder via
|
|
276
|
+
* TaskBoardCoreProps.columns.
|
|
276
277
|
*/
|
|
277
278
|
declare const DEFAULT_BOARD_COLUMNS: BoardColumn[];
|
|
278
279
|
/** Priority filter options (UI order). */
|
|
@@ -432,6 +433,12 @@ interface TaskBoardCoreProps {
|
|
|
432
433
|
columns?: BoardColumn[];
|
|
433
434
|
/** Read-only mode — disables drag-to-move. */
|
|
434
435
|
readonly?: boolean;
|
|
436
|
+
/**
|
|
437
|
+
* Ask for confirmation before a drag-drop moves a task to another column.
|
|
438
|
+
* Defaults to `true` — an accidental drag shouldn't silently change a task's
|
|
439
|
+
* status. Set `false` for instant, Linear-style moves.
|
|
440
|
+
*/
|
|
441
|
+
confirmMove?: boolean;
|
|
435
442
|
/** Hide the board's own header (title + count). */
|
|
436
443
|
hideHeader?: boolean;
|
|
437
444
|
/**
|
|
@@ -483,7 +490,7 @@ interface TaskBoardCoreProps {
|
|
|
483
490
|
* (optimistic cache update + `UPDATE_WORK_ITEM`; reverts on error). Filtering
|
|
484
491
|
* is controlled by the parent toolbar. Farm-free, semantic-token only.
|
|
485
492
|
*/
|
|
486
|
-
declare function TaskBoardCore({ projectId, columns, readonly, hideHeader, priority, type, search, assigneeId, hiddenFields, resolveAssignee, linkSourceProduct, renderLinkIcon, onTaskClick, className, workspaceId: workspaceIdProp, }: TaskBoardCoreProps): react.JSX.Element;
|
|
493
|
+
declare function TaskBoardCore({ projectId, columns, readonly, confirmMove, hideHeader, priority, type, search, assigneeId, hiddenFields, resolveAssignee, linkSourceProduct, renderLinkIcon, onTaskClick, className, workspaceId: workspaceIdProp, }: TaskBoardCoreProps): react.JSX.Element;
|
|
487
494
|
|
|
488
495
|
interface TaskBoardProps extends TaskBoardCoreProps {
|
|
489
496
|
/** Workspace API gateway URL (URL mode). */
|
|
@@ -795,6 +802,14 @@ interface TaskDetailCoreProps {
|
|
|
795
802
|
resolveAssignee?: ResolveAssignee;
|
|
796
803
|
/** Optional host-provided member directory → renders a picker instead of a raw id field. */
|
|
797
804
|
assigneeOptions?: AssigneeOption[];
|
|
805
|
+
/**
|
|
806
|
+
* Product key for cross-product entity links (e.g. "healthybowl"). When set,
|
|
807
|
+
* the read view shows this task's linked records (fields/crops/animals). Opt-in
|
|
808
|
+
* so the SDK stays farm-free.
|
|
809
|
+
*/
|
|
810
|
+
linkSourceProduct?: string;
|
|
811
|
+
/** Optional host hook to render an icon per linked-entity type. */
|
|
812
|
+
renderLinkIcon?: RenderLinkIcon;
|
|
798
813
|
/** Extra classes on the root container. */
|
|
799
814
|
className?: string;
|
|
800
815
|
}
|
|
@@ -803,7 +818,7 @@ interface TaskDetailCoreProps {
|
|
|
803
818
|
* edit. Fetches via `planmagnetWorkItem(id)`, saves via
|
|
804
819
|
* `planmagnetUpdateWorkItem`. BYO-Apollo, semantic-token only, farm-free.
|
|
805
820
|
*/
|
|
806
|
-
declare function TaskDetailCore({ id, readonly, hiddenFields, hideHeader, onUpdated, onDeleted, onError, resolveAssignee, assigneeOptions, className, }: TaskDetailCoreProps): react.JSX.Element;
|
|
821
|
+
declare function TaskDetailCore({ id, readonly, hiddenFields, hideHeader, onUpdated, onDeleted, onError, resolveAssignee, assigneeOptions, linkSourceProduct, renderLinkIcon, className, }: TaskDetailCoreProps): react.JSX.Element;
|
|
807
822
|
|
|
808
823
|
interface TaskDetailProps extends TaskDetailCoreProps {
|
|
809
824
|
/** Workspace API gateway URL (URL mode). */
|
|
@@ -862,6 +877,9 @@ interface TaskLabels {
|
|
|
862
877
|
noTasks: string;
|
|
863
878
|
noTasksFound: string;
|
|
864
879
|
dropHere: string;
|
|
880
|
+
moveConfirmTitle: string;
|
|
881
|
+
moveConfirmPrompt: string;
|
|
882
|
+
moveConfirm: string;
|
|
865
883
|
unassigned: string;
|
|
866
884
|
assigned: string;
|
|
867
885
|
overdue: string;
|
|
@@ -897,6 +915,9 @@ interface TaskLabels {
|
|
|
897
915
|
storyPointsLabel: string;
|
|
898
916
|
labelsLabel: string;
|
|
899
917
|
labelsPlaceholder: string;
|
|
918
|
+
linkedRecordsLabel: string;
|
|
919
|
+
createdLabel: string;
|
|
920
|
+
updatedLabel: string;
|
|
900
921
|
create: string;
|
|
901
922
|
creating: string;
|
|
902
923
|
cancel: string;
|
|
@@ -973,6 +994,11 @@ interface TasksPageCoreProps {
|
|
|
973
994
|
views?: TaskView[];
|
|
974
995
|
/** Initial view. Defaults to "board". */
|
|
975
996
|
defaultView?: TaskView;
|
|
997
|
+
/**
|
|
998
|
+
* Ask for confirmation before a board drag-drop moves a task. Defaults to
|
|
999
|
+
* `true`; set `false` for instant, Linear-style moves.
|
|
1000
|
+
*/
|
|
1001
|
+
confirmMove?: boolean;
|
|
976
1002
|
/** Optional host hook to resolve an assignee id → display name. */
|
|
977
1003
|
resolveAssignee?: ResolveAssignee;
|
|
978
1004
|
/**
|
|
@@ -1022,7 +1048,7 @@ interface TasksPageCoreProps {
|
|
|
1022
1048
|
* BYO-Apollo: reads the ambient `<ApolloProvider>` and takes `workspaceId` from
|
|
1023
1049
|
* a prop or the PlanMagnetProvider context. Semantic tokens only, farm-free.
|
|
1024
1050
|
*/
|
|
1025
|
-
declare function TasksPageCore({ workspaceId: workspaceIdProp, projectId, boardProjectId, columns, readonly, hiddenFields, views, defaultView, resolveAssignee, linkSourceProduct, renderLinkIcon, assigneeOptions, currentActorId, labels, openItemId, header, onTaskSaved, createSurface, detailSurface, className, }: TasksPageCoreProps): react.JSX.Element;
|
|
1051
|
+
declare function TasksPageCore({ workspaceId: workspaceIdProp, projectId, boardProjectId, columns, readonly, hiddenFields, views, defaultView, confirmMove, resolveAssignee, linkSourceProduct, renderLinkIcon, assigneeOptions, currentActorId, labels, openItemId, header, onTaskSaved, createSurface, detailSurface, className, }: TasksPageCoreProps): react.JSX.Element;
|
|
1026
1052
|
|
|
1027
1053
|
interface TasksPageProps extends TasksPageCoreProps {
|
|
1028
1054
|
/** Workspace API gateway URL (URL mode). */
|
package/dist/index.js
CHANGED
|
@@ -536,6 +536,10 @@ function formatDueDate(iso) {
|
|
|
536
536
|
d.getFullYear() === now.getFullYear() ? "MMM d" : "MMM d yyyy"
|
|
537
537
|
);
|
|
538
538
|
}
|
|
539
|
+
function formatDateFull(iso) {
|
|
540
|
+
const d = parseDate(iso);
|
|
541
|
+
return d ? format(d, "MMM d, yyyy") : null;
|
|
542
|
+
}
|
|
539
543
|
function isOverdue(iso, status) {
|
|
540
544
|
const d = parseDate(iso);
|
|
541
545
|
if (!d) return false;
|
|
@@ -632,7 +636,8 @@ var DEFAULT_BOARD_COLUMNS = [
|
|
|
632
636
|
{ status: "IN_PROGRESS", label: "In Progress" },
|
|
633
637
|
{ status: "IN_REVIEW", label: "In Review" },
|
|
634
638
|
{ status: "TESTING", label: "Testing" },
|
|
635
|
-
{ status: "DONE", label: "Done" }
|
|
639
|
+
{ status: "DONE", label: "Done" },
|
|
640
|
+
{ status: "CANCELLED", label: "Cancelled" }
|
|
636
641
|
];
|
|
637
642
|
var TASK_PRIORITIES = [
|
|
638
643
|
"NONE",
|
|
@@ -702,6 +707,9 @@ var DEFAULT_TASK_LABELS = {
|
|
|
702
707
|
noTasks: "No tasks",
|
|
703
708
|
noTasksFound: "No tasks found.",
|
|
704
709
|
dropHere: "Drop here",
|
|
710
|
+
moveConfirmTitle: "Move task?",
|
|
711
|
+
moveConfirmPrompt: 'Move "{task}" to {status}?',
|
|
712
|
+
moveConfirm: "Move",
|
|
705
713
|
unassigned: "Unassigned",
|
|
706
714
|
assigned: "Assigned",
|
|
707
715
|
overdue: "{n} overdue",
|
|
@@ -737,6 +745,9 @@ var DEFAULT_TASK_LABELS = {
|
|
|
737
745
|
storyPointsLabel: "Story points",
|
|
738
746
|
labelsLabel: "Labels",
|
|
739
747
|
labelsPlaceholder: "comma, separated, labels",
|
|
748
|
+
linkedRecordsLabel: "Linked records",
|
|
749
|
+
createdLabel: "Created",
|
|
750
|
+
updatedLabel: "Updated",
|
|
740
751
|
create: "Create task",
|
|
741
752
|
creating: "Creating\u2026",
|
|
742
753
|
cancel: "Cancel",
|
|
@@ -1082,6 +1093,7 @@ function TaskBoardCore({
|
|
|
1082
1093
|
projectId,
|
|
1083
1094
|
columns = DEFAULT_BOARD_COLUMNS,
|
|
1084
1095
|
readonly,
|
|
1096
|
+
confirmMove = true,
|
|
1085
1097
|
hideHeader,
|
|
1086
1098
|
priority = "ALL",
|
|
1087
1099
|
type = "ALL",
|
|
@@ -1104,6 +1116,7 @@ function TaskBoardCore({
|
|
|
1104
1116
|
const [draggingId, setDraggingId] = useState(null);
|
|
1105
1117
|
const [dragOver, setDragOver] = useState(null);
|
|
1106
1118
|
const [moveError, setMoveError] = useState(null);
|
|
1119
|
+
const [pendingMove, setPendingMove] = useState(null);
|
|
1107
1120
|
const [updateItem] = useMutation(UPDATE_WORK_ITEM);
|
|
1108
1121
|
const { data, loading, error } = useQuery(
|
|
1109
1122
|
LIST_WORK_ITEMS,
|
|
@@ -1170,7 +1183,9 @@ function TaskBoardCore({
|
|
|
1170
1183
|
const task = tasks.find((t) => t.id === draggingId);
|
|
1171
1184
|
setDragOver(null);
|
|
1172
1185
|
setDraggingId(null);
|
|
1173
|
-
if (task
|
|
1186
|
+
if (!task || task.status === status) return;
|
|
1187
|
+
if (confirmMove) setPendingMove({ task, toStatus: status });
|
|
1188
|
+
else moveTask(task, status);
|
|
1174
1189
|
};
|
|
1175
1190
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
|
|
1176
1191
|
!hideHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
|
|
@@ -1230,7 +1245,43 @@ function TaskBoardCore({
|
|
|
1230
1245
|
},
|
|
1231
1246
|
col.status
|
|
1232
1247
|
);
|
|
1233
|
-
}) })
|
|
1248
|
+
}) }),
|
|
1249
|
+
/* @__PURE__ */ jsx(
|
|
1250
|
+
Modal,
|
|
1251
|
+
{
|
|
1252
|
+
open: pendingMove != null,
|
|
1253
|
+
onClose: () => setPendingMove(null),
|
|
1254
|
+
ariaLabel: L.moveConfirmTitle,
|
|
1255
|
+
className: "max-w-sm",
|
|
1256
|
+
children: pendingMove && /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-6", children: [
|
|
1257
|
+
/* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-foreground", children: L.moveConfirmTitle }),
|
|
1258
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: L.moveConfirmPrompt.replace("{task}", pendingMove.task.title).replace("{status}", L.status[pendingMove.toStatus]) }),
|
|
1259
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
1260
|
+
/* @__PURE__ */ jsx(
|
|
1261
|
+
"button",
|
|
1262
|
+
{
|
|
1263
|
+
type: "button",
|
|
1264
|
+
onClick: () => setPendingMove(null),
|
|
1265
|
+
className: "rounded-md bg-muted px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted/70",
|
|
1266
|
+
children: L.cancel
|
|
1267
|
+
}
|
|
1268
|
+
),
|
|
1269
|
+
/* @__PURE__ */ jsx(
|
|
1270
|
+
"button",
|
|
1271
|
+
{
|
|
1272
|
+
type: "button",
|
|
1273
|
+
onClick: () => {
|
|
1274
|
+
moveTask(pendingMove.task, pendingMove.toStatus);
|
|
1275
|
+
setPendingMove(null);
|
|
1276
|
+
},
|
|
1277
|
+
className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:brightness-110",
|
|
1278
|
+
children: L.moveConfirm
|
|
1279
|
+
}
|
|
1280
|
+
)
|
|
1281
|
+
] })
|
|
1282
|
+
] })
|
|
1283
|
+
}
|
|
1284
|
+
)
|
|
1234
1285
|
] });
|
|
1235
1286
|
}
|
|
1236
1287
|
function TaskBoard({
|
|
@@ -2415,6 +2466,8 @@ function TaskDetailCore({
|
|
|
2415
2466
|
onError: onError2,
|
|
2416
2467
|
resolveAssignee,
|
|
2417
2468
|
assigneeOptions,
|
|
2469
|
+
linkSourceProduct,
|
|
2470
|
+
renderLinkIcon,
|
|
2418
2471
|
className
|
|
2419
2472
|
}) {
|
|
2420
2473
|
const client = useApolloClient();
|
|
@@ -2428,6 +2481,11 @@ function TaskDetailCore({
|
|
|
2428
2481
|
skip: !id
|
|
2429
2482
|
});
|
|
2430
2483
|
const item = data?.planmagnetWorkItem ?? null;
|
|
2484
|
+
const { linksByItem } = useWorkItemLinks(
|
|
2485
|
+
item?.workspaceId,
|
|
2486
|
+
linkSourceProduct
|
|
2487
|
+
);
|
|
2488
|
+
const links = item ? linksByItem.get(item.id) ?? [] : [];
|
|
2431
2489
|
const [editing, setEditing] = useState(false);
|
|
2432
2490
|
const [confirmingDelete, setConfirmingDelete] = useState(false);
|
|
2433
2491
|
const [title, setTitle] = useState("");
|
|
@@ -2595,7 +2653,7 @@ function TaskDetailCore({
|
|
|
2595
2653
|
),
|
|
2596
2654
|
/* @__PURE__ */ jsx("span", { className: "text-foreground", children: resolveAssignee?.(item.assigneeId)?.name ?? L.assigned })
|
|
2597
2655
|
] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: L.unassigned }) }),
|
|
2598
|
-
!hidden.has("dueDate") && /* @__PURE__ */ jsx(Field, { label: L.dueDateLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.dueDate ?? "\u2014" }) }),
|
|
2656
|
+
!hidden.has("dueDate") && /* @__PURE__ */ jsx(Field, { label: L.dueDateLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: formatDateFull(item.dueDate) ?? "\u2014" }) }),
|
|
2599
2657
|
!hidden.has("storyPoints") && /* @__PURE__ */ jsx(Field, { label: L.storyPointsLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.storyPoints ?? 0 }) }),
|
|
2600
2658
|
!hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
|
|
2601
2659
|
/* @__PURE__ */ jsx("dt", { className: labelClass2, children: L.description }),
|
|
@@ -2611,6 +2669,29 @@ function TaskDetailCore({
|
|
|
2611
2669
|
},
|
|
2612
2670
|
l
|
|
2613
2671
|
)) })
|
|
2672
|
+
] }),
|
|
2673
|
+
links.length > 0 && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
|
|
2674
|
+
/* @__PURE__ */ jsx("dt", { className: labelClass2, children: L.linkedRecordsLabel }),
|
|
2675
|
+
/* @__PURE__ */ jsx("dd", { className: "mt-1 flex flex-wrap gap-1.5", children: links.map((link) => /* @__PURE__ */ jsx(
|
|
2676
|
+
LinkChip,
|
|
2677
|
+
{
|
|
2678
|
+
link,
|
|
2679
|
+
renderIcon: renderLinkIcon
|
|
2680
|
+
},
|
|
2681
|
+
link.id
|
|
2682
|
+
)) })
|
|
2683
|
+
] }),
|
|
2684
|
+
(item.createdAt || item.updatedAt) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-1 border-t border-border pt-3 text-xs text-muted-foreground sm:col-span-2", children: [
|
|
2685
|
+
item.createdAt && /* @__PURE__ */ jsxs("span", { children: [
|
|
2686
|
+
L.createdLabel,
|
|
2687
|
+
" ",
|
|
2688
|
+
formatDateFull(item.createdAt)
|
|
2689
|
+
] }),
|
|
2690
|
+
item.updatedAt && /* @__PURE__ */ jsxs("span", { children: [
|
|
2691
|
+
L.updatedLabel,
|
|
2692
|
+
" ",
|
|
2693
|
+
formatDateFull(item.updatedAt)
|
|
2694
|
+
] })
|
|
2614
2695
|
] })
|
|
2615
2696
|
] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSave, className: "space-y-4", children: [
|
|
2616
2697
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
@@ -2818,6 +2899,7 @@ function TasksPageCore({
|
|
|
2818
2899
|
hiddenFields,
|
|
2819
2900
|
views,
|
|
2820
2901
|
defaultView = "board",
|
|
2902
|
+
confirmMove,
|
|
2821
2903
|
resolveAssignee,
|
|
2822
2904
|
linkSourceProduct,
|
|
2823
2905
|
renderLinkIcon,
|
|
@@ -2896,6 +2978,8 @@ function TasksPageCore({
|
|
|
2896
2978
|
hiddenFields,
|
|
2897
2979
|
resolveAssignee,
|
|
2898
2980
|
assigneeOptions,
|
|
2981
|
+
linkSourceProduct,
|
|
2982
|
+
renderLinkIcon,
|
|
2899
2983
|
onUpdated: handleUpdated,
|
|
2900
2984
|
onDeleted: handleDeleted
|
|
2901
2985
|
}
|
|
@@ -2939,6 +3023,7 @@ function TasksPageCore({
|
|
|
2939
3023
|
projectId: boardProjectId,
|
|
2940
3024
|
columns,
|
|
2941
3025
|
readonly,
|
|
3026
|
+
confirmMove,
|
|
2942
3027
|
hideHeader: true,
|
|
2943
3028
|
priority,
|
|
2944
3029
|
type,
|