@tiendanube/live-state 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{LiveStateProvider-BEiLZeen.js → LiveStateProvider--BHGXDwQ.js} +10 -10
- package/dist/{LiveStateProvider-BEiLZeen.js.map → LiveStateProvider--BHGXDwQ.js.map} +1 -1
- package/dist/{LiveStateProvider-B_uOhVFY.cjs → LiveStateProvider-B0jRdNna.cjs} +2 -2
- package/dist/{LiveStateProvider-B_uOhVFY.cjs.map → LiveStateProvider-B0jRdNna.cjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +96 -82
- package/dist/index.js.map +1 -1
- package/dist/src/components/LiveStateMessage.d.ts +9 -0
- package/dist/src/components/LiveStateMessage.d.ts.map +1 -0
- package/dist/src/components/{LiveStateInfo.d.ts → LiveStatePromo.d.ts} +6 -6
- package/dist/src/components/LiveStatePromo.d.ts.map +1 -0
- package/dist/src/components/LiveStateRenderer.d.ts +2 -10
- package/dist/src/components/LiveStateRenderer.d.ts.map +1 -1
- package/dist/src/components/RichText.d.ts.map +1 -1
- package/dist/src/hooks/useLiveState.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/providers/LiveStateProvider.d.ts +1 -1
- package/dist/src/providers/LiveStateProvider.d.ts.map +1 -1
- package/dist/src/query-client.d.ts +9 -8
- package/dist/src/query-client.d.ts.map +1 -1
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +6 -24
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/query.d.ts +19 -15
- package/dist/src/utils/query.d.ts.map +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +2 -1
- package/dist/testing.js.map +1 -1
- package/package.json +7 -5
- package/dist/src/components/LiveStateAlert.d.ts +0 -24
- package/dist/src/components/LiveStateAlert.d.ts.map +0 -1
- package/dist/src/components/LiveStateInfo.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
2
1
|
import { LiveStateFetcher } from '../types';
|
|
3
2
|
/**
|
|
4
|
-
* React Query key used by `useLiveState`.
|
|
3
|
+
* Internal React Query key used by `useLiveState`.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* // Invalidate after user pays an overdue instalment
|
|
12
|
-
* queryClient.invalidateQueries({ queryKey: LIVE_STATE_QUERY_KEY });
|
|
5
|
+
* Not exported from the public API on purpose — consumers interact with the
|
|
6
|
+
* cache through the `prefetchLiveState` and `invalidateLiveState` helpers
|
|
7
|
+
* instead, so that React Query remains an internal implementation detail.
|
|
13
8
|
*/
|
|
14
9
|
export declare const LIVE_STATE_QUERY_KEY: readonly ["live-state"];
|
|
15
10
|
/**
|
|
@@ -23,16 +18,25 @@ export declare const LIVE_STATE_QUERY_KEY: readonly ["live-state"];
|
|
|
23
18
|
* a no-op — no extra request is made.
|
|
24
19
|
*
|
|
25
20
|
* @param fetcher - The same fetcher function passed to `LiveStateProvider`.
|
|
26
|
-
* @param queryClient - Optional. Defaults to the lib's `defaultQueryClient`.
|
|
27
|
-
* Pass the same `QueryClient` that was given to `LiveStateProvider` if you
|
|
28
|
-
* are using a custom one.
|
|
29
21
|
*
|
|
30
22
|
* @example
|
|
31
23
|
* // In a route loader (before the page renders)
|
|
32
24
|
* await prefetchLiveState(LENDING_FETCHER);
|
|
25
|
+
*/
|
|
26
|
+
export declare function prefetchLiveState(fetcher: LiveStateFetcher): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Invalidates the live-state cache, triggering an immediate re-fetch on every
|
|
29
|
+
* mounted `useLiveState` consumer.
|
|
30
|
+
*
|
|
31
|
+
* Call this after a user action that changes the backend state so the
|
|
32
|
+
* notification reflects the new state without waiting for the next polling
|
|
33
|
+
* tick or page reload.
|
|
33
34
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
35
|
+
* @example
|
|
36
|
+
* // After the user pays an overdue instalment
|
|
37
|
+
* await payInstalment();
|
|
38
|
+
* await invalidateLiveState();
|
|
39
|
+
* // → the banner disappears immediately, no need to wait for staleTime to expire
|
|
36
40
|
*/
|
|
37
|
-
export declare function
|
|
41
|
+
export declare function invalidateLiveState(): Promise<void>;
|
|
38
42
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/utils/query.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/utils/query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,yBAA0B,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD"}
|
package/dist/testing.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./LiveStateProvider-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./LiveStateProvider-B0jRdNna.cjs`);let t=require(`react`);t=e.E(t,1);let n=require(`react/jsx-runtime`);function r(e={}){return{context:`awareness`,model:`promo`,type:`info`,title:`Mock notification`,message:`This is a mock notification for testing.`,cta:{label:`Learn more`,url:`/mock`,type:`internal`},...e}}var i=t.default.createContext(null);function a({children:r,liveState:a=null,isLoading:o=!1,isError:s=!1,onEvent:c}){let l=t.default.useCallback(async()=>{if(o)return new Promise(()=>{});if(s)throw Error(`Mock fetch error`);return a},[a,o,s]),u=t.default.useMemo(()=>e.o(void 0),[]),d=t.default.useMemo(()=>new e.u({defaultOptions:{queries:{retry:!1,staleTime:0}}}),[]),f=t.default.useMemo(()=>({fetcher:l,onEvent:c,disabled:!0,log:u}),[l,c,u]);return(0,n.jsx)(e.c,{client:d,children:(0,n.jsx)(i.Provider,{value:f,children:r})})}function o(e={}){return{liveState:e.liveState??null,isLoading:e.isLoading??!1,isError:e.isError??!1,error:e.error??null,refresh:e.refresh??(()=>Promise.resolve())}}exports.MockLiveStateProvider=a,exports.createMockLiveState=r,exports.mockUseLiveState=o,exports.useLiveStateContext=e.n;
|
|
2
2
|
//# sourceMappingURL=testing.cjs.map
|
package/dist/testing.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.cjs","names":[],"sources":["../src/testing/index.tsx"],"sourcesContent":["/**\n * @tiendanube/live-state/testing\n *\n * Test utilities for consumers of this library.\n * Import from this sub-path in test files only — do NOT import in production code.\n *\n * @example\n * import { MockLiveStateProvider, createMockLiveState } from '@tiendanube/live-state/testing';\n */\n\nimport React from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport type { LiveStateResponse, TrackingProperties, LogLevel } from '../types';\nimport { createLogger } from '../utils/logger';\n\n// Re-export context internals so consumers can build custom wrappers\nexport { useLiveStateContext } from '../providers/LiveStateProvider';\n\n// ---------------------------------------------------------------------------\n// Mock data factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a minimal valid LiveStateResponse for testing.\n * Override any field by passing a partial object.\n *\n * @example\n * const data = createMockLiveState({ type: 'warning', context: 'cart' });\n */\nexport function createMockLiveState(\n overrides: Partial<LiveStateResponse> = {},\n): LiveStateResponse {\n return {\n context: 'awareness',\n type: 'info',\n title: 'Mock notification',\n message: 'This is a mock notification for testing.',\n cta: {\n label: 'Learn more',\n url: '/mock',\n type: 'internal',\n },\n ...overrides,\n };\n}\n\n// ---------------------------------------------------------------------------\n// MockLiveStateProvider\n// ---------------------------------------------------------------------------\n\ninterface MockLiveStateProviderProps {\n children: React.ReactNode;\n /** Mock live state data. Pass null to simulate \"no notification\". */\n liveState?: LiveStateResponse | null;\n /** Simulates loading state */\n isLoading?: boolean;\n /** Simulates error state */\n isError?: boolean;\n /** Spy on tracking events fired by the components */\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n}\n\ntype LoggerFn = (\n level: LogLevel,\n message: string,\n context?: Record<string, unknown>,\n) => void;\n\ninterface MockContextValue {\n fetcher: () => Promise<LiveStateResponse | null>;\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n disabled: boolean;\n log: LoggerFn;\n}\n\n// Minimal context shape matching LiveStateContextValue\nconst MockContext = React.createContext<MockContextValue | null>(null);\n\n/**\n * Drop-in replacement for `LiveStateProvider` in tests.\n * Controls `liveState`, `isLoading` and `isError` directly — no real fetcher needed.\n *\n * @example\n * render(\n * <MockLiveStateProvider liveState={createMockLiveState({ type: 'alert' })}>\n * <MyComponent />\n * </MockLiveStateProvider>\n * );\n */\nexport function MockLiveStateProvider({\n children,\n liveState = null,\n isLoading = false,\n isError = false,\n onEvent,\n}: MockLiveStateProviderProps) {\n const fetcher = React.useCallback(async () => {\n if (isLoading) return new Promise<LiveStateResponse | null>(() => {});\n if (isError) throw new Error('Mock fetch error');\n return liveState;\n }, [liveState, isLoading, isError]);\n\n const log = React.useMemo(() => createLogger(undefined), []);\n\n // Fresh QueryClient per mount — prevents test pollution between test cases.\n const queryClient = React.useMemo(\n ()
|
|
1
|
+
{"version":3,"file":"testing.cjs","names":[],"sources":["../src/testing/index.tsx"],"sourcesContent":["/**\n * @tiendanube/live-state/testing\n *\n * Test utilities for consumers of this library.\n * Import from this sub-path in test files only — do NOT import in production code.\n *\n * @example\n * import { MockLiveStateProvider, createMockLiveState } from '@tiendanube/live-state/testing';\n */\n\nimport React from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport type { LiveStateResponse, TrackingProperties, LogLevel } from '../types';\nimport { createLogger } from '../utils/logger';\n\n// Re-export context internals so consumers can build custom wrappers\nexport { useLiveStateContext } from '../providers/LiveStateProvider';\n\n// ---------------------------------------------------------------------------\n// Mock data factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a minimal valid LiveStateResponse for testing.\n * Override any field by passing a partial object.\n *\n * @example\n * const data = createMockLiveState({ type: 'warning', context: 'cart' });\n */\nexport function createMockLiveState(\n overrides: Partial<LiveStateResponse> = {},\n): LiveStateResponse {\n return {\n context: 'awareness',\n model: 'promo',\n type: 'info',\n title: 'Mock notification',\n message: 'This is a mock notification for testing.',\n cta: {\n label: 'Learn more',\n url: '/mock',\n type: 'internal',\n },\n ...overrides,\n };\n}\n\n// ---------------------------------------------------------------------------\n// MockLiveStateProvider\n// ---------------------------------------------------------------------------\n\ninterface MockLiveStateProviderProps {\n children: React.ReactNode;\n /** Mock live state data. Pass null to simulate \"no notification\". */\n liveState?: LiveStateResponse | null;\n /** Simulates loading state */\n isLoading?: boolean;\n /** Simulates error state */\n isError?: boolean;\n /** Spy on tracking events fired by the components */\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n}\n\ntype LoggerFn = (\n level: LogLevel,\n message: string,\n context?: Record<string, unknown>,\n) => void;\n\ninterface MockContextValue {\n fetcher: () => Promise<LiveStateResponse | null>;\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n disabled: boolean;\n log: LoggerFn;\n}\n\n// Minimal context shape matching LiveStateContextValue\nconst MockContext = React.createContext<MockContextValue | null>(null);\n\n/**\n * Drop-in replacement for `LiveStateProvider` in tests.\n * Controls `liveState`, `isLoading` and `isError` directly — no real fetcher needed.\n *\n * @example\n * render(\n * <MockLiveStateProvider liveState={createMockLiveState({ type: 'alert' })}>\n * <MyComponent />\n * </MockLiveStateProvider>\n * );\n */\nexport function MockLiveStateProvider({\n children,\n liveState = null,\n isLoading = false,\n isError = false,\n onEvent,\n}: MockLiveStateProviderProps) {\n const fetcher = React.useCallback(async () => {\n if (isLoading) return new Promise<LiveStateResponse | null>(() => {});\n if (isError) throw new Error('Mock fetch error');\n return liveState;\n }, [liveState, isLoading, isError]);\n\n const log = React.useMemo(() => createLogger(undefined), []);\n\n // Fresh QueryClient per mount — prevents test pollution between test cases.\n const queryClient = React.useMemo(\n () =>\n new QueryClient({\n defaultOptions: { queries: { retry: false, staleTime: 0 } },\n }),\n [],\n );\n\n const contextValue: MockContextValue = React.useMemo(\n () => ({ fetcher, onEvent, disabled: true, log }),\n [fetcher, onEvent, log],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <MockContext.Provider value={contextValue}>\n {children}\n </MockContext.Provider>\n </QueryClientProvider>\n );\n}\n\n// Override the real context hook so components inside MockLiveStateProvider\n// receive the mock context instead of the real one.\n// This works because useLiveStateContext calls useContext(LiveStateContext) from\n// the real provider — we need to patch the module in tests.\n// Consumers should use vi.mock / jest.mock to swap the provider if needed,\n// or use MockLiveStateProvider which wraps the real context wholesale.\n\n/**\n * Returns a pre-configured mock for the `useLiveState` hook.\n * Use with `vi.mock` / `jest.mock` to replace the real hook in unit tests.\n *\n * @example\n * vi.mock('@tiendanube/live-state', async (importOriginal) => ({\n * ...(await importOriginal()),\n * useLiveState: () => mockUseLiveState({ liveState: createMockLiveState() }),\n * }));\n */\nexport function mockUseLiveState(\n overrides: {\n liveState?: LiveStateResponse | null;\n isLoading?: boolean;\n isError?: boolean;\n error?: Error | null;\n refresh?: () => Promise<void>;\n } = {},\n) {\n return {\n liveState: overrides.liveState ?? null,\n isLoading: overrides.isLoading ?? false,\n isError: overrides.isError ?? false,\n error: overrides.error ?? null,\n refresh: overrides.refresh ?? (() => Promise.resolve()),\n };\n}\n"],"mappings":"4LA6BA,SAAgB,EACd,EAAwC,EAAE,CACvB,CACnB,MAAO,CACL,QAAS,YACT,MAAO,QACP,KAAM,OACN,MAAO,oBACP,QAAS,2CACT,IAAK,CACH,MAAO,aACP,IAAK,QACL,KAAM,WACP,CACD,GAAG,EACJ,CAiCH,IAAM,EAAc,EAAA,QAAM,cAAuC,KAAK,CAatE,SAAgB,EAAsB,CACpC,WACA,YAAY,KACZ,YAAY,GACZ,UAAU,GACV,WAC6B,CAC7B,IAAM,EAAU,EAAA,QAAM,YAAY,SAAY,CAC5C,GAAI,EAAW,OAAO,IAAI,YAAwC,GAAG,CACrE,GAAI,EAAS,MAAU,MAAM,mBAAmB,CAChD,OAAO,GACN,CAAC,EAAW,EAAW,EAAQ,CAAC,CAE7B,EAAM,EAAA,QAAM,YAAc,EAAA,EAAa,IAAA,GAAU,CAAE,EAAE,CAAC,CAGtD,EAAc,EAAA,QAAM,YAEtB,IAAI,EAAA,EAAY,CACd,eAAgB,CAAE,QAAS,CAAE,MAAO,GAAO,UAAW,EAAG,CAAE,CAC5D,CAAC,CACJ,EAAE,CACH,CAEK,EAAiC,EAAA,QAAM,aACpC,CAAE,UAAS,UAAS,SAAU,GAAM,MAAK,EAChD,CAAC,EAAS,EAAS,EAAI,CACxB,CAED,OACE,EAAA,EAAA,KAAC,EAAA,EAAD,CAAqB,OAAQ,YAC3B,EAAA,EAAA,KAAC,EAAY,SAAb,CAAsB,MAAO,EAC1B,WACoB,CAAA,CACH,CAAA,CAqB1B,SAAgB,EACd,EAMI,EAAE,CACN,CACA,MAAO,CACL,UAAW,EAAU,WAAa,KAClC,UAAW,EAAU,WAAa,GAClC,QAAS,EAAU,SAAW,GAC9B,MAAO,EAAU,OAAS,KAC1B,QAAS,EAAU,cAAkB,QAAQ,SAAS,EACvD"}
|
package/dist/testing.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { c as e, n as t, o as n, u as r } from "./LiveStateProvider
|
|
1
|
+
import { c as e, n as t, o as n, u as r } from "./LiveStateProvider--BHGXDwQ.js";
|
|
2
2
|
import i from "react";
|
|
3
3
|
import { jsx as a } from "react/jsx-runtime";
|
|
4
4
|
//#region src/testing/index.tsx
|
|
5
5
|
function o(e = {}) {
|
|
6
6
|
return {
|
|
7
7
|
context: "awareness",
|
|
8
|
+
model: "promo",
|
|
8
9
|
type: "info",
|
|
9
10
|
title: "Mock notification",
|
|
10
11
|
message: "This is a mock notification for testing.",
|
package/dist/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","names":[],"sources":["../src/testing/index.tsx"],"sourcesContent":["/**\n * @tiendanube/live-state/testing\n *\n * Test utilities for consumers of this library.\n * Import from this sub-path in test files only — do NOT import in production code.\n *\n * @example\n * import { MockLiveStateProvider, createMockLiveState } from '@tiendanube/live-state/testing';\n */\n\nimport React from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport type { LiveStateResponse, TrackingProperties, LogLevel } from '../types';\nimport { createLogger } from '../utils/logger';\n\n// Re-export context internals so consumers can build custom wrappers\nexport { useLiveStateContext } from '../providers/LiveStateProvider';\n\n// ---------------------------------------------------------------------------\n// Mock data factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a minimal valid LiveStateResponse for testing.\n * Override any field by passing a partial object.\n *\n * @example\n * const data = createMockLiveState({ type: 'warning', context: 'cart' });\n */\nexport function createMockLiveState(\n overrides: Partial<LiveStateResponse> = {},\n): LiveStateResponse {\n return {\n context: 'awareness',\n type: 'info',\n title: 'Mock notification',\n message: 'This is a mock notification for testing.',\n cta: {\n label: 'Learn more',\n url: '/mock',\n type: 'internal',\n },\n ...overrides,\n };\n}\n\n// ---------------------------------------------------------------------------\n// MockLiveStateProvider\n// ---------------------------------------------------------------------------\n\ninterface MockLiveStateProviderProps {\n children: React.ReactNode;\n /** Mock live state data. Pass null to simulate \"no notification\". */\n liveState?: LiveStateResponse | null;\n /** Simulates loading state */\n isLoading?: boolean;\n /** Simulates error state */\n isError?: boolean;\n /** Spy on tracking events fired by the components */\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n}\n\ntype LoggerFn = (\n level: LogLevel,\n message: string,\n context?: Record<string, unknown>,\n) => void;\n\ninterface MockContextValue {\n fetcher: () => Promise<LiveStateResponse | null>;\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n disabled: boolean;\n log: LoggerFn;\n}\n\n// Minimal context shape matching LiveStateContextValue\nconst MockContext = React.createContext<MockContextValue | null>(null);\n\n/**\n * Drop-in replacement for `LiveStateProvider` in tests.\n * Controls `liveState`, `isLoading` and `isError` directly — no real fetcher needed.\n *\n * @example\n * render(\n * <MockLiveStateProvider liveState={createMockLiveState({ type: 'alert' })}>\n * <MyComponent />\n * </MockLiveStateProvider>\n * );\n */\nexport function MockLiveStateProvider({\n children,\n liveState = null,\n isLoading = false,\n isError = false,\n onEvent,\n}: MockLiveStateProviderProps) {\n const fetcher = React.useCallback(async () => {\n if (isLoading) return new Promise<LiveStateResponse | null>(() => {});\n if (isError) throw new Error('Mock fetch error');\n return liveState;\n }, [liveState, isLoading, isError]);\n\n const log = React.useMemo(() => createLogger(undefined), []);\n\n // Fresh QueryClient per mount — prevents test pollution between test cases.\n const queryClient = React.useMemo(\n ()
|
|
1
|
+
{"version":3,"file":"testing.js","names":[],"sources":["../src/testing/index.tsx"],"sourcesContent":["/**\n * @tiendanube/live-state/testing\n *\n * Test utilities for consumers of this library.\n * Import from this sub-path in test files only — do NOT import in production code.\n *\n * @example\n * import { MockLiveStateProvider, createMockLiveState } from '@tiendanube/live-state/testing';\n */\n\nimport React from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport type { LiveStateResponse, TrackingProperties, LogLevel } from '../types';\nimport { createLogger } from '../utils/logger';\n\n// Re-export context internals so consumers can build custom wrappers\nexport { useLiveStateContext } from '../providers/LiveStateProvider';\n\n// ---------------------------------------------------------------------------\n// Mock data factories\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a minimal valid LiveStateResponse for testing.\n * Override any field by passing a partial object.\n *\n * @example\n * const data = createMockLiveState({ type: 'warning', context: 'cart' });\n */\nexport function createMockLiveState(\n overrides: Partial<LiveStateResponse> = {},\n): LiveStateResponse {\n return {\n context: 'awareness',\n model: 'promo',\n type: 'info',\n title: 'Mock notification',\n message: 'This is a mock notification for testing.',\n cta: {\n label: 'Learn more',\n url: '/mock',\n type: 'internal',\n },\n ...overrides,\n };\n}\n\n// ---------------------------------------------------------------------------\n// MockLiveStateProvider\n// ---------------------------------------------------------------------------\n\ninterface MockLiveStateProviderProps {\n children: React.ReactNode;\n /** Mock live state data. Pass null to simulate \"no notification\". */\n liveState?: LiveStateResponse | null;\n /** Simulates loading state */\n isLoading?: boolean;\n /** Simulates error state */\n isError?: boolean;\n /** Spy on tracking events fired by the components */\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n}\n\ntype LoggerFn = (\n level: LogLevel,\n message: string,\n context?: Record<string, unknown>,\n) => void;\n\ninterface MockContextValue {\n fetcher: () => Promise<LiveStateResponse | null>;\n onEvent?: (eventName: string, properties?: TrackingProperties) => void;\n disabled: boolean;\n log: LoggerFn;\n}\n\n// Minimal context shape matching LiveStateContextValue\nconst MockContext = React.createContext<MockContextValue | null>(null);\n\n/**\n * Drop-in replacement for `LiveStateProvider` in tests.\n * Controls `liveState`, `isLoading` and `isError` directly — no real fetcher needed.\n *\n * @example\n * render(\n * <MockLiveStateProvider liveState={createMockLiveState({ type: 'alert' })}>\n * <MyComponent />\n * </MockLiveStateProvider>\n * );\n */\nexport function MockLiveStateProvider({\n children,\n liveState = null,\n isLoading = false,\n isError = false,\n onEvent,\n}: MockLiveStateProviderProps) {\n const fetcher = React.useCallback(async () => {\n if (isLoading) return new Promise<LiveStateResponse | null>(() => {});\n if (isError) throw new Error('Mock fetch error');\n return liveState;\n }, [liveState, isLoading, isError]);\n\n const log = React.useMemo(() => createLogger(undefined), []);\n\n // Fresh QueryClient per mount — prevents test pollution between test cases.\n const queryClient = React.useMemo(\n () =>\n new QueryClient({\n defaultOptions: { queries: { retry: false, staleTime: 0 } },\n }),\n [],\n );\n\n const contextValue: MockContextValue = React.useMemo(\n () => ({ fetcher, onEvent, disabled: true, log }),\n [fetcher, onEvent, log],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <MockContext.Provider value={contextValue}>\n {children}\n </MockContext.Provider>\n </QueryClientProvider>\n );\n}\n\n// Override the real context hook so components inside MockLiveStateProvider\n// receive the mock context instead of the real one.\n// This works because useLiveStateContext calls useContext(LiveStateContext) from\n// the real provider — we need to patch the module in tests.\n// Consumers should use vi.mock / jest.mock to swap the provider if needed,\n// or use MockLiveStateProvider which wraps the real context wholesale.\n\n/**\n * Returns a pre-configured mock for the `useLiveState` hook.\n * Use with `vi.mock` / `jest.mock` to replace the real hook in unit tests.\n *\n * @example\n * vi.mock('@tiendanube/live-state', async (importOriginal) => ({\n * ...(await importOriginal()),\n * useLiveState: () => mockUseLiveState({ liveState: createMockLiveState() }),\n * }));\n */\nexport function mockUseLiveState(\n overrides: {\n liveState?: LiveStateResponse | null;\n isLoading?: boolean;\n isError?: boolean;\n error?: Error | null;\n refresh?: () => Promise<void>;\n } = {},\n) {\n return {\n liveState: overrides.liveState ?? null,\n isLoading: overrides.isLoading ?? false,\n isError: overrides.isError ?? false,\n error: overrides.error ?? null,\n refresh: overrides.refresh ?? (() => Promise.resolve()),\n };\n}\n"],"mappings":";;;;AA6BA,SAAgB,EACd,IAAwC,EAAE,EACvB;AACnB,QAAO;EACL,SAAS;EACT,OAAO;EACP,MAAM;EACN,OAAO;EACP,SAAS;EACT,KAAK;GACH,OAAO;GACP,KAAK;GACL,MAAM;GACP;EACD,GAAG;EACJ;;AAiCH,IAAM,IAAc,EAAM,cAAuC,KAAK;AAatE,SAAgB,EAAsB,EACpC,aACA,eAAY,MACZ,eAAY,IACZ,aAAU,IACV,cAC6B;CAC7B,IAAM,IAAU,EAAM,YAAY,YAAY;AAC5C,MAAI,EAAW,QAAO,IAAI,cAAwC,GAAG;AACrE,MAAI,EAAS,OAAU,MAAM,mBAAmB;AAChD,SAAO;IACN;EAAC;EAAW;EAAW;EAAQ,CAAC,EAE7B,IAAM,EAAM,cAAc,EAAa,KAAA,EAAU,EAAE,EAAE,CAAC,EAGtD,IAAc,EAAM,cAEtB,IAAI,EAAY,EACd,gBAAgB,EAAE,SAAS;EAAE,OAAO;EAAO,WAAW;EAAG,EAAE,EAC5D,CAAC,EACJ,EAAE,CACH,EAEK,IAAiC,EAAM,eACpC;EAAE;EAAS;EAAS,UAAU;EAAM;EAAK,GAChD;EAAC;EAAS;EAAS;EAAI,CACxB;AAED,QACE,kBAAC,GAAD;EAAqB,QAAQ;YAC3B,kBAAC,EAAY,UAAb;GAAsB,OAAO;GAC1B;GACoB,CAAA;EACH,CAAA;;AAqB1B,SAAgB,EACd,IAMI,EAAE,EACN;AACA,QAAO;EACL,WAAW,EAAU,aAAa;EAClC,WAAW,EAAU,aAAa;EAClC,SAAS,EAAU,WAAW;EAC9B,OAAO,EAAU,SAAS;EAC1B,SAAS,EAAU,kBAAkB,QAAQ,SAAS;EACvD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiendanube/live-state",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Generic React library for rendering live state notifications",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"typesVersions": {
|
|
21
21
|
"*": {
|
|
22
|
-
"testing": [
|
|
22
|
+
"testing": [
|
|
23
|
+
"./dist/testing.d.ts"
|
|
24
|
+
]
|
|
23
25
|
}
|
|
24
26
|
},
|
|
25
27
|
"files": [
|
|
@@ -45,13 +47,13 @@
|
|
|
45
47
|
"peerDependencies": {
|
|
46
48
|
"@nimbus-ds/components": "^5.41.0",
|
|
47
49
|
"@nimbus-ds/icons": "^1.14.0",
|
|
48
|
-
"@tanstack/react-query": "^4.0.0 || ^5.0.0",
|
|
49
50
|
"react": "^18.0.0 || ^19.0.0",
|
|
50
51
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
51
52
|
},
|
|
52
53
|
"dependencies": {
|
|
53
54
|
"@amplitude/analytics-browser": "^2.11.1",
|
|
54
|
-
"@microsoft/clarity": "^1.0.0"
|
|
55
|
+
"@microsoft/clarity": "^1.0.0",
|
|
56
|
+
"@tanstack/react-query": "^5.0.0"
|
|
55
57
|
},
|
|
56
58
|
"devDependencies": {
|
|
57
59
|
"@eslint/js": "^10.0.1",
|
|
@@ -119,4 +121,4 @@
|
|
|
119
121
|
"eslint-plugin-react-hooks/eslint": "^10.0.0",
|
|
120
122
|
"postcss": ">=8.5.10"
|
|
121
123
|
}
|
|
122
|
-
}
|
|
124
|
+
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { LiveStateResponse, TrackingConfig } from '../types';
|
|
2
|
-
export interface LiveStateAlertProps {
|
|
3
|
-
data: LiveStateResponse;
|
|
4
|
-
trackingConfig: TrackingConfig;
|
|
5
|
-
/** When provided, shows a close button and calls this on dismiss */
|
|
6
|
-
onClose?: () => void;
|
|
7
|
-
/**
|
|
8
|
-
* Override CTA click behaviour.
|
|
9
|
-
* When provided, replaces default navigation so the caller controls what
|
|
10
|
-
* happens on click (e.g. prevent navigation in a simulator, use a router).
|
|
11
|
-
*/
|
|
12
|
-
onCtaClick?: (cta: import('../types').CtaConfig) => void;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* LiveStateAlert
|
|
16
|
-
*
|
|
17
|
-
* Renders an Alert component (Nimbus) for alert/warning types.
|
|
18
|
-
* Automatically tracks view, click, and close events.
|
|
19
|
-
* Shows a close button when onClose is provided.
|
|
20
|
-
*
|
|
21
|
-
* See examples/ directory for usage examples.
|
|
22
|
-
*/
|
|
23
|
-
export declare function LiveStateAlert({ data, trackingConfig, onClose, onCtaClick, }: LiveStateAlertProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
-
//# sourceMappingURL=LiveStateAlert.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LiveStateAlert.d.ts","sourceRoot":"","sources":["../../../src/components/LiveStateAlert.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAOlE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,cAAc,EAAE,cAAc,CAAC;IAC/B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;CAC1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,OAAO,EACP,UAAU,GACX,EAAE,mBAAmB,2CA6ErB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LiveStateInfo.d.ts","sourceRoot":"","sources":["../../../src/components/LiveStateInfo.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAOlE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,CAAC;IACxB,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;CAC1D;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,cAAc,EACd,cAAuB,EACvB,OAAO,EACP,QAAQ,EAAE,YAAY,EACtB,UAAU,GACX,EAAE,kBAAkB,2CA0JpB"}
|