@mohasinac/appkit 2.7.57 → 2.7.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +7 -1
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -2
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/configs/tailwind.d.ts +16 -3
- package/dist/configs/tailwind.js +18 -5
- package/dist/features/account/components/AddressBook.js +1 -1
- package/dist/features/account/components/BuyerAccountGuideView.js +7 -7
- package/dist/features/account/components/BuyerAuctionsGuideView.js +7 -7
- package/dist/features/account/components/BuyerOrdersGuideView.js +6 -6
- package/dist/features/account/components/BuyerShoppingGuideView.js +7 -7
- package/dist/features/account/components/UserOffersPanel.js +1 -1
- package/dist/features/account/components/UserSupportView.js +4 -4
- package/dist/features/admin/components/AdminAdsView.js +1 -1
- package/dist/features/admin/components/AdminAllEventEntriesView.js +1 -1
- package/dist/features/admin/components/AdminAnalyticsGuideView.js +3 -3
- package/dist/features/admin/components/AdminBidsView.js +1 -1
- package/dist/features/admin/components/AdminBlogView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +1 -1
- package/dist/features/admin/components/AdminBundlesView.js +1 -1
- package/dist/features/admin/components/AdminCarouselView.js +2 -2
- package/dist/features/admin/components/AdminCartsView.js +1 -1
- package/dist/features/admin/components/AdminCatalogGuideView.js +5 -5
- package/dist/features/admin/components/AdminCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminContactEditorView.js +2 -2
- package/dist/features/admin/components/AdminContactView.js +1 -1
- package/dist/features/admin/components/AdminContentGuideView.js +6 -6
- package/dist/features/admin/components/AdminCouponsView.js +1 -1
- package/dist/features/admin/components/AdminFaqsView.js +1 -1
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
- package/dist/features/admin/components/AdminFeaturesView.js +1 -1
- package/dist/features/admin/components/AdminGuideHubView.js +1 -1
- package/dist/features/admin/components/AdminHistoryView.js +1 -1
- package/dist/features/admin/components/AdminListingScaffold.js +1 -1
- package/dist/features/admin/components/AdminNewsletterView.js +1 -1
- package/dist/features/admin/components/AdminNotificationsView.js +1 -1
- package/dist/features/admin/components/AdminOrdersGuideView.js +5 -5
- package/dist/features/admin/components/AdminOrdersView.js +1 -1
- package/dist/features/admin/components/AdminPayoutsView.js +1 -1
- package/dist/features/admin/components/AdminProductsView.js +1 -1
- package/dist/features/admin/components/AdminReturnRequestsView.js +1 -1
- package/dist/features/admin/components/AdminReviewsView.js +1 -1
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -3
- package/dist/features/admin/components/AdminScammersView.js +4 -4
- package/dist/features/admin/components/AdminSectionsView.js +1 -1
- package/dist/features/admin/components/AdminSessionsView.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +1 -1
- package/dist/features/admin/components/AdminStoreAddressesView.js +1 -1
- package/dist/features/admin/components/AdminStoresGuideView.js +6 -6
- package/dist/features/admin/components/AdminStoresView.js +1 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +1 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +4 -4
- package/dist/features/admin/components/AdminSupportTicketsView.js +7 -7
- package/dist/features/admin/components/AdminTeamGuideView.js +4 -4
- package/dist/features/admin/components/AdminTeamView.js +1 -1
- package/dist/features/admin/components/AdminTrustGuideView.js +5 -5
- package/dist/features/admin/components/AdminUserEditorView.js +1 -1
- package/dist/features/admin/components/AdminUsersGuideView.js +5 -5
- package/dist/features/admin/components/AdminUsersView.js +1 -1
- package/dist/features/admin/components/AdminViewCards.js +1 -1
- package/dist/features/admin/components/AdminWishlistsView.js +1 -1
- package/dist/features/admin/components/DataTable.js +1 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +2 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
- package/dist/features/auth/components/VerifyEmailView.js +1 -1
- package/dist/features/blog/components/BlogListView.js +1 -1
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/cart/components/CartDrawer.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
- package/dist/features/checkout/components/CheckoutStepper.js +1 -1
- package/dist/features/collections/components/CollectionCard.js +1 -1
- package/dist/features/copilot/components/AdminCopilotView.js +2 -2
- package/dist/features/events/components/AdminEventsView.js +1 -1
- package/dist/features/events/components/EventPollWidget.js +2 -2
- package/dist/features/events/components/EventStatusBadge.js +4 -4
- package/dist/features/events/components/SpinWheelView.js +1 -1
- package/dist/features/faq/components/FAQAccordion.js +2 -2
- package/dist/features/forms/Input.js +3 -3
- package/dist/features/forms/Select.js +2 -2
- package/dist/features/forms/Textarea.js +2 -2
- package/dist/features/forms/utils.d.ts +1 -1
- package/dist/features/forms/utils.js +1 -1
- package/dist/features/homepage/components/CharacterHotspotForm.js +2 -2
- package/dist/features/layout/BottomActions.js +2 -2
- package/dist/features/layout/ListingLayout.js +3 -3
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/media/index.d.ts +2 -0
- package/dist/features/media/index.js +1 -0
- package/dist/features/media/modals/ImageCropModal.js +1 -1
- package/dist/features/media/modals/ImageEditor.d.ts +12 -0
- package/dist/features/media/modals/ImageEditor.js +73 -0
- package/dist/features/media/upload/ImageUpload.d.ts +5 -1
- package/dist/features/media/upload/ImageUpload.js +33 -8
- package/dist/features/media/upload/MediaUploadField.d.ts +5 -1
- package/dist/features/media/upload/MediaUploadField.js +26 -12
- package/dist/features/orders/components/OrdersList.js +7 -7
- package/dist/features/orders/components/RefundHistoryTable.js +2 -2
- package/dist/features/orders/components/RefundRequestView.js +3 -3
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderBadge.js +4 -4
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/pre-orders/components/PreorderCard.js +2 -2
- package/dist/features/products/components/CustomSectionsEditor.js +1 -1
- package/dist/features/products/components/MakeOfferButton.js +2 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
- package/dist/features/products/components/PrizeDrawItemsEditor.js +3 -3
- package/dist/features/products/components/PrizeRevealModal.js +3 -3
- package/dist/features/products/components/ProductDetailPageView.js +4 -4
- package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
- package/dist/features/products/components/ProductGrid.js +3 -3
- package/dist/features/promotions/components/CouponCard.js +2 -2
- package/dist/features/promotions/components/PromotionsView.js +1 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +2 -2
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +2 -2
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +2 -2
- package/dist/features/seller/components/SellerAuctionsView.js +1 -1
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerBundlesView.js +2 -2
- package/dist/features/seller/components/SellerClassifiedView.js +3 -3
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
- package/dist/features/seller/components/SellerFeaturesView.js +1 -1
- package/dist/features/seller/components/SellerLiveView.js +4 -4
- package/dist/features/seller/components/SellerOffersPanel.js +2 -2
- package/dist/features/seller/components/SellerOffersView.js +1 -1
- package/dist/features/seller/components/SellerOrdersView.js +2 -2
- package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerProductsCards.js +1 -1
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerReviewsView.js +1 -1
- package/dist/features/seller/components/SellerShippingConfigsView.js +3 -3
- package/dist/features/seller/components/SellerStoreCategoriesView.js +2 -2
- package/dist/features/seller/components/SellerTemplatesView.js +2 -2
- package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
- package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
- package/dist/features/stores/components/StoreHeader.js +1 -1
- package/dist/features/stores/components/StoreListingsGuideView.js +3 -3
- package/dist/features/stores/components/StoreOrdersGuideView.js +4 -4
- package/dist/features/stores/components/StoreSettingsGuideView.js +2 -2
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +4 -4
- package/dist/features/wishlist/components/WishlistPage.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/styles.css +286 -3
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/motion.d.ts +162 -0
- package/dist/tokens/motion.js +89 -0
- package/dist/ui/DataTable.js +3 -2
- package/dist/ui/components/Accordion.js +2 -1
- package/dist/ui/components/Card.d.ts +5 -2
- package/dist/ui/components/Card.js +29 -11
- package/dist/ui/components/Div.d.ts +2 -16
- package/dist/ui/components/Div.js +2 -16
- package/dist/ui/components/Layout.d.ts +9 -19
- package/dist/ui/components/Layout.js +9 -7
- package/dist/ui/components/Modal.js +7 -4
- package/dist/ui/components/Motion.d.ts +75 -0
- package/dist/ui/components/Motion.js +122 -0
- package/dist/ui/components/Semantic.d.ts +81 -14
- package/dist/ui/components/Semantic.js +75 -10
- package/dist/ui/components/Semantic.style.css +261 -2
- package/dist/ui/components/SideDrawer.d.ts +1 -1
- package/dist/ui/components/SideDrawer.js +8 -6
- package/dist/ui/components/SideModal.d.ts +1 -1
- package/dist/ui/components/SideModal.js +11 -9
- package/dist/ui/components/StackedViewShell.js +6 -1
- package/dist/ui/components/Toast.js +5 -2
- package/dist/ui/components/Typography.d.ts +44 -3
- package/dist/ui/components/Typography.js +15 -30
- package/dist/ui/components/Typography.style.css +24 -0
- package/dist/ui/components/VacationBanner.js +2 -1
- package/dist/ui/components/surface-tokens.d.ts +70 -0
- package/dist/ui/components/surface-tokens.js +68 -0
- package/dist/ui/forms/FormShell.d.ts +6 -1
- package/dist/ui/forms/FormShell.js +32 -4
- package/dist/ui/index.d.ts +9 -2
- package/dist/ui/index.js +4 -2
- package/dist/validation/schemas.d.ts +28 -28
- package/package.json +3 -1
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState, useCallback } from "react";
|
|
4
4
|
import { useTranslations } from "next-intl";
|
|
5
|
+
import { motion, AnimatePresence, useReducedMotion } from "motion/react";
|
|
5
6
|
import { Button } from "./Button";
|
|
6
7
|
import { Row } from "./Layout";
|
|
7
8
|
import { Heading, Span } from "./Typography";
|
|
8
9
|
import { useSwipe } from "../../react";
|
|
9
10
|
import { Text } from "./Typography";
|
|
11
|
+
import { SPRING_SNAPPY } from "../../tokens/motion";
|
|
10
12
|
const UI_SIDE_DRAWER = {
|
|
11
13
|
backdrop: "appkit-side-drawer__backdrop",
|
|
12
14
|
root: "appkit-side-drawer",
|
|
@@ -142,11 +144,11 @@ export function SideDrawer({ isOpen, onClose, title, children, footer, mode = "v
|
|
|
142
144
|
: { onSwipeRight: () => attemptClose() }),
|
|
143
145
|
minSwipeDistance: 60,
|
|
144
146
|
});
|
|
145
|
-
|
|
146
|
-
return null;
|
|
147
|
+
const reduced = useReducedMotion();
|
|
147
148
|
const positionClass = side === "left" ? UI_SIDE_DRAWER.left : UI_SIDE_DRAWER.right;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
const slideX = side === "left" ? "-100%" : "100%";
|
|
150
|
+
return (_jsx(AnimatePresence, { children: isOpen && (_jsxs(_Fragment, { children: [_jsx(motion.div, { className: UI_SIDE_DRAWER.backdrop, onClick: attemptClose, "aria-hidden": "true", initial: reduced ? false : { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 } }), _jsxs(motion.div, { ref: drawerRef, className: [UI_SIDE_DRAWER.root, positionClass].join(" "), role: "dialog", "aria-modal": "true", "aria-labelledby": "drawer-title", initial: reduced ? false : { x: slideX }, animate: { x: 0 }, exit: { x: slideX }, transition: SPRING_SNAPPY, "data-section": "sidedrawer-div-598", children: [_jsxs(Row, { justify: "between", gap: "none", className: [
|
|
151
|
+
UI_SIDE_DRAWER.header,
|
|
152
|
+
UI_SIDE_DRAWER.headerMode[mode],
|
|
153
|
+
].join(" "), children: [_jsxs(Row, { gap: "3", className: "min-w-0", children: [_jsx(Button, { variant: "ghost", onClick: attemptClose, className: UI_SIDE_DRAWER.closeBtn, "aria-label": tActions("close"), children: _jsx("svg", { className: UI_SIDE_DRAWER.closeIcon, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }), _jsx(Heading, { level: 3, id: "drawer-title", className: "truncate", children: title })] }), mode === "delete" && (_jsx(Span, { className: UI_SIDE_DRAWER.deleteBadge, children: tActions("delete") }))] }), _jsx("div", { className: UI_SIDE_DRAWER.content, "data-section": "sidedrawer-div-599", children: children }), footer && _jsx("div", { className: UI_SIDE_DRAWER.footer, "data-section": "sidedrawer-div-600", children: footer })] }), showUnsavedWarning && (_jsxs(_Fragment, { children: [_jsx("div", { className: UI_SIDE_DRAWER.warnBackdrop, onClick: cancelClose }), _jsxs("div", { className: UI_SIDE_DRAWER.warnDialog, "data-section": "sidedrawer-div-601", children: [_jsxs("div", { className: UI_SIDE_DRAWER.warnHeader, "data-section": "sidedrawer-div-602", children: [_jsx("div", { className: UI_SIDE_DRAWER.warnIcon, "data-section": "sidedrawer-div-603", children: _jsx("svg", { fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }) }), _jsxs("div", { "data-section": "sidedrawer-div-604", children: [_jsx(Heading, { level: 4, className: "mb-1", children: tConfirm("unsavedChangesTitle") }), _jsx(Text, { className: UI_SIDE_DRAWER.warnText, children: tConfirm("unsavedChangesDescription") })] })] }), _jsxs("div", { className: UI_SIDE_DRAWER.warnActions, "data-section": "sidedrawer-div-605", children: [_jsx(Button, { variant: "outline", onClick: cancelClose, size: "sm", children: tActions("keepEditing") }), _jsx(Button, { variant: "danger", onClick: confirmClose, size: "sm", children: tActions("discardChanges") })] })] })] }))] })) }));
|
|
152
154
|
}
|
|
@@ -21,4 +21,4 @@ export interface SideModalProps {
|
|
|
21
21
|
* - backdrop click closes panel
|
|
22
22
|
* - role="dialog" + aria-modal + aria-labelledby
|
|
23
23
|
*/
|
|
24
|
-
export declare function SideModal({ isOpen, onClose, title, side, children, className, }: SideModalProps): import("react/jsx-runtime").JSX.Element
|
|
24
|
+
export declare function SideModal({ isOpen, onClose, title, side, children, className, }: SideModalProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef } from "react";
|
|
4
|
+
import { motion, AnimatePresence, useReducedMotion } from "motion/react";
|
|
4
5
|
import { Button, Div, Heading } from "..";
|
|
6
|
+
import { SPRING_SNAPPY } from "../../tokens/motion";
|
|
5
7
|
/**
|
|
6
8
|
* SideModal — slides in from the right (or left) on desktop (60 vw),
|
|
7
9
|
* full-screen drawer on mobile (< sm breakpoint).
|
|
@@ -48,13 +50,13 @@ export function SideModal({ isOpen, onClose, title, side = "right", children, cl
|
|
|
48
50
|
document.body.style.overflow = "";
|
|
49
51
|
};
|
|
50
52
|
}, [isOpen]);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return (_jsxs(Div, { className: "appkit-side-modal", "aria-hidden": !isOpen, children: [_jsx(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
const reduced = useReducedMotion();
|
|
54
|
+
const slideX = side === "left" ? "-100%" : "100%";
|
|
55
|
+
return (_jsx(AnimatePresence, { children: isOpen && (_jsxs(Div, { className: "appkit-side-modal", "aria-hidden": !isOpen, children: [_jsx(motion.div, { className: "appkit-side-modal__backdrop", onClick: onClose, "aria-hidden": "true", initial: reduced ? false : { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 } }), _jsxs(motion.div, { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-labelledby": title ? titleId.current : undefined, className: [
|
|
56
|
+
"appkit-side-modal__panel",
|
|
57
|
+
`appkit-side-modal__panel--${side}`,
|
|
58
|
+
className,
|
|
59
|
+
]
|
|
60
|
+
.filter(Boolean)
|
|
61
|
+
.join(" "), initial: reduced ? false : { x: slideX }, animate: { x: 0 }, exit: { x: slideX }, transition: SPRING_SNAPPY, children: [title && (_jsxs(Div, { className: "appkit-side-modal__header", children: [_jsx(Heading, { level: 2, id: titleId.current, className: "text-base font-semibold text-neutral-900 dark:text-white truncate", children: title }), _jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, "aria-label": "Close panel", className: "ml-2 flex-shrink-0", children: "\u2715" })] })), _jsx(Div, { className: "appkit-side-modal__body", children: children })] })] })) }));
|
|
60
62
|
}
|
|
@@ -33,5 +33,10 @@ export function StackedViewShell({ title, labels = {},
|
|
|
33
33
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
34
34
|
portal, renderHeader, sections = [], isEmpty = false, renderEmpty, overlays, className = "", }) {
|
|
35
35
|
const displayTitle = title ?? labels?.title;
|
|
36
|
-
return (_jsxs(Div, { className: className, children: [renderHeader ? (renderHeader()) : displayTitle ? (_jsx(Heading, { level: 1, className: "text-2xl font-bold mb-6", children: displayTitle })) : null, isEmpty && renderEmpty ? (renderEmpty()) : (_jsx(_Fragment, { children: sections.map((slot, i) =>
|
|
36
|
+
return (_jsxs(Div, { className: className, children: [renderHeader ? (renderHeader()) : displayTitle ? (_jsx(Heading, { level: 1, className: "text-2xl font-bold mb-6", children: displayTitle })) : null, isEmpty && renderEmpty ? (renderEmpty()) : (_jsx(_Fragment, { children: sections.map((slot, i) => {
|
|
37
|
+
const resolved = resolveSlot(slot);
|
|
38
|
+
if (resolved == null)
|
|
39
|
+
return null;
|
|
40
|
+
return _jsx(React.Fragment, { children: resolved }, i);
|
|
41
|
+
}) })), overlays] }));
|
|
37
42
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
|
+
import { motion, AnimatePresence, useReducedMotion } from "motion/react";
|
|
4
5
|
import { Button } from "./Button";
|
|
5
6
|
import { Text } from "./Typography";
|
|
7
|
+
import { SPRING_SNAPPY } from "../../tokens/motion";
|
|
6
8
|
const ToastContext = React.createContext(undefined);
|
|
7
9
|
function buildToastId() {
|
|
8
10
|
return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -47,14 +49,15 @@ export function ToastProvider({ children, position = "top-right", }) {
|
|
|
47
49
|
}, [hideToast]);
|
|
48
50
|
return (_jsxs(ToastContext.Provider, { value: { showToast, hideToast }, children: [children, _jsx("div", { "aria-live": "polite", "aria-atomic": "true", "data-testid": "toast-container", className: [UI_TOAST.container, UI_TOAST.positions[position]]
|
|
49
51
|
.filter(Boolean)
|
|
50
|
-
.join(" "), "data-section": "toast-div-623", children: toasts.map((toast) => (_jsx(ToastRow, { toast: toast, onClose: hideToast }, toast.id))) })] }));
|
|
52
|
+
.join(" "), "data-section": "toast-div-623", children: _jsx(AnimatePresence, { mode: "popLayout", children: toasts.map((toast) => (_jsx(ToastRow, { toast: toast, onClose: hideToast }, toast.id))) }) })] }));
|
|
51
53
|
}
|
|
52
54
|
function ToastRow({ toast, onClose, }) {
|
|
55
|
+
const reduced = useReducedMotion();
|
|
53
56
|
const iconMap = {
|
|
54
57
|
success: _jsx("span", { "aria-hidden": "true", children: "\u2713" }),
|
|
55
58
|
error: _jsx("span", { "aria-hidden": "true", children: "!" }),
|
|
56
59
|
warning: _jsx("span", { "aria-hidden": "true", children: "!" }),
|
|
57
60
|
info: _jsx("span", { "aria-hidden": "true", children: "i" }),
|
|
58
61
|
};
|
|
59
|
-
return (_jsxs(
|
|
62
|
+
return (_jsxs(motion.div, { role: "alert", "data-testid": "toast", className: [UI_TOAST.row, UI_TOAST.variants[toast.variant]].join(" "), layout: true, initial: reduced ? false : { opacity: 0, x: 24, scale: 0.95 }, animate: { opacity: 1, x: 0, scale: 1 }, exit: { opacity: 0, x: 24, scale: 0.95 }, transition: SPRING_SNAPPY, "data-section": "toast-div-624", children: [_jsx("div", { className: UI_TOAST.icon, "data-section": "toast-div-625", children: iconMap[toast.variant] }), _jsx(Text, { as: "div", size: "sm", weight: "medium", className: "flex-1 pr-1", children: toast.message }), toast.action && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => { toast.action.onClick(); onClose(toast.id); }, className: "min-h-0 shrink-0 px-2 py-1 font-semibold underline", children: toast.action.label })), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onClose(toast.id), className: "min-h-0 shrink-0 px-2 py-1", "aria-label": "Close notification", children: "\u00D7" })] }));
|
|
60
63
|
}
|
|
@@ -1,19 +1,59 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
declare const TYPOGRAPHY: {
|
|
3
|
+
readonly headingLevel: {
|
|
4
|
+
readonly 1: "appkit-heading--h1";
|
|
5
|
+
readonly 2: "appkit-heading--h2";
|
|
6
|
+
readonly 3: "appkit-heading--h3";
|
|
7
|
+
readonly 4: "appkit-heading--h4";
|
|
8
|
+
readonly 5: "appkit-heading--h5";
|
|
9
|
+
readonly 6: "appkit-heading--h6";
|
|
10
|
+
};
|
|
11
|
+
readonly textSize: {
|
|
12
|
+
readonly xs: "appkit-text--xs";
|
|
13
|
+
readonly sm: "appkit-text--sm";
|
|
14
|
+
readonly base: "appkit-text--base";
|
|
15
|
+
readonly lg: "appkit-text--lg";
|
|
16
|
+
readonly xl: "appkit-text--xl";
|
|
17
|
+
};
|
|
18
|
+
readonly textWeight: {
|
|
19
|
+
readonly normal: "appkit-font--normal";
|
|
20
|
+
readonly medium: "appkit-font--medium";
|
|
21
|
+
readonly semibold: "appkit-font--semibold";
|
|
22
|
+
readonly bold: "appkit-font--bold";
|
|
23
|
+
};
|
|
24
|
+
readonly colorVariant: {
|
|
25
|
+
readonly primary: "appkit-color--primary";
|
|
26
|
+
readonly secondary: "appkit-color--secondary";
|
|
27
|
+
readonly muted: "appkit-color--muted";
|
|
28
|
+
readonly faint: "appkit-color--faint";
|
|
29
|
+
readonly error: "appkit-color--error";
|
|
30
|
+
readonly danger: "appkit-color--error";
|
|
31
|
+
readonly success: "appkit-color--success";
|
|
32
|
+
readonly warning: "appkit-color--warning";
|
|
33
|
+
readonly info: "appkit-color--info";
|
|
34
|
+
readonly none: "";
|
|
35
|
+
readonly inherit: "";
|
|
36
|
+
readonly accent: "appkit-color--accent";
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export type ColorVariant = keyof typeof TYPOGRAPHY.colorVariant;
|
|
2
40
|
interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
3
41
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
4
42
|
variant?: "primary" | "secondary" | "muted" | "none";
|
|
43
|
+
color?: ColorVariant;
|
|
5
44
|
children: React.ReactNode;
|
|
6
45
|
}
|
|
7
|
-
export declare function Heading({ level, variant, className, children, ...props }: HeadingProps): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
export declare function Heading({ level, variant, color, className, children, ...props }: HeadingProps): import("react/jsx-runtime").JSX.Element;
|
|
8
47
|
interface TextProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
9
48
|
variant?: "primary" | "secondary" | "muted" | "error" | "success" | "none";
|
|
49
|
+
color?: ColorVariant;
|
|
10
50
|
size?: "xs" | "sm" | "base" | "lg" | "xl";
|
|
11
51
|
weight?: "normal" | "medium" | "semibold" | "bold";
|
|
12
52
|
/** Override the rendered element. Defaults to `p`. */
|
|
13
53
|
as?: React.ElementType;
|
|
14
54
|
children: React.ReactNode;
|
|
15
55
|
}
|
|
16
|
-
export declare function Text({ variant, size, weight, className, as: Tag, children, ...props }: TextProps): import("react/jsx-runtime").JSX.Element;
|
|
56
|
+
export declare function Text({ variant, color, size, weight, className, as: Tag, children, ...props }: TextProps): import("react/jsx-runtime").JSX.Element;
|
|
17
57
|
interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
|
|
18
58
|
required?: boolean;
|
|
19
59
|
children: React.ReactNode;
|
|
@@ -42,9 +82,10 @@ export declare function Caption({ variant, className, children, ...props }: Capt
|
|
|
42
82
|
interface SpanProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
43
83
|
/** Colour variant. "inherit" (default) applies no colour class. */
|
|
44
84
|
variant?: "inherit" | "primary" | "secondary" | "muted" | "error" | "success" | "accent";
|
|
85
|
+
color?: ColorVariant;
|
|
45
86
|
size?: "xs" | "sm" | "base" | "lg" | "xl";
|
|
46
87
|
weight?: "normal" | "medium" | "semibold" | "bold";
|
|
47
88
|
children?: React.ReactNode;
|
|
48
89
|
}
|
|
49
|
-
export declare function Span({ variant, size, weight, className, children, ...props }: SpanProps): import("react/jsx-runtime").JSX.Element;
|
|
90
|
+
export declare function Span({ variant, color, size, weight, className, children, ...props }: SpanProps): import("react/jsx-runtime").JSX.Element;
|
|
50
91
|
export {};
|
|
@@ -25,30 +25,36 @@ const TYPOGRAPHY = {
|
|
|
25
25
|
primary: "appkit-color--primary",
|
|
26
26
|
secondary: "appkit-color--secondary",
|
|
27
27
|
muted: "appkit-color--muted",
|
|
28
|
+
faint: "appkit-color--faint",
|
|
28
29
|
error: "appkit-color--error",
|
|
30
|
+
danger: "appkit-color--error",
|
|
29
31
|
success: "appkit-color--success",
|
|
32
|
+
warning: "appkit-color--warning",
|
|
33
|
+
info: "appkit-color--info",
|
|
30
34
|
none: "",
|
|
31
35
|
inherit: "",
|
|
32
36
|
accent: "appkit-color--accent",
|
|
33
37
|
},
|
|
34
38
|
};
|
|
35
|
-
export function Heading({ level = 1, variant = "primary", className = "", children, ...props }) {
|
|
39
|
+
export function Heading({ level = 1, variant = "primary", color, className = "", children, ...props }) {
|
|
36
40
|
const Tag = `h${level}`;
|
|
41
|
+
const resolvedColor = color ?? variant;
|
|
37
42
|
return (_jsx(Tag, { className: [
|
|
38
43
|
"appkit-heading",
|
|
39
44
|
TYPOGRAPHY.headingLevel[level],
|
|
40
|
-
TYPOGRAPHY.colorVariant[
|
|
45
|
+
TYPOGRAPHY.colorVariant[resolvedColor],
|
|
41
46
|
className,
|
|
42
47
|
]
|
|
43
48
|
.filter(Boolean)
|
|
44
49
|
.join(" "), ...props, children: children }));
|
|
45
50
|
}
|
|
46
|
-
export function Text({ variant = "primary", size = "base", weight = "normal", className = "", as: Tag = "p", children, ...props }) {
|
|
51
|
+
export function Text({ variant = "primary", color, size = "base", weight = "normal", className = "", as: Tag = "p", children, ...props }) {
|
|
52
|
+
const resolvedColor = color ?? variant;
|
|
47
53
|
return (_jsx(Tag, { className: [
|
|
48
54
|
"appkit-text",
|
|
49
55
|
TYPOGRAPHY.textSize[size],
|
|
50
56
|
TYPOGRAPHY.textWeight[weight],
|
|
51
|
-
TYPOGRAPHY.colorVariant[
|
|
57
|
+
TYPOGRAPHY.colorVariant[resolvedColor],
|
|
52
58
|
className,
|
|
53
59
|
]
|
|
54
60
|
.filter(Boolean)
|
|
@@ -67,34 +73,13 @@ export function Caption({ variant = "default", className = "", children, ...prop
|
|
|
67
73
|
.filter(Boolean)
|
|
68
74
|
.join(" "), ...props, children: children }));
|
|
69
75
|
}
|
|
70
|
-
export function Span({ variant = "inherit", size, weight, className = "", children, ...props }) {
|
|
71
|
-
const
|
|
72
|
-
inherit: "",
|
|
73
|
-
primary: "appkit-color--primary",
|
|
74
|
-
secondary: "appkit-color--secondary",
|
|
75
|
-
muted: "appkit-color--muted",
|
|
76
|
-
error: "appkit-color--error",
|
|
77
|
-
success: "appkit-color--success",
|
|
78
|
-
accent: "appkit-color--accent",
|
|
79
|
-
};
|
|
80
|
-
const sizeClasses = {
|
|
81
|
-
xs: "appkit-text--xs",
|
|
82
|
-
sm: "appkit-text--sm",
|
|
83
|
-
base: "appkit-text--base",
|
|
84
|
-
lg: "appkit-text--lg",
|
|
85
|
-
xl: "appkit-text--xl",
|
|
86
|
-
};
|
|
87
|
-
const weightClasses = {
|
|
88
|
-
normal: "appkit-font--normal",
|
|
89
|
-
medium: "appkit-font--medium",
|
|
90
|
-
semibold: "appkit-font--semibold",
|
|
91
|
-
bold: "appkit-font--bold",
|
|
92
|
-
};
|
|
76
|
+
export function Span({ variant = "inherit", color, size, weight, className = "", children, ...props }) {
|
|
77
|
+
const resolvedColor = color ?? variant;
|
|
93
78
|
const classes = [
|
|
94
79
|
"appkit-span",
|
|
95
|
-
size ?
|
|
96
|
-
weight ?
|
|
97
|
-
|
|
80
|
+
size ? TYPOGRAPHY.textSize[size] : "",
|
|
81
|
+
weight ? TYPOGRAPHY.textWeight[weight] : "",
|
|
82
|
+
TYPOGRAPHY.colorVariant[resolvedColor],
|
|
98
83
|
className,
|
|
99
84
|
]
|
|
100
85
|
.filter(Boolean)
|
|
@@ -107,6 +107,18 @@
|
|
|
107
107
|
color: var(--appkit-color-secondary);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
.appkit-color--faint {
|
|
111
|
+
color: var(--appkit-color-zinc-400);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.appkit-color--warning {
|
|
115
|
+
color: var(--appkit-color-warning, #d97706);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.appkit-color--info {
|
|
119
|
+
color: var(--appkit-color-info, #0284c7);
|
|
120
|
+
}
|
|
121
|
+
|
|
110
122
|
.dark .appkit-color--primary {
|
|
111
123
|
color: var(--appkit-color-text);
|
|
112
124
|
}
|
|
@@ -131,6 +143,18 @@
|
|
|
131
143
|
color: var(--appkit-color-primary-400);
|
|
132
144
|
}
|
|
133
145
|
|
|
146
|
+
.dark .appkit-color--faint {
|
|
147
|
+
color: var(--appkit-color-zinc-600);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.dark .appkit-color--warning {
|
|
151
|
+
color: var(--appkit-color-warning, #fbbf24);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.dark .appkit-color--info {
|
|
155
|
+
color: var(--appkit-color-info, #38bdf8);
|
|
156
|
+
}
|
|
157
|
+
|
|
134
158
|
.appkit-label {
|
|
135
159
|
display: block;
|
|
136
160
|
margin-bottom: 0.375rem;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Alert } from "./Alert";
|
|
4
|
+
import { Span } from "./Typography";
|
|
4
5
|
/**
|
|
5
6
|
* S-STORE-6-A — Vacation-mode banner shown on product detail + checkout
|
|
6
7
|
* pages when the seller has paused new orders.
|
|
@@ -12,5 +13,5 @@ export function VacationBanner({ storeName, message, returnDate, className, }) {
|
|
|
12
13
|
month: "short",
|
|
13
14
|
day: "numeric",
|
|
14
15
|
});
|
|
15
|
-
return (_jsx(Alert, { variant: "warning", className: className, children: _jsxs("div", { className: "text-sm", children: [_jsx("
|
|
16
|
+
return (_jsx(Alert, { variant: "warning", className: className, children: _jsxs("div", { className: "text-sm", children: [_jsx(Span, { weight: "bold", children: storeName ? `${storeName} is on vacation` : "Store is on vacation" }), message ? _jsxs("span", { children: [" \u2014 ", message] }) : null, formattedDate ? _jsxs("span", { children: [" Returns ", formattedDate, "."] }) : null, _jsx("div", { className: "text-xs opacity-80 mt-1", children: "New orders are paused; you can still wishlist items." })] }) }));
|
|
16
17
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface & layout tokens — shared prop maps for all layout primitives.
|
|
3
|
+
*
|
|
4
|
+
* These maps power the Bootstrap/MUI-style props (`surface`, `padding`,
|
|
5
|
+
* `rounded`, `border`, `shadow`) on Stack, Row, Grid, Container, Section,
|
|
6
|
+
* Article, Main, Aside, Div, BlockHeader, and BlockFooter.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SURFACE_MAP: {
|
|
9
|
+
readonly none: "";
|
|
10
|
+
readonly default: "bg-white dark:bg-slate-900";
|
|
11
|
+
readonly muted: "bg-zinc-50 dark:bg-slate-950";
|
|
12
|
+
readonly subtle: "bg-zinc-100 dark:bg-slate-900";
|
|
13
|
+
readonly inset: "bg-zinc-200 dark:bg-slate-800";
|
|
14
|
+
readonly card: "bg-white dark:bg-slate-900 border border-zinc-200 dark:border-slate-700 rounded-xl shadow-sm";
|
|
15
|
+
readonly elevated: "bg-white dark:bg-slate-900 border border-zinc-200 dark:border-slate-700 rounded-2xl shadow-md";
|
|
16
|
+
readonly interactive: "bg-white dark:bg-slate-900 border border-zinc-200 dark:border-slate-700 rounded-xl shadow-sm hover:shadow-md hover:border-primary-300/60 dark:hover:border-secondary-500/60 transition-all cursor-pointer";
|
|
17
|
+
readonly glass: "backdrop-blur-md bg-white/85 dark:bg-slate-900/85 border border-zinc-200/60 dark:border-slate-700/40 rounded-2xl shadow-lg";
|
|
18
|
+
readonly form: "bg-white dark:bg-slate-900 rounded-2xl border border-zinc-200 dark:border-slate-700 shadow-sm";
|
|
19
|
+
};
|
|
20
|
+
export type SurfaceKey = keyof typeof SURFACE_MAP;
|
|
21
|
+
export declare const PADDING_MAP: {
|
|
22
|
+
readonly none: "";
|
|
23
|
+
readonly xs: "p-2";
|
|
24
|
+
readonly sm: "p-3";
|
|
25
|
+
readonly md: "p-4";
|
|
26
|
+
readonly lg: "p-6";
|
|
27
|
+
readonly xl: "p-8";
|
|
28
|
+
readonly card: "p-5 sm:p-6 lg:p-8";
|
|
29
|
+
readonly section: "py-10 sm:py-14 xl:py-20";
|
|
30
|
+
readonly sectionSm: "py-6 sm:py-10";
|
|
31
|
+
readonly page: "py-6 sm:py-8 lg:py-10";
|
|
32
|
+
readonly inline: "px-4 py-3";
|
|
33
|
+
readonly inlineSm: "px-3 py-2";
|
|
34
|
+
readonly inlineLg: "px-6 py-4";
|
|
35
|
+
};
|
|
36
|
+
export type PaddingKey = keyof typeof PADDING_MAP;
|
|
37
|
+
export declare const ROUNDED_MAP: {
|
|
38
|
+
readonly none: "";
|
|
39
|
+
readonly sm: "rounded-sm";
|
|
40
|
+
readonly md: "rounded-md";
|
|
41
|
+
readonly lg: "rounded-lg";
|
|
42
|
+
readonly xl: "rounded-xl";
|
|
43
|
+
readonly "2xl": "rounded-2xl";
|
|
44
|
+
readonly full: "rounded-full";
|
|
45
|
+
};
|
|
46
|
+
export type RoundedKey = keyof typeof ROUNDED_MAP;
|
|
47
|
+
export declare const BORDER_MAP: {
|
|
48
|
+
readonly none: "";
|
|
49
|
+
readonly default: "border border-zinc-200 dark:border-slate-700";
|
|
50
|
+
readonly subtle: "border border-zinc-100 dark:border-slate-800/60";
|
|
51
|
+
readonly strong: "border border-zinc-300 dark:border-slate-600";
|
|
52
|
+
readonly dashed: "border border-dashed border-zinc-300 dark:border-slate-600";
|
|
53
|
+
};
|
|
54
|
+
export type BorderKey = keyof typeof BORDER_MAP;
|
|
55
|
+
export declare const SHADOW_MAP: {
|
|
56
|
+
readonly none: "";
|
|
57
|
+
readonly sm: "shadow-sm";
|
|
58
|
+
readonly md: "shadow-md";
|
|
59
|
+
readonly lg: "shadow-lg";
|
|
60
|
+
readonly xl: "shadow-xl";
|
|
61
|
+
};
|
|
62
|
+
export type ShadowKey = keyof typeof SHADOW_MAP;
|
|
63
|
+
export interface SurfaceProps {
|
|
64
|
+
surface?: SurfaceKey;
|
|
65
|
+
padding?: PaddingKey;
|
|
66
|
+
rounded?: RoundedKey;
|
|
67
|
+
border?: BorderKey;
|
|
68
|
+
shadow?: ShadowKey;
|
|
69
|
+
}
|
|
70
|
+
export declare function buildSurfaceClasses(props: SurfaceProps): string;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface & layout tokens — shared prop maps for all layout primitives.
|
|
3
|
+
*
|
|
4
|
+
* These maps power the Bootstrap/MUI-style props (`surface`, `padding`,
|
|
5
|
+
* `rounded`, `border`, `shadow`) on Stack, Row, Grid, Container, Section,
|
|
6
|
+
* Article, Main, Aside, Div, BlockHeader, and BlockFooter.
|
|
7
|
+
*/
|
|
8
|
+
export const SURFACE_MAP = {
|
|
9
|
+
none: "",
|
|
10
|
+
default: "bg-white dark:bg-slate-900",
|
|
11
|
+
muted: "bg-zinc-50 dark:bg-slate-950",
|
|
12
|
+
subtle: "bg-zinc-100 dark:bg-slate-900",
|
|
13
|
+
inset: "bg-zinc-200 dark:bg-slate-800",
|
|
14
|
+
card: "bg-white dark:bg-slate-900 border border-zinc-200 dark:border-slate-700 rounded-xl shadow-sm",
|
|
15
|
+
elevated: "bg-white dark:bg-slate-900 border border-zinc-200 dark:border-slate-700 rounded-2xl shadow-md",
|
|
16
|
+
interactive: "bg-white dark:bg-slate-900 border border-zinc-200 dark:border-slate-700 rounded-xl shadow-sm hover:shadow-md hover:border-primary-300/60 dark:hover:border-secondary-500/60 transition-all cursor-pointer",
|
|
17
|
+
glass: "backdrop-blur-md bg-white/85 dark:bg-slate-900/85 border border-zinc-200/60 dark:border-slate-700/40 rounded-2xl shadow-lg",
|
|
18
|
+
form: "bg-white dark:bg-slate-900 rounded-2xl border border-zinc-200 dark:border-slate-700 shadow-sm",
|
|
19
|
+
};
|
|
20
|
+
export const PADDING_MAP = {
|
|
21
|
+
none: "",
|
|
22
|
+
xs: "p-2",
|
|
23
|
+
sm: "p-3",
|
|
24
|
+
md: "p-4",
|
|
25
|
+
lg: "p-6",
|
|
26
|
+
xl: "p-8",
|
|
27
|
+
card: "p-5 sm:p-6 lg:p-8",
|
|
28
|
+
section: "py-10 sm:py-14 xl:py-20",
|
|
29
|
+
sectionSm: "py-6 sm:py-10",
|
|
30
|
+
page: "py-6 sm:py-8 lg:py-10",
|
|
31
|
+
inline: "px-4 py-3",
|
|
32
|
+
inlineSm: "px-3 py-2",
|
|
33
|
+
inlineLg: "px-6 py-4",
|
|
34
|
+
};
|
|
35
|
+
export const ROUNDED_MAP = {
|
|
36
|
+
none: "",
|
|
37
|
+
sm: "rounded-sm",
|
|
38
|
+
md: "rounded-md",
|
|
39
|
+
lg: "rounded-lg",
|
|
40
|
+
xl: "rounded-xl",
|
|
41
|
+
"2xl": "rounded-2xl",
|
|
42
|
+
full: "rounded-full",
|
|
43
|
+
};
|
|
44
|
+
export const BORDER_MAP = {
|
|
45
|
+
none: "",
|
|
46
|
+
default: "border border-zinc-200 dark:border-slate-700",
|
|
47
|
+
subtle: "border border-zinc-100 dark:border-slate-800/60",
|
|
48
|
+
strong: "border border-zinc-300 dark:border-slate-600",
|
|
49
|
+
dashed: "border border-dashed border-zinc-300 dark:border-slate-600",
|
|
50
|
+
};
|
|
51
|
+
export const SHADOW_MAP = {
|
|
52
|
+
none: "",
|
|
53
|
+
sm: "shadow-sm",
|
|
54
|
+
md: "shadow-md",
|
|
55
|
+
lg: "shadow-lg",
|
|
56
|
+
xl: "shadow-xl",
|
|
57
|
+
};
|
|
58
|
+
export function buildSurfaceClasses(props) {
|
|
59
|
+
return [
|
|
60
|
+
props.surface ? SURFACE_MAP[props.surface] : "",
|
|
61
|
+
props.padding ? PADDING_MAP[props.padding] : "",
|
|
62
|
+
props.rounded ? ROUNDED_MAP[props.rounded] : "",
|
|
63
|
+
props.border ? BORDER_MAP[props.border] : "",
|
|
64
|
+
props.shadow ? SHADOW_MAP[props.shadow] : "",
|
|
65
|
+
]
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.join(" ");
|
|
68
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { type ReactNode } from "react";
|
|
2
|
+
import type { ZodType } from "zod";
|
|
2
3
|
export interface FormShellStep {
|
|
3
4
|
id: string;
|
|
4
5
|
label: string;
|
|
@@ -32,6 +33,10 @@ export interface FormShellProps {
|
|
|
32
33
|
onPublish: (values: Record<string, unknown>) => Promise<void>;
|
|
33
34
|
/** Current form values — caller owns state */
|
|
34
35
|
values: Record<string, unknown>;
|
|
36
|
+
/** Zod schema for auto-validation on publish. Errors are mapped to field names. */
|
|
37
|
+
schema?: ZodType;
|
|
38
|
+
/** When true + schema provided, validate on every value change (not just publish). */
|
|
39
|
+
validateOnChange?: boolean;
|
|
35
40
|
/** Whether any values differ from the persisted state */
|
|
36
41
|
isDirty?: boolean;
|
|
37
42
|
draftId?: string;
|
|
@@ -63,4 +68,4 @@ export interface FormShellProviderProps {
|
|
|
63
68
|
values?: Record<string, unknown>;
|
|
64
69
|
}
|
|
65
70
|
export declare function FormShellProvider({ children, onSaveDraft, isDirty, autoSaveDelayMs, values, }: FormShellProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
66
|
-
export declare function FormShell({ steps, onSaveDraft, onPublish, values, isDirty, autoSaveDelayMs, publishLabel, saveDraftLabel, title, className, mobileAccordion, }: FormShellProps): import("react/jsx-runtime").JSX.Element;
|
|
71
|
+
export declare function FormShell({ steps, onSaveDraft, onPublish, values, schema, validateOnChange, isDirty, autoSaveDelayMs, publishLabel, saveDraftLabel, title, className, mobileAccordion, }: FormShellProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
4
4
|
import { Button } from "../components/Button";
|
|
5
|
-
import { Heading, Text } from "../components/Typography";
|
|
5
|
+
import { Heading, Span, Text } from "../components/Typography";
|
|
6
6
|
// ─── Context ──────────────────────────────────────────────────────────────────
|
|
7
7
|
export const FormShellContext = createContext(null);
|
|
8
8
|
export function useFormShell() {
|
|
@@ -61,7 +61,7 @@ function ErrorSummary({ errors, visible }) {
|
|
|
61
61
|
const entries = Object.entries(errors).filter(([, v]) => v);
|
|
62
62
|
if (!visible || entries.length === 0)
|
|
63
63
|
return null;
|
|
64
|
-
return (_jsxs("div", { className: "appkit-formshell__error-summary", role: "alert", "aria-live": "assertive", children: [_jsxs(Text, { size: "sm", variant: "error", className: "appkit-formshell__error-summary__title", children: ["Please fix ", entries.length, " error", entries.length !== 1 ? "s" : "", " before publishing."] }), _jsx("ul", { className: "appkit-formshell__error-summary__list", children: entries.map(([field, msg]) => (_jsx("li", { children: _jsxs(Text, { size: "sm", variant: "error", children: [_jsx("
|
|
64
|
+
return (_jsxs("div", { className: "appkit-formshell__error-summary", role: "alert", "aria-live": "assertive", children: [_jsxs(Text, { size: "sm", variant: "error", className: "appkit-formshell__error-summary__title", children: ["Please fix ", entries.length, " error", entries.length !== 1 ? "s" : "", " before publishing."] }), _jsx("ul", { className: "appkit-formshell__error-summary__list", children: entries.map(([field, msg]) => (_jsx("li", { children: _jsxs(Text, { size: "sm", variant: "error", children: [_jsx(Span, { weight: "bold", children: field }), ": ", msg] }) }, field))) })] }));
|
|
65
65
|
}
|
|
66
66
|
export function FormShellProvider({ children, onSaveDraft, isDirty = false, autoSaveDelayMs = 2000, values = {}, }) {
|
|
67
67
|
const [errors, setErrors] = useState({});
|
|
@@ -122,8 +122,25 @@ export function FormShellProvider({ children, onSaveDraft, isDirty = false, auto
|
|
|
122
122
|
}), [errors, touched, setFieldError, setFieldTouched, clearFieldError, isDirty]);
|
|
123
123
|
return _jsx(FormShellContext.Provider, { value: ctx, children: children });
|
|
124
124
|
}
|
|
125
|
+
// ─── Schema validation helper ────────────────────────────────────────────────
|
|
126
|
+
function validateSchema(schema, values, setFieldError, setErrors) {
|
|
127
|
+
const result = schema.safeParse(values);
|
|
128
|
+
if (result.success) {
|
|
129
|
+
setErrors({});
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
const newErrors = {};
|
|
133
|
+
for (const issue of result.error.issues) {
|
|
134
|
+
const path = issue.path.join(".");
|
|
135
|
+
if (path && !newErrors[path]) {
|
|
136
|
+
newErrors[path] = issue.message;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
setErrors(newErrors);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
125
142
|
// ─── FormShell ────────────────────────────────────────────────────────────────
|
|
126
|
-
export function FormShell({ steps, onSaveDraft, onPublish, values, isDirty = false, autoSaveDelayMs = 2000, publishLabel = "Publish", saveDraftLabel = "Save Draft", title, className = "", mobileAccordion = true, }) {
|
|
143
|
+
export function FormShell({ steps, onSaveDraft, onPublish, values, schema, validateOnChange = false, isDirty = false, autoSaveDelayMs = 2000, publishLabel = "Publish", saveDraftLabel = "Save Draft", title, className = "", mobileAccordion = true, }) {
|
|
127
144
|
const [errors, setErrors] = useState({});
|
|
128
145
|
const [touched, setTouched] = useState({});
|
|
129
146
|
const [currentStep, setCurrentStep] = useState(0);
|
|
@@ -198,8 +215,19 @@ export function FormShell({ steps, onSaveDraft, onPublish, values, isDirty = fal
|
|
|
198
215
|
setIsSubmitting(false);
|
|
199
216
|
}
|
|
200
217
|
}, [onSaveDraft, values]);
|
|
218
|
+
// Schema-driven live validation on value changes
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
if (!schema || !validateOnChange)
|
|
221
|
+
return;
|
|
222
|
+
validateSchema(schema, values, setFieldError, setErrors);
|
|
223
|
+
}, [schema, validateOnChange, values, setFieldError]);
|
|
201
224
|
const handlePublish = useCallback(async () => {
|
|
202
225
|
setShowErrorSummary(true);
|
|
226
|
+
if (schema) {
|
|
227
|
+
const valid = validateSchema(schema, values, setFieldError, setErrors);
|
|
228
|
+
if (!valid)
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
203
231
|
if (!isPublishReady)
|
|
204
232
|
return;
|
|
205
233
|
setIsSubmitting(true);
|
|
@@ -209,7 +237,7 @@ export function FormShell({ steps, onSaveDraft, onPublish, values, isDirty = fal
|
|
|
209
237
|
finally {
|
|
210
238
|
setIsSubmitting(false);
|
|
211
239
|
}
|
|
212
|
-
}, [isPublishReady, onPublish, values]);
|
|
240
|
+
}, [isPublishReady, onPublish, values, schema, setFieldError]);
|
|
213
241
|
const ctx = useMemo(() => ({
|
|
214
242
|
errors,
|
|
215
243
|
touched,
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -10,10 +10,11 @@ export type { FieldCheckboxProps } from "./forms";
|
|
|
10
10
|
export { FieldCheckbox } from "./forms";
|
|
11
11
|
export { buildColumns, createColumnBuilder, renderBoolean, renderCurrency, renderCurrencyCompact, renderCount, renderNullable, renderRating, } from "./columns";
|
|
12
12
|
export type { BooleanRenderOpts, RatingMode, RatingRenderOpts, } from "./columns";
|
|
13
|
-
export type { SectionProps, ArticleProps, MainProps, AsideProps, NavProps, BlockHeaderProps, BlockFooterProps, HeaderProps, FooterProps, UlProps, OlProps, LiProps, } from "./components/Semantic";
|
|
14
|
-
export { Section, Article, Main, Aside, Nav, BlockHeader, BlockFooter, Header, Footer, Ul, Ol, Li, } from "./components/Semantic";
|
|
13
|
+
export type { SectionProps, ArticleProps, MainProps, AsideProps, NavProps, BlockHeaderProps, BlockFooterProps, HeaderProps, FooterProps, UlProps, OlProps, LiProps, TableProps, TheadProps, TbodyProps, TrProps, ThProps, TdProps, CodeProps, PreProps, BlockquoteProps, FigureProps, FigcaptionProps, DlProps, DtProps, DdProps, } from "./components/Semantic";
|
|
14
|
+
export { Section, Article, Main, Aside, Nav, BlockHeader, BlockFooter, Header, Footer, Ul, Ol, Li, Table, Thead, Tbody, Tr, Th, Td, Code, Pre, Blockquote, Figure, Figcaption, Dl, Dt, Dd, } from "./components/Semantic";
|
|
15
15
|
export type { DivProps } from "./components/Div";
|
|
16
16
|
export { Div } from "./components/Div";
|
|
17
|
+
export type { ColorVariant } from "./components/Typography";
|
|
17
18
|
export { Heading, Text, Label, Caption, Span } from "./components/Typography";
|
|
18
19
|
export { FilterChipGroup } from "./components/FilterChipGroup";
|
|
19
20
|
export type { FilterChipGroupProps, FilterChipGroupTab, } from "./components/FilterChipGroup";
|
|
@@ -166,6 +167,8 @@ export type { DataTableProps, DataTableColumn } from "./DataTable";
|
|
|
166
167
|
export { DataTable } from "./DataTable";
|
|
167
168
|
export type { TableConfig, TableViewMode, PaginationConfig, StickyConfig, } from "../contracts";
|
|
168
169
|
export { DEFAULT_TABLE_CONFIG, DEFAULT_PAGINATION_CONFIG, DEFAULT_STICKY_CONFIG, mergeTableConfig, } from "../contracts";
|
|
170
|
+
export type { SurfaceKey, PaddingKey, RoundedKey, BorderKey, ShadowKey, SurfaceProps, } from "./components/surface-tokens";
|
|
171
|
+
export { SURFACE_MAP, PADDING_MAP, ROUNDED_MAP, BORDER_MAP, SHADOW_MAP, buildSurfaceClasses, } from "./components/surface-tokens";
|
|
169
172
|
export type { GapKey, ContainerSize, GridCols, ViewPortal, ContainerProps, StackProps, RowProps, GridProps, } from "./components/Layout";
|
|
170
173
|
export { Container, Stack, Row, Grid, GRID_MAP } from "./components/Layout";
|
|
171
174
|
export { classNames, mergeTailwindClasses } from "./style.helper";
|
|
@@ -203,3 +206,7 @@ export type { FormActionBarProps, FormActionBarBreadcrumb } from "./components/F
|
|
|
203
206
|
export { FormActionBar } from "./components/FormActionBar";
|
|
204
207
|
export type { ConfirmDeleteModalProps } from "./components/ConfirmDeleteModal";
|
|
205
208
|
export { ConfirmDeleteModal } from "./components/ConfirmDeleteModal";
|
|
209
|
+
export type { FadeInProps, SlideUpProps, SlideInProps, ScaleInProps, CollapseProps, PressScaleProps, HoverLiftProps, AnimatedListProps, AnimatedDivProps, AnimatedStackProps, AnimatedRowProps, DraggableProps, SwipeableProps, } from "./components/Motion";
|
|
210
|
+
export { FadeIn, SlideUp, SlideIn, ScaleIn, Collapse, PressScale, HoverLift, AnimatedList, AnimatedDiv, AnimatedStack, AnimatedRow, Draggable, Swipeable, AnimatePresence, } from "./components/Motion";
|
|
211
|
+
export type { MotionPreset } from "../tokens/motion";
|
|
212
|
+
export { MOTION_PRESETS, SPRING_SNAPPY, SPRING_GENTLE, EASE_OUT, } from "../tokens/motion";
|