@mohasinac/appkit 3.6.2 → 3.6.4

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.
@@ -3,10 +3,20 @@
3
3
  *
4
4
  * appkit ships pre-compiled dist/tailwind-utilities.css covering every class
5
5
  * appkit components emit. The consumer's Tailwind config does NOT need to scan
6
- * node_modules/@mohasinac/appkit/** and does NOT need a safelist.
6
+ * node_modules/@mohasinac/appkit/**.
7
7
  *
8
8
  * Consumer must provide `content` globs for their own source files.
9
9
  *
10
+ * Loaded via a Tailwind v4 `@config "./tailwind.config.js";` directive in the
11
+ * consumer's CSS entry point — v4's config-compat bridge still honors
12
+ * `content`/`theme`/`plugins`/`darkMode` from a JS config exactly like v3 did.
13
+ *
14
+ * NOTE (Tailwind v4 migration, 2026-08-16): `safelist` is NOT supported by the
15
+ * v4 `@config` compat bridge. Any safelist classes must live in the consumer's
16
+ * CSS entry point via `@source inline("...")` instead — see src/app/globals.css.
17
+ * Do not add a `safelist` key back to this factory's override shape; it would
18
+ * silently no-op under v4.
19
+ *
10
20
  * @example
11
21
  * ```js
12
22
  * // tailwind.config.js
@@ -20,13 +30,11 @@ export interface TailwindConfigOverride {
20
30
  content?: string[];
21
31
  theme?: Record<string, unknown>;
22
32
  plugins?: unknown[];
23
- safelist?: unknown[];
24
33
  [key: string]: unknown;
25
34
  }
26
35
  export declare function defineTailwindConfig(override?: TailwindConfigOverride): {
27
36
  darkMode: "class";
28
37
  content: string[];
29
- safelist: unknown[];
30
38
  theme: {
31
39
  extend: {
32
40
  colors: {
@@ -3,10 +3,20 @@
3
3
  *
4
4
  * appkit ships pre-compiled dist/tailwind-utilities.css covering every class
5
5
  * appkit components emit. The consumer's Tailwind config does NOT need to scan
6
- * node_modules/@mohasinac/appkit/** and does NOT need a safelist.
6
+ * node_modules/@mohasinac/appkit/**.
7
7
  *
8
8
  * Consumer must provide `content` globs for their own source files.
9
9
  *
10
+ * Loaded via a Tailwind v4 `@config "./tailwind.config.js";` directive in the
11
+ * consumer's CSS entry point — v4's config-compat bridge still honors
12
+ * `content`/`theme`/`plugins`/`darkMode` from a JS config exactly like v3 did.
13
+ *
14
+ * NOTE (Tailwind v4 migration, 2026-08-16): `safelist` is NOT supported by the
15
+ * v4 `@config` compat bridge. Any safelist classes must live in the consumer's
16
+ * CSS entry point via `@source inline("...")` instead — see src/app/globals.css.
17
+ * Do not add a `safelist` key back to this factory's override shape; it would
18
+ * silently no-op under v4.
19
+ *
10
20
  * @example
11
21
  * ```js
12
22
  * // tailwind.config.js
@@ -17,11 +27,10 @@
17
27
  * ```
18
28
  */
19
29
  export function defineTailwindConfig(override = {}) {
20
- const { content: consumerContent = [], theme: consumerTheme = {}, plugins: consumerPlugins = [], safelist: consumerSafelist = [], ...rest } = override;
30
+ const { content: consumerContent = [], theme: consumerTheme = {}, plugins: consumerPlugins = [], ...rest } = override;
21
31
  return {
22
32
  darkMode: "class",
23
33
  content: [...consumerContent],
24
- safelist: [...consumerSafelist],
25
34
  theme: {
26
35
  extend: {
27
36
  colors: {
@@ -185,7 +185,7 @@ export function HeroCarousel({ initialSlides, push } = {}) {
185
185
  return (_jsxs(Section, { ref: sectionRef, className: `relative w-full ${heightClass} overflow-hidden`, "aria-roledescription": "carousel", "aria-label": "Hero carousel", onKeyDown: handleKeyDown, onMouseEnter: () => setIsPaused(true), onMouseLeave: () => setIsPaused(false), onFocus: () => setIsPaused(true), onBlur: () => setIsPaused(false), tabIndex: 0, children: [_jsx(Div, { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: `Slide ${currentSlide + 1} of ${slides.length}` }), _jsx(Div, { className: POSITION_FILL, children: _jsx(Div, { layout: "flex", ref: slidesRef, onScroll: handleSlidesScroll, className: "h-full overflow-x-auto scroll-smooth snap-x snap-mandatory [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", style: { gap: 0 }, children: slides.map((slide, slideIndex) => {
186
186
  const slideHeightClass = getSlideHeightClass(slide.settings?.height);
187
187
  const hasCards = slide.cards && slide.cards.length > 0;
188
- return (_jsxs(Div, { className: `snap-start flex-none w-full relative self-stretch bg-neutral-900 ${slideHeightClass}`, children: [_jsx(Div, { className: POSITION_FILL, children: _jsx(SlideBackground, { bg: slide.background, legacy: slide.media, mobileLegacy: slide.mobileMedia, isMobile: isMobile, priority: slideIndex === 0 }) }), slide.overlay && (_jsxs(Div, { layout: "flex-col", align: "start", justify: "center", className: `${POSITION_FILL} text-left md:px-[4rem] lg:px-[8rem]`, padding: "x-lg", children: [slide.overlay.subtitle && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-1 !/80 mb-1 md:mb-2 tracking-widest", mdSize: "sm", size: "xs", transform: "uppercase", children: slide.overlay.subtitle })), slide.overlay.title && (_jsx(Heading, { color: "inverse", level: 1, className: "stagger-2 font-display ! mb-2 md:mb-4", size: "4xl", shadow: "2xl", mdSize: "6xl", lgSize: "8xl", children: slide.overlay.title })), slide.overlay.description && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-3 !/90 mb-4 md:mb-8 max-w-2xl", mdSize: "lg", lgSize: "xl", size: "sm", children: slide.overlay.description })), slide.overlay.button && (_jsx(Div, { className: "stagger-4", children: _jsx(Button, { variant: slide.overlay.button.variant, size: "sm", onClick: makeButtonClickHandler(slide.overlay.button.link, slide.overlay.button.openInNewTab, push), children: slide.overlay.button.text }) }))] })), hasCards && (_jsx(Div, { className: `${POSITION_FILL} grid gap-[var(--appkit-space-2)] md:gap-[var(--appkit-space-4)] md:p-[var(--appkit-space-8)]`, padding: "md", style: {
188
+ return (_jsxs(Div, { className: `snap-start flex-none w-full relative self-stretch bg-neutral-900 ${slideHeightClass}`, children: [_jsx(Div, { className: POSITION_FILL, children: _jsx(SlideBackground, { bg: slide.background, legacy: slide.media, mobileLegacy: slide.mobileMedia, isMobile: isMobile, priority: slideIndex === 0 }) }), slide.overlay && (_jsxs(Div, { layout: "flex-col", align: "start", justify: "center", className: `${POSITION_FILL} text-left md:px-[4rem] lg:px-[8rem]`, padding: "x-lg", children: [slide.overlay.subtitle && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-1 !/80 mb-1 md:mb-2 tracking-widest", mdSize: "sm", size: "xs", transform: "uppercase", children: slide.overlay.subtitle })), slide.overlay.title && (_jsx(Heading, { color: "inverse", level: 1, className: "stagger-2 font-display ! mb-2 md:mb-4 break-words", size: "4xl", shadow: "2xl", mdSize: "6xl", lgSize: "8xl", children: slide.overlay.title })), slide.overlay.description && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-3 !/90 mb-4 md:mb-8 max-w-2xl", mdSize: "lg", lgSize: "xl", size: "sm", children: slide.overlay.description })), slide.overlay.button && (_jsx(Div, { className: "stagger-4", children: _jsx(Button, { variant: slide.overlay.button.variant, size: "sm", onClick: makeButtonClickHandler(slide.overlay.button.link, slide.overlay.button.openInNewTab, push), children: slide.overlay.button.text }) }))] })), hasCards && (_jsx(Div, { className: `${POSITION_FILL} grid gap-[var(--appkit-space-2)] md:gap-[var(--appkit-space-4)] md:p-[var(--appkit-space-8)]`, padding: "md", style: {
189
189
  gridTemplateRows: "repeat(2, 1fr)",
190
190
  gridTemplateColumns: isMobile ? "1fr" : "repeat(3, 1fr)",
191
191
  alignContent: "center",
@@ -9,5 +9,5 @@ export function WelcomeSection({ title, subtitle, pillLabel, showCTA = true, cta
9
9
  if (isLoading) {
10
10
  return (_jsx(Section, { className: `relative overflow-hidden md:py-[6rem] ${className}`, paddingY: "y-4xl", paddingX: "x-md", children: _jsxs(Div, { className: "animate-pulse max-w-4xl mx-auto text-left", children: [_jsx(Div, { className: "h-6 w-52 mb-6", surface: "subtle", rounded: "full" }), _jsx(Div, { className: "h-20 mb-4 max-w-2xl", surface: "subtle", rounded: "lg" }), _jsx(Div, { className: "h-6 mb-8 max-w-lg", surface: "subtle", rounded: "lg" }), _jsxs(Row, { justify: "start", gap: "md", children: [_jsx(Div, { className: "h-12 w-36", surface: "subtle", rounded: "xl" }), _jsx(Div, { className: "h-12 w-36", surface: "subtle", rounded: "xl" })] })] }) }));
11
11
  }
12
- return (_jsxs(Section, { className: `relative overflow-hidden md:py-[7rem] ${className}`, paddingY: "y-5xl", paddingX: "x-md", children: [_jsx(Div, { className: "pointer-events-none absolute -top-32 -left-32 w-[28rem] h-[28rem] bg-primary/10 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "pointer-events-none absolute -bottom-40 -right-40 w-[36rem] h-[36rem] bg-secondary/10 dark:bg-secondary/15 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "relative z-10 max-w-7xl mx-auto", children: _jsxs(Grid, { align: "center", gap: "2xl", className: "grid-cols-1 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2", children: [_jsxs(Div, { className: "text-left", children: [pillLabel && (_jsx(Div, { children: _jsxs(Span, { layout: "inline-flex", gap: "md", size: "xs", weight: "medium", className: "border border-primary-[500]/30 bg-primary-500/10 px-[1.25rem] py-[0.375rem] tracking-[0.2em] text-primary-700 dark:text-primary-400 backdrop-blur-sm", rounded: "full", transform: "uppercase", children: [_jsx(Span, { className: "w-1.5 h-1.5 bg-primary-500 inline-block", rounded: "full", "aria-hidden": "true" }), pillLabel, _jsx(Span, { className: "w-1.5 h-1.5 bg-primary-500 inline-block", rounded: "full", "aria-hidden": "true" })] }) })), _jsx(Heading, { level: 1, variant: "none", gradient: "brand-tri", className: "mt-4 font-display leading-[1.1] tracking-tight", size: "5xl", mdSize: "6xl", lgSize: "7xl", xlSize: "8xl", children: title }), subtitle && (_jsx(Text, { className: `mt-4 ${themed.textSecondary} max-w-xl leading-relaxed`, size: "xl", children: subtitle })), showCTA && (_jsxs(Row, { wrap: true, gap: "md", className: "mt-8", justify: "start", children: [ctaHref ? (_jsx(TextLink, { rounded: "xl", href: ctaHref, className: "inline-flex items-[center] justify-[center] px-[2rem] py-[0.875rem] !bg-primary hover:!bg-primary-600 text-white dark:!bg-primary dark:hover:!bg-primary-600 dark:text-white btn-glow transition-all hover:scale-[1.02]", size: "base", weight: "bold", children: ctaLabel })) : (_jsx(Button, { variant: "primary", size: "lg", onClick: onCtaClick, children: ctaLabel })), secondaryCtaHref ? (_jsx(TextLink, { rounded: "xl", href: secondaryCtaHref, className: "inline-flex items-[center] justify-[center] border-2 border-cobalt/40 dark:border-cobalt-400/40 px-[2rem] py-[0.875rem] text-cobalt-700 dark:text-cobalt-300 hover:bg-cobalt-50 dark:hover:bg-cobalt-900/20 transition-all hover:scale-[1.02]", size: "base", weight: "semibold", children: secondaryCtaLabel })) : (_jsx(Button, { variant: "outline", size: "lg", onClick: onSecondaryCtaClick, children: secondaryCtaLabel }))] })), trustChips.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-6", justify: "start", children: trustChips.map((chip) => (_jsxs(Span, { layout: "inline-flex", gap: "xs", size: "xs", weight: "medium", className: "border border-zinc-[200] dark:border-slate-[700] px-[0.875rem] py-[0.375rem]", rounded: "full", surface: "subtle", color: "muted", children: [chip.emoji, " ", chip.label] }, chip.key))) }))] }), _jsx(Div, { className: "hidden lg:block", children: _jsxs(Div, { className: `relative overflow-hidden aspect-[4/3] bg-[image:var(--appkit-gradient-section-mesh)]`, shadow: "2xl", border: "default", rounded: "3xl", children: [_jsx(Div, { className: "absolute inset-0 bg-[image:var(--appkit-gradient-glass)]" }), _jsx(Row, { centered: true, className: `absolute inset-0 ${flex.center} px-[2.5rem]`, children: _jsx(SiteLogo, { title: brandLogoText || "LetItRip.in", size: "hero" }) })] }) })] }) })] }));
12
+ return (_jsxs(Section, { className: `relative overflow-hidden md:py-[7rem] ${className}`, paddingY: "y-5xl", paddingX: "x-md", children: [_jsx(Div, { className: "pointer-events-none absolute -top-32 -left-32 w-[28rem] h-[28rem] bg-primary/10 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "pointer-events-none absolute -bottom-40 -right-40 w-[36rem] h-[36rem] bg-secondary/10 dark:bg-secondary/15 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "relative z-10 max-w-7xl mx-auto", children: _jsxs(Grid, { align: "center", gap: "2xl", className: "grid-cols-1 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2", children: [_jsxs(Div, { className: "text-left", children: [pillLabel && (_jsx(Div, { children: _jsxs(Span, { layout: "inline-flex", gap: "md", size: "xs", weight: "medium", className: "border border-primary-[500]/30 bg-primary-500/10 px-[1.25rem] py-[0.375rem] tracking-[0.2em] text-primary-700 dark:text-primary-400 backdrop-blur-sm", rounded: "full", transform: "uppercase", children: [_jsx(Span, { className: "w-1.5 h-1.5 bg-primary-500 inline-block", rounded: "full", "aria-hidden": "true" }), pillLabel, _jsx(Span, { className: "w-1.5 h-1.5 bg-primary-500 inline-block", rounded: "full", "aria-hidden": "true" })] }) })), _jsx(Heading, { level: 1, variant: "none", gradient: "brand-tri", className: "mt-4 font-display leading-[1.1] tracking-tight break-words", size: "5xl", mdSize: "6xl", lgSize: "7xl", xlSize: "7xl", children: title }), subtitle && (_jsx(Text, { className: `mt-4 ${themed.textSecondary} max-w-xl leading-relaxed`, size: "xl", children: subtitle })), showCTA && (_jsxs(Row, { wrap: true, gap: "md", className: "mt-8", justify: "start", children: [ctaHref ? (_jsx(TextLink, { rounded: "xl", href: ctaHref, className: "inline-flex items-[center] justify-[center] px-[2rem] py-[0.875rem] !bg-primary hover:!bg-primary-600 text-white dark:!bg-primary dark:hover:!bg-primary-600 dark:text-white btn-glow transition-all hover:scale-[1.02]", size: "base", weight: "bold", children: ctaLabel })) : (_jsx(Button, { variant: "primary", size: "lg", onClick: onCtaClick, children: ctaLabel })), secondaryCtaHref ? (_jsx(TextLink, { rounded: "xl", href: secondaryCtaHref, className: "inline-flex items-[center] justify-[center] border-2 border-cobalt/40 dark:border-cobalt-400/40 px-[2rem] py-[0.875rem] text-cobalt-700 dark:text-cobalt-300 hover:bg-cobalt-50 dark:hover:bg-cobalt-900/20 transition-all hover:scale-[1.02]", size: "base", weight: "semibold", children: secondaryCtaLabel })) : (_jsx(Button, { variant: "outline", size: "lg", onClick: onSecondaryCtaClick, children: secondaryCtaLabel }))] })), trustChips.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-6", justify: "start", children: trustChips.map((chip) => (_jsxs(Span, { layout: "inline-flex", gap: "xs", size: "xs", weight: "medium", className: "border border-zinc-[200] dark:border-slate-[700] px-[0.875rem] py-[0.375rem]", rounded: "full", surface: "subtle", color: "muted", children: [chip.emoji, " ", chip.label] }, chip.key))) }))] }), _jsx(Div, { className: "hidden lg:block", children: _jsxs(Div, { className: `relative overflow-hidden aspect-[4/3] bg-[image:var(--appkit-gradient-section-mesh)]`, shadow: "2xl", border: "default", rounded: "3xl", children: [_jsx(Div, { className: "absolute inset-0 bg-[image:var(--appkit-gradient-glass)]" }), _jsx(Row, { centered: true, className: `absolute inset-0 ${flex.center} px-[2.5rem]`, children: _jsx(SiteLogo, { title: brandLogoText || "LetItRip.in", size: "hero" }) })] }) })] }) })] }));
13
13
  }
@@ -0,0 +1,50 @@
1
+ import type { JsonValue } from "../../schemas/types";
2
+ /**
3
+ * Plain constants + types shared between client hooks (useRealtimeEvent) and
4
+ * server-side RTDB writers (e.g. src/app/api/auth/event/init/route.ts).
5
+ *
6
+ * Deliberately NOT in a "use client" file. useRealtimeEvent.ts is "use
7
+ * client" (it uses React hooks), and Next.js's server bundler replaces every
8
+ * export of a "use client" module with an opaque client-reference when a
9
+ * server module imports it directly — including plain, non-React constants
10
+ * like RTDBPayloadStatus. A server route importing RTDBPayloadStatus.PENDING
11
+ * from the old location got `undefined` at runtime, which Firebase RTDB's
12
+ * `.set()` rejects outright ("value argument contains undefined in property
13
+ * ...status"), silently breaking every RTDB-backed realtime event (Google
14
+ * OAuth popup flow, payment event bridge, chat) in production. Confirmed via
15
+ * live Vercel logs 2026-08-17.
16
+ */
17
+ export declare const RealtimeEventType: {
18
+ readonly AUTH: "auth";
19
+ readonly PAYMENT: "payment";
20
+ readonly CHAT: "chat";
21
+ readonly BID: "bid";
22
+ readonly BULK: "bulk";
23
+ };
24
+ export type RealtimeEventType = (typeof RealtimeEventType)[keyof typeof RealtimeEventType];
25
+ export declare const RealtimeEventStatus: {
26
+ readonly IDLE: "idle";
27
+ readonly SUBSCRIBING: "subscribing";
28
+ readonly PENDING: "pending";
29
+ readonly SUCCESS: "success";
30
+ readonly FAILED: "failed";
31
+ readonly TIMEOUT: "timeout";
32
+ };
33
+ export type RealtimeEventStatus = (typeof RealtimeEventStatus)[keyof typeof RealtimeEventStatus];
34
+ export declare const RTDBPayloadStatus: {
35
+ readonly PENDING: "pending";
36
+ readonly SUCCESS: "success";
37
+ readonly FAILED: "failed";
38
+ readonly ERROR: "error";
39
+ };
40
+ export interface RTDBEventPayload {
41
+ status: (typeof RTDBPayloadStatus)[keyof typeof RTDBPayloadStatus];
42
+ error?: string;
43
+ [key: string]: JsonValue | undefined;
44
+ }
45
+ export interface RealtimeEventMessages {
46
+ tokenFailure?: string;
47
+ connectionLost?: string;
48
+ timedOut?: string;
49
+ failure?: string;
50
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Plain constants + types shared between client hooks (useRealtimeEvent) and
3
+ * server-side RTDB writers (e.g. src/app/api/auth/event/init/route.ts).
4
+ *
5
+ * Deliberately NOT in a "use client" file. useRealtimeEvent.ts is "use
6
+ * client" (it uses React hooks), and Next.js's server bundler replaces every
7
+ * export of a "use client" module with an opaque client-reference when a
8
+ * server module imports it directly — including plain, non-React constants
9
+ * like RTDBPayloadStatus. A server route importing RTDBPayloadStatus.PENDING
10
+ * from the old location got `undefined` at runtime, which Firebase RTDB's
11
+ * `.set()` rejects outright ("value argument contains undefined in property
12
+ * ...status"), silently breaking every RTDB-backed realtime event (Google
13
+ * OAuth popup flow, payment event bridge, chat) in production. Confirmed via
14
+ * live Vercel logs 2026-08-17.
15
+ */
16
+ export const RealtimeEventType = {
17
+ AUTH: "auth",
18
+ PAYMENT: "payment",
19
+ CHAT: "chat",
20
+ BID: "bid",
21
+ BULK: "bulk",
22
+ };
23
+ export const RealtimeEventStatus = {
24
+ IDLE: "idle",
25
+ SUBSCRIBING: "subscribing",
26
+ PENDING: "pending",
27
+ SUCCESS: "success",
28
+ FAILED: "failed",
29
+ TIMEOUT: "timeout",
30
+ };
31
+ export const RTDBPayloadStatus = {
32
+ PENDING: "pending",
33
+ SUCCESS: "success",
34
+ FAILED: "failed",
35
+ ERROR: "error",
36
+ };
@@ -1,39 +1,6 @@
1
- import type { JsonValue } from "../../schemas/types";
2
1
  import { type IClientRealtimeProvider } from "../../contracts/client-realtime";
3
- export declare const RealtimeEventType: {
4
- readonly AUTH: "auth";
5
- readonly PAYMENT: "payment";
6
- readonly CHAT: "chat";
7
- readonly BID: "bid";
8
- readonly BULK: "bulk";
9
- };
10
- export type RealtimeEventType = (typeof RealtimeEventType)[keyof typeof RealtimeEventType];
11
- export declare const RealtimeEventStatus: {
12
- readonly IDLE: "idle";
13
- readonly SUBSCRIBING: "subscribing";
14
- readonly PENDING: "pending";
15
- readonly SUCCESS: "success";
16
- readonly FAILED: "failed";
17
- readonly TIMEOUT: "timeout";
18
- };
19
- export type RealtimeEventStatus = (typeof RealtimeEventStatus)[keyof typeof RealtimeEventStatus];
20
- export declare const RTDBPayloadStatus: {
21
- readonly PENDING: "pending";
22
- readonly SUCCESS: "success";
23
- readonly FAILED: "failed";
24
- readonly ERROR: "error";
25
- };
26
- export interface RTDBEventPayload {
27
- status: (typeof RTDBPayloadStatus)[keyof typeof RTDBPayloadStatus];
28
- error?: string;
29
- [key: string]: JsonValue | undefined;
30
- }
31
- export interface RealtimeEventMessages {
32
- tokenFailure?: string;
33
- connectionLost?: string;
34
- timedOut?: string;
35
- failure?: string;
36
- }
2
+ import { RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, type RTDBEventPayload, type RealtimeEventMessages } from "./realtime-event-constants";
3
+ export { RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, type RTDBEventPayload, type RealtimeEventMessages, };
37
4
  export interface UseRealtimeEventConfig<TData = undefined> {
38
5
  type: RealtimeEventType;
39
6
  rtdbPath: string;
@@ -2,27 +2,13 @@
2
2
  import { normalizeError } from "../../errors/normalize";
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { getClientRealtimeProvider, } from "../../contracts/client-realtime";
5
- export const RealtimeEventType = {
6
- AUTH: "auth",
7
- PAYMENT: "payment",
8
- CHAT: "chat",
9
- BID: "bid",
10
- BULK: "bulk",
11
- };
12
- export const RealtimeEventStatus = {
13
- IDLE: "idle",
14
- SUBSCRIBING: "subscribing",
15
- PENDING: "pending",
16
- SUCCESS: "success",
17
- FAILED: "failed",
18
- TIMEOUT: "timeout",
19
- };
20
- export const RTDBPayloadStatus = {
21
- PENDING: "pending",
22
- SUCCESS: "success",
23
- FAILED: "failed",
24
- ERROR: "error",
25
- };
5
+ import { RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, } from "./realtime-event-constants";
6
+ // Re-exported for existing client import paths — the canonical definitions
7
+ // now live in realtime-event-constants.ts (a plain, non-"use client" module)
8
+ // so server code can import them without hitting the client-reference
9
+ // substitution Next.js applies to "use client" module exports. See that
10
+ // file's comment for the full story.
11
+ export { RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, };
26
12
  const DEFAULT_TIMEOUT_MS = 3 * 60 * 1000;
27
13
  const DEFAULT_MESSAGES = {
28
14
  tokenFailure: "Failed to initialize realtime tracking.",
@@ -52,5 +52,7 @@ export { useModalStack } from "./useModalStack";
52
52
  export type { ModalEntry } from "./useModalStack";
53
53
  export { ErrorBoundary } from "./ErrorBoundary";
54
54
  export type { ErrorBoundaryProps } from "./ErrorBoundary";
55
- export { useRealtimeEvent, RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, } from "./hooks/useRealtimeEvent";
56
- export type { RTDBEventPayload, RealtimeEventMessages, RealtimeEventType as RealtimeEventTypeValue, RealtimeEventStatus as RealtimeEventStatusValue, UseRealtimeEventConfig, UseRealtimeEventReturn, } from "./hooks/useRealtimeEvent";
55
+ export { useRealtimeEvent } from "./hooks/useRealtimeEvent";
56
+ export type { UseRealtimeEventConfig, UseRealtimeEventReturn, } from "./hooks/useRealtimeEvent";
57
+ export { RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, } from "./hooks/realtime-event-constants";
58
+ export type { RTDBEventPayload, RealtimeEventMessages, RealtimeEventType as RealtimeEventTypeValue, RealtimeEventStatus as RealtimeEventStatusValue, } from "./hooks/realtime-event-constants";
@@ -53,4 +53,11 @@ export { useModalStack } from "./useModalStack";
53
53
  // Error boundary
54
54
  export { ErrorBoundary } from "./ErrorBoundary";
55
55
  // Realtime event bridge
56
- export { useRealtimeEvent, RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, } from "./hooks/useRealtimeEvent";
56
+ // RealtimeEventType/RealtimeEventStatus/RTDBPayloadStatus/RTDBEventPayload/
57
+ // RealtimeEventMessages come from realtime-event-constants.ts (plain module,
58
+ // no "use client") rather than useRealtimeEvent.ts directly — server code
59
+ // importing these via the main @mohasinac/appkit barrel needs the real
60
+ // values, not the client-reference placeholder Next.js substitutes for
61
+ // "use client" module exports.
62
+ export { useRealtimeEvent } from "./hooks/useRealtimeEvent";
63
+ export { RealtimeEventType, RealtimeEventStatus, RTDBPayloadStatus, } from "./hooks/realtime-event-constants";