@industry-theme/backlogmd-kanban-panel 1.0.5 → 1.0.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"KanbanPanel.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAGrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AA6LpD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAMrD,CAAC"}
1
+ {"version":3,"file":"KanbanPanel.d.ts","sourceRoot":"","sources":["../../src/panels/KanbanPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAGrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAmMpD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAMrD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"KanbanColumn.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/components/KanbanColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAyQpD,CAAC"}
1
+ {"version":3,"file":"KanbanColumn.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/components/KanbanColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA8QpD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useKanbanData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/hooks/useKanbanData.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,IAAI,EAAwB,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,4CAA4C;AAC5C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,WAAW,CAAC;AAEjD,wCAAwC;AACxC,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAG9D,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,8CAA8C;IAC9C,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,kCAAkC;IAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvC,mDAAmD;IACnD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,mBAAmB,CAoUrB"}
1
+ {"version":3,"file":"useKanbanData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/hooks/useKanbanData.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,IAAI,EAAwB,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,4CAA4C;AAC5C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,WAAW,CAAC;AAEjD,wCAAwC;AACxC,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAG9D,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,8CAA8C;IAC9C,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,kCAAkC;IAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvC,mDAAmD;IACnD,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAED,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,mBAAmB,CAwVrB"}
@@ -7,6 +7,7 @@
7
7
  import type { Task } from '@backlog-md/core';
8
8
  /**
9
9
  * Generate mock tasks for testing the kanban board
10
+ * Creates 25 active tasks and 10 completed tasks to test pagination
10
11
  */
11
12
  export declare function generateMockTasks(): Task[];
12
13
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mockData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/mocks/mockData.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,EAAE,CAuJ1C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB;;;;;;;;;;;;EAcjC"}
1
+ {"version":3,"file":"mockData.d.ts","sourceRoot":"","sources":["../../../../src/panels/kanban/mocks/mockData.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAsE7C;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,EAAE,CAqD1C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB;;;;;;;;;;;;EAcjC"}
@@ -954,25 +954,18 @@ class Core {
954
954
  const tasksLimit = (options == null ? void 0 : options.tasksLimit) ?? 10;
955
955
  const completedLimit = (options == null ? void 0 : options.completedLimit) ?? 10;
956
956
  const offset = (options == null ? void 0 : options.offset) ?? 0;
957
- const tasksSortDirection = (options == null ? void 0 : options.tasksSortDirection) ?? "asc";
957
+ (options == null ? void 0 : options.tasksSortDirection) ?? "asc";
958
958
  const completedSortByIdDesc = (options == null ? void 0 : options.completedSortByIdDesc) ?? true;
959
959
  const sources = ["tasks", "completed"];
960
960
  const bySource = /* @__PURE__ */ new Map();
961
961
  for (const source of sources) {
962
962
  let entries = Array.from(this.taskIndex.values()).filter((e) => e.source === source);
963
963
  const limit = source === "tasks" ? tasksLimit : completedLimit;
964
- if (source === "completed" && completedSortByIdDesc) {
965
- entries = entries.sort((a, b) => {
966
- const aNum = parseInt(a.id.replace(/\D/g, ""), 10) || 0;
967
- const bNum = parseInt(b.id.replace(/\D/g, ""), 10) || 0;
968
- return bNum - aNum;
969
- });
970
- } else {
971
- entries = entries.sort((a, b) => {
972
- const cmp = a.title.localeCompare(b.title);
973
- return tasksSortDirection === "asc" ? cmp : -cmp;
974
- });
975
- }
964
+ entries = entries.sort((a, b) => {
965
+ const aNum = parseInt(a.id.replace(/\D/g, ""), 10) || 0;
966
+ const bNum = parseInt(b.id.replace(/\D/g, ""), 10) || 0;
967
+ return source === "completed" && completedSortByIdDesc ? bNum - aNum : aNum - bNum;
968
+ });
976
969
  const total = entries.length;
977
970
  const pageEntries = entries.slice(offset, offset + limit);
978
971
  const items = await this.loadTasks(pageEntries.map((e) => e.id));
@@ -1002,21 +995,14 @@ class Core {
1002
995
  throw new Error("Core not lazy initialized. Call initializeLazy() first.");
1003
996
  }
1004
997
  const limit = (options == null ? void 0 : options.limit) ?? 10;
1005
- const sortDirection = (options == null ? void 0 : options.sortDirection) ?? "asc";
998
+ (options == null ? void 0 : options.sortDirection) ?? "asc";
1006
999
  const completedSortByIdDesc = (options == null ? void 0 : options.completedSortByIdDesc) ?? true;
1007
1000
  let entries = Array.from(this.taskIndex.values()).filter((e) => e.source === source);
1008
- if (source === "completed" && completedSortByIdDesc) {
1009
- entries = entries.sort((a, b) => {
1010
- const aNum = parseInt(a.id.replace(/\D/g, ""), 10) || 0;
1011
- const bNum = parseInt(b.id.replace(/\D/g, ""), 10) || 0;
1012
- return bNum - aNum;
1013
- });
1014
- } else {
1015
- entries = entries.sort((a, b) => {
1016
- const cmp = a.title.localeCompare(b.title);
1017
- return sortDirection === "asc" ? cmp : -cmp;
1018
- });
1019
- }
1001
+ entries = entries.sort((a, b) => {
1002
+ const aNum = parseInt(a.id.replace(/\D/g, ""), 10) || 0;
1003
+ const bNum = parseInt(b.id.replace(/\D/g, ""), 10) || 0;
1004
+ return source === "completed" && completedSortByIdDesc ? bNum - aNum : aNum - bNum;
1005
+ });
1020
1006
  const total = entries.length;
1021
1007
  const pageEntries = entries.slice(currentOffset, currentOffset + limit);
1022
1008
  const items = await this.loadTasks(pageEntries.map((e) => e.id));
@@ -1417,8 +1403,9 @@ function useKanbanData(options) {
1417
1403
  activeFilePathRef.current = null;
1418
1404
  }
1419
1405
  }, []);
1406
+ const fileTreeVersionRef = useRef(null);
1420
1407
  const loadBacklogData = useCallback(async () => {
1421
- var _a;
1408
+ var _a, _b;
1422
1409
  if (!context || !actions) {
1423
1410
  console.log("[useKanbanData] No context provided");
1424
1411
  setIsBacklogProject(false);
@@ -1427,21 +1414,29 @@ function useKanbanData(options) {
1427
1414
  setColumnStates(/* @__PURE__ */ new Map());
1428
1415
  setIsLoading(false);
1429
1416
  coreRef.current = null;
1417
+ fileTreeVersionRef.current = null;
1418
+ return;
1419
+ }
1420
+ const fileTreeSlice = context.getRepositorySlice("fileTree");
1421
+ if (!((_a = fileTreeSlice == null ? void 0 : fileTreeSlice.data) == null ? void 0 : _a.allFiles)) {
1422
+ console.log("[useKanbanData] FileTree not available");
1423
+ setIsBacklogProject(false);
1424
+ setTasks([]);
1425
+ setTasksBySource(/* @__PURE__ */ new Map());
1426
+ setColumnStates(/* @__PURE__ */ new Map());
1427
+ coreRef.current = null;
1428
+ fileTreeVersionRef.current = null;
1429
+ return;
1430
+ }
1431
+ const currentVersion = fileTreeSlice.data.sha || ((_b = fileTreeSlice.data.metadata) == null ? void 0 : _b.sourceSha) || "unknown";
1432
+ if (coreRef.current && fileTreeVersionRef.current === currentVersion) {
1433
+ console.log("[useKanbanData] Data already loaded for this file tree version, skipping");
1434
+ setIsLoading(false);
1430
1435
  return;
1431
1436
  }
1432
1437
  setIsLoading(true);
1433
1438
  setError(null);
1434
1439
  try {
1435
- const fileTreeSlice = context.getRepositorySlice("fileTree");
1436
- if (!((_a = fileTreeSlice == null ? void 0 : fileTreeSlice.data) == null ? void 0 : _a.allFiles)) {
1437
- console.log("[useKanbanData] FileTree not available");
1438
- setIsBacklogProject(false);
1439
- setTasks([]);
1440
- setTasksBySource(/* @__PURE__ */ new Map());
1441
- setColumnStates(/* @__PURE__ */ new Map());
1442
- coreRef.current = null;
1443
- return;
1444
- }
1445
1440
  const files = fileTreeSlice.data.allFiles;
1446
1441
  const filePaths = files.map((f) => f.path);
1447
1442
  const fs = new PanelFileSystemAdapter({
@@ -1504,6 +1499,7 @@ function useKanbanData(options) {
1504
1499
  console.log(
1505
1500
  `[useKanbanData] Loaded ${allTasks.length}/${totalTasks} tasks (active: ${tasksLimit}, completed: ${completedLimit})`
1506
1501
  );
1502
+ fileTreeVersionRef.current = currentVersion;
1507
1503
  setTasks(allTasks);
1508
1504
  setTasksBySource(newTasksBySource);
1509
1505
  setColumnStates(newColumnStates);
@@ -1515,6 +1511,7 @@ function useKanbanData(options) {
1515
1511
  setTasksBySource(/* @__PURE__ */ new Map());
1516
1512
  setColumnStates(/* @__PURE__ */ new Map());
1517
1513
  coreRef.current = null;
1514
+ fileTreeVersionRef.current = null;
1518
1515
  } finally {
1519
1516
  setIsLoading(false);
1520
1517
  }
@@ -1645,9 +1642,15 @@ const KanbanColumn = ({
1645
1642
  "div",
1646
1643
  {
1647
1644
  style: {
1648
- flex: "1",
1649
- minWidth: "min(280px, 85vw)",
1650
- // Responsive width for mobile
1645
+ flex: "1 1 0",
1646
+ // Grow to fill available width equally
1647
+ minWidth: "280px",
1648
+ maxWidth: "500px",
1649
+ // Cap max width for readability
1650
+ height: "100%",
1651
+ // Fill parent height
1652
+ minHeight: 0,
1653
+ // Allow shrinking
1651
1654
  display: "flex",
1652
1655
  flexDirection: "column",
1653
1656
  gap: "12px",
@@ -1700,6 +1703,8 @@ const KanbanColumn = ({
1700
1703
  {
1701
1704
  style: {
1702
1705
  flex: 1,
1706
+ minHeight: 0,
1707
+ // Critical: allows flex child to shrink and scroll
1703
1708
  display: "flex",
1704
1709
  flexDirection: "column",
1705
1710
  gap: "8px",
@@ -1712,6 +1717,8 @@ const KanbanColumn = ({
1712
1717
  {
1713
1718
  onClick: () => onTaskClick == null ? void 0 : onTaskClick(task),
1714
1719
  style: {
1720
+ flexShrink: 0,
1721
+ // Prevent card from shrinking
1715
1722
  background: theme2.colors.surface,
1716
1723
  borderRadius: theme2.radii[2],
1717
1724
  padding: "12px",
@@ -2227,9 +2234,13 @@ const KanbanPanelContent = ({
2227
2234
  // Responsive padding for mobile
2228
2235
  fontFamily: theme2.fonts.body,
2229
2236
  height: "100%",
2237
+ boxSizing: "border-box",
2238
+ // Include padding in height calculation
2230
2239
  display: "flex",
2231
2240
  flexDirection: "column",
2232
2241
  gap: "16px",
2242
+ overflow: "hidden",
2243
+ // Prevent outer scrolling
2233
2244
  backgroundColor: theme2.colors.background,
2234
2245
  color: theme2.colors.text
2235
2246
  },
@@ -2238,6 +2249,8 @@ const KanbanPanelContent = ({
2238
2249
  "div",
2239
2250
  {
2240
2251
  style: {
2252
+ flexShrink: 0,
2253
+ // Don't shrink header
2241
2254
  display: "flex",
2242
2255
  alignItems: "center",
2243
2256
  gap: "12px",
@@ -2263,6 +2276,8 @@ const KanbanPanelContent = ({
2263
2276
  "div",
2264
2277
  {
2265
2278
  style: {
2279
+ flexShrink: 0,
2280
+ // Don't shrink error message
2266
2281
  padding: "12px",
2267
2282
  background: `${theme2.colors.error}20`,
2268
2283
  border: `1px solid ${theme2.colors.error}`,
@@ -2292,9 +2307,13 @@ const KanbanPanelContent = ({
2292
2307
  flex: 1,
2293
2308
  display: "flex",
2294
2309
  gap: "16px",
2310
+ justifyContent: "center",
2311
+ // Center columns when they hit max-width
2295
2312
  overflowX: "auto",
2296
2313
  overflowY: "hidden",
2297
2314
  paddingBottom: "8px",
2315
+ minHeight: 0,
2316
+ // Allow flex child to shrink below content size
2298
2317
  WebkitOverflowScrolling: "touch"
2299
2318
  // Smooth scrolling on iOS
2300
2319
  },