@object-ui/components 14.0.0 → 15.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,191 @@
1
1
  # @object-ui/components
2
2
 
3
+ ## 15.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - @object-ui/types@15.0.0
8
+ - @object-ui/core@15.0.0
9
+ - @object-ui/i18n@15.0.0
10
+ - @object-ui/react@15.0.0
11
+ - @object-ui/react-runtime@15.0.0
12
+ - @object-ui/sdui-parser@15.0.0
13
+
14
+ ## 14.1.0
15
+
16
+ ### Minor Changes
17
+
18
+ - dea65f7: Unify the list-view conditional tier onto the canonical CEL engine (#1584).
19
+
20
+ Conditional formatting (list / grid / kanban) and row-action `visible` /
21
+ `disabled` predicates are now evaluated by `@objectstack/formula`'s
22
+ `ExpressionEngine` — the same engine the server uses — instead of the legacy
23
+ JS-dialect `ExpressionEvaluator`, matching how `@objectstack/spec` already types
24
+ these surfaces (`ExpressionInputSchema` / CEL). The whole platform now speaks one
25
+ expression dialect (framework ADR-0058).
26
+
27
+ - `@object-ui/core`: new `evalRowPredicate` + `resolveConditionalFormatting`
28
+ helpers (next to `evalFieldPredicate`). One implementation of all three
29
+ formatting rule shapes; dialect routing (a `{ dialect: 'cel' }` envelope is
30
+ always CEL; a bare string is CEL unless it carries legacy-only syntax
31
+ (`${…}` / `===` / `?.` / `.includes()`), which routes to the old engine with a
32
+ one-time deprecation warning); the native `{ field, operator, value }` form is
33
+ translated to CEL.
34
+ - `@object-ui/react`: new `useRowPredicate` hook (canonical CEL, ambient
35
+ predicate scope merged).
36
+ - Consumers converged: `ListView.evaluateConditionalFormatting` (thin wrapper,
37
+ export kept), `ObjectGrid` row styling (inline copy removed), kanban card
38
+ styles, and the grid / data-table row-action menus. `plugin-view`'s kanban
39
+ branch now forwards top-level `conditionalFormatting` (previously dropped).
40
+ - Row-action `visible` fails **closed** (broken predicate → hidden + warn);
41
+ `disabled` fails soft. The CEL `in` operator (and list membership) now work in
42
+ row predicates — the legacy engine could not parse them.
43
+ - The legacy `FormField.condition: { field, equals/notEquals/in }` is retired to
44
+ a CEL translation (back-compat preserved); `FieldDesigner` migrated to
45
+ `visibleWhen`.
46
+
47
+ Fully back-compat: existing conditional-formatting rules, row-action predicates,
48
+ and form `condition` metadata keep working (translated / routed as needed).
49
+
50
+ - 073e7aa: Conditional tabs (framework#2606): the `page:tabs` renderer honors an item-level
51
+ `visibleWhen` CEL predicate — when it evaluates FALSE the WHOLE tab (header +
52
+ panel) is omitted from the strip, unlike a child component's own `visibleWhen`,
53
+ which hides only the panel content and leaves an empty tab header behind. The
54
+ predicate binds the same environment as page-component `visibleWhen` (record
55
+ fields bare and via `record.`/`data.`, `user`/`current_user`, and page state as
56
+ `page.<var>`) and re-evaluates live as page variables change. The strip is now
57
+ controlled: when the ACTIVE tab's predicate flips false, selection falls back to
58
+ the first visible tab instead of leaving a blank panel, and the user's own
59
+ selection is restored if the tab becomes visible again. Canonical ADR-0089 key
60
+ only — the deprecated `visibility`/`visibleOn` aliases are not read on this new
61
+ surface. Items without `visibleWhen` behave exactly as before.
62
+ - 6c0135c: feat(page-header): metadata-driven multi-button record header (#2361)
63
+
64
+ The record detail page header no longer hardcodes a single inline primary
65
+ button (`INLINE_MAX = 1`). It now renders up to `maxVisible` actions
66
+ side-by-side (default 3 desktop / 1 mobile, overridable via
67
+ `maxVisible` / `mobileMaxVisible` on the `page:header` schema) — the same
68
+ contract as `action:bar` — so multi-action objects (e.g. Lead: Convert /
69
+ Assign / Return) can surface several primary buttons at once.
70
+
71
+ Which actions claim the inline slots is declared in metadata, mirroring the
72
+ `action:bar` #2339 rules:
73
+
74
+ - `order` ascending (unset = 0; lower = more prominent), stable sort;
75
+ - `variant: 'primary'` as a tie-break within equal order (also mapped to the
76
+ Shadcn `default` Button variant instead of leaking through);
77
+ - `component: 'action:menu'` pins an action inside the `⋯` overflow menu
78
+ regardless of the action count.
79
+
80
+ The synthesized system actions declare their placement accordingly:
81
+ `sys_edit` gets `order: 100` (behind every authored business action, but
82
+ still inline when slots remain), while `sys_share` / `sys_delete` are pinned
83
+ into the `⋯` menu via `component: 'action:menu'` — Delete never surfaces as
84
+ an inline red button just because an object has few actions.
85
+
86
+ ### Patch Changes
87
+
88
+ - 055e1d2: fix(components): exit inline edit mode for injected cell editors (#2321)
89
+
90
+ Non-discrete inline-edit cells (text, number, date, lookup, user, currency,
91
+ percent, …) got permanently stuck in edit mode: the host-injected `@object-ui/fields`
92
+ widget staged its value on every change but had no way to leave edit mode, so
93
+ clicking outside, pressing Enter, and the row Save button all failed to dismiss
94
+ the editor. Only discrete pickers (select/boolean/radio/rating), which commit on
95
+ selection, exited correctly.
96
+
97
+ The DataTable now gives injected widget editors the same exit affordances the
98
+ built-in `<input>` editors have:
99
+
100
+ - **Click-outside** commits the staged value and exits, via a capture-phase
101
+ document `pointerdown` listener. It is portal-aware — clicking inside a lookup
102
+ popover / record-picker dialog the widget itself opened does not exit, and a
103
+ modal that merely hosts the grid does not suppress the commit.
104
+ - **Enter** commits and exits (a multi-line `textarea` keeps inserting newlines).
105
+ - **Escape** reverts this session's staged changes and exits.
106
+
107
+ Keys that bubble up through a React portal from the widget's own popover keep
108
+ driving that popover rather than the cell. Built-in editors are untouched.
109
+
110
+ - f30ff68: fix(components): keep the list-view horizontal scrollbar pinned to the viewport bottom
111
+
112
+ In a list/grid view with many columns, the horizontal scrollbar was only
113
+ reachable after scrolling all the way to the last row. Root cause: the shadcn
114
+ `<Table>` wraps its `<table>` in a `overflow-auto` scroll `<div>`. When
115
+ `DataTable` already renders the table inside a _bounded_
116
+ `flex-1 min-h-0 overflow-auto` region, that default wrapper became a SECOND,
117
+ height-unbounded scroll container — it stretched to the full table height, so
118
+ its horizontal scrollbar sat at the bottom of _all_ rows.
119
+
120
+ - `Table` gains an optional `containerClassName` prop that overrides the
121
+ scroll-wrapper `<div>`'s classes (default behavior unchanged).
122
+ - `DataTable` passes `containerClassName="overflow-visible"` so the outer
123
+ bounded container owns both axes and the horizontal scrollbar stays pinned to
124
+ the viewport bottom — reachable from any scroll position, no need to scroll to
125
+ the last row.
126
+
127
+ Verified end-to-end against the running console (data-table with 60+ rows × 19
128
+ columns): the horizontal scroller is now the bounded `flex-1 min-h-0
129
+ overflow-auto` region (bottom on-screen, within the viewport) and the table can
130
+ be scrolled fully right while still at the top row.
131
+
132
+ - 4afb251: Record-level inline edit polish (objectui#2572, follow-up to #2407) — the five
133
+ rough edges from the live showcase verification pass:
134
+
135
+ - **Expanded reference values pass through to the picker.** `InlineFieldInput`
136
+ no longer collapses an `$expand`-ed record object to a bare id before
137
+ handing it to `LookupField` / `UserField` — the picker resolves the display
138
+ name it already carries instead of re-fetching the referenced record via
139
+ `findOne` (or sticking on the placeholder when it can't). `LookupField`
140
+ still hands its Level-2 pickers (PeoplePicker / RecordPickerDialog) bare
141
+ ids, collapsed via the existing `normalizeId`.
142
+ - **Approval-lock preflight.** The record page now re-reads the approval
143
+ state whenever the record is invalidated (a save can _trigger_ an approval
144
+ flow that locks the record), derives one `approvalLocked` signal
145
+ (`approval_status` pending/in_approval OR an open pending request), gates
146
+ the inline-edit session's `canEdit` with it — hiding the pencil affordances
147
+ and no-op'ing `enter()` on a locked record — and drives the save bar's
148
+ `locked`/`lockedHint` so users can't type into a draft that Save would
149
+ reject with `RECORD_LOCKED`.
150
+ - **Numeric field types edit with the real numeric widgets.** `number` /
151
+ `currency` / `percent` route to `NumberField` / `CurrencyField` /
152
+ `PercentField` (the same widgets the form uses) instead of a free-text
153
+ input: numeric keyboard, symbol adornment, fraction↔percent display
154
+ conversion, and numbers (not strings) into the draft. `NumberField` and
155
+ `CurrencyField` now surface metadata `min`/`max` on the input, `NumberField`
156
+ honors an explicit `step` and steps by 1 for `scale: 0` (previously fell
157
+ back to `any`).
158
+ - **Header Edit CTA stands down during an inline session.** The synthesized
159
+ `sys_edit` action carries `disableDuringInlineEdit`, and the `page:header`
160
+ renderer greys such actions out while `InlineEditContext.editing` — the
161
+ classic form-edit surface can no longer be stacked on top of a live inline
162
+ draft.
163
+ - **Keyboard shortcuts for the shared edit session.** `InlineEditSaveBar`
164
+ binds **Esc → cancel** (deferring to any open Radix layer — popover /
165
+ select / dialog — which owns Escape for "close") and **Cmd/Ctrl+Enter →
166
+ save**, both respecting `saving`/`locked`.
167
+
168
+ - Updated dependencies [82441e4]
169
+ - Updated dependencies [2efa9fd]
170
+ - Updated dependencies [0890fa7]
171
+ - Updated dependencies [2ded18c]
172
+ - Updated dependencies [e628d1f]
173
+ - Updated dependencies [5523fc4]
174
+ - Updated dependencies [887062c]
175
+ - Updated dependencies [23d65c3]
176
+ - Updated dependencies [9e2d58f]
177
+ - Updated dependencies [dea65f7]
178
+ - Updated dependencies [5b52624]
179
+ - Updated dependencies [d5b1bc0]
180
+ - Updated dependencies [f94905d]
181
+ - Updated dependencies [f0f10f5]
182
+ - @object-ui/i18n@14.1.0
183
+ - @object-ui/core@14.1.0
184
+ - @object-ui/types@14.1.0
185
+ - @object-ui/react@14.1.0
186
+ - @object-ui/react-runtime@14.1.0
187
+ - @object-ui/sdui-parser@14.1.0
188
+
3
189
  ## 14.0.0
4
190
 
5
191
  ### Minor Changes
package/dist/index.css CHANGED
@@ -2651,6 +2651,9 @@
2651
2651
  .\[-webkit-overflow-scrolling\:touch\] {
2652
2652
  -webkit-overflow-scrolling: touch;
2653
2653
  }
2654
+ .\[page\:header\] {
2655
+ page: header;
2656
+ }
2654
2657
  .duration-75 {
2655
2658
  animation-duration: 75ms;
2656
2659
  }