@burdenoff/planmagnet-fe-sdk 2026.704.4 → 2026.705.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.js CHANGED
@@ -512,6 +512,44 @@ var DELETE_WORK_ITEM = gql`
512
512
  planmagnetDeleteWorkItem(id: $id)
513
513
  }
514
514
  `;
515
+ var ENTITY_COMMENT_FIELDS = gql`
516
+ fragment EntityCommentFields on EntityComment {
517
+ id
518
+ authorId
519
+ authorType
520
+ content {
521
+ text
522
+ }
523
+ createdAt
524
+ edited
525
+ editedAt
526
+ status
527
+ }
528
+ `;
529
+ var GET_ENTITY_COMMENTS = gql`
530
+ query GetEntityComments($input: GetCommentsInput!) {
531
+ getEntityComments(input: $input) {
532
+ items {
533
+ ...EntityCommentFields
534
+ }
535
+ total
536
+ }
537
+ }
538
+ ${ENTITY_COMMENT_FIELDS}
539
+ `;
540
+ var CREATE_ENTITY_COMMENT = gql`
541
+ mutation CreateEntityComment($input: CreateEntityCommentInput!) {
542
+ createEntityComment(input: $input) {
543
+ ...EntityCommentFields
544
+ }
545
+ }
546
+ ${ENTITY_COMMENT_FIELDS}
547
+ `;
548
+ var DELETE_ENTITY_COMMENT = gql`
549
+ mutation DeleteEntityComment($input: DeleteCommentInput!) {
550
+ deleteEntityComment(input: $input)
551
+ }
552
+ `;
515
553
  function cn(...inputs) {
516
554
  return twMerge(clsx(inputs));
517
555
  }
@@ -748,6 +786,18 @@ var DEFAULT_TASK_LABELS = {
748
786
  linkedRecordsLabel: "Linked records",
749
787
  createdLabel: "Created",
750
788
  updatedLabel: "Updated",
789
+ parentLabel: "Parent",
790
+ subtasksLabel: "Sub-tasks",
791
+ addSubtask: "Add sub-task",
792
+ commentsLabel: "Comments",
793
+ commentPlaceholder: "Write a comment\u2026",
794
+ postComment: "Comment",
795
+ posting: "Posting\u2026",
796
+ noComments: "No comments yet",
797
+ you: "You",
798
+ editedTag: "(edited)",
799
+ failedToComment: "Failed to post comment",
800
+ failedToDeleteComment: "Failed to delete comment",
751
801
  create: "Create task",
752
802
  creating: "Creating\u2026",
753
803
  cancel: "Cancel",
@@ -1370,6 +1420,10 @@ function CreateTaskCore({
1370
1420
  projectId,
1371
1421
  title: title.trim(),
1372
1422
  type,
1423
+ // Sub-task linkage: parentId is not an editable form field — it rides
1424
+ // through from defaultValues (the "Add sub-task" flow) so a created work
1425
+ // item nests under its parent.
1426
+ ...defaultValues?.parentId ? { parentId: defaultValues.parentId } : {},
1373
1427
  ...hidden.has("status") ? {} : { status },
1374
1428
  ...hidden.has("priority") ? {} : { priority },
1375
1429
  ...hidden.has("description") || !description.trim() ? {} : { description: description.trim() },
@@ -2447,8 +2501,129 @@ function TaskToolbar({
2447
2501
  }
2448
2502
  );
2449
2503
  }
2450
- var fieldClass2 = "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring";
2451
2504
  var labelClass2 = "text-xs font-medium uppercase tracking-wide text-muted-foreground";
2505
+ var fieldClass2 = "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring";
2506
+ function TaskCommentsCore({
2507
+ entityType,
2508
+ entityId,
2509
+ currentActorId,
2510
+ resolveAssignee,
2511
+ readonly,
2512
+ className
2513
+ }) {
2514
+ const L = useTaskLabels();
2515
+ const [text, setText] = useState("");
2516
+ const [error, setError] = useState(null);
2517
+ const { data, loading, refetch } = useQuery(
2518
+ GET_ENTITY_COMMENTS,
2519
+ {
2520
+ variables: {
2521
+ input: {
2522
+ entityType,
2523
+ entityId,
2524
+ take: 100,
2525
+ sortBy: "createdAt",
2526
+ sortOrder: "asc"
2527
+ }
2528
+ },
2529
+ skip: !entityId,
2530
+ errorPolicy: "all"
2531
+ }
2532
+ );
2533
+ const comments = data?.getEntityComments?.items ?? [];
2534
+ const [createComment, { loading: posting }] = useMutation(CREATE_ENTITY_COMMENT);
2535
+ const [deleteComment] = useMutation(
2536
+ DELETE_ENTITY_COMMENT
2537
+ );
2538
+ const authorName = (id) => id === currentActorId ? L.you : resolveAssignee?.(id)?.name ?? void 0;
2539
+ const handlePost = async (e) => {
2540
+ e.preventDefault();
2541
+ const body = text.trim();
2542
+ if (!body) return;
2543
+ setError(null);
2544
+ try {
2545
+ await createComment({
2546
+ variables: {
2547
+ input: {
2548
+ entityType,
2549
+ entityId,
2550
+ content: { text: body },
2551
+ contentType: "TEXT"
2552
+ }
2553
+ }
2554
+ });
2555
+ setText("");
2556
+ await refetch();
2557
+ } catch {
2558
+ setError(L.failedToComment);
2559
+ }
2560
+ };
2561
+ const handleDelete = async (id) => {
2562
+ setError(null);
2563
+ try {
2564
+ await deleteComment({ variables: { input: { id, soft: true } } });
2565
+ await refetch();
2566
+ } catch {
2567
+ setError(L.failedToDeleteComment);
2568
+ }
2569
+ };
2570
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
2571
+ /* @__PURE__ */ jsxs("div", { className: labelClass2, children: [
2572
+ L.commentsLabel,
2573
+ comments.length > 0 ? ` (${comments.length})` : ""
2574
+ ] }),
2575
+ /* @__PURE__ */ jsx("ul", { className: "space-y-3", children: comments.length === 0 && !loading ? /* @__PURE__ */ jsx("li", { className: "text-sm text-muted-foreground", children: L.noComments }) : comments.map((c) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2", children: [
2576
+ /* @__PURE__ */ jsx(Avatar, { id: c.authorId, name: authorName(c.authorId), size: "sm" }),
2577
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2578
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2579
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: authorName(c.authorId) ?? c.authorId.slice(0, 8) }),
2580
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: formatDateFull(c.createdAt) }),
2581
+ c.edited && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: L.editedTag }),
2582
+ !readonly && c.authorId === currentActorId && /* @__PURE__ */ jsx(
2583
+ "button",
2584
+ {
2585
+ type: "button",
2586
+ onClick: () => handleDelete(c.id),
2587
+ "aria-label": L.del,
2588
+ title: L.del,
2589
+ className: "ml-auto rounded p-1 text-muted-foreground hover:text-destructive",
2590
+ children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
2591
+ }
2592
+ )
2593
+ ] }),
2594
+ /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap break-words text-sm text-foreground", children: c.content?.text })
2595
+ ] })
2596
+ ] }, c.id)) }),
2597
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }),
2598
+ !readonly && /* @__PURE__ */ jsxs("form", { onSubmit: handlePost, className: "space-y-2", children: [
2599
+ /* @__PURE__ */ jsx(
2600
+ "textarea",
2601
+ {
2602
+ className: cn(fieldClass2, "min-h-[60px]"),
2603
+ rows: 2,
2604
+ value: text,
2605
+ onChange: (e) => setText(e.target.value),
2606
+ placeholder: L.commentPlaceholder,
2607
+ "aria-label": L.commentsLabel
2608
+ }
2609
+ ),
2610
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
2611
+ "button",
2612
+ {
2613
+ type: "submit",
2614
+ disabled: posting || !text.trim(),
2615
+ className: cn(
2616
+ "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground",
2617
+ (posting || !text.trim()) && "cursor-not-allowed opacity-50"
2618
+ ),
2619
+ children: posting ? L.posting : L.postComment
2620
+ }
2621
+ ) })
2622
+ ] })
2623
+ ] });
2624
+ }
2625
+ var fieldClass3 = "w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring";
2626
+ var labelClass3 = "text-xs font-medium uppercase tracking-wide text-muted-foreground";
2452
2627
  var priorityVariant = {
2453
2628
  NONE: "muted",
2454
2629
  LOW: "muted",
@@ -2468,6 +2643,10 @@ function TaskDetailCore({
2468
2643
  assigneeOptions,
2469
2644
  linkSourceProduct,
2470
2645
  renderLinkIcon,
2646
+ onOpenItem,
2647
+ onAddSubtask,
2648
+ commentsEntityType,
2649
+ currentActorId,
2471
2650
  className
2472
2651
  }) {
2473
2652
  const client = useApolloClient();
@@ -2486,6 +2665,20 @@ function TaskDetailCore({
2486
2665
  linkSourceProduct
2487
2666
  );
2488
2667
  const links = item ? linksByItem.get(item.id) ?? [] : [];
2668
+ const { data: parentData } = useQuery(GET_WORK_ITEM, {
2669
+ variables: { id: item?.parentId },
2670
+ skip: !item?.parentId
2671
+ });
2672
+ const parent = parentData?.planmagnetWorkItem ?? null;
2673
+ const { data: childData } = useQuery(LIST_WORK_ITEMS, {
2674
+ variables: {
2675
+ workspaceId: item?.workspaceId,
2676
+ filter: { parentId: item?.id },
2677
+ pagination: { first: 100 }
2678
+ },
2679
+ skip: !item?.id || !item?.workspaceId
2680
+ });
2681
+ const children = childData?.planmagnetWorkItems?.items ?? [];
2489
2682
  const [editing, setEditing] = useState(false);
2490
2683
  const [confirmingDelete, setConfirmingDelete] = useState(false);
2491
2684
  const [title, setTitle] = useState("");
@@ -2638,69 +2831,133 @@ function TaskDetailCore({
2638
2831
  ": ",
2639
2832
  deleteError.message
2640
2833
  ] }),
2641
- !editing ? /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
2642
- !hidden.has("type") && /* @__PURE__ */ jsx(Field, { label: L.typeLabel, children: /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: L.type[item.type] }) }),
2643
- !hidden.has("status") && /* @__PURE__ */ jsx(Field, { label: L.statusLabel, children: /* @__PURE__ */ jsx("span", { className: "capitalize text-foreground", children: L.status[item.status] }) }),
2644
- !hidden.has("priority") && /* @__PURE__ */ jsx(Field, { label: L.priorityLabel, children: /* @__PURE__ */ jsx(Badge, { variant: priorityVariant[item.priority], children: L.priority[item.priority] }) }),
2645
- !hidden.has("assignee") && /* @__PURE__ */ jsx(Field, { label: L.assigneeLabel, children: item.assigneeId ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
2646
- /* @__PURE__ */ jsx(
2647
- Avatar,
2648
- {
2649
- id: item.assigneeId,
2650
- name: resolveAssignee?.(item.assigneeId)?.name,
2651
- size: "sm"
2652
- }
2653
- ),
2654
- /* @__PURE__ */ jsx("span", { className: "text-foreground", children: resolveAssignee?.(item.assigneeId)?.name ?? L.assigned })
2655
- ] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: L.unassigned }) }),
2656
- !hidden.has("dueDate") && /* @__PURE__ */ jsx(Field, { label: L.dueDateLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: formatDateFull(item.dueDate) ?? "\u2014" }) }),
2657
- !hidden.has("storyPoints") && /* @__PURE__ */ jsx(Field, { label: L.storyPointsLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.storyPoints ?? 0 }) }),
2658
- !hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2659
- /* @__PURE__ */ jsx("dt", { className: labelClass2, children: L.description }),
2660
- /* @__PURE__ */ jsx("dd", { className: "mt-1 whitespace-pre-wrap text-sm text-foreground", children: item.description || "\u2014" })
2661
- ] }),
2662
- !hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2663
- /* @__PURE__ */ jsx("dt", { className: labelClass2, children: L.labelsLabel }),
2664
- /* @__PURE__ */ jsx("dd", { className: "mt-1 flex flex-wrap gap-1", children: (item.labels ?? []).length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "\u2014" }) : item.labels.map((l) => /* @__PURE__ */ jsx(
2665
- "span",
2666
- {
2667
- className: "rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground",
2668
- children: l
2669
- },
2670
- l
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)
2834
+ !editing ? /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
2835
+ /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
2836
+ !hidden.has("type") && /* @__PURE__ */ jsx(Field, { label: L.typeLabel, children: /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: L.type[item.type] }) }),
2837
+ !hidden.has("status") && /* @__PURE__ */ jsx(Field, { label: L.statusLabel, children: /* @__PURE__ */ jsx("span", { className: "capitalize text-foreground", children: L.status[item.status] }) }),
2838
+ !hidden.has("priority") && /* @__PURE__ */ jsx(Field, { label: L.priorityLabel, children: /* @__PURE__ */ jsx(Badge, { variant: priorityVariant[item.priority], children: L.priority[item.priority] }) }),
2839
+ !hidden.has("assignee") && /* @__PURE__ */ jsx(Field, { label: L.assigneeLabel, children: item.assigneeId ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
2840
+ /* @__PURE__ */ jsx(
2841
+ Avatar,
2842
+ {
2843
+ id: item.assigneeId,
2844
+ name: resolveAssignee?.(item.assigneeId)?.name,
2845
+ size: "sm"
2846
+ }
2847
+ ),
2848
+ /* @__PURE__ */ jsx("span", { className: "text-foreground", children: resolveAssignee?.(item.assigneeId)?.name ?? L.assigned })
2849
+ ] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: L.unassigned }) }),
2850
+ !hidden.has("dueDate") && /* @__PURE__ */ jsx(Field, { label: L.dueDateLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: formatDateFull(item.dueDate) ?? "\u2014" }) }),
2851
+ !hidden.has("storyPoints") && /* @__PURE__ */ jsx(Field, { label: L.storyPointsLabel, children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.storyPoints ?? 0 }) }),
2852
+ !hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2853
+ /* @__PURE__ */ jsx("dt", { className: labelClass3, children: L.description }),
2854
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 whitespace-pre-wrap text-sm text-foreground", children: item.description || "\u2014" })
2855
+ ] }),
2856
+ !hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2857
+ /* @__PURE__ */ jsx("dt", { className: labelClass3, children: L.labelsLabel }),
2858
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 flex flex-wrap gap-1", children: (item.labels ?? []).length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "\u2014" }) : item.labels.map((l) => /* @__PURE__ */ jsx(
2859
+ "span",
2860
+ {
2861
+ className: "rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground",
2862
+ children: l
2863
+ },
2864
+ l
2865
+ )) })
2866
+ ] }),
2867
+ links.length > 0 && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2868
+ /* @__PURE__ */ jsx("dt", { className: labelClass3, children: L.linkedRecordsLabel }),
2869
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 flex flex-wrap gap-1.5", children: links.map((link) => /* @__PURE__ */ jsx(
2870
+ LinkChip,
2871
+ {
2872
+ link,
2873
+ renderIcon: renderLinkIcon
2874
+ },
2875
+ link.id
2876
+ )) })
2689
2877
  ] }),
2690
- item.updatedAt && /* @__PURE__ */ jsxs("span", { children: [
2691
- L.updatedLabel,
2692
- " ",
2693
- formatDateFull(item.updatedAt)
2878
+ parent && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2879
+ /* @__PURE__ */ jsx("dt", { className: labelClass3, children: L.parentLabel }),
2880
+ /* @__PURE__ */ jsx("dd", { className: "mt-1", children: /* @__PURE__ */ jsxs(
2881
+ "button",
2882
+ {
2883
+ type: "button",
2884
+ onClick: () => onOpenItem?.(parent.id),
2885
+ className: "inline-flex max-w-full items-center gap-1.5 rounded-md border border-border bg-muted/40 px-2 py-1 text-sm text-foreground hover:bg-muted",
2886
+ children: [
2887
+ /* @__PURE__ */ jsx(StatusIcon, { status: parent.status }),
2888
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: parent.key }),
2889
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: parent.title })
2890
+ ]
2891
+ }
2892
+ ) })
2893
+ ] }),
2894
+ (children.length > 0 || onAddSubtask && canEdit) && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
2895
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
2896
+ /* @__PURE__ */ jsxs("dt", { className: labelClass3, children: [
2897
+ L.subtasksLabel,
2898
+ children.length > 0 ? ` (${children.length})` : ""
2899
+ ] }),
2900
+ onAddSubtask && canEdit && /* @__PURE__ */ jsxs(
2901
+ "button",
2902
+ {
2903
+ type: "button",
2904
+ onClick: () => onAddSubtask({
2905
+ id: item.id,
2906
+ projectId: item.projectId
2907
+ }),
2908
+ className: "text-xs font-medium text-primary hover:underline",
2909
+ children: [
2910
+ "+ ",
2911
+ L.addSubtask
2912
+ ]
2913
+ }
2914
+ )
2915
+ ] }),
2916
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 space-y-1", children: children.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "\u2014" }) : children.map((c) => /* @__PURE__ */ jsxs(
2917
+ "button",
2918
+ {
2919
+ type: "button",
2920
+ onClick: () => onOpenItem?.(c.id),
2921
+ className: "flex w-full items-center gap-2 rounded-md px-2 py-1 text-left text-sm hover:bg-muted",
2922
+ children: [
2923
+ /* @__PURE__ */ jsx(StatusIcon, { status: c.status }),
2924
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: c.key }),
2925
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-foreground", children: c.title })
2926
+ ]
2927
+ },
2928
+ c.id
2929
+ )) })
2930
+ ] }),
2931
+ (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: [
2932
+ item.createdAt && /* @__PURE__ */ jsxs("span", { children: [
2933
+ L.createdLabel,
2934
+ " ",
2935
+ formatDateFull(item.createdAt)
2936
+ ] }),
2937
+ item.updatedAt && /* @__PURE__ */ jsxs("span", { children: [
2938
+ L.updatedLabel,
2939
+ " ",
2940
+ formatDateFull(item.updatedAt)
2941
+ ] })
2694
2942
  ] })
2695
- ] })
2943
+ ] }),
2944
+ commentsEntityType && /* @__PURE__ */ jsx("div", { className: "border-t border-border pt-4", children: /* @__PURE__ */ jsx(
2945
+ TaskCommentsCore,
2946
+ {
2947
+ entityType: commentsEntityType,
2948
+ entityId: item.id,
2949
+ currentActorId,
2950
+ resolveAssignee
2951
+ }
2952
+ ) })
2696
2953
  ] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSave, className: "space-y-4", children: [
2697
2954
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2698
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-title", className: labelClass2, children: L.title }),
2955
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-title", className: labelClass3, children: L.title }),
2699
2956
  /* @__PURE__ */ jsx(
2700
2957
  "input",
2701
2958
  {
2702
2959
  id: "pm-detail-title",
2703
- className: fieldClass2,
2960
+ className: fieldClass3,
2704
2961
  value: title,
2705
2962
  onChange: (e) => setTitle(e.target.value),
2706
2963
  required: true
@@ -2708,12 +2965,12 @@ function TaskDetailCore({
2708
2965
  )
2709
2966
  ] }),
2710
2967
  !hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2711
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-desc", className: labelClass2, children: L.description }),
2968
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-desc", className: labelClass3, children: L.description }),
2712
2969
  /* @__PURE__ */ jsx(
2713
2970
  "textarea",
2714
2971
  {
2715
2972
  id: "pm-detail-desc",
2716
- className: cn(fieldClass2, "min-h-[80px]"),
2973
+ className: cn(fieldClass3, "min-h-[80px]"),
2717
2974
  value: description,
2718
2975
  onChange: (e) => setDescription(e.target.value)
2719
2976
  }
@@ -2721,12 +2978,12 @@ function TaskDetailCore({
2721
2978
  ] }),
2722
2979
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
2723
2980
  !hidden.has("type") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2724
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-type", className: labelClass2, children: L.typeLabel }),
2981
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-type", className: labelClass3, children: L.typeLabel }),
2725
2982
  /* @__PURE__ */ jsx(
2726
2983
  "select",
2727
2984
  {
2728
2985
  id: "pm-detail-type",
2729
- className: cn(fieldClass2, "capitalize"),
2986
+ className: cn(fieldClass3, "capitalize"),
2730
2987
  value: type,
2731
2988
  onChange: (e) => setType(e.target.value),
2732
2989
  children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: L.type[t] }, t))
@@ -2734,12 +2991,12 @@ function TaskDetailCore({
2734
2991
  )
2735
2992
  ] }),
2736
2993
  !hidden.has("status") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2737
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-status", className: labelClass2, children: L.statusLabel }),
2994
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-status", className: labelClass3, children: L.statusLabel }),
2738
2995
  /* @__PURE__ */ jsx(
2739
2996
  "select",
2740
2997
  {
2741
2998
  id: "pm-detail-status",
2742
- className: cn(fieldClass2, "capitalize"),
2999
+ className: cn(fieldClass3, "capitalize"),
2743
3000
  value: status,
2744
3001
  onChange: (e) => setStatus(e.target.value),
2745
3002
  children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: L.status[s] }, s))
@@ -2747,12 +3004,12 @@ function TaskDetailCore({
2747
3004
  )
2748
3005
  ] }),
2749
3006
  !hidden.has("priority") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2750
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-priority", className: labelClass2, children: L.priorityLabel }),
3007
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-priority", className: labelClass3, children: L.priorityLabel }),
2751
3008
  /* @__PURE__ */ jsx(
2752
3009
  "select",
2753
3010
  {
2754
3011
  id: "pm-detail-priority",
2755
- className: cn(fieldClass2, "capitalize"),
3012
+ className: cn(fieldClass3, "capitalize"),
2756
3013
  value: priority,
2757
3014
  onChange: (e) => setPriority(e.target.value),
2758
3015
  children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: L.priority[p] }, p))
@@ -2760,12 +3017,12 @@ function TaskDetailCore({
2760
3017
  )
2761
3018
  ] }),
2762
3019
  !hidden.has("assignee") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2763
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-assignee", className: labelClass2, children: L.assigneeLabel }),
3020
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-assignee", className: labelClass3, children: L.assigneeLabel }),
2764
3021
  assigneeOptions && assigneeOptions.length > 0 ? /* @__PURE__ */ jsxs(
2765
3022
  "select",
2766
3023
  {
2767
3024
  id: "pm-detail-assignee",
2768
- className: fieldClass2,
3025
+ className: fieldClass3,
2769
3026
  value: assigneeId,
2770
3027
  onChange: (e) => setAssigneeId(e.target.value),
2771
3028
  children: [
@@ -2777,7 +3034,7 @@ function TaskDetailCore({
2777
3034
  "input",
2778
3035
  {
2779
3036
  id: "pm-detail-assignee",
2780
- className: fieldClass2,
3037
+ className: fieldClass3,
2781
3038
  value: assigneeId,
2782
3039
  onChange: (e) => setAssigneeId(e.target.value),
2783
3040
  placeholder: L.assigneePlaceholder
@@ -2785,27 +3042,27 @@ function TaskDetailCore({
2785
3042
  )
2786
3043
  ] }),
2787
3044
  !hidden.has("dueDate") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2788
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-due", className: labelClass2, children: L.dueDateLabel }),
3045
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-due", className: labelClass3, children: L.dueDateLabel }),
2789
3046
  /* @__PURE__ */ jsx(
2790
3047
  "input",
2791
3048
  {
2792
3049
  id: "pm-detail-due",
2793
3050
  type: "date",
2794
- className: fieldClass2,
3051
+ className: fieldClass3,
2795
3052
  value: dueDate,
2796
3053
  onChange: (e) => setDueDate(e.target.value)
2797
3054
  }
2798
3055
  )
2799
3056
  ] }),
2800
3057
  !hidden.has("storyPoints") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2801
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-points", className: labelClass2, children: L.storyPointsLabel }),
3058
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-points", className: labelClass3, children: L.storyPointsLabel }),
2802
3059
  /* @__PURE__ */ jsx(
2803
3060
  "input",
2804
3061
  {
2805
3062
  id: "pm-detail-points",
2806
3063
  type: "number",
2807
3064
  min: 0,
2808
- className: fieldClass2,
3065
+ className: fieldClass3,
2809
3066
  value: storyPoints,
2810
3067
  onChange: (e) => setStoryPoints(e.target.value)
2811
3068
  }
@@ -2813,12 +3070,12 @@ function TaskDetailCore({
2813
3070
  ] })
2814
3071
  ] }),
2815
3072
  !hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
2816
- /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-labels", className: labelClass2, children: L.labelsLabel }),
3073
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-labels", className: labelClass3, children: L.labelsLabel }),
2817
3074
  /* @__PURE__ */ jsx(
2818
3075
  "input",
2819
3076
  {
2820
3077
  id: "pm-detail-labels",
2821
- className: fieldClass2,
3078
+ className: fieldClass3,
2822
3079
  value: labels,
2823
3080
  onChange: (e) => setLabels(e.target.value),
2824
3081
  placeholder: L.labelsPlaceholder
@@ -2858,7 +3115,7 @@ function TaskDetailCore({
2858
3115
  }
2859
3116
  function Field({ label, children }) {
2860
3117
  return /* @__PURE__ */ jsxs("div", { children: [
2861
- /* @__PURE__ */ jsx("dt", { className: labelClass2, children: label }),
3118
+ /* @__PURE__ */ jsx("dt", { className: labelClass3, children: label }),
2862
3119
  /* @__PURE__ */ jsx("dd", { className: "mt-1 text-sm", children })
2863
3120
  ] });
2864
3121
  }
@@ -2905,6 +3162,7 @@ function TasksPageCore({
2905
3162
  renderLinkIcon,
2906
3163
  assigneeOptions,
2907
3164
  currentActorId,
3165
+ commentsEntityType,
2908
3166
  labels,
2909
3167
  openItemId,
2910
3168
  header,
@@ -2924,6 +3182,7 @@ function TasksPageCore({
2924
3182
  const [mine, setMine] = useState(false);
2925
3183
  const [creating, setCreating] = useState(false);
2926
3184
  const [selectedId, setSelectedId] = useState(null);
3185
+ const [createDefaults, setCreateDefaults] = useState(null);
2927
3186
  useEffect(() => {
2928
3187
  if (openItemId) setSelectedId(openItemId);
2929
3188
  }, [openItemId]);
@@ -2935,10 +3194,31 @@ function TasksPageCore({
2935
3194
  (workItem) => {
2936
3195
  refetchBoard();
2937
3196
  setCreating(false);
3197
+ setCreateDefaults(null);
2938
3198
  onTaskSaved?.({ workItem, operation: "created" });
2939
3199
  },
2940
3200
  [refetchBoard, onTaskSaved]
2941
3201
  );
3202
+ const handleAddSubtask = useCallback(
3203
+ (parent) => {
3204
+ setSelectedId(null);
3205
+ setCreateDefaults({
3206
+ parentId: parent.id,
3207
+ projectId: parent.projectId,
3208
+ type: "SUB_TASK"
3209
+ });
3210
+ setCreating(true);
3211
+ },
3212
+ []
3213
+ );
3214
+ const startCreate = useCallback(() => {
3215
+ setCreateDefaults(null);
3216
+ setCreating(true);
3217
+ }, []);
3218
+ const cancelCreate = useCallback(() => {
3219
+ setCreating(false);
3220
+ setCreateDefaults(null);
3221
+ }, []);
2942
3222
  const handleUpdated = useCallback(
2943
3223
  (workItem) => {
2944
3224
  refetchBoard();
@@ -2966,8 +3246,9 @@ function TasksPageCore({
2966
3246
  projectId,
2967
3247
  assigneeOptions,
2968
3248
  hiddenFields,
3249
+ defaultValues: createDefaults ?? void 0,
2969
3250
  onCreated: handleCreated,
2970
- onCancel: () => setCreating(false)
3251
+ onCancel: cancelCreate
2971
3252
  }
2972
3253
  );
2973
3254
  const detailView = selectedId != null ? /* @__PURE__ */ jsx(
@@ -2981,7 +3262,11 @@ function TasksPageCore({
2981
3262
  linkSourceProduct,
2982
3263
  renderLinkIcon,
2983
3264
  onUpdated: handleUpdated,
2984
- onDeleted: handleDeleted
3265
+ onDeleted: handleDeleted,
3266
+ onOpenItem: handleSelect,
3267
+ onAddSubtask: handleAddSubtask,
3268
+ commentsEntityType,
3269
+ currentActorId
2985
3270
  }
2986
3271
  ) : null;
2987
3272
  const listPriority = priority === "ALL" ? void 0 : priority;
@@ -3009,7 +3294,7 @@ function TasksPageCore({
3009
3294
  onPriorityChange: setPriority,
3010
3295
  type,
3011
3296
  onTypeChange: setType,
3012
- onNewTask: () => setCreating(true),
3297
+ onNewTask: startCreate,
3013
3298
  canCreate,
3014
3299
  mine,
3015
3300
  onMineChange: currentActorId ? setMine : void 0
@@ -3071,7 +3356,7 @@ function TasksPageCore({
3071
3356
  Modal,
3072
3357
  {
3073
3358
  open: creating,
3074
- onClose: () => setCreating(false),
3359
+ onClose: cancelCreate,
3075
3360
  ariaLabel: "Create task",
3076
3361
  className: "max-w-xl",
3077
3362
  children: /* @__PURE__ */ jsx("div", { className: "p-2 pt-8", children: createForm })
@@ -3117,6 +3402,6 @@ function TasksPage({
3117
3402
  );
3118
3403
  }
3119
3404
 
3120
- export { Avatar, 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, 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 };
3405
+ export { Avatar, 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 };
3121
3406
  //# sourceMappingURL=index.js.map
3122
3407
  //# sourceMappingURL=index.js.map