@burdenoff/planmagnet-fe-sdk 2026.706.7 → 2026.813.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.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { onError } from '@apollo/client/link/error';
6
6
  import { CombinedGraphQLErrors } from '@apollo/client/errors';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
8
  import { gql } from '@apollo/client';
9
- import { CircleX, CircleCheckBig, CircleDotDashed, CircleDot, Circle, CircleDashed, User, Link2, CalendarDays, Trash2, ChevronUp, ChevronDown, ChevronLeft, ChevronRight, Flag, Plus, CalendarRange, List, LayoutGrid, Search, Pencil, SmilePlus } from 'lucide-react';
9
+ import { CircleX, CircleCheckBig, CircleDotDashed, CircleDot, Circle, CircleDashed, User, Link2, CalendarDays, Trash2, ChevronUp, ChevronDown, ChevronLeft, ChevronRight, Flag, Plus, CalendarRange, List, LayoutGrid, Search, Bookmark, Check, Pencil, SmilePlus } from 'lucide-react';
10
10
  import { clsx } from 'clsx';
11
11
  import { twMerge } from 'tailwind-merge';
12
12
  import { startOfWeek, format, addDays, addWeeks, endOfWeek, eachDayOfInterval, addMonths, startOfMonth, endOfMonth, isToday, isSameMonth, startOfDay, parseISO, isValid } from 'date-fns';
@@ -282,6 +282,12 @@ var WORK_ITEM_SUMMARY_FIELDS = gql`
282
282
  storyPoints
283
283
  dueDate
284
284
  labels
285
+ # Board reorder ordering. sortOrder maps a Prisma \`position\` column and is
286
+ # unsafe to SELECT BACK FROM A MUTATION (serialization crash), but SAFE on
287
+ # this QUERY read path — a WorkItem.sortOrder field resolver maps position →
288
+ # sortOrder. The board sorts cards by this ascending so a drag-to-reorder
289
+ # persists across refetch (the list query itself orders by createdAt).
290
+ sortOrder
285
291
  }
286
292
  `;
287
293
  var WORK_ITEM_FIELDS = gql`
@@ -406,10 +412,11 @@ var UPDATE_WORK_ITEM = gql`
406
412
  var MOVE_WORK_ITEM = gql`
407
413
  mutation MoveWorkItem($id: ID!, $input: PlanmagnetMoveWorkItemInput!) {
408
414
  planmagnetMoveWorkItem(id: $id, input: $input) {
409
- ...WorkItemFields
415
+ id
416
+ status
417
+ sprintId
410
418
  }
411
419
  }
412
- ${WORK_ITEM_FIELDS}
413
420
  `;
414
421
  var WORK_ITEM_LINK_FIELDS = gql`
415
422
  fragment WorkItemLinkFields on WorkItemLink {
@@ -808,6 +815,22 @@ var DEFAULT_TASK_LABELS = {
808
815
  allTypes: "All types",
809
816
  newTask: "New task",
810
817
  myTasks: "My tasks",
818
+ savedViews: "Views",
819
+ saveView: "Save current view",
820
+ viewName: "View name",
821
+ saveViewAction: "Save",
822
+ deleteView: "Delete",
823
+ noSavedViews: "No saved views",
824
+ defaultViewName: "Default",
825
+ keyboardShortcuts: "Keyboard shortcuts",
826
+ shortcutNewTask: "New task",
827
+ shortcutSearch: "Focus search",
828
+ shortcutBoardView: "Board view",
829
+ shortcutListView: "List view",
830
+ shortcutTimelineView: "Timeline view",
831
+ shortcutMyTasks: "Toggle My tasks",
832
+ shortcutHelp: "Toggle this help",
833
+ shortcutClose: "Close overlay",
811
834
  noTasks: "No tasks",
812
835
  noTasksFound: "No tasks found.",
813
836
  dropHere: "Drop here",
@@ -896,6 +919,7 @@ var DEFAULT_TASK_LABELS = {
896
919
  projectRequired: "A projectId is required to create a task.",
897
920
  errorLoading: "Error loading tasks",
898
921
  moveFailed: "Couldn't move the task. Please try again.",
922
+ reorderFailed: "Couldn't reorder the task. Please try again.",
899
923
  failedToCreate: "Failed to create task",
900
924
  failedToSave: "Failed to save",
901
925
  failedToDelete: "Failed to delete",
@@ -1094,6 +1118,7 @@ function TaskCard({
1094
1118
  draggable,
1095
1119
  onDragStart,
1096
1120
  onDragEnd,
1121
+ onDragOver,
1097
1122
  dragging,
1098
1123
  resolveAssignee,
1099
1124
  links,
@@ -1128,6 +1153,7 @@ function TaskCard({
1128
1153
  draggable,
1129
1154
  onDragStart: draggable ? (e) => onDragStart?.(task, e) : void 0,
1130
1155
  onDragEnd: draggable ? (e) => onDragEnd?.(task, e) : void 0,
1156
+ onDragOver: draggable ? onDragOver : void 0,
1131
1157
  onClick: onClick ? () => onClick(task) : void 0,
1132
1158
  onKeyDown: handleKey,
1133
1159
  className: cn(
@@ -1223,6 +1249,13 @@ function useWorkItemLinks(workspaceId, sourceProduct, limit = 500) {
1223
1249
  }, [data]);
1224
1250
  return { linksByItem, loading };
1225
1251
  }
1252
+ function bySortOrder(tasks) {
1253
+ return tasks.map((task, index) => ({ task, index })).sort((a, b) => {
1254
+ const ao = a.task.sortOrder ?? Number.MAX_SAFE_INTEGER;
1255
+ const bo = b.task.sortOrder ?? Number.MAX_SAFE_INTEGER;
1256
+ return ao === bo ? a.index - b.index : ao - bo;
1257
+ }).map((entry) => entry.task);
1258
+ }
1226
1259
  function TaskBoardCore({
1227
1260
  projectId,
1228
1261
  columns = DEFAULT_BOARD_COLUMNS,
@@ -1249,9 +1282,11 @@ function TaskBoardCore({
1249
1282
  const { linksByItem } = useWorkItemLinks(workspaceId, linkSourceProduct);
1250
1283
  const [draggingId, setDraggingId] = useState(null);
1251
1284
  const [dragOver, setDragOver] = useState(null);
1285
+ const [dropIndex, setDropIndex] = useState(null);
1252
1286
  const [moveError, setMoveError] = useState(null);
1253
1287
  const [pendingMove, setPendingMove] = useState(null);
1254
1288
  const [updateItem] = useMutation(UPDATE_WORK_ITEM);
1289
+ const [moveItem] = useMutation(MOVE_WORK_ITEM);
1255
1290
  const { data, loading, error } = useQuery(
1256
1291
  LIST_WORK_ITEMS,
1257
1292
  {
@@ -1280,6 +1315,44 @@ function TaskBoardCore({
1280
1315
  },
1281
1316
  [client, updateItem, L]
1282
1317
  );
1318
+ const reorderTask = useCallback(
1319
+ (columnTasks, fromIndex, toIndex) => {
1320
+ if (fromIndex === toIndex || fromIndex < 0) return;
1321
+ const ordered = columnTasks.slice();
1322
+ const [moved] = ordered.splice(fromIndex, 1);
1323
+ if (!moved) return;
1324
+ const insertAt = Math.max(0, Math.min(toIndex, ordered.length));
1325
+ ordered.splice(insertAt, 0, moved);
1326
+ const changed = [];
1327
+ ordered.forEach((task, index) => {
1328
+ const prev = task.sortOrder ?? null;
1329
+ if (prev !== index) {
1330
+ changed.push({ id: task.id, from: prev, to: index });
1331
+ }
1332
+ });
1333
+ if (changed.length === 0) return;
1334
+ setMoveError(null);
1335
+ const setOrder = (id, value) => {
1336
+ const cacheId = client.cache.identify({ __typename: "WorkItem", id });
1337
+ if (cacheId) {
1338
+ client.cache.modify({
1339
+ id: cacheId,
1340
+ fields: { sortOrder: () => value }
1341
+ });
1342
+ }
1343
+ };
1344
+ for (const c of changed) setOrder(c.id, c.to);
1345
+ Promise.all(
1346
+ changed.map(
1347
+ (c) => moveItem({ variables: { id: c.id, input: { sortOrder: c.to } } })
1348
+ )
1349
+ ).catch(() => {
1350
+ for (const c of changed) setOrder(c.id, c.from);
1351
+ setMoveError(L.reorderFailed);
1352
+ });
1353
+ },
1354
+ [client, moveItem, L]
1355
+ );
1283
1356
  if (!workspaceId) {
1284
1357
  return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TaskBoard: no workspaceId provided (prop or PlanMagnetProvider)." });
1285
1358
  }
@@ -1306,18 +1379,41 @@ function TaskBoardCore({
1306
1379
  return true;
1307
1380
  });
1308
1381
  const canDrag = !readonly;
1382
+ const columnTasksFor = (status) => bySortOrder(filtered.filter((t) => t.status === status));
1309
1383
  const onColumnDragOver = (status) => (e) => {
1310
1384
  if (!canDrag || !draggingId) return;
1311
1385
  e.preventDefault();
1312
1386
  if (dragOver !== status) setDragOver(status);
1387
+ if (dropIndex === null) setDropIndex(columnTasksFor(status).length);
1388
+ };
1389
+ const onCardDragOver = (status, index) => (e) => {
1390
+ if (!canDrag || !draggingId) return;
1391
+ e.preventDefault();
1392
+ e.stopPropagation();
1393
+ if (dragOver !== status) setDragOver(status);
1394
+ const rect = e.currentTarget.getBoundingClientRect();
1395
+ const after = e.clientY - rect.top > rect.height / 2;
1396
+ const next = after ? index + 1 : index;
1397
+ if (dropIndex !== next) setDropIndex(next);
1398
+ };
1399
+ const clearDrag = () => {
1400
+ setDragOver(null);
1401
+ setDraggingId(null);
1402
+ setDropIndex(null);
1313
1403
  };
1314
1404
  const onColumnDrop = (status) => (e) => {
1315
1405
  if (!canDrag) return;
1316
1406
  e.preventDefault();
1317
1407
  const task = tasks.find((t) => t.id === draggingId);
1318
- setDragOver(null);
1319
- setDraggingId(null);
1320
- if (!task || task.status === status) return;
1408
+ const targetIndex = dropIndex;
1409
+ clearDrag();
1410
+ if (!task) return;
1411
+ if (task.status === status) {
1412
+ const colTasks = columnTasksFor(status);
1413
+ const fromIndex = colTasks.findIndex((t) => t.id === task.id);
1414
+ if (targetIndex !== null) reorderTask(colTasks, fromIndex, targetIndex);
1415
+ return;
1416
+ }
1321
1417
  if (confirmMove) setPendingMove({ task, toStatus: status });
1322
1418
  else moveTask(task, status);
1323
1419
  };
@@ -1332,8 +1428,9 @@ function TaskBoardCore({
1332
1428
  ] }),
1333
1429
  moveError && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-1.5 text-xs text-destructive", children: moveError }),
1334
1430
  /* @__PURE__ */ jsx("div", { className: "flex gap-3 overflow-x-auto pb-2", children: columns.map((col) => {
1335
- const colTasks = filtered.filter((t) => t.status === col.status);
1431
+ const colTasks = columnTasksFor(col.status);
1336
1432
  const isOver = dragOver === col.status;
1433
+ const showDropLine = canDrag && isOver && dropIndex !== null && colTasks.some((t) => t.id === draggingId);
1337
1434
  return /* @__PURE__ */ jsxs(
1338
1435
  "div",
1339
1436
  {
@@ -1352,29 +1449,45 @@ function TaskBoardCore({
1352
1449
  ] }),
1353
1450
  /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 text-xs font-medium text-muted-foreground", children: colTasks.length })
1354
1451
  ] }),
1355
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 px-2 pb-2", children: colTasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border/70 px-3 py-6 text-center text-xs text-muted-foreground", children: isOver ? L.dropHere : L.noTasks }) : colTasks.map((task) => /* @__PURE__ */ jsx(
1356
- TaskCard,
1357
- {
1358
- task,
1359
- hidden,
1360
- onClick: onTaskClick,
1361
- draggable: canDrag,
1362
- dragging: draggingId === task.id,
1363
- resolveAssignee,
1364
- links: linksByItem.get(task.id),
1365
- renderLinkIcon,
1366
- onDragStart: (t, e) => {
1367
- setDraggingId(t.id);
1368
- e.dataTransfer.effectAllowed = "move";
1369
- e.dataTransfer.setData("text/plain", t.id);
1370
- },
1371
- onDragEnd: () => {
1372
- setDraggingId(null);
1373
- setDragOver(null);
1452
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 px-2 pb-2", children: colTasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border/70 px-3 py-6 text-center text-xs text-muted-foreground", children: isOver ? L.dropHere : L.noTasks }) : colTasks.map((task, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
1453
+ showDropLine && dropIndex === index && /* @__PURE__ */ jsx(
1454
+ "div",
1455
+ {
1456
+ "aria-hidden": "true",
1457
+ "data-testid": "reorder-drop-line",
1458
+ className: "h-0.5 rounded-full bg-primary"
1374
1459
  }
1375
- },
1376
- task.id
1377
- )) })
1460
+ ),
1461
+ /* @__PURE__ */ jsx(
1462
+ TaskCard,
1463
+ {
1464
+ task,
1465
+ hidden,
1466
+ onClick: onTaskClick,
1467
+ draggable: canDrag,
1468
+ dragging: draggingId === task.id,
1469
+ resolveAssignee,
1470
+ links: linksByItem.get(task.id),
1471
+ renderLinkIcon,
1472
+ onDragOver: onCardDragOver(col.status, index),
1473
+ onDragStart: (t, e) => {
1474
+ setDraggingId(t.id);
1475
+ setDropIndex(null);
1476
+ e.dataTransfer.effectAllowed = "move";
1477
+ e.dataTransfer.setData("text/plain", t.id);
1478
+ },
1479
+ onDragEnd: clearDrag
1480
+ }
1481
+ ),
1482
+ showDropLine && index === colTasks.length - 1 && dropIndex >= colTasks.length && /* @__PURE__ */ jsx(
1483
+ "div",
1484
+ {
1485
+ "aria-hidden": "true",
1486
+ "data-testid": "reorder-drop-line",
1487
+ className: "h-0.5 rounded-full bg-primary"
1488
+ }
1489
+ )
1490
+ ] }, task.id)) })
1378
1491
  ]
1379
1492
  },
1380
1493
  col.status
@@ -1455,6 +1568,7 @@ function CreateTaskCore({
1455
1568
  projectId: projectIdProp,
1456
1569
  assigneeOptions,
1457
1570
  hiddenFields,
1571
+ statuses,
1458
1572
  defaultValues,
1459
1573
  hideHeader,
1460
1574
  submitLabel,
@@ -1464,6 +1578,7 @@ function CreateTaskCore({
1464
1578
  className,
1465
1579
  workspaceId: workspaceIdProp
1466
1580
  }) {
1581
+ const statusOptions = statuses ?? TASK_STATUSES;
1467
1582
  const ctx = usePlanMagnetContextSafe();
1468
1583
  const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
1469
1584
  const projectId = projectIdProp ?? defaultValues?.projectId;
@@ -1608,7 +1723,7 @@ function CreateTaskCore({
1608
1723
  className: cn(fieldClass, "capitalize"),
1609
1724
  value: status,
1610
1725
  onChange: (e) => setStatus(e.target.value),
1611
- children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
1726
+ children: statusOptions.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
1612
1727
  }
1613
1728
  )
1614
1729
  ] }),
@@ -1847,9 +1962,11 @@ function TaskListCore({
1847
1962
  limit = 200,
1848
1963
  selectable = false,
1849
1964
  assigneeOptions,
1965
+ statuses,
1850
1966
  className,
1851
1967
  workspaceId: workspaceIdProp
1852
1968
  }) {
1969
+ const statusOptions = statuses ?? TASK_STATUSES;
1853
1970
  const ctx = usePlanMagnetContextSafe();
1854
1971
  const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
1855
1972
  const { linksByItem } = useWorkItemLinks(workspaceId, linkSourceProduct);
@@ -1991,7 +2108,7 @@ function TaskListCore({
1991
2108
  className: bulkFieldClass,
1992
2109
  children: [
1993
2110
  /* @__PURE__ */ jsx("option", { value: "", children: L.bulkSetStatus }),
1994
- TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
2111
+ statusOptions.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
1995
2112
  ]
1996
2113
  }
1997
2114
  ),
@@ -2796,6 +2913,7 @@ function TaskToolbar({
2796
2913
  views = ["board", "list", "timeline"],
2797
2914
  search,
2798
2915
  onSearchChange,
2916
+ searchInputRef,
2799
2917
  priority,
2800
2918
  onPriorityChange,
2801
2919
  type,
@@ -2804,6 +2922,7 @@ function TaskToolbar({
2804
2922
  canCreate,
2805
2923
  mine,
2806
2924
  onMineChange,
2925
+ leadingActions,
2807
2926
  className
2808
2927
  }) {
2809
2928
  const L = useTaskLabels();
@@ -2852,6 +2971,7 @@ function TaskToolbar({
2852
2971
  }
2853
2972
  ),
2854
2973
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
2974
+ leadingActions,
2855
2975
  /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2856
2976
  /* @__PURE__ */ jsx(
2857
2977
  Search,
@@ -2863,6 +2983,7 @@ function TaskToolbar({
2863
2983
  /* @__PURE__ */ jsx(
2864
2984
  "input",
2865
2985
  {
2986
+ ref: searchInputRef,
2866
2987
  type: "search",
2867
2988
  value: search,
2868
2989
  onChange: (e) => onSearchChange(e.target.value),
@@ -3406,6 +3527,7 @@ function TaskDetailCore({
3406
3527
  id,
3407
3528
  readonly,
3408
3529
  hiddenFields,
3530
+ statuses,
3409
3531
  hideHeader,
3410
3532
  onUpdated,
3411
3533
  onDeleted,
@@ -3457,6 +3579,8 @@ function TaskDetailCore({
3457
3579
  const [description, setDescription] = useState("");
3458
3580
  const [type, setType] = useState("TASK");
3459
3581
  const [status, setStatus] = useState("BACKLOG");
3582
+ const allowedStatuses = statuses ?? TASK_STATUSES;
3583
+ const statusOptions = allowedStatuses.includes(status) ? allowedStatuses : [...allowedStatuses, status];
3460
3584
  const [priority, setPriority] = useState("NONE");
3461
3585
  const [assigneeId, setAssigneeId] = useState("");
3462
3586
  const [dueDate, setDueDate] = useState("");
@@ -3773,7 +3897,7 @@ function TaskDetailCore({
3773
3897
  className: cn(fieldClass3, "capitalize"),
3774
3898
  value: status,
3775
3899
  onChange: (e) => setStatus(e.target.value),
3776
- children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
3900
+ children: statusOptions.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
3777
3901
  }
3778
3902
  )
3779
3903
  ] }),
@@ -3921,6 +4045,300 @@ function TaskDetail({
3921
4045
  }
3922
4046
  );
3923
4047
  }
4048
+ function SavedViewsMenu({
4049
+ views,
4050
+ activeViewId,
4051
+ onSaveView,
4052
+ onApplyView,
4053
+ onDeleteView,
4054
+ className
4055
+ }) {
4056
+ const L = useTaskLabels();
4057
+ const [open, setOpen] = useState(false);
4058
+ const [naming, setNaming] = useState(false);
4059
+ const [name, setName] = useState("");
4060
+ const rootRef = useRef(null);
4061
+ useEffect(() => {
4062
+ if (!open) return;
4063
+ const onDown = (e) => {
4064
+ if (rootRef.current && !rootRef.current.contains(e.target)) {
4065
+ setOpen(false);
4066
+ setNaming(false);
4067
+ }
4068
+ };
4069
+ const onKey = (e) => {
4070
+ if (e.key === "Escape") {
4071
+ setOpen(false);
4072
+ setNaming(false);
4073
+ }
4074
+ };
4075
+ document.addEventListener("mousedown", onDown);
4076
+ document.addEventListener("keydown", onKey);
4077
+ return () => {
4078
+ document.removeEventListener("mousedown", onDown);
4079
+ document.removeEventListener("keydown", onKey);
4080
+ };
4081
+ }, [open]);
4082
+ const activeName = views.find((v) => v.id === activeViewId)?.name ?? L.defaultViewName;
4083
+ const commitSave = () => {
4084
+ const trimmed = name.trim();
4085
+ if (!trimmed) return;
4086
+ onSaveView(trimmed);
4087
+ setName("");
4088
+ setNaming(false);
4089
+ setOpen(false);
4090
+ };
4091
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cn("relative", className), children: [
4092
+ /* @__PURE__ */ jsxs(
4093
+ "button",
4094
+ {
4095
+ type: "button",
4096
+ onClick: () => setOpen((o) => !o),
4097
+ "aria-haspopup": "menu",
4098
+ "aria-expanded": open,
4099
+ "aria-label": L.savedViews,
4100
+ className: cn(
4101
+ "flex h-8 max-w-[10rem] items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium transition-colors",
4102
+ activeViewId ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-muted-foreground hover:bg-muted/50 hover:text-foreground"
4103
+ ),
4104
+ children: [
4105
+ /* @__PURE__ */ jsx(Bookmark, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }),
4106
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: activeName })
4107
+ ]
4108
+ }
4109
+ ),
4110
+ open && /* @__PURE__ */ jsxs(
4111
+ "div",
4112
+ {
4113
+ role: "menu",
4114
+ className: "absolute right-0 top-full z-30 mt-1 w-56 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
4115
+ children: [
4116
+ /* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-[0.65rem] font-semibold uppercase tracking-wide text-muted-foreground", children: L.savedViews }),
4117
+ views.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: L.noSavedViews }) : /* @__PURE__ */ jsx("ul", { className: "max-h-56 overflow-auto", children: views.map((v) => {
4118
+ const active = v.id === activeViewId;
4119
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
4120
+ /* @__PURE__ */ jsxs(
4121
+ "button",
4122
+ {
4123
+ type: "button",
4124
+ role: "menuitemradio",
4125
+ "aria-checked": active,
4126
+ onClick: () => {
4127
+ onApplyView(v.id);
4128
+ setOpen(false);
4129
+ },
4130
+ className: cn(
4131
+ "flex min-w-0 flex-1 items-center gap-1.5 rounded px-2 py-1.5 text-left text-xs transition-colors hover:bg-muted/60",
4132
+ active ? "text-foreground" : "text-muted-foreground"
4133
+ ),
4134
+ children: [
4135
+ /* @__PURE__ */ jsx(
4136
+ Check,
4137
+ {
4138
+ className: cn(
4139
+ "h-3.5 w-3.5 shrink-0",
4140
+ active ? "opacity-100" : "opacity-0"
4141
+ ),
4142
+ "aria-hidden": "true"
4143
+ }
4144
+ ),
4145
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: v.name })
4146
+ ]
4147
+ }
4148
+ ),
4149
+ /* @__PURE__ */ jsx(
4150
+ "button",
4151
+ {
4152
+ type: "button",
4153
+ onClick: () => onDeleteView(v.id),
4154
+ "aria-label": `${L.deleteView}: ${v.name}`,
4155
+ className: "shrink-0 rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
4156
+ children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
4157
+ }
4158
+ )
4159
+ ] }, v.id);
4160
+ }) }),
4161
+ /* @__PURE__ */ jsx("div", { className: "my-1 h-px bg-border" }),
4162
+ naming ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 p-1", children: [
4163
+ /* @__PURE__ */ jsx(
4164
+ "input",
4165
+ {
4166
+ type: "text",
4167
+ autoFocus: true,
4168
+ value: name,
4169
+ onChange: (e) => setName(e.target.value),
4170
+ onKeyDown: (e) => {
4171
+ if (e.key === "Enter") commitSave();
4172
+ },
4173
+ placeholder: L.viewName,
4174
+ "aria-label": L.viewName,
4175
+ className: "h-7 min-w-0 flex-1 rounded border border-border bg-background px-2 text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
4176
+ }
4177
+ ),
4178
+ /* @__PURE__ */ jsx(
4179
+ "button",
4180
+ {
4181
+ type: "button",
4182
+ onClick: commitSave,
4183
+ disabled: !name.trim(),
4184
+ className: "h-7 shrink-0 rounded bg-primary px-2 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50",
4185
+ children: L.saveViewAction
4186
+ }
4187
+ )
4188
+ ] }) : /* @__PURE__ */ jsxs(
4189
+ "button",
4190
+ {
4191
+ type: "button",
4192
+ role: "menuitem",
4193
+ onClick: () => setNaming(true),
4194
+ className: "flex w-full items-center gap-1.5 rounded px-2 py-1.5 text-left text-xs font-medium text-foreground transition-colors hover:bg-muted/60",
4195
+ children: [
4196
+ /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
4197
+ L.saveView
4198
+ ]
4199
+ }
4200
+ )
4201
+ ]
4202
+ }
4203
+ )
4204
+ ] });
4205
+ }
4206
+ var STORAGE_PREFIX = "planmagnet:views:";
4207
+ var DEBOUNCE_MS = 400;
4208
+ function makeStorageKey(workspaceId, suffix) {
4209
+ return suffix ? `${STORAGE_PREFIX}${workspaceId}:${suffix}` : `${STORAGE_PREFIX}${workspaceId}`;
4210
+ }
4211
+ function safeStorage() {
4212
+ try {
4213
+ if (typeof window === "undefined") return null;
4214
+ const ls = window.localStorage;
4215
+ const probe = "__pm_probe__";
4216
+ ls.setItem(probe, probe);
4217
+ ls.removeItem(probe);
4218
+ return ls;
4219
+ } catch {
4220
+ return null;
4221
+ }
4222
+ }
4223
+ function readPayload(key) {
4224
+ const ls = safeStorage();
4225
+ if (!ls) return null;
4226
+ try {
4227
+ const raw = ls.getItem(key);
4228
+ if (!raw) return null;
4229
+ const parsed = JSON.parse(raw);
4230
+ if (!parsed || parsed.v !== 1) return null;
4231
+ return parsed;
4232
+ } catch {
4233
+ return null;
4234
+ }
4235
+ }
4236
+ function writePayload(key, payload) {
4237
+ const ls = safeStorage();
4238
+ if (!ls) return;
4239
+ try {
4240
+ ls.setItem(key, JSON.stringify(payload));
4241
+ } catch {
4242
+ }
4243
+ }
4244
+ function makeId() {
4245
+ const rand = Math.random().toString(36).slice(2, 10);
4246
+ return `v_${Date.now().toString(36)}_${rand}`;
4247
+ }
4248
+ function useSavedViews({
4249
+ storageKey,
4250
+ enabled,
4251
+ current
4252
+ }) {
4253
+ const initial = useMemo(
4254
+ () => enabled ? readPayload(storageKey) : null,
4255
+ [enabled, storageKey]
4256
+ );
4257
+ const [views, setViews] = useState(initial?.views ?? []);
4258
+ const [activeViewId, setActiveViewId] = useState(
4259
+ initial?.activeViewId ?? null
4260
+ );
4261
+ const restored = enabled ? initial?.current ?? null : null;
4262
+ const viewsRef = useRef(views);
4263
+ viewsRef.current = views;
4264
+ const activeViewIdRef = useRef(activeViewId);
4265
+ activeViewIdRef.current = activeViewId;
4266
+ useEffect(() => {
4267
+ if (!enabled) return;
4268
+ const handle = setTimeout(() => {
4269
+ writePayload(storageKey, {
4270
+ v: 1,
4271
+ current,
4272
+ views: viewsRef.current,
4273
+ activeViewId: activeViewIdRef.current
4274
+ });
4275
+ }, DEBOUNCE_MS);
4276
+ return () => clearTimeout(handle);
4277
+ }, [enabled, storageKey, current]);
4278
+ const flush = useCallback(
4279
+ (nextViews, nextActive) => {
4280
+ if (!enabled) return;
4281
+ writePayload(storageKey, {
4282
+ v: 1,
4283
+ current,
4284
+ views: nextViews,
4285
+ activeViewId: nextActive
4286
+ });
4287
+ },
4288
+ [enabled, storageKey, current]
4289
+ );
4290
+ const saveView = useCallback(
4291
+ (name) => {
4292
+ if (!enabled) return null;
4293
+ const trimmed = name.trim();
4294
+ if (!trimmed) return null;
4295
+ const id = makeId();
4296
+ const next = [
4297
+ ...viewsRef.current,
4298
+ { id, name: trimmed, state: current }
4299
+ ];
4300
+ setViews(next);
4301
+ setActiveViewId(id);
4302
+ flush(next, id);
4303
+ return id;
4304
+ },
4305
+ [enabled, current, flush]
4306
+ );
4307
+ const applyView = useCallback(
4308
+ (id) => {
4309
+ const found = viewsRef.current.find((v) => v.id === id);
4310
+ if (!found) return null;
4311
+ setActiveViewId(id);
4312
+ flush(viewsRef.current, id);
4313
+ return found.state;
4314
+ },
4315
+ [flush]
4316
+ );
4317
+ const deleteView = useCallback(
4318
+ (id) => {
4319
+ const next = viewsRef.current.filter((v) => v.id !== id);
4320
+ const nextActive = activeViewIdRef.current === id ? null : activeViewIdRef.current;
4321
+ setViews(next);
4322
+ setActiveViewId(nextActive);
4323
+ flush(next, nextActive);
4324
+ },
4325
+ [flush]
4326
+ );
4327
+ const clearActiveView = useCallback(() => {
4328
+ if (activeViewIdRef.current == null) return;
4329
+ setActiveViewId(null);
4330
+ flush(viewsRef.current, null);
4331
+ }, [flush]);
4332
+ return {
4333
+ restored,
4334
+ views,
4335
+ activeViewId,
4336
+ saveView,
4337
+ applyView,
4338
+ deleteView,
4339
+ clearActiveView
4340
+ };
4341
+ }
3924
4342
  function TasksPageCore({
3925
4343
  workspaceId: workspaceIdProp,
3926
4344
  projectId,
@@ -3946,19 +4364,27 @@ function TasksPageCore({
3946
4364
  onTaskSaved,
3947
4365
  createSurface = "modal",
3948
4366
  detailSurface = "drawer",
4367
+ enableSavedViews,
4368
+ persistViewKey,
4369
+ enableShortcuts,
3949
4370
  className
3950
4371
  }) {
4372
+ const allowedStatuses = columns?.map((c) => c.status);
3951
4373
  const ctx = usePlanMagnetContextSafe();
3952
4374
  const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
3953
4375
  const client = useApolloClient();
3954
4376
  const mergedLabels = mergeTaskLabels(labels);
4377
+ const savedViewsEnabled = Boolean(enableSavedViews || persistViewKey);
3955
4378
  const [view, setView] = useState(defaultView);
3956
4379
  const [search, setSearch] = useState("");
3957
4380
  const [priority, setPriority] = useState("ALL");
3958
4381
  const [type, setType] = useState("ALL");
3959
4382
  const [mine, setMine] = useState(false);
4383
+ const [savedListColumns, setSavedListColumns] = useState(null);
3960
4384
  const [creating, setCreating] = useState(false);
3961
4385
  const [selectedId, setSelectedId] = useState(null);
4386
+ const [showHelp, setShowHelp] = useState(false);
4387
+ const searchInputRef = useRef(null);
3962
4388
  const [createDefaults, setCreateDefaults] = useState(null);
3963
4389
  useEffect(() => {
3964
4390
  if (openItemId) setSelectedId(openItemId);
@@ -4010,6 +4436,169 @@ function TasksPageCore({
4010
4436
  setSelectedId(task.id);
4011
4437
  }, []);
4012
4438
  const handleSelect = useCallback((id) => setSelectedId(id), []);
4439
+ const persistEnabled = savedViewsEnabled && Boolean(workspaceId);
4440
+ const storageKey = useMemo(
4441
+ () => makeStorageKey(workspaceId ?? "", persistViewKey),
4442
+ [workspaceId, persistViewKey]
4443
+ );
4444
+ const currentViewState = useMemo(
4445
+ () => ({
4446
+ view,
4447
+ priority,
4448
+ type,
4449
+ search,
4450
+ mine,
4451
+ listColumns: savedListColumns
4452
+ }),
4453
+ [view, priority, type, search, mine, savedListColumns]
4454
+ );
4455
+ const applyViewState = useCallback((s) => {
4456
+ setView(s.view);
4457
+ setPriority(s.priority);
4458
+ setType(s.type);
4459
+ setSearch(s.search);
4460
+ setMine(s.mine);
4461
+ setSavedListColumns(s.listColumns);
4462
+ }, []);
4463
+ const {
4464
+ restored,
4465
+ views: savedViews,
4466
+ activeViewId,
4467
+ saveView,
4468
+ applyView,
4469
+ deleteView,
4470
+ clearActiveView
4471
+ } = useSavedViews({
4472
+ storageKey,
4473
+ enabled: persistEnabled,
4474
+ current: currentViewState
4475
+ });
4476
+ const [didRestore, setDidRestore] = useState(false);
4477
+ useEffect(() => {
4478
+ if (didRestore || !persistEnabled) return;
4479
+ if (restored) applyViewState(restored);
4480
+ setDidRestore(true);
4481
+ }, [persistEnabled]);
4482
+ const handleApplySavedView = useCallback(
4483
+ (id) => {
4484
+ const s = applyView(id);
4485
+ if (s) applyViewState(s);
4486
+ },
4487
+ [applyView, applyViewState]
4488
+ );
4489
+ const detachOnEdit = useCallback(() => {
4490
+ if (activeViewId != null) clearActiveView();
4491
+ }, [activeViewId, clearActiveView]);
4492
+ const handleViewChange = useCallback(
4493
+ (v) => {
4494
+ setView(v);
4495
+ detachOnEdit();
4496
+ },
4497
+ [detachOnEdit]
4498
+ );
4499
+ const handleSearchChange = useCallback(
4500
+ (s) => {
4501
+ setSearch(s);
4502
+ detachOnEdit();
4503
+ },
4504
+ [detachOnEdit]
4505
+ );
4506
+ const handlePriorityChange = useCallback(
4507
+ (p) => {
4508
+ setPriority(p);
4509
+ detachOnEdit();
4510
+ },
4511
+ [detachOnEdit]
4512
+ );
4513
+ const handleTypeChange = useCallback(
4514
+ (t) => {
4515
+ setType(t);
4516
+ detachOnEdit();
4517
+ },
4518
+ [detachOnEdit]
4519
+ );
4520
+ const handleMineChange = useCallback(
4521
+ (m) => {
4522
+ setMine(m);
4523
+ detachOnEdit();
4524
+ },
4525
+ [detachOnEdit]
4526
+ );
4527
+ const enabledViews = useMemo(
4528
+ () => views ?? ["board", "list", "timeline"],
4529
+ [views]
4530
+ );
4531
+ const shortcutsCanCreate = !readonly && Boolean(projectId);
4532
+ useEffect(() => {
4533
+ if (!enableShortcuts) return;
4534
+ const onKeyDown = (e) => {
4535
+ if (e.ctrlKey || e.metaKey || e.altKey) return;
4536
+ const target = e.target;
4537
+ if (target) {
4538
+ const tag = target.tagName;
4539
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || target.isContentEditable) {
4540
+ if (e.key !== "Escape") return;
4541
+ }
4542
+ }
4543
+ switch (e.key) {
4544
+ case "c":
4545
+ if (shortcutsCanCreate) {
4546
+ e.preventDefault();
4547
+ startCreate();
4548
+ }
4549
+ break;
4550
+ case "/":
4551
+ e.preventDefault();
4552
+ searchInputRef.current?.focus();
4553
+ break;
4554
+ case "b":
4555
+ if (enabledViews.includes("board")) {
4556
+ e.preventDefault();
4557
+ setView("board");
4558
+ }
4559
+ break;
4560
+ case "l":
4561
+ if (enabledViews.includes("list")) {
4562
+ e.preventDefault();
4563
+ setView("list");
4564
+ }
4565
+ break;
4566
+ case "g":
4567
+ if (enabledViews.includes("timeline")) {
4568
+ e.preventDefault();
4569
+ setView("timeline");
4570
+ }
4571
+ break;
4572
+ case "m":
4573
+ if (currentActorId) {
4574
+ e.preventDefault();
4575
+ setMine((prev) => !prev);
4576
+ }
4577
+ break;
4578
+ case "?":
4579
+ e.preventDefault();
4580
+ setShowHelp((v) => !v);
4581
+ break;
4582
+ case "Escape":
4583
+ if (showHelp) setShowHelp(false);
4584
+ if (creating) cancelCreate();
4585
+ if (selectedId != null) setSelectedId(null);
4586
+ break;
4587
+ }
4588
+ };
4589
+ document.addEventListener("keydown", onKeyDown);
4590
+ return () => document.removeEventListener("keydown", onKeyDown);
4591
+ }, [
4592
+ enableShortcuts,
4593
+ enabledViews,
4594
+ shortcutsCanCreate,
4595
+ currentActorId,
4596
+ creating,
4597
+ selectedId,
4598
+ showHelp,
4599
+ startCreate,
4600
+ cancelCreate
4601
+ ]);
4013
4602
  if (!workspaceId) {
4014
4603
  return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TasksPage: no workspaceId provided (prop or PlanMagnetProvider)." });
4015
4604
  }
@@ -4021,6 +4610,7 @@ function TasksPageCore({
4021
4610
  {
4022
4611
  workspaceId,
4023
4612
  projectId,
4613
+ statuses: allowedStatuses,
4024
4614
  assigneeOptions,
4025
4615
  hiddenFields,
4026
4616
  defaultValues: createDefaults ?? void 0,
@@ -4033,6 +4623,7 @@ function TasksPageCore({
4033
4623
  {
4034
4624
  id: selectedId,
4035
4625
  readonly,
4626
+ statuses: allowedStatuses,
4036
4627
  hiddenFields,
4037
4628
  resolveAssignee,
4038
4629
  assigneeOptions,
@@ -4050,32 +4641,37 @@ function TasksPageCore({
4050
4641
  const listPriority = priority === "ALL" ? void 0 : priority;
4051
4642
  const listType = type === "ALL" ? void 0 : type;
4052
4643
  const mineAssignee = mine && currentActorId ? currentActorId : void 0;
4053
- const listColumns = linkSourceProduct ? [
4054
- "title",
4055
- "status",
4056
- "priority",
4057
- "assignee",
4058
- "dueDate",
4059
- "linkedRecord"
4060
- ] : void 0;
4644
+ const derivedListColumns = linkSourceProduct ? ["title", "status", "priority", "assignee", "dueDate", "linkedRecord"] : void 0;
4645
+ const listColumns = savedListColumns ?? derivedListColumns;
4061
4646
  return /* @__PURE__ */ jsx(TaskLabelsProvider, { value: mergedLabels, children: /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 p-6", className), children: [
4062
4647
  header && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: typeof header === "string" ? /* @__PURE__ */ jsx("h1", { className: "truncate text-2xl font-semibold text-foreground", children: header }) : header }),
4063
4648
  /* @__PURE__ */ jsx(
4064
4649
  TaskToolbar,
4065
4650
  {
4066
4651
  view,
4067
- onViewChange: setView,
4652
+ onViewChange: savedViewsEnabled ? handleViewChange : setView,
4068
4653
  views,
4069
4654
  search,
4070
- onSearchChange: setSearch,
4655
+ onSearchChange: savedViewsEnabled ? handleSearchChange : setSearch,
4656
+ searchInputRef: enableShortcuts ? searchInputRef : void 0,
4071
4657
  priority,
4072
- onPriorityChange: setPriority,
4658
+ onPriorityChange: savedViewsEnabled ? handlePriorityChange : setPriority,
4073
4659
  type,
4074
- onTypeChange: setType,
4660
+ onTypeChange: savedViewsEnabled ? handleTypeChange : setType,
4075
4661
  onNewTask: startCreate,
4076
4662
  canCreate,
4077
4663
  mine,
4078
- onMineChange: currentActorId ? setMine : void 0
4664
+ onMineChange: currentActorId ? savedViewsEnabled ? handleMineChange : setMine : void 0,
4665
+ leadingActions: savedViewsEnabled ? /* @__PURE__ */ jsx(
4666
+ SavedViewsMenu,
4667
+ {
4668
+ views: savedViews,
4669
+ activeViewId,
4670
+ onSaveView: saveView,
4671
+ onApplyView: handleApplySavedView,
4672
+ onDeleteView: deleteView
4673
+ }
4674
+ ) : void 0
4079
4675
  }
4080
4676
  ),
4081
4677
  showInlineCreate && /* @__PURE__ */ jsx("div", { children: createForm }),
@@ -4104,6 +4700,7 @@ function TasksPageCore({
4104
4700
  {
4105
4701
  workspaceId,
4106
4702
  projectId: boardProjectId,
4703
+ statuses: allowedStatuses,
4107
4704
  priority: listPriority,
4108
4705
  type: listType,
4109
4706
  search: search || void 0,
@@ -4153,9 +4750,60 @@ function TasksPageCore({
4153
4750
  ariaLabel: "Task detail",
4154
4751
  children: /* @__PURE__ */ jsx("div", { className: "p-2 pt-8", children: detailView })
4155
4752
  }
4753
+ ),
4754
+ enableShortcuts && /* @__PURE__ */ jsx(
4755
+ Modal,
4756
+ {
4757
+ open: showHelp,
4758
+ onClose: () => setShowHelp(false),
4759
+ ariaLabel: mergedLabels.keyboardShortcuts,
4760
+ className: "max-w-sm",
4761
+ children: /* @__PURE__ */ jsx(
4762
+ ShortcutsHelp,
4763
+ {
4764
+ labels: mergedLabels,
4765
+ enabledViews,
4766
+ canCreate,
4767
+ showMine: Boolean(currentActorId)
4768
+ }
4769
+ )
4770
+ }
4156
4771
  )
4157
4772
  ] }) });
4158
4773
  }
4774
+ function ShortcutRow({ keys, label }) {
4775
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 py-1.5", children: [
4776
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground", children: label }),
4777
+ /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1", children: keys.map((k) => /* @__PURE__ */ jsx(
4778
+ "kbd",
4779
+ {
4780
+ className: "inline-flex min-w-[1.5rem] items-center justify-center rounded border border-border bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground",
4781
+ children: k
4782
+ },
4783
+ k
4784
+ )) })
4785
+ ] });
4786
+ }
4787
+ function ShortcutsHelp({
4788
+ labels: L,
4789
+ enabledViews,
4790
+ canCreate,
4791
+ showMine
4792
+ }) {
4793
+ return /* @__PURE__ */ jsxs("div", { className: "p-6 pt-8", children: [
4794
+ /* @__PURE__ */ jsx("h2", { className: "mb-3 text-base font-semibold text-foreground", children: L.keyboardShortcuts }),
4795
+ /* @__PURE__ */ jsxs("div", { className: "divide-y divide-border", children: [
4796
+ canCreate && /* @__PURE__ */ jsx(ShortcutRow, { keys: ["c"], label: L.shortcutNewTask }),
4797
+ /* @__PURE__ */ jsx(ShortcutRow, { keys: ["/"], label: L.shortcutSearch }),
4798
+ enabledViews.includes("board") && /* @__PURE__ */ jsx(ShortcutRow, { keys: ["b"], label: L.shortcutBoardView }),
4799
+ enabledViews.includes("list") && /* @__PURE__ */ jsx(ShortcutRow, { keys: ["l"], label: L.shortcutListView }),
4800
+ enabledViews.includes("timeline") && /* @__PURE__ */ jsx(ShortcutRow, { keys: ["g"], label: L.shortcutTimelineView }),
4801
+ showMine && /* @__PURE__ */ jsx(ShortcutRow, { keys: ["m"], label: L.shortcutMyTasks }),
4802
+ /* @__PURE__ */ jsx(ShortcutRow, { keys: ["?"], label: L.shortcutHelp }),
4803
+ /* @__PURE__ */ jsx(ShortcutRow, { keys: ["Esc"], label: L.shortcutClose })
4804
+ ] })
4805
+ ] });
4806
+ }
4159
4807
  function TasksPage({
4160
4808
  apiGatewayUrl,
4161
4809
  authToken,
@@ -4185,6 +4833,6 @@ function TasksPage({
4185
4833
  );
4186
4834
  }
4187
4835
 
4188
- export { Avatar, BULK_UPDATE_WORK_ITEMS, Badge, CREATE_WORK_ITEM, CREATE_WORK_ITEM_LINK, CreateTask, CreateTaskCore, DEFAULT_BOARD_COLUMNS, DEFAULT_TASK_LABELS, DELETE_WORK_ITEM, DELETE_WORK_ITEM_LINK, Drawer, GET_PROJECTS, GET_WORK_ITEM, LIST_MILESTONES, LIST_WORK_ITEMS, LIST_WORK_ITEM_LINKS, LinkChip, MILESTONE_FIELDS, MOVE_WORK_ITEM, Modal, PRIORITY_META, PROJECT_SUMMARY_FIELDS, PlanMagnetProvider, PriorityIndicator, STATUS_META, StatusIcon, StatusPill, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, TaskBoard, TaskBoardCore, TaskCard, TaskCommentsCore, TaskDetail, TaskDetailCore, TaskLabelsProvider, TaskList, TaskListCore, TaskTimelineCore, TaskToolbar, TasksPage, TasksPageCore, TypeBadge, UPDATE_WORK_ITEM, WORK_ITEM_FIELDS, WORK_ITEM_LINK_FIELDS, WORK_ITEM_SUMMARY_FIELDS, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, mergeTaskLabels, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, useMilestones, usePlanMagnetContext, usePlanMagnetContextSafe, useTaskLabels, useWorkItemLinks, validateTrustedOrigin, waitForPlanMagnetClient };
4836
+ export { Avatar, BULK_UPDATE_WORK_ITEMS, Badge, CREATE_WORK_ITEM, CREATE_WORK_ITEM_LINK, CreateTask, CreateTaskCore, DEFAULT_BOARD_COLUMNS, DEFAULT_TASK_LABELS, DELETE_WORK_ITEM, DELETE_WORK_ITEM_LINK, Drawer, GET_PROJECTS, GET_WORK_ITEM, LIST_MILESTONES, LIST_WORK_ITEMS, LIST_WORK_ITEM_LINKS, LinkChip, MILESTONE_FIELDS, MOVE_WORK_ITEM, Modal, PRIORITY_META, PROJECT_SUMMARY_FIELDS, PlanMagnetProvider, PriorityIndicator, STATUS_META, SavedViewsMenu, StatusIcon, StatusPill, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, TaskBoard, TaskBoardCore, TaskCard, TaskCommentsCore, TaskDetail, TaskDetailCore, TaskLabelsProvider, TaskList, TaskListCore, TaskTimelineCore, TaskToolbar, TasksPage, TasksPageCore, TypeBadge, UPDATE_WORK_ITEM, WORK_ITEM_FIELDS, WORK_ITEM_LINK_FIELDS, WORK_ITEM_SUMMARY_FIELDS, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, makeStorageKey, mergeTaskLabels, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, useMilestones, usePlanMagnetContext, usePlanMagnetContextSafe, useSavedViews, useTaskLabels, useWorkItemLinks, validateTrustedOrigin, waitForPlanMagnetClient };
4189
4837
  //# sourceMappingURL=index.js.map
4190
4838
  //# sourceMappingURL=index.js.map