@burdenoff/planmagnet-fe-sdk 2026.703.1 → 2026.703.2

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 CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, HTMLAttributes } from 'react';
2
+ import { DragEvent, ReactNode, HTMLAttributes, ComponentType } from 'react';
3
3
  import { ApolloClient } from '@apollo/client/core';
4
4
  import * as graphql from 'graphql';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
6
6
  import { VariantProps } from 'class-variance-authority';
7
+ import { LucideProps } from 'lucide-react';
7
8
  import { ClassValue } from 'clsx';
8
9
 
9
10
  /**
@@ -178,23 +179,64 @@ declare const TASK_STATUSES: TaskStatus[];
178
179
  */
179
180
  declare function enumLabel(value: string): string;
180
181
 
182
+ /**
183
+ * Optional host hook: resolve an assignee id to a display name (the SDK has no
184
+ * user directory). When omitted the avatar falls back to id-initials.
185
+ */
186
+ type ResolveAssignee = (assigneeId: string) => {
187
+ name?: string | null;
188
+ } | null | undefined;
189
+ interface TaskCardProps {
190
+ task: Task;
191
+ /** Field names to hide (key/type/priority/labels/storyPoints/assignee/dueDate). */
192
+ hidden?: ReadonlySet<string>;
193
+ onClick?: (task: Task) => void;
194
+ /** Enable native drag (board wires this to move-between-columns). */
195
+ draggable?: boolean;
196
+ onDragStart?: (task: Task, e: DragEvent<HTMLDivElement>) => void;
197
+ onDragEnd?: (task: Task, e: DragEvent<HTMLDivElement>) => void;
198
+ /** True while this card is the one being dragged. */
199
+ dragging?: boolean;
200
+ resolveAssignee?: ResolveAssignee;
201
+ className?: string;
202
+ }
203
+ /**
204
+ * TaskCard — a Linear-style board card. Presentational + prop-driven; renders
205
+ * only real fields (no invented assignee names or entity links). Semantic
206
+ * tokens only.
207
+ */
208
+ declare function TaskCard({ task, hidden, onClick, draggable, onDragStart, onDragEnd, dragging, resolveAssignee, className, }: TaskCardProps): react.JSX.Element;
209
+
181
210
  interface TaskBoardCoreProps {
182
211
  /** Scope the board to one project (client-side filter for Phase 1). */
183
212
  projectId?: string;
184
213
  /** Board columns to render (defaults to DEFAULT_BOARD_COLUMNS). */
185
214
  columns?: BoardColumn[];
186
- /** Read-only mode — hides interactive affordances (no create/drag in Phase 1 either way). */
215
+ /** Read-only mode — disables drag-to-move. */
187
216
  readonly?: boolean;
188
- /** Hide the board header (title + count). */
217
+ /** Hide the board's own header (title + count). */
189
218
  hideHeader?: boolean;
190
- /** Hide the priority/type filter bar. */
219
+ /**
220
+ * @deprecated Filtering is now controlled by the parent toolbar via the
221
+ * `priority`/`type`/`search` props. Accepted for backward compatibility; the
222
+ * board no longer renders its own filter chips.
223
+ */
191
224
  hideFilters?: boolean;
225
+ /** Controlled priority filter ("ALL" or a specific priority). */
226
+ priority?: TaskPriority | "ALL";
227
+ /** Controlled type filter ("ALL" or a specific type). */
228
+ type?: TaskType | "ALL";
229
+ /** Controlled free-text search (matches title/key/labels). */
230
+ search?: string;
231
+ /** Controlled assignee filter (actor id). */
232
+ assigneeId?: string;
192
233
  /**
193
- * Field names to hide on each task card. Product-agnostic hook so hosts can
194
- * suppress fields that don't apply. Supported: 'key' | 'priority' | 'type' |
195
- * 'labels' | 'storyPoints' | 'assignee' | 'dueDate'.
234
+ * Field names to hide on each task card. Supported: 'key' | 'priority' |
235
+ * 'type' | 'labels' | 'storyPoints' | 'assignee' | 'dueDate'.
196
236
  */
197
237
  hiddenFields?: string[];
238
+ /** Optional host hook to resolve an assignee id → display name. */
239
+ resolveAssignee?: ResolveAssignee;
198
240
  /** Called when a task card is clicked. */
199
241
  onTaskClick?: (task: Task) => void;
200
242
  /** Extra classes on the root container. */
@@ -208,12 +250,14 @@ interface TaskBoardCoreProps {
208
250
  /**
209
251
  * TaskBoardCore — provider-less, prop-driven, product-agnostic Kanban board.
210
252
  *
211
- * - Reads Apollo via the ambient `<ApolloProvider>` (BYO). It never creates a
212
- * client and never assumes a router.
253
+ * - Reads Apollo via the ambient `<ApolloProvider>` (BYO). Never creates a
254
+ * client, never assumes a router.
213
255
  * - `workspaceId` comes from a prop or the PlanMagnetProvider context.
214
- * - Read-only in Phase 1 (no drag/create). Farm-free: no Field/Crop logic.
256
+ * - Linear-style columns + cards, with native drag-to-move between columns
257
+ * (optimistic cache update + `UPDATE_WORK_ITEM`; reverts on error). Filtering
258
+ * is controlled by the parent toolbar. Farm-free, semantic-token only.
215
259
  */
216
- declare function TaskBoardCore({ projectId, columns, readonly: _readonly, hideHeader, hideFilters, hiddenFields, onTaskClick, className, workspaceId: workspaceIdProp, }: TaskBoardCoreProps): react.JSX.Element;
260
+ declare function TaskBoardCore({ projectId, columns, readonly, hideHeader, priority, type, search, assigneeId, hiddenFields, resolveAssignee, onTaskClick, className, workspaceId: workspaceIdProp, }: TaskBoardCoreProps): react.JSX.Element;
217
261
 
218
262
  interface TaskBoardProps extends TaskBoardCoreProps {
219
263
  /** Workspace API gateway URL (URL mode). */
@@ -368,14 +412,16 @@ interface TaskListCoreProps {
368
412
  search?: string;
369
413
  /** Columns to render (order preserved). */
370
414
  columns?: TaskListColumn[];
371
- /** Sort key (client-side). */
415
+ /** Initial sort key. */
372
416
  sortBy?: TaskListSort;
373
- /** Sort direction. Defaults to ascending. */
417
+ /** Initial sort direction. Defaults to ascending. */
374
418
  sortDir?: "asc" | "desc";
375
419
  /** Hide the header (title + count). */
376
420
  hideHeader?: boolean;
377
421
  /** Called with the work-item id when a row is clicked. */
378
422
  onSelect?: (id: string) => void;
423
+ /** Optional host hook to resolve an assignee id → display name. */
424
+ resolveAssignee?: ResolveAssignee;
379
425
  /** Max items to fetch (pagination.first). Defaults to 200. */
380
426
  limit?: number;
381
427
  /** Extra classes on the root container. */
@@ -386,11 +432,12 @@ interface TaskListCoreProps {
386
432
  /**
387
433
  * TaskListCore — provider-less, prop-driven compact list/table of work items.
388
434
  *
389
- * Same data source as TaskBoardCore (`LIST_WORK_ITEMS`) but a dense table
390
- * layout instead of a kanban. Filters map to the server-side `WorkItemFilter`;
391
- * sort is applied client-side. BYO-Apollo, semantic-token only, farm-free.
435
+ * Same data source as TaskBoardCore (`LIST_WORK_ITEMS`) but a dense, Linear-style
436
+ * table: status pills, priority signal bars, assignee avatars, click-to-sort
437
+ * headers. Filters map to the server-side filter; sort is client-side.
438
+ * BYO-Apollo, semantic-token only, farm-free.
392
439
  */
393
- declare function TaskListCore({ projectId, status, type, priority, assigneeId, search, columns, sortBy, sortDir, hideHeader, onSelect, limit, className, workspaceId: workspaceIdProp, }: TaskListCoreProps): react.JSX.Element;
440
+ declare function TaskListCore({ projectId, status, type, priority, assigneeId, search, columns, sortBy, sortDir, hideHeader, onSelect, resolveAssignee, limit, className, workspaceId: workspaceIdProp, }: TaskListCoreProps): react.JSX.Element;
394
441
 
395
442
  interface TaskListProps extends TaskListCoreProps {
396
443
  /** Workspace API gateway URL (URL mode). */
@@ -431,6 +478,62 @@ interface TaskListProps extends TaskListCoreProps {
431
478
  */
432
479
  declare function TaskList({ apiGatewayUrl, authToken, workspaceToken, workspaceId, tenantId, organizationId, trustedOrigins, onAuthError, workspaceClient, ...coreProps }: TaskListProps): react.JSX.Element;
433
480
 
481
+ type TimelineMode = "week" | "month";
482
+ interface TaskTimelineCoreProps {
483
+ /** Scope the timeline to one project (client-side filter). */
484
+ projectId?: string;
485
+ /** Controlled priority filter ("ALL" or a specific priority). */
486
+ priority?: TaskPriority | "ALL";
487
+ /** Controlled type filter ("ALL" or a specific type). */
488
+ type?: TaskType | "ALL";
489
+ /** Controlled free-text search (matches title/key/labels). */
490
+ search?: string;
491
+ /** Controlled assignee filter (actor id). */
492
+ assigneeId?: string;
493
+ /** Default mode. */
494
+ defaultMode?: TimelineMode;
495
+ /** Called with the work-item id when a task chip is clicked. */
496
+ onSelect?: (id: string) => void;
497
+ /** Optional host hook to resolve an assignee id → display name. */
498
+ resolveAssignee?: ResolveAssignee;
499
+ className?: string;
500
+ workspaceId?: string;
501
+ }
502
+ /**
503
+ * TaskTimelineCore — a week/month schedule of work items by due date.
504
+ *
505
+ * The spec's "week/month timeline that shows when work is scheduled and what's
506
+ * due". We only have a single `dueDate` per work item (no start/end), so this is
507
+ * an agenda-style schedule (chip on its due day) rather than a span Gantt —
508
+ * honest to the data. Overdue and undated work is surfaced explicitly so nothing
509
+ * hides. BYO-Apollo, semantic-token only, farm-free.
510
+ */
511
+ declare function TaskTimelineCore({ projectId, priority, type, search, assigneeId, defaultMode, onSelect, resolveAssignee, className, workspaceId: workspaceIdProp, }: TaskTimelineCoreProps): react.JSX.Element;
512
+
513
+ /** The three task views the toolbar can switch between. */
514
+ type TaskView = "board" | "list" | "timeline";
515
+ interface TaskToolbarProps {
516
+ view: TaskView;
517
+ onViewChange: (view: TaskView) => void;
518
+ /** Which views to offer (order preserved). Defaults to all three. */
519
+ views?: TaskView[];
520
+ search: string;
521
+ onSearchChange: (search: string) => void;
522
+ priority: TaskPriority | "ALL";
523
+ onPriorityChange: (priority: TaskPriority | "ALL") => void;
524
+ type: TaskType | "ALL";
525
+ onTypeChange: (type: TaskType | "ALL") => void;
526
+ onNewTask?: () => void;
527
+ canCreate?: boolean;
528
+ className?: string;
529
+ }
530
+ /**
531
+ * TaskToolbar — the single Linear-style control bar for the Tasks experience:
532
+ * view tabs (Board / List / Timeline) + search + priority/type filters + a
533
+ * "New task" action. Fully controlled; semantic-token only.
534
+ */
535
+ declare function TaskToolbar({ view, onViewChange, views, search, onSearchChange, priority, onPriorityChange, type, onTypeChange, onNewTask, canCreate, className, }: TaskToolbarProps): react.JSX.Element;
536
+
434
537
  /** Fields that can be hidden / suppressed on the detail view + edit form. */
435
538
  type TaskDetailField = "description" | "type" | "status" | "priority" | "assignee" | "dueDate" | "labels" | "storyPoints";
436
539
  interface TaskDetailCoreProps {
@@ -519,22 +622,27 @@ interface TasksPageCoreProps {
519
622
  * omitted the board still renders read-only-ish (create is disabled).
520
623
  */
521
624
  projectId?: string;
522
- /** Scope the board to a single project (client-side filter). */
625
+ /** Scope the views to a single project (client-side filter). */
523
626
  boardProjectId?: string;
524
627
  /** Board columns to render (defaults to DEFAULT_BOARD_COLUMNS). */
525
628
  columns?: BoardColumn[];
526
- /** Read-only — hides the "New task" button and disables detail editing. */
629
+ /** Read-only — hides the "New task" button, disables drag + detail editing. */
527
630
  readonly?: boolean;
528
631
  /**
529
632
  * Field names to hide across the board cards, create form, and detail view.
530
633
  * A product-agnostic hook so hosts can suppress fields that don't apply.
531
634
  */
532
635
  hiddenFields?: TasksPageField[];
533
- /** Hide the board's priority/type filter bar. */
534
- hideFilters?: boolean;
636
+ /** Which views to offer (order preserved). Defaults to all three. */
637
+ views?: TaskView[];
638
+ /** Initial view. Defaults to "board". */
639
+ defaultView?: TaskView;
640
+ /** Optional host hook to resolve an assignee id → display name. */
641
+ resolveAssignee?: ResolveAssignee;
535
642
  /**
536
- * Header/title slot. Pass a string for the default heading, or any node to
537
- * fully own the header area. Omit for no header.
643
+ * Header/title slot rendered ABOVE the toolbar. Pass a string for the default
644
+ * heading, or any node to fully own the title area. Omit for no title (e.g.
645
+ * when the host shell already renders the page title).
538
646
  */
539
647
  header?: ReactNode;
540
648
  /** Called after a successful create OR update (board is refetched first). */
@@ -548,20 +656,14 @@ interface TasksPageCoreProps {
548
656
  }
549
657
  /**
550
658
  * TasksPageCore — a complete, provider-less, BYO-Apollo Tasks experience in a
551
- * single mount. Composes the existing `TaskBoardCore`, `CreateTaskCore`, and
552
- * `TaskDetailCore` so a host app (e.g. HealthyBowl) doesn't have to wire the
553
- * three together itself:
659
+ * single mount. A Linear-style shell: one toolbar (Board / List / Timeline tabs
660
+ * + search + priority/type filters + "New task"), the selected view, a create
661
+ * modal, and a click-to-open detail drawer.
554
662
  *
555
- * - renders the kanban `TaskBoardCore`,
556
- * - a "New task" button opens `CreateTaskCore` (modal or inline),
557
- * - clicking a card opens `TaskDetailCore` (drawer or inline) with inline edit,
558
- * - `CreateTaskCore.onCreated` + `TaskDetailCore.onUpdated` refetch the board.
559
- *
560
- * BYO-Apollo like the sibling cores: reads the ambient `<ApolloProvider>` and
561
- * takes `workspaceId` from a prop or the PlanMagnetProvider context. Semantic
562
- * tokens only, farm-free, strict TS.
663
+ * BYO-Apollo: reads the ambient `<ApolloProvider>` and takes `workspaceId` from
664
+ * a prop or the PlanMagnetProvider context. Semantic tokens only, farm-free.
563
665
  */
564
- declare function TasksPageCore({ workspaceId: workspaceIdProp, projectId, boardProjectId, columns, readonly, hiddenFields, hideFilters, header, onTaskSaved, createSurface, detailSurface, className, }: TasksPageCoreProps): react.JSX.Element;
666
+ declare function TasksPageCore({ workspaceId: workspaceIdProp, projectId, boardProjectId, columns, readonly, hiddenFields, views, defaultView, resolveAssignee, header, onTaskSaved, createSurface, detailSurface, className, }: TasksPageCoreProps): react.JSX.Element;
565
667
 
566
668
  interface TasksPageProps extends TasksPageCoreProps {
567
669
  /** Workspace API gateway URL (URL mode). */
@@ -816,6 +918,82 @@ interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, VariantProps<typeo
816
918
  */
817
919
  declare function Badge({ className, variant, ...props }: BadgeProps): react.JSX.Element;
818
920
 
921
+ declare const SIZES: {
922
+ readonly sm: "h-5 w-5 text-[9px]";
923
+ readonly md: "h-6 w-6 text-[10px]";
924
+ readonly lg: "h-8 w-8 text-xs";
925
+ };
926
+ interface AvatarProps {
927
+ /** Assignee actor id (used for the deterministic tint + fallback initials). */
928
+ id?: string | null;
929
+ /** Resolved display name, if the host has a directory. */
930
+ name?: string | null;
931
+ size?: keyof typeof SIZES;
932
+ className?: string;
933
+ }
934
+ declare function Avatar({ id, name, size, className }: AvatarProps): react.JSX.Element;
935
+
936
+ /**
937
+ * Linear-style task indicators — status, priority, type.
938
+ *
939
+ * A hard rule of the codebase is "semantic tokens only, never raw colors". The
940
+ * default token palette only exposes a handful of hues (primary / secondary /
941
+ * muted / accent / destructive), which is not enough to give each of the six
942
+ * statuses its own distinct color like a raw-palette design would.
943
+ *
944
+ * So — exactly like Linear — status is differentiated primarily by icon SHAPE
945
+ * (dashed → empty → dotted → filled → check), with a subtle muted→primary tone
946
+ * progression, and priority by a filled-BAR count. This reads as a polished PM
947
+ * tool while staying 100% within the semantic-token contract.
948
+ */
949
+ interface StatusMeta {
950
+ icon: ComponentType<LucideProps>;
951
+ /** Icon tone (semantic token). */
952
+ tone: string;
953
+ }
954
+ /**
955
+ * Per-status icon + tone. Shape carries the meaning; tone progresses from muted
956
+ * (not started) toward primary (in flight / done). Overridable by hosts only
957
+ * via the column labels, never by raw color.
958
+ */
959
+ declare const STATUS_META: Record<TaskStatus, StatusMeta>;
960
+ interface StatusIconProps {
961
+ status: TaskStatus;
962
+ className?: string;
963
+ }
964
+ /** A single status glyph — shape-differentiated, token-toned. */
965
+ declare function StatusIcon({ status, className }: StatusIconProps): react.JSX.Element;
966
+ interface StatusPillProps {
967
+ status: TaskStatus;
968
+ className?: string;
969
+ }
970
+ /** Status as a compact bordered pill (icon + label) — used in the list view. */
971
+ declare function StatusPill({ status, className }: StatusPillProps): react.JSX.Element;
972
+ interface PriorityMeta {
973
+ /** Number of filled bars (0–3). */
974
+ level: number;
975
+ /** Fill tone (semantic token) applied to the filled bars + label. */
976
+ tone: string;
977
+ }
978
+ declare const PRIORITY_META: Record<TaskPriority, PriorityMeta>;
979
+ interface PriorityIndicatorProps {
980
+ priority: TaskPriority;
981
+ /** Show the text label next to the bars. */
982
+ showLabel?: boolean;
983
+ className?: string;
984
+ }
985
+ /**
986
+ * Linear-style priority signal — three bars, filled by level. NONE renders all
987
+ * bars faint (its own recognizable "no priority" look).
988
+ */
989
+ declare function PriorityIndicator({ priority, showLabel, className, }: PriorityIndicatorProps): react.JSX.Element;
990
+ interface TypeBadgeProps {
991
+ type: TaskType;
992
+ className?: string;
993
+ }
994
+ /** Work-item type as a subtle badge. */
995
+ declare function TypeBadge({ type, className }: TypeBadgeProps): react.JSX.Element;
996
+
819
997
  interface ModalProps {
820
998
  open: boolean;
821
999
  onClose: () => void;
@@ -837,4 +1015,4 @@ declare function Drawer(props: DrawerProps): react.JSX.Element;
837
1015
 
838
1016
  declare function cn(...inputs: ClassValue[]): string;
839
1017
 
840
- export { Badge, type BadgeProps, type BoardColumn, CREATE_WORK_ITEM, CreateTask, CreateTaskCore, type CreateTaskCoreProps, type CreateTaskField, type CreateTaskInput, type CreateTaskProps, DEFAULT_BOARD_COLUMNS, Drawer, type DrawerProps, GET_PROJECTS, GET_WORK_ITEM, LIST_WORK_ITEMS, type ListTasksInput, MOVE_WORK_ITEM, Modal, type ModalProps, PROJECT_SUMMARY_FIELDS, type PlanMagnetClientConfig, type PlanMagnetConfig, PlanMagnetProvider, type PlanMagnetProviderProps, type Project, type ProjectList, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, type Task, TaskBoard, TaskBoardCore, type TaskBoardCoreProps, type TaskBoardProps, TaskDetail, TaskDetailCore, type TaskDetailCoreProps, type TaskDetailField, type TaskDetailProps, TaskList, type TaskListColumn, TaskListCore, type TaskListCoreProps, type TaskListProps, type TaskListSort, type TaskPageInfo, type TaskPaginationInput, type TaskPriority, type TaskSavedResult, type TaskStatus, type TaskType, TasksPage, TasksPageCore, type TasksPageCoreProps, type TasksPageField, type TasksPageProps, type TasksPageSaved, UPDATE_WORK_ITEM, type UpdateTaskInput, WORK_ITEM_FIELDS, WORK_ITEM_SUMMARY_FIELDS, type WorkItemDetail, type WorkItemLinkRelation, type WorkItemList, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, usePlanMagnetContext, usePlanMagnetContextSafe, validateTrustedOrigin, waitForPlanMagnetClient };
1018
+ export { Avatar, type AvatarProps, Badge, type BadgeProps, type BoardColumn, CREATE_WORK_ITEM, CreateTask, CreateTaskCore, type CreateTaskCoreProps, type CreateTaskField, type CreateTaskInput, type CreateTaskProps, DEFAULT_BOARD_COLUMNS, Drawer, type DrawerProps, GET_PROJECTS, GET_WORK_ITEM, LIST_WORK_ITEMS, type ListTasksInput, MOVE_WORK_ITEM, Modal, type ModalProps, PRIORITY_META, PROJECT_SUMMARY_FIELDS, type PlanMagnetClientConfig, type PlanMagnetConfig, PlanMagnetProvider, type PlanMagnetProviderProps, PriorityIndicator, type PriorityIndicatorProps, type Project, type ProjectList, type ResolveAssignee, STATUS_META, StatusIcon, type StatusIconProps, StatusPill, type StatusPillProps, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, type Task, TaskBoard, TaskBoardCore, type TaskBoardCoreProps, type TaskBoardProps, TaskCard, type TaskCardProps, TaskDetail, TaskDetailCore, type TaskDetailCoreProps, type TaskDetailField, type TaskDetailProps, TaskList, type TaskListColumn, TaskListCore, type TaskListCoreProps, type TaskListProps, type TaskListSort, type TaskPageInfo, type TaskPaginationInput, type TaskPriority, type TaskSavedResult, type TaskStatus, TaskTimelineCore, type TaskTimelineCoreProps, TaskToolbar, type TaskToolbarProps, type TaskType, type TaskView, TasksPage, TasksPageCore, type TasksPageCoreProps, type TasksPageField, type TasksPageProps, type TasksPageSaved, TypeBadge, type TypeBadgeProps, UPDATE_WORK_ITEM, type UpdateTaskInput, WORK_ITEM_FIELDS, WORK_ITEM_SUMMARY_FIELDS, type WorkItemDetail, type WorkItemLinkRelation, type WorkItemList, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, usePlanMagnetContext, usePlanMagnetContextSafe, validateTrustedOrigin, waitForPlanMagnetClient };