hs-uix 2.1.1 → 2.2.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 +3 -1
- package/common-components.d.ts +319 -68
- package/dist/calendar.js +355 -57
- package/dist/calendar.mjs +356 -57
- package/dist/common-components.js +3546 -88
- package/dist/common-components.mjs +3530 -84
- package/dist/datatable.js +108 -18
- package/dist/datatable.mjs +108 -18
- package/dist/experimental.js +2876 -0
- package/dist/experimental.mjs +2883 -0
- package/dist/feed.js +267 -38
- package/dist/feed.mjs +260 -37
- package/dist/filter.js +1379 -0
- package/dist/filter.mjs +1334 -0
- package/dist/form.js +222 -26
- package/dist/form.mjs +227 -27
- package/dist/index.js +3208 -287
- package/dist/index.mjs +3156 -283
- package/dist/kanban.js +282 -62
- package/dist/kanban.mjs +273 -61
- package/dist/safe.js +9207 -0
- package/dist/safe.mjs +9298 -0
- package/dist/utils.js +491 -75
- package/dist/utils.mjs +491 -75
- package/experimental.d.ts +1 -0
- package/filter.d.ts +1 -0
- package/index.d.ts +45 -3
- package/package.json +19 -1
- package/safe.d.ts +1 -0
- package/src/calendar/README.md +74 -5
- package/src/calendar/index.d.ts +95 -1
- package/src/common-components/README.md +140 -1
- package/src/datatable/README.md +0 -2
- package/src/experimental/README.md +126 -0
- package/src/experimental/index.d.ts +346 -0
- package/src/feed/README.md +69 -0
- package/src/feed/index.d.ts +103 -0
- package/src/filter/README.md +148 -0
- package/src/filter/index.d.ts +221 -0
- package/src/form/README.md +132 -4
- package/src/form/index.d.ts +82 -1
- package/src/kanban/README.md +119 -6
- package/src/kanban/index.d.ts +153 -2
- package/src/safe/README.md +108 -0
- package/src/safe/index.d.ts +158 -0
- package/src/utils/README.md +39 -0
- package/src/wizard/README.md +158 -0
- package/src/wizard/index.d.ts +138 -0
- package/utils.d.ts +17 -0
package/dist/kanban.js
CHANGED
|
@@ -30,7 +30,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var kanban_exports = {};
|
|
31
31
|
__export(kanban_exports, {
|
|
32
32
|
Kanban: () => Kanban,
|
|
33
|
-
KanbanCardActions: () => KanbanCardActions
|
|
33
|
+
KanbanCardActions: () => KanbanCardActions,
|
|
34
|
+
UNASSIGNED_LANE_KEY: () => UNASSIGNED_LANE_KEY,
|
|
35
|
+
computeStageCounts: () => computeStageCounts,
|
|
36
|
+
evaluateWip: () => evaluateWip,
|
|
37
|
+
findNewlyExceededWip: () => findNewlyExceededWip,
|
|
38
|
+
getLaneKey: () => getLaneKey,
|
|
39
|
+
orderLaneKeys: () => orderLaneKeys,
|
|
40
|
+
partitionLanes: () => partitionLanes,
|
|
41
|
+
resolveLaneLabel: () => resolveLaneLabel,
|
|
42
|
+
resolveWipLimit: () => resolveWipLimit
|
|
34
43
|
});
|
|
35
44
|
module.exports = __toCommonJS(kanban_exports);
|
|
36
45
|
|
|
@@ -203,6 +212,109 @@ var useSelectionReset = ({ resetKey, enabled, isControlled, clearSelection }) =>
|
|
|
203
212
|
}, [resetKey, enabled, isControlled, clearSelection]);
|
|
204
213
|
};
|
|
205
214
|
|
|
215
|
+
// src/kanban/kanbanLanes.js
|
|
216
|
+
var UNASSIGNED_LANE_KEY = "__unassigned";
|
|
217
|
+
var UNKNOWN_STAGE_KEY = "__unknown";
|
|
218
|
+
var getLaneKey = (row, swimlaneBy) => {
|
|
219
|
+
const raw = typeof swimlaneBy === "function" ? swimlaneBy(row) : row == null ? void 0 : row[swimlaneBy];
|
|
220
|
+
if (raw == null || raw === "") return UNASSIGNED_LANE_KEY;
|
|
221
|
+
return String(raw);
|
|
222
|
+
};
|
|
223
|
+
var orderLaneKeys = (seenKeys, swimlaneOrder) => {
|
|
224
|
+
const seen = Array.isArray(seenKeys) ? seenKeys : [];
|
|
225
|
+
if (!Array.isArray(swimlaneOrder) || swimlaneOrder.length === 0) return [...seen];
|
|
226
|
+
const explicit = [];
|
|
227
|
+
for (const key of swimlaneOrder) {
|
|
228
|
+
const normalized = String(key);
|
|
229
|
+
if (!explicit.includes(normalized)) explicit.push(normalized);
|
|
230
|
+
}
|
|
231
|
+
const rest = seen.filter((key) => !explicit.includes(key));
|
|
232
|
+
return [...explicit, ...rest];
|
|
233
|
+
};
|
|
234
|
+
var partitionLanes = (rows, { swimlaneBy, swimlaneOrder } = {}) => {
|
|
235
|
+
const rowsByLane = {};
|
|
236
|
+
const firstSeen = [];
|
|
237
|
+
for (const row of rows || []) {
|
|
238
|
+
const key = getLaneKey(row, swimlaneBy);
|
|
239
|
+
if (!rowsByLane[key]) {
|
|
240
|
+
rowsByLane[key] = [];
|
|
241
|
+
firstSeen.push(key);
|
|
242
|
+
}
|
|
243
|
+
rowsByLane[key].push(row);
|
|
244
|
+
}
|
|
245
|
+
const laneKeys = orderLaneKeys(firstSeen, swimlaneOrder);
|
|
246
|
+
for (const key of laneKeys) {
|
|
247
|
+
if (!rowsByLane[key]) rowsByLane[key] = [];
|
|
248
|
+
}
|
|
249
|
+
return { laneKeys, rowsByLane };
|
|
250
|
+
};
|
|
251
|
+
var resolveLaneLabel = (laneKey, swimlaneLabels, rows, unassignedLabel) => {
|
|
252
|
+
if (typeof swimlaneLabels === "function") {
|
|
253
|
+
const out = swimlaneLabels(laneKey, rows || []);
|
|
254
|
+
if (out != null) return out;
|
|
255
|
+
} else if (swimlaneLabels && typeof swimlaneLabels === "object") {
|
|
256
|
+
const out = swimlaneLabels[laneKey];
|
|
257
|
+
if (out != null) return out;
|
|
258
|
+
}
|
|
259
|
+
if (laneKey === UNASSIGNED_LANE_KEY) return unassignedLabel || "Unassigned";
|
|
260
|
+
return String(laneKey);
|
|
261
|
+
};
|
|
262
|
+
var bucketRowsByStage = (rows, stages, getStage) => {
|
|
263
|
+
const map = {};
|
|
264
|
+
for (const stage of stages || []) map[stage.value] = [];
|
|
265
|
+
for (const row of rows || []) {
|
|
266
|
+
const key = getStage(row);
|
|
267
|
+
if (map[key]) {
|
|
268
|
+
map[key].push(row);
|
|
269
|
+
} else if ((stages || []).length > 0) {
|
|
270
|
+
if (!map[UNKNOWN_STAGE_KEY]) map[UNKNOWN_STAGE_KEY] = [];
|
|
271
|
+
map[UNKNOWN_STAGE_KEY].push(row);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return map;
|
|
275
|
+
};
|
|
276
|
+
var sortBuckets = (buckets, comparator) => {
|
|
277
|
+
if (!comparator) return buckets;
|
|
278
|
+
const out = {};
|
|
279
|
+
for (const key of Object.keys(buckets || {})) {
|
|
280
|
+
out[key] = [...buckets[key]].sort(comparator);
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
};
|
|
284
|
+
var resolveWipLimit = (stage, wipLimits) => {
|
|
285
|
+
const override = wipLimits ? wipLimits[stage == null ? void 0 : stage.value] : void 0;
|
|
286
|
+
const limit = override != null ? override : stage == null ? void 0 : stage.wipLimit;
|
|
287
|
+
if (typeof limit !== "number" || !Number.isFinite(limit) || limit < 0) return null;
|
|
288
|
+
return limit;
|
|
289
|
+
};
|
|
290
|
+
var computeStageCounts = (stages, buckets, stageMeta) => {
|
|
291
|
+
const counts = {};
|
|
292
|
+
for (const stage of stages || []) {
|
|
293
|
+
const meta = stageMeta ? stageMeta[stage.value] : void 0;
|
|
294
|
+
counts[stage.value] = meta && meta.totalCount != null ? meta.totalCount : ((buckets == null ? void 0 : buckets[stage.value]) || []).length;
|
|
295
|
+
}
|
|
296
|
+
return counts;
|
|
297
|
+
};
|
|
298
|
+
var evaluateWip = (stages, counts, wipLimits) => {
|
|
299
|
+
const out = {};
|
|
300
|
+
for (const stage of stages || []) {
|
|
301
|
+
const limit = resolveWipLimit(stage, wipLimits);
|
|
302
|
+
const count = (counts == null ? void 0 : counts[stage.value]) || 0;
|
|
303
|
+
out[stage.value] = { count, limit, exceeded: limit != null && count > limit };
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
};
|
|
307
|
+
var findNewlyExceededWip = (prev, next) => {
|
|
308
|
+
const events = [];
|
|
309
|
+
for (const stageId of Object.keys(next || {})) {
|
|
310
|
+
const entry = next[stageId];
|
|
311
|
+
if (!entry || !entry.exceeded) continue;
|
|
312
|
+
if (prev && prev[stageId] && prev[stageId].exceeded) continue;
|
|
313
|
+
events.push({ stageId, count: entry.count, limit: entry.limit });
|
|
314
|
+
}
|
|
315
|
+
return events;
|
|
316
|
+
};
|
|
317
|
+
|
|
206
318
|
// src/common-components/CollectionSortSelect.js
|
|
207
319
|
var import_react2 = __toESM(require("react"));
|
|
208
320
|
var import_ui_extensions2 = require("@hubspot/ui-extensions");
|
|
@@ -552,7 +664,7 @@ var GENERATED_ICONS = {
|
|
|
552
664
|
"ZoomOut": { "viewBox": "0 0 32 32", "paths": ["M14.42 26.75c2.85 0 5.47-.97 7.56-2.6l-.03.02 5.28 5.34a1.619 1.619 0 0 0 2.76-1.15c0-.45-.18-.85-.47-1.14l-5.33-5.33c1.59-2.06 2.55-4.68 2.55-7.52C26.74 7.54 21.2 2 14.37 2S2 7.55 2 14.38s5.54 12.37 12.37 12.37h.05m0-21.55c5.06 0 9.16 4.1 9.16 9.16s-4.1 9.16-9.16 9.16-9.16-4.1-9.16-9.16c.01-5.05 4.11-9.14 9.16-9.15Zm-4.31 10.78h8.62c.89 0 1.62-.72 1.62-1.62s-.72-1.62-1.62-1.62h-8.62c-.89 0-1.62.72-1.62 1.62s.72 1.62 1.62 1.62"] }
|
|
553
665
|
};
|
|
554
666
|
|
|
555
|
-
// src/common-components/
|
|
667
|
+
// src/common-components/nativeIconNames.js
|
|
556
668
|
var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
557
669
|
"add",
|
|
558
670
|
"appointment",
|
|
@@ -564,12 +676,12 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
564
676
|
"block",
|
|
565
677
|
"book",
|
|
566
678
|
"bulb",
|
|
679
|
+
"callTranscript",
|
|
567
680
|
"calling",
|
|
568
681
|
"callingHangup",
|
|
569
682
|
"callingMade",
|
|
570
683
|
"callingMissed",
|
|
571
684
|
"callingVoicemail",
|
|
572
|
-
"callTranscript",
|
|
573
685
|
"campaigns",
|
|
574
686
|
"cap",
|
|
575
687
|
"checkCircle",
|
|
@@ -598,13 +710,13 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
598
710
|
"enroll",
|
|
599
711
|
"exclamation",
|
|
600
712
|
"exclamationCircle",
|
|
601
|
-
"facebook",
|
|
602
713
|
"faceHappy",
|
|
603
714
|
"faceHappyFilled",
|
|
604
715
|
"faceNeutral",
|
|
605
716
|
"faceNeutralFilled",
|
|
606
717
|
"faceSad",
|
|
607
718
|
"faceSadFilled",
|
|
719
|
+
"facebook",
|
|
608
720
|
"favoriteHollow",
|
|
609
721
|
"file",
|
|
610
722
|
"filledXCircleIcon",
|
|
@@ -745,6 +857,8 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
745
857
|
"zoomIn",
|
|
746
858
|
"zoomOut"
|
|
747
859
|
]);
|
|
860
|
+
|
|
861
|
+
// src/common-components/Icon.js
|
|
748
862
|
var NATIVE_COLORS = /* @__PURE__ */ new Set(["inherit", "alert", "warning", "success"]);
|
|
749
863
|
var NATIVE_SIZE_TOKENS = {
|
|
750
864
|
sm: "sm",
|
|
@@ -957,6 +1071,7 @@ var CollectionFilterControl = ({
|
|
|
957
1071
|
{ key: name, direction: "row", align: "center", gap: "xs" },
|
|
958
1072
|
h3(import_ui_extensions5.DateInput, {
|
|
959
1073
|
name: `${controlName}-from`,
|
|
1074
|
+
label: filter.fromLabel ?? labels.dateFrom,
|
|
960
1075
|
placeholder: filter.fromLabel ?? labels.dateFrom,
|
|
961
1076
|
format: "medium",
|
|
962
1077
|
value: rangeValue.from ?? null,
|
|
@@ -965,6 +1080,7 @@ var CollectionFilterControl = ({
|
|
|
965
1080
|
h3(Icon, { name: "right", size: "sm" }),
|
|
966
1081
|
h3(import_ui_extensions5.DateInput, {
|
|
967
1082
|
name: `${controlName}-to`,
|
|
1083
|
+
label: filter.toLabel ?? labels.dateTo,
|
|
968
1084
|
placeholder: filter.toLabel ?? labels.dateTo,
|
|
969
1085
|
format: "medium",
|
|
970
1086
|
value: rangeValue.to ?? null,
|
|
@@ -1309,6 +1425,12 @@ var DEFAULT_LABELS3 = {
|
|
|
1309
1425
|
errorTitle: "Something went wrong.",
|
|
1310
1426
|
errorMessage: "An error occurred while loading data.",
|
|
1311
1427
|
cardCount: (n) => String(n),
|
|
1428
|
+
// "5 / 4" — count vs WIP limit in the stage header. The slash format is the
|
|
1429
|
+
// standard kanban convention; override for tighter ("5/4") or verbose forms.
|
|
1430
|
+
wipCount: (count, limit) => `${count} / ${limit}`,
|
|
1431
|
+
overWip: "Over WIP",
|
|
1432
|
+
laneCount: (n) => String(n),
|
|
1433
|
+
unassignedLane: "Unassigned",
|
|
1312
1434
|
moveTo: "Move",
|
|
1313
1435
|
clearAll: "Clear all",
|
|
1314
1436
|
selectAll: (count, label) => `Select all ${count} ${label}`,
|
|
@@ -1535,10 +1657,14 @@ var KanbanColumn = ({
|
|
|
1535
1657
|
onToggleCollapsed,
|
|
1536
1658
|
columnFooter,
|
|
1537
1659
|
countDisplay,
|
|
1660
|
+
wip,
|
|
1661
|
+
compactEmpty,
|
|
1538
1662
|
labels,
|
|
1539
1663
|
children
|
|
1540
1664
|
}) => {
|
|
1541
|
-
const
|
|
1665
|
+
const hasWipLimit = wip != null && wip.limit != null;
|
|
1666
|
+
const countLabel = hasWipLimit ? labels.wipCount(wip.count, wip.limit) : labels.cardCount(totalCount != null ? totalCount : bucketCount);
|
|
1667
|
+
const overWipNode = wip && wip.exceeded ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.StatusTag, { variant: "warning" }, labels.overWip) : null;
|
|
1542
1668
|
const countNode = countDisplay === "text" ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { format: { fontWeight: "demibold" } }, countLabel) : countDisplay === "none" ? null : /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tag, { variant: "default" }, countLabel);
|
|
1543
1669
|
if (collapsed) {
|
|
1544
1670
|
const rotated = makeRotatedLabelDataUri(stage.label);
|
|
@@ -1571,8 +1697,11 @@ var KanbanColumn = ({
|
|
|
1571
1697
|
}
|
|
1572
1698
|
) : null));
|
|
1573
1699
|
}
|
|
1700
|
+
if (compactEmpty && !loading && rows.length === 0 && bucketCount === 0) {
|
|
1701
|
+
return /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tile, { compact: true }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", align: "center", justify: "between", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, stage.shortLabel || stage.label), /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy", format: { italic: true } }, labels.emptyColumn)));
|
|
1702
|
+
}
|
|
1574
1703
|
const footerContent = stage.footer ? stage.footer(rows) : columnFooter ? columnFooter(rows, stage) : null;
|
|
1575
|
-
return /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tile, { compact: true }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", align: "center", justify: "between", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { format: { fontWeight: "demibold" } }, stage.shortLabel || stage.label), countNode, loading ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.LoadingSpinner, { size: "xs" }) : null), /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Button, { variant: "transparent", size: "sm", onClick: onToggleCollapsed, tooltip: "Collapse" }, /* @__PURE__ */ import_react8.default.createElement(Icon, { name: "left", size: "sm", screenReaderText: `Collapse ${stage.label}` }))), footerContent ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy" }, footerContent) : null, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Divider, null), children, error ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Alert, { variant: "danger", title: labels.errorTitle }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", gap: "xs", align: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy" }, error), onLoadMore ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Button, { variant: "transparent", size: "xs", onClick: () => onLoadMore(stage.value) }, labels.retryLoadMore) : null)) : null, !error && hasMore && onLoadMore && !loading && bucketCount > 0 ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Link, { onClick: () => onLoadMore(stage.value) }, labels.loadMore(bucketCount, totalCount))) : null, !error && loading && hasMore ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.LoadingSpinner, { size: "sm", layout: "centered", label: labels.loadingMore }) : null, !error && !hasMore && bucketCount > rows.length ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Link, { onClick: onToggleExpanded }, expanded ? labels.showLess : labels.showMore(rows.length, bucketCount))) : null, rows.length === 0 && bucketCount === 0 && !loading ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy", format: { italic: true } }, labels.emptyColumn) : null));
|
|
1704
|
+
return /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tile, { compact: true }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", align: "center", justify: "between", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { format: { fontWeight: "demibold" } }, stage.shortLabel || stage.label), countNode, overWipNode, loading ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.LoadingSpinner, { size: "xs" }) : null), /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Button, { variant: "transparent", size: "sm", onClick: onToggleCollapsed, tooltip: "Collapse" }, /* @__PURE__ */ import_react8.default.createElement(Icon, { name: "left", size: "sm", screenReaderText: `Collapse ${stage.label}` }))), footerContent ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy" }, footerContent) : null, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Divider, null), children, error ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Alert, { variant: "danger", title: labels.errorTitle }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", gap: "xs", align: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy" }, error), onLoadMore ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Button, { variant: "transparent", size: "xs", onClick: () => onLoadMore(stage.value) }, labels.retryLoadMore) : null)) : null, !error && hasMore && onLoadMore && !loading && bucketCount > 0 ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Link, { onClick: () => onLoadMore(stage.value) }, labels.loadMore(bucketCount, totalCount))) : null, !error && loading && hasMore ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.LoadingSpinner, { size: "sm", layout: "centered", label: labels.loadingMore }) : null, !error && !hasMore && bucketCount > rows.length ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Link, { onClick: onToggleExpanded }, expanded ? labels.showLess : labels.showMore(rows.length, bucketCount))) : null, rows.length === 0 && bucketCount === 0 && !loading ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { variant: "microcopy", format: { italic: true } }, labels.emptyColumn) : null));
|
|
1576
1705
|
};
|
|
1577
1706
|
var renderMetricsPanel = (metrics) => {
|
|
1578
1707
|
if (!metrics) return null;
|
|
@@ -1611,14 +1740,14 @@ var KanbanToolbar = ({
|
|
|
1611
1740
|
sortOptions,
|
|
1612
1741
|
sortValue,
|
|
1613
1742
|
onSortChange,
|
|
1614
|
-
|
|
1615
|
-
|
|
1743
|
+
showMetricsButton,
|
|
1744
|
+
metricsPanel,
|
|
1616
1745
|
onToggleMetrics,
|
|
1617
1746
|
labels,
|
|
1618
1747
|
toolbarLeftFlex,
|
|
1619
1748
|
toolbarRightFlex
|
|
1620
1749
|
}) => {
|
|
1621
|
-
const rightControls = (sortOptions == null ? void 0 : sortOptions.length) > 0 ||
|
|
1750
|
+
const rightControls = (sortOptions == null ? void 0 : sortOptions.length) > 0 || showMetricsButton ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, sortOptions && sortOptions.length > 0 ? /* @__PURE__ */ import_react8.default.createElement(
|
|
1622
1751
|
CollectionSortSelect,
|
|
1623
1752
|
{
|
|
1624
1753
|
name: "kanban-sort",
|
|
@@ -1627,7 +1756,7 @@ var KanbanToolbar = ({
|
|
|
1627
1756
|
options: sortOptions,
|
|
1628
1757
|
onChange: onSortChange
|
|
1629
1758
|
}
|
|
1630
|
-
) : null,
|
|
1759
|
+
) : null, showMetricsButton ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Button, { variant: "secondary", size: "small", onClick: onToggleMetrics }, /* @__PURE__ */ import_react8.default.createElement(Icon, { name: "gauge", size: "sm" }), " ", labels.metricsButton) : null) : null;
|
|
1631
1760
|
return /* @__PURE__ */ import_react8.default.createElement(
|
|
1632
1761
|
CollectionToolbar,
|
|
1633
1762
|
{
|
|
@@ -1654,7 +1783,7 @@ var KanbanToolbar = ({
|
|
|
1654
1783
|
onRemove: onFilterRemove
|
|
1655
1784
|
},
|
|
1656
1785
|
right: rightControls,
|
|
1657
|
-
footer:
|
|
1786
|
+
footer: metricsPanel,
|
|
1658
1787
|
labels,
|
|
1659
1788
|
leftFlex: toolbarLeftFlex,
|
|
1660
1789
|
rightFlex: toolbarRightFlex
|
|
@@ -1706,6 +1835,18 @@ var Kanban = ({
|
|
|
1706
1835
|
// --- Per-stage pagination ---
|
|
1707
1836
|
stageMeta,
|
|
1708
1837
|
onLoadMore,
|
|
1838
|
+
// --- WIP limits ---
|
|
1839
|
+
wipLimits,
|
|
1840
|
+
onWipExceeded,
|
|
1841
|
+
// --- Swimlanes ---
|
|
1842
|
+
swimlaneBy,
|
|
1843
|
+
swimlaneLabels,
|
|
1844
|
+
swimlaneOrder,
|
|
1845
|
+
collapseLanes = true,
|
|
1846
|
+
collapsedLanes,
|
|
1847
|
+
defaultCollapsedLanes,
|
|
1848
|
+
onCollapsedLanesChange,
|
|
1849
|
+
metricsPerLane = false,
|
|
1709
1850
|
// --- Selection ---
|
|
1710
1851
|
selectable = false,
|
|
1711
1852
|
selectedIds,
|
|
@@ -1770,6 +1911,9 @@ var Kanban = ({
|
|
|
1770
1911
|
const [internalFilters, setInternalFilters] = (0, import_react8.useState)(() => getEmptyFilterValues(filters));
|
|
1771
1912
|
const [internalSort, setInternalSort] = (0, import_react8.useState)(defaultSort || (((_a = sortOptions == null ? void 0 : sortOptions[0]) == null ? void 0 : _a.value) ?? ""));
|
|
1772
1913
|
const [internalCollapsed, setInternalCollapsed] = (0, import_react8.useState)([]);
|
|
1914
|
+
const [internalCollapsedLanes, setInternalCollapsedLanes] = (0, import_react8.useState)(
|
|
1915
|
+
() => defaultCollapsedLanes || []
|
|
1916
|
+
);
|
|
1773
1917
|
const [internalExpanded, setInternalExpanded] = (0, import_react8.useState)([]);
|
|
1774
1918
|
const [internalSelection, setInternalSelection] = (0, import_react8.useState)([]);
|
|
1775
1919
|
const [internalShowMetrics, setInternalShowMetrics] = (0, import_react8.useState)(false);
|
|
@@ -1786,6 +1930,7 @@ var Kanban = ({
|
|
|
1786
1930
|
const resolvedFilters = filterValues != null ? filterValues : internalFilters;
|
|
1787
1931
|
const resolvedSort = sort != null ? sort : internalSort;
|
|
1788
1932
|
const resolvedCollapsed = collapsedStages != null ? collapsedStages : internalCollapsed;
|
|
1933
|
+
const resolvedCollapsedLanes = collapsedLanes != null ? collapsedLanes : internalCollapsedLanes;
|
|
1789
1934
|
const resolvedExpanded = expandedStages != null ? expandedStages : internalExpanded;
|
|
1790
1935
|
const resolvedSelection = selectedIds != null ? selectedIds : internalSelection;
|
|
1791
1936
|
const searchEnabled = showSearch && Array.isArray(searchFields) && searchFields.length > 0;
|
|
@@ -1802,9 +1947,10 @@ var Kanban = ({
|
|
|
1802
1947
|
search: overrides.search != null ? overrides.search : resolvedSearch,
|
|
1803
1948
|
filters: overrides.filters != null ? overrides.filters : resolvedFilters,
|
|
1804
1949
|
sort: overrides.sort != null ? overrides.sort : resolvedSort || null,
|
|
1805
|
-
collapsedStages: overrides.collapsedStages != null ? overrides.collapsedStages : resolvedCollapsed
|
|
1950
|
+
collapsedStages: overrides.collapsedStages != null ? overrides.collapsedStages : resolvedCollapsed,
|
|
1951
|
+
collapsedLanes: overrides.collapsedLanes != null ? overrides.collapsedLanes : resolvedCollapsedLanes
|
|
1806
1952
|
});
|
|
1807
|
-
}, [onParamsChange, resolvedCollapsed, resolvedFilters, resolvedSearch, resolvedSort]);
|
|
1953
|
+
}, [onParamsChange, resolvedCollapsed, resolvedCollapsedLanes, resolvedFilters, resolvedSearch, resolvedSort]);
|
|
1808
1954
|
const lastAppliedSearchRef = (0, import_react8.useRef)(searchValue != null ? searchValue : "");
|
|
1809
1955
|
(0, import_react8.useEffect)(() => {
|
|
1810
1956
|
if (searchValue == null) return;
|
|
@@ -1863,6 +2009,15 @@ var Kanban = ({
|
|
|
1863
2009
|
},
|
|
1864
2010
|
[fireParamsChange, resolvedCollapsed, collapsedStages, onCollapsedStagesChange]
|
|
1865
2011
|
);
|
|
2012
|
+
const handleLaneCollapsed = (0, import_react8.useCallback)(
|
|
2013
|
+
(laneKey) => {
|
|
2014
|
+
const next = resolvedCollapsedLanes.includes(laneKey) ? resolvedCollapsedLanes.filter((k) => k !== laneKey) : [...resolvedCollapsedLanes, laneKey];
|
|
2015
|
+
if (onCollapsedLanesChange) onCollapsedLanesChange(next);
|
|
2016
|
+
if (collapsedLanes == null) setInternalCollapsedLanes(next);
|
|
2017
|
+
fireParamsChange({ collapsedLanes: next });
|
|
2018
|
+
},
|
|
2019
|
+
[fireParamsChange, resolvedCollapsedLanes, collapsedLanes, onCollapsedLanesChange]
|
|
2020
|
+
);
|
|
1866
2021
|
const handleExpanded = (0, import_react8.useCallback)(
|
|
1867
2022
|
(stageValue) => {
|
|
1868
2023
|
const next = resolvedExpanded.includes(stageValue) ? resolvedExpanded.filter((v) => v !== stageValue) : [...resolvedExpanded, stageValue];
|
|
@@ -1931,33 +2086,45 @@ var Kanban = ({
|
|
|
1931
2086
|
}
|
|
1932
2087
|
return result;
|
|
1933
2088
|
}, [data, resolvedSearch, resolvedFilters, filters, searchEnabled, searchFields, fuzzySearch, fuzzyOptions]);
|
|
1934
|
-
const buckets = (0, import_react8.useMemo)(
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
const key = getStageFor(row);
|
|
1939
|
-
if (map[key]) {
|
|
1940
|
-
map[key].push(row);
|
|
1941
|
-
} else if (stages.length > 0) {
|
|
1942
|
-
if (!map.__unknown) map.__unknown = [];
|
|
1943
|
-
map.__unknown.push(row);
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
return map;
|
|
1947
|
-
}, [filteredData, stages, getStageFor]);
|
|
2089
|
+
const buckets = (0, import_react8.useMemo)(
|
|
2090
|
+
() => bucketRowsByStage(filteredData, stages, getStageFor),
|
|
2091
|
+
[filteredData, stages, getStageFor]
|
|
2092
|
+
);
|
|
1948
2093
|
const sortComparator = (0, import_react8.useMemo)(() => {
|
|
1949
2094
|
if (!sortOptions || !resolvedSort) return null;
|
|
1950
2095
|
const opt = sortOptions.find((s) => s.value === resolvedSort);
|
|
1951
2096
|
return (opt == null ? void 0 : opt.comparator) || null;
|
|
1952
2097
|
}, [sortOptions, resolvedSort]);
|
|
1953
|
-
const sortedBuckets = (0, import_react8.useMemo)(() =>
|
|
1954
|
-
|
|
2098
|
+
const sortedBuckets = (0, import_react8.useMemo)(() => sortBuckets(buckets, sortComparator), [buckets, sortComparator]);
|
|
2099
|
+
const hasLanes = swimlaneBy != null;
|
|
2100
|
+
const laneData = (0, import_react8.useMemo)(() => {
|
|
2101
|
+
if (!hasLanes) return null;
|
|
2102
|
+
return partitionLanes(filteredData, { swimlaneBy, swimlaneOrder });
|
|
2103
|
+
}, [hasLanes, filteredData, swimlaneBy, swimlaneOrder]);
|
|
2104
|
+
const laneBuckets = (0, import_react8.useMemo)(() => {
|
|
2105
|
+
if (!laneData) return null;
|
|
1955
2106
|
const out = {};
|
|
1956
|
-
for (const
|
|
1957
|
-
out[
|
|
2107
|
+
for (const laneKey of laneData.laneKeys) {
|
|
2108
|
+
out[laneKey] = sortBuckets(
|
|
2109
|
+
bucketRowsByStage(laneData.rowsByLane[laneKey] || [], stages, getStageFor),
|
|
2110
|
+
sortComparator
|
|
2111
|
+
);
|
|
1958
2112
|
}
|
|
1959
2113
|
return out;
|
|
1960
|
-
}, [
|
|
2114
|
+
}, [laneData, stages, getStageFor, sortComparator]);
|
|
2115
|
+
const wipByStage = (0, import_react8.useMemo)(
|
|
2116
|
+
() => evaluateWip(stages, computeStageCounts(stages, buckets, stageMeta), wipLimits),
|
|
2117
|
+
[stages, buckets, stageMeta, wipLimits]
|
|
2118
|
+
);
|
|
2119
|
+
const prevWipRef = (0, import_react8.useRef)({});
|
|
2120
|
+
(0, import_react8.useEffect)(() => {
|
|
2121
|
+
const newlyExceeded = findNewlyExceededWip(prevWipRef.current, wipByStage);
|
|
2122
|
+
prevWipRef.current = wipByStage;
|
|
2123
|
+
if (!onWipExceeded) return;
|
|
2124
|
+
for (const event of newlyExceeded) {
|
|
2125
|
+
onWipExceeded(event.stageId, event.count, event.limit);
|
|
2126
|
+
}
|
|
2127
|
+
}, [wipByStage, onWipExceeded]);
|
|
1961
2128
|
const activeChips = (0, import_react8.useMemo)(
|
|
1962
2129
|
() => buildActiveFilterChips(filters, resolvedFilters),
|
|
1963
2130
|
[filters, resolvedFilters]
|
|
@@ -2084,6 +2251,52 @@ var Kanban = ({
|
|
|
2084
2251
|
selectionActions: selectionActions || [],
|
|
2085
2252
|
labels
|
|
2086
2253
|
};
|
|
2254
|
+
const metricsProvided = metrics != null && (!Array.isArray(metrics) || metrics.length > 0);
|
|
2255
|
+
const perLaneMetricsActive = hasLanes && metricsPerLane && typeof metrics === "function";
|
|
2256
|
+
const globalMetricsContent = metricsProvided && !perLaneMetricsActive ? typeof metrics === "function" ? metrics(filteredData, null) : metrics : null;
|
|
2257
|
+
const renderStageColumns = (bucketMap, laneKey) => {
|
|
2258
|
+
const inLane = laneKey != null;
|
|
2259
|
+
return /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", gap: "sm", wrap: "nowrap" }, stages.map((stage) => {
|
|
2260
|
+
const stageRows = bucketMap[stage.value] || [];
|
|
2261
|
+
const meta = inLane ? void 0 : stageMeta == null ? void 0 : stageMeta[stage.value];
|
|
2262
|
+
const isExpanded = resolvedExpanded.includes(stage.value);
|
|
2263
|
+
const clamp = isExpanded ? maxCardsExpanded : maxCardsPerColumn;
|
|
2264
|
+
const visibleRows = stageRows.slice(0, clamp);
|
|
2265
|
+
const isCollapsed = resolvedCollapsed.includes(stage.value);
|
|
2266
|
+
const stageWip = wipByStage[stage.value];
|
|
2267
|
+
const wip = inLane ? (stageWip == null ? void 0 : stageWip.exceeded) ? { count: stageWip.count, limit: null, exceeded: true } : null : stageWip;
|
|
2268
|
+
return /* @__PURE__ */ import_react8.default.createElement(
|
|
2269
|
+
import_ui_extensions8.AutoGrid,
|
|
2270
|
+
{
|
|
2271
|
+
key: inLane ? `${laneKey}::${stage.value}` : stage.value,
|
|
2272
|
+
columnWidth: isCollapsed ? 72 : effectiveColumnWidth
|
|
2273
|
+
},
|
|
2274
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
2275
|
+
KanbanColumn,
|
|
2276
|
+
{
|
|
2277
|
+
stage,
|
|
2278
|
+
rows: visibleRows,
|
|
2279
|
+
bucketCount: stageRows.length,
|
|
2280
|
+
totalCount: meta == null ? void 0 : meta.totalCount,
|
|
2281
|
+
hasMore: meta == null ? void 0 : meta.hasMore,
|
|
2282
|
+
loading: meta == null ? void 0 : meta.loading,
|
|
2283
|
+
error: meta == null ? void 0 : meta.error,
|
|
2284
|
+
onLoadMore: inLane ? void 0 : onLoadMore,
|
|
2285
|
+
expanded: isExpanded,
|
|
2286
|
+
onToggleExpanded: () => handleExpanded(stage.value),
|
|
2287
|
+
collapsed: isCollapsed,
|
|
2288
|
+
onToggleCollapsed: () => handleCollapsed(stage.value),
|
|
2289
|
+
columnFooter,
|
|
2290
|
+
countDisplay,
|
|
2291
|
+
wip,
|
|
2292
|
+
compactEmpty: inLane,
|
|
2293
|
+
labels
|
|
2294
|
+
},
|
|
2295
|
+
visibleRows.map((row) => renderCardNode(row, stage))
|
|
2296
|
+
)
|
|
2297
|
+
);
|
|
2298
|
+
}));
|
|
2299
|
+
};
|
|
2087
2300
|
const mainContent = error ? renderErrorState ? renderErrorState({
|
|
2088
2301
|
error,
|
|
2089
2302
|
title: labels.errorTitle,
|
|
@@ -2095,35 +2308,32 @@ var Kanban = ({
|
|
|
2095
2308
|
) : filteredData.length === 0 ? renderEmptyState ? renderEmptyState({
|
|
2096
2309
|
title: labels.emptyTitle,
|
|
2097
2310
|
message: labels.emptyMessage
|
|
2098
|
-
}) : /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tile, null, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.EmptyState, { title: labels.emptyTitle, layout: "vertical" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, null, labels.emptyMessage)))) : /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "
|
|
2099
|
-
const
|
|
2100
|
-
const
|
|
2101
|
-
const
|
|
2102
|
-
const
|
|
2103
|
-
const
|
|
2104
|
-
const
|
|
2105
|
-
|
|
2106
|
-
|
|
2311
|
+
}) : /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tile, null, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.EmptyState, { title: labels.emptyTitle, layout: "vertical" }, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, null, labels.emptyMessage)))) : hasLanes ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "column", gap: "md" }, ((laneData == null ? void 0 : laneData.laneKeys) || []).map((laneKey, laneIndex) => {
|
|
2312
|
+
const laneRows = laneData.rowsByLane[laneKey] || [];
|
|
2313
|
+
const laneLabel = resolveLaneLabel(laneKey, swimlaneLabels, laneRows, labels.unassignedLane);
|
|
2314
|
+
const laneLabelText = typeof laneLabel === "string" ? laneLabel : String(laneKey);
|
|
2315
|
+
const isLaneCollapsed = collapseLanes && resolvedCollapsedLanes.includes(laneKey);
|
|
2316
|
+
const laneCountLabel = labels.laneCount(laneRows.length);
|
|
2317
|
+
const laneCountNode = countDisplay === "none" ? null : countDisplay === "text" ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { format: { fontWeight: "demibold" } }, laneCountLabel) : /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Tag, { variant: "default" }, laneCountLabel);
|
|
2318
|
+
const laneMetricsNode = !isLaneCollapsed && perLaneMetricsActive && resolvedShowMetrics ? renderMetricsPanel(metrics(laneRows, laneKey)) : null;
|
|
2319
|
+
return /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { key: laneKey, direction: "column", gap: "xs" }, laneIndex > 0 ? /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Divider, null) : null, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "row", align: "center", gap: "xs" }, collapseLanes ? /* @__PURE__ */ import_react8.default.createElement(
|
|
2320
|
+
import_ui_extensions8.Button,
|
|
2107
2321
|
{
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
hasMore: meta == null ? void 0 : meta.hasMore,
|
|
2113
|
-
loading: meta == null ? void 0 : meta.loading,
|
|
2114
|
-
error: meta == null ? void 0 : meta.error,
|
|
2115
|
-
onLoadMore,
|
|
2116
|
-
expanded: isExpanded,
|
|
2117
|
-
onToggleExpanded: () => handleExpanded(stage.value),
|
|
2118
|
-
collapsed: isCollapsed,
|
|
2119
|
-
onToggleCollapsed: () => handleCollapsed(stage.value),
|
|
2120
|
-
columnFooter,
|
|
2121
|
-
countDisplay,
|
|
2122
|
-
labels
|
|
2322
|
+
variant: "transparent",
|
|
2323
|
+
size: "sm",
|
|
2324
|
+
onClick: () => handleLaneCollapsed(laneKey),
|
|
2325
|
+
tooltip: isLaneCollapsed ? `Expand ${laneLabelText}` : `Collapse ${laneLabelText}`
|
|
2123
2326
|
},
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2327
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
2328
|
+
Icon,
|
|
2329
|
+
{
|
|
2330
|
+
name: isLaneCollapsed ? "right" : "down",
|
|
2331
|
+
size: "sm",
|
|
2332
|
+
screenReaderText: isLaneCollapsed ? `Expand ${laneLabelText}` : `Collapse ${laneLabelText}`
|
|
2333
|
+
}
|
|
2334
|
+
)
|
|
2335
|
+
) : null, /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Text, { format: { fontWeight: "demibold" } }, laneLabel), laneCountNode), laneMetricsNode, !isLaneCollapsed ? renderStageColumns((laneBuckets == null ? void 0 : laneBuckets[laneKey]) || {}, laneKey) : null);
|
|
2336
|
+
})) : renderStageColumns(sortedBuckets, null);
|
|
2127
2337
|
const resolvedShowClearFiltersButton = showClearFiltersButton ?? showFilterBadges;
|
|
2128
2338
|
return /* @__PURE__ */ import_react8.default.createElement(import_ui_extensions8.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
2129
2339
|
KanbanToolbar,
|
|
@@ -2143,8 +2353,8 @@ var Kanban = ({
|
|
|
2143
2353
|
sortOptions,
|
|
2144
2354
|
sortValue: resolvedSort,
|
|
2145
2355
|
onSortChange: handleSort,
|
|
2146
|
-
|
|
2147
|
-
|
|
2356
|
+
showMetricsButton: metricsProvided,
|
|
2357
|
+
metricsPanel: resolvedShowMetrics && globalMetricsContent ? renderMetricsPanel(globalMetricsContent) : null,
|
|
2148
2358
|
onToggleMetrics: toggleMetrics,
|
|
2149
2359
|
labels,
|
|
2150
2360
|
toolbarLeftFlex,
|
|
@@ -2152,6 +2362,7 @@ var Kanban = ({
|
|
|
2152
2362
|
}
|
|
2153
2363
|
), showSelectionBar && selectable && selectedCount > 0 ? renderSelectionBar ? renderSelectionBar(selectionBarProps) : /* @__PURE__ */ import_react8.default.createElement(DefaultSelectionBar, { ...selectionBarProps }) : null, mainContent);
|
|
2154
2364
|
};
|
|
2365
|
+
Kanban.displayName = "Kanban";
|
|
2155
2366
|
|
|
2156
2367
|
// src/kanban/KanbanCardActions.jsx
|
|
2157
2368
|
var import_react9 = __toESM(require("react"));
|
|
@@ -2214,5 +2425,14 @@ var KanbanCardActions = ({
|
|
|
2214
2425
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2215
2426
|
0 && (module.exports = {
|
|
2216
2427
|
Kanban,
|
|
2217
|
-
KanbanCardActions
|
|
2428
|
+
KanbanCardActions,
|
|
2429
|
+
UNASSIGNED_LANE_KEY,
|
|
2430
|
+
computeStageCounts,
|
|
2431
|
+
evaluateWip,
|
|
2432
|
+
findNewlyExceededWip,
|
|
2433
|
+
getLaneKey,
|
|
2434
|
+
orderLaneKeys,
|
|
2435
|
+
partitionLanes,
|
|
2436
|
+
resolveLaneLabel,
|
|
2437
|
+
resolveWipLimit
|
|
2218
2438
|
});
|