@object-ui/fields 11.2.0 → 11.4.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/dist/FieldEditWidget.d.ts +21 -0
  3. package/dist/FieldEditWidget.test.d.ts +8 -0
  4. package/dist/__tests__/NumberCellRenderer.test.d.ts +0 -0
  5. package/dist/__tests__/lookupCellReferenceKey.test.d.ts +0 -0
  6. package/dist/index.cjs +4 -4
  7. package/dist/index.d.ts +8 -0
  8. package/dist/index.js +2155 -1438
  9. package/dist/widgets/LookupField.dependsOn.test.d.ts +8 -0
  10. package/dist/widgets/PeoplePicker.d.ts +63 -0
  11. package/dist/widgets/PeoplePicker.test.d.ts +8 -0
  12. package/dist/widgets/PeoplePickerComponents.test.d.ts +8 -0
  13. package/dist/widgets/PersonRow.d.ts +23 -0
  14. package/dist/widgets/RecordPickerDialog.d.ts +9 -1
  15. package/dist/widgets/SelectionTray.d.ts +27 -0
  16. package/dist/widgets/UserField.d.ts +0 -13
  17. package/dist/widgets/UserFieldPicker.test.d.ts +8 -0
  18. package/dist/widgets/deriveLookupColumns.d.ts +12 -4
  19. package/dist/widgets/personDisplay.d.ts +37 -0
  20. package/dist/widgets/personDisplay.test.d.ts +8 -0
  21. package/dist/widgets/useRecordQuery.d.ts +87 -0
  22. package/dist/widgets/useRecordQuery.test.d.ts +8 -0
  23. package/package.json +11 -11
  24. package/src/FieldEditWidget.test.ts +61 -0
  25. package/src/FieldEditWidget.tsx +146 -0
  26. package/src/__tests__/NumberCellRenderer.test.tsx +60 -0
  27. package/src/__tests__/lookupCellReferenceKey.test.tsx +57 -0
  28. package/src/complex-widgets.test.tsx +241 -0
  29. package/src/index.tsx +33 -4
  30. package/src/widgets/GridField.test.tsx +14 -0
  31. package/src/widgets/GridField.tsx +7 -8
  32. package/src/widgets/LookupField.dependsOn.test.tsx +233 -0
  33. package/src/widgets/LookupField.tsx +397 -199
  34. package/src/widgets/NumberField.tsx +4 -2
  35. package/src/widgets/PeoplePicker.test.tsx +334 -0
  36. package/src/widgets/PeoplePicker.tsx +552 -0
  37. package/src/widgets/PeoplePickerComponents.test.tsx +104 -0
  38. package/src/widgets/PersonRow.tsx +117 -0
  39. package/src/widgets/RecordPickerDialog.tsx +58 -129
  40. package/src/widgets/SelectionTray.tsx +110 -0
  41. package/src/widgets/UserField.tsx +20 -1
  42. package/src/widgets/UserFieldPicker.test.tsx +78 -0
  43. package/src/widgets/deriveLookupColumns.test.ts +25 -0
  44. package/src/widgets/deriveLookupColumns.ts +24 -10
  45. package/src/widgets/personDisplay.test.ts +113 -0
  46. package/src/widgets/personDisplay.ts +92 -0
  47. package/src/widgets/useRecordQuery.test.ts +174 -0
  48. package/src/widgets/useRecordQuery.ts +264 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,158 @@
1
1
  # @object-ui/fields
2
2
 
3
+ ## 11.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 19f2533: Detail-page related lists: `relatedList: 'primary'` → own tab, multi-FK & self-referential related lists, unified picker columns (framework #2579).
8
+
9
+ - **plugin-detail** (`buildDefaultTabs`): the default related-list layout is now
10
+ the ADR-0085 prominence rule — lists whose FK declares `relatedList: 'primary'`
11
+ each get their OWN tab; every other related list collapses into a single
12
+ "Related" tab. With no primary lists this is byte-for-byte the previous stacked
13
+ default, so it is opt-in per relationship. `relatedLayout: 'tabs' | 'stack'`
14
+ remain app-level overrides (force all-own-tabs / all-stacked).
15
+ - **app-shell** (`deriveRelatedLists`): emits one related list per eligible FK —
16
+ a child referencing the parent through several relationships (e.g.
17
+ `primary_account` + `partner_account`) now surfaces each, disambiguated by the
18
+ FK label; includes self-referential relationships (hierarchies → a "child"
19
+ list); and carries the `isPrimary` prominence flag through. `RecordDetailView`
20
+ threads `isPrimary` into the synthesized page.
21
+ - **fields** (`deriveLookupColumns`): the lookup-picker default columns now
22
+ prefer the object's ADR-0085 `highlightFields` (then legacy `displayFields`,
23
+ then the field walk) — the same "how to list this object" source the related
24
+ list uses, so a picker and a related list of the same object agree with zero
25
+ per-surface config.
26
+
27
+ Pairs with the `@objectstack/spec` change that makes `relatedList` a tri-state
28
+ (`boolean | 'primary'`) and `record:related_list` `columns` optional.
29
+
30
+ ### Patch Changes
31
+
32
+ - bce581a: Fix dependent (cascading) lookups: unlock on parent selection and enforce the
33
+ cascade filter on every candidate surface (#2215).
34
+
35
+ Two breaks made `depends_on` unusable end to end:
36
+
37
+ - **The gate never unlocked in create mode.** `LookupField` resolved dependent
38
+ values from `ctx.formValues` — a member `SchemaRendererContext` never had —
39
+ and nothing injected the `dependentValues` prop, so with a fresh record
40
+ (`ctx.data = {}`) the child lookup stayed disabled no matter what the user
41
+ picked in the parent field. The form renderer now injects its live form
42
+ values (the same reactive snapshot that drives field rules) as
43
+ `dependentValues` for data-source fields.
44
+ - **The Level-2 table picker bypassed the cascade.** The `depends_on` chain
45
+ only reached the quick-select popover filter; `RecordPickerDialog` (and the
46
+ search-first `PeoplePicker`) received just `lookup_filters`, listing the full
47
+ unfiltered record set. Both pickers now take a `baseFilter` — a hard
48
+ `$filter` constraint merged after `lookupFilters` and user filter-bar input,
49
+ so it can never be widened back out — and `LookupField` passes the dependent
50
+ chain there, shares the same filter with the popover query, and disables the
51
+ browse-all button while dependencies are missing.
52
+
53
+ - 5160832: fix(fields): inline-edit relational fields with the standard picker (not a text box)
54
+
55
+ Inline cell editing reuses the form's field widgets, but the inline map
56
+ (`EDIT_WIDGETS`) was a hand-maintained subset of the form's (`fieldWidgetMap`)
57
+ and had drifted: **lookup / master_detail / user / owner** had perfectly good
58
+ form pickers yet fell back to a plain text box inline (you'd type a raw record
59
+ id). Wire them up — `lookup`/`master_detail` → `LookupField`, `user`/`owner` →
60
+ `UserField`, the exact widgets the form uses. They read the related-object
61
+ dataSource from `SchemaRendererContext` (which the grid provides), so the
62
+ record picker opens, fetches, and selects inline.
63
+
64
+ To stop the two lists drifting again, `index` now exports `FORM_FIELD_TYPES`
65
+ and a drift-guard test pins the contract: every form widget type must have an
66
+ explicit inline decision — an editor in `EDIT_WIDGETS` or an entry in the new
67
+ `INLINE_EXCLUDED_FIELD_TYPES` (computed/binary/heavy/container types, each with
68
+ a reason). A future form widget can no longer silently become a text box (or a
69
+ missing editor) in the grid.
70
+
71
+ - 69d6b94: feat(fields): inline-edit structured-value fields (color, address, location, geolocation, code, qrcode)
72
+
73
+ Completes the inline-editor ↔ form-widget parity from the previous fix: the six
74
+ structured types that already had lightweight form widgets — `color`,
75
+ `address`, `location`, `geolocation`, `code`, `qrcode` — now edit inline with
76
+ those same widgets instead of being deferred. All are dependency-light (no map
77
+ or code-editor libraries) and use the standard `FieldWidgetProps`. Verified
78
+ inline on the field-zoo: color → a color picker, code → a textarea, the rest
79
+ their value editors. The drift-guard's exclusion set now contains only the
80
+ genuinely-non-inline types (computed, binary, heavy editors, containers).
81
+
82
+ - 243a9ba: fix(fields): inline lookup editor shows the selected record's name (not the "Select…" placeholder)
83
+
84
+ When editing a `lookup` / `master_detail` / `user` / `owner` field inline in the
85
+ data grid, the `LookupField` picker showed the placeholder instead of the
86
+ current record's name. The grid requests `$expand` for visible reference
87
+ columns, so a lookup cell's value arrives as the related record **object**
88
+ (`{ id, name }`) rather than a bare id. The read cell (`LookupCellRenderer`)
89
+ already resolves objects via the display-name path, but the inline editor only
90
+ matched **primitive** ids (`findOption(value)` with a strict `===`), so an
91
+ object value never resolved — and the hydration effect made it worse by calling
92
+ `findOne(referenceTo, <object>)` with a bogus id.
93
+
94
+ `LookupField` now resolves an expanded-reference object directly into its
95
+ display option (mirroring the read cell), skips the pointless per-object fetch,
96
+ and normalises object values to their id for option matching / multi-select
97
+ toggle / removal. `FieldEditWidget` also renders the relational pickers
98
+ `compact` inline — the same single-line, borderless trigger the line-item grid
99
+ uses — so the record name shows **in** the trigger instead of a chip stacked
100
+ above a "Select…" button.
101
+
102
+ - 289be5b: fix(fields): align inline lookup value resolution with the read cell (external-id strings, tolerant id match)
103
+
104
+ Follow-up to #2125. `LookupField`'s inline display now resolves every value
105
+ shape the read cell (`LookupCellRenderer`) does:
106
+
107
+ - **JSON-encoded external-id references** (`'{"externalId":"Website Relaunch"}'`)
108
+ are parsed and shown by their external id, and excluded from the hydration
109
+ fetch (so we never `findOne` with a raw JSON string). `recordToOption` gained
110
+ an `externalId` fallback for both the value and the label.
111
+ - **Tolerant id matching** — a `String()`-coerced fallback (`findOptionLoose`)
112
+ resolves a numeric cell value against a string-keyed option (and vice versa),
113
+ matching the read cell's `String(a) === String(b)` comparison. Only consulted
114
+ when the strict match misses, so homogeneous option lists are unaffected.
115
+
116
+ Also adds explicit inline-editor tests for `user` / `owner` fields (they
117
+ delegate to `LookupField` via `UserField`), completing coverage for the full
118
+ relational set wired inline in #2122.
119
+
120
+ - 09e1b26: Show inline line-item (master-detail subform) row actions always, not on hover.
121
+ In grid mode the per-row remove (🗑) and duplicate buttons were `opacity-0`
122
+ until the row was hovered (`group-hover`), so they read as "delete not
123
+ supported" and were unreachable on touch / coarse-pointer devices with no hover.
124
+ They now render at full opacity (kept muted via `text-muted-foreground`); the
125
+ action column width was already reserved, so there is no layout shift. Existing
126
+ `allow_delete: false` / `readonly` / `disabled` / `min_rows` gating is unchanged.
127
+ - Updated dependencies [8bf6295]
128
+ - Updated dependencies [1948c5b]
129
+ - Updated dependencies [bce581a]
130
+ - Updated dependencies [9cd9be1]
131
+ - Updated dependencies [c38d107]
132
+ - Updated dependencies [7782698]
133
+ - Updated dependencies [790558b]
134
+ - Updated dependencies [e84d64d]
135
+ - @object-ui/types@11.4.0
136
+ - @object-ui/components@11.4.0
137
+ - @object-ui/i18n@11.4.0
138
+ - @object-ui/core@11.4.0
139
+ - @object-ui/providers@11.4.0
140
+ - @object-ui/react@11.4.0
141
+
142
+ ## 11.3.0
143
+
144
+ ### Patch Changes
145
+
146
+ - Updated dependencies [d88c8ec]
147
+ - Updated dependencies [b7237bb]
148
+ - Updated dependencies [d23d6eb]
149
+ - @object-ui/components@11.3.0
150
+ - @object-ui/i18n@11.3.0
151
+ - @object-ui/core@11.3.0
152
+ - @object-ui/react@11.3.0
153
+ - @object-ui/types@11.3.0
154
+ - @object-ui/providers@11.3.0
155
+
3
156
  ## 11.2.0
4
157
 
5
158
  ### Patch Changes
@@ -0,0 +1,21 @@
1
+ import { default as React } from 'react';
2
+ import { FieldWidgetProps } from './widgets/types';
3
+ /**
4
+ * Form field types that are deliberately NOT given an inline editor — every
5
+ * other form widget type must be in {@link EDIT_WIDGETS}. This pairing is
6
+ * enforced by a test against the form's widget map (`FORM_FIELD_TYPES`) so the
7
+ * two can't silently drift again (which is how `lookup` was missed). To add a
8
+ * type to inline editing, move it from here into EDIT_WIDGETS.
9
+ */
10
+ export declare const INLINE_EXCLUDED_FIELD_TYPES: Set<string>;
11
+ /** Field types whose value is chosen in one discrete gesture (no free typing). */
12
+ export declare const DISCRETE_EDIT_TYPES: Set<string>;
13
+ /** True when a field type has a dedicated in-place edit widget. */
14
+ export declare function hasFieldEditWidget(type: string | undefined): boolean;
15
+ /**
16
+ * Render the dedicated edit widget for a field's type — the SAME control the
17
+ * form uses — as a controlled `{ value, onChange, field }` input. Returns
18
+ * `null` for types without a registered widget so the caller can fall back to
19
+ * a plain editor.
20
+ */
21
+ export declare function FieldEditWidget({ field, value, onChange, readonly, }: FieldWidgetProps<any>): React.ReactElement | null;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export {};
File without changes