@mittwald/flow-react-components 1.6.0-next.21 → 1.6.0-next.24
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/AGENTS.md +11 -88
- package/dist/assets/component-index.json +1 -1
- package/dist/assets/doc-properties.json +1 -1
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.mjs +41 -12
- package/dist/js/packages/components/src/components/CodeEditor/CodeEditor.mjs.map +1 -1
- package/dist/js/packages/components/src/components/CodeEditor/hooks/useCodeEditorExtensions.mjs +29 -16
- package/dist/js/packages/components/src/components/CodeEditor/hooks/useCodeEditorExtensions.mjs.map +1 -1
- package/dist/js/packages/components/src/components/DeprecationWarningProvider/DeprecationWarningProvider.mjs +40 -8
- package/dist/js/packages/components/src/components/DeprecationWarningProvider/DeprecationWarningProvider.mjs.map +1 -1
- package/dist/js/packages/components/src/components/Markdown/Markdown.mjs +9 -5
- package/dist/js/packages/components/src/components/Markdown/Markdown.mjs.map +1 -1
- package/dist/js/packages/components/src/components/TranslationProvider/useLocalizedStringFormatter.mjs +15 -2
- package/dist/js/packages/components/src/components/TranslationProvider/useLocalizedStringFormatter.mjs.map +1 -1
- package/package.json +10 -10
package/AGENTS.md
CHANGED
|
@@ -426,75 +426,15 @@ Four traps cost time in every new browser test:
|
|
|
426
426
|
technology lands on (the input or the group), spread after `rest`: its
|
|
427
427
|
`aria-describedby` references the error only while one is rendered and already
|
|
428
428
|
contains the consumer's own ids. See
|
|
429
|
-
[
|
|
429
|
+
[FORM_FIELDS.md](https://github.com/mittwald/flow/blob/main/packages/components/FORM_FIELDS.md).
|
|
430
430
|
|
|
431
431
|
## Building a form field
|
|
432
432
|
|
|
433
433
|
A form field is any component a user enters a value with — anything that calls
|
|
434
|
-
`useFieldComponent`.
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
| Aspect | Requirement |
|
|
439
|
-
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
440
|
-
| `isDisabled` | Control is not operable (`disabled` or `aria-disabled`), disabled styling via the `formControl` mixin, `Label` disabled. Every inner button too. |
|
|
441
|
-
| `isReadOnly` | Value cannot change, control still focusable and submitted. Native `readonly` / react-aria's `isReadOnly` where it exists, otherwise `aria-readonly` — never by disabling the control. Inner buttons that change the value off. |
|
|
442
|
-
| `isRequired` | `required` or `aria-required` on the control; `Label` drops its "optional" marker (`useFieldComponent` does that). |
|
|
443
|
-
| `isInvalid` | `aria-invalid` on the control, invalid styling, `FieldError` rendered and linked. |
|
|
444
|
-
| `validationBehavior` | `"native"` blocks form submission on a constraint violation, `"aria"` does not. react-hook-form's `Field` passes `"aria"`. |
|
|
445
|
-
| `Label` / `FieldDescription` | Children slots via `useFieldComponent`; `Label` names the control. `controlProps` (with `aria-describedby`) land on the **focusable control** (or the group of a grouped control), not on a wrapper `div`. |
|
|
446
|
-
| `name` / `form` | The value is in the `FormData` of the surrounding (or `form`-referenced) form. A custom control renders a hidden input. |
|
|
447
|
-
| `defaultValue` / `value` | Both work; `onChange` reports user changes with the field's own value type (a `number` field reports a `number`). |
|
|
448
|
-
| `ref` | Points at the focusable control — react-hook-form focuses it on a validation error. |
|
|
449
|
-
| `autoFocus`, `onFocus`/`onBlur` | Reach the focusable control. react-hook-form marks a field touched via `onBlur`. |
|
|
450
|
-
|
|
451
|
-
An exception needs a reason that holds for the field's nature (a `Slider` always
|
|
452
|
-
has a value, so it has no required state) — not "not implemented yet".
|
|
453
|
-
|
|
454
|
-
Checklist beyond the component itself:
|
|
455
|
-
|
|
456
|
-
- **Contract test.** Call `testFormFieldContract`
|
|
457
|
-
(`src/tests/formFieldContract/`) in the field's `*.browser.test.tsx`. The
|
|
458
|
-
adapter renders the field, names its control, two values (the first one
|
|
459
|
-
submits an entry, the two submit different entries), their `FormData` entries
|
|
460
|
-
and a user interaction that changes the value. The interaction passes `force`
|
|
461
|
-
on, so the test can also try it on a disabled or read-only field.
|
|
462
|
-
`getValueButtons` narrows the inner buttons a read-only field turns off; it
|
|
463
|
-
defaults to all. Justified exceptions go in `exceptions` with their reason. An
|
|
464
|
-
excepted aspect must fail on one of its own expectations — once it passes, or
|
|
465
|
-
fails on a lookup or a timeout instead, the run fails:
|
|
466
|
-
|
|
467
|
-
```tsx
|
|
468
|
-
testFormFieldContract("TextField", {
|
|
469
|
-
render: (props) => <TextField {...props} />,
|
|
470
|
-
getControl: (screen) => screen.getByRole("textbox"),
|
|
471
|
-
values: ["foo", "bar"],
|
|
472
|
-
toFormValue: (value) => value,
|
|
473
|
-
changeValue: async (screen, { force }) => {
|
|
474
|
-
await userEvent.fill(screen.getByRole("textbox"), "bar", { force });
|
|
475
|
-
},
|
|
476
|
-
});
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
It checks behavior and ARIA, not looks — the disabled, read-only and invalid
|
|
480
|
-
states also get scenarios in the field's visual test
|
|
481
|
-
(`packages/remote-react-components/src/tests/visual`).
|
|
482
|
-
|
|
483
|
-
- **react-hook-form.** Register the field in the props context of
|
|
484
|
-
`src/integrations/react-hook-form/components/Field/Field.tsx`. `Field` passes
|
|
485
|
-
`name`, `value` and `defaultValue` together, `onChange`, `onBlur`, `ref`,
|
|
486
|
-
`form`, `isRequired`, `isReadOnly`, `isInvalid` and `validationBehavior` —
|
|
487
|
-
spread the rest props through instead of destructuring a fixed list, or they
|
|
488
|
-
are dropped silently. A field whose value prop is not `value` gets it mapped
|
|
489
|
-
there (`selectedKey` for `ComboBox`, `isSelected` for `Checkbox`). `Field`
|
|
490
|
-
does not pass `isDisabled` yet (#3368).
|
|
491
|
-
- **Remote.** A field that mirrors its value with `useControlledHostValueProps`
|
|
492
|
-
passes the type's empty value (see the controlled-from-the-first-render
|
|
493
|
-
convention below). A text input among them also needs its `flr-*` tag in
|
|
494
|
-
`controlledComponentNames`
|
|
495
|
-
(`packages/remote-react-components/src/lib/createRemoteComponent.ts`), or it
|
|
496
|
-
drops characters under fast typing
|
|
497
|
-
([docs/remote-ui.md](https://github.com/mittwald/flow/blob/main/docs/remote-ui.md)).
|
|
434
|
+
`useFieldComponent`. Building or changing one → read
|
|
435
|
+
[FORM_FIELDS.md](https://github.com/mittwald/flow/blob/main/packages/components/FORM_FIELDS.md):
|
|
436
|
+
the contract it supports end to end, `testFormFieldContract`, and the
|
|
437
|
+
react-hook-form and remote wiring.
|
|
498
438
|
|
|
499
439
|
## Every remote binding reads this package
|
|
500
440
|
|
|
@@ -535,29 +475,12 @@ to make a rule stick.
|
|
|
535
475
|
|
|
536
476
|
## Public API surfaces
|
|
537
477
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
| `./nextjs`, `./react-hook-form`, `./mittwald-password-tools-js` | Integrations (`src/integrations/`): wrappers around third-party dependencies that not every consumer should pay for — they get their own export entry instead of entering the core surface. |
|
|
545
|
-
| `./all.css`, `./all-layered.css` | Bundled stylesheet, plain and `@layer`-wrapped. |
|
|
546
|
-
| `./component-index` | Generated consumer-facing index: every public component with its status and its own props (`dev/component-index/`). What the docs site's prop tables read, and the one prop dataset a consumer's agent should use. |
|
|
547
|
-
| `./doc-properties` | `react-docgen-typescript` output in its raw `ComponentDoc[]` shape, filtered to the props a consumer can act on. Prefer `./component-index`. The unfiltered dump the generators above read is `.cache/doc-properties.json`, which is not published. |
|
|
548
|
-
|
|
549
|
-
**Adding any new export entry?** Add the subpath to `keptSubpaths` in
|
|
550
|
-
`packages/codemods/src/migrations/imports-to-package-root/transform.ts`. That
|
|
551
|
-
codemod collapses subpath imports onto the package root with a catch-all `else`,
|
|
552
|
-
so a subpath that is not listed gets flattened onto a root that does not export
|
|
553
|
-
its names. The guard beside the transform fails the codemods unit tests when you
|
|
554
|
-
forget.
|
|
555
|
-
|
|
556
|
-
**Adding a new integration export entry?** Also register it in the component
|
|
557
|
-
status registry so it is covered: add the entry to `STATUS_EXPORT_ENTRIES`
|
|
558
|
-
(`dev/status-registry/exportEntries.ts`) — the `FlowExportEntry` union and the
|
|
559
|
-
registry regenerate from it. A generation-time guard fails if an entry resolves
|
|
560
|
-
to zero components.
|
|
478
|
+
Adding or changing an export entry (`.`, `./internal`, `./flr-universal`, an
|
|
479
|
+
integration, a stylesheet or data entry) → read
|
|
480
|
+
[EXPORTS.md](https://github.com/mittwald/flow/blob/main/packages/components/EXPORTS.md):
|
|
481
|
+
what each entry holds and the registries a new one has to join.
|
|
482
|
+
|
|
483
|
+
## Prop JSDoc
|
|
561
484
|
|
|
562
485
|
Prop JSDoc feeds the generated `doc-properties.json` and the docs site: write
|
|
563
486
|
doc comments on public props, use `@default` for defaults and `@internal` for
|