@vtex/faststore 0.0.4 → 0.0.6
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/CHANGELOG.md +67 -0
- package/dist/actions.json +181 -0
- package/dist/catalog.json +1595 -481
- package/dist/client.d.ts +2 -1
- package/dist/client.js +2 -1
- package/dist/components.d.ts +31 -7
- package/dist/components.js +35 -13
- package/dist/content-types.json +73 -0
- package/dist/docs/access-code-sign-in.md +1 -1
- package/dist/docs/account-access-gate.md +153 -0
- package/dist/docs/account-entry-point.md +1 -2
- package/dist/docs/account-menu.md +164 -0
- package/dist/docs/address-summary.md +24 -3
- package/dist/docs/alert-dialog.md +204 -0
- package/dist/docs/billing-address.md +284 -0
- package/dist/docs/buy-button.md +1 -1
- package/dist/docs/card-entry.md +250 -0
- package/dist/docs/cardholder-document.md +142 -0
- package/dist/docs/cart.md +1 -1
- package/dist/docs/client-preferences-fieldset.md +148 -0
- package/dist/docs/client-preferences.md +2 -1
- package/dist/docs/client-profile-fieldset.md +184 -0
- package/dist/docs/client-profile.md +1 -1
- package/dist/docs/document-field.md +58 -4
- package/dist/docs/field.md +317 -0
- package/dist/docs/form.md +307 -0
- package/dist/docs/identity-edit.md +6 -6
- package/dist/docs/identity-summary.md +5 -5
- package/dist/docs/installments.md +248 -0
- package/dist/docs/my-account-profile.md +1 -0
- package/dist/docs/order-placed-payment-summary.md +138 -0
- package/dist/docs/payment-method-badges.md +232 -0
- package/dist/docs/payment-methods.md +1 -0
- package/dist/docs/payment.md +218 -0
- package/dist/docs/phone-field.md +58 -4
- package/dist/docs/place-order.md +157 -0
- package/dist/docs/save-card.md +186 -0
- package/dist/docs/saved-cards.md +218 -0
- package/dist/docs/select.md +465 -0
- package/dist/docs/session.md +1 -1
- package/dist/docs/shipping-address.md +110 -258
- package/dist/docs/sign-in-redirect.md +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/internal/client.d.ts +3 -1
- package/dist/internal/client.js +3 -1
- package/dist/matter/access-code-sign-in/access-code-sign-in.js +9 -8
- package/dist/matter/access-code-sign-in/access-code-sign-in.js.map +1 -1
- package/dist/matter/account-access-gate/account-access-gate.d.ts +86 -0
- package/dist/matter/account-access-gate/account-access-gate.js +283 -0
- package/dist/matter/account-access-gate/account-access-gate.js.map +1 -0
- package/dist/matter/account-access-gate/sign-out-intent.d.ts +17 -0
- package/dist/matter/account-access-gate/sign-out-intent.js +62 -0
- package/dist/matter/account-access-gate/sign-out-intent.js.map +1 -0
- package/dist/matter/account-entry-point/account-entry-point.js +2 -2
- package/dist/matter/account-entry-point/account-entry-point.js.map +1 -1
- package/dist/matter/account-menu/account-menu.d.ts +88 -0
- package/dist/matter/account-menu/account-menu.js +246 -0
- package/dist/matter/account-menu/account-menu.js.map +1 -0
- package/dist/matter/billing-address/billing-address.d.ts +165 -0
- package/dist/matter/billing-address/billing-address.js +408 -0
- package/dist/matter/billing-address/billing-address.js.map +1 -0
- package/dist/matter/card-entry/card-capture.d.ts +25 -0
- package/dist/matter/card-entry/card-capture.js +25 -0
- package/dist/matter/card-entry/card-capture.js.map +1 -0
- package/dist/matter/card-entry/card-entry.d.ts +120 -0
- package/dist/matter/card-entry/card-entry.js +832 -0
- package/dist/matter/card-entry/card-entry.js.map +1 -0
- package/dist/matter/cardholder-document/cardholder-document.d.ts +45 -0
- package/dist/matter/cardholder-document/cardholder-document.js +70 -0
- package/dist/matter/cardholder-document/cardholder-document.js.map +1 -0
- package/dist/matter/cart/cart.d.ts +1 -1
- package/dist/matter/cart/cart.js +2 -2
- package/dist/matter/cart/cart.js.map +1 -1
- package/dist/matter/client-preferences/client-preferences-fieldset.d.ts +77 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.js +299 -0
- package/dist/matter/client-preferences/client-preferences-fieldset.js.map +1 -0
- package/dist/matter/client-preferences/client-preferences.d.ts +3 -5
- package/dist/matter/client-preferences/client-preferences.js +6 -6
- package/dist/matter/client-preferences/client-preferences.js.map +1 -1
- package/dist/matter/client-profile/client-profile.d.ts +4 -6
- package/dist/matter/client-profile/client-profile.js +9 -6
- package/dist/matter/client-profile/client-profile.js.map +1 -1
- package/dist/matter/client-profile-form/client-profile-fieldset.d.ts +119 -0
- package/dist/matter/client-profile-form/client-profile-fieldset.js +488 -0
- package/dist/matter/client-profile-form/client-profile-fieldset.js.map +1 -0
- package/dist/matter/delivery-options/delivery-options.js.map +1 -1
- package/dist/matter/identity-edit/identity-edit.js +2 -2
- package/dist/matter/identity-edit/identity-edit.js.map +1 -1
- package/dist/matter/identity-summary/identity-summary.js +2 -2
- package/dist/matter/identity-summary/identity-summary.js.map +1 -1
- package/dist/matter/installments/installments-select.d.ts +42 -0
- package/dist/matter/installments/installments-select.js +167 -0
- package/dist/matter/installments/installments-select.js.map +1 -0
- package/dist/matter/installments/installments.d.ts +58 -0
- package/dist/matter/installments/installments.js +176 -0
- package/dist/matter/installments/installments.js.map +1 -0
- package/dist/matter/installments/use-installments-selection.d.ts +29 -0
- package/dist/matter/installments/use-installments-selection.js +95 -0
- package/dist/matter/installments/use-installments-selection.js.map +1 -0
- package/dist/matter/my-account-profile/my-account-profile.js +5 -5
- package/dist/matter/my-account-profile/my-account-profile.js.map +1 -1
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.d.ts +63 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js +305 -0
- package/dist/matter/order-placed-payment-summary/order-placed-payment-summary.js.map +1 -0
- package/dist/matter/payment/payment-card-capture.d.ts +19 -0
- package/dist/matter/payment/payment-card-capture.js +129 -0
- package/dist/matter/payment/payment-card-capture.js.map +1 -0
- package/dist/matter/payment/payment-controller.d.ts +24 -0
- package/dist/matter/payment/payment-controller.js +107 -0
- package/dist/matter/payment/payment-controller.js.map +1 -0
- package/dist/matter/payment/payment-method-badges.d.ts +57 -0
- package/dist/matter/payment/payment-method-badges.js +192 -0
- package/dist/matter/payment/payment-method-badges.js.map +1 -0
- package/dist/matter/payment/payment.d.ts +89 -0
- package/dist/matter/payment/payment.js +263 -0
- package/dist/matter/payment/payment.js.map +1 -0
- package/dist/matter/payment/use-payment-method-selection.d.ts +302 -0
- package/dist/matter/payment/use-payment-method-selection.js +458 -0
- package/dist/matter/payment/use-payment-method-selection.js.map +1 -0
- package/dist/matter/payment/use-payment-submit-gate.d.ts +111 -0
- package/dist/matter/payment/use-payment-submit-gate.js +144 -0
- package/dist/matter/payment/use-payment-submit-gate.js.map +1 -0
- package/dist/matter/place-order/place-order.d.ts +74 -0
- package/dist/matter/place-order/place-order.js +379 -0
- package/dist/matter/place-order/place-order.js.map +1 -0
- package/dist/matter/product-list/product-list.d.ts +1 -0
- package/dist/matter/product-list/product-list.js.map +1 -1
- package/dist/matter/product-shelf/product-shelf.d.ts +1 -0
- package/dist/matter/product-shelf/product-shelf.js +2 -0
- package/dist/matter/product-shelf/product-shelf.js.map +1 -1
- package/dist/matter/region/region.js +1 -1
- package/dist/matter/region/region.js.map +1 -1
- package/dist/matter/save-card/save-card.d.ts +49 -0
- package/dist/matter/save-card/save-card.js +188 -0
- package/dist/matter/save-card/save-card.js.map +1 -0
- package/dist/matter/saved-cards/saved-cards.d.ts +79 -0
- package/dist/matter/saved-cards/saved-cards.js +387 -0
- package/dist/matter/saved-cards/saved-cards.js.map +1 -0
- package/dist/matter/shipping-address/country-descriptors.js +20 -10
- package/dist/matter/shipping-address/country-descriptors.js.map +1 -1
- package/dist/matter/shipping-address/shipping-address.d.ts +113 -174
- package/dist/matter/shipping-address/shipping-address.js +481 -792
- package/dist/matter/shipping-address/shipping-address.js.map +1 -1
- package/dist/matter/shipping-simulator/shipping-simulator.js.map +1 -1
- package/dist/matter/variant-selector/variant-selector.js +1 -1
- package/dist/particles/address-summary/address-summary.d.ts +24 -0
- package/dist/particles/address-summary/address-summary.js +83 -2
- package/dist/particles/address-summary/address-summary.js.map +1 -1
- package/dist/particles/alert-dialog/alert-dialog.d.ts +68 -0
- package/dist/particles/alert-dialog/alert-dialog.js +187 -0
- package/dist/particles/alert-dialog/alert-dialog.js.map +1 -0
- package/dist/particles/checkbox/checkbox.d.ts +7 -3
- package/dist/particles/checkbox/checkbox.js +4 -1
- package/dist/particles/checkbox/checkbox.js.map +1 -1
- package/dist/particles/document-field/document-field.d.ts +48 -5
- package/dist/particles/document-field/document-field.js +189 -32
- package/dist/particles/document-field/document-field.js.map +1 -1
- package/dist/particles/field/bound-field-registry.js +52 -0
- package/dist/particles/field/bound-field-registry.js.map +1 -0
- package/dist/particles/field/field.d.ts +116 -0
- package/dist/particles/field/field.js +497 -6
- package/dist/particles/field/field.js.map +1 -1
- package/dist/particles/fieldset/fieldset.js +2 -2
- package/dist/particles/fieldset/fieldset.js.map +1 -1
- package/dist/particles/footer-social/footer-social.js +1 -1
- package/dist/particles/form/form.d.ts +104 -0
- package/dist/particles/form/form.js +485 -0
- package/dist/particles/form/form.js.map +1 -0
- package/dist/particles/incentives/incentives.js +1 -1
- package/dist/particles/phone-field/phone-field.d.ts +38 -10
- package/dist/particles/phone-field/phone-field.js +183 -39
- package/dist/particles/phone-field/phone-field.js.map +1 -1
- package/dist/particles/postal-code-field/postal-code-field.js +2 -2
- package/dist/particles/postal-code-field/postal-code-field.js.map +1 -1
- package/dist/particles/select/field-select.d.ts +43 -0
- package/dist/particles/select/field-select.js +150 -0
- package/dist/particles/select/field-select.js.map +1 -0
- package/dist/particles/select/select.d.ts +2 -0
- package/dist/particles/select/select.js.map +1 -1
- package/dist/particles/shared/compose-refs.js +21 -0
- package/dist/particles/shared/compose-refs.js.map +1 -0
- package/dist/schema.graphql +701 -2
- package/dist/sdk/actions/analytics-action-provider.d.ts +15 -0
- package/dist/sdk/actions/analytics-action-provider.js +19 -0
- package/dist/sdk/actions/analytics-action-provider.js.map +1 -0
- package/dist/sdk/actions/cart-action-provider.d.ts +1 -1
- package/dist/sdk/actions/cart-action-provider.js +1 -1
- package/dist/sdk/actions/cart-action-provider.js.map +1 -1
- package/dist/sdk/actions/index.d.ts +3 -1
- package/dist/sdk/actions/index.js +3 -1
- package/dist/sdk/actions/payment-action-provider.d.ts +22 -0
- package/dist/sdk/actions/payment-action-provider.js +26 -0
- package/dist/sdk/actions/payment-action-provider.js.map +1 -0
- package/dist/sdk/actions/session-action-provider.d.ts +1 -1
- package/dist/sdk/actions/session-action-provider.js +1 -1
- package/dist/sdk/actions/session-action-provider.js.map +1 -1
- package/dist/sdk/actions/shipping-action-provider.d.ts +1 -1
- package/dist/sdk/actions/shipping-action-provider.js +1 -1
- package/dist/sdk/actions/shipping-action-provider.js.map +1 -1
- package/dist/sdk/actions/types.d.ts +6 -2
- package/dist/sdk/analytics/analytics-destination.d.ts +43 -0
- package/dist/sdk/analytics/analytics-destination.js +90 -0
- package/dist/sdk/analytics/analytics-destination.js.map +1 -0
- package/dist/sdk/analytics/use-analytics-actions.d.ts +57 -0
- package/dist/sdk/analytics/use-analytics-actions.js +108 -0
- package/dist/sdk/analytics/use-analytics-actions.js.map +1 -0
- package/dist/sdk/cache/storefront-cache.js +1 -1
- package/dist/sdk/cache/storefront-cache.js.map +1 -1
- package/dist/sdk/cart/operations.d.ts +4 -4
- package/dist/sdk/cart/operations.js +1 -1
- package/dist/sdk/cart/operations.js.map +1 -1
- package/dist/sdk/cart/optimistic.js +1 -1
- package/dist/sdk/cart/optimistic.js.map +1 -1
- package/dist/sdk/cart/use-cart-actions.d.ts +1 -1
- package/dist/sdk/cart/use-cart-actions.js +4 -4
- package/dist/sdk/cart/use-cart-actions.js.map +1 -1
- package/dist/sdk/cart/use-cart-validate-on-open.js +1 -1
- package/dist/sdk/cart/use-cart-validate-on-open.js.map +1 -1
- package/dist/sdk/cart/write-gate.js +1 -1
- package/dist/sdk/cart/write-gate.js.map +1 -1
- package/dist/sdk/data/entity-resolution-context.js +31 -0
- package/dist/sdk/data/entity-resolution-context.js.map +1 -0
- package/dist/sdk/data/entity-subscriber.js +18 -8
- package/dist/sdk/data/entity-subscriber.js.map +1 -1
- package/dist/sdk/data/index.js +1 -0
- package/dist/sdk/data/page-reactive-data-root.d.ts +38 -2
- package/dist/sdk/data/page-reactive-data-root.js +4 -2
- package/dist/sdk/data/page-reactive-data-root.js.map +1 -1
- package/dist/sdk/data/reactive-data-provider.d.ts +1 -1
- package/dist/sdk/data/reactive-data-provider.js +8 -4
- package/dist/sdk/data/reactive-data-provider.js.map +1 -1
- package/dist/sdk/data/reactive-list-item-data-provider.d.ts +1 -1
- package/dist/sdk/data/reactive-list-item-data-provider.js +13 -5
- package/dist/sdk/data/reactive-list-item-data-provider.js.map +1 -1
- package/dist/sdk/data/use-reactive-data-settled.js +39 -0
- package/dist/sdk/data/use-reactive-data-settled.js.map +1 -0
- package/dist/sdk/data/use-reactive-entity.js +6 -2
- package/dist/sdk/data/use-reactive-entity.js.map +1 -1
- package/dist/sdk/generated/fragment-types.js +2 -0
- package/dist/sdk/generated/fragment-types.js.map +1 -1
- package/dist/sdk/generated/gql.js +2 -1
- package/dist/sdk/generated/gql.js.map +1 -1
- package/dist/sdk/generated/graphql.js +85 -1
- package/dist/sdk/generated/graphql.js.map +1 -1
- package/dist/sdk/i18n/messages/en-US.js +3 -0
- package/dist/sdk/i18n/messages/en-US.json +3 -0
- package/dist/sdk/i18n/messages/en-US.json.d.ts +3 -0
- package/dist/sdk/i18n/messages/es-ES.js +3 -0
- package/dist/sdk/i18n/messages/es-ES.json +3 -0
- package/dist/sdk/i18n/messages/pt-BR.js +3 -0
- package/dist/sdk/i18n/messages/pt-BR.json +3 -0
- package/dist/sdk/identity/operations.js.map +1 -1
- package/dist/sdk/identity/use-identity-actions.d.ts +1 -1
- package/dist/sdk/identity/use-identity-actions.js +3 -2
- package/dist/sdk/identity/use-identity-actions.js.map +1 -1
- package/dist/sdk/payment/gateway-origin.js +35 -0
- package/dist/sdk/payment/gateway-origin.js.map +1 -0
- package/dist/sdk/payment/gateway.d.ts +85 -0
- package/dist/sdk/payment/gateway.js +183 -0
- package/dist/sdk/payment/gateway.js.map +1 -0
- package/dist/sdk/payment/operations.d.ts +52 -0
- package/dist/sdk/payment/operations.js +223 -0
- package/dist/sdk/payment/operations.js.map +1 -0
- package/dist/sdk/payment/security-code-mask.js +71 -0
- package/dist/sdk/payment/security-code-mask.js.map +1 -0
- package/dist/sdk/payment/submission-registry.d.ts +33 -0
- package/dist/sdk/payment/submission-registry.js +58 -0
- package/dist/sdk/payment/submission-registry.js.map +1 -0
- package/dist/sdk/payment/use-payment-actions.d.ts +78 -0
- package/dist/sdk/payment/use-payment-actions.js +276 -0
- package/dist/sdk/payment/use-payment-actions.js.map +1 -0
- package/dist/sdk/payment/use-place-order.d.ts +65 -0
- package/dist/sdk/payment/use-place-order.js +640 -0
- package/dist/sdk/payment/use-place-order.js.map +1 -0
- package/dist/sdk/session/auth-operations.d.ts +1 -1
- package/dist/sdk/session/auth-operations.js.map +1 -1
- package/dist/sdk/session/use-session-actions.d.ts +1 -1
- package/dist/sdk/session/use-session-actions.js.map +1 -1
- package/dist/sdk/session/use-session-revalidation.js +65 -0
- package/dist/sdk/session/use-session-revalidation.js.map +1 -0
- package/dist/sdk/shipping/option-select-operations.d.ts +1 -1
- package/dist/sdk/shipping/option-select-operations.js.map +1 -1
- package/dist/sdk/shipping/request-timeout.js +1 -1
- package/dist/sdk/shipping/request-timeout.js.map +1 -1
- package/dist/sdk/shipping/shipping-operations.d.ts +1 -1
- package/dist/sdk/shipping/shipping-operations.js.map +1 -1
- package/dist/sdk/shipping/use-shipping-actions.d.ts +2 -2
- package/dist/sdk/shipping/use-shipping-actions.js +1 -1
- package/dist/sdk/shipping/use-shipping-actions.js.map +1 -1
- package/dist/sdk/state/cart.d.ts +3 -4
- package/dist/sdk/state/cart.js +6 -7
- package/dist/sdk/state/cart.js.map +1 -1
- package/dist/utils/loggable-error-name.js +49 -0
- package/dist/utils/loggable-error-name.js.map +1 -0
- package/dist/utils/resolve-authored-copy.js +18 -0
- package/dist/utils/resolve-authored-copy.js.map +1 -0
- package/dist/utils/safe-href.js +3 -3
- package/dist/utils/safe-href.js.map +1 -1
- package/dist/utils/substitute-template.js +33 -0
- package/dist/utils/substitute-template.js.map +1 -0
- package/package.json +2 -1
- package/src/styles/tailwind.css +34 -0
- package/dist/docs/client-profile-form.md +0 -192
- package/dist/matter/client-profile-form/client-profile-form.d.ts +0 -126
- package/dist/matter/client-profile-form/client-profile-form.js +0 -662
- package/dist/matter/client-profile-form/client-profile-form.js.map +0 -1
|
@@ -1,13 +1,370 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { defineComponent } from "../../core/dist/define-component.js";
|
|
3
3
|
import "../../core/dist/index.js";
|
|
4
|
+
import { Checkbox } from "../checkbox/checkbox.js";
|
|
5
|
+
import { registerFieldClearer } from "./bound-field-registry.js";
|
|
6
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef } from "react";
|
|
4
7
|
import { jsx } from "react/jsx-runtime";
|
|
5
8
|
import { Field } from "@base-ui/react/field";
|
|
9
|
+
import { useController, useFormContext, useFormState } from "react-hook-form";
|
|
6
10
|
//#region src/particles/field/field.tsx
|
|
11
|
+
/**
|
|
12
|
+
* The one place `RegisterOptions` is named as a value type. `FieldRule`'s members are declared
|
|
13
|
+
* independently of react-hook-form's (Decision 5), but each already carries react-hook-form's own
|
|
14
|
+
* runtime shape (a bare value, or `{ value, message }`), so this is an assertion, not a per-member
|
|
15
|
+
* transform. `field-rule.type-test.tsx` pins the boundary from the other side: it fails to compile if
|
|
16
|
+
* `FieldRule` ever widens back to a bare `RegisterOptions` alias.
|
|
17
|
+
*/
|
|
18
|
+
function toRegisterOptions(rule) {
|
|
19
|
+
return rule;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* react-hook-form's own reading of `required`: `.value` for the object form
|
|
23
|
+
* (`{ value: boolean; message: string }`), plain truthiness otherwise (a boolean or a message
|
|
24
|
+
* string). A message string is itself the copy, which is why the two are read together.
|
|
25
|
+
*/
|
|
26
|
+
function readBaseline(rule) {
|
|
27
|
+
const required = rule?.required;
|
|
28
|
+
if (typeof required === "object" && required !== null) return {
|
|
29
|
+
required: Boolean(required.value),
|
|
30
|
+
message: required.value ? required.message : void 0
|
|
31
|
+
};
|
|
32
|
+
if (typeof required === "string") return {
|
|
33
|
+
required: true,
|
|
34
|
+
message: required
|
|
35
|
+
};
|
|
36
|
+
return { required: Boolean(required) };
|
|
37
|
+
}
|
|
38
|
+
/** A `validate` member is either one function or a record of named ones; downstream only wants the record. */
|
|
39
|
+
function normaliseValidators(validate) {
|
|
40
|
+
if (!validate) return {};
|
|
41
|
+
return typeof validate === "function" ? { validate } : { ...validate };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Composes `validator` into `rule` under `name`, alongside whatever the rule already validates —
|
|
45
|
+
* never instead of it. The two composites reach for this to keep their own format check while a
|
|
46
|
+
* fieldset-supplied validator stays in force; before it, both discarded their own validation whole
|
|
47
|
+
* the moment the fieldset supplied any.
|
|
48
|
+
*/
|
|
49
|
+
function mergeFieldValidator(rule, name, validator) {
|
|
50
|
+
return {
|
|
51
|
+
...rule,
|
|
52
|
+
validate: {
|
|
53
|
+
...normaliseValidators(rule?.validate),
|
|
54
|
+
[name]: validator
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The one resolution of `required = baselineRequired || authorRaise`. The fieldset's `FieldRule` is
|
|
60
|
+
* the baseline; a control may raise a field to required and never lower one, so `raise.required`
|
|
61
|
+
* only ever adds. Read-only deliberately plays no part: a field that is read-only and required stays
|
|
62
|
+
* required, and an unsatisfiable form is the declared baseline's fault, not this function's.
|
|
63
|
+
*
|
|
64
|
+
* Baseline copy wins over the raise's, matching react-hook-form's own order — it evaluates `required`
|
|
65
|
+
* before `validate`, so the fieldset's message was already the one a shopper saw whenever both existed.
|
|
66
|
+
*
|
|
67
|
+
* `required` catches an empty string but not a space-filled one (`inputValue === ''` is
|
|
68
|
+
* react-hook-form's only emptiness test for a string), so the blank check goes in beside it. It is
|
|
69
|
+
* installed last, so it cannot be displaced by a same-named validator from the rule.
|
|
70
|
+
*/
|
|
71
|
+
function resolveRequiredness(rule, raise) {
|
|
72
|
+
const baseline = readBaseline(rule);
|
|
73
|
+
const required = baseline.required || Boolean(raise?.required);
|
|
74
|
+
if (!required) return {
|
|
75
|
+
required: false,
|
|
76
|
+
rule
|
|
77
|
+
};
|
|
78
|
+
const message = baseline.message ?? (baseline.required ? void 0 : raise?.message);
|
|
79
|
+
const notBlank = (value) => String(value ?? "").trim().length > 0 || message || false;
|
|
80
|
+
return {
|
|
81
|
+
required,
|
|
82
|
+
message,
|
|
83
|
+
rule: {
|
|
84
|
+
...mergeFieldValidator(rule, "notBlank", notBlank),
|
|
85
|
+
required: message ?? true
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const FieldContext = createContext(null);
|
|
90
|
+
/** Reads the field contract. Returns null when no binding is above the caller. */
|
|
91
|
+
function useField() {
|
|
92
|
+
return useContext(FieldContext);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Per (control, field name), the seed the *fieldset supplied* for that name — `contract.defaultValue`
|
|
96
|
+
* as handed down, not the value any one part narrowed it to before calling `resetField`. The
|
|
97
|
+
* distinction only shows up where the RFC says two parts may bind one name ("A fieldset registers
|
|
98
|
+
* once, collecting the field names its own children mount, refcounted so that a part remounting, or
|
|
99
|
+
* two parts binding one name, never unregisters a name still in use"): a text part and a checkbox
|
|
100
|
+
* part over the same name narrow one seed to two different types, so a ledger holding the narrowed
|
|
101
|
+
* value disagrees with itself on every render — neither part's entry ever satisfies the other's
|
|
102
|
+
* `seedsEqual` check, and the two reset each other forever. Keyed on what the fieldset supplied, both
|
|
103
|
+
* parts read the same entry, the first to run adopts and the rest skip. The second part's own
|
|
104
|
+
* `useController` registration still carries its own narrowing, so it reads dirty against a baseline
|
|
105
|
+
* it did not set — the honest outcome, and better than a hang.
|
|
106
|
+
*
|
|
107
|
+
* Keyed by the `control` object itself rather than by any `FieldBinding` component instance. Adoption is a
|
|
108
|
+
* property of the field name within this form, not of whichever component instance happens to be
|
|
109
|
+
* mounted right now: a fieldset's own conditional control (the `documentType` gate on
|
|
110
|
+
* `ClientProfileDocumentControl`, a country-descriptor swap in `ShippingAddressFieldset`) unmounts and
|
|
111
|
+
* remounts its `FieldBinding` with a brand-new instance that remembers nothing, while the shopper's
|
|
112
|
+
* edit survives the unmount in `control._formValues` — nothing in this codebase sets
|
|
113
|
+
* `shouldUnregister`. A `useRef` latch scoped to the instance cannot see that history and re-adopts the
|
|
114
|
+
* stale seed over the surviving edit; this ledger can, because it outlives the instance. A `WeakMap` so
|
|
115
|
+
* a form that itself unmounts (a fresh `useForm()` call, a fresh `control`) starts over empty, exactly
|
|
116
|
+
* as it should.
|
|
117
|
+
*
|
|
118
|
+
* A `Map` of seeds, not a `Set` of names: recording only that a name was adopted cannot distinguish a
|
|
119
|
+
* seed already in force from a different one that supersedes it, so a later `defaultValue` could never
|
|
120
|
+
* reach the form — that was the whole bug this ledger replaces. `has(name)` is read separately from
|
|
121
|
+
* `get(name)` everywhere below, so "never adopted" and "adopted `undefined`" stay distinguishable
|
|
122
|
+
* states.
|
|
123
|
+
*/
|
|
124
|
+
const adoptedSeeds = /* @__PURE__ */ new WeakMap();
|
|
125
|
+
function adoptedSeedsFor(control) {
|
|
126
|
+
let seeds = adoptedSeeds.get(control);
|
|
127
|
+
if (!seeds) {
|
|
128
|
+
seeds = /* @__PURE__ */ new Map();
|
|
129
|
+
adoptedSeeds.set(control, seeds);
|
|
130
|
+
}
|
|
131
|
+
return seeds;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Structural rather than referential equality between two seeds, mirroring `valuesEqual` in
|
|
135
|
+
* `form.tsx:128-130` and its documented reasoning: a field's seed is a primitive or plain record a
|
|
136
|
+
* bound Control's contract carries (a string, a boolean, a small object) — never a function or a
|
|
137
|
+
* circular structure — so a `JSON.stringify` comparison is a safe stand-in for a real deep-equal.
|
|
138
|
+
* Duplicated rather than imported: `field.tsx` imports nothing from `form.tsx`, and the particles are
|
|
139
|
+
* deliberately independent modules.
|
|
140
|
+
*
|
|
141
|
+
* `Object.is` is rejected here even though neither shipped shape's `normalise` (`TEXT_FIELD_VALUE`,
|
|
142
|
+
* `BOOLEAN_FIELD_VALUE`) can hand this function anything but a primitive today — this guard is
|
|
143
|
+
* defensive against a shape that does not exist yet, not against a reachable path. The day a shape's
|
|
144
|
+
* `normalise` returns a record or an array, a fieldset that hands out a freshly-allocated seed with
|
|
145
|
+
* the same content on every render would fail `Object.is` against itself, and the
|
|
146
|
+
* resetField → formState → render → resetField chain below would never terminate (measured: swapping
|
|
147
|
+
* in `Object.is` hung the suite past 150 seconds, until a render ceiling was added that turns the same
|
|
148
|
+
* mutation into a named failure in seconds). Do not remove this as dead code on the
|
|
149
|
+
* grounds that no object-shaped seed reaches it today — the regression test that pins it is
|
|
150
|
+
* `field.test.tsx`'s `'terminates when the seed is a fresh, structurally identical object literal on
|
|
151
|
+
* every render'`, which exercises `useSeedAdoption` through a test-only shape precisely because no
|
|
152
|
+
* shipped shape can.
|
|
153
|
+
*/
|
|
154
|
+
function seedsEqual(a, b) {
|
|
155
|
+
return a === b || JSON.stringify(a) === JSON.stringify(b);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* react-hook-form copies a per-field `defaultValue` into control._defaultValues only when
|
|
159
|
+
* shouldUnregister is set, which nothing here sets — so without this, the pristine comparison for a
|
|
160
|
+
* seeded field runs against `undefined` and any touched field stays dirty for good. Adopted once per
|
|
161
|
+
* (control, name) for a given seed, tracked in `adoptedSeeds`, which survives this component instance
|
|
162
|
+
* unmounting and remounting — so a remount with the same stale seed prop never overwrites a shopper's
|
|
163
|
+
* live edit, and a later, *different* seed reaches a field the shopper has not touched without the
|
|
164
|
+
* shopper having to reload the page.
|
|
165
|
+
*
|
|
166
|
+
* Called from `useBoundField`, not from `FieldBinding` (relocated, T57): the caller is now the very
|
|
167
|
+
* part whose own `useController` call registers `name`. `useController` calls `control.register(name,
|
|
168
|
+
* …)` from a `useRef` initialiser during the first render, and `register` adds to `_names.mount`
|
|
169
|
+
* synchronously — before that render returns, let alone before this effect's first run. So the mount
|
|
170
|
+
* guard below is satisfied on this effect's very first run for the caller's own name; the ordering
|
|
171
|
+
* `FieldBinding` could not rely on (a descendant control mounting on a *later* commit than the binding
|
|
172
|
+
* around it) no longer arises, because binder and adopter are now one and the same component instance.
|
|
173
|
+
* The T-5 test (`field.test.tsx`, a control that shows up on a later render than its enclosing
|
|
174
|
+
* `FieldBinding`) still passes — not because that race is still possible, but because nothing here
|
|
175
|
+
* special-cases it away: the guard simply reads true the one time it is asked.
|
|
176
|
+
*
|
|
177
|
+
* No dependency array all the same: this effect must still re-run on every render, because the guards
|
|
178
|
+
* below can otherwise miss their only remaining chance — the dirty-then-clean case. A seed arriving
|
|
179
|
+
* while the field is dirty is skipped by the third guard and never recorded; the only later signal that
|
|
180
|
+
* it can now be adopted is the field itself turning clean, which changes neither `name` nor the
|
|
181
|
+
* normalised seed this hook receives, so a dependency array keyed to its own arguments would never
|
|
182
|
+
* re-invoke it. Re-running on every render costs nothing extra here: every guard below but the
|
|
183
|
+
* adopting one is a no-op, and useFormContext() already forces a re-render on every formState emission
|
|
184
|
+
* regardless (Invariant 4 is violated in letter, not by this effect), so this adds no new re-render of
|
|
185
|
+
* its own.
|
|
186
|
+
*
|
|
187
|
+
* The first guard below is what does termination, not just correctness: react-hook-form rebuilds
|
|
188
|
+
* formState on every emission and FormProvider memoises its context value with formState in its own
|
|
189
|
+
* dependency list, so useFormContext()'s return value changes identity after every resetField call.
|
|
190
|
+
* Without that guard, that identity change would drive another render, which would call resetField
|
|
191
|
+
* again, which would change formState again — an unbounded loop. Its early return breaks it: once the
|
|
192
|
+
* ledger's recorded seed for this name is equal (by `seedsEqual`) to the current `defaultValue`, every
|
|
193
|
+
* further run for that name exits before reaching resetField — which is also why it must be the first
|
|
194
|
+
* check after the ledger lookup, ahead of even the mount guard.
|
|
195
|
+
*
|
|
196
|
+
* Precondition this re-seed relies on and does not itself enforce: `defaultValue` regressing to a
|
|
197
|
+
* reactive fragment's incomplete-read fallback once the field has already adopted real data.
|
|
198
|
+
* Probing this against `useReactiveEntity`'s fallback expression (`use-reactive-entity.ts:57`), mounting
|
|
199
|
+
* a clean field over real, complete data and then trying to make `fragmentResult.complete` flip back to
|
|
200
|
+
* false: measured as **reachable**, not merely suspected. Two of the three probes reproduced it —
|
|
201
|
+
* evicting a field the fragment selects (`cache.evict({ id, fieldName })`, then `cache.gc()`) and
|
|
202
|
+
* moving the root query's entity id to one never written to the cache (a session or orderForm change)
|
|
203
|
+
* both regress the read, and this effect cannot tell that apart from a genuine, saved change: the
|
|
204
|
+
* second probe blanked a clean control from "Ada" to "", and an independent audit reproduced it.
|
|
205
|
+
* `client.clearStore()` on a still-mounted, still-referenced entity did not reproduce it. The
|
|
206
|
+
* fieldsets close that gap above this hook: they withhold their controls until `useEntityDataResolved`
|
|
207
|
+
* reports their entity resolved, so a regressed read never reaches this effect through a fieldset.
|
|
208
|
+
*/
|
|
209
|
+
function useSeedAdoption(name, suppliedSeed, narrowedSeed) {
|
|
210
|
+
const form = useFormContext();
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (!form) return;
|
|
213
|
+
const seeds = adoptedSeedsFor(form.control);
|
|
214
|
+
if (seeds.has(name) && seedsEqual(seeds.get(name), suppliedSeed)) return;
|
|
215
|
+
if (!form.control._names.mount.has(name)) return;
|
|
216
|
+
if (seeds.has(name) && form.getFieldState(name).isDirty) return;
|
|
217
|
+
form.resetField(name, { defaultValue: narrowedSeed });
|
|
218
|
+
seeds.set(name, suppliedSeed);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function FieldBinding({ name, label, placeholder, defaultValue, rule, options, disabled, readOnly, autoComplete, inputMode, children }) {
|
|
222
|
+
const contract = useMemo(() => ({
|
|
223
|
+
name,
|
|
224
|
+
label,
|
|
225
|
+
placeholder,
|
|
226
|
+
defaultValue,
|
|
227
|
+
rule,
|
|
228
|
+
options,
|
|
229
|
+
disabled,
|
|
230
|
+
readOnly,
|
|
231
|
+
autoComplete,
|
|
232
|
+
inputMode
|
|
233
|
+
}), [
|
|
234
|
+
name,
|
|
235
|
+
label,
|
|
236
|
+
placeholder,
|
|
237
|
+
defaultValue,
|
|
238
|
+
rule,
|
|
239
|
+
options,
|
|
240
|
+
disabled,
|
|
241
|
+
readOnly,
|
|
242
|
+
autoComplete,
|
|
243
|
+
inputMode
|
|
244
|
+
]);
|
|
245
|
+
return /* @__PURE__ */ jsx(FieldContext.Provider, {
|
|
246
|
+
value: contract,
|
|
247
|
+
children
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/** A text-shaped bound field: empty is `''`, and a non-string seed narrows to `''`. */
|
|
251
|
+
const TEXT_FIELD_VALUE = {
|
|
252
|
+
empty: "",
|
|
253
|
+
normalise: (seed) => typeof seed === "string" ? seed : ""
|
|
254
|
+
};
|
|
255
|
+
/** A boolean-shaped bound field: empty is `false`, and any seed narrows through `Boolean(...)`. */
|
|
256
|
+
const BOOLEAN_FIELD_VALUE = {
|
|
257
|
+
empty: false,
|
|
258
|
+
normalise: (seed) => Boolean(seed)
|
|
259
|
+
};
|
|
260
|
+
/**
|
|
261
|
+
* The only caller of `useController` in this package (I-1). Registers the field with react-hook-form,
|
|
262
|
+
* adopts the same normalised seed as the dirty baseline (Decision 1), and registers a clearer that
|
|
263
|
+
* writes the shape's own empty value for as long as the part stays mounted (FR-5) — three facts a
|
|
264
|
+
* bound part previously scattered across its own call site, `FieldBinding` and `FormClear`.
|
|
265
|
+
*
|
|
266
|
+
* The effective rule is `rule ?? contract.rule`: a part with no rule of its own (`BoundFieldControl`,
|
|
267
|
+
* `BoundFieldCheckbox`, `BoundFieldSelectRoot`) falls back to the contract's; `BoundPhoneField` and
|
|
268
|
+
* `BoundDocumentField` pass their own `useMemo`-derived rule, which already merges the particle's
|
|
269
|
+
* format check into `contract.rule` rather than replacing it.
|
|
270
|
+
*
|
|
271
|
+
* Requiredness resolves here rather than at each call site (FR: one chokepoint), so no bound control
|
|
272
|
+
* can register a rule whose enforcement and announcement disagree, or forget the blank check. A
|
|
273
|
+
* control that wants its field required passes a `raise`; only `FieldSelectTrigger`, which announces
|
|
274
|
+
* from a different component than the one that binds, calls `resolveRequiredness` for itself.
|
|
275
|
+
*/
|
|
276
|
+
function useBoundField(contract, shape, rule, raise) {
|
|
277
|
+
const { control, setValue } = useFormContext();
|
|
278
|
+
const raiseRequired = raise?.required;
|
|
279
|
+
const raiseMessage = raise?.message;
|
|
280
|
+
const requiredness = useMemo(() => resolveRequiredness(rule ?? contract.rule, {
|
|
281
|
+
required: raiseRequired,
|
|
282
|
+
message: raiseMessage
|
|
283
|
+
}), [
|
|
284
|
+
rule,
|
|
285
|
+
contract.rule,
|
|
286
|
+
raiseRequired,
|
|
287
|
+
raiseMessage
|
|
288
|
+
]);
|
|
289
|
+
const seed = shape.normalise(contract.defaultValue);
|
|
290
|
+
const { field } = useController({
|
|
291
|
+
name: contract.name,
|
|
292
|
+
rules: toRegisterOptions(requiredness.rule),
|
|
293
|
+
defaultValue: seed
|
|
294
|
+
});
|
|
295
|
+
useSeedAdoption(contract.name, contract.defaultValue, seed);
|
|
296
|
+
useEffect(() => registerFieldClearer(control, contract.name, () => setValue(contract.name, shape.empty, { shouldDirty: true })), [
|
|
297
|
+
control,
|
|
298
|
+
contract.name,
|
|
299
|
+
setValue,
|
|
300
|
+
shape.empty
|
|
301
|
+
]);
|
|
302
|
+
return {
|
|
303
|
+
...field,
|
|
304
|
+
required: requiredness.required
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/** Exported so those tasks import it rather than redefine it. */
|
|
308
|
+
const FieldsetFieldContext = createContext(null);
|
|
309
|
+
/** Unchanged: the registry above the caller, or null. Now carrying a namespace. */
|
|
310
|
+
function useFieldsetContext() {
|
|
311
|
+
return useContext(FieldsetFieldContext);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Registers `${namespace}.${key}` with the enclosing fieldset while the caller is mounted, and returns
|
|
315
|
+
* that full name. Throws during render when a registry is above the caller and declares a different
|
|
316
|
+
* namespace. Registers nothing and throws nothing when no registry is above. Holds no state: the
|
|
317
|
+
* refcount belongs to the provider.
|
|
318
|
+
*/
|
|
319
|
+
function useFieldsetField(namespace, key) {
|
|
320
|
+
const registry = useFieldsetContext();
|
|
321
|
+
const name = `${namespace}.${key}`;
|
|
322
|
+
if (registry && registry.namespace !== namespace) throw new Error(`A control asked to register "${name}", but the fieldset registry above it owns the namespace "${registry.namespace}". A registry serves exactly one namespace, declared by the fieldset that provides it.`);
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
if (!registry) return;
|
|
325
|
+
return registry.registerFieldName(name);
|
|
326
|
+
}, [registry, name]);
|
|
327
|
+
return name;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* The field-name bookkeeping a fieldset provides. Refcounted, so two callers of one name collapse to one
|
|
331
|
+
* entry however they arrived — including a caller that reaches `registerFieldName` directly.
|
|
332
|
+
*/
|
|
333
|
+
function useFieldsetFieldNames(namespace) {
|
|
334
|
+
const counts = useRef(/* @__PURE__ */ new Map());
|
|
335
|
+
const registerFieldName = useCallback((name) => {
|
|
336
|
+
counts.current.set(name, (counts.current.get(name) ?? 0) + 1);
|
|
337
|
+
let released = false;
|
|
338
|
+
return () => {
|
|
339
|
+
if (released) return;
|
|
340
|
+
released = true;
|
|
341
|
+
const remaining = (counts.current.get(name) ?? 0) - 1;
|
|
342
|
+
if (remaining > 0) counts.current.set(name, remaining);
|
|
343
|
+
else counts.current.delete(name);
|
|
344
|
+
};
|
|
345
|
+
}, []);
|
|
346
|
+
const getFieldNames = useCallback(() => Array.from(counts.current.keys()), []);
|
|
347
|
+
return {
|
|
348
|
+
registry: useMemo(() => ({
|
|
349
|
+
namespace,
|
|
350
|
+
registerFieldName
|
|
351
|
+
}), [namespace, registerFieldName]),
|
|
352
|
+
getFieldNames
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Throws during render when an ancestor fieldset is already providing field registration for this
|
|
357
|
+
* subtree. Every fieldset calls it in one line.
|
|
358
|
+
*/
|
|
359
|
+
function useNoAncestorFieldset(componentName) {
|
|
360
|
+
const ancestor = useFieldsetContext();
|
|
361
|
+
if (ancestor) throw new Error(`${componentName} cannot be nested inside another fieldset. An ancestor fieldset owning the namespace "${ancestor.namespace}" already provides field registration for this subtree, so this fieldset's controls would register under that namespace instead of their own. Compose fieldsets as siblings under the same FormRoot instead of nesting them.`);
|
|
362
|
+
}
|
|
7
363
|
const FieldRootDefinition = defineComponent({
|
|
8
364
|
name: "FieldRoot",
|
|
9
365
|
importPath: "@vtex/faststore/components",
|
|
10
366
|
component: FieldRoot,
|
|
367
|
+
providesContext: "field",
|
|
11
368
|
editor: {
|
|
12
369
|
label: "Field Root",
|
|
13
370
|
category: "layout"
|
|
@@ -17,34 +374,37 @@ const FieldRootDefinition = defineComponent({
|
|
|
17
374
|
default: false,
|
|
18
375
|
label: "Disabled"
|
|
19
376
|
} },
|
|
20
|
-
guideline: "Form field container that connects a label, input, and validation messages via ARIA. Use Field.Control as the input element, or place a compatible Base UI input (Input, Checkbox, Select) as a direct child. Set invalid=true to trigger Field.Error display."
|
|
377
|
+
guideline: "Form field container that connects a label, input, and validation messages via ARIA. Use Field.Control as the input element, or place a compatible Base UI input (Input, Checkbox, Select) as a direct child. Set invalid=true to trigger Field.Error display. Wrapping a bound Control feeds invalid/dirty/touched from react-hook-form automatically."
|
|
21
378
|
});
|
|
22
379
|
const FieldLabelDefinition = defineComponent({
|
|
23
380
|
name: "FieldLabel",
|
|
24
381
|
importPath: "@vtex/faststore/components",
|
|
25
382
|
component: FieldLabel,
|
|
383
|
+
requiresContext: "field",
|
|
26
384
|
editor: {
|
|
27
385
|
label: "Field Label",
|
|
28
386
|
category: "layout"
|
|
29
387
|
},
|
|
30
388
|
schema: {},
|
|
31
|
-
guideline: "Accessible label inside Field.Root. Automatically associated with Field.Control's input via ARIA. Place before Field.Control in the DOM."
|
|
389
|
+
guideline: "Accessible label inside Field.Root. Automatically associated with Field.Control's input via ARIA. Place before Field.Control in the DOM. Under a bound Control, a childless Field.Label renders the field contract's label."
|
|
32
390
|
});
|
|
33
391
|
const FieldControlDefinition = defineComponent({
|
|
34
392
|
name: "FieldControl",
|
|
35
393
|
importPath: "@vtex/faststore/components",
|
|
36
394
|
component: FieldControl,
|
|
395
|
+
requiresContext: "field",
|
|
37
396
|
editor: {
|
|
38
397
|
label: "Field Control",
|
|
39
398
|
category: "layout"
|
|
40
399
|
},
|
|
41
400
|
schema: {},
|
|
42
|
-
guideline: "Renders a native `<input>` element directly. It IS the input — do not place any child inside it. Pass input attributes (type, placeholder, required, etc.) directly as props. It is automatically linked to Field.Label and Field.Error via ARIA."
|
|
401
|
+
guideline: "Renders a native `<input>` element directly. It IS the input — do not place any child inside it. Pass input attributes (type, placeholder, required, etc.) directly as props. It is automatically linked to Field.Label and Field.Error via ARIA. Under a bound Control, it registers with react-hook-form using the field contract's name, seed value, and validation rule."
|
|
43
402
|
});
|
|
44
403
|
const FieldDescriptionDefinition = defineComponent({
|
|
45
404
|
name: "FieldDescription",
|
|
46
405
|
importPath: "@vtex/faststore/components",
|
|
47
406
|
component: FieldDescription,
|
|
407
|
+
requiresContext: "field",
|
|
48
408
|
editor: {
|
|
49
409
|
label: "Field Description",
|
|
50
410
|
category: "layout"
|
|
@@ -56,17 +416,19 @@ const FieldErrorDefinition = defineComponent({
|
|
|
56
416
|
name: "FieldError",
|
|
57
417
|
importPath: "@vtex/faststore/components",
|
|
58
418
|
component: FieldError,
|
|
419
|
+
requiresContext: "field",
|
|
59
420
|
editor: {
|
|
60
421
|
label: "Field Error",
|
|
61
422
|
category: "layout"
|
|
62
423
|
},
|
|
63
424
|
schema: {},
|
|
64
|
-
guideline: "Validation error message inside Field.Root. Shown when the field is in an invalid state. Linked to the control via aria-describedby."
|
|
425
|
+
guideline: "Validation error message inside Field.Root. Shown when the field is in an invalid state. Linked to the control via aria-describedby. Under a bound Control, it renders react-hook-form's error message for the field contract's name."
|
|
65
426
|
});
|
|
66
427
|
const FieldValidityDefinition = defineComponent({
|
|
67
428
|
name: "FieldValidity",
|
|
68
429
|
importPath: "@vtex/faststore/components",
|
|
69
430
|
component: FieldValidity,
|
|
431
|
+
requiresContext: "field",
|
|
70
432
|
editor: {
|
|
71
433
|
label: "Field Validity",
|
|
72
434
|
category: "layout"
|
|
@@ -74,7 +436,30 @@ const FieldValidityDefinition = defineComponent({
|
|
|
74
436
|
schema: {},
|
|
75
437
|
guideline: "Validation feedback slot using a render prop for custom messages derived from the field's validity state. Use for dynamic messages when Field.Error text is not fixed."
|
|
76
438
|
});
|
|
439
|
+
const FieldCheckboxDefinition = defineComponent({
|
|
440
|
+
name: "FieldCheckbox",
|
|
441
|
+
importPath: "@vtex/faststore/components",
|
|
442
|
+
component: FieldCheckbox,
|
|
443
|
+
requiresContext: "field",
|
|
444
|
+
editor: {
|
|
445
|
+
label: "Field Checkbox",
|
|
446
|
+
category: "action"
|
|
447
|
+
},
|
|
448
|
+
schema: {},
|
|
449
|
+
guideline: "Bound boolean control over the shipped Checkbox particle: reads the enclosing field contract and drives Checkbox.Root through react-hook-form. Compose Checkbox.Indicator as a child for the visual check mark. Place inside Field.Root, the only ancestor that provides the field context it requires today — a bound Control will satisfy it too, once one ships."
|
|
450
|
+
});
|
|
77
451
|
function FieldRoot({ disabled, invalid, name, className, children, ...props }) {
|
|
452
|
+
const contract = useField();
|
|
453
|
+
const formContext = useFormContext();
|
|
454
|
+
if (contract && formContext) return /* @__PURE__ */ jsx(BoundFieldRoot, {
|
|
455
|
+
...props,
|
|
456
|
+
contract,
|
|
457
|
+
disabled,
|
|
458
|
+
invalid,
|
|
459
|
+
name,
|
|
460
|
+
className,
|
|
461
|
+
children
|
|
462
|
+
});
|
|
78
463
|
return /* @__PURE__ */ jsx(Field.Root, {
|
|
79
464
|
...props,
|
|
80
465
|
disabled,
|
|
@@ -85,7 +470,31 @@ function FieldRoot({ disabled, invalid, name, className, children, ...props }) {
|
|
|
85
470
|
children
|
|
86
471
|
});
|
|
87
472
|
}
|
|
473
|
+
function BoundFieldRoot({ contract, disabled, invalid, name, className, children, ...props }) {
|
|
474
|
+
const { getFieldState, control } = useFormContext();
|
|
475
|
+
const { invalid: rhfInvalid, isDirty, isTouched } = getFieldState(contract.name, useFormState({ name: contract.name }));
|
|
476
|
+
const isRegistered = control._names.mount.has(contract.name);
|
|
477
|
+
return /* @__PURE__ */ jsx(Field.Root, {
|
|
478
|
+
...props,
|
|
479
|
+
name: name ?? contract.name,
|
|
480
|
+
disabled: disabled ?? contract.disabled,
|
|
481
|
+
invalid: invalid ?? rhfInvalid,
|
|
482
|
+
dirty: isRegistered ? isDirty : void 0,
|
|
483
|
+
touched: isRegistered ? isTouched : void 0,
|
|
484
|
+
className,
|
|
485
|
+
"data-fs-field-root": "",
|
|
486
|
+
children
|
|
487
|
+
});
|
|
488
|
+
}
|
|
88
489
|
function FieldLabel({ className, children, ...props }) {
|
|
490
|
+
const contract = useField();
|
|
491
|
+
const formContext = useFormContext();
|
|
492
|
+
if (contract && formContext) return /* @__PURE__ */ jsx(BoundFieldLabel, {
|
|
493
|
+
...props,
|
|
494
|
+
contract,
|
|
495
|
+
className,
|
|
496
|
+
children
|
|
497
|
+
});
|
|
89
498
|
return /* @__PURE__ */ jsx(Field.Label, {
|
|
90
499
|
...props,
|
|
91
500
|
className,
|
|
@@ -93,9 +502,43 @@ function FieldLabel({ className, children, ...props }) {
|
|
|
93
502
|
children
|
|
94
503
|
});
|
|
95
504
|
}
|
|
505
|
+
function BoundFieldLabel({ contract, className, children, ...props }) {
|
|
506
|
+
return /* @__PURE__ */ jsx(Field.Label, {
|
|
507
|
+
...props,
|
|
508
|
+
className,
|
|
509
|
+
"data-fs-field-label": "",
|
|
510
|
+
children: children ?? contract.label
|
|
511
|
+
});
|
|
512
|
+
}
|
|
96
513
|
function FieldControl({ className, ...props }) {
|
|
514
|
+
const contract = useField();
|
|
515
|
+
const formContext = useFormContext();
|
|
516
|
+
if (contract && formContext) return /* @__PURE__ */ jsx(BoundFieldControl, {
|
|
517
|
+
...props,
|
|
518
|
+
contract,
|
|
519
|
+
className
|
|
520
|
+
});
|
|
521
|
+
return /* @__PURE__ */ jsx(Field.Control, {
|
|
522
|
+
...props,
|
|
523
|
+
className,
|
|
524
|
+
"data-fs-field-control": ""
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
function BoundFieldControl({ contract, placeholder, disabled, readOnly, autoComplete, inputMode, className, ...props }) {
|
|
528
|
+
const field = useBoundField(contract, TEXT_FIELD_VALUE);
|
|
97
529
|
return /* @__PURE__ */ jsx(Field.Control, {
|
|
98
530
|
...props,
|
|
531
|
+
name: field.name,
|
|
532
|
+
value: field.value,
|
|
533
|
+
onChange: field.onChange,
|
|
534
|
+
onBlur: field.onBlur,
|
|
535
|
+
ref: field.ref,
|
|
536
|
+
placeholder: placeholder ?? contract.placeholder,
|
|
537
|
+
disabled: disabled ?? contract.disabled,
|
|
538
|
+
readOnly: readOnly ?? contract.readOnly,
|
|
539
|
+
autoComplete: autoComplete ?? contract.autoComplete,
|
|
540
|
+
inputMode: inputMode ?? contract.inputMode,
|
|
541
|
+
"aria-required": field.required || void 0,
|
|
99
542
|
className,
|
|
100
543
|
"data-fs-field-control": ""
|
|
101
544
|
});
|
|
@@ -109,6 +552,14 @@ function FieldDescription({ className, children, ...props }) {
|
|
|
109
552
|
});
|
|
110
553
|
}
|
|
111
554
|
function FieldError({ className, children, ...props }) {
|
|
555
|
+
const contract = useField();
|
|
556
|
+
const formContext = useFormContext();
|
|
557
|
+
if (contract && formContext) return /* @__PURE__ */ jsx(BoundFieldError, {
|
|
558
|
+
...props,
|
|
559
|
+
contract,
|
|
560
|
+
className,
|
|
561
|
+
children
|
|
562
|
+
});
|
|
112
563
|
return /* @__PURE__ */ jsx(Field.Error, {
|
|
113
564
|
...props,
|
|
114
565
|
className,
|
|
@@ -116,18 +567,58 @@ function FieldError({ className, children, ...props }) {
|
|
|
116
567
|
children
|
|
117
568
|
});
|
|
118
569
|
}
|
|
570
|
+
function BoundFieldError({ contract, className, children, match: _match, ...props }) {
|
|
571
|
+
const { getFieldState } = useFormContext();
|
|
572
|
+
const { error } = getFieldState(contract.name, useFormState({ name: contract.name }));
|
|
573
|
+
if (!error) return null;
|
|
574
|
+
if (!children && !error.message) return null;
|
|
575
|
+
return /* @__PURE__ */ jsx(Field.Error, {
|
|
576
|
+
...props,
|
|
577
|
+
match: true,
|
|
578
|
+
className,
|
|
579
|
+
"data-fs-field-error": "",
|
|
580
|
+
children: children ?? error.message
|
|
581
|
+
});
|
|
582
|
+
}
|
|
119
583
|
function FieldValidity({ children }) {
|
|
120
584
|
return /* @__PURE__ */ jsx(Field.Validity, { children });
|
|
121
585
|
}
|
|
586
|
+
function FieldCheckbox({ className, children }) {
|
|
587
|
+
const contract = useField();
|
|
588
|
+
const formContext = useFormContext();
|
|
589
|
+
if (contract && formContext) return /* @__PURE__ */ jsx(BoundFieldCheckbox, {
|
|
590
|
+
contract,
|
|
591
|
+
className,
|
|
592
|
+
children
|
|
593
|
+
});
|
|
594
|
+
return /* @__PURE__ */ jsx(Checkbox.Root, {
|
|
595
|
+
className,
|
|
596
|
+
children
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
function BoundFieldCheckbox({ contract, className, children }) {
|
|
600
|
+
const field = useBoundField(contract, BOOLEAN_FIELD_VALUE);
|
|
601
|
+
return /* @__PURE__ */ jsx(Checkbox.Root, {
|
|
602
|
+
checked: field.value,
|
|
603
|
+
onCheckedChange: field.onChange,
|
|
604
|
+
onBlur: field.onBlur,
|
|
605
|
+
ref: field.ref,
|
|
606
|
+
disabled: contract.disabled,
|
|
607
|
+
className,
|
|
608
|
+
"data-fs-field-checkbox": "",
|
|
609
|
+
children
|
|
610
|
+
});
|
|
611
|
+
}
|
|
122
612
|
const Field$1 = {
|
|
123
613
|
Root: FieldRoot,
|
|
124
614
|
Label: FieldLabel,
|
|
125
615
|
Control: FieldControl,
|
|
126
616
|
Description: FieldDescription,
|
|
127
617
|
Error: FieldError,
|
|
128
|
-
Validity: FieldValidity
|
|
618
|
+
Validity: FieldValidity,
|
|
619
|
+
Checkbox: FieldCheckbox
|
|
129
620
|
};
|
|
130
621
|
//#endregion
|
|
131
|
-
export { Field$1 as Field, FieldControl, FieldControlDefinition, FieldDescription, FieldDescriptionDefinition, FieldError, FieldErrorDefinition, FieldLabel, FieldLabelDefinition, FieldRoot, FieldRootDefinition, FieldValidity, FieldValidityDefinition };
|
|
622
|
+
export { BOOLEAN_FIELD_VALUE, Field$1 as Field, FieldBinding, FieldCheckbox, FieldCheckboxDefinition, FieldControl, FieldControlDefinition, FieldDescription, FieldDescriptionDefinition, FieldError, FieldErrorDefinition, FieldLabel, FieldLabelDefinition, FieldRoot, FieldRootDefinition, FieldValidity, FieldValidityDefinition, FieldsetFieldContext, TEXT_FIELD_VALUE, mergeFieldValidator, resolveRequiredness, useBoundField, useField, useFieldsetContext, useFieldsetField, useFieldsetFieldNames, useNoAncestorFieldset };
|
|
132
623
|
|
|
133
624
|
//# sourceMappingURL=field.js.map
|