hazo_ui 6.4.0 → 6.5.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/CHANGE_LOG.md +43 -0
- package/README.md +42 -0
- package/dist/index.cjs +210 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -2
- package/dist/index.d.ts +42 -2
- package/dist/index.js +211 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import * as SelectPrimitive from '@radix-ui/react-select';
|
|
|
15
15
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
16
16
|
import { DayPicker } from 'react-day-picker';
|
|
17
17
|
import { format } from 'date-fns';
|
|
18
|
-
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter, closestCorners, DragOverlay, useDroppable } from '@dnd-kit/core';
|
|
18
|
+
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter, pointerWithin, rectIntersection, closestCorners, DragOverlay, useDroppable } from '@dnd-kit/core';
|
|
19
19
|
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
|
|
20
20
|
import { CSS } from '@dnd-kit/utilities';
|
|
21
21
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
@@ -9021,10 +9021,15 @@ function KanbanCard({
|
|
|
9021
9021
|
isDragging
|
|
9022
9022
|
} = useSortable({
|
|
9023
9023
|
id: item.id,
|
|
9024
|
-
// sectionKey
|
|
9025
|
-
// section, not just its column (
|
|
9026
|
-
// the gaps between cards, but the cards themselves
|
|
9027
|
-
|
|
9024
|
+
// sectionKey and laneKey ride along so a drop *onto a card* resolves to
|
|
9025
|
+
// that card's section and lane, not just its column (the section bands
|
|
9026
|
+
// and lane rows cover the gaps between cards, but the cards themselves
|
|
9027
|
+
// are the sortable).
|
|
9028
|
+
data: {
|
|
9029
|
+
columnKey: item.columnKey,
|
|
9030
|
+
sectionKey: item.sectionKey,
|
|
9031
|
+
laneKey: item.laneKey
|
|
9032
|
+
}
|
|
9028
9033
|
});
|
|
9029
9034
|
const priority_var = item.priority ? `--hazo-kanban-priority-${String(item.priority).toLowerCase()}` : null;
|
|
9030
9035
|
const style = {
|
|
@@ -9085,8 +9090,16 @@ function KanbanCard({
|
|
|
9085
9090
|
}
|
|
9086
9091
|
);
|
|
9087
9092
|
}
|
|
9088
|
-
function
|
|
9089
|
-
return `
|
|
9093
|
+
function tree_droppable_id(prefix, tree_key, lane_key, rest) {
|
|
9094
|
+
return lane_key == null ? `${prefix}:${tree_key}::${rest}` : `${prefix}:${tree_key}::${lane_key}::${rest}`;
|
|
9095
|
+
}
|
|
9096
|
+
function section_droppable_id(column_key, section_key, tree_key, lane_key) {
|
|
9097
|
+
return tree_droppable_id(
|
|
9098
|
+
"section",
|
|
9099
|
+
tree_key,
|
|
9100
|
+
lane_key,
|
|
9101
|
+
`${column_key}::${section_key}`
|
|
9102
|
+
);
|
|
9090
9103
|
}
|
|
9091
9104
|
function group_items_by_section(items, sections) {
|
|
9092
9105
|
const bySection = /* @__PURE__ */ new Map();
|
|
@@ -9106,11 +9119,13 @@ function KanbanColumn({
|
|
|
9106
9119
|
emptyColumn,
|
|
9107
9120
|
cardClassName,
|
|
9108
9121
|
showEdit,
|
|
9109
|
-
onEditRequest
|
|
9122
|
+
onEditRequest,
|
|
9123
|
+
laneKey,
|
|
9124
|
+
treeKey
|
|
9110
9125
|
}) {
|
|
9111
9126
|
const { setNodeRef, isOver } = useDroppable({
|
|
9112
|
-
id:
|
|
9113
|
-
data: { columnKey: column.key, isColumn: true }
|
|
9127
|
+
id: tree_droppable_id("column", treeKey, laneKey, column.key),
|
|
9128
|
+
data: { columnKey: column.key, laneKey, isColumn: true }
|
|
9114
9129
|
});
|
|
9115
9130
|
const sections = column.sections;
|
|
9116
9131
|
const { bySection, unmatched } = React27.useMemo(
|
|
@@ -9156,6 +9171,8 @@ function KanbanColumn({
|
|
|
9156
9171
|
KanbanColumnHead,
|
|
9157
9172
|
{
|
|
9158
9173
|
columnKey: column.key,
|
|
9174
|
+
laneKey,
|
|
9175
|
+
treeKey,
|
|
9159
9176
|
title: column.title,
|
|
9160
9177
|
count: items.length,
|
|
9161
9178
|
droppable: sections != null
|
|
@@ -9171,6 +9188,8 @@ function KanbanColumn({
|
|
|
9171
9188
|
KanbanSectionBand,
|
|
9172
9189
|
{
|
|
9173
9190
|
columnKey: column.key,
|
|
9191
|
+
laneKey,
|
|
9192
|
+
treeKey,
|
|
9174
9193
|
section,
|
|
9175
9194
|
items: bySection.get(section.key) ?? [],
|
|
9176
9195
|
emptyColumn,
|
|
@@ -9183,6 +9202,8 @@ function KanbanColumn({
|
|
|
9183
9202
|
KanbanSectionStrip,
|
|
9184
9203
|
{
|
|
9185
9204
|
columnKey: column.key,
|
|
9205
|
+
laneKey,
|
|
9206
|
+
treeKey,
|
|
9186
9207
|
section
|
|
9187
9208
|
},
|
|
9188
9209
|
section.key
|
|
@@ -9196,13 +9217,15 @@ function KanbanColumn({
|
|
|
9196
9217
|
}
|
|
9197
9218
|
function KanbanColumnHead({
|
|
9198
9219
|
columnKey,
|
|
9220
|
+
laneKey,
|
|
9221
|
+
treeKey,
|
|
9199
9222
|
title,
|
|
9200
9223
|
count,
|
|
9201
9224
|
droppable
|
|
9202
9225
|
}) {
|
|
9203
9226
|
const { setNodeRef, isOver } = useDroppable({
|
|
9204
|
-
id:
|
|
9205
|
-
data: { columnKey, isColumn: true },
|
|
9227
|
+
id: tree_droppable_id("columnhead", treeKey, laneKey, columnKey),
|
|
9228
|
+
data: { columnKey, laneKey, isColumn: true },
|
|
9206
9229
|
disabled: !droppable
|
|
9207
9230
|
});
|
|
9208
9231
|
return /* @__PURE__ */ jsxs(
|
|
@@ -9223,14 +9246,16 @@ function KanbanColumnHead({
|
|
|
9223
9246
|
}
|
|
9224
9247
|
function KanbanSectionBand({
|
|
9225
9248
|
columnKey,
|
|
9249
|
+
laneKey,
|
|
9250
|
+
treeKey,
|
|
9226
9251
|
section,
|
|
9227
9252
|
items,
|
|
9228
9253
|
emptyColumn,
|
|
9229
9254
|
renderCards
|
|
9230
9255
|
}) {
|
|
9231
9256
|
const { setNodeRef, isOver } = useDroppable({
|
|
9232
|
-
id: section_droppable_id(columnKey, section.key),
|
|
9233
|
-
data: { columnKey, sectionKey: section.key, isSection: true }
|
|
9257
|
+
id: section_droppable_id(columnKey, section.key, treeKey, laneKey),
|
|
9258
|
+
data: { columnKey, laneKey, sectionKey: section.key, isSection: true }
|
|
9234
9259
|
});
|
|
9235
9260
|
return /* @__PURE__ */ jsxs(
|
|
9236
9261
|
"div",
|
|
@@ -9253,11 +9278,13 @@ function KanbanSectionBand({
|
|
|
9253
9278
|
}
|
|
9254
9279
|
function KanbanSectionStrip({
|
|
9255
9280
|
columnKey,
|
|
9281
|
+
laneKey,
|
|
9282
|
+
treeKey,
|
|
9256
9283
|
section
|
|
9257
9284
|
}) {
|
|
9258
9285
|
const { setNodeRef, isOver } = useDroppable({
|
|
9259
|
-
id: section_droppable_id(columnKey, section.key),
|
|
9260
|
-
data: { columnKey, sectionKey: section.key, isSection: true }
|
|
9286
|
+
id: section_droppable_id(columnKey, section.key, treeKey, laneKey),
|
|
9287
|
+
data: { columnKey, laneKey, sectionKey: section.key, isSection: true }
|
|
9261
9288
|
});
|
|
9262
9289
|
return /* @__PURE__ */ jsx(
|
|
9263
9290
|
"div",
|
|
@@ -9271,6 +9298,54 @@ function KanbanSectionStrip({
|
|
|
9271
9298
|
}
|
|
9272
9299
|
);
|
|
9273
9300
|
}
|
|
9301
|
+
function lane_droppable_id(lane_key, tree_key) {
|
|
9302
|
+
return `lane:${tree_key}::${lane_key}`;
|
|
9303
|
+
}
|
|
9304
|
+
function KanbanLaneHead({
|
|
9305
|
+
lane,
|
|
9306
|
+
count,
|
|
9307
|
+
treeKey
|
|
9308
|
+
}) {
|
|
9309
|
+
const { setNodeRef, isOver } = useDroppable({
|
|
9310
|
+
id: lane_droppable_id(lane.key, treeKey),
|
|
9311
|
+
data: { laneKey: lane.key, isLane: true }
|
|
9312
|
+
});
|
|
9313
|
+
return /* @__PURE__ */ jsxs(
|
|
9314
|
+
"div",
|
|
9315
|
+
{
|
|
9316
|
+
ref: setNodeRef,
|
|
9317
|
+
className: cn(
|
|
9318
|
+
"cls_hazo_kanban_lane_head mb-2 flex items-center gap-3 rounded-sm px-1 py-1",
|
|
9319
|
+
isOver && "cls_hazo_kanban_lane_head_over bg-accent/30 ring-1 ring-ring/40"
|
|
9320
|
+
),
|
|
9321
|
+
children: [
|
|
9322
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_title text-xs font-semibold uppercase tracking-wider text-foreground", children: lane.title }),
|
|
9323
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_rule h-px flex-1 bg-border" }),
|
|
9324
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_count rounded-full bg-muted px-2 py-0.5 text-[11px] tabular-nums text-foreground", children: count })
|
|
9325
|
+
]
|
|
9326
|
+
}
|
|
9327
|
+
);
|
|
9328
|
+
}
|
|
9329
|
+
function KanbanLaneStrip({
|
|
9330
|
+
lane,
|
|
9331
|
+
treeKey
|
|
9332
|
+
}) {
|
|
9333
|
+
const { setNodeRef, isOver } = useDroppable({
|
|
9334
|
+
id: lane_droppable_id(lane.key, treeKey),
|
|
9335
|
+
data: { laneKey: lane.key, isLane: true }
|
|
9336
|
+
});
|
|
9337
|
+
return /* @__PURE__ */ jsx(
|
|
9338
|
+
"div",
|
|
9339
|
+
{
|
|
9340
|
+
ref: setNodeRef,
|
|
9341
|
+
className: cn(
|
|
9342
|
+
"cls_hazo_kanban_lane_strip mb-2 rounded-md border border-dashed border-border px-2 py-1 text-[11px] uppercase tracking-wider text-muted-foreground",
|
|
9343
|
+
isOver && "cls_hazo_kanban_lane_strip_over border-solid bg-accent/30 text-foreground ring-1 ring-ring/30"
|
|
9344
|
+
),
|
|
9345
|
+
children: lane.title
|
|
9346
|
+
}
|
|
9347
|
+
);
|
|
9348
|
+
}
|
|
9274
9349
|
var DEFAULT_PRIORITIES = ["P0", "P1", "P2", "P3"];
|
|
9275
9350
|
function humanize(key) {
|
|
9276
9351
|
return key.replace(/[_\-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\s+/g, " ").trim().split(" ").map((w) => w ? w[0].toUpperCase() + w.slice(1) : w).join(" ");
|
|
@@ -9677,6 +9752,10 @@ function applyKanbanFilter(items, filter) {
|
|
|
9677
9752
|
return true;
|
|
9678
9753
|
});
|
|
9679
9754
|
}
|
|
9755
|
+
var UNMATCHED_LANE_KEY = "__hazo_lane_unmatched__";
|
|
9756
|
+
function bucket_key(lane_key, column_key) {
|
|
9757
|
+
return lane_key == null ? column_key : `${lane_key}\0${column_key}`;
|
|
9758
|
+
}
|
|
9680
9759
|
function default_announcements(itemLabel) {
|
|
9681
9760
|
return {
|
|
9682
9761
|
onDragStart: ({ item, fromColumn }) => `Picked up ${itemLabel(item)}. Currently in ${fromColumn}. Use arrow keys to choose a different column. Press space to drop, escape to cancel.`,
|
|
@@ -9685,38 +9764,50 @@ function default_announcements(itemLabel) {
|
|
|
9685
9764
|
onDragCancel: ({ item, fromColumn }) => `Movement cancelled. ${itemLabel(item)} returned to ${fromColumn}.`
|
|
9686
9765
|
};
|
|
9687
9766
|
}
|
|
9688
|
-
function group_items_by_column(items, overlay, columns) {
|
|
9767
|
+
function group_items_by_column(items, overlay, columns, lanes) {
|
|
9689
9768
|
const out = /* @__PURE__ */ new Map();
|
|
9690
|
-
|
|
9769
|
+
const lane_keys = lanes ? [...lanes.map((l) => l.key), UNMATCHED_LANE_KEY] : [void 0];
|
|
9770
|
+
for (const lane_key of lane_keys)
|
|
9771
|
+
for (const col of columns) out.set(bucket_key(lane_key, col.key), []);
|
|
9691
9772
|
const overlay_inserts = /* @__PURE__ */ new Map();
|
|
9692
|
-
for (const
|
|
9773
|
+
for (const key of out.keys()) overlay_inserts.set(key, []);
|
|
9774
|
+
const declared = lanes ? new Set(lanes.map((l) => l.key)) : null;
|
|
9775
|
+
function resolve_lane(lane_key) {
|
|
9776
|
+
if (!declared) return void 0;
|
|
9777
|
+
return lane_key != null && declared.has(lane_key) ? lane_key : UNMATCHED_LANE_KEY;
|
|
9778
|
+
}
|
|
9693
9779
|
for (const item of items) {
|
|
9694
9780
|
const ov = overlay.get(item.id);
|
|
9695
9781
|
if (ov) {
|
|
9696
|
-
const bucket = overlay_inserts.get(
|
|
9782
|
+
const bucket = overlay_inserts.get(
|
|
9783
|
+
bucket_key(resolve_lane(ov.laneKey), ov.columnKey)
|
|
9784
|
+
);
|
|
9697
9785
|
if (bucket) {
|
|
9698
|
-
const placed = ov.sectionKey === item.sectionKey ? item : { ...item, sectionKey: ov.sectionKey };
|
|
9786
|
+
const placed = ov.sectionKey === item.sectionKey && ov.laneKey === item.laneKey ? item : { ...item, sectionKey: ov.sectionKey, laneKey: ov.laneKey };
|
|
9699
9787
|
bucket.push({ item: placed, index: ov.index });
|
|
9700
9788
|
}
|
|
9701
9789
|
} else {
|
|
9702
|
-
const bucket = out.get(
|
|
9790
|
+
const bucket = out.get(
|
|
9791
|
+
bucket_key(resolve_lane(item.laneKey), item.columnKey)
|
|
9792
|
+
);
|
|
9703
9793
|
if (bucket) bucket.push(item);
|
|
9704
9794
|
}
|
|
9705
9795
|
}
|
|
9706
|
-
for (const
|
|
9707
|
-
|
|
9796
|
+
for (const [key, inserts] of overlay_inserts) {
|
|
9797
|
+
if (inserts.length === 0) continue;
|
|
9708
9798
|
inserts.sort((a, b) => a.index - b.index);
|
|
9709
|
-
const arr = out.get(
|
|
9799
|
+
const arr = out.get(key) ?? [];
|
|
9710
9800
|
for (const { item, index } of inserts) {
|
|
9711
9801
|
const at = Math.max(0, Math.min(index, arr.length));
|
|
9712
9802
|
arr.splice(at, 0, item);
|
|
9713
9803
|
}
|
|
9714
|
-
out.set(
|
|
9804
|
+
out.set(key, arr);
|
|
9715
9805
|
}
|
|
9716
9806
|
return out;
|
|
9717
9807
|
}
|
|
9718
9808
|
function HazoUiKanban({
|
|
9719
9809
|
columns,
|
|
9810
|
+
lanes,
|
|
9720
9811
|
items,
|
|
9721
9812
|
renderCard,
|
|
9722
9813
|
onMove,
|
|
@@ -9764,7 +9855,7 @@ function HazoUiKanban({
|
|
|
9764
9855
|
const next = new Map(prev);
|
|
9765
9856
|
for (const [item_id, pos] of prev.entries()) {
|
|
9766
9857
|
const item = items.find((i) => i.id === item_id);
|
|
9767
|
-
if (item && item.columnKey === pos.columnKey && item.sectionKey === pos.sectionKey) {
|
|
9858
|
+
if (item && item.columnKey === pos.columnKey && item.sectionKey === pos.sectionKey && item.laneKey === pos.laneKey) {
|
|
9768
9859
|
next.delete(item_id);
|
|
9769
9860
|
changed = true;
|
|
9770
9861
|
}
|
|
@@ -9773,8 +9864,8 @@ function HazoUiKanban({
|
|
|
9773
9864
|
});
|
|
9774
9865
|
}, [items, overlay]);
|
|
9775
9866
|
const grouped = React27.useMemo(
|
|
9776
|
-
() => group_items_by_column(items, overlay, columns),
|
|
9777
|
-
[items, overlay, columns]
|
|
9867
|
+
() => group_items_by_column(items, overlay, columns, lanes),
|
|
9868
|
+
[items, overlay, columns, lanes]
|
|
9778
9869
|
);
|
|
9779
9870
|
const find_item = React27.useCallback(
|
|
9780
9871
|
(id) => items.find((i) => i.id === id),
|
|
@@ -9784,6 +9875,13 @@ function HazoUiKanban({
|
|
|
9784
9875
|
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
|
|
9785
9876
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
9786
9877
|
);
|
|
9878
|
+
const collision_detection = React27.useCallback((args) => {
|
|
9879
|
+
const under_pointer = pointerWithin(args);
|
|
9880
|
+
if (under_pointer.length > 0) return under_pointer;
|
|
9881
|
+
const overlapping = rectIntersection(args);
|
|
9882
|
+
if (overlapping.length > 0) return overlapping;
|
|
9883
|
+
return closestCorners(args);
|
|
9884
|
+
}, []);
|
|
9787
9885
|
const merged_announcements = React27.useMemo(() => {
|
|
9788
9886
|
const defaults = default_announcements(label_fn);
|
|
9789
9887
|
return {
|
|
@@ -9812,7 +9910,7 @@ function HazoUiKanban({
|
|
|
9812
9910
|
const id = String(active.id);
|
|
9813
9911
|
const item = find_item(id);
|
|
9814
9912
|
if (!item) return "";
|
|
9815
|
-
const over_col_key = over ? over.data?.current?.columnKey ??
|
|
9913
|
+
const over_col_key = over ? over.data?.current?.columnKey ?? item.columnKey : null;
|
|
9816
9914
|
const col = over_col_key ? columns.find((c) => c.key === over_col_key) : null;
|
|
9817
9915
|
return merged_announcements.onDragOver({
|
|
9818
9916
|
item,
|
|
@@ -9827,10 +9925,13 @@ function HazoUiKanban({
|
|
|
9827
9925
|
const item = find_item(id);
|
|
9828
9926
|
if (!item) return "";
|
|
9829
9927
|
const from_col = columns.find((c) => c.key === item.columnKey);
|
|
9830
|
-
const over_col_key = over
|
|
9928
|
+
const over_col_key = over?.data?.current?.columnKey ?? item.columnKey;
|
|
9929
|
+
const over_lane_key = lanes ? over?.data?.current?.laneKey ?? item.laneKey : void 0;
|
|
9831
9930
|
const to_col = over_col_key ? columns.find((c) => c.key === over_col_key) ?? from_col : from_col;
|
|
9832
|
-
const target =
|
|
9833
|
-
|
|
9931
|
+
const target = grouped.get(
|
|
9932
|
+
bucket_key(over_lane_key, over_col_key ?? item.columnKey)
|
|
9933
|
+
) ?? [];
|
|
9934
|
+
const on_shell = !over || String(over.id).startsWith("column:") || String(over.id).startsWith("columnhead:") || String(over.id).startsWith("section:") || String(over.id).startsWith("lane:");
|
|
9834
9935
|
const new_index = on_shell ? target.length : target.findIndex((it) => it.id === String(over.id));
|
|
9835
9936
|
return merged_announcements.onDragEnd({
|
|
9836
9937
|
item,
|
|
@@ -9850,7 +9951,7 @@ function HazoUiKanban({
|
|
|
9850
9951
|
});
|
|
9851
9952
|
}
|
|
9852
9953
|
}),
|
|
9853
|
-
[find_item, columns, grouped, merged_announcements]
|
|
9954
|
+
[find_item, columns, lanes, grouped, merged_announcements]
|
|
9854
9955
|
);
|
|
9855
9956
|
const handle_drag_start = React27.useCallback((event) => {
|
|
9856
9957
|
set_active_id(String(event.active.id));
|
|
@@ -9877,31 +9978,35 @@ function HazoUiKanban({
|
|
|
9877
9978
|
if (!event.over) return;
|
|
9878
9979
|
const over_id = String(event.over.id);
|
|
9879
9980
|
const over_data = event.over.data?.current;
|
|
9880
|
-
const dest_column_key = over_data?.columnKey ??
|
|
9981
|
+
const dest_column_key = over_data?.columnKey ?? item.columnKey;
|
|
9881
9982
|
const dest_column = columns.find((c) => c.key === dest_column_key);
|
|
9882
9983
|
if (!dest_column) return;
|
|
9984
|
+
const dest_lane_key = lanes ? over_data?.laneKey ?? item.laneKey : void 0;
|
|
9985
|
+
const dest_lane = lanes?.find((l) => l.key === dest_lane_key);
|
|
9986
|
+
if (lanes && dest_lane?.accepts && !dest_lane.accepts(item)) return;
|
|
9883
9987
|
const dest_section_key = dest_column.sections ? over_data?.sectionKey ?? item.sectionKey : void 0;
|
|
9884
9988
|
const dest_section = dest_column.sections?.find(
|
|
9885
9989
|
(s) => s.key === dest_section_key
|
|
9886
9990
|
);
|
|
9887
9991
|
if (dest_column.accepts && !dest_column.accepts(item)) return;
|
|
9888
9992
|
if (dest_section?.accepts && !dest_section.accepts(item)) return;
|
|
9889
|
-
const dest_items_pre_overlay = grouped.get(dest_column_key) ?? [];
|
|
9993
|
+
const dest_items_pre_overlay = grouped.get(bucket_key(dest_lane_key, dest_column_key)) ?? [];
|
|
9890
9994
|
let new_index;
|
|
9891
|
-
if (over_data?.isColumn || over_data?.isSection) {
|
|
9995
|
+
if (over_data?.isColumn || over_data?.isSection || over_data?.isLane) {
|
|
9892
9996
|
new_index = dest_items_pre_overlay.length;
|
|
9893
9997
|
} else {
|
|
9894
9998
|
const idx = dest_items_pre_overlay.findIndex((i) => i.id === over_id);
|
|
9895
9999
|
new_index = idx === -1 ? dest_items_pre_overlay.length : idx;
|
|
9896
10000
|
}
|
|
9897
10001
|
const handle = make_revert_handle(active_id_str);
|
|
9898
|
-
if (item.columnKey === dest_column_key && item.sectionKey === dest_section_key) {
|
|
10002
|
+
if (item.columnKey === dest_column_key && item.sectionKey === dest_section_key && item.laneKey === dest_lane_key) {
|
|
9899
10003
|
if (active_id_str === over_id) return;
|
|
9900
10004
|
set_overlay((prev) => {
|
|
9901
10005
|
const next = new Map(prev);
|
|
9902
10006
|
next.set(active_id_str, {
|
|
9903
10007
|
columnKey: dest_column_key,
|
|
9904
10008
|
sectionKey: dest_section_key,
|
|
10009
|
+
laneKey: dest_lane_key,
|
|
9905
10010
|
index: new_index
|
|
9906
10011
|
});
|
|
9907
10012
|
return next;
|
|
@@ -9911,6 +10016,7 @@ function HazoUiKanban({
|
|
|
9911
10016
|
item,
|
|
9912
10017
|
columnKey: dest_column_key,
|
|
9913
10018
|
sectionKey: dest_section_key,
|
|
10019
|
+
laneKey: dest_lane_key,
|
|
9914
10020
|
newIndex: new_index,
|
|
9915
10021
|
revert: handle.revert
|
|
9916
10022
|
};
|
|
@@ -9922,6 +10028,7 @@ function HazoUiKanban({
|
|
|
9922
10028
|
next.set(active_id_str, {
|
|
9923
10029
|
columnKey: dest_column_key,
|
|
9924
10030
|
sectionKey: dest_section_key,
|
|
10031
|
+
laneKey: dest_lane_key,
|
|
9925
10032
|
index: new_index
|
|
9926
10033
|
});
|
|
9927
10034
|
return next;
|
|
@@ -9933,12 +10040,14 @@ function HazoUiKanban({
|
|
|
9933
10040
|
toColumn: dest_column_key,
|
|
9934
10041
|
fromSection: item.sectionKey,
|
|
9935
10042
|
toSection: dest_section_key,
|
|
10043
|
+
fromLane: item.laneKey,
|
|
10044
|
+
toLane: dest_lane_key,
|
|
9936
10045
|
newIndex: new_index,
|
|
9937
10046
|
revert: handle.revert
|
|
9938
10047
|
};
|
|
9939
10048
|
onMove?.(move_event);
|
|
9940
10049
|
},
|
|
9941
|
-
[find_item, columns, grouped, onMove, onReorder, make_revert_handle]
|
|
10050
|
+
[find_item, columns, lanes, grouped, onMove, onReorder, make_revert_handle]
|
|
9942
10051
|
);
|
|
9943
10052
|
const handle_drag_cancel = React27.useCallback(() => {
|
|
9944
10053
|
set_active_id(null);
|
|
@@ -9949,13 +10058,56 @@ function HazoUiKanban({
|
|
|
9949
10058
|
`(max-width: ${Math.max(0, mobileBreakpoint - 1)}px)`
|
|
9950
10059
|
);
|
|
9951
10060
|
const mobile_classes = is_custom_breakpoint ? is_mobile_via_query ? "block" : "hidden" : "sm:hidden";
|
|
9952
|
-
const desktop_classes = is_custom_breakpoint ? is_mobile_via_query ? "hidden" : "grid" : "hidden sm:grid";
|
|
10061
|
+
const desktop_classes = is_custom_breakpoint ? is_mobile_via_query ? "hidden" : lanes ? "block" : "grid" : lanes ? "hidden sm:block" : "hidden sm:grid";
|
|
10062
|
+
const grid_style = {
|
|
10063
|
+
gridTemplateColumns: `repeat(${columns.length}, minmax(0, 1fr))`
|
|
10064
|
+
};
|
|
10065
|
+
function lane_total(lane_key) {
|
|
10066
|
+
let total = 0;
|
|
10067
|
+
for (const col of columns)
|
|
10068
|
+
total += (grouped.get(bucket_key(lane_key, col.key)) ?? []).length;
|
|
10069
|
+
return total;
|
|
10070
|
+
}
|
|
10071
|
+
function render_column(col, tree_key, lane_key) {
|
|
10072
|
+
return /* @__PURE__ */ jsx(
|
|
10073
|
+
KanbanColumn,
|
|
10074
|
+
{
|
|
10075
|
+
column: col,
|
|
10076
|
+
laneKey: lane_key,
|
|
10077
|
+
treeKey: tree_key,
|
|
10078
|
+
items: grouped.get(bucket_key(lane_key, col.key)) ?? [],
|
|
10079
|
+
renderCard,
|
|
10080
|
+
emptyColumn,
|
|
10081
|
+
cardClassName,
|
|
10082
|
+
showEdit: show_edit,
|
|
10083
|
+
onEditRequest: handle_edit_request
|
|
10084
|
+
},
|
|
10085
|
+
col.key
|
|
10086
|
+
);
|
|
10087
|
+
}
|
|
10088
|
+
function render_lane_row(lane, tree_key, only_column) {
|
|
10089
|
+
const count = only_column ? (grouped.get(bucket_key(lane.key, only_column.key)) ?? []).length : lane_total(lane.key);
|
|
10090
|
+
if (lane.collapseWhenEmpty && count === 0) {
|
|
10091
|
+
return /* @__PURE__ */ jsx(KanbanLaneStrip, { lane, treeKey: tree_key }, lane.key);
|
|
10092
|
+
}
|
|
10093
|
+
return /* @__PURE__ */ jsxs("div", { className: "cls_hazo_kanban_lane", children: [
|
|
10094
|
+
/* @__PURE__ */ jsx(KanbanLaneHead, { lane, count, treeKey: tree_key }),
|
|
10095
|
+
only_column ? render_column(only_column, tree_key, lane.key) : /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_lane_grid grid gap-3", style: grid_style, children: columns.map((col) => render_column(col, tree_key, lane.key)) })
|
|
10096
|
+
] }, lane.key);
|
|
10097
|
+
}
|
|
10098
|
+
function render_unmatched_lane(tree_key, only_column) {
|
|
10099
|
+
const count = only_column ? (grouped.get(bucket_key(UNMATCHED_LANE_KEY, only_column.key)) ?? []).length : lane_total(UNMATCHED_LANE_KEY);
|
|
10100
|
+
if (count === 0) return null;
|
|
10101
|
+
return /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_lane cls_hazo_kanban_lane_unmatched", children: only_column ? render_column(only_column, tree_key, UNMATCHED_LANE_KEY) : /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_lane_grid grid gap-3", style: grid_style, children: columns.map(
|
|
10102
|
+
(col) => render_column(col, tree_key, UNMATCHED_LANE_KEY)
|
|
10103
|
+
) }) });
|
|
10104
|
+
}
|
|
9953
10105
|
return /* @__PURE__ */ jsxs(
|
|
9954
10106
|
DndContext,
|
|
9955
10107
|
{
|
|
9956
10108
|
id: dnd_context_id,
|
|
9957
10109
|
sensors,
|
|
9958
|
-
collisionDetection:
|
|
10110
|
+
collisionDetection: collision_detection,
|
|
9959
10111
|
onDragStart: handle_drag_start,
|
|
9960
10112
|
onDragEnd: handle_drag_end,
|
|
9961
10113
|
onDragCancel: handle_drag_cancel,
|
|
@@ -9964,43 +10116,33 @@ function HazoUiKanban({
|
|
|
9964
10116
|
/* @__PURE__ */ jsxs("div", { className: cn("cls_hazo_kanban w-full", className), children: [
|
|
9965
10117
|
/* @__PURE__ */ jsx("div", { className: cn("cls_hazo_kanban_mobile", mobile_classes), children: /* @__PURE__ */ jsxs(Tabs, { value: active_tab, onValueChange: set_active_tab, children: [
|
|
9966
10118
|
/* @__PURE__ */ jsx(TabsList, { className: "grid w-full", style: { gridTemplateColumns: `repeat(${columns.length}, 1fr)` }, children: columns.map((col) => {
|
|
9967
|
-
const count =
|
|
10119
|
+
const count = lanes ? lanes.reduce(
|
|
10120
|
+
(n, lane) => n + (grouped.get(bucket_key(lane.key, col.key)) ?? []).length,
|
|
10121
|
+
(grouped.get(bucket_key(UNMATCHED_LANE_KEY, col.key)) ?? []).length
|
|
10122
|
+
) : (grouped.get(col.key) ?? []).length;
|
|
9968
10123
|
return /* @__PURE__ */ jsxs(TabsTrigger, { value: col.key, className: "flex flex-col gap-0.5", children: [
|
|
9969
10124
|
/* @__PURE__ */ jsx("span", { className: "text-xs", children: col.title }),
|
|
9970
10125
|
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: count })
|
|
9971
10126
|
] }, col.key);
|
|
9972
10127
|
}) }),
|
|
9973
|
-
columns.map((col) => /* @__PURE__ */ jsx(TabsContent, { value: col.key, className: "mt-3", children: /* @__PURE__ */
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
items: grouped.get(col.key) ?? [],
|
|
9978
|
-
renderCard,
|
|
9979
|
-
emptyColumn,
|
|
9980
|
-
cardClassName,
|
|
9981
|
-
showEdit: show_edit,
|
|
9982
|
-
onEditRequest: handle_edit_request
|
|
9983
|
-
}
|
|
9984
|
-
) }, col.key))
|
|
10128
|
+
columns.map((col) => /* @__PURE__ */ jsx(TabsContent, { value: col.key, className: "mt-3", children: lanes ? /* @__PURE__ */ jsxs("div", { className: "cls_hazo_kanban_lanes flex flex-col gap-4", children: [
|
|
10129
|
+
lanes.map((lane) => render_lane_row(lane, "m", col)),
|
|
10130
|
+
render_unmatched_lane("m", col)
|
|
10131
|
+
] }) : render_column(col, "m") }, col.key))
|
|
9985
10132
|
] }) }),
|
|
9986
10133
|
/* @__PURE__ */ jsx(
|
|
9987
10134
|
"div",
|
|
9988
10135
|
{
|
|
9989
|
-
className: cn(
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
showEdit: show_edit,
|
|
10000
|
-
onEditRequest: handle_edit_request
|
|
10001
|
-
},
|
|
10002
|
-
col.key
|
|
10003
|
-
))
|
|
10136
|
+
className: cn(
|
|
10137
|
+
"cls_hazo_kanban_desktop",
|
|
10138
|
+
lanes ? "space-y-4" : "gap-3",
|
|
10139
|
+
desktop_classes
|
|
10140
|
+
),
|
|
10141
|
+
style: lanes ? void 0 : grid_style,
|
|
10142
|
+
children: lanes ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10143
|
+
lanes.map((lane) => render_lane_row(lane, "d")),
|
|
10144
|
+
render_unmatched_lane("d")
|
|
10145
|
+
] }) : columns.map((col) => render_column(col, "d"))
|
|
10004
10146
|
}
|
|
10005
10147
|
),
|
|
10006
10148
|
/* @__PURE__ */ jsx(DragOverlay, { children: active_item ? /* @__PURE__ */ jsx(
|