@stll/workspace-ui 0.5.1 → 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/dist/index.d.ts CHANGED
@@ -14,4 +14,5 @@ import { CreateWorkspaceKanbanSchemaParams, KANBAN_EMPTY_GROUP_VISIBILITIES, Kan
14
14
  import { WorkspaceKanbanGroupingPicker } from "./kanban-grouping-picker.js";
15
15
  import { WorkspaceViewDirection, WorkspaceViewDropPosition, reorderWorkspaceViewIds, toWorkspaceViewDropPosition } from "./view-switcher.logic.js";
16
16
  import { WorkspaceViewSwitcher, WorkspaceViewSwitcherEditing, WorkspaceViewSwitcherItem, WorkspaceViewSwitcherProps, WorkspaceViewSwitcherReorder } from "./view-switcher.js";
17
- export { type ApplyCalculationSelectionParams, CONDITION_OPERATORS, type CalculationFormatters, CalculationKindPicker, type CalculationKindPickerProps, type CalculationLabels, CalculationPicker, type CalculationPickerProps, type CalculationProperty, type CalculationResult, type CalculationSelection, CalculationSummary, type CalculationSummaryProps, type ColorVariants, ColumnCalculation, ConditionBuilder, type ConditionBuilderLabels, type ConditionCapabilities, type ConditionOperator, type CreateWorkspaceKanbanSchemaParams, FIELD_CONTENT_TYPES, type FieldContent, type FieldOption, type FieldOptionChoice, FieldValue, type FieldValueType, type FormatCalculationParams, type FormatMoneyCentsParams, type FormattedCalculation, type FormulaCellRenderCtx, type GenericProperty, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, type KanbanBoardPresentation, type KanbanEmptyGroupVisibility, type KanbanPresentedLane, type KanbanSavedAxisState, type KanbanSavedGroupReference, type KanbanSavedSubgroupState, type KanbanSavedViewState, MoneyFieldValue, type OptionColor, PersonFieldValue, PropertyIcon, type PropertyIconType, type ResolveWorkspaceKanbanViewParams, type ResolvedWorkspaceKanbanView, SortChips, type SortChipsLabels, type SortChipsProps, type SortDescriptor, type SortableProperty, TableSkeletonRows, type UseCalculationParams, type ValueEditorKind, type ValueEditorRenderCtx, type WorkspaceCalculationLabels, type WorkspaceFieldContent, type WorkspaceKanbanBuiltInGroupLabel, type WorkspaceKanbanGroupingChoice, WorkspaceKanbanGroupingPicker, type WorkspaceKanbanGroupingPickerLabels, type WorkspaceKanbanGroupingPickerProps, type WorkspaceKanbanProperty, type WorkspaceViewDirection, type WorkspaceViewDropPosition, WorkspaceViewSwitcher, type WorkspaceViewSwitcherEditing, type WorkspaceViewSwitcherItem, type WorkspaceViewSwitcherProps, type WorkspaceViewSwitcherReorder, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, currencyMinorUnitDigits, emptyColor, fieldForNode, formatCalculationResult, formatMoneyCents, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
17
+ import { WorkspaceFrame, WorkspaceFrameEndRail, WorkspaceFrameInspector, WorkspaceFrameNavigation, WorkspaceFrameNavigationItem, WorkspaceFrameProps, WorkspaceFrameTopBar } from "./workspace-frame.js";
18
+ export { type ApplyCalculationSelectionParams, CONDITION_OPERATORS, type CalculationFormatters, CalculationKindPicker, type CalculationKindPickerProps, type CalculationLabels, CalculationPicker, type CalculationPickerProps, type CalculationProperty, type CalculationResult, type CalculationSelection, CalculationSummary, type CalculationSummaryProps, type ColorVariants, ColumnCalculation, ConditionBuilder, type ConditionBuilderLabels, type ConditionCapabilities, type ConditionOperator, type CreateWorkspaceKanbanSchemaParams, FIELD_CONTENT_TYPES, type FieldContent, type FieldOption, type FieldOptionChoice, FieldValue, type FieldValueType, type FormatCalculationParams, type FormatMoneyCentsParams, type FormattedCalculation, type FormulaCellRenderCtx, type GenericProperty, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, type KanbanBoardPresentation, type KanbanEmptyGroupVisibility, type KanbanPresentedLane, type KanbanSavedAxisState, type KanbanSavedGroupReference, type KanbanSavedSubgroupState, type KanbanSavedViewState, MoneyFieldValue, type OptionColor, PersonFieldValue, PropertyIcon, type PropertyIconType, type ResolveWorkspaceKanbanViewParams, type ResolvedWorkspaceKanbanView, SortChips, type SortChipsLabels, type SortChipsProps, type SortDescriptor, type SortableProperty, TableSkeletonRows, type UseCalculationParams, type ValueEditorKind, type ValueEditorRenderCtx, type WorkspaceCalculationLabels, type WorkspaceFieldContent, WorkspaceFrame, type WorkspaceFrameEndRail, type WorkspaceFrameInspector, type WorkspaceFrameNavigation, type WorkspaceFrameNavigationItem, type WorkspaceFrameProps, type WorkspaceFrameTopBar, type WorkspaceKanbanBuiltInGroupLabel, type WorkspaceKanbanGroupingChoice, WorkspaceKanbanGroupingPicker, type WorkspaceKanbanGroupingPickerLabels, type WorkspaceKanbanGroupingPickerProps, type WorkspaceKanbanProperty, type WorkspaceViewDirection, type WorkspaceViewDropPosition, WorkspaceViewSwitcher, type WorkspaceViewSwitcherEditing, type WorkspaceViewSwitcherItem, type WorkspaceViewSwitcherProps, type WorkspaceViewSwitcherReorder, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, currencyMinorUnitDigits, emptyColor, fieldForNode, formatCalculationResult, formatMoneyCents, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
package/dist/index.js CHANGED
@@ -14,4 +14,5 @@ import { KANBAN_EMPTY_GROUP_VISIBILITIES, createWorkspaceKanbanSchema, getWorksp
14
14
  import { WorkspaceKanbanGroupingPicker } from "./kanban-grouping-picker.js";
15
15
  import { reorderWorkspaceViewIds, toWorkspaceViewDropPosition } from "./view-switcher.logic.js";
16
16
  import { WorkspaceViewSwitcher } from "./view-switcher.js";
17
- export { CONDITION_OPERATORS, CalculationKindPicker, CalculationPicker, CalculationSummary, ColumnCalculation, ConditionBuilder, FIELD_CONTENT_TYPES, FieldValue, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, MoneyFieldValue, PersonFieldValue, PropertyIcon, SortChips, TableSkeletonRows, WorkspaceKanbanGroupingPicker, WorkspaceViewSwitcher, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, currencyMinorUnitDigits, emptyColor, fieldForNode, formatCalculationResult, formatMoneyCents, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
17
+ import { WorkspaceFrame } from "./workspace-frame.js";
18
+ export { CONDITION_OPERATORS, CalculationKindPicker, CalculationPicker, CalculationSummary, ColumnCalculation, ConditionBuilder, FIELD_CONTENT_TYPES, FieldValue, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, MoneyFieldValue, PersonFieldValue, PropertyIcon, SortChips, TableSkeletonRows, WorkspaceFrame, WorkspaceKanbanGroupingPicker, WorkspaceViewSwitcher, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, currencyMinorUnitDigits, emptyColor, fieldForNode, formatCalculationResult, formatMoneyCents, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
@@ -1,5 +1,5 @@
1
1
  import { GenericProperty } from "./types.js";
2
- import { KanbanBoardCell, KanbanBoardLane, KanbanBoardMatrix, KanbanBuiltInGroup, KanbanGroup, KanbanGrouping, KanbanSchema } from "@stll/ui/kanban";
2
+ import { KanbanBoardCell, KanbanBoardColumn, KanbanBoardLane, KanbanBoardMatrix, KanbanBuiltInGroup, KanbanGrouping, KanbanSchema } from "@stll/ui/kanban";
3
3
  //#region src/kanban-view.d.ts
4
4
  declare const KANBAN_EMPTY_GROUP_VISIBILITIES: {
5
5
  readonly hide: "hide";
@@ -89,7 +89,7 @@ type KanbanPresentedLane<TRow> = {
89
89
  lane: KanbanBoardLane;
90
90
  };
91
91
  type KanbanBoardPresentation<TRow> = {
92
- columns: KanbanGroup[];
92
+ columns: KanbanBoardColumn[];
93
93
  lanes: KanbanPresentedLane<TRow>[];
94
94
  matrix: KanbanBoardMatrix<TRow>;
95
95
  };
@@ -71,7 +71,7 @@ const orderGroups = (groups, orderedGroups) => {
71
71
  for (const group of groups) if (!refersToGroup(orderedGroups, group)) ordered.push(group);
72
72
  return ordered;
73
73
  };
74
- const isGroupEmpty = (group, matrix) => matrix.cells.every((cell) => cell.coordinate.column.value !== group.value || cell.rows.length === 0);
74
+ const isGroupEmpty = (group, matrix) => matrix.cells.every((cell) => cell.coordinate.column.type !== group.type || group.type === "group" && cell.coordinate.column.type === "group" && cell.coordinate.column.group.value !== group.group.value || group.type === "destination" && cell.coordinate.column.type === "destination" && cell.coordinate.column.destination.id !== group.destination.id || cell.rows.length === 0);
75
75
  const isLaneEmpty = (lane, matrix) => matrix.cells.every((cell) => cell.coordinate.lane.type !== lane.type || lane.type === "group" && cell.coordinate.lane.type === "group" && cell.coordinate.lane.group.value !== lane.group.value || cell.rows.length === 0);
76
76
  /**
77
77
  * Apply saved presentation state without rebuilding the matrix. This preserves
@@ -79,7 +79,10 @@ const isLaneEmpty = (lane, matrix) => matrix.cells.every((cell) => cell.coordina
79
79
  * individually hide groups, reorder them, and collapse swimlanes.
80
80
  */
81
81
  const presentKanbanBoard = ({ matrix, state }) => {
82
- const columns = orderGroups(matrix.columns, state.group.orderedGroups).filter((group) => !refersToGroup(state.group.hiddenGroups, group) && (state.group.emptyGroups === "show" || !isGroupEmpty(group, matrix)));
82
+ const columns = [...orderGroups(matrix.columns.filter((column) => column.type === "group").map((column) => column.group), state.group.orderedGroups).map((group) => ({
83
+ group,
84
+ type: "group"
85
+ })).filter((column) => !refersToGroup(state.group.hiddenGroups, column.group) && (state.group.emptyGroups === "show" || !isGroupEmpty(column, matrix))), ...matrix.columns.filter((column) => column.type === "destination")];
83
86
  const subgroupState = state.subgroup;
84
87
  return {
85
88
  columns,
@@ -7,7 +7,7 @@ const RESPONSIVE_ACTION_TOOLBAR_SLOT_CLASS = {
7
7
  action: "shrink-0"
8
8
  };
9
9
  const ResponsiveActionToolbar = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
10
- className: cn("flex min-w-0 flex-nowrap items-center gap-2 overflow-x-auto", className),
10
+ className: cn("flex min-w-0 [scrollbar-width:none] flex-nowrap items-center gap-2 overflow-x-auto [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden", className),
11
11
  ...props
12
12
  });
13
13
  const ResponsiveActionToolbarItem = ({ slot, className, children }) => /* @__PURE__ */ jsx("div", {
@@ -134,7 +134,7 @@ const WorkspaceViewTab = ({ actions, canReorder, direction, getDragData, getDrop
134
134
  view.id
135
135
  ]);
136
136
  return /* @__PURE__ */ jsxs("div", {
137
- className: "relative",
137
+ className: "relative flex items-center",
138
138
  ref: setTabContainer,
139
139
  children: [
140
140
  dropPosition !== null && /* @__PURE__ */ jsx("span", {
@@ -151,7 +151,10 @@ const WorkspaceViewTab = ({ actions, canReorder, direction, getDragData, getDrop
151
151
  children: view.name
152
152
  })]
153
153
  }),
154
- actions
154
+ actions === null || actions === void 0 ? null : /* @__PURE__ */ jsx("div", {
155
+ className: "absolute inset-e-0 top-1/2 -translate-y-1/2",
156
+ children: actions
157
+ })
155
158
  ]
156
159
  });
157
160
  };
@@ -0,0 +1,73 @@
1
+ import { ComponentProps, ReactElement, ReactNode } from "react";
2
+ import { InspectorDock } from "@stll/ui/inspector";
3
+ import { WorkspaceEndRail, WorkspaceShell } from "@stll/ui/workspace-shell";
4
+ //#region src/workspace-frame.d.ts
5
+ type WorkspaceFrameNavigationItem = {
6
+ id: string;
7
+ label: string;
8
+ icon: ReactNode;
9
+ active?: boolean;
10
+ disabled?: boolean;
11
+ onActivate: () => void;
12
+ };
13
+ type WorkspaceFrameNavigation = {
14
+ label: string;
15
+ items: readonly WorkspaceFrameNavigationItem[];
16
+ header?: ReactNode;
17
+ footer?: ReactNode;
18
+ compact: {
19
+ content: ReactElement;
20
+ label: string;
21
+ open: boolean;
22
+ onOpenChange: (open: boolean) => void;
23
+ trigger: ReactElement | null;
24
+ };
25
+ };
26
+ type WorkspaceFrameInspector = {
27
+ pane: ReactNode;
28
+ showPaneContent: boolean;
29
+ width: number;
30
+ resizeHandleLabel: string;
31
+ resizeHandleProps: ComponentProps<typeof InspectorDock>["resizeHandleProps"];
32
+ onResetWidth?: (() => void) | undefined;
33
+ mobile?: {
34
+ content: ReactElement;
35
+ label: string;
36
+ open: boolean;
37
+ onOpenChange: (open: boolean) => void;
38
+ };
39
+ };
40
+ type WorkspaceFrameEndRail = {
41
+ label: string;
42
+ topAction: ReactNode;
43
+ chatAction: ComponentProps<typeof WorkspaceEndRail>["chatAction"];
44
+ children?: ReactNode;
45
+ overlay?: ReactNode;
46
+ };
47
+ type WorkspaceFrameProps = {
48
+ children: ReactNode;
49
+ } & ({
50
+ composition: "described";
51
+ navigation: WorkspaceFrameNavigation;
52
+ topBar: WorkspaceFrameTopBar;
53
+ endRail: WorkspaceFrameEndRail;
54
+ inspector?: WorkspaceFrameInspector;
55
+ } | {
56
+ composition: "host-responsive";
57
+ navigation: ComponentProps<typeof WorkspaceShell>["navigation"];
58
+ topBar: ComponentProps<typeof WorkspaceShell>["topBar"];
59
+ endDock: ReactElement;
60
+ });
61
+ type WorkspaceFrameTopBar = {
62
+ leading?: ReactNode;
63
+ center?: ReactNode;
64
+ actions?: ReactNode;
65
+ };
66
+ /**
67
+ * Stella's complete workspace frame. Hosts provide route descriptors and
68
+ * actions; this component owns the shell, application rail, end rail, and
69
+ * desktop inspector footprint.
70
+ */
71
+ declare const WorkspaceFrame: (props: WorkspaceFrameProps) => import("react").JSX.Element;
72
+ //#endregion
73
+ export { WorkspaceFrame, WorkspaceFrameEndRail, WorkspaceFrameInspector, WorkspaceFrameNavigation, WorkspaceFrameNavigationItem, WorkspaceFrameProps, WorkspaceFrameTopBar };
@@ -0,0 +1,91 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { cn } from "@stll/ui/utils";
4
+ import { ApplicationRail, ApplicationRailButton, ApplicationRailContent, ApplicationRailFooter, ApplicationRailHeader, ApplicationRailMenu } from "@stll/ui/application-rail";
5
+ import { InspectorDock, TOOLBAR_ROW_HEIGHT } from "@stll/ui/inspector";
6
+ import { Sheet, SheetPopup, SheetTitle } from "@stll/ui/sheet";
7
+ import { WorkspaceEndRail, WorkspaceShell } from "@stll/ui/workspace-shell";
8
+ //#region src/workspace-frame.tsx
9
+ /**
10
+ * Stella's complete workspace frame. Hosts provide route descriptors and
11
+ * actions; this component owns the shell, application rail, end rail, and
12
+ * desktop inspector footprint.
13
+ */
14
+ const WorkspaceFrame = (props) => {
15
+ if (props.composition === "host-responsive") return /* @__PURE__ */ jsx(WorkspaceShell, {
16
+ endDock: props.endDock,
17
+ navigation: props.navigation,
18
+ topBar: props.topBar,
19
+ children: props.children
20
+ });
21
+ const { children, endRail, inspector, navigation, topBar } = props;
22
+ const desktopNavigation = /* @__PURE__ */ jsxs(ApplicationRail, {
23
+ "aria-label": navigation.label,
24
+ children: [
25
+ /* @__PURE__ */ jsx(ApplicationRailHeader, { children: navigation.header }),
26
+ /* @__PURE__ */ jsx(ApplicationRailContent, { children: /* @__PURE__ */ jsx(ApplicationRailMenu, { children: navigation.items.map((item) => /* @__PURE__ */ jsx(ApplicationRailButton, {
27
+ "aria-current": item.active ? "page" : void 0,
28
+ "aria-label": item.label,
29
+ "data-active": item.active || void 0,
30
+ disabled: item.disabled,
31
+ title: item.label,
32
+ className: "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
33
+ onClick: item.onActivate,
34
+ children: item.icon
35
+ }, item.id)) }) }),
36
+ /* @__PURE__ */ jsx(ApplicationRailFooter, { children: navigation.footer })
37
+ ]
38
+ });
39
+ const endDock = inspector ? /* @__PURE__ */ jsx(InspectorDock, {
40
+ rail: /* @__PURE__ */ jsx(WorkspaceEndRail, { ...endRail }),
41
+ resizeHandleLabel: inspector.resizeHandleLabel,
42
+ resizeHandleProps: inspector.resizeHandleProps,
43
+ showPaneContent: inspector.showPaneContent,
44
+ width: inspector.width,
45
+ onResetWidth: inspector.onResetWidth,
46
+ children: inspector.pane
47
+ }) : /* @__PURE__ */ jsx(WorkspaceEndRail, { ...endRail });
48
+ const frame = /* @__PURE__ */ jsx(WorkspaceShell, {
49
+ endDock,
50
+ navigation: {
51
+ compact: navigation.compact,
52
+ desktop: desktopNavigation,
53
+ mode: "shell-managed"
54
+ },
55
+ topBar: ({ compactNavigationTrigger }) => /* @__PURE__ */ jsxs("div", {
56
+ className: cn("flex min-w-0 items-center gap-2 overflow-hidden border-b px-4", TOOLBAR_ROW_HEIGHT),
57
+ children: [
58
+ compactNavigationTrigger,
59
+ /* @__PURE__ */ jsx("div", {
60
+ className: "min-w-0 flex-1",
61
+ children: topBar.leading
62
+ }),
63
+ /* @__PURE__ */ jsx("div", {
64
+ className: "min-w-0",
65
+ children: topBar.center
66
+ }),
67
+ /* @__PURE__ */ jsx("div", {
68
+ className: "ms-auto flex shrink-0 items-center gap-0.5",
69
+ children: topBar.actions
70
+ })
71
+ ]
72
+ }),
73
+ children
74
+ });
75
+ if (inspector?.mobile === void 0) return frame;
76
+ return /* @__PURE__ */ jsxs(Sheet, {
77
+ open: inspector.mobile.open,
78
+ onOpenChange: inspector.mobile.onOpenChange,
79
+ children: [frame, /* @__PURE__ */ jsxs(SheetPopup, {
80
+ className: "h-dvh w-full max-w-none border-0 p-0 md:hidden",
81
+ showCloseButton: false,
82
+ side: "inline-end",
83
+ children: [/* @__PURE__ */ jsx(SheetTitle, {
84
+ className: "sr-only",
85
+ children: inspector.mobile.label
86
+ }), inspector.mobile.content]
87
+ })]
88
+ });
89
+ };
90
+ //#endregion
91
+ export { WorkspaceFrame };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/workspace-ui",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Reusable workspace presentation components and view helpers for Stella.",
5
5
  "keywords": [
6
6
  "calculations",
@@ -91,6 +91,10 @@
91
91
  "types": "./dist/view-switcher.d.ts",
92
92
  "import": "./dist/view-switcher.js"
93
93
  },
94
+ "./workspace-frame": {
95
+ "types": "./dist/workspace-frame.d.ts",
96
+ "import": "./dist/workspace-frame.js"
97
+ },
94
98
  "./view-switcher-logic": {
95
99
  "types": "./dist/view-switcher.logic.d.ts",
96
100
  "import": "./dist/view-switcher.logic.js"
@@ -115,7 +119,7 @@
115
119
  "@stll/calculations": "^0.1.0",
116
120
  "@stll/conditions": "^0.2.0",
117
121
  "@stll/money": "^0.1.0",
118
- "@stll/ui": "^0.13.0",
122
+ "@stll/ui": "^0.14.0",
119
123
  "better-result": "3.0.0",
120
124
  "lucide-react": "1.30.0",
121
125
  "use-intl": "4.13.5"