@object-ui/fields 17.1.0 → 17.2.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 +194 -0
- package/dist/FieldEditWidget.d.ts +2 -2
- package/dist/__tests__/spec-symbol-batch7.test.d.ts +8 -0
- package/dist/__tests__/widget-props-contract.test.d.ts +8 -0
- package/dist/index.cjs +3 -3
- package/dist/index.js +290 -292
- package/dist/widgets/AddressField.d.ts +2 -2
- package/dist/widgets/AutoNumberField.d.ts +2 -2
- package/dist/widgets/AvatarField.d.ts +2 -2
- package/dist/widgets/BooleanField.d.ts +2 -2
- package/dist/widgets/CapabilityMultiSelectField.d.ts +2 -2
- package/dist/widgets/CheckboxesField.d.ts +2 -2
- package/dist/widgets/CodeField.d.ts +2 -2
- package/dist/widgets/ColorField.d.ts +2 -2
- package/dist/widgets/CurrencyField.d.ts +2 -2
- package/dist/widgets/DateField.d.ts +2 -2
- package/dist/widgets/DateTimeField.d.ts +2 -2
- package/dist/widgets/EmailField.d.ts +2 -2
- package/dist/widgets/FileField.d.ts +2 -2
- package/dist/widgets/FilterConditionField.d.ts +2 -2
- package/dist/widgets/FormulaField.d.ts +2 -2
- package/dist/widgets/GeolocationField.d.ts +2 -2
- package/dist/widgets/GridField.d.ts +2 -2
- package/dist/widgets/ImageField.d.ts +2 -2
- package/dist/widgets/LocationField.d.ts +2 -2
- package/dist/widgets/LookupField.d.ts +2 -2
- package/dist/widgets/MasterDetailField.d.ts +2 -2
- package/dist/widgets/MultiSelectField.d.ts +2 -2
- package/dist/widgets/NumberField.d.ts +2 -2
- package/dist/widgets/ObjectField.d.ts +2 -2
- package/dist/widgets/ObjectRefField.d.ts +2 -2
- package/dist/widgets/PasswordField.d.ts +2 -2
- package/dist/widgets/PercentField.d.ts +2 -2
- package/dist/widgets/PhoneField.d.ts +2 -2
- package/dist/widgets/QRCodeField.d.ts +2 -2
- package/dist/widgets/RadioField.d.ts +2 -2
- package/dist/widgets/RatingField.d.ts +2 -2
- package/dist/widgets/RecipientPickerField.d.ts +2 -2
- package/dist/widgets/RichTextField.d.ts +2 -2
- package/dist/widgets/SelectField.d.ts +2 -2
- package/dist/widgets/SignatureField.d.ts +2 -2
- package/dist/widgets/SliderField.d.ts +2 -2
- package/dist/widgets/SummaryField.d.ts +2 -2
- package/dist/widgets/TagsField.d.ts +2 -2
- package/dist/widgets/TextAreaField.d.ts +2 -2
- package/dist/widgets/TextField.d.ts +2 -2
- package/dist/widgets/TimeField.d.ts +2 -2
- package/dist/widgets/UrlField.d.ts +2 -2
- package/dist/widgets/UserField.d.ts +2 -2
- package/dist/widgets/VectorField.d.ts +2 -2
- package/dist/widgets/file-value.d.ts +20 -33
- package/dist/widgets/types.d.ts +119 -3
- package/package.json +8 -8
- package/src/FieldEditWidget.tsx +6 -4
- package/src/__tests__/spec-symbol-batch7.test.ts +112 -0
- package/src/__tests__/widget-props-contract.test.tsx +129 -0
- package/src/complex-widgets.test.tsx +3 -3
- package/src/datetime-widgets.test.tsx +2 -2
- package/src/index.tsx +3 -1
- package/src/widgets/AddressField.tsx +2 -2
- package/src/widgets/AutoNumberField.tsx +2 -2
- package/src/widgets/AvatarField.tsx +2 -2
- package/src/widgets/BooleanField.tsx +2 -2
- package/src/widgets/CapabilityMultiSelectField.tsx +4 -4
- package/src/widgets/CheckboxesField.tsx +4 -4
- package/src/widgets/CodeField.tsx +2 -2
- package/src/widgets/ColorField.tsx +2 -2
- package/src/widgets/CurrencyField.tsx +2 -2
- package/src/widgets/DateField.tsx +2 -2
- package/src/widgets/DateTimeField.tsx +2 -2
- package/src/widgets/EmailField.tsx +2 -2
- package/src/widgets/FileField.tsx +2 -2
- package/src/widgets/FilterConditionField.tsx +3 -3
- package/src/widgets/FormulaField.tsx +2 -2
- package/src/widgets/GeolocationField.tsx +2 -2
- package/src/widgets/GridField.tsx +3 -3
- package/src/widgets/ImageField.tsx +2 -2
- package/src/widgets/LocationField.tsx +2 -2
- package/src/widgets/LookupField.tsx +10 -10
- package/src/widgets/MasterDetailField.tsx +2 -2
- package/src/widgets/MultiSelectField.tsx +4 -4
- package/src/widgets/NumberField.tsx +2 -2
- package/src/widgets/ObjectField.tsx +2 -2
- package/src/widgets/ObjectRefField.tsx +4 -4
- package/src/widgets/PasswordField.tsx +2 -2
- package/src/widgets/PercentField.tsx +2 -2
- package/src/widgets/PhoneField.tsx +2 -2
- package/src/widgets/QRCodeField.tsx +2 -2
- package/src/widgets/RadioField.tsx +4 -4
- package/src/widgets/RatingField.tsx +2 -2
- package/src/widgets/RecipientPickerField.tsx +4 -4
- package/src/widgets/RichTextField.tsx +2 -2
- package/src/widgets/SelectField.tsx +5 -5
- package/src/widgets/SignatureField.tsx +2 -2
- package/src/widgets/SliderField.tsx +2 -2
- package/src/widgets/SummaryField.tsx +2 -2
- package/src/widgets/TagsField.tsx +3 -3
- package/src/widgets/TextAreaField.tsx +2 -2
- package/src/widgets/TextField.tsx +2 -2
- package/src/widgets/TimeField.tsx +2 -2
- package/src/widgets/UrlField.tsx +2 -2
- package/src/widgets/UserField.tsx +2 -2
- package/src/widgets/VectorField.tsx +2 -2
- package/src/widgets/file-value.ts +21 -5
- package/src/widgets/types.ts +129 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,199 @@
|
|
|
1
1
|
# @object-ui/fields
|
|
2
2
|
|
|
3
|
+
## 17.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 785b8a5: `FieldWidgetComponentProps` stops claiming to have every key (objectui#3221).
|
|
8
|
+
|
|
9
|
+
**Breaking for widget authors**: the exported `FieldWidgetComponentProps` no
|
|
10
|
+
longer ends in `[key: string]: any`. FROM: any prop name at all type-checked and
|
|
11
|
+
read as `any`. TO: the type declares a closed set — the controlled-input
|
|
12
|
+
contract (`value` / `onChange` / `field` / `readonly` / `disabled` /
|
|
13
|
+
`className` / `errorMessage` / `onUploadingChange`), the host plumbing a
|
|
14
|
+
renderer forwards (`schema`, `dataSource`, `dependentValues`, `dependsOn`,
|
|
15
|
+
`emptyHint`, `compact`, `onSelectRecord`, `onCreateNew`), and DOM pass-through
|
|
16
|
+
(`id`, `name`, `autoFocus`, `tabIndex`, `onBlur`/`onFocus`/`onClick`, every
|
|
17
|
+
`aria-*`, and `data-*` via a template-literal key). A custom widget reading
|
|
18
|
+
anything else now fails `tsc`; the fix is to read it off `field` (the metadata)
|
|
19
|
+
or to add the key here with its producer named.
|
|
20
|
+
|
|
21
|
+
Scored `minor`, not `major`, per this repo's fixed-group rule — objectui's major
|
|
22
|
+
tracks `@objectstack`, so breaking changes of our own ship as minor with the
|
|
23
|
+
semantics spelled out (see AGENTS.md §版本号策略). The practical blast radius is
|
|
24
|
+
small: every call site in this monorepo — `plugin-detail`'s inline editor,
|
|
25
|
+
`plugin-grid`'s cell editor, `app-shell`'s metadata inspectors, the form
|
|
26
|
+
renderer — compiles unchanged, because the closed set was derived from them.
|
|
27
|
+
|
|
28
|
+
Why it mattered: an index signature is the objectstack#4075 mechanism — **a type
|
|
29
|
+
that claims to have every key can never be reported as missing one**. Three
|
|
30
|
+
things followed, and all three are now fixed:
|
|
31
|
+
|
|
32
|
+
- `props.required` and `props.error`, both declared by the spec's
|
|
33
|
+
`FieldWidgetPropsSchema` and both absent here, were legal reads typed `any`
|
|
34
|
+
and `undefined` at runtime forever. They are compile errors now, which is what
|
|
35
|
+
makes the `error` / `errorMessage` divergence (objectui#3222) decidable by the
|
|
36
|
+
compiler instead of by a symbol guard. This change deliberately does **not**
|
|
37
|
+
resolve that divergence — only make it visible.
|
|
38
|
+
- A misspelled prop (`readOnly` for `readonly`, `onchange` for `onChange`)
|
|
39
|
+
compiled and silently did nothing.
|
|
40
|
+
- Any structural / parity comparison against the type was useless _in
|
|
41
|
+
principle_, which is why objectui#3161's batch-7 symbol guard was the only
|
|
42
|
+
detector that could see the collision at all.
|
|
43
|
+
|
|
44
|
+
Also cleaned up inside the package: ~20 `(props as any).x` reads of keys the
|
|
45
|
+
type now declares (`compact`, `dataSource`, `disabled`, `name`, `id`,
|
|
46
|
+
`onCreateNew`, `onSelectRecord`, `contextRecord`, `dependentValues`) read
|
|
47
|
+
through the type instead — leaving them would have kept the "a typo compiles"
|
|
48
|
+
half of the defect alive at exactly the sites that matter. The three batch-7
|
|
49
|
+
tripwires that existed to go red on this change
|
|
50
|
+
(`_IndexSignatureStillThere` / `_RequiredSilentlyReadsAsAny` /
|
|
51
|
+
`_ErrorSilentlyReadsAsAny`) are replaced by their inverse, so re-widening the
|
|
52
|
+
type fails a test rather than passing one.
|
|
53
|
+
|
|
54
|
+
- 4a51e77: Stop declaring 14 symbols across ten packages under names `@objectstack/spec`
|
|
55
|
+
owns (objectui#3161, objectstack#4115 batch 7 — the long tail, one or two
|
|
56
|
+
entries per package). All ten packages leave the ledger, which drops from 17
|
|
57
|
+
collisions across 11 packages to 3 across 1.
|
|
58
|
+
|
|
59
|
+
**Renamed exports** — in every case the spec exports the same name for a
|
|
60
|
+
_different_ thing, so the old name was a mis-description rather than a dialect:
|
|
61
|
+
|
|
62
|
+
| package | was | now | what the spec's same-named export is |
|
|
63
|
+
| :------------------------- | :--------------------------------- | :--------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| `@object-ui/fields` | `FieldWidgetProps` | `FieldWidgetComponentProps` | the DECLARED field-widget plugin props contract (a zod object; `field.type` is the `FieldType` enum, `readonly`/`required` carry defaults) |
|
|
65
|
+
| `@object-ui/layout` | `PageHeaderProps` | `PageHeaderComponentProps` | the authored `page:header` node — a zod schema of `title`, `subtitle`, an icon NAME, `breadcrumb`, `actions: string[]` |
|
|
66
|
+
| `@object-ui/layout` | `Page` | `PageNodeRenderer` | the authored page metadata DOCUMENT (`name`, `label`, `type`, `regions`) |
|
|
67
|
+
| `@object-ui/plugin-detail` | `ObjectFieldLike` | `ObjectDefFieldLike` | the i18n duck type `translateObject` walks (`help`/`description`, plus `[key: string]: any`) |
|
|
68
|
+
| `@object-ui/plugin-grid` | `ColumnSummaryConfig` | `ColumnSummarySetting` | the OBJECT form of `ListColumn.summary` **only** — the local one was the whole union, shorthand included |
|
|
69
|
+
| `@object-ui/plugin-grid` | `isMultiValueField` | `hasMultiValueShape` | the spec's classifier, which requires a def with a `type`; the local one is called with `undefined` |
|
|
70
|
+
| `@object-ui/collaboration` | `RealtimeConfig` | `RealtimeSubscriptionConfig` | the app's realtime DECLARATION (`enabled`, `transport`, `subscriptions[]`) |
|
|
71
|
+
| `@object-ui/plugin-charts` | `ChartConfig` | `ChartContainerConfig` | the authored chart document (`type`, `xAxis`, `series`, `showLegend`, …) |
|
|
72
|
+
| `@object-ui/plugin-form` | `FormSection` / `FormSectionProps` | `FormSectionContainer` / `FormSectionContainerProps` | the authored form-section metadata (`name`, `pane`, `visibleWhen`, `fields`) |
|
|
73
|
+
| `@object-ui/providers` | `Theme` | `ThemePreference` | a whole theme DOCUMENT (`name`, `label`, `colors`, `typography`) |
|
|
74
|
+
| `@object-ui/runner` | `App` (default export) | `RunnerApp` | the authored application metadata type **and** the `App.create()` builder |
|
|
75
|
+
| `@object-ui/sdui-parser` | `ValidationResult` | `ManifestValidationResult` | plugin-manifest validation (`{ valid, errors?, warnings? }`), exported from both `kernel` and `contracts` |
|
|
76
|
+
|
|
77
|
+
`ManifestValidationResult` follows the `<what was validated>Validation<Error|Result>`
|
|
78
|
+
convention registered on objectstack#4115 (`@object-ui/core` took
|
|
79
|
+
`SchemaNodeValidationResult` in batch 4). `PageHeaderComponentProps` deliberately
|
|
80
|
+
reuses the name `@object-ui/app-shell` already chose for its own header props in
|
|
81
|
+
batch 3, so one concept does not acquire two dialect names one package apart.
|
|
82
|
+
|
|
83
|
+
**Now derived from the spec instead of hand-written:**
|
|
84
|
+
|
|
85
|
+
- `@object-ui/fields` — `isFileIdToken` is re-exported from
|
|
86
|
+
`@objectstack/spec/data`. The local copy was character-for-character identical
|
|
87
|
+
to the spec's function while its comment said it "mirrors" it, so every
|
|
88
|
+
behaviour test passed and only reference identity could tell the two apart.
|
|
89
|
+
The regex is a wire decision: widening it server-side while a copy here kept
|
|
90
|
+
the old bound would make every new id read as "not a reference", and the
|
|
91
|
+
widget would submit the legacy inline blob to a backend expecting a reference.
|
|
92
|
+
- `@object-ui/plugin-detail` — `FeedFilterMode` is re-exported from
|
|
93
|
+
`@objectstack/spec/data`, in a file that already imported the sibling
|
|
94
|
+
`FeedItemType` from the spec.
|
|
95
|
+
- `@object-ui/plugin-grid` — the eleven-member aggregation union is now the
|
|
96
|
+
spec's `ColumnSummary` enum, so the total `Record<ColumnSummaryType, string>`
|
|
97
|
+
label map turns a member the spec adds into a compile error instead of a
|
|
98
|
+
blank footer cell. `ColumnSummarySetting` is `NonNullable<ListColumn['summary']>`,
|
|
99
|
+
i.e. whatever forms the spec itself accepts. `hasMultiValueShape` delegates to
|
|
100
|
+
the spec's `isMultiValueField` rather than re-deriving it from
|
|
101
|
+
`MULTI_OPTION_TYPES` / `MULTI_CAPABLE_TYPES`.
|
|
102
|
+
- `@object-ui/providers` — `ThemePreference` is the spec's `ThemeMode` union
|
|
103
|
+
plus the one legacy `'system'` spelling this provider still honours for stored
|
|
104
|
+
preferences, read off the schema's own `_zod` carrier so the package takes no
|
|
105
|
+
zod dependency.
|
|
106
|
+
|
|
107
|
+
`@objectstack/spec` moves from `devDependencies` to `dependencies` in
|
|
108
|
+
`@object-ui/fields` (it re-exports a runtime function) and `@object-ui/providers`
|
|
109
|
+
(its public `.d.ts` now references the spec).
|
|
110
|
+
|
|
111
|
+
Scored `minor`, not `major`, per this repo's fixed-group rule — objectui's major
|
|
112
|
+
tracks `@objectstack`, so breaking changes of our own ship as minor with the
|
|
113
|
+
semantics spelled out above (see AGENTS.md §版本号策略). A `major` here would carry
|
|
114
|
+
all 39 packages of the fixed group to `18.0.0` and off objectstack's 17.x line.
|
|
115
|
+
|
|
116
|
+
### Patch Changes
|
|
117
|
+
|
|
118
|
+
- a8ad6c0: A required boolean must be savable in its UNCHECKED state — `false` and `0` are values.
|
|
119
|
+
|
|
120
|
+
Reported against an AI-built task tracker whose 任务 object has a required
|
|
121
|
+
`是否完成` boolean: the create form showed the switch OFF, answered "是否完成不能
|
|
122
|
+
为空", and saved instantly once the switch was turned ON. The app could only ever
|
|
123
|
+
create ALREADY-DONE tasks — the one state the control shows by default was the
|
|
124
|
+
one value it refused to save (cloud#972).
|
|
125
|
+
|
|
126
|
+
Two defects stacked, and either alone is enough to break it:
|
|
127
|
+
|
|
128
|
+
**The `required` verdict read truthiness, not presence.** `@objectstack/spec`
|
|
129
|
+
FieldSchema.required (ADR-0113) is "an insert must provide a NON-NULL value",
|
|
130
|
+
and objectql's record validator implements exactly that. react-hook-form's
|
|
131
|
+
built-in rule instead fails whenever `isBoolean(value) && !value` — its
|
|
132
|
+
accept-the-terms checkbox heritage — silently redefining every required boolean
|
|
133
|
+
as "must be TRUE", including a select whose chosen option value is `false`. It
|
|
134
|
+
also disagreed the other way, letting a whitespace-only string through for the
|
|
135
|
+
server to reject with a 400. The form renderer no longer hands RHF its own
|
|
136
|
+
`required`: the check is now a `validate` entry keyed `required` (so the error
|
|
137
|
+
still surfaces as `type: 'required'`, which the conditional-required cleanup
|
|
138
|
+
keys on) backed by a new shared `isMissingForRequired` in `@object-ui/core`, a
|
|
139
|
+
deliberate mirror of objectql `record-validator.isMissing` — `undefined`,
|
|
140
|
+
`null`, blank-after-trim string, empty array. Deleting the inherited rule also
|
|
141
|
+
stops a `required` that rode in on `validation` from outliving a `requiredWhen`
|
|
142
|
+
that resolved to FALSE.
|
|
143
|
+
|
|
144
|
+
**A boolean field held `undefined` while displaying "off".** A two-state control
|
|
145
|
+
has no third state, but a field with no entry in `defaultValues` rendered an OFF
|
|
146
|
+
switch backed by nothing: the create payload omitted the column (it lands null,
|
|
147
|
+
which reads as unchecked but isn't) and the presence check above would still
|
|
148
|
+
refuse it. The form renderer now folds `false` into `defaultValues` for every
|
|
149
|
+
boolean-widget field the caller left unset — in `defaultValues` itself, not
|
|
150
|
+
per-Controller, because that object is also the dirty-check baseline and what
|
|
151
|
+
the defaults-reset window replays. Every surface gets it, including the
|
|
152
|
+
modal/drawer create dialogs that start from a bare `{}`. An authored default
|
|
153
|
+
(or a loaded record, `null` included) still wins.
|
|
154
|
+
|
|
155
|
+
`WizardForm`'s cross-step gate had its own copy of the empty-value predicate; it
|
|
156
|
+
now imports the shared one so it cannot drift from the per-field verdict. And
|
|
157
|
+
the field-demo renderer read `schema.defaultValue || schema.value`, throwing
|
|
158
|
+
away an authored default of `false` / `0` / `''` — same falsy-as-empty class,
|
|
159
|
+
now `??`.
|
|
160
|
+
|
|
161
|
+
Verified end to end on a local stack against the exact metadata shape
|
|
162
|
+
`apply_blueprint` materializes (`{ type: 'boolean', required: true }`, no
|
|
163
|
+
default): a 是否完成 = 否 task with 工时 = 0 now creates and persists as
|
|
164
|
+
`{ hours: 0, is_done: false }`, turning the switch on still stores `true`, and a
|
|
165
|
+
blank required text is still refused.
|
|
166
|
+
|
|
167
|
+
- Updated dependencies [4ae0ac4]
|
|
168
|
+
- Updated dependencies [696e3c1]
|
|
169
|
+
- Updated dependencies [bca45cc]
|
|
170
|
+
- Updated dependencies [a889e31]
|
|
171
|
+
- Updated dependencies [09d30a4]
|
|
172
|
+
- Updated dependencies [4bf612c]
|
|
173
|
+
- Updated dependencies [335041c]
|
|
174
|
+
- Updated dependencies [b414983]
|
|
175
|
+
- Updated dependencies [256f8cc]
|
|
176
|
+
- Updated dependencies [d9668a7]
|
|
177
|
+
- Updated dependencies [4b470b9]
|
|
178
|
+
- Updated dependencies [cb82705]
|
|
179
|
+
- Updated dependencies [f572849]
|
|
180
|
+
- Updated dependencies [4a51e77]
|
|
181
|
+
- Updated dependencies [f6e8d78]
|
|
182
|
+
- Updated dependencies [ea96284]
|
|
183
|
+
- Updated dependencies [d3584c6]
|
|
184
|
+
- Updated dependencies [a8ad6c0]
|
|
185
|
+
- Updated dependencies [444457c]
|
|
186
|
+
- Updated dependencies [850033c]
|
|
187
|
+
- Updated dependencies [022e4c3]
|
|
188
|
+
- Updated dependencies [009e25d]
|
|
189
|
+
- Updated dependencies [726b89c]
|
|
190
|
+
- @object-ui/types@17.2.0
|
|
191
|
+
- @object-ui/components@17.2.0
|
|
192
|
+
- @object-ui/core@17.2.0
|
|
193
|
+
- @object-ui/react@17.2.0
|
|
194
|
+
- @object-ui/i18n@17.2.0
|
|
195
|
+
- @object-ui/providers@17.2.0
|
|
196
|
+
|
|
3
197
|
## 17.1.0
|
|
4
198
|
|
|
5
199
|
### Minor Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { FieldWidgetComponentProps } from './widgets/types';
|
|
3
3
|
/**
|
|
4
4
|
* Form field types that are deliberately NOT given an inline editor — every
|
|
5
5
|
* other form widget type must be in {@link EDIT_WIDGETS}. This pairing is
|
|
@@ -25,4 +25,4 @@ export declare function isInlineExcludedFieldType(type: string | undefined): boo
|
|
|
25
25
|
* `null` for types without a registered widget so the caller can fall back to
|
|
26
26
|
* a plain editor.
|
|
27
27
|
*/
|
|
28
|
-
export declare function FieldEditWidget({ field, value, onChange, readonly, }:
|
|
28
|
+
export declare function FieldEditWidget({ field, value, onChange, readonly, }: FieldWidgetComponentProps<any>): React.ReactElement | null;
|