@thorprovider/blocks 3.0.2 → 4.1.0
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 +61 -21
- package/dist/blocks/designs/checkout-commerce-v1/block.d.ts +49 -0
- package/dist/blocks/designs/checkout-commerce-v1/block.d.ts.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/block.js +2487 -0
- package/dist/blocks/designs/checkout-commerce-v1/block.js.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/block.mjs +2467 -0
- package/dist/blocks/designs/checkout-commerce-v1/block.mjs.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/data-context.d.ts +8 -0
- package/dist/blocks/designs/checkout-commerce-v1/data-context.d.ts.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/data-context.js +44 -0
- package/dist/blocks/designs/checkout-commerce-v1/data-context.js.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/data-context.mjs +19 -0
- package/dist/blocks/designs/checkout-commerce-v1/data-context.mjs.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/index.d.ts +3 -0
- package/dist/blocks/designs/checkout-commerce-v1/index.d.ts.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/index.js +36 -0
- package/dist/blocks/designs/checkout-commerce-v1/index.js.map +1 -0
- package/dist/blocks/designs/checkout-commerce-v1/index.mjs +6 -0
- package/dist/blocks/designs/checkout-commerce-v1/index.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/block.d.ts +12 -0
- package/dist/blocks/designs/marketplace-product-card/block.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/block.js +243 -0
- package/dist/blocks/designs/marketplace-product-card/block.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/block.mjs +233 -0
- package/dist/blocks/designs/marketplace-product-card/block.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/index.d.ts +3 -0
- package/dist/blocks/designs/marketplace-product-card/index.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/index.js +36 -0
- package/dist/blocks/designs/marketplace-product-card/index.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/index.mjs +6 -0
- package/dist/blocks/designs/marketplace-product-card/index.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.d.ts +13 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.js +36 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.mjs +12 -0
- package/dist/blocks/designs/marketplace-product-card/normalize.mjs.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/variants.d.ts +72 -0
- package/dist/blocks/designs/marketplace-product-card/variants.d.ts.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/variants.js +123 -0
- package/dist/blocks/designs/marketplace-product-card/variants.js.map +1 -0
- package/dist/blocks/designs/marketplace-product-card/variants.mjs +89 -0
- package/dist/blocks/designs/marketplace-product-card/variants.mjs.map +1 -0
- package/dist/blocks/e-commerce/account/account-frame.d.ts +38 -0
- package/dist/blocks/e-commerce/account/account-frame.d.ts.map +1 -0
- package/dist/blocks/e-commerce/account/account-frame.js +102 -0
- package/dist/blocks/e-commerce/account/account-frame.js.map +1 -0
- package/dist/blocks/e-commerce/account/account-frame.mjs +78 -0
- package/dist/blocks/e-commerce/account/account-frame.mjs.map +1 -0
- package/dist/blocks/e-commerce/account/address-book.d.ts +79 -0
- package/dist/blocks/e-commerce/account/address-book.d.ts.map +1 -0
- package/dist/blocks/e-commerce/account/address-book.js +250 -0
- package/dist/blocks/e-commerce/account/address-book.js.map +1 -0
- package/dist/blocks/e-commerce/account/address-book.mjs +225 -0
- package/dist/blocks/e-commerce/account/address-book.mjs.map +1 -0
- package/dist/blocks/e-commerce/account/profile-form.d.ts +35 -0
- package/dist/blocks/e-commerce/account/profile-form.d.ts.map +1 -0
- package/dist/blocks/e-commerce/account/profile-form.js +100 -0
- package/dist/blocks/e-commerce/account/profile-form.js.map +1 -0
- package/dist/blocks/e-commerce/account/profile-form.mjs +76 -0
- package/dist/blocks/e-commerce/account/profile-form.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.js +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.mjs +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkbox-check.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.d.ts +11 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.js +46 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.mjs +22 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-equality.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.d.ts +28 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.js +278 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.mjs +260 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-address-fields.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.d.ts +12 -9
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.js +49 -71
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.mjs +50 -72
- package/dist/blocks/e-commerce/checkout-forms/checkout-contact-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.js +6 -3
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.mjs +6 -3
- package/dist/blocks/e-commerce/checkout-forms/checkout-country-field.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.d.ts +7 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.js +41 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.mjs +16 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-id-context.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.d.ts +24 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.js +75 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.mjs +58 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-location-select.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.d.ts +3 -2
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.js +9 -2
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.mjs +9 -2
- package/dist/blocks/e-commerce/checkout-forms/checkout-order-summary.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.d.ts +23 -8
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.js +136 -31
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.mjs +143 -32
- package/dist/blocks/e-commerce/checkout-forms/checkout-payment-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.d.ts +13 -7
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.js +179 -28
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.mjs +180 -29
- package/dist/blocks/e-commerce/checkout-forms/checkout-review-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.d.ts +20 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.js +199 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.mjs +175 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-saved-addresses.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.d.ts +14 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.js +136 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.mjs +109 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-section-nav.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.d.ts +32 -10
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.js +265 -147
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.mjs +272 -148
- package/dist/blocks/e-commerce/checkout-forms/checkout-shipping-step.mjs.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.d.ts +13 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.js +74 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.mjs +50 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-header.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.d.ts +7 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.d.ts.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.js +91 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.js.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.mjs +65 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout-step-summary.mjs.map +1 -0
- package/dist/blocks/e-commerce/checkout-forms/checkout.d.ts +174 -44
- package/dist/blocks/e-commerce/checkout-forms/checkout.d.ts.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout.js +532 -108
- package/dist/blocks/e-commerce/checkout-forms/checkout.js.map +1 -1
- package/dist/blocks/e-commerce/checkout-forms/checkout.mjs +542 -109
- package/dist/blocks/e-commerce/checkout-forms/checkout.mjs.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.d.ts.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.js +44 -20
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.js.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.mjs +44 -20
- package/dist/blocks/e-commerce/navigation/storefront-navbar-cart-sheet.mjs.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar.d.ts.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar.js +21 -10
- package/dist/blocks/e-commerce/navigation/storefront-navbar.js.map +1 -1
- package/dist/blocks/e-commerce/navigation/storefront-navbar.mjs +21 -10
- package/dist/blocks/e-commerce/navigation/storefront-navbar.mjs.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-card.d.ts.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-card.js +36 -9
- package/dist/blocks/e-commerce/product-list/product-card.js.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-card.mjs +36 -9
- package/dist/blocks/e-commerce/product-list/product-card.mjs.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-showcase-1.d.ts.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-showcase-1.js +7 -2
- package/dist/blocks/e-commerce/product-list/product-showcase-1.js.map +1 -1
- package/dist/blocks/e-commerce/product-list/product-showcase-1.mjs +7 -2
- package/dist/blocks/e-commerce/product-list/product-showcase-1.mjs.map +1 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.d.ts.map +1 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.js +5 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.js.map +1 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.mjs +5 -1
- package/dist/blocks/e-commerce/product-overview/product-quick-view-dialog.mjs.map +1 -1
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.d.ts.map +1 -1
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.js +71 -51
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.js.map +1 -1
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.mjs +71 -51
- package/dist/blocks/e-commerce/storefront-hero/storefront-hero.mjs.map +1 -1
- package/dist/blocks/marketing/banners/banner-1.d.ts.map +1 -1
- package/dist/blocks/marketing/banners/banner-1.js +15 -27
- package/dist/blocks/marketing/banners/banner-1.js.map +1 -1
- package/dist/blocks/marketing/banners/banner-1.mjs +16 -28
- package/dist/blocks/marketing/banners/banner-1.mjs.map +1 -1
- package/dist/index.d.ts +16 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -0
- package/dist/index.mjs.map +1 -1
- package/dist/lib/contracts/checkout-commerce-v1.d.ts +2350 -0
- package/dist/lib/contracts/checkout-commerce-v1.d.ts.map +1 -0
- package/dist/lib/contracts/checkout-commerce-v1.js +417 -0
- package/dist/lib/contracts/checkout-commerce-v1.js.map +1 -0
- package/dist/lib/contracts/checkout-commerce-v1.mjs +392 -0
- package/dist/lib/contracts/checkout-commerce-v1.mjs.map +1 -0
- package/dist/lib/contracts/marketplace-product-card.d.ts +324 -0
- package/dist/lib/contracts/marketplace-product-card.d.ts.map +1 -0
- package/dist/lib/contracts/marketplace-product-card.js +85 -0
- package/dist/lib/contracts/marketplace-product-card.js.map +1 -0
- package/dist/lib/contracts/marketplace-product-card.mjs +61 -0
- package/dist/lib/contracts/marketplace-product-card.mjs.map +1 -0
- package/dist/lib/contracts.d.ts +2289 -178
- package/dist/lib/contracts.d.ts.map +1 -1
- package/dist/lib/contracts.js +332 -25
- package/dist/lib/contracts.js.map +1 -1
- package/dist/lib/contracts.mjs +278 -5
- package/dist/lib/contracts.mjs.map +1 -1
- package/dist/lib/money-schema.d.ts +19 -0
- package/dist/lib/money-schema.d.ts.map +1 -0
- package/dist/lib/money-schema.js +33 -0
- package/dist/lib/money-schema.js.map +1 -0
- package/dist/lib/money-schema.mjs +9 -0
- package/dist/lib/money-schema.mjs.map +1 -0
- package/dist/lib/motion.d.ts +29 -0
- package/dist/lib/motion.d.ts.map +1 -0
- package/dist/lib/motion.js +65 -0
- package/dist/lib/motion.js.map +1 -0
- package/dist/lib/motion.mjs +41 -0
- package/dist/lib/motion.mjs.map +1 -0
- package/dist/ui/accordion.d.ts +3 -1
- package/dist/ui/accordion.d.ts.map +1 -1
- package/dist/ui/accordion.js +21 -5
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/accordion.mjs +21 -5
- package/dist/ui/accordion.mjs.map +1 -1
- package/dist/ui/input-group.d.ts +1 -1
- package/package.json +18 -3
- package/dist/.tsbuildinfo +0 -1
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { Badge } from "../../../ui/badge.mjs";
|
|
5
|
+
import { Button } from "../../../ui/button.mjs";
|
|
6
|
+
import { Card, CardContent, CardHeader, CardTitle } from "../../../ui/card.mjs";
|
|
7
|
+
import { Field, FieldGroup, FieldLabel } from "../../../ui/field.mjs";
|
|
8
|
+
import { Input } from "../../../ui/input.mjs";
|
|
9
|
+
import { cn } from "../../../lib/utils.mjs";
|
|
10
|
+
const defaultLabels = {
|
|
11
|
+
title: "Direcciones",
|
|
12
|
+
description: "Direcciones guardadas para tus pedidos.",
|
|
13
|
+
emptyLabel: "A\xFAn no tienes direcciones guardadas.",
|
|
14
|
+
addLabel: "A\xF1adir direcci\xF3n",
|
|
15
|
+
editLabel: "Editar",
|
|
16
|
+
deleteLabel: "Eliminar",
|
|
17
|
+
confirmDeleteLabel: "\xBFEliminar esta direcci\xF3n?",
|
|
18
|
+
cancelLabel: "Cancelar",
|
|
19
|
+
defaultShippingLabel: "Env\xEDo predeterminado",
|
|
20
|
+
defaultBillingLabel: "Facturaci\xF3n predeterminada",
|
|
21
|
+
setDefaultShippingLabel: "Usar para env\xEDo",
|
|
22
|
+
setDefaultBillingLabel: "Usar para facturaci\xF3n"
|
|
23
|
+
};
|
|
24
|
+
function AddressEntry({
|
|
25
|
+
address,
|
|
26
|
+
copy,
|
|
27
|
+
onEdit,
|
|
28
|
+
onDelete,
|
|
29
|
+
onSetDefaultShipping,
|
|
30
|
+
onSetDefaultBilling
|
|
31
|
+
}) {
|
|
32
|
+
const [confirming, setConfirming] = useState(false);
|
|
33
|
+
const containerRef = useRef(null);
|
|
34
|
+
return /* @__PURE__ */ jsx(
|
|
35
|
+
"li",
|
|
36
|
+
{
|
|
37
|
+
ref: containerRef,
|
|
38
|
+
tabIndex: -1,
|
|
39
|
+
"data-slot": "address-book-entry",
|
|
40
|
+
className: "focus-visible:ring-ring rounded-lg outline-none focus-visible:ring-2",
|
|
41
|
+
children: /* @__PURE__ */ jsxs(Card, { children: [
|
|
42
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "flex flex-row items-start justify-between gap-4", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
43
|
+
/* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: address.recipientName }),
|
|
44
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [
|
|
45
|
+
address.isDefaultShipping ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: copy.defaultShippingLabel }) : null,
|
|
46
|
+
address.isDefaultBilling ? /* @__PURE__ */ jsx(Badge, { variant: "outline", children: copy.defaultBillingLabel }) : null
|
|
47
|
+
] })
|
|
48
|
+
] }) }),
|
|
49
|
+
/* @__PURE__ */ jsxs(CardContent, { children: [
|
|
50
|
+
/* @__PURE__ */ jsx("address", { className: "text-muted-foreground text-sm not-italic", children: address.lines.map((line, index) => /* @__PURE__ */ jsx("span", { className: "block", children: line }, `${address.id}:${index}`)) }),
|
|
51
|
+
confirming ? /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-wrap items-center gap-2", role: "group", "aria-label": copy.confirmDeleteLabel, children: [
|
|
52
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm", children: copy.confirmDeleteLabel }),
|
|
53
|
+
/* @__PURE__ */ jsx(
|
|
54
|
+
Button,
|
|
55
|
+
{
|
|
56
|
+
type: "button",
|
|
57
|
+
variant: "destructive",
|
|
58
|
+
size: "sm",
|
|
59
|
+
onClick: () => {
|
|
60
|
+
onDelete?.(address.id);
|
|
61
|
+
setConfirming(false);
|
|
62
|
+
containerRef.current?.focus();
|
|
63
|
+
},
|
|
64
|
+
children: copy.deleteLabel
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setConfirming(false), children: copy.cancelLabel })
|
|
68
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-wrap gap-2", children: [
|
|
69
|
+
onEdit ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onEdit(address.id), children: copy.editLabel }) : null,
|
|
70
|
+
onDelete ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setConfirming(true), children: copy.deleteLabel }) : null,
|
|
71
|
+
onSetDefaultShipping && !address.isDefaultShipping ? /* @__PURE__ */ jsx(
|
|
72
|
+
Button,
|
|
73
|
+
{
|
|
74
|
+
type: "button",
|
|
75
|
+
variant: "ghost",
|
|
76
|
+
size: "sm",
|
|
77
|
+
onClick: () => onSetDefaultShipping(address.id),
|
|
78
|
+
children: copy.setDefaultShippingLabel
|
|
79
|
+
}
|
|
80
|
+
) : null,
|
|
81
|
+
onSetDefaultBilling && !address.isDefaultBilling ? /* @__PURE__ */ jsx(
|
|
82
|
+
Button,
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
variant: "ghost",
|
|
86
|
+
size: "sm",
|
|
87
|
+
onClick: () => onSetDefaultBilling(address.id),
|
|
88
|
+
children: copy.setDefaultBillingLabel
|
|
89
|
+
}
|
|
90
|
+
) : null
|
|
91
|
+
] })
|
|
92
|
+
] })
|
|
93
|
+
] })
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
function AddressBook({
|
|
98
|
+
addresses,
|
|
99
|
+
labels,
|
|
100
|
+
onCreate,
|
|
101
|
+
onEdit,
|
|
102
|
+
onDelete,
|
|
103
|
+
onSetDefaultShipping,
|
|
104
|
+
onSetDefaultBilling,
|
|
105
|
+
className
|
|
106
|
+
}) {
|
|
107
|
+
const copy = { ...defaultLabels, ...labels };
|
|
108
|
+
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-lg border p-6", className), children: [
|
|
109
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
110
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
111
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: copy.title }),
|
|
112
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: copy.description })
|
|
113
|
+
] }),
|
|
114
|
+
onCreate ? /* @__PURE__ */ jsx(Button, { type: "button", onClick: onCreate, children: copy.addLabel }) : null
|
|
115
|
+
] }),
|
|
116
|
+
addresses.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-6 text-sm", "data-slot": "address-book-empty", children: copy.emptyLabel }) : /* @__PURE__ */ jsx("ul", { className: "mt-6 grid list-none grid-cols-1 gap-4 p-0 md:grid-cols-2", children: addresses.map((address) => /* @__PURE__ */ jsx(
|
|
117
|
+
AddressEntry,
|
|
118
|
+
{
|
|
119
|
+
address,
|
|
120
|
+
copy,
|
|
121
|
+
onEdit,
|
|
122
|
+
onDelete,
|
|
123
|
+
onSetDefaultShipping,
|
|
124
|
+
onSetDefaultBilling
|
|
125
|
+
},
|
|
126
|
+
address.id
|
|
127
|
+
)) })
|
|
128
|
+
] });
|
|
129
|
+
}
|
|
130
|
+
const defaultFormLabels = {
|
|
131
|
+
title: "Direcci\xF3n",
|
|
132
|
+
submit: "Guardar direcci\xF3n",
|
|
133
|
+
saving: "Guardando\u2026",
|
|
134
|
+
cancel: "Cancelar",
|
|
135
|
+
requiredError: "Este campo es obligatorio."
|
|
136
|
+
};
|
|
137
|
+
function AddressForm({
|
|
138
|
+
fields,
|
|
139
|
+
labels,
|
|
140
|
+
pending = false,
|
|
141
|
+
error,
|
|
142
|
+
fieldErrors,
|
|
143
|
+
onSubmit,
|
|
144
|
+
onCancel,
|
|
145
|
+
className
|
|
146
|
+
}) {
|
|
147
|
+
const copy = { ...defaultFormLabels, ...labels };
|
|
148
|
+
const visibleFields = fields.filter(
|
|
149
|
+
(field) => field.type !== "select" || Array.isArray(field.options) && field.options.length > 0
|
|
150
|
+
);
|
|
151
|
+
const signature = visibleFields.map((field) => `${field.name}:${field.value ?? ""}`).join("|");
|
|
152
|
+
const [values, setValues] = useState(
|
|
153
|
+
() => Object.fromEntries(visibleFields.map((field) => [field.name, field.value ?? ""]))
|
|
154
|
+
);
|
|
155
|
+
const [localErrors, setLocalErrors] = useState({});
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
setValues(Object.fromEntries(visibleFields.map((field) => [field.name, field.value ?? ""])));
|
|
158
|
+
setLocalErrors({});
|
|
159
|
+
}, [signature]);
|
|
160
|
+
const submit = (event) => {
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
const nextErrors = {};
|
|
163
|
+
for (const field of visibleFields) {
|
|
164
|
+
if (field.required && (values[field.name] ?? "").trim() === "") {
|
|
165
|
+
nextErrors[field.name] = copy.requiredError;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
setLocalErrors(nextErrors);
|
|
169
|
+
if (Object.keys(nextErrors).length > 0) return;
|
|
170
|
+
onSubmit(Object.fromEntries(visibleFields.map((field) => [field.name, values[field.name] ?? ""])));
|
|
171
|
+
};
|
|
172
|
+
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-lg border p-6", className), children: [
|
|
173
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: copy.title }),
|
|
174
|
+
/* @__PURE__ */ jsxs("form", { className: "mt-6", noValidate: true, onSubmit: submit, children: [
|
|
175
|
+
/* @__PURE__ */ jsx("fieldset", { disabled: pending, "aria-busy": pending, className: "contents", children: /* @__PURE__ */ jsx(FieldGroup, { className: "grid grid-cols-1 gap-5 sm:grid-cols-2", children: visibleFields.map((field) => {
|
|
176
|
+
const id = `address-${field.name}`;
|
|
177
|
+
const message = localErrors[field.name] ?? fieldErrors?.[field.name];
|
|
178
|
+
return /* @__PURE__ */ jsxs(Field, { children: [
|
|
179
|
+
/* @__PURE__ */ jsx(FieldLabel, { htmlFor: id, children: field.label }),
|
|
180
|
+
field.type === "select" ? /* @__PURE__ */ jsxs(
|
|
181
|
+
"select",
|
|
182
|
+
{
|
|
183
|
+
id,
|
|
184
|
+
name: field.name,
|
|
185
|
+
value: values[field.name] ?? "",
|
|
186
|
+
required: field.required,
|
|
187
|
+
"aria-invalid": message ? true : void 0,
|
|
188
|
+
"aria-describedby": message ? `${id}-error` : void 0,
|
|
189
|
+
className: "border-input bg-background h-9 w-full rounded-md border px-3 text-sm",
|
|
190
|
+
onChange: (event) => setValues((current) => ({ ...current, [field.name]: event.target.value })),
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014" }),
|
|
193
|
+
(field.options ?? []).map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, option.value))
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
) : /* @__PURE__ */ jsx(
|
|
197
|
+
Input,
|
|
198
|
+
{
|
|
199
|
+
id,
|
|
200
|
+
name: field.name,
|
|
201
|
+
type: field.type ?? "text",
|
|
202
|
+
value: values[field.name] ?? "",
|
|
203
|
+
required: field.required,
|
|
204
|
+
autoComplete: field.autoComplete,
|
|
205
|
+
"aria-invalid": message ? true : void 0,
|
|
206
|
+
"aria-describedby": message ? `${id}-error` : void 0,
|
|
207
|
+
onChange: (event) => setValues((current) => ({ ...current, [field.name]: event.target.value }))
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
message ? /* @__PURE__ */ jsx("p", { id: `${id}-error`, className: "text-destructive text-sm", children: message }) : null
|
|
211
|
+
] }, field.name);
|
|
212
|
+
}) }) }),
|
|
213
|
+
error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-destructive mt-4 text-sm", children: error }) : null,
|
|
214
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-wrap gap-2", children: [
|
|
215
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", disabled: pending, children: pending ? copy.saving : copy.submit }),
|
|
216
|
+
onCancel ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", disabled: pending, onClick: onCancel, children: copy.cancel }) : null
|
|
217
|
+
] })
|
|
218
|
+
] })
|
|
219
|
+
] });
|
|
220
|
+
}
|
|
221
|
+
export {
|
|
222
|
+
AddressBook,
|
|
223
|
+
AddressForm
|
|
224
|
+
};
|
|
225
|
+
//# sourceMappingURL=address-book.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/account/address-book.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useRef, useState } from 'react'\nimport type { FormEvent } from 'react'\nimport { Badge } from '../../../ui/badge'\nimport { Button } from '../../../ui/button'\nimport { Card, CardContent, CardHeader, CardTitle } from '../../../ui/card'\nimport { Field, FieldGroup, FieldLabel } from '../../../ui/field'\nimport { Input } from '../../../ui/input'\nimport { cn } from '../../../lib/utils'\n\n/** One address exactly as the host supplies it; the block formats no fields. */\nexport interface AccountAddress {\n id: string\n recipientName: string\n /** Address lines in display order (street, city, region, postal code, country). */\n lines: string[]\n isDefaultShipping?: boolean\n isDefaultBilling?: boolean\n}\n\nexport interface AddressBookLabels {\n title: string\n description: string\n emptyLabel: string\n addLabel: string\n editLabel: string\n deleteLabel: string\n confirmDeleteLabel: string\n cancelLabel: string\n defaultShippingLabel: string\n defaultBillingLabel: string\n setDefaultShippingLabel: string\n setDefaultBillingLabel: string\n}\n\nconst defaultLabels: AddressBookLabels = {\n title: 'Direcciones',\n description: 'Direcciones guardadas para tus pedidos.',\n emptyLabel: 'Aún no tienes direcciones guardadas.',\n addLabel: 'Añadir dirección',\n editLabel: 'Editar',\n deleteLabel: 'Eliminar',\n confirmDeleteLabel: '¿Eliminar esta dirección?',\n cancelLabel: 'Cancelar',\n defaultShippingLabel: 'Envío predeterminado',\n defaultBillingLabel: 'Facturación predeterminada',\n setDefaultShippingLabel: 'Usar para envío',\n setDefaultBillingLabel: 'Usar para facturación',\n}\n\nexport interface AddressBookProps {\n addresses: AccountAddress[]\n labels?: Partial<AddressBookLabels>\n onCreate?: () => void\n onEdit?: (id: string) => void\n onDelete?: (id: string) => void\n onSetDefaultShipping?: (id: string) => void\n onSetDefaultBilling?: (id: string) => void\n className?: string\n}\n\nfunction AddressEntry({\n address,\n copy,\n onEdit,\n onDelete,\n onSetDefaultShipping,\n onSetDefaultBilling,\n}: {\n address: AccountAddress\n copy: AddressBookLabels\n onEdit?: (id: string) => void\n onDelete?: (id: string) => void\n onSetDefaultShipping?: (id: string) => void\n onSetDefaultBilling?: (id: string) => void\n}) {\n const [confirming, setConfirming] = useState(false)\n const containerRef = useRef<HTMLLIElement | null>(null)\n\n return (\n <li\n ref={containerRef}\n tabIndex={-1}\n data-slot=\"address-book-entry\"\n className=\"focus-visible:ring-ring rounded-lg outline-none focus-visible:ring-2\"\n >\n <Card>\n <CardHeader className=\"flex flex-row items-start justify-between gap-4\">\n <div>\n <CardTitle className=\"text-base\">{address.recipientName}</CardTitle>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {address.isDefaultShipping ? (\n <Badge variant=\"secondary\">{copy.defaultShippingLabel}</Badge>\n ) : null}\n {address.isDefaultBilling ? (\n <Badge variant=\"outline\">{copy.defaultBillingLabel}</Badge>\n ) : null}\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <address className=\"text-muted-foreground text-sm not-italic\">\n {address.lines.map((line, index) => (\n <span key={`${address.id}:${index}`} className=\"block\">\n {line}\n </span>\n ))}\n </address>\n\n {confirming ? (\n <div className=\"mt-4 flex flex-wrap items-center gap-2\" role=\"group\" aria-label={copy.confirmDeleteLabel}>\n <span className=\"text-sm\">{copy.confirmDeleteLabel}</span>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => {\n onDelete?.(address.id)\n setConfirming(false)\n containerRef.current?.focus()\n }}\n >\n {copy.deleteLabel}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setConfirming(false)}>\n {copy.cancelLabel}\n </Button>\n </div>\n ) : (\n <div className=\"mt-4 flex flex-wrap gap-2\">\n {onEdit ? (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => onEdit(address.id)}>\n {copy.editLabel}\n </Button>\n ) : null}\n {onDelete ? (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setConfirming(true)}>\n {copy.deleteLabel}\n </Button>\n ) : null}\n {onSetDefaultShipping && !address.isDefaultShipping ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onSetDefaultShipping(address.id)}\n >\n {copy.setDefaultShippingLabel}\n </Button>\n ) : null}\n {onSetDefaultBilling && !address.isDefaultBilling ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onSetDefaultBilling(address.id)}\n >\n {copy.setDefaultBillingLabel}\n </Button>\n ) : null}\n </div>\n )}\n </CardContent>\n </Card>\n </li>\n )\n}\n\n/**\n * The address book: renders the host's addresses verbatim, in the supplied\n * order, and reports every action. Deletion is a two-step inline confirmation\n * and the entry stays until the host supplies a refreshed list — the block never\n * removes it optimistically.\n */\nexport function AddressBook({\n addresses,\n labels,\n onCreate,\n onEdit,\n onDelete,\n onSetDefaultShipping,\n onSetDefaultBilling,\n className,\n}: AddressBookProps) {\n const copy = { ...defaultLabels, ...labels }\n return (\n <section className={cn('rounded-lg border p-6', className)}>\n <div className=\"flex flex-wrap items-start justify-between gap-4\">\n <div>\n <h2 className=\"text-lg font-semibold\">{copy.title}</h2>\n <p className=\"text-muted-foreground mt-1 text-sm\">{copy.description}</p>\n </div>\n {onCreate ? (\n <Button type=\"button\" onClick={onCreate}>\n {copy.addLabel}\n </Button>\n ) : null}\n </div>\n\n {addresses.length === 0 ? (\n <p className=\"text-muted-foreground mt-6 text-sm\" data-slot=\"address-book-empty\">\n {copy.emptyLabel}\n </p>\n ) : (\n <ul className=\"mt-6 grid list-none grid-cols-1 gap-4 p-0 md:grid-cols-2\">\n {addresses.map((address) => (\n <AddressEntry\n key={address.id}\n address={address}\n copy={copy}\n onEdit={onEdit}\n onDelete={onDelete}\n onSetDefaultShipping={onSetDefaultShipping}\n onSetDefaultBilling={onSetDefaultBilling}\n />\n ))}\n </ul>\n )}\n </section>\n )\n}\n\n/** One field of the address form, declared by the host. */\nexport interface AddressFormField {\n name: string\n label: string\n value?: string\n type?: 'text' | 'tel' | 'email' | 'select'\n required?: boolean\n autoComplete?: string\n /** Required for `select`; a select without options is not rendered. */\n options?: { value: string; label: string }[]\n}\n\nexport interface AddressFormLabels {\n title: string\n submit: string\n saving: string\n cancel: string\n requiredError: string\n}\n\nconst defaultFormLabels: AddressFormLabels = {\n title: 'Dirección',\n submit: 'Guardar dirección',\n saving: 'Guardando…',\n cancel: 'Cancelar',\n requiredError: 'Este campo es obligatorio.',\n}\n\nexport interface AddressFormProps {\n fields: AddressFormField[]\n labels?: Partial<AddressFormLabels>\n pending?: boolean\n error?: string | null\n /** Host-supplied field errors, keyed by field name. */\n fieldErrors?: Record<string, string>\n onSubmit: (values: Record<string, string>) => void\n onCancel?: () => void\n className?: string\n}\n\n/**\n * The address editor. It validates only the constraints the host declares (a\n * required field), never invents country or postal rules, and omits a select\n * the host supplied without options.\n */\nexport function AddressForm({\n fields,\n labels,\n pending = false,\n error,\n fieldErrors,\n onSubmit,\n onCancel,\n className,\n}: AddressFormProps) {\n const copy = { ...defaultFormLabels, ...labels }\n const visibleFields = fields.filter(\n (field) => field.type !== 'select' || (Array.isArray(field.options) && field.options.length > 0),\n )\n const signature = visibleFields.map((field) => `${field.name}:${field.value ?? ''}`).join('|')\n const [values, setValues] = useState<Record<string, string>>(() =>\n Object.fromEntries(visibleFields.map((field) => [field.name, field.value ?? ''])),\n )\n const [localErrors, setLocalErrors] = useState<Record<string, string>>({})\n\n // Re-seed when the host supplies new values (e.g. opening a different address).\n useEffect(() => {\n setValues(Object.fromEntries(visibleFields.map((field) => [field.name, field.value ?? ''])))\n setLocalErrors({})\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [signature])\n\n const submit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n const nextErrors: Record<string, string> = {}\n for (const field of visibleFields) {\n if (field.required && (values[field.name] ?? '').trim() === '') {\n nextErrors[field.name] = copy.requiredError\n }\n }\n setLocalErrors(nextErrors)\n if (Object.keys(nextErrors).length > 0) return\n onSubmit(Object.fromEntries(visibleFields.map((field) => [field.name, values[field.name] ?? ''])))\n }\n\n return (\n <section className={cn('rounded-lg border p-6', className)}>\n <h2 className=\"text-lg font-semibold\">{copy.title}</h2>\n <form className=\"mt-6\" noValidate onSubmit={submit}>\n <fieldset disabled={pending} aria-busy={pending} className=\"contents\">\n <FieldGroup className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n {visibleFields.map((field) => {\n const id = `address-${field.name}`\n const message = localErrors[field.name] ?? fieldErrors?.[field.name]\n return (\n <Field key={field.name}>\n <FieldLabel htmlFor={id}>{field.label}</FieldLabel>\n {field.type === 'select' ? (\n <select\n id={id}\n name={field.name}\n value={values[field.name] ?? ''}\n required={field.required}\n aria-invalid={message ? true : undefined}\n aria-describedby={message ? `${id}-error` : undefined}\n className=\"border-input bg-background h-9 w-full rounded-md border px-3 text-sm\"\n onChange={(event) =>\n setValues((current) => ({ ...current, [field.name]: event.target.value }))\n }\n >\n <option value=\"\">—</option>\n {(field.options ?? []).map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n ) : (\n <Input\n id={id}\n name={field.name}\n type={field.type ?? 'text'}\n value={values[field.name] ?? ''}\n required={field.required}\n autoComplete={field.autoComplete}\n aria-invalid={message ? true : undefined}\n aria-describedby={message ? `${id}-error` : undefined}\n onChange={(event) =>\n setValues((current) => ({ ...current, [field.name]: event.target.value }))\n }\n />\n )}\n {message ? (\n <p id={`${id}-error`} className=\"text-destructive text-sm\">\n {message}\n </p>\n ) : null}\n </Field>\n )\n })}\n </FieldGroup>\n </fieldset>\n\n {error ? (\n <p role=\"alert\" className=\"text-destructive mt-4 text-sm\">\n {error}\n </p>\n ) : null}\n\n <div className=\"mt-6 flex flex-wrap gap-2\">\n <Button type=\"submit\" disabled={pending}>\n {pending ? copy.saving : copy.submit}\n </Button>\n {onCancel ? (\n <Button type=\"button\" variant=\"outline\" disabled={pending} onClick={onCancel}>\n {copy.cancel}\n </Button>\n ) : null}\n </div>\n </form>\n </section>\n )\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** One editable (or read-only) profile field the host declares. */
|
|
2
|
+
export interface ProfileField {
|
|
3
|
+
name: string;
|
|
4
|
+
label: string;
|
|
5
|
+
value?: string;
|
|
6
|
+
type?: 'text' | 'tel' | 'email';
|
|
7
|
+
required?: boolean;
|
|
8
|
+
/** Rendered as read-only; a field the host omits is absent entirely. */
|
|
9
|
+
readOnly?: boolean;
|
|
10
|
+
autoComplete?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ProfileFormLabels {
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
submit: string;
|
|
16
|
+
saving: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ProfileFormProps {
|
|
19
|
+
/** Exactly the fields the host declares, in order. */
|
|
20
|
+
fields: ProfileField[];
|
|
21
|
+
labels?: Partial<ProfileFormLabels>;
|
|
22
|
+
/** Host-owned mutation state; the form never claims success on its own. */
|
|
23
|
+
pending?: boolean;
|
|
24
|
+
error?: string | null;
|
|
25
|
+
onSubmit: (values: Record<string, string>) => void;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The profile editor. It renders only host-declared fields, keeps the entered
|
|
30
|
+
* values while a save is pending or fails, and reports the values to the host —
|
|
31
|
+
* it never calls a backend and never invents a field (an email change, for
|
|
32
|
+
* example, is absent when the host does not declare it).
|
|
33
|
+
*/
|
|
34
|
+
export declare function ProfileForm({ fields, labels, pending, error, onSubmit, className, }: ProfileFormProps): import("react").JSX.Element;
|
|
35
|
+
//# sourceMappingURL=profile-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-form.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/account/profile-form.tsx"],"names":[],"mappings":"AAQA,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AASD,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACnC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAA;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,MAAM,EACN,OAAe,EACf,KAAK,EACL,QAAQ,EACR,SAAS,GACV,EAAE,gBAAgB,+BAoElB"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var profile_form_exports = {};
|
|
21
|
+
__export(profile_form_exports, {
|
|
22
|
+
ProfileForm: () => ProfileForm
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(profile_form_exports);
|
|
25
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_button = require("../../../ui/button.js");
|
|
28
|
+
var import_field = require("../../../ui/field.js");
|
|
29
|
+
var import_input = require("../../../ui/input.js");
|
|
30
|
+
var import_utils = require("../../../lib/utils.js");
|
|
31
|
+
const defaultLabels = {
|
|
32
|
+
title: "Datos personales",
|
|
33
|
+
description: "Actualiza los datos de tu cuenta.",
|
|
34
|
+
submit: "Guardar cambios",
|
|
35
|
+
saving: "Guardando\u2026"
|
|
36
|
+
};
|
|
37
|
+
function ProfileForm({
|
|
38
|
+
fields,
|
|
39
|
+
labels,
|
|
40
|
+
pending = false,
|
|
41
|
+
error,
|
|
42
|
+
onSubmit,
|
|
43
|
+
className
|
|
44
|
+
}) {
|
|
45
|
+
const copy = { ...defaultLabels, ...labels };
|
|
46
|
+
const signature = fields.map((field) => `${field.name}:${field.value ?? ""}`).join("|");
|
|
47
|
+
const [values, setValues] = (0, import_react.useState)(
|
|
48
|
+
() => Object.fromEntries(fields.map((field) => [field.name, field.value ?? ""]))
|
|
49
|
+
);
|
|
50
|
+
(0, import_react.useEffect)(() => {
|
|
51
|
+
setValues(Object.fromEntries(fields.map((field) => [field.name, field.value ?? ""])));
|
|
52
|
+
}, [signature]);
|
|
53
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: (0, import_utils.cn)("rounded-lg border p-6", className), children: [
|
|
54
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg font-semibold", children: copy.title }),
|
|
55
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground mt-1 text-sm", children: copy.description }),
|
|
56
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
57
|
+
"form",
|
|
58
|
+
{
|
|
59
|
+
className: "mt-6",
|
|
60
|
+
noValidate: true,
|
|
61
|
+
onSubmit: (event) => {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
const submitted = Object.fromEntries(
|
|
64
|
+
fields.map((field) => [field.name, values[field.name] ?? ""])
|
|
65
|
+
);
|
|
66
|
+
onSubmit(submitted);
|
|
67
|
+
},
|
|
68
|
+
children: [
|
|
69
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("fieldset", { disabled: pending, "aria-busy": pending, className: "contents", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_field.FieldGroup, { className: "grid grid-cols-1 gap-5 sm:grid-cols-2", children: fields.map((field) => {
|
|
70
|
+
const id = `profile-${field.name}`;
|
|
71
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_field.Field, { children: [
|
|
72
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_field.FieldLabel, { htmlFor: id, children: field.label }),
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
74
|
+
import_input.Input,
|
|
75
|
+
{
|
|
76
|
+
id,
|
|
77
|
+
name: field.name,
|
|
78
|
+
type: field.type ?? "text",
|
|
79
|
+
value: values[field.name] ?? "",
|
|
80
|
+
readOnly: field.readOnly,
|
|
81
|
+
required: field.required,
|
|
82
|
+
autoComplete: field.autoComplete,
|
|
83
|
+
"aria-readonly": field.readOnly || void 0,
|
|
84
|
+
onChange: (event) => setValues((current) => ({ ...current, [field.name]: event.target.value }))
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
] }, field.name);
|
|
88
|
+
}) }) }),
|
|
89
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: "text-destructive mt-4 text-sm", children: error }) : null,
|
|
90
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { type: "submit", className: "mt-6", disabled: pending, children: pending ? copy.saving : copy.submit })
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
97
|
+
0 && (module.exports = {
|
|
98
|
+
ProfileForm
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=profile-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/account/profile-form.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport { Button } from '../../../ui/button'\nimport { Field, FieldGroup, FieldLabel } from '../../../ui/field'\nimport { Input } from '../../../ui/input'\nimport { cn } from '../../../lib/utils'\n\n/** One editable (or read-only) profile field the host declares. */\nexport interface ProfileField {\n name: string\n label: string\n value?: string\n type?: 'text' | 'tel' | 'email'\n required?: boolean\n /** Rendered as read-only; a field the host omits is absent entirely. */\n readOnly?: boolean\n autoComplete?: string\n}\n\nexport interface ProfileFormLabels {\n title: string\n description: string\n submit: string\n saving: string\n}\n\nconst defaultLabels: ProfileFormLabels = {\n title: 'Datos personales',\n description: 'Actualiza los datos de tu cuenta.',\n submit: 'Guardar cambios',\n saving: 'Guardando…',\n}\n\nexport interface ProfileFormProps {\n /** Exactly the fields the host declares, in order. */\n fields: ProfileField[]\n labels?: Partial<ProfileFormLabels>\n /** Host-owned mutation state; the form never claims success on its own. */\n pending?: boolean\n error?: string | null\n onSubmit: (values: Record<string, string>) => void\n className?: string\n}\n\n/**\n * The profile editor. It renders only host-declared fields, keeps the entered\n * values while a save is pending or fails, and reports the values to the host —\n * it never calls a backend and never invents a field (an email change, for\n * example, is absent when the host does not declare it).\n */\nexport function ProfileForm({\n fields,\n labels,\n pending = false,\n error,\n onSubmit,\n className,\n}: ProfileFormProps) {\n const copy = { ...defaultLabels, ...labels }\n const signature = fields.map((field) => `${field.name}:${field.value ?? ''}`).join('|')\n const [values, setValues] = useState<Record<string, string>>(() =>\n Object.fromEntries(fields.map((field) => [field.name, field.value ?? ''])),\n )\n\n // Re-seed when the host supplies new default values (for example after a\n // successful save). The signature covers field identity and values, so a\n // pending/error prop change never clears what the shopper typed.\n useEffect(() => {\n setValues(Object.fromEntries(fields.map((field) => [field.name, field.value ?? ''])))\n }, [signature])\n\n return (\n <section className={cn('rounded-lg border p-6', className)}>\n <h2 className=\"text-lg font-semibold\">{copy.title}</h2>\n <p className=\"text-muted-foreground mt-1 text-sm\">{copy.description}</p>\n\n <form\n className=\"mt-6\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault()\n const submitted = Object.fromEntries(\n fields.map((field) => [field.name, values[field.name] ?? '']),\n )\n onSubmit(submitted)\n }}\n >\n <fieldset disabled={pending} aria-busy={pending} className=\"contents\">\n <FieldGroup className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n {fields.map((field) => {\n const id = `profile-${field.name}`\n return (\n <Field key={field.name}>\n <FieldLabel htmlFor={id}>{field.label}</FieldLabel>\n <Input\n id={id}\n name={field.name}\n type={field.type ?? 'text'}\n value={values[field.name] ?? ''}\n readOnly={field.readOnly}\n required={field.required}\n autoComplete={field.autoComplete}\n aria-readonly={field.readOnly || undefined}\n onChange={(event) =>\n setValues((current) => ({ ...current, [field.name]: event.target.value }))\n }\n />\n </Field>\n )\n })}\n </FieldGroup>\n </fieldset>\n\n {error ? (\n <p role=\"alert\" className=\"text-destructive mt-4 text-sm\">\n {error}\n </p>\n ) : null}\n\n <Button type=\"submit\" className=\"mt-6\" disabled={pending}>\n {pending ? copy.saving : copy.submit}\n </Button>\n </form>\n </section>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0EM;AAxEN,mBAAoC;AACpC,oBAAuB;AACvB,mBAA8C;AAC9C,mBAAsB;AACtB,mBAAmB;AAqBnB,MAAM,gBAAmC;AAAA,EACvC,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,QAAQ;AACV;AAmBO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,OAAO,EAAE,GAAG,eAAe,GAAG,OAAO;AAC3C,QAAM,YAAY,OAAO,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,IAAI,MAAM,SAAS,EAAE,EAAE,EAAE,KAAK,GAAG;AACtF,QAAM,CAAC,QAAQ,SAAS,QAAI;AAAA,IAAiC,MAC3D,OAAO,YAAY,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;AAAA,EAC3E;AAKA,8BAAU,MAAM;AACd,cAAU,OAAO,YAAY,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC;AAAA,EACtF,GAAG,CAAC,SAAS,CAAC;AAEd,SACE,6CAAC,aAAQ,eAAW,iBAAG,yBAAyB,SAAS,GACvD;AAAA,gDAAC,QAAG,WAAU,yBAAyB,eAAK,OAAM;AAAA,IAClD,4CAAC,OAAE,WAAU,sCAAsC,eAAK,aAAY;AAAA,IAEpE;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,YAAU;AAAA,QACV,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,gBAAM,YAAY,OAAO;AAAA,YACvB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,OAAO,MAAM,IAAI,KAAK,EAAE,CAAC;AAAA,UAC9D;AACA,mBAAS,SAAS;AAAA,QACpB;AAAA,QAEA;AAAA,sDAAC,cAAS,UAAU,SAAS,aAAW,SAAS,WAAU,YACzD,sDAAC,2BAAW,WAAU,yCACnB,iBAAO,IAAI,CAAC,UAAU;AACrB,kBAAM,KAAK,WAAW,MAAM,IAAI;AAChC,mBACE,6CAAC,sBACC;AAAA,0DAAC,2BAAW,SAAS,IAAK,gBAAM,OAAM;AAAA,cACtC;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA,MAAM,MAAM;AAAA,kBACZ,MAAM,MAAM,QAAQ;AAAA,kBACpB,OAAO,OAAO,MAAM,IAAI,KAAK;AAAA,kBAC7B,UAAU,MAAM;AAAA,kBAChB,UAAU,MAAM;AAAA,kBAChB,cAAc,MAAM;AAAA,kBACpB,iBAAe,MAAM,YAAY;AAAA,kBACjC,UAAU,CAAC,UACT,UAAU,CAAC,aAAa,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,OAAO,MAAM,EAAE;AAAA;AAAA,cAE7E;AAAA,iBAdU,MAAM,IAelB;AAAA,UAEJ,CAAC,GACH,GACF;AAAA,UAEC,QACC,4CAAC,OAAE,MAAK,SAAQ,WAAU,iCACvB,iBACH,IACE;AAAA,UAEJ,4CAAC,wBAAO,MAAK,UAAS,WAAU,QAAO,UAAU,SAC9C,oBAAU,KAAK,SAAS,KAAK,QAChC;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { Button } from "../../../ui/button.mjs";
|
|
5
|
+
import { Field, FieldGroup, FieldLabel } from "../../../ui/field.mjs";
|
|
6
|
+
import { Input } from "../../../ui/input.mjs";
|
|
7
|
+
import { cn } from "../../../lib/utils.mjs";
|
|
8
|
+
const defaultLabels = {
|
|
9
|
+
title: "Datos personales",
|
|
10
|
+
description: "Actualiza los datos de tu cuenta.",
|
|
11
|
+
submit: "Guardar cambios",
|
|
12
|
+
saving: "Guardando\u2026"
|
|
13
|
+
};
|
|
14
|
+
function ProfileForm({
|
|
15
|
+
fields,
|
|
16
|
+
labels,
|
|
17
|
+
pending = false,
|
|
18
|
+
error,
|
|
19
|
+
onSubmit,
|
|
20
|
+
className
|
|
21
|
+
}) {
|
|
22
|
+
const copy = { ...defaultLabels, ...labels };
|
|
23
|
+
const signature = fields.map((field) => `${field.name}:${field.value ?? ""}`).join("|");
|
|
24
|
+
const [values, setValues] = useState(
|
|
25
|
+
() => Object.fromEntries(fields.map((field) => [field.name, field.value ?? ""]))
|
|
26
|
+
);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setValues(Object.fromEntries(fields.map((field) => [field.name, field.value ?? ""])));
|
|
29
|
+
}, [signature]);
|
|
30
|
+
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-lg border p-6", className), children: [
|
|
31
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: copy.title }),
|
|
32
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: copy.description }),
|
|
33
|
+
/* @__PURE__ */ jsxs(
|
|
34
|
+
"form",
|
|
35
|
+
{
|
|
36
|
+
className: "mt-6",
|
|
37
|
+
noValidate: true,
|
|
38
|
+
onSubmit: (event) => {
|
|
39
|
+
event.preventDefault();
|
|
40
|
+
const submitted = Object.fromEntries(
|
|
41
|
+
fields.map((field) => [field.name, values[field.name] ?? ""])
|
|
42
|
+
);
|
|
43
|
+
onSubmit(submitted);
|
|
44
|
+
},
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsx("fieldset", { disabled: pending, "aria-busy": pending, className: "contents", children: /* @__PURE__ */ jsx(FieldGroup, { className: "grid grid-cols-1 gap-5 sm:grid-cols-2", children: fields.map((field) => {
|
|
47
|
+
const id = `profile-${field.name}`;
|
|
48
|
+
return /* @__PURE__ */ jsxs(Field, { children: [
|
|
49
|
+
/* @__PURE__ */ jsx(FieldLabel, { htmlFor: id, children: field.label }),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
Input,
|
|
52
|
+
{
|
|
53
|
+
id,
|
|
54
|
+
name: field.name,
|
|
55
|
+
type: field.type ?? "text",
|
|
56
|
+
value: values[field.name] ?? "",
|
|
57
|
+
readOnly: field.readOnly,
|
|
58
|
+
required: field.required,
|
|
59
|
+
autoComplete: field.autoComplete,
|
|
60
|
+
"aria-readonly": field.readOnly || void 0,
|
|
61
|
+
onChange: (event) => setValues((current) => ({ ...current, [field.name]: event.target.value }))
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
] }, field.name);
|
|
65
|
+
}) }) }),
|
|
66
|
+
error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-destructive mt-4 text-sm", children: error }) : null,
|
|
67
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", className: "mt-6", disabled: pending, children: pending ? copy.saving : copy.submit })
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
] });
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
ProfileForm
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=profile-form.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/account/profile-form.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport { Button } from '../../../ui/button'\nimport { Field, FieldGroup, FieldLabel } from '../../../ui/field'\nimport { Input } from '../../../ui/input'\nimport { cn } from '../../../lib/utils'\n\n/** One editable (or read-only) profile field the host declares. */\nexport interface ProfileField {\n name: string\n label: string\n value?: string\n type?: 'text' | 'tel' | 'email'\n required?: boolean\n /** Rendered as read-only; a field the host omits is absent entirely. */\n readOnly?: boolean\n autoComplete?: string\n}\n\nexport interface ProfileFormLabels {\n title: string\n description: string\n submit: string\n saving: string\n}\n\nconst defaultLabels: ProfileFormLabels = {\n title: 'Datos personales',\n description: 'Actualiza los datos de tu cuenta.',\n submit: 'Guardar cambios',\n saving: 'Guardando…',\n}\n\nexport interface ProfileFormProps {\n /** Exactly the fields the host declares, in order. */\n fields: ProfileField[]\n labels?: Partial<ProfileFormLabels>\n /** Host-owned mutation state; the form never claims success on its own. */\n pending?: boolean\n error?: string | null\n onSubmit: (values: Record<string, string>) => void\n className?: string\n}\n\n/**\n * The profile editor. It renders only host-declared fields, keeps the entered\n * values while a save is pending or fails, and reports the values to the host —\n * it never calls a backend and never invents a field (an email change, for\n * example, is absent when the host does not declare it).\n */\nexport function ProfileForm({\n fields,\n labels,\n pending = false,\n error,\n onSubmit,\n className,\n}: ProfileFormProps) {\n const copy = { ...defaultLabels, ...labels }\n const signature = fields.map((field) => `${field.name}:${field.value ?? ''}`).join('|')\n const [values, setValues] = useState<Record<string, string>>(() =>\n Object.fromEntries(fields.map((field) => [field.name, field.value ?? ''])),\n )\n\n // Re-seed when the host supplies new default values (for example after a\n // successful save). The signature covers field identity and values, so a\n // pending/error prop change never clears what the shopper typed.\n useEffect(() => {\n setValues(Object.fromEntries(fields.map((field) => [field.name, field.value ?? ''])))\n }, [signature])\n\n return (\n <section className={cn('rounded-lg border p-6', className)}>\n <h2 className=\"text-lg font-semibold\">{copy.title}</h2>\n <p className=\"text-muted-foreground mt-1 text-sm\">{copy.description}</p>\n\n <form\n className=\"mt-6\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault()\n const submitted = Object.fromEntries(\n fields.map((field) => [field.name, values[field.name] ?? '']),\n )\n onSubmit(submitted)\n }}\n >\n <fieldset disabled={pending} aria-busy={pending} className=\"contents\">\n <FieldGroup className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n {fields.map((field) => {\n const id = `profile-${field.name}`\n return (\n <Field key={field.name}>\n <FieldLabel htmlFor={id}>{field.label}</FieldLabel>\n <Input\n id={id}\n name={field.name}\n type={field.type ?? 'text'}\n value={values[field.name] ?? ''}\n readOnly={field.readOnly}\n required={field.required}\n autoComplete={field.autoComplete}\n aria-readonly={field.readOnly || undefined}\n onChange={(event) =>\n setValues((current) => ({ ...current, [field.name]: event.target.value }))\n }\n />\n </Field>\n )\n })}\n </FieldGroup>\n </fieldset>\n\n {error ? (\n <p role=\"alert\" className=\"text-destructive mt-4 text-sm\">\n {error}\n </p>\n ) : null}\n\n <Button type=\"submit\" className=\"mt-6\" disabled={pending}>\n {pending ? copy.saving : copy.submit}\n </Button>\n </form>\n </section>\n )\n}\n"],"mappings":";AA0EM,cAmBU,YAnBV;AAxEN,SAAS,WAAW,gBAAgB;AACpC,SAAS,cAAc;AACvB,SAAS,OAAO,YAAY,kBAAkB;AAC9C,SAAS,aAAa;AACtB,SAAS,UAAU;AAqBnB,MAAM,gBAAmC;AAAA,EACvC,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,QAAQ;AACV;AAmBO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,OAAO,EAAE,GAAG,eAAe,GAAG,OAAO;AAC3C,QAAM,YAAY,OAAO,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,IAAI,MAAM,SAAS,EAAE,EAAE,EAAE,KAAK,GAAG;AACtF,QAAM,CAAC,QAAQ,SAAS,IAAI;AAAA,IAAiC,MAC3D,OAAO,YAAY,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;AAAA,EAC3E;AAKA,YAAU,MAAM;AACd,cAAU,OAAO,YAAY,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC;AAAA,EACtF,GAAG,CAAC,SAAS,CAAC;AAEd,SACE,qBAAC,aAAQ,WAAW,GAAG,yBAAyB,SAAS,GACvD;AAAA,wBAAC,QAAG,WAAU,yBAAyB,eAAK,OAAM;AAAA,IAClD,oBAAC,OAAE,WAAU,sCAAsC,eAAK,aAAY;AAAA,IAEpE;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,YAAU;AAAA,QACV,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,gBAAM,YAAY,OAAO;AAAA,YACvB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,OAAO,MAAM,IAAI,KAAK,EAAE,CAAC;AAAA,UAC9D;AACA,mBAAS,SAAS;AAAA,QACpB;AAAA,QAEA;AAAA,8BAAC,cAAS,UAAU,SAAS,aAAW,SAAS,WAAU,YACzD,8BAAC,cAAW,WAAU,yCACnB,iBAAO,IAAI,CAAC,UAAU;AACrB,kBAAM,KAAK,WAAW,MAAM,IAAI;AAChC,mBACE,qBAAC,SACC;AAAA,kCAAC,cAAW,SAAS,IAAK,gBAAM,OAAM;AAAA,cACtC;AAAA,gBAAC;AAAA;AAAA,kBACC;AAAA,kBACA,MAAM,MAAM;AAAA,kBACZ,MAAM,MAAM,QAAQ;AAAA,kBACpB,OAAO,OAAO,MAAM,IAAI,KAAK;AAAA,kBAC7B,UAAU,MAAM;AAAA,kBAChB,UAAU,MAAM;AAAA,kBAChB,cAAc,MAAM;AAAA,kBACpB,iBAAe,MAAM,YAAY;AAAA,kBACjC,UAAU,CAAC,UACT,UAAU,CAAC,aAAa,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,GAAG,MAAM,OAAO,MAAM,EAAE;AAAA;AAAA,cAE7E;AAAA,iBAdU,MAAM,IAelB;AAAA,UAEJ,CAAC,GACH,GACF;AAAA,UAEC,QACC,oBAAC,OAAE,MAAK,SAAQ,WAAU,iCACvB,iBACH,IACE;AAAA,UAEJ,oBAAC,UAAO,MAAK,UAAS,WAAU,QAAO,UAAU,SAC9C,oBAAU,KAAK,SAAS,KAAK,QAChC;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -36,7 +36,7 @@ function CheckboxCheck({ className, indeterminate, ...props }) {
|
|
|
36
36
|
const [length, setLength] = (0, import_react.useState)(15);
|
|
37
37
|
(0, import_react.useLayoutEffect)(() => {
|
|
38
38
|
const path = pathRef.current;
|
|
39
|
-
if (path) {
|
|
39
|
+
if (path && typeof path.getTotalLength === "function") {
|
|
40
40
|
setLength(Math.ceil(path.getTotalLength()));
|
|
41
41
|
}
|
|
42
42
|
}, []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/blocks/e-commerce/checkout-forms/checkbox-check.tsx"],"sourcesContent":["'use client'\n\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox'\n\nimport { cn } from '../../../lib/utils'\n\nconst BOX_MS = 150\nconst DRAW_MS = 350\nconst UNCHECK_MS = 150\nconst EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'\n\nexport function CheckboxCheck({ className, indeterminate, ...props }: CheckboxPrimitive.Root.Props) {\n const pathRef = useRef<SVGPathElement>(null)\n const [length, setLength] = useState(15)\n\n useLayoutEffect(() => {\n const path = pathRef.current\n if (path) {\n setLength(Math.ceil(path.getTotalLength()))\n }\n }, [])\n\n const mark = indeterminate ? 'M2.12 5.08H8.47' : 'M1.69 5.08L3.81 7.2L8.47 2.54'\n\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n 'peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary',\n 'motion-reduce:transition-none',\n className\n )}\n style={{ transition: `background-color ${BOX_MS}ms ${EASE}, border-color ${BOX_MS}ms ${EASE}` }}\n indeterminate={indeterminate}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n keepMounted\n data-slot=\"checkbox-indicator\"\n className={cn(\n 'grid size-3.5 place-content-center text-current',\n '[&_path]:[transition:stroke-dashoffset_var(--check-uncheck)_var(--check-ease)]',\n '[&_path]:[stroke-dashoffset:var(--check-len)]',\n 'data-checked:[&_path]:[stroke-dashoffset:0]',\n 'data-checked:[&_path]:[transition-duration:var(--check-draw)]',\n 'motion-reduce:[&_path]:transition-none'\n )}\n style={\n {\n '--check-len': length,\n '--check-draw': `${DRAW_MS}ms`,\n '--check-uncheck': `${UNCHECK_MS}ms`,\n '--check-ease': EASE,\n } as React.CSSProperties\n }\n >\n <svg viewBox=\"0 0 10.1668 10.1668\" fill=\"none\" aria-hidden className=\"size-full overflow-visible\">\n <path\n ref={pathRef}\n d={mark}\n stroke=\"currentColor\"\n strokeWidth={0.9}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{ strokeDasharray: length }}\n />\n </svg>\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport default CheckboxCheck"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0DU;AAxDV,mBAAkD;AAClD,sBAA8C;AAE9C,mBAAmB;AAEnB,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,aAAa;AACnB,MAAM,OAAO;AAEN,SAAS,cAAc,EAAE,WAAW,eAAe,GAAG,MAAM,GAAiC;AAClG,QAAM,cAAU,qBAAuB,IAAI;AAC3C,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAS,EAAE;AAEvC,oCAAgB,MAAM;AACpB,UAAM,OAAO,QAAQ;AACrB,QAAI,
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/checkout-forms/checkbox-check.tsx"],"sourcesContent":["'use client'\n\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox'\n\nimport { cn } from '../../../lib/utils'\n\nconst BOX_MS = 150\nconst DRAW_MS = 350\nconst UNCHECK_MS = 150\nconst EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'\n\nexport function CheckboxCheck({ className, indeterminate, ...props }: CheckboxPrimitive.Root.Props) {\n const pathRef = useRef<SVGPathElement>(null)\n const [length, setLength] = useState(15)\n\n useLayoutEffect(() => {\n const path = pathRef.current\n if (path && typeof path.getTotalLength === 'function') {\n setLength(Math.ceil(path.getTotalLength()))\n }\n }, [])\n\n const mark = indeterminate ? 'M2.12 5.08H8.47' : 'M1.69 5.08L3.81 7.2L8.47 2.54'\n\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n 'peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary',\n 'motion-reduce:transition-none',\n className\n )}\n style={{ transition: `background-color ${BOX_MS}ms ${EASE}, border-color ${BOX_MS}ms ${EASE}` }}\n indeterminate={indeterminate}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n keepMounted\n data-slot=\"checkbox-indicator\"\n className={cn(\n 'grid size-3.5 place-content-center text-current',\n '[&_path]:[transition:stroke-dashoffset_var(--check-uncheck)_var(--check-ease)]',\n '[&_path]:[stroke-dashoffset:var(--check-len)]',\n 'data-checked:[&_path]:[stroke-dashoffset:0]',\n 'data-checked:[&_path]:[transition-duration:var(--check-draw)]',\n 'motion-reduce:[&_path]:transition-none'\n )}\n style={\n {\n '--check-len': length,\n '--check-draw': `${DRAW_MS}ms`,\n '--check-uncheck': `${UNCHECK_MS}ms`,\n '--check-ease': EASE,\n } as React.CSSProperties\n }\n >\n <svg viewBox=\"0 0 10.1668 10.1668\" fill=\"none\" aria-hidden className=\"size-full overflow-visible\">\n <path\n ref={pathRef}\n d={mark}\n stroke=\"currentColor\"\n strokeWidth={0.9}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{ strokeDasharray: length }}\n />\n </svg>\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport default CheckboxCheck"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0DU;AAxDV,mBAAkD;AAClD,sBAA8C;AAE9C,mBAAmB;AAEnB,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,aAAa;AACnB,MAAM,OAAO;AAEN,SAAS,cAAc,EAAE,WAAW,eAAe,GAAG,MAAM,GAAiC;AAClG,QAAM,cAAU,qBAAuB,IAAI;AAC3C,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAS,EAAE;AAEvC,oCAAgB,MAAM;AACpB,UAAM,OAAO,QAAQ;AACrB,QAAI,QAAQ,OAAO,KAAK,mBAAmB,YAAY;AACrD,gBAAU,KAAK,KAAK,KAAK,eAAe,CAAC,CAAC;AAAA,IAC5C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,gBAAgB,oBAAoB;AAEjD,SACE;AAAA,IAAC,gBAAAA,SAAkB;AAAA,IAAlB;AAAA,MACC,aAAU;AAAA,MACV,eAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,YAAY,oBAAoB,MAAM,MAAM,IAAI,kBAAkB,MAAM,MAAM,IAAI,GAAG;AAAA,MAC9F;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,QAAC,gBAAAA,SAAkB;AAAA,QAAlB;AAAA,UACC,aAAW;AAAA,UACX,aAAU;AAAA,UACV,eAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,OACE;AAAA,YACE,eAAe;AAAA,YACf,gBAAgB,GAAG,OAAO;AAAA,YAC1B,mBAAmB,GAAG,UAAU;AAAA,YAChC,gBAAgB;AAAA,UAClB;AAAA,UAGF,sDAAC,SAAI,SAAQ,uBAAsB,MAAK,QAAO,eAAW,MAAC,WAAU,8BACnE;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,GAAG;AAAA,cACH,QAAO;AAAA,cACP,aAAa;AAAA,cACb,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,OAAO,EAAE,iBAAiB,OAAO;AAAA;AAAA,UACnC,GACF;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,yBAAQ;","names":["CheckboxPrimitive"]}
|
|
@@ -12,7 +12,7 @@ function CheckboxCheck({ className, indeterminate, ...props }) {
|
|
|
12
12
|
const [length, setLength] = useState(15);
|
|
13
13
|
useLayoutEffect(() => {
|
|
14
14
|
const path = pathRef.current;
|
|
15
|
-
if (path) {
|
|
15
|
+
if (path && typeof path.getTotalLength === "function") {
|
|
16
16
|
setLength(Math.ceil(path.getTotalLength()));
|
|
17
17
|
}
|
|
18
18
|
}, []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/blocks/e-commerce/checkout-forms/checkbox-check.tsx"],"sourcesContent":["'use client'\n\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox'\n\nimport { cn } from '../../../lib/utils'\n\nconst BOX_MS = 150\nconst DRAW_MS = 350\nconst UNCHECK_MS = 150\nconst EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'\n\nexport function CheckboxCheck({ className, indeterminate, ...props }: CheckboxPrimitive.Root.Props) {\n const pathRef = useRef<SVGPathElement>(null)\n const [length, setLength] = useState(15)\n\n useLayoutEffect(() => {\n const path = pathRef.current\n if (path) {\n setLength(Math.ceil(path.getTotalLength()))\n }\n }, [])\n\n const mark = indeterminate ? 'M2.12 5.08H8.47' : 'M1.69 5.08L3.81 7.2L8.47 2.54'\n\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n 'peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary',\n 'motion-reduce:transition-none',\n className\n )}\n style={{ transition: `background-color ${BOX_MS}ms ${EASE}, border-color ${BOX_MS}ms ${EASE}` }}\n indeterminate={indeterminate}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n keepMounted\n data-slot=\"checkbox-indicator\"\n className={cn(\n 'grid size-3.5 place-content-center text-current',\n '[&_path]:[transition:stroke-dashoffset_var(--check-uncheck)_var(--check-ease)]',\n '[&_path]:[stroke-dashoffset:var(--check-len)]',\n 'data-checked:[&_path]:[stroke-dashoffset:0]',\n 'data-checked:[&_path]:[transition-duration:var(--check-draw)]',\n 'motion-reduce:[&_path]:transition-none'\n )}\n style={\n {\n '--check-len': length,\n '--check-draw': `${DRAW_MS}ms`,\n '--check-uncheck': `${UNCHECK_MS}ms`,\n '--check-ease': EASE,\n } as React.CSSProperties\n }\n >\n <svg viewBox=\"0 0 10.1668 10.1668\" fill=\"none\" aria-hidden className=\"size-full overflow-visible\">\n <path\n ref={pathRef}\n d={mark}\n stroke=\"currentColor\"\n strokeWidth={0.9}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{ strokeDasharray: length }}\n />\n </svg>\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport default CheckboxCheck"],"mappings":";AA0DU;AAxDV,SAAS,iBAAiB,QAAQ,gBAAgB;AAClD,SAAS,YAAY,yBAAyB;AAE9C,SAAS,UAAU;AAEnB,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,aAAa;AACnB,MAAM,OAAO;AAEN,SAAS,cAAc,EAAE,WAAW,eAAe,GAAG,MAAM,GAAiC;AAClG,QAAM,UAAU,OAAuB,IAAI;AAC3C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AAEvC,kBAAgB,MAAM;AACpB,UAAM,OAAO,QAAQ;AACrB,QAAI,
|
|
1
|
+
{"version":3,"sources":["../../../../src/blocks/e-commerce/checkout-forms/checkbox-check.tsx"],"sourcesContent":["'use client'\n\nimport { useLayoutEffect, useRef, useState } from 'react'\nimport { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox'\n\nimport { cn } from '../../../lib/utils'\n\nconst BOX_MS = 150\nconst DRAW_MS = 350\nconst UNCHECK_MS = 150\nconst EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'\n\nexport function CheckboxCheck({ className, indeterminate, ...props }: CheckboxPrimitive.Root.Props) {\n const pathRef = useRef<SVGPathElement>(null)\n const [length, setLength] = useState(15)\n\n useLayoutEffect(() => {\n const path = pathRef.current\n if (path && typeof path.getTotalLength === 'function') {\n setLength(Math.ceil(path.getTotalLength()))\n }\n }, [])\n\n const mark = indeterminate ? 'M2.12 5.08H8.47' : 'M1.69 5.08L3.81 7.2L8.47 2.54'\n\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n 'peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary',\n 'motion-reduce:transition-none',\n className\n )}\n style={{ transition: `background-color ${BOX_MS}ms ${EASE}, border-color ${BOX_MS}ms ${EASE}` }}\n indeterminate={indeterminate}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n keepMounted\n data-slot=\"checkbox-indicator\"\n className={cn(\n 'grid size-3.5 place-content-center text-current',\n '[&_path]:[transition:stroke-dashoffset_var(--check-uncheck)_var(--check-ease)]',\n '[&_path]:[stroke-dashoffset:var(--check-len)]',\n 'data-checked:[&_path]:[stroke-dashoffset:0]',\n 'data-checked:[&_path]:[transition-duration:var(--check-draw)]',\n 'motion-reduce:[&_path]:transition-none'\n )}\n style={\n {\n '--check-len': length,\n '--check-draw': `${DRAW_MS}ms`,\n '--check-uncheck': `${UNCHECK_MS}ms`,\n '--check-ease': EASE,\n } as React.CSSProperties\n }\n >\n <svg viewBox=\"0 0 10.1668 10.1668\" fill=\"none\" aria-hidden className=\"size-full overflow-visible\">\n <path\n ref={pathRef}\n d={mark}\n stroke=\"currentColor\"\n strokeWidth={0.9}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{ strokeDasharray: length }}\n />\n </svg>\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport default CheckboxCheck"],"mappings":";AA0DU;AAxDV,SAAS,iBAAiB,QAAQ,gBAAgB;AAClD,SAAS,YAAY,yBAAyB;AAE9C,SAAS,UAAU;AAEnB,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,aAAa;AACnB,MAAM,OAAO;AAEN,SAAS,cAAc,EAAE,WAAW,eAAe,GAAG,MAAM,GAAiC;AAClG,QAAM,UAAU,OAAuB,IAAI;AAC3C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,EAAE;AAEvC,kBAAgB,MAAM;AACpB,UAAM,OAAO,QAAQ;AACrB,QAAI,QAAQ,OAAO,KAAK,mBAAmB,YAAY;AACrD,gBAAU,KAAK,KAAK,KAAK,eAAe,CAAC,CAAC;AAAA,IAC5C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,gBAAgB,oBAAoB;AAEjD,SACE;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,EAAE,YAAY,oBAAoB,MAAM,MAAM,IAAI,kBAAkB,MAAM,MAAM,IAAI,GAAG;AAAA,MAC9F;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,QAAC,kBAAkB;AAAA,QAAlB;AAAA,UACC,aAAW;AAAA,UACX,aAAU;AAAA,UACV,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,OACE;AAAA,YACE,eAAe;AAAA,YACf,gBAAgB,GAAG,OAAO;AAAA,YAC1B,mBAAmB,GAAG,UAAU;AAAA,YAChC,gBAAgB;AAAA,UAClB;AAAA,UAGF,8BAAC,SAAI,SAAQ,uBAAsB,MAAK,QAAO,eAAW,MAAC,WAAU,8BACnE;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,GAAG;AAAA,cACH,QAAO;AAAA,cACP,aAAa;AAAA,cACb,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,OAAO,EAAE,iBAAiB,OAAO;AAAA;AAAA,UACnC,GACF;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,yBAAQ;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CheckoutAddressValues } from '@thorprovider/types';
|
|
2
|
+
/**
|
|
3
|
+
* Compare two controlled addresses for the saved-address affordances.
|
|
4
|
+
*
|
|
5
|
+
* The host may serialise an absent optional field as `undefined` or as an
|
|
6
|
+
* empty string; both mean "not supplied" and must compare equal. Whitespace is
|
|
7
|
+
* ignored so a value that only gained surrounding spaces is still the same
|
|
8
|
+
* address. Every address key participates.
|
|
9
|
+
*/
|
|
10
|
+
export declare function addressesEqual(a: CheckoutAddressValues, b: CheckoutAddressValues): boolean;
|
|
11
|
+
//# sourceMappingURL=checkout-address-equality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout-address-equality.d.ts","sourceRoot":"","sources":["../../../../src/blocks/e-commerce/checkout-forms/checkout-address-equality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAmBhE;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,qBAAqB,EACxB,CAAC,EAAE,qBAAqB,GACvB,OAAO,CAET"}
|