@stll/workspace-ui 0.2.1 → 0.3.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.
@@ -42,6 +42,12 @@ type ConditionCapabilities = {
42
42
  fields: FieldOption[];
43
43
  /** Allow nested groups (the "+ Add group" affordance + bordered subgroups). */
44
44
  allowNesting?: boolean;
45
+ /**
46
+ * How many children the caller's backend accepts in one group. The add
47
+ * affordances are disabled at the cap, so a tree cannot be edited into a
48
+ * shape the server would reject. Omitted means no cap.
49
+ */
50
+ maxChildren?: number | undefined;
45
51
  /** Offer a "ƒ Calculated value…" item that switches a leaf's left operand to
46
52
  * a formula edited via `FormulaCell`. */
47
53
  allowFormula?: boolean;
@@ -41,8 +41,10 @@ const ConditionBuilder = ({ value, onChange, capabilities, labels, locale }) =>
41
41
  const ConditionBuilderTree = ({ value, onChange, capabilities }) => {
42
42
  const labels = useLabels();
43
43
  const group = asGroup(value);
44
- const { fields, allowNesting = false } = capabilities;
44
+ const { fields, allowNesting = false, maxChildren } = capabilities;
45
45
  const firstField = fields.at(0);
46
+ const atChildCap = maxChildren !== void 0 && group.children.length >= maxChildren;
47
+ const canAdd = firstField !== void 0 && !atChildCap;
46
48
  return /* @__PURE__ */ jsxs("div", {
47
49
  className: "flex flex-col gap-2",
48
50
  children: [/* @__PURE__ */ jsx("div", {
@@ -77,9 +79,9 @@ const ConditionBuilderTree = ({ value, onChange, capabilities }) => {
77
79
  className: "ms-[5.375rem] flex flex-wrap gap-1",
78
80
  children: [/* @__PURE__ */ jsxs(Button, {
79
81
  className: "w-fit justify-start",
80
- disabled: !firstField,
82
+ disabled: !canAdd,
81
83
  onClick: () => {
82
- if (firstField) onChange(appendChild(group, leafFromField(firstField)));
84
+ if (firstField && !atChildCap) onChange(appendChild(group, leafFromField(firstField)));
83
85
  },
84
86
  size: "xs",
85
87
  type: "button",
@@ -87,9 +89,9 @@ const ConditionBuilderTree = ({ value, onChange, capabilities }) => {
87
89
  children: [/* @__PURE__ */ jsx(PlusIcon, {}), labels.addCondition]
88
90
  }), allowNesting && /* @__PURE__ */ jsxs(Button, {
89
91
  className: "w-fit justify-start",
90
- disabled: !firstField,
92
+ disabled: !canAdd,
91
93
  onClick: () => {
92
- if (firstField) onChange(appendChild(group, {
94
+ if (firstField && !atChildCap) onChange(appendChild(group, {
93
95
  type: "group",
94
96
  combinator: "and",
95
97
  children: [leafFromField(firstField)]
package/dist/sorts.d.ts CHANGED
@@ -22,6 +22,12 @@ type SortChipsProps = {
22
22
  properties: readonly SortableProperty[];
23
23
  onUpdate: (sorts: SortDescriptor[]) => void;
24
24
  labels: SortChipsLabels;
25
+ /**
26
+ * How many sorts the caller's backend accepts. The add-sort trigger is
27
+ * disabled at the cap, so a view cannot be edited into a layout the server
28
+ * would reject. Omitted means no cap.
29
+ */
30
+ maxSorts?: number | undefined;
25
31
  };
26
32
  /**
27
33
  * The view's sorts as chips, plus the menu that adds one.
@@ -30,7 +36,7 @@ type SortChipsProps = {
30
36
  * the caller's answer, so this reads nothing but the three fields a chip
31
37
  * draws.
32
38
  */
33
- declare const SortChips: ({ sorts, properties, onUpdate, labels }: SortChipsProps) => import("react").JSX.Element;
39
+ declare const SortChips: ({ sorts, properties, onUpdate, labels, maxSorts }: SortChipsProps) => import("react").JSX.Element;
34
40
  /**
35
41
  * What ascending means depends on what is being sorted: A→Z for words, 1→9 for
36
42
  * numbers, an arrow for dates. A type with no idiom falls back to the arrow
package/dist/sorts.js CHANGED
@@ -11,7 +11,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
11
  * the caller's answer, so this reads nothing but the three fields a chip
12
12
  * draws.
13
13
  */
14
- const SortChips = ({ sorts, properties, onUpdate, labels }) => /* @__PURE__ */ jsxs(Fragment, { children: [sorts.map((sort) => {
14
+ const SortChips = ({ sorts, properties, onUpdate, labels, maxSorts }) => /* @__PURE__ */ jsxs(Fragment, { children: [sorts.map((sort) => {
15
15
  const property = properties.find((candidate) => candidate.id === sort.propertyId);
16
16
  if (!property) return null;
17
17
  return /* @__PURE__ */ jsx(SortChip, {
@@ -30,6 +30,7 @@ const SortChips = ({ sorts, properties, onUpdate, labels }) => /* @__PURE__ */ j
30
30
  propertyType: property.type
31
31
  }, sort.propertyId);
32
32
  }), /* @__PURE__ */ jsx(AddSortButton, {
33
+ disabled: maxSorts !== void 0 && sorts.length >= maxSorts,
33
34
  labels,
34
35
  onAdd: (sort) => onUpdate([...sorts, sort]),
35
36
  properties,
@@ -80,8 +81,9 @@ const SortChip = ({ propertyName, propertyType, desc, onToggle, onRemove, labels
80
81
  })]
81
82
  });
82
83
  };
83
- const AddSortButton = ({ properties, sortedPropertyIds, onAdd, labels }) => /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
84
+ const AddSortButton = ({ properties, sortedPropertyIds, onAdd, labels, disabled }) => /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
84
85
  "aria-label": labels.add,
86
+ disabled,
85
87
  render: /* @__PURE__ */ jsx(Button, {
86
88
  size: "icon-xs",
87
89
  variant: "ghost"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/workspace-ui",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Reusable workspace presentation components and view helpers for Stella.",
5
5
  "keywords": [
6
6
  "calculations",
@@ -103,7 +103,7 @@
103
103
  "@stll/calculations": "^0.1.0",
104
104
  "@stll/conditions": "^0.2.0",
105
105
  "@stll/money": "^0.1.0",
106
- "@stll/ui": "^0.5.0",
106
+ "@stll/ui": "^0.5.1",
107
107
  "better-result": "3.0.0",
108
108
  "lucide-react": "1.30.0",
109
109
  "use-intl": "4.13.5"