@molecule/app-react 1.9.0 → 1.10.1
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/README.md +27 -16
- package/dist/hooks/useProfileForm.d.ts +10 -3
- package/dist/hooks/useProfileForm.d.ts.map +1 -1
- package/dist/hooks/useProfileForm.js +17 -6
- package/dist/hooks/useProfileForm.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-10-
|
|
6
|
+
Generated: 2026-10-23T14:56:06.342Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/app-react
|
|
@@ -17,7 +17,8 @@ into React idioms.
|
|
|
17
17
|
|
|
18
18
|
**Editable account/profile forms:** `useProfileForm` composes the bonded form
|
|
19
19
|
and auth clients. It hydrates asynchronous user data without erasing dirty
|
|
20
|
-
fields,
|
|
20
|
+
fields, uses session ownership independently of editable profile identity,
|
|
21
|
+
snapshots controlled values on native form submission, submits only
|
|
21
22
|
changed fields through an app-supplied adapter, and persists/publishes the
|
|
22
23
|
server's saved user. Use its `onSaved` callback to update other query caches
|
|
23
24
|
from that response before navigating. Configure the endpoint, method and JSON
|
|
@@ -32,7 +33,6 @@ envelope once in `AuthClientConfig`; no page-local session store is needed.
|
|
|
32
33
|
```tsx
|
|
33
34
|
const profile = useProfileForm<User, { name: string; email: string }>({
|
|
34
35
|
defaultValues: { name: '', email: '' },
|
|
35
|
-
getIdentity: (user) => user.id,
|
|
36
36
|
toValues: (user) => ({ name: user.name ?? '', email: user.email ?? '' }),
|
|
37
37
|
toPatch: (changes) => changes,
|
|
38
38
|
onSaved: async (user) => {
|
|
@@ -167,6 +167,15 @@ interface AuthClient<T = UserProfile, TRegister extends RegisterExtraShape<TRegi
|
|
|
167
167
|
* Gets the current user.
|
|
168
168
|
*/
|
|
169
169
|
getUser(): T | null;
|
|
170
|
+
/**
|
|
171
|
+
* Optional ownership marker for the current session. Compare values only within
|
|
172
|
+
* this client: replacing or ending a session changes it, including re-adopting
|
|
173
|
+
* the same token and user. Profile updates and same-session refreshes keep it.
|
|
174
|
+
* Consumers can use it to discard stale async work without treating editable
|
|
175
|
+
* user fields as an immutable account identifier. Providers without this
|
|
176
|
+
* capability require the consumer's own stable identity check.
|
|
177
|
+
*/
|
|
178
|
+
getSessionRevision?(): number;
|
|
170
179
|
/**
|
|
171
180
|
* Updates the cached user object (state + persistent storage) without
|
|
172
181
|
* hitting the network. Intended for local refreshes after a per-app
|
|
@@ -302,14 +311,6 @@ interface AuthClient<T = UserProfile, TRegister extends RegisterExtraShape<TRegi
|
|
|
302
311
|
* Resolves IMMEDIATELY when no restore is in flight: before `initialize()` is ever
|
|
303
312
|
* called, and after it has finished. A restore that failed resolves too (it settled the
|
|
304
313
|
* question), so an HTTP client can await this before every request without risking one
|
|
305
|
-
* held forever. That is what makes the fetch-before-restore race impossible: a page that
|
|
306
|
-
* fetches viewer-dependent data on mount waits here instead of going out anonymously
|
|
307
|
-
* (see `setAuthGate` in `@molecule/app-http`).
|
|
308
|
-
*
|
|
309
|
-
* Optional: a provider that restores no session has nothing to wait for. Without it, an
|
|
310
|
-
* HTTP client bonded to that provider sends first-paint requests unauthenticated.
|
|
311
|
-
*
|
|
312
|
-
* A provider whose restore sends a request THROUGH the gated HTTP client must send that
|
|
313
314
|
// … truncated — the full declaration is in node_modules/@molecule/app-react/dist
|
|
314
315
|
```
|
|
315
316
|
|
|
@@ -978,8 +979,13 @@ interface UseProfileFormOptions<TUser, TValues extends Record<string, unknown>>
|
|
|
978
979
|
> {
|
|
979
980
|
/** Complete controlled-field defaults, including blank write-only fields. */
|
|
980
981
|
defaultValues: TValues
|
|
981
|
-
/**
|
|
982
|
-
|
|
982
|
+
/**
|
|
983
|
+
* Optional additional account identity check; changing it discards prior edits.
|
|
984
|
+
* By default ownership follows the auth client's session revision, so editable
|
|
985
|
+
* fields can change during a save. Providers without getSessionRevision must
|
|
986
|
+
* supply this callback with an identity that remains stable across profile edits.
|
|
987
|
+
*/
|
|
988
|
+
getIdentity?: (user: TUser) => string
|
|
983
989
|
/** Maps the current/saved user into controlled values, e.g. nullable text to ''. */
|
|
984
990
|
toValues: (user: TUser) => TValues
|
|
985
991
|
/**
|
|
@@ -2336,7 +2342,9 @@ function usePreview(): UsePreviewResult
|
|
|
2336
2342
|
Owns load → edit → submit → publish for the signed-in user's profile.
|
|
2337
2343
|
|
|
2338
2344
|
Same-account background updates refresh untouched fields but preserve dirty
|
|
2339
|
-
controls.
|
|
2345
|
+
controls. Session ownership comes from the auth client, independently of mutable
|
|
2346
|
+
profile fields; an explicit getIdentity adds the caller's identity check.
|
|
2347
|
+
Submission snapshots the registered values before asynchronous
|
|
2340
2348
|
validation, sends only changed fields through `toPatch`, and uses the auth
|
|
2341
2349
|
client's configured updateProfile transport. The saved server response becomes
|
|
2342
2350
|
the clean baseline; edits made while saving remain dirty. No request is made
|
|
@@ -3149,8 +3157,11 @@ Peer dependencies:
|
|
|
3149
3157
|
({ ...changes, ...(password?.trim() ? { password } : {}) })`. `changes`
|
|
3150
3158
|
contains only edited fields, so do not fill omitted fields with null or
|
|
3151
3159
|
copy every property of the auth user into the request. `reset()` discards
|
|
3152
|
-
edits to the newest baseline.
|
|
3153
|
-
|
|
3160
|
+
edits to the newest baseline. Auth clients with `getSessionRevision()` own
|
|
3161
|
+
the form by session, so changing a username-derived id does not discard a
|
|
3162
|
+
successful save. An optional `getIdentity(user)` adds an identity check and
|
|
3163
|
+
clears edits when it changes; use a stable value. Providers without session
|
|
3164
|
+
revisions must supply that callback. Field comparisons are shallow, matching form providers.
|
|
3154
3165
|
A submission whose account or auth client changes, or whose form unmounts,
|
|
3155
3166
|
during asynchronous validation is discarded before any mutation or saved
|
|
3156
3167
|
callback. Same-account background hydration does not discard the submit.
|
|
@@ -9,8 +9,13 @@ import { type UseFormOptions, type UseFormResult } from './useForm.js';
|
|
|
9
9
|
export interface UseProfileFormOptions<TUser, TValues extends Record<string, unknown>> extends Omit<UseFormOptions<TValues>, 'defaultValues'> {
|
|
10
10
|
/** Complete controlled-field defaults, including blank write-only fields. */
|
|
11
11
|
defaultValues: TValues;
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Optional additional account identity check; changing it discards prior edits.
|
|
14
|
+
* By default ownership follows the auth client's session revision, so editable
|
|
15
|
+
* fields can change during a save. Providers without getSessionRevision must
|
|
16
|
+
* supply this callback with an identity that remains stable across profile edits.
|
|
17
|
+
*/
|
|
18
|
+
getIdentity?: (user: TUser) => string;
|
|
14
19
|
/** Maps the current/saved user into controlled values, e.g. nullable text to ''. */
|
|
15
20
|
toValues: (user: TUser) => TValues;
|
|
16
21
|
/**
|
|
@@ -57,7 +62,9 @@ export interface UseProfileFormResult<TUser, TValues extends Record<string, unkn
|
|
|
57
62
|
* Owns load → edit → submit → publish for the signed-in user's profile.
|
|
58
63
|
*
|
|
59
64
|
* Same-account background updates refresh untouched fields but preserve dirty
|
|
60
|
-
* controls.
|
|
65
|
+
* controls. Session ownership comes from the auth client, independently of mutable
|
|
66
|
+
* profile fields; an explicit getIdentity adds the caller's identity check.
|
|
67
|
+
* Submission snapshots the registered values before asynchronous
|
|
61
68
|
* validation, sends only changed fields through `toPatch`, and uses the auth
|
|
62
69
|
* client's configured updateProfile transport. The saved server response becomes
|
|
63
70
|
* the clean baseline; edits made while saving remain dirty. No request is made
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProfileForm.d.ts","sourceRoot":"","sources":["../../src/hooks/useProfileForm.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG5D,OAAO,EAAW,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAE/E,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB,CAAC,KAAK,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,IAAI,CACjG,cAAc,CAAC,OAAO,CAAC,EACvB,eAAe,CAChB;IACC,6EAA6E;IAC7E,aAAa,EAAE,OAAO,CAAA;IACtB
|
|
1
|
+
{"version":3,"file":"useProfileForm.d.ts","sourceRoot":"","sources":["../../src/hooks/useProfileForm.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG5D,OAAO,EAAW,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAE/E,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB,CAAC,KAAK,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,IAAI,CACjG,cAAc,CAAC,OAAO,CAAC,EACvB,eAAe,CAChB;IACC,6EAA6E;IAC7E,aAAa,EAAE,OAAO,CAAA;IACtB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAA;IACrC,oFAAoF;IACpF,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAA;IAClC;;;;OAIG;IACH,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,CAAA;IACjF;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD;AAED,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB,CAAC,KAAK,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,IAAI,CAChG,aAAa,CAAC,OAAO,CAAC,EACtB,UAAU,GAAG,cAAc,GAAG,OAAO,CACtC;IACC,8CAA8C;IAC9C,IAAI,EAAE,KAAK,GAAG,IAAI,CAAA;IAClB,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAA;IACd;;;OAGG;IACH,KAAK,EAAE,OAAO,CAAA;IACd,2EAA2E;IAC3E,QAAQ,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,EAChC,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,KACxD,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAA;IAC7D,sEAAsE;IACtE,SAAS,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,IAAI,CAAA;KAAE,CAAA;IAC1E;;;OAGG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAA;IACxC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3E,OAAO,EAAE,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,GAC7C,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,CAsMtC"}
|
|
@@ -10,7 +10,9 @@ import { useForm } from './useForm.js';
|
|
|
10
10
|
* Owns load → edit → submit → publish for the signed-in user's profile.
|
|
11
11
|
*
|
|
12
12
|
* Same-account background updates refresh untouched fields but preserve dirty
|
|
13
|
-
* controls.
|
|
13
|
+
* controls. Session ownership comes from the auth client, independently of mutable
|
|
14
|
+
* profile fields; an explicit getIdentity adds the caller's identity check.
|
|
15
|
+
* Submission snapshots the registered values before asynchronous
|
|
14
16
|
* validation, sends only changed fields through `toPatch`, and uses the auth
|
|
15
17
|
* client's configured updateProfile transport. The saved server response becomes
|
|
16
18
|
* the clean baseline; edits made while saving remain dirty. No request is made
|
|
@@ -72,14 +74,21 @@ export function useProfileForm(options) {
|
|
|
72
74
|
}
|
|
73
75
|
return;
|
|
74
76
|
}
|
|
75
|
-
const
|
|
77
|
+
const revision = client.getSessionRevision?.();
|
|
78
|
+
const identity = config.getIdentity?.(user);
|
|
79
|
+
if (revision === undefined && !config.getIdentity) {
|
|
80
|
+
throw new Error('useProfileForm: provide getIdentity when the auth client has no session revision');
|
|
81
|
+
}
|
|
76
82
|
const previous = owner.current;
|
|
77
|
-
const sameAccount = !previous ||
|
|
83
|
+
const sameAccount = !previous ||
|
|
84
|
+
(previous.client === client &&
|
|
85
|
+
previous.revision === revision &&
|
|
86
|
+
previous.identity === identity);
|
|
78
87
|
const previousBaseline = baseline.current;
|
|
79
88
|
// Keep this token across same-account hydration, but replace it when the
|
|
80
89
|
// account/client changes. A pending validation belongs to that exact owner.
|
|
81
90
|
if (!previous || !sameAccount)
|
|
82
|
-
owner.current = { client, identity };
|
|
91
|
+
owner.current = { client, revision, identity };
|
|
83
92
|
rebase(config.toValues(user), sameAccount ? previousBaseline : undefined);
|
|
84
93
|
if (!sameAccount) {
|
|
85
94
|
pendingPropagation.current = undefined;
|
|
@@ -93,7 +102,8 @@ export function useProfileForm(options) {
|
|
|
93
102
|
if (!mounted.current || !currentUser)
|
|
94
103
|
return Promise.resolve(undefined);
|
|
95
104
|
const config = optionsRef.current;
|
|
96
|
-
const
|
|
105
|
+
const revision = client.getSessionRevision?.();
|
|
106
|
+
const identity = config.getIdentity?.(currentUser);
|
|
97
107
|
const submissionOwner = owner.current;
|
|
98
108
|
const ownsProfile = () => {
|
|
99
109
|
const current = client.getUser();
|
|
@@ -101,7 +111,8 @@ export function useProfileForm(options) {
|
|
|
101
111
|
committedClient.current === client &&
|
|
102
112
|
owner.current === submissionOwner &&
|
|
103
113
|
current !== null &&
|
|
104
|
-
|
|
114
|
+
client.getSessionRevision?.() === revision &&
|
|
115
|
+
config.getIdentity?.(current) === identity);
|
|
105
116
|
};
|
|
106
117
|
const snapshot = readValues();
|
|
107
118
|
const before = { ...baseline.current };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProfileForm.js","sourceRoot":"","sources":["../../src/hooks/useProfileForm.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAI1F,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EAAE,OAAO,EAA2C,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"useProfileForm.js","sourceRoot":"","sources":["../../src/hooks/useProfileForm.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* **Editable account/profile forms:** `useProfileForm` composes the bonded form
|
|
10
10
|
* and auth clients. It hydrates asynchronous user data without erasing dirty
|
|
11
|
-
* fields,
|
|
11
|
+
* fields, uses session ownership independently of editable profile identity,
|
|
12
|
+
* snapshots controlled values on native form submission, submits only
|
|
12
13
|
* changed fields through an app-supplied adapter, and persists/publishes the
|
|
13
14
|
* server's saved user. Use its `onSaved` callback to update other query caches
|
|
14
15
|
* from that response before navigating. Configure the endpoint, method and JSON
|
|
@@ -18,7 +19,6 @@
|
|
|
18
19
|
* ```tsx
|
|
19
20
|
* const profile = useProfileForm<User, { name: string; email: string }>({
|
|
20
21
|
* defaultValues: { name: '', email: '' },
|
|
21
|
-
* getIdentity: (user) => user.id,
|
|
22
22
|
* toValues: (user) => ({ name: user.name ?? '', email: user.email ?? '' }),
|
|
23
23
|
* toPatch: (changes) => changes,
|
|
24
24
|
* onSaved: async (user) => {
|
|
@@ -83,8 +83,11 @@
|
|
|
83
83
|
* ({ ...changes, ...(password?.trim() ? { password } : {}) })`. `changes`
|
|
84
84
|
* contains only edited fields, so do not fill omitted fields with null or
|
|
85
85
|
* copy every property of the auth user into the request. `reset()` discards
|
|
86
|
-
* edits to the newest baseline.
|
|
87
|
-
*
|
|
86
|
+
* edits to the newest baseline. Auth clients with `getSessionRevision()` own
|
|
87
|
+
* the form by session, so changing a username-derived id does not discard a
|
|
88
|
+
* successful save. An optional `getIdentity(user)` adds an identity check and
|
|
89
|
+
* clears edits when it changes; use a stable value. Providers without session
|
|
90
|
+
* revisions must supply that callback. Field comparisons are shallow, matching form providers.
|
|
88
91
|
* A submission whose account or auth client changes, or whose form unmounts,
|
|
89
92
|
* during asynchronous validation is discarded before any mutation or saved
|
|
90
93
|
* callback. Same-account background hydration does not discard the submit.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqJG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* **Editable account/profile forms:** `useProfileForm` composes the bonded form
|
|
10
10
|
* and auth clients. It hydrates asynchronous user data without erasing dirty
|
|
11
|
-
* fields,
|
|
11
|
+
* fields, uses session ownership independently of editable profile identity,
|
|
12
|
+
* snapshots controlled values on native form submission, submits only
|
|
12
13
|
* changed fields through an app-supplied adapter, and persists/publishes the
|
|
13
14
|
* server's saved user. Use its `onSaved` callback to update other query caches
|
|
14
15
|
* from that response before navigating. Configure the endpoint, method and JSON
|
|
@@ -18,7 +19,6 @@
|
|
|
18
19
|
* ```tsx
|
|
19
20
|
* const profile = useProfileForm<User, { name: string; email: string }>({
|
|
20
21
|
* defaultValues: { name: '', email: '' },
|
|
21
|
-
* getIdentity: (user) => user.id,
|
|
22
22
|
* toValues: (user) => ({ name: user.name ?? '', email: user.email ?? '' }),
|
|
23
23
|
* toPatch: (changes) => changes,
|
|
24
24
|
* onSaved: async (user) => {
|
|
@@ -83,8 +83,11 @@
|
|
|
83
83
|
* ({ ...changes, ...(password?.trim() ? { password } : {}) })`. `changes`
|
|
84
84
|
* contains only edited fields, so do not fill omitted fields with null or
|
|
85
85
|
* copy every property of the auth user into the request. `reset()` discards
|
|
86
|
-
* edits to the newest baseline.
|
|
87
|
-
*
|
|
86
|
+
* edits to the newest baseline. Auth clients with `getSessionRevision()` own
|
|
87
|
+
* the form by session, so changing a username-derived id does not discard a
|
|
88
|
+
* successful save. An optional `getIdentity(user)` adds an identity check and
|
|
89
|
+
* clears edits when it changes; use a stable value. Providers without session
|
|
90
|
+
* revisions must supply that callback. Field comparisons are shallow, matching form providers.
|
|
88
91
|
* A submission whose account or auth client changes, or whose form unmounts,
|
|
89
92
|
* during asynchronous validation is discarded before any mutation or saved
|
|
90
93
|
* callback. Same-account background hydration does not discard the submit.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqJG;AAEH,cAAc,qBAAqB,CAAA;AACnC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/app-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "React framework bindings for molecule.dev",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -58,15 +58,15 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@molecule/app-ai-models": "1.4.
|
|
62
|
-
"@molecule/app-bonds-default-react": "1.1.
|
|
63
|
-
"@molecule/app-i18n": "1.0.
|
|
64
|
-
"@testing-library/dom": "10.4.
|
|
65
|
-
"@testing-library/react": "16.3.
|
|
66
|
-
"@types/node": "26.
|
|
67
|
-
"@types/react": "19.
|
|
68
|
-
"react": "19.
|
|
69
|
-
"react-dom": "19.
|
|
61
|
+
"@molecule/app-ai-models": "1.4.3",
|
|
62
|
+
"@molecule/app-bonds-default-react": "1.1.7",
|
|
63
|
+
"@molecule/app-i18n": "1.0.4",
|
|
64
|
+
"@testing-library/dom": "10.4.2",
|
|
65
|
+
"@testing-library/react": "16.3.3",
|
|
66
|
+
"@types/node": "26.6.5",
|
|
67
|
+
"@types/react": "19.3.0",
|
|
68
|
+
"react": "19.3.1",
|
|
69
|
+
"react-dom": "19.3.1",
|
|
70
70
|
"typescript": "6.0.3",
|
|
71
71
|
"vitest": "4.1.12"
|
|
72
72
|
},
|