@mittwald/flow-react-components 0.2.0-alpha.895 → 0.2.0-alpha.897
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 +226 -0
- package/CHANGELOG.md +10 -0
- package/CLAUDE.md +1 -0
- package/dist/assets/doc-properties.json +14848 -14848
- package/dist/css/all.css +1 -1
- package/dist/js/@mittwald/password-tools-js.mjs +2 -2
- package/dist/js/_virtual/_.locale.json@95341064edeb0e38b66d786dbd62955c.mjs +2 -2
- package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs +31 -18
- package/dist/js/packages/components/src/components/PasswordCreationField/PasswordCreationField.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.mjs +26 -37
- package/dist/js/packages/components/src/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/generateValidationTranslation.mjs +2 -2
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/getStateFromLatestPolicyValidationResult.mjs +5 -5
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/getStateFromLatestPolicyValidationResult.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/usePolicyValidationResult.mjs +25 -42
- package/dist/js/packages/components/src/components/PasswordCreationField/lib/usePolicyValidationResult.mjs.map +1 -1
- package/dist/js/packages/components/src/components/PasswordCreationField/worker/generatePassword.mjs +2 -2
- package/dist/js/packages/components/src/integrations/@mittwald/password-tools-js/defaultPasswordCreationPolicy.mjs +3 -0
- package/dist/js/packages/components/src/integrations/@mittwald/password-tools-js/defaultPasswordCreationPolicy.mjs.map +1 -1
- package/dist/js/packages/components/src/integrations/@mittwald/password-tools-js/usePasswordCreationFieldValidation.mjs +3 -3
- package/dist/js/packages/components/src/integrations/@mittwald/password-tools-js/usePasswordCreationFieldValidation.mjs.map +1 -1
- package/dist/js/packages/design-tokens/dist/json/all-dark.json.mjs +1 -1
- package/dist/js/packages/design-tokens/dist/json/all-light.json.mjs +1 -1
- package/dist/types/components/PasswordCreationField/PasswordCreationField.d.ts.map +1 -1
- package/dist/types/components/PasswordCreationField/components/ComplexityIndicator/ComplexityIndicator.d.ts.map +1 -1
- package/dist/types/components/PasswordCreationField/lib/usePolicyValidationResult.d.ts.map +1 -1
- package/dist/types/components/PasswordCreationField/stories/Default.stories.d.ts +1 -1
- package/dist/types/components/PasswordCreationField/stories/Default.stories.d.ts.map +1 -1
- package/dist/types/integrations/@mittwald/password-tools-js/defaultPasswordCreationPolicy.d.ts +1 -1
- package/dist/types/integrations/@mittwald/password-tools-js/defaultPasswordCreationPolicy.d.ts.map +1 -1
- package/dist/types/integrations/@mittwald/password-tools-js/index.d.ts +2 -2
- package/dist/types/integrations/@mittwald/password-tools-js/index.d.ts.map +1 -1
- package/dist/types/integrations/@mittwald/password-tools-js/usePasswordCreationFieldValidation.d.ts +1 -1
- package/dist/types/integrations/@mittwald/password-tools-js/usePasswordCreationFieldValidation.d.ts.map +1 -1
- package/dist/types/lib/theming/hooks/useDesignTokens.d.ts +48 -0
- package/dist/types/lib/theming/hooks/useDesignTokens.d.ts.map +1 -1
- package/package.json +8 -8
package/AGENTS.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# @mittwald/flow-react-components — Agent Guide
|
|
2
|
+
|
|
3
|
+
Component patterns for the core package. Read the
|
|
4
|
+
[root AGENTS.md](../../AGENTS.md) first for repo-wide rules (generated code,
|
|
5
|
+
Definition of Done, workflow).
|
|
6
|
+
|
|
7
|
+
## Component anatomy
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/components/Button/
|
|
11
|
+
├── Button.tsx # implementation (hand-written)
|
|
12
|
+
├── Button.module.scss # styles (hand-written)
|
|
13
|
+
├── index.ts # barrel (hand-written)
|
|
14
|
+
├── view.ts # GENERATED — remote view declaration (@flr-generate only)
|
|
15
|
+
├── stories/
|
|
16
|
+
│ ├── Default.stories.tsx # Storybook stories (expected for every component)
|
|
17
|
+
│ └── lib.tsx # shared story fixtures/helpers (optional)
|
|
18
|
+
├── components/ # subcomponents, same anatomy (optional)
|
|
19
|
+
├── locales/ # de-DE.locale.json + en-US.locale.json (when UI text)
|
|
20
|
+
└── *.browser.test.tsx # behavior tests (when behavior is non-trivial)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The barrel exports the view first (only on `@flr-generate` components), then
|
|
24
|
+
the component:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
export * from "./view";
|
|
28
|
+
export { type ButtonProps, Button } from "./Button";
|
|
29
|
+
export { default } from "./Button";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## The flowComponent factory
|
|
33
|
+
|
|
34
|
+
Nearly every component registers through
|
|
35
|
+
`flowComponent(name, Implementation, options?)`
|
|
36
|
+
(`src/lib/componentFactory/flowComponent.tsx`). It wires up the props context,
|
|
37
|
+
tunnel support, `wrapWith`, and remote isolation — do not rebuild any of that
|
|
38
|
+
manually.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import type { PropsWithChildren } from "react";
|
|
42
|
+
import type Aria from "react-aria-components";
|
|
43
|
+
import {
|
|
44
|
+
flowComponent,
|
|
45
|
+
type FlowComponentProps,
|
|
46
|
+
} from "@/lib/componentFactory/flowComponent";
|
|
47
|
+
|
|
48
|
+
export interface ButtonProps
|
|
49
|
+
extends PropsWithChildren<Omit<Aria.ButtonProps, "children">>,
|
|
50
|
+
FlowComponentProps<HTMLButtonElement> {
|
|
51
|
+
/** The color of the button. @default "primary" */
|
|
52
|
+
color?: "primary" | "accent" | "secondary" | "danger";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** @flr-generate all */
|
|
56
|
+
export const Button = flowComponent("Button", (props) => {
|
|
57
|
+
const { color = "primary", className, ref, ...rest } = props;
|
|
58
|
+
// …
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export default Button;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Conventions:
|
|
65
|
+
|
|
66
|
+
- Props type is exported as `<Name>Props`; it extends the wrapped React Aria
|
|
67
|
+
props plus `FlowComponentProps<RefElement>`.
|
|
68
|
+
- **Ref as prop** (React 19) — no `forwardRef`.
|
|
69
|
+
- `options.type`: `"ui"` (default — gets props-context isolation),
|
|
70
|
+
`"layout"`, or `"provider"`. The factory applies `ClearPropsContext`
|
|
71
|
+
isolation for UI components itself — don't add extra clearing casually.
|
|
72
|
+
- The registered name must match the component/directory name, and the props
|
|
73
|
+
type must be registered in `src/components/propTypes/index.ts`
|
|
74
|
+
(`FlowComponentPropsTypes`) — `flowComponent` names are typed as `keyof`
|
|
75
|
+
of that hand-maintained registry, so a missing entry fails the typecheck.
|
|
76
|
+
- Most components wrap `react-aria-components` primitives; expose ARIA props
|
|
77
|
+
directly only where React Aria lacks the behavior.
|
|
78
|
+
|
|
79
|
+
## PropsContext — contextual composability
|
|
80
|
+
|
|
81
|
+
`PropsContext` makes components adapt **automatically** when composed inside
|
|
82
|
+
other components: they receive default prop values and, mainly, CSS classes
|
|
83
|
+
from their surroundings. This is the backbone of Flow's composability.
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// IllustratedMessage.tsx — every <Icon> inside renders large:
|
|
87
|
+
const propsContext: PropsContext = {
|
|
88
|
+
Icon: { className: styles.icon, size: "l" },
|
|
89
|
+
Heading: { className: styles.heading, color },
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div {...rest}>
|
|
94
|
+
<PropsContextProvider props={propsContext}>{children}</PropsContextProvider>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- Contexts **nest** (a context can configure props contexts of nested
|
|
100
|
+
components) and support **dynamic props**:
|
|
101
|
+
`dynamic((localProps) => value)` derives values from the consumer's props.
|
|
102
|
+
- Local props always win over context props.
|
|
103
|
+
- Although exported, `PropsContext` is **primarily an internal API** — prefer
|
|
104
|
+
it for intra-Flow composition, not as a consumer-facing feature.
|
|
105
|
+
- **Only put remote-capable components into a `PropsContext`** — non-remote
|
|
106
|
+
components break remote rendering.
|
|
107
|
+
- When parent context must not leak into a component's children, use targeted
|
|
108
|
+
clearing, e.g. `wrapWith: <ClearPropsContext />` (see `Modal.tsx`).
|
|
109
|
+
|
|
110
|
+
## Views — remote-transparent composition
|
|
111
|
+
|
|
112
|
+
Components tagged `/** @flr-generate all */` get a generated view
|
|
113
|
+
(`view.ts` + `src/views/<Name>View.tsx`). **Inside `flr-universal` components,
|
|
114
|
+
compose other Flow components through their views** (`@/views/*`) — a view
|
|
115
|
+
automatically switches to the remote counterpart in a remote context:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
import ButtonView from "@/views/ButtonView"; // ✓ works local and remote
|
|
119
|
+
import { Button } from "@/components/Button"; // ✗ host-only in remote context
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Remote generation details:
|
|
123
|
+
|
|
124
|
+
- `@flr-generate all` on the component const marks it for generation.
|
|
125
|
+
- `@flr-ignore-props` excludes props that must not cross the remote boundary —
|
|
126
|
+
either because they cannot be serialized, or because they could do **too
|
|
127
|
+
much on the host side**. A global ignore list lives in
|
|
128
|
+
`dev/remote-components-generator/config.ts`: `style` and
|
|
129
|
+
`dangerouslySetInnerHTML` are always ignored for safety; `ref`,
|
|
130
|
+
`controller`, `tunnel`, `key`, `children`, `wrapWith` because they don't
|
|
131
|
+
serialize. Use the per-component tag for additional cases (see
|
|
132
|
+
`TunnelEntry.tsx`).
|
|
133
|
+
- After changing props of an `@flr-generate` component:
|
|
134
|
+
`pnpm nx build:remote-components components` and **commit** the results
|
|
135
|
+
(view.ts, `src/views/*`, `remote-*/src/auto-generated/**`).
|
|
136
|
+
- Props of these components are consumed by mStudio extension developers —
|
|
137
|
+
no breaking changes; deprecate instead:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
const warnDeprecation = useWarnDeprecation();
|
|
141
|
+
if ("action" in props) {
|
|
142
|
+
warnDeprecation("The 'action' prop is deprecated. Use 'onAction' instead.");
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Styling
|
|
147
|
+
|
|
148
|
+
- One `<Name>.module.scss` per component. Scoped class names are generated
|
|
149
|
+
from the component's **path** (`dev/vite/cssModuleClassNameGenerator.ts`) —
|
|
150
|
+
deliberately semantic CSS that could be used standalone. Never bypass CSS
|
|
151
|
+
modules for component roots (the global reset targets `flow--` classes).
|
|
152
|
+
- Root class is the lower-camel component name (`.button`); modifier classes
|
|
153
|
+
match prop values (`.size-s`, `.primary`).
|
|
154
|
+
- Class composition with `clsx`, consumer `className` appended last:
|
|
155
|
+
`clsx(styles.button, styles[size], styles[color], className)`.
|
|
156
|
+
- **Use design-token CSS variables** — global (`--font-size-text--m`) or
|
|
157
|
+
component-namespaced (`--button--corner-radius`). No hard-coded colors,
|
|
158
|
+
sizes, radii.
|
|
159
|
+
- Shared mixins via `@use "@/styles/mixins/…"`: `focus` (focus ring),
|
|
160
|
+
`formControl` (border/color/interaction states of form fields), `ellipsis`.
|
|
161
|
+
Group repeated variants in local mixins.
|
|
162
|
+
- Structure sections with comments: `/* Elements */`, `/* States */`,
|
|
163
|
+
`/* Size */`, `/* Variants */`.
|
|
164
|
+
|
|
165
|
+
## Testing — the actual bar
|
|
166
|
+
|
|
167
|
+
| Artifact | When |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| `stories/Default.stories.tsx` | **Always.** Realistic args, controls, meaningful variants. Story title category matches the docs (`Actions/…`, `Form Controls/…`, `Overlays/…`, `Status/…`). |
|
|
170
|
+
| `*.browser.test.tsx` (vitest browser mode) | Component has real **behavior**: interaction, controlled state, async flows, form integration, controllers. Render with `vitest-browser-react`, interact via `userEvent`, query by role. |
|
|
171
|
+
| `*.test.ts(x)` (unit) | Pure logic in `src/lib/` or component utility functions. |
|
|
172
|
+
| `*.test-types.tsx` | Generic/typed public APIs — `expectTypeOf` plus `@ts-expect-error` negative assertions. |
|
|
173
|
+
|
|
174
|
+
Run: `pnpm nx test:unit components`,
|
|
175
|
+
`pnpm nx test:browser components --browser.name=webkit`. Browser tests need
|
|
176
|
+
`pnpm test:browser:prepare` once.
|
|
177
|
+
|
|
178
|
+
## i18n & a11y
|
|
179
|
+
|
|
180
|
+
- Component-internal UI text lives in colocated `locales/de-DE.locale.json`
|
|
181
|
+
**and** `locales/en-US.locale.json` — always add both languages. The
|
|
182
|
+
strings support ICU MessageFormat (variables, `plural`, `select` — see
|
|
183
|
+
`PasswordCreationField/locales/` for real usage). Import the files with a
|
|
184
|
+
glob import and consume them via the Flow hook:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
import locales from "./locales/*.locale.json";
|
|
188
|
+
import { useLocalizedStringFormatter } from "@/components/TranslationProvider";
|
|
189
|
+
|
|
190
|
+
const stringFormatter = useLocalizedStringFormatter(locales, "Modal");
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
- Introducing a **new language** is welcome — but translate everything
|
|
194
|
+
initially: every `locales/` directory in the package gets the new file.
|
|
195
|
+
- Icon-only buttons get a localized `aria-label`; decorative icons are
|
|
196
|
+
`aria-hidden` (the `Icon` component handles this when no label is given).
|
|
197
|
+
- Form fields wire label/description/error via `useFieldComponent`
|
|
198
|
+
(generates ids, sets `aria-describedby`).
|
|
199
|
+
|
|
200
|
+
## Public API surfaces
|
|
201
|
+
|
|
202
|
+
| Export | Contents |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| `.` (default) | Everything listed **manually** in `src/components/public.ts` — new public components must be added there. |
|
|
205
|
+
| `./internal` | Advanced internals (`flowComponent`, prop helper types, …). |
|
|
206
|
+
| `./flr-universal` | Curated subset that works local *and* remote. Adding to `public.ts` does **not** add here. |
|
|
207
|
+
| `./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. |
|
|
208
|
+
| `./all.css` | Bundled stylesheet. |
|
|
209
|
+
| `./doc-properties` | Generated prop metadata for the docs site. |
|
|
210
|
+
|
|
211
|
+
Prop JSDoc feeds the generated `doc-properties.json` and the docs site: write
|
|
212
|
+
doc comments on public props, use `@default` for defaults and `@internal` for
|
|
213
|
+
props to hide.
|
|
214
|
+
|
|
215
|
+
## Misc
|
|
216
|
+
|
|
217
|
+
- Feature flags: `src/flags.ts` holds a few behavior toggles; there is no
|
|
218
|
+
formal policy around them.
|
|
219
|
+
- `SettingsProvider` (`src/components/SettingsProvider/`) is the built-in
|
|
220
|
+
persistence for component settings (e.g. `List` remembering its view
|
|
221
|
+
settings), with pluggable backends (localStorage by default). Internal
|
|
222
|
+
component infrastructure — extension developers don't need it.
|
|
223
|
+
- `stories/lib.tsx` holds story-only fixtures — never import it from
|
|
224
|
+
component code.
|
|
225
|
+
- Storybook discovers all `src/**/*.stories.tsx` automatically; there is no
|
|
226
|
+
registry to update.
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [0.2.0-alpha.897](https://github.com/mittwald/flow/compare/0.2.0-alpha.896...0.2.0-alpha.897) (2026-07-09)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **PasswordCreationField:** adjust validation behavior ([#2618](https://github.com/mittwald/flow/issues/2618)) ([4bb31c3](https://github.com/mittwald/flow/commit/4bb31c3377334bc0f73cd1225f84992c6901422a))
|
|
11
|
+
|
|
12
|
+
# [0.2.0-alpha.896](https://github.com/mittwald/flow/compare/0.2.0-alpha.895...0.2.0-alpha.896) (2026-07-07)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @mittwald/flow-react-components
|
|
15
|
+
|
|
6
16
|
# [0.2.0-alpha.895](https://github.com/mittwald/flow/compare/0.2.0-alpha.894...0.2.0-alpha.895) (2026-07-07)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @mittwald/flow-react-components
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|