@stll/ui 0.9.0 → 0.12.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.
Files changed (40) hide show
  1. package/README.md +90 -15
  2. package/dist/components/breadcrumb.d.ts +1 -1
  3. package/dist/components/button-variants.d.ts +2 -2
  4. package/dist/components/button.d.ts +1 -1
  5. package/dist/components/combobox.js +1 -1
  6. package/dist/components/command.d.ts +1 -1
  7. package/dist/components/command.js +1 -1
  8. package/dist/components/date-picker-popover.js +1 -1
  9. package/dist/components/input-group.d.ts +1 -1
  10. package/dist/components/pagination.d.ts +1 -1
  11. package/dist/components/pagination.js +1 -1
  12. package/dist/components/select.d.ts +1 -1
  13. package/dist/components/select.js +8 -10
  14. package/dist/components/workspace-shell.d.ts +77 -0
  15. package/dist/components/workspace-shell.js +106 -0
  16. package/dist/index.d.ts +7 -6
  17. package/dist/index.js +11 -10
  18. package/dist/inspector/chrome.d.ts +5 -1
  19. package/dist/inspector/chrome.js +14 -2
  20. package/dist/inspector/index.d.ts +2 -2
  21. package/dist/inspector/index.js +2 -2
  22. package/dist/inspector/layout-tokens.d.ts +5 -1
  23. package/dist/inspector/layout-tokens.js +5 -1
  24. package/dist/kanban/grouping.d.ts +17 -17
  25. package/dist/kanban/index.d.ts +4 -3
  26. package/dist/kanban/index.js +3 -2
  27. package/dist/kanban/matrix.d.ts +15 -15
  28. package/dist/kanban/sortable-interactions.d.ts +75 -13
  29. package/dist/kanban/sortable-interactions.js +345 -28
  30. package/dist/kanban/sortable-interactions.logic.d.ts +79 -0
  31. package/dist/kanban/sortable-interactions.logic.js +205 -0
  32. package/dist/kanban/virtual-cell.d.ts +19 -2
  33. package/dist/kanban/virtual-cell.js +53 -7
  34. package/dist/lib/control-size.d.ts +1 -1
  35. package/dist/lib/overlay-layer.d.ts +2 -1
  36. package/dist/lib/overlay-layer.js +2 -1
  37. package/dist/review/review-comment-card.js +1 -1
  38. package/package.json +7 -7
  39. package/dist/components/application-shell.d.ts +0 -27
  40. package/dist/components/application-shell.js +0 -25
@@ -0,0 +1,205 @@
1
+ import { closestCorners, getFirstCollision, pointerWithin } from "@dnd-kit/core";
2
+ //#region src/kanban/sortable-interactions.logic.ts
3
+ const KANBAN_DROP_TARGET_TYPES = {
4
+ CELL: "kanban-cell",
5
+ ITEM: "kanban-item"
6
+ };
7
+ const isRecord = (value) => typeof value === "object" && value !== null;
8
+ const isUniqueIdentifier = (value) => typeof value === "string" || typeof value === "number";
9
+ const isCellPosition = (value) => isRecord(value) && typeof value["column"] === "number" && typeof value["lane"] === "number" && Number.isInteger(value["column"]) && Number.isInteger(value["lane"]) && value["column"] >= 0 && value["lane"] >= 0;
10
+ const isKanbanCellVirtualNavigation = (value) => isRecord(value) && (value["type"] === "static" || value["type"] === "virtual" && typeof value["requestScroll"] === "function");
11
+ const isKanbanCellDropData = (value) => isRecord(value) && value["type"] === KANBAN_DROP_TARGET_TYPES.CELL && Array.isArray(value["itemIds"]) && value["itemIds"].every(isUniqueIdentifier) && isKanbanCellVirtualNavigation(value["navigation"]) && isCellPosition(value["position"]);
12
+ const isKanbanItemDropData = (value) => {
13
+ if (!isRecord(value) || value["type"] !== KANBAN_DROP_TARGET_TYPES.ITEM) return false;
14
+ const navigation = value["navigation"];
15
+ const current = isRecord(navigation) ? navigation["current"] : void 0;
16
+ return isRecord(navigation) && isRecord(current) && (current["type"] === "idle" || (current["type"] === "ready" || current["type"] === "pending") && isUniqueIdentifier(current["targetId"]));
17
+ };
18
+ const getKanbanKeyboardTargetState = (value) => isKanbanItemDropData(value) ? value.navigation.current : void 0;
19
+ /**
20
+ * dnd-kit computes collisions while rendering but publishes the resulting drop
21
+ * target to its sensor context a render later, and resolves a drop from that
22
+ * published value. A drag that ends before the two agree, which every input
23
+ * can do because a single move produces a single render, drops the item on the
24
+ * previously published target.
25
+ *
26
+ * Keyboard navigation names its target outright, so it is compared directly: a
27
+ * pending target is still waiting for a virtual cell to mount an offscreen row
28
+ * and has produced no collision at all, and a ready one is only settled once it
29
+ * is the published target. Until then both the collisions and the published
30
+ * target still describe where the board was before the user navigated away.
31
+ */
32
+ const isKanbanDropSettled = ({ active, collisions, over }) => {
33
+ const target = getKanbanKeyboardTargetState(active?.data.current);
34
+ if (target?.type === "pending") return false;
35
+ if (target?.type === "ready") return over?.id === target.targetId;
36
+ return getFirstCollision(collisions, "id") === (over?.id ?? null);
37
+ };
38
+ const clearKanbanKeyboardTarget = (value) => {
39
+ if (isKanbanItemDropData(value) && value.navigation.current.type !== "idle") value.navigation.current = { type: "idle" };
40
+ };
41
+ const getSortableData = (value) => {
42
+ if (!isRecord(value)) return null;
43
+ const sortable = value["sortable"];
44
+ if (!isRecord(sortable) || !isUniqueIdentifier(sortable["containerId"]) || typeof sortable["index"] !== "number" || !Number.isInteger(sortable["index"]) || !Array.isArray(sortable["items"]) || !sortable["items"].every(isUniqueIdentifier)) return null;
45
+ return {
46
+ containerId: sortable["containerId"],
47
+ index: sortable["index"],
48
+ items: sortable["items"]
49
+ };
50
+ };
51
+ const isKanbanDroppable = ({ data }) => {
52
+ const value = data.current;
53
+ return isKanbanCellDropData(value) || isKanbanItemDropData(value);
54
+ };
55
+ /**
56
+ * Pointer and touch input must be inside a registered board target. Once that
57
+ * boundary is established, closest corners gives stable ranking across cells.
58
+ */
59
+ const KANBAN_BOARD_COLLISION_DETECTION = (args) => {
60
+ const boardContainers = args.droppableContainers.filter(isKanbanDroppable);
61
+ if (args.pointerCoordinates === null) {
62
+ const activeData = args.active.data.current;
63
+ if (isKanbanItemDropData(activeData)) {
64
+ if (activeData.navigation.current.type === "pending") return [];
65
+ if (activeData.navigation.current.type !== "ready") return closestCorners({
66
+ ...args,
67
+ droppableContainers: boardContainers
68
+ });
69
+ const { targetId } = activeData.navigation.current;
70
+ return boardContainers.some(({ id }) => id === targetId) ? [{ id: targetId }] : [];
71
+ }
72
+ return closestCorners({
73
+ ...args,
74
+ droppableContainers: boardContainers
75
+ });
76
+ }
77
+ const intersections = pointerWithin({
78
+ ...args,
79
+ droppableContainers: boardContainers
80
+ });
81
+ if (intersections.length === 0) return [];
82
+ const intersectingIds = new Set(intersections.map((intersection) => intersection.id));
83
+ return closestCorners({
84
+ ...args,
85
+ droppableContainers: boardContainers.filter(({ id }) => intersectingIds.has(id))
86
+ });
87
+ };
88
+ const getAdjacentCell = (cells, current, direction) => {
89
+ let columnOffset = 0;
90
+ let laneOffset = 0;
91
+ switch (direction) {
92
+ case "down":
93
+ laneOffset = 1;
94
+ break;
95
+ case "left":
96
+ columnOffset = -1;
97
+ break;
98
+ case "right":
99
+ columnOffset = 1;
100
+ break;
101
+ case "up": laneOffset = -1;
102
+ }
103
+ return cells.find(({ position }) => position.column === current.position.column + columnOffset && position.lane === current.position.lane + laneOffset);
104
+ };
105
+ const getKanbanKeyboardTarget = ({ activeId, cells, currentCellId, currentOverId, direction }) => {
106
+ const currentCell = cells.find(({ id }) => id === currentCellId);
107
+ if (currentCell === void 0) return;
108
+ const overIndex = currentCell.itemIds.indexOf(currentOverId);
109
+ const activeIndex = currentCell.itemIds.indexOf(activeId);
110
+ const currentIndex = overIndex !== -1 ? overIndex : activeIndex;
111
+ if (direction === "down" && currentIndex >= 0) {
112
+ const nextItem = currentCell.itemIds.at(currentIndex + 1);
113
+ if (nextItem !== void 0) return nextItem;
114
+ }
115
+ if (direction === "up" && currentIndex > 0) return currentCell.itemIds.at(currentIndex - 1);
116
+ const adjacentCell = getAdjacentCell(cells, currentCell, direction);
117
+ if (adjacentCell === void 0) return;
118
+ if (adjacentCell.itemIds.length === 0) return adjacentCell.id;
119
+ if (direction === "down") return adjacentCell.itemIds.at(0);
120
+ if (direction === "up") return adjacentCell.itemIds.at(-1);
121
+ const targetIndex = Math.max(currentIndex, 0);
122
+ return adjacentCell.itemIds.at(Math.min(targetIndex, adjacentCell.itemIds.length - 1)) ?? adjacentCell.id;
123
+ };
124
+ const getDirection = (code) => {
125
+ switch (code) {
126
+ case "ArrowDown": return "down";
127
+ case "ArrowLeft": return "left";
128
+ case "ArrowRight": return "right";
129
+ case "ArrowUp": return "up";
130
+ default: return null;
131
+ }
132
+ };
133
+ const getCellId = (container) => {
134
+ const data = container.data.current;
135
+ if (isKanbanCellDropData(data)) return container.id;
136
+ if (!isKanbanItemDropData(data)) return null;
137
+ return getSortableData(data)?.containerId ?? null;
138
+ };
139
+ /** Ordered two-dimensional navigation over item and empty-cell targets. */
140
+ const kanbanKeyboardCoordinates = (event, { active, context }) => {
141
+ const direction = getDirection(event.code);
142
+ if (direction === null) return;
143
+ event.preventDefault();
144
+ const cells = context.droppableContainers.getEnabled().filter(({ data }) => {
145
+ const value = data.current;
146
+ return isKanbanCellDropData(value);
147
+ }).flatMap((container) => {
148
+ const data = container.data.current;
149
+ return isKanbanCellDropData(data) ? [{
150
+ ...data,
151
+ id: container.id
152
+ }] : [];
153
+ });
154
+ const activeData = context.active?.data.current;
155
+ const keyboardTarget = getKanbanKeyboardTargetState(activeData);
156
+ const overId = keyboardTarget?.type === "ready" ? keyboardTarget.targetId : context.over?.id ?? active;
157
+ const overContainer = context.droppableContainers.get(overId);
158
+ const activeContainer = context.droppableContainers.get(active);
159
+ const currentCellId = (overContainer && getCellId(overContainer)) ?? (activeContainer && getCellId(activeContainer));
160
+ if (currentCellId === null || currentCellId === void 0) return;
161
+ const targetId = getKanbanKeyboardTarget({
162
+ activeId: active,
163
+ cells,
164
+ currentCellId,
165
+ currentOverId: overId,
166
+ direction
167
+ });
168
+ if (targetId === void 0) return;
169
+ const targetNode = context.droppableContainers.get(targetId)?.node.current;
170
+ if (targetNode === null || targetNode === void 0) {
171
+ const targetCell = cells.find(({ itemIds }) => itemIds.includes(targetId));
172
+ if (isKanbanItemDropData(activeData) && targetCell?.navigation.type === "virtual") {
173
+ activeData.navigation.current = {
174
+ targetId,
175
+ type: "pending"
176
+ };
177
+ targetCell.navigation.requestScroll({
178
+ itemId: targetId,
179
+ type: "item"
180
+ });
181
+ }
182
+ return;
183
+ }
184
+ const targetRect = context.droppableRects.get(targetId);
185
+ if (targetRect === void 0) return;
186
+ if (isKanbanItemDropData(activeData)) activeData.navigation.current = {
187
+ targetId,
188
+ type: "ready"
189
+ };
190
+ requestAnimationFrame(() => {
191
+ requestAnimationFrame(() => {
192
+ targetNode.scrollIntoView({
193
+ behavior: "instant",
194
+ block: "nearest",
195
+ inline: "nearest"
196
+ });
197
+ });
198
+ });
199
+ return {
200
+ x: targetRect.left,
201
+ y: targetRect.top
202
+ };
203
+ };
204
+ //#endregion
205
+ export { KANBAN_BOARD_COLLISION_DETECTION, KANBAN_DROP_TARGET_TYPES, clearKanbanKeyboardTarget, getKanbanKeyboardTarget, getKanbanKeyboardTargetState, isKanbanCellDropData, isKanbanDropSettled, kanbanKeyboardCoordinates };
@@ -1,4 +1,7 @@
1
+ import { UseKanbanDropTargetOptions } from "./sortable-interactions.js";
1
2
  import { Key, ReactNode, RefObject } from "react";
3
+ import { UniqueIdentifier } from "@dnd-kit/core";
4
+ import { SortableContextProps, SortingStrategy } from "@dnd-kit/sortable";
2
5
  //#region src/kanban/virtual-cell.d.ts
3
6
  declare const KANBAN_VIRTUAL_CELL_PAGINATION: {
4
7
  readonly NONE: "none";
@@ -13,11 +16,25 @@ type KanbanVirtualCellPagination = {
13
16
  pageKey: string | number;
14
17
  onRequestMore: () => void;
15
18
  };
19
+ /**
20
+ * Makes a virtual cell the canonical sortable context for its rendered rows.
21
+ *
22
+ * `getRowKey` remains responsible for React and virtualizer identity. A
23
+ * separate sortable identifier avoids narrowing an existing React key contract
24
+ * merely to support dnd-kit consumers.
25
+ */
26
+ type KanbanVirtualCellSortableContext<TRow> = {
27
+ dropTarget: Omit<UseKanbanDropTargetOptions, "itemIds" | "navigation">;
28
+ getRowId: (row: TRow) => UniqueIdentifier;
29
+ disabled?: SortableContextProps["disabled"] | undefined;
30
+ strategy?: SortingStrategy | undefined;
31
+ };
16
32
  type KanbanVirtualCellProps<TRow> = {
17
33
  rows: readonly TRow[];
18
34
  getRowKey: (row: TRow) => Key;
19
35
  renderRow: (row: TRow) => ReactNode;
20
36
  pagination: KanbanVirtualCellPagination;
37
+ sortable?: KanbanVirtualCellSortableContext<TRow> | undefined;
21
38
  containerRef?: RefObject<HTMLDivElement | null> | undefined;
22
39
  active?: boolean | undefined;
23
40
  backgroundColor?: string | undefined;
@@ -28,6 +45,6 @@ type KanbanVirtualCellProps<TRow> = {
28
45
  className?: string | undefined;
29
46
  };
30
47
  /** Bounded, virtualized Kanban cell with cursor-page request deduplication. */
31
- declare const KanbanVirtualCell: <TRow>({ rows, getRowKey, renderRow, pagination, containerRef, active, backgroundColor, footer, estimateSize, overscan, loadMoreThreshold, className }: KanbanVirtualCellProps<TRow>) => import("react").JSX.Element;
48
+ declare const KanbanVirtualCell: <TRow>({ rows, getRowKey, renderRow, pagination, sortable, containerRef, active, backgroundColor, footer, estimateSize, overscan, loadMoreThreshold, className }: KanbanVirtualCellProps<TRow>) => import("react").JSX.Element;
32
49
  //#endregion
33
- export { KANBAN_VIRTUAL_CELL_PAGINATION, KanbanVirtualCell, KanbanVirtualCellPagination, KanbanVirtualCellProps };
50
+ export { KANBAN_VIRTUAL_CELL_PAGINATION, KanbanVirtualCell, KanbanVirtualCellPagination, KanbanVirtualCellProps, KanbanVirtualCellSortableContext };
@@ -1,20 +1,34 @@
1
1
  import { cn } from "../lib/utils.js";
2
+ import { useKanbanDropTarget } from "./sortable-interactions.js";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useRef } from "react";
4
- import { useVirtualizer } from "@tanstack/react-virtual";
4
+ import { useId, useRef } from "react";
5
+ import { useDndContext } from "@dnd-kit/core";
6
+ import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
7
+ import { defaultRangeExtractor, useVirtualizer } from "@tanstack/react-virtual";
5
8
  //#region src/kanban/virtual-cell.tsx
6
9
  const DEFAULT_ESTIMATE_SIZE_PX = 128;
7
10
  const DEFAULT_OVERSCAN = 8;
8
11
  const DEFAULT_LOAD_MORE_THRESHOLD_PX = 200;
12
+ const retainActiveSortableIndex = (range, activeIndex) => {
13
+ const indexes = defaultRangeExtractor(range);
14
+ if (activeIndex < 0 || indexes.includes(activeIndex)) return indexes;
15
+ indexes.push(activeIndex);
16
+ indexes.sort((left, right) => left - right);
17
+ return indexes;
18
+ };
9
19
  const KANBAN_VIRTUAL_CELL_PAGINATION = {
10
20
  NONE: "none",
11
21
  CURSOR: "cursor"
12
22
  };
13
23
  /** Bounded, virtualized Kanban cell with cursor-page request deduplication. */
14
- const KanbanVirtualCell = ({ rows, getRowKey, renderRow, pagination, containerRef, active = false, backgroundColor, footer, estimateSize = DEFAULT_ESTIMATE_SIZE_PX, overscan = DEFAULT_OVERSCAN, loadMoreThreshold = DEFAULT_LOAD_MORE_THRESHOLD_PX, className }) => {
24
+ const KanbanVirtualCell = ({ rows, getRowKey, renderRow, pagination, sortable, containerRef, active = false, backgroundColor, footer, estimateSize = DEFAULT_ESTIMATE_SIZE_PX, overscan = DEFAULT_OVERSCAN, loadMoreThreshold = DEFAULT_LOAD_MORE_THRESHOLD_PX, className }) => {
15
25
  const internalRef = useRef(null);
16
- const scrollRef = containerRef ?? internalRef;
26
+ const fallbackDropTargetId = useId();
27
+ const scrollRef = internalRef;
17
28
  const requestedPageKeyRef = useRef(null);
29
+ const itemIds = sortable ? rows.map(sortable.getRowId) : [];
30
+ const { active: activeDrag } = useDndContext();
31
+ const activeSortableIndex = activeDrag === null ? -1 : itemIds.indexOf(activeDrag.id);
18
32
  const virtualizer = useVirtualizer({
19
33
  count: rows.length,
20
34
  estimateSize: () => estimateSize,
@@ -23,7 +37,25 @@ const KanbanVirtualCell = ({ rows, getRowKey, renderRow, pagination, containerRe
23
37
  return row === void 0 ? index : getRowKey(row);
24
38
  },
25
39
  getScrollElement: () => scrollRef.current,
26
- overscan
40
+ overscan,
41
+ rangeExtractor: (range) => retainActiveSortableIndex(range, activeSortableIndex)
42
+ });
43
+ const requestScroll = ({ itemId }) => {
44
+ const index = itemIds.indexOf(itemId);
45
+ if (index !== -1) virtualizer.scrollToIndex(index, { align: "auto" });
46
+ };
47
+ const dropTarget = useKanbanDropTarget({
48
+ disabled: sortable?.dropTarget.disabled ?? sortable === void 0,
49
+ id: sortable?.dropTarget.id ?? fallbackDropTargetId,
50
+ itemIds,
51
+ navigation: sortable === void 0 ? { type: "static" } : {
52
+ requestScroll,
53
+ type: "virtual"
54
+ },
55
+ position: sortable?.dropTarget.position ?? {
56
+ column: -1,
57
+ lane: -1
58
+ }
27
59
  });
28
60
  const handleScroll = ({ currentTarget }) => {
29
61
  if (pagination.type !== "cursor" || !pagination.hasMore || pagination.loading) return;
@@ -32,10 +64,16 @@ const KanbanVirtualCell = ({ rows, getRowKey, renderRow, pagination, containerRe
32
64
  requestedPageKeyRef.current = pagination.pageKey;
33
65
  pagination.onRequestMore();
34
66
  };
35
- return /* @__PURE__ */ jsxs("div", {
67
+ const setScrollElement = (element) => {
68
+ internalRef.current = element;
69
+ if (containerRef) containerRef.current = element;
70
+ dropTarget.setNodeRef(element);
71
+ };
72
+ const content = /* @__PURE__ */ jsxs("div", {
36
73
  className: cn("bg-muted/20 max-h-[min(60vh,40rem)] min-h-20 overflow-y-auto overscroll-y-contain rounded-xl p-2 transition-[background-color,outline-color]", active && "bg-primary/5 ring-primary/50 ring-2", className),
74
+ "data-kanban-cell": sortable?.dropTarget.id,
37
75
  onScroll: handleScroll,
38
- ref: scrollRef,
76
+ ref: setScrollElement,
39
77
  style: backgroundColor ? { backgroundColor } : void 0,
40
78
  children: [/* @__PURE__ */ jsx("div", {
41
79
  className: "relative",
@@ -53,6 +91,14 @@ const KanbanVirtualCell = ({ rows, getRowKey, renderRow, pagination, containerRe
53
91
  })
54
92
  }), footer]
55
93
  });
94
+ if (sortable === void 0) return content;
95
+ return /* @__PURE__ */ jsx(SortableContext, {
96
+ ...sortable.disabled === void 0 ? {} : { disabled: sortable.disabled },
97
+ id: sortable.dropTarget.id,
98
+ items: itemIds,
99
+ strategy: sortable.strategy ?? verticalListSortingStrategy,
100
+ children: content
101
+ });
56
102
  };
57
103
  //#endregion
58
104
  export { KANBAN_VIRTUAL_CELL_PAGINATION, KanbanVirtualCell };
@@ -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 };
@@ -1,4 +1,5 @@
1
1
  //#region src/lib/overlay-layer.d.ts
2
+ declare const BOARD_DRAG_OVERLAY_Z_INDEX = 75;
2
3
  declare const OVERLAY_LAYER_CLASS_NAMES: {
3
4
  /** Docked composer, suggestion chips, and other in-pane floating chrome. */
4
5
  readonly chrome: "z-[80]";
@@ -19,4 +20,4 @@ declare const OVERLAY_LAYER_CLASS_NAMES: {
19
20
  };
20
21
  type OverlayLayer = keyof typeof OVERLAY_LAYER_CLASS_NAMES;
21
22
  //#endregion
22
- export { OVERLAY_LAYER_CLASS_NAMES, OverlayLayer };
23
+ export { BOARD_DRAG_OVERLAY_Z_INDEX, OVERLAY_LAYER_CLASS_NAMES, OverlayLayer };
@@ -1,4 +1,5 @@
1
1
  //#region src/lib/overlay-layer.ts
2
+ const BOARD_DRAG_OVERLAY_Z_INDEX = 75;
2
3
  const OVERLAY_LAYER_CLASS_NAMES = {
3
4
  /** Docked composer, suggestion chips, and other in-pane floating chrome. */
4
5
  chrome: "z-[80]",
@@ -18,4 +19,4 @@ const OVERLAY_LAYER_CLASS_NAMES = {
18
19
  "search-child": "z-[100]"
19
20
  };
20
21
  //#endregion
21
- export { OVERLAY_LAYER_CLASS_NAMES };
22
+ export { BOARD_DRAG_OVERLAY_Z_INDEX, OVERLAY_LAYER_CLASS_NAMES };
@@ -1,6 +1,6 @@
1
1
  import { cn } from "../lib/utils.js";
2
- import { BidiText } from "../components/bidi-text.js";
3
2
  import { Button } from "../components/button.js";
3
+ import { BidiText } from "../components/bidi-text.js";
4
4
  import { ReviewAuthorAvatar } from "./review-author-avatar.js";
5
5
  import { CheckIcon, RotateCcwIcon, Trash2Icon } from "lucide-react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/ui",
3
- "version": "0.9.0",
3
+ "version": "0.12.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",
@@ -45,9 +45,9 @@
45
45
  "types": "./dist/components/alert-dialog.d.ts",
46
46
  "import": "./dist/components/alert-dialog.js"
47
47
  },
48
- "./application-shell": {
49
- "types": "./dist/components/application-shell.d.ts",
50
- "import": "./dist/components/application-shell.js"
48
+ "./workspace-shell": {
49
+ "types": "./dist/components/workspace-shell.d.ts",
50
+ "import": "./dist/components/workspace-shell.js"
51
51
  },
52
52
  "./avatar": {
53
53
  "types": "./dist/components/avatar.d.ts",
@@ -330,9 +330,9 @@
330
330
  "types": "./dist/components/alert-dialog.d.ts",
331
331
  "import": "./dist/components/alert-dialog.js"
332
332
  },
333
- "./components/application-shell": {
334
- "types": "./dist/components/application-shell.d.ts",
335
- "import": "./dist/components/application-shell.js"
333
+ "./components/workspace-shell": {
334
+ "types": "./dist/components/workspace-shell.d.ts",
335
+ "import": "./dist/components/workspace-shell.js"
336
336
  },
337
337
  "./components/avatar": {
338
338
  "types": "./dist/components/avatar.d.ts",
@@ -1,27 +0,0 @@
1
- import { ReactNode } from "react";
2
- //#region src/components/application-shell.d.ts
3
- type ApplicationShellProps = {
4
- /**
5
- * The application navigation surface. It stays a direct sibling of the
6
- * content column so sidebar implementations can reserve their own width.
7
- */
8
- sidebar: ReactNode;
9
- /** The route chrome rendered above the application content. */
10
- header?: ReactNode | undefined;
11
- /** An optional dock or rail at the inline-end edge. */
12
- inspector?: ReactNode | undefined;
13
- /** The active route or page content. */
14
- children: ReactNode;
15
- className?: string | undefined;
16
- mainClassName?: string | undefined;
17
- };
18
- /**
19
- * The three-column application frame: navigation, page chrome and content,
20
- * then an optional inline-end inspector. Product navigation, route state, and
21
- * inspector behaviour stay in the host; this primitive only owns the layout
22
- * relationship that lets those surfaces share a viewport without nesting one
23
- * inside another.
24
- */
25
- declare const ApplicationShell: ({ children, className, header, inspector, mainClassName, sidebar }: ApplicationShellProps) => import("react").JSX.Element;
26
- //#endregion
27
- export { ApplicationShell, type ApplicationShellProps };
@@ -1,25 +0,0 @@
1
- import { cn } from "../lib/utils.js";
2
- import { jsxs } from "react/jsx-runtime";
3
- //#region src/components/application-shell.tsx
4
- /**
5
- * The three-column application frame: navigation, page chrome and content,
6
- * then an optional inline-end inspector. Product navigation, route state, and
7
- * inspector behaviour stay in the host; this primitive only owns the layout
8
- * relationship that lets those surfaces share a viewport without nesting one
9
- * inside another.
10
- */
11
- const ApplicationShell = ({ children, className, header, inspector, mainClassName, sidebar }) => /* @__PURE__ */ jsxs("div", {
12
- className: cn("flex min-h-svh w-full", className),
13
- "data-slot": "application-shell",
14
- children: [
15
- sidebar,
16
- /* @__PURE__ */ jsxs("main", {
17
- className: cn("bg-background relative flex w-full min-w-0 flex-1 flex-col overflow-hidden", "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ms-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ms-2", mainClassName),
18
- "data-slot": "application-shell-main",
19
- children: [header, children]
20
- }),
21
- inspector
22
- ]
23
- });
24
- //#endregion
25
- export { ApplicationShell };