hazo_ui 6.5.0 → 6.7.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 +75 -0
- package/dist/index.cjs +62 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +62 -33
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -1902,6 +1902,17 @@ interface KanbanLane {
|
|
|
1902
1902
|
title: string;
|
|
1903
1903
|
/** Optional gate: returning false rejects a drop into this lane. */
|
|
1904
1904
|
accepts?: (item: KanbanItem) => boolean;
|
|
1905
|
+
/**
|
|
1906
|
+
* Per-lane controls rendered in the lane heading, between the rule and the
|
|
1907
|
+
* count — an "add to this lane" button, an overflow menu, a lane filter.
|
|
1908
|
+
* Also rendered (right-aligned) on a `collapseWhenEmpty` lane's drop strip,
|
|
1909
|
+
* so a lane's actions do not disappear the moment it empties.
|
|
1910
|
+
*
|
|
1911
|
+
* The heading is a drop target but not a drag handle, so interactive nodes
|
|
1912
|
+
* here work without any `stopPropagation` dance — unlike controls rendered
|
|
1913
|
+
* inside a card by `renderCard`.
|
|
1914
|
+
*/
|
|
1915
|
+
actions?: React$1.ReactNode;
|
|
1905
1916
|
/**
|
|
1906
1917
|
* When true and the lane currently holds no cards, it renders as a thin
|
|
1907
1918
|
* full-width drop strip instead of a heading plus an empty column grid.
|
|
@@ -2031,6 +2042,22 @@ interface HazoUiKanbanProps<T extends KanbanItem = KanbanItem> {
|
|
|
2031
2042
|
announcements?: Partial<KanbanAnnouncements>;
|
|
2032
2043
|
/** Rendered when a column has zero items. Default: muted "—" placeholder. */
|
|
2033
2044
|
emptyColumn?: React$1.ReactNode;
|
|
2045
|
+
/**
|
|
2046
|
+
* Rendered at the foot of every column body, below the cards (or below the
|
|
2047
|
+
* `emptyColumn` placeholder). Called once per rendered copy of a column, so
|
|
2048
|
+
* on a laned board it fires once per (lane, column) pair and `laneKey` says
|
|
2049
|
+
* which — that is what makes a per-lane "+ Add item" affordance possible
|
|
2050
|
+
* without the consumer having to reach into the board's internals.
|
|
2051
|
+
*
|
|
2052
|
+
* Return `null` for the columns that should not have one. The footer sits
|
|
2053
|
+
* inside the column's droppable but outside its `SortableContext`, so it
|
|
2054
|
+
* never participates in ordering and never becomes a drop target itself.
|
|
2055
|
+
*/
|
|
2056
|
+
renderColumnFooter?: (ctx: {
|
|
2057
|
+
columnKey: string;
|
|
2058
|
+
/** `undefined` on a board without lanes. */
|
|
2059
|
+
laneKey?: string;
|
|
2060
|
+
}) => React$1.ReactNode;
|
|
2034
2061
|
/** Class on the board root. */
|
|
2035
2062
|
className?: string;
|
|
2036
2063
|
/** Class on each card shell (the wrapper around renderCard output). */
|
|
@@ -2214,7 +2241,7 @@ declare function applyKanbanFilter<T extends KanbanItem>(items: T[], filter: Kan
|
|
|
2214
2241
|
* event.revert() and the overlay entry is dropped.
|
|
2215
2242
|
*/
|
|
2216
2243
|
|
|
2217
|
-
declare function HazoUiKanban<T extends KanbanItem = KanbanItem>({ columns, lanes, items, renderCard, onMove, onReorder, mobileBreakpoint, announcements, emptyColumn, className, cardClassName, itemLabel, editorFields, editorPriorities, editorTitle, renderCardEditor, hideEditorFooter, onCardSave, disableEdit, }: HazoUiKanbanProps<T>): React$1.JSX.Element;
|
|
2244
|
+
declare function HazoUiKanban<T extends KanbanItem = KanbanItem>({ columns, lanes, items, renderCard, onMove, onReorder, mobileBreakpoint, announcements, emptyColumn, renderColumnFooter, className, cardClassName, itemLabel, editorFields, editorPriorities, editorTitle, renderCardEditor, hideEditorFooter, onCardSave, disableEdit, }: HazoUiKanbanProps<T>): React$1.JSX.Element;
|
|
2218
2245
|
|
|
2219
2246
|
declare const Table: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableElement> & React$1.RefAttributes<HTMLTableElement>>;
|
|
2220
2247
|
declare const TableHeader: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableSectionElement> & React$1.RefAttributes<HTMLTableSectionElement>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1902,6 +1902,17 @@ interface KanbanLane {
|
|
|
1902
1902
|
title: string;
|
|
1903
1903
|
/** Optional gate: returning false rejects a drop into this lane. */
|
|
1904
1904
|
accepts?: (item: KanbanItem) => boolean;
|
|
1905
|
+
/**
|
|
1906
|
+
* Per-lane controls rendered in the lane heading, between the rule and the
|
|
1907
|
+
* count — an "add to this lane" button, an overflow menu, a lane filter.
|
|
1908
|
+
* Also rendered (right-aligned) on a `collapseWhenEmpty` lane's drop strip,
|
|
1909
|
+
* so a lane's actions do not disappear the moment it empties.
|
|
1910
|
+
*
|
|
1911
|
+
* The heading is a drop target but not a drag handle, so interactive nodes
|
|
1912
|
+
* here work without any `stopPropagation` dance — unlike controls rendered
|
|
1913
|
+
* inside a card by `renderCard`.
|
|
1914
|
+
*/
|
|
1915
|
+
actions?: React$1.ReactNode;
|
|
1905
1916
|
/**
|
|
1906
1917
|
* When true and the lane currently holds no cards, it renders as a thin
|
|
1907
1918
|
* full-width drop strip instead of a heading plus an empty column grid.
|
|
@@ -2031,6 +2042,22 @@ interface HazoUiKanbanProps<T extends KanbanItem = KanbanItem> {
|
|
|
2031
2042
|
announcements?: Partial<KanbanAnnouncements>;
|
|
2032
2043
|
/** Rendered when a column has zero items. Default: muted "—" placeholder. */
|
|
2033
2044
|
emptyColumn?: React$1.ReactNode;
|
|
2045
|
+
/**
|
|
2046
|
+
* Rendered at the foot of every column body, below the cards (or below the
|
|
2047
|
+
* `emptyColumn` placeholder). Called once per rendered copy of a column, so
|
|
2048
|
+
* on a laned board it fires once per (lane, column) pair and `laneKey` says
|
|
2049
|
+
* which — that is what makes a per-lane "+ Add item" affordance possible
|
|
2050
|
+
* without the consumer having to reach into the board's internals.
|
|
2051
|
+
*
|
|
2052
|
+
* Return `null` for the columns that should not have one. The footer sits
|
|
2053
|
+
* inside the column's droppable but outside its `SortableContext`, so it
|
|
2054
|
+
* never participates in ordering and never becomes a drop target itself.
|
|
2055
|
+
*/
|
|
2056
|
+
renderColumnFooter?: (ctx: {
|
|
2057
|
+
columnKey: string;
|
|
2058
|
+
/** `undefined` on a board without lanes. */
|
|
2059
|
+
laneKey?: string;
|
|
2060
|
+
}) => React$1.ReactNode;
|
|
2034
2061
|
/** Class on the board root. */
|
|
2035
2062
|
className?: string;
|
|
2036
2063
|
/** Class on each card shell (the wrapper around renderCard output). */
|
|
@@ -2214,7 +2241,7 @@ declare function applyKanbanFilter<T extends KanbanItem>(items: T[], filter: Kan
|
|
|
2214
2241
|
* event.revert() and the overlay entry is dropped.
|
|
2215
2242
|
*/
|
|
2216
2243
|
|
|
2217
|
-
declare function HazoUiKanban<T extends KanbanItem = KanbanItem>({ columns, lanes, items, renderCard, onMove, onReorder, mobileBreakpoint, announcements, emptyColumn, className, cardClassName, itemLabel, editorFields, editorPriorities, editorTitle, renderCardEditor, hideEditorFooter, onCardSave, disableEdit, }: HazoUiKanbanProps<T>): React$1.JSX.Element;
|
|
2244
|
+
declare function HazoUiKanban<T extends KanbanItem = KanbanItem>({ columns, lanes, items, renderCard, onMove, onReorder, mobileBreakpoint, announcements, emptyColumn, renderColumnFooter, className, cardClassName, itemLabel, editorFields, editorPriorities, editorTitle, renderCardEditor, hideEditorFooter, onCardSave, disableEdit, }: HazoUiKanbanProps<T>): React$1.JSX.Element;
|
|
2218
2245
|
|
|
2219
2246
|
declare const Table: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableElement> & React$1.RefAttributes<HTMLTableElement>>;
|
|
2220
2247
|
declare const TableHeader: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableSectionElement> & React$1.RefAttributes<HTMLTableSectionElement>>;
|
package/dist/index.js
CHANGED
|
@@ -9038,6 +9038,12 @@ function KanbanCard({
|
|
|
9038
9038
|
backgroundColor: "hsl(var(--hazo-kanban-card-bg))",
|
|
9039
9039
|
border: `1px solid hsl(var(--hazo-kanban-card-border))`,
|
|
9040
9040
|
borderLeft: priority_var ? `4px solid hsl(var(${priority_var}))` : `1px solid hsl(var(--hazo-kanban-card-border))`,
|
|
9041
|
+
// Opt-in lift. A card whose background equals the column's (the case for
|
|
9042
|
+
// every palette where --card and --background resolve to the same value)
|
|
9043
|
+
// is separated by nothing but a 1px border, which reads as flat at a
|
|
9044
|
+
// glance. The fallback is `none`, so a consumer that never sets the token
|
|
9045
|
+
// renders exactly as before.
|
|
9046
|
+
boxShadow: "var(--hazo-kanban-card-shadow, none)",
|
|
9041
9047
|
opacity: isDragging && !dragging ? 0.4 : 1,
|
|
9042
9048
|
cursor: "grab"
|
|
9043
9049
|
};
|
|
@@ -9046,6 +9052,9 @@ function KanbanCard({
|
|
|
9046
9052
|
{
|
|
9047
9053
|
ref: setNodeRef,
|
|
9048
9054
|
style,
|
|
9055
|
+
"data-column-key": item.columnKey,
|
|
9056
|
+
"data-lane-key": item.laneKey,
|
|
9057
|
+
"data-section-key": item.sectionKey,
|
|
9049
9058
|
className: cn(
|
|
9050
9059
|
"cls_hazo_kanban_card group relative rounded-md p-3 mb-2 select-none",
|
|
9051
9060
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
@@ -9117,6 +9126,7 @@ function KanbanColumn({
|
|
|
9117
9126
|
items,
|
|
9118
9127
|
renderCard,
|
|
9119
9128
|
emptyColumn,
|
|
9129
|
+
footer,
|
|
9120
9130
|
cardClassName,
|
|
9121
9131
|
showEdit,
|
|
9122
9132
|
onEditRequest,
|
|
@@ -9162,6 +9172,8 @@ function KanbanColumn({
|
|
|
9162
9172
|
"div",
|
|
9163
9173
|
{
|
|
9164
9174
|
ref: setNodeRef,
|
|
9175
|
+
"data-column-key": column.key,
|
|
9176
|
+
"data-lane-key": laneKey,
|
|
9165
9177
|
className: cn(
|
|
9166
9178
|
"cls_hazo_kanban_column flex flex-col rounded-md p-2",
|
|
9167
9179
|
isOver && "cls_hazo_kanban_column_over bg-accent/30 ring-2 ring-ring/40"
|
|
@@ -9183,34 +9195,43 @@ function KanbanColumn({
|
|
|
9183
9195
|
{
|
|
9184
9196
|
items: ordered.map((i) => i.id),
|
|
9185
9197
|
strategy: verticalListSortingStrategy,
|
|
9186
|
-
children: /* @__PURE__ */ jsx(
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
section
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
section
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9198
|
+
children: /* @__PURE__ */ jsx(
|
|
9199
|
+
"div",
|
|
9200
|
+
{
|
|
9201
|
+
"data-column-key": column.key,
|
|
9202
|
+
"data-lane-key": laneKey,
|
|
9203
|
+
className: "cls_hazo_kanban_column_body flex-1 min-h-[40px]",
|
|
9204
|
+
children: !sections ? items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_column_empty text-xs text-muted-foreground py-2 px-1", children: emptyColumn }) : render_cards(items) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
9205
|
+
expanded_sections.map((section) => /* @__PURE__ */ jsx(
|
|
9206
|
+
KanbanSectionBand,
|
|
9207
|
+
{
|
|
9208
|
+
columnKey: column.key,
|
|
9209
|
+
laneKey,
|
|
9210
|
+
treeKey,
|
|
9211
|
+
section,
|
|
9212
|
+
items: bySection.get(section.key) ?? [],
|
|
9213
|
+
emptyColumn,
|
|
9214
|
+
renderCards: render_cards
|
|
9215
|
+
},
|
|
9216
|
+
section.key
|
|
9217
|
+
)),
|
|
9218
|
+
unmatched.length > 0 && /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_section cls_hazo_kanban_section_unmatched", children: render_cards(unmatched) }),
|
|
9219
|
+
collapsed_sections.length > 0 && /* @__PURE__ */ 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__ */ jsx(
|
|
9220
|
+
KanbanSectionStrip,
|
|
9221
|
+
{
|
|
9222
|
+
columnKey: column.key,
|
|
9223
|
+
laneKey,
|
|
9224
|
+
treeKey,
|
|
9225
|
+
section
|
|
9226
|
+
},
|
|
9227
|
+
section.key
|
|
9228
|
+
)) })
|
|
9229
|
+
] })
|
|
9230
|
+
}
|
|
9231
|
+
)
|
|
9212
9232
|
}
|
|
9213
|
-
)
|
|
9233
|
+
),
|
|
9234
|
+
footer ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_column_footer mt-1", children: footer }) : null
|
|
9214
9235
|
]
|
|
9215
9236
|
}
|
|
9216
9237
|
);
|
|
@@ -9232,6 +9253,8 @@ function KanbanColumnHead({
|
|
|
9232
9253
|
"div",
|
|
9233
9254
|
{
|
|
9234
9255
|
ref: droppable ? setNodeRef : void 0,
|
|
9256
|
+
"data-column-key": columnKey,
|
|
9257
|
+
"data-lane-key": laneKey,
|
|
9235
9258
|
className: cn(
|
|
9236
9259
|
"cls_hazo_kanban_column_head mb-2 flex items-center justify-between rounded-sm px-1 text-xs uppercase tracking-wider text-muted-foreground",
|
|
9237
9260
|
droppable && "py-1",
|
|
@@ -9321,6 +9344,7 @@ function KanbanLaneHead({
|
|
|
9321
9344
|
children: [
|
|
9322
9345
|
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_title text-xs font-semibold uppercase tracking-wider text-foreground", children: lane.title }),
|
|
9323
9346
|
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_rule h-px flex-1 bg-border" }),
|
|
9347
|
+
lane.actions ? /* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_actions flex items-center gap-1", children: lane.actions }) : null,
|
|
9324
9348
|
/* @__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
9349
|
]
|
|
9326
9350
|
}
|
|
@@ -9334,15 +9358,18 @@ function KanbanLaneStrip({
|
|
|
9334
9358
|
id: lane_droppable_id(lane.key, treeKey),
|
|
9335
9359
|
data: { laneKey: lane.key, isLane: true }
|
|
9336
9360
|
});
|
|
9337
|
-
return /* @__PURE__ */
|
|
9361
|
+
return /* @__PURE__ */ jsxs(
|
|
9338
9362
|
"div",
|
|
9339
9363
|
{
|
|
9340
9364
|
ref: setNodeRef,
|
|
9341
9365
|
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",
|
|
9366
|
+
"cls_hazo_kanban_lane_strip mb-2 flex items-center gap-3 rounded-md border border-dashed border-border px-2 py-1 text-[11px] uppercase tracking-wider text-muted-foreground",
|
|
9343
9367
|
isOver && "cls_hazo_kanban_lane_strip_over border-solid bg-accent/30 text-foreground ring-1 ring-ring/30"
|
|
9344
9368
|
),
|
|
9345
|
-
children:
|
|
9369
|
+
children: [
|
|
9370
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_title", children: lane.title }),
|
|
9371
|
+
lane.actions ? /* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_lane_actions ml-auto flex items-center gap-1", children: lane.actions }) : null
|
|
9372
|
+
]
|
|
9346
9373
|
}
|
|
9347
9374
|
);
|
|
9348
9375
|
}
|
|
@@ -9815,6 +9842,7 @@ function HazoUiKanban({
|
|
|
9815
9842
|
mobileBreakpoint = 640,
|
|
9816
9843
|
announcements,
|
|
9817
9844
|
emptyColumn = "\u2014",
|
|
9845
|
+
renderColumnFooter,
|
|
9818
9846
|
className,
|
|
9819
9847
|
cardClassName,
|
|
9820
9848
|
itemLabel,
|
|
@@ -10068,7 +10096,7 @@ function HazoUiKanban({
|
|
|
10068
10096
|
total += (grouped.get(bucket_key(lane_key, col.key)) ?? []).length;
|
|
10069
10097
|
return total;
|
|
10070
10098
|
}
|
|
10071
|
-
function render_column(col, tree_key, lane_key) {
|
|
10099
|
+
function render_column(col, tree_key, lane_key, with_footer = true) {
|
|
10072
10100
|
return /* @__PURE__ */ jsx(
|
|
10073
10101
|
KanbanColumn,
|
|
10074
10102
|
{
|
|
@@ -10078,6 +10106,7 @@ function HazoUiKanban({
|
|
|
10078
10106
|
items: grouped.get(bucket_key(lane_key, col.key)) ?? [],
|
|
10079
10107
|
renderCard,
|
|
10080
10108
|
emptyColumn,
|
|
10109
|
+
footer: with_footer ? renderColumnFooter?.({ columnKey: col.key, laneKey: lane_key }) ?? null : null,
|
|
10081
10110
|
cardClassName,
|
|
10082
10111
|
showEdit: show_edit,
|
|
10083
10112
|
onEditRequest: handle_edit_request
|
|
@@ -10098,8 +10127,8 @@ function HazoUiKanban({
|
|
|
10098
10127
|
function render_unmatched_lane(tree_key, only_column) {
|
|
10099
10128
|
const count = only_column ? (grouped.get(bucket_key(UNMATCHED_LANE_KEY, only_column.key)) ?? []).length : lane_total(UNMATCHED_LANE_KEY);
|
|
10100
10129
|
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)
|
|
10130
|
+
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, false) : /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_lane_grid grid gap-3", style: grid_style, children: columns.map(
|
|
10131
|
+
(col) => render_column(col, tree_key, UNMATCHED_LANE_KEY, false)
|
|
10103
10132
|
) }) });
|
|
10104
10133
|
}
|
|
10105
10134
|
return /* @__PURE__ */ jsxs(
|