hazo_ui 6.3.1 → 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 +85 -0
- package/README.md +42 -0
- package/dist/index.cjs +371 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -4
- package/dist/index.d.ts +83 -4
- package/dist/index.js +372 -74
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -9089,7 +9089,18 @@ function KanbanCard({
|
|
|
9089
9089
|
transform,
|
|
9090
9090
|
transition,
|
|
9091
9091
|
isDragging
|
|
9092
|
-
} = sortable.useSortable({
|
|
9092
|
+
} = sortable.useSortable({
|
|
9093
|
+
id: item.id,
|
|
9094
|
+
// sectionKey and laneKey ride along so a drop *onto a card* resolves to
|
|
9095
|
+
// that card's section and lane, not just its column (the section bands
|
|
9096
|
+
// and lane rows cover the gaps between cards, but the cards themselves
|
|
9097
|
+
// are the sortable).
|
|
9098
|
+
data: {
|
|
9099
|
+
columnKey: item.columnKey,
|
|
9100
|
+
sectionKey: item.sectionKey,
|
|
9101
|
+
laneKey: item.laneKey
|
|
9102
|
+
}
|
|
9103
|
+
});
|
|
9093
9104
|
const priority_var = item.priority ? `--hazo-kanban-priority-${String(item.priority).toLowerCase()}` : null;
|
|
9094
9105
|
const style = {
|
|
9095
9106
|
transform: utilities.CSS.Transform.toString(transform),
|
|
@@ -9149,6 +9160,28 @@ function KanbanCard({
|
|
|
9149
9160
|
}
|
|
9150
9161
|
);
|
|
9151
9162
|
}
|
|
9163
|
+
function tree_droppable_id(prefix, tree_key, lane_key, rest) {
|
|
9164
|
+
return lane_key == null ? `${prefix}:${tree_key}::${rest}` : `${prefix}:${tree_key}::${lane_key}::${rest}`;
|
|
9165
|
+
}
|
|
9166
|
+
function section_droppable_id(column_key, section_key, tree_key, lane_key) {
|
|
9167
|
+
return tree_droppable_id(
|
|
9168
|
+
"section",
|
|
9169
|
+
tree_key,
|
|
9170
|
+
lane_key,
|
|
9171
|
+
`${column_key}::${section_key}`
|
|
9172
|
+
);
|
|
9173
|
+
}
|
|
9174
|
+
function group_items_by_section(items, sections) {
|
|
9175
|
+
const bySection = /* @__PURE__ */ new Map();
|
|
9176
|
+
for (const section of sections) bySection.set(section.key, []);
|
|
9177
|
+
const unmatched = [];
|
|
9178
|
+
for (const item of items) {
|
|
9179
|
+
const bucket = item.sectionKey != null ? bySection.get(item.sectionKey) : void 0;
|
|
9180
|
+
if (bucket) bucket.push(item);
|
|
9181
|
+
else unmatched.push(item);
|
|
9182
|
+
}
|
|
9183
|
+
return { bySection, unmatched };
|
|
9184
|
+
}
|
|
9152
9185
|
function KanbanColumn({
|
|
9153
9186
|
column,
|
|
9154
9187
|
items,
|
|
@@ -9156,12 +9189,45 @@ function KanbanColumn({
|
|
|
9156
9189
|
emptyColumn,
|
|
9157
9190
|
cardClassName,
|
|
9158
9191
|
showEdit,
|
|
9159
|
-
onEditRequest
|
|
9192
|
+
onEditRequest,
|
|
9193
|
+
laneKey,
|
|
9194
|
+
treeKey
|
|
9160
9195
|
}) {
|
|
9161
9196
|
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
9162
|
-
id:
|
|
9163
|
-
data: { columnKey: column.key, isColumn: true }
|
|
9197
|
+
id: tree_droppable_id("column", treeKey, laneKey, column.key),
|
|
9198
|
+
data: { columnKey: column.key, laneKey, isColumn: true }
|
|
9164
9199
|
});
|
|
9200
|
+
const sections = column.sections;
|
|
9201
|
+
const { bySection, unmatched } = React27__namespace.useMemo(
|
|
9202
|
+
() => sections ? group_items_by_section(items, sections) : { bySection: /* @__PURE__ */ new Map(), unmatched: items },
|
|
9203
|
+
[items, sections]
|
|
9204
|
+
);
|
|
9205
|
+
const ordered = React27__namespace.useMemo(() => {
|
|
9206
|
+
if (!sections) return items;
|
|
9207
|
+
const out = [];
|
|
9208
|
+
for (const section of sections) out.push(...bySection.get(section.key) ?? []);
|
|
9209
|
+
out.push(...unmatched);
|
|
9210
|
+
return out;
|
|
9211
|
+
}, [items, sections, bySection, unmatched]);
|
|
9212
|
+
function render_cards(list) {
|
|
9213
|
+
return list.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9214
|
+
KanbanCard,
|
|
9215
|
+
{
|
|
9216
|
+
item,
|
|
9217
|
+
renderCard,
|
|
9218
|
+
cardClassName,
|
|
9219
|
+
showEdit,
|
|
9220
|
+
onEditRequest
|
|
9221
|
+
},
|
|
9222
|
+
item.id
|
|
9223
|
+
));
|
|
9224
|
+
}
|
|
9225
|
+
const expanded_sections = (sections ?? []).filter(
|
|
9226
|
+
(s) => !(s.collapseWhenEmpty && (bySection.get(s.key) ?? []).length === 0)
|
|
9227
|
+
);
|
|
9228
|
+
const collapsed_sections = (sections ?? []).filter(
|
|
9229
|
+
(s) => s.collapseWhenEmpty && (bySection.get(s.key) ?? []).length === 0
|
|
9230
|
+
);
|
|
9165
9231
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9166
9232
|
"div",
|
|
9167
9233
|
{
|
|
@@ -9171,32 +9237,185 @@ function KanbanColumn({
|
|
|
9171
9237
|
isOver && "cls_hazo_kanban_column_over bg-accent/30 ring-2 ring-ring/40"
|
|
9172
9238
|
),
|
|
9173
9239
|
children: [
|
|
9174
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9240
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9241
|
+
KanbanColumnHead,
|
|
9242
|
+
{
|
|
9243
|
+
columnKey: column.key,
|
|
9244
|
+
laneKey,
|
|
9245
|
+
treeKey,
|
|
9246
|
+
title: column.title,
|
|
9247
|
+
count: items.length,
|
|
9248
|
+
droppable: sections != null
|
|
9249
|
+
}
|
|
9250
|
+
),
|
|
9178
9251
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9179
9252
|
sortable.SortableContext,
|
|
9180
9253
|
{
|
|
9181
|
-
items:
|
|
9254
|
+
items: ordered.map((i) => i.id),
|
|
9182
9255
|
strategy: sortable.verticalListSortingStrategy,
|
|
9183
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_column_body flex-1 min-h-[40px]", children: items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_column_empty text-xs text-muted-foreground py-2 px-1", children: emptyColumn }) : items
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9256
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_column_body flex-1 min-h-[40px]", children: !sections ? items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_column_empty text-xs text-muted-foreground py-2 px-1", children: emptyColumn }) : render_cards(items) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9257
|
+
expanded_sections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9258
|
+
KanbanSectionBand,
|
|
9259
|
+
{
|
|
9260
|
+
columnKey: column.key,
|
|
9261
|
+
laneKey,
|
|
9262
|
+
treeKey,
|
|
9263
|
+
section,
|
|
9264
|
+
items: bySection.get(section.key) ?? [],
|
|
9265
|
+
emptyColumn,
|
|
9266
|
+
renderCards: render_cards
|
|
9267
|
+
},
|
|
9268
|
+
section.key
|
|
9269
|
+
)),
|
|
9270
|
+
unmatched.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_section cls_hazo_kanban_section_unmatched", children: render_cards(unmatched) }),
|
|
9271
|
+
collapsed_sections.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_section_strips mt-2 flex flex-wrap gap-1 border-t border-dashed border-border pt-2", children: collapsed_sections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9272
|
+
KanbanSectionStrip,
|
|
9273
|
+
{
|
|
9274
|
+
columnKey: column.key,
|
|
9275
|
+
laneKey,
|
|
9276
|
+
treeKey,
|
|
9277
|
+
section
|
|
9278
|
+
},
|
|
9279
|
+
section.key
|
|
9280
|
+
)) })
|
|
9281
|
+
] }) })
|
|
9194
9282
|
}
|
|
9195
9283
|
)
|
|
9196
9284
|
]
|
|
9197
9285
|
}
|
|
9198
9286
|
);
|
|
9199
9287
|
}
|
|
9288
|
+
function KanbanColumnHead({
|
|
9289
|
+
columnKey,
|
|
9290
|
+
laneKey,
|
|
9291
|
+
treeKey,
|
|
9292
|
+
title,
|
|
9293
|
+
count,
|
|
9294
|
+
droppable
|
|
9295
|
+
}) {
|
|
9296
|
+
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
9297
|
+
id: tree_droppable_id("columnhead", treeKey, laneKey, columnKey),
|
|
9298
|
+
data: { columnKey, laneKey, isColumn: true },
|
|
9299
|
+
disabled: !droppable
|
|
9300
|
+
});
|
|
9301
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9302
|
+
"div",
|
|
9303
|
+
{
|
|
9304
|
+
ref: droppable ? setNodeRef : void 0,
|
|
9305
|
+
className: cn(
|
|
9306
|
+
"cls_hazo_kanban_column_head mb-2 flex items-center justify-between rounded-sm px-1 text-xs uppercase tracking-wider text-muted-foreground",
|
|
9307
|
+
droppable && "py-1",
|
|
9308
|
+
isOver && "cls_hazo_kanban_column_head_over bg-accent/30 text-foreground ring-1 ring-ring/40"
|
|
9309
|
+
),
|
|
9310
|
+
children: [
|
|
9311
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_column_title", children: title }),
|
|
9312
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_column_count rounded-full bg-muted px-2 py-0.5 text-foreground", children: count })
|
|
9313
|
+
]
|
|
9314
|
+
}
|
|
9315
|
+
);
|
|
9316
|
+
}
|
|
9317
|
+
function KanbanSectionBand({
|
|
9318
|
+
columnKey,
|
|
9319
|
+
laneKey,
|
|
9320
|
+
treeKey,
|
|
9321
|
+
section,
|
|
9322
|
+
items,
|
|
9323
|
+
emptyColumn,
|
|
9324
|
+
renderCards
|
|
9325
|
+
}) {
|
|
9326
|
+
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
9327
|
+
id: section_droppable_id(columnKey, section.key, treeKey, laneKey),
|
|
9328
|
+
data: { columnKey, laneKey, sectionKey: section.key, isSection: true }
|
|
9329
|
+
});
|
|
9330
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9331
|
+
"div",
|
|
9332
|
+
{
|
|
9333
|
+
ref: setNodeRef,
|
|
9334
|
+
className: cn(
|
|
9335
|
+
"cls_hazo_kanban_section rounded-sm",
|
|
9336
|
+
isOver && "cls_hazo_kanban_section_over bg-accent/20 ring-1 ring-ring/30"
|
|
9337
|
+
),
|
|
9338
|
+
children: [
|
|
9339
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cls_hazo_kanban_section_head mt-2 mb-1 flex items-center gap-2 px-1 first:mt-0", children: [
|
|
9340
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_section_title text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: section.title }),
|
|
9341
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_section_rule h-px flex-1 bg-border" }),
|
|
9342
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_section_count text-[11px] tabular-nums text-muted-foreground", children: items.length })
|
|
9343
|
+
] }),
|
|
9344
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_section_body min-h-[32px]", children: items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_section_empty px-1 py-1 text-xs text-muted-foreground", children: emptyColumn }) : renderCards(items) })
|
|
9345
|
+
]
|
|
9346
|
+
}
|
|
9347
|
+
);
|
|
9348
|
+
}
|
|
9349
|
+
function KanbanSectionStrip({
|
|
9350
|
+
columnKey,
|
|
9351
|
+
laneKey,
|
|
9352
|
+
treeKey,
|
|
9353
|
+
section
|
|
9354
|
+
}) {
|
|
9355
|
+
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
9356
|
+
id: section_droppable_id(columnKey, section.key, treeKey, laneKey),
|
|
9357
|
+
data: { columnKey, laneKey, sectionKey: section.key, isSection: true }
|
|
9358
|
+
});
|
|
9359
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9360
|
+
"div",
|
|
9361
|
+
{
|
|
9362
|
+
ref: setNodeRef,
|
|
9363
|
+
className: cn(
|
|
9364
|
+
"cls_hazo_kanban_section_strip rounded-full border border-dashed border-border px-2 py-0.5 text-[11px] text-muted-foreground",
|
|
9365
|
+
isOver && "cls_hazo_kanban_section_strip_over border-solid bg-accent/30 text-foreground ring-1 ring-ring/30"
|
|
9366
|
+
),
|
|
9367
|
+
children: section.title
|
|
9368
|
+
}
|
|
9369
|
+
);
|
|
9370
|
+
}
|
|
9371
|
+
function lane_droppable_id(lane_key, tree_key) {
|
|
9372
|
+
return `lane:${tree_key}::${lane_key}`;
|
|
9373
|
+
}
|
|
9374
|
+
function KanbanLaneHead({
|
|
9375
|
+
lane,
|
|
9376
|
+
count,
|
|
9377
|
+
treeKey
|
|
9378
|
+
}) {
|
|
9379
|
+
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
9380
|
+
id: lane_droppable_id(lane.key, treeKey),
|
|
9381
|
+
data: { laneKey: lane.key, isLane: true }
|
|
9382
|
+
});
|
|
9383
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9384
|
+
"div",
|
|
9385
|
+
{
|
|
9386
|
+
ref: setNodeRef,
|
|
9387
|
+
className: cn(
|
|
9388
|
+
"cls_hazo_kanban_lane_head mb-2 flex items-center gap-3 rounded-sm px-1 py-1",
|
|
9389
|
+
isOver && "cls_hazo_kanban_lane_head_over bg-accent/30 ring-1 ring-ring/40"
|
|
9390
|
+
),
|
|
9391
|
+
children: [
|
|
9392
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_lane_title text-xs font-semibold uppercase tracking-wider text-foreground", children: lane.title }),
|
|
9393
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_hazo_kanban_lane_rule h-px flex-1 bg-border" }),
|
|
9394
|
+
/* @__PURE__ */ jsxRuntime.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 })
|
|
9395
|
+
]
|
|
9396
|
+
}
|
|
9397
|
+
);
|
|
9398
|
+
}
|
|
9399
|
+
function KanbanLaneStrip({
|
|
9400
|
+
lane,
|
|
9401
|
+
treeKey
|
|
9402
|
+
}) {
|
|
9403
|
+
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
9404
|
+
id: lane_droppable_id(lane.key, treeKey),
|
|
9405
|
+
data: { laneKey: lane.key, isLane: true }
|
|
9406
|
+
});
|
|
9407
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9408
|
+
"div",
|
|
9409
|
+
{
|
|
9410
|
+
ref: setNodeRef,
|
|
9411
|
+
className: cn(
|
|
9412
|
+
"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",
|
|
9413
|
+
isOver && "cls_hazo_kanban_lane_strip_over border-solid bg-accent/30 text-foreground ring-1 ring-ring/30"
|
|
9414
|
+
),
|
|
9415
|
+
children: lane.title
|
|
9416
|
+
}
|
|
9417
|
+
);
|
|
9418
|
+
}
|
|
9200
9419
|
var DEFAULT_PRIORITIES = ["P0", "P1", "P2", "P3"];
|
|
9201
9420
|
function humanize(key) {
|
|
9202
9421
|
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(" ");
|
|
@@ -9603,6 +9822,10 @@ function applyKanbanFilter(items, filter) {
|
|
|
9603
9822
|
return true;
|
|
9604
9823
|
});
|
|
9605
9824
|
}
|
|
9825
|
+
var UNMATCHED_LANE_KEY = "__hazo_lane_unmatched__";
|
|
9826
|
+
function bucket_key(lane_key, column_key) {
|
|
9827
|
+
return lane_key == null ? column_key : `${lane_key}\0${column_key}`;
|
|
9828
|
+
}
|
|
9606
9829
|
function default_announcements(itemLabel) {
|
|
9607
9830
|
return {
|
|
9608
9831
|
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.`,
|
|
@@ -9611,37 +9834,50 @@ function default_announcements(itemLabel) {
|
|
|
9611
9834
|
onDragCancel: ({ item, fromColumn }) => `Movement cancelled. ${itemLabel(item)} returned to ${fromColumn}.`
|
|
9612
9835
|
};
|
|
9613
9836
|
}
|
|
9614
|
-
function group_items_by_column(items, overlay, columns) {
|
|
9837
|
+
function group_items_by_column(items, overlay, columns, lanes) {
|
|
9615
9838
|
const out = /* @__PURE__ */ new Map();
|
|
9616
|
-
|
|
9839
|
+
const lane_keys = lanes ? [...lanes.map((l) => l.key), UNMATCHED_LANE_KEY] : [void 0];
|
|
9840
|
+
for (const lane_key of lane_keys)
|
|
9841
|
+
for (const col of columns) out.set(bucket_key(lane_key, col.key), []);
|
|
9617
9842
|
const overlay_inserts = /* @__PURE__ */ new Map();
|
|
9618
|
-
for (const
|
|
9843
|
+
for (const key of out.keys()) overlay_inserts.set(key, []);
|
|
9844
|
+
const declared = lanes ? new Set(lanes.map((l) => l.key)) : null;
|
|
9845
|
+
function resolve_lane(lane_key) {
|
|
9846
|
+
if (!declared) return void 0;
|
|
9847
|
+
return lane_key != null && declared.has(lane_key) ? lane_key : UNMATCHED_LANE_KEY;
|
|
9848
|
+
}
|
|
9619
9849
|
for (const item of items) {
|
|
9620
9850
|
const ov = overlay.get(item.id);
|
|
9621
9851
|
if (ov) {
|
|
9622
|
-
const bucket = overlay_inserts.get(
|
|
9852
|
+
const bucket = overlay_inserts.get(
|
|
9853
|
+
bucket_key(resolve_lane(ov.laneKey), ov.columnKey)
|
|
9854
|
+
);
|
|
9623
9855
|
if (bucket) {
|
|
9624
|
-
|
|
9856
|
+
const placed = ov.sectionKey === item.sectionKey && ov.laneKey === item.laneKey ? item : { ...item, sectionKey: ov.sectionKey, laneKey: ov.laneKey };
|
|
9857
|
+
bucket.push({ item: placed, index: ov.index });
|
|
9625
9858
|
}
|
|
9626
9859
|
} else {
|
|
9627
|
-
const bucket = out.get(
|
|
9860
|
+
const bucket = out.get(
|
|
9861
|
+
bucket_key(resolve_lane(item.laneKey), item.columnKey)
|
|
9862
|
+
);
|
|
9628
9863
|
if (bucket) bucket.push(item);
|
|
9629
9864
|
}
|
|
9630
9865
|
}
|
|
9631
|
-
for (const
|
|
9632
|
-
|
|
9866
|
+
for (const [key, inserts] of overlay_inserts) {
|
|
9867
|
+
if (inserts.length === 0) continue;
|
|
9633
9868
|
inserts.sort((a, b) => a.index - b.index);
|
|
9634
|
-
const arr = out.get(
|
|
9869
|
+
const arr = out.get(key) ?? [];
|
|
9635
9870
|
for (const { item, index } of inserts) {
|
|
9636
9871
|
const at = Math.max(0, Math.min(index, arr.length));
|
|
9637
9872
|
arr.splice(at, 0, item);
|
|
9638
9873
|
}
|
|
9639
|
-
out.set(
|
|
9874
|
+
out.set(key, arr);
|
|
9640
9875
|
}
|
|
9641
9876
|
return out;
|
|
9642
9877
|
}
|
|
9643
9878
|
function HazoUiKanban({
|
|
9644
9879
|
columns,
|
|
9880
|
+
lanes,
|
|
9645
9881
|
items,
|
|
9646
9882
|
renderCard,
|
|
9647
9883
|
onMove,
|
|
@@ -9689,7 +9925,7 @@ function HazoUiKanban({
|
|
|
9689
9925
|
const next = new Map(prev);
|
|
9690
9926
|
for (const [item_id, pos] of prev.entries()) {
|
|
9691
9927
|
const item = items.find((i) => i.id === item_id);
|
|
9692
|
-
if (item && item.columnKey === pos.columnKey) {
|
|
9928
|
+
if (item && item.columnKey === pos.columnKey && item.sectionKey === pos.sectionKey && item.laneKey === pos.laneKey) {
|
|
9693
9929
|
next.delete(item_id);
|
|
9694
9930
|
changed = true;
|
|
9695
9931
|
}
|
|
@@ -9698,8 +9934,8 @@ function HazoUiKanban({
|
|
|
9698
9934
|
});
|
|
9699
9935
|
}, [items, overlay]);
|
|
9700
9936
|
const grouped = React27__namespace.useMemo(
|
|
9701
|
-
() => group_items_by_column(items, overlay, columns),
|
|
9702
|
-
[items, overlay, columns]
|
|
9937
|
+
() => group_items_by_column(items, overlay, columns, lanes),
|
|
9938
|
+
[items, overlay, columns, lanes]
|
|
9703
9939
|
);
|
|
9704
9940
|
const find_item = React27__namespace.useCallback(
|
|
9705
9941
|
(id) => items.find((i) => i.id === id),
|
|
@@ -9709,6 +9945,13 @@ function HazoUiKanban({
|
|
|
9709
9945
|
core$1.useSensor(core$1.PointerSensor, { activationConstraint: { distance: 5 } }),
|
|
9710
9946
|
core$1.useSensor(core$1.KeyboardSensor, { coordinateGetter: sortable.sortableKeyboardCoordinates })
|
|
9711
9947
|
);
|
|
9948
|
+
const collision_detection = React27__namespace.useCallback((args) => {
|
|
9949
|
+
const under_pointer = core$1.pointerWithin(args);
|
|
9950
|
+
if (under_pointer.length > 0) return under_pointer;
|
|
9951
|
+
const overlapping = core$1.rectIntersection(args);
|
|
9952
|
+
if (overlapping.length > 0) return overlapping;
|
|
9953
|
+
return core$1.closestCorners(args);
|
|
9954
|
+
}, []);
|
|
9712
9955
|
const merged_announcements = React27__namespace.useMemo(() => {
|
|
9713
9956
|
const defaults = default_announcements(label_fn);
|
|
9714
9957
|
return {
|
|
@@ -9737,7 +9980,7 @@ function HazoUiKanban({
|
|
|
9737
9980
|
const id = String(active.id);
|
|
9738
9981
|
const item = find_item(id);
|
|
9739
9982
|
if (!item) return "";
|
|
9740
|
-
const over_col_key = over ? over.data?.current?.columnKey ??
|
|
9983
|
+
const over_col_key = over ? over.data?.current?.columnKey ?? item.columnKey : null;
|
|
9741
9984
|
const col = over_col_key ? columns.find((c) => c.key === over_col_key) : null;
|
|
9742
9985
|
return merged_announcements.onDragOver({
|
|
9743
9986
|
item,
|
|
@@ -9752,10 +9995,14 @@ function HazoUiKanban({
|
|
|
9752
9995
|
const item = find_item(id);
|
|
9753
9996
|
if (!item) return "";
|
|
9754
9997
|
const from_col = columns.find((c) => c.key === item.columnKey);
|
|
9755
|
-
const over_col_key = over
|
|
9998
|
+
const over_col_key = over?.data?.current?.columnKey ?? item.columnKey;
|
|
9999
|
+
const over_lane_key = lanes ? over?.data?.current?.laneKey ?? item.laneKey : void 0;
|
|
9756
10000
|
const to_col = over_col_key ? columns.find((c) => c.key === over_col_key) ?? from_col : from_col;
|
|
9757
|
-
const target =
|
|
9758
|
-
|
|
10001
|
+
const target = grouped.get(
|
|
10002
|
+
bucket_key(over_lane_key, over_col_key ?? item.columnKey)
|
|
10003
|
+
) ?? [];
|
|
10004
|
+
const on_shell = !over || String(over.id).startsWith("column:") || String(over.id).startsWith("columnhead:") || String(over.id).startsWith("section:") || String(over.id).startsWith("lane:");
|
|
10005
|
+
const new_index = on_shell ? target.length : target.findIndex((it) => it.id === String(over.id));
|
|
9759
10006
|
return merged_announcements.onDragEnd({
|
|
9760
10007
|
item,
|
|
9761
10008
|
fromColumn: from_col?.title ?? item.columnKey,
|
|
@@ -9774,7 +10021,7 @@ function HazoUiKanban({
|
|
|
9774
10021
|
});
|
|
9775
10022
|
}
|
|
9776
10023
|
}),
|
|
9777
|
-
[find_item, columns, grouped, merged_announcements]
|
|
10024
|
+
[find_item, columns, lanes, grouped, merged_announcements]
|
|
9778
10025
|
);
|
|
9779
10026
|
const handle_drag_start = React27__namespace.useCallback((event) => {
|
|
9780
10027
|
set_active_id(String(event.active.id));
|
|
@@ -9801,25 +10048,35 @@ function HazoUiKanban({
|
|
|
9801
10048
|
if (!event.over) return;
|
|
9802
10049
|
const over_id = String(event.over.id);
|
|
9803
10050
|
const over_data = event.over.data?.current;
|
|
9804
|
-
const dest_column_key = over_data?.columnKey ??
|
|
10051
|
+
const dest_column_key = over_data?.columnKey ?? item.columnKey;
|
|
9805
10052
|
const dest_column = columns.find((c) => c.key === dest_column_key);
|
|
9806
10053
|
if (!dest_column) return;
|
|
10054
|
+
const dest_lane_key = lanes ? over_data?.laneKey ?? item.laneKey : void 0;
|
|
10055
|
+
const dest_lane = lanes?.find((l) => l.key === dest_lane_key);
|
|
10056
|
+
if (lanes && dest_lane?.accepts && !dest_lane.accepts(item)) return;
|
|
10057
|
+
const dest_section_key = dest_column.sections ? over_data?.sectionKey ?? item.sectionKey : void 0;
|
|
10058
|
+
const dest_section = dest_column.sections?.find(
|
|
10059
|
+
(s) => s.key === dest_section_key
|
|
10060
|
+
);
|
|
9807
10061
|
if (dest_column.accepts && !dest_column.accepts(item)) return;
|
|
9808
|
-
|
|
10062
|
+
if (dest_section?.accepts && !dest_section.accepts(item)) return;
|
|
10063
|
+
const dest_items_pre_overlay = grouped.get(bucket_key(dest_lane_key, dest_column_key)) ?? [];
|
|
9809
10064
|
let new_index;
|
|
9810
|
-
if (over_data?.isColumn) {
|
|
10065
|
+
if (over_data?.isColumn || over_data?.isSection || over_data?.isLane) {
|
|
9811
10066
|
new_index = dest_items_pre_overlay.length;
|
|
9812
10067
|
} else {
|
|
9813
10068
|
const idx = dest_items_pre_overlay.findIndex((i) => i.id === over_id);
|
|
9814
10069
|
new_index = idx === -1 ? dest_items_pre_overlay.length : idx;
|
|
9815
10070
|
}
|
|
9816
10071
|
const handle = make_revert_handle(active_id_str);
|
|
9817
|
-
if (item.columnKey === dest_column_key) {
|
|
10072
|
+
if (item.columnKey === dest_column_key && item.sectionKey === dest_section_key && item.laneKey === dest_lane_key) {
|
|
9818
10073
|
if (active_id_str === over_id) return;
|
|
9819
10074
|
set_overlay((prev) => {
|
|
9820
10075
|
const next = new Map(prev);
|
|
9821
10076
|
next.set(active_id_str, {
|
|
9822
10077
|
columnKey: dest_column_key,
|
|
10078
|
+
sectionKey: dest_section_key,
|
|
10079
|
+
laneKey: dest_lane_key,
|
|
9823
10080
|
index: new_index
|
|
9824
10081
|
});
|
|
9825
10082
|
return next;
|
|
@@ -9828,6 +10085,8 @@ function HazoUiKanban({
|
|
|
9828
10085
|
itemId: active_id_str,
|
|
9829
10086
|
item,
|
|
9830
10087
|
columnKey: dest_column_key,
|
|
10088
|
+
sectionKey: dest_section_key,
|
|
10089
|
+
laneKey: dest_lane_key,
|
|
9831
10090
|
newIndex: new_index,
|
|
9832
10091
|
revert: handle.revert
|
|
9833
10092
|
};
|
|
@@ -9838,6 +10097,8 @@ function HazoUiKanban({
|
|
|
9838
10097
|
const next = new Map(prev);
|
|
9839
10098
|
next.set(active_id_str, {
|
|
9840
10099
|
columnKey: dest_column_key,
|
|
10100
|
+
sectionKey: dest_section_key,
|
|
10101
|
+
laneKey: dest_lane_key,
|
|
9841
10102
|
index: new_index
|
|
9842
10103
|
});
|
|
9843
10104
|
return next;
|
|
@@ -9847,12 +10108,16 @@ function HazoUiKanban({
|
|
|
9847
10108
|
item,
|
|
9848
10109
|
fromColumn: item.columnKey,
|
|
9849
10110
|
toColumn: dest_column_key,
|
|
10111
|
+
fromSection: item.sectionKey,
|
|
10112
|
+
toSection: dest_section_key,
|
|
10113
|
+
fromLane: item.laneKey,
|
|
10114
|
+
toLane: dest_lane_key,
|
|
9850
10115
|
newIndex: new_index,
|
|
9851
10116
|
revert: handle.revert
|
|
9852
10117
|
};
|
|
9853
10118
|
onMove?.(move_event);
|
|
9854
10119
|
},
|
|
9855
|
-
[find_item, columns, grouped, onMove, onReorder, make_revert_handle]
|
|
10120
|
+
[find_item, columns, lanes, grouped, onMove, onReorder, make_revert_handle]
|
|
9856
10121
|
);
|
|
9857
10122
|
const handle_drag_cancel = React27__namespace.useCallback(() => {
|
|
9858
10123
|
set_active_id(null);
|
|
@@ -9863,13 +10128,56 @@ function HazoUiKanban({
|
|
|
9863
10128
|
`(max-width: ${Math.max(0, mobileBreakpoint - 1)}px)`
|
|
9864
10129
|
);
|
|
9865
10130
|
const mobile_classes = is_custom_breakpoint ? is_mobile_via_query ? "block" : "hidden" : "sm:hidden";
|
|
9866
|
-
const desktop_classes = is_custom_breakpoint ? is_mobile_via_query ? "hidden" : "grid" : "hidden sm:grid";
|
|
10131
|
+
const desktop_classes = is_custom_breakpoint ? is_mobile_via_query ? "hidden" : lanes ? "block" : "grid" : lanes ? "hidden sm:block" : "hidden sm:grid";
|
|
10132
|
+
const grid_style = {
|
|
10133
|
+
gridTemplateColumns: `repeat(${columns.length}, minmax(0, 1fr))`
|
|
10134
|
+
};
|
|
10135
|
+
function lane_total(lane_key) {
|
|
10136
|
+
let total = 0;
|
|
10137
|
+
for (const col of columns)
|
|
10138
|
+
total += (grouped.get(bucket_key(lane_key, col.key)) ?? []).length;
|
|
10139
|
+
return total;
|
|
10140
|
+
}
|
|
10141
|
+
function render_column(col, tree_key, lane_key) {
|
|
10142
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10143
|
+
KanbanColumn,
|
|
10144
|
+
{
|
|
10145
|
+
column: col,
|
|
10146
|
+
laneKey: lane_key,
|
|
10147
|
+
treeKey: tree_key,
|
|
10148
|
+
items: grouped.get(bucket_key(lane_key, col.key)) ?? [],
|
|
10149
|
+
renderCard,
|
|
10150
|
+
emptyColumn,
|
|
10151
|
+
cardClassName,
|
|
10152
|
+
showEdit: show_edit,
|
|
10153
|
+
onEditRequest: handle_edit_request
|
|
10154
|
+
},
|
|
10155
|
+
col.key
|
|
10156
|
+
);
|
|
10157
|
+
}
|
|
10158
|
+
function render_lane_row(lane, tree_key, only_column) {
|
|
10159
|
+
const count = only_column ? (grouped.get(bucket_key(lane.key, only_column.key)) ?? []).length : lane_total(lane.key);
|
|
10160
|
+
if (lane.collapseWhenEmpty && count === 0) {
|
|
10161
|
+
return /* @__PURE__ */ jsxRuntime.jsx(KanbanLaneStrip, { lane, treeKey: tree_key }, lane.key);
|
|
10162
|
+
}
|
|
10163
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cls_hazo_kanban_lane", children: [
|
|
10164
|
+
/* @__PURE__ */ jsxRuntime.jsx(KanbanLaneHead, { lane, count, treeKey: tree_key }),
|
|
10165
|
+
only_column ? render_column(only_column, tree_key, lane.key) : /* @__PURE__ */ jsxRuntime.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)) })
|
|
10166
|
+
] }, lane.key);
|
|
10167
|
+
}
|
|
10168
|
+
function render_unmatched_lane(tree_key, only_column) {
|
|
10169
|
+
const count = only_column ? (grouped.get(bucket_key(UNMATCHED_LANE_KEY, only_column.key)) ?? []).length : lane_total(UNMATCHED_LANE_KEY);
|
|
10170
|
+
if (count === 0) return null;
|
|
10171
|
+
return /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("div", { className: "cls_hazo_kanban_lane_grid grid gap-3", style: grid_style, children: columns.map(
|
|
10172
|
+
(col) => render_column(col, tree_key, UNMATCHED_LANE_KEY)
|
|
10173
|
+
) }) });
|
|
10174
|
+
}
|
|
9867
10175
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9868
10176
|
core$1.DndContext,
|
|
9869
10177
|
{
|
|
9870
10178
|
id: dnd_context_id,
|
|
9871
10179
|
sensors,
|
|
9872
|
-
collisionDetection:
|
|
10180
|
+
collisionDetection: collision_detection,
|
|
9873
10181
|
onDragStart: handle_drag_start,
|
|
9874
10182
|
onDragEnd: handle_drag_end,
|
|
9875
10183
|
onDragCancel: handle_drag_cancel,
|
|
@@ -9878,43 +10186,33 @@ function HazoUiKanban({
|
|
|
9878
10186
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("cls_hazo_kanban w-full", className), children: [
|
|
9879
10187
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("cls_hazo_kanban_mobile", mobile_classes), children: /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { value: active_tab, onValueChange: set_active_tab, children: [
|
|
9880
10188
|
/* @__PURE__ */ jsxRuntime.jsx(TabsList, { className: "grid w-full", style: { gridTemplateColumns: `repeat(${columns.length}, 1fr)` }, children: columns.map((col) => {
|
|
9881
|
-
const count =
|
|
10189
|
+
const count = lanes ? lanes.reduce(
|
|
10190
|
+
(n, lane) => n + (grouped.get(bucket_key(lane.key, col.key)) ?? []).length,
|
|
10191
|
+
(grouped.get(bucket_key(UNMATCHED_LANE_KEY, col.key)) ?? []).length
|
|
10192
|
+
) : (grouped.get(col.key) ?? []).length;
|
|
9882
10193
|
return /* @__PURE__ */ jsxRuntime.jsxs(TabsTrigger, { value: col.key, className: "flex flex-col gap-0.5", children: [
|
|
9883
10194
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: col.title }),
|
|
9884
10195
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: count })
|
|
9885
10196
|
] }, col.key);
|
|
9886
10197
|
}) }),
|
|
9887
|
-
columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: col.key, className: "mt-3", children: /* @__PURE__ */ jsxRuntime.
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
items: grouped.get(col.key) ?? [],
|
|
9892
|
-
renderCard,
|
|
9893
|
-
emptyColumn,
|
|
9894
|
-
cardClassName,
|
|
9895
|
-
showEdit: show_edit,
|
|
9896
|
-
onEditRequest: handle_edit_request
|
|
9897
|
-
}
|
|
9898
|
-
) }, col.key))
|
|
10198
|
+
columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: col.key, className: "mt-3", children: lanes ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cls_hazo_kanban_lanes flex flex-col gap-4", children: [
|
|
10199
|
+
lanes.map((lane) => render_lane_row(lane, "m", col)),
|
|
10200
|
+
render_unmatched_lane("m", col)
|
|
10201
|
+
] }) : render_column(col, "m") }, col.key))
|
|
9899
10202
|
] }) }),
|
|
9900
10203
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9901
10204
|
"div",
|
|
9902
10205
|
{
|
|
9903
|
-
className: cn(
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
showEdit: show_edit,
|
|
9914
|
-
onEditRequest: handle_edit_request
|
|
9915
|
-
},
|
|
9916
|
-
col.key
|
|
9917
|
-
))
|
|
10206
|
+
className: cn(
|
|
10207
|
+
"cls_hazo_kanban_desktop",
|
|
10208
|
+
lanes ? "space-y-4" : "gap-3",
|
|
10209
|
+
desktop_classes
|
|
10210
|
+
),
|
|
10211
|
+
style: lanes ? void 0 : grid_style,
|
|
10212
|
+
children: lanes ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10213
|
+
lanes.map((lane) => render_lane_row(lane, "d")),
|
|
10214
|
+
render_unmatched_lane("d")
|
|
10215
|
+
] }) : columns.map((col) => render_column(col, "d"))
|
|
9918
10216
|
}
|
|
9919
10217
|
),
|
|
9920
10218
|
/* @__PURE__ */ jsxRuntime.jsx(core$1.DragOverlay, { children: active_item ? /* @__PURE__ */ jsxRuntime.jsx(
|