hs-uix 2.1.0 → 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 +397 -119
- package/dist/calendar.mjs +399 -119
- 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 +3255 -353
- package/dist/index.mjs +3199 -344
- 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 +76 -5
- package/src/calendar/index.d.ts +108 -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/utils.js
CHANGED
|
@@ -31,6 +31,7 @@ var utils_exports = {};
|
|
|
31
31
|
__export(utils_exports, {
|
|
32
32
|
CrmDataTable: () => CrmDataTable,
|
|
33
33
|
CrmKanban: () => CrmKanban,
|
|
34
|
+
applyPatches: () => applyPatches,
|
|
34
35
|
buildActiveFilterChips: () => buildActiveFilterChips,
|
|
35
36
|
buildCrmSearchConfig: () => buildCrmSearchConfig,
|
|
36
37
|
buildOptions: () => buildOptions,
|
|
@@ -69,6 +70,130 @@ __export(utils_exports, {
|
|
|
69
70
|
});
|
|
70
71
|
module.exports = __toCommonJS(utils_exports);
|
|
71
72
|
|
|
73
|
+
// src/utils/applyPatches.js
|
|
74
|
+
function applyPatches(doc, patches) {
|
|
75
|
+
if (!patches || patches.length === 0) return doc;
|
|
76
|
+
let out = doc ?? {};
|
|
77
|
+
for (const op of patches) {
|
|
78
|
+
out = applyOne(out, op);
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
function applyOne(doc, op) {
|
|
83
|
+
const path = parsePointer(op.path);
|
|
84
|
+
switch (op.op) {
|
|
85
|
+
case "add":
|
|
86
|
+
return setAt(doc, path, op.value, true);
|
|
87
|
+
case "replace":
|
|
88
|
+
return setAt(doc, path, op.value, false);
|
|
89
|
+
case "remove":
|
|
90
|
+
return removeAt(doc, path);
|
|
91
|
+
case "move": {
|
|
92
|
+
const from = parsePointer(op.from);
|
|
93
|
+
const value = getAt(doc, from);
|
|
94
|
+
const removed = removeAt(doc, from);
|
|
95
|
+
return setAt(removed, path, value, true);
|
|
96
|
+
}
|
|
97
|
+
case "copy": {
|
|
98
|
+
const from = parsePointer(op.from);
|
|
99
|
+
const value = getAt(doc, from);
|
|
100
|
+
return setAt(doc, path, deepClone(value), true);
|
|
101
|
+
}
|
|
102
|
+
default:
|
|
103
|
+
console.warn("[hs-uix] applyPatches: ignoring unsupported op:", op.op);
|
|
104
|
+
return doc;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function parsePointer(pointer) {
|
|
108
|
+
if (!pointer || pointer === "/") return [];
|
|
109
|
+
if (pointer[0] !== "/") {
|
|
110
|
+
throw new Error(`invalid JSON Pointer (must start with /): ${pointer}`);
|
|
111
|
+
}
|
|
112
|
+
return pointer.slice(1).split("/").map((seg) => seg.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
113
|
+
}
|
|
114
|
+
function getAt(obj, segs) {
|
|
115
|
+
let cur = obj;
|
|
116
|
+
for (const seg of segs) {
|
|
117
|
+
if (cur == null) return void 0;
|
|
118
|
+
if (Array.isArray(cur)) {
|
|
119
|
+
cur = cur[Number(seg)];
|
|
120
|
+
} else if (typeof cur === "object") {
|
|
121
|
+
cur = Object.prototype.hasOwnProperty.call(cur, seg) ? cur[seg] : void 0;
|
|
122
|
+
} else {
|
|
123
|
+
return void 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return cur;
|
|
127
|
+
}
|
|
128
|
+
function setAt(obj, segs, value, insert) {
|
|
129
|
+
if (segs.length === 0) return value;
|
|
130
|
+
const [head, ...rest] = segs;
|
|
131
|
+
if (Array.isArray(obj)) {
|
|
132
|
+
const next = obj.slice();
|
|
133
|
+
const idx = head === "-" ? next.length : Number(head);
|
|
134
|
+
if (rest.length === 0) {
|
|
135
|
+
if (head === "-") {
|
|
136
|
+
next.push(value);
|
|
137
|
+
} else if (insert && Number.isInteger(idx) && idx >= 0 && idx <= next.length) {
|
|
138
|
+
next.splice(idx, 0, value);
|
|
139
|
+
} else {
|
|
140
|
+
next[idx] = value;
|
|
141
|
+
}
|
|
142
|
+
return next;
|
|
143
|
+
}
|
|
144
|
+
const existing2 = idx >= 0 && idx < next.length ? next[idx] : void 0;
|
|
145
|
+
next[idx] = setAt(
|
|
146
|
+
existing2 ?? (looksLikeArrayIndex(rest[0]) ? [] : {}),
|
|
147
|
+
rest,
|
|
148
|
+
value,
|
|
149
|
+
insert
|
|
150
|
+
);
|
|
151
|
+
return next;
|
|
152
|
+
}
|
|
153
|
+
const base = obj && typeof obj === "object" ? obj : {};
|
|
154
|
+
if (rest.length === 0) {
|
|
155
|
+
return { ...base, [head]: value };
|
|
156
|
+
}
|
|
157
|
+
const existing = base[head];
|
|
158
|
+
const child = setAt(
|
|
159
|
+
existing ?? (looksLikeArrayIndex(rest[0]) ? [] : {}),
|
|
160
|
+
rest,
|
|
161
|
+
value,
|
|
162
|
+
insert
|
|
163
|
+
);
|
|
164
|
+
return { ...base, [head]: child };
|
|
165
|
+
}
|
|
166
|
+
function removeAt(obj, segs) {
|
|
167
|
+
if (segs.length === 0) return void 0;
|
|
168
|
+
const [head, ...rest] = segs;
|
|
169
|
+
if (Array.isArray(obj)) {
|
|
170
|
+
const idx = Number(head);
|
|
171
|
+
if (!Number.isInteger(idx) || idx < 0 || idx >= obj.length) return obj;
|
|
172
|
+
const next = obj.slice();
|
|
173
|
+
if (rest.length === 0) {
|
|
174
|
+
next.splice(idx, 1);
|
|
175
|
+
} else {
|
|
176
|
+
next[idx] = removeAt(next[idx], rest);
|
|
177
|
+
}
|
|
178
|
+
return next;
|
|
179
|
+
}
|
|
180
|
+
if (!obj || typeof obj !== "object") return obj;
|
|
181
|
+
if (rest.length === 0) {
|
|
182
|
+
const next = { ...obj };
|
|
183
|
+
delete next[head];
|
|
184
|
+
return next;
|
|
185
|
+
}
|
|
186
|
+
if (!(head in obj)) return obj;
|
|
187
|
+
return { ...obj, [head]: removeAt(obj[head], rest) };
|
|
188
|
+
}
|
|
189
|
+
function looksLikeArrayIndex(seg) {
|
|
190
|
+
return seg === "-" || /^\d+$/.test(seg);
|
|
191
|
+
}
|
|
192
|
+
function deepClone(v) {
|
|
193
|
+
const json = v === void 0 ? void 0 : JSON.stringify(v);
|
|
194
|
+
return json === void 0 ? void 0 : JSON.parse(json);
|
|
195
|
+
}
|
|
196
|
+
|
|
72
197
|
// src/utils/collections.js
|
|
73
198
|
var sumBy = (items, keyOrFn) => (items || []).reduce((total, item) => {
|
|
74
199
|
const value = typeof keyOrFn === "function" ? keyOrFn(item) : item == null ? void 0 : item[keyOrFn];
|
|
@@ -597,7 +722,7 @@ var GENERATED_ICONS = {
|
|
|
597
722
|
"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"] }
|
|
598
723
|
};
|
|
599
724
|
|
|
600
|
-
// src/common-components/
|
|
725
|
+
// src/common-components/nativeIconNames.js
|
|
601
726
|
var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
602
727
|
"add",
|
|
603
728
|
"appointment",
|
|
@@ -609,12 +734,12 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
609
734
|
"block",
|
|
610
735
|
"book",
|
|
611
736
|
"bulb",
|
|
737
|
+
"callTranscript",
|
|
612
738
|
"calling",
|
|
613
739
|
"callingHangup",
|
|
614
740
|
"callingMade",
|
|
615
741
|
"callingMissed",
|
|
616
742
|
"callingVoicemail",
|
|
617
|
-
"callTranscript",
|
|
618
743
|
"campaigns",
|
|
619
744
|
"cap",
|
|
620
745
|
"checkCircle",
|
|
@@ -643,13 +768,13 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
643
768
|
"enroll",
|
|
644
769
|
"exclamation",
|
|
645
770
|
"exclamationCircle",
|
|
646
|
-
"facebook",
|
|
647
771
|
"faceHappy",
|
|
648
772
|
"faceHappyFilled",
|
|
649
773
|
"faceNeutral",
|
|
650
774
|
"faceNeutralFilled",
|
|
651
775
|
"faceSad",
|
|
652
776
|
"faceSadFilled",
|
|
777
|
+
"facebook",
|
|
653
778
|
"favoriteHollow",
|
|
654
779
|
"file",
|
|
655
780
|
"filledXCircleIcon",
|
|
@@ -790,6 +915,8 @@ var NATIVE_ICON_NAMES = /* @__PURE__ */ new Set([
|
|
|
790
915
|
"zoomIn",
|
|
791
916
|
"zoomOut"
|
|
792
917
|
]);
|
|
918
|
+
|
|
919
|
+
// src/common-components/Icon.js
|
|
793
920
|
var NATIVE_COLORS = /* @__PURE__ */ new Set(["inherit", "alert", "warning", "success"]);
|
|
794
921
|
var NATIVE_SIZE_TOKENS = {
|
|
795
922
|
sm: "sm",
|
|
@@ -1002,6 +1129,7 @@ var CollectionFilterControl = ({
|
|
|
1002
1129
|
{ key: name, direction: "row", align: "center", gap: "xs" },
|
|
1003
1130
|
h3(import_ui_extensions5.DateInput, {
|
|
1004
1131
|
name: `${controlName}-from`,
|
|
1132
|
+
label: filter.fromLabel ?? labels.dateFrom,
|
|
1005
1133
|
placeholder: filter.fromLabel ?? labels.dateFrom,
|
|
1006
1134
|
format: "medium",
|
|
1007
1135
|
value: rangeValue.from ?? null,
|
|
@@ -1010,6 +1138,7 @@ var CollectionFilterControl = ({
|
|
|
1010
1138
|
h3(Icon, { name: "right", size: "sm" }),
|
|
1011
1139
|
h3(import_ui_extensions5.DateInput, {
|
|
1012
1140
|
name: `${controlName}-to`,
|
|
1141
|
+
label: filter.toLabel ?? labels.dateTo,
|
|
1013
1142
|
placeholder: filter.toLabel ?? labels.dateTo,
|
|
1014
1143
|
format: "medium",
|
|
1015
1144
|
value: rangeValue.to ?? null,
|
|
@@ -1148,6 +1277,45 @@ var editValidationError = (result) => {
|
|
|
1148
1277
|
return typeof result === "string" ? result : "Invalid value";
|
|
1149
1278
|
};
|
|
1150
1279
|
|
|
1280
|
+
// src/datatable/rowExpansion.js
|
|
1281
|
+
var extractRowId = (row, rowIdField = "id", fallback = void 0) => {
|
|
1282
|
+
const id = row == null ? void 0 : row[rowIdField];
|
|
1283
|
+
return id != null ? id : fallback;
|
|
1284
|
+
};
|
|
1285
|
+
var normalizeExpandedIds = (ids) => {
|
|
1286
|
+
if (ids == null) return /* @__PURE__ */ new Set();
|
|
1287
|
+
const list = ids instanceof Set ? [...ids] : Array.isArray(ids) ? ids : [ids];
|
|
1288
|
+
return new Set(list.filter((id) => id != null));
|
|
1289
|
+
};
|
|
1290
|
+
var expandRowId = (expandedIds, rowId, expandSingle = false) => {
|
|
1291
|
+
if (rowId == null) return expandedIds;
|
|
1292
|
+
if (expandSingle) return /* @__PURE__ */ new Set([rowId]);
|
|
1293
|
+
const next = new Set(expandedIds);
|
|
1294
|
+
next.add(rowId);
|
|
1295
|
+
return next;
|
|
1296
|
+
};
|
|
1297
|
+
var collapseRowId = (expandedIds, rowId) => {
|
|
1298
|
+
if (rowId == null || !expandedIds.has(rowId)) return expandedIds;
|
|
1299
|
+
const next = new Set(expandedIds);
|
|
1300
|
+
next.delete(rowId);
|
|
1301
|
+
return next;
|
|
1302
|
+
};
|
|
1303
|
+
var toggleExpandedId = (expandedIds, rowId, expandSingle = false) => {
|
|
1304
|
+
if (rowId == null) return expandedIds;
|
|
1305
|
+
return expandedIds.has(rowId) ? collapseRowId(expandedIds, rowId) : expandRowId(expandedIds, rowId, expandSingle);
|
|
1306
|
+
};
|
|
1307
|
+
var withDetailRows = (items, expandedIds, rowIdField = "id") => {
|
|
1308
|
+
if (!expandedIds || expandedIds.size === 0) return items;
|
|
1309
|
+
const out = [];
|
|
1310
|
+
items.forEach((item) => {
|
|
1311
|
+
out.push(item);
|
|
1312
|
+
if (item.type === "data" && expandedIds.has(extractRowId(item.row, rowIdField))) {
|
|
1313
|
+
out.push({ type: "detail", row: item.row });
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
return out;
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1151
1319
|
// src/datatable/DataTable.jsx
|
|
1152
1320
|
var import_ui_extensions7 = require("@hubspot/ui-extensions");
|
|
1153
1321
|
var NARROW_EDIT_TYPES = /* @__PURE__ */ new Set(["checkbox", "toggle"]);
|
|
@@ -1359,6 +1527,21 @@ var DataTable = ({
|
|
|
1359
1527
|
hideRowActionsWhenSelectionActive = false,
|
|
1360
1528
|
// hide row action column while selected-row action bar is visible
|
|
1361
1529
|
// -----------------------------------------------------------------------
|
|
1530
|
+
// Row expansion (detail rows)
|
|
1531
|
+
// -----------------------------------------------------------------------
|
|
1532
|
+
renderExpandedRow,
|
|
1533
|
+
// (row) => ReactNode — providing this enables the feature
|
|
1534
|
+
expandedRowIds: externalExpandedRowIds,
|
|
1535
|
+
// controlled — array of expanded row IDs
|
|
1536
|
+
defaultExpandedRowIds,
|
|
1537
|
+
// uncontrolled — initially expanded row IDs
|
|
1538
|
+
onExpandedRowsChange,
|
|
1539
|
+
// (expandedRowIds[]) => void
|
|
1540
|
+
expandOn = "icon",
|
|
1541
|
+
// "icon" (chevron toggle column) | "row" (click row content)
|
|
1542
|
+
expandSingle = false,
|
|
1543
|
+
// accordion mode — expanding a row collapses the others
|
|
1544
|
+
// -----------------------------------------------------------------------
|
|
1362
1545
|
// Inline editing
|
|
1363
1546
|
// -----------------------------------------------------------------------
|
|
1364
1547
|
editMode,
|
|
@@ -1603,6 +1786,25 @@ var DataTable = ({
|
|
|
1603
1786
|
});
|
|
1604
1787
|
return rows;
|
|
1605
1788
|
}, [groupedData, paginatedRows, expandedGroups]);
|
|
1789
|
+
const expandable = typeof renderExpandedRow === "function";
|
|
1790
|
+
const showExpandColumn = expandable && expandOn === "icon";
|
|
1791
|
+
const [internalExpandedRowIds, setInternalExpandedRowIds] = (0, import_react7.useState)(
|
|
1792
|
+
() => normalizeExpandedIds(defaultExpandedRowIds)
|
|
1793
|
+
);
|
|
1794
|
+
const expandedRowIds = (0, import_react7.useMemo)(
|
|
1795
|
+
() => externalExpandedRowIds != null ? normalizeExpandedIds(externalExpandedRowIds) : internalExpandedRowIds,
|
|
1796
|
+
[externalExpandedRowIds, internalExpandedRowIds]
|
|
1797
|
+
);
|
|
1798
|
+
const toggleRowExpanded = (0, import_react7.useCallback)((rowId) => {
|
|
1799
|
+
if (rowId == null) return;
|
|
1800
|
+
const next = toggleExpandedId(expandedRowIds, rowId, expandSingle);
|
|
1801
|
+
if (externalExpandedRowIds == null) setInternalExpandedRowIds(next);
|
|
1802
|
+
if (onExpandedRowsChange) onExpandedRowsChange([...next]);
|
|
1803
|
+
}, [expandedRowIds, expandSingle, externalExpandedRowIds, onExpandedRowsChange]);
|
|
1804
|
+
const renderedRows = (0, import_react7.useMemo)(() => {
|
|
1805
|
+
if (!expandable) return displayRows;
|
|
1806
|
+
return withDetailRows(displayRows, expandedRowIds, rowIdField);
|
|
1807
|
+
}, [expandable, displayRows, expandedRowIds, rowIdField]);
|
|
1606
1808
|
const footerData = serverSide ? data : filteredData;
|
|
1607
1809
|
const activeChips = (0, import_react7.useMemo)(
|
|
1608
1810
|
() => buildActiveFilterChips(filters, filterValues),
|
|
@@ -1754,6 +1956,7 @@ var DataTable = ({
|
|
|
1754
1956
|
const type = col.editType || "text";
|
|
1755
1957
|
const rowId = row[rowIdField];
|
|
1756
1958
|
const fieldName = `edit-${rowId}-${col.field}`;
|
|
1959
|
+
const inputLabel = typeof col.label === "string" ? col.label : col.field;
|
|
1757
1960
|
const commit = (val) => commitEdit(row, col.field, val);
|
|
1758
1961
|
const exitEdit = () => {
|
|
1759
1962
|
if (editError) return;
|
|
@@ -1794,15 +1997,15 @@ var DataTable = ({
|
|
|
1794
1997
|
case "multiselect":
|
|
1795
1998
|
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.MultiSelect, { ...extra, name: fieldName, label: "", value: editValue || [], onChange: commit, options: resolveEditOptions(col, data) });
|
|
1796
1999
|
case "date":
|
|
1797
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: fieldName, label:
|
|
2000
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: fieldName, label: inputLabel, value: editValue, onChange: commit });
|
|
1798
2001
|
case "time":
|
|
1799
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra, name: fieldName, label:
|
|
2002
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra, name: fieldName, label: inputLabel, value: editValue, onChange: commit });
|
|
1800
2003
|
case "datetime":
|
|
1801
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: `${fieldName}-date`, label:
|
|
2004
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: `${fieldName}-date`, label: `${inputLabel} date`, value: editValue == null ? void 0 : editValue.date, onChange: (val) => {
|
|
1802
2005
|
const next = { ...editValue, date: val };
|
|
1803
2006
|
handleInput(next);
|
|
1804
2007
|
commitEdit(row, col.field, next, { keepEditing: true });
|
|
1805
|
-
}, onBlur: maybeExitDatetimeEdit }), /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label:
|
|
2008
|
+
}, onBlur: maybeExitDatetimeEdit }), /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label: `${inputLabel} time`, value: editValue == null ? void 0 : editValue.time, onChange: (val) => {
|
|
1806
2009
|
const next = { ...editValue, time: val };
|
|
1807
2010
|
handleInput(next);
|
|
1808
2011
|
commitEdit(row, col.field, next, { keepEditing: true });
|
|
@@ -1816,7 +2019,8 @@ var DataTable = ({
|
|
|
1816
2019
|
}
|
|
1817
2020
|
};
|
|
1818
2021
|
const resolvedEditMode = editMode || (columns.some((col) => col.editable) ? "discrete" : null);
|
|
1819
|
-
const useColumnRendering = selectable || !!resolvedEditMode || editingRowId != null || showRowActionsColumn || !renderRow;
|
|
2022
|
+
const useColumnRendering = selectable || !!resolvedEditMode || editingRowId != null || showRowActionsColumn || expandable || !renderRow;
|
|
2023
|
+
const totalColumnCount = columns.length + (selectable ? 1 : 0) + (showExpandColumn ? 1 : 0) + (showRowActionsColumn ? 1 : 0);
|
|
1820
2024
|
const autoWidths = (0, import_react7.useMemo)(
|
|
1821
2025
|
() => autoWidth ? computeAutoWidths(columns, data) : {},
|
|
1822
2026
|
[columns, data, autoWidth]
|
|
@@ -1835,6 +2039,7 @@ var DataTable = ({
|
|
|
1835
2039
|
const type = col.editType || "text";
|
|
1836
2040
|
const rowId = row[rowIdField];
|
|
1837
2041
|
const fieldName = `inline-${rowId}-${col.field}`;
|
|
2042
|
+
const inputLabel = typeof col.label === "string" ? col.label : col.field;
|
|
1838
2043
|
const cellKey = `${rowId}-${col.field}`;
|
|
1839
2044
|
const value = row[col.field];
|
|
1840
2045
|
const validate = col.editValidate;
|
|
@@ -1883,13 +2088,13 @@ var DataTable = ({
|
|
|
1883
2088
|
case "multiselect":
|
|
1884
2089
|
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.MultiSelect, { ...extra, name: fieldName, label: "", value: value || [], onChange: fire, options: resolveEditOptions(col, data) });
|
|
1885
2090
|
case "date":
|
|
1886
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: fieldName, label:
|
|
2091
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: fieldName, label: inputLabel, value, onChange: fire });
|
|
1887
2092
|
case "time":
|
|
1888
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra, name: fieldName, label:
|
|
2093
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra, name: fieldName, label: inputLabel, value, onChange: fire });
|
|
1889
2094
|
case "datetime":
|
|
1890
|
-
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: `${fieldName}-date`, label:
|
|
2095
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.DateInput, { ...extra, name: `${fieldName}-date`, label: `${inputLabel} date`, value: value == null ? void 0 : value.date, onChange: (val) => {
|
|
1891
2096
|
fire({ ...value, date: val });
|
|
1892
|
-
} }), /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label:
|
|
2097
|
+
} }), /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TimeInput, { ...extra.timeProps || {}, name: `${fieldName}-time`, label: `${inputLabel} time`, value: value == null ? void 0 : value.time, onChange: (val) => {
|
|
1893
2098
|
fire({ ...value, time: val });
|
|
1894
2099
|
} }));
|
|
1895
2100
|
case "toggle":
|
|
@@ -2043,7 +2248,7 @@ var DataTable = ({
|
|
|
2043
2248
|
checked: allVisibleSelected,
|
|
2044
2249
|
onChange: handleSelectAll
|
|
2045
2250
|
}
|
|
2046
|
-
)), columns.map((col) => {
|
|
2251
|
+
)), showExpandColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { width: "min" }), columns.map((col) => {
|
|
2047
2252
|
const headerAlign = resolvedEditMode === "inline" && col.editable ? void 0 : col.align;
|
|
2048
2253
|
return /* @__PURE__ */ import_react7.default.createElement(
|
|
2049
2254
|
import_ui_extensions7.TableHeader,
|
|
@@ -2057,8 +2262,8 @@ var DataTable = ({
|
|
|
2057
2262
|
col.description ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, col.label, "\xA0", /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Link, { inline: true, variant: "dark", overlay: /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Tooltip, null, col.description) }, /* @__PURE__ */ import_react7.default.createElement(Icon, { name: "info", screenReaderText: typeof col.description === "string" ? col.description : void 0 }))) : col.label
|
|
2058
2263
|
);
|
|
2059
2264
|
}), showRowActionsColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { width: "min" }))),
|
|
2060
|
-
/* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableBody, null,
|
|
2061
|
-
(item, idx) => item.type === "group-header" ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, { key: `group-${item.group.key}` }, selectable && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }), columns.map((col, colIdx) => {
|
|
2265
|
+
/* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableBody, null, renderedRows.map(
|
|
2266
|
+
(item, idx) => item.type === "group-header" ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, { key: `group-${item.group.key}` }, selectable && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }), showExpandColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }), columns.map((col, colIdx) => {
|
|
2062
2267
|
var _a, _b, _c;
|
|
2063
2268
|
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { key: col.field, width: getCellWidth(col), align: colIdx === 0 ? void 0 : col.align }, colIdx === 0 ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2064
2269
|
Icon,
|
|
@@ -2075,7 +2280,7 @@ var DataTable = ({
|
|
|
2075
2280
|
},
|
|
2076
2281
|
/* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Text, { format: { fontWeight: "demibold" } }, item.group.label)
|
|
2077
2282
|
)) : ((_a = groupBy.aggregations) == null ? void 0 : _a[col.field]) ? groupBy.aggregations[col.field](item.group.rows, item.group.key) : ((_c = (_b = groupBy.groupValues) == null ? void 0 : _b[item.group.key]) == null ? void 0 : _c[col.field]) ?? "");
|
|
2078
|
-
}), showRowActionsColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" })) : useColumnRendering ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, { key: item.row[rowIdField] ?? idx }, selectable && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2283
|
+
}), showRowActionsColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" })) : item.type === "detail" ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, { key: `detail-${item.row[rowIdField] ?? idx}` }, /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { colSpan: totalColumnCount }, renderExpandedRow(item.row))) : useColumnRendering ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, { key: item.row[rowIdField] ?? idx }, selectable && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2079
2284
|
import_ui_extensions7.Checkbox,
|
|
2080
2285
|
{
|
|
2081
2286
|
name: `select-${item.row[rowIdField]}`,
|
|
@@ -2083,13 +2288,22 @@ var DataTable = ({
|
|
|
2083
2288
|
checked: selectedIds.has(item.row[rowIdField]),
|
|
2084
2289
|
onChange: (checked) => handleSelectRow(item.row[rowIdField], checked)
|
|
2085
2290
|
}
|
|
2291
|
+
)), showExpandColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }, /* @__PURE__ */ import_react7.default.createElement(
|
|
2292
|
+
Icon,
|
|
2293
|
+
{
|
|
2294
|
+
name: expandedRowIds.has(item.row[rowIdField]) ? "upCarat" : "downCarat",
|
|
2295
|
+
onClick: () => toggleRowExpanded(item.row[rowIdField]),
|
|
2296
|
+
screenReaderText: expandedRowIds.has(item.row[rowIdField]) ? "Collapse row" : "Expand row"
|
|
2297
|
+
}
|
|
2086
2298
|
)), columns.map((col) => {
|
|
2087
2299
|
const rowId = item.row[rowIdField];
|
|
2088
2300
|
const isDiscreteEditing = resolvedEditMode === "discrete" && (editingCell == null ? void 0 : editingCell.rowId) === rowId && (editingCell == null ? void 0 : editingCell.field) === col.field;
|
|
2089
2301
|
const isRowEditing = editingRowId != null && rowId === editingRowId && col.editable;
|
|
2090
2302
|
const isShowingInput = isDiscreteEditing || isRowEditing || resolvedEditMode === "inline" && col.editable;
|
|
2091
2303
|
const cellAlign = isShowingInput ? void 0 : col.align;
|
|
2092
|
-
|
|
2304
|
+
const cellContent = renderCellContent(item.row, col);
|
|
2305
|
+
const wrapInRowToggle = expandable && expandOn === "row" && !col.editable && !isShowingInput;
|
|
2306
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { key: col.field, width: isDiscreteEditing || isRowEditing ? "auto" : getCellWidth(col), align: cellAlign }, wrapInRowToggle ? /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Link, { variant: "dark", onClick: () => toggleRowExpanded(rowId) }, cellContent) : cellContent);
|
|
2093
2307
|
}), showRowActionsColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableCell, { width: "min" }, /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.Flex, { direction: "row", align: "center", gap: "xs", wrap: "nowrap" }, (() => {
|
|
2094
2308
|
const resolvedRowActions = typeof rowActions === "function" ? rowActions(item.row) : rowActions;
|
|
2095
2309
|
const actions = Array.isArray(resolvedRowActions) ? resolvedRowActions : [];
|
|
@@ -2106,17 +2320,121 @@ var DataTable = ({
|
|
|
2106
2320
|
));
|
|
2107
2321
|
})()))) : renderRow(item.row)
|
|
2108
2322
|
)),
|
|
2109
|
-
(footer || columns.some((col) => col.footer)) && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableFooter, null, typeof footer === "function" ? footer(footerData) : /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, null, selectable && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { width: "min" }), columns.map((col) => {
|
|
2323
|
+
(footer || columns.some((col) => col.footer)) && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableFooter, null, typeof footer === "function" ? footer(footerData) : /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableRow, null, selectable && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { width: "min" }), showExpandColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { width: "min" }), columns.map((col) => {
|
|
2110
2324
|
const footerDef = col.footer;
|
|
2111
2325
|
const content = typeof footerDef === "function" ? footerDef(footerData) : footerDef || "";
|
|
2112
2326
|
return /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { key: col.field, align: col.align }, content);
|
|
2113
2327
|
}), showRowActionsColumn && /* @__PURE__ */ import_react7.default.createElement(import_ui_extensions7.TableHeader, { width: "min" })))
|
|
2114
2328
|
));
|
|
2115
2329
|
};
|
|
2330
|
+
DataTable.displayName = "DataTable";
|
|
2116
2331
|
|
|
2117
2332
|
// src/kanban/Kanban.jsx
|
|
2118
2333
|
var import_react10 = __toESM(require("react"));
|
|
2119
2334
|
|
|
2335
|
+
// src/kanban/kanbanLanes.js
|
|
2336
|
+
var UNASSIGNED_LANE_KEY = "__unassigned";
|
|
2337
|
+
var UNKNOWN_STAGE_KEY = "__unknown";
|
|
2338
|
+
var getLaneKey = (row, swimlaneBy) => {
|
|
2339
|
+
const raw = typeof swimlaneBy === "function" ? swimlaneBy(row) : row == null ? void 0 : row[swimlaneBy];
|
|
2340
|
+
if (raw == null || raw === "") return UNASSIGNED_LANE_KEY;
|
|
2341
|
+
return String(raw);
|
|
2342
|
+
};
|
|
2343
|
+
var orderLaneKeys = (seenKeys, swimlaneOrder) => {
|
|
2344
|
+
const seen = Array.isArray(seenKeys) ? seenKeys : [];
|
|
2345
|
+
if (!Array.isArray(swimlaneOrder) || swimlaneOrder.length === 0) return [...seen];
|
|
2346
|
+
const explicit = [];
|
|
2347
|
+
for (const key of swimlaneOrder) {
|
|
2348
|
+
const normalized = String(key);
|
|
2349
|
+
if (!explicit.includes(normalized)) explicit.push(normalized);
|
|
2350
|
+
}
|
|
2351
|
+
const rest = seen.filter((key) => !explicit.includes(key));
|
|
2352
|
+
return [...explicit, ...rest];
|
|
2353
|
+
};
|
|
2354
|
+
var partitionLanes = (rows, { swimlaneBy, swimlaneOrder } = {}) => {
|
|
2355
|
+
const rowsByLane = {};
|
|
2356
|
+
const firstSeen = [];
|
|
2357
|
+
for (const row of rows || []) {
|
|
2358
|
+
const key = getLaneKey(row, swimlaneBy);
|
|
2359
|
+
if (!rowsByLane[key]) {
|
|
2360
|
+
rowsByLane[key] = [];
|
|
2361
|
+
firstSeen.push(key);
|
|
2362
|
+
}
|
|
2363
|
+
rowsByLane[key].push(row);
|
|
2364
|
+
}
|
|
2365
|
+
const laneKeys = orderLaneKeys(firstSeen, swimlaneOrder);
|
|
2366
|
+
for (const key of laneKeys) {
|
|
2367
|
+
if (!rowsByLane[key]) rowsByLane[key] = [];
|
|
2368
|
+
}
|
|
2369
|
+
return { laneKeys, rowsByLane };
|
|
2370
|
+
};
|
|
2371
|
+
var resolveLaneLabel = (laneKey, swimlaneLabels, rows, unassignedLabel) => {
|
|
2372
|
+
if (typeof swimlaneLabels === "function") {
|
|
2373
|
+
const out = swimlaneLabels(laneKey, rows || []);
|
|
2374
|
+
if (out != null) return out;
|
|
2375
|
+
} else if (swimlaneLabels && typeof swimlaneLabels === "object") {
|
|
2376
|
+
const out = swimlaneLabels[laneKey];
|
|
2377
|
+
if (out != null) return out;
|
|
2378
|
+
}
|
|
2379
|
+
if (laneKey === UNASSIGNED_LANE_KEY) return unassignedLabel || "Unassigned";
|
|
2380
|
+
return String(laneKey);
|
|
2381
|
+
};
|
|
2382
|
+
var bucketRowsByStage = (rows, stages, getStage) => {
|
|
2383
|
+
const map = {};
|
|
2384
|
+
for (const stage of stages || []) map[stage.value] = [];
|
|
2385
|
+
for (const row of rows || []) {
|
|
2386
|
+
const key = getStage(row);
|
|
2387
|
+
if (map[key]) {
|
|
2388
|
+
map[key].push(row);
|
|
2389
|
+
} else if ((stages || []).length > 0) {
|
|
2390
|
+
if (!map[UNKNOWN_STAGE_KEY]) map[UNKNOWN_STAGE_KEY] = [];
|
|
2391
|
+
map[UNKNOWN_STAGE_KEY].push(row);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
return map;
|
|
2395
|
+
};
|
|
2396
|
+
var sortBuckets = (buckets, comparator) => {
|
|
2397
|
+
if (!comparator) return buckets;
|
|
2398
|
+
const out = {};
|
|
2399
|
+
for (const key of Object.keys(buckets || {})) {
|
|
2400
|
+
out[key] = [...buckets[key]].sort(comparator);
|
|
2401
|
+
}
|
|
2402
|
+
return out;
|
|
2403
|
+
};
|
|
2404
|
+
var resolveWipLimit = (stage, wipLimits) => {
|
|
2405
|
+
const override = wipLimits ? wipLimits[stage == null ? void 0 : stage.value] : void 0;
|
|
2406
|
+
const limit = override != null ? override : stage == null ? void 0 : stage.wipLimit;
|
|
2407
|
+
if (typeof limit !== "number" || !Number.isFinite(limit) || limit < 0) return null;
|
|
2408
|
+
return limit;
|
|
2409
|
+
};
|
|
2410
|
+
var computeStageCounts = (stages, buckets, stageMeta) => {
|
|
2411
|
+
const counts = {};
|
|
2412
|
+
for (const stage of stages || []) {
|
|
2413
|
+
const meta = stageMeta ? stageMeta[stage.value] : void 0;
|
|
2414
|
+
counts[stage.value] = meta && meta.totalCount != null ? meta.totalCount : ((buckets == null ? void 0 : buckets[stage.value]) || []).length;
|
|
2415
|
+
}
|
|
2416
|
+
return counts;
|
|
2417
|
+
};
|
|
2418
|
+
var evaluateWip = (stages, counts, wipLimits) => {
|
|
2419
|
+
const out = {};
|
|
2420
|
+
for (const stage of stages || []) {
|
|
2421
|
+
const limit = resolveWipLimit(stage, wipLimits);
|
|
2422
|
+
const count = (counts == null ? void 0 : counts[stage.value]) || 0;
|
|
2423
|
+
out[stage.value] = { count, limit, exceeded: limit != null && count > limit };
|
|
2424
|
+
}
|
|
2425
|
+
return out;
|
|
2426
|
+
};
|
|
2427
|
+
var findNewlyExceededWip = (prev, next) => {
|
|
2428
|
+
const events = [];
|
|
2429
|
+
for (const stageId of Object.keys(next || {})) {
|
|
2430
|
+
const entry = next[stageId];
|
|
2431
|
+
if (!entry || !entry.exceeded) continue;
|
|
2432
|
+
if (prev && prev[stageId] && prev[stageId].exceeded) continue;
|
|
2433
|
+
events.push({ stageId, count: entry.count, limit: entry.limit });
|
|
2434
|
+
}
|
|
2435
|
+
return events;
|
|
2436
|
+
};
|
|
2437
|
+
|
|
2120
2438
|
// src/common-components/CollectionSortSelect.js
|
|
2121
2439
|
var import_react8 = __toESM(require("react"));
|
|
2122
2440
|
var import_ui_extensions8 = require("@hubspot/ui-extensions");
|
|
@@ -2363,6 +2681,12 @@ var DEFAULT_LABELS3 = {
|
|
|
2363
2681
|
errorTitle: "Something went wrong.",
|
|
2364
2682
|
errorMessage: "An error occurred while loading data.",
|
|
2365
2683
|
cardCount: (n) => String(n),
|
|
2684
|
+
// "5 / 4" — count vs WIP limit in the stage header. The slash format is the
|
|
2685
|
+
// standard kanban convention; override for tighter ("5/4") or verbose forms.
|
|
2686
|
+
wipCount: (count, limit) => `${count} / ${limit}`,
|
|
2687
|
+
overWip: "Over WIP",
|
|
2688
|
+
laneCount: (n) => String(n),
|
|
2689
|
+
unassignedLane: "Unassigned",
|
|
2366
2690
|
moveTo: "Move",
|
|
2367
2691
|
clearAll: "Clear all",
|
|
2368
2692
|
selectAll: (count, label) => `Select all ${count} ${label}`,
|
|
@@ -2589,10 +2913,14 @@ var KanbanColumn = ({
|
|
|
2589
2913
|
onToggleCollapsed,
|
|
2590
2914
|
columnFooter,
|
|
2591
2915
|
countDisplay,
|
|
2916
|
+
wip,
|
|
2917
|
+
compactEmpty,
|
|
2592
2918
|
labels,
|
|
2593
2919
|
children
|
|
2594
2920
|
}) => {
|
|
2595
|
-
const
|
|
2921
|
+
const hasWipLimit = wip != null && wip.limit != null;
|
|
2922
|
+
const countLabel = hasWipLimit ? labels.wipCount(wip.count, wip.limit) : labels.cardCount(totalCount != null ? totalCount : bucketCount);
|
|
2923
|
+
const overWipNode = wip && wip.exceeded ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.StatusTag, { variant: "warning" }, labels.overWip) : null;
|
|
2596
2924
|
const countNode = countDisplay === "text" ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { format: { fontWeight: "demibold" } }, countLabel) : countDisplay === "none" ? null : /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tag, { variant: "default" }, countLabel);
|
|
2597
2925
|
if (collapsed) {
|
|
2598
2926
|
const rotated = makeRotatedLabelDataUri(stage.label);
|
|
@@ -2625,8 +2953,11 @@ var KanbanColumn = ({
|
|
|
2625
2953
|
}
|
|
2626
2954
|
) : null));
|
|
2627
2955
|
}
|
|
2956
|
+
if (compactEmpty && !loading && rows.length === 0 && bucketCount === 0) {
|
|
2957
|
+
return /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tile, { compact: true }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", align: "center", justify: "between", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy", format: { fontWeight: "demibold" } }, stage.shortLabel || stage.label), /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy", format: { italic: true } }, labels.emptyColumn)));
|
|
2958
|
+
}
|
|
2628
2959
|
const footerContent = stage.footer ? stage.footer(rows) : columnFooter ? columnFooter(rows, stage) : null;
|
|
2629
|
-
return /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tile, { compact: true }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", align: "center", justify: "between", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { format: { fontWeight: "demibold" } }, stage.shortLabel || stage.label), countNode, loading ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.LoadingSpinner, { size: "xs" }) : null), /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Button, { variant: "transparent", size: "sm", onClick: onToggleCollapsed, tooltip: "Collapse" }, /* @__PURE__ */ import_react10.default.createElement(Icon, { name: "left", size: "sm", screenReaderText: `Collapse ${stage.label}` }))), footerContent ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy" }, footerContent) : null, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Divider, null), children, error ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Alert, { variant: "danger", title: labels.errorTitle }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", gap: "xs", align: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy" }, error), onLoadMore ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Button, { variant: "transparent", size: "xs", onClick: () => onLoadMore(stage.value) }, labels.retryLoadMore) : null)) : null, !error && hasMore && onLoadMore && !loading && bucketCount > 0 ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Link, { onClick: () => onLoadMore(stage.value) }, labels.loadMore(bucketCount, totalCount))) : null, !error && loading && hasMore ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.LoadingSpinner, { size: "sm", layout: "centered", label: labels.loadingMore }) : null, !error && !hasMore && bucketCount > rows.length ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Link, { onClick: onToggleExpanded }, expanded ? labels.showLess : labels.showMore(rows.length, bucketCount))) : null, rows.length === 0 && bucketCount === 0 && !loading ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy", format: { italic: true } }, labels.emptyColumn) : null));
|
|
2960
|
+
return /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tile, { compact: true }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "column", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", align: "center", justify: "between", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", align: "center", gap: "xs" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { format: { fontWeight: "demibold" } }, stage.shortLabel || stage.label), countNode, overWipNode, loading ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.LoadingSpinner, { size: "xs" }) : null), /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Button, { variant: "transparent", size: "sm", onClick: onToggleCollapsed, tooltip: "Collapse" }, /* @__PURE__ */ import_react10.default.createElement(Icon, { name: "left", size: "sm", screenReaderText: `Collapse ${stage.label}` }))), footerContent ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy" }, footerContent) : null, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Divider, null), children, error ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Alert, { variant: "danger", title: labels.errorTitle }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", gap: "xs", align: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy" }, error), onLoadMore ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Button, { variant: "transparent", size: "xs", onClick: () => onLoadMore(stage.value) }, labels.retryLoadMore) : null)) : null, !error && hasMore && onLoadMore && !loading && bucketCount > 0 ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Link, { onClick: () => onLoadMore(stage.value) }, labels.loadMore(bucketCount, totalCount))) : null, !error && loading && hasMore ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.LoadingSpinner, { size: "sm", layout: "centered", label: labels.loadingMore }) : null, !error && !hasMore && bucketCount > rows.length ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", justify: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Link, { onClick: onToggleExpanded }, expanded ? labels.showLess : labels.showMore(rows.length, bucketCount))) : null, rows.length === 0 && bucketCount === 0 && !loading ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { variant: "microcopy", format: { italic: true } }, labels.emptyColumn) : null));
|
|
2630
2961
|
};
|
|
2631
2962
|
var renderMetricsPanel = (metrics) => {
|
|
2632
2963
|
if (!metrics) return null;
|
|
@@ -2665,14 +2996,14 @@ var KanbanToolbar = ({
|
|
|
2665
2996
|
sortOptions,
|
|
2666
2997
|
sortValue,
|
|
2667
2998
|
onSortChange,
|
|
2668
|
-
|
|
2669
|
-
|
|
2999
|
+
showMetricsButton,
|
|
3000
|
+
metricsPanel,
|
|
2670
3001
|
onToggleMetrics,
|
|
2671
3002
|
labels,
|
|
2672
3003
|
toolbarLeftFlex,
|
|
2673
3004
|
toolbarRightFlex
|
|
2674
3005
|
}) => {
|
|
2675
|
-
const rightControls = (sortOptions == null ? void 0 : sortOptions.length) > 0 ||
|
|
3006
|
+
const rightControls = (sortOptions == null ? void 0 : sortOptions.length) > 0 || showMetricsButton ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, sortOptions && sortOptions.length > 0 ? /* @__PURE__ */ import_react10.default.createElement(
|
|
2676
3007
|
CollectionSortSelect,
|
|
2677
3008
|
{
|
|
2678
3009
|
name: "kanban-sort",
|
|
@@ -2681,7 +3012,7 @@ var KanbanToolbar = ({
|
|
|
2681
3012
|
options: sortOptions,
|
|
2682
3013
|
onChange: onSortChange
|
|
2683
3014
|
}
|
|
2684
|
-
) : null,
|
|
3015
|
+
) : null, showMetricsButton ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Button, { variant: "secondary", size: "small", onClick: onToggleMetrics }, /* @__PURE__ */ import_react10.default.createElement(Icon, { name: "gauge", size: "sm" }), " ", labels.metricsButton) : null) : null;
|
|
2685
3016
|
return /* @__PURE__ */ import_react10.default.createElement(
|
|
2686
3017
|
CollectionToolbar,
|
|
2687
3018
|
{
|
|
@@ -2708,7 +3039,7 @@ var KanbanToolbar = ({
|
|
|
2708
3039
|
onRemove: onFilterRemove
|
|
2709
3040
|
},
|
|
2710
3041
|
right: rightControls,
|
|
2711
|
-
footer:
|
|
3042
|
+
footer: metricsPanel,
|
|
2712
3043
|
labels,
|
|
2713
3044
|
leftFlex: toolbarLeftFlex,
|
|
2714
3045
|
rightFlex: toolbarRightFlex
|
|
@@ -2760,6 +3091,18 @@ var Kanban = ({
|
|
|
2760
3091
|
// --- Per-stage pagination ---
|
|
2761
3092
|
stageMeta,
|
|
2762
3093
|
onLoadMore,
|
|
3094
|
+
// --- WIP limits ---
|
|
3095
|
+
wipLimits,
|
|
3096
|
+
onWipExceeded,
|
|
3097
|
+
// --- Swimlanes ---
|
|
3098
|
+
swimlaneBy,
|
|
3099
|
+
swimlaneLabels,
|
|
3100
|
+
swimlaneOrder,
|
|
3101
|
+
collapseLanes = true,
|
|
3102
|
+
collapsedLanes,
|
|
3103
|
+
defaultCollapsedLanes,
|
|
3104
|
+
onCollapsedLanesChange,
|
|
3105
|
+
metricsPerLane = false,
|
|
2763
3106
|
// --- Selection ---
|
|
2764
3107
|
selectable = false,
|
|
2765
3108
|
selectedIds,
|
|
@@ -2824,6 +3167,9 @@ var Kanban = ({
|
|
|
2824
3167
|
const [internalFilters, setInternalFilters] = (0, import_react10.useState)(() => getEmptyFilterValues(filters));
|
|
2825
3168
|
const [internalSort, setInternalSort] = (0, import_react10.useState)(defaultSort || (((_a = sortOptions == null ? void 0 : sortOptions[0]) == null ? void 0 : _a.value) ?? ""));
|
|
2826
3169
|
const [internalCollapsed, setInternalCollapsed] = (0, import_react10.useState)([]);
|
|
3170
|
+
const [internalCollapsedLanes, setInternalCollapsedLanes] = (0, import_react10.useState)(
|
|
3171
|
+
() => defaultCollapsedLanes || []
|
|
3172
|
+
);
|
|
2827
3173
|
const [internalExpanded, setInternalExpanded] = (0, import_react10.useState)([]);
|
|
2828
3174
|
const [internalSelection, setInternalSelection] = (0, import_react10.useState)([]);
|
|
2829
3175
|
const [internalShowMetrics, setInternalShowMetrics] = (0, import_react10.useState)(false);
|
|
@@ -2840,6 +3186,7 @@ var Kanban = ({
|
|
|
2840
3186
|
const resolvedFilters = filterValues != null ? filterValues : internalFilters;
|
|
2841
3187
|
const resolvedSort = sort != null ? sort : internalSort;
|
|
2842
3188
|
const resolvedCollapsed = collapsedStages != null ? collapsedStages : internalCollapsed;
|
|
3189
|
+
const resolvedCollapsedLanes = collapsedLanes != null ? collapsedLanes : internalCollapsedLanes;
|
|
2843
3190
|
const resolvedExpanded = expandedStages != null ? expandedStages : internalExpanded;
|
|
2844
3191
|
const resolvedSelection = selectedIds != null ? selectedIds : internalSelection;
|
|
2845
3192
|
const searchEnabled = showSearch && Array.isArray(searchFields) && searchFields.length > 0;
|
|
@@ -2856,9 +3203,10 @@ var Kanban = ({
|
|
|
2856
3203
|
search: overrides.search != null ? overrides.search : resolvedSearch,
|
|
2857
3204
|
filters: overrides.filters != null ? overrides.filters : resolvedFilters,
|
|
2858
3205
|
sort: overrides.sort != null ? overrides.sort : resolvedSort || null,
|
|
2859
|
-
collapsedStages: overrides.collapsedStages != null ? overrides.collapsedStages : resolvedCollapsed
|
|
3206
|
+
collapsedStages: overrides.collapsedStages != null ? overrides.collapsedStages : resolvedCollapsed,
|
|
3207
|
+
collapsedLanes: overrides.collapsedLanes != null ? overrides.collapsedLanes : resolvedCollapsedLanes
|
|
2860
3208
|
});
|
|
2861
|
-
}, [onParamsChange, resolvedCollapsed, resolvedFilters, resolvedSearch, resolvedSort]);
|
|
3209
|
+
}, [onParamsChange, resolvedCollapsed, resolvedCollapsedLanes, resolvedFilters, resolvedSearch, resolvedSort]);
|
|
2862
3210
|
const lastAppliedSearchRef = (0, import_react10.useRef)(searchValue != null ? searchValue : "");
|
|
2863
3211
|
(0, import_react10.useEffect)(() => {
|
|
2864
3212
|
if (searchValue == null) return;
|
|
@@ -2917,6 +3265,15 @@ var Kanban = ({
|
|
|
2917
3265
|
},
|
|
2918
3266
|
[fireParamsChange, resolvedCollapsed, collapsedStages, onCollapsedStagesChange]
|
|
2919
3267
|
);
|
|
3268
|
+
const handleLaneCollapsed = (0, import_react10.useCallback)(
|
|
3269
|
+
(laneKey) => {
|
|
3270
|
+
const next = resolvedCollapsedLanes.includes(laneKey) ? resolvedCollapsedLanes.filter((k) => k !== laneKey) : [...resolvedCollapsedLanes, laneKey];
|
|
3271
|
+
if (onCollapsedLanesChange) onCollapsedLanesChange(next);
|
|
3272
|
+
if (collapsedLanes == null) setInternalCollapsedLanes(next);
|
|
3273
|
+
fireParamsChange({ collapsedLanes: next });
|
|
3274
|
+
},
|
|
3275
|
+
[fireParamsChange, resolvedCollapsedLanes, collapsedLanes, onCollapsedLanesChange]
|
|
3276
|
+
);
|
|
2920
3277
|
const handleExpanded = (0, import_react10.useCallback)(
|
|
2921
3278
|
(stageValue) => {
|
|
2922
3279
|
const next = resolvedExpanded.includes(stageValue) ? resolvedExpanded.filter((v) => v !== stageValue) : [...resolvedExpanded, stageValue];
|
|
@@ -2985,33 +3342,45 @@ var Kanban = ({
|
|
|
2985
3342
|
}
|
|
2986
3343
|
return result;
|
|
2987
3344
|
}, [data, resolvedSearch, resolvedFilters, filters, searchEnabled, searchFields, fuzzySearch, fuzzyOptions]);
|
|
2988
|
-
const buckets = (0, import_react10.useMemo)(
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
const key = getStageFor(row);
|
|
2993
|
-
if (map[key]) {
|
|
2994
|
-
map[key].push(row);
|
|
2995
|
-
} else if (stages.length > 0) {
|
|
2996
|
-
if (!map.__unknown) map.__unknown = [];
|
|
2997
|
-
map.__unknown.push(row);
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
return map;
|
|
3001
|
-
}, [filteredData, stages, getStageFor]);
|
|
3345
|
+
const buckets = (0, import_react10.useMemo)(
|
|
3346
|
+
() => bucketRowsByStage(filteredData, stages, getStageFor),
|
|
3347
|
+
[filteredData, stages, getStageFor]
|
|
3348
|
+
);
|
|
3002
3349
|
const sortComparator = (0, import_react10.useMemo)(() => {
|
|
3003
3350
|
if (!sortOptions || !resolvedSort) return null;
|
|
3004
3351
|
const opt = sortOptions.find((s) => s.value === resolvedSort);
|
|
3005
3352
|
return (opt == null ? void 0 : opt.comparator) || null;
|
|
3006
3353
|
}, [sortOptions, resolvedSort]);
|
|
3007
|
-
const sortedBuckets = (0, import_react10.useMemo)(() =>
|
|
3008
|
-
|
|
3354
|
+
const sortedBuckets = (0, import_react10.useMemo)(() => sortBuckets(buckets, sortComparator), [buckets, sortComparator]);
|
|
3355
|
+
const hasLanes = swimlaneBy != null;
|
|
3356
|
+
const laneData = (0, import_react10.useMemo)(() => {
|
|
3357
|
+
if (!hasLanes) return null;
|
|
3358
|
+
return partitionLanes(filteredData, { swimlaneBy, swimlaneOrder });
|
|
3359
|
+
}, [hasLanes, filteredData, swimlaneBy, swimlaneOrder]);
|
|
3360
|
+
const laneBuckets = (0, import_react10.useMemo)(() => {
|
|
3361
|
+
if (!laneData) return null;
|
|
3009
3362
|
const out = {};
|
|
3010
|
-
for (const
|
|
3011
|
-
out[
|
|
3363
|
+
for (const laneKey of laneData.laneKeys) {
|
|
3364
|
+
out[laneKey] = sortBuckets(
|
|
3365
|
+
bucketRowsByStage(laneData.rowsByLane[laneKey] || [], stages, getStageFor),
|
|
3366
|
+
sortComparator
|
|
3367
|
+
);
|
|
3012
3368
|
}
|
|
3013
3369
|
return out;
|
|
3014
|
-
}, [
|
|
3370
|
+
}, [laneData, stages, getStageFor, sortComparator]);
|
|
3371
|
+
const wipByStage = (0, import_react10.useMemo)(
|
|
3372
|
+
() => evaluateWip(stages, computeStageCounts(stages, buckets, stageMeta), wipLimits),
|
|
3373
|
+
[stages, buckets, stageMeta, wipLimits]
|
|
3374
|
+
);
|
|
3375
|
+
const prevWipRef = (0, import_react10.useRef)({});
|
|
3376
|
+
(0, import_react10.useEffect)(() => {
|
|
3377
|
+
const newlyExceeded = findNewlyExceededWip(prevWipRef.current, wipByStage);
|
|
3378
|
+
prevWipRef.current = wipByStage;
|
|
3379
|
+
if (!onWipExceeded) return;
|
|
3380
|
+
for (const event of newlyExceeded) {
|
|
3381
|
+
onWipExceeded(event.stageId, event.count, event.limit);
|
|
3382
|
+
}
|
|
3383
|
+
}, [wipByStage, onWipExceeded]);
|
|
3015
3384
|
const activeChips = (0, import_react10.useMemo)(
|
|
3016
3385
|
() => buildActiveFilterChips(filters, resolvedFilters),
|
|
3017
3386
|
[filters, resolvedFilters]
|
|
@@ -3138,6 +3507,52 @@ var Kanban = ({
|
|
|
3138
3507
|
selectionActions: selectionActions || [],
|
|
3139
3508
|
labels
|
|
3140
3509
|
};
|
|
3510
|
+
const metricsProvided = metrics != null && (!Array.isArray(metrics) || metrics.length > 0);
|
|
3511
|
+
const perLaneMetricsActive = hasLanes && metricsPerLane && typeof metrics === "function";
|
|
3512
|
+
const globalMetricsContent = metricsProvided && !perLaneMetricsActive ? typeof metrics === "function" ? metrics(filteredData, null) : metrics : null;
|
|
3513
|
+
const renderStageColumns = (bucketMap, laneKey) => {
|
|
3514
|
+
const inLane = laneKey != null;
|
|
3515
|
+
return /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", gap: "sm", wrap: "nowrap" }, stages.map((stage) => {
|
|
3516
|
+
const stageRows = bucketMap[stage.value] || [];
|
|
3517
|
+
const meta = inLane ? void 0 : stageMeta == null ? void 0 : stageMeta[stage.value];
|
|
3518
|
+
const isExpanded = resolvedExpanded.includes(stage.value);
|
|
3519
|
+
const clamp = isExpanded ? maxCardsExpanded : maxCardsPerColumn;
|
|
3520
|
+
const visibleRows = stageRows.slice(0, clamp);
|
|
3521
|
+
const isCollapsed = resolvedCollapsed.includes(stage.value);
|
|
3522
|
+
const stageWip = wipByStage[stage.value];
|
|
3523
|
+
const wip = inLane ? (stageWip == null ? void 0 : stageWip.exceeded) ? { count: stageWip.count, limit: null, exceeded: true } : null : stageWip;
|
|
3524
|
+
return /* @__PURE__ */ import_react10.default.createElement(
|
|
3525
|
+
import_ui_extensions10.AutoGrid,
|
|
3526
|
+
{
|
|
3527
|
+
key: inLane ? `${laneKey}::${stage.value}` : stage.value,
|
|
3528
|
+
columnWidth: isCollapsed ? 72 : effectiveColumnWidth
|
|
3529
|
+
},
|
|
3530
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
3531
|
+
KanbanColumn,
|
|
3532
|
+
{
|
|
3533
|
+
stage,
|
|
3534
|
+
rows: visibleRows,
|
|
3535
|
+
bucketCount: stageRows.length,
|
|
3536
|
+
totalCount: meta == null ? void 0 : meta.totalCount,
|
|
3537
|
+
hasMore: meta == null ? void 0 : meta.hasMore,
|
|
3538
|
+
loading: meta == null ? void 0 : meta.loading,
|
|
3539
|
+
error: meta == null ? void 0 : meta.error,
|
|
3540
|
+
onLoadMore: inLane ? void 0 : onLoadMore,
|
|
3541
|
+
expanded: isExpanded,
|
|
3542
|
+
onToggleExpanded: () => handleExpanded(stage.value),
|
|
3543
|
+
collapsed: isCollapsed,
|
|
3544
|
+
onToggleCollapsed: () => handleCollapsed(stage.value),
|
|
3545
|
+
columnFooter,
|
|
3546
|
+
countDisplay,
|
|
3547
|
+
wip,
|
|
3548
|
+
compactEmpty: inLane,
|
|
3549
|
+
labels
|
|
3550
|
+
},
|
|
3551
|
+
visibleRows.map((row) => renderCardNode(row, stage))
|
|
3552
|
+
)
|
|
3553
|
+
);
|
|
3554
|
+
}));
|
|
3555
|
+
};
|
|
3141
3556
|
const mainContent = error ? renderErrorState ? renderErrorState({
|
|
3142
3557
|
error,
|
|
3143
3558
|
title: labels.errorTitle,
|
|
@@ -3149,35 +3564,32 @@ var Kanban = ({
|
|
|
3149
3564
|
) : filteredData.length === 0 ? renderEmptyState ? renderEmptyState({
|
|
3150
3565
|
title: labels.emptyTitle,
|
|
3151
3566
|
message: labels.emptyMessage
|
|
3152
|
-
}) : /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tile, null, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.EmptyState, { title: labels.emptyTitle, layout: "vertical" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, null, labels.emptyMessage)))) : /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "
|
|
3153
|
-
const
|
|
3154
|
-
const
|
|
3155
|
-
const
|
|
3156
|
-
const
|
|
3157
|
-
const
|
|
3158
|
-
const
|
|
3159
|
-
|
|
3160
|
-
|
|
3567
|
+
}) : /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tile, null, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "column", align: "center", justify: "center" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.EmptyState, { title: labels.emptyTitle, layout: "vertical" }, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, null, labels.emptyMessage)))) : hasLanes ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "column", gap: "md" }, ((laneData == null ? void 0 : laneData.laneKeys) || []).map((laneKey, laneIndex) => {
|
|
3568
|
+
const laneRows = laneData.rowsByLane[laneKey] || [];
|
|
3569
|
+
const laneLabel = resolveLaneLabel(laneKey, swimlaneLabels, laneRows, labels.unassignedLane);
|
|
3570
|
+
const laneLabelText = typeof laneLabel === "string" ? laneLabel : String(laneKey);
|
|
3571
|
+
const isLaneCollapsed = collapseLanes && resolvedCollapsedLanes.includes(laneKey);
|
|
3572
|
+
const laneCountLabel = labels.laneCount(laneRows.length);
|
|
3573
|
+
const laneCountNode = countDisplay === "none" ? null : countDisplay === "text" ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { format: { fontWeight: "demibold" } }, laneCountLabel) : /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Tag, { variant: "default" }, laneCountLabel);
|
|
3574
|
+
const laneMetricsNode = !isLaneCollapsed && perLaneMetricsActive && resolvedShowMetrics ? renderMetricsPanel(metrics(laneRows, laneKey)) : null;
|
|
3575
|
+
return /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { key: laneKey, direction: "column", gap: "xs" }, laneIndex > 0 ? /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Divider, null) : null, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "row", align: "center", gap: "xs" }, collapseLanes ? /* @__PURE__ */ import_react10.default.createElement(
|
|
3576
|
+
import_ui_extensions10.Button,
|
|
3161
3577
|
{
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
hasMore: meta == null ? void 0 : meta.hasMore,
|
|
3167
|
-
loading: meta == null ? void 0 : meta.loading,
|
|
3168
|
-
error: meta == null ? void 0 : meta.error,
|
|
3169
|
-
onLoadMore,
|
|
3170
|
-
expanded: isExpanded,
|
|
3171
|
-
onToggleExpanded: () => handleExpanded(stage.value),
|
|
3172
|
-
collapsed: isCollapsed,
|
|
3173
|
-
onToggleCollapsed: () => handleCollapsed(stage.value),
|
|
3174
|
-
columnFooter,
|
|
3175
|
-
countDisplay,
|
|
3176
|
-
labels
|
|
3578
|
+
variant: "transparent",
|
|
3579
|
+
size: "sm",
|
|
3580
|
+
onClick: () => handleLaneCollapsed(laneKey),
|
|
3581
|
+
tooltip: isLaneCollapsed ? `Expand ${laneLabelText}` : `Collapse ${laneLabelText}`
|
|
3177
3582
|
},
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3583
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
3584
|
+
Icon,
|
|
3585
|
+
{
|
|
3586
|
+
name: isLaneCollapsed ? "right" : "down",
|
|
3587
|
+
size: "sm",
|
|
3588
|
+
screenReaderText: isLaneCollapsed ? `Expand ${laneLabelText}` : `Collapse ${laneLabelText}`
|
|
3589
|
+
}
|
|
3590
|
+
)
|
|
3591
|
+
) : null, /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Text, { format: { fontWeight: "demibold" } }, laneLabel), laneCountNode), laneMetricsNode, !isLaneCollapsed ? renderStageColumns((laneBuckets == null ? void 0 : laneBuckets[laneKey]) || {}, laneKey) : null);
|
|
3592
|
+
})) : renderStageColumns(sortedBuckets, null);
|
|
3181
3593
|
const resolvedShowClearFiltersButton = showClearFiltersButton ?? showFilterBadges;
|
|
3182
3594
|
return /* @__PURE__ */ import_react10.default.createElement(import_ui_extensions10.Flex, { direction: "column", gap: "sm" }, /* @__PURE__ */ import_react10.default.createElement(
|
|
3183
3595
|
KanbanToolbar,
|
|
@@ -3197,8 +3609,8 @@ var Kanban = ({
|
|
|
3197
3609
|
sortOptions,
|
|
3198
3610
|
sortValue: resolvedSort,
|
|
3199
3611
|
onSortChange: handleSort,
|
|
3200
|
-
|
|
3201
|
-
|
|
3612
|
+
showMetricsButton: metricsProvided,
|
|
3613
|
+
metricsPanel: resolvedShowMetrics && globalMetricsContent ? renderMetricsPanel(globalMetricsContent) : null,
|
|
3202
3614
|
onToggleMetrics: toggleMetrics,
|
|
3203
3615
|
labels,
|
|
3204
3616
|
toolbarLeftFlex,
|
|
@@ -3206,6 +3618,7 @@ var Kanban = ({
|
|
|
3206
3618
|
}
|
|
3207
3619
|
), showSelectionBar && selectable && selectedCount > 0 ? renderSelectionBar ? renderSelectionBar(selectionBarProps) : /* @__PURE__ */ import_react10.default.createElement(DefaultSelectionBar, { ...selectionBarProps }) : null, mainContent);
|
|
3208
3620
|
};
|
|
3621
|
+
Kanban.displayName = "Kanban";
|
|
3209
3622
|
|
|
3210
3623
|
// src/utils/objectPath.js
|
|
3211
3624
|
var getByPath = (obj, path) => {
|
|
@@ -3772,6 +4185,8 @@ var CrmKanban = ({
|
|
|
3772
4185
|
board
|
|
3773
4186
|
);
|
|
3774
4187
|
};
|
|
4188
|
+
CrmDataTable.displayName = "CrmDataTable";
|
|
4189
|
+
CrmKanban.displayName = "CrmKanban";
|
|
3775
4190
|
|
|
3776
4191
|
// src/utils/formatters.js
|
|
3777
4192
|
var DEFAULT_LOCALE = "en-US";
|
|
@@ -4083,6 +4498,7 @@ var deriveCardFieldsFromColumns = (columns, opts = {}) => {
|
|
|
4083
4498
|
0 && (module.exports = {
|
|
4084
4499
|
CrmDataTable,
|
|
4085
4500
|
CrmKanban,
|
|
4501
|
+
applyPatches,
|
|
4086
4502
|
buildActiveFilterChips,
|
|
4087
4503
|
buildCrmSearchConfig,
|
|
4088
4504
|
buildOptions,
|