Releases: objectstack-ai/objectui
Release list
@object-ui/types@15.0.0
@object-ui/types@15.0.0
@object-ui/types@14.1.0
Minor Changes
-
887062c: feat(dashboard): dashboard-level filters (date / region) driving multiple charts (framework#2501)
A dashboard's
dateRange+globalFiltersdeclarations are now wired end to
end: the filter values live as dashboard-level variables (the page variables
primitive, so they're also readable aspage.<name>in widget expressions),
a filter bar renders above the widgets, and at render time the dashboard
broadcasts the active values into every bound widget's inline query —
AND-merged with the widget's ownfilter. Charts stay inline and
self-contained; each widget maps a filter to its own field.@object-ui/types—globalFilters[].name(stable filter/variable key,
defaults tofield) andDashboardWidgetSchema.filterBindings
(Record<string, string | false>: per-widget field override /false
opt-out). Zod mirrors included. Pending paired@objectstack/spec
alignment (framework#2501) — same precedent asdataset/
categoryGranularity.@object-ui/core— new puredashboard-filtersmodule
(resolveDashboardFilterDefs,dashboardFilterVariableDefs,
buildFilterCondition,buildWidgetScopedFilter);mergeFilterslifted
from plugin-report (re-exported there unchanged). Date presets emit
date-macro tokens ({30_days_ago}…) so widgets resolve them at query time
like hand-authored filters.@object-ui/plugin-dashboard—DashboardFilterBar(date presets +
custom range calendar, select with staticoptionsoroptionsFrom,
text/number inputs, reset);DashboardRenderermounts a
PageVariablesProviderwhen filters are declared and merges the
widget-scoped condition into inline widgets'filterand dataset widgets'
runtimeFilter. Dashboards without filters render exactly as before.
Binding precedence: explicit
filterBindingsstring/false→ legacy
targetWidgetsallow-list → the filter's ownfield(dateRange defaults to
created_at). Static-data widgets are not filtered. -
d5b1bc0: remove(tenant): drop the zero-consumer
@object-ui/tenantpackage and thetypes/tenant.tsmirror (#2564)@object-ui/tenant(TenantProvider/TenantGuard/TenantScopedQuery/
createTenantResolver/useTenant/useTenantBranding) was an
exported-but-dead aspirational surface: no workspace package depended on it
and nothing imported it. ItsTenantConfig.isolationstrategy enum
('database' | 'schema' | 'row' | 'hybrid') was the UI mirror of the spec's
tenancy.strategy, which framework#2763/framework#2962 removed under the same
enforce-or-remove doctrine — the platform has exactly two tenancy modes, and
neither is configured client-side.@object-ui/typesno longer exports the tenant type family
(TenantConfig,TenantIsolationStrategy,TenantStatus,TenantPlan,
TenantBranding,TenantLimits,TenantContext,
TenantResolutionStrategy,TenantProviderConfig,
TenantScopedQueryConfig).Migration: real tenant scoping is server-enforced —
createAuthenticatedFetch
(@object-ui/auth) already injects the active organization asX-Tenant-ID
on every API call, and the backend applies row-level isolation
(tenancy.enabled+tenantFieldin@objectstack/spec). Per-tenant
branding is aThemeSchemaconcern. The skills guides and docs that
advertised the dead package have been rewritten to say exactly that. -
f0f10f5: feat(kanban): default lane field honours the ADR-0085
stageFieldroleKanban views without an explicit
groupByField/groupFieldhard-coded their
lane field to the literal'status'(in both app-shell's ObjectView options
and plugin-list's ListView fallback) — ignoring the object's declared
lifecycle and even inventing a field the object doesn't have. The default now
resolves through the sharedstageFielddetector:- explicit view config (unchanged, always wins);
- the object's
stageFieldsemantic role; stageField: false→ no default lanes (the status-shaped field is
declared non-linear; the board renders its empty state until the view
picks a lane field explicitly);- else the shared name/type heuristic (status / stage / state / phase by
name, then status/stage by type) — never a nonexistent field.
detectStatusFieldmoved from@object-ui/plugin-detailto
@object-ui/types(new export, with theStatusFieldSourceinput type) so
plugin-list and app-shell share the exact semantics; plugin-detail re-exports
it unchanged.Also fixes ListView's pre-existing rules-of-hooks error while touching the
file:useListFieldLabelwrappeduseObjectLabel()in try/catch (hook-order
desync risk; the hook is provider-safe) — same fix as objectui#2595's
useFieldLabel.Behavior change is limited to kanban views with no explicit lane field on
objects that either declarestageField(now honoured), declare
stageField: false(now suppressed), or have no status-shaped field at all
(previously grouped by a nonexistentstatusinto one "undefined" lane; now
an honest empty state). Objects with a realstatusfield — the common case —
are unchanged.
Patch Changes
-
2ded18c: Fix: a dashboard filter declaring its static
optionsin the
@objectstack/specobject form (options: [{ value, label }]— the shape
the spec validates and what framework-authored dashboards ship) crashed the
whole dashboard with "Objects are not valid as a React child". Caught driving
the showcase Revenue Pulse dashboard in a real browser.resolveDashboardFilterDefsnow normalizes both the spec object form and the
bare-string shorthand (options: ['EMEA']) to{ value, label }pairs —
DashboardFilterDef.optionsis typed accordingly — and the filter bar's
select renders labels (the trigger now shows the selected option's label, not
its raw value).@object-ui/typesaligns theGlobalFilterSchema.options
shape with the spec union. -
e628d1f: Dashboard-level filters follow-ups (#2578, framework#2501):
- i18n: the
DashboardFilterBarstrings now ship as real locale entries —
dashboard.filters.*(bar label, "All time", "Custom…", "All", "Reset",
and the 13 date-range preset labels) added toenandzh. Previously the
bar always rendered theuseSafeTranslateEnglish fallbacks. - types:
GlobalFilterSchema.nameandDashboardWidgetSchema.filterBindings
landed in@objectstack/spec(framework#2501), so the local type
annotations flip from "Pending alignment" to "Aligned" — no shape changes.
Also adds five schema-catalog examples (
plugin-dashboard/filtered-dashboard-*:
dynamicoptionsFromoptions, text/number/lookup filter types, dataset +
inline widget mix,targetWidgetsallow-list, date presets + custom range)
and a new "Dashboard-Level Filters" guide page covering the full tutorial,
page.*expression usage, and known limitations with workarounds. - i18n: the
-
9e2d58f: Kanban
conditionalFormattingnow accepts CEL rules in its type + schema (#1584 follow-up).Since #1584 moved kanban card styling onto the shared CEL evaluator, the runtime
already accepts the spec{ condition, style }rule shape — but the type and zod
schema still only allowed the native{ field, operator, value }shape, so a
CEL kanban rule failed validation for something that worked at runtime. The
KanbanConditionalFormattingRuletype andObjectKanbanSchemazod schema are
widened to a union of both shapes, matching list/gridconditionalFormattingand
the runtime. Back-compat: the native shape keeps validating unchanged.
@object-ui/sdui-parser@15.0.0
@object-ui/sdui-parser@15.0.0
@object-ui/sdui-parser@14.1.0
@object-ui/sdui-parser@14.1.0
@object-ui/runner@15.0.0
Patch Changes
- @object-ui/plugin-kanban@15.0.0
- @object-ui/types@15.0.0
- @object-ui/core@15.0.0
- @object-ui/react@15.0.0
- @object-ui/components@15.0.0
- @object-ui/plugin-charts@15.0.0
@object-ui/runner@14.1.0
Patch Changes
- Updated dependencies [0890fa7]
- Updated dependencies [2ded18c]
- Updated dependencies [e628d1f]
- Updated dependencies [5523fc4]
- Updated dependencies [887062c]
- Updated dependencies [055e1d2]
- Updated dependencies [d741937]
- Updated dependencies [9e2d58f]
- Updated dependencies [dea65f7]
- Updated dependencies [f30ff68]
- Updated dependencies [073e7aa]
- Updated dependencies [6c0135c]
- Updated dependencies [5b52624]
- Updated dependencies [4afb251]
- Updated dependencies [d5b1bc0]
- Updated dependencies [f94905d]
- Updated dependencies [f0f10f5]
- @object-ui/core@14.1.0
- @object-ui/types@14.1.0
- @object-ui/react@14.1.0
- @object-ui/components@14.1.0
- @object-ui/plugin-kanban@14.1.0
- @object-ui/plugin-charts@14.1.0
@object-ui/react@15.0.0
Patch Changes
- @object-ui/types@15.0.0
- @object-ui/core@15.0.0
- @object-ui/i18n@15.0.0
- @object-ui/data-objectstack@15.0.0
@object-ui/react@14.1.0
Minor Changes
-
5523fc4: Dashboard-level filters — the three #2578 item-5 enhancements (framework#2501):
- react: nested
PageVariablesProviders now MERGE instead of shadowing
wholesale. A filtered dashboard embedded in a Page with its ownvariables
keeps the outer page variables readable inside widget subtrees (page.*);
an inner definition shadows only the SAME name; writes route to the scope
that defines the variable (writing an outer-defined name from inside the
nested subtree updates the outer provider);resetVariablesstays local.
Names defined nowhere still write locally, exactly as before. - core:
buildWidgetScopedFilteraccepts an optionalknownFieldsset —
a DEFAULT binding whose target field is not on the widget's object is
skipped with a console warning instead of emitting a query the backend
empty-matches. ExplicitfilterBindingsstrings are always honoured (a
typo surfaces as a visibly empty widget, never a silently dropped filter).
OmittingknownFieldspreserves the previous unchecked behaviour. - plugin-dashboard:
DashboardRendererfeedsknownFieldsfrom
dataSource.getObjectSchemafor inlineobjectwidgets (best-effort —
unchecked while metadata loads or when the source can't describe objects).
optionsFromdynamic filter options now resolve DISTINCT values
server-side via a dataset GROUP BY (queryDatasetwith an inline draft)
when the data source supports it, falling back to the previous client-side
top-200 dedupe otherwise.
- react: nested
-
dea65f7: Unify the list-view conditional tier onto the canonical CEL engine (#1584).
Conditional formatting (list / grid / kanban) and row-action
visible/
disabledpredicates are now evaluated by@objectstack/formula's
ExpressionEngine— the same engine the server uses — instead of the legacy
JS-dialectExpressionEvaluator, matching how@objectstack/specalready types
these surfaces (ExpressionInputSchema/ CEL). The whole platform now speaks one
expression dialect (framework ADR-0058).@object-ui/core: newevalRowPredicate+resolveConditionalFormatting
helpers (next toevalFieldPredicate). One implementation of all three
formatting rule shapes; dialect routing (a{ dialect: 'cel' }envelope is
always CEL; a bare string is CEL unless it carries legacy-only syntax
(${…}/===/?./.includes()), which routes to the old engine with a
one-time deprecation warning); the native{ field, operator, value }form is
translated to CEL.@object-ui/react: newuseRowPredicatehook (canonical CEL, ambient
predicate scope merged).- Consumers converged:
ListView.evaluateConditionalFormatting(thin wrapper,
export kept),ObjectGridrow styling (inline copy removed), kanban card
styles, and the grid / data-table row-action menus.plugin-view's kanban
branch now forwards top-levelconditionalFormatting(previously dropped). - Row-action
visiblefails closed (broken predicate → hidden + warn);
disabledfails soft. The CELinoperator (and list membership) now work in
row predicates — the legacy engine could not parse them. - The legacy
FormField.condition: { field, equals/notEquals/in }is retired to
a CEL translation (back-compat preserved);FieldDesignermigrated to
visibleWhen.
Fully back-compat: existing conditional-formatting rules, row-action predicates,
and formconditionmetadata keep working (translated / routed as needed). -
5b52624: feat(detail): record-level inline edit — shared
InlineEditContext+ one atomic Save (objectui#2407 P1)Lift the inline-edit session out of
DetailView's private state into a
record-level, shared context so a record page's surfaces can share ONE draft and
commit it in ONE atomic, cross-field-validated write (replacing the per-field
save loop).InlineEditContext/InlineEditProvider/useInlineEdit(@object-ui/react)
— pure UI state (editing,canEdit,draft,autoFocusField,saving,
error+enter/setField/cancel/reset). A separate context from
RecordContext(mirrorsHighlightFieldsContext) so per-keystroke draft churn
doesn't re-render otherrecord:*consumers.<InlineEditSaveBar>(@object-ui/plugin-detail) — the record-level sticky
Save/Cancel bar. Commits the whole draft in ONE
dataSource.update(obj, id, draft, { ifMatch: data.updated_at })→refresh();
a409 CONCURRENT_UPDATEreuses<ConcurrentUpdateDialog>(reload / overwrite).
A callback mode (onFieldSave) preserves the drawer's per-field persistence
contract with plugin-gantt/calendar/kanban.DetailViewnow consumesuseInlineEdit()instead of owning inline-edit
state; its header/inline Save-Cancel bars and per-field batch-save are removed
(the approval-lock badge stays). Rendered without a provider it is simply
read-only.record:detailsandRecordDetailDrawereach wrap theirDetailView
in an<InlineEditProvider>+<InlineEditSaveBar>. The object-lifecycle /
permission gate flows throughcanEdit; computed / readonly / system fields
and the OCC path are unchanged.
Guardrails preserved: computed (
formula/summary/rollup/auto_number) +
readonly+ system fields expose no editor;canEditgate; OCC (ifMatch+
ConcurrentUpdateDialog); the atomic partial update carries only user-edited
keys (never computed/read-only). Editable highlights ride on top of this in P2. -
f94905d: remove(react): drop the unused
FormRenderer/FieldFactoryduplicate render path (#2545)FormRenderer(and its captiveFieldFactory) was an exported-but-dead second
form render path: zero runtime consumers anywhere in the repo — the only import
was its own test file. It duplicated@object-ui/plugin-form'sObjectForm
(the path every app actually uses via the component registry) but had drifted
into a degraded variant: raw-HTML/Tailwind instead of the shared UI primitives,
a hard-coded Submit button, and no support forsubmitBehavior/aria/
groups.Breaking (ships as minor per the pre-1.0 launch-window convention): the
public exportsFormRenderer,FormRendererProps,FieldFactory,
FieldFactoryProps, andExtendedFormFieldare removed from
@object-ui/react. Render forms through theobject-formschema node
(@object-ui/plugin-formObjectForm, reachable from aFormViewSchemavia
SchemaRenderer/ the spec bridge) instead. Closes Phase 4 of #2545.
Patch Changes
- Updated dependencies [82441e4]
- Updated dependencies [2efa9fd]
- Updated dependencies [0890fa7]
- Updated dependencies [2ded18c]
- Updated dependencies [e628d1f]
- Updated dependencies [5523fc4]
- Updated dependencies [887062c]
- Updated dependencies [23d65c3]
- Updated dependencies [9e2d58f]
- Updated dependencies [dea65f7]
- Updated dependencies [d5b1bc0]
- Updated dependencies [f0f10f5]
- @object-ui/i18n@14.1.0
- @object-ui/core@14.1.0
- @object-ui/types@14.1.0
- @object-ui/data-objectstack@14.1.0
@object-ui/react-runtime@15.0.0
@object-ui/react-runtime@15.0.0
@object-ui/react-runtime@14.1.0
@object-ui/react-runtime@14.1.0