@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.
@@ -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?: "link" | "default" | "destructive" | "destructive-outline" | "ghost" | "outline" | "secondary" | null | undefined;
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-start" | "inline-end" | "block-start" | "block-end" | null | undefined;
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(group, column, cellFor(column)?.rows.length ?? 0),
383
- renderFoldedBand: (_band, span) => foldedCount(span, cells)
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, "max-h-[min(60vh,40rem)] min-h-20 overflow-y-auto overscroll-y-contain rounded-xl p-2 transition-[background-color,outline-color]", active && accentVariants === void 0 && "bg-primary/5 ring-primary/50 ring-2", className),
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.27.2",
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"