@burdenoff/planmagnet-fe-sdk 2026.703.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 ADDED
@@ -0,0 +1,1764 @@
1
+ import { createContext, useMemo, useEffect, useContext, useState, useCallback } from 'react';
2
+ import { ApolloProvider, useQuery, useMutation, useApolloClient } from '@apollo/client/react';
3
+ import { createHttpLink, ApolloClient, from, InMemoryCache } from '@apollo/client/core';
4
+ import { setContext } from '@apollo/client/link/context';
5
+ import { onError } from '@apollo/client/link/error';
6
+ import { CombinedGraphQLErrors } from '@apollo/client/errors';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+ import { Card, CardContent } from '@burdenoff/fe-libs/ui';
9
+ import { Filter } from 'lucide-react';
10
+ import { gql } from '@apollo/client';
11
+ import { clsx } from 'clsx';
12
+ import { twMerge } from 'tailwind-merge';
13
+ import { cva } from 'class-variance-authority';
14
+
15
+ var clientInstance = null;
16
+ function buildCache() {
17
+ return new InMemoryCache({
18
+ typePolicies: {
19
+ Query: {
20
+ fields: {
21
+ planmagnetWorkItems: { merge: false },
22
+ planmagnetProjects: { merge: false },
23
+ planmagnetWorkItemLinks: { merge: false }
24
+ }
25
+ },
26
+ WorkItem: { keyFields: ["id"] },
27
+ PlanmagnetProject: { keyFields: ["id"] },
28
+ Project: { keyFields: ["id"] },
29
+ WorkItemLink: { keyFields: ["id"] }
30
+ }
31
+ });
32
+ }
33
+ function createPlanMagnetClient(config2) {
34
+ const graphqlUrl = getGraphQLUrl(config2.apiGatewayUrl);
35
+ const httpLink = createHttpLink({ uri: graphqlUrl });
36
+ const authLink = setContext((_, { headers }) => ({
37
+ headers: {
38
+ ...headers,
39
+ ...config2.authToken && {
40
+ authorization: `Bearer ${config2.authToken}`
41
+ },
42
+ ...config2.workspaceToken && {
43
+ "x-workspace-authorization": `Bearer ${config2.workspaceToken}`
44
+ },
45
+ "x-workspace-id": config2.workspaceId,
46
+ ...config2.tenantId && { "x-tenant-id": config2.tenantId }
47
+ }
48
+ }));
49
+ const errorLink = onError(({ error }) => {
50
+ if (!config2.onAuthError) return;
51
+ if (CombinedGraphQLErrors.is(error)) {
52
+ for (const graphQLError of error.errors) {
53
+ const code = graphQLError.extensions?.code;
54
+ if (code === "UNAUTHENTICATED" || code === "FORBIDDEN") {
55
+ config2.onAuthError();
56
+ return;
57
+ }
58
+ }
59
+ } else if (error) {
60
+ const msg = error.message ?? "";
61
+ if (msg.includes("401") || msg.includes("403") || msg.includes("Unauthorized")) {
62
+ config2.onAuthError();
63
+ }
64
+ }
65
+ });
66
+ return new ApolloClient({
67
+ link: from([errorLink, authLink, httpLink]),
68
+ cache: buildCache(),
69
+ defaultOptions: {
70
+ watchQuery: { fetchPolicy: "cache-and-network" },
71
+ query: { fetchPolicy: "network-only" }
72
+ }
73
+ });
74
+ }
75
+ function getGraphQLUrl(apiGatewayUrl) {
76
+ const normalizedBase = apiGatewayUrl.endsWith("/") ? apiGatewayUrl.slice(0, -1) : apiGatewayUrl;
77
+ if (normalizedBase.endsWith("/graphql")) {
78
+ return normalizedBase;
79
+ }
80
+ return `${normalizedBase}/workspaces/graphql`;
81
+ }
82
+ function setPlanMagnetClient(client) {
83
+ clientInstance = client;
84
+ }
85
+ function getPlanMagnetClient() {
86
+ if (!clientInstance) {
87
+ throw new Error(
88
+ "PlanMagnet client not initialized. Use PlanMagnetProvider or call setPlanMagnetClient()."
89
+ );
90
+ }
91
+ return clientInstance;
92
+ }
93
+ function getPlanMagnetClientSafe() {
94
+ return clientInstance;
95
+ }
96
+ function isPlanMagnetClientReady() {
97
+ return clientInstance !== null;
98
+ }
99
+ function waitForPlanMagnetClient(timeoutMs = 1e4, intervalMs = 100) {
100
+ return new Promise((resolve) => {
101
+ if (clientInstance) {
102
+ resolve(clientInstance);
103
+ return;
104
+ }
105
+ const start = Date.now();
106
+ const timer = setInterval(() => {
107
+ if (clientInstance) {
108
+ clearInterval(timer);
109
+ resolve(clientInstance);
110
+ } else if (Date.now() - start >= timeoutMs) {
111
+ clearInterval(timer);
112
+ resolve(null);
113
+ }
114
+ }, intervalMs);
115
+ });
116
+ }
117
+ function resetPlanMagnetClient() {
118
+ clientInstance = null;
119
+ }
120
+
121
+ // src/config/index.ts
122
+ var runtimeConfig = {
123
+ apiGatewayUrl: "",
124
+ workspaceId: ""
125
+ };
126
+ var config = new Proxy({}, {
127
+ get(_, prop) {
128
+ return runtimeConfig[prop];
129
+ }
130
+ });
131
+ function getPlanMagnetConfig() {
132
+ return { ...runtimeConfig };
133
+ }
134
+ function setPlanMagnetConfig(newConfig) {
135
+ runtimeConfig = { ...runtimeConfig, ...newConfig };
136
+ }
137
+ function resetPlanMagnetConfig() {
138
+ runtimeConfig = {
139
+ apiGatewayUrl: "",
140
+ workspaceId: ""
141
+ };
142
+ }
143
+ function normalizeOrigin(origin) {
144
+ return origin.replace(/\/$/, "");
145
+ }
146
+ function validateTrustedOrigin(trustedOrigins) {
147
+ if (typeof window === "undefined" || !trustedOrigins?.length) {
148
+ return;
149
+ }
150
+ const currentOrigin = normalizeOrigin(window.location.origin);
151
+ const allowedOrigins = trustedOrigins.map(normalizeOrigin);
152
+ if (!allowedOrigins.includes(currentOrigin)) {
153
+ throw new Error(
154
+ `PlanMagnet SDK blocked untrusted origin: ${currentOrigin}`
155
+ );
156
+ }
157
+ }
158
+ function getGraphQLEndpoint(baseUrl) {
159
+ const url = baseUrl || runtimeConfig.apiGatewayUrl;
160
+ if (!url) {
161
+ throw new Error("PlanMagnet SDK requires apiGatewayUrl to be configured");
162
+ }
163
+ const normalizedBase = url.endsWith("/") ? url.slice(0, -1) : url;
164
+ if (normalizedBase.endsWith("/graphql")) {
165
+ return normalizedBase;
166
+ }
167
+ return `${normalizedBase}/workspaces/graphql`;
168
+ }
169
+ var PlanMagnetContext = createContext(null);
170
+ function PlanMagnetProvider({
171
+ apiGatewayUrl,
172
+ authToken,
173
+ workspaceToken,
174
+ workspaceId,
175
+ tenantId,
176
+ organizationId,
177
+ trustedOrigins,
178
+ onAuthError,
179
+ workspaceClient: externalWorkspaceClient,
180
+ apolloClient: legacyClient,
181
+ children
182
+ }) {
183
+ validateTrustedOrigin(trustedOrigins);
184
+ const workspaceClient = useMemo(() => {
185
+ if (externalWorkspaceClient) return externalWorkspaceClient;
186
+ if (legacyClient) return legacyClient;
187
+ if (apiGatewayUrl) {
188
+ return createPlanMagnetClient({
189
+ apiGatewayUrl,
190
+ authToken,
191
+ workspaceToken,
192
+ workspaceId,
193
+ tenantId,
194
+ onAuthError
195
+ });
196
+ }
197
+ throw new Error(
198
+ "PlanMagnetProvider: Either provide workspaceClient or apiGatewayUrl"
199
+ );
200
+ }, [
201
+ apiGatewayUrl,
202
+ authToken,
203
+ workspaceToken,
204
+ workspaceId,
205
+ tenantId,
206
+ onAuthError,
207
+ externalWorkspaceClient,
208
+ legacyClient
209
+ ]);
210
+ useEffect(() => {
211
+ setPlanMagnetClient(workspaceClient);
212
+ return () => {
213
+ resetPlanMagnetClient();
214
+ };
215
+ }, [workspaceClient]);
216
+ useEffect(() => {
217
+ setPlanMagnetConfig({
218
+ apiGatewayUrl,
219
+ authToken,
220
+ workspaceId,
221
+ tenantId,
222
+ organizationId,
223
+ trustedOrigins
224
+ });
225
+ return () => {
226
+ resetPlanMagnetConfig();
227
+ };
228
+ }, [
229
+ apiGatewayUrl,
230
+ authToken,
231
+ workspaceId,
232
+ tenantId,
233
+ organizationId,
234
+ trustedOrigins
235
+ ]);
236
+ const contextValue = useMemo(
237
+ () => ({
238
+ apiGatewayUrl,
239
+ authToken,
240
+ workspaceId,
241
+ tenantId,
242
+ organizationId,
243
+ trustedOrigins,
244
+ workspaceClient
245
+ }),
246
+ [
247
+ apiGatewayUrl,
248
+ authToken,
249
+ workspaceId,
250
+ tenantId,
251
+ organizationId,
252
+ trustedOrigins,
253
+ workspaceClient
254
+ ]
255
+ );
256
+ return /* @__PURE__ */ jsx(PlanMagnetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ApolloProvider, { client: workspaceClient, children }) });
257
+ }
258
+ function usePlanMagnetContext() {
259
+ const context = useContext(PlanMagnetContext);
260
+ if (!context) {
261
+ throw new Error(
262
+ "usePlanMagnetContext must be used within PlanMagnetProvider"
263
+ );
264
+ }
265
+ return context;
266
+ }
267
+ function usePlanMagnetContextSafe() {
268
+ return useContext(PlanMagnetContext);
269
+ }
270
+ var WORK_ITEM_SUMMARY_FIELDS = gql`
271
+ fragment WorkItemSummaryFields on WorkItem {
272
+ id
273
+ key
274
+ title
275
+ type
276
+ status
277
+ priority
278
+ assigneeId
279
+ sprintId
280
+ storyPoints
281
+ dueDate
282
+ labels
283
+ }
284
+ `;
285
+ var WORK_ITEM_FIELDS = gql`
286
+ fragment WorkItemFields on WorkItem {
287
+ id
288
+ workspaceId
289
+ projectId
290
+ key
291
+ title
292
+ description
293
+ type
294
+ status
295
+ priority
296
+ assigneeId
297
+ reporterId
298
+ parentId
299
+ sprintId
300
+ storyPoints
301
+ estimateMinutes
302
+ timeSpentMinutes
303
+ dueDate
304
+ labels
305
+ tags
306
+ sortOrder
307
+ metadata
308
+ createdBy
309
+ createdAt
310
+ updatedAt
311
+ updatedBy
312
+ deletedAt
313
+ }
314
+ `;
315
+ var PROJECT_SUMMARY_FIELDS = gql`
316
+ fragment ProjectSummaryFields on Project {
317
+ id
318
+ name
319
+ key
320
+ status
321
+ methodology
322
+ ownerId
323
+ startDate
324
+ endDate
325
+ tags
326
+ }
327
+ `;
328
+ var LIST_WORK_ITEMS = gql`
329
+ query ListWorkItems(
330
+ $workspaceId: ID!
331
+ $filter: PlanmagnetWorkItemFilter
332
+ $pagination: PlanmagnetPaginationInput
333
+ ) {
334
+ planmagnetWorkItems(
335
+ workspaceId: $workspaceId
336
+ filter: $filter
337
+ pagination: $pagination
338
+ ) {
339
+ items {
340
+ ...WorkItemSummaryFields
341
+ }
342
+ pageInfo {
343
+ hasNextPage
344
+ hasPreviousPage
345
+ startCursor
346
+ endCursor
347
+ totalCount
348
+ }
349
+ totalCount
350
+ }
351
+ }
352
+ ${WORK_ITEM_SUMMARY_FIELDS}
353
+ `;
354
+ var GET_WORK_ITEM = gql`
355
+ query GetWorkItem($id: ID!) {
356
+ planmagnetWorkItem(id: $id) {
357
+ ...WorkItemFields
358
+ }
359
+ }
360
+ ${WORK_ITEM_FIELDS}
361
+ `;
362
+ var GET_PROJECTS = gql`
363
+ query GetProjects(
364
+ $workspaceId: ID!
365
+ $filter: PlanmagnetProjectFilter
366
+ $pagination: PlanmagnetPaginationInput
367
+ ) {
368
+ planmagnetProjects(
369
+ workspaceId: $workspaceId
370
+ filter: $filter
371
+ pagination: $pagination
372
+ ) {
373
+ items {
374
+ ...ProjectSummaryFields
375
+ }
376
+ pageInfo {
377
+ hasNextPage
378
+ hasPreviousPage
379
+ startCursor
380
+ endCursor
381
+ totalCount
382
+ }
383
+ totalCount
384
+ }
385
+ }
386
+ ${PROJECT_SUMMARY_FIELDS}
387
+ `;
388
+ var CREATE_WORK_ITEM = gql`
389
+ mutation CreateWorkItem($input: PlanmagnetCreateWorkItemInput!) {
390
+ planmagnetCreateWorkItem(input: $input) {
391
+ ...WorkItemFields
392
+ }
393
+ }
394
+ ${WORK_ITEM_FIELDS}
395
+ `;
396
+ var UPDATE_WORK_ITEM = gql`
397
+ mutation UpdateWorkItem($id: ID!, $input: PlanmagnetUpdateWorkItemInput!) {
398
+ planmagnetUpdateWorkItem(id: $id, input: $input) {
399
+ ...WorkItemFields
400
+ }
401
+ }
402
+ ${WORK_ITEM_FIELDS}
403
+ `;
404
+ var MOVE_WORK_ITEM = gql`
405
+ mutation MoveWorkItem($id: ID!, $input: PlanmagnetMoveWorkItemInput!) {
406
+ planmagnetMoveWorkItem(id: $id, input: $input) {
407
+ ...WorkItemFields
408
+ }
409
+ }
410
+ ${WORK_ITEM_FIELDS}
411
+ `;
412
+ function cn(...inputs) {
413
+ return twMerge(clsx(inputs));
414
+ }
415
+
416
+ // src/types/index.ts
417
+ var DEFAULT_BOARD_COLUMNS = [
418
+ { status: "BACKLOG", label: "Backlog" },
419
+ { status: "TODO", label: "To Do" },
420
+ { status: "IN_PROGRESS", label: "In Progress" },
421
+ { status: "IN_REVIEW", label: "In Review" },
422
+ { status: "TESTING", label: "Testing" },
423
+ { status: "DONE", label: "Done" }
424
+ ];
425
+ var TASK_PRIORITIES = [
426
+ "NONE",
427
+ "LOW",
428
+ "MEDIUM",
429
+ "HIGH",
430
+ "CRITICAL"
431
+ ];
432
+ var TASK_TYPES = [
433
+ "TASK",
434
+ "STORY",
435
+ "BUG",
436
+ "EPIC",
437
+ "SUB_TASK"
438
+ ];
439
+ var TASK_STATUSES = [
440
+ "BACKLOG",
441
+ "TODO",
442
+ "IN_PROGRESS",
443
+ "IN_REVIEW",
444
+ "TESTING",
445
+ "DONE",
446
+ "CANCELLED"
447
+ ];
448
+ function enumLabel(value) {
449
+ return value.toLowerCase().replace(/_/g, " ");
450
+ }
451
+ var columnAccent = {
452
+ BACKLOG: "border-t-muted-foreground/40",
453
+ TODO: "border-t-primary/50",
454
+ IN_PROGRESS: "border-t-primary",
455
+ IN_REVIEW: "border-t-secondary-foreground/50",
456
+ TESTING: "border-t-accent-foreground/50",
457
+ DONE: "border-t-primary/70",
458
+ CANCELLED: "border-t-destructive/60"
459
+ };
460
+ var priorityTone = {
461
+ NONE: "bg-muted text-muted-foreground",
462
+ LOW: "bg-muted text-muted-foreground",
463
+ MEDIUM: "bg-secondary text-secondary-foreground",
464
+ HIGH: "bg-accent text-accent-foreground",
465
+ CRITICAL: "bg-destructive/15 text-destructive"
466
+ };
467
+ var typeTone = {
468
+ TASK: "bg-secondary text-secondary-foreground",
469
+ STORY: "bg-primary/10 text-primary",
470
+ BUG: "bg-destructive/15 text-destructive",
471
+ EPIC: "bg-accent text-accent-foreground",
472
+ SUB_TASK: "bg-muted text-muted-foreground"
473
+ };
474
+ function TaskBoardCore({
475
+ projectId,
476
+ columns = DEFAULT_BOARD_COLUMNS,
477
+ readonly: _readonly,
478
+ hideHeader,
479
+ hideFilters,
480
+ hiddenFields,
481
+ onTaskClick,
482
+ className,
483
+ workspaceId: workspaceIdProp
484
+ }) {
485
+ const ctx = usePlanMagnetContextSafe();
486
+ const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
487
+ const [priorityFilter, setPriorityFilter] = useState(
488
+ "ALL"
489
+ );
490
+ const [typeFilter, setTypeFilter] = useState("ALL");
491
+ const hidden = useMemo(() => new Set(hiddenFields ?? []), [hiddenFields]);
492
+ const { data, loading, error } = useQuery(
493
+ LIST_WORK_ITEMS,
494
+ {
495
+ variables: {
496
+ workspaceId,
497
+ ...projectId ? { filter: { projectId } } : {},
498
+ pagination: { first: 200 }
499
+ },
500
+ skip: !workspaceId
501
+ }
502
+ );
503
+ if (!workspaceId) {
504
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TaskBoard: no workspaceId provided (prop or PlanMagnetProvider)." });
505
+ }
506
+ if (loading && !data) {
507
+ return /* @__PURE__ */ jsx(
508
+ "div",
509
+ {
510
+ className: cn(
511
+ "flex items-center justify-center p-12",
512
+ className
513
+ ),
514
+ children: /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" })
515
+ }
516
+ );
517
+ }
518
+ if (error && !data) {
519
+ return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
520
+ "Error loading tasks: ",
521
+ error.message
522
+ ] });
523
+ }
524
+ const tasks = data?.planmagnetWorkItems?.items ?? [];
525
+ const filtered = tasks.filter(
526
+ (t) => (priorityFilter === "ALL" || t.priority === priorityFilter) && (typeFilter === "ALL" || t.type === typeFilter)
527
+ );
528
+ const gridCols = columns.length <= 4 ? "md:grid-cols-4" : columns.length === 5 ? "md:grid-cols-5" : "md:grid-cols-6";
529
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 p-6", className), children: [
530
+ !hideHeader && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { children: [
531
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-foreground", children: "Task Board" }),
532
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
533
+ tasks.length,
534
+ " ",
535
+ tasks.length === 1 ? "task" : "tasks"
536
+ ] })
537
+ ] }) }),
538
+ !hideFilters && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-4", children: [
539
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4 text-muted-foreground" }),
540
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
541
+ /* @__PURE__ */ jsx(
542
+ FilterChip,
543
+ {
544
+ active: priorityFilter === "ALL",
545
+ label: "all",
546
+ onClick: () => setPriorityFilter("ALL")
547
+ }
548
+ ),
549
+ TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx(
550
+ FilterChip,
551
+ {
552
+ active: priorityFilter === p,
553
+ label: p.toLowerCase(),
554
+ onClick: () => setPriorityFilter(p)
555
+ },
556
+ p
557
+ ))
558
+ ] }),
559
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
560
+ /* @__PURE__ */ jsx(
561
+ FilterChip,
562
+ {
563
+ active: typeFilter === "ALL",
564
+ label: "all",
565
+ onClick: () => setTypeFilter("ALL")
566
+ }
567
+ ),
568
+ TASK_TYPES.map((t) => /* @__PURE__ */ jsx(
569
+ FilterChip,
570
+ {
571
+ active: typeFilter === t,
572
+ label: t.toLowerCase().replace("_", " "),
573
+ onClick: () => setTypeFilter(t)
574
+ },
575
+ t
576
+ ))
577
+ ] })
578
+ ] }),
579
+ /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-1 gap-3 overflow-x-auto", gridCols), children: columns.map((col) => {
580
+ const colTasks = filtered.filter((t) => t.status === col.status);
581
+ return /* @__PURE__ */ jsxs("div", { className: "min-w-[200px]", children: [
582
+ /* @__PURE__ */ jsx(
583
+ "div",
584
+ {
585
+ className: cn(
586
+ "rounded-t-md border-t-2 bg-muted/50 p-2",
587
+ columnAccent[col.status] ?? "border-t-muted-foreground/40"
588
+ ),
589
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
590
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: col.label }),
591
+ /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 text-xs text-muted-foreground", children: colTasks.length })
592
+ ] })
593
+ }
594
+ ),
595
+ /* @__PURE__ */ jsx("div", { className: "mt-2 space-y-2", children: colTasks.map((task) => /* @__PURE__ */ jsx(
596
+ Card,
597
+ {
598
+ className: cn(
599
+ "shadow-sm",
600
+ onTaskClick && "cursor-pointer hover:border-primary"
601
+ ),
602
+ onClick: onTaskClick ? () => onTaskClick(task) : void 0,
603
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "space-y-2 p-3", children: [
604
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium leading-tight text-foreground", children: task.title }),
605
+ !hidden.has("key") && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: task.key }),
606
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
607
+ !hidden.has("priority") && /* @__PURE__ */ jsx(
608
+ "span",
609
+ {
610
+ className: cn(
611
+ "rounded-full px-1.5 py-0.5 text-[10px] capitalize",
612
+ priorityTone[task.priority]
613
+ ),
614
+ children: task.priority.toLowerCase()
615
+ }
616
+ ),
617
+ !hidden.has("type") && /* @__PURE__ */ jsx(
618
+ "span",
619
+ {
620
+ className: cn(
621
+ "rounded-full px-1.5 py-0.5 text-[10px] capitalize",
622
+ typeTone[task.type]
623
+ ),
624
+ children: task.type.toLowerCase().replace("_", " ")
625
+ }
626
+ )
627
+ ] }),
628
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
629
+ !hidden.has("labels") && /* @__PURE__ */ jsx("div", { className: "flex gap-1", children: (task.labels ?? []).slice(0, 2).map((l) => /* @__PURE__ */ jsx(
630
+ "span",
631
+ {
632
+ className: "rounded bg-muted px-1 py-0.5 text-[9px] text-muted-foreground",
633
+ children: l
634
+ },
635
+ l
636
+ )) }),
637
+ !hidden.has("storyPoints") && /* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-primary/10 text-[10px] font-medium text-primary", children: task.storyPoints ?? 0 })
638
+ ] }),
639
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-[10px] text-muted-foreground", children: [
640
+ !hidden.has("assignee") && /* @__PURE__ */ jsx("span", { children: task.assigneeId ?? "Unassigned" }),
641
+ !hidden.has("dueDate") && /* @__PURE__ */ jsx("span", { children: task.dueDate ?? "" })
642
+ ] })
643
+ ] })
644
+ },
645
+ task.id
646
+ )) })
647
+ ] }, col.status);
648
+ }) })
649
+ ] });
650
+ }
651
+ function FilterChip({
652
+ active,
653
+ label,
654
+ onClick
655
+ }) {
656
+ return /* @__PURE__ */ jsx(
657
+ "button",
658
+ {
659
+ type: "button",
660
+ onClick,
661
+ className: cn(
662
+ "rounded px-2 py-1 text-xs capitalize",
663
+ active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:bg-muted/70"
664
+ ),
665
+ children: label
666
+ }
667
+ );
668
+ }
669
+ function TaskBoard({
670
+ apiGatewayUrl,
671
+ authToken,
672
+ workspaceToken,
673
+ workspaceId,
674
+ tenantId,
675
+ organizationId,
676
+ trustedOrigins,
677
+ onAuthError,
678
+ workspaceClient,
679
+ ...coreProps
680
+ }) {
681
+ return /* @__PURE__ */ jsx(
682
+ PlanMagnetProvider,
683
+ {
684
+ apiGatewayUrl,
685
+ authToken,
686
+ workspaceToken,
687
+ workspaceId,
688
+ tenantId,
689
+ organizationId,
690
+ trustedOrigins,
691
+ onAuthError,
692
+ workspaceClient,
693
+ children: /* @__PURE__ */ jsx(TaskBoardCore, { workspaceId, ...coreProps })
694
+ }
695
+ );
696
+ }
697
+ var DEFAULT_TYPE = "TASK";
698
+ var DEFAULT_STATUS = "BACKLOG";
699
+ var DEFAULT_PRIORITY = "NONE";
700
+ var fieldClass = "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";
701
+ var labelClass = "text-sm font-medium text-foreground";
702
+ function CreateTaskCore({
703
+ projectId: projectIdProp,
704
+ hiddenFields,
705
+ defaultValues,
706
+ hideHeader,
707
+ submitLabel = "Create task",
708
+ onCreated,
709
+ onError: onError2,
710
+ onCancel,
711
+ className,
712
+ workspaceId: workspaceIdProp
713
+ }) {
714
+ const ctx = usePlanMagnetContextSafe();
715
+ const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
716
+ const projectId = projectIdProp ?? defaultValues?.projectId;
717
+ const hidden = useMemo(
718
+ () => new Set(hiddenFields ?? []),
719
+ [hiddenFields]
720
+ );
721
+ const [title, setTitle] = useState(defaultValues?.title ?? "");
722
+ const [description, setDescription] = useState(
723
+ defaultValues?.description ?? ""
724
+ );
725
+ const [type, setType] = useState(
726
+ defaultValues?.type ?? DEFAULT_TYPE
727
+ );
728
+ const [status, setStatus] = useState(
729
+ defaultValues?.status ?? DEFAULT_STATUS
730
+ );
731
+ const [priority, setPriority] = useState(
732
+ defaultValues?.priority ?? DEFAULT_PRIORITY
733
+ );
734
+ const [assigneeId, setAssigneeId] = useState(defaultValues?.assigneeId ?? "");
735
+ const [dueDate, setDueDate] = useState(defaultValues?.dueDate ?? "");
736
+ const [labels, setLabels] = useState(
737
+ (defaultValues?.labels ?? []).join(", ")
738
+ );
739
+ const [storyPoints, setStoryPoints] = useState(
740
+ defaultValues?.storyPoints != null ? String(defaultValues.storyPoints) : ""
741
+ );
742
+ const [createWorkItem, { loading, error }] = useMutation(CREATE_WORK_ITEM);
743
+ const canSubmit = Boolean(workspaceId && projectId && title.trim());
744
+ const handleSubmit = async (e) => {
745
+ e.preventDefault();
746
+ if (!canSubmit || !projectId) return;
747
+ const parsedLabels = labels.split(",").map((l) => l.trim()).filter(Boolean);
748
+ const parsedPoints = storyPoints.trim() ? Number(storyPoints) : void 0;
749
+ const input = {
750
+ projectId,
751
+ title: title.trim(),
752
+ type,
753
+ ...hidden.has("status") ? {} : { status },
754
+ ...hidden.has("priority") ? {} : { priority },
755
+ ...hidden.has("description") || !description.trim() ? {} : { description: description.trim() },
756
+ ...hidden.has("assignee") || !assigneeId.trim() ? {} : { assigneeId: assigneeId.trim() },
757
+ ...hidden.has("dueDate") || !dueDate.trim() ? {} : { dueDate },
758
+ ...hidden.has("labels") || parsedLabels.length === 0 ? {} : { labels: parsedLabels },
759
+ ...hidden.has("storyPoints") || parsedPoints == null || Number.isNaN(parsedPoints) ? {} : { storyPoints: parsedPoints }
760
+ };
761
+ try {
762
+ const result = await createWorkItem({ variables: { input } });
763
+ const created = result.data?.planmagnetCreateWorkItem;
764
+ if (created) {
765
+ const cfg = getPlanMagnetConfig();
766
+ try {
767
+ await cfg.onTaskSaved?.({
768
+ id: created.id,
769
+ key: created.key,
770
+ title: created.title,
771
+ projectId: created.projectId,
772
+ operation: "created"
773
+ });
774
+ } catch {
775
+ }
776
+ onCreated?.(created);
777
+ resetForm();
778
+ }
779
+ } catch (err) {
780
+ onError2?.(err instanceof Error ? err : new Error(String(err)));
781
+ }
782
+ };
783
+ function resetForm() {
784
+ setTitle("");
785
+ setDescription("");
786
+ setType(DEFAULT_TYPE);
787
+ setStatus(DEFAULT_STATUS);
788
+ setPriority(DEFAULT_PRIORITY);
789
+ setAssigneeId("");
790
+ setDueDate("");
791
+ setLabels("");
792
+ setStoryPoints("");
793
+ }
794
+ if (!workspaceId) {
795
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "CreateTask: no workspaceId provided (prop or PlanMagnetProvider)." });
796
+ }
797
+ return /* @__PURE__ */ jsx(Card, { className: cn("shadow-sm", className), children: /* @__PURE__ */ jsx(CardContent, { className: "p-6", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
798
+ !hideHeader && /* @__PURE__ */ jsxs("div", { children: [
799
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground", children: "New task" }),
800
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Create a work item in this workspace." })
801
+ ] }),
802
+ !projectId && /* @__PURE__ */ jsx("p", { className: "rounded-md bg-destructive/10 p-2 text-xs text-destructive", children: "A projectId is required to create a task." }),
803
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
804
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-title", className: labelClass, children: "Title" }),
805
+ /* @__PURE__ */ jsx(
806
+ "input",
807
+ {
808
+ id: "pm-title",
809
+ className: fieldClass,
810
+ value: title,
811
+ onChange: (e) => setTitle(e.target.value),
812
+ placeholder: "What needs doing?",
813
+ required: true
814
+ }
815
+ )
816
+ ] }),
817
+ !hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
818
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-description", className: labelClass, children: "Description" }),
819
+ /* @__PURE__ */ jsx(
820
+ "textarea",
821
+ {
822
+ id: "pm-description",
823
+ className: cn(fieldClass, "min-h-[80px]"),
824
+ value: description,
825
+ onChange: (e) => setDescription(e.target.value),
826
+ placeholder: "Add more detail (optional)"
827
+ }
828
+ )
829
+ ] }),
830
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
831
+ !hidden.has("type") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
832
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-type", className: labelClass, children: "Type" }),
833
+ /* @__PURE__ */ jsx(
834
+ "select",
835
+ {
836
+ id: "pm-type",
837
+ className: cn(fieldClass, "capitalize"),
838
+ value: type,
839
+ onChange: (e) => setType(e.target.value),
840
+ children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: enumLabel(t) }, t))
841
+ }
842
+ )
843
+ ] }),
844
+ !hidden.has("status") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
845
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-status", className: labelClass, children: "Status" }),
846
+ /* @__PURE__ */ jsx(
847
+ "select",
848
+ {
849
+ id: "pm-status",
850
+ className: cn(fieldClass, "capitalize"),
851
+ value: status,
852
+ onChange: (e) => setStatus(e.target.value),
853
+ children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: enumLabel(s) }, s))
854
+ }
855
+ )
856
+ ] }),
857
+ !hidden.has("priority") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
858
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-priority", className: labelClass, children: "Priority" }),
859
+ /* @__PURE__ */ jsx(
860
+ "select",
861
+ {
862
+ id: "pm-priority",
863
+ className: cn(fieldClass, "capitalize"),
864
+ value: priority,
865
+ onChange: (e) => setPriority(e.target.value),
866
+ children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: enumLabel(p) }, p))
867
+ }
868
+ )
869
+ ] }),
870
+ !hidden.has("assignee") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
871
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-assignee", className: labelClass, children: "Assignee" }),
872
+ /* @__PURE__ */ jsx(
873
+ "input",
874
+ {
875
+ id: "pm-assignee",
876
+ className: fieldClass,
877
+ value: assigneeId,
878
+ onChange: (e) => setAssigneeId(e.target.value),
879
+ placeholder: "Actor ID (optional)"
880
+ }
881
+ )
882
+ ] }),
883
+ !hidden.has("dueDate") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
884
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-due", className: labelClass, children: "Due date" }),
885
+ /* @__PURE__ */ jsx(
886
+ "input",
887
+ {
888
+ id: "pm-due",
889
+ type: "date",
890
+ className: fieldClass,
891
+ value: dueDate,
892
+ onChange: (e) => setDueDate(e.target.value)
893
+ }
894
+ )
895
+ ] }),
896
+ !hidden.has("storyPoints") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
897
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-points", className: labelClass, children: "Story points" }),
898
+ /* @__PURE__ */ jsx(
899
+ "input",
900
+ {
901
+ id: "pm-points",
902
+ type: "number",
903
+ min: 0,
904
+ className: fieldClass,
905
+ value: storyPoints,
906
+ onChange: (e) => setStoryPoints(e.target.value),
907
+ placeholder: "0"
908
+ }
909
+ )
910
+ ] })
911
+ ] }),
912
+ !hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
913
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-labels", className: labelClass, children: "Labels" }),
914
+ /* @__PURE__ */ jsx(
915
+ "input",
916
+ {
917
+ id: "pm-labels",
918
+ className: fieldClass,
919
+ value: labels,
920
+ onChange: (e) => setLabels(e.target.value),
921
+ placeholder: "comma, separated, labels"
922
+ }
923
+ )
924
+ ] }),
925
+ error && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
926
+ "Failed to create task: ",
927
+ error.message
928
+ ] }),
929
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
930
+ onCancel && /* @__PURE__ */ jsx(
931
+ "button",
932
+ {
933
+ type: "button",
934
+ onClick: onCancel,
935
+ className: "rounded-md bg-muted px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted/70",
936
+ children: "Cancel"
937
+ }
938
+ ),
939
+ /* @__PURE__ */ jsx(
940
+ "button",
941
+ {
942
+ type: "submit",
943
+ disabled: !canSubmit || loading,
944
+ className: cn(
945
+ "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
946
+ (!canSubmit || loading) && "cursor-not-allowed opacity-50"
947
+ ),
948
+ children: loading ? "Creating\u2026" : submitLabel
949
+ }
950
+ )
951
+ ] })
952
+ ] }) }) });
953
+ }
954
+ function CreateTask({
955
+ apiGatewayUrl,
956
+ authToken,
957
+ workspaceToken,
958
+ workspaceId,
959
+ tenantId,
960
+ organizationId,
961
+ trustedOrigins,
962
+ onAuthError,
963
+ workspaceClient,
964
+ ...coreProps
965
+ }) {
966
+ return /* @__PURE__ */ jsx(
967
+ PlanMagnetProvider,
968
+ {
969
+ apiGatewayUrl,
970
+ authToken,
971
+ workspaceToken,
972
+ workspaceId,
973
+ tenantId,
974
+ organizationId,
975
+ trustedOrigins,
976
+ onAuthError,
977
+ workspaceClient,
978
+ children: /* @__PURE__ */ jsx(CreateTaskCore, { workspaceId, ...coreProps })
979
+ }
980
+ );
981
+ }
982
+ var badgeVariants = cva(
983
+ "inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium capitalize transition-colors",
984
+ {
985
+ variants: {
986
+ variant: {
987
+ default: "bg-primary/10 text-primary",
988
+ muted: "bg-muted text-muted-foreground",
989
+ secondary: "bg-secondary text-secondary-foreground",
990
+ accent: "bg-accent text-accent-foreground",
991
+ destructive: "bg-destructive/15 text-destructive"
992
+ }
993
+ },
994
+ defaultVariants: {
995
+ variant: "default"
996
+ }
997
+ }
998
+ );
999
+ function Badge({ className, variant, ...props }) {
1000
+ return /* @__PURE__ */ jsx("span", { className: cn(badgeVariants({ variant }), className), ...props });
1001
+ }
1002
+ function OverlayShell({
1003
+ open,
1004
+ onClose,
1005
+ children,
1006
+ ariaLabel,
1007
+ className,
1008
+ variant
1009
+ }) {
1010
+ useEffect(() => {
1011
+ if (!open) return;
1012
+ const onKeyDown = (e) => {
1013
+ if (e.key === "Escape") onClose();
1014
+ };
1015
+ document.addEventListener("keydown", onKeyDown);
1016
+ return () => document.removeEventListener("keydown", onKeyDown);
1017
+ }, [open, onClose]);
1018
+ if (!open) return null;
1019
+ const isModal = variant === "modal";
1020
+ return /* @__PURE__ */ jsx(
1021
+ "div",
1022
+ {
1023
+ className: cn(
1024
+ "fixed inset-0 z-50 flex bg-foreground/40",
1025
+ isModal ? "items-center justify-center p-4" : "justify-end"
1026
+ ),
1027
+ onClick: onClose,
1028
+ children: /* @__PURE__ */ jsxs(
1029
+ "div",
1030
+ {
1031
+ role: "dialog",
1032
+ "aria-modal": "true",
1033
+ "aria-label": ariaLabel,
1034
+ className: cn(
1035
+ "relative overflow-y-auto bg-background text-foreground shadow-lg",
1036
+ isModal ? "max-h-[90vh] w-full max-w-2xl rounded-lg" : "h-full w-full max-w-lg",
1037
+ className
1038
+ ),
1039
+ onClick: (e) => e.stopPropagation(),
1040
+ children: [
1041
+ /* @__PURE__ */ jsx(
1042
+ "button",
1043
+ {
1044
+ type: "button",
1045
+ "aria-label": "Close",
1046
+ onClick: onClose,
1047
+ className: "absolute right-3 top-3 z-10 rounded-md bg-muted px-2 py-1 text-sm font-medium text-muted-foreground hover:bg-muted/70",
1048
+ children: "\u2715"
1049
+ }
1050
+ ),
1051
+ children
1052
+ ]
1053
+ }
1054
+ )
1055
+ }
1056
+ );
1057
+ }
1058
+ function Modal(props) {
1059
+ return /* @__PURE__ */ jsx(OverlayShell, { variant: "modal", ...props });
1060
+ }
1061
+ function Drawer(props) {
1062
+ return /* @__PURE__ */ jsx(OverlayShell, { variant: "drawer", ...props });
1063
+ }
1064
+ var DEFAULT_COLUMNS = [
1065
+ "key",
1066
+ "title",
1067
+ "type",
1068
+ "status",
1069
+ "priority",
1070
+ "assignee",
1071
+ "dueDate"
1072
+ ];
1073
+ var priorityRank = {
1074
+ CRITICAL: 0,
1075
+ HIGH: 1,
1076
+ MEDIUM: 2,
1077
+ LOW: 3,
1078
+ NONE: 4
1079
+ };
1080
+ var statusRank = {
1081
+ BACKLOG: 0,
1082
+ TODO: 1,
1083
+ IN_PROGRESS: 2,
1084
+ IN_REVIEW: 3,
1085
+ TESTING: 4,
1086
+ DONE: 5,
1087
+ CANCELLED: 6
1088
+ };
1089
+ var priorityVariant = {
1090
+ NONE: "muted",
1091
+ LOW: "muted",
1092
+ MEDIUM: "secondary",
1093
+ HIGH: "accent",
1094
+ CRITICAL: "destructive"
1095
+ };
1096
+ var COLUMN_LABELS = {
1097
+ key: "Key",
1098
+ title: "Title",
1099
+ type: "Type",
1100
+ status: "Status",
1101
+ priority: "Priority",
1102
+ assignee: "Assignee",
1103
+ dueDate: "Due",
1104
+ storyPoints: "Points",
1105
+ labels: "Labels"
1106
+ };
1107
+ function TaskListCore({
1108
+ projectId,
1109
+ status,
1110
+ type,
1111
+ priority,
1112
+ assigneeId,
1113
+ search,
1114
+ columns = DEFAULT_COLUMNS,
1115
+ sortBy,
1116
+ sortDir = "asc",
1117
+ hideHeader,
1118
+ onSelect,
1119
+ limit = 200,
1120
+ className,
1121
+ workspaceId: workspaceIdProp
1122
+ }) {
1123
+ const ctx = usePlanMagnetContextSafe();
1124
+ const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
1125
+ const filter = useMemo(() => {
1126
+ const f = {};
1127
+ if (projectId) f.projectId = projectId;
1128
+ if (status) f.status = status;
1129
+ if (type) f.type = type;
1130
+ if (priority) f.priority = priority;
1131
+ if (assigneeId) f.assigneeId = assigneeId;
1132
+ if (search) f.search = search;
1133
+ return f;
1134
+ }, [projectId, status, type, priority, assigneeId, search]);
1135
+ const { data, loading, error } = useQuery(
1136
+ LIST_WORK_ITEMS,
1137
+ {
1138
+ variables: {
1139
+ workspaceId,
1140
+ ...Object.keys(filter).length ? { filter } : {},
1141
+ pagination: { first: limit }
1142
+ },
1143
+ skip: !workspaceId
1144
+ }
1145
+ );
1146
+ const rows = useMemo(() => {
1147
+ const items = data?.planmagnetWorkItems?.items ?? [];
1148
+ if (!sortBy) return items;
1149
+ const dir = sortDir === "desc" ? -1 : 1;
1150
+ return [...items].sort((a, b) => dir * compareTasks(a, b, sortBy));
1151
+ }, [data, sortBy, sortDir]);
1152
+ if (!workspaceId) {
1153
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TaskList: no workspaceId provided (prop or PlanMagnetProvider)." });
1154
+ }
1155
+ if (loading && !data) {
1156
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center justify-center p-12", className), children: /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" }) });
1157
+ }
1158
+ if (error && !data) {
1159
+ return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
1160
+ "Error loading tasks: ",
1161
+ error.message
1162
+ ] });
1163
+ }
1164
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4 p-6", className), children: [
1165
+ !hideHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
1166
+ /* @__PURE__ */ jsxs("div", { children: [
1167
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-foreground", children: "Tasks" }),
1168
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
1169
+ rows.length,
1170
+ " ",
1171
+ rows.length === 1 ? "task" : "tasks"
1172
+ ] })
1173
+ ] }),
1174
+ (status || type || priority || search) && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
1175
+ /* @__PURE__ */ jsx(Filter, { className: "h-3.5 w-3.5" }),
1176
+ " filtered"
1177
+ ] })
1178
+ ] }),
1179
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-sm", children: [
1180
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "border-b border-border bg-muted/50 text-left", children: columns.map((col) => /* @__PURE__ */ jsx(
1181
+ "th",
1182
+ {
1183
+ className: "px-3 py-2 font-medium text-muted-foreground",
1184
+ children: COLUMN_LABELS[col]
1185
+ },
1186
+ col
1187
+ )) }) }),
1188
+ /* @__PURE__ */ jsxs("tbody", { children: [
1189
+ rows.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
1190
+ "td",
1191
+ {
1192
+ colSpan: columns.length,
1193
+ className: "px-3 py-6 text-center text-muted-foreground",
1194
+ children: "No tasks found."
1195
+ }
1196
+ ) }),
1197
+ rows.map((task) => /* @__PURE__ */ jsx(
1198
+ "tr",
1199
+ {
1200
+ onClick: onSelect ? () => onSelect(task.id) : void 0,
1201
+ className: cn(
1202
+ "border-b border-border last:border-0",
1203
+ onSelect && "cursor-pointer hover:bg-muted/40"
1204
+ ),
1205
+ children: columns.map((col) => /* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-foreground", children: renderCell(col, task) }, col))
1206
+ },
1207
+ task.id
1208
+ ))
1209
+ ] })
1210
+ ] }) })
1211
+ ] });
1212
+ }
1213
+ function renderCell(col, task) {
1214
+ switch (col) {
1215
+ case "key":
1216
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: task.key });
1217
+ case "title":
1218
+ return /* @__PURE__ */ jsx("span", { className: "font-medium", children: task.title });
1219
+ case "type":
1220
+ return /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: enumLabel(task.type) });
1221
+ case "status":
1222
+ return /* @__PURE__ */ jsx("span", { className: "capitalize text-muted-foreground", children: enumLabel(task.status) });
1223
+ case "priority":
1224
+ return /* @__PURE__ */ jsx(Badge, { variant: priorityVariant[task.priority], children: enumLabel(task.priority) });
1225
+ case "assignee":
1226
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: task.assigneeId ?? "Unassigned" });
1227
+ case "dueDate":
1228
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: task.dueDate ?? "\u2014" });
1229
+ case "storyPoints":
1230
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: task.storyPoints ?? 0 });
1231
+ case "labels":
1232
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: (task.labels ?? []).slice(0, 3).map((l) => /* @__PURE__ */ jsx(
1233
+ "span",
1234
+ {
1235
+ className: "rounded bg-muted px-1 py-0.5 text-[10px] text-muted-foreground",
1236
+ children: l
1237
+ },
1238
+ l
1239
+ )) });
1240
+ default:
1241
+ return null;
1242
+ }
1243
+ }
1244
+ function compareTasks(a, b, sortBy) {
1245
+ switch (sortBy) {
1246
+ case "priority":
1247
+ return priorityRank[a.priority] - priorityRank[b.priority];
1248
+ case "status":
1249
+ return statusRank[a.status] - statusRank[b.status];
1250
+ case "title":
1251
+ return a.title.localeCompare(b.title);
1252
+ case "type":
1253
+ return a.type.localeCompare(b.type);
1254
+ case "dueDate":
1255
+ return (a.dueDate ?? "").localeCompare(b.dueDate ?? "");
1256
+ case "storyPoints":
1257
+ return (a.storyPoints ?? 0) - (b.storyPoints ?? 0);
1258
+ default:
1259
+ return 0;
1260
+ }
1261
+ }
1262
+ function TaskList({
1263
+ apiGatewayUrl,
1264
+ authToken,
1265
+ workspaceToken,
1266
+ workspaceId,
1267
+ tenantId,
1268
+ organizationId,
1269
+ trustedOrigins,
1270
+ onAuthError,
1271
+ workspaceClient,
1272
+ ...coreProps
1273
+ }) {
1274
+ return /* @__PURE__ */ jsx(
1275
+ PlanMagnetProvider,
1276
+ {
1277
+ apiGatewayUrl,
1278
+ authToken,
1279
+ workspaceToken,
1280
+ workspaceId,
1281
+ tenantId,
1282
+ organizationId,
1283
+ trustedOrigins,
1284
+ onAuthError,
1285
+ workspaceClient,
1286
+ children: /* @__PURE__ */ jsx(TaskListCore, { workspaceId, ...coreProps })
1287
+ }
1288
+ );
1289
+ }
1290
+ 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";
1291
+ var labelClass2 = "text-xs font-medium uppercase tracking-wide text-muted-foreground";
1292
+ var priorityVariant2 = {
1293
+ NONE: "muted",
1294
+ LOW: "muted",
1295
+ MEDIUM: "secondary",
1296
+ HIGH: "accent",
1297
+ CRITICAL: "destructive"
1298
+ };
1299
+ function TaskDetailCore({
1300
+ id,
1301
+ readonly,
1302
+ hiddenFields,
1303
+ hideHeader,
1304
+ onUpdated,
1305
+ onError: onError2,
1306
+ className
1307
+ }) {
1308
+ const hidden = useMemo(
1309
+ () => new Set(hiddenFields ?? []),
1310
+ [hiddenFields]
1311
+ );
1312
+ const { data, loading, error } = useQuery(GET_WORK_ITEM, {
1313
+ variables: { id },
1314
+ skip: !id
1315
+ });
1316
+ const item = data?.planmagnetWorkItem ?? null;
1317
+ const [editing, setEditing] = useState(false);
1318
+ const [title, setTitle] = useState("");
1319
+ const [description, setDescription] = useState("");
1320
+ const [type, setType] = useState("TASK");
1321
+ const [status, setStatus] = useState("BACKLOG");
1322
+ const [priority, setPriority] = useState("NONE");
1323
+ const [assigneeId, setAssigneeId] = useState("");
1324
+ const [dueDate, setDueDate] = useState("");
1325
+ const [labels, setLabels] = useState("");
1326
+ const [storyPoints, setStoryPoints] = useState("");
1327
+ useEffect(() => {
1328
+ if (!item) return;
1329
+ setTitle(item.title);
1330
+ setDescription(item.description ?? "");
1331
+ setType(item.type);
1332
+ setStatus(item.status);
1333
+ setPriority(item.priority);
1334
+ setAssigneeId(item.assigneeId ?? "");
1335
+ setDueDate(item.dueDate ? String(item.dueDate).slice(0, 10) : "");
1336
+ setLabels((item.labels ?? []).join(", "));
1337
+ setStoryPoints(item.storyPoints != null ? String(item.storyPoints) : "");
1338
+ }, [item]);
1339
+ const [updateWorkItem, { loading: saving, error: saveError }] = useMutation(UPDATE_WORK_ITEM);
1340
+ const handleSave = async (e) => {
1341
+ e.preventDefault();
1342
+ if (!item) return;
1343
+ const parsedLabels = labels.split(",").map((l) => l.trim()).filter(Boolean);
1344
+ const parsedPoints = storyPoints.trim() ? Number(storyPoints) : void 0;
1345
+ const input = {
1346
+ title: title.trim(),
1347
+ ...hidden.has("description") ? {} : { description: description.trim() },
1348
+ ...hidden.has("type") ? {} : { type },
1349
+ ...hidden.has("status") ? {} : { status },
1350
+ ...hidden.has("priority") ? {} : { priority },
1351
+ ...hidden.has("assignee") ? {} : { assigneeId: assigneeId.trim() },
1352
+ ...hidden.has("dueDate") ? {} : { dueDate: dueDate || void 0 },
1353
+ ...hidden.has("labels") ? {} : { labels: parsedLabels },
1354
+ ...hidden.has("storyPoints") || parsedPoints == null || Number.isNaN(parsedPoints) ? {} : { storyPoints: parsedPoints }
1355
+ };
1356
+ try {
1357
+ const result = await updateWorkItem({
1358
+ variables: { id: item.id, input }
1359
+ });
1360
+ const updated = result.data?.planmagnetUpdateWorkItem;
1361
+ if (updated) {
1362
+ const cfg = getPlanMagnetConfig();
1363
+ try {
1364
+ await cfg.onTaskSaved?.({
1365
+ id: updated.id,
1366
+ key: updated.key,
1367
+ title: updated.title,
1368
+ projectId: updated.projectId,
1369
+ operation: "updated"
1370
+ });
1371
+ } catch {
1372
+ }
1373
+ onUpdated?.(updated);
1374
+ setEditing(false);
1375
+ }
1376
+ } catch (err) {
1377
+ onError2?.(err instanceof Error ? err : new Error(String(err)));
1378
+ }
1379
+ };
1380
+ if (!id) {
1381
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TaskDetail: no work-item id provided." });
1382
+ }
1383
+ if (loading && !data) {
1384
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center justify-center p-12", className), children: /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" }) });
1385
+ }
1386
+ if (error && !data) {
1387
+ return /* @__PURE__ */ jsxs("div", { className: cn("p-6 text-sm text-destructive", className), children: [
1388
+ "Error loading task: ",
1389
+ error.message
1390
+ ] });
1391
+ }
1392
+ if (!item) {
1393
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-muted-foreground", className), children: "Task not found." });
1394
+ }
1395
+ const canEdit = !readonly;
1396
+ return /* @__PURE__ */ jsx(Card, { className: cn("shadow-sm", className), children: /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4 p-6", children: [
1397
+ !hideHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
1398
+ /* @__PURE__ */ jsxs("div", { children: [
1399
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: item.key }),
1400
+ /* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-foreground", children: item.title })
1401
+ ] }),
1402
+ canEdit && !editing && /* @__PURE__ */ jsx(
1403
+ "button",
1404
+ {
1405
+ type: "button",
1406
+ onClick: () => setEditing(true),
1407
+ className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground",
1408
+ children: "Edit"
1409
+ }
1410
+ )
1411
+ ] }),
1412
+ !editing ? /* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1413
+ !hidden.has("type") && /* @__PURE__ */ jsx(Field, { label: "Type", children: /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: enumLabel(item.type) }) }),
1414
+ !hidden.has("status") && /* @__PURE__ */ jsx(Field, { label: "Status", children: /* @__PURE__ */ jsx("span", { className: "capitalize text-foreground", children: enumLabel(item.status) }) }),
1415
+ !hidden.has("priority") && /* @__PURE__ */ jsx(Field, { label: "Priority", children: /* @__PURE__ */ jsx(Badge, { variant: priorityVariant2[item.priority], children: enumLabel(item.priority) }) }),
1416
+ !hidden.has("assignee") && /* @__PURE__ */ jsx(Field, { label: "Assignee", children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.assigneeId ?? "Unassigned" }) }),
1417
+ !hidden.has("dueDate") && /* @__PURE__ */ jsx(Field, { label: "Due date", children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.dueDate ?? "\u2014" }) }),
1418
+ !hidden.has("storyPoints") && /* @__PURE__ */ jsx(Field, { label: "Story points", children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: item.storyPoints ?? 0 }) }),
1419
+ !hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
1420
+ /* @__PURE__ */ jsx("dt", { className: labelClass2, children: "Description" }),
1421
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 whitespace-pre-wrap text-sm text-foreground", children: item.description || "\u2014" })
1422
+ ] }),
1423
+ !hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "sm:col-span-2", children: [
1424
+ /* @__PURE__ */ jsx("dt", { className: labelClass2, children: "Labels" }),
1425
+ /* @__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(
1426
+ "span",
1427
+ {
1428
+ className: "rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground",
1429
+ children: l
1430
+ },
1431
+ l
1432
+ )) })
1433
+ ] })
1434
+ ] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSave, className: "space-y-4", children: [
1435
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1436
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-title", className: labelClass2, children: "Title" }),
1437
+ /* @__PURE__ */ jsx(
1438
+ "input",
1439
+ {
1440
+ id: "pm-detail-title",
1441
+ className: fieldClass2,
1442
+ value: title,
1443
+ onChange: (e) => setTitle(e.target.value),
1444
+ required: true
1445
+ }
1446
+ )
1447
+ ] }),
1448
+ !hidden.has("description") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1449
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-desc", className: labelClass2, children: "Description" }),
1450
+ /* @__PURE__ */ jsx(
1451
+ "textarea",
1452
+ {
1453
+ id: "pm-detail-desc",
1454
+ className: cn(fieldClass2, "min-h-[80px]"),
1455
+ value: description,
1456
+ onChange: (e) => setDescription(e.target.value)
1457
+ }
1458
+ )
1459
+ ] }),
1460
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1461
+ !hidden.has("type") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1462
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-type", className: labelClass2, children: "Type" }),
1463
+ /* @__PURE__ */ jsx(
1464
+ "select",
1465
+ {
1466
+ id: "pm-detail-type",
1467
+ className: cn(fieldClass2, "capitalize"),
1468
+ value: type,
1469
+ onChange: (e) => setType(e.target.value),
1470
+ children: TASK_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: enumLabel(t) }, t))
1471
+ }
1472
+ )
1473
+ ] }),
1474
+ !hidden.has("status") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1475
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-status", className: labelClass2, children: "Status" }),
1476
+ /* @__PURE__ */ jsx(
1477
+ "select",
1478
+ {
1479
+ id: "pm-detail-status",
1480
+ className: cn(fieldClass2, "capitalize"),
1481
+ value: status,
1482
+ onChange: (e) => setStatus(e.target.value),
1483
+ children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: enumLabel(s) }, s))
1484
+ }
1485
+ )
1486
+ ] }),
1487
+ !hidden.has("priority") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1488
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-priority", className: labelClass2, children: "Priority" }),
1489
+ /* @__PURE__ */ jsx(
1490
+ "select",
1491
+ {
1492
+ id: "pm-detail-priority",
1493
+ className: cn(fieldClass2, "capitalize"),
1494
+ value: priority,
1495
+ onChange: (e) => setPriority(e.target.value),
1496
+ children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: enumLabel(p) }, p))
1497
+ }
1498
+ )
1499
+ ] }),
1500
+ !hidden.has("assignee") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1501
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-assignee", className: labelClass2, children: "Assignee" }),
1502
+ /* @__PURE__ */ jsx(
1503
+ "input",
1504
+ {
1505
+ id: "pm-detail-assignee",
1506
+ className: fieldClass2,
1507
+ value: assigneeId,
1508
+ onChange: (e) => setAssigneeId(e.target.value),
1509
+ placeholder: "Actor ID"
1510
+ }
1511
+ )
1512
+ ] }),
1513
+ !hidden.has("dueDate") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1514
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-due", className: labelClass2, children: "Due date" }),
1515
+ /* @__PURE__ */ jsx(
1516
+ "input",
1517
+ {
1518
+ id: "pm-detail-due",
1519
+ type: "date",
1520
+ className: fieldClass2,
1521
+ value: dueDate,
1522
+ onChange: (e) => setDueDate(e.target.value)
1523
+ }
1524
+ )
1525
+ ] }),
1526
+ !hidden.has("storyPoints") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1527
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-points", className: labelClass2, children: "Story points" }),
1528
+ /* @__PURE__ */ jsx(
1529
+ "input",
1530
+ {
1531
+ id: "pm-detail-points",
1532
+ type: "number",
1533
+ min: 0,
1534
+ className: fieldClass2,
1535
+ value: storyPoints,
1536
+ onChange: (e) => setStoryPoints(e.target.value)
1537
+ }
1538
+ )
1539
+ ] })
1540
+ ] }),
1541
+ !hidden.has("labels") && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1542
+ /* @__PURE__ */ jsx("label", { htmlFor: "pm-detail-labels", className: labelClass2, children: "Labels" }),
1543
+ /* @__PURE__ */ jsx(
1544
+ "input",
1545
+ {
1546
+ id: "pm-detail-labels",
1547
+ className: fieldClass2,
1548
+ value: labels,
1549
+ onChange: (e) => setLabels(e.target.value),
1550
+ placeholder: "comma, separated, labels"
1551
+ }
1552
+ )
1553
+ ] }),
1554
+ saveError && /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
1555
+ "Failed to save: ",
1556
+ saveError.message
1557
+ ] }),
1558
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
1559
+ /* @__PURE__ */ jsx(
1560
+ "button",
1561
+ {
1562
+ type: "button",
1563
+ onClick: () => setEditing(false),
1564
+ className: "rounded-md bg-muted px-4 py-2 text-sm font-medium text-muted-foreground hover:bg-muted/70",
1565
+ children: "Cancel"
1566
+ }
1567
+ ),
1568
+ /* @__PURE__ */ jsx(
1569
+ "button",
1570
+ {
1571
+ type: "submit",
1572
+ disabled: saving || !title.trim(),
1573
+ className: cn(
1574
+ "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground",
1575
+ (saving || !title.trim()) && "cursor-not-allowed opacity-50"
1576
+ ),
1577
+ children: saving ? "Saving\u2026" : "Save changes"
1578
+ }
1579
+ )
1580
+ ] })
1581
+ ] })
1582
+ ] }) });
1583
+ }
1584
+ function Field({ label, children }) {
1585
+ return /* @__PURE__ */ jsxs("div", { children: [
1586
+ /* @__PURE__ */ jsx("dt", { className: labelClass2, children: label }),
1587
+ /* @__PURE__ */ jsx("dd", { className: "mt-1 text-sm", children })
1588
+ ] });
1589
+ }
1590
+ function TaskDetail({
1591
+ apiGatewayUrl,
1592
+ authToken,
1593
+ workspaceToken,
1594
+ workspaceId,
1595
+ tenantId,
1596
+ organizationId,
1597
+ trustedOrigins,
1598
+ onAuthError,
1599
+ workspaceClient,
1600
+ ...coreProps
1601
+ }) {
1602
+ return /* @__PURE__ */ jsx(
1603
+ PlanMagnetProvider,
1604
+ {
1605
+ apiGatewayUrl,
1606
+ authToken,
1607
+ workspaceToken,
1608
+ workspaceId,
1609
+ tenantId,
1610
+ organizationId,
1611
+ trustedOrigins,
1612
+ onAuthError,
1613
+ workspaceClient,
1614
+ children: /* @__PURE__ */ jsx(TaskDetailCore, { ...coreProps })
1615
+ }
1616
+ );
1617
+ }
1618
+ function TasksPageCore({
1619
+ workspaceId: workspaceIdProp,
1620
+ projectId,
1621
+ boardProjectId,
1622
+ columns,
1623
+ readonly,
1624
+ hiddenFields,
1625
+ hideFilters,
1626
+ header,
1627
+ onTaskSaved,
1628
+ createSurface = "modal",
1629
+ detailSurface = "drawer",
1630
+ className
1631
+ }) {
1632
+ const ctx = usePlanMagnetContextSafe();
1633
+ const workspaceId = workspaceIdProp ?? ctx?.workspaceId;
1634
+ const client = useApolloClient();
1635
+ const [creating, setCreating] = useState(false);
1636
+ const [selectedId, setSelectedId] = useState(null);
1637
+ const refetchBoard = useCallback(() => {
1638
+ void client.refetchQueries({ include: [LIST_WORK_ITEMS] }).catch(() => {
1639
+ });
1640
+ }, [client]);
1641
+ const handleCreated = useCallback(
1642
+ (workItem) => {
1643
+ refetchBoard();
1644
+ setCreating(false);
1645
+ onTaskSaved?.({ workItem, operation: "created" });
1646
+ },
1647
+ [refetchBoard, onTaskSaved]
1648
+ );
1649
+ const handleUpdated = useCallback(
1650
+ (workItem) => {
1651
+ refetchBoard();
1652
+ onTaskSaved?.({ workItem, operation: "updated" });
1653
+ },
1654
+ [refetchBoard, onTaskSaved]
1655
+ );
1656
+ const handleTaskClick = useCallback((task) => {
1657
+ setSelectedId(task.id);
1658
+ }, []);
1659
+ if (!workspaceId) {
1660
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 text-sm text-destructive", className), children: "TasksPage: no workspaceId provided (prop or PlanMagnetProvider)." });
1661
+ }
1662
+ const canCreate = !readonly && Boolean(projectId);
1663
+ const showInlineCreate = creating && createSurface === "inline";
1664
+ const showInlineDetail = selectedId != null && detailSurface === "inline";
1665
+ const createForm = /* @__PURE__ */ jsx(
1666
+ CreateTaskCore,
1667
+ {
1668
+ workspaceId,
1669
+ projectId,
1670
+ hiddenFields,
1671
+ onCreated: handleCreated,
1672
+ onCancel: () => setCreating(false)
1673
+ }
1674
+ );
1675
+ const detailView = selectedId != null ? /* @__PURE__ */ jsx(
1676
+ TaskDetailCore,
1677
+ {
1678
+ id: selectedId,
1679
+ readonly,
1680
+ hiddenFields,
1681
+ onUpdated: handleUpdated
1682
+ }
1683
+ ) : null;
1684
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
1685
+ (header || canCreate) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 px-6 pt-6", children: [
1686
+ /* @__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 }),
1687
+ canCreate && /* @__PURE__ */ jsx(
1688
+ "button",
1689
+ {
1690
+ type: "button",
1691
+ onClick: () => setCreating(true),
1692
+ className: "shrink-0 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90",
1693
+ children: "New task"
1694
+ }
1695
+ )
1696
+ ] }),
1697
+ showInlineCreate && /* @__PURE__ */ jsx("div", { className: "px-6", children: createForm }),
1698
+ /* @__PURE__ */ jsx(
1699
+ TaskBoardCore,
1700
+ {
1701
+ workspaceId,
1702
+ projectId: boardProjectId,
1703
+ columns,
1704
+ readonly,
1705
+ hideHeader: Boolean(header),
1706
+ hideFilters,
1707
+ hiddenFields,
1708
+ onTaskClick: handleTaskClick
1709
+ }
1710
+ ),
1711
+ showInlineDetail && /* @__PURE__ */ jsx("div", { className: "px-6 pb-6", children: detailView }),
1712
+ createSurface === "modal" && /* @__PURE__ */ jsx(
1713
+ Modal,
1714
+ {
1715
+ open: creating,
1716
+ onClose: () => setCreating(false),
1717
+ ariaLabel: "Create task",
1718
+ className: "max-w-xl",
1719
+ children: /* @__PURE__ */ jsx("div", { className: "p-2 pt-8", children: createForm })
1720
+ }
1721
+ ),
1722
+ detailSurface === "drawer" && /* @__PURE__ */ jsx(
1723
+ Drawer,
1724
+ {
1725
+ open: selectedId != null,
1726
+ onClose: () => setSelectedId(null),
1727
+ ariaLabel: "Task detail",
1728
+ children: /* @__PURE__ */ jsx("div", { className: "p-2 pt-8", children: detailView })
1729
+ }
1730
+ )
1731
+ ] });
1732
+ }
1733
+ function TasksPage({
1734
+ apiGatewayUrl,
1735
+ authToken,
1736
+ workspaceToken,
1737
+ workspaceId,
1738
+ tenantId,
1739
+ organizationId,
1740
+ trustedOrigins,
1741
+ onAuthError,
1742
+ workspaceClient,
1743
+ ...coreProps
1744
+ }) {
1745
+ return /* @__PURE__ */ jsx(
1746
+ PlanMagnetProvider,
1747
+ {
1748
+ apiGatewayUrl,
1749
+ authToken,
1750
+ workspaceToken,
1751
+ workspaceId,
1752
+ tenantId,
1753
+ organizationId,
1754
+ trustedOrigins,
1755
+ onAuthError,
1756
+ workspaceClient,
1757
+ children: /* @__PURE__ */ jsx(TasksPageCore, { workspaceId, ...coreProps })
1758
+ }
1759
+ );
1760
+ }
1761
+
1762
+ export { Badge, CREATE_WORK_ITEM, CreateTask, CreateTaskCore, DEFAULT_BOARD_COLUMNS, Drawer, GET_PROJECTS, GET_WORK_ITEM, LIST_WORK_ITEMS, MOVE_WORK_ITEM, Modal, PROJECT_SUMMARY_FIELDS, PlanMagnetProvider, TASK_PRIORITIES, TASK_STATUSES, TASK_TYPES, TaskBoard, TaskBoardCore, TaskDetail, TaskDetailCore, TaskList, TaskListCore, TasksPage, TasksPageCore, UPDATE_WORK_ITEM, WORK_ITEM_FIELDS, WORK_ITEM_SUMMARY_FIELDS, badgeVariants, cn, config, createPlanMagnetClient, enumLabel, getGraphQLEndpoint, getPlanMagnetClient, getPlanMagnetClientSafe, getPlanMagnetConfig, isPlanMagnetClientReady, resetPlanMagnetClient, resetPlanMagnetConfig, setPlanMagnetClient, setPlanMagnetConfig, usePlanMagnetContext, usePlanMagnetContextSafe, validateTrustedOrigin, waitForPlanMagnetClient };
1763
+ //# sourceMappingURL=index.js.map
1764
+ //# sourceMappingURL=index.js.map