@industry-theme/backlogmd-kanban-panel 1.0.4 → 1.0.6

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;AA4LpD;;;;;;;;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"}
@@ -29,14 +29,17 @@ export interface UseKanbanDataResult {
29
29
  interface UseKanbanDataOptions {
30
30
  context?: PanelContextValue;
31
31
  actions?: PanelActions;
32
- /** Number of tasks to load per column (default: 10) */
33
- pageSize?: number;
32
+ /** Number of active tasks to load (default: 20) */
33
+ tasksLimit?: number;
34
+ /** Number of completed tasks to load (default: 5) */
35
+ completedLimit?: number;
34
36
  }
35
37
  /**
36
38
  * Hook for managing kanban board data with lazy loading
37
39
  *
38
40
  * Uses 2-column view (Active/Completed) based on directory structure.
39
41
  * Only loads task content for displayed items (no file reads on init).
42
+ * Completed tasks are sorted by ID descending (most recent first).
40
43
  */
41
44
  export declare function useKanbanData(options?: UseKanbanDataOptions): UseKanbanDataResult;
42
45
  export {};
@@ -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,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,mBAAmB,CA4TrB"}
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"}
@@ -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"}
@@ -944,46 +944,38 @@ class Core {
944
944
  * Groups by directory (tasks/ or completed/) instead of status.
945
945
  * Only loads task content for items in the requested page.
946
946
  *
947
- * @param pagination - Pagination options (applied per source)
947
+ * @param options - Per-source pagination options
948
948
  * @returns Paginated tasks grouped by source
949
949
  */
950
- async getTasksBySourcePaginated(pagination) {
950
+ async getTasksBySourcePaginated(options) {
951
951
  if (!this.lazyInitialized) {
952
952
  throw new Error("Core not lazy initialized. Call initializeLazy() first.");
953
953
  }
954
- const limit = (pagination == null ? void 0 : pagination.limit) ?? 10;
955
- const offset = (pagination == null ? void 0 : pagination.offset) ?? 0;
956
- const sortBy = (pagination == null ? void 0 : pagination.sortBy) ?? "title";
957
- const sortDirection = (pagination == null ? void 0 : pagination.sortDirection) ?? "asc";
954
+ const tasksLimit = (options == null ? void 0 : options.tasksLimit) ?? 10;
955
+ const completedLimit = (options == null ? void 0 : options.completedLimit) ?? 10;
956
+ const offset = (options == null ? void 0 : options.offset) ?? 0;
957
+ (options == null ? void 0 : options.tasksSortDirection) ?? "asc";
958
+ const completedSortByIdDesc = (options == null ? void 0 : options.completedSortByIdDesc) ?? true;
958
959
  const sources = ["tasks", "completed"];
959
960
  const bySource = /* @__PURE__ */ new Map();
960
961
  for (const source of sources) {
961
962
  let entries = Array.from(this.taskIndex.values()).filter((e) => e.source === source);
963
+ const limit = source === "tasks" ? tasksLimit : completedLimit;
962
964
  entries = entries.sort((a, b) => {
963
- const cmp = a.title.localeCompare(b.title);
964
- return sortDirection === "asc" ? cmp : -cmp;
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;
965
968
  });
966
969
  const total = entries.length;
967
970
  const pageEntries = entries.slice(offset, offset + limit);
968
971
  const items = await this.loadTasks(pageEntries.map((e) => e.id));
969
- if (sortBy !== "title" && items.length > 0) {
970
- const sorted = sortTasksBy(items, sortBy, sortDirection);
971
- bySource.set(source, {
972
- items: sorted,
973
- total,
974
- hasMore: offset + limit < total,
975
- offset,
976
- limit
977
- });
978
- } else {
979
- bySource.set(source, {
980
- items,
981
- total,
982
- hasMore: offset + limit < total,
983
- offset,
984
- limit
985
- });
986
- }
972
+ bySource.set(source, {
973
+ items,
974
+ total,
975
+ hasMore: offset + limit < total,
976
+ offset,
977
+ limit
978
+ });
987
979
  }
988
980
  return {
989
981
  bySource,
@@ -995,19 +987,21 @@ class Core {
995
987
  *
996
988
  * @param source - Source to load more from ("tasks" or "completed")
997
989
  * @param currentOffset - Current offset (items already loaded)
998
- * @param pagination - Pagination options
990
+ * @param options - Pagination options
999
991
  * @returns Paginated result for the source
1000
992
  */
1001
- async loadMoreForSource(source, currentOffset, pagination) {
993
+ async loadMoreForSource(source, currentOffset, options) {
1002
994
  if (!this.lazyInitialized) {
1003
995
  throw new Error("Core not lazy initialized. Call initializeLazy() first.");
1004
996
  }
1005
- const limit = (pagination == null ? void 0 : pagination.limit) ?? 10;
1006
- const sortDirection = (pagination == null ? void 0 : pagination.sortDirection) ?? "asc";
997
+ const limit = (options == null ? void 0 : options.limit) ?? 10;
998
+ (options == null ? void 0 : options.sortDirection) ?? "asc";
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
1001
  entries = entries.sort((a, b) => {
1009
- const cmp = a.title.localeCompare(b.title);
1010
- return sortDirection === "asc" ? cmp : -cmp;
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;
1011
1005
  });
1012
1006
  const total = entries.length;
1013
1007
  const pageEntries = entries.slice(currentOffset, currentOffset + limit);
@@ -1352,9 +1346,15 @@ const SOURCE_DISPLAY_LABELS = {
1352
1346
  completed: "Completed"
1353
1347
  };
1354
1348
  const DEFAULT_SOURCES = ["tasks", "completed"];
1355
- const DEFAULT_PAGE_SIZE = 10;
1349
+ const DEFAULT_TASKS_LIMIT = 20;
1350
+ const DEFAULT_COMPLETED_LIMIT = 5;
1356
1351
  function useKanbanData(options) {
1357
- const { context, actions, pageSize = DEFAULT_PAGE_SIZE } = options || {};
1352
+ const {
1353
+ context,
1354
+ actions,
1355
+ tasksLimit = DEFAULT_TASKS_LIMIT,
1356
+ completedLimit = DEFAULT_COMPLETED_LIMIT
1357
+ } = options || {};
1358
1358
  const [tasks, setTasks] = useState([]);
1359
1359
  const [sources] = useState(DEFAULT_SOURCES);
1360
1360
  const [isLoading, setIsLoading] = useState(true);
@@ -1453,10 +1453,11 @@ function useKanbanData(options) {
1453
1453
  await core.initializeLazy(filePaths);
1454
1454
  coreRef.current = core;
1455
1455
  const paginatedResult = await core.getTasksBySourcePaginated({
1456
- limit: pageSize,
1456
+ tasksLimit,
1457
+ completedLimit,
1457
1458
  offset: 0,
1458
- sortBy: "title",
1459
- sortDirection: "asc"
1459
+ tasksSortDirection: "asc",
1460
+ completedSortByIdDesc: true
1460
1461
  });
1461
1462
  const newTasksBySource = /* @__PURE__ */ new Map();
1462
1463
  const newColumnStates = /* @__PURE__ */ new Map();
@@ -1487,7 +1488,7 @@ function useKanbanData(options) {
1487
1488
  0
1488
1489
  );
1489
1490
  console.log(
1490
- `[useKanbanData] Loaded ${allTasks.length}/${totalTasks} tasks (page size: ${pageSize})`
1491
+ `[useKanbanData] Loaded ${allTasks.length}/${totalTasks} tasks (active: ${tasksLimit}, completed: ${completedLimit})`
1491
1492
  );
1492
1493
  setTasks(allTasks);
1493
1494
  setTasksBySource(newTasksBySource);
@@ -1503,7 +1504,7 @@ function useKanbanData(options) {
1503
1504
  } finally {
1504
1505
  setIsLoading(false);
1505
1506
  }
1506
- }, [context, actions, fetchFileContent, pageSize]);
1507
+ }, [context, actions, fetchFileContent, tasksLimit, completedLimit]);
1507
1508
  useEffect(() => {
1508
1509
  loadBacklogData();
1509
1510
  }, [loadBacklogData]);
@@ -1528,13 +1529,14 @@ function useKanbanData(options) {
1528
1529
  });
1529
1530
  try {
1530
1531
  const currentOffset = currentState.tasks.length;
1532
+ const limit = source === "tasks" ? tasksLimit : completedLimit;
1531
1533
  const result = await core.loadMoreForSource(
1532
1534
  source,
1533
1535
  currentOffset,
1534
1536
  {
1535
- limit: pageSize,
1536
- sortBy: "title",
1537
- sortDirection: "asc"
1537
+ limit,
1538
+ sortDirection: "asc",
1539
+ completedSortByIdDesc: source === "completed"
1538
1540
  }
1539
1541
  );
1540
1542
  console.log(
@@ -1574,7 +1576,7 @@ function useKanbanData(options) {
1574
1576
  });
1575
1577
  }
1576
1578
  },
1577
- [columnStates, pageSize]
1579
+ [columnStates, tasksLimit, completedLimit]
1578
1580
  );
1579
1581
  const refreshData = useCallback(async () => {
1580
1582
  await loadBacklogData();
@@ -1629,9 +1631,15 @@ const KanbanColumn = ({
1629
1631
  "div",
1630
1632
  {
1631
1633
  style: {
1632
- flex: "1",
1633
- minWidth: "min(280px, 85vw)",
1634
- // Responsive width for mobile
1634
+ flex: "1 1 0",
1635
+ // Grow to fill available width equally
1636
+ minWidth: "280px",
1637
+ maxWidth: "500px",
1638
+ // Cap max width for readability
1639
+ height: "100%",
1640
+ // Fill parent height
1641
+ minHeight: 0,
1642
+ // Allow shrinking
1635
1643
  display: "flex",
1636
1644
  flexDirection: "column",
1637
1645
  gap: "12px",
@@ -1684,6 +1692,8 @@ const KanbanColumn = ({
1684
1692
  {
1685
1693
  style: {
1686
1694
  flex: 1,
1695
+ minHeight: 0,
1696
+ // Critical: allows flex child to shrink and scroll
1687
1697
  display: "flex",
1688
1698
  flexDirection: "column",
1689
1699
  gap: "8px",
@@ -1696,6 +1706,8 @@ const KanbanColumn = ({
1696
1706
  {
1697
1707
  onClick: () => onTaskClick == null ? void 0 : onTaskClick(task),
1698
1708
  style: {
1709
+ flexShrink: 0,
1710
+ // Prevent card from shrinking
1699
1711
  background: theme2.colors.surface,
1700
1712
  borderRadius: theme2.radii[2],
1701
1713
  padding: "12px",
@@ -2137,7 +2149,8 @@ const KanbanPanelContent = ({
2137
2149
  const { sources, tasksBySource, columnStates, loadMore, error, isBacklogProject, refreshData } = useKanbanData({
2138
2150
  context,
2139
2151
  actions,
2140
- pageSize: 3
2152
+ tasksLimit: 20,
2153
+ completedLimit: 5
2141
2154
  });
2142
2155
  const handleTaskClick = (task) => {
2143
2156
  setSelectedTask(task);
@@ -2210,9 +2223,13 @@ const KanbanPanelContent = ({
2210
2223
  // Responsive padding for mobile
2211
2224
  fontFamily: theme2.fonts.body,
2212
2225
  height: "100%",
2226
+ boxSizing: "border-box",
2227
+ // Include padding in height calculation
2213
2228
  display: "flex",
2214
2229
  flexDirection: "column",
2215
2230
  gap: "16px",
2231
+ overflow: "hidden",
2232
+ // Prevent outer scrolling
2216
2233
  backgroundColor: theme2.colors.background,
2217
2234
  color: theme2.colors.text
2218
2235
  },
@@ -2221,6 +2238,8 @@ const KanbanPanelContent = ({
2221
2238
  "div",
2222
2239
  {
2223
2240
  style: {
2241
+ flexShrink: 0,
2242
+ // Don't shrink header
2224
2243
  display: "flex",
2225
2244
  alignItems: "center",
2226
2245
  gap: "12px",
@@ -2246,6 +2265,8 @@ const KanbanPanelContent = ({
2246
2265
  "div",
2247
2266
  {
2248
2267
  style: {
2268
+ flexShrink: 0,
2269
+ // Don't shrink error message
2249
2270
  padding: "12px",
2250
2271
  background: `${theme2.colors.error}20`,
2251
2272
  border: `1px solid ${theme2.colors.error}`,
@@ -2275,9 +2296,13 @@ const KanbanPanelContent = ({
2275
2296
  flex: 1,
2276
2297
  display: "flex",
2277
2298
  gap: "16px",
2299
+ justifyContent: "center",
2300
+ // Center columns when they hit max-width
2278
2301
  overflowX: "auto",
2279
2302
  overflowY: "hidden",
2280
2303
  paddingBottom: "8px",
2304
+ minHeight: 0,
2305
+ // Allow flex child to shrink below content size
2281
2306
  WebkitOverflowScrolling: "touch"
2282
2307
  // Smooth scrolling on iOS
2283
2308
  },