@stll/ui 0.20.0 → 0.21.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.
@@ -10,8 +10,8 @@
10
10
  */
11
11
  declare const buttonAccessibleDisabledClass = "cursor-not-allowed opacity-64";
12
12
  declare const buttonVariants: (props?: ({
13
- size?: "xs" | "sm" | "icon" | "default" | "lg" | "icon-sm" | "chip" | "icon-lg" | "icon-xl" | "icon-xs" | "xl" | null | undefined;
14
- variant?: "link" | "destructive" | "outline" | "default" | "destructive-outline" | "ghost" | "secondary" | null | undefined;
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;
15
15
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
16
16
  //#endregion
17
17
  export { buttonAccessibleDisabledClass, buttonVariants };
@@ -0,0 +1,37 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/components/context-menu.d.ts
3
+ type ContextMenuAction = {
4
+ label: string;
5
+ icon?: ReactNode;
6
+ onClick?: () => void;
7
+ variant?: "default" | "destructive";
8
+ disabled?: boolean;
9
+ /** Set on a toggle-style action: it renders as a checkbox item whose
10
+ * state assistive technology can read. `onClick` flips it. */
11
+ checked?: boolean;
12
+ submenu?: readonly ContextMenuAction[];
13
+ /** Draw a divider above this item — e.g. to set a trailing "New …" action
14
+ * apart from the list of existing choices above it. */
15
+ separatorBefore?: boolean;
16
+ /** Keep the menu open after the click, for a toggle the user may flip
17
+ * several of in a row. */
18
+ closeOnClick?: boolean;
19
+ };
20
+ type ContextMenuProps = {
21
+ actions: readonly ContextMenuAction[];
22
+ children: ReactNode;
23
+ };
24
+ /**
25
+ * Wrap arbitrary content with a right-click context menu. Built on
26
+ * base-ui's `ContextMenu`, which is purpose-built for right-click /
27
+ * long-press triggers — it tracks the cursor anchor itself and uses
28
+ * dismissal semantics tuned for context menus, so the popup doesn't
29
+ * close on incidental pointer movement the way a hover/click `Menu`
30
+ * does.
31
+ *
32
+ * Renders only the children when `actions` is empty so callers can
33
+ * pass conditionally.
34
+ */
35
+ declare const ContextMenu: ({ actions, children }: ContextMenuProps) => ReactNode;
36
+ //#endregion
37
+ export { ContextMenu, ContextMenuAction, ContextMenuProps };
@@ -0,0 +1,48 @@
1
+ "use client";
2
+ import { cn } from "../lib/utils.js";
3
+ import { DropdownMenuCheckboxItem as MenuCheckboxItem, DropdownMenuContent as MenuPopup, DropdownMenuItem as MenuItem, DropdownMenuSeparator as MenuSeparator, DropdownMenuSub as MenuSub, DropdownMenuSubContent as MenuSubPopup, DropdownMenuSubTrigger as MenuSubTrigger } from "./menu.js";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { ContextMenu as ContextMenu$1 } from "@base-ui/react/context-menu";
6
+ //#region src/components/context-menu.tsx
7
+ /**
8
+ * Wrap arbitrary content with a right-click context menu. Built on
9
+ * base-ui's `ContextMenu`, which is purpose-built for right-click /
10
+ * long-press triggers — it tracks the cursor anchor itself and uses
11
+ * dismissal semantics tuned for context menus, so the popup doesn't
12
+ * close on incidental pointer movement the way a hover/click `Menu`
13
+ * does.
14
+ *
15
+ * Renders only the children when `actions` is empty so callers can
16
+ * pass conditionally.
17
+ */
18
+ const ContextMenu = ({ actions, children }) => {
19
+ if (actions.length === 0) return children;
20
+ return /* @__PURE__ */ jsxs(ContextMenu$1.Root, { children: [/* @__PURE__ */ jsx(ContextMenu$1.Trigger, {
21
+ "data-slot": "context-menu-trigger",
22
+ render: /* @__PURE__ */ jsx("div", { className: "contents" }),
23
+ children
24
+ }), /* @__PURE__ */ jsx(MenuPopup, {
25
+ "data-slot": "context-menu-popup",
26
+ children: actions.map((action) => /* @__PURE__ */ jsx(ContextMenuActionItem, { action }, action.label))
27
+ })] });
28
+ };
29
+ const ContextMenuActionItem = ({ action }) => {
30
+ const separator = action.separatorBefore ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null;
31
+ if (action.submenu) return /* @__PURE__ */ jsxs(Fragment, { children: [separator, /* @__PURE__ */ jsxs(MenuSub, { children: [/* @__PURE__ */ jsxs(MenuSubTrigger, { children: [action.icon, action.label] }), /* @__PURE__ */ jsx(MenuSubPopup, { children: action.submenu.map((sub) => /* @__PURE__ */ jsx(ContextMenuActionItem, { action: sub }, sub.label)) })] })] });
32
+ if (action.checked !== void 0) return /* @__PURE__ */ jsxs(Fragment, { children: [separator, /* @__PURE__ */ jsxs(MenuCheckboxItem, {
33
+ checked: action.checked,
34
+ closeOnClick: action.closeOnClick ?? true,
35
+ disabled: action.disabled === true,
36
+ onCheckedChange: () => action.onClick?.(),
37
+ children: [action.icon, action.label]
38
+ })] });
39
+ return /* @__PURE__ */ jsxs(Fragment, { children: [separator, /* @__PURE__ */ jsxs(MenuItem, {
40
+ className: cn(action.variant === "destructive" && "text-destructive"),
41
+ closeOnClick: action.closeOnClick ?? true,
42
+ disabled: action.disabled === true,
43
+ onClick: action.onClick,
44
+ children: [action.icon, action.label]
45
+ })] });
46
+ };
47
+ //#endregion
48
+ export { ContextMenu };
@@ -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-end" | "inline-start" | "block-end" | "block-start" | null | undefined;
8
+ align?: "inline-start" | "block-end" | "block-start" | "inline-end" | 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;
@@ -30,7 +30,7 @@ declare function useSidebar(): SidebarContextProps;
30
30
  * left for the content column. Mobile reports 0: there the sidebar is an
31
31
  * overlay sheet and occupies no layout width.
32
32
  */
33
- declare function useSidebarInlineSize(): 0 | 256 | 48;
33
+ declare function useSidebarInlineSize(): 0 | 48 | 256;
34
34
  declare const SidebarProvider: ({ defaultOpen, forceCollapsed, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }: React.ComponentProps<"div"> & {
35
35
  defaultOpen?: boolean;
36
36
  forceCollapsed?: boolean;
@@ -82,8 +82,8 @@ declare const SidebarGroupContent: ({ className, ...props }: React.ComponentProp
82
82
  declare const SidebarMenu: ({ className, ...props }: React.ComponentProps<"ul">) => import("react").JSX.Element;
83
83
  declare const SidebarMenuItem: ({ className, ...props }: React.ComponentProps<"li">) => import("react").JSX.Element;
84
84
  declare const sidebarMenuButtonVariants: (props?: ({
85
- variant?: "outline" | "default" | null | undefined;
86
- size?: "sm" | "default" | "lg" | "rail" | null | undefined;
85
+ variant?: "default" | "outline" | null | undefined;
86
+ size?: "default" | "lg" | "sm" | "rail" | null | undefined;
87
87
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
88
88
  declare const SidebarMenuButton: ({ asChild, isActive, variant, size, tooltip, className, ...props }: React.ComponentProps<"button"> & {
89
89
  asChild?: boolean;
@@ -269,7 +269,7 @@ const sidebarMenuButtonVariants = cva("peer/menu-button ring-sidebar-ring hover:
269
269
  lg: "h-12 text-sm",
270
270
  /** A 44px target in both states, for a sidebar that stands in for
271
271
  * the application rail on touch and hybrid devices. */
272
- rail: "h-11 text-sm group-data-[collapsible=icon]:size-11! group-data-[collapsible=icon]:justify-center"
272
+ rail: "h-11 text-sm group-data-[collapsible=icon]:size-11! group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:p-0! group-data-[collapsible=icon]:[&>span:last-child]:sr-only"
273
273
  }
274
274
  },
275
275
  defaultVariants: {
@@ -8,7 +8,7 @@ import { Tabs } from "@base-ui/react/tabs";
8
8
  */
9
9
  declare const InspectorTabs: ({ className, ...props }: Omit<Tabs.Root.Props, "orientation">) => React$1.JSX.Element;
10
10
  declare const INSPECTOR_RAIL_MEDIA_QUERY: "(min-width: 48rem)";
11
- declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "vertical" | "horizontal";
11
+ declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "horizontal" | "vertical";
12
12
  declare const InspectorTabList: ({ className, ...props }: Tabs.List.Props) => React$1.JSX.Element;
13
13
  declare const InspectorTab: ({ className, ...props }: Tabs.Tab.Props) => React$1.JSX.Element;
14
14
  declare const InspectorTabPanel: ({ className, ...props }: Tabs.Panel.Props) => React$1.JSX.Element;
@@ -226,9 +226,9 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
226
226
  className: "min-w-max",
227
227
  children: [
228
228
  /* @__PURE__ */ jsxs("div", {
229
- className: "bg-background sticky top-0 z-20 pt-4 pb-3",
229
+ className: "bg-background sticky top-0 z-20 pt-2 pb-2",
230
230
  children: [hasBands ? /* @__PURE__ */ jsx("div", {
231
- className: "flex items-end gap-3 pb-1.5",
231
+ className: "flex items-end gap-3 pb-1",
232
232
  "data-kanban-band-row": "",
233
233
  children: spans.map((span) => {
234
234
  const band = span.band;
@@ -285,7 +285,7 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
285
285
  const collapsed = isLaneCollapsed ? isLaneCollapsed(group, count) : defaultCollapsed;
286
286
  const cellFor = (column) => cells.find((candidate) => columnKey(candidate.coordinate.column) === columnKey(column));
287
287
  return /* @__PURE__ */ jsxs("section", {
288
- className: "border-border/60 border-b py-2 first:pt-0 last:border-b-0",
288
+ className: "border-border/60 border-b py-1 first:pt-0 last:border-b-0",
289
289
  children: [
290
290
  /* @__PURE__ */ jsx("div", {
291
291
  className: "bg-background/95 sticky start-0 z-10 flex min-h-11 items-center backdrop-blur-sm",
@@ -311,7 +311,7 @@ const KanbanSubgroupBoard = ({ matrix, renderColumnHeader, renderLaneIdentity, r
311
311
  ]
312
312
  })
313
313
  }),
314
- renderRow({
314
+ collapsed && renderRow({
315
315
  label: "Lane column counts",
316
316
  renderColumn: (column) => {
317
317
  const columnRows = cellFor(column)?.rows.length ?? 0;
@@ -5,6 +5,6 @@ declare const CONTROL_SIZE: Readonly<{
5
5
  readonly lg: "lg";
6
6
  }>;
7
7
  type ControlSize = (typeof CONTROL_SIZE)[keyof typeof CONTROL_SIZE];
8
- declare const CONTROL_SIZES: readonly ("sm" | "default" | "lg")[];
8
+ declare const CONTROL_SIZES: readonly ("default" | "lg" | "sm")[];
9
9
  //#endregion
10
10
  export { CONTROL_SIZE, CONTROL_SIZES, type ControlSize };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/ui",
3
- "version": "0.20.0",
3
+ "version": "0.21.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",
@@ -93,6 +93,10 @@
93
93
  "types": "./dist/components/composer.d.ts",
94
94
  "import": "./dist/components/composer.js"
95
95
  },
96
+ "./context-menu": {
97
+ "types": "./dist/components/context-menu.d.ts",
98
+ "import": "./dist/components/context-menu.js"
99
+ },
96
100
  "./control-size": {
97
101
  "types": "./dist/lib/control-size.d.ts",
98
102
  "import": "./dist/lib/control-size.js"