Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .changeset/plugin-form-readme-truth-5011.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
'@object-ui/plugin-form': patch
---

`packages/plugin-form/README.md`: three assertions about this package's export
surface were false, and the export names are now taken from the built
`dist/index.d.ts` (TS compiler API `checker.getExportsOfModule`) with every
TypeScript block compiled against those same declarations under `strict`.

- **`formComponents`** — fiction, and not a name that could be corrected: there
is no aggregate component map on the surface at all, so the "Manual
Registration" section described a mechanism that does not exist. Copying it got
`undefined` and threw on `Object.entries(undefined)`. It is replaced by what
actually happens: registration is a side effect of importing the entry, whose
six `ComponentRegistry.register(...)` calls claim
`plugin-form:object-form`, `view:form`, `plugin-form:embeddable-form`,
`plugin-form:form-analytics`, `plugin-form:object-master-detail-form` and
`record:line_items` — the two `skipFallback: true` calls being why bare `form`
and bare `line_items` are *not* taken over. The section also lists the real
export surface, and shows the thing the old snippet was reaching for: putting
an exported component on a schema type of your own, with the caveat that the
package's own registered renderers are internal wrappers that first resolve
`dataSource` from `SchemaRendererContext`.
- **`FormSchema` / `FormField`** — real types imported from the wrong package.
Both are protocol types declared in `@object-ui/types` (`src/form.ts`); this
package imports them and does not re-export them, so the documented import was
a `TS2305` pair. Only the import path changed — no re-export was added to make
the old path true, since widening a package's public surface is a contract
change and not a documentation fix. The section now also points at the form
types that *are* on this entry (`TabbedFormSchema`, `WizardFormSchema`,
`ModalFormSchema`, …).
- **`isRuntimeDefault` "(re-exported here)"** — the create-defaults section
claimed the predicate is re-exported by this package. It is re-exported by
`src/schemaDefaults.ts` for internal use only, never from the entry, and the
package publishes just the `"."` export — so `import { isRuntimeDefault } from
'@object-ui/plugin-form'` is another `TS2305`. The parenthetical now says where
the re-export actually lives.

No code, types or runtime behaviour change — the diff is one README plus this
changeset. It declares a patch because `README.md` is in the package's published
`files`, so the correction reaches npm with the next release.
119 changes: 110 additions & 9 deletions packages/plugin-form/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,18 +35,112 @@ const schema = {
};
```

### Manual Registration
### What the side-effect import registers

There is no component map to iterate: registration is a side effect of importing
the package entry, which makes six `ComponentRegistry.register(...)` calls. These
are the schema types those calls claim, read off the calls themselves in
`src/index.tsx`:

| Namespaced type | Bare-name fallback | Component behind it |
|---|---|---|
| `plugin-form:object-form` | `object-form` | `ObjectForm` — metadata-driven form over one record |
| `view:form` | none | the same renderer under the view protocol |
| `plugin-form:embeddable-form` | `embeddable-form` | `EmbeddableForm` — standalone public form |
| `plugin-form:form-analytics` | `form-analytics` | `FormAnalytics` — submission dashboard |
| `plugin-form:object-master-detail-form` | `object-master-detail-form` | `MasterDetailForm` — parent + child line items in one submit |
| `record:line_items` | none | `LineItemsPanel` — child grid bound to the record on the page |

`ComponentRegistry.register` also registers a namespaced type under its bare name
for backwards compatibility, unless the call passes `skipFallback: true`
(`@object-ui/core`, `src/registry/Registry.ts`). Two calls here do: bare `form`
stays the basic `@object-ui/components` form, and bare `line_items` is left to
whoever else claims it.

### Public exports

The package entry exports these — components, their prop/schema types, and the
layout helpers. There is no aggregate map among them:

```typescript
import {
ObjectForm,
TabbedForm,
WizardForm,
SplitForm,
DrawerForm,
ModalForm,
EmbeddableForm,
MasterDetailForm,
LineItemsPanel,
FormAnalytics,
FormSectionContainer,
applyAutoLayout,
applyAutoColSpan,
inferColumns,
inferModalSize,
isWideFieldType,
isAutoGeneratedFieldType,
containerGridColsFor,
filterCreateModeFields,
filterSystemFields,
filterAutoGeneratedFields,
deriveDetail,
deriveColumns,
deriveFormFields,
findRelationshipField,
resolveInlineMode,
} from '@object-ui/plugin-form';

import type {
ObjectFormComponentProps,
ObjectFormProps, // deprecated alias of ObjectFormComponentProps
FormSectionContainerProps,
TabbedFormProps,
TabbedFormSchema,
FormSectionConfig,
WizardFormProps,
WizardFormSchema,
SplitFormProps,
SplitFormSchema,
DrawerFormProps,
DrawerFormSchema,
ModalFormProps,
ModalFormSchema,
EmbeddableFormProps,
EmbeddableFormConfig,
EmbeddableFormTexts,
FormAnalyticsProps,
FormSubmissionMetric,
MasterDetailFormProps,
MasterDetailFormSchema,
MasterDetailDetailConfig,
LineItemsPanelSchema,
DerivedDetail,
InlineMode,
} from '@object-ui/plugin-form';
```

### Registering a component under your own key

To put one of these components on a schema type of your own, register the
exported component:

```typescript
import { formComponents } from '@object-ui/plugin-form';
import { ComponentRegistry } from '@object-ui/core';
import { ObjectForm } from '@object-ui/plugin-form';

// Register form components
Object.entries(formComponents).forEach(([type, component]) => {
ComponentRegistry.register(type, component);
});
ComponentRegistry.register('my-form', ObjectForm, { namespace: 'my-app' });
```

The renderers this package registers for itself are internal wrappers rather
than these exported components. `SchemaRenderer` hands a registered component its
`schema` (plus the schema's own props), but never a `dataSource` — that travels
on `SchemaRendererContext` — so each wrapper reads it off the context first.
`ObjectForm` takes `dataSource` as a prop, optional because inline `customFields`
need no adapter, so a custom-key registration either supplies one or wraps the
component the same way.

## Schema API

### Form
Expand DownExpand Up@@ -154,8 +248,9 @@ required to provide the value. Showing what the server *will* supply, as a
non-authoritative preview, is a separate follow-up.

Every consumer reads one predicate, `isRuntimeDefault` in `@object-ui/core`
(re-exported here) — which is what keeps a form from seeding a field it also
refuses to submit. The static half is decided at the producer, in
(re-exported for this package's own use by `src/schemaDefaults.ts`, not from the
package entry listed above) — which is what keeps a form from seeding a field it
also refuses to submit. The static half is decided at the producer, in
`isRequiredInForm`; the conditional half cannot be, because `requiredWhen` is
resolved downstream against the live record, so it is suppressed inside the one
evaluator that resolves it — `resolveFieldRuleState`, reading
Expand DownExpand Up@@ -404,8 +499,14 @@ const schema = {

## TypeScript Support

`FormSchema` and `FormField` are protocol types, so they live in
`@object-ui/types` alongside the rest of the JSON contract. This package imports
them and does not re-export them — the form types on its own entry are the
per-container ones (`TabbedFormSchema`, `WizardFormSchema`, `ModalFormSchema`, …)
listed under [Public exports](#public-exports).

```typescript
import type { FormSchema, FormField } from '@object-ui/plugin-form';
import type { FormSchema, FormField } from '@object-ui/types';

const emailField: FormField = {
name: 'email',
Expand Down