@stll/ui 0.27.2 → 0.28.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/dist/components/button-variants.d.ts +1 -1
- package/dist/components/input-group.d.ts +1 -1
- package/dist/components/view-toolbar.d.ts +11 -0
- package/dist/components/view-toolbar.js +26 -0
- package/dist/kanban/card-shell.d.ts +3 -1
- package/dist/kanban/card-shell.js +3 -3
- package/dist/kanban/column-header.js +1 -1
- package/dist/kanban/subgroup-board.d.ts +3 -2
- package/dist/kanban/subgroup-board.js +13 -7
- package/dist/kanban/virtual-cell.js +1 -1
- package/dist/lib/overlay-layer.d.ts +7 -0
- package/dist/lib/overlay-layer.js +7 -0
- package/package.json +5 -1
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
export declare const buttonAccessibleDisabledClass = "cursor-not-allowed opacity-64";
|
|
12
12
|
export declare const buttonVariants: (props?: ({
|
|
13
13
|
size?: "default" | "chip" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "lg" | "sm" | "xl" | "xs" | null | undefined;
|
|
14
|
-
variant?: "
|
|
14
|
+
variant?: "default" | "link" | "destructive" | "destructive-outline" | "ghost" | "outline" | "secondary" | null | undefined;
|
|
15
15
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
16
16
|
//#endregion
|
|
@@ -5,7 +5,7 @@ import { VariantProps } from "class-variance-authority";
|
|
|
5
5
|
//#region src/components/input-group.d.ts
|
|
6
6
|
declare const InputGroup: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
|
|
7
7
|
declare const inputGroupAddonVariants: (props?: ({
|
|
8
|
-
align?: "inline-
|
|
8
|
+
align?: "inline-end" | "inline-start" | "block-end" | "block-start" | null | undefined;
|
|
9
9
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
10
|
declare const InputGroupAddon: ({ className, align, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) => React$1.JSX.Element;
|
|
11
11
|
declare const InputGroupText: ({ className, ...props }: React$1.ComponentProps<"span">) => React$1.JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Button } from "./button.js";
|
|
2
|
+
import { ComponentProps } from "react";
|
|
3
|
+
//#region src/components/view-toolbar.d.ts
|
|
4
|
+
/** Shared view controls stay compact and scroll horizontally on small screens. */
|
|
5
|
+
export declare const ViewToolbarChrome: ({ className, ...props }: ComponentProps<"div">) => import("react").JSX.Element;
|
|
6
|
+
type ViewFilterButtonProps = Omit<ComponentProps<typeof Button>, "children" | "size" | "variant" | "aria-label" | "title"> & {
|
|
7
|
+
label: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const ViewFilterButton: ({ label, ...props }: ViewFilterButtonProps) => import("react").JSX.Element;
|
|
10
|
+
export declare const ViewFilterChip: ({ className, ...props }: Omit<ComponentProps<typeof Button>, "size" | "variant">) => import("react").JSX.Element;
|
|
11
|
+
//#endregion
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Button } from "./button.js";
|
|
3
|
+
import { FilterIcon } from "lucide-react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/view-toolbar.tsx
|
|
6
|
+
/** Shared view controls stay compact and scroll horizontally on small screens. */
|
|
7
|
+
const ViewToolbarChrome = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
8
|
+
className: cn("flex min-w-0 shrink-0 [scrollbar-width:none] flex-nowrap items-center gap-1 overflow-x-auto px-2 py-1 [-ms-overflow-style:none] md:flex-wrap md:overflow-visible [&::-webkit-scrollbar]:hidden", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
const ViewFilterButton = ({ label, ...props }) => /* @__PURE__ */ jsx(Button, {
|
|
12
|
+
...props,
|
|
13
|
+
"aria-label": label,
|
|
14
|
+
size: "icon-xs",
|
|
15
|
+
title: label,
|
|
16
|
+
variant: "ghost",
|
|
17
|
+
children: /* @__PURE__ */ jsx(FilterIcon, { className: "size-3.5" })
|
|
18
|
+
});
|
|
19
|
+
const ViewFilterChip = ({ className, ...props }) => /* @__PURE__ */ jsx(Button, {
|
|
20
|
+
...props,
|
|
21
|
+
className: cn("gap-1.5 font-normal", className),
|
|
22
|
+
size: "xs",
|
|
23
|
+
variant: "secondary"
|
|
24
|
+
});
|
|
25
|
+
//#endregion
|
|
26
|
+
export { ViewFilterButton, ViewFilterChip, ViewToolbarChrome };
|
|
@@ -2,6 +2,8 @@ import { ReactNode, RefObject } from "react";
|
|
|
2
2
|
//#region src/kanban/card-shell.d.ts
|
|
3
3
|
export type KanbanCardShellProps = {
|
|
4
4
|
children: ReactNode;
|
|
5
|
+
/** Proposed work stays visually distinct until a person accepts it. */
|
|
6
|
+
appearance?: "standard" | "proposal" | undefined;
|
|
5
7
|
/** Overlay slot pinned to the top-end corner (row actions). */
|
|
6
8
|
actions?: ReactNode;
|
|
7
9
|
/**
|
|
@@ -66,5 +68,5 @@ export type KanbanCardShellProps = {
|
|
|
66
68
|
* Nothing here clips its overflow: a pinned identity row stops sticking the
|
|
67
69
|
* moment anything between it and the scroll container clips.
|
|
68
70
|
*/
|
|
69
|
-
export declare const KanbanCardShell: ({ children, actions, actionsVisibility, stickyHeader, active, onOpen, bodyRef, dragRef, className }: KanbanCardShellProps) => import("react").JSX.Element;
|
|
71
|
+
export declare const KanbanCardShell: ({ children, appearance, actions, actionsVisibility, stickyHeader, active, onOpen, bodyRef, dragRef, className }: KanbanCardShellProps) => import("react").JSX.Element;
|
|
70
72
|
//#endregion
|
|
@@ -15,7 +15,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
* Nothing here clips its overflow: a pinned identity row stops sticking the
|
|
16
16
|
* moment anything between it and the scroll container clips.
|
|
17
17
|
*/
|
|
18
|
-
const KanbanCardShell = ({ children, actions, actionsVisibility = "always", stickyHeader, active, onOpen, bodyRef, dragRef, className }) => {
|
|
18
|
+
const KanbanCardShell = ({ children, appearance = "standard", actions, actionsVisibility = "always", stickyHeader, active, onOpen, bodyRef, dragRef, className }) => {
|
|
19
19
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
20
20
|
stickyHeader === void 0 || stickyHeader === null ? null : /* @__PURE__ */ jsx("div", {
|
|
21
21
|
className: cn(STICKY_HEADER_CLASS, KANBAN_CARD_STICKY_TOP_CLASS),
|
|
@@ -34,7 +34,7 @@ const KanbanCardShell = ({ children, actions, actionsVisibility = "always", stic
|
|
|
34
34
|
"data-active": active ? "true" : void 0,
|
|
35
35
|
ref: dragRef,
|
|
36
36
|
children: /* @__PURE__ */ jsx("div", {
|
|
37
|
-
className: cn(CARD_CLASS, active && ACTIVE_CLASS, className),
|
|
37
|
+
className: cn(CARD_CLASS, appearance === "proposal" && "border-dashed", active && ACTIVE_CLASS, className),
|
|
38
38
|
ref: bodyRef,
|
|
39
39
|
children: body
|
|
40
40
|
})
|
|
@@ -44,7 +44,7 @@ const KanbanCardShell = ({ children, actions, actionsVisibility = "always", stic
|
|
|
44
44
|
"data-active": active ? "true" : void 0,
|
|
45
45
|
ref: dragRef,
|
|
46
46
|
children: /* @__PURE__ */ jsx("div", {
|
|
47
|
-
className: cn(CARD_CLASS, "cursor-pointer transition-shadow hover:shadow-md", active && ACTIVE_CLASS, className),
|
|
47
|
+
className: cn(CARD_CLASS, appearance === "proposal" && "border-dashed", "cursor-pointer transition-shadow hover:shadow-md", active && ACTIVE_CLASS, className),
|
|
48
48
|
onClick: containedEventHandler(onOpen),
|
|
49
49
|
onKeyDown: (event) => {
|
|
50
50
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
@@ -20,7 +20,7 @@ const KanbanColumnHeader = ({ swatch, title, meta, calculation, dragHandle, acti
|
|
|
20
20
|
className: "sticky start-0 z-10 flex w-fit max-w-full items-center gap-2 bg-inherit",
|
|
21
21
|
"data-kanban-column-title": "",
|
|
22
22
|
children: [swatch, /* @__PURE__ */ jsxs("span", {
|
|
23
|
-
className: "flex min-w-0 flex-1 items-center gap-1.5 truncate",
|
|
23
|
+
className: "flex min-w-0 flex-1 items-center gap-1.5 truncate text-sm font-medium",
|
|
24
24
|
children: [title, meta !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
25
25
|
className: "text-muted-foreground text-xs",
|
|
26
26
|
children: meta
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { KanbanBandToggleActivation } from "./column-band-header.js";
|
|
2
2
|
import { KanbanColumnBand, KanbanGroup } from "./grouping.js";
|
|
3
3
|
import { KanbanBoardCell, KanbanBoardColumn, KanbanBoardMatrix } from "./matrix.js";
|
|
4
|
-
import { ReactNode } from "react";
|
|
4
|
+
import { ReactNode, Ref } from "react";
|
|
5
5
|
//#region src/kanban/subgroup-board.d.ts
|
|
6
6
|
export type KanbanSubgroupColumnHeaderContext = {
|
|
7
7
|
column: KanbanBoardColumn;
|
|
@@ -73,6 +73,7 @@ type KanbanSubgroupCollapseControl = {
|
|
|
73
73
|
onLaneCollapsedChange: (group: KanbanGroup, collapsed: boolean) => void;
|
|
74
74
|
};
|
|
75
75
|
export type KanbanSubgroupBoardProps<TRow> = {
|
|
76
|
+
scrollRef?: Ref<HTMLDivElement> | undefined;
|
|
76
77
|
matrix: KanbanBoardMatrix<TRow>;
|
|
77
78
|
renderColumnHeader: (context: KanbanSubgroupColumnHeaderContext) => ReactNode;
|
|
78
79
|
renderLaneIdentity: (context: KanbanSubgroupLaneIdentityContext) => ReactNode;
|
|
@@ -152,5 +153,5 @@ export type KanbanSubgroupBoardProps<TRow> = {
|
|
|
152
153
|
* in every state; the caption line never grows past its own height, so a
|
|
153
154
|
* folded band costs no vertical space.
|
|
154
155
|
*/
|
|
155
|
-
export declare const KanbanSubgroupBoard: <TRow>({ matrix, renderColumnHeader, renderLaneIdentity, renderCell, renderLaneColumnSummary, renderLaneColumnAction, renderBandHeader, renderCollapsedBandCell, formatBandToggleLabel, formatCount, isLaneCollapsed, onLaneCollapsedChange, isBandCollapsed, onBandCollapsedChange, footer, className, dragOverBandId, isDragging }: KanbanSubgroupBoardProps<TRow>) => import("react").JSX.Element;
|
|
156
|
+
export declare const KanbanSubgroupBoard: <TRow>({ scrollRef, matrix, renderColumnHeader, renderLaneIdentity, renderCell, renderLaneColumnSummary, renderLaneColumnAction, renderBandHeader, renderCollapsedBandCell, formatBandToggleLabel, formatCount, isLaneCollapsed, onLaneCollapsedChange, isBandCollapsed, onBandCollapsedChange, footer, className, dragOverBandId, isDragging }: KanbanSubgroupBoardProps<TRow>) => import("react").JSX.Element;
|
|
156
157
|
//#endregion
|
|
@@ -42,7 +42,7 @@ const rowsIn = (cells) => cells.reduce((sum, cell) => sum + cell.rows.length, 0)
|
|
|
42
42
|
* in every state; the caption line never grows past its own height, so a
|
|
43
43
|
* folded band costs no vertical space.
|
|
44
44
|
*/
|
|
45
|
-
const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, renderCell, renderLaneColumnSummary, renderLaneColumnAction, renderBandHeader, renderCollapsedBandCell, formatBandToggleLabel, formatCount = String, isLaneCollapsed, onLaneCollapsedChange, isBandCollapsed, onBandCollapsedChange, footer, className, dragOverBandId, isDragging }) => {
|
|
45
|
+
const KanbanSubgroupBoard = ({ scrollRef, matrix, renderColumnHeader, renderLaneIdentity, renderCell, renderLaneColumnSummary, renderLaneColumnAction, renderBandHeader, renderCollapsedBandCell, formatBandToggleLabel, formatCount = String, isLaneCollapsed, onLaneCollapsedChange, isBandCollapsed, onBandCollapsedChange, footer, className, dragOverBandId, isDragging }) => {
|
|
46
46
|
const [collapsedLaneValues, setCollapsedLaneValues] = useState(() => /* @__PURE__ */ new Set());
|
|
47
47
|
const [expandedEmptyLaneValues, setExpandedEmptyLaneValues] = useState(() => /* @__PURE__ */ new Set());
|
|
48
48
|
const [collapsedBandIds, setCollapsedBandIds] = useState(() => /* @__PURE__ */ new Set());
|
|
@@ -251,17 +251,17 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
|
|
|
251
251
|
});
|
|
252
252
|
};
|
|
253
253
|
/** One column's cell in a lane's row: what it holds, then what it offers. */
|
|
254
|
-
const laneColumnCell = (group, column, count) => /* @__PURE__ */ jsxs("div", {
|
|
254
|
+
const laneColumnCell = ({ group, column, count, laneCount }) => /* @__PURE__ */ jsxs("div", {
|
|
255
255
|
className: cn("flex items-center gap-1 px-3", "h-9"),
|
|
256
256
|
"data-kanban-lane-column-count": count,
|
|
257
|
-
children: [renderLaneColumnSummary ? renderLaneColumnSummary({
|
|
257
|
+
children: [laneCount > 0 && (renderLaneColumnSummary ? renderLaneColumnSummary({
|
|
258
258
|
column,
|
|
259
259
|
count,
|
|
260
260
|
lane: group
|
|
261
261
|
}) : /* @__PURE__ */ jsx("span", {
|
|
262
262
|
className: "text-muted-foreground text-xs tabular-nums",
|
|
263
263
|
children: formatCount(count)
|
|
264
|
-
}), renderLaneColumnAction === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
264
|
+
})), renderLaneColumnAction === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
265
265
|
className: "ms-auto flex items-center",
|
|
266
266
|
children: renderLaneColumnAction({
|
|
267
267
|
column,
|
|
@@ -279,6 +279,7 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
|
|
|
279
279
|
const laneCellsStickyTopStyle = { [KANBAN_STICKY_TOP_VAR]: `${String(headerHeight + LANE_ROW_HEIGHT_PX)}px` };
|
|
280
280
|
return /* @__PURE__ */ jsx("div", {
|
|
281
281
|
className: cn("h-full overflow-auto px-4 pb-4", className),
|
|
282
|
+
ref: scrollRef,
|
|
282
283
|
style: stickyTopStyle,
|
|
283
284
|
children: /* @__PURE__ */ jsxs("div", {
|
|
284
285
|
className: "min-w-max",
|
|
@@ -358,7 +359,7 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
|
|
|
358
359
|
"data-kanban-lane-identity": "",
|
|
359
360
|
children: /* @__PURE__ */ jsxs("button", {
|
|
360
361
|
"aria-expanded": !collapsed,
|
|
361
|
-
className: cn("hover:bg-muted/60 flex items-center gap-2 rounded-lg px-2 text-start transition-[background-color]", "h-9", KANBAN_CHROME_TOGGLE_COARSE_TARGET_CLASS),
|
|
362
|
+
className: cn("hover:bg-muted/60 flex items-center gap-2 rounded-lg px-2 text-start text-sm font-medium transition-[background-color]", "h-9", KANBAN_CHROME_TOGGLE_COARSE_TARGET_CLASS),
|
|
362
363
|
onClick: () => setLaneCollapsed(group, count, !collapsed),
|
|
363
364
|
type: "button",
|
|
364
365
|
children: [
|
|
@@ -379,8 +380,13 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
|
|
|
379
380
|
})
|
|
380
381
|
}), renderRow({
|
|
381
382
|
label: "Lane column summaries",
|
|
382
|
-
renderColumn: (column) => laneColumnCell(
|
|
383
|
-
|
|
383
|
+
renderColumn: (column) => laneColumnCell({
|
|
384
|
+
group,
|
|
385
|
+
column,
|
|
386
|
+
count: cellFor(column)?.rows.length ?? 0,
|
|
387
|
+
laneCount: count
|
|
388
|
+
}),
|
|
389
|
+
renderFoldedBand: (_band, span) => count > 0 ? foldedCount(span, cells) : null
|
|
384
390
|
})]
|
|
385
391
|
}), !collapsed && /* @__PURE__ */ jsx("div", {
|
|
386
392
|
style: laneCellsStickyTopStyle,
|
|
@@ -128,7 +128,7 @@ const KanbanVirtualCell = ({ rows, getRowKey, renderRow, pagination, sortable, c
|
|
|
128
128
|
})
|
|
129
129
|
}) : null;
|
|
130
130
|
const content = /* @__PURE__ */ jsxs("div", {
|
|
131
|
-
className: cn(KANBAN_CELL_SURFACE_CLASS, "
|
|
131
|
+
className: cn(KANBAN_CELL_SURFACE_CLASS, "min-h-20 rounded-xl p-2 transition-[background-color,outline-color]", rows.length === 0 ? "overflow-visible" : "max-h-[min(60vh,40rem)] overflow-y-auto overscroll-y-contain", active && accentVariants === void 0 && "bg-primary/5 ring-primary/50 ring-2", className),
|
|
132
132
|
"data-kanban-cell": sortable?.dropTarget.id,
|
|
133
133
|
"data-kanban-cell-accent": accentVariants === void 0 ? void 0 : "true",
|
|
134
134
|
onScroll: handleScroll,
|
|
@@ -16,6 +16,13 @@ export declare const SHELL_CHROME_LAYER_CLASS_NAME = "z-30";
|
|
|
16
16
|
export declare const OVERLAY_LAYER_CLASS_NAMES: {
|
|
17
17
|
/** Docked composer, suggestion chips, and other in-pane floating chrome. */
|
|
18
18
|
readonly chrome: "z-[80]";
|
|
19
|
+
/**
|
|
20
|
+
* In-pane controls floating over the docked composer (a review bar, a
|
|
21
|
+
* suggestion stepper). The composer's veil blurs everything beneath it with
|
|
22
|
+
* `backdrop-filter`; one step above `chrome` keeps these controls sharp
|
|
23
|
+
* regardless of mount order.
|
|
24
|
+
*/
|
|
25
|
+
readonly "chrome-raised": "z-[81]";
|
|
19
26
|
/** Dialogs, sheets, popovers, tooltips: above chrome, below toasts. */
|
|
20
27
|
readonly default: "z-[85]";
|
|
21
28
|
/** Search sits a hair above a plain dialog so its own popup wins. */
|
|
@@ -16,6 +16,13 @@ const SHELL_CHROME_LAYER_CLASS_NAME = "z-30";
|
|
|
16
16
|
const OVERLAY_LAYER_CLASS_NAMES = {
|
|
17
17
|
/** Docked composer, suggestion chips, and other in-pane floating chrome. */
|
|
18
18
|
chrome: "z-[80]",
|
|
19
|
+
/**
|
|
20
|
+
* In-pane controls floating over the docked composer (a review bar, a
|
|
21
|
+
* suggestion stepper). The composer's veil blurs everything beneath it with
|
|
22
|
+
* `backdrop-filter`; one step above `chrome` keeps these controls sharp
|
|
23
|
+
* regardless of mount order.
|
|
24
|
+
*/
|
|
25
|
+
"chrome-raised": "z-[81]",
|
|
19
26
|
/** Dialogs, sheets, popovers, tooltips: above chrome, below toasts. */
|
|
20
27
|
default: "z-[85]",
|
|
21
28
|
/** Search sits a hair above a plain dialog so its own popup wins. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Stella's design system: bidi-aware React primitives built on Base UI, the dockable inspector pane, and the Tailwind v4 theme they are styled with.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"base-ui",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"types": "./dist/index.d.ts",
|
|
34
34
|
"import": "./dist/index.js"
|
|
35
35
|
},
|
|
36
|
+
"./view-toolbar": {
|
|
37
|
+
"types": "./dist/components/view-toolbar.d.ts",
|
|
38
|
+
"import": "./dist/components/view-toolbar.js"
|
|
39
|
+
},
|
|
36
40
|
"./accordion": {
|
|
37
41
|
"types": "./dist/components/accordion.d.ts",
|
|
38
42
|
"import": "./dist/components/accordion.js"
|