@industry-theme/backlogmd-kanban-panel 0.1.0
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/README.md +184 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/mocks/panelContext.d.ts +24 -0
- package/dist/mocks/panelContext.d.ts.map +1 -0
- package/dist/panels/KanbanPanel.d.ts +13 -0
- package/dist/panels/KanbanPanel.d.ts.map +1 -0
- package/dist/panels/KanbanPanel.stories.d.ts +15 -0
- package/dist/panels/KanbanPanel.stories.d.ts.map +1 -0
- package/dist/panels/kanban/backlog-types/index.d.ts +196 -0
- package/dist/panels/kanban/backlog-types/index.d.ts.map +1 -0
- package/dist/panels/kanban/backlog-utils/board.d.ts +13 -0
- package/dist/panels/kanban/backlog-utils/board.d.ts.map +1 -0
- package/dist/panels/kanban/components/KanbanColumn.d.ts +10 -0
- package/dist/panels/kanban/components/KanbanColumn.d.ts.map +1 -0
- package/dist/panels/kanban/hooks/useKanbanData.d.ts +16 -0
- package/dist/panels/kanban/hooks/useKanbanData.d.ts.map +1 -0
- package/dist/panels/kanban/mocks/mockData.d.ts +32 -0
- package/dist/panels/kanban/mocks/mockData.d.ts.map +1 -0
- package/dist/panels.bundle.js +939 -0
- package/dist/panels.bundle.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import React2, { forwardRef, createElement, createContext, useState, useEffect, useContext, useMemo, useCallback } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* @license lucide-react v0.552.0 - ISC
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the ISC license.
|
|
7
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
10
|
+
const toCamelCase = (string) => string.replace(
|
|
11
|
+
/^([A-Z])|[\s-_]+(\w)/g,
|
|
12
|
+
(match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()
|
|
13
|
+
);
|
|
14
|
+
const toPascalCase = (string) => {
|
|
15
|
+
const camelCase = toCamelCase(string);
|
|
16
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
17
|
+
};
|
|
18
|
+
const mergeClasses = (...classes) => classes.filter((className, index, array) => {
|
|
19
|
+
return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
|
|
20
|
+
}).join(" ").trim();
|
|
21
|
+
const hasA11yProp = (props) => {
|
|
22
|
+
for (const prop in props) {
|
|
23
|
+
if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @license lucide-react v0.552.0 - ISC
|
|
30
|
+
*
|
|
31
|
+
* This source code is licensed under the ISC license.
|
|
32
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
33
|
+
*/
|
|
34
|
+
var defaultAttributes = {
|
|
35
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
36
|
+
width: 24,
|
|
37
|
+
height: 24,
|
|
38
|
+
viewBox: "0 0 24 24",
|
|
39
|
+
fill: "none",
|
|
40
|
+
stroke: "currentColor",
|
|
41
|
+
strokeWidth: 2,
|
|
42
|
+
strokeLinecap: "round",
|
|
43
|
+
strokeLinejoin: "round"
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* @license lucide-react v0.552.0 - ISC
|
|
47
|
+
*
|
|
48
|
+
* This source code is licensed under the ISC license.
|
|
49
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
50
|
+
*/
|
|
51
|
+
const Icon = forwardRef(
|
|
52
|
+
({
|
|
53
|
+
color = "currentColor",
|
|
54
|
+
size = 24,
|
|
55
|
+
strokeWidth = 2,
|
|
56
|
+
absoluteStrokeWidth,
|
|
57
|
+
className = "",
|
|
58
|
+
children,
|
|
59
|
+
iconNode,
|
|
60
|
+
...rest
|
|
61
|
+
}, ref) => createElement(
|
|
62
|
+
"svg",
|
|
63
|
+
{
|
|
64
|
+
ref,
|
|
65
|
+
...defaultAttributes,
|
|
66
|
+
width: size,
|
|
67
|
+
height: size,
|
|
68
|
+
stroke: color,
|
|
69
|
+
strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
|
|
70
|
+
className: mergeClasses("lucide", className),
|
|
71
|
+
...!children && !hasA11yProp(rest) && { "aria-hidden": "true" },
|
|
72
|
+
...rest
|
|
73
|
+
},
|
|
74
|
+
[
|
|
75
|
+
...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
|
|
76
|
+
...Array.isArray(children) ? children : [children]
|
|
77
|
+
]
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
/**
|
|
81
|
+
* @license lucide-react v0.552.0 - ISC
|
|
82
|
+
*
|
|
83
|
+
* This source code is licensed under the ISC license.
|
|
84
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
85
|
+
*/
|
|
86
|
+
const createLucideIcon = (iconName, iconNode) => {
|
|
87
|
+
const Component = forwardRef(
|
|
88
|
+
({ className, ...props }, ref) => createElement(Icon, {
|
|
89
|
+
ref,
|
|
90
|
+
iconNode,
|
|
91
|
+
className: mergeClasses(
|
|
92
|
+
`lucide-${toKebabCase(toPascalCase(iconName))}`,
|
|
93
|
+
`lucide-${iconName}`,
|
|
94
|
+
className
|
|
95
|
+
),
|
|
96
|
+
...props
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
Component.displayName = toPascalCase(iconName);
|
|
100
|
+
return Component;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* @license lucide-react v0.552.0 - ISC
|
|
104
|
+
*
|
|
105
|
+
* This source code is licensed under the ISC license.
|
|
106
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
107
|
+
*/
|
|
108
|
+
const __iconNode$2 = [
|
|
109
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
110
|
+
["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
|
|
111
|
+
["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
|
|
112
|
+
];
|
|
113
|
+
const CircleAlert = createLucideIcon("circle-alert", __iconNode$2);
|
|
114
|
+
/**
|
|
115
|
+
* @license lucide-react v0.552.0 - ISC
|
|
116
|
+
*
|
|
117
|
+
* This source code is licensed under the ISC license.
|
|
118
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
119
|
+
*/
|
|
120
|
+
const __iconNode$1 = [
|
|
121
|
+
["path", { d: "M5 3v14", key: "9nsxs2" }],
|
|
122
|
+
["path", { d: "M12 3v8", key: "1h2ygw" }],
|
|
123
|
+
["path", { d: "M19 3v18", key: "1sk56x" }]
|
|
124
|
+
];
|
|
125
|
+
const Kanban = createLucideIcon("kanban", __iconNode$1);
|
|
126
|
+
/**
|
|
127
|
+
* @license lucide-react v0.552.0 - ISC
|
|
128
|
+
*
|
|
129
|
+
* This source code is licensed under the ISC license.
|
|
130
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
131
|
+
*/
|
|
132
|
+
const __iconNode = [
|
|
133
|
+
["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
|
|
134
|
+
["path", { d: "M21 3v5h-5", key: "1q7to0" }],
|
|
135
|
+
["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
|
|
136
|
+
["path", { d: "M8 16H3v5", key: "1cv678" }]
|
|
137
|
+
];
|
|
138
|
+
const RefreshCw = createLucideIcon("refresh-cw", __iconNode);
|
|
139
|
+
var terminalTheme = {
|
|
140
|
+
space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
|
|
141
|
+
fonts: {
|
|
142
|
+
body: '"SF Mono", "Monaco", "Inconsolata", "Fira Code", monospace',
|
|
143
|
+
heading: '"SF Mono", "Monaco", "Inconsolata", "Fira Code", monospace',
|
|
144
|
+
monospace: '"SF Mono", "Monaco", "Inconsolata", "Fira Code", monospace'
|
|
145
|
+
},
|
|
146
|
+
fontSizes: [12, 14, 16, 18, 20, 24, 32, 48, 64, 96],
|
|
147
|
+
fontScale: 1,
|
|
148
|
+
fontWeights: {
|
|
149
|
+
body: 400,
|
|
150
|
+
heading: 500,
|
|
151
|
+
bold: 600,
|
|
152
|
+
light: 300,
|
|
153
|
+
medium: 500,
|
|
154
|
+
semibold: 600
|
|
155
|
+
},
|
|
156
|
+
lineHeights: {
|
|
157
|
+
body: 1.6,
|
|
158
|
+
heading: 1.3,
|
|
159
|
+
tight: 1.4,
|
|
160
|
+
relaxed: 1.8
|
|
161
|
+
},
|
|
162
|
+
breakpoints: ["640px", "768px", "1024px", "1280px"],
|
|
163
|
+
sizes: [16, 32, 64, 128, 256, 512, 768, 1024, 1536],
|
|
164
|
+
radii: [0, 2, 4, 6, 8, 12, 16, 24],
|
|
165
|
+
shadows: [
|
|
166
|
+
"none",
|
|
167
|
+
"0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
|
168
|
+
"0 2px 4px 0 rgba(0, 0, 0, 0.06)",
|
|
169
|
+
"0 4px 6px 0 rgba(0, 0, 0, 0.07)",
|
|
170
|
+
"0 8px 12px 0 rgba(0, 0, 0, 0.08)",
|
|
171
|
+
"0 16px 24px 0 rgba(0, 0, 0, 0.10)"
|
|
172
|
+
],
|
|
173
|
+
zIndices: [0, 1, 10, 20, 30, 40, 50],
|
|
174
|
+
colors: {
|
|
175
|
+
text: "#e4e4e4",
|
|
176
|
+
background: "rgba(10, 10, 10, 0.85)",
|
|
177
|
+
primary: "#66b3ff",
|
|
178
|
+
secondary: "#80c4ff",
|
|
179
|
+
accent: "#66ff99",
|
|
180
|
+
highlight: "rgba(102, 179, 255, 0.15)",
|
|
181
|
+
muted: "rgba(26, 26, 26, 0.8)",
|
|
182
|
+
success: "#66ff99",
|
|
183
|
+
warning: "#ffcc66",
|
|
184
|
+
error: "#ff6666",
|
|
185
|
+
info: "#66b3ff",
|
|
186
|
+
border: "rgba(255, 255, 255, 0.1)",
|
|
187
|
+
backgroundSecondary: "rgba(15, 15, 15, 0.9)",
|
|
188
|
+
backgroundTertiary: "rgba(20, 20, 20, 0.9)",
|
|
189
|
+
backgroundLight: "rgba(255, 255, 255, 0.05)",
|
|
190
|
+
backgroundHover: "rgba(102, 179, 255, 0.08)",
|
|
191
|
+
surface: "rgba(15, 15, 15, 0.95)",
|
|
192
|
+
textSecondary: "rgba(255, 255, 255, 0.7)",
|
|
193
|
+
textTertiary: "rgba(255, 255, 255, 0.5)",
|
|
194
|
+
textMuted: "rgba(255, 255, 255, 0.4)",
|
|
195
|
+
highlightBg: "rgba(255, 235, 59, 0.25)",
|
|
196
|
+
highlightBorder: "rgba(255, 235, 59, 0.5)"
|
|
197
|
+
},
|
|
198
|
+
modes: {
|
|
199
|
+
light: {
|
|
200
|
+
text: "#1a1a1a",
|
|
201
|
+
background: "rgba(255, 255, 255, 0.9)",
|
|
202
|
+
primary: "#0066cc",
|
|
203
|
+
secondary: "#0052a3",
|
|
204
|
+
accent: "#00cc88",
|
|
205
|
+
highlight: "rgba(0, 102, 204, 0.08)",
|
|
206
|
+
muted: "rgba(245, 245, 245, 0.8)",
|
|
207
|
+
success: "#00cc88",
|
|
208
|
+
warning: "#ffaa00",
|
|
209
|
+
error: "#ff3333",
|
|
210
|
+
info: "#0066cc",
|
|
211
|
+
border: "rgba(0, 0, 0, 0.1)",
|
|
212
|
+
backgroundSecondary: "rgba(250, 250, 250, 0.9)",
|
|
213
|
+
backgroundTertiary: "rgba(245, 245, 245, 0.9)",
|
|
214
|
+
backgroundLight: "rgba(0, 0, 0, 0.02)",
|
|
215
|
+
backgroundHover: "rgba(0, 102, 204, 0.04)",
|
|
216
|
+
surface: "rgba(255, 255, 255, 0.95)",
|
|
217
|
+
textSecondary: "rgba(0, 0, 0, 0.6)",
|
|
218
|
+
textTertiary: "rgba(0, 0, 0, 0.4)",
|
|
219
|
+
textMuted: "rgba(0, 0, 0, 0.3)",
|
|
220
|
+
highlightBg: "rgba(255, 235, 59, 0.3)",
|
|
221
|
+
highlightBorder: "rgba(255, 235, 59, 0.6)"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
buttons: {
|
|
225
|
+
primary: {
|
|
226
|
+
color: "white",
|
|
227
|
+
bg: "primary",
|
|
228
|
+
borderWidth: 0,
|
|
229
|
+
"&:hover": {
|
|
230
|
+
bg: "secondary"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
secondary: {
|
|
234
|
+
color: "primary",
|
|
235
|
+
bg: "transparent",
|
|
236
|
+
borderWidth: 1,
|
|
237
|
+
borderStyle: "solid",
|
|
238
|
+
borderColor: "primary",
|
|
239
|
+
"&:hover": {
|
|
240
|
+
bg: "highlight"
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
ghost: {
|
|
244
|
+
color: "text",
|
|
245
|
+
bg: "transparent",
|
|
246
|
+
"&:hover": {
|
|
247
|
+
bg: "backgroundHover"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
text: {
|
|
252
|
+
heading: {
|
|
253
|
+
fontFamily: "heading",
|
|
254
|
+
fontWeight: "heading",
|
|
255
|
+
lineHeight: "heading"
|
|
256
|
+
},
|
|
257
|
+
body: {
|
|
258
|
+
fontFamily: "body",
|
|
259
|
+
fontWeight: "body",
|
|
260
|
+
lineHeight: "body"
|
|
261
|
+
},
|
|
262
|
+
caption: {
|
|
263
|
+
fontSize: 1,
|
|
264
|
+
color: "textSecondary"
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
cards: {
|
|
268
|
+
primary: {
|
|
269
|
+
bg: "surface",
|
|
270
|
+
border: "1px solid",
|
|
271
|
+
borderColor: "border",
|
|
272
|
+
borderRadius: 1
|
|
273
|
+
},
|
|
274
|
+
secondary: {
|
|
275
|
+
bg: "backgroundSecondary",
|
|
276
|
+
border: "1px solid",
|
|
277
|
+
borderColor: "border",
|
|
278
|
+
borderRadius: 1
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
function getMode(theme2, mode) {
|
|
283
|
+
if (!mode || !theme2.modes || !theme2.modes[mode]) {
|
|
284
|
+
return theme2.colors;
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
...theme2.colors,
|
|
288
|
+
...theme2.modes[mode]
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
var ThemeContext;
|
|
292
|
+
var getThemeContext = () => {
|
|
293
|
+
if (typeof window !== "undefined") {
|
|
294
|
+
const globalWindow = window;
|
|
295
|
+
if (!globalWindow.__principlemd_theme_context__) {
|
|
296
|
+
globalWindow.__principlemd_theme_context__ = createContext(void 0);
|
|
297
|
+
}
|
|
298
|
+
return globalWindow.__principlemd_theme_context__;
|
|
299
|
+
} else {
|
|
300
|
+
if (!ThemeContext) {
|
|
301
|
+
ThemeContext = createContext(void 0);
|
|
302
|
+
}
|
|
303
|
+
return ThemeContext;
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
var ThemeContextSingleton = getThemeContext();
|
|
307
|
+
var useTheme = () => {
|
|
308
|
+
const context = useContext(ThemeContextSingleton);
|
|
309
|
+
if (!context) {
|
|
310
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
311
|
+
}
|
|
312
|
+
return context;
|
|
313
|
+
};
|
|
314
|
+
var ThemeProvider = ({
|
|
315
|
+
children,
|
|
316
|
+
theme: customTheme = theme,
|
|
317
|
+
initialMode
|
|
318
|
+
}) => {
|
|
319
|
+
const [mode, setMode] = useState(initialMode);
|
|
320
|
+
const activeTheme = React2.useMemo(() => {
|
|
321
|
+
if (!mode || !customTheme.modes || !customTheme.modes[mode]) {
|
|
322
|
+
return customTheme;
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
...customTheme,
|
|
326
|
+
colors: getMode(customTheme, mode)
|
|
327
|
+
};
|
|
328
|
+
}, [customTheme, mode]);
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
if (!initialMode) {
|
|
331
|
+
const savedMode = localStorage.getItem("principlemd-theme-mode");
|
|
332
|
+
if (savedMode) {
|
|
333
|
+
setMode(savedMode);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}, [initialMode]);
|
|
337
|
+
useEffect(() => {
|
|
338
|
+
if (mode) {
|
|
339
|
+
localStorage.setItem("principlemd-theme-mode", mode);
|
|
340
|
+
} else {
|
|
341
|
+
localStorage.removeItem("principlemd-theme-mode");
|
|
342
|
+
}
|
|
343
|
+
}, [mode]);
|
|
344
|
+
const value = {
|
|
345
|
+
theme: activeTheme,
|
|
346
|
+
mode,
|
|
347
|
+
setMode
|
|
348
|
+
};
|
|
349
|
+
return /* @__PURE__ */ React2.createElement(ThemeContextSingleton.Provider, {
|
|
350
|
+
value
|
|
351
|
+
}, children);
|
|
352
|
+
};
|
|
353
|
+
var theme = terminalTheme;
|
|
354
|
+
function generateMockTasks() {
|
|
355
|
+
return [
|
|
356
|
+
{
|
|
357
|
+
id: "task-001",
|
|
358
|
+
title: "Implement user authentication",
|
|
359
|
+
status: "To Do",
|
|
360
|
+
assignee: ["alice@example.com"],
|
|
361
|
+
createdDate: "2025-11-01T10:00:00Z",
|
|
362
|
+
updatedDate: "2025-11-15T14:30:00Z",
|
|
363
|
+
labels: ["feature", "security"],
|
|
364
|
+
dependencies: [],
|
|
365
|
+
description: "Add OAuth2 authentication flow with support for multiple providers (Google, GitHub). Include session management and token refresh logic.",
|
|
366
|
+
priority: "high",
|
|
367
|
+
ordinal: 1,
|
|
368
|
+
filePath: "backlog/task-001.md",
|
|
369
|
+
source: "local"
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
id: "task-002",
|
|
373
|
+
title: "Design database schema",
|
|
374
|
+
status: "To Do",
|
|
375
|
+
assignee: ["bob@example.com"],
|
|
376
|
+
createdDate: "2025-11-02T09:15:00Z",
|
|
377
|
+
labels: ["database", "architecture"],
|
|
378
|
+
dependencies: [],
|
|
379
|
+
description: "Create normalized database schema for user data, tasks, and relationships. Include migration scripts.",
|
|
380
|
+
priority: "high",
|
|
381
|
+
ordinal: 2,
|
|
382
|
+
filePath: "backlog/task-002.md",
|
|
383
|
+
source: "local"
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
id: "task-003",
|
|
387
|
+
title: "Build REST API endpoints",
|
|
388
|
+
status: "In Progress",
|
|
389
|
+
assignee: ["charlie@example.com"],
|
|
390
|
+
createdDate: "2025-11-03T11:20:00Z",
|
|
391
|
+
updatedDate: "2025-11-16T09:00:00Z",
|
|
392
|
+
labels: ["backend", "api"],
|
|
393
|
+
dependencies: ["task-002"],
|
|
394
|
+
description: "Implement RESTful API endpoints for CRUD operations. Include validation, error handling, and rate limiting.",
|
|
395
|
+
implementationPlan: `
|
|
396
|
+
## Implementation Steps
|
|
397
|
+
1. Set up Express/Fastify server
|
|
398
|
+
2. Define API routes and handlers
|
|
399
|
+
3. Add request validation middleware
|
|
400
|
+
4. Implement error handling
|
|
401
|
+
5. Add rate limiting
|
|
402
|
+
6. Write API documentation
|
|
403
|
+
`.trim(),
|
|
404
|
+
priority: "high",
|
|
405
|
+
ordinal: 1,
|
|
406
|
+
filePath: "backlog/task-003.md",
|
|
407
|
+
source: "local"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
id: "task-004",
|
|
411
|
+
title: "Create UI component library",
|
|
412
|
+
status: "In Progress",
|
|
413
|
+
assignee: ["diana@example.com", "eve@example.com"],
|
|
414
|
+
createdDate: "2025-11-04T13:45:00Z",
|
|
415
|
+
updatedDate: "2025-11-17T16:20:00Z",
|
|
416
|
+
labels: ["frontend", "ui"],
|
|
417
|
+
dependencies: [],
|
|
418
|
+
description: "Build reusable React components with TypeScript. Include buttons, forms, modals, and data tables.",
|
|
419
|
+
priority: "medium",
|
|
420
|
+
ordinal: 2,
|
|
421
|
+
acceptanceCriteriaItems: [
|
|
422
|
+
{ index: 0, text: "All components are fully typed", checked: true },
|
|
423
|
+
{ index: 1, text: "Components support theme customization", checked: true },
|
|
424
|
+
{ index: 2, text: "Storybook stories for each component", checked: false },
|
|
425
|
+
{ index: 3, text: "Accessibility audit passes", checked: false }
|
|
426
|
+
],
|
|
427
|
+
filePath: "backlog/task-004.md",
|
|
428
|
+
source: "local"
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
id: "task-005",
|
|
432
|
+
title: "Set up CI/CD pipeline",
|
|
433
|
+
status: "Done",
|
|
434
|
+
assignee: ["frank@example.com"],
|
|
435
|
+
createdDate: "2025-11-05T08:30:00Z",
|
|
436
|
+
updatedDate: "2025-11-10T17:00:00Z",
|
|
437
|
+
labels: ["devops", "automation"],
|
|
438
|
+
dependencies: [],
|
|
439
|
+
description: "Configure GitHub Actions for automated testing, building, and deployment.",
|
|
440
|
+
priority: "medium",
|
|
441
|
+
ordinal: 1,
|
|
442
|
+
filePath: "backlog/task-005.md",
|
|
443
|
+
source: "completed"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
id: "task-006",
|
|
447
|
+
title: "Write unit tests",
|
|
448
|
+
status: "Done",
|
|
449
|
+
assignee: ["grace@example.com"],
|
|
450
|
+
createdDate: "2025-11-06T10:00:00Z",
|
|
451
|
+
updatedDate: "2025-11-12T14:30:00Z",
|
|
452
|
+
labels: ["testing", "quality"],
|
|
453
|
+
dependencies: ["task-003"],
|
|
454
|
+
description: "Add comprehensive unit tests for all API endpoints and utility functions. Aim for 80%+ coverage.",
|
|
455
|
+
priority: "medium",
|
|
456
|
+
ordinal: 2,
|
|
457
|
+
filePath: "backlog/task-006.md",
|
|
458
|
+
source: "completed"
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
id: "task-007",
|
|
462
|
+
title: "Optimize database queries",
|
|
463
|
+
status: "To Do",
|
|
464
|
+
assignee: ["henry@example.com"],
|
|
465
|
+
createdDate: "2025-11-07T15:20:00Z",
|
|
466
|
+
labels: ["performance", "database"],
|
|
467
|
+
dependencies: ["task-002", "task-003"],
|
|
468
|
+
description: "Profile and optimize slow database queries. Add indexes where needed.",
|
|
469
|
+
priority: "low",
|
|
470
|
+
ordinal: 3,
|
|
471
|
+
filePath: "backlog/task-007.md",
|
|
472
|
+
source: "local"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
id: "task-008",
|
|
476
|
+
title: "Implement real-time notifications",
|
|
477
|
+
status: "To Do",
|
|
478
|
+
assignee: [],
|
|
479
|
+
createdDate: "2025-11-08T09:45:00Z",
|
|
480
|
+
labels: ["feature", "realtime"],
|
|
481
|
+
dependencies: ["task-003"],
|
|
482
|
+
description: "Add WebSocket support for real-time notifications when tasks are updated or assigned.",
|
|
483
|
+
priority: "low",
|
|
484
|
+
ordinal: 4,
|
|
485
|
+
filePath: "backlog/task-008.md",
|
|
486
|
+
source: "local"
|
|
487
|
+
}
|
|
488
|
+
];
|
|
489
|
+
}
|
|
490
|
+
function getDefaultStatuses() {
|
|
491
|
+
return ["To Do", "In Progress", "Done"];
|
|
492
|
+
}
|
|
493
|
+
function useKanbanData() {
|
|
494
|
+
const [tasks, setTasks] = useState(() => generateMockTasks());
|
|
495
|
+
const [statuses] = useState(() => getDefaultStatuses());
|
|
496
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
497
|
+
const [error, setError] = useState(null);
|
|
498
|
+
const tasksByStatus = useMemo(() => {
|
|
499
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
500
|
+
for (const status of statuses) {
|
|
501
|
+
grouped.set(status, []);
|
|
502
|
+
}
|
|
503
|
+
for (const task of tasks) {
|
|
504
|
+
const statusKey = task.status ?? "";
|
|
505
|
+
const list = grouped.get(statusKey);
|
|
506
|
+
if (list) {
|
|
507
|
+
list.push(task);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
for (const [status, taskList] of grouped.entries()) {
|
|
511
|
+
taskList.sort((a, b) => {
|
|
512
|
+
if (a.ordinal !== void 0 && b.ordinal !== void 0) {
|
|
513
|
+
return a.ordinal - b.ordinal;
|
|
514
|
+
}
|
|
515
|
+
const priorityOrder = { high: 3, medium: 2, low: 1 };
|
|
516
|
+
const aPriority = priorityOrder[a.priority] || 0;
|
|
517
|
+
const bPriority = priorityOrder[b.priority] || 0;
|
|
518
|
+
if (aPriority !== bPriority) {
|
|
519
|
+
return bPriority - aPriority;
|
|
520
|
+
}
|
|
521
|
+
return new Date(b.createdDate).getTime() - new Date(a.createdDate).getTime();
|
|
522
|
+
});
|
|
523
|
+
grouped.set(status, taskList);
|
|
524
|
+
}
|
|
525
|
+
return grouped;
|
|
526
|
+
}, [tasks, statuses]);
|
|
527
|
+
const refreshData = useCallback(async () => {
|
|
528
|
+
setIsLoading(true);
|
|
529
|
+
setError(null);
|
|
530
|
+
try {
|
|
531
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
532
|
+
const newTasks = generateMockTasks();
|
|
533
|
+
setTasks(newTasks);
|
|
534
|
+
} catch (err) {
|
|
535
|
+
setError(err instanceof Error ? err.message : "Failed to refresh data");
|
|
536
|
+
} finally {
|
|
537
|
+
setIsLoading(false);
|
|
538
|
+
}
|
|
539
|
+
}, []);
|
|
540
|
+
const updateTaskStatus = useCallback(async (taskId, newStatus) => {
|
|
541
|
+
setError(null);
|
|
542
|
+
setTasks(
|
|
543
|
+
(prevTasks) => prevTasks.map(
|
|
544
|
+
(task) => task.id === taskId ? { ...task, status: newStatus, updatedDate: (/* @__PURE__ */ new Date()).toISOString() } : task
|
|
545
|
+
)
|
|
546
|
+
);
|
|
547
|
+
try {
|
|
548
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
549
|
+
} catch (err) {
|
|
550
|
+
setError(err instanceof Error ? err.message : "Failed to update task");
|
|
551
|
+
setTasks(generateMockTasks());
|
|
552
|
+
}
|
|
553
|
+
}, []);
|
|
554
|
+
return {
|
|
555
|
+
tasks,
|
|
556
|
+
statuses,
|
|
557
|
+
isLoading,
|
|
558
|
+
error,
|
|
559
|
+
tasksByStatus,
|
|
560
|
+
refreshData,
|
|
561
|
+
updateTaskStatus
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
const KanbanColumn = ({
|
|
565
|
+
status,
|
|
566
|
+
tasks,
|
|
567
|
+
onTaskClick
|
|
568
|
+
}) => {
|
|
569
|
+
const { theme: theme2 } = useTheme();
|
|
570
|
+
const getPriorityColor = (priority) => {
|
|
571
|
+
switch (priority) {
|
|
572
|
+
case "high":
|
|
573
|
+
return theme2.colors.error;
|
|
574
|
+
case "medium":
|
|
575
|
+
return theme2.colors.warning;
|
|
576
|
+
case "low":
|
|
577
|
+
return theme2.colors.info;
|
|
578
|
+
default:
|
|
579
|
+
return theme2.colors.border;
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
return /* @__PURE__ */ jsxs(
|
|
583
|
+
"div",
|
|
584
|
+
{
|
|
585
|
+
style: {
|
|
586
|
+
flex: "0 0 320px",
|
|
587
|
+
display: "flex",
|
|
588
|
+
flexDirection: "column",
|
|
589
|
+
gap: "12px",
|
|
590
|
+
background: theme2.colors.backgroundSecondary,
|
|
591
|
+
borderRadius: theme2.radii[2],
|
|
592
|
+
padding: "16px",
|
|
593
|
+
border: `1px solid ${theme2.colors.border}`
|
|
594
|
+
},
|
|
595
|
+
children: [
|
|
596
|
+
/* @__PURE__ */ jsxs(
|
|
597
|
+
"div",
|
|
598
|
+
{
|
|
599
|
+
style: {
|
|
600
|
+
display: "flex",
|
|
601
|
+
alignItems: "center",
|
|
602
|
+
justifyContent: "space-between"
|
|
603
|
+
},
|
|
604
|
+
children: [
|
|
605
|
+
/* @__PURE__ */ jsx(
|
|
606
|
+
"h3",
|
|
607
|
+
{
|
|
608
|
+
style: {
|
|
609
|
+
margin: 0,
|
|
610
|
+
fontSize: theme2.fontSizes[3],
|
|
611
|
+
color: theme2.colors.text,
|
|
612
|
+
fontWeight: theme2.fontWeights.semibold
|
|
613
|
+
},
|
|
614
|
+
children: status
|
|
615
|
+
}
|
|
616
|
+
),
|
|
617
|
+
/* @__PURE__ */ jsx(
|
|
618
|
+
"span",
|
|
619
|
+
{
|
|
620
|
+
style: {
|
|
621
|
+
fontSize: theme2.fontSizes[1],
|
|
622
|
+
color: theme2.colors.textSecondary,
|
|
623
|
+
background: theme2.colors.background,
|
|
624
|
+
padding: "2px 8px",
|
|
625
|
+
borderRadius: theme2.radii[1]
|
|
626
|
+
},
|
|
627
|
+
children: tasks.length
|
|
628
|
+
}
|
|
629
|
+
)
|
|
630
|
+
]
|
|
631
|
+
}
|
|
632
|
+
),
|
|
633
|
+
/* @__PURE__ */ jsx(
|
|
634
|
+
"div",
|
|
635
|
+
{
|
|
636
|
+
style: {
|
|
637
|
+
flex: 1,
|
|
638
|
+
display: "flex",
|
|
639
|
+
flexDirection: "column",
|
|
640
|
+
gap: "8px",
|
|
641
|
+
overflowY: "auto"
|
|
642
|
+
},
|
|
643
|
+
children: tasks.map((task) => /* @__PURE__ */ jsxs(
|
|
644
|
+
"div",
|
|
645
|
+
{
|
|
646
|
+
onClick: () => onTaskClick == null ? void 0 : onTaskClick(task),
|
|
647
|
+
style: {
|
|
648
|
+
background: theme2.colors.surface,
|
|
649
|
+
borderRadius: theme2.radii[2],
|
|
650
|
+
padding: "12px",
|
|
651
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
652
|
+
borderLeft: `4px solid ${getPriorityColor(task.priority)}`,
|
|
653
|
+
cursor: onTaskClick ? "pointer" : "default",
|
|
654
|
+
transition: "all 0.2s ease"
|
|
655
|
+
},
|
|
656
|
+
onMouseEnter: (e) => {
|
|
657
|
+
if (onTaskClick) {
|
|
658
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
659
|
+
e.currentTarget.style.boxShadow = `0 4px 8px ${theme2.colors.border}`;
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
onMouseLeave: (e) => {
|
|
663
|
+
if (onTaskClick) {
|
|
664
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
665
|
+
e.currentTarget.style.boxShadow = "none";
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
children: [
|
|
669
|
+
/* @__PURE__ */ jsx(
|
|
670
|
+
"h4",
|
|
671
|
+
{
|
|
672
|
+
style: {
|
|
673
|
+
margin: "0 0 8px 0",
|
|
674
|
+
fontSize: theme2.fontSizes[2],
|
|
675
|
+
color: theme2.colors.text,
|
|
676
|
+
fontWeight: theme2.fontWeights.medium
|
|
677
|
+
},
|
|
678
|
+
children: task.title
|
|
679
|
+
}
|
|
680
|
+
),
|
|
681
|
+
task.description && /* @__PURE__ */ jsx(
|
|
682
|
+
"p",
|
|
683
|
+
{
|
|
684
|
+
style: {
|
|
685
|
+
margin: "0 0 8px 0",
|
|
686
|
+
fontSize: theme2.fontSizes[1],
|
|
687
|
+
color: theme2.colors.textSecondary,
|
|
688
|
+
overflow: "hidden",
|
|
689
|
+
textOverflow: "ellipsis",
|
|
690
|
+
display: "-webkit-box",
|
|
691
|
+
WebkitLineClamp: 2,
|
|
692
|
+
WebkitBoxOrient: "vertical",
|
|
693
|
+
lineHeight: "1.4"
|
|
694
|
+
},
|
|
695
|
+
children: task.description
|
|
696
|
+
}
|
|
697
|
+
),
|
|
698
|
+
task.labels && task.labels.length > 0 && /* @__PURE__ */ jsx(
|
|
699
|
+
"div",
|
|
700
|
+
{
|
|
701
|
+
style: {
|
|
702
|
+
display: "flex",
|
|
703
|
+
gap: "4px",
|
|
704
|
+
flexWrap: "wrap",
|
|
705
|
+
marginBottom: "8px"
|
|
706
|
+
},
|
|
707
|
+
children: task.labels.map((label) => /* @__PURE__ */ jsx(
|
|
708
|
+
"span",
|
|
709
|
+
{
|
|
710
|
+
style: {
|
|
711
|
+
fontSize: theme2.fontSizes[0],
|
|
712
|
+
color: theme2.colors.primary,
|
|
713
|
+
background: `${theme2.colors.primary}20`,
|
|
714
|
+
padding: "2px 8px",
|
|
715
|
+
borderRadius: theme2.radii[1],
|
|
716
|
+
fontWeight: theme2.fontWeights.medium
|
|
717
|
+
},
|
|
718
|
+
children: label
|
|
719
|
+
},
|
|
720
|
+
label
|
|
721
|
+
))
|
|
722
|
+
}
|
|
723
|
+
),
|
|
724
|
+
/* @__PURE__ */ jsxs(
|
|
725
|
+
"div",
|
|
726
|
+
{
|
|
727
|
+
style: {
|
|
728
|
+
display: "flex",
|
|
729
|
+
alignItems: "center",
|
|
730
|
+
justifyContent: "space-between",
|
|
731
|
+
fontSize: theme2.fontSizes[0],
|
|
732
|
+
color: theme2.colors.textMuted
|
|
733
|
+
},
|
|
734
|
+
children: [
|
|
735
|
+
/* @__PURE__ */ jsx(
|
|
736
|
+
"span",
|
|
737
|
+
{
|
|
738
|
+
style: {
|
|
739
|
+
fontFamily: theme2.fonts.monospace
|
|
740
|
+
},
|
|
741
|
+
children: task.id
|
|
742
|
+
}
|
|
743
|
+
),
|
|
744
|
+
task.assignee && task.assignee.length > 0 && /* @__PURE__ */ jsxs(
|
|
745
|
+
"span",
|
|
746
|
+
{
|
|
747
|
+
style: {
|
|
748
|
+
color: theme2.colors.textSecondary
|
|
749
|
+
},
|
|
750
|
+
children: [
|
|
751
|
+
task.assignee.length,
|
|
752
|
+
" assignee",
|
|
753
|
+
task.assignee.length !== 1 ? "s" : ""
|
|
754
|
+
]
|
|
755
|
+
}
|
|
756
|
+
)
|
|
757
|
+
]
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
]
|
|
761
|
+
},
|
|
762
|
+
task.id
|
|
763
|
+
))
|
|
764
|
+
}
|
|
765
|
+
)
|
|
766
|
+
]
|
|
767
|
+
}
|
|
768
|
+
);
|
|
769
|
+
};
|
|
770
|
+
const KanbanPanelContent = ({
|
|
771
|
+
context
|
|
772
|
+
}) => {
|
|
773
|
+
const { theme: theme2 } = useTheme();
|
|
774
|
+
const [_selectedTask, setSelectedTask] = useState(null);
|
|
775
|
+
const {
|
|
776
|
+
statuses,
|
|
777
|
+
tasksByStatus,
|
|
778
|
+
isLoading,
|
|
779
|
+
error,
|
|
780
|
+
refreshData
|
|
781
|
+
} = useKanbanData();
|
|
782
|
+
const handleTaskClick = (task) => {
|
|
783
|
+
setSelectedTask(task);
|
|
784
|
+
};
|
|
785
|
+
const handleRefresh = async () => {
|
|
786
|
+
await refreshData();
|
|
787
|
+
};
|
|
788
|
+
return /* @__PURE__ */ jsxs(
|
|
789
|
+
"div",
|
|
790
|
+
{
|
|
791
|
+
style: {
|
|
792
|
+
padding: "20px",
|
|
793
|
+
fontFamily: theme2.fonts.body,
|
|
794
|
+
height: "100%",
|
|
795
|
+
display: "flex",
|
|
796
|
+
flexDirection: "column",
|
|
797
|
+
gap: "16px",
|
|
798
|
+
backgroundColor: theme2.colors.background,
|
|
799
|
+
color: theme2.colors.text
|
|
800
|
+
},
|
|
801
|
+
children: [
|
|
802
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
|
|
803
|
+
/* @__PURE__ */ jsx(Kanban, { size: 24, color: theme2.colors.primary }),
|
|
804
|
+
/* @__PURE__ */ jsx(
|
|
805
|
+
"h2",
|
|
806
|
+
{
|
|
807
|
+
style: {
|
|
808
|
+
margin: 0,
|
|
809
|
+
fontSize: theme2.fontSizes[4],
|
|
810
|
+
color: theme2.colors.text
|
|
811
|
+
},
|
|
812
|
+
children: "Kanban Board"
|
|
813
|
+
}
|
|
814
|
+
),
|
|
815
|
+
context.currentScope.repository && /* @__PURE__ */ jsx(
|
|
816
|
+
"span",
|
|
817
|
+
{
|
|
818
|
+
style: {
|
|
819
|
+
marginLeft: "auto",
|
|
820
|
+
fontSize: theme2.fontSizes[1],
|
|
821
|
+
color: theme2.colors.textSecondary,
|
|
822
|
+
fontFamily: theme2.fonts.monospace
|
|
823
|
+
},
|
|
824
|
+
children: context.currentScope.repository.name
|
|
825
|
+
}
|
|
826
|
+
),
|
|
827
|
+
/* @__PURE__ */ jsxs(
|
|
828
|
+
"button",
|
|
829
|
+
{
|
|
830
|
+
onClick: handleRefresh,
|
|
831
|
+
disabled: isLoading,
|
|
832
|
+
style: {
|
|
833
|
+
padding: "8px 12px",
|
|
834
|
+
display: "flex",
|
|
835
|
+
alignItems: "center",
|
|
836
|
+
gap: "6px",
|
|
837
|
+
border: `1px solid ${theme2.colors.border}`,
|
|
838
|
+
borderRadius: theme2.radii[1],
|
|
839
|
+
background: theme2.colors.surface,
|
|
840
|
+
color: theme2.colors.text,
|
|
841
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
842
|
+
opacity: isLoading ? 0.6 : 1
|
|
843
|
+
},
|
|
844
|
+
children: [
|
|
845
|
+
/* @__PURE__ */ jsx(RefreshCw, { size: 16, style: { animation: isLoading ? "spin 1s linear infinite" : "none" } }),
|
|
846
|
+
"Refresh"
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
)
|
|
850
|
+
] }),
|
|
851
|
+
error && /* @__PURE__ */ jsxs(
|
|
852
|
+
"div",
|
|
853
|
+
{
|
|
854
|
+
style: {
|
|
855
|
+
padding: "12px",
|
|
856
|
+
background: `${theme2.colors.error}20`,
|
|
857
|
+
border: `1px solid ${theme2.colors.error}`,
|
|
858
|
+
borderRadius: theme2.radii[2],
|
|
859
|
+
display: "flex",
|
|
860
|
+
alignItems: "center",
|
|
861
|
+
gap: "8px",
|
|
862
|
+
color: theme2.colors.error
|
|
863
|
+
},
|
|
864
|
+
children: [
|
|
865
|
+
/* @__PURE__ */ jsx(CircleAlert, { size: 16 }),
|
|
866
|
+
/* @__PURE__ */ jsx("span", { children: error })
|
|
867
|
+
]
|
|
868
|
+
}
|
|
869
|
+
),
|
|
870
|
+
/* @__PURE__ */ jsx(
|
|
871
|
+
"div",
|
|
872
|
+
{
|
|
873
|
+
style: {
|
|
874
|
+
flex: 1,
|
|
875
|
+
display: "flex",
|
|
876
|
+
gap: "16px",
|
|
877
|
+
overflowX: "auto",
|
|
878
|
+
paddingBottom: "8px"
|
|
879
|
+
},
|
|
880
|
+
children: statuses.map((status) => {
|
|
881
|
+
const columnTasks = tasksByStatus.get(status) || [];
|
|
882
|
+
return /* @__PURE__ */ jsx(
|
|
883
|
+
KanbanColumn,
|
|
884
|
+
{
|
|
885
|
+
status,
|
|
886
|
+
tasks: columnTasks,
|
|
887
|
+
onTaskClick: handleTaskClick
|
|
888
|
+
},
|
|
889
|
+
status
|
|
890
|
+
);
|
|
891
|
+
})
|
|
892
|
+
}
|
|
893
|
+
)
|
|
894
|
+
]
|
|
895
|
+
}
|
|
896
|
+
);
|
|
897
|
+
};
|
|
898
|
+
const KanbanPanel = (props) => {
|
|
899
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(KanbanPanelContent, { ...props }) });
|
|
900
|
+
};
|
|
901
|
+
const panels = [
|
|
902
|
+
{
|
|
903
|
+
metadata: {
|
|
904
|
+
id: "principal-ade.kanban-panel",
|
|
905
|
+
name: "Kanban Board",
|
|
906
|
+
icon: "📋",
|
|
907
|
+
version: "0.1.0",
|
|
908
|
+
author: "Principal ADE",
|
|
909
|
+
description: "Kanban board for visualizing Backlog.md tasks",
|
|
910
|
+
slices: ["fileTree"]
|
|
911
|
+
// Data slices this panel depends on
|
|
912
|
+
},
|
|
913
|
+
component: KanbanPanel,
|
|
914
|
+
// Optional: Called when this specific panel is mounted
|
|
915
|
+
onMount: async (context) => {
|
|
916
|
+
var _a;
|
|
917
|
+
console.log(
|
|
918
|
+
"Kanban Panel mounted",
|
|
919
|
+
(_a = context.currentScope.repository) == null ? void 0 : _a.path
|
|
920
|
+
);
|
|
921
|
+
},
|
|
922
|
+
// Optional: Called when this specific panel is unmounted
|
|
923
|
+
onUnmount: async (_context) => {
|
|
924
|
+
console.log("Kanban Panel unmounting");
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
];
|
|
928
|
+
const onPackageLoad = async () => {
|
|
929
|
+
console.log("Panel package loaded - Kanban Panel Extension");
|
|
930
|
+
};
|
|
931
|
+
const onPackageUnload = async () => {
|
|
932
|
+
console.log("Panel package unloading - Kanban Panel Extension");
|
|
933
|
+
};
|
|
934
|
+
export {
|
|
935
|
+
onPackageLoad,
|
|
936
|
+
onPackageUnload,
|
|
937
|
+
panels
|
|
938
|
+
};
|
|
939
|
+
//# sourceMappingURL=panels.bundle.js.map
|