@mohasinac/appkit 2.7.49 → 2.7.50
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/SidebarCollapseToggle.d.ts +19 -0
- package/dist/_internal/client/features/layout/SidebarCollapseToggle.js +15 -0
- package/dist/_internal/client/features/layout/index.d.ts +2 -0
- package/dist/_internal/client/features/layout/index.js +1 -0
- package/dist/_internal/server/features/checkout/actions.js +25 -2
- package/dist/_internal/server/features/promotions/actions.js +3 -1
- package/dist/_internal/shared/actions/action-registry.js +149 -0
- package/dist/client.d.ts +16 -0
- package/dist/client.js +11 -0
- package/dist/features/account/components/UserSidebar.js +2 -1
- package/dist/features/admin/components/AdminBlogEditorView.js +6 -2
- package/dist/features/admin/components/AdminSidebar.js +2 -1
- package/dist/features/auth/repository/session.repository.js +16 -1
- package/dist/features/cart/hooks/useAddToCart.d.ts +2 -0
- package/dist/features/cart/hooks/useAddToCart.js +2 -0
- package/dist/features/cart/hooks/useGuestCart.d.ts +2 -0
- package/dist/features/cart/utils/guest-cart.d.ts +7 -0
- package/dist/features/cart/utils/pending-ops.d.ts +6 -0
- package/dist/features/categories/components/CategoryBundlesListing.js +9 -1
- package/dist/features/categories/components/CategoryProductsListing.js +6 -10
- package/dist/features/categories/schemas/firestore.d.ts +9 -0
- package/dist/features/events/components/EventRaffleWinnerView.d.ts +9 -1
- package/dist/features/events/components/EventRaffleWinnerView.js +3 -3
- package/dist/features/events/components/SpinWheelView.js +3 -3
- package/dist/features/layout/BottomNavLayout.d.ts +5 -0
- package/dist/features/layout/BottomNavLayout.js +21 -0
- package/dist/features/layout/TitleBar.js +7 -1
- package/dist/features/layout/TitleBarLayout.d.ts +8 -2
- package/dist/features/layout/TitleBarLayout.js +11 -7
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +9 -5
- package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +3 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +8 -12
- package/dist/features/products/components/ProductDetailActions.d.ts +5 -1
- package/dist/features/products/components/ProductDetailActions.js +3 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +2 -0
- package/dist/features/products/components/ProductDetailPageView.js +4 -0
- package/dist/features/products/components/ProductGrid.js +3 -3
- package/dist/features/products/components/ProductsIndexListing.js +15 -8
- package/dist/features/promotions/components/CouponCard.d.ts +11 -1
- package/dist/features/promotions/components/CouponCard.js +36 -2
- package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +27 -0
- package/dist/features/promotions/repository/claimed-coupons.repository.js +115 -0
- package/dist/features/promotions/schemas/firestore.d.ts +34 -0
- package/dist/features/promotions/schemas/firestore.js +13 -0
- package/dist/features/seller/components/SellerAddressesView.js +3 -2
- package/dist/features/seller/components/SellerBidsView.js +33 -3
- package/dist/features/seller/components/SellerOrdersView.js +35 -0
- package/dist/features/seller/components/SellerProductShell.d.ts +2 -0
- package/dist/features/seller/components/SellerProductShell.js +26 -4
- package/dist/features/seller/components/SellerProductsCards.d.ts +19 -0
- package/dist/features/seller/components/SellerProductsCards.js +19 -0
- package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +14 -0
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +20 -0
- package/dist/features/seller/components/SellerProductsView.d.ts +3 -1
- package/dist/features/seller/components/SellerProductsView.js +68 -19
- package/dist/features/seller/components/SellerReviewsView.js +67 -4
- package/dist/features/seller/components/SellerSidebar.js +2 -1
- package/dist/features/seller/components/seller-products-styles.d.ts +7 -0
- package/dist/features/seller/components/seller-products-styles.js +14 -0
- package/dist/features/shell/FormShell.d.ts +7 -1
- package/dist/features/shell/FormShell.js +5 -2
- package/dist/features/store-extensions/index.d.ts +4 -0
- package/dist/features/store-extensions/index.js +4 -0
- package/dist/features/store-extensions/repository/rbac.repositories.d.ts +23 -0
- package/dist/features/store-extensions/repository/rbac.repositories.js +32 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +91 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.js +127 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +244 -0
- package/dist/features/store-extensions/schemas/firestore.js +158 -0
- package/dist/features/store-extensions/schemas/rbac.d.ts +65 -0
- package/dist/features/store-extensions/schemas/rbac.js +43 -0
- package/dist/features/stores/components/InteractiveStoreCard.js +7 -3
- package/dist/features/stores/components/StoreProductsListing.js +6 -10
- package/dist/features/stores/schemas/firestore.d.ts +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/next/routing/route-map.d.ts +79 -0
- package/dist/next/routing/route-map.js +34 -0
- package/dist/react/hooks/useFormStatePreservation.d.ts +17 -0
- package/dist/react/hooks/useFormStatePreservation.js +62 -0
- package/dist/react/hooks/useInlineRowEdit.d.ts +24 -0
- package/dist/react/hooks/useInlineRowEdit.js +68 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.js +4 -0
- package/dist/repositories/index.d.ts +4 -0
- package/dist/repositories/index.js +5 -0
- package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
- package/dist/seed/claimed-coupons-seed-data.d.ts +13 -0
- package/dist/seed/claimed-coupons-seed-data.js +79 -0
- package/dist/seed/index.d.ts +2 -0
- package/dist/seed/index.js +3 -0
- package/dist/seed/manifest.js +17 -0
- package/dist/seed/store-extensions-seed-data.d.ts +19 -0
- package/dist/seed/store-extensions-seed-data.js +421 -0
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.style.css +20 -12
- package/dist/ui/components/ClaimCouponButton.d.ts +28 -0
- package/dist/ui/components/ClaimCouponButton.js +89 -0
- package/dist/ui/components/QuickCreateModal.d.ts +15 -0
- package/dist/ui/components/QuickCreateModal.js +48 -0
- package/dist/ui/components/QuickCreateModal.style.css +84 -0
- package/dist/ui/components/StickyBottomBar.d.ts +22 -0
- package/dist/ui/components/StickyBottomBar.js +20 -0
- package/dist/ui/components/VacationBanner.d.ts +11 -0
- package/dist/ui/components/VacationBanner.js +16 -0
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.js +4 -0
- package/package.json +1 -1
|
@@ -81,41 +81,49 @@
|
|
|
81
81
|
gap: 0.625rem;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
/* Filled variants — colour rules use a chained-class selector (specificity
|
|
85
|
+
(0,2,0)) so they beat single-class Tailwind text utilities (0,1,0). This
|
|
86
|
+
guarantees contrast-safe foregrounds even when call-sites add a stray
|
|
87
|
+
`text-*` className. Tailwind utilities still apply for non-color props
|
|
88
|
+
like `text-xs` (font-size). See plan §4 "Defensive layer" + the global
|
|
89
|
+
sweep request 2026-05-18. */
|
|
90
|
+
|
|
91
|
+
.appkit-button.appkit-button--primary {
|
|
85
92
|
background: var(--appkit-color-primary-700);
|
|
86
93
|
color: var(--appkit-color-text-on-primary);
|
|
87
94
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
88
95
|
}
|
|
89
96
|
|
|
90
|
-
.appkit-button--primary:hover:not(:disabled) {
|
|
97
|
+
.appkit-button.appkit-button--primary:hover:not(:disabled) {
|
|
91
98
|
background: var(--appkit-color-primary-800);
|
|
92
99
|
}
|
|
93
100
|
|
|
94
|
-
.dark .appkit-button--primary {
|
|
101
|
+
.dark .appkit-button.appkit-button--primary {
|
|
95
102
|
background: var(--appkit-color-secondary);
|
|
103
|
+
color: var(--appkit-color-text-on-primary);
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
.dark .appkit-button--primary:hover:not(:disabled) {
|
|
106
|
+
.dark .appkit-button.appkit-button--primary:hover:not(:disabled) {
|
|
99
107
|
background: var(--appkit-color-secondary-400);
|
|
100
108
|
}
|
|
101
109
|
|
|
102
|
-
.appkit-button--secondary {
|
|
110
|
+
.appkit-button.appkit-button--secondary {
|
|
103
111
|
background: var(--appkit-color-surface);
|
|
104
112
|
border-color: var(--appkit-color-primary-700);
|
|
105
113
|
color: var(--appkit-color-primary-700);
|
|
106
114
|
}
|
|
107
115
|
|
|
108
|
-
.appkit-button--secondary:hover:not(:disabled) {
|
|
116
|
+
.appkit-button.appkit-button--secondary:hover:not(:disabled) {
|
|
109
117
|
background: color-mix(in srgb, var(--appkit-color-primary-700) 8%, transparent);
|
|
110
118
|
}
|
|
111
119
|
|
|
112
|
-
.dark .appkit-button--secondary {
|
|
120
|
+
.dark .appkit-button.appkit-button--secondary {
|
|
113
121
|
background: transparent;
|
|
114
122
|
border-color: var(--appkit-color-secondary);
|
|
115
123
|
color: var(--appkit-color-secondary);
|
|
116
124
|
}
|
|
117
125
|
|
|
118
|
-
.dark .appkit-button--secondary:hover:not(:disabled) {
|
|
126
|
+
.dark .appkit-button.appkit-button--secondary:hover:not(:disabled) {
|
|
119
127
|
background: color-mix(in srgb, var(--appkit-color-secondary) 12%, transparent);
|
|
120
128
|
}
|
|
121
129
|
|
|
@@ -156,21 +164,21 @@
|
|
|
156
164
|
background: rgba(30, 41, 59, 0.5);
|
|
157
165
|
}
|
|
158
166
|
|
|
159
|
-
.appkit-button--danger {
|
|
167
|
+
.appkit-button.appkit-button--danger {
|
|
160
168
|
background: var(--appkit-color-error);
|
|
161
169
|
color: var(--appkit-color-text-on-primary);
|
|
162
170
|
}
|
|
163
171
|
|
|
164
|
-
.appkit-button--danger:hover:not(:disabled) {
|
|
172
|
+
.appkit-button.appkit-button--danger:hover:not(:disabled) {
|
|
165
173
|
background: var(--appkit-color-error-hover);
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
.appkit-button--warning {
|
|
176
|
+
.appkit-button.appkit-button--warning {
|
|
169
177
|
background: var(--appkit-color-warning);
|
|
170
178
|
color: var(--appkit-color-text-on-primary);
|
|
171
179
|
}
|
|
172
180
|
|
|
173
|
-
.appkit-button--warning:hover:not(:disabled) {
|
|
181
|
+
.appkit-button.appkit-button--warning:hover:not(:disabled) {
|
|
174
182
|
background: var(--appkit-color-amber-400);
|
|
175
183
|
}
|
|
176
184
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaimCouponButton — surfaced anywhere a user wins or earns a coupon
|
|
3
|
+
* (SpinWheel "YOU WON" panel, raffle winner page, prize-draw reveal modal,
|
|
4
|
+
* promotional inserts).
|
|
5
|
+
*
|
|
6
|
+
* Behaviour:
|
|
7
|
+
* 1. If the visitor is not signed in, opens the standard LoginRequiredModal —
|
|
8
|
+
* no coupon is copied or saved. The wallet is per-user, so anonymous
|
|
9
|
+
* claims would be lost.
|
|
10
|
+
* 2. POST `/api/user/coupons/claim` to persist the claim into the user's
|
|
11
|
+
* wallet (idempotent — second claim is a no-op).
|
|
12
|
+
* 3. Copy the code to the clipboard so the user can paste it at checkout.
|
|
13
|
+
*
|
|
14
|
+
* No more cart deep-link — the wallet ("My Coupons" page) is the single home
|
|
15
|
+
* for claimed coupons, and the user applies them from there at checkout.
|
|
16
|
+
*/
|
|
17
|
+
import React from "react";
|
|
18
|
+
export interface ClaimCouponButtonProps {
|
|
19
|
+
couponCode: string;
|
|
20
|
+
/** Optional server-side claim handler — overrides the default wallet POST. */
|
|
21
|
+
onClaim?: (code: string) => Promise<void> | void;
|
|
22
|
+
/** Override the button label. */
|
|
23
|
+
label?: string;
|
|
24
|
+
className?: string;
|
|
25
|
+
size?: "sm" | "md" | "lg";
|
|
26
|
+
source?: "manual" | "promo" | "spin" | "raffle" | "prize-draw";
|
|
27
|
+
}
|
|
28
|
+
export declare function ClaimCouponButton({ couponCode, onClaim, label, className, size, source, }: ClaimCouponButtonProps): React.JSX.Element;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* ClaimCouponButton — surfaced anywhere a user wins or earns a coupon
|
|
5
|
+
* (SpinWheel "YOU WON" panel, raffle winner page, prize-draw reveal modal,
|
|
6
|
+
* promotional inserts).
|
|
7
|
+
*
|
|
8
|
+
* Behaviour:
|
|
9
|
+
* 1. If the visitor is not signed in, opens the standard LoginRequiredModal —
|
|
10
|
+
* no coupon is copied or saved. The wallet is per-user, so anonymous
|
|
11
|
+
* claims would be lost.
|
|
12
|
+
* 2. POST `/api/user/coupons/claim` to persist the claim into the user's
|
|
13
|
+
* wallet (idempotent — second claim is a no-op).
|
|
14
|
+
* 3. Copy the code to the clipboard so the user can paste it at checkout.
|
|
15
|
+
*
|
|
16
|
+
* No more cart deep-link — the wallet ("My Coupons" page) is the single home
|
|
17
|
+
* for claimed coupons, and the user applies them from there at checkout.
|
|
18
|
+
*/
|
|
19
|
+
import { useCallback, useState } from "react";
|
|
20
|
+
import { Button } from "./Button";
|
|
21
|
+
import { LoginRequiredModal } from "./LoginRequiredModal";
|
|
22
|
+
import { useSession } from "../../react/contexts/SessionContext";
|
|
23
|
+
import { useToast } from "./Toast";
|
|
24
|
+
async function postClaim(couponCode, source) {
|
|
25
|
+
if (typeof fetch === "undefined")
|
|
26
|
+
return false;
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch("/api/user/coupons/claim", {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: { "Content-Type": "application/json" },
|
|
31
|
+
credentials: "include",
|
|
32
|
+
body: JSON.stringify({ couponCode, source }),
|
|
33
|
+
});
|
|
34
|
+
return res.ok;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function copyToClipboard(text) {
|
|
41
|
+
if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await navigator.clipboard.writeText(text);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function ClaimCouponButton({ couponCode, onClaim, label, className, size = "md", source = "manual", }) {
|
|
53
|
+
const { user, loading } = useSession();
|
|
54
|
+
const { showToast } = useToast();
|
|
55
|
+
const [busy, setBusy] = useState(false);
|
|
56
|
+
const [claimed, setClaimed] = useState(false);
|
|
57
|
+
const [loginOpen, setLoginOpen] = useState(false);
|
|
58
|
+
const handleClick = useCallback(async () => {
|
|
59
|
+
if (busy || !couponCode)
|
|
60
|
+
return;
|
|
61
|
+
if (loading)
|
|
62
|
+
return;
|
|
63
|
+
if (!user) {
|
|
64
|
+
setLoginOpen(true);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
setBusy(true);
|
|
68
|
+
try {
|
|
69
|
+
const ok = onClaim != null
|
|
70
|
+
? (await Promise.resolve(onClaim(couponCode)), true)
|
|
71
|
+
: await postClaim(couponCode, source);
|
|
72
|
+
if (!ok) {
|
|
73
|
+
showToast("Could not save coupon. Please try again.", "error");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
await copyToClipboard(couponCode);
|
|
77
|
+
setClaimed(true);
|
|
78
|
+
showToast(`${couponCode} saved to your coupons.`, "success");
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
setBusy(false);
|
|
82
|
+
}
|
|
83
|
+
}, [busy, couponCode, loading, onClaim, showToast, source, user]);
|
|
84
|
+
return (_jsxs(_Fragment, { children: [_jsx(Button, { type: "button", variant: "primary", size: size, onClick: handleClick, disabled: busy || !couponCode || loading, className: className, children: busy
|
|
85
|
+
? "Saving…"
|
|
86
|
+
: claimed
|
|
87
|
+
? "Saved to My Coupons"
|
|
88
|
+
: (label ?? "Claim coupon") }), _jsx(LoginRequiredModal, { isOpen: loginOpen, onClose: () => setLoginOpen(false), message: "Sign in to save coupons to your wallet." })] }));
|
|
89
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface QuickCreateModalProps<T = unknown> {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
title: string;
|
|
5
|
+
onSave: () => Promise<T> | T;
|
|
6
|
+
onSaved?: (doc: T) => void;
|
|
7
|
+
onCancel: () => void;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
fullPageHref?: string;
|
|
10
|
+
saveLabel?: string;
|
|
11
|
+
cancelLabel?: string;
|
|
12
|
+
isSaving?: boolean;
|
|
13
|
+
saveDisabled?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function QuickCreateModal<T = unknown>({ isOpen, title, onSave, onSaved, onCancel, children, fullPageHref, saveLabel, cancelLabel, isSaving, saveDisabled, }: QuickCreateModalProps<T>): React.ReactPortal | null;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
5
|
+
import { Button } from "./Button";
|
|
6
|
+
import { Div } from "./Div";
|
|
7
|
+
import { Heading } from "./Typography";
|
|
8
|
+
import { Row } from "./Layout";
|
|
9
|
+
export function QuickCreateModal({ isOpen, title, onSave, onSaved, onCancel, children, fullPageHref, saveLabel = "Save", cancelLabel = "Cancel", isSaving = false, saveDisabled = false, }) {
|
|
10
|
+
const [busy, setBusy] = React.useState(false);
|
|
11
|
+
const titleId = React.useId();
|
|
12
|
+
const panelRef = React.useRef(null);
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
if (!isOpen)
|
|
15
|
+
return;
|
|
16
|
+
const prev = document.body.style.overflow;
|
|
17
|
+
document.body.style.overflow = "hidden";
|
|
18
|
+
return () => {
|
|
19
|
+
document.body.style.overflow = prev;
|
|
20
|
+
};
|
|
21
|
+
}, [isOpen]);
|
|
22
|
+
React.useEffect(() => {
|
|
23
|
+
if (!isOpen)
|
|
24
|
+
return;
|
|
25
|
+
const handler = (e) => {
|
|
26
|
+
if (e.key === "Escape" && !busy)
|
|
27
|
+
onCancel();
|
|
28
|
+
};
|
|
29
|
+
document.addEventListener("keydown", handler);
|
|
30
|
+
return () => document.removeEventListener("keydown", handler);
|
|
31
|
+
}, [isOpen, onCancel, busy]);
|
|
32
|
+
const handleSave = async () => {
|
|
33
|
+
if (saveDisabled || busy)
|
|
34
|
+
return;
|
|
35
|
+
setBusy(true);
|
|
36
|
+
try {
|
|
37
|
+
const doc = await onSave();
|
|
38
|
+
onSaved?.(doc);
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
setBusy(false);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
if (!isOpen || typeof document === "undefined")
|
|
45
|
+
return null;
|
|
46
|
+
const saving = busy || isSaving;
|
|
47
|
+
return createPortal(_jsxs(Div, { className: "appkit-quick-create-modal", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [_jsx(Div, { className: "appkit-quick-create-modal__backdrop", "aria-hidden": "true", onClick: () => !saving && onCancel() }), _jsxs(Div, { ref: panelRef, tabIndex: -1, className: "appkit-quick-create-modal__panel", children: [_jsxs(Div, { className: "appkit-quick-create-modal__header", children: [_jsx(Heading, { level: 2, id: titleId, className: "appkit-quick-create-modal__title", children: title }), _jsx(Button, { variant: "ghost", size: "sm", type: "button", onClick: onCancel, "aria-label": "Close", disabled: saving, children: "\u00D7" })] }), _jsx(Div, { className: "appkit-quick-create-modal__body", children: children }), _jsxs(Div, { className: "appkit-quick-create-modal__footer", children: [fullPageHref ? (_jsx("a", { href: fullPageHref, target: "_blank", rel: "noreferrer", className: "appkit-quick-create-modal__full-link", children: "Add more details \u2192" })) : (_jsx("span", {})), _jsxs(Row, { className: "appkit-quick-create-modal__actions", children: [_jsx(Button, { variant: "ghost", type: "button", onClick: onCancel, disabled: saving, children: cancelLabel }), _jsx(Button, { variant: "primary", type: "button", onClick: handleSave, disabled: saving || saveDisabled, isLoading: saving, children: saveLabel })] })] })] })] }), document.body);
|
|
48
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
.appkit-quick-create-modal {
|
|
2
|
+
position: fixed;
|
|
3
|
+
inset: 0;
|
|
4
|
+
z-index: var(--appkit-z-modal, 1000);
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: stretch;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.appkit-quick-create-modal__backdrop {
|
|
11
|
+
position: absolute;
|
|
12
|
+
inset: 0;
|
|
13
|
+
background: rgb(0 0 0 / 0.45);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.appkit-quick-create-modal__panel {
|
|
17
|
+
position: relative;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
background: var(--appkit-color-surface, #ffffff);
|
|
21
|
+
color: var(--appkit-color-foreground, inherit);
|
|
22
|
+
width: 100%;
|
|
23
|
+
max-width: 560px;
|
|
24
|
+
margin: auto;
|
|
25
|
+
max-height: 92vh;
|
|
26
|
+
border-radius: 0.75rem;
|
|
27
|
+
box-shadow: var(--appkit-shadow-lg, 0 20px 40px rgb(0 0 0 / 0.25));
|
|
28
|
+
outline: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.appkit-quick-create-modal__header {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: space-between;
|
|
35
|
+
padding: 1rem 1.25rem;
|
|
36
|
+
border-bottom: 1px solid var(--appkit-color-border, rgb(0 0 0 / 0.1));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.appkit-quick-create-modal__title {
|
|
40
|
+
margin: 0;
|
|
41
|
+
font-size: 1.125rem;
|
|
42
|
+
font-weight: 600;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.appkit-quick-create-modal__body {
|
|
46
|
+
flex: 1 1 auto;
|
|
47
|
+
overflow-y: auto;
|
|
48
|
+
padding: 1.25rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.appkit-quick-create-modal__footer {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
gap: 0.75rem;
|
|
56
|
+
padding: 1rem 1.25rem;
|
|
57
|
+
border-top: 1px solid var(--appkit-color-border, rgb(0 0 0 / 0.1));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.appkit-quick-create-modal__full-link {
|
|
61
|
+
font-size: 0.875rem;
|
|
62
|
+
color: var(--appkit-color-primary, #6366f1);
|
|
63
|
+
text-decoration: underline;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.appkit-quick-create-modal__actions {
|
|
67
|
+
gap: 0.5rem;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media (max-width: 640px) {
|
|
71
|
+
.appkit-quick-create-modal {
|
|
72
|
+
align-items: flex-end;
|
|
73
|
+
}
|
|
74
|
+
.appkit-quick-create-modal__panel {
|
|
75
|
+
max-width: 100%;
|
|
76
|
+
margin: 0;
|
|
77
|
+
border-radius: 0.75rem 0.75rem 0 0;
|
|
78
|
+
max-height: 92vh;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[data-theme="dark"] .appkit-quick-create-modal__panel {
|
|
83
|
+
background: var(--appkit-color-surface-dark, #1e293b);
|
|
84
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StickyBottomBar — fixed-bottom action bar that sits above the mobile
|
|
3
|
+
* BottomNavLayout (when present) and below any modals.
|
|
4
|
+
*
|
|
5
|
+
* Reads `--bottom-nav-height` written by `BottomNavLayout` (4rem when the
|
|
6
|
+
* navbar is rendered below `lg`, 0px otherwise). Falls back to 0px when the
|
|
7
|
+
* variable is unset so the bar still pins to the viewport bottom on routes
|
|
8
|
+
* that don't render a bottom nav.
|
|
9
|
+
*
|
|
10
|
+
* z-index sits above the navbar (`z-40`) but below modal overlays.
|
|
11
|
+
*/
|
|
12
|
+
import React from "react";
|
|
13
|
+
export interface StickyBottomBarProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
/** Optional extra className appended to the bar wrapper. */
|
|
16
|
+
className?: string;
|
|
17
|
+
/** Hide on `lg` and up. Defaults to `true` — matches BottomNavLayout's responsive scope. */
|
|
18
|
+
mobileOnly?: boolean;
|
|
19
|
+
/** Test id passthrough. */
|
|
20
|
+
"data-testid"?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function StickyBottomBar({ children, className, mobileOnly, "data-testid": testId, }: StickyBottomBarProps): React.JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
const BAR_STYLE = {
|
|
4
|
+
bottom: "var(--bottom-nav-height, 0px)",
|
|
5
|
+
zIndex: 45,
|
|
6
|
+
};
|
|
7
|
+
export function StickyBottomBar({ children, className, mobileOnly = true, "data-testid": testId, }) {
|
|
8
|
+
return (_jsx("div", {
|
|
9
|
+
// eslint-disable-next-line lir/no-inline-static-style
|
|
10
|
+
style: BAR_STYLE, "data-testid": testId, className: [
|
|
11
|
+
"fixed left-0 right-0",
|
|
12
|
+
mobileOnly ? "lg:hidden" : "",
|
|
13
|
+
"bg-white/95 dark:bg-slate-950/95 backdrop-blur-md",
|
|
14
|
+
"border-t border-zinc-200 dark:border-slate-800",
|
|
15
|
+
"shadow-2xl pb-safe",
|
|
16
|
+
className ?? "",
|
|
17
|
+
]
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.join(" "), children: children }));
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface VacationBannerProps {
|
|
2
|
+
storeName?: string;
|
|
3
|
+
message?: string;
|
|
4
|
+
returnDate?: Date | string;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* S-STORE-6-A — Vacation-mode banner shown on product detail + checkout
|
|
9
|
+
* pages when the seller has paused new orders.
|
|
10
|
+
*/
|
|
11
|
+
export declare function VacationBanner({ storeName, message, returnDate, className, }: VacationBannerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Alert } from "./Alert";
|
|
4
|
+
/**
|
|
5
|
+
* S-STORE-6-A — Vacation-mode banner shown on product detail + checkout
|
|
6
|
+
* pages when the seller has paused new orders.
|
|
7
|
+
*/
|
|
8
|
+
export function VacationBanner({ storeName, message, returnDate, className, }) {
|
|
9
|
+
const formattedDate = returnDate &&
|
|
10
|
+
new Date(returnDate).toLocaleDateString(undefined, {
|
|
11
|
+
year: "numeric",
|
|
12
|
+
month: "short",
|
|
13
|
+
day: "numeric",
|
|
14
|
+
});
|
|
15
|
+
return (_jsx(Alert, { variant: "warning", className: className, children: _jsxs("div", { className: "text-sm", children: [_jsx("strong", { 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
|
+
}
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -50,6 +50,10 @@ export type { StatusBadgeProps, StatusBadgeStatus, BadgeOrderStatus, BadgePaymen
|
|
|
50
50
|
export { StatusBadge } from "./components/StatusBadge";
|
|
51
51
|
export type { ModalProps } from "./components/Modal";
|
|
52
52
|
export { Modal, ModalFooter } from "./components/Modal";
|
|
53
|
+
export type { QuickCreateModalProps } from "./components/QuickCreateModal";
|
|
54
|
+
export { QuickCreateModal } from "./components/QuickCreateModal";
|
|
55
|
+
export type { VacationBannerProps } from "./components/VacationBanner";
|
|
56
|
+
export { VacationBanner } from "./components/VacationBanner";
|
|
53
57
|
export type { UnsavedChangesModalProps, UnsavedChangesLabels, } from "./components/UnsavedChangesModal";
|
|
54
58
|
export { UnsavedChangesModal } from "./components/UnsavedChangesModal";
|
|
55
59
|
export type { LoginRequiredModalProps } from "./components/LoginRequiredModal";
|
|
@@ -187,6 +191,10 @@ export type { BulkActionBarProps, BulkActionBarLabels, BulkActionItem, } from ".
|
|
|
187
191
|
export { BulkActionBar } from "./components/BulkActionBar";
|
|
188
192
|
export type { BulkActionsBarProps, BulkAction } from "./components/BulkActionsBar";
|
|
189
193
|
export { BulkActionsBar } from "./components/BulkActionsBar";
|
|
194
|
+
export type { StickyBottomBarProps } from "./components/StickyBottomBar";
|
|
195
|
+
export { StickyBottomBar } from "./components/StickyBottomBar";
|
|
196
|
+
export type { ClaimCouponButtonProps } from "./components/ClaimCouponButton";
|
|
197
|
+
export { ClaimCouponButton } from "./components/ClaimCouponButton";
|
|
190
198
|
export type { FlowStep, FlowDiagramProps } from "./components/FlowDiagram";
|
|
191
199
|
export { FlowDiagram } from "./components/FlowDiagram";
|
|
192
200
|
export type { BaseListingCardRootProps, BaseListingCardHeroProps, BaseListingCardInfoProps, BaseListingCardCheckboxProps, } from "./components/BaseListingCard";
|
package/dist/ui/index.js
CHANGED
|
@@ -29,6 +29,8 @@ export { Progress, IndeterminateProgress } from "./components/Progress";
|
|
|
29
29
|
export { Pagination } from "./components/Pagination";
|
|
30
30
|
export { StatusBadge } from "./components/StatusBadge";
|
|
31
31
|
export { Modal, ModalFooter } from "./components/Modal";
|
|
32
|
+
export { QuickCreateModal } from "./components/QuickCreateModal";
|
|
33
|
+
export { VacationBanner } from "./components/VacationBanner";
|
|
32
34
|
export { UnsavedChangesModal } from "./components/UnsavedChangesModal";
|
|
33
35
|
export { LoginRequiredModal } from "./components/LoginRequiredModal";
|
|
34
36
|
export { Drawer } from "./components/Drawer";
|
|
@@ -99,6 +101,8 @@ export { DetailViewShell } from "./components/DetailViewShell";
|
|
|
99
101
|
export { StackedViewShell } from "./components/StackedViewShell";
|
|
100
102
|
export { BulkActionBar } from "./components/BulkActionBar";
|
|
101
103
|
export { BulkActionsBar } from "./components/BulkActionsBar";
|
|
104
|
+
export { StickyBottomBar } from "./components/StickyBottomBar";
|
|
105
|
+
export { ClaimCouponButton } from "./components/ClaimCouponButton";
|
|
102
106
|
export { FlowDiagram } from "./components/FlowDiagram";
|
|
103
107
|
export { BaseListingCard } from "./components/BaseListingCard";
|
|
104
108
|
export { default as ImageGallery } from "./components/ImageGallery";
|