@mohasinac/appkit 2.5.1 → 2.6.1
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/jobs.d.ts +24 -0
- package/dist/jobs.js +27 -0
- package/dist/next/api/routeHandler.js +6 -4
- package/dist/server-entry.d.ts +0 -2
- package/dist/server-entry.js +5 -2
- package/dist/ui/components/Button.js +21 -2
- package/dist/ui/components/Button.style.css +34 -0
- package/package.json +5 -1
package/dist/jobs.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mohasinac/appkit/jobs` — Firebase Functions binders + job handlers.
|
|
3
|
+
*
|
|
4
|
+
* Carved out of `server-entry.ts` 2026-05-12 because the import chain reaches
|
|
5
|
+
* `firebase-functions/v2/{https,scheduler,firestore}`, which is only
|
|
6
|
+
* available in the Firebase Functions runtime — not in Vercel Next.js
|
|
7
|
+
* lambdas. Re-exporting these from the main server surface forced every
|
|
8
|
+
* consumer (including the letitrip Next app) to install `firebase-functions`
|
|
9
|
+
* as a dep just to get past `next build`.
|
|
10
|
+
*
|
|
11
|
+
* Now: only the `appkit/functions/` package imports this subpath. The
|
|
12
|
+
* letitrip Next app never reaches `firebase-functions` because it's not in
|
|
13
|
+
* any of the chains rooted at `@mohasinac/appkit` or
|
|
14
|
+
* `@mohasinac/appkit/server`.
|
|
15
|
+
*
|
|
16
|
+
* Usage (functions/src/index.ts):
|
|
17
|
+
* import {
|
|
18
|
+
* bindToFirebase,
|
|
19
|
+
* couponExpiryHandler,
|
|
20
|
+
* listingProcessorHandler,
|
|
21
|
+
* } from "@mohasinac/appkit/jobs";
|
|
22
|
+
*/
|
|
23
|
+
export { couponExpiryHandler, offerExpiryHandler, cartPruneHandler, notificationPruneHandler, dailyDataCleanupHandler, cleanupRtdbEventsHandler, auctionSettlementHandler, autoPayoutEligibilityHandler, countersReconcileHandler, onOrderCreateHandler, onOrderStatusChangeHandler, onBidPlacedHandler, onReviewWriteHandler, promotionsHandler, mediaTmpCleanupHandler, pendingOrderTimeoutHandler, productStatsSyncHandler, positionsReconcileHandler, payoutBatchHandler, weeklyPayoutEligibilityHandler, onCategoryWriteHandler, onProductWriteHandler, onStoreWriteHandler, adminAnalyticsHandler, storeAnalyticsHandler, listingProcessorHandler, supportedListingCollections, bindSchedule, bindDocumentWritten, bindDocumentCreated, bindDocumentUpdated, bindCallable, bindHttps, bindToFirebase, } from "./_internal/server/jobs/index.js";
|
|
24
|
+
export type { PromotionsCallableResult, AdminAnalyticsResult, StoreAnalyticsInput, StoreAnalyticsResult, ListingRequestBody, ListingResponseBody, JobContext, JobLogger, JobHandlers, ScheduleHandler, FirestoreTriggerHandler, FirestoreTriggerEvent, CallableHandler, BindHttpsOptions, } from "./_internal/server/jobs/index.js";
|
package/dist/jobs.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mohasinac/appkit/jobs` — Firebase Functions binders + job handlers.
|
|
3
|
+
*
|
|
4
|
+
* Carved out of `server-entry.ts` 2026-05-12 because the import chain reaches
|
|
5
|
+
* `firebase-functions/v2/{https,scheduler,firestore}`, which is only
|
|
6
|
+
* available in the Firebase Functions runtime — not in Vercel Next.js
|
|
7
|
+
* lambdas. Re-exporting these from the main server surface forced every
|
|
8
|
+
* consumer (including the letitrip Next app) to install `firebase-functions`
|
|
9
|
+
* as a dep just to get past `next build`.
|
|
10
|
+
*
|
|
11
|
+
* Now: only the `appkit/functions/` package imports this subpath. The
|
|
12
|
+
* letitrip Next app never reaches `firebase-functions` because it's not in
|
|
13
|
+
* any of the chains rooted at `@mohasinac/appkit` or
|
|
14
|
+
* `@mohasinac/appkit/server`.
|
|
15
|
+
*
|
|
16
|
+
* Usage (functions/src/index.ts):
|
|
17
|
+
* import {
|
|
18
|
+
* bindToFirebase,
|
|
19
|
+
* couponExpiryHandler,
|
|
20
|
+
* listingProcessorHandler,
|
|
21
|
+
* } from "@mohasinac/appkit/jobs";
|
|
22
|
+
*/
|
|
23
|
+
export {
|
|
24
|
+
// S4–S5: Job handlers (pure, framework-agnostic)
|
|
25
|
+
couponExpiryHandler, offerExpiryHandler, cartPruneHandler, notificationPruneHandler, dailyDataCleanupHandler, cleanupRtdbEventsHandler, auctionSettlementHandler, autoPayoutEligibilityHandler, countersReconcileHandler, onOrderCreateHandler, onOrderStatusChangeHandler, onBidPlacedHandler, onReviewWriteHandler, promotionsHandler, mediaTmpCleanupHandler, pendingOrderTimeoutHandler, productStatsSyncHandler, positionsReconcileHandler, payoutBatchHandler, weeklyPayoutEligibilityHandler, onCategoryWriteHandler, onProductWriteHandler, onStoreWriteHandler, adminAnalyticsHandler, storeAnalyticsHandler, listingProcessorHandler, supportedListingCollections,
|
|
26
|
+
// Firebase binder adapter
|
|
27
|
+
bindSchedule, bindDocumentWritten, bindDocumentCreated, bindDocumentUpdated, bindCallable, bindHttps, bindToFirebase, } from "./_internal/server/jobs/index.js";
|
|
@@ -128,10 +128,12 @@ export function createRouteHandler(options) {
|
|
|
128
128
|
return response;
|
|
129
129
|
}
|
|
130
130
|
catch (err) {
|
|
131
|
-
|
|
132
|
-
const status = typeof
|
|
133
|
-
?
|
|
134
|
-
:
|
|
131
|
+
const e = err;
|
|
132
|
+
const status = typeof e?.statusCode === "number"
|
|
133
|
+
? e.statusCode
|
|
134
|
+
: typeof e?.status === "number"
|
|
135
|
+
? e.status
|
|
136
|
+
: 500;
|
|
135
137
|
const message = err instanceof Error ? err.message : "Internal server error";
|
|
136
138
|
// 401/403 are expected for protected routes and should not be error-noisy.
|
|
137
139
|
if (status >= 500) {
|
package/dist/server-entry.d.ts
CHANGED
|
@@ -36,8 +36,6 @@ export { createCheckoutOrderAction, attachPaymentAction, formatShippingAddress,
|
|
|
36
36
|
export { createPaymentIntentAction, verifyPaymentSignatureAction, resolvePaymentFee, PAYMENTS_DEFAULT_RAZORPAY_FEE_PERCENT, PAYMENTS_RECEIPT_PREFIX, type CreatePaymentIntentInput, type CreatePaymentIntentResult, type VerifyPaymentSignatureInput, type ResolvedPaymentFee, } from "./_internal/server/features/payments/index";
|
|
37
37
|
export { getSublistingCategoryForDetail } from "./_internal/server/features/sublisting-categories/index";
|
|
38
38
|
export { getStoreForDetail, listStoreProductsInitial, listStoreAuctionsInitial, listStorePreOrdersInitial, listSitemapStores, STORES_PAGE_SIZE, STORES_PRODUCTS_PAGE_SIZE, STORES_SITEMAP_LIMIT, STORES_FEATURED_LIMIT, } from "./_internal/server/features/stores/index";
|
|
39
|
-
export { couponExpiryHandler, offerExpiryHandler, cartPruneHandler, notificationPruneHandler, dailyDataCleanupHandler, cleanupRtdbEventsHandler, auctionSettlementHandler, autoPayoutEligibilityHandler, countersReconcileHandler, onOrderCreateHandler, onOrderStatusChangeHandler, onBidPlacedHandler, onReviewWriteHandler, promotionsHandler, type PromotionsCallableResult, mediaTmpCleanupHandler, pendingOrderTimeoutHandler, productStatsSyncHandler, positionsReconcileHandler, payoutBatchHandler, weeklyPayoutEligibilityHandler, onCategoryWriteHandler, onProductWriteHandler, onStoreWriteHandler, adminAnalyticsHandler, type AdminAnalyticsResult, storeAnalyticsHandler, type StoreAnalyticsInput, type StoreAnalyticsResult, listingProcessorHandler, supportedListingCollections, type ListingRequestBody, type ListingResponseBody, bindSchedule, bindDocumentWritten, bindDocumentCreated, bindDocumentUpdated, bindCallable, bindHttps, bindToFirebase, } from "./_internal/server/jobs/index";
|
|
40
|
-
export type { JobContext, JobLogger, JobHandlers, ScheduleHandler, FirestoreTriggerHandler, FirestoreTriggerEvent, CallableHandler, } from "./_internal/server/jobs/index";
|
|
41
39
|
export { AppShell, DashboardScaffold } from "./_internal/client/scaffolds/index";
|
|
42
40
|
export type { AppShellProps, AppShellRenderContext, DashboardScaffoldProps, DashboardScaffoldRenderContext, } from "./_internal/client/scaffolds/index";
|
|
43
41
|
export { toClient, clientInitial } from "./_internal/shared/serialization/index";
|
package/dist/server-entry.js
CHANGED
|
@@ -62,8 +62,11 @@ export { createPaymentIntentAction, verifyPaymentSignatureAction, resolvePayment
|
|
|
62
62
|
export { getSublistingCategoryForDetail } from "./_internal/server/features/sublisting-categories/index";
|
|
63
63
|
// S3: stores data layer
|
|
64
64
|
export { getStoreForDetail, listStoreProductsInitial, listStoreAuctionsInitial, listStorePreOrdersInitial, listSitemapStores, STORES_PAGE_SIZE, STORES_PRODUCTS_PAGE_SIZE, STORES_SITEMAP_LIMIT, STORES_FEATURED_LIMIT, } from "./_internal/server/features/stores/index";
|
|
65
|
-
// S4–S5: Job handlers +
|
|
66
|
-
|
|
65
|
+
// S4–S5: Job handlers + Firebase binders moved to the `@mohasinac/appkit/jobs`
|
|
66
|
+
// subpath (2.6.0, 2026-05-12). The chain reaches `firebase-functions/v2/*`
|
|
67
|
+
// which is only available in the Firebase Functions runtime, not in Vercel
|
|
68
|
+
// Next.js lambdas. Consumers that need them (i.e. `functions/src/index.ts`)
|
|
69
|
+
// import directly from `@mohasinac/appkit/jobs`.
|
|
67
70
|
// S6: client scaffolds (server-side type-aware import; runtime is "use client")
|
|
68
71
|
export { AppShell, DashboardScaffold } from "./_internal/client/scaffolds/index";
|
|
69
72
|
// CC-3: hydration helpers
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React from "react";
|
|
3
|
+
import React, { useCallback } from "react";
|
|
3
4
|
import { twMerge } from "tailwind-merge";
|
|
4
5
|
import { Loader2 } from "lucide-react";
|
|
6
|
+
function spawnRipple(host, clientX, clientY) {
|
|
7
|
+
const rect = host.getBoundingClientRect();
|
|
8
|
+
const size = Math.max(rect.width, rect.height);
|
|
9
|
+
const ripple = document.createElement("span");
|
|
10
|
+
ripple.className = "appkit-button__ripple";
|
|
11
|
+
ripple.style.width = ripple.style.height = `${size}px`;
|
|
12
|
+
ripple.style.left = `${clientX - rect.left - size / 2}px`;
|
|
13
|
+
ripple.style.top = `${clientY - rect.top - size / 2}px`;
|
|
14
|
+
host.appendChild(ripple);
|
|
15
|
+
ripple.addEventListener("animationend", () => ripple.remove(), { once: true });
|
|
16
|
+
}
|
|
5
17
|
/**
|
|
6
18
|
* Button — versatile button with multiple variants, sizes, and loading state.
|
|
7
19
|
*
|
|
@@ -27,6 +39,13 @@ const UI_BUTTON = {
|
|
|
27
39
|
};
|
|
28
40
|
export function Button({ variant = "primary", size = "md", className = "", isLoading = false, disabled, children, asChild = false, ...props }) {
|
|
29
41
|
const classes = twMerge(UI_BUTTON.base, UI_BUTTON.variants[variant], UI_BUTTON.sizes[size], className);
|
|
42
|
+
const userOnClick = props.onClick;
|
|
43
|
+
const handleClick = useCallback((event) => {
|
|
44
|
+
if (!disabled && !isLoading) {
|
|
45
|
+
spawnRipple(event.currentTarget, event.clientX, event.clientY);
|
|
46
|
+
}
|
|
47
|
+
userOnClick?.(event);
|
|
48
|
+
}, [disabled, isLoading, userOnClick]);
|
|
30
49
|
if (asChild && React.isValidElement(children)) {
|
|
31
50
|
const child = children;
|
|
32
51
|
return React.cloneElement(child, {
|
|
@@ -35,5 +54,5 @@ export function Button({ variant = "primary", size = "md", className = "", isLoa
|
|
|
35
54
|
...(disabled ? { "aria-disabled": true } : {}),
|
|
36
55
|
});
|
|
37
56
|
}
|
|
38
|
-
return (_jsxs("button", { className: classes, disabled: disabled || isLoading, "aria-busy": isLoading || undefined, ...props, children: [isLoading && (_jsx(Loader2, { className: "appkit-button__spinner", "aria-hidden": "true" })), isLoading ? (_jsx("span", { className: "appkit-button__content appkit-button__content--loading", children: children })) : (_jsx("span", { className: "appkit-button__content", children: children }))] }));
|
|
57
|
+
return (_jsxs("button", { className: classes, disabled: disabled || isLoading, "aria-busy": isLoading || undefined, ...props, onClick: handleClick, children: [isLoading && (_jsx(Loader2, { className: "appkit-button__spinner", "aria-hidden": "true" })), isLoading ? (_jsx("span", { className: "appkit-button__content appkit-button__content--loading", children: children })) : (_jsx("span", { className: "appkit-button__content", children: children }))] }));
|
|
39
58
|
}
|
|
@@ -11,6 +11,40 @@
|
|
|
11
11
|
transition: all 0.2s ease;
|
|
12
12
|
cursor: pointer;
|
|
13
13
|
user-select: none;
|
|
14
|
+
position: relative;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
isolation: isolate;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.appkit-button__ripple {
|
|
20
|
+
position: absolute;
|
|
21
|
+
border-radius: 9999px;
|
|
22
|
+
background: currentColor;
|
|
23
|
+
opacity: 0.28;
|
|
24
|
+
pointer-events: none;
|
|
25
|
+
transform: scale(0);
|
|
26
|
+
animation: appkit-button-ripple 520ms cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
|
27
|
+
z-index: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.appkit-button__content,
|
|
31
|
+
.appkit-button__spinner {
|
|
32
|
+
position: relative;
|
|
33
|
+
z-index: 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@keyframes appkit-button-ripple {
|
|
37
|
+
to {
|
|
38
|
+
transform: scale(2.4);
|
|
39
|
+
opacity: 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@media (prefers-reduced-motion: reduce) {
|
|
44
|
+
.appkit-button__ripple {
|
|
45
|
+
animation-duration: 1ms;
|
|
46
|
+
opacity: 0;
|
|
47
|
+
}
|
|
14
48
|
}
|
|
15
49
|
|
|
16
50
|
.appkit-button:focus-visible {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mohasinac/appkit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"types": "./dist/server.d.ts",
|
|
40
40
|
"import": "./dist/server.js"
|
|
41
41
|
},
|
|
42
|
+
"./jobs": {
|
|
43
|
+
"types": "./dist/jobs.d.ts",
|
|
44
|
+
"import": "./dist/jobs.js"
|
|
45
|
+
},
|
|
42
46
|
"./providers": {
|
|
43
47
|
"types": "./dist/providers.d.ts",
|
|
44
48
|
"import": "./dist/providers.js"
|