@formality-ui/react 0.2.3 → 0.2.4

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/dist/index.d.cts CHANGED
@@ -202,10 +202,12 @@ declare function defineInputs<T extends Record<string, ReactInputConfig>>(inputs
202
202
  * `<Field>` renders your input component via React Hook Form's `<Controller>`.
203
203
  * At runtime Formality merges a `coreProps` bundle onto the component (name,
204
204
  * value, onChange, onBlur, and — as a React-special key — `ref`). The three
205
- * members below are the **injected-props contract**: `formState` reaches
206
- * templates and render-prop children; `state` (subscribed field state) and a
207
- * top-level `forwardRef` key are delivered at runtime by `<Field>` (see
208
- * "Runtime delivery" below).
205
+ * members below are the **injected-props contract**: `formState` always
206
+ * reaches templates and render-prop children, and reaches plain components
207
+ * that have opted into Formality state via `provideState` /
208
+ * `passSubscriptions`; `state` (subscribed field state) and a top-level
209
+ * `forwardRef` key are delivered at runtime by `<Field>` (see "Runtime
210
+ * delivery" below).
209
211
  *
210
212
  * **Destructure before forwarding.** Component authors MUST destructure
211
213
  * `state`, `formState`, and `forwardRef` OUT of props before spreading the
package/dist/index.d.ts CHANGED
@@ -202,10 +202,12 @@ declare function defineInputs<T extends Record<string, ReactInputConfig>>(inputs
202
202
  * `<Field>` renders your input component via React Hook Form's `<Controller>`.
203
203
  * At runtime Formality merges a `coreProps` bundle onto the component (name,
204
204
  * value, onChange, onBlur, and — as a React-special key — `ref`). The three
205
- * members below are the **injected-props contract**: `formState` reaches
206
- * templates and render-prop children; `state` (subscribed field state) and a
207
- * top-level `forwardRef` key are delivered at runtime by `<Field>` (see
208
- * "Runtime delivery" below).
205
+ * members below are the **injected-props contract**: `formState` always
206
+ * reaches templates and render-prop children, and reaches plain components
207
+ * that have opted into Formality state via `provideState` /
208
+ * `passSubscriptions`; `state` (subscribed field state) and a top-level
209
+ * `forwardRef` key are delivered at runtime by `<Field>` (see "Runtime
210
+ * delivery" below).
209
211
  *
210
212
  * **Destructure before forwarding.** Component authors MUST destructure
211
213
  * `state`, `formState`, and `forwardRef` OUT of props before spreading the
package/dist/index.js CHANGED
@@ -1086,6 +1086,40 @@ function Field({
1086
1086
  const label = useMemo(() => {
1087
1087
  return resolveLabel(name, fieldConfig, fieldSelectProps, restProps);
1088
1088
  }, [name, fieldConfig, fieldSelectProps, restProps]);
1089
+ const passSubscriptionsEnabled = fieldConfig.passSubscriptions === true;
1090
+ const provideStateEnabled = fieldConfig.provideState === true;
1091
+ const subscribedWatchNames = useMemo(
1092
+ () => passSubscriptionsEnabled && allSubscriptions.length > 0 ? allSubscriptions : [],
1093
+ [passSubscriptionsEnabled, allSubscriptions]
1094
+ );
1095
+ const subscribedValues = useWatch({
1096
+ control: methods.control,
1097
+ name: subscribedWatchNames.length > 0 ? subscribedWatchNames : []
1098
+ });
1099
+ const subscribedState = useMemo(() => {
1100
+ if (!passSubscriptionsEnabled || subscribedWatchNames.length === 0) {
1101
+ return void 0;
1102
+ }
1103
+ const result = {};
1104
+ const values = Array.isArray(subscribedValues) ? subscribedValues : [subscribedValues];
1105
+ subscribedWatchNames.forEach((fieldName, i) => {
1106
+ const fs = methods.getFieldState(fieldName);
1107
+ result[fieldName] = makeProxyState({
1108
+ value: values[i],
1109
+ isTouched: fs.isTouched,
1110
+ isDirty: fs.isDirty,
1111
+ isValidating: fs.isValidating,
1112
+ error: fs.error,
1113
+ invalid: fs.invalid
1114
+ });
1115
+ });
1116
+ return result;
1117
+ }, [
1118
+ passSubscriptionsEnabled,
1119
+ subscribedWatchNames,
1120
+ subscribedValues,
1121
+ methods
1122
+ ]);
1089
1123
  const validationRules = useMemo(() => {
1090
1124
  return {
1091
1125
  ...fieldConfig.rules,
@@ -1163,6 +1197,24 @@ function Field({
1163
1197
  inputConfig.formatter,
1164
1198
  providerConfig.formatters
1165
1199
  );
1200
+ const stateInjection = {};
1201
+ if (provideStateEnabled) {
1202
+ stateInjection[providerConfig.defaultSubscriptionPropName] = makeProxyState({
1203
+ value: field.value,
1204
+ isTouched: fieldState.isTouched,
1205
+ isDirty: fieldState.isDirty,
1206
+ isValidating: fieldState.isValidating,
1207
+ error: fieldState.error,
1208
+ invalid: fieldState.invalid
1209
+ });
1210
+ }
1211
+ if (passSubscriptionsEnabled && subscribedState) {
1212
+ const subsPropName = fieldConfig.passSubscriptionsAs ?? providerConfig.defaultSubscriptionPropName;
1213
+ stateInjection[subsPropName] = subscribedState;
1214
+ }
1215
+ if (provideStateEnabled || passSubscriptionsEnabled) {
1216
+ stateInjection.formState = formState;
1217
+ }
1166
1218
  const finalProps = mergeFieldProps({
1167
1219
  providerDefaultFieldProps: providerConfig.defaultFieldProps,
1168
1220
  providerSelectDefaultFieldProps: providerSelectProps,
@@ -1180,7 +1232,8 @@ function Field({
1180
1232
  [inputConfig.inputFieldProp ?? "value"]: formattedValue,
1181
1233
  onChange: handleChange(field.onChange),
1182
1234
  onBlur: field.onBlur,
1183
- forwardRef: field.ref
1235
+ forwardRef: field.ref,
1236
+ ...stateInjection
1184
1237
  }
1185
1238
  });
1186
1239
  const Component = inputConfig.component;
@@ -1199,10 +1252,22 @@ function Field({
1199
1252
  }
1200
1253
  );
1201
1254
  } else if (isHostComponent) {
1202
- const { forwardRef: hostRef, ...restHostProps } = finalProps;
1255
+ const subsPropName = fieldConfig.passSubscriptionsAs ?? providerConfig.defaultSubscriptionPropName;
1256
+ const strippedHostProps = {};
1257
+ const nonDomKeys = /* @__PURE__ */ new Set([
1258
+ "forwardRef",
1259
+ "formState",
1260
+ "state",
1261
+ subsPropName
1262
+ ]);
1263
+ for (const [key, value] of Object.entries(finalProps)) {
1264
+ if (!nonDomKeys.has(key)) {
1265
+ strippedHostProps[key] = value;
1266
+ }
1267
+ }
1203
1268
  renderedField = createElement(inputConfig.component, {
1204
- ...restHostProps,
1205
- ref: hostRef
1269
+ ...strippedHostProps,
1270
+ ref: finalProps.forwardRef
1206
1271
  });
1207
1272
  } else {
1208
1273
  renderedField = /* @__PURE__ */ jsx(Component, { ...finalProps });