@stll/ui 0.5.2 → 0.6.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/README.md CHANGED
@@ -10,7 +10,8 @@ be rendered and tested without a surrounding application — and a change to one
10
10
  cannot reach into product code by accident. Lint enforces that boundary; the
11
11
  export map below is what "part of the design system" means.
12
12
 
13
- Peer dependencies: `react`, `react-dom`, `@base-ui/react`, `tailwindcss` (v4).
13
+ Peer dependencies: `react`, `react-dom`, `@base-ui/react`, `tailwindcss` (v4),
14
+ `@dnd-kit/core`, and `@dnd-kit/sortable`.
14
15
 
15
16
  ## Import
16
17
 
@@ -35,6 +36,50 @@ convenience; the subpaths are the real surface, and in-repo code uses those.
35
36
  minor. They will be removed after that; the export guard checks that both
36
37
  spellings land on the same module for as long as they both exist.
37
38
 
39
+ ## Sortable boards
40
+
41
+ `@stll/ui/kanban` provides input and accessibility primitives only; the caller
42
+ keeps item identifiers, order changes, and persisted mutations. Wrap the board
43
+ in `KanbanSortableBoard`, render sortable items through `useKanbanSortable`,
44
+ and attach the returned bindings to `KanbanDragHandle`.
45
+
46
+ ```tsx
47
+ import {
48
+ KanbanDragHandle,
49
+ KanbanSortableBoard,
50
+ KanbanSortableList,
51
+ useKanbanSortable,
52
+ } from "@stll/ui/kanban";
53
+
54
+ const Card = ({ id }: { id: string }) => {
55
+ const { dragHandle, setNodeRef } = useKanbanSortable({ id });
56
+ return (
57
+ <article ref={setNodeRef}>
58
+ <KanbanDragHandle bindings={dragHandle} label="Move card" />
59
+ </article>
60
+ );
61
+ };
62
+
63
+ <KanbanSortableBoard onDragEnd={handleDragEnd}>
64
+ <KanbanSortableList items={cardIds}>
65
+ {cardIds.map((id) => (
66
+ <Card id={id} key={id} />
67
+ ))}
68
+ </KanbanSortableList>
69
+ </KanbanSortableBoard>;
70
+ ```
71
+
72
+ The default sensors are mouse (8px movement), touch (150ms delay with 8px
73
+ tolerance), and keyboard. Scroll containers retain `touch-action: auto`; only
74
+ `KanbanDragHandle` disables touch panning. `KanbanSortableBoard` also accepts
75
+ custom `sensors`, `accessibility`, collision detection, keyboard coordinates,
76
+ auto-scroll options, and an `overlay` render function.
77
+
78
+ `getKanbanHorizontalEdge` takes `input: "pointer"` with a current client-x and
79
+ `direction: "ltr" | "rtl"` for mouse and touch input. Keyboard calls use
80
+ `input: "keyboard"` and require source and target indices, so every move has a
81
+ logical edge without relying on ambiguous geometry.
82
+
38
83
  ## Styles
39
84
 
40
85
  No compiled CSS ships. The components carry Tailwind class names, so the
@@ -67,7 +112,9 @@ and bidi isolation.
67
112
 
68
113
  ```sh
69
114
  bun run build # tsdown, one output module per source module, with .d.ts
70
- bun run test # bun test src
115
+ bun run test # unit tests
116
+ bun run test:unit # unit tests only
117
+ bun run test:browser # Chromium mobile-input tests
71
118
  bun run typecheck
72
119
  bun run lint
73
120
  ```
@@ -76,6 +123,8 @@ bun run lint
76
123
  runs the publish path end to end: build, `prepare-publish`, `bun pm pack`, then
77
124
  resolves and imports every declared subpath from the built `dist`.
78
125
 
126
+ `bun run pack:check` runs that published-package check for this package.
127
+
79
128
  This package is published, so a change here needs a changeset:
80
129
 
81
130
  ```sh
@@ -10,7 +10,7 @@
10
10
  */
11
11
  declare const buttonAccessibleDisabledClass = "cursor-not-allowed opacity-64";
12
12
  declare const buttonVariants: (props?: ({
13
- size?: "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "lg" | "sm" | "xl" | "xs" | null | undefined;
13
+ size?: "sm" | "default" | "lg" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "xl" | "xs" | null | undefined;
14
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
@@ -5,7 +5,7 @@ import * as React$1 from "react";
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" | "block-end" | "block-start" | "inline-end" | null | undefined;
8
+ align?: "inline-end" | "inline-start" | "block-start" | "block-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;
@@ -0,0 +1,36 @@
1
+ import { ComponentProps } from "react";
2
+ //#region src/components/loader.d.ts
3
+ /**
4
+ * The one indeterminate loading indicator: the Stella mark breathing. Inline
5
+ * (`sm`) next to a control that is busy, `md` in a row, `lg` for a region.
6
+ * Content with a known shape gets a `Skeleton` instead, never a loader.
7
+ */
8
+ declare const Loader: ({ label, size, className, ...props }: LoaderProps) => import("react").JSX.Element;
9
+ /**
10
+ * A region whose content has no shape yet (a job running, a first fetch): the
11
+ * mark, one line saying what is happening, and at most one line of detail.
12
+ * Progress is stated in the detail text, never drawn as a bar that guesses.
13
+ */
14
+ declare const LoaderState: ({ label, detail, hint, className }: LoaderStateProps) => import("react").JSX.Element;
15
+ declare const LOADER_SIZE: {
16
+ readonly sm: "size-4";
17
+ readonly md: "size-6";
18
+ readonly lg: "size-8";
19
+ };
20
+ type LoaderSize = keyof typeof LOADER_SIZE;
21
+ type LoaderProps = Omit<ComponentProps<"span">, "children"> & {
22
+ /** What is pending, for assistive technology ("Loading matters"). */
23
+ label: string;
24
+ size?: LoaderSize;
25
+ };
26
+ type LoaderStateProps = {
27
+ /** What is happening, shown as the title and announced. */
28
+ label: string;
29
+ /** A short line under the title: a name, a fraction, a percentage. */
30
+ detail?: string | undefined;
31
+ /** Expectation-setting copy, kept small. */
32
+ hint?: string | undefined;
33
+ className?: string | undefined;
34
+ };
35
+ //#endregion
36
+ export { Loader, LoaderState };
@@ -0,0 +1,54 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { StellaMark } from "./stella-mark.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/loader.tsx
5
+ /**
6
+ * The one indeterminate loading indicator: the Stella mark breathing. Inline
7
+ * (`sm`) next to a control that is busy, `md` in a row, `lg` for a region.
8
+ * Content with a known shape gets a `Skeleton` instead, never a loader.
9
+ */
10
+ const Loader = ({ label, size = "md", className, ...props }) => /* @__PURE__ */ jsx("span", {
11
+ "aria-busy": "true",
12
+ "aria-label": label,
13
+ className: cn("inline-flex shrink-0 items-center justify-center", className),
14
+ "data-slot": "loader",
15
+ role: "status",
16
+ ...props,
17
+ children: /* @__PURE__ */ jsx(LoaderMark, { size })
18
+ });
19
+ /**
20
+ * A region whose content has no shape yet (a job running, a first fetch): the
21
+ * mark, one line saying what is happening, and at most one line of detail.
22
+ * Progress is stated in the detail text, never drawn as a bar that guesses.
23
+ */
24
+ const LoaderState = ({ label, detail, hint, className }) => /* @__PURE__ */ jsxs("div", {
25
+ "aria-busy": "true",
26
+ className: cn("flex h-full flex-col items-center justify-center gap-3 px-6 text-center", className),
27
+ "data-slot": "loader-state",
28
+ role: "status",
29
+ children: [/* @__PURE__ */ jsx(LoaderMark, { size: "lg" }), /* @__PURE__ */ jsxs("div", {
30
+ className: "space-y-1",
31
+ children: [
32
+ /* @__PURE__ */ jsx("p", {
33
+ className: "text-foreground text-sm font-medium",
34
+ children: label
35
+ }),
36
+ detail !== void 0 && /* @__PURE__ */ jsx("p", {
37
+ className: "text-muted-foreground truncate text-xs tabular-nums",
38
+ children: detail
39
+ }),
40
+ hint !== void 0 && /* @__PURE__ */ jsx("p", {
41
+ className: "text-muted-foreground text-[11px] text-pretty",
42
+ children: hint
43
+ })
44
+ ]
45
+ })]
46
+ });
47
+ const LOADER_SIZE = {
48
+ sm: "size-4",
49
+ md: "size-6",
50
+ lg: "size-8"
51
+ };
52
+ const LoaderMark = ({ size }) => /* @__PURE__ */ jsx(StellaMark, { className: cn("animate-loader text-muted-foreground motion-reduce:animate-none motion-reduce:opacity-70", LOADER_SIZE[size]) });
53
+ //#endregion
54
+ export { Loader, LoaderState };
package/dist/index.d.ts CHANGED
@@ -66,10 +66,12 @@ import "./inspector/index.js";
66
66
  import { KanbanCardFieldSelection, selectKanbanCardFieldIds } from "./kanban/card-properties.js";
67
67
  import { KanbanCardShell, KanbanCardShellProps } from "./kanban/card-shell.js";
68
68
  import { KanbanColumnHeader, KanbanColumnHeaderProps } from "./kanban/column-header.js";
69
+ import { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanDragHandle, KanbanDragHandleProps, KanbanSortableBindings, KanbanSortableBoard, KanbanSortableBoardProps, KanbanSortableColumns, KanbanSortableColumnsProps, KanbanSortableList, KanbanSortableListProps, UseKanbanSortableOptions, useKanbanSortable, useKanbanSortableSensors } from "./kanban/sortable-interactions.js";
70
+ import { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KanbanDirection, KanbanHorizontalEdge, getKanbanHorizontalEdge } from "./kanban/sortable-edge.js";
69
71
  import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, RegisterKanbanBoardAutoScrollOptions, RegisterKanbanCardDragOptions, registerKanbanBoardAutoScroll, registerKanbanCardDrag } from "./kanban/drag-interactions.js";
70
72
  import { ColorVariants, OptionColor, emptyColor, optionColors, resolveOptionColor } from "./lib/option-color.js";
71
73
  import { KanbanBuiltInGroup, KanbanGroup, KanbanGroupOption, KanbanGrouping, KanbanSchema, ResolveKanbanGroupingParams, getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./kanban/grouping.js";
72
74
  import "./kanban/index.js";
73
75
  import { cn, composeRefs } from "./lib/utils.js";
74
76
  import { getFirstWeekday, getLocaleWeekInfo, getWeekendDays } from "./lib/week.js";
75
- export { Accordion, AccordionPanel as AccordionContent, AccordionPanel, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogBackdrop, AlertDialogBackdrop as AlertDialogOverlay, AlertDialogClose, AlertDialogPopup as AlertDialogContent, AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport, AnchoredToastProvider, Avatar, AvatarFallback, AvatarImage, type BidiDirection, BidiText, type BidiTextProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CalendarCell, type CalendarDateRange, CalendarEntryButton, CalendarEntrySurface, CalendarGrid, CalendarHeaderCell, CalendarHeaderRow, Checkbox, ColorPicker, ColorPickerContent, type ColorPickerContentProps, type ColorPickerProps, type ColorPreset, ColorVariants, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxClear, ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxRow, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandCollection, CommandDialog, CommandDialogPopup, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, DEFAULT_PRESETS, DataTable, type DataTableAriaSort, type DataTableColumn, type DataTableProps, type DataTableRowAction, DatePickerPopover, type DatePickerPopoverProps, DestructiveActionConfirmation, DestructiveConfirmDialog, type DestructiveConfirmDialogProps, Dialog, DialogBackdrop, DialogBackdrop as DialogOverlay, DialogClose, DialogPopup as DialogContent, DialogPopup, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPortal, DialogTitle, DialogTrigger, DialogViewport, DirectionalIcon, DiscordLogoIcon, Menu as DropdownMenu, Menu, MenuCheckboxItem as DropdownMenuCheckboxItem, MenuCheckboxItem, MenuPopup as DropdownMenuContent, MenuPopup, MenuCreateHandle as DropdownMenuCreateHandle, MenuCreateHandle, MenuGroup as DropdownMenuGroup, MenuGroup, MenuItem as DropdownMenuItem, MenuItem, MenuGroupLabel as DropdownMenuLabel, MenuGroupLabel, MenuPortal as DropdownMenuPortal, MenuPortal, MenuRadioGroup as DropdownMenuRadioGroup, MenuRadioGroup, MenuRadioItem as DropdownMenuRadioItem, MenuRadioItem, MenuSeparator as DropdownMenuSeparator, MenuSeparator, MenuShortcut as DropdownMenuShortcut, MenuShortcut, MenuSub as DropdownMenuSub, MenuSub, MenuSubPopup as DropdownMenuSubContent, MenuSubPopup, MenuSubTrigger as DropdownMenuSubTrigger, MenuSubTrigger, MenuTrigger as DropdownMenuTrigger, MenuTrigger, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Form, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GitHubLogoIcon, HexColorPicker, type HexColorPickerProps, PreviewCard as HoverCard, PreviewCard, PreviewCardPopup as HoverCardContent, PreviewCardPopup, PreviewCardTrigger as HoverCardTrigger, PreviewCardTrigger, INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, KANBAN_BOARD_AUTO_SCROLL_SOURCES, type KanbanBuiltInGroup, type KanbanCardFieldSelection, KanbanCardShell, type KanbanCardShellProps, KanbanColumnHeader, type KanbanColumnHeaderProps, type KanbanGroup, type KanbanGroupOption, type KanbanGrouping, type KanbanSchema, Label, MenuPreviewLayout, OVERLAY_LAYER_CLASS_NAMES, OptionColor, OutlineItem, OutlineRail, OutlineRailProps, OverlayLayer, PROPERTY_ROW_GRID, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverPanel, PopoverTitle, PopoverTrigger, PreviewCardPrimitive, PreviewPane, type RegisterKanbanBoardAutoScrollOptions, type RegisterKanbanCardDragOptions, type ResolveKanbanGroupingParams, ResourceCalendar, type ResourceCalendarColumn, type ResourceCalendarEntry, type ResourceCalendarEntryTone, type ResourceCalendarLaneLayout, type ResourceCalendarLanePlacement, type ResourceCalendarPlacement, type ResourceCalendarResource, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, ScrollArea, ScrollBar, ScrollToTop, ScrollToTopProps, SecretInput, type SecretInputProps, SegmentedIconToggle, Select, SelectPopup as SelectContent, SelectPopup, SelectGroup, SelectGroupLabel, SelectItem, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBackdrop, SheetBackdrop as SheetOverlay, SheetClose, SheetPopup as SheetContent, SheetPopup, SheetDescription, SheetFooter, SheetHeader, SheetPanel, SheetPortal, type SheetSide, SheetTitle, SheetTrigger, Skeleton, type SortDirection, SortableHead, StellaMark, StellaWordmarkLatin, TOAST_RIGHT_OFFSET_VAR, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, Table, TableBody, TableCaption, TableCell, type TableColumnCapabilities, type TableColumnDescriptor, TableFooter, TableHead, TableHeader, TableRow, type TableSchema, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, TextSeparator, Textarea, type TextareaProps, type ToastPosition, ToastProvider, Tooltip, TooltipPopup as TooltipContent, TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger, UserText, assertConsecutiveCalendarDates, buttonAccessibleDisabledClass, buttonVariants, cn, composeRefs, containedEventHandler, containedHandler, contentDir, duplicateColumnIds, emptyColor, findTableColumn, getFirstWeekday, getKanbanGroupingPropertyId, getKanbanGroups, getLocaleWeekInfo, getResourceCalendarPlacement, getWeekendDays, hideableColumnIds, isKanbanGroupingRenderable, isStructuredInputType, layoutResourceCalendarEntries, nextCalendarDate, optionColors, parsePersistedPaneWidth, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKanbanGroupOptions, resolveKanbanGrouping, resolveKeyboardWidth, resolveOptionColor, selectKanbanCardFieldIds, selectKanbanRows, shouldForceSidebarCollapsed, sortableColumnIds, stellaToast, tableColumnIds, tableColumnSizing, useComboboxFilter, useContentDir, useDestructiveActionConfirmation, useInspectorPaneWidth, useIsMobile, useLatest, useViewportWidth, visibleColumnIds };
77
+ export { Accordion, AccordionPanel as AccordionContent, AccordionPanel, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogBackdrop, AlertDialogBackdrop as AlertDialogOverlay, AlertDialogClose, AlertDialogPopup as AlertDialogContent, AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport, AnchoredToastProvider, Avatar, AvatarFallback, AvatarImage, type BidiDirection, BidiText, type BidiTextProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CalendarCell, type CalendarDateRange, CalendarEntryButton, CalendarEntrySurface, CalendarGrid, CalendarHeaderCell, CalendarHeaderRow, Checkbox, ColorPicker, ColorPickerContent, type ColorPickerContentProps, type ColorPickerProps, type ColorPreset, ColorVariants, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxClear, ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxRow, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandCollection, CommandDialog, CommandDialogPopup, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, DEFAULT_PRESETS, DataTable, type DataTableAriaSort, type DataTableColumn, type DataTableProps, type DataTableRowAction, DatePickerPopover, type DatePickerPopoverProps, DestructiveActionConfirmation, DestructiveConfirmDialog, type DestructiveConfirmDialogProps, Dialog, DialogBackdrop, DialogBackdrop as DialogOverlay, DialogClose, DialogPopup as DialogContent, DialogPopup, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPortal, DialogTitle, DialogTrigger, DialogViewport, DirectionalIcon, DiscordLogoIcon, Menu as DropdownMenu, Menu, MenuCheckboxItem as DropdownMenuCheckboxItem, MenuCheckboxItem, MenuPopup as DropdownMenuContent, MenuPopup, MenuCreateHandle as DropdownMenuCreateHandle, MenuCreateHandle, MenuGroup as DropdownMenuGroup, MenuGroup, MenuItem as DropdownMenuItem, MenuItem, MenuGroupLabel as DropdownMenuLabel, MenuGroupLabel, MenuPortal as DropdownMenuPortal, MenuPortal, MenuRadioGroup as DropdownMenuRadioGroup, MenuRadioGroup, MenuRadioItem as DropdownMenuRadioItem, MenuRadioItem, MenuSeparator as DropdownMenuSeparator, MenuSeparator, MenuShortcut as DropdownMenuShortcut, MenuShortcut, MenuSub as DropdownMenuSub, MenuSub, MenuSubPopup as DropdownMenuSubContent, MenuSubPopup, MenuSubTrigger as DropdownMenuSubTrigger, MenuSubTrigger, MenuTrigger as DropdownMenuTrigger, MenuTrigger, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Form, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GitHubLogoIcon, HexColorPicker, type HexColorPickerProps, PreviewCard as HoverCard, PreviewCard, PreviewCardPopup as HoverCardContent, PreviewCardPopup, PreviewCardTrigger as HoverCardTrigger, PreviewCardTrigger, INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, KANBAN_BOARD_AUTO_SCROLL_SOURCES, KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, type KanbanBuiltInGroup, type KanbanCardFieldSelection, KanbanCardShell, type KanbanCardShellProps, KanbanColumnHeader, type KanbanColumnHeaderProps, type KanbanDirection, KanbanDragHandle, type KanbanDragHandleProps, type KanbanGroup, type KanbanGroupOption, type KanbanGrouping, type KanbanHorizontalEdge, type KanbanSchema, type KanbanSortableBindings, KanbanSortableBoard, type KanbanSortableBoardProps, KanbanSortableColumns, type KanbanSortableColumnsProps, KanbanSortableList, type KanbanSortableListProps, Label, MenuPreviewLayout, OVERLAY_LAYER_CLASS_NAMES, OptionColor, OutlineItem, OutlineRail, OutlineRailProps, OverlayLayer, PROPERTY_ROW_GRID, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverPanel, PopoverTitle, PopoverTrigger, PreviewCardPrimitive, PreviewPane, type RegisterKanbanBoardAutoScrollOptions, type RegisterKanbanCardDragOptions, type ResolveKanbanGroupingParams, ResourceCalendar, type ResourceCalendarColumn, type ResourceCalendarEntry, type ResourceCalendarEntryTone, type ResourceCalendarLaneLayout, type ResourceCalendarLanePlacement, type ResourceCalendarPlacement, type ResourceCalendarResource, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, ScrollArea, ScrollBar, ScrollToTop, ScrollToTopProps, SecretInput, type SecretInputProps, SegmentedIconToggle, Select, SelectPopup as SelectContent, SelectPopup, SelectGroup, SelectGroupLabel, SelectItem, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBackdrop, SheetBackdrop as SheetOverlay, SheetClose, SheetPopup as SheetContent, SheetPopup, SheetDescription, SheetFooter, SheetHeader, SheetPanel, SheetPortal, type SheetSide, SheetTitle, SheetTrigger, Skeleton, type SortDirection, SortableHead, StellaMark, StellaWordmarkLatin, TOAST_RIGHT_OFFSET_VAR, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, Table, TableBody, TableCaption, TableCell, type TableColumnCapabilities, type TableColumnDescriptor, TableFooter, TableHead, TableHeader, TableRow, type TableSchema, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, TextSeparator, Textarea, type TextareaProps, type ToastPosition, ToastProvider, Tooltip, TooltipPopup as TooltipContent, TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger, type UseKanbanSortableOptions, UserText, assertConsecutiveCalendarDates, buttonAccessibleDisabledClass, buttonVariants, cn, composeRefs, containedEventHandler, containedHandler, contentDir, duplicateColumnIds, emptyColor, findTableColumn, getFirstWeekday, getKanbanGroupingPropertyId, getKanbanGroups, getKanbanHorizontalEdge, getLocaleWeekInfo, getResourceCalendarPlacement, getWeekendDays, hideableColumnIds, isKanbanGroupingRenderable, isStructuredInputType, layoutResourceCalendarEntries, nextCalendarDate, optionColors, parsePersistedPaneWidth, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKanbanGroupOptions, resolveKanbanGrouping, resolveKeyboardWidth, resolveOptionColor, selectKanbanCardFieldIds, selectKanbanRows, shouldForceSidebarCollapsed, sortableColumnIds, stellaToast, tableColumnIds, tableColumnSizing, useComboboxFilter, useContentDir, useDestructiveActionConfirmation, useInspectorPaneWidth, useIsMobile, useKanbanSortable, useKanbanSortableSensors, useLatest, useViewportWidth, visibleColumnIds };
package/dist/index.js CHANGED
@@ -65,7 +65,9 @@ import { INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, parseP
65
65
  import { selectKanbanCardFieldIds } from "./kanban/card-properties.js";
66
66
  import { KanbanCardShell } from "./kanban/card-shell.js";
67
67
  import { KanbanColumnHeader } from "./kanban/column-header.js";
68
+ import { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanDragHandle, KanbanSortableBoard, KanbanSortableColumns, KanbanSortableList, useKanbanSortable, useKanbanSortableSensors } from "./kanban/sortable-interactions.js";
69
+ import { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, getKanbanHorizontalEdge } from "./kanban/sortable-edge.js";
68
70
  import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, registerKanbanBoardAutoScroll, registerKanbanCardDrag } from "./kanban/drag-interactions.js";
69
71
  import { getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./kanban/grouping.js";
70
72
  import { emptyColor, optionColors, resolveOptionColor } from "./lib/option-color.js";
71
- export { Accordion, AccordionPanel as AccordionContent, AccordionPanel, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogBackdrop, AlertDialogBackdrop as AlertDialogOverlay, AlertDialogClose, AlertDialogPopup as AlertDialogContent, AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport, AnchoredToastProvider, Avatar, AvatarFallback, AvatarImage, BidiText, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CalendarCell, CalendarEntryButton, CalendarEntrySurface, CalendarGrid, CalendarHeaderCell, CalendarHeaderRow, Checkbox, ColorPicker, ColorPickerContent, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxClear, ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxRow, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandCollection, CommandDialog, CommandDialogPopup, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, DEFAULT_PRESETS, DataTable, DatePickerPopover, DestructiveActionConfirmation, DestructiveConfirmDialog, Dialog, DialogBackdrop, DialogBackdrop as DialogOverlay, DialogClose, DialogPopup as DialogContent, DialogPopup, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPortal, DialogTitle, DialogTrigger, DialogViewport, DirectionalIcon, DiscordLogoIcon, Menu as DropdownMenu, Menu, MenuCheckboxItem as DropdownMenuCheckboxItem, MenuCheckboxItem, MenuPopup as DropdownMenuContent, MenuPopup, MenuCreateHandle as DropdownMenuCreateHandle, MenuCreateHandle, MenuGroup as DropdownMenuGroup, MenuGroup, MenuItem as DropdownMenuItem, MenuItem, MenuGroupLabel as DropdownMenuLabel, MenuGroupLabel, MenuPortal as DropdownMenuPortal, MenuPortal, MenuRadioGroup as DropdownMenuRadioGroup, MenuRadioGroup, MenuRadioItem as DropdownMenuRadioItem, MenuRadioItem, MenuSeparator as DropdownMenuSeparator, MenuSeparator, MenuShortcut as DropdownMenuShortcut, MenuShortcut, MenuSub as DropdownMenuSub, MenuSub, MenuSubPopup as DropdownMenuSubContent, MenuSubPopup, MenuSubTrigger as DropdownMenuSubTrigger, MenuSubTrigger, MenuTrigger as DropdownMenuTrigger, MenuTrigger, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Form, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GitHubLogoIcon, HexColorPicker, PreviewCard as HoverCard, PreviewCard, PreviewCardPopup as HoverCardContent, PreviewCardPopup, PreviewCardTrigger as HoverCardTrigger, PreviewCardTrigger, INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, KANBAN_BOARD_AUTO_SCROLL_SOURCES, KanbanCardShell, KanbanColumnHeader, Label, MenuPreviewLayout, OVERLAY_LAYER_CLASS_NAMES, OutlineRail, PROPERTY_ROW_GRID, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverPanel, PopoverTitle, PopoverTrigger, PreviewCardPrimitive, PreviewPane, ResourceCalendar, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, ScrollArea, ScrollBar, ScrollToTop, SecretInput, SegmentedIconToggle, Select, SelectPopup as SelectContent, SelectPopup, SelectGroup, SelectGroupLabel, SelectItem, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBackdrop, SheetBackdrop as SheetOverlay, SheetClose, SheetPopup as SheetContent, SheetPopup, SheetDescription, SheetFooter, SheetHeader, SheetPanel, SheetPortal, SheetTitle, SheetTrigger, Skeleton, SortableHead, StellaMark, StellaWordmarkLatin, TOAST_RIGHT_OFFSET_VAR, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, TextSeparator, Textarea, ToastProvider, Tooltip, TooltipPopup as TooltipContent, TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger, UserText, assertConsecutiveCalendarDates, buttonAccessibleDisabledClass, buttonVariants, cn, composeRefs, containedEventHandler, containedHandler, contentDir, duplicateColumnIds, emptyColor, findTableColumn, getFirstWeekday, getKanbanGroupingPropertyId, getKanbanGroups, getLocaleWeekInfo, getResourceCalendarPlacement, getWeekendDays, hideableColumnIds, isKanbanGroupingRenderable, isStructuredInputType, layoutResourceCalendarEntries, nextCalendarDate, optionColors, parsePersistedPaneWidth, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKanbanGroupOptions, resolveKanbanGrouping, resolveKeyboardWidth, resolveOptionColor, selectKanbanCardFieldIds, selectKanbanRows, shouldForceSidebarCollapsed, sortableColumnIds, stellaToast, tableColumnIds, tableColumnSizing, useComboboxFilter, useContentDir, useDestructiveActionConfirmation, useInspectorPaneWidth, useIsMobile, useLatest, useViewportWidth, visibleColumnIds };
73
+ export { Accordion, AccordionPanel as AccordionContent, AccordionPanel, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogBackdrop, AlertDialogBackdrop as AlertDialogOverlay, AlertDialogClose, AlertDialogPopup as AlertDialogContent, AlertDialogPopup, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPanel, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertDialogViewport, AnchoredToastProvider, Avatar, AvatarFallback, AvatarImage, BidiText, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, CalendarCell, CalendarEntryButton, CalendarEntrySurface, CalendarGrid, CalendarHeaderCell, CalendarHeaderRow, Checkbox, ColorPicker, ColorPickerContent, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxClear, ComboboxCollection, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxRow, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandCollection, CommandDialog, CommandDialogPopup, CommandDialogTrigger, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, DEFAULT_PRESETS, DataTable, DatePickerPopover, DestructiveActionConfirmation, DestructiveConfirmDialog, Dialog, DialogBackdrop, DialogBackdrop as DialogOverlay, DialogClose, DialogPopup as DialogContent, DialogPopup, DialogCreateHandle, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPortal, DialogTitle, DialogTrigger, DialogViewport, DirectionalIcon, DiscordLogoIcon, Menu as DropdownMenu, Menu, MenuCheckboxItem as DropdownMenuCheckboxItem, MenuCheckboxItem, MenuPopup as DropdownMenuContent, MenuPopup, MenuCreateHandle as DropdownMenuCreateHandle, MenuCreateHandle, MenuGroup as DropdownMenuGroup, MenuGroup, MenuItem as DropdownMenuItem, MenuItem, MenuGroupLabel as DropdownMenuLabel, MenuGroupLabel, MenuPortal as DropdownMenuPortal, MenuPortal, MenuRadioGroup as DropdownMenuRadioGroup, MenuRadioGroup, MenuRadioItem as DropdownMenuRadioItem, MenuRadioItem, MenuSeparator as DropdownMenuSeparator, MenuSeparator, MenuShortcut as DropdownMenuShortcut, MenuShortcut, MenuSub as DropdownMenuSub, MenuSub, MenuSubPopup as DropdownMenuSubContent, MenuSubPopup, MenuSubTrigger as DropdownMenuSubTrigger, MenuSubTrigger, MenuTrigger as DropdownMenuTrigger, MenuTrigger, Field, FieldControl, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, Form, Frame, FrameDescription, FrameFooter, FrameHeader, FramePanel, FrameTitle, GitHubLogoIcon, HexColorPicker, PreviewCard as HoverCard, PreviewCard, PreviewCardPopup as HoverCardContent, PreviewCardPopup, PreviewCardTrigger as HoverCardTrigger, PreviewCardTrigger, INSPECTOR_CONTENT_MIN_WIDTH, INSPECTOR_PANE_DEFAULT_WIDTH, INSPECTOR_PANE_KEYBOARD_PAGE_STEP, INSPECTOR_PANE_KEYBOARD_STEP, INSPECTOR_PANE_MAX_WIDTH, INSPECTOR_PANE_MIN_WIDTH, INSPECTOR_RAIL_WIDTH, Input, InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Inspector, InspectorActions, InspectorContent, InspectorDescription, InspectorDock, InspectorEmptyRow, InspectorHeader, InspectorHeaderText, InspectorProperty, InspectorPropertyLabel, InspectorPropertyList, InspectorPropertyValue, InspectorRail, InspectorRailCell, InspectorRailIconButton, InspectorRailTab, InspectorSection, InspectorSectionTitle, InspectorTitle, KANBAN_BOARD_AUTO_SCROLL_SOURCES, KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanCardShell, KanbanColumnHeader, KanbanDragHandle, KanbanSortableBoard, KanbanSortableColumns, KanbanSortableList, Label, MenuPreviewLayout, OVERLAY_LAYER_CLASS_NAMES, OutlineRail, PROPERTY_ROW_GRID, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverClose, PopoverPopup as PopoverContent, PopoverPopup, PopoverCreateHandle, PopoverDescription, PopoverPanel, PopoverTitle, PopoverTrigger, PreviewCardPrimitive, PreviewPane, ResourceCalendar, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, ScrollArea, ScrollBar, ScrollToTop, SecretInput, SegmentedIconToggle, Select, SelectPopup as SelectContent, SelectPopup, SelectGroup, SelectGroupLabel, SelectItem, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetBackdrop, SheetBackdrop as SheetOverlay, SheetClose, SheetPopup as SheetContent, SheetPopup, SheetDescription, SheetFooter, SheetHeader, SheetPanel, SheetPortal, SheetTitle, SheetTrigger, Skeleton, SortableHead, StellaMark, StellaWordmarkLatin, TOAST_RIGHT_OFFSET_VAR, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsPanel as TabsContent, TabsPanel, TabsList, TabsTab, TabsTab as TabsTrigger, TextSeparator, Textarea, ToastProvider, Tooltip, TooltipPopup as TooltipContent, TooltipPopup, TooltipCreateHandle, TooltipProvider, TooltipTrigger, UserText, assertConsecutiveCalendarDates, buttonAccessibleDisabledClass, buttonVariants, cn, composeRefs, containedEventHandler, containedHandler, contentDir, duplicateColumnIds, emptyColor, findTableColumn, getFirstWeekday, getKanbanGroupingPropertyId, getKanbanGroups, getKanbanHorizontalEdge, getLocaleWeekInfo, getResourceCalendarPlacement, getWeekendDays, hideableColumnIds, isKanbanGroupingRenderable, isStructuredInputType, layoutResourceCalendarEntries, nextCalendarDate, optionColors, parsePersistedPaneWidth, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveDragWidth, resolveInspectorDockWidth, resolveInspectorPaneMaxWidth, resolveInspectorPaneWidth, resolveKanbanGroupOptions, resolveKanbanGrouping, resolveKeyboardWidth, resolveOptionColor, selectKanbanCardFieldIds, selectKanbanRows, shouldForceSidebarCollapsed, sortableColumnIds, stellaToast, tableColumnIds, tableColumnSizing, useComboboxFilter, useContentDir, useDestructiveActionConfirmation, useInspectorPaneWidth, useIsMobile, useKanbanSortable, useKanbanSortableSensors, useLatest, useViewportWidth, visibleColumnIds };
@@ -30,7 +30,12 @@ declare const InspectorRail: ({ className, ...props }: React$1.ComponentProps<"n
30
30
  /** A rail cell: same height as every header strip and property row. */
31
31
  declare const InspectorRailCell: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
32
32
  declare const InspectorRailIconButton: ({ className, ...props }: React$1.ComponentProps<"button">) => React$1.JSX.Element;
33
- /** A square rail chip. Active state uses the same filled box in every dock. */
33
+ /**
34
+ * A rail tab: one full-width row, bordered like every other rail cell, so
35
+ * the stack reads as boxes in every dock. The active tab carries a 2px spine
36
+ * on the rail's inline-start edge — the same affordance the workspace rail
37
+ * uses to say "this pane is showing that tab".
38
+ */
34
39
  declare const InspectorRailTab: ({ active, className, ...props }: React$1.ComponentProps<"button"> & {
35
40
  active?: boolean;
36
41
  }) => React$1.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../lib/utils.js";
2
- import { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_HIT_TARGET_SIZE, TOOLBAR_ROW_HEIGHT } from "./layout-tokens.js";
2
+ import { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, TOOLBAR_ROW_HEIGHT } from "./layout-tokens.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/inspector/chrome.tsx
5
5
  /**
@@ -49,10 +49,15 @@ const InspectorRailIconButton = ({ className, ...props }) => /* @__PURE__ */ jsx
49
49
  type: "button",
50
50
  ...props
51
51
  });
52
- /** A square rail chip. Active state uses the same filled box in every dock. */
52
+ /**
53
+ * A rail tab: one full-width row, bordered like every other rail cell, so
54
+ * the stack reads as boxes in every dock. The active tab carries a 2px spine
55
+ * on the rail's inline-start edge — the same affordance the workspace rail
56
+ * uses to say "this pane is showing that tab".
57
+ */
53
58
  const InspectorRailTab = ({ active = false, className, ...props }) => /* @__PURE__ */ jsx("button", {
54
59
  "aria-current": active ? "true" : void 0,
55
- className: cn("group/tab relative flex items-center justify-center rounded-md transition-colors before:pointer-events-none before:absolute before:inset-2 before:rounded-md before:transition-colors before:content-[''] [&>*]:relative [&>*]:z-10", SIDE_RAIL_TAB_HIT_TARGET_SIZE, active ? "text-foreground before:bg-accent" : "text-muted-foreground hover:text-foreground hover:before:bg-accent", className),
60
+ className: cn("group/tab relative flex w-full shrink-0 items-center justify-center border-b transition-colors", TOOLBAR_ROW_HEIGHT, active ? "bg-background text-foreground before:bg-primary before:absolute before:inset-y-0 before:inset-s-0 before:w-0.5" : "text-muted-foreground hover:bg-accent hover:text-foreground", className),
56
61
  "data-active": active ? "" : void 0,
57
62
  "data-slot": "inspector-rail-tab",
58
63
  type: "button",
@@ -21,9 +21,8 @@ declare const SIDE_RAIL_WIDTH: "w-12";
21
21
  */
22
22
  declare const SIDE_RAIL_CONTAINER_CLASS: "bg-sidebar flex shrink-0 flex-col border-s border-e w-12";
23
23
  declare const SIDE_RAIL_ICON_BUTTON_SIZE: "size-8";
24
- declare const SIDE_RAIL_TAB_HIT_TARGET_SIZE: "size-12";
25
24
  declare const SIDE_RAIL_TAB_ICON_SIZE: "size-3.5";
26
25
  /** Two-column grid the key/value rows share. */
27
26
  declare const PROPERTY_ROW_GRID: "grid-cols-[8rem_minmax(0,1fr)]";
28
27
  //#endregion
29
- export { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_HIT_TARGET_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX };
28
+ export { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX };
@@ -21,9 +21,8 @@ const SIDE_RAIL_WIDTH = "w-12";
21
21
  */
22
22
  const SIDE_RAIL_CONTAINER_CLASS = `bg-sidebar flex shrink-0 flex-col border-s border-e ${SIDE_RAIL_WIDTH}`;
23
23
  const SIDE_RAIL_ICON_BUTTON_SIZE = "size-8";
24
- const SIDE_RAIL_TAB_HIT_TARGET_SIZE = "size-12";
25
24
  const SIDE_RAIL_TAB_ICON_SIZE = "size-3.5";
26
25
  /** Two-column grid the key/value rows share. */
27
26
  const PROPERTY_ROW_GRID = "grid-cols-[8rem_minmax(0,1fr)]";
28
27
  //#endregion
29
- export { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_HIT_TARGET_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX };
28
+ export { PROPERTY_ROW_GRID, SIDE_RAIL_CONTAINER_CLASS, SIDE_RAIL_ICON_BUTTON_SIZE, SIDE_RAIL_TAB_ICON_SIZE, SIDE_RAIL_WIDTH, TOOLBAR_ROW_HEIGHT, TOOLBAR_ROW_HEIGHT_PX };
@@ -1,6 +1,8 @@
1
1
  import { KanbanCardFieldSelection, selectKanbanCardFieldIds } from "./card-properties.js";
2
2
  import { KanbanCardShell, KanbanCardShellProps } from "./card-shell.js";
3
3
  import { KanbanColumnHeader, KanbanColumnHeaderProps } from "./column-header.js";
4
+ import { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanDragHandle, KanbanDragHandleProps, KanbanSortableBindings, KanbanSortableBoard, KanbanSortableBoardProps, KanbanSortableColumns, KanbanSortableColumnsProps, KanbanSortableList, KanbanSortableListProps, UseKanbanSortableOptions, useKanbanSortable, useKanbanSortableSensors } from "./sortable-interactions.js";
5
+ import { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KanbanDirection, KanbanHorizontalEdge, getKanbanHorizontalEdge } from "./sortable-edge.js";
4
6
  import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, RegisterKanbanBoardAutoScrollOptions, RegisterKanbanCardDragOptions, registerKanbanBoardAutoScroll, registerKanbanCardDrag } from "./drag-interactions.js";
5
7
  import { KanbanBuiltInGroup, KanbanGroup, KanbanGroupOption, KanbanGrouping, KanbanSchema, ResolveKanbanGroupingParams, getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./grouping.js";
6
- export { KANBAN_BOARD_AUTO_SCROLL_SOURCES, type KanbanBuiltInGroup, type KanbanCardFieldSelection, KanbanCardShell, type KanbanCardShellProps, KanbanColumnHeader, type KanbanColumnHeaderProps, type KanbanGroup, type KanbanGroupOption, type KanbanGrouping, type KanbanSchema, type RegisterKanbanBoardAutoScrollOptions, type RegisterKanbanCardDragOptions, type ResolveKanbanGroupingParams, getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanCardFieldIds, selectKanbanRows };
8
+ export { KANBAN_BOARD_AUTO_SCROLL_SOURCES, KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, type KanbanBuiltInGroup, type KanbanCardFieldSelection, KanbanCardShell, type KanbanCardShellProps, KanbanColumnHeader, type KanbanColumnHeaderProps, type KanbanDirection, KanbanDragHandle, type KanbanDragHandleProps, type KanbanGroup, type KanbanGroupOption, type KanbanGrouping, type KanbanHorizontalEdge, type KanbanSchema, type KanbanSortableBindings, KanbanSortableBoard, type KanbanSortableBoardProps, KanbanSortableColumns, type KanbanSortableColumnsProps, KanbanSortableList, type KanbanSortableListProps, type RegisterKanbanBoardAutoScrollOptions, type RegisterKanbanCardDragOptions, type ResolveKanbanGroupingParams, type UseKanbanSortableOptions, getKanbanGroupingPropertyId, getKanbanGroups, getKanbanHorizontalEdge, isKanbanGroupingRenderable, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanCardFieldIds, selectKanbanRows, useKanbanSortable, useKanbanSortableSensors };
@@ -1,6 +1,8 @@
1
1
  import { selectKanbanCardFieldIds } from "./card-properties.js";
2
2
  import { KanbanCardShell } from "./card-shell.js";
3
3
  import { KanbanColumnHeader } from "./column-header.js";
4
+ import { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanDragHandle, KanbanSortableBoard, KanbanSortableColumns, KanbanSortableList, useKanbanSortable, useKanbanSortableSensors } from "./sortable-interactions.js";
5
+ import { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, getKanbanHorizontalEdge } from "./sortable-edge.js";
4
6
  import { KANBAN_BOARD_AUTO_SCROLL_SOURCES, registerKanbanBoardAutoScroll, registerKanbanCardDrag } from "./drag-interactions.js";
5
7
  import { getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanRows } from "./grouping.js";
6
- export { KANBAN_BOARD_AUTO_SCROLL_SOURCES, KanbanCardShell, KanbanColumnHeader, getKanbanGroupingPropertyId, getKanbanGroups, isKanbanGroupingRenderable, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanCardFieldIds, selectKanbanRows };
8
+ export { KANBAN_BOARD_AUTO_SCROLL_SOURCES, KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanCardShell, KanbanColumnHeader, KanbanDragHandle, KanbanSortableBoard, KanbanSortableColumns, KanbanSortableList, getKanbanGroupingPropertyId, getKanbanGroups, getKanbanHorizontalEdge, isKanbanGroupingRenderable, registerKanbanBoardAutoScroll, registerKanbanCardDrag, resolveKanbanGroupOptions, resolveKanbanGrouping, selectKanbanCardFieldIds, selectKanbanRows, useKanbanSortable, useKanbanSortableSensors };
@@ -0,0 +1,39 @@
1
+ import { ClientRect } from "@dnd-kit/core";
2
+ //#region src/kanban/sortable-edge.d.ts
3
+ declare const KANBAN_HORIZONTAL_EDGES: {
4
+ readonly before: "before";
5
+ readonly after: "after";
6
+ };
7
+ type KanbanHorizontalEdge = (typeof KANBAN_HORIZONTAL_EDGES)[keyof typeof KANBAN_HORIZONTAL_EDGES];
8
+ declare const KANBAN_DIRECTIONS: {
9
+ readonly ltr: "ltr";
10
+ readonly rtl: "rtl";
11
+ };
12
+ type KanbanDirection = (typeof KANBAN_DIRECTIONS)[keyof typeof KANBAN_DIRECTIONS];
13
+ type KanbanPointerHorizontalEdgeOptions = {
14
+ input: "pointer";
15
+ /** The drag's current viewport x coordinate for mouse or touch input. */
16
+ currentClientX: number;
17
+ overRect: ClientRect;
18
+ /** Maps physical mouse and touch positions to the board's logical order. */
19
+ direction?: KanbanDirection | undefined;
20
+ };
21
+ type KanbanKeyboardHorizontalEdgeOptions = {
22
+ input: "keyboard";
23
+ /** The source item's position in logical board order. */
24
+ sourceIndex: number;
25
+ /** The target item's position in logical board order. */
26
+ targetIndex: number;
27
+ };
28
+ type KanbanHorizontalEdgeOptions = KanbanPointerHorizontalEdgeOptions | KanbanKeyboardHorizontalEdgeOptions;
29
+ /**
30
+ * Resolves a horizontal insertion edge without consulting application data.
31
+ *
32
+ * Mouse and touch callers pass their current viewport coordinate. Keyboard
33
+ * callers pass source and target indices, making every logical move
34
+ * unambiguous. This deliberately avoids drag deltas, which include scroll
35
+ * reconciliation and are not viewport coordinates.
36
+ */
37
+ declare const getKanbanHorizontalEdge: ({ ...options }: KanbanHorizontalEdgeOptions) => KanbanHorizontalEdge;
38
+ //#endregion
39
+ export { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, KanbanDirection, KanbanHorizontalEdge, KanbanHorizontalEdgeOptions, getKanbanHorizontalEdge };
@@ -0,0 +1,27 @@
1
+ //#region src/kanban/sortable-edge.ts
2
+ const KANBAN_HORIZONTAL_EDGES = {
3
+ before: "before",
4
+ after: "after"
5
+ };
6
+ const KANBAN_DIRECTIONS = {
7
+ ltr: "ltr",
8
+ rtl: "rtl"
9
+ };
10
+ /**
11
+ * Resolves a horizontal insertion edge without consulting application data.
12
+ *
13
+ * Mouse and touch callers pass their current viewport coordinate. Keyboard
14
+ * callers pass source and target indices, making every logical move
15
+ * unambiguous. This deliberately avoids drag deltas, which include scroll
16
+ * reconciliation and are not viewport coordinates.
17
+ */
18
+ const getKanbanHorizontalEdge = ({ ...options }) => {
19
+ if (options.input === "keyboard") return options.sourceIndex < options.targetIndex ? KANBAN_HORIZONTAL_EDGES.after : KANBAN_HORIZONTAL_EDGES.before;
20
+ const { currentClientX, direction = KANBAN_DIRECTIONS.ltr, overRect } = options;
21
+ const physicalEdge = currentClientX < getRectCenterX(overRect) ? KANBAN_HORIZONTAL_EDGES.before : KANBAN_HORIZONTAL_EDGES.after;
22
+ if (direction === KANBAN_DIRECTIONS.rtl) return physicalEdge === KANBAN_HORIZONTAL_EDGES.before ? KANBAN_HORIZONTAL_EDGES.after : KANBAN_HORIZONTAL_EDGES.before;
23
+ return physicalEdge;
24
+ };
25
+ const getRectCenterX = ({ left, width }) => left + width / 2;
26
+ //#endregion
27
+ export { KANBAN_DIRECTIONS, KANBAN_HORIZONTAL_EDGES, getKanbanHorizontalEdge };
@@ -0,0 +1,75 @@
1
+ import { Button } from "../components/button.js";
2
+ import * as React$1 from "react";
3
+ import { AutoScrollOptions, CollisionDetection, DndContextProps, DragCancelEvent, DragEndEvent, DragOverlayProps, DragStartEvent, KeyboardCoordinateGetter, UniqueIdentifier } from "@dnd-kit/core";
4
+ import { SortableContextProps, useSortable } from "@dnd-kit/sortable";
5
+ //#region src/kanban/sortable-interactions.d.ts
6
+ declare const KANBAN_MOUSE_ACTIVATION_DISTANCE = 8;
7
+ declare const KANBAN_TOUCH_ACTIVATION_CONSTRAINT: {
8
+ readonly delay: 150;
9
+ readonly tolerance: 8;
10
+ };
11
+ type KanbanSortableBoardProps = {
12
+ children: React$1.ReactNode;
13
+ onDragEnd: (event: DragEndEvent) => void;
14
+ collisionDetection?: CollisionDetection | undefined;
15
+ keyboardCoordinates?: KeyboardCoordinateGetter | undefined;
16
+ autoScroll?: boolean | AutoScrollOptions | undefined;
17
+ /** Replaces the default mouse, touch, and keyboard sensors when supplied. */
18
+ sensors?: DndContextProps["sensors"] | undefined;
19
+ /** Overrides dnd-kit's screen-reader announcements when supplied. */
20
+ accessibility?: DndContextProps["accessibility"] | undefined;
21
+ onDragStart?: ((event: DragStartEvent) => void) | undefined;
22
+ onDragCancel?: ((event: DragCancelEvent) => void) | undefined;
23
+ /** Rendered in document.body while an item is active. */
24
+ overlay?: ((activeId: UniqueIdentifier | null) => React$1.ReactNode) | undefined;
25
+ overlayProps?: Omit<DragOverlayProps, "children"> | undefined;
26
+ };
27
+ /**
28
+ * Input-complete drag context for sortable boards.
29
+ *
30
+ * The consumer owns identifiers and the result of a drop; this component owns
31
+ * the sensor activation rules, keyboard navigation, auto-scroll configuration,
32
+ * and overlay lifecycle shared by sortable board UIs.
33
+ */
34
+ declare const KanbanSortableBoard: ({ children, onDragEnd, collisionDetection, keyboardCoordinates, autoScroll, sensors, accessibility, onDragStart, onDragCancel, overlay, overlayProps }: KanbanSortableBoardProps) => React$1.JSX.Element;
35
+ declare const useKanbanSortableSensors: (keyboardCoordinates?: KeyboardCoordinateGetter) => import("@dnd-kit/core").SensorDescriptor<import("@dnd-kit/core").SensorOptions>[];
36
+ type KanbanSortableListProps = SortableContextProps & React$1.ComponentProps<"div">;
37
+ /** A vertical card list that preserves native vertical touch scrolling. */
38
+ declare const KanbanSortableList: ({ className, children, id, items, strategy, disabled, ...props }: KanbanSortableListProps) => React$1.JSX.Element;
39
+ type KanbanSortableColumnsProps = SortableContextProps & React$1.ComponentProps<"div">;
40
+ /** A horizontal column list that keeps the board pan gesture available. */
41
+ declare const KanbanSortableColumns: ({ className, children, id, items, strategy, disabled, ...props }: KanbanSortableColumnsProps) => React$1.JSX.Element;
42
+ type KanbanSortableBindings = Pick<ReturnType<typeof useSortable>, "attributes" | "listeners" | "setActivatorNodeRef">;
43
+ type UseKanbanSortableOptions = {
44
+ id: UniqueIdentifier;
45
+ disabled?: boolean | undefined;
46
+ };
47
+ /**
48
+ * Connect a sortable item and its separate drag handle without making the
49
+ * item's content a touch-none activation surface.
50
+ */
51
+ declare const useKanbanSortable: ({ id, disabled }: UseKanbanSortableOptions) => {
52
+ isDragging: boolean;
53
+ setNodeRef: (node: HTMLElement | null) => void;
54
+ style: {
55
+ transform: string | undefined;
56
+ transition: string | undefined;
57
+ };
58
+ dragHandle: {
59
+ attributes: import("@dnd-kit/core").DraggableAttributes;
60
+ listeners: import("@dnd-kit/core/dist/hooks/utilities").SyntheticListenerMap | undefined;
61
+ setActivatorNodeRef: (element: HTMLElement | null) => void;
62
+ };
63
+ };
64
+ type KanbanDragHandleProps = {
65
+ bindings: KanbanSortableBindings;
66
+ label: string;
67
+ } & Omit<React$1.ComponentProps<typeof Button>, "aria-label" | "children" | "ref" | "tooltip" | "type">;
68
+ /**
69
+ * A 44px keyboard-accessible drag activator. The handle is the only board
70
+ * surface that disables touch panning, leaving cards and scroll regions free
71
+ * for ordinary scrolling.
72
+ */
73
+ declare const KanbanDragHandle: ({ bindings, label, className, ...props }: KanbanDragHandleProps) => React$1.JSX.Element;
74
+ //#endregion
75
+ export { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanDragHandle, KanbanDragHandleProps, KanbanSortableBindings, KanbanSortableBoard, KanbanSortableBoardProps, KanbanSortableColumns, KanbanSortableColumnsProps, KanbanSortableList, KanbanSortableListProps, UseKanbanSortableOptions, useKanbanSortable, useKanbanSortableSensors };
@@ -0,0 +1,210 @@
1
+ "use client";
2
+ import { cn } from "../lib/utils.js";
3
+ import { Button } from "../components/button.js";
4
+ import { isActiveTouchChange } from "./touch-identity.js";
5
+ import { GripVerticalIcon } from "lucide-react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import * as React$1 from "react";
8
+ import { createPortal } from "react-dom";
9
+ import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, useSensor, useSensors } from "@dnd-kit/core";
10
+ import { SortableContext, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
11
+ //#region src/kanban/sortable-interactions.tsx
12
+ const KANBAN_MOUSE_ACTIVATION_DISTANCE = 8;
13
+ const KANBAN_TOUCH_ACTIVATION_CONSTRAINT = {
14
+ delay: 150,
15
+ tolerance: 8
16
+ };
17
+ const hasTouchLists = (event) => "changedTouches" in event && "touches" in event;
18
+ const getTouchIdentifier = (event) => {
19
+ if (!hasTouchLists(event)) return null;
20
+ return event.changedTouches.item(0)?.identifier ?? event.touches.item(0)?.identifier ?? null;
21
+ };
22
+ const getTouchIdentifiers = (touches) => {
23
+ const identifiers = [];
24
+ for (let index = 0; index < touches.length; index += 1) {
25
+ const identifier = touches.item(index)?.identifier;
26
+ if (identifier !== void 0) identifiers.push(identifier);
27
+ }
28
+ return identifiers;
29
+ };
30
+ /**
31
+ * Keeps a delayed touch drag bound to the finger that activated it.
32
+ *
33
+ * dnd-kit's stock touch sensor attaches document-level lifecycle listeners,
34
+ * so a second finger can otherwise move, end, or cancel the active drag. The
35
+ * capture listeners below suppress only secondary touch changes before those
36
+ * listeners receive them; browser scrolling remains native because no default
37
+ * action is prevented here.
38
+ */
39
+ var KanbanTouchSensor = class extends TouchSensor {
40
+ identityListeners;
41
+ ownerDocument;
42
+ touchIdentifier;
43
+ constructor(props) {
44
+ const identityListeners = new AbortController();
45
+ super({
46
+ ...props,
47
+ onAbort: (active) => {
48
+ identityListeners.abort();
49
+ props.onAbort(active);
50
+ },
51
+ onCancel: () => {
52
+ identityListeners.abort();
53
+ props.onCancel();
54
+ },
55
+ onEnd: () => {
56
+ identityListeners.abort();
57
+ props.onEnd();
58
+ }
59
+ });
60
+ this.identityListeners = identityListeners;
61
+ this.ownerDocument = getTouchDocument(props.event);
62
+ this.touchIdentifier = getTouchIdentifier(props.event);
63
+ this.ownerDocument.addEventListener("touchmove", this.handleTouchMove, {
64
+ capture: true,
65
+ passive: false,
66
+ signal: identityListeners.signal
67
+ });
68
+ this.ownerDocument.addEventListener("touchend", this.handleTouchEnd, {
69
+ capture: true,
70
+ signal: identityListeners.signal
71
+ });
72
+ this.ownerDocument.addEventListener("touchcancel", this.handleTouchCancel, {
73
+ capture: true,
74
+ signal: identityListeners.signal
75
+ });
76
+ }
77
+ handleTouchMove = (event) => {
78
+ if (this.isPrimaryTouchChange(event)) return;
79
+ event.stopImmediatePropagation();
80
+ };
81
+ handleTouchEnd = (event) => {
82
+ if (!this.isPrimaryTouchChange(event)) {
83
+ event.stopImmediatePropagation();
84
+ return;
85
+ }
86
+ this.detachIdentityListeners();
87
+ };
88
+ handleTouchCancel = (event) => {
89
+ if (!this.isPrimaryTouchChange(event)) {
90
+ event.stopImmediatePropagation();
91
+ return;
92
+ }
93
+ this.detachIdentityListeners();
94
+ };
95
+ isPrimaryTouchChange = (event) => isActiveTouchChange({
96
+ activeTouchIdentifier: this.touchIdentifier,
97
+ changedTouchIdentifiers: getTouchIdentifiers(event.changedTouches)
98
+ });
99
+ detachIdentityListeners = () => {
100
+ this.identityListeners.abort();
101
+ };
102
+ };
103
+ const getTouchDocument = (event) => {
104
+ if (event.target instanceof Node && event.target.ownerDocument) return event.target.ownerDocument;
105
+ return document;
106
+ };
107
+ /**
108
+ * Input-complete drag context for sortable boards.
109
+ *
110
+ * The consumer owns identifiers and the result of a drop; this component owns
111
+ * the sensor activation rules, keyboard navigation, auto-scroll configuration,
112
+ * and overlay lifecycle shared by sortable board UIs.
113
+ */
114
+ const KanbanSortableBoard = ({ children, onDragEnd, collisionDetection, keyboardCoordinates, autoScroll, sensors, accessibility, onDragStart, onDragCancel, overlay, overlayProps }) => {
115
+ const [activeId, setActiveId] = React$1.useState(null);
116
+ const defaultSensors = useKanbanSortableSensors(keyboardCoordinates);
117
+ const handleDragStart = (event) => {
118
+ setActiveId(event.active.id);
119
+ onDragStart?.(event);
120
+ };
121
+ const handleDragEnd = (event) => {
122
+ setActiveId(null);
123
+ onDragEnd(event);
124
+ };
125
+ const handleDragCancel = (event) => {
126
+ setActiveId(null);
127
+ onDragCancel?.(event);
128
+ };
129
+ return /* @__PURE__ */ jsxs(DndContext, {
130
+ ...autoScroll === void 0 ? {} : { autoScroll },
131
+ ...accessibility === void 0 ? {} : { accessibility },
132
+ ...collisionDetection === void 0 ? {} : { collisionDetection },
133
+ onDragCancel: handleDragCancel,
134
+ onDragEnd: handleDragEnd,
135
+ onDragStart: handleDragStart,
136
+ sensors: sensors ?? defaultSensors,
137
+ children: [children, overlay && typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsx(DragOverlay, {
138
+ ...overlayProps,
139
+ children: overlay(activeId)
140
+ }), document.body) : null]
141
+ });
142
+ };
143
+ const useKanbanSortableSensors = (keyboardCoordinates = sortableKeyboardCoordinates) => useSensors(useSensor(MouseSensor, { activationConstraint: { distance: 8 } }), useSensor(KanbanTouchSensor, { activationConstraint: KANBAN_TOUCH_ACTIVATION_CONSTRAINT }), useSensor(KeyboardSensor, { coordinateGetter: keyboardCoordinates }));
144
+ /** A vertical card list that preserves native vertical touch scrolling. */
145
+ const KanbanSortableList = ({ className, children, id, items, strategy, disabled, ...props }) => /* @__PURE__ */ jsx(SortableContext, {
146
+ ...disabled === void 0 ? {} : { disabled },
147
+ ...id === void 0 ? {} : { id },
148
+ items,
149
+ ...strategy === void 0 ? {} : { strategy },
150
+ children: /* @__PURE__ */ jsx("div", {
151
+ className: cn("min-h-0 touch-auto overflow-y-auto overscroll-y-contain", className),
152
+ ...props,
153
+ children
154
+ })
155
+ });
156
+ /** A horizontal column list that keeps the board pan gesture available. */
157
+ const KanbanSortableColumns = ({ className, children, id, items, strategy, disabled, ...props }) => /* @__PURE__ */ jsx(SortableContext, {
158
+ ...disabled === void 0 ? {} : { disabled },
159
+ ...id === void 0 ? {} : { id },
160
+ items,
161
+ ...strategy === void 0 ? {} : { strategy },
162
+ children: /* @__PURE__ */ jsx("div", {
163
+ className: cn("flex min-h-0 touch-auto overflow-x-auto overscroll-x-contain", className),
164
+ ...props,
165
+ children
166
+ })
167
+ });
168
+ /**
169
+ * Connect a sortable item and its separate drag handle without making the
170
+ * item's content a touch-none activation surface.
171
+ */
172
+ const useKanbanSortable = ({ id, disabled }) => {
173
+ const sortable = useSortable({
174
+ id,
175
+ ...disabled === void 0 ? {} : { disabled }
176
+ });
177
+ return {
178
+ isDragging: sortable.isDragging,
179
+ setNodeRef: sortable.setNodeRef,
180
+ style: {
181
+ transform: sortable.transform ? `translate3d(${sortable.transform.x}px, ${sortable.transform.y}px, 0)` : void 0,
182
+ transition: sortable.transition
183
+ },
184
+ dragHandle: {
185
+ attributes: sortable.attributes,
186
+ listeners: sortable.listeners,
187
+ setActivatorNodeRef: sortable.setActivatorNodeRef
188
+ }
189
+ };
190
+ };
191
+ /**
192
+ * A 44px keyboard-accessible drag activator. The handle is the only board
193
+ * surface that disables touch panning, leaving cards and scroll regions free
194
+ * for ordinary scrolling.
195
+ */
196
+ const KanbanDragHandle = ({ bindings, label, className, ...props }) => /* @__PURE__ */ jsx(Button, {
197
+ ...props,
198
+ ...bindings.attributes,
199
+ ...bindings.listeners,
200
+ "aria-label": label,
201
+ className: cn("size-11 touch-none sm:size-11", className),
202
+ ref: (element) => bindings.setActivatorNodeRef(element),
203
+ size: "icon-xl",
204
+ tooltip: false,
205
+ type: "button",
206
+ variant: "ghost",
207
+ children: /* @__PURE__ */ jsx(GripVerticalIcon, { "aria-hidden": "true" })
208
+ });
209
+ //#endregion
210
+ export { KANBAN_MOUSE_ACTIVATION_DISTANCE, KANBAN_TOUCH_ACTIVATION_CONSTRAINT, KanbanDragHandle, KanbanSortableBoard, KanbanSortableColumns, KanbanSortableList, useKanbanSortable, useKanbanSortableSensors };
@@ -0,0 +1,8 @@
1
+ //#region src/kanban/touch-identity.d.ts
2
+ type ActiveTouchChangeOptions = {
3
+ activeTouchIdentifier: number | null;
4
+ changedTouchIdentifiers: readonly number[];
5
+ };
6
+ declare const isActiveTouchChange: ({ activeTouchIdentifier, changedTouchIdentifiers }: ActiveTouchChangeOptions) => boolean;
7
+ //#endregion
8
+ export { isActiveTouchChange };
@@ -0,0 +1,4 @@
1
+ //#region src/kanban/touch-identity.ts
2
+ const isActiveTouchChange = ({ activeTouchIdentifier, changedTouchIdentifiers }) => activeTouchIdentifier === null || changedTouchIdentifiers.includes(activeTouchIdentifier);
3
+ //#endregion
4
+ export { isActiveTouchChange };
@@ -69,6 +69,32 @@
69
69
  affordance the user has to notice, not merely acknowledge. */
70
70
  --animate-attention-flash: attention-flash 700ms ease-out;
71
71
  --animate-attention-flash-twice: attention-flash 700ms ease-out 2;
72
+ /* The Stella mark breathing: the one indeterminate loading motion.
73
+ Opacity and scale only, so it never triggers layout. */
74
+ --animate-loader: loader 1.8s ease-in-out infinite;
75
+ /* A list item settling into place; callers stagger it by index. */
76
+ --animate-rise: rise 240ms ease-out both;
77
+ @keyframes loader {
78
+ 0%,
79
+ 100% {
80
+ opacity: 0.35;
81
+ transform: scale(0.94);
82
+ }
83
+ 50% {
84
+ opacity: 1;
85
+ transform: scale(1);
86
+ }
87
+ }
88
+ @keyframes rise {
89
+ from {
90
+ opacity: 0;
91
+ transform: translateY(4px);
92
+ }
93
+ to {
94
+ opacity: 1;
95
+ transform: translateY(0);
96
+ }
97
+ }
72
98
  @keyframes skeleton {
73
99
  to {
74
100
  background-position: -200% 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/ui",
3
- "version": "0.5.2",
3
+ "version": "0.6.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",
@@ -201,6 +201,10 @@
201
201
  "types": "./dist/components/sheet.d.ts",
202
202
  "import": "./dist/components/sheet.js"
203
203
  },
204
+ "./loader": {
205
+ "types": "./dist/components/loader.d.ts",
206
+ "import": "./dist/components/loader.js"
207
+ },
204
208
  "./skeleton": {
205
209
  "types": "./dist/components/skeleton.d.ts",
206
210
  "import": "./dist/components/skeleton.js"
@@ -490,7 +494,10 @@
490
494
  "clean": "git clean -xdf dist .cache .turbo node_modules",
491
495
  "build": "tsdown",
492
496
  "pack:dry-run": "bun pm pack --dry-run",
493
- "test": "bun test src",
497
+ "test": "bun run test:unit",
498
+ "test:unit": "bun test src --path-ignore-patterns '**/*.playwright.spec.ts'",
499
+ "test:browser": "playwright test --config playwright.config.ts",
500
+ "pack:check": "cd ../.. && bun scripts/check-published-exports.ts packages/ui",
494
501
  "typecheck": "bun ../../packages/scripts/src/tsc-native.ts --noEmit",
495
502
  "lint": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --report-unused-disable-directives-severity=error --deny-warnings --type-aware packages/ui",
496
503
  "lint:fix": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --type-aware --fix packages/ui",
@@ -506,8 +513,11 @@
506
513
  },
507
514
  "devDependencies": {
508
515
  "@atlaskit/pragmatic-drag-and-drop": "^3.0.0",
509
- "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.0.1",
516
+ "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.1.0",
510
517
  "@base-ui/react": "1.7.0",
518
+ "@dnd-kit/core": "^6.3.1",
519
+ "@dnd-kit/sortable": "^10.0.0",
520
+ "@playwright/test": "^1.62.0",
511
521
  "@stll/typescript-config": "0.0.0",
512
522
  "@types/react": "^19.2.17",
513
523
  "@types/react-dom": "^19.2.3",
@@ -515,12 +525,15 @@
515
525
  "react": "^19.2.8",
516
526
  "react-dom": "^19.2.8",
517
527
  "tailwindcss": "4.3.3",
518
- "tsdown": "0.22.14"
528
+ "tsdown": "0.22.14",
529
+ "vite": "8.2.1"
519
530
  },
520
531
  "peerDependencies": {
521
532
  "@atlaskit/pragmatic-drag-and-drop": "^3.0.0",
522
- "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.0.1",
533
+ "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.1.0",
523
534
  "@base-ui/react": "^1.7.0",
535
+ "@dnd-kit/core": "^6.3.1",
536
+ "@dnd-kit/sortable": "^10.0.0",
524
537
  "react": ">=19",
525
538
  "react-dom": ">=19",
526
539
  "tailwindcss": "^4.3.0"