@thxgg/steward 0.1.12 → 0.1.14

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.
Files changed (89) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/-k8zG74W.js +61 -0
  3. package/.output/public/_nuxt/B-5VWizU.js +1 -0
  4. package/.output/public/_nuxt/{Bq6edYSd.js → BDqHART1.js} +1 -1
  5. package/.output/public/_nuxt/BMAq0QVD.js +42 -0
  6. package/.output/public/_nuxt/BPeTf9dd.js +1 -0
  7. package/.output/public/_nuxt/{dOaEkD-3.js → BubpH_wW.js} +1 -1
  8. package/.output/public/_nuxt/C2HGkiSP.js +1 -0
  9. package/.output/public/_nuxt/CMu9GKTH.js +4 -0
  10. package/.output/public/_nuxt/{BZ1iIOYp.js → CVvrkZkq.js} +1 -1
  11. package/.output/public/_nuxt/C_NevjZD.js +3 -0
  12. package/.output/public/_nuxt/Detail.CzXXlavD.css +1 -0
  13. package/.output/public/_nuxt/_prd_.KTotLoF_.css +1 -0
  14. package/.output/public/_nuxt/builds/latest.json +1 -1
  15. package/.output/public/_nuxt/builds/meta/b57a8fc3-6a38-4f58-b2ae-54768412ea40.json +1 -0
  16. package/.output/public/_nuxt/entry.LcDOtJnR.css +1 -0
  17. package/.output/public/_nuxt/{BFv4l3hn.js → nYTZJhvT.js} +1 -1
  18. package/.output/public/_nuxt/{kTT8NKtq.js → qKRNa41x.js} +1 -1
  19. package/.output/public/_nuxt/qt5OEWHC.js +1 -0
  20. package/.output/public/_nuxt/{C897Egk9.js → uTyw4SRK.js} +1 -1
  21. package/.output/public/_nuxt/{DoNqd8jQ.js → wbj-mIhK.js} +1 -1
  22. package/.output/server/chunks/_/git.mjs.map +1 -1
  23. package/.output/server/chunks/_/task-graph.mjs +196 -0
  24. package/.output/server/chunks/_/task-graph.mjs.map +1 -0
  25. package/.output/server/chunks/build/{_prd_-CkKfJB6U.mjs → Detail-DC-KJQ1f.mjs} +911 -1688
  26. package/.output/server/chunks/build/Detail-DC-KJQ1f.mjs.map +1 -0
  27. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-D0sb4vsK.mjs +4 -0
  28. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-D0sb4vsK.mjs.map +1 -0
  29. package/.output/server/chunks/build/DiffViewer-styles.CkSjCQ0r.mjs +10 -0
  30. package/.output/server/chunks/build/DiffViewer-styles.CkSjCQ0r.mjs.map +1 -0
  31. package/.output/server/chunks/build/DiffViewer-styles.FJJuYjYB.mjs +8 -0
  32. package/.output/server/chunks/build/DiffViewer-styles.FJJuYjYB.mjs.map +1 -0
  33. package/.output/server/chunks/build/_prd_-C1C4GAhW.mjs +1596 -0
  34. package/.output/server/chunks/build/_prd_-C1C4GAhW.mjs.map +1 -0
  35. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  36. package/.output/server/chunks/build/{default-B5nw9_Xg.mjs → default-DWCOHHTE.mjs} +32 -20
  37. package/.output/server/chunks/build/default-DWCOHHTE.mjs.map +1 -0
  38. package/.output/server/chunks/build/{index-CTpuP9Mj.mjs → index-CckL_NBD.mjs} +2 -2
  39. package/.output/server/chunks/build/index-CckL_NBD.mjs.map +1 -0
  40. package/.output/server/chunks/build/{index-D21S97KB.mjs → index-QVeSHT3L.mjs} +3 -3
  41. package/.output/server/chunks/build/index-QVeSHT3L.mjs.map +1 -0
  42. package/.output/server/chunks/build/repo-graph-CTEkxiYd.mjs +205 -0
  43. package/.output/server/chunks/build/repo-graph-CTEkxiYd.mjs.map +1 -0
  44. package/.output/server/chunks/build/server.mjs +12 -3
  45. package/.output/server/chunks/build/styles.mjs +4 -4
  46. package/.output/server/chunks/build/{usePrd-YhvN6Ary.mjs → usePrd-SqcxGyFU.mjs} +20 -2
  47. package/.output/server/chunks/build/usePrd-SqcxGyFU.mjs.map +1 -0
  48. package/.output/server/chunks/nitro/nitro.mjs +669 -637
  49. package/.output/server/chunks/routes/api/repos/_repoId/graph.get.mjs +41 -0
  50. package/.output/server/chunks/routes/api/repos/_repoId/graph.get.mjs.map +1 -0
  51. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/graph.get.mjs +42 -0
  52. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/graph.get.mjs.map +1 -0
  53. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/progress.get.mjs +1 -1
  54. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks/_taskId/commits.get.mjs +1 -1
  55. package/.output/server/chunks/routes/api/repos/_repoId/prd/_prdSlug/tasks.get.mjs +1 -1
  56. package/.output/server/chunks/routes/api/repos/_repoId/prds.get.mjs +1 -1
  57. package/.output/server/node_modules/@vue-flow/background/dist/vue-flow-background.mjs +126 -0
  58. package/.output/server/node_modules/@vue-flow/background/package.json +73 -0
  59. package/.output/server/node_modules/@vue-flow/controls/dist/vue-flow-controls.mjs +207 -0
  60. package/.output/server/node_modules/@vue-flow/controls/package.json +77 -0
  61. package/.output/server/node_modules/@vue-flow/core/dist/vue-flow-core.mjs +10186 -0
  62. package/.output/server/node_modules/@vue-flow/core/package.json +95 -0
  63. package/.output/server/package.json +4 -1
  64. package/dist/app/types/graph.js +1 -0
  65. package/dist/host/src/api/git.js +71 -1
  66. package/dist/host/src/help.js +12 -0
  67. package/dist/server/utils/git.js +104 -1
  68. package/dist/server/utils/task-graph.js +190 -0
  69. package/docs/MCP.md +21 -0
  70. package/package.json +5 -1
  71. package/.output/public/_nuxt/BuQdImno.js +0 -1
  72. package/.output/public/_nuxt/CMUOpExW.js +0 -3
  73. package/.output/public/_nuxt/DE885CbX.js +0 -1
  74. package/.output/public/_nuxt/DomrzX-T.js +0 -76
  75. package/.output/public/_nuxt/R2cvz8mH.js +0 -4
  76. package/.output/public/_nuxt/_prd_.DYvuV73Q.css +0 -1
  77. package/.output/public/_nuxt/builds/meta/6f66fabf-cc26-482b-8adf-f8731dd68f83.json +0 -1
  78. package/.output/public/_nuxt/entry.Dk19PK4d.css +0 -1
  79. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-ZdBUa15f.mjs +0 -4
  80. package/.output/server/chunks/build/DiffViewer-styles-1.mjs-ZdBUa15f.mjs.map +0 -1
  81. package/.output/server/chunks/build/DiffViewer-styles.CoMVrk_N.mjs +0 -8
  82. package/.output/server/chunks/build/DiffViewer-styles.CoMVrk_N.mjs.map +0 -1
  83. package/.output/server/chunks/build/DiffViewer-styles.cLfMOdMh.mjs +0 -10
  84. package/.output/server/chunks/build/DiffViewer-styles.cLfMOdMh.mjs.map +0 -1
  85. package/.output/server/chunks/build/_prd_-CkKfJB6U.mjs.map +0 -1
  86. package/.output/server/chunks/build/default-B5nw9_Xg.mjs.map +0 -1
  87. package/.output/server/chunks/build/index-CTpuP9Mj.mjs.map +0 -1
  88. package/.output/server/chunks/build/index-D21S97KB.mjs.map +0 -1
  89. package/.output/server/chunks/build/usePrd-YhvN6Ary.mjs.map +0 -1
@@ -0,0 +1,1596 @@
1
+ import { _ as __nuxt_component_0$2 } from './nuxt-link-SvT1nf8Z.mjs';
2
+ import { defineComponent, computed, ref, watch, inject, mergeProps, unref, withCtx, createVNode, createTextVNode, isRef, openBlock, createBlock, toDisplayString, createCommentVNode, renderSlot, resolveDynamicComponent, useSSRContext } from 'vue';
3
+ import { ssrRenderAttrs, ssrRenderComponent, ssrInterpolate, ssrRenderAttr, ssrRenderSlot, ssrRenderList, ssrRenderClass, ssrRenderVNode } from 'vue/server-renderer';
4
+ import { Loader2, AlertCircle, RefreshCw, FileText, LayoutGrid, GitBranch, User, Calendar, CircleDot, ExternalLink, Circle, CheckCircle2, PlayCircle, Minus, ArrowDown, ArrowUp } from 'lucide-vue-next';
5
+ import { _ as __nuxt_component_0$2$1, a as __nuxt_component_1$1, B as Badge } from './Detail-DC-KJQ1f.mjs';
6
+ import { marked } from 'marked';
7
+ import { codeToHtml } from 'shiki';
8
+ import DOMPurify from 'dompurify';
9
+ import { u as useRepos, a as usePrd, b as useToast, c as cn } from './usePrd-SqcxGyFU.mjs';
10
+ import { _ as _export_sfc } from './_plugin-vue_export-helper-1tPrXgE0.mjs';
11
+ import { reactiveOmit } from '@vueuse/core';
12
+ import { useForwardPropsEmits, TabsRoot, TabsList as TabsList$1, useForwardProps, TabsTrigger as TabsTrigger$1, TabsContent as TabsContent$1 } from 'reka-ui';
13
+ import { B as Button } from './index-CckL_NBD.mjs';
14
+ import { b as useRoute, a as useRouter } from './server.mjs';
15
+ import '../nitro/nitro.mjs';
16
+ import 'node:http';
17
+ import 'node:https';
18
+ import 'node:events';
19
+ import 'node:buffer';
20
+ import 'node:fs';
21
+ import 'node:path';
22
+ import 'node:crypto';
23
+ import 'node:os';
24
+ import 'node:url';
25
+ import '@vue-flow/background';
26
+ import '@vue-flow/controls';
27
+ import '@vue-flow/core';
28
+ import 'shiki/bundle/web';
29
+ import 'class-variance-authority';
30
+ import 'clsx';
31
+ import 'tailwind-merge';
32
+ import 'vue-sonner';
33
+ import '@vue/shared';
34
+ import 'perfect-debounce';
35
+ import '../routes/renderer.mjs';
36
+ import 'vue-bundle-renderer/runtime';
37
+ import 'unhead/server';
38
+ import 'devalue';
39
+ import 'unhead/utils';
40
+ import 'vue-router';
41
+
42
+ const _sfc_main$g = /* @__PURE__ */ defineComponent({
43
+ __name: "Meta",
44
+ __ssrInlineRender: true,
45
+ props: {
46
+ metadata: {}
47
+ },
48
+ setup(__props) {
49
+ const props = __props;
50
+ const statusVariant = computed(() => {
51
+ const status = props.metadata.status?.toLowerCase();
52
+ if (!status) return "secondary";
53
+ if (status.includes("complete") || status.includes("done")) return "default";
54
+ if (status.includes("progress") || status.includes("active")) return "default";
55
+ if (status.includes("draft")) return "secondary";
56
+ if (status.includes("blocked") || status.includes("paused")) return "destructive";
57
+ return "secondary";
58
+ });
59
+ const hasMetadata = computed(() => {
60
+ return props.metadata.author || props.metadata.date || props.metadata.status || props.metadata.shortcutStory;
61
+ });
62
+ return (_ctx, _push, _parent, _attrs) => {
63
+ if (unref(hasMetadata)) {
64
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "flex flex-wrap items-center gap-3 text-sm" }, _attrs))}>`);
65
+ if (__props.metadata.author) {
66
+ _push(`<div class="flex items-center gap-1.5 text-muted-foreground">`);
67
+ _push(ssrRenderComponent(unref(User), { class: "size-3.5" }, null, _parent));
68
+ _push(`<span>${ssrInterpolate(__props.metadata.author)}</span></div>`);
69
+ } else {
70
+ _push(`<!---->`);
71
+ }
72
+ if (__props.metadata.date) {
73
+ _push(`<div class="flex items-center gap-1.5 text-muted-foreground">`);
74
+ _push(ssrRenderComponent(unref(Calendar), { class: "size-3.5" }, null, _parent));
75
+ _push(`<span>${ssrInterpolate(__props.metadata.date)}</span></div>`);
76
+ } else {
77
+ _push(`<!---->`);
78
+ }
79
+ if (__props.metadata.status) {
80
+ _push(ssrRenderComponent(unref(Badge), {
81
+ variant: unref(statusVariant),
82
+ class: "gap-1"
83
+ }, {
84
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
85
+ if (_push2) {
86
+ _push2(ssrRenderComponent(unref(CircleDot), { class: "size-3" }, null, _parent2, _scopeId));
87
+ _push2(` ${ssrInterpolate(__props.metadata.status)}`);
88
+ } else {
89
+ return [
90
+ createVNode(unref(CircleDot), { class: "size-3" }),
91
+ createTextVNode(" " + toDisplayString(__props.metadata.status), 1)
92
+ ];
93
+ }
94
+ }),
95
+ _: 1
96
+ }, _parent));
97
+ } else {
98
+ _push(`<!---->`);
99
+ }
100
+ if (__props.metadata.shortcutStory && __props.metadata.shortcutUrl) {
101
+ _push(`<a${ssrRenderAttr("href", __props.metadata.shortcutUrl)} target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-1.5 text-primary hover:underline">`);
102
+ _push(ssrRenderComponent(unref(ExternalLink), { class: "size-3.5" }, null, _parent));
103
+ _push(`<span>${ssrInterpolate(__props.metadata.shortcutStory)}</span></a>`);
104
+ } else if (__props.metadata.shortcutStory) {
105
+ _push(`<span class="flex items-center gap-1.5 text-muted-foreground">`);
106
+ _push(ssrRenderComponent(unref(ExternalLink), { class: "size-3.5" }, null, _parent));
107
+ _push(`<span>${ssrInterpolate(__props.metadata.shortcutStory)}</span></span>`);
108
+ } else {
109
+ _push(`<!---->`);
110
+ }
111
+ _push(`</div>`);
112
+ } else {
113
+ _push(`<!---->`);
114
+ }
115
+ };
116
+ }
117
+ });
118
+ const _sfc_setup$g = _sfc_main$g.setup;
119
+ _sfc_main$g.setup = (props, ctx) => {
120
+ const ssrContext = useSSRContext();
121
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/prd/Meta.vue");
122
+ return _sfc_setup$g ? _sfc_setup$g(props, ctx) : void 0;
123
+ };
124
+ const __nuxt_component_1 = Object.assign(_sfc_main$g, { __name: "PrdMeta" });
125
+ const _sfc_main$f = /* @__PURE__ */ defineComponent({
126
+ __name: "Viewer",
127
+ __ssrInlineRender: true,
128
+ props: {
129
+ content: {}
130
+ },
131
+ setup(__props) {
132
+ const props = __props;
133
+ const renderedHtml = ref("");
134
+ const isLoading = ref(true);
135
+ const purifyConfig = {
136
+ ADD_TAGS: ["style"],
137
+ ADD_ATTR: ["style", "class", "target", "rel"]
138
+ };
139
+ const renderer = new marked.Renderer();
140
+ renderer.link = ({ href, title, text }) => {
141
+ const titleAttr = title ? ` title="${title}"` : "";
142
+ return `<a href="${href}"${titleAttr} target="_blank" rel="noopener noreferrer">${text}</a>`;
143
+ };
144
+ async function highlightCode(code, lang) {
145
+ try {
146
+ return await codeToHtml(code, {
147
+ lang: lang || "text",
148
+ themes: {
149
+ light: "github-light",
150
+ dark: "github-dark"
151
+ }
152
+ });
153
+ } catch {
154
+ return `<pre><code class="language-${lang}">${escapeHtml(code)}</code></pre>`;
155
+ }
156
+ }
157
+ function escapeHtml(text) {
158
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
159
+ }
160
+ async function renderMarkdown(content) {
161
+ const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
162
+ const placeholders = [];
163
+ let placeholderIndex = 0;
164
+ const contentWithPlaceholders = content.replace(codeBlockRegex, (_, lang, code) => {
165
+ const placeholder = `CODEBLOCK${placeholderIndex++}PLACEHOLDER`;
166
+ placeholders.push({ placeholder, lang: lang || "text", code: code.trim() });
167
+ return placeholder;
168
+ });
169
+ marked.setOptions({
170
+ renderer,
171
+ gfm: true,
172
+ breaks: true
173
+ });
174
+ let html = await marked.parse(contentWithPlaceholders);
175
+ const highlightPromises = placeholders.map(async ({ placeholder, lang, code }) => {
176
+ const highlighted = await highlightCode(code, lang);
177
+ return { placeholder, highlighted };
178
+ });
179
+ const results = await Promise.all(highlightPromises);
180
+ for (const { placeholder, highlighted } of results) {
181
+ html = html.replace(`<p>${placeholder}</p>`, highlighted);
182
+ html = html.replace(placeholder, highlighted);
183
+ }
184
+ return DOMPurify.sanitize(html, purifyConfig);
185
+ }
186
+ watch(() => props.content, async (newContent) => {
187
+ if (newContent) {
188
+ isLoading.value = true;
189
+ try {
190
+ renderedHtml.value = await renderMarkdown(newContent);
191
+ } finally {
192
+ isLoading.value = false;
193
+ }
194
+ }
195
+ }, { immediate: true });
196
+ return (_ctx, _push, _parent, _attrs) => {
197
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "prd-viewer" }, _attrs))}>`);
198
+ if (unref(isLoading)) {
199
+ _push(`<div class="flex items-center justify-center py-8"><div class="size-6 animate-spin rounded-full border-2 border-primary border-t-transparent"></div></div>`);
200
+ } else {
201
+ _push(`<div class="prose prose-sm dark:prose-invert max-w-none">${unref(renderedHtml) ?? ""}</div>`);
202
+ }
203
+ _push(`</div>`);
204
+ };
205
+ }
206
+ });
207
+ const _sfc_setup$f = _sfc_main$f.setup;
208
+ _sfc_main$f.setup = (props, ctx) => {
209
+ const ssrContext = useSSRContext();
210
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/prd/Viewer.vue");
211
+ return _sfc_setup$f ? _sfc_setup$f(props, ctx) : void 0;
212
+ };
213
+ const __nuxt_component_2 = Object.assign(_sfc_main$f, { __name: "PrdViewer" });
214
+ const _sfc_main$e = /* @__PURE__ */ defineComponent({
215
+ __name: "Card",
216
+ __ssrInlineRender: true,
217
+ props: {
218
+ class: {}
219
+ },
220
+ setup(__props) {
221
+ const props = __props;
222
+ return (_ctx, _push, _parent, _attrs) => {
223
+ _push(`<div${ssrRenderAttrs(mergeProps({
224
+ "data-slot": "card",
225
+ class: unref(cn)(
226
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
227
+ props.class
228
+ )
229
+ }, _attrs))}>`);
230
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
231
+ _push(`</div>`);
232
+ };
233
+ }
234
+ });
235
+ const _sfc_setup$e = _sfc_main$e.setup;
236
+ _sfc_main$e.setup = (props, ctx) => {
237
+ const ssrContext = useSSRContext();
238
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/Card.vue");
239
+ return _sfc_setup$e ? _sfc_setup$e(props, ctx) : void 0;
240
+ };
241
+ const Card = Object.assign(_sfc_main$e, { __name: "UiCard" });
242
+ const _sfc_main$d = /* @__PURE__ */ defineComponent({
243
+ __name: "CardAction",
244
+ __ssrInlineRender: true,
245
+ props: {
246
+ class: {}
247
+ },
248
+ setup(__props) {
249
+ const props = __props;
250
+ return (_ctx, _push, _parent, _attrs) => {
251
+ _push(`<div${ssrRenderAttrs(mergeProps({
252
+ "data-slot": "card-action",
253
+ class: unref(cn)("col-start-2 row-span-2 row-start-1 self-start justify-self-end", props.class)
254
+ }, _attrs))}>`);
255
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
256
+ _push(`</div>`);
257
+ };
258
+ }
259
+ });
260
+ const _sfc_setup$d = _sfc_main$d.setup;
261
+ _sfc_main$d.setup = (props, ctx) => {
262
+ const ssrContext = useSSRContext();
263
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/CardAction.vue");
264
+ return _sfc_setup$d ? _sfc_setup$d(props, ctx) : void 0;
265
+ };
266
+ Object.assign(_sfc_main$d, { __name: "UiCardAction" });
267
+ const _sfc_main$c = /* @__PURE__ */ defineComponent({
268
+ __name: "CardContent",
269
+ __ssrInlineRender: true,
270
+ props: {
271
+ class: {}
272
+ },
273
+ setup(__props) {
274
+ const props = __props;
275
+ return (_ctx, _push, _parent, _attrs) => {
276
+ _push(`<div${ssrRenderAttrs(mergeProps({
277
+ "data-slot": "card-content",
278
+ class: unref(cn)("px-6", props.class)
279
+ }, _attrs))}>`);
280
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
281
+ _push(`</div>`);
282
+ };
283
+ }
284
+ });
285
+ const _sfc_setup$c = _sfc_main$c.setup;
286
+ _sfc_main$c.setup = (props, ctx) => {
287
+ const ssrContext = useSSRContext();
288
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/CardContent.vue");
289
+ return _sfc_setup$c ? _sfc_setup$c(props, ctx) : void 0;
290
+ };
291
+ const CardContent = Object.assign(_sfc_main$c, { __name: "UiCardContent" });
292
+ const _sfc_main$b = /* @__PURE__ */ defineComponent({
293
+ __name: "CardDescription",
294
+ __ssrInlineRender: true,
295
+ props: {
296
+ class: {}
297
+ },
298
+ setup(__props) {
299
+ const props = __props;
300
+ return (_ctx, _push, _parent, _attrs) => {
301
+ _push(`<p${ssrRenderAttrs(mergeProps({
302
+ "data-slot": "card-description",
303
+ class: unref(cn)("text-muted-foreground text-sm", props.class)
304
+ }, _attrs))}>`);
305
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
306
+ _push(`</p>`);
307
+ };
308
+ }
309
+ });
310
+ const _sfc_setup$b = _sfc_main$b.setup;
311
+ _sfc_main$b.setup = (props, ctx) => {
312
+ const ssrContext = useSSRContext();
313
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/CardDescription.vue");
314
+ return _sfc_setup$b ? _sfc_setup$b(props, ctx) : void 0;
315
+ };
316
+ Object.assign(_sfc_main$b, { __name: "UiCardDescription" });
317
+ const _sfc_main$a = /* @__PURE__ */ defineComponent({
318
+ __name: "CardFooter",
319
+ __ssrInlineRender: true,
320
+ props: {
321
+ class: {}
322
+ },
323
+ setup(__props) {
324
+ const props = __props;
325
+ return (_ctx, _push, _parent, _attrs) => {
326
+ _push(`<div${ssrRenderAttrs(mergeProps({
327
+ "data-slot": "card-footer",
328
+ class: unref(cn)("flex items-center px-6 [.border-t]:pt-6", props.class)
329
+ }, _attrs))}>`);
330
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
331
+ _push(`</div>`);
332
+ };
333
+ }
334
+ });
335
+ const _sfc_setup$a = _sfc_main$a.setup;
336
+ _sfc_main$a.setup = (props, ctx) => {
337
+ const ssrContext = useSSRContext();
338
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/CardFooter.vue");
339
+ return _sfc_setup$a ? _sfc_setup$a(props, ctx) : void 0;
340
+ };
341
+ Object.assign(_sfc_main$a, { __name: "UiCardFooter" });
342
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
343
+ __name: "CardHeader",
344
+ __ssrInlineRender: true,
345
+ props: {
346
+ class: {}
347
+ },
348
+ setup(__props) {
349
+ const props = __props;
350
+ return (_ctx, _push, _parent, _attrs) => {
351
+ _push(`<div${ssrRenderAttrs(mergeProps({
352
+ "data-slot": "card-header",
353
+ class: unref(cn)("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", props.class)
354
+ }, _attrs))}>`);
355
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
356
+ _push(`</div>`);
357
+ };
358
+ }
359
+ });
360
+ const _sfc_setup$9 = _sfc_main$9.setup;
361
+ _sfc_main$9.setup = (props, ctx) => {
362
+ const ssrContext = useSSRContext();
363
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/CardHeader.vue");
364
+ return _sfc_setup$9 ? _sfc_setup$9(props, ctx) : void 0;
365
+ };
366
+ Object.assign(_sfc_main$9, { __name: "UiCardHeader" });
367
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
368
+ __name: "CardTitle",
369
+ __ssrInlineRender: true,
370
+ props: {
371
+ class: {}
372
+ },
373
+ setup(__props) {
374
+ const props = __props;
375
+ return (_ctx, _push, _parent, _attrs) => {
376
+ _push(`<h3${ssrRenderAttrs(mergeProps({
377
+ "data-slot": "card-title",
378
+ class: unref(cn)("leading-none font-semibold", props.class)
379
+ }, _attrs))}>`);
380
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push, _parent);
381
+ _push(`</h3>`);
382
+ };
383
+ }
384
+ });
385
+ const _sfc_setup$8 = _sfc_main$8.setup;
386
+ _sfc_main$8.setup = (props, ctx) => {
387
+ const ssrContext = useSSRContext();
388
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/card/CardTitle.vue");
389
+ return _sfc_setup$8 ? _sfc_setup$8(props, ctx) : void 0;
390
+ };
391
+ Object.assign(_sfc_main$8, { __name: "UiCardTitle" });
392
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
393
+ __name: "Card",
394
+ __ssrInlineRender: true,
395
+ props: {
396
+ task: {},
397
+ blockedBy: {}
398
+ },
399
+ emits: ["click"],
400
+ setup(__props, { emit: __emit }) {
401
+ const props = __props;
402
+ const emit = __emit;
403
+ const categoryConfig = computed(() => {
404
+ switch (props.task.category) {
405
+ case "setup":
406
+ return { label: "Setup", variant: "secondary" };
407
+ case "feature":
408
+ return { label: "Feature", variant: "default" };
409
+ case "integration":
410
+ return { label: "Integration", variant: "outline" };
411
+ case "testing":
412
+ return { label: "Testing", variant: "secondary" };
413
+ case "documentation":
414
+ return { label: "Docs", variant: "secondary" };
415
+ default:
416
+ return { label: props.task.category, variant: "secondary" };
417
+ }
418
+ });
419
+ const priorityConfig = computed(() => {
420
+ switch (props.task.priority) {
421
+ case "critical":
422
+ return { icon: ArrowUp, class: "text-destructive", label: "Critical" };
423
+ case "high":
424
+ return { icon: ArrowUp, class: "text-orange-500", label: "High" };
425
+ case "medium":
426
+ return { icon: Minus, class: "text-muted-foreground", label: "Medium" };
427
+ case "low":
428
+ return { icon: ArrowDown, class: "text-muted-foreground", label: "Low" };
429
+ default:
430
+ return { icon: Minus, class: "text-muted-foreground", label: "Unknown" };
431
+ }
432
+ });
433
+ const isBlocked = computed(() => {
434
+ return props.blockedBy && props.blockedBy.length > 0;
435
+ });
436
+ const taskNumber = computed(() => {
437
+ const match = props.task.id.match(/(\d+)$/);
438
+ const value = match?.[1];
439
+ return value ? parseInt(value, 10) : 0;
440
+ });
441
+ const blockedCount = computed(() => {
442
+ return props.blockedBy?.length ?? 0;
443
+ });
444
+ function handleClick() {
445
+ emit("click", props.task);
446
+ }
447
+ return (_ctx, _push, _parent, _attrs) => {
448
+ _push(ssrRenderComponent(unref(Card), mergeProps({
449
+ class: ["cursor-pointer py-0 gap-0 transition-all hover:shadow-md hover:border-primary/50", { "opacity-60": unref(isBlocked) }],
450
+ onClick: handleClick
451
+ }, _attrs), {
452
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
453
+ if (_push2) {
454
+ _push2(ssrRenderComponent(unref(CardContent), { class: "p-2.5" }, {
455
+ default: withCtx((_2, _push3, _parent3, _scopeId2) => {
456
+ if (_push3) {
457
+ _push3(`<div class="flex items-center justify-between gap-2 mb-1.5"${_scopeId2}>`);
458
+ _push3(ssrRenderComponent(unref(Badge), {
459
+ variant: unref(categoryConfig).variant,
460
+ class: "text-xs"
461
+ }, {
462
+ default: withCtx((_3, _push4, _parent4, _scopeId3) => {
463
+ if (_push4) {
464
+ _push4(`${ssrInterpolate(unref(categoryConfig).label)}`);
465
+ } else {
466
+ return [
467
+ createTextVNode(toDisplayString(unref(categoryConfig).label), 1)
468
+ ];
469
+ }
470
+ }),
471
+ _: 1
472
+ }, _parent3, _scopeId2));
473
+ ssrRenderVNode(_push3, createVNode(resolveDynamicComponent(unref(priorityConfig).icon), {
474
+ class: ["size-4", unref(priorityConfig).class],
475
+ title: unref(priorityConfig).label
476
+ }, null), _parent3, _scopeId2);
477
+ _push3(`</div><h4 class="text-sm font-medium leading-snug"${_scopeId2}><span class="text-muted-foreground"${_scopeId2}>#${ssrInterpolate(unref(taskNumber))}</span> ${ssrInterpolate(__props.task.title)}</h4>`);
478
+ if (unref(isBlocked)) {
479
+ _push3(`<div class="mt-2 flex items-center gap-1.5 text-xs text-destructive"${_scopeId2}>`);
480
+ _push3(ssrRenderComponent(unref(AlertCircle), { class: "size-3.5" }, null, _parent3, _scopeId2));
481
+ _push3(`<span${_scopeId2}>Blocked by ${ssrInterpolate(unref(blockedCount))} task${ssrInterpolate(unref(blockedCount) === 1 ? "" : "s")}</span></div>`);
482
+ } else {
483
+ _push3(`<!---->`);
484
+ }
485
+ } else {
486
+ return [
487
+ createVNode("div", { class: "flex items-center justify-between gap-2 mb-1.5" }, [
488
+ createVNode(unref(Badge), {
489
+ variant: unref(categoryConfig).variant,
490
+ class: "text-xs"
491
+ }, {
492
+ default: withCtx(() => [
493
+ createTextVNode(toDisplayString(unref(categoryConfig).label), 1)
494
+ ]),
495
+ _: 1
496
+ }, 8, ["variant"]),
497
+ (openBlock(), createBlock(resolveDynamicComponent(unref(priorityConfig).icon), {
498
+ class: ["size-4", unref(priorityConfig).class],
499
+ title: unref(priorityConfig).label
500
+ }, null, 8, ["class", "title"]))
501
+ ]),
502
+ createVNode("h4", { class: "text-sm font-medium leading-snug" }, [
503
+ createVNode("span", { class: "text-muted-foreground" }, "#" + toDisplayString(unref(taskNumber)), 1),
504
+ createTextVNode(" " + toDisplayString(__props.task.title), 1)
505
+ ]),
506
+ unref(isBlocked) ? (openBlock(), createBlock("div", {
507
+ key: 0,
508
+ class: "mt-2 flex items-center gap-1.5 text-xs text-destructive"
509
+ }, [
510
+ createVNode(unref(AlertCircle), { class: "size-3.5" }),
511
+ createVNode("span", null, "Blocked by " + toDisplayString(unref(blockedCount)) + " task" + toDisplayString(unref(blockedCount) === 1 ? "" : "s"), 1)
512
+ ])) : createCommentVNode("", true)
513
+ ];
514
+ }
515
+ }),
516
+ _: 1
517
+ }, _parent2, _scopeId));
518
+ } else {
519
+ return [
520
+ createVNode(unref(CardContent), { class: "p-2.5" }, {
521
+ default: withCtx(() => [
522
+ createVNode("div", { class: "flex items-center justify-between gap-2 mb-1.5" }, [
523
+ createVNode(unref(Badge), {
524
+ variant: unref(categoryConfig).variant,
525
+ class: "text-xs"
526
+ }, {
527
+ default: withCtx(() => [
528
+ createTextVNode(toDisplayString(unref(categoryConfig).label), 1)
529
+ ]),
530
+ _: 1
531
+ }, 8, ["variant"]),
532
+ (openBlock(), createBlock(resolveDynamicComponent(unref(priorityConfig).icon), {
533
+ class: ["size-4", unref(priorityConfig).class],
534
+ title: unref(priorityConfig).label
535
+ }, null, 8, ["class", "title"]))
536
+ ]),
537
+ createVNode("h4", { class: "text-sm font-medium leading-snug" }, [
538
+ createVNode("span", { class: "text-muted-foreground" }, "#" + toDisplayString(unref(taskNumber)), 1),
539
+ createTextVNode(" " + toDisplayString(__props.task.title), 1)
540
+ ]),
541
+ unref(isBlocked) ? (openBlock(), createBlock("div", {
542
+ key: 0,
543
+ class: "mt-2 flex items-center gap-1.5 text-xs text-destructive"
544
+ }, [
545
+ createVNode(unref(AlertCircle), { class: "size-3.5" }),
546
+ createVNode("span", null, "Blocked by " + toDisplayString(unref(blockedCount)) + " task" + toDisplayString(unref(blockedCount) === 1 ? "" : "s"), 1)
547
+ ])) : createCommentVNode("", true)
548
+ ]),
549
+ _: 1
550
+ })
551
+ ];
552
+ }
553
+ }),
554
+ _: 1
555
+ }, _parent));
556
+ };
557
+ }
558
+ });
559
+ const _sfc_setup$7 = _sfc_main$7.setup;
560
+ _sfc_main$7.setup = (props, ctx) => {
561
+ const ssrContext = useSSRContext();
562
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/tasks/Card.vue");
563
+ return _sfc_setup$7 ? _sfc_setup$7(props, ctx) : void 0;
564
+ };
565
+ const __nuxt_component_0$1 = Object.assign(_sfc_main$7, { __name: "TasksCard" });
566
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
567
+ __name: "Column",
568
+ __ssrInlineRender: true,
569
+ props: {
570
+ status: {},
571
+ tasks: {},
572
+ blockedByMap: {}
573
+ },
574
+ emits: ["taskClick"],
575
+ setup(__props, { emit: __emit }) {
576
+ const props = __props;
577
+ const emit = __emit;
578
+ const statusConfig = computed(() => {
579
+ switch (props.status) {
580
+ case "pending":
581
+ return {
582
+ label: "Pending",
583
+ icon: Circle,
584
+ headerClass: "bg-muted/50",
585
+ iconClass: "text-muted-foreground"
586
+ };
587
+ case "in_progress":
588
+ return {
589
+ label: "In Progress",
590
+ icon: PlayCircle,
591
+ headerClass: "bg-blue-500/10",
592
+ iconClass: "text-blue-500"
593
+ };
594
+ case "completed":
595
+ return {
596
+ label: "Completed",
597
+ icon: CheckCircle2,
598
+ headerClass: "bg-green-500/10",
599
+ iconClass: "text-green-500"
600
+ };
601
+ default:
602
+ return {
603
+ label: props.status,
604
+ icon: Circle,
605
+ headerClass: "bg-muted/50",
606
+ iconClass: "text-muted-foreground"
607
+ };
608
+ }
609
+ });
610
+ function getBlockedBy(taskId) {
611
+ return props.blockedByMap?.get(taskId) ?? [];
612
+ }
613
+ function handleTaskClick(task) {
614
+ emit("taskClick", task);
615
+ }
616
+ return (_ctx, _push, _parent, _attrs) => {
617
+ const _component_TasksCard = __nuxt_component_0$1;
618
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "flex h-full min-w-56 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-card" }, _attrs))} data-v-a1317eba><div class="${ssrRenderClass([unref(statusConfig).headerClass, "flex items-center gap-2 rounded-t-lg border-b border-border px-3 py-2"])}" data-v-a1317eba>`);
619
+ ssrRenderVNode(_push, createVNode(resolveDynamicComponent(unref(statusConfig).icon), {
620
+ class: ["size-4", unref(statusConfig).iconClass]
621
+ }, null), _parent);
622
+ _push(`<h3 class="text-sm font-medium" data-v-a1317eba>${ssrInterpolate(unref(statusConfig).label)}</h3><span class="ml-auto text-xs text-muted-foreground" data-v-a1317eba>${ssrInterpolate(__props.tasks.length)}</span></div><div class="scrollbar-hide min-h-0 flex-1 overflow-y-auto p-1.5" data-v-a1317eba><div class="space-y-1.5" data-v-a1317eba><!--[-->`);
623
+ ssrRenderList(__props.tasks, (task) => {
624
+ _push(ssrRenderComponent(_component_TasksCard, {
625
+ key: task.id,
626
+ task,
627
+ "blocked-by": getBlockedBy(task.id),
628
+ onClick: handleTaskClick
629
+ }, null, _parent));
630
+ });
631
+ _push(`<!--]-->`);
632
+ if (__props.tasks.length === 0) {
633
+ _push(`<div class="py-8 text-center text-sm text-muted-foreground" data-v-a1317eba> No tasks </div>`);
634
+ } else {
635
+ _push(`<!---->`);
636
+ }
637
+ _push(`</div></div></div>`);
638
+ };
639
+ }
640
+ });
641
+ const _sfc_setup$6 = _sfc_main$6.setup;
642
+ _sfc_main$6.setup = (props, ctx) => {
643
+ const ssrContext = useSSRContext();
644
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/tasks/Column.vue");
645
+ return _sfc_setup$6 ? _sfc_setup$6(props, ctx) : void 0;
646
+ };
647
+ const __nuxt_component_0 = /* @__PURE__ */ Object.assign(_export_sfc(_sfc_main$6, [["__scopeId", "data-v-a1317eba"]]), { __name: "TasksColumn" });
648
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
649
+ __name: "Board",
650
+ __ssrInlineRender: true,
651
+ props: {
652
+ tasks: {}
653
+ },
654
+ emits: ["taskClick"],
655
+ setup(__props, { emit: __emit }) {
656
+ const props = __props;
657
+ const emit = __emit;
658
+ function getTaskNumber(task) {
659
+ const match = task.id.match(/(\d+)$/);
660
+ const value = match?.[1];
661
+ return value ? parseInt(value, 10) : 0;
662
+ }
663
+ const pendingTasks = computed(
664
+ () => props.tasks.filter((t) => t.status === "pending").sort((a, b) => getTaskNumber(a) - getTaskNumber(b))
665
+ );
666
+ const inProgressTasks = computed(
667
+ () => props.tasks.filter((t) => t.status === "in_progress").sort((a, b) => getTaskNumber(a) - getTaskNumber(b))
668
+ );
669
+ const completedTasks = computed(
670
+ () => props.tasks.filter((t) => t.status === "completed").sort((a, b) => {
671
+ const aTime = a.completedAt ? new Date(a.completedAt).getTime() : 0;
672
+ const bTime = b.completedAt ? new Date(b.completedAt).getTime() : 0;
673
+ return bTime - aTime;
674
+ })
675
+ );
676
+ const blockedByMap = computed(() => {
677
+ const map = /* @__PURE__ */ new Map();
678
+ const completedIds = new Set(completedTasks.value.map((t) => t.id));
679
+ for (const task of props.tasks) {
680
+ if (task.dependencies.length > 0) {
681
+ const blockers = task.dependencies.filter((depId) => !completedIds.has(depId));
682
+ if (blockers.length > 0) {
683
+ map.set(task.id, blockers);
684
+ }
685
+ }
686
+ }
687
+ return map;
688
+ });
689
+ const columns = [
690
+ { status: "pending", tasks: pendingTasks },
691
+ { status: "in_progress", tasks: inProgressTasks },
692
+ { status: "completed", tasks: completedTasks }
693
+ ];
694
+ function handleTaskClick(task) {
695
+ emit("taskClick", task);
696
+ }
697
+ return (_ctx, _push, _parent, _attrs) => {
698
+ const _component_TasksColumn = __nuxt_component_0;
699
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "flex h-full gap-3 overflow-x-auto pb-2" }, _attrs))}><!--[-->`);
700
+ ssrRenderList(columns, (column) => {
701
+ _push(ssrRenderComponent(_component_TasksColumn, {
702
+ key: column.status,
703
+ status: column.status,
704
+ tasks: column.tasks.value,
705
+ "blocked-by-map": unref(blockedByMap),
706
+ onTaskClick: handleTaskClick
707
+ }, null, _parent));
708
+ });
709
+ _push(`<!--]--></div>`);
710
+ };
711
+ }
712
+ });
713
+ const _sfc_setup$5 = _sfc_main$5.setup;
714
+ _sfc_main$5.setup = (props, ctx) => {
715
+ const ssrContext = useSSRContext();
716
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/tasks/Board.vue");
717
+ return _sfc_setup$5 ? _sfc_setup$5(props, ctx) : void 0;
718
+ };
719
+ const __nuxt_component_3 = Object.assign(_sfc_main$5, { __name: "TasksBoard" });
720
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
721
+ __name: "Tabs",
722
+ __ssrInlineRender: true,
723
+ props: {
724
+ defaultValue: {},
725
+ orientation: {},
726
+ dir: {},
727
+ activationMode: {},
728
+ modelValue: {},
729
+ unmountOnHide: { type: Boolean },
730
+ asChild: { type: Boolean },
731
+ as: {},
732
+ class: {}
733
+ },
734
+ emits: ["update:modelValue"],
735
+ setup(__props, { emit: __emit }) {
736
+ const props = __props;
737
+ const emits = __emit;
738
+ const delegatedProps = reactiveOmit(props, "class");
739
+ const forwarded = useForwardPropsEmits(delegatedProps, emits);
740
+ return (_ctx, _push, _parent, _attrs) => {
741
+ _push(ssrRenderComponent(unref(TabsRoot), mergeProps({ "data-slot": "tabs" }, unref(forwarded), {
742
+ class: unref(cn)("flex flex-col gap-2", props.class)
743
+ }, _attrs), {
744
+ default: withCtx((slotProps, _push2, _parent2, _scopeId) => {
745
+ if (_push2) {
746
+ ssrRenderSlot(_ctx.$slots, "default", slotProps, null, _push2, _parent2, _scopeId);
747
+ } else {
748
+ return [
749
+ renderSlot(_ctx.$slots, "default", slotProps)
750
+ ];
751
+ }
752
+ }),
753
+ _: 3
754
+ }, _parent));
755
+ };
756
+ }
757
+ });
758
+ const _sfc_setup$4 = _sfc_main$4.setup;
759
+ _sfc_main$4.setup = (props, ctx) => {
760
+ const ssrContext = useSSRContext();
761
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/tabs/Tabs.vue");
762
+ return _sfc_setup$4 ? _sfc_setup$4(props, ctx) : void 0;
763
+ };
764
+ const Tabs = Object.assign(_sfc_main$4, { __name: "UiTabs" });
765
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
766
+ __name: "TabsContent",
767
+ __ssrInlineRender: true,
768
+ props: {
769
+ value: {},
770
+ forceMount: { type: Boolean },
771
+ asChild: { type: Boolean },
772
+ as: {},
773
+ class: {}
774
+ },
775
+ setup(__props) {
776
+ const props = __props;
777
+ const delegatedProps = reactiveOmit(props, "class");
778
+ return (_ctx, _push, _parent, _attrs) => {
779
+ _push(ssrRenderComponent(unref(TabsContent$1), mergeProps({
780
+ "data-slot": "tabs-content",
781
+ class: unref(cn)("flex-1 outline-none", props.class)
782
+ }, unref(delegatedProps), _attrs), {
783
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
784
+ if (_push2) {
785
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push2, _parent2, _scopeId);
786
+ } else {
787
+ return [
788
+ renderSlot(_ctx.$slots, "default")
789
+ ];
790
+ }
791
+ }),
792
+ _: 3
793
+ }, _parent));
794
+ };
795
+ }
796
+ });
797
+ const _sfc_setup$3 = _sfc_main$3.setup;
798
+ _sfc_main$3.setup = (props, ctx) => {
799
+ const ssrContext = useSSRContext();
800
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/tabs/TabsContent.vue");
801
+ return _sfc_setup$3 ? _sfc_setup$3(props, ctx) : void 0;
802
+ };
803
+ const TabsContent = Object.assign(_sfc_main$3, { __name: "UiTabsContent" });
804
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
805
+ __name: "TabsList",
806
+ __ssrInlineRender: true,
807
+ props: {
808
+ loop: { type: Boolean },
809
+ asChild: { type: Boolean },
810
+ as: {},
811
+ class: {}
812
+ },
813
+ setup(__props) {
814
+ const props = __props;
815
+ const delegatedProps = reactiveOmit(props, "class");
816
+ return (_ctx, _push, _parent, _attrs) => {
817
+ _push(ssrRenderComponent(unref(TabsList$1), mergeProps({ "data-slot": "tabs-list" }, unref(delegatedProps), {
818
+ class: unref(cn)(
819
+ "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
820
+ props.class
821
+ )
822
+ }, _attrs), {
823
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
824
+ if (_push2) {
825
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push2, _parent2, _scopeId);
826
+ } else {
827
+ return [
828
+ renderSlot(_ctx.$slots, "default")
829
+ ];
830
+ }
831
+ }),
832
+ _: 3
833
+ }, _parent));
834
+ };
835
+ }
836
+ });
837
+ const _sfc_setup$2 = _sfc_main$2.setup;
838
+ _sfc_main$2.setup = (props, ctx) => {
839
+ const ssrContext = useSSRContext();
840
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/tabs/TabsList.vue");
841
+ return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
842
+ };
843
+ const TabsList = Object.assign(_sfc_main$2, { __name: "UiTabsList" });
844
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
845
+ __name: "TabsTrigger",
846
+ __ssrInlineRender: true,
847
+ props: {
848
+ value: {},
849
+ disabled: { type: Boolean },
850
+ asChild: { type: Boolean },
851
+ as: {},
852
+ class: {}
853
+ },
854
+ setup(__props) {
855
+ const props = __props;
856
+ const delegatedProps = reactiveOmit(props, "class");
857
+ const forwardedProps = useForwardProps(delegatedProps);
858
+ return (_ctx, _push, _parent, _attrs) => {
859
+ _push(ssrRenderComponent(unref(TabsTrigger$1), mergeProps({
860
+ "data-slot": "tabs-trigger",
861
+ class: unref(cn)(
862
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
863
+ props.class
864
+ )
865
+ }, unref(forwardedProps), _attrs), {
866
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
867
+ if (_push2) {
868
+ ssrRenderSlot(_ctx.$slots, "default", {}, null, _push2, _parent2, _scopeId);
869
+ } else {
870
+ return [
871
+ renderSlot(_ctx.$slots, "default")
872
+ ];
873
+ }
874
+ }),
875
+ _: 3
876
+ }, _parent));
877
+ };
878
+ }
879
+ });
880
+ const _sfc_setup$1 = _sfc_main$1.setup;
881
+ _sfc_main$1.setup = (props, ctx) => {
882
+ const ssrContext = useSSRContext();
883
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/ui/tabs/TabsTrigger.vue");
884
+ return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
885
+ };
886
+ const TabsTrigger = Object.assign(_sfc_main$1, { __name: "UiTabsTrigger" });
887
+ const TASK_QUERY_KEY = "task";
888
+ const TASK_PRD_QUERY_KEY = "taskPrd";
889
+ const _sfc_main = /* @__PURE__ */ defineComponent({
890
+ __name: "[prd]",
891
+ __ssrInlineRender: true,
892
+ setup(__props) {
893
+ function getSingleQueryParam(value) {
894
+ if (typeof value === "string") {
895
+ const trimmed = value.trim();
896
+ return trimmed.length > 0 ? trimmed : null;
897
+ }
898
+ if (Array.isArray(value) && value.length > 0) {
899
+ const first = value[0];
900
+ if (typeof first === "string") {
901
+ const trimmed = first.trim();
902
+ return trimmed.length > 0 ? trimmed : null;
903
+ }
904
+ }
905
+ return null;
906
+ }
907
+ const route = useRoute();
908
+ const router = useRouter();
909
+ const { selectRepo } = useRepos();
910
+ const {
911
+ fetchDocument,
912
+ fetchTasks,
913
+ fetchProgress,
914
+ fetchTaskCommits,
915
+ fetchPrdGraph
916
+ } = usePrd();
917
+ const { showError } = useToast();
918
+ const repoId = computed(() => route.params.repo);
919
+ const prdSlug = computed(() => route.params.prd);
920
+ const document = ref(null);
921
+ const tasksFile = ref(null);
922
+ const progressFile = ref(null);
923
+ const isLoading = ref(true);
924
+ const error = ref(null);
925
+ const activeTab = ref("document");
926
+ const prdGraph = ref(null);
927
+ const graphLoading = ref(false);
928
+ const graphError = ref(null);
929
+ const tasksByPrd = ref({});
930
+ const selectedTask = ref(null);
931
+ const selectedTaskPrdSlug = ref(null);
932
+ const detailOpen = ref(false);
933
+ const selectedTaskCommits = ref([]);
934
+ const taskQueryId = computed(() => getSingleQueryParam(route.query[TASK_QUERY_KEY]));
935
+ const taskQueryPrd = computed(() => getSingleQueryParam(route.query[TASK_PRD_QUERY_KEY]));
936
+ const routeTaskSelection = computed(() => {
937
+ if (!taskQueryId.value) {
938
+ return null;
939
+ }
940
+ return {
941
+ taskId: taskQueryId.value,
942
+ prdSlug: taskQueryPrd.value || prdSlug.value
943
+ };
944
+ });
945
+ function cacheTasksForPrd(slug, tasks) {
946
+ tasksByPrd.value = {
947
+ ...tasksByPrd.value,
948
+ [slug]: tasks
949
+ };
950
+ }
951
+ async function getTasksForPrd(slug) {
952
+ if (slug === prdSlug.value) {
953
+ return tasksFile.value;
954
+ }
955
+ if (Object.prototype.hasOwnProperty.call(tasksByPrd.value, slug)) {
956
+ return tasksByPrd.value[slug] ?? null;
957
+ }
958
+ const tasks = await fetchTasks(slug);
959
+ cacheTasksForPrd(slug, tasks);
960
+ return tasks;
961
+ }
962
+ function buildBaseQuery() {
963
+ const query = {};
964
+ for (const [key, value] of Object.entries(route.query)) {
965
+ if (key === TASK_QUERY_KEY || key === TASK_PRD_QUERY_KEY) {
966
+ continue;
967
+ }
968
+ if (typeof value === "string") {
969
+ query[key] = value;
970
+ continue;
971
+ }
972
+ if (Array.isArray(value)) {
973
+ const values = value.filter((entry) => typeof entry === "string");
974
+ if (values.length > 0) {
975
+ query[key] = values;
976
+ }
977
+ }
978
+ }
979
+ return query;
980
+ }
981
+ async function syncTaskQuery(taskId, sourcePrdSlug = null) {
982
+ const nextQuery = buildBaseQuery();
983
+ if (taskId) {
984
+ nextQuery[TASK_QUERY_KEY] = taskId;
985
+ if (sourcePrdSlug && sourcePrdSlug !== prdSlug.value) {
986
+ nextQuery[TASK_PRD_QUERY_KEY] = sourcePrdSlug;
987
+ }
988
+ }
989
+ const nextTaskId = typeof nextQuery[TASK_QUERY_KEY] === "string" ? nextQuery[TASK_QUERY_KEY] : null;
990
+ const nextTaskPrd = typeof nextQuery[TASK_PRD_QUERY_KEY] === "string" ? nextQuery[TASK_PRD_QUERY_KEY] : null;
991
+ if (taskQueryId.value === nextTaskId && taskQueryPrd.value === nextTaskPrd) {
992
+ return;
993
+ }
994
+ await router.replace({ query: nextQuery });
995
+ }
996
+ async function openTaskDetail(task, sourcePrdSlug) {
997
+ selectedTask.value = task;
998
+ selectedTaskPrdSlug.value = sourcePrdSlug;
999
+ detailOpen.value = true;
1000
+ selectedTaskCommits.value = [];
1001
+ await syncTaskQuery(task.id, sourcePrdSlug);
1002
+ selectedTaskCommits.value = await fetchTaskCommits(sourcePrdSlug, task.id);
1003
+ }
1004
+ async function syncTaskDetailFromRoute() {
1005
+ const selection = routeTaskSelection.value;
1006
+ if (!selection) {
1007
+ selectedTask.value = null;
1008
+ selectedTaskPrdSlug.value = null;
1009
+ selectedTaskCommits.value = [];
1010
+ detailOpen.value = false;
1011
+ return;
1012
+ }
1013
+ const sourceTasks = await getTasksForPrd(selection.prdSlug);
1014
+ const task = sourceTasks?.tasks.find((entry) => entry.id === selection.taskId);
1015
+ if (!task) {
1016
+ selectedTask.value = null;
1017
+ selectedTaskPrdSlug.value = null;
1018
+ selectedTaskCommits.value = [];
1019
+ detailOpen.value = false;
1020
+ showError("Task unavailable", `Could not find ${selection.taskId} in ${selection.prdSlug}.`);
1021
+ await syncTaskQuery(null);
1022
+ return;
1023
+ }
1024
+ const isSameTask = selectedTask.value?.id === task.id && selectedTaskPrdSlug.value === selection.prdSlug;
1025
+ selectedTask.value = task;
1026
+ selectedTaskPrdSlug.value = selection.prdSlug;
1027
+ detailOpen.value = true;
1028
+ if (!isSameTask) {
1029
+ selectedTaskCommits.value = await fetchTaskCommits(selection.prdSlug, task.id);
1030
+ }
1031
+ }
1032
+ const taskTitles = computed(() => {
1033
+ const map = /* @__PURE__ */ new Map();
1034
+ const sourcePrdSlug = selectedTaskPrdSlug.value || prdSlug.value;
1035
+ const sourceTasks = sourcePrdSlug === prdSlug.value ? tasksFile.value : tasksByPrd.value[sourcePrdSlug] ?? null;
1036
+ if (!sourceTasks?.tasks) {
1037
+ return map;
1038
+ }
1039
+ for (const task of sourceTasks.tasks) {
1040
+ map.set(task.id, task.title);
1041
+ }
1042
+ return map;
1043
+ });
1044
+ watch(activeTab, (tab) => {
1045
+ });
1046
+ const fileChangeEvent = inject("fileChangeEvent", ref(null));
1047
+ async function loadDocument() {
1048
+ const doc = await fetchDocument(prdSlug.value);
1049
+ if (doc) {
1050
+ document.value = doc;
1051
+ }
1052
+ }
1053
+ async function loadTasksAndProgress() {
1054
+ const [tasks, progress] = await Promise.all([
1055
+ fetchTasks(prdSlug.value),
1056
+ fetchProgress(prdSlug.value)
1057
+ ]);
1058
+ tasksFile.value = tasks;
1059
+ progressFile.value = progress;
1060
+ cacheTasksForPrd(prdSlug.value, tasks);
1061
+ }
1062
+ async function loadGraph(force = false) {
1063
+ graphLoading.value = true;
1064
+ try {
1065
+ if (!force && prdGraph.value?.prdSlug === prdSlug.value) {
1066
+ return;
1067
+ }
1068
+ const graph = await fetchPrdGraph(prdSlug.value);
1069
+ if (!graph) {
1070
+ graphError.value = "Failed to load PRD graph.";
1071
+ return;
1072
+ }
1073
+ prdGraph.value = graph;
1074
+ graphError.value = null;
1075
+ } finally {
1076
+ graphLoading.value = false;
1077
+ }
1078
+ }
1079
+ async function ensureGraphLoaded(force = false) {
1080
+ if (activeTab.value !== "graph") {
1081
+ return;
1082
+ }
1083
+ await loadGraph(force);
1084
+ }
1085
+ async function loadData() {
1086
+ isLoading.value = true;
1087
+ error.value = null;
1088
+ graphError.value = null;
1089
+ prdGraph.value = null;
1090
+ tasksByPrd.value = {};
1091
+ try {
1092
+ selectRepo(repoId.value);
1093
+ const [doc, tasks, progress] = await Promise.all([
1094
+ fetchDocument(prdSlug.value),
1095
+ fetchTasks(prdSlug.value),
1096
+ fetchProgress(prdSlug.value)
1097
+ ]);
1098
+ if (!doc) {
1099
+ error.value = `PRD "${prdSlug.value}" not found in this repository.`;
1100
+ return;
1101
+ }
1102
+ document.value = doc;
1103
+ tasksFile.value = tasks;
1104
+ progressFile.value = progress;
1105
+ cacheTasksForPrd(prdSlug.value, tasks);
1106
+ if (!tasks && activeTab.value === "board") {
1107
+ activeTab.value = "document";
1108
+ }
1109
+ await ensureGraphLoaded();
1110
+ await syncTaskDetailFromRoute();
1111
+ } catch (err) {
1112
+ const fetchErr = err;
1113
+ if (fetchErr.statusCode === 404) {
1114
+ error.value = `PRD "${prdSlug.value}" not found. Check if the file exists in docs/prd/.`;
1115
+ } else if (fetchErr.statusCode === 500) {
1116
+ error.value = "Server error while loading the PRD. Check the file format.";
1117
+ showError("Server error", fetchErr.data?.message || "Failed to read PRD file");
1118
+ } else {
1119
+ error.value = "Failed to load PRD document. Please try again.";
1120
+ showError("Load failed", "Could not fetch the PRD document");
1121
+ }
1122
+ } finally {
1123
+ isLoading.value = false;
1124
+ }
1125
+ }
1126
+ watch(activeTab, async (tab) => {
1127
+ if (tab === "graph") {
1128
+ await ensureGraphLoaded();
1129
+ }
1130
+ });
1131
+ watch(
1132
+ () => [route.query[TASK_QUERY_KEY], route.query[TASK_PRD_QUERY_KEY], prdSlug.value],
1133
+ async () => {
1134
+ if (isLoading.value) {
1135
+ return;
1136
+ }
1137
+ await syncTaskDetailFromRoute();
1138
+ }
1139
+ );
1140
+ watch(detailOpen, async (isOpen) => {
1141
+ if (!isOpen && routeTaskSelection.value) {
1142
+ await syncTaskQuery(null);
1143
+ }
1144
+ });
1145
+ watch(
1146
+ () => fileChangeEvent.value,
1147
+ async (event) => {
1148
+ if (!event) {
1149
+ return;
1150
+ }
1151
+ if (event.category === "prd") {
1152
+ await loadDocument();
1153
+ if (activeTab.value === "graph") {
1154
+ await loadGraph(true);
1155
+ }
1156
+ return;
1157
+ }
1158
+ if (event.category !== "tasks" && event.category !== "progress") {
1159
+ return;
1160
+ }
1161
+ const isCurrentPrdChange = event.path?.includes(`/${prdSlug.value}/`) ?? false;
1162
+ if (isCurrentPrdChange) {
1163
+ await loadTasksAndProgress();
1164
+ prdGraph.value = null;
1165
+ }
1166
+ if (activeTab.value === "graph") {
1167
+ if (isCurrentPrdChange) {
1168
+ await loadGraph(true);
1169
+ }
1170
+ }
1171
+ }
1172
+ );
1173
+ watch([repoId, prdSlug], loadData);
1174
+ async function handleTaskClick(task) {
1175
+ await openTaskDetail(task, prdSlug.value);
1176
+ }
1177
+ async function handleGraphTaskClick(payload) {
1178
+ const sourceTasks = await getTasksForPrd(payload.prdSlug);
1179
+ const task = sourceTasks?.tasks.find((entry) => entry.id === payload.taskId);
1180
+ if (!task) {
1181
+ showError("Task unavailable", `Could not find ${payload.taskId} in ${payload.prdSlug}.`);
1182
+ return;
1183
+ }
1184
+ await openTaskDetail(task, payload.prdSlug);
1185
+ }
1186
+ return (_ctx, _push, _parent, _attrs) => {
1187
+ const _component_NuxtLink = __nuxt_component_0$2;
1188
+ const _component_PrdMeta = __nuxt_component_1;
1189
+ const _component_PrdViewer = __nuxt_component_2;
1190
+ const _component_TasksBoard = __nuxt_component_3;
1191
+ const _component_GraphExplorer = __nuxt_component_0$2$1;
1192
+ const _component_TasksDetail = __nuxt_component_1$1;
1193
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "h-full p-4 md:p-6" }, _attrs))}>`);
1194
+ if (unref(isLoading)) {
1195
+ _push(`<div class="flex h-full items-center justify-center"><div class="flex flex-col items-center gap-4">`);
1196
+ _push(ssrRenderComponent(unref(Loader2), { class: "size-8 animate-spin text-primary" }, null, _parent));
1197
+ _push(`<p class="text-sm text-muted-foreground">Loading PRD...</p></div></div>`);
1198
+ } else if (unref(error)) {
1199
+ _push(`<div class="flex h-full items-center justify-center"><div class="flex max-w-md flex-col items-center gap-4 text-center">`);
1200
+ _push(ssrRenderComponent(unref(AlertCircle), { class: "size-12 text-destructive" }, null, _parent));
1201
+ _push(`<h2 class="text-lg font-semibold">Error Loading PRD</h2><p class="text-sm text-muted-foreground">${ssrInterpolate(unref(error))}</p><div class="flex gap-3">`);
1202
+ _push(ssrRenderComponent(unref(Button), {
1203
+ variant: "outline",
1204
+ size: "sm",
1205
+ onClick: loadData
1206
+ }, {
1207
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
1208
+ if (_push2) {
1209
+ _push2(ssrRenderComponent(unref(RefreshCw), { class: "mr-2 size-4" }, null, _parent2, _scopeId));
1210
+ _push2(` Retry `);
1211
+ } else {
1212
+ return [
1213
+ createVNode(unref(RefreshCw), { class: "mr-2 size-4" }),
1214
+ createTextVNode(" Retry ")
1215
+ ];
1216
+ }
1217
+ }),
1218
+ _: 1
1219
+ }, _parent));
1220
+ _push(ssrRenderComponent(_component_NuxtLink, { to: "/" }, {
1221
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
1222
+ if (_push2) {
1223
+ _push2(ssrRenderComponent(unref(Button), {
1224
+ variant: "ghost",
1225
+ size: "sm"
1226
+ }, {
1227
+ default: withCtx((_2, _push3, _parent3, _scopeId2) => {
1228
+ if (_push3) {
1229
+ _push3(` Go back home `);
1230
+ } else {
1231
+ return [
1232
+ createTextVNode(" Go back home ")
1233
+ ];
1234
+ }
1235
+ }),
1236
+ _: 1
1237
+ }, _parent2, _scopeId));
1238
+ } else {
1239
+ return [
1240
+ createVNode(unref(Button), {
1241
+ variant: "ghost",
1242
+ size: "sm"
1243
+ }, {
1244
+ default: withCtx(() => [
1245
+ createTextVNode(" Go back home ")
1246
+ ]),
1247
+ _: 1
1248
+ })
1249
+ ];
1250
+ }
1251
+ }),
1252
+ _: 1
1253
+ }, _parent));
1254
+ _push(`</div></div></div>`);
1255
+ } else if (unref(document)) {
1256
+ _push(`<div class="mx-auto max-w-6xl space-y-6"><div class="space-y-2"><h1 class="text-2xl font-bold tracking-tight">${ssrInterpolate(unref(document).name)}</h1>`);
1257
+ _push(ssrRenderComponent(_component_PrdMeta, {
1258
+ metadata: unref(document).metadata
1259
+ }, null, _parent));
1260
+ _push(`</div>`);
1261
+ _push(ssrRenderComponent(unref(Tabs), {
1262
+ modelValue: unref(activeTab),
1263
+ "onUpdate:modelValue": ($event) => isRef(activeTab) ? activeTab.value = $event : null,
1264
+ class: "w-full"
1265
+ }, {
1266
+ default: withCtx((_, _push2, _parent2, _scopeId) => {
1267
+ if (_push2) {
1268
+ _push2(ssrRenderComponent(unref(TabsList), null, {
1269
+ default: withCtx((_2, _push3, _parent3, _scopeId2) => {
1270
+ if (_push3) {
1271
+ _push3(ssrRenderComponent(unref(TabsTrigger), {
1272
+ value: "document",
1273
+ class: "gap-2"
1274
+ }, {
1275
+ default: withCtx((_3, _push4, _parent4, _scopeId3) => {
1276
+ if (_push4) {
1277
+ _push4(ssrRenderComponent(unref(FileText), { class: "size-4" }, null, _parent4, _scopeId3));
1278
+ _push4(` Document `);
1279
+ } else {
1280
+ return [
1281
+ createVNode(unref(FileText), { class: "size-4" }),
1282
+ createTextVNode(" Document ")
1283
+ ];
1284
+ }
1285
+ }),
1286
+ _: 1
1287
+ }, _parent3, _scopeId2));
1288
+ _push3(ssrRenderComponent(unref(TabsTrigger), {
1289
+ value: "board",
1290
+ class: "gap-2",
1291
+ disabled: !unref(tasksFile)
1292
+ }, {
1293
+ default: withCtx((_3, _push4, _parent4, _scopeId3) => {
1294
+ if (_push4) {
1295
+ _push4(ssrRenderComponent(unref(LayoutGrid), { class: "size-4" }, null, _parent4, _scopeId3));
1296
+ _push4(` Task Board `);
1297
+ if (unref(tasksFile)) {
1298
+ _push4(`<span class="text-xs text-muted-foreground"${_scopeId3}> (${ssrInterpolate(unref(tasksFile).tasks.length)}) </span>`);
1299
+ } else {
1300
+ _push4(`<!---->`);
1301
+ }
1302
+ } else {
1303
+ return [
1304
+ createVNode(unref(LayoutGrid), { class: "size-4" }),
1305
+ createTextVNode(" Task Board "),
1306
+ unref(tasksFile) ? (openBlock(), createBlock("span", {
1307
+ key: 0,
1308
+ class: "text-xs text-muted-foreground"
1309
+ }, " (" + toDisplayString(unref(tasksFile).tasks.length) + ") ", 1)) : createCommentVNode("", true)
1310
+ ];
1311
+ }
1312
+ }),
1313
+ _: 1
1314
+ }, _parent3, _scopeId2));
1315
+ _push3(ssrRenderComponent(unref(TabsTrigger), {
1316
+ value: "graph",
1317
+ class: "gap-2"
1318
+ }, {
1319
+ default: withCtx((_3, _push4, _parent4, _scopeId3) => {
1320
+ if (_push4) {
1321
+ _push4(ssrRenderComponent(unref(GitBranch), { class: "size-4" }, null, _parent4, _scopeId3));
1322
+ _push4(` Graph `);
1323
+ } else {
1324
+ return [
1325
+ createVNode(unref(GitBranch), { class: "size-4" }),
1326
+ createTextVNode(" Graph ")
1327
+ ];
1328
+ }
1329
+ }),
1330
+ _: 1
1331
+ }, _parent3, _scopeId2));
1332
+ } else {
1333
+ return [
1334
+ createVNode(unref(TabsTrigger), {
1335
+ value: "document",
1336
+ class: "gap-2"
1337
+ }, {
1338
+ default: withCtx(() => [
1339
+ createVNode(unref(FileText), { class: "size-4" }),
1340
+ createTextVNode(" Document ")
1341
+ ]),
1342
+ _: 1
1343
+ }),
1344
+ createVNode(unref(TabsTrigger), {
1345
+ value: "board",
1346
+ class: "gap-2",
1347
+ disabled: !unref(tasksFile)
1348
+ }, {
1349
+ default: withCtx(() => [
1350
+ createVNode(unref(LayoutGrid), { class: "size-4" }),
1351
+ createTextVNode(" Task Board "),
1352
+ unref(tasksFile) ? (openBlock(), createBlock("span", {
1353
+ key: 0,
1354
+ class: "text-xs text-muted-foreground"
1355
+ }, " (" + toDisplayString(unref(tasksFile).tasks.length) + ") ", 1)) : createCommentVNode("", true)
1356
+ ]),
1357
+ _: 1
1358
+ }, 8, ["disabled"]),
1359
+ createVNode(unref(TabsTrigger), {
1360
+ value: "graph",
1361
+ class: "gap-2"
1362
+ }, {
1363
+ default: withCtx(() => [
1364
+ createVNode(unref(GitBranch), { class: "size-4" }),
1365
+ createTextVNode(" Graph ")
1366
+ ]),
1367
+ _: 1
1368
+ })
1369
+ ];
1370
+ }
1371
+ }),
1372
+ _: 1
1373
+ }, _parent2, _scopeId));
1374
+ _push2(ssrRenderComponent(unref(TabsContent), {
1375
+ value: "document",
1376
+ class: "mt-4"
1377
+ }, {
1378
+ default: withCtx((_2, _push3, _parent3, _scopeId2) => {
1379
+ if (_push3) {
1380
+ _push3(`<div class="rounded-lg border border-border bg-card p-4 md:p-6"${_scopeId2}>`);
1381
+ _push3(ssrRenderComponent(_component_PrdViewer, {
1382
+ content: unref(document).content
1383
+ }, null, _parent3, _scopeId2));
1384
+ _push3(`</div>`);
1385
+ } else {
1386
+ return [
1387
+ createVNode("div", { class: "rounded-lg border border-border bg-card p-4 md:p-6" }, [
1388
+ createVNode(_component_PrdViewer, {
1389
+ content: unref(document).content
1390
+ }, null, 8, ["content"])
1391
+ ])
1392
+ ];
1393
+ }
1394
+ }),
1395
+ _: 1
1396
+ }, _parent2, _scopeId));
1397
+ _push2(ssrRenderComponent(unref(TabsContent), {
1398
+ value: "board",
1399
+ class: "mt-4"
1400
+ }, {
1401
+ default: withCtx((_2, _push3, _parent3, _scopeId2) => {
1402
+ if (_push3) {
1403
+ if (unref(tasksFile)) {
1404
+ _push3(`<div class="h-[calc(100vh-280px)] min-h-[400px]"${_scopeId2}>`);
1405
+ _push3(ssrRenderComponent(_component_TasksBoard, {
1406
+ tasks: unref(tasksFile).tasks,
1407
+ onTaskClick: handleTaskClick
1408
+ }, null, _parent3, _scopeId2));
1409
+ _push3(`</div>`);
1410
+ } else {
1411
+ _push3(`<div class="py-12 text-center"${_scopeId2}>`);
1412
+ _push3(ssrRenderComponent(unref(LayoutGrid), { class: "mx-auto size-12 text-muted-foreground/50" }, null, _parent3, _scopeId2));
1413
+ _push3(`<p class="mt-4 text-muted-foreground"${_scopeId2}> No tasks found for this PRD </p><p class="mt-1 text-sm text-muted-foreground/70"${_scopeId2}> Task state has not been generated for this PRD yet. </p></div>`);
1414
+ }
1415
+ } else {
1416
+ return [
1417
+ unref(tasksFile) ? (openBlock(), createBlock("div", {
1418
+ key: 0,
1419
+ class: "h-[calc(100vh-280px)] min-h-[400px]"
1420
+ }, [
1421
+ createVNode(_component_TasksBoard, {
1422
+ tasks: unref(tasksFile).tasks,
1423
+ onTaskClick: handleTaskClick
1424
+ }, null, 8, ["tasks"])
1425
+ ])) : (openBlock(), createBlock("div", {
1426
+ key: 1,
1427
+ class: "py-12 text-center"
1428
+ }, [
1429
+ createVNode(unref(LayoutGrid), { class: "mx-auto size-12 text-muted-foreground/50" }),
1430
+ createVNode("p", { class: "mt-4 text-muted-foreground" }, " No tasks found for this PRD "),
1431
+ createVNode("p", { class: "mt-1 text-sm text-muted-foreground/70" }, " Task state has not been generated for this PRD yet. ")
1432
+ ]))
1433
+ ];
1434
+ }
1435
+ }),
1436
+ _: 1
1437
+ }, _parent2, _scopeId));
1438
+ _push2(ssrRenderComponent(unref(TabsContent), {
1439
+ value: "graph",
1440
+ class: "mt-4"
1441
+ }, {
1442
+ default: withCtx((_2, _push3, _parent3, _scopeId2) => {
1443
+ if (_push3) {
1444
+ _push3(`<div class="h-[calc(100vh-300px)] min-h-[440px] motion-safe:transition-[opacity,transform] motion-safe:duration-200 motion-safe:ease-[var(--ease-out-cubic)] motion-reduce:transition-none"${_scopeId2}>`);
1445
+ _push3(ssrRenderComponent(_component_GraphExplorer, {
1446
+ payload: unref(prdGraph),
1447
+ scope: "prd",
1448
+ loading: unref(graphLoading),
1449
+ error: unref(graphError),
1450
+ onTaskClick: handleGraphTaskClick
1451
+ }, null, _parent3, _scopeId2));
1452
+ _push3(`</div>`);
1453
+ } else {
1454
+ return [
1455
+ createVNode("div", { class: "h-[calc(100vh-300px)] min-h-[440px] motion-safe:transition-[opacity,transform] motion-safe:duration-200 motion-safe:ease-[var(--ease-out-cubic)] motion-reduce:transition-none" }, [
1456
+ createVNode(_component_GraphExplorer, {
1457
+ payload: unref(prdGraph),
1458
+ scope: "prd",
1459
+ loading: unref(graphLoading),
1460
+ error: unref(graphError),
1461
+ onTaskClick: handleGraphTaskClick
1462
+ }, null, 8, ["payload", "loading", "error"])
1463
+ ])
1464
+ ];
1465
+ }
1466
+ }),
1467
+ _: 1
1468
+ }, _parent2, _scopeId));
1469
+ } else {
1470
+ return [
1471
+ createVNode(unref(TabsList), null, {
1472
+ default: withCtx(() => [
1473
+ createVNode(unref(TabsTrigger), {
1474
+ value: "document",
1475
+ class: "gap-2"
1476
+ }, {
1477
+ default: withCtx(() => [
1478
+ createVNode(unref(FileText), { class: "size-4" }),
1479
+ createTextVNode(" Document ")
1480
+ ]),
1481
+ _: 1
1482
+ }),
1483
+ createVNode(unref(TabsTrigger), {
1484
+ value: "board",
1485
+ class: "gap-2",
1486
+ disabled: !unref(tasksFile)
1487
+ }, {
1488
+ default: withCtx(() => [
1489
+ createVNode(unref(LayoutGrid), { class: "size-4" }),
1490
+ createTextVNode(" Task Board "),
1491
+ unref(tasksFile) ? (openBlock(), createBlock("span", {
1492
+ key: 0,
1493
+ class: "text-xs text-muted-foreground"
1494
+ }, " (" + toDisplayString(unref(tasksFile).tasks.length) + ") ", 1)) : createCommentVNode("", true)
1495
+ ]),
1496
+ _: 1
1497
+ }, 8, ["disabled"]),
1498
+ createVNode(unref(TabsTrigger), {
1499
+ value: "graph",
1500
+ class: "gap-2"
1501
+ }, {
1502
+ default: withCtx(() => [
1503
+ createVNode(unref(GitBranch), { class: "size-4" }),
1504
+ createTextVNode(" Graph ")
1505
+ ]),
1506
+ _: 1
1507
+ })
1508
+ ]),
1509
+ _: 1
1510
+ }),
1511
+ createVNode(unref(TabsContent), {
1512
+ value: "document",
1513
+ class: "mt-4"
1514
+ }, {
1515
+ default: withCtx(() => [
1516
+ createVNode("div", { class: "rounded-lg border border-border bg-card p-4 md:p-6" }, [
1517
+ createVNode(_component_PrdViewer, {
1518
+ content: unref(document).content
1519
+ }, null, 8, ["content"])
1520
+ ])
1521
+ ]),
1522
+ _: 1
1523
+ }),
1524
+ createVNode(unref(TabsContent), {
1525
+ value: "board",
1526
+ class: "mt-4"
1527
+ }, {
1528
+ default: withCtx(() => [
1529
+ unref(tasksFile) ? (openBlock(), createBlock("div", {
1530
+ key: 0,
1531
+ class: "h-[calc(100vh-280px)] min-h-[400px]"
1532
+ }, [
1533
+ createVNode(_component_TasksBoard, {
1534
+ tasks: unref(tasksFile).tasks,
1535
+ onTaskClick: handleTaskClick
1536
+ }, null, 8, ["tasks"])
1537
+ ])) : (openBlock(), createBlock("div", {
1538
+ key: 1,
1539
+ class: "py-12 text-center"
1540
+ }, [
1541
+ createVNode(unref(LayoutGrid), { class: "mx-auto size-12 text-muted-foreground/50" }),
1542
+ createVNode("p", { class: "mt-4 text-muted-foreground" }, " No tasks found for this PRD "),
1543
+ createVNode("p", { class: "mt-1 text-sm text-muted-foreground/70" }, " Task state has not been generated for this PRD yet. ")
1544
+ ]))
1545
+ ]),
1546
+ _: 1
1547
+ }),
1548
+ createVNode(unref(TabsContent), {
1549
+ value: "graph",
1550
+ class: "mt-4"
1551
+ }, {
1552
+ default: withCtx(() => [
1553
+ createVNode("div", { class: "h-[calc(100vh-300px)] min-h-[440px] motion-safe:transition-[opacity,transform] motion-safe:duration-200 motion-safe:ease-[var(--ease-out-cubic)] motion-reduce:transition-none" }, [
1554
+ createVNode(_component_GraphExplorer, {
1555
+ payload: unref(prdGraph),
1556
+ scope: "prd",
1557
+ loading: unref(graphLoading),
1558
+ error: unref(graphError),
1559
+ onTaskClick: handleGraphTaskClick
1560
+ }, null, 8, ["payload", "loading", "error"])
1561
+ ])
1562
+ ]),
1563
+ _: 1
1564
+ })
1565
+ ];
1566
+ }
1567
+ }),
1568
+ _: 1
1569
+ }, _parent));
1570
+ _push(`</div>`);
1571
+ } else {
1572
+ _push(`<!---->`);
1573
+ }
1574
+ _push(ssrRenderComponent(_component_TasksDetail, {
1575
+ open: unref(detailOpen),
1576
+ "onUpdate:open": ($event) => isRef(detailOpen) ? detailOpen.value = $event : null,
1577
+ task: unref(selectedTask),
1578
+ "task-titles": unref(taskTitles),
1579
+ commits: unref(selectedTaskCommits),
1580
+ "repo-id": unref(repoId),
1581
+ "task-prd-slug": unref(selectedTaskPrdSlug),
1582
+ "current-prd-slug": unref(prdSlug)
1583
+ }, null, _parent));
1584
+ _push(`</div>`);
1585
+ };
1586
+ }
1587
+ });
1588
+ const _sfc_setup = _sfc_main.setup;
1589
+ _sfc_main.setup = (props, ctx) => {
1590
+ const ssrContext = useSSRContext();
1591
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/[repo]/[prd].vue");
1592
+ return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
1593
+ };
1594
+
1595
+ export { _sfc_main as default };
1596
+ //# sourceMappingURL=_prd_-C1C4GAhW.mjs.map