@tiendanube/live-state 1.1.0 → 1.3.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/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +99 -87
- 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/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +8 -3
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +1 -0
- package/dist/testing.js.map +1 -1
- package/package.json +5 -3
- 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
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#client","#selectError","#currentThenable","#currentQuery","#executeFetch","#updateTimers","#clearStaleTimeout","#clearRefetchInterval","#updateQuery","#updateStaleTimeout","#computeRefetchInterval","#currentRefetchInterval","#updateRefetchInterval","#currentResult","#currentResultOptions","#currentResultState","#trackedProps","#staleTimeoutId","#refetchIntervalId","#currentQueryInitialState","#lastQueryWithDefinedData","#selectFn","#selectResult","#notify","React","React","React"],"sources":["../node_modules/@tanstack/query-core/build/modern/queryObserver.js","../node_modules/@tanstack/react-query/build/modern/IsRestoringProvider.js","../node_modules/@tanstack/react-query/build/modern/QueryErrorResetBoundary.js","../node_modules/@tanstack/react-query/build/modern/errorBoundaryUtils.js","../node_modules/@tanstack/react-query/build/modern/suspense.js","../node_modules/@tanstack/react-query/build/modern/useBaseQuery.js","../node_modules/@tanstack/react-query/build/modern/useQuery.js","../src/utils/query.ts","../src/hooks/useLiveState.ts","../src/hooks/useTrackEvent.ts","../src/utils/closable-storage.ts","../src/hooks/useClosable.ts","../src/utils/cta.ts","../src/utils/sanitize.ts","../src/components/RichText.tsx","../src/components/LiveStateAlert.tsx","../src/components/LiveStateInfo.tsx","../src/components/LiveStateRenderer.tsx"],"sourcesContent":["// src/queryObserver.ts\nimport { focusManager } from \"./focusManager.js\";\nimport { environmentManager } from \"./environmentManager.js\";\nimport { notifyManager } from \"./notifyManager.js\";\nimport { fetchState } from \"./query.js\";\nimport { Subscribable } from \"./subscribable.js\";\nimport { pendingThenable } from \"./thenable.js\";\nimport {\n isValidTimeout,\n noop,\n replaceData,\n resolveQueryBoolean,\n resolveStaleTime,\n shallowEqualObjects,\n timeUntilStale\n} from \"./utils.js\";\nimport { timeoutManager } from \"./timeoutManager.js\";\nvar QueryObserver = class extends Subscribable {\n constructor(client, options) {\n super();\n this.options = options;\n this.#client = client;\n this.#selectError = null;\n this.#currentThenable = pendingThenable();\n this.bindMethods();\n this.setOptions(options);\n }\n #client;\n #currentQuery = void 0;\n #currentQueryInitialState = void 0;\n #currentResult = void 0;\n #currentResultState;\n #currentResultOptions;\n #currentThenable;\n #selectError;\n #selectFn;\n #selectResult;\n // This property keeps track of the last query with defined data.\n // It will be used to pass the previous data and query to the placeholder function between renders.\n #lastQueryWithDefinedData;\n #staleTimeoutId;\n #refetchIntervalId;\n #currentRefetchInterval;\n #trackedProps = /* @__PURE__ */ new Set();\n bindMethods() {\n this.refetch = this.refetch.bind(this);\n }\n onSubscribe() {\n if (this.listeners.size === 1) {\n this.#currentQuery.addObserver(this);\n if (shouldFetchOnMount(this.#currentQuery, this.options)) {\n this.#executeFetch();\n } else {\n this.updateResult();\n }\n this.#updateTimers();\n }\n }\n onUnsubscribe() {\n if (!this.hasListeners()) {\n this.destroy();\n }\n }\n shouldFetchOnReconnect() {\n return shouldFetchOn(\n this.#currentQuery,\n this.options,\n this.options.refetchOnReconnect\n );\n }\n shouldFetchOnWindowFocus() {\n return shouldFetchOn(\n this.#currentQuery,\n this.options,\n this.options.refetchOnWindowFocus\n );\n }\n destroy() {\n this.listeners = /* @__PURE__ */ new Set();\n this.#clearStaleTimeout();\n this.#clearRefetchInterval();\n this.#currentQuery.removeObserver(this);\n }\n setOptions(options) {\n const prevOptions = this.options;\n const prevQuery = this.#currentQuery;\n this.options = this.#client.defaultQueryOptions(options);\n if (this.options.enabled !== void 0 && typeof this.options.enabled !== \"boolean\" && typeof this.options.enabled !== \"function\" && typeof resolveQueryBoolean(this.options.enabled, this.#currentQuery) !== \"boolean\") {\n throw new Error(\n \"Expected enabled to be a boolean or a callback that returns a boolean\"\n );\n }\n this.#updateQuery();\n this.#currentQuery.setOptions(this.options);\n if (prevOptions._defaulted && !shallowEqualObjects(this.options, prevOptions)) {\n this.#client.getQueryCache().notify({\n type: \"observerOptionsUpdated\",\n query: this.#currentQuery,\n observer: this\n });\n }\n const mounted = this.hasListeners();\n if (mounted && shouldFetchOptionally(\n this.#currentQuery,\n prevQuery,\n this.options,\n prevOptions\n )) {\n this.#executeFetch();\n }\n this.updateResult();\n if (mounted && (this.#currentQuery !== prevQuery || resolveQueryBoolean(this.options.enabled, this.#currentQuery) !== resolveQueryBoolean(prevOptions.enabled, this.#currentQuery) || resolveStaleTime(this.options.staleTime, this.#currentQuery) !== resolveStaleTime(prevOptions.staleTime, this.#currentQuery))) {\n this.#updateStaleTimeout();\n }\n const nextRefetchInterval = this.#computeRefetchInterval();\n if (mounted && (this.#currentQuery !== prevQuery || resolveQueryBoolean(this.options.enabled, this.#currentQuery) !== resolveQueryBoolean(prevOptions.enabled, this.#currentQuery) || nextRefetchInterval !== this.#currentRefetchInterval)) {\n this.#updateRefetchInterval(nextRefetchInterval);\n }\n }\n getOptimisticResult(options) {\n const query = this.#client.getQueryCache().build(this.#client, options);\n const result = this.createResult(query, options);\n if (shouldAssignObserverCurrentProperties(this, result)) {\n this.#currentResult = result;\n this.#currentResultOptions = this.options;\n this.#currentResultState = this.#currentQuery.state;\n }\n return result;\n }\n getCurrentResult() {\n return this.#currentResult;\n }\n trackResult(result, onPropTracked) {\n return new Proxy(result, {\n get: (target, key) => {\n this.trackProp(key);\n onPropTracked?.(key);\n if (key === \"promise\") {\n this.trackProp(\"data\");\n if (!this.options.experimental_prefetchInRender && this.#currentThenable.status === \"pending\") {\n this.#currentThenable.reject(\n new Error(\n \"experimental_prefetchInRender feature flag is not enabled\"\n )\n );\n }\n }\n return Reflect.get(target, key);\n }\n });\n }\n trackProp(key) {\n this.#trackedProps.add(key);\n }\n getCurrentQuery() {\n return this.#currentQuery;\n }\n refetch({ ...options } = {}) {\n return this.fetch({\n ...options\n });\n }\n fetchOptimistic(options) {\n const defaultedOptions = this.#client.defaultQueryOptions(options);\n const query = this.#client.getQueryCache().build(this.#client, defaultedOptions);\n return query.fetch().then(() => this.createResult(query, defaultedOptions));\n }\n fetch(fetchOptions) {\n return this.#executeFetch({\n ...fetchOptions,\n cancelRefetch: fetchOptions.cancelRefetch ?? true\n }).then(() => {\n this.updateResult();\n return this.#currentResult;\n });\n }\n #executeFetch(fetchOptions) {\n this.#updateQuery();\n let promise = this.#currentQuery.fetch(\n this.options,\n fetchOptions\n );\n if (!fetchOptions?.throwOnError) {\n promise = promise.catch(noop);\n }\n return promise;\n }\n #updateStaleTimeout() {\n this.#clearStaleTimeout();\n const staleTime = resolveStaleTime(\n this.options.staleTime,\n this.#currentQuery\n );\n if (environmentManager.isServer() || this.#currentResult.isStale || !isValidTimeout(staleTime)) {\n return;\n }\n const time = timeUntilStale(this.#currentResult.dataUpdatedAt, staleTime);\n const timeout = time + 1;\n this.#staleTimeoutId = timeoutManager.setTimeout(() => {\n if (!this.#currentResult.isStale) {\n this.updateResult();\n }\n }, timeout);\n }\n #computeRefetchInterval() {\n return (typeof this.options.refetchInterval === \"function\" ? this.options.refetchInterval(this.#currentQuery) : this.options.refetchInterval) ?? false;\n }\n #updateRefetchInterval(nextInterval) {\n this.#clearRefetchInterval();\n this.#currentRefetchInterval = nextInterval;\n if (environmentManager.isServer() || resolveQueryBoolean(this.options.enabled, this.#currentQuery) === false || !isValidTimeout(this.#currentRefetchInterval) || this.#currentRefetchInterval === 0) {\n return;\n }\n this.#refetchIntervalId = timeoutManager.setInterval(() => {\n if (this.options.refetchIntervalInBackground || focusManager.isFocused()) {\n this.#executeFetch();\n }\n }, this.#currentRefetchInterval);\n }\n #updateTimers() {\n this.#updateStaleTimeout();\n this.#updateRefetchInterval(this.#computeRefetchInterval());\n }\n #clearStaleTimeout() {\n if (this.#staleTimeoutId !== void 0) {\n timeoutManager.clearTimeout(this.#staleTimeoutId);\n this.#staleTimeoutId = void 0;\n }\n }\n #clearRefetchInterval() {\n if (this.#refetchIntervalId !== void 0) {\n timeoutManager.clearInterval(this.#refetchIntervalId);\n this.#refetchIntervalId = void 0;\n }\n }\n createResult(query, options) {\n const prevQuery = this.#currentQuery;\n const prevOptions = this.options;\n const prevResult = this.#currentResult;\n const prevResultState = this.#currentResultState;\n const prevResultOptions = this.#currentResultOptions;\n const queryChange = query !== prevQuery;\n const queryInitialState = queryChange ? query.state : this.#currentQueryInitialState;\n const { state } = query;\n let newState = { ...state };\n let isPlaceholderData = false;\n let data;\n if (options._optimisticResults) {\n const mounted = this.hasListeners();\n const fetchOnMount = !mounted && shouldFetchOnMount(query, options);\n const fetchOptionally = mounted && shouldFetchOptionally(query, prevQuery, options, prevOptions);\n if (fetchOnMount || fetchOptionally) {\n newState = {\n ...newState,\n ...fetchState(state.data, query.options)\n };\n }\n if (options._optimisticResults === \"isRestoring\") {\n newState.fetchStatus = \"idle\";\n }\n }\n let { error, errorUpdatedAt, status } = newState;\n data = newState.data;\n let skipSelect = false;\n if (options.placeholderData !== void 0 && data === void 0 && status === \"pending\") {\n let placeholderData;\n if (prevResult?.isPlaceholderData && options.placeholderData === prevResultOptions?.placeholderData) {\n placeholderData = prevResult.data;\n skipSelect = true;\n } else {\n placeholderData = typeof options.placeholderData === \"function\" ? options.placeholderData(\n this.#lastQueryWithDefinedData?.state.data,\n this.#lastQueryWithDefinedData\n ) : options.placeholderData;\n }\n if (placeholderData !== void 0) {\n status = \"success\";\n data = replaceData(\n prevResult?.data,\n placeholderData,\n options\n );\n isPlaceholderData = true;\n }\n }\n if (options.select && data !== void 0 && !skipSelect) {\n if (prevResult && data === prevResultState?.data && options.select === this.#selectFn) {\n data = this.#selectResult;\n } else {\n try {\n this.#selectFn = options.select;\n data = options.select(data);\n data = replaceData(prevResult?.data, data, options);\n this.#selectResult = data;\n this.#selectError = null;\n } catch (selectError) {\n this.#selectError = selectError;\n }\n }\n }\n if (this.#selectError) {\n error = this.#selectError;\n data = this.#selectResult;\n errorUpdatedAt = Date.now();\n status = \"error\";\n }\n const isFetching = newState.fetchStatus === \"fetching\";\n const isPending = status === \"pending\";\n const isError = status === \"error\";\n const isLoading = isPending && isFetching;\n const hasData = data !== void 0;\n const result = {\n status,\n fetchStatus: newState.fetchStatus,\n isPending,\n isSuccess: status === \"success\",\n isError,\n isInitialLoading: isLoading,\n isLoading,\n data,\n dataUpdatedAt: newState.dataUpdatedAt,\n error,\n errorUpdatedAt,\n failureCount: newState.fetchFailureCount,\n failureReason: newState.fetchFailureReason,\n errorUpdateCount: newState.errorUpdateCount,\n isFetched: query.isFetched(),\n isFetchedAfterMount: newState.dataUpdateCount > queryInitialState.dataUpdateCount || newState.errorUpdateCount > queryInitialState.errorUpdateCount,\n isFetching,\n isRefetching: isFetching && !isPending,\n isLoadingError: isError && !hasData,\n isPaused: newState.fetchStatus === \"paused\",\n isPlaceholderData,\n isRefetchError: isError && hasData,\n isStale: isStale(query, options),\n refetch: this.refetch,\n promise: this.#currentThenable,\n isEnabled: resolveQueryBoolean(options.enabled, query) !== false\n };\n const nextResult = result;\n if (this.options.experimental_prefetchInRender) {\n const hasResultData = nextResult.data !== void 0;\n const isErrorWithoutData = nextResult.status === \"error\" && !hasResultData;\n const finalizeThenableIfPossible = (thenable) => {\n if (isErrorWithoutData) {\n thenable.reject(nextResult.error);\n } else if (hasResultData) {\n thenable.resolve(nextResult.data);\n }\n };\n const recreateThenable = () => {\n const pending = this.#currentThenable = nextResult.promise = pendingThenable();\n finalizeThenableIfPossible(pending);\n };\n const prevThenable = this.#currentThenable;\n switch (prevThenable.status) {\n case \"pending\":\n if (query.queryHash === prevQuery.queryHash) {\n finalizeThenableIfPossible(prevThenable);\n }\n break;\n case \"fulfilled\":\n if (isErrorWithoutData || nextResult.data !== prevThenable.value) {\n recreateThenable();\n }\n break;\n case \"rejected\":\n if (!isErrorWithoutData || nextResult.error !== prevThenable.reason) {\n recreateThenable();\n }\n break;\n }\n }\n return nextResult;\n }\n updateResult() {\n const prevResult = this.#currentResult;\n const nextResult = this.createResult(this.#currentQuery, this.options);\n this.#currentResultState = this.#currentQuery.state;\n this.#currentResultOptions = this.options;\n if (this.#currentResultState.data !== void 0) {\n this.#lastQueryWithDefinedData = this.#currentQuery;\n }\n if (shallowEqualObjects(nextResult, prevResult)) {\n return;\n }\n this.#currentResult = nextResult;\n const shouldNotifyListeners = () => {\n if (!prevResult) {\n return true;\n }\n const { notifyOnChangeProps } = this.options;\n const notifyOnChangePropsValue = typeof notifyOnChangeProps === \"function\" ? notifyOnChangeProps() : notifyOnChangeProps;\n if (notifyOnChangePropsValue === \"all\" || !notifyOnChangePropsValue && !this.#trackedProps.size) {\n return true;\n }\n const includedProps = new Set(\n notifyOnChangePropsValue ?? this.#trackedProps\n );\n if (this.options.throwOnError) {\n includedProps.add(\"error\");\n }\n return Object.keys(this.#currentResult).some((key) => {\n const typedKey = key;\n const changed = this.#currentResult[typedKey] !== prevResult[typedKey];\n return changed && includedProps.has(typedKey);\n });\n };\n this.#notify({ listeners: shouldNotifyListeners() });\n }\n #updateQuery() {\n const query = this.#client.getQueryCache().build(this.#client, this.options);\n if (query === this.#currentQuery) {\n return;\n }\n const prevQuery = this.#currentQuery;\n this.#currentQuery = query;\n this.#currentQueryInitialState = query.state;\n if (this.hasListeners()) {\n prevQuery?.removeObserver(this);\n query.addObserver(this);\n }\n }\n onQueryUpdate() {\n this.updateResult();\n if (this.hasListeners()) {\n this.#updateTimers();\n }\n }\n #notify(notifyOptions) {\n notifyManager.batch(() => {\n if (notifyOptions.listeners) {\n this.listeners.forEach((listener) => {\n listener(this.#currentResult);\n });\n }\n this.#client.getQueryCache().notify({\n query: this.#currentQuery,\n type: \"observerResultsUpdated\"\n });\n });\n }\n};\nfunction shouldLoadOnMount(query, options) {\n return resolveQueryBoolean(options.enabled, query) !== false && query.state.data === void 0 && !(query.state.status === \"error\" && resolveQueryBoolean(options.retryOnMount, query) === false);\n}\nfunction shouldFetchOnMount(query, options) {\n return shouldLoadOnMount(query, options) || query.state.data !== void 0 && shouldFetchOn(query, options, options.refetchOnMount);\n}\nfunction shouldFetchOn(query, options, field) {\n if (resolveQueryBoolean(options.enabled, query) !== false && resolveStaleTime(options.staleTime, query) !== \"static\") {\n const value = typeof field === \"function\" ? field(query) : field;\n return value === \"always\" || value !== false && isStale(query, options);\n }\n return false;\n}\nfunction shouldFetchOptionally(query, prevQuery, options, prevOptions) {\n return (query !== prevQuery || resolveQueryBoolean(prevOptions.enabled, query) === false) && (!options.suspense || query.state.status !== \"error\") && isStale(query, options);\n}\nfunction isStale(query, options) {\n return resolveQueryBoolean(options.enabled, query) !== false && query.isStaleByTime(resolveStaleTime(options.staleTime, query));\n}\nfunction shouldAssignObserverCurrentProperties(observer, optimisticResult) {\n if (!shallowEqualObjects(observer.getCurrentResult(), optimisticResult)) {\n return true;\n }\n return false;\n}\nexport {\n QueryObserver\n};\n//# sourceMappingURL=queryObserver.js.map","\"use client\";\n\n// src/IsRestoringProvider.ts\nimport * as React from \"react\";\nvar IsRestoringContext = React.createContext(false);\nvar useIsRestoring = () => React.useContext(IsRestoringContext);\nvar IsRestoringProvider = IsRestoringContext.Provider;\nexport {\n IsRestoringProvider,\n useIsRestoring\n};\n//# sourceMappingURL=IsRestoringProvider.js.map","\"use client\";\n\n// src/QueryErrorResetBoundary.tsx\nimport * as React from \"react\";\nimport { jsx } from \"react/jsx-runtime\";\nfunction createValue() {\n let isReset = false;\n return {\n clearReset: () => {\n isReset = false;\n },\n reset: () => {\n isReset = true;\n },\n isReset: () => {\n return isReset;\n }\n };\n}\nvar QueryErrorResetBoundaryContext = React.createContext(createValue());\nvar useQueryErrorResetBoundary = () => React.useContext(QueryErrorResetBoundaryContext);\nvar QueryErrorResetBoundary = ({\n children\n}) => {\n const [value] = React.useState(() => createValue());\n return /* @__PURE__ */ jsx(QueryErrorResetBoundaryContext.Provider, { value, children: typeof children === \"function\" ? children(value) : children });\n};\nexport {\n QueryErrorResetBoundary,\n useQueryErrorResetBoundary\n};\n//# sourceMappingURL=QueryErrorResetBoundary.js.map","\"use client\";\n\n// src/errorBoundaryUtils.ts\nimport * as React from \"react\";\nimport { shouldThrowError } from \"@tanstack/query-core\";\nvar ensurePreventErrorBoundaryRetry = (options, errorResetBoundary, query) => {\n const throwOnError = query?.state.error && typeof options.throwOnError === \"function\" ? shouldThrowError(options.throwOnError, [query.state.error, query]) : options.throwOnError;\n if (options.suspense || options.experimental_prefetchInRender || throwOnError) {\n if (!errorResetBoundary.isReset()) {\n options.retryOnMount = false;\n }\n }\n};\nvar useClearResetErrorBoundary = (errorResetBoundary) => {\n React.useEffect(() => {\n errorResetBoundary.clearReset();\n }, [errorResetBoundary]);\n};\nvar getHasError = ({\n result,\n errorResetBoundary,\n throwOnError,\n query,\n suspense\n}) => {\n return result.isError && !errorResetBoundary.isReset() && !result.isFetching && query && (suspense && result.data === void 0 || shouldThrowError(throwOnError, [result.error, query]));\n};\nexport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary\n};\n//# sourceMappingURL=errorBoundaryUtils.js.map","// src/suspense.ts\nvar defaultThrowOnError = (_error, query) => query.state.data === void 0;\nvar ensureSuspenseTimers = (defaultedOptions) => {\n if (defaultedOptions.suspense) {\n const MIN_SUSPENSE_TIME_MS = 1e3;\n const clamp = (value) => value === \"static\" ? value : Math.max(value ?? MIN_SUSPENSE_TIME_MS, MIN_SUSPENSE_TIME_MS);\n const originalStaleTime = defaultedOptions.staleTime;\n defaultedOptions.staleTime = typeof originalStaleTime === \"function\" ? (...args) => clamp(originalStaleTime(...args)) : clamp(originalStaleTime);\n if (typeof defaultedOptions.gcTime === \"number\") {\n defaultedOptions.gcTime = Math.max(\n defaultedOptions.gcTime,\n MIN_SUSPENSE_TIME_MS\n );\n }\n }\n};\nvar willFetch = (result, isRestoring) => result.isLoading && result.isFetching && !isRestoring;\nvar shouldSuspend = (defaultedOptions, result) => defaultedOptions?.suspense && result.isPending;\nvar fetchOptimistic = (defaultedOptions, observer, errorResetBoundary) => observer.fetchOptimistic(defaultedOptions).catch(() => {\n errorResetBoundary.clearReset();\n});\nexport {\n defaultThrowOnError,\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch\n};\n//# sourceMappingURL=suspense.js.map","\"use client\";\n\n// src/useBaseQuery.ts\nimport * as React from \"react\";\nimport { environmentManager, noop, notifyManager } from \"@tanstack/query-core\";\nimport { useQueryClient } from \"./QueryClientProvider.js\";\nimport { useQueryErrorResetBoundary } from \"./QueryErrorResetBoundary.js\";\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary\n} from \"./errorBoundaryUtils.js\";\nimport { useIsRestoring } from \"./IsRestoringProvider.js\";\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch\n} from \"./suspense.js\";\nfunction useBaseQuery(options, Observer, queryClient) {\n if (process.env.NODE_ENV !== \"production\") {\n if (typeof options !== \"object\" || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object'\n );\n }\n }\n const isRestoring = useIsRestoring();\n const errorResetBoundary = useQueryErrorResetBoundary();\n const client = useQueryClient(queryClient);\n const defaultedOptions = client.defaultQueryOptions(options);\n client.getDefaultOptions().queries?._experimental_beforeQuery?.(\n defaultedOptions\n );\n const query = client.getQueryCache().get(defaultedOptions.queryHash);\n if (process.env.NODE_ENV !== \"production\") {\n if (!defaultedOptions.queryFn) {\n console.error(\n `[${defaultedOptions.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`\n );\n }\n }\n defaultedOptions._optimisticResults = isRestoring ? \"isRestoring\" : \"optimistic\";\n ensureSuspenseTimers(defaultedOptions);\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary, query);\n useClearResetErrorBoundary(errorResetBoundary);\n const isNewCacheEntry = !client.getQueryCache().get(defaultedOptions.queryHash);\n const [observer] = React.useState(\n () => new Observer(\n client,\n defaultedOptions\n )\n );\n const result = observer.getOptimisticResult(defaultedOptions);\n const shouldSubscribe = !isRestoring && options.subscribed !== false;\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = shouldSubscribe ? observer.subscribe(notifyManager.batchCalls(onStoreChange)) : noop;\n observer.updateResult();\n return unsubscribe;\n },\n [observer, shouldSubscribe]\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult()\n );\n React.useEffect(() => {\n observer.setOptions(defaultedOptions);\n }, [defaultedOptions, observer]);\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary);\n }\n if (getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query,\n suspense: defaultedOptions.suspense\n })) {\n throw result.error;\n }\n ;\n client.getDefaultOptions().queries?._experimental_afterQuery?.(\n defaultedOptions,\n result\n );\n if (defaultedOptions.experimental_prefetchInRender && !environmentManager.isServer() && willFetch(result, isRestoring)) {\n const promise = isNewCacheEntry ? (\n // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n ) : (\n // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n query?.promise\n );\n promise?.catch(noop).finally(() => {\n observer.updateResult();\n });\n }\n return !defaultedOptions.notifyOnChangeProps ? observer.trackResult(result) : result;\n}\nexport {\n useBaseQuery\n};\n//# sourceMappingURL=useBaseQuery.js.map","\"use client\";\n\n// src/useQuery.ts\nimport { QueryObserver } from \"@tanstack/query-core\";\nimport { useBaseQuery } from \"./useBaseQuery.js\";\nfunction useQuery(options, queryClient) {\n return useBaseQuery(options, QueryObserver, queryClient);\n}\nexport {\n useQuery\n};\n//# sourceMappingURL=useQuery.js.map","import { defaultQueryClient } from '../query-client';\nimport type { LiveStateFetcher } from '../types';\n\n/**\n * Internal React Query key used by `useLiveState`.\n *\n * Not exported from the public API on purpose — consumers interact with the\n * cache through the `prefetchLiveState` and `invalidateLiveState` helpers\n * instead, so that React Query remains an internal implementation detail.\n */\nexport const LIVE_STATE_QUERY_KEY = ['live-state'] as const;\n\n/**\n * Pre-warms the live-state cache before the component tree mounts.\n *\n * Call this as early as possible (e.g. in a route loader or top-level effect)\n * so that when `LiveStateProvider` renders, data is already available and no\n * loading state is shown to the user.\n *\n * If the cache already contains fresh data (within `staleTime`), the call is\n * a no-op — no extra request is made.\n *\n * @param fetcher - The same fetcher function passed to `LiveStateProvider`.\n *\n * @example\n * // In a route loader (before the page renders)\n * await prefetchLiveState(LENDING_FETCHER);\n */\nexport async function prefetchLiveState(\n fetcher: LiveStateFetcher,\n): Promise<void> {\n await defaultQueryClient.prefetchQuery({\n queryKey: LIVE_STATE_QUERY_KEY,\n queryFn: ({ signal }) => fetcher({ signal }),\n staleTime: 60_000,\n });\n}\n\n/**\n * Invalidates the live-state cache, triggering an immediate re-fetch on every\n * mounted `useLiveState` consumer.\n *\n * Call this after a user action that changes the backend state so the\n * notification reflects the new state without waiting for the next polling\n * tick or page reload.\n *\n * @example\n * // After the user pays an overdue instalment\n * await payInstalment();\n * await invalidateLiveState();\n * // → the banner disappears immediately, no need to wait for staleTime to expire\n */\nexport async function invalidateLiveState(): Promise<void> {\n await defaultQueryClient.invalidateQueries({\n queryKey: LIVE_STATE_QUERY_KEY,\n });\n}\n","import { useEffect } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { LIVE_STATE_QUERY_KEY } from '../utils/query';\nimport type { LiveStateResponse } from '../types';\n\ninterface UseLiveStateReturn {\n /** Live state data */\n liveState: LiveStateResponse | null;\n\n /** True while the first fetch is in progress */\n isLoading: boolean;\n\n /**\n * True when the last fetch attempt resulted in an error.\n * Use this to implement fallbacks or custom error logging.\n * Note: the lib already logs a warning to the console on every error.\n */\n isError: boolean;\n\n /**\n * The raw error from the last failed fetch, or null.\n * Pair with `isError` for more specific error handling.\n */\n error: Error | null;\n\n /** Manually trigger a re-fetch */\n refresh: () => Promise<void>;\n}\n\n/**\n * useLiveState hook\n *\n * Fetches and manages live state data using React Query with automatic caching,\n * deduplication, and revalidation.\n *\n * Must be used within LiveStateProvider. See examples/ directory for usage.\n */\nexport function useLiveState(): UseLiveStateReturn {\n const { fetcher, mockData, refetchInterval, log } = useLiveStateContext();\n\n // When mockData is provided, bypass React Query entirely — the fetcher is never called.\n // This enables local development and Storybook without a real backend.\n const isMocked = mockData !== undefined;\n\n const { data, error, isLoading, refetch } = useQuery<\n LiveStateResponse | null,\n Error\n >({\n queryKey: LIVE_STATE_QUERY_KEY,\n queryFn: ({ signal }) => fetcher({ signal }),\n enabled: !isMocked,\n staleTime: 60_000,\n retry: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: true,\n refetchInterval: isMocked ? false : refetchInterval,\n });\n\n useEffect(() => {\n if (error) {\n log('error', 'Failed to fetch live state', { error });\n }\n }, [error, log]);\n\n const refresh = async () => {\n if (isMocked) return; // no-op when mocked\n try {\n await refetch();\n } catch (err) {\n log('error', 'Failed to refresh live state', { error: err });\n }\n };\n\n if (isMocked) {\n return {\n liveState: mockData,\n isLoading: false,\n isError: false,\n error: null,\n refresh,\n };\n }\n\n return {\n liveState: data ?? null,\n isLoading,\n isError: error != null,\n error: error ?? null,\n refresh,\n };\n}\n","import { useCallback } from 'react';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { trackEvent } from '../utils/analytics';\nimport type { TrackingProperties } from '../types';\n\n/**\n * useTrackEvent\n *\n * Returns a `track` function that fires both the internal analytics\n * (Amplitude + Clarity) and the optional `onEvent` callback provided\n * to LiveStateProvider — useful for simulators and debugging tools.\n */\nexport function useTrackEvent() {\n const { onEvent, disabled, log } = useLiveStateContext();\n\n const track = useCallback(\n (eventName: string, properties?: TrackingProperties) => {\n // onEvent callback fires even when disabled — it is an observability\n // hook, not an analytics SDK, so the caller opts in deliberately.\n onEvent?.(eventName, properties);\n\n // Skip SDK calls when analytics are disabled (e.g. dev/test environments)\n if (!disabled) {\n trackEvent(eventName, properties, log);\n }\n },\n [onEvent, disabled, log],\n );\n\n return track;\n}\n","export const LIVE_STATE_STORAGE_KEY = '@tiendanube/live-state:closable';\n\n/** @internal */\nconst STORAGE_KEY = LIVE_STATE_STORAGE_KEY;\n\nexport interface ClosableState {\n count: number;\n closedAt: number;\n}\n\nexport type ClosableStates = Record<string, Record<string, ClosableState>>;\n\n/**\n * Reads closable states from localStorage.\n * Normalises legacy format (plain number) to the current shape ({ count, closedAt }).\n * Returns an empty object on any error (fail-silent).\n */\nexport function getClosableStates(): ClosableStates {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return {};\n\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== 'object' || parsed === null) return {};\n\n const normalized: ClosableStates = {};\n\n for (const [ctx, ctxState] of Object.entries(\n parsed as Record<string, unknown>,\n )) {\n if (typeof ctxState !== 'object' || ctxState === null) continue;\n\n normalized[ctx] = {};\n\n for (const [id, entry] of Object.entries(\n ctxState as Record<string, unknown>,\n )) {\n if (typeof entry === 'number') {\n // legacy format: plain close count\n normalized[ctx][id] = { count: entry, closedAt: 0 };\n } else if (typeof entry === 'object' && entry !== null) {\n const candidate = entry as Partial<ClosableState>;\n normalized[ctx][id] = {\n count: typeof candidate.count === 'number' ? candidate.count : 0,\n closedAt:\n typeof candidate.closedAt === 'number' ? candidate.closedAt : 0,\n };\n }\n }\n }\n\n return normalized;\n } catch {\n return {};\n }\n}\n\n/**\n * Persists closable states to localStorage.\n * Fails silently if localStorage is unavailable or full.\n */\nexport function setClosableStates(states: ClosableStates): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(states));\n } catch {\n // localStorage unavailable or quota exceeded — application continues normally\n }\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport {\n getClosableStates,\n setClosableStates,\n} from '../utils/closable-storage';\n\nexport interface UseClosableOptions {\n /** Notification context (e.g. 'awareness', 'charge') */\n context: string;\n /** Unique notification ID (campaignId). If absent, always visible — no close tracking. */\n id: string | undefined;\n /** Maximum number of times the user can close before it is hidden permanently */\n maxCloseTimes?: number;\n /** Milliseconds after which the close counter resets (optional) */\n expiresIn?: number;\n}\n\nexport interface UseClosableReturn {\n /** Whether the notification should be shown. null = initial check in progress. */\n isVisible: boolean | null;\n /** Call this to record a close action */\n close: () => void;\n}\n\n/**\n * Manages the close state of a notification using localStorage.\n *\n * After the user closes a notification `maxCloseTimes` times, it is hidden\n * permanently. Optionally, the counter resets after `expiresIn` milliseconds.\n *\n * Fails silently — errors in localStorage never break the application.\n *\n * @example\n * ```tsx\n * const { isVisible, close } = useClosable({\n * context: 'awareness',\n * id: 'awareness-2026-q1',\n * maxCloseTimes: 3,\n * expiresIn: 86_400_000, // 1 day\n * });\n *\n * if (!isVisible) return null;\n * return <Notification onClose={close} />;\n * ```\n */\nexport function useClosable({\n context,\n id,\n maxCloseTimes = 3,\n expiresIn,\n}: UseClosableOptions): UseClosableReturn {\n const [isVisible, setIsVisible] = useState<boolean | null>(null);\n\n useEffect(() => {\n // No ID means no close tracking — always show\n if (!id) {\n setIsVisible(true);\n return;\n }\n\n const states = getClosableStates();\n const entry = states[context]?.[id];\n\n if (!entry) {\n setIsVisible(true);\n return;\n }\n\n const { count, closedAt } = entry;\n\n // Check expiry — reset counter and show if expired\n if (expiresIn != null && closedAt > 0) {\n const elapsed = Date.now() - closedAt;\n if (elapsed > expiresIn) {\n const updated = { ...states };\n if (updated[context]) {\n delete updated[context][id];\n setClosableStates(updated);\n }\n setIsVisible(true);\n return;\n }\n }\n\n setIsVisible(count < maxCloseTimes);\n }, [context, id, maxCloseTimes, expiresIn]);\n\n const close = useCallback(() => {\n // Always hide visually\n setIsVisible(false);\n\n // Only persist to localStorage if there is an id to track\n if (!id) return;\n\n const states = getClosableStates();\n const currentCount = states[context]?.[id]?.count ?? 0;\n\n const updated: typeof states = {\n ...states,\n [context]: {\n ...(states[context] ?? {}),\n [id]: {\n count: currentCount + 1,\n closedAt: Date.now(),\n },\n },\n };\n\n setClosableStates(updated);\n }, [context, id]);\n\n return { isVisible, close };\n}\n","import type { CtaConfig } from '../types';\nimport { createLogger, type LoggerFn } from './logger';\n\n/**\n * Handle CTA click based on type\n *\n * @param cta - CTA configuration from LiveStateResponse\n * @param log - Optional logger (defaults to console.warn)\n */\nexport function handleCtaClick(cta: CtaConfig, log?: LoggerFn): void {\n const logger = createLogger(log);\n try {\n switch (cta.type) {\n case 'internal':\n window.location.href = cta.url;\n break;\n\n case 'whatsapp': {\n const whatsappUrl = cta.whatsappMessage\n ? `${cta.url}?text=${encodeURIComponent(cta.whatsappMessage)}`\n : cta.url;\n window.open(whatsappUrl, '_blank');\n break;\n }\n\n case 'external':\n window.open(cta.url, '_blank');\n break;\n\n default:\n logger('warn', `Unknown CTA type: ${(cta as CtaConfig).type}`, { cta });\n }\n } catch (error) {\n logger('error', 'Failed to handle CTA click', { cta, error });\n }\n}\n","/**\n * Minimal HTML sanitiser for notification content.\n *\n * Allows only a strict allowlist of inline formatting tags that are expected\n * in notification messages (strong, em, b, i, br, span). All other tags and\n * attributes are stripped, preventing XSS even if the backend is compromised.\n *\n * This intentionally avoids a runtime dependency on DOMPurify or similar\n * libraries — the allowlist is narrow enough to be maintained safely here.\n */\n\n/** Tags that are safe to render inside notification text */\nconst ALLOWED_TAGS = new Set(['strong', 'em', 'b', 'i', 'br', 'span']);\n\n/**\n * Tags whose entire content (open tag + inner text + close tag) must be\n * removed, not just the surrounding tags. This prevents script injection\n * even if the backend is compromised.\n */\nconst BLOCK_TAGS_RE =\n /<(script|style|iframe|object|embed|form|input|button|textarea|select|link|meta|head|body|html|svg|math)[\\s\\S]*?<\\/\\1\\s*>|<(script|style|iframe|object|embed|form|input|button|textarea|select|link|meta|head|body|html|svg|math)[^>]*\\/?>/gi;\n\n/**\n * Strips all HTML tags except those in ALLOWED_TAGS.\n * Attributes are removed from all allowed tags to prevent event-handler\n * injection (e.g. `<span onclick=\"...\">`).\n * Dangerous tags (script, style, iframe, …) have their entire content removed.\n *\n * Returns the sanitised HTML string, safe to pass to `dangerouslySetInnerHTML`.\n */\nexport function sanitizeHtml(input: string): string {\n // Step 1: remove dangerous tags and their inner content entirely\n const withoutDangerous = input.replace(BLOCK_TAGS_RE, '');\n\n // Step 2: remove all attributes from every remaining tag\n const withoutAttributes = withoutDangerous.replace(\n /<([a-zA-Z][a-zA-Z0-9]*)\\s[^>]*>/g,\n '<$1>',\n );\n\n // Step 3: strip any remaining tag that is not in the allowlist\n return withoutAttributes.replace(\n /<\\/?([a-zA-Z][a-zA-Z0-9]*)[^>]*>/g,\n (match, tag: string) => (ALLOWED_TAGS.has(tag.toLowerCase()) ? match : ''),\n );\n}\n\n/**\n * Returns true when the string contains at least one HTML tag,\n * indicating it should be rendered as rich text.\n */\nexport function containsHtml(input: string): boolean {\n return /<[a-zA-Z][^>]*>/.test(input);\n}\n","import { Text } from '@nimbus-ds/components';\nimport type { ComponentProps } from 'react';\nimport { sanitizeHtml, containsHtml } from '../utils/sanitize';\n\ntype TextProps = ComponentProps<typeof Text>;\n\ninterface RichTextProps extends Omit<TextProps, 'children'> {\n content: string;\n}\n\n/**\n * RichText\n *\n * Renders a text string that may contain inline HTML formatting (e.g. <strong>,\n * <em>, <br>). When HTML is detected, the content is sanitised through a strict\n * allowlist before being injected via dangerouslySetInnerHTML. Plain strings\n * are rendered via the Nimbus Text component without any DOM injection.\n *\n * Allowed tags: strong, em, b, i, br, span. All attributes are stripped.\n */\nexport function RichText({ content, ...textProps }: RichTextProps) {\n if (containsHtml(content)) {\n const safe = sanitizeHtml(content);\n return (\n <Text {...textProps}>\n <span dangerouslySetInnerHTML={{ __html: safe }} />\n </Text>\n );\n }\n\n return <Text {...textProps}>{content}</Text>;\n}\n","import { useCallback, useEffect } from 'react';\nimport { Alert, Box, Button } from '@nimbus-ds/components';\nimport type { LiveStateResponse, TrackingConfig } from '../types';\nimport { buildTrackingProperties, buildEventName } from '../utils/analytics';\nimport { handleCtaClick } from '../utils/cta';\nimport { useTrackEvent } from '../hooks/useTrackEvent';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { RichText } from './RichText';\n\nexport interface LiveStateAlertProps {\n data: LiveStateResponse;\n trackingConfig: TrackingConfig;\n /** When provided, shows a close button and calls this on dismiss */\n onClose?: () => void;\n /**\n * Override CTA click behaviour.\n * When provided, replaces default navigation so the caller controls what\n * happens on click (e.g. prevent navigation in a simulator, use a router).\n */\n onCtaClick?: (cta: import('../types').CtaConfig) => void;\n}\n\n/**\n * LiveStateAlert\n *\n * Renders an Alert component (Nimbus) for alert/warning types.\n * Automatically tracks view, click, and close events.\n * Shows a close button when onClose is provided.\n *\n * See examples/ directory for usage examples.\n */\nexport function LiveStateAlert({\n data,\n trackingConfig,\n onClose,\n onCtaClick,\n}: LiveStateAlertProps) {\n const track = useTrackEvent();\n const { log } = useLiveStateContext();\n const appearance = data.type === 'alert' ? 'danger' : 'warning';\n\n const buildEventProperties = useCallback(\n () =>\n buildTrackingProperties({\n context: data.context,\n campaignId: data.campaignId,\n group: data.group,\n ...data.metadata,\n ...trackingConfig.properties,\n }),\n [data, trackingConfig.properties],\n );\n\n const handleClick = useCallback(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'click',\n );\n track(eventName, buildEventProperties());\n if (onCtaClick) {\n onCtaClick(data.cta);\n } else {\n handleCtaClick(data.cta, log);\n }\n }, [data, trackingConfig, buildEventProperties, track, onCtaClick, log]);\n\n const handleClose = useCallback(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'close',\n );\n track(eventName, buildEventProperties());\n onClose?.();\n }, [onClose, data, trackingConfig, buildEventProperties, track]);\n\n useEffect(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'view',\n );\n track(eventName, buildEventProperties());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <Alert\n appearance={appearance}\n title={data.title}\n onRemove={onClose ? handleClose : undefined}>\n <Box\n display=\"flex\"\n alignItems=\"flex-start\"\n gap=\"3\"\n flexWrap=\"wrap\"\n flexDirection=\"column\">\n <Box flex=\"1 1 auto\" minWidth=\"220px\">\n <RichText content={data.message} />\n </Box>\n\n <Box display=\"flex\" justifyContent=\"flex-end\" marginTop=\"2\">\n <Button appearance=\"primary\" onClick={handleClick}>\n {data.cta.label}\n </Button>\n </Box>\n </Box>\n </Alert>\n );\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { Card, Box, Text, Link, Icon } from '@nimbus-ds/components';\nimport { MoneyIcon, CloseIcon } from '@nimbus-ds/icons';\nimport type { LiveStateResponse, TrackingConfig } from '../types';\nimport { buildTrackingProperties, buildEventName } from '../utils/analytics';\nimport { handleCtaClick } from '../utils/cta';\nimport { useTrackEvent } from '../hooks/useTrackEvent';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { RichText } from './RichText';\n\nexport interface LiveStateInfoProps {\n data: LiveStateResponse;\n trackingConfig: TrackingConfig;\n defaultVariant?: 'blue' | 'white';\n /** When provided, shows a close button and calls this on dismiss */\n onClose?: () => void;\n /**\n * Override mobile layout detection.\n * When provided, bypasses `window.innerWidth < 750` so simulators and\n * testing tools can force a specific layout without resizing the window.\n */\n isMobile?: boolean;\n /**\n * Override CTA click behaviour.\n * When provided, replaces default navigation so the caller controls what\n * happens on click (e.g. prevent navigation in a simulator, use a router).\n */\n onCtaClick?: (cta: import('../types').CtaConfig) => void;\n}\n\nconst ICON_COLOR_MAP = {\n blue: { background: '#0050C3', icon: '#FFFFFF' },\n white: { background: '#FFFFFF', icon: '#0059D5' },\n} as const;\n\n/**\n * LiveStateInfo\n *\n * Renders a Card component (Nimbus) for info type.\n * Uses MoneyIcon with colored circle background, Text components,\n * and a Link-style CTA — matching the LendingBanner design reference.\n * Automatically tracks view, click, and close events.\n * Shows a close button when onClose is provided.\n *\n * See examples/ directory for usage examples.\n */\nexport function LiveStateInfo({\n data,\n trackingConfig,\n defaultVariant = 'blue',\n onClose,\n isMobile: isMobileProp,\n onCtaClick,\n}: LiveStateInfoProps) {\n const track = useTrackEvent();\n const { log } = useLiveStateContext();\n const variant = data.variant || defaultVariant;\n const iconConfig = ICON_COLOR_MAP[variant];\n\n const [isMobileWindow, setIsMobileWindow] = useState(\n () => window.innerWidth < 750,\n );\n\n useEffect(() => {\n const handler = () => setIsMobileWindow(window.innerWidth < 750);\n window.addEventListener('resize', handler);\n return () => window.removeEventListener('resize', handler);\n }, []);\n\n // Prop overrides window detection — allows simulators/tests to force layout\n const isMobile = isMobileProp ?? isMobileWindow;\n\n const buildEventProperties = useCallback(\n () =>\n buildTrackingProperties({\n context: data.context,\n campaignId: data.campaignId,\n group: data.group,\n ...data.metadata,\n ...trackingConfig.properties,\n }),\n [data, trackingConfig.properties],\n );\n\n const handleClick = useCallback(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'click',\n );\n track(eventName, buildEventProperties());\n if (onCtaClick) {\n onCtaClick(data.cta);\n } else {\n handleCtaClick(data.cta, log);\n }\n }, [data, trackingConfig, buildEventProperties, track, onCtaClick, log]);\n\n const handleClose = useCallback(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'close',\n );\n track(eventName, buildEventProperties());\n onClose?.();\n }, [onClose, data, trackingConfig, buildEventProperties, track]);\n\n useEffect(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'view',\n );\n track(eventName, buildEventProperties());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const ctaLink = (\n <Link\n as=\"a\"\n textDecoration=\"none\"\n onClick={handleClick}\n data-testid=\"live-state-cta-link\">\n <Text color=\"primary-interactive\" fontSize=\"base\">\n {data.cta.label}\n </Text>\n </Link>\n );\n\n return (\n <Card>\n <Box display=\"flex\" flexDirection=\"row\" justifyContent=\"space-between\">\n {/* Left: icon + text (+ cta on mobile) */}\n <Box\n display=\"flex\"\n gap=\"4\"\n alignItems={isMobile ? 'flex-start' : 'center'}\n paddingRight=\"1-5\">\n <Box minWidth=\"32px\">\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: '35%',\n borderColor: variant === 'white' ? '#E7E7E7' : 'transparent',\n borderWidth: 1,\n borderStyle: 'solid',\n background: iconConfig.background,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}>\n <MoneyIcon style={{ color: iconConfig.icon }} />\n </div>\n </Box>\n\n <Box display=\"grid\" gap=\"2\">\n <Box>\n <RichText\n content={data.title}\n fontSize=\"base\"\n color=\"neutral-textHigh\"\n />\n <RichText\n content={data.message}\n fontSize=\"base\"\n color=\"neutral-textLow\"\n />\n </Box>\n\n {/* CTA shown below text on mobile */}\n {isMobile && ctaLink}\n </Box>\n </Box>\n\n {/* Right: cta (desktop only) + close button */}\n {(!isMobile || onClose) && (\n <Box\n display=\"flex\"\n flexDirection={isMobile ? 'column' : 'row'}\n alignItems={isMobile ? 'flex-end' : 'center'}\n gap=\"2\">\n {/* CTA shown on the right side on desktop */}\n {!isMobile && ctaLink}\n\n {onClose && (\n <button\n type=\"button\"\n data-testid=\"live-state-close-button\"\n aria-label=\"Fechar notificação\"\n onClick={handleClose}\n style={{\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}>\n <Icon\n source={<CloseIcon width=\"18px\" height=\"18px\" />}\n color=\"neutral-interactive\"\n />\n </button>\n )}\n </Box>\n )}\n </Box>\n </Card>\n );\n}\n","import type { LiveStateRendererProps } from '../types';\nimport { useClosable } from '../hooks/useClosable';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { LiveStateAlert } from './LiveStateAlert';\nimport { LiveStateInfo } from './LiveStateInfo';\n\n/**\n * LiveStateRenderer\n *\n * Main component that validates payload, filters by context, and renders\n * the appropriate visual component (Alert or Info) based on type.\n * Handles closable notifications via useClosable when closable is configured.\n *\n * See examples/ directory for usage examples.\n */\nexport function LiveStateRenderer({\n data,\n loading,\n trackingConfig,\n allowedContexts,\n defaultVariant,\n isMobile,\n onCtaClick,\n}: LiveStateRendererProps) {\n const { log, onNavigate } = useLiveStateContext();\n\n // Priority: onCtaClick (per-renderer) > onNavigate (provider) > default handler\n const resolvedCtaClick = onCtaClick ?? onNavigate;\n const { isVisible, close } = useClosable({\n context: data?.context ?? '',\n id: data?.campaignId,\n maxCloseTimes: data?.metadata?.maxCloseTimes,\n expiresIn: data?.metadata?.expiresIn,\n });\n\n // Don't render while loading or no data\n if (loading || !data) {\n return null;\n }\n\n // Validate required fields\n if (\n !data.context ||\n !data.type ||\n !data.title ||\n !data.message ||\n !data.cta?.label ||\n !data.cta?.url ||\n !data.cta?.type\n ) {\n log('warn', 'Invalid payload, missing required fields', { data });\n return null;\n }\n\n // Filter by allowed contexts\n if (allowedContexts && !allowedContexts.includes(data.context)) {\n return null;\n }\n\n // Awaiting localStorage check\n if (isVisible === null) {\n return null;\n }\n\n // Hidden — user reached maxCloseTimes\n if (!isVisible) {\n return null;\n }\n\n // Pass onClose whenever closable is true.\n // campaignId is optional — useClosable handles id=undefined gracefully\n // (always visible, no localStorage tracking).\n const onClose = data.closable ? close : undefined;\n\n // Render appropriate component based on type\n if (data.type === 'alert' || data.type === 'warning') {\n return (\n <LiveStateAlert\n data={data}\n onClose={onClose}\n trackingConfig={trackingConfig}\n onCtaClick={resolvedCtaClick}\n />\n );\n }\n\n if (data.type === 'info') {\n return (\n <LiveStateInfo\n data={data}\n onClose={onClose}\n trackingConfig={trackingConfig}\n defaultVariant={defaultVariant}\n isMobile={isMobile}\n onCtaClick={resolvedCtaClick}\n />\n );\n }\n\n log('warn', `Unknown type: ${data.type}`, { data });\n return null;\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["#client","#selectError","#currentThenable","#currentQuery","#executeFetch","#updateTimers","#clearStaleTimeout","#clearRefetchInterval","#updateQuery","#updateStaleTimeout","#computeRefetchInterval","#currentRefetchInterval","#updateRefetchInterval","#currentResult","#currentResultOptions","#currentResultState","#trackedProps","#staleTimeoutId","#refetchIntervalId","#currentQueryInitialState","#lastQueryWithDefinedData","#selectFn","#selectResult","#notify","React","React","React"],"sources":["../node_modules/@tanstack/query-core/build/modern/queryObserver.js","../node_modules/@tanstack/react-query/build/modern/IsRestoringProvider.js","../node_modules/@tanstack/react-query/build/modern/QueryErrorResetBoundary.js","../node_modules/@tanstack/react-query/build/modern/errorBoundaryUtils.js","../node_modules/@tanstack/react-query/build/modern/suspense.js","../node_modules/@tanstack/react-query/build/modern/useBaseQuery.js","../node_modules/@tanstack/react-query/build/modern/useQuery.js","../src/utils/query.ts","../src/hooks/useLiveState.ts","../src/hooks/useTrackEvent.ts","../src/utils/closable-storage.ts","../src/hooks/useClosable.ts","../src/utils/cta.ts","../src/utils/sanitize.ts","../src/components/RichText.tsx","../src/components/LiveStateMessage.tsx","../src/components/LiveStatePromo.tsx","../src/components/LiveStateRenderer.tsx"],"sourcesContent":["// src/queryObserver.ts\nimport { focusManager } from \"./focusManager.js\";\nimport { environmentManager } from \"./environmentManager.js\";\nimport { notifyManager } from \"./notifyManager.js\";\nimport { fetchState } from \"./query.js\";\nimport { Subscribable } from \"./subscribable.js\";\nimport { pendingThenable } from \"./thenable.js\";\nimport {\n isValidTimeout,\n noop,\n replaceData,\n resolveQueryBoolean,\n resolveStaleTime,\n shallowEqualObjects,\n timeUntilStale\n} from \"./utils.js\";\nimport { timeoutManager } from \"./timeoutManager.js\";\nvar QueryObserver = class extends Subscribable {\n constructor(client, options) {\n super();\n this.options = options;\n this.#client = client;\n this.#selectError = null;\n this.#currentThenable = pendingThenable();\n this.bindMethods();\n this.setOptions(options);\n }\n #client;\n #currentQuery = void 0;\n #currentQueryInitialState = void 0;\n #currentResult = void 0;\n #currentResultState;\n #currentResultOptions;\n #currentThenable;\n #selectError;\n #selectFn;\n #selectResult;\n // This property keeps track of the last query with defined data.\n // It will be used to pass the previous data and query to the placeholder function between renders.\n #lastQueryWithDefinedData;\n #staleTimeoutId;\n #refetchIntervalId;\n #currentRefetchInterval;\n #trackedProps = /* @__PURE__ */ new Set();\n bindMethods() {\n this.refetch = this.refetch.bind(this);\n }\n onSubscribe() {\n if (this.listeners.size === 1) {\n this.#currentQuery.addObserver(this);\n if (shouldFetchOnMount(this.#currentQuery, this.options)) {\n this.#executeFetch();\n } else {\n this.updateResult();\n }\n this.#updateTimers();\n }\n }\n onUnsubscribe() {\n if (!this.hasListeners()) {\n this.destroy();\n }\n }\n shouldFetchOnReconnect() {\n return shouldFetchOn(\n this.#currentQuery,\n this.options,\n this.options.refetchOnReconnect\n );\n }\n shouldFetchOnWindowFocus() {\n return shouldFetchOn(\n this.#currentQuery,\n this.options,\n this.options.refetchOnWindowFocus\n );\n }\n destroy() {\n this.listeners = /* @__PURE__ */ new Set();\n this.#clearStaleTimeout();\n this.#clearRefetchInterval();\n this.#currentQuery.removeObserver(this);\n }\n setOptions(options) {\n const prevOptions = this.options;\n const prevQuery = this.#currentQuery;\n this.options = this.#client.defaultQueryOptions(options);\n if (this.options.enabled !== void 0 && typeof this.options.enabled !== \"boolean\" && typeof this.options.enabled !== \"function\" && typeof resolveQueryBoolean(this.options.enabled, this.#currentQuery) !== \"boolean\") {\n throw new Error(\n \"Expected enabled to be a boolean or a callback that returns a boolean\"\n );\n }\n this.#updateQuery();\n this.#currentQuery.setOptions(this.options);\n if (prevOptions._defaulted && !shallowEqualObjects(this.options, prevOptions)) {\n this.#client.getQueryCache().notify({\n type: \"observerOptionsUpdated\",\n query: this.#currentQuery,\n observer: this\n });\n }\n const mounted = this.hasListeners();\n if (mounted && shouldFetchOptionally(\n this.#currentQuery,\n prevQuery,\n this.options,\n prevOptions\n )) {\n this.#executeFetch();\n }\n this.updateResult();\n if (mounted && (this.#currentQuery !== prevQuery || resolveQueryBoolean(this.options.enabled, this.#currentQuery) !== resolveQueryBoolean(prevOptions.enabled, this.#currentQuery) || resolveStaleTime(this.options.staleTime, this.#currentQuery) !== resolveStaleTime(prevOptions.staleTime, this.#currentQuery))) {\n this.#updateStaleTimeout();\n }\n const nextRefetchInterval = this.#computeRefetchInterval();\n if (mounted && (this.#currentQuery !== prevQuery || resolveQueryBoolean(this.options.enabled, this.#currentQuery) !== resolveQueryBoolean(prevOptions.enabled, this.#currentQuery) || nextRefetchInterval !== this.#currentRefetchInterval)) {\n this.#updateRefetchInterval(nextRefetchInterval);\n }\n }\n getOptimisticResult(options) {\n const query = this.#client.getQueryCache().build(this.#client, options);\n const result = this.createResult(query, options);\n if (shouldAssignObserverCurrentProperties(this, result)) {\n this.#currentResult = result;\n this.#currentResultOptions = this.options;\n this.#currentResultState = this.#currentQuery.state;\n }\n return result;\n }\n getCurrentResult() {\n return this.#currentResult;\n }\n trackResult(result, onPropTracked) {\n return new Proxy(result, {\n get: (target, key) => {\n this.trackProp(key);\n onPropTracked?.(key);\n if (key === \"promise\") {\n this.trackProp(\"data\");\n if (!this.options.experimental_prefetchInRender && this.#currentThenable.status === \"pending\") {\n this.#currentThenable.reject(\n new Error(\n \"experimental_prefetchInRender feature flag is not enabled\"\n )\n );\n }\n }\n return Reflect.get(target, key);\n }\n });\n }\n trackProp(key) {\n this.#trackedProps.add(key);\n }\n getCurrentQuery() {\n return this.#currentQuery;\n }\n refetch({ ...options } = {}) {\n return this.fetch({\n ...options\n });\n }\n fetchOptimistic(options) {\n const defaultedOptions = this.#client.defaultQueryOptions(options);\n const query = this.#client.getQueryCache().build(this.#client, defaultedOptions);\n return query.fetch().then(() => this.createResult(query, defaultedOptions));\n }\n fetch(fetchOptions) {\n return this.#executeFetch({\n ...fetchOptions,\n cancelRefetch: fetchOptions.cancelRefetch ?? true\n }).then(() => {\n this.updateResult();\n return this.#currentResult;\n });\n }\n #executeFetch(fetchOptions) {\n this.#updateQuery();\n let promise = this.#currentQuery.fetch(\n this.options,\n fetchOptions\n );\n if (!fetchOptions?.throwOnError) {\n promise = promise.catch(noop);\n }\n return promise;\n }\n #updateStaleTimeout() {\n this.#clearStaleTimeout();\n const staleTime = resolveStaleTime(\n this.options.staleTime,\n this.#currentQuery\n );\n if (environmentManager.isServer() || this.#currentResult.isStale || !isValidTimeout(staleTime)) {\n return;\n }\n const time = timeUntilStale(this.#currentResult.dataUpdatedAt, staleTime);\n const timeout = time + 1;\n this.#staleTimeoutId = timeoutManager.setTimeout(() => {\n if (!this.#currentResult.isStale) {\n this.updateResult();\n }\n }, timeout);\n }\n #computeRefetchInterval() {\n return (typeof this.options.refetchInterval === \"function\" ? this.options.refetchInterval(this.#currentQuery) : this.options.refetchInterval) ?? false;\n }\n #updateRefetchInterval(nextInterval) {\n this.#clearRefetchInterval();\n this.#currentRefetchInterval = nextInterval;\n if (environmentManager.isServer() || resolveQueryBoolean(this.options.enabled, this.#currentQuery) === false || !isValidTimeout(this.#currentRefetchInterval) || this.#currentRefetchInterval === 0) {\n return;\n }\n this.#refetchIntervalId = timeoutManager.setInterval(() => {\n if (this.options.refetchIntervalInBackground || focusManager.isFocused()) {\n this.#executeFetch();\n }\n }, this.#currentRefetchInterval);\n }\n #updateTimers() {\n this.#updateStaleTimeout();\n this.#updateRefetchInterval(this.#computeRefetchInterval());\n }\n #clearStaleTimeout() {\n if (this.#staleTimeoutId !== void 0) {\n timeoutManager.clearTimeout(this.#staleTimeoutId);\n this.#staleTimeoutId = void 0;\n }\n }\n #clearRefetchInterval() {\n if (this.#refetchIntervalId !== void 0) {\n timeoutManager.clearInterval(this.#refetchIntervalId);\n this.#refetchIntervalId = void 0;\n }\n }\n createResult(query, options) {\n const prevQuery = this.#currentQuery;\n const prevOptions = this.options;\n const prevResult = this.#currentResult;\n const prevResultState = this.#currentResultState;\n const prevResultOptions = this.#currentResultOptions;\n const queryChange = query !== prevQuery;\n const queryInitialState = queryChange ? query.state : this.#currentQueryInitialState;\n const { state } = query;\n let newState = { ...state };\n let isPlaceholderData = false;\n let data;\n if (options._optimisticResults) {\n const mounted = this.hasListeners();\n const fetchOnMount = !mounted && shouldFetchOnMount(query, options);\n const fetchOptionally = mounted && shouldFetchOptionally(query, prevQuery, options, prevOptions);\n if (fetchOnMount || fetchOptionally) {\n newState = {\n ...newState,\n ...fetchState(state.data, query.options)\n };\n }\n if (options._optimisticResults === \"isRestoring\") {\n newState.fetchStatus = \"idle\";\n }\n }\n let { error, errorUpdatedAt, status } = newState;\n data = newState.data;\n let skipSelect = false;\n if (options.placeholderData !== void 0 && data === void 0 && status === \"pending\") {\n let placeholderData;\n if (prevResult?.isPlaceholderData && options.placeholderData === prevResultOptions?.placeholderData) {\n placeholderData = prevResult.data;\n skipSelect = true;\n } else {\n placeholderData = typeof options.placeholderData === \"function\" ? options.placeholderData(\n this.#lastQueryWithDefinedData?.state.data,\n this.#lastQueryWithDefinedData\n ) : options.placeholderData;\n }\n if (placeholderData !== void 0) {\n status = \"success\";\n data = replaceData(\n prevResult?.data,\n placeholderData,\n options\n );\n isPlaceholderData = true;\n }\n }\n if (options.select && data !== void 0 && !skipSelect) {\n if (prevResult && data === prevResultState?.data && options.select === this.#selectFn) {\n data = this.#selectResult;\n } else {\n try {\n this.#selectFn = options.select;\n data = options.select(data);\n data = replaceData(prevResult?.data, data, options);\n this.#selectResult = data;\n this.#selectError = null;\n } catch (selectError) {\n this.#selectError = selectError;\n }\n }\n }\n if (this.#selectError) {\n error = this.#selectError;\n data = this.#selectResult;\n errorUpdatedAt = Date.now();\n status = \"error\";\n }\n const isFetching = newState.fetchStatus === \"fetching\";\n const isPending = status === \"pending\";\n const isError = status === \"error\";\n const isLoading = isPending && isFetching;\n const hasData = data !== void 0;\n const result = {\n status,\n fetchStatus: newState.fetchStatus,\n isPending,\n isSuccess: status === \"success\",\n isError,\n isInitialLoading: isLoading,\n isLoading,\n data,\n dataUpdatedAt: newState.dataUpdatedAt,\n error,\n errorUpdatedAt,\n failureCount: newState.fetchFailureCount,\n failureReason: newState.fetchFailureReason,\n errorUpdateCount: newState.errorUpdateCount,\n isFetched: query.isFetched(),\n isFetchedAfterMount: newState.dataUpdateCount > queryInitialState.dataUpdateCount || newState.errorUpdateCount > queryInitialState.errorUpdateCount,\n isFetching,\n isRefetching: isFetching && !isPending,\n isLoadingError: isError && !hasData,\n isPaused: newState.fetchStatus === \"paused\",\n isPlaceholderData,\n isRefetchError: isError && hasData,\n isStale: isStale(query, options),\n refetch: this.refetch,\n promise: this.#currentThenable,\n isEnabled: resolveQueryBoolean(options.enabled, query) !== false\n };\n const nextResult = result;\n if (this.options.experimental_prefetchInRender) {\n const hasResultData = nextResult.data !== void 0;\n const isErrorWithoutData = nextResult.status === \"error\" && !hasResultData;\n const finalizeThenableIfPossible = (thenable) => {\n if (isErrorWithoutData) {\n thenable.reject(nextResult.error);\n } else if (hasResultData) {\n thenable.resolve(nextResult.data);\n }\n };\n const recreateThenable = () => {\n const pending = this.#currentThenable = nextResult.promise = pendingThenable();\n finalizeThenableIfPossible(pending);\n };\n const prevThenable = this.#currentThenable;\n switch (prevThenable.status) {\n case \"pending\":\n if (query.queryHash === prevQuery.queryHash) {\n finalizeThenableIfPossible(prevThenable);\n }\n break;\n case \"fulfilled\":\n if (isErrorWithoutData || nextResult.data !== prevThenable.value) {\n recreateThenable();\n }\n break;\n case \"rejected\":\n if (!isErrorWithoutData || nextResult.error !== prevThenable.reason) {\n recreateThenable();\n }\n break;\n }\n }\n return nextResult;\n }\n updateResult() {\n const prevResult = this.#currentResult;\n const nextResult = this.createResult(this.#currentQuery, this.options);\n this.#currentResultState = this.#currentQuery.state;\n this.#currentResultOptions = this.options;\n if (this.#currentResultState.data !== void 0) {\n this.#lastQueryWithDefinedData = this.#currentQuery;\n }\n if (shallowEqualObjects(nextResult, prevResult)) {\n return;\n }\n this.#currentResult = nextResult;\n const shouldNotifyListeners = () => {\n if (!prevResult) {\n return true;\n }\n const { notifyOnChangeProps } = this.options;\n const notifyOnChangePropsValue = typeof notifyOnChangeProps === \"function\" ? notifyOnChangeProps() : notifyOnChangeProps;\n if (notifyOnChangePropsValue === \"all\" || !notifyOnChangePropsValue && !this.#trackedProps.size) {\n return true;\n }\n const includedProps = new Set(\n notifyOnChangePropsValue ?? this.#trackedProps\n );\n if (this.options.throwOnError) {\n includedProps.add(\"error\");\n }\n return Object.keys(this.#currentResult).some((key) => {\n const typedKey = key;\n const changed = this.#currentResult[typedKey] !== prevResult[typedKey];\n return changed && includedProps.has(typedKey);\n });\n };\n this.#notify({ listeners: shouldNotifyListeners() });\n }\n #updateQuery() {\n const query = this.#client.getQueryCache().build(this.#client, this.options);\n if (query === this.#currentQuery) {\n return;\n }\n const prevQuery = this.#currentQuery;\n this.#currentQuery = query;\n this.#currentQueryInitialState = query.state;\n if (this.hasListeners()) {\n prevQuery?.removeObserver(this);\n query.addObserver(this);\n }\n }\n onQueryUpdate() {\n this.updateResult();\n if (this.hasListeners()) {\n this.#updateTimers();\n }\n }\n #notify(notifyOptions) {\n notifyManager.batch(() => {\n if (notifyOptions.listeners) {\n this.listeners.forEach((listener) => {\n listener(this.#currentResult);\n });\n }\n this.#client.getQueryCache().notify({\n query: this.#currentQuery,\n type: \"observerResultsUpdated\"\n });\n });\n }\n};\nfunction shouldLoadOnMount(query, options) {\n return resolveQueryBoolean(options.enabled, query) !== false && query.state.data === void 0 && !(query.state.status === \"error\" && resolveQueryBoolean(options.retryOnMount, query) === false);\n}\nfunction shouldFetchOnMount(query, options) {\n return shouldLoadOnMount(query, options) || query.state.data !== void 0 && shouldFetchOn(query, options, options.refetchOnMount);\n}\nfunction shouldFetchOn(query, options, field) {\n if (resolveQueryBoolean(options.enabled, query) !== false && resolveStaleTime(options.staleTime, query) !== \"static\") {\n const value = typeof field === \"function\" ? field(query) : field;\n return value === \"always\" || value !== false && isStale(query, options);\n }\n return false;\n}\nfunction shouldFetchOptionally(query, prevQuery, options, prevOptions) {\n return (query !== prevQuery || resolveQueryBoolean(prevOptions.enabled, query) === false) && (!options.suspense || query.state.status !== \"error\") && isStale(query, options);\n}\nfunction isStale(query, options) {\n return resolveQueryBoolean(options.enabled, query) !== false && query.isStaleByTime(resolveStaleTime(options.staleTime, query));\n}\nfunction shouldAssignObserverCurrentProperties(observer, optimisticResult) {\n if (!shallowEqualObjects(observer.getCurrentResult(), optimisticResult)) {\n return true;\n }\n return false;\n}\nexport {\n QueryObserver\n};\n//# sourceMappingURL=queryObserver.js.map","\"use client\";\n\n// src/IsRestoringProvider.ts\nimport * as React from \"react\";\nvar IsRestoringContext = React.createContext(false);\nvar useIsRestoring = () => React.useContext(IsRestoringContext);\nvar IsRestoringProvider = IsRestoringContext.Provider;\nexport {\n IsRestoringProvider,\n useIsRestoring\n};\n//# sourceMappingURL=IsRestoringProvider.js.map","\"use client\";\n\n// src/QueryErrorResetBoundary.tsx\nimport * as React from \"react\";\nimport { jsx } from \"react/jsx-runtime\";\nfunction createValue() {\n let isReset = false;\n return {\n clearReset: () => {\n isReset = false;\n },\n reset: () => {\n isReset = true;\n },\n isReset: () => {\n return isReset;\n }\n };\n}\nvar QueryErrorResetBoundaryContext = React.createContext(createValue());\nvar useQueryErrorResetBoundary = () => React.useContext(QueryErrorResetBoundaryContext);\nvar QueryErrorResetBoundary = ({\n children\n}) => {\n const [value] = React.useState(() => createValue());\n return /* @__PURE__ */ jsx(QueryErrorResetBoundaryContext.Provider, { value, children: typeof children === \"function\" ? children(value) : children });\n};\nexport {\n QueryErrorResetBoundary,\n useQueryErrorResetBoundary\n};\n//# sourceMappingURL=QueryErrorResetBoundary.js.map","\"use client\";\n\n// src/errorBoundaryUtils.ts\nimport * as React from \"react\";\nimport { shouldThrowError } from \"@tanstack/query-core\";\nvar ensurePreventErrorBoundaryRetry = (options, errorResetBoundary, query) => {\n const throwOnError = query?.state.error && typeof options.throwOnError === \"function\" ? shouldThrowError(options.throwOnError, [query.state.error, query]) : options.throwOnError;\n if (options.suspense || options.experimental_prefetchInRender || throwOnError) {\n if (!errorResetBoundary.isReset()) {\n options.retryOnMount = false;\n }\n }\n};\nvar useClearResetErrorBoundary = (errorResetBoundary) => {\n React.useEffect(() => {\n errorResetBoundary.clearReset();\n }, [errorResetBoundary]);\n};\nvar getHasError = ({\n result,\n errorResetBoundary,\n throwOnError,\n query,\n suspense\n}) => {\n return result.isError && !errorResetBoundary.isReset() && !result.isFetching && query && (suspense && result.data === void 0 || shouldThrowError(throwOnError, [result.error, query]));\n};\nexport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary\n};\n//# sourceMappingURL=errorBoundaryUtils.js.map","// src/suspense.ts\nvar defaultThrowOnError = (_error, query) => query.state.data === void 0;\nvar ensureSuspenseTimers = (defaultedOptions) => {\n if (defaultedOptions.suspense) {\n const MIN_SUSPENSE_TIME_MS = 1e3;\n const clamp = (value) => value === \"static\" ? value : Math.max(value ?? MIN_SUSPENSE_TIME_MS, MIN_SUSPENSE_TIME_MS);\n const originalStaleTime = defaultedOptions.staleTime;\n defaultedOptions.staleTime = typeof originalStaleTime === \"function\" ? (...args) => clamp(originalStaleTime(...args)) : clamp(originalStaleTime);\n if (typeof defaultedOptions.gcTime === \"number\") {\n defaultedOptions.gcTime = Math.max(\n defaultedOptions.gcTime,\n MIN_SUSPENSE_TIME_MS\n );\n }\n }\n};\nvar willFetch = (result, isRestoring) => result.isLoading && result.isFetching && !isRestoring;\nvar shouldSuspend = (defaultedOptions, result) => defaultedOptions?.suspense && result.isPending;\nvar fetchOptimistic = (defaultedOptions, observer, errorResetBoundary) => observer.fetchOptimistic(defaultedOptions).catch(() => {\n errorResetBoundary.clearReset();\n});\nexport {\n defaultThrowOnError,\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch\n};\n//# sourceMappingURL=suspense.js.map","\"use client\";\n\n// src/useBaseQuery.ts\nimport * as React from \"react\";\nimport { environmentManager, noop, notifyManager } from \"@tanstack/query-core\";\nimport { useQueryClient } from \"./QueryClientProvider.js\";\nimport { useQueryErrorResetBoundary } from \"./QueryErrorResetBoundary.js\";\nimport {\n ensurePreventErrorBoundaryRetry,\n getHasError,\n useClearResetErrorBoundary\n} from \"./errorBoundaryUtils.js\";\nimport { useIsRestoring } from \"./IsRestoringProvider.js\";\nimport {\n ensureSuspenseTimers,\n fetchOptimistic,\n shouldSuspend,\n willFetch\n} from \"./suspense.js\";\nfunction useBaseQuery(options, Observer, queryClient) {\n if (process.env.NODE_ENV !== \"production\") {\n if (typeof options !== \"object\" || Array.isArray(options)) {\n throw new Error(\n 'Bad argument type. Starting with v5, only the \"Object\" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object'\n );\n }\n }\n const isRestoring = useIsRestoring();\n const errorResetBoundary = useQueryErrorResetBoundary();\n const client = useQueryClient(queryClient);\n const defaultedOptions = client.defaultQueryOptions(options);\n client.getDefaultOptions().queries?._experimental_beforeQuery?.(\n defaultedOptions\n );\n const query = client.getQueryCache().get(defaultedOptions.queryHash);\n if (process.env.NODE_ENV !== \"production\") {\n if (!defaultedOptions.queryFn) {\n console.error(\n `[${defaultedOptions.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`\n );\n }\n }\n defaultedOptions._optimisticResults = isRestoring ? \"isRestoring\" : \"optimistic\";\n ensureSuspenseTimers(defaultedOptions);\n ensurePreventErrorBoundaryRetry(defaultedOptions, errorResetBoundary, query);\n useClearResetErrorBoundary(errorResetBoundary);\n const isNewCacheEntry = !client.getQueryCache().get(defaultedOptions.queryHash);\n const [observer] = React.useState(\n () => new Observer(\n client,\n defaultedOptions\n )\n );\n const result = observer.getOptimisticResult(defaultedOptions);\n const shouldSubscribe = !isRestoring && options.subscribed !== false;\n React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => {\n const unsubscribe = shouldSubscribe ? observer.subscribe(notifyManager.batchCalls(onStoreChange)) : noop;\n observer.updateResult();\n return unsubscribe;\n },\n [observer, shouldSubscribe]\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult()\n );\n React.useEffect(() => {\n observer.setOptions(defaultedOptions);\n }, [defaultedOptions, observer]);\n if (shouldSuspend(defaultedOptions, result)) {\n throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary);\n }\n if (getHasError({\n result,\n errorResetBoundary,\n throwOnError: defaultedOptions.throwOnError,\n query,\n suspense: defaultedOptions.suspense\n })) {\n throw result.error;\n }\n ;\n client.getDefaultOptions().queries?._experimental_afterQuery?.(\n defaultedOptions,\n result\n );\n if (defaultedOptions.experimental_prefetchInRender && !environmentManager.isServer() && willFetch(result, isRestoring)) {\n const promise = isNewCacheEntry ? (\n // Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted\n fetchOptimistic(defaultedOptions, observer, errorResetBoundary)\n ) : (\n // subscribe to the \"cache promise\" so that we can finalize the currentThenable once data comes in\n query?.promise\n );\n promise?.catch(noop).finally(() => {\n observer.updateResult();\n });\n }\n return !defaultedOptions.notifyOnChangeProps ? observer.trackResult(result) : result;\n}\nexport {\n useBaseQuery\n};\n//# sourceMappingURL=useBaseQuery.js.map","\"use client\";\n\n// src/useQuery.ts\nimport { QueryObserver } from \"@tanstack/query-core\";\nimport { useBaseQuery } from \"./useBaseQuery.js\";\nfunction useQuery(options, queryClient) {\n return useBaseQuery(options, QueryObserver, queryClient);\n}\nexport {\n useQuery\n};\n//# sourceMappingURL=useQuery.js.map","import { defaultQueryClient } from '../query-client';\nimport type { LiveStateFetcher } from '../types';\n\n/**\n * Internal React Query key used by `useLiveState`.\n *\n * Not exported from the public API on purpose — consumers interact with the\n * cache through the `prefetchLiveState` and `invalidateLiveState` helpers\n * instead, so that React Query remains an internal implementation detail.\n */\nexport const LIVE_STATE_QUERY_KEY = ['live-state'] as const;\n\n/**\n * Pre-warms the live-state cache before the component tree mounts.\n *\n * Call this as early as possible (e.g. in a route loader or top-level effect)\n * so that when `LiveStateProvider` renders, data is already available and no\n * loading state is shown to the user.\n *\n * If the cache already contains fresh data (within `staleTime`), the call is\n * a no-op — no extra request is made.\n *\n * @param fetcher - The same fetcher function passed to `LiveStateProvider`.\n *\n * @example\n * // In a route loader (before the page renders)\n * await prefetchLiveState(LENDING_FETCHER);\n */\nexport async function prefetchLiveState(\n fetcher: LiveStateFetcher,\n): Promise<void> {\n await defaultQueryClient.prefetchQuery({\n queryKey: LIVE_STATE_QUERY_KEY,\n queryFn: ({ signal }) => fetcher({ signal }),\n staleTime: 60_000,\n });\n}\n\n/**\n * Invalidates the live-state cache, triggering an immediate re-fetch on every\n * mounted `useLiveState` consumer.\n *\n * Call this after a user action that changes the backend state so the\n * notification reflects the new state without waiting for the next polling\n * tick or page reload.\n *\n * @example\n * // After the user pays an overdue instalment\n * await payInstalment();\n * await invalidateLiveState();\n * // → the banner disappears immediately, no need to wait for staleTime to expire\n */\nexport async function invalidateLiveState(): Promise<void> {\n await defaultQueryClient.invalidateQueries({\n queryKey: LIVE_STATE_QUERY_KEY,\n });\n}\n","import { useEffect } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { LIVE_STATE_QUERY_KEY } from '../utils/query';\nimport type { LiveStateResponse } from '../types';\n\ninterface UseLiveStateReturn {\n /** Live state data */\n liveState: LiveStateResponse | null;\n\n /** True while the first fetch is in progress */\n isLoading: boolean;\n\n /**\n * True when the last fetch attempt resulted in an error.\n * Use this to implement fallbacks or custom error logging.\n * Note: the lib already logs a warning to the console on every error.\n */\n isError: boolean;\n\n /**\n * The raw error from the last failed fetch, or null.\n * Pair with `isError` for more specific error handling.\n */\n error: Error | null;\n\n /** Manually trigger a re-fetch */\n refresh: () => Promise<void>;\n}\n\n/**\n * useLiveState hook\n *\n * Fetches and manages live state data using React Query with automatic caching,\n * deduplication, and revalidation.\n *\n * Must be used within LiveStateProvider. See examples/ directory for usage.\n */\nexport function useLiveState(): UseLiveStateReturn {\n const { fetcher, mockData, refetchInterval, log } = useLiveStateContext();\n\n // When mockData is provided, bypass React Query entirely — the fetcher is never called.\n // This enables local development and Storybook without a real backend.\n const isMocked = mockData !== undefined;\n\n const { data, error, isLoading, refetch } = useQuery<\n LiveStateResponse | null,\n Error\n >({\n queryKey: LIVE_STATE_QUERY_KEY,\n queryFn: ({ signal }) => fetcher({ signal }),\n enabled: !isMocked,\n staleTime: 60_000,\n retry: false,\n refetchOnWindowFocus: false,\n refetchOnReconnect: true,\n refetchInterval: isMocked ? false : refetchInterval,\n });\n\n useEffect(() => {\n if (error) {\n log('error', 'Failed to fetch live state', { error });\n }\n }, [error, log]);\n\n const refresh = async () => {\n if (isMocked) return; // no-op when mocked\n try {\n await refetch();\n } catch (err) {\n log('error', 'Failed to refresh live state', { error: err });\n }\n };\n\n if (isMocked) {\n return {\n liveState: mockData,\n isLoading: false,\n isError: false,\n error: null,\n refresh,\n };\n }\n\n return {\n liveState: data ?? null,\n isLoading,\n isError: error != null,\n error: error ?? null,\n refresh,\n };\n}\n","import { useCallback } from 'react';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { trackEvent } from '../utils/analytics';\nimport type { TrackingProperties } from '../types';\n\n/**\n * useTrackEvent\n *\n * Returns a `track` function that fires both the internal analytics\n * (Amplitude + Clarity) and the optional `onEvent` callback provided\n * to LiveStateProvider — useful for simulators and debugging tools.\n */\nexport function useTrackEvent() {\n const { onEvent, disabled, log } = useLiveStateContext();\n\n const track = useCallback(\n (eventName: string, properties?: TrackingProperties) => {\n // onEvent callback fires even when disabled — it is an observability\n // hook, not an analytics SDK, so the caller opts in deliberately.\n onEvent?.(eventName, properties);\n\n // Skip SDK calls when analytics are disabled (e.g. dev/test environments)\n if (!disabled) {\n trackEvent(eventName, properties, log);\n }\n },\n [onEvent, disabled, log],\n );\n\n return track;\n}\n","export const LIVE_STATE_STORAGE_KEY = '@tiendanube/live-state:closable';\n\n/** @internal */\nconst STORAGE_KEY = LIVE_STATE_STORAGE_KEY;\n\nexport interface ClosableState {\n count: number;\n closedAt: number;\n}\n\nexport type ClosableStates = Record<string, Record<string, ClosableState>>;\n\n/**\n * Reads closable states from localStorage.\n * Normalises legacy format (plain number) to the current shape ({ count, closedAt }).\n * Returns an empty object on any error (fail-silent).\n */\nexport function getClosableStates(): ClosableStates {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return {};\n\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== 'object' || parsed === null) return {};\n\n const normalized: ClosableStates = {};\n\n for (const [ctx, ctxState] of Object.entries(\n parsed as Record<string, unknown>,\n )) {\n if (typeof ctxState !== 'object' || ctxState === null) continue;\n\n normalized[ctx] = {};\n\n for (const [id, entry] of Object.entries(\n ctxState as Record<string, unknown>,\n )) {\n if (typeof entry === 'number') {\n // legacy format: plain close count\n normalized[ctx][id] = { count: entry, closedAt: 0 };\n } else if (typeof entry === 'object' && entry !== null) {\n const candidate = entry as Partial<ClosableState>;\n normalized[ctx][id] = {\n count: typeof candidate.count === 'number' ? candidate.count : 0,\n closedAt:\n typeof candidate.closedAt === 'number' ? candidate.closedAt : 0,\n };\n }\n }\n }\n\n return normalized;\n } catch {\n return {};\n }\n}\n\n/**\n * Persists closable states to localStorage.\n * Fails silently if localStorage is unavailable or full.\n */\nexport function setClosableStates(states: ClosableStates): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(states));\n } catch {\n // localStorage unavailable or quota exceeded — application continues normally\n }\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport {\n getClosableStates,\n setClosableStates,\n} from '../utils/closable-storage';\n\nexport interface UseClosableOptions {\n /** Notification context (e.g. 'awareness', 'charge') */\n context: string;\n /** Unique notification ID (campaignId). If absent, always visible — no close tracking. */\n id: string | undefined;\n /** Maximum number of times the user can close before it is hidden permanently */\n maxCloseTimes?: number;\n /** Milliseconds after which the close counter resets (optional) */\n expiresIn?: number;\n}\n\nexport interface UseClosableReturn {\n /** Whether the notification should be shown. null = initial check in progress. */\n isVisible: boolean | null;\n /** Call this to record a close action */\n close: () => void;\n}\n\n/**\n * Manages the close state of a notification using localStorage.\n *\n * After the user closes a notification `maxCloseTimes` times, it is hidden\n * permanently. Optionally, the counter resets after `expiresIn` milliseconds.\n *\n * Fails silently — errors in localStorage never break the application.\n *\n * @example\n * ```tsx\n * const { isVisible, close } = useClosable({\n * context: 'awareness',\n * id: 'awareness-2026-q1',\n * maxCloseTimes: 3,\n * expiresIn: 86_400_000, // 1 day\n * });\n *\n * if (!isVisible) return null;\n * return <Notification onClose={close} />;\n * ```\n */\nexport function useClosable({\n context,\n id,\n maxCloseTimes = 3,\n expiresIn,\n}: UseClosableOptions): UseClosableReturn {\n const [isVisible, setIsVisible] = useState<boolean | null>(null);\n\n useEffect(() => {\n // No ID means no close tracking — always show\n if (!id) {\n setIsVisible(true);\n return;\n }\n\n const states = getClosableStates();\n const entry = states[context]?.[id];\n\n if (!entry) {\n setIsVisible(true);\n return;\n }\n\n const { count, closedAt } = entry;\n\n // Check expiry — reset counter and show if expired\n if (expiresIn != null && closedAt > 0) {\n const elapsed = Date.now() - closedAt;\n if (elapsed > expiresIn) {\n const updated = { ...states };\n if (updated[context]) {\n delete updated[context][id];\n setClosableStates(updated);\n }\n setIsVisible(true);\n return;\n }\n }\n\n setIsVisible(count < maxCloseTimes);\n }, [context, id, maxCloseTimes, expiresIn]);\n\n const close = useCallback(() => {\n // Always hide visually\n setIsVisible(false);\n\n // Only persist to localStorage if there is an id to track\n if (!id) return;\n\n const states = getClosableStates();\n const currentCount = states[context]?.[id]?.count ?? 0;\n\n const updated: typeof states = {\n ...states,\n [context]: {\n ...(states[context] ?? {}),\n [id]: {\n count: currentCount + 1,\n closedAt: Date.now(),\n },\n },\n };\n\n setClosableStates(updated);\n }, [context, id]);\n\n return { isVisible, close };\n}\n","import type { CtaConfig } from '../types';\nimport { createLogger, type LoggerFn } from './logger';\n\n/**\n * Handle CTA click based on type\n *\n * @param cta - CTA configuration from LiveStateResponse\n * @param log - Optional logger (defaults to console.warn)\n */\nexport function handleCtaClick(cta: CtaConfig, log?: LoggerFn): void {\n const logger = createLogger(log);\n try {\n switch (cta.type) {\n case 'internal':\n window.location.href = cta.url;\n break;\n\n case 'whatsapp': {\n const whatsappUrl = cta.whatsappMessage\n ? `${cta.url}?text=${encodeURIComponent(cta.whatsappMessage)}`\n : cta.url;\n window.open(whatsappUrl, '_blank');\n break;\n }\n\n case 'external':\n window.open(cta.url, '_blank');\n break;\n\n default:\n logger('warn', `Unknown CTA type: ${(cta as CtaConfig).type}`, { cta });\n }\n } catch (error) {\n logger('error', 'Failed to handle CTA click', { cta, error });\n }\n}\n","/**\n * Minimal HTML sanitiser for notification content.\n *\n * Allows only a strict allowlist of inline formatting tags that are expected\n * in notification messages (strong, em, b, i, br, span). All other tags and\n * attributes are stripped, preventing XSS even if the backend is compromised.\n *\n * This intentionally avoids a runtime dependency on DOMPurify or similar\n * libraries — the allowlist is narrow enough to be maintained safely here.\n */\n\n/** Tags that are safe to render inside notification text */\nconst ALLOWED_TAGS = new Set(['strong', 'em', 'b', 'i', 'br', 'span']);\n\n/**\n * Tags whose entire content (open tag + inner text + close tag) must be\n * removed, not just the surrounding tags. This prevents script injection\n * even if the backend is compromised.\n */\nconst BLOCK_TAGS_RE =\n /<(script|style|iframe|object|embed|form|input|button|textarea|select|link|meta|head|body|html|svg|math)[\\s\\S]*?<\\/\\1\\s*>|<(script|style|iframe|object|embed|form|input|button|textarea|select|link|meta|head|body|html|svg|math)[^>]*\\/?>/gi;\n\n/**\n * Strips all HTML tags except those in ALLOWED_TAGS.\n * Attributes are removed from all allowed tags to prevent event-handler\n * injection (e.g. `<span onclick=\"...\">`).\n * Dangerous tags (script, style, iframe, …) have their entire content removed.\n *\n * Returns the sanitised HTML string, safe to pass to `dangerouslySetInnerHTML`.\n */\nexport function sanitizeHtml(input: string): string {\n // Step 1: remove dangerous tags and their inner content entirely\n const withoutDangerous = input.replace(BLOCK_TAGS_RE, '');\n\n // Step 2: remove all attributes from every remaining tag\n const withoutAttributes = withoutDangerous.replace(\n /<([a-zA-Z][a-zA-Z0-9]*)\\s[^>]*>/g,\n '<$1>',\n );\n\n // Step 3: strip any remaining tag that is not in the allowlist\n return withoutAttributes.replace(\n /<\\/?([a-zA-Z][a-zA-Z0-9]*)[^>]*>/g,\n (match, tag: string) => (ALLOWED_TAGS.has(tag.toLowerCase()) ? match : ''),\n );\n}\n\n/**\n * Returns true when the string contains at least one HTML tag,\n * indicating it should be rendered as rich text.\n */\nexport function containsHtml(input: string): boolean {\n return /<[a-zA-Z][^>]*>/.test(input);\n}\n","import { Text } from '@nimbus-ds/components';\nimport type { ComponentProps } from 'react';\nimport { sanitizeHtml, containsHtml } from '../utils/sanitize';\n\ntype TextProps = ComponentProps<typeof Text>;\n\ninterface RichTextProps extends Omit<TextProps, 'children'> {\n content: string;\n}\n\n/**\n * RichText\n *\n * Renders a text string that may contain inline HTML formatting (e.g. <strong>,\n * <em>, <br>). When HTML is detected, the content is sanitised through a strict\n * allowlist before being injected via dangerouslySetInnerHTML. Plain strings\n * are rendered via the Nimbus Text component without any DOM injection.\n *\n * Allowed tags: strong, em, b, i, br, span. All attributes are stripped.\n */\nexport function RichText({ content, ...textProps }: RichTextProps) {\n if (containsHtml(content)) {\n const safe = sanitizeHtml(content);\n return (\n <Text {...textProps}>\n <span dangerouslySetInnerHTML={{ __html: safe }} />\n </Text>\n );\n }\n\n return <Text {...textProps}>{content}</Text>;\n}\n","import { useCallback, useEffect } from 'react';\nimport { Alert, Box, Button } from '@nimbus-ds/components';\nimport type { LiveStateResponse, TrackingConfig, CtaConfig } from '../types';\nimport { buildTrackingProperties, buildEventName } from '../utils/analytics';\nimport { handleCtaClick } from '../utils/cta';\nimport { useTrackEvent } from '../hooks/useTrackEvent';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { RichText } from './RichText';\n\nconst APPEARANCE_MAP = {\n alert: 'danger',\n warning: 'warning',\n info: 'primary',\n} as const;\n\nexport interface LiveStateMessageProps {\n data: LiveStateResponse;\n trackingConfig: TrackingConfig;\n onClose?: () => void;\n onCtaClick?: (cta: CtaConfig) => void;\n}\n\nexport function LiveStateMessage({\n data,\n trackingConfig,\n onClose,\n onCtaClick,\n}: LiveStateMessageProps) {\n const track = useTrackEvent();\n const { log } = useLiveStateContext();\n const appearance = APPEARANCE_MAP[data.type] ?? 'danger';\n\n const buildEventProperties = useCallback(\n () =>\n buildTrackingProperties({\n context: data.context,\n campaignId: data.campaignId,\n group: data.group,\n ...data.metadata,\n ...trackingConfig.properties,\n }),\n [data, trackingConfig.properties],\n );\n\n const handleClick = useCallback(() => {\n if (!data.cta) return;\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'click',\n );\n track(eventName, buildEventProperties());\n if (onCtaClick) {\n onCtaClick(data.cta);\n } else {\n handleCtaClick(data.cta, log);\n }\n }, [data, trackingConfig, buildEventProperties, track, onCtaClick, log]);\n\n const handleClose = useCallback(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'close',\n );\n track(eventName, buildEventProperties());\n onClose?.();\n }, [onClose, data, trackingConfig, buildEventProperties, track]);\n\n useEffect(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'view',\n );\n track(eventName, buildEventProperties());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <Alert\n appearance={appearance}\n title={data.title}\n data-testid=\"live-state-message\"\n onRemove={onClose ? handleClose : undefined}>\n <Box\n display=\"flex\"\n alignItems=\"flex-start\"\n gap=\"3\"\n flexWrap=\"wrap\"\n flexDirection=\"column\">\n <Box flex=\"1 1 auto\" minWidth=\"220px\">\n <RichText content={data.message} />\n </Box>\n\n {data.cta && (\n <Box display=\"flex\" justifyContent=\"flex-end\" marginTop=\"2\">\n <Button\n appearance=\"primary\"\n onClick={handleClick}\n data-testid=\"live-state-message-cta-button\">\n {data.cta.label}\n </Button>\n </Box>\n )}\n </Box>\n </Alert>\n );\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { Card, Box, Text, Link, Icon } from '@nimbus-ds/components';\nimport { MoneyIcon, CloseIcon } from '@nimbus-ds/icons';\nimport type { LiveStateResponse, TrackingConfig, CtaConfig } from '../types';\nimport { buildTrackingProperties, buildEventName } from '../utils/analytics';\nimport { handleCtaClick } from '../utils/cta';\nimport { useTrackEvent } from '../hooks/useTrackEvent';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { RichText } from './RichText';\n\nexport interface LiveStatePromoProps {\n data: LiveStateResponse;\n trackingConfig: TrackingConfig;\n defaultVariant?: 'blue' | 'white';\n /** When provided, shows a close button and calls this on dismiss */\n onClose?: () => void;\n /**\n * Override mobile layout detection.\n * When provided, bypasses `window.innerWidth < 750` so simulators and\n * testing tools can force a specific layout without resizing the window.\n */\n isMobile?: boolean;\n /**\n * Override CTA click behaviour.\n * When provided, replaces default navigation so the caller controls what\n * happens on click (e.g. prevent navigation in a simulator, use a router).\n */\n onCtaClick?: (cta: CtaConfig) => void;\n}\n\nconst ICON_COLOR_MAP = {\n blue: { background: '#0050C3', icon: '#FFFFFF' },\n white: { background: '#FFFFFF', icon: '#0059D5' },\n} as const;\n\n/**\n * LiveStatePromo\n *\n * Renders a Card component (Nimbus) for info type.\n * Uses MoneyIcon with colored circle background, Text components,\n * and a Link-style CTA — matching the LendingBanner design reference.\n * Automatically tracks view, click, and close events.\n * Shows a close button when onClose is provided.\n *\n * See examples/ directory for usage examples.\n */\nexport function LiveStatePromo({\n data,\n trackingConfig,\n defaultVariant = 'blue',\n onClose,\n isMobile: isMobileProp,\n onCtaClick,\n}: LiveStatePromoProps) {\n const track = useTrackEvent();\n const { log } = useLiveStateContext();\n const variant = data.variant || defaultVariant;\n const iconConfig = ICON_COLOR_MAP[variant];\n\n const [isMobileWindow, setIsMobileWindow] = useState(\n () => window.innerWidth < 750,\n );\n\n useEffect(() => {\n const handler = () => setIsMobileWindow(window.innerWidth < 750);\n window.addEventListener('resize', handler);\n return () => window.removeEventListener('resize', handler);\n }, []);\n\n const isMobile = isMobileProp ?? isMobileWindow;\n\n const buildEventProperties = useCallback(\n () =>\n buildTrackingProperties({\n context: data.context,\n campaignId: data.campaignId,\n group: data.group,\n ...data.metadata,\n ...trackingConfig.properties,\n }),\n [data, trackingConfig.properties],\n );\n\n const handleClick = useCallback(() => {\n if (!data.cta) return;\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'click',\n );\n track(eventName, buildEventProperties());\n if (onCtaClick) {\n onCtaClick(data.cta);\n } else {\n handleCtaClick(data.cta, log);\n }\n }, [data, trackingConfig, buildEventProperties, track, onCtaClick, log]);\n\n const handleClose = useCallback(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'close',\n );\n track(eventName, buildEventProperties());\n onClose?.();\n }, [onClose, data, trackingConfig, buildEventProperties, track]);\n\n useEffect(() => {\n const eventName = buildEventName(\n trackingConfig.prefix,\n trackingConfig.page,\n data.context,\n 'view',\n );\n track(eventName, buildEventProperties());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const ctaLink = data.cta ? (\n <Link\n as=\"a\"\n textDecoration=\"none\"\n onClick={handleClick}\n data-testid=\"live-state-promo-cta-link\">\n <Text color=\"primary-interactive\" fontSize=\"base\">\n {data.cta.label}\n </Text>\n </Link>\n ) : null;\n\n return (\n <Card>\n <Box\n display=\"flex\"\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n data-testid=\"live-state-promo\">\n {/* Left: icon + text (+ cta on mobile) */}\n <Box\n display=\"flex\"\n gap=\"4\"\n alignItems={isMobile ? 'flex-start' : 'center'}\n paddingRight=\"1-5\">\n <Box minWidth=\"32px\">\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: '35%',\n borderColor: variant === 'white' ? '#E7E7E7' : 'transparent',\n borderWidth: 1,\n borderStyle: 'solid',\n background: iconConfig.background,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}>\n <MoneyIcon style={{ color: iconConfig.icon }} />\n </div>\n </Box>\n\n <Box display=\"grid\" gap=\"2\">\n <Box>\n <RichText\n content={data.title}\n fontSize=\"base\"\n color=\"neutral-textHigh\"\n />\n <RichText\n content={data.message}\n fontSize=\"base\"\n color=\"neutral-textLow\"\n />\n </Box>\n\n {isMobile && ctaLink}\n </Box>\n </Box>\n\n {((!isMobile && ctaLink) || onClose) && (\n <Box\n display=\"flex\"\n flexDirection={isMobile ? 'column' : 'row'}\n alignItems={isMobile ? 'flex-end' : 'center'}\n gap=\"2\">\n {!isMobile && ctaLink}\n\n {onClose && (\n <button\n type=\"button\"\n data-testid=\"live-state-close-button\"\n aria-label=\"Fechar notificação\"\n onClick={handleClose}\n style={{\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}>\n <Icon\n source={<CloseIcon width=\"18px\" height=\"18px\" />}\n color=\"neutral-interactive\"\n />\n </button>\n )}\n </Box>\n )}\n </Box>\n </Card>\n );\n}\n","import type React from 'react';\nimport type { LiveStateRendererProps, LiveStateModel } from '../types';\nimport { useClosable } from '../hooks/useClosable';\nimport { useLiveStateContext } from '../providers/LiveStateProvider';\nimport { LiveStateMessage } from './LiveStateMessage';\nimport { LiveStatePromo } from './LiveStatePromo';\n\nexport function LiveStateRenderer({\n data,\n loading,\n trackingConfig,\n allowedContexts,\n defaultVariant,\n isMobile,\n onCtaClick,\n}: LiveStateRendererProps) {\n const { log, onNavigate } = useLiveStateContext();\n\n // Priority: onCtaClick (per-renderer) > onNavigate (provider) > default handler\n const resolvedCtaClick = onCtaClick ?? onNavigate;\n const { isVisible, close } = useClosable({\n context: data?.context ?? '',\n id: data?.campaignId,\n maxCloseTimes: data?.metadata?.maxCloseTimes,\n expiresIn: data?.metadata?.expiresIn,\n });\n\n // Don't render while loading or no data\n if (loading || !data) {\n return null;\n }\n\n // Validate required fields. CTA is optional, but if present it must be complete.\n const hasPartialCta =\n data.cta != null && (!data.cta.label || !data.cta.url || !data.cta.type);\n if (\n !data.context ||\n !data.model ||\n !data.type ||\n !data.title ||\n !data.message ||\n hasPartialCta\n ) {\n log('warn', 'Invalid payload, missing required fields', { data });\n return null;\n }\n\n // Filter by allowed contexts\n if (allowedContexts && !allowedContexts.includes(data.context)) {\n return null;\n }\n\n // Awaiting localStorage check\n if (isVisible === null) {\n return null;\n }\n\n // Hidden — user reached maxCloseTimes\n if (!isVisible) {\n return null;\n }\n\n // Pass onClose whenever closable is true.\n // campaignId is optional — useClosable handles id=undefined gracefully\n // (always visible, no localStorage tracking).\n const onClose = data.closable ? close : undefined;\n\n const componentByModel: Record<LiveStateModel, React.ReactElement> = {\n message: (\n <LiveStateMessage\n data={data}\n onClose={onClose}\n trackingConfig={trackingConfig}\n onCtaClick={resolvedCtaClick}\n />\n ),\n promo: (\n <LiveStatePromo\n data={data}\n onClose={onClose}\n trackingConfig={trackingConfig}\n defaultVariant={defaultVariant}\n isMobile={isMobile}\n onCtaClick={resolvedCtaClick}\n />\n ),\n };\n\n return componentByModel[data.model];\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LiveStateResponse, TrackingConfig, CtaConfig } from '../types';
|
|
2
|
+
export interface LiveStateMessageProps {
|
|
3
|
+
data: LiveStateResponse;
|
|
4
|
+
trackingConfig: TrackingConfig;
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
onCtaClick?: (cta: CtaConfig) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function LiveStateMessage({ data, trackingConfig, onClose, onCtaClick, }: LiveStateMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=LiveStateMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveStateMessage.d.ts","sourceRoot":"","sources":["../../../src/components/LiveStateMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAa7E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,iBAAiB,CAAC;IACxB,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;CACvC;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,cAAc,EACd,OAAO,EACP,UAAU,GACX,EAAE,qBAAqB,2CAoFvB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { LiveStateResponse, TrackingConfig } from '../types';
|
|
2
|
-
export interface
|
|
1
|
+
import { LiveStateResponse, TrackingConfig, CtaConfig } from '../types';
|
|
2
|
+
export interface LiveStatePromoProps {
|
|
3
3
|
data: LiveStateResponse;
|
|
4
4
|
trackingConfig: TrackingConfig;
|
|
5
5
|
defaultVariant?: 'blue' | 'white';
|
|
@@ -16,10 +16,10 @@ export interface LiveStateInfoProps {
|
|
|
16
16
|
* When provided, replaces default navigation so the caller controls what
|
|
17
17
|
* happens on click (e.g. prevent navigation in a simulator, use a router).
|
|
18
18
|
*/
|
|
19
|
-
onCtaClick?: (cta:
|
|
19
|
+
onCtaClick?: (cta: CtaConfig) => void;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* LiveStatePromo
|
|
23
23
|
*
|
|
24
24
|
* Renders a Card component (Nimbus) for info type.
|
|
25
25
|
* Uses MoneyIcon with colored circle background, Text components,
|
|
@@ -29,5 +29,5 @@ export interface LiveStateInfoProps {
|
|
|
29
29
|
*
|
|
30
30
|
* See examples/ directory for usage examples.
|
|
31
31
|
*/
|
|
32
|
-
export declare function
|
|
33
|
-
//# sourceMappingURL=
|
|
32
|
+
export declare function LiveStatePromo({ data, trackingConfig, defaultVariant, onClose, isMobile: isMobileProp, onCtaClick, }: LiveStatePromoProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
//# sourceMappingURL=LiveStatePromo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveStatePromo.d.ts","sourceRoot":"","sources":["../../../src/components/LiveStatePromo.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAO7E,MAAM,WAAW,mBAAmB;IAClC,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,SAAS,KAAK,IAAI,CAAC;CACvC;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,cAAuB,EACvB,OAAO,EACP,QAAQ,EAAE,YAAY,EACtB,UAAU,GACX,EAAE,mBAAmB,2CAmKrB"}
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
1
2
|
import { LiveStateRendererProps } from '../types';
|
|
2
|
-
|
|
3
|
-
* LiveStateRenderer
|
|
4
|
-
*
|
|
5
|
-
* Main component that validates payload, filters by context, and renders
|
|
6
|
-
* the appropriate visual component (Alert or Info) based on type.
|
|
7
|
-
* Handles closable notifications via useClosable when closable is configured.
|
|
8
|
-
*
|
|
9
|
-
* See examples/ directory for usage examples.
|
|
10
|
-
*/
|
|
11
|
-
export declare function LiveStateRenderer({ data, loading, trackingConfig, allowedContexts, defaultVariant, isMobile, onCtaClick, }: LiveStateRendererProps): import("react/jsx-runtime").JSX.Element | null;
|
|
3
|
+
export declare function LiveStateRenderer({ data, loading, trackingConfig, allowedContexts, defaultVariant, isMobile, onCtaClick, }: LiveStateRendererProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | null;
|
|
12
4
|
//# sourceMappingURL=LiveStateRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveStateRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/LiveStateRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"LiveStateRenderer.d.ts","sourceRoot":"","sources":["../../../src/components/LiveStateRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,UAAU,CAAC;AAMvE,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EACf,cAAc,EACd,QAAQ,EACR,UAAU,GACX,EAAE,sBAAsB,iFA0ExB"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export type { LiveStateResponse, LiveStateFetcher, CtaConfig, BaseTrackingConfig, TrackingConfig, TrackingProperties, TrackingValue, AnalyticsConfig, LogLevel, LiveStateProviderProps, LiveStateRendererProps, } from './types';
|
|
1
|
+
export type { LiveStateResponse, LiveStateModel, LiveStateFetcher, CtaConfig, BaseTrackingConfig, TrackingConfig, TrackingProperties, TrackingValue, AnalyticsConfig, LogLevel, LiveStateProviderProps, LiveStateRendererProps, } from './types';
|
|
2
2
|
export { LiveStateProvider } from './providers/LiveStateProvider';
|
|
3
3
|
export { useLiveState } from './hooks/useLiveState';
|
|
4
4
|
export { useTrackEvent } from './hooks/useTrackEvent';
|
|
5
5
|
export { LiveStateRenderer } from './components/LiveStateRenderer';
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
6
|
+
export { LiveStateMessage } from './components/LiveStateMessage';
|
|
7
|
+
export { LiveStatePromo } from './components/LiveStatePromo';
|
|
8
8
|
export { handleCtaClick } from './utils/cta';
|
|
9
9
|
export { trackEvent } from './utils/analytics';
|
|
10
10
|
export { LIVE_STATE_STORAGE_KEY } from './utils/closable-storage';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAY,MAAM,UAAU,CAAC;AAIhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAMrE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACzC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAY,MAAM,UAAU,CAAC;AAIhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAMrE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,iBAAiB,CAAM,GACzC,iBAAiB,CAcnB;AAMD,UAAU,0BAA0B;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,qEAAqE;IACrE,SAAS,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,8BAA8B;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACxE;AAkBD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,SAAgB,EAChB,SAAiB,EACjB,OAAe,EACf,OAAO,GACR,EAAE,0BAA0B,2CA8B5B;AASD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE;IACT,SAAS,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;;;;;mBADY,OAAO,CAAC,IAAI,CAAC;EAUhC"}
|
|
@@ -27,20 +27,24 @@ export interface CtaConfig {
|
|
|
27
27
|
/** Pre-formatted WhatsApp message (only if type='whatsapp') */
|
|
28
28
|
whatsappMessage?: string;
|
|
29
29
|
}
|
|
30
|
+
/** Layout model — determines which component renders */
|
|
31
|
+
export type LiveStateModel = 'message' | 'promo';
|
|
30
32
|
/**
|
|
31
33
|
* Live State Response from backend API
|
|
32
34
|
*/
|
|
33
35
|
export interface LiveStateResponse {
|
|
34
36
|
/** Business context (charge, cart, awareness, etc) */
|
|
35
37
|
context: string;
|
|
36
|
-
/**
|
|
38
|
+
/** Layout model — determines which component renders */
|
|
39
|
+
model: LiveStateModel;
|
|
40
|
+
/** Visual component type — drives appearance within the model */
|
|
37
41
|
type: 'alert' | 'warning' | 'info';
|
|
38
42
|
/** Title (already interpolated by backend) */
|
|
39
43
|
title: string;
|
|
40
44
|
/** Message (already interpolated by backend) */
|
|
41
45
|
message: string;
|
|
42
|
-
/** Call-to-action configuration */
|
|
43
|
-
cta
|
|
46
|
+
/** Call-to-action configuration. Optional — when omitted, the notification renders without a CTA button/link. */
|
|
47
|
+
cta?: CtaConfig;
|
|
44
48
|
/** Campaign ID (indicates this is a campaign) */
|
|
45
49
|
campaignId?: string;
|
|
46
50
|
/** Group/theme variation (e.g., 'abandoned', 'doubts' for cart) */
|
|
@@ -202,6 +206,7 @@ export interface LiveStateProviderProps {
|
|
|
202
206
|
* disabled={import.meta.env.PROD === false}
|
|
203
207
|
* mockData={import.meta.env.PROD ? undefined : {
|
|
204
208
|
* context: 'awareness',
|
|
209
|
+
* model: 'promo',
|
|
205
210
|
* type: 'info',
|
|
206
211
|
* title: 'Test notification',
|
|
207
212
|
* message: 'Testing locally.',
|
|
@@ -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;AAEvC;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IAEd,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;;;OAOG;IACH,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAE3C,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAEhB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/dist/testing.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
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`,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;
|
|
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 () =>\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,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"}
|
|
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"}
|