@stll/workspace-ui 0.0.1-placeholder.0 → 0.1.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 ADDED
@@ -0,0 +1,48 @@
1
+ # @stll/workspace-ui
2
+
3
+ Reusable React presentation modules for Stella workspaces: field values,
4
+ property icons, sorting chips, condition builders, table loading rows, and
5
+ column calculations.
6
+
7
+ The package owns view-level rendering contracts while the surrounding workspace
8
+ supplies its data, labels, and locale. The condition builder resolves no
9
+ strings itself; labels and field options arrive through its props.
10
+
11
+ ## Imports
12
+
13
+ Use the explicit subpaths for focused modules:
14
+
15
+ ```tsx
16
+ import { ConditionBuilder } from "@stll/workspace-ui/conditions";
17
+ import { FieldValue } from "@stll/workspace-ui/field-value";
18
+ import { SortChips } from "@stll/workspace-ui/sorts";
19
+ ```
20
+
21
+ The package also exposes a root entry for code that uses several workspace
22
+ surfaces together. The subpaths remain the clearest way to declare a module's
23
+ boundary.
24
+
25
+ ## Development
26
+
27
+ ```sh
28
+ bun run build # tsdown, one output module per source module
29
+ bun run test # bun test src
30
+ bun run typecheck
31
+ bun run lint
32
+ ```
33
+
34
+ Peer dependencies: `react`, `react-dom`, `@base-ui/react`, TanStack React Table,
35
+ and Tailwind CSS v4. The package's components use Tailwind utility classes; the
36
+ host owns the Tailwind entry point and token configuration.
37
+
38
+ Include both published component packages in that entry point so Tailwind scans
39
+ their shipped class names:
40
+
41
+ ```css
42
+ @import "tailwindcss";
43
+ @import "@stll/ui/theme.css";
44
+ @source "../node_modules/@stll/ui/dist";
45
+ @source "../node_modules/@stll/workspace-ui/dist";
46
+ ```
47
+
48
+ This package is published, so public API changes need a changeset.
@@ -0,0 +1,54 @@
1
+ import { CalculationResult } from "@stll/calculations";
2
+ import { CentsAmount } from "@stll/money";
3
+ //#region src/calculation-format.d.ts
4
+ type CalculationFormatters = {
5
+ number: (value: number) => string;
6
+ money: (amountCents: CentsAmount, currency: string) => string;
7
+ percent: (ratio: number) => string;
8
+ };
9
+ type CalculationLabels = {
10
+ /** The reduction's short name, e.g. "Sum". */
11
+ kind: string;
12
+ /** Stands in for a value the reduction cannot produce. */
13
+ unavailable: string;
14
+ };
15
+ type FormattedCalculation = {
16
+ /** One compact line, for the column header. */
17
+ summary: string;
18
+ /**
19
+ * One line per currency, for the tooltip. Empty when the summary already
20
+ * says everything: there is nothing to expand for a single unit.
21
+ */
22
+ breakdown: readonly string[];
23
+ };
24
+ type FormatCalculationParams = {
25
+ result: CalculationResult;
26
+ formatters: CalculationFormatters;
27
+ labels: CalculationLabels;
28
+ };
29
+ declare const formatCalculationResult: ({ result, formatters, labels }: FormatCalculationParams) => FormattedCalculation;
30
+ /**
31
+ * How many minor units make a major one, for this currency: 100 for CZK, 1 for
32
+ * JPY, 1000 for KWD. It is a property of the currency and not of the reader, so
33
+ * the lookup is deliberately locale-independent.
34
+ *
35
+ * A malformed code makes the `Intl.NumberFormat` constructor throw, before any
36
+ * `?? 2` on its result could help, so the fallback has to wrap the call.
37
+ */
38
+ declare const currencyMinorUnitDigits: (currency: string) => number;
39
+ type FormatMoneyCentsParams = {
40
+ amountCents: number;
41
+ currency: string;
42
+ locale: string;
43
+ };
44
+ /**
45
+ * Money is stored in minor units, and how many of them make a major one is a
46
+ * property of the currency. Ask the currency rather than assuming a hundred.
47
+ *
48
+ * A code `Intl` rejects falls back to the amount beside the raw code: a column
49
+ * showing "1500 A1C" is wrong-looking data, which is the truth, where a thrown
50
+ * RangeError would take the whole board down with it.
51
+ */
52
+ declare const formatMoneyCents: ({ amountCents, currency, locale }: FormatMoneyCentsParams) => string;
53
+ //#endregion
54
+ export { CalculationFormatters, CalculationLabels, FormatCalculationParams, FormatMoneyCentsParams, FormattedCalculation, currencyMinorUnitDigits, formatCalculationResult, formatMoneyCents };
@@ -0,0 +1,72 @@
1
+ import { Result } from "better-result";
2
+ //#region src/calculation-format.ts
3
+ /**
4
+ * Turning a calculation result into the two strings a view shows: the compact
5
+ * line in the header, and the breakdown behind it.
6
+ *
7
+ * Formatting is separate from reducing because the reduction is the same
8
+ * everywhere and the formatting is not: it needs the reader's locale, and a
9
+ * monetary reduction has one line per currency to lay out.
10
+ */
11
+ const formatCalculationResult = ({ result, formatters, labels }) => {
12
+ switch (result.type) {
13
+ case "count":
14
+ case "number": return line(labels.kind, formatters.number(result.value));
15
+ case "ratio": return line(labels.kind, formatters.percent(result.value));
16
+ case "money": {
17
+ const amounts = result.totals.map((total) => formatters.money(total.amountCents, total.currency));
18
+ if (amounts.length === 0) return line(labels.kind, labels.unavailable);
19
+ return {
20
+ summary: `${labels.kind} ${amounts.join(SEPARATOR)}`,
21
+ breakdown: amounts.length > 1 ? amounts : []
22
+ };
23
+ }
24
+ case "unsupported": return line(labels.kind, labels.unavailable);
25
+ default: return result;
26
+ }
27
+ };
28
+ /**
29
+ * Two, the ISO 4217 default, used when a stored code is one `Intl` will not
30
+ * accept. Validation at the API boundary keeps those out, but a row written
31
+ * before that constraint existed must still render rather than throw.
32
+ */
33
+ const DEFAULT_MINOR_UNIT_DIGITS = 2;
34
+ /**
35
+ * How many minor units make a major one, for this currency: 100 for CZK, 1 for
36
+ * JPY, 1000 for KWD. It is a property of the currency and not of the reader, so
37
+ * the lookup is deliberately locale-independent.
38
+ *
39
+ * A malformed code makes the `Intl.NumberFormat` constructor throw, before any
40
+ * `?? 2` on its result could help, so the fallback has to wrap the call.
41
+ */
42
+ const currencyMinorUnitDigits = (currency) => {
43
+ const resolved = Result.try(() => new Intl.NumberFormat("en", {
44
+ style: "currency",
45
+ currency
46
+ }).resolvedOptions().maximumFractionDigits);
47
+ if (resolved.isErr()) return DEFAULT_MINOR_UNIT_DIGITS;
48
+ return resolved.value ?? DEFAULT_MINOR_UNIT_DIGITS;
49
+ };
50
+ /**
51
+ * Money is stored in minor units, and how many of them make a major one is a
52
+ * property of the currency. Ask the currency rather than assuming a hundred.
53
+ *
54
+ * A code `Intl` rejects falls back to the amount beside the raw code: a column
55
+ * showing "1500 A1C" is wrong-looking data, which is the truth, where a thrown
56
+ * RangeError would take the whole board down with it.
57
+ */
58
+ const formatMoneyCents = ({ amountCents, currency, locale }) => {
59
+ const major = amountCents / 10 ** currencyMinorUnitDigits(currency);
60
+ const formatted = Result.try(() => new Intl.NumberFormat(locale, {
61
+ style: "currency",
62
+ currency
63
+ }).format(major));
64
+ return formatted.isErr() ? `${major} ${currency}` : formatted.value;
65
+ };
66
+ const SEPARATOR = " · ";
67
+ const line = (kind, value) => ({
68
+ summary: `${kind} ${value}`,
69
+ breakdown: []
70
+ });
71
+ //#endregion
72
+ export { currencyMinorUnitDigits, formatCalculationResult, formatMoneyCents };
@@ -0,0 +1,15 @@
1
+ import { CalculationKind } from "@stll/calculations";
2
+ //#region src/calculation-selection.d.ts
3
+ type CalculationSelection = {
4
+ propertyId: string;
5
+ kind: CalculationKind;
6
+ };
7
+ type ApplyCalculationSelectionParams = {
8
+ selections: readonly CalculationSelection[];
9
+ propertyId: string;
10
+ /** The reduction to show, or null to stop showing one. */
11
+ kind: CalculationKind | null;
12
+ };
13
+ declare const applyCalculationSelection: ({ selections, propertyId, kind }: ApplyCalculationSelectionParams) => CalculationSelection[];
14
+ //#endregion
15
+ export { ApplyCalculationSelectionParams, CalculationSelection, applyCalculationSelection };
@@ -0,0 +1,14 @@
1
+ //#region src/calculation-selection.ts
2
+ const applyCalculationSelection = ({ selections, propertyId, kind }) => {
3
+ if (kind === null) return selections.filter((selection) => selection.propertyId !== propertyId);
4
+ if (selections.some((selection) => selection.propertyId === propertyId)) return selections.map((selection) => selection.propertyId === propertyId ? {
5
+ propertyId,
6
+ kind
7
+ } : selection);
8
+ return [...selections, {
9
+ propertyId,
10
+ kind
11
+ }];
12
+ };
13
+ //#endregion
14
+ export { applyCalculationSelection };
@@ -0,0 +1,67 @@
1
+ import { FormattedCalculation } from "./calculation-format.js";
2
+ import { CalculationSelection } from "./calculation-selection.js";
3
+ import { CalculationKind, CalculationResult, CalculationValue } from "@stll/calculations";
4
+ import { ReactNode } from "react";
5
+ //#region src/calculations.d.ts
6
+ /** A property a view can calculate over, with the reductions its values allow. */
7
+ type CalculationProperty = {
8
+ id: string;
9
+ name: string;
10
+ kinds: readonly CalculationKind[];
11
+ };
12
+ type WorkspaceCalculationLabels = {
13
+ choose: string;
14
+ kinds: Record<CalculationKind, string>;
15
+ noProperties: string;
16
+ none: string;
17
+ unavailable: string;
18
+ };
19
+ type CalculationPickerProps = {
20
+ labels: WorkspaceCalculationLabels;
21
+ properties: readonly CalculationProperty[];
22
+ selections: readonly CalculationSelection[];
23
+ onChange: (selections: CalculationSelection[]) => void;
24
+ /** Trigger content. Defaults to the calculation glyph. */
25
+ children?: ReactNode;
26
+ };
27
+ /**
28
+ * Choose what a view calculates: a property, then a reduction. Every step is a
29
+ * menu item, so the whole choice is reachable from the keyboard.
30
+ */
31
+ declare const CalculationPicker: ({ labels, properties, selections, onChange, children }: CalculationPickerProps) => import("react").JSX.Element;
32
+ type CalculationKindPickerProps = {
33
+ labels: WorkspaceCalculationLabels;
34
+ /** Reductions this column's values allow. */
35
+ kinds: readonly CalculationKind[];
36
+ /** The reduction currently shown, or null for none. */
37
+ value: CalculationKind | null;
38
+ onChange: (kind: CalculationKind | null) => void;
39
+ /** Trigger content. Defaults to the calculation glyph. */
40
+ children?: ReactNode;
41
+ };
42
+ /**
43
+ * Choose one column's reduction. The board picks a property first (it shows one
44
+ * line for the whole board); a table column already is the property.
45
+ */
46
+ declare const CalculationKindPicker: ({ labels, kinds, value, onChange, children }: CalculationKindPickerProps) => import("react").JSX.Element;
47
+ type CalculationSummaryProps = {
48
+ calculation: FormattedCalculation;
49
+ };
50
+ /**
51
+ * The calculation as one compact line. When it reduces to several currencies
52
+ * the line stays short and the full set sits behind a tooltip.
53
+ */
54
+ declare const CalculationSummary: ({ calculation }: CalculationSummaryProps) => import("react").JSX.Element;
55
+ type UseCalculationParams = {
56
+ kind: CalculationKind;
57
+ labels: WorkspaceCalculationLabels;
58
+ values: readonly CalculationValue[];
59
+ /** Every value in the view, for a reduction relative to the whole. */
60
+ scopeValues?: readonly CalculationValue[] | undefined;
61
+ };
62
+ /** Reduce a column's values and format the answer for the reader's locale. */
63
+ declare const useCalculation: ({ kind, labels, values, scopeValues }: UseCalculationParams) => FormattedCalculation;
64
+ /** One configured calculation, reduced over a column and rendered compactly. */
65
+ declare const ColumnCalculation: (params: UseCalculationParams) => import("react").JSX.Element;
66
+ //#endregion
67
+ export { CalculationKindPicker, CalculationKindPickerProps, CalculationPicker, CalculationPickerProps, CalculationProperty, type CalculationResult, type CalculationSelection, CalculationSummary, CalculationSummaryProps, ColumnCalculation, UseCalculationParams, WorkspaceCalculationLabels, useCalculation };
@@ -0,0 +1,108 @@
1
+ import { formatCalculationResult, formatMoneyCents } from "./calculation-format.js";
2
+ import { applyCalculationSelection } from "./calculation-selection.js";
3
+ import { CheckIcon, SigmaIcon } from "lucide-react";
4
+ import { useFormatter, useLocale } from "use-intl";
5
+ import { runCalculation } from "@stll/calculations";
6
+ import { Button } from "@stll/ui/button";
7
+ import { Menu, MenuItem, MenuPopup, MenuSub, MenuSubPopup, MenuSubTrigger, MenuTrigger } from "@stll/ui/menu";
8
+ import { Tooltip, TooltipPopup, TooltipTrigger } from "@stll/ui/tooltip";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/calculations.tsx
11
+ /**
12
+ * Choose what a view calculates: a property, then a reduction. Every step is a
13
+ * menu item, so the whole choice is reachable from the keyboard.
14
+ */
15
+ const CalculationPicker = ({ labels, properties, selections, onChange, children }) => {
16
+ const select = (propertyId, kind) => {
17
+ onChange(applyCalculationSelection({
18
+ selections,
19
+ propertyId,
20
+ kind
21
+ }));
22
+ };
23
+ return /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
24
+ "aria-label": labels.choose,
25
+ render: /* @__PURE__ */ jsx(Button, {
26
+ size: "icon-xs",
27
+ variant: "ghost"
28
+ }),
29
+ children: children ?? /* @__PURE__ */ jsx(SigmaIcon, {})
30
+ }), /* @__PURE__ */ jsxs(MenuPopup, { children: [properties.length === 0 && /* @__PURE__ */ jsx(MenuItem, {
31
+ disabled: true,
32
+ children: labels.noProperties
33
+ }), properties.map((property) => {
34
+ const selected = selections.find((selection) => selection.propertyId === property.id);
35
+ return /* @__PURE__ */ jsxs(MenuSub, { children: [/* @__PURE__ */ jsx(MenuSubTrigger, { children: property.name }), /* @__PURE__ */ jsxs(MenuSubPopup, { children: [/* @__PURE__ */ jsxs(MenuItem, {
36
+ onClick: () => select(property.id, null),
37
+ children: [selected === void 0 ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx("span", {}), labels.none]
38
+ }), property.kinds.map((kind) => /* @__PURE__ */ jsxs(MenuItem, {
39
+ onClick: () => select(property.id, kind),
40
+ children: [selected?.kind === kind ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx("span", {}), labels.kinds[kind]]
41
+ }, kind))] })] }, property.id);
42
+ })] })] });
43
+ };
44
+ /**
45
+ * Choose one column's reduction. The board picks a property first (it shows one
46
+ * line for the whole board); a table column already is the property.
47
+ */
48
+ const CalculationKindPicker = ({ labels, kinds, value, onChange, children }) => /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
49
+ "aria-label": labels.choose,
50
+ render: /* @__PURE__ */ jsx(Button, {
51
+ size: "icon-xs",
52
+ variant: "ghost"
53
+ }),
54
+ children: children ?? /* @__PURE__ */ jsx(SigmaIcon, {})
55
+ }), /* @__PURE__ */ jsxs(MenuPopup, { children: [/* @__PURE__ */ jsxs(MenuItem, {
56
+ onClick: () => onChange(null),
57
+ children: [value === null ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx("span", {}), labels.none]
58
+ }), kinds.map((kind) => /* @__PURE__ */ jsxs(MenuItem, {
59
+ onClick: () => onChange(kind),
60
+ children: [value === kind ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx("span", {}), labels.kinds[kind]]
61
+ }, kind))] })] });
62
+ /**
63
+ * The calculation as one compact line. When it reduces to several currencies
64
+ * the line stays short and the full set sits behind a tooltip.
65
+ */
66
+ const CalculationSummary = ({ calculation }) => {
67
+ if (calculation.breakdown.length === 0) return /* @__PURE__ */ jsx("span", {
68
+ className: "text-muted-foreground shrink-0 text-xs tabular-nums",
69
+ children: calculation.summary
70
+ });
71
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
72
+ render: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground shrink-0 text-xs tabular-nums" }),
73
+ children: calculation.summary
74
+ }), /* @__PURE__ */ jsx(TooltipPopup, { children: /* @__PURE__ */ jsx("ul", { children: calculation.breakdown.map((entry) => /* @__PURE__ */ jsx("li", { children: entry }, entry)) }) })] });
75
+ };
76
+ /** Reduce a column's values and format the answer for the reader's locale. */
77
+ const useCalculation = ({ kind, labels, values, scopeValues }) => {
78
+ const formatters = useCalculationFormatters();
79
+ return formatCalculationResult({
80
+ result: runCalculation({
81
+ kind,
82
+ values,
83
+ scopeValues
84
+ }),
85
+ formatters,
86
+ labels: {
87
+ kind: labels.kinds[kind],
88
+ unavailable: labels.unavailable
89
+ }
90
+ });
91
+ };
92
+ /** One configured calculation, reduced over a column and rendered compactly. */
93
+ const ColumnCalculation = (params) => /* @__PURE__ */ jsx(CalculationSummary, { calculation: useCalculation(params) });
94
+ const useCalculationFormatters = () => {
95
+ const format = useFormatter();
96
+ const locale = useLocale();
97
+ return {
98
+ number: (value) => format.number(value),
99
+ money: (amountCents, currency) => formatMoneyCents({
100
+ amountCents,
101
+ currency,
102
+ locale
103
+ }),
104
+ percent: (ratio) => format.number(ratio, { style: "percent" })
105
+ };
106
+ };
107
+ //#endregion
108
+ export { CalculationKindPicker, CalculationPicker, CalculationSummary, ColumnCalculation, useCalculation };
@@ -0,0 +1,2 @@
1
+ import { ColorVariants, OptionColor, emptyColor, optionColors, resolveOptionColor } from "@stll/ui/option-color";
2
+ export { type ColorVariants, type OptionColor, emptyColor, optionColors, resolveOptionColor };
package/dist/colors.js ADDED
@@ -0,0 +1,2 @@
1
+ import { emptyColor, optionColors, resolveOptionColor } from "@stll/ui/option-color";
2
+ export { emptyColor, optionColors, resolveOptionColor };
@@ -0,0 +1,98 @@
1
+ import { ConditionOperator, FieldOption, FieldValueType, ValueEditorKind } from "./logic.js";
2
+ import { ReactNode } from "react";
3
+ import { ConditionNode, GroupNode } from "@stll/conditions";
4
+ //#region src/conditions/builder.d.ts
5
+ /**
6
+ * Every string the builder draws. The module resolves none of them: a host
7
+ * brings its own catalogue, and an exported module that reached into one would
8
+ * only work inside the app whose messages it happened to know.
9
+ */
10
+ type ConditionBuilderLabels = {
11
+ /** "+ Add condition". */
12
+ addCondition: string;
13
+ /** "+ Add group". */
14
+ addGroup: string;
15
+ /** Leads the first row: "When". */
16
+ when: string;
17
+ /** Accessible name of the and/or select. */
18
+ match: string;
19
+ and: string;
20
+ or: string;
21
+ /** Removes one row or group. */
22
+ remove: string;
23
+ /** Placeholder in the field select. */
24
+ fieldPlaceholder: string;
25
+ /** Placeholder in the value editor. */
26
+ valuePlaceholder: string;
27
+ /** The "ƒ Calculated value…" item. */
28
+ useFormula: string;
29
+ /** The date editor's own three. */
30
+ clearDate: string;
31
+ selectDate: string;
32
+ today: string;
33
+ /** How an operator reads for a given value type. */
34
+ operator: (valueType: FieldValueType, op: ConditionOperator) => string;
35
+ };
36
+ /** Capability flags and host injections that let one recursive builder serve
37
+ * both the View filter surface and the template rule surface. The host owns
38
+ * the field list and (optionally) the value editors; the builder owns the
39
+ * tree shape, the gutter, nesting, and the formula escape hatch. */
40
+ type ConditionCapabilities = {
41
+ /** Operands the picker may target (property / builtin / kind / path). */
42
+ fields: FieldOption[];
43
+ /** Allow nested groups (the "+ Add group" affordance + bordered subgroups). */
44
+ allowNesting?: boolean;
45
+ /** Offer a "ƒ Calculated value…" item that switches a leaf's left operand to
46
+ * a formula edited via `FormulaCell`. */
47
+ allowFormula?: boolean;
48
+ /** Numeric operands a formula leaf may reference; required for `allowFormula`. */
49
+ formulaNumberFields?: readonly {
50
+ path: string;
51
+ label: string;
52
+ }[];
53
+ /** Host-injected value editor (e.g. faceted selects). Return null to fall back
54
+ * to the builder's built-in editor for that kind. */
55
+ renderValueEditor?: (ctx: ValueEditorRenderCtx) => React.ReactNode | null;
56
+ /** Draws the formula cell for a formula leaf; required for `allowFormula`. */
57
+ renderFormulaCell?: (ctx: FormulaCellRenderCtx) => ReactNode;
58
+ /** Restrict the operator set per value type (e.g. the template surface only
59
+ * exposes operators its serializer can render). Defaults to the logic's
60
+ * `operatorsFor`. */
61
+ operatorsFor?: (valueType: FieldValueType) => readonly ConditionOperator[];
62
+ /** Override how a value type renders its value editor. Defaults to the logic's
63
+ * `valueEditorFor`. */
64
+ valueEditorFor?: (valueType: FieldValueType, op: ConditionOperator) => ValueEditorKind;
65
+ };
66
+ /**
67
+ * The formula editor is a slot: its expression language belongs to the host,
68
+ * so the builder hands it the expression and takes back either a new one or a
69
+ * request to go back to an ordinary field. Rebuilding the leaf stays here,
70
+ * because that is AST work.
71
+ */
72
+ type FormulaCellRenderCtx = {
73
+ expr: string;
74
+ numberFields: readonly {
75
+ path: string;
76
+ label: string;
77
+ }[];
78
+ onChangeExpr: (expr: string) => void;
79
+ onUseField: () => void;
80
+ };
81
+ type ValueEditorRenderCtx = {
82
+ editorKind: ValueEditorKind;
83
+ field: FieldOption;
84
+ node: ConditionNode;
85
+ operator: ConditionOperator;
86
+ emit: (value: string | string[]) => void;
87
+ };
88
+ type ConditionBuilderProps = {
89
+ value: ConditionNode | null;
90
+ onChange: (next: GroupNode) => void;
91
+ capabilities: ConditionCapabilities;
92
+ labels: ConditionBuilderLabels;
93
+ /** Formatting locale for the date editor. */
94
+ locale: string;
95
+ };
96
+ declare const ConditionBuilder: ({ value, onChange, capabilities, labels, locale }: ConditionBuilderProps) => import("react").JSX.Element;
97
+ //#endregion
98
+ export { ConditionBuilder, ConditionBuilderLabels, ConditionCapabilities, FormulaCellRenderCtx, ValueEditorRenderCtx };