runid-lys 0.3.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-03-13
11
+
12
+ ### Added
13
+
14
+ - `updatePageParams` method in `PageContextProvider` to merge additional params into the current page context without replacing existing ones
15
+
16
+ ## [0.3.1] - 2026-03-10
17
+
18
+ ### Fixed
19
+
20
+ - `ClientProvider` no longer syncs clientId to URL when user is disconnected, preventing interference with login redirect navigation
21
+
10
22
  ## [0.3.0] - 2026-03-07
11
23
 
12
24
  ### Added
@@ -78,6 +78,8 @@ const usePageContext = () => {
78
78
  context: DEFAULT_CONTEXT,
79
79
  setPageContext: () => {
80
80
  },
81
+ updatePageParams: () => {
82
+ },
81
83
  clearPageContext: () => {
82
84
  }
83
85
  }), []);
@@ -91,14 +93,21 @@ const PageContextProvider = ({ children }) => {
91
93
  const setPageContext = useCallback((pageName, params = {}) => {
92
94
  setContext({ pageName, params });
93
95
  }, []);
96
+ const updatePageParams = useCallback((additionalParams) => {
97
+ setContext((prev) => ({
98
+ ...prev,
99
+ params: { ...prev.params, ...additionalParams }
100
+ }));
101
+ }, []);
94
102
  const clearPageContext = useCallback(() => {
95
103
  setContext({ pageName: null, params: {} });
96
104
  }, []);
97
105
  const contextValue = useMemo(() => ({
98
106
  context,
99
107
  setPageContext,
108
+ updatePageParams,
100
109
  clearPageContext
101
- }), [context, setPageContext, clearPageContext]);
110
+ }), [context, setPageContext, updatePageParams, clearPageContext]);
102
111
  return /* @__PURE__ */ jsx(PageContextContext.Provider, { value: contextValue, children });
103
112
  };
104
113
  const RefreshSignalContext = createContext({ nodes: [], version: 0 });
@@ -2100,13 +2109,13 @@ const ClientProvider = ({ children }) => {
2100
2109
  }
2101
2110
  }, [user, updateUrl]);
2102
2111
  useEffect(() => {
2103
- if (isLocked) return;
2112
+ if (isLocked || !user) return;
2104
2113
  if (selectedClientId) {
2105
2114
  updateUrl({ [URL_PARAM_KEY]: selectedClientId });
2106
2115
  } else {
2107
2116
  updateUrl({ [URL_PARAM_KEY]: null });
2108
2117
  }
2109
- }, [selectedClientId, location.pathname, isLocked, updateUrl]);
2118
+ }, [selectedClientId, location.pathname, isLocked, user, updateUrl]);
2110
2119
  const clientId = useMemo(() => {
2111
2120
  if (user == null ? void 0 : user.clientId) {
2112
2121
  return user.clientId;
@@ -2169,4 +2178,4 @@ export {
2169
2178
  useWebserviceAccess as x,
2170
2179
  webserviceAccessProviderConfig as y
2171
2180
  };
2172
- //# sourceMappingURL=constants-DEt8avUj.js.map
2181
+ //# sourceMappingURL=constants-U3LBcAa7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-U3LBcAa7.js","sources":["../src/providers/ErrorBoundaryProvider/index.tsx","../src/providers/FilterLabelsProvider/hooks.ts","../src/providers/FilterLabelsProvider/index.tsx","../src/providers/PageContextProvider/hooks.ts","../src/providers/PageContextProvider/index.tsx","../src/providers/LysQueryProvider/RefreshSignalContext.ts","../src/providers/ChatbotProvider/index.tsx","../src/providers/UrlQueriesProvider/hooks.ts","../src/providers/UrlQueriesProvider/index.tsx","../src/providers/AlertMessageProvider/hooks.ts","../src/providers/AlertMessageProvider/index.tsx","../src/providers/LocaleProvider/index.tsx","../src/providers/LysDialogProvider/hooks.ts","../src/providers/LysDialogProvider/reducer.ts","../src/providers/LysDialogProvider/index.tsx","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderLogoutMutation.graphql.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderLoginMutation.graphql.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderRefreshMutation.graphql.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderQuery.graphql.ts","../src/providers/LocaleProvider/hooks.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserFragment_user.graphql.ts","../src/providers/ConnectedUserProvider/ConnectedUserFragment.ts","../src/providers/ConnectedUserProvider/index.tsx","../src/providers/WebserviceAccessProvider/__generated__/WebserviceAccessProviderQuery.graphql.ts","../src/providers/WebserviceAccessProvider/hooks.ts","../src/providers/WebserviceAccessProvider/translations.ts","../src/providers/WebserviceAccessProvider/index.tsx","../src/providers/SignalProvider/hooks.ts","../src/providers/SignalProvider/index.tsx","../src/providers/LysQueryProvider/hooks.ts","../src/providers/hooks/usePermissionCheck.ts","../src/providers/LysQueryProvider/LysLoadingContext.ts","../src/providers/LysQueryProvider/index.tsx","../src/providers/LysMutationProvider/hooks.ts","../src/providers/LysMutationProvider/index.tsx","../src/providers/ClientProvider/hooks.ts","../src/providers/ClientProvider/index.tsx","../src/providers/LysQueryProvider/constants.ts"],"sourcesContent":["import React, {ReactNode} from \"react\";\n\ninterface Props {\n onError?: ((error: Error) => void) | undefined\n children: ReactNode\n fallback?: ReactNode\n}\n\ninterface State {\n hasError: boolean\n error: Error | null\n}\n\n/**\n * Error boundary component\n * Catches React rendering errors and calls onError callback\n *\n * Important: onError is called in componentDidCatch (not render) to allow\n * state updates in the callback without React warnings.\n */\nclass ErrorBoundaryProvider extends React.Component<Props, State> {\n state: State = {hasError: false, error: null};\n\n static getDerivedStateFromError(error: Error): State {\n // Update state so next render shows fallback UI\n return {hasError: true, error};\n }\n\n componentDidCatch(error: Error, _errorInfo: React.ErrorInfo) {\n // Call onError callback for side effects (logging, state updates, etc.)\n // This is the correct place for side effects, not render()\n if (this.props.onError) {\n this.props.onError(error);\n }\n }\n\n render() {\n const {children, fallback = null} = this.props;\n const {hasError} = this.state;\n\n // When there's an error, render fallback (or null) instead of children\n // This prevents the infinite loop where children keep throwing\n if (hasError) {\n return fallback;\n }\n\n return children;\n }\n}\n\nexport default ErrorBoundaryProvider\n","import {createContext, useContext} from \"react\";\n\n/**\n * Filter labels context type\n */\ninterface FilterLabelsContextType {\n /**\n * Set a label for a filter value\n */\n setLabel: (key: string, label: string) => void;\n\n /**\n * Get a label for a filter value (returns value if not found)\n */\n getLabel: (key: string) => string;\n}\n\n/**\n * Filter labels context\n */\nconst FilterLabelsContext = createContext<FilterLabelsContextType>({\n setLabel: () => {\n console.warn(\"FilterLabelsProvider not initialized: setLabel\");\n },\n getLabel: (key: string) => key\n});\n\n/**\n * Hook to access filter labels context\n */\nfunction useFilterLabels() {\n return useContext(FilterLabelsContext);\n}\n\nexport {\n FilterLabelsContext,\n useFilterLabels\n};\n","import React from \"react\";\nimport {FilterLabelsContext} from \"./hooks\";\n\n/**\n * LocalStorage key for persisting filter labels\n */\nconst STORAGE_KEY = \"lys-filter-labels\";\n\n/**\n * FilterLabelsProvider props\n */\ninterface FilterLabelsProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Load labels from localStorage\n */\nconst loadFromStorage = (): Record<string, string> => {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n return stored ? JSON.parse(stored) : {};\n } catch {\n return {};\n }\n};\n\n/**\n * Save a label to localStorage\n */\nconst saveLabel = (key: string, label: string): void => {\n try {\n const labels = loadFromStorage();\n labels[key] = label;\n localStorage.setItem(STORAGE_KEY, JSON.stringify(labels));\n } catch {\n // Ignore storage errors (quota exceeded, etc.)\n }\n};\n\n/**\n * Get a label from localStorage (returns the key itself if not found)\n */\nconst getLabel = (key: string): string => {\n const labels = loadFromStorage();\n return labels[key] || key;\n};\n\n/**\n * FilterLabelsProvider component\n *\n * Global provider that stores display labels for filter values.\n * Used to show human-readable labels in active filter badges\n * instead of raw values (IDs, codes, etc.).\n *\n * Labels are stored directly in localStorage (no React state).\n *\n * Usage:\n * - SelectElement calls setLabel(value, label) when selection changes\n * - SearchFilterFeature calls getLabel(value) to display the label\n */\nconst FilterLabelsProvider: React.FC<FilterLabelsProviderProps> = ({children}) => {\n return (\n <FilterLabelsContext.Provider value={{setLabel: saveLabel, getLabel}}>\n {children}\n </FilterLabelsContext.Provider>\n );\n};\n\nFilterLabelsProvider.displayName = \"FilterLabelsProvider\";\n\nexport default FilterLabelsProvider;\n","import {createContext, useContext, useMemo} from \"react\";\nimport {PageContext, PageContextValue} from \"./types\";\n\nexport const PageContextContext = createContext<PageContextValue | null>(null);\n\n/**\n * Default context value when PageContextProvider is not in the tree.\n * All functions are no-ops, allowing the app to work without the provider.\n */\nconst DEFAULT_CONTEXT: PageContext = {\n pageName: null,\n params: {}\n};\n\n/**\n * Hook to access page context.\n * Returns a working context even if PageContextProvider is not mounted.\n * This allows the app to function without the provider (graceful degradation).\n */\nexport const usePageContext = (): PageContextValue => {\n const context = useContext(PageContextContext);\n\n // Memoize fallback to avoid creating new objects on each render\n const fallback = useMemo<PageContextValue>(() => ({\n context: DEFAULT_CONTEXT,\n setPageContext: () => {},\n updatePageParams: () => {},\n clearPageContext: () => {}\n }), []);\n\n return context ?? fallback;\n};\n","import React, {useState, useCallback, useMemo} from \"react\";\nimport {PageContextContext} from \"./hooks\";\nimport {PageContext, PageContextParamValue} from \"./types\";\n\ninterface PageContextProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * PageContextProvider component\n *\n * Provides page context tracking for chatbot context-aware features:\n * - Current page name (e.g., \"FinancialDashboardPage\")\n * - Page params (e.g., {companyId: \"123\", year: 2024})\n *\n * This context is sent to the chatbot to:\n * - Filter available tools by page\n * - Inject params into mutations for security\n * - Reduce AI hallucinations by providing explicit context\n *\n * Place this provider above ChatbotProvider in the component tree.\n */\nconst PageContextProvider: React.FC<PageContextProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [context, setContext] = useState<PageContext>({\n pageName: null,\n params: {}\n });\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Set the current page context (pageName + params).\n * Called by RouteProvider when route or URL params change.\n */\n const setPageContext = useCallback((\n pageName: string,\n params: Record<string, PageContextParamValue> = {}\n ) => {\n setContext({pageName, params});\n }, []);\n\n /**\n * Merge additional params into the current page context.\n * Useful for components that need to add dynamic state (e.g., live slider values)\n * without overwriting the base params set by RouteProvider.\n */\n const updatePageParams = useCallback((\n additionalParams: Record<string, PageContextParamValue>\n ) => {\n setContext(prev => ({\n ...prev,\n params: {...prev.params, ...additionalParams}\n }));\n }, []);\n\n /**\n * Clear the page context.\n */\n const clearPageContext = useCallback(() => {\n setContext({pageName: null, params: {}});\n }, []);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n const contextValue = useMemo(() => ({\n context,\n setPageContext,\n updatePageParams,\n clearPageContext\n }), [context, setPageContext, updatePageParams, clearPageContext]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <PageContextContext.Provider value={contextValue}>\n {children}\n </PageContextContext.Provider>\n );\n};\n\nexport default PageContextProvider;\n","import {createContext, useContext} from \"react\";\n\nexport interface RefreshSignal {\n nodes: string[];\n version: number;\n}\n\nconst RefreshSignalContext = createContext<RefreshSignal>({nodes: [], version: 0});\n\nexport const useRefreshSignal = (): RefreshSignal => {\n return useContext(RefreshSignalContext);\n};\n\nexport default RefreshSignalContext;\n","import React, {useState, useCallback, useMemo} from \"react\";\nimport {ChatbotContext} from \"./hooks\";\nimport {ChatMessage, RefreshSignal} from \"./types\";\nimport RefreshSignalContext from \"../LysQueryProvider/RefreshSignalContext\";\n\ninterface ChatbotProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * ChatbotProvider component\n *\n * Provides global chatbot state management:\n * - Message history persistence across page navigation\n * - Conversation ID tracking\n * - Chatbot mode state (open/closed)\n *\n * Place this provider high in the component tree (above RouteProvider)\n * to ensure state persists across route changes.\n */\nconst ChatbotProvider: React.FC<ChatbotProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [conversationId, setConversationId] = useState<string | null>(null);\n const [isChatbotMode, setIsChatbotMode] = useState<boolean>(false);\n const [isChatbotEnabled, setIsChatbotEnabled] = useState<boolean>(true);\n const [isStreaming, setIsStreaming] = useState<boolean>(false);\n const [refreshSignal, setRefreshSignal] = useState<RefreshSignal>({nodes: [], version: 0});\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Add a single message to the conversation\n */\n const addMessage = useCallback((message: ChatMessage) => {\n setMessages(prev => [...prev, message]);\n }, []);\n\n /**\n * Append content to the last assistant message (for streaming)\n */\n const updateLastMessage = useCallback((contentDelta: string) => {\n setMessages(prev => {\n if (prev.length === 0) return prev;\n const last = prev[prev.length - 1];\n if (last.role !== \"assistant\") return prev;\n const updated = [...prev];\n updated[updated.length - 1] = {...last, content: last.content + contentDelta};\n return updated;\n });\n }, []);\n\n /**\n * Clear the conversation and reset state\n */\n const clearConversation = useCallback(() => {\n setMessages([]);\n setConversationId(null);\n }, []);\n\n /**\n * Trigger a refresh signal for the specified node types\n * LysQueryProvider instances listening to these nodes will refetch their data\n */\n const triggerRefresh = useCallback((nodes: string[]) => {\n setRefreshSignal(prev => ({\n nodes,\n version: prev.version + 1\n }));\n }, []);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n const contextValue = useMemo(() => ({\n messages,\n conversationId,\n isChatbotMode,\n isChatbotEnabled,\n isStreaming,\n refreshSignal,\n setMessages,\n setConversationId,\n setIsChatbotMode,\n setIsChatbotEnabled,\n setIsStreaming,\n addMessage,\n updateLastMessage,\n clearConversation,\n triggerRefresh\n }), [messages, conversationId, isChatbotMode, isChatbotEnabled, isStreaming, refreshSignal, addMessage, updateLastMessage, clearConversation, triggerRefresh]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <ChatbotContext.Provider value={contextValue}>\n <RefreshSignalContext.Provider value={refreshSignal}>\n {children}\n </RefreshSignalContext.Provider>\n </ChatbotContext.Provider>\n );\n};\n\nexport default ChatbotProvider;\n","import {createContext, useContext} from \"react\";\nimport {UrlQueryValue} from \"./types\";\n\nconst UrlQueriesContext = createContext<{\n hasStagedChanges: boolean;\n appliedParams: URLSearchParams;\n stagedParams: {[key: string]: UrlQueryValue};\n stage: (key: string, value: UrlQueryValue) => void;\n edit: (key: string, value: UrlQueryValue) => void;\n update: (data: {[key: string]: UrlQueryValue}) => void;\n apply: () => void;\n}>({\n hasStagedChanges: false,\n appliedParams: new URLSearchParams(),\n stagedParams: {},\n stage: () => console.error(\"stage not implemented\"),\n edit: () => console.error(\"edit not implemented\"),\n update: () => console.error(\"update not implemented\"),\n apply: () => console.error(\"apply not implemented\")\n});\n\n/**\n * Hook to access URL query parameters with staging support\n *\n * Features:\n * - appliedParams: Current URL search params\n * - stagedParams: Staged changes not yet applied to URL\n * - edit(): Apply a single change immediately to URL\n * - stage(): Stage a change without updating URL\n * - apply(): Apply all staged changes at once\n * - update(): Update multiple params directly\n * - hasStagedChanges: Whether there are unapplied staged changes\n */\nconst useUrlQueries = () => {\n return useContext(UrlQueriesContext);\n};\n\nexport {\n UrlQueriesContext,\n useUrlQueries,\n};\n","import * as React from \"react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState\n} from \"react\";\nimport {useSearchParams} from \"react-router-dom\";\nimport {UrlQueriesContext} from \"./hooks\";\nimport {UrlQueriesProviderProps, UrlQueryValue} from \"./types\";\n\n/**\n * UrlQueriesProvider - Manages URL query parameters with staging support\n *\n * Features:\n * - Synchronizes URL search params with React state\n * - Supports staged changes via stagedParams\n * - Type conversion (string → number/boolean)\n * - Batch updates with apply()\n *\n * Use cases:\n * - Filter bars: Stage multiple filter changes, apply all at once\n * - Form state: Keep form state in URL for sharing/bookmarking\n * - Pagination: Track page/limit in URL\n */\nconst UrlQueriesProvider: React.ComponentType<UrlQueriesProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const [searchParams, setSearchParams] = useSearchParams();\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [initialized, setInitialized] = useState<boolean>(false);\n const [stagedParams, setStagedParams] = useState<{[key: string]: UrlQueryValue}>({});\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n /**\n * Check if staged params differ from current URL\n */\n const hasStagedChanges: boolean = useMemo(() => {\n return Object.keys(stagedParams).some(key =>\n stagedParams[key]?.toString() !== searchParams.get(key)\n );\n }, [searchParams, stagedParams]);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Stage a change without updating URL\n * Useful for filter bars where user configures multiple filters before applying\n */\n const stage = useCallback((key: string, value: UrlQueryValue) => {\n setStagedParams(prev => {\n if (prev[key]?.toString() === value?.toString()) {\n return prev;\n }\n return {...prev, [key]: value};\n });\n }, []);\n\n /**\n * Apply change immediately to URL\n */\n const edit = useCallback((key: string, value: UrlQueryValue) => {\n stage(key, value);\n setSearchParams(prev => {\n if (value !== undefined && value !== null) {\n prev.set(key, value.toString());\n } else {\n prev.delete(key);\n }\n return prev;\n });\n }, [stage, setSearchParams]);\n\n /**\n * Apply all staged changes to URL\n */\n const apply = useCallback(() => {\n const newSearchParams = new URLSearchParams();\n\n Object.entries(stagedParams).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n newSearchParams.set(key, value.toString());\n }\n });\n\n setSearchParams(newSearchParams);\n }, [stagedParams, setSearchParams]);\n\n /**\n * Batched update: accumulates changes from multiple update() calls\n * within the same microtask and flushes them in a single setSearchParams call.\n *\n * Why batching is needed:\n * react-router's setSearchParams does NOT chain functional updates like React's\n * setState — each call gets the same `prev` snapshot. When multiple components\n * call update() in the same effect cycle (e.g. ClientProvider sets clientId while\n * DashboardFiltersFeature resets companyId), the last call would overwrite the first.\n * Batching via queueMicrotask merges all pending changes into one setSearchParams call.\n */\n const pendingUpdatesRef = useRef<{[key: string]: UrlQueryValue}>({});\n const flushScheduledRef = useRef(false);\n\n const update = useCallback((data: {[key: string]: UrlQueryValue}) => {\n Object.assign(pendingUpdatesRef.current, data);\n\n if (!flushScheduledRef.current) {\n flushScheduledRef.current = true;\n queueMicrotask(() => {\n flushScheduledRef.current = false;\n const pending = {...pendingUpdatesRef.current};\n pendingUpdatesRef.current = {};\n\n setSearchParams(prev => {\n const next = new URLSearchParams(prev);\n Object.entries(pending).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n next.set(key, value.toString());\n } else {\n next.delete(key);\n }\n });\n return next;\n });\n });\n }\n }, [setSearchParams]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Initialize stagedParams from URL on mount\n * Converts string values to appropriate types (number, boolean)\n */\n useEffect(() => {\n const newTmpParameters: {[key: string]: UrlQueryValue} = {};\n\n searchParams.forEach((value, key) => {\n // Convert to number if possible\n if (!isNaN(+value)) {\n newTmpParameters[key] = Number(value);\n }\n // Convert to boolean if \"true\" or \"false\"\n else if (value === \"true\" || value === \"false\") {\n newTmpParameters[key] = value === \"true\";\n }\n // Keep as string\n else {\n newTmpParameters[key] = value;\n }\n });\n\n if (Object.keys(newTmpParameters).length) {\n setStagedParams(newTmpParameters);\n }\n\n setInitialized(true);\n }, [searchParams]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <UrlQueriesContext.Provider\n value={{\n hasStagedChanges,\n appliedParams: searchParams,\n stagedParams,\n stage,\n edit,\n update,\n apply\n }}\n >\n {initialized && children}\n </UrlQueriesContext.Provider>\n );\n};\n\nexport default UrlQueriesProvider;\n","import {createContext, useContext} from \"react\";\nimport {AlertMessageInterface} from \"./types\";\n\n/**\n * Alert message context\n */\nconst AlertMessageContext = createContext<{\n merge(messages: AlertMessageInterface[]): void\n}>({\n merge: () => {\n console.warn(\"AlertMessageProvider not initialized\")\n }\n});\n\n/**\n * Hook to access alert messages\n */\nfunction useAlertMessages() {\n return useContext(AlertMessageContext)\n}\n\nexport {\n AlertMessageContext,\n useAlertMessages\n}\n","import * as React from \"react\";\nimport {useState, useCallback, useRef} from \"react\";\nimport {\n AlertMessageProviderProps,\n DatedAlertMessageType\n} from \"./types\";\nimport { AlertMessageContext } from \"./hooks\";\n\n/**\n * Alert message provider\n * Manages centralized alert/error display\n *\n * Requires an alertGenerator function to render alerts.\n */\nconst AlertMessageProvider: React.ComponentType<AlertMessageProviderProps> = (\n {\n children,\n alertGenerator,\n }) => {\n\n /*******************************************************************************************************************\n * STATES\n * ****************************************************************************************************************/\n\n const [messages, setMessages] = useState<DatedAlertMessageType[]>([])\n const messageIdCounter = useRef(0);\n\n /*******************************************************************************************************************\n * CALLBACKS\n * ****************************************************************************************************************/\n\n /**\n * Remove a message by index\n */\n const handleRemove = useCallback((index: number) => {\n setMessages(prev => prev.filter((_, i) => i !== index));\n }, []);\n\n /**\n * Merge new messages into the state\n */\n const handleMerge = useCallback((messages_: { text: string; level: string }[]) => {\n if (messages_.length > 0) {\n const datedMessages = messages_.map((message) => {\n // Log to console\n const logMethod = message.level === \"CRITICAL\" || message.level === \"ERROR\"\n ? console.error\n : message.level === \"WARNING\"\n ? console.warn\n : console.log;\n\n logMethod(`[${message.level}]`, message.text);\n\n // Generate unique ID\n messageIdCounter.current += 1;\n const uniqueId = `alert-${Date.now()}-${messageIdCounter.current}`;\n\n return {\n ...message,\n id: uniqueId,\n createdAt: new Date()\n }\n }) as DatedAlertMessageType[];\n setMessages(prev => [...prev, ...datedMessages]);\n }\n }, []);\n\n /*******************************************************************************************************************\n * RENDER\n * ****************************************************************************************************************/\n\n return(\n <>\n <AlertMessageContext.Provider value={{\n merge: handleMerge\n }}>\n {children}\n </AlertMessageContext.Provider>\n {alertGenerator(messages, handleRemove)}\n </>\n );\n};\n\nexport default AlertMessageProvider;\n","import React, {createContext, useState, useCallback, useMemo} from \"react\";\nimport {IntlProvider} from \"react-intl\";\nimport {LocaleProviderProps, LocaleContextInterface} from \"./types\";\n\n/**\n * LocaleProvider context\n */\nexport const LocaleContext = createContext<LocaleContextInterface | undefined>(undefined);\n\n/**\n * LocaleProvider component\n *\n * Wraps IntlProvider and provides a hook to dynamically change locale\n * Used by ConnectedUserProvider to update locale based on user's language preference\n */\nconst LocaleProvider: React.FC<LocaleProviderProps> = ({defaultLocale, messageSources, children}) => {\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [locale, setLocale] = useState<string>(defaultLocale);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Update locale\n */\n const updateLocale = useCallback((newLocale: string) => {\n setLocale(newLocale);\n }, []);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n /**\n * Get messages for the current locale from the provided message sources\n */\n const messages = useMemo(() => {\n return messageSources[locale] || {};\n }, [locale, messageSources]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <LocaleContext.Provider value={{locale, updateLocale}}>\n <IntlProvider locale={locale} messages={messages}>\n {children}\n </IntlProvider>\n </LocaleContext.Provider>\n );\n};\n\nexport default LocaleProvider;\n","import { createContext, useCallback, useContext, useEffect, useMemo, useRef } from \"react\"\nimport { ComponentType } from \"react\"\nimport { LysDialogContextValue, DialogSize, DialogPlacement } from \"./types\"\n\n/**\n * Default context value with error handlers\n */\nconst defaultContextValue: LysDialogContextValue = {\n current: null,\n stack: [],\n isOpen: false,\n canGoBack: false,\n open: () => {\n console.error(\"useLysDialog: open() called outside of LysDialogProvider\")\n },\n update: () => {\n console.error(\"useLysDialog: update() called outside of LysDialogProvider\")\n },\n close: () => {\n console.error(\"useLysDialog: close() called outside of LysDialogProvider\")\n },\n back: () => {\n console.error(\"useLysDialog: back() called outside of LysDialogProvider\")\n },\n closeAll: () => {\n console.error(\"useLysDialog: closeAll() called outside of LysDialogProvider\")\n },\n register: () => {\n console.error(\"useLysDialog: register() called outside of LysDialogProvider\")\n return () => {}\n },\n getExpectedKeys: () => {\n console.error(\"useLysDialog: getExpectedKeys() called outside of LysDialogProvider\")\n return []\n }\n}\n\n/**\n * Dialog context\n */\nexport const LysDialogContext = createContext<LysDialogContextValue>(defaultContextValue)\n\n/**\n * Hook to access dialog context\n *\n * Usage:\n * ```tsx\n * const dialog = useLysDialog()\n *\n * // Open a dialog\n * dialog.open({\n * uniqueKey: \"my-dialog\",\n * title: \"My Dialog\",\n * body: <div>Content</div>\n * })\n *\n * // Close current dialog (return to previous)\n * dialog.close()\n *\n * // Close all dialogs\n * dialog.closeAll()\n * ```\n */\nexport const useLysDialog = (): LysDialogContextValue => {\n return useContext(LysDialogContext)\n}\n\n/**\n * Configuration for useDialogWithUpdates hook\n */\nexport interface UseDialogWithUpdatesConfig<P extends Record<string, any>> {\n /**\n * Unique key for the dialog\n */\n uniqueKey: string\n\n /**\n * Dialog title\n */\n title: string\n\n /**\n * Body component (not JSX, the component itself)\n */\n body: ComponentType<P>\n\n /**\n * Props to pass to the body component\n * These will be automatically updated when they change\n */\n bodyProps: P\n\n /**\n * Dependencies array to trigger bodyProps updates\n * Only when these values change will the dialog be updated\n * This avoids infinite loops caused by unstable object references\n *\n * @example\n * // Update only when data or isLoading changes\n * deps: [data, isLoading]\n */\n deps?: React.DependencyList\n\n /**\n * Dialog size\n * @default \"md\"\n */\n size?: DialogSize\n\n /**\n * Dialog placement\n * @default \"end\"\n */\n placement?: DialogPlacement\n\n /**\n * Backdrop behavior\n * @default true\n */\n backdrop?: boolean | \"static\"\n\n /**\n * Enable URL synchronization\n * @default true\n */\n syncWithUrl?: boolean\n}\n\n/**\n * Return type for useDialogWithUpdates hook\n */\nexport interface UseDialogWithUpdatesReturn {\n /**\n * Open the dialog\n */\n open: () => void\n\n /**\n * Close the dialog\n */\n close: () => void\n\n /**\n * The unique key of the dialog\n */\n uniqueKey: string\n\n /**\n * Whether this dialog is currently open\n */\n isOpen: boolean\n}\n\n/**\n * Hook for dialog with automatic updates\n *\n * This hook encapsulates the pattern of opening a dialog and automatically\n * updating its bodyProps when they change. It eliminates the need to manually\n * write useEffect for dialog.update().\n *\n * Usage:\n * ```tsx\n * const myDialog = useDialogWithUpdates({\n * uniqueKey: \"my-dialog\",\n * title: \"My Dialog\",\n * body: MyDialogBody,\n * bodyProps: { data, isLoading, onSubmit }\n * });\n *\n * // Open the dialog\n * <button onClick={myDialog.open}>Open</button>\n *\n * // The dialog will automatically update when bodyProps change\n * ```\n */\nexport function useDialogWithUpdates<P extends Record<string, any>>(\n config: UseDialogWithUpdatesConfig<P>\n): UseDialogWithUpdatesReturn {\n const {open, update, close, current} = useLysDialog();\n const {uniqueKey, title, body, bodyProps, deps, size = \"md\", placement = \"end\", backdrop, syncWithUrl} = config;\n\n /**\n * Store bodyProps in a ref to always have the latest value\n * without causing re-renders in useCallback dependencies\n */\n const bodyPropsRef = useRef(bodyProps);\n bodyPropsRef.current = bodyProps;\n\n /**\n * Check if this dialog is currently open\n */\n const isOpen = useMemo(() => current?.uniqueKey === uniqueKey, [current?.uniqueKey, uniqueKey]);\n\n /**\n * Track if dialog was opened to prevent updates before first open\n */\n const wasOpenedRef = useRef(false);\n\n /**\n * Open the dialog\n */\n const handleOpen = useCallback(() => {\n wasOpenedRef.current = true;\n open({\n uniqueKey,\n title,\n body,\n bodyProps: bodyPropsRef.current,\n size,\n placement,\n backdrop,\n syncWithUrl\n });\n }, [open, uniqueKey, title, body, size, placement, backdrop, syncWithUrl]);\n\n /**\n * Close the dialog\n */\n const handleClose = useCallback(() => {\n close();\n }, [close]);\n\n /**\n * Auto-update bodyProps when deps change (only if dialog is currently open)\n * Uses wasOpenedRef to prevent updates before the dialog was ever opened\n * Uses ref to get latest bodyProps without causing infinite loops\n *\n * If deps is not provided, no automatic updates will occur\n */\n useEffect(() => {\n if (isOpen && wasOpenedRef.current) {\n update(uniqueKey, {bodyProps: bodyPropsRef.current});\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen, uniqueKey, update, ...(deps || [])]);\n\n return {\n open: handleOpen,\n close: handleClose,\n uniqueKey,\n isOpen\n };\n}","import { DialogState, DialogAction } from \"./types\"\n\n/**\n * Initial state for dialog reducer\n */\nexport const initialDialogState: DialogState = {\n stack: []\n}\n\n/**\n * Dialog reducer to manage stack of dialogs\n *\n * Actions:\n * - INIT: Initialize stack from URL (used on mount)\n * - PUSH: Add a new dialog to the stack\n * - POP: Remove the last dialog from the stack (back button)\n * - CLEAR: Remove all dialogs from the stack (close all)\n * - UPDATE: Update props or title of an existing dialog\n */\nexport function dialogReducer(state: DialogState, action: DialogAction): DialogState {\n switch (action.type) {\n case \"INIT\":\n // Initialize stack (used when restoring from URL)\n return {\n ...state,\n stack: action.payload\n }\n\n case \"PUSH\":\n // Add new dialog to stack\n return {\n ...state,\n stack: [...state.stack, action.payload]\n }\n\n case \"POP\":\n // Remove last dialog from stack\n if (state.stack.length === 0) {\n return state\n }\n return {\n ...state,\n stack: state.stack.slice(0, -1)\n }\n\n case \"CLEAR\":\n // Remove all dialogs\n return {\n ...state,\n stack: []\n }\n\n case \"UPDATE\":\n // Update an existing dialog's props, title, or loading state\n return {\n ...state,\n stack: state.stack.map(dialog => {\n if (dialog.uniqueKey === action.payload.uniqueKey) {\n return {\n ...dialog,\n ...(action.payload.title !== undefined && { title: action.payload.title }),\n ...(action.payload.bodyProps !== undefined && { bodyProps: action.payload.bodyProps }),\n ...(action.payload.loading !== undefined && { loading: action.payload.loading })\n }\n }\n return dialog\n })\n }\n\n default:\n return state\n }\n}","import { ComponentType, useCallback, useEffect, useMemo, useReducer, useRef } from \"react\"\nimport { LysDialogContext } from \"./hooks\"\nimport { DialogComponentRefInterface, DialogConfig, DialogUpdatePayload, LysDialogProviderProps } from \"./types\"\nimport { dialogReducer, initialDialogState } from \"./reducer\"\nimport { useUrlQueries } from \"../UrlQueriesProvider/hooks\"\n\nconst DIALOG_STACK_PARAM = \"dStack\"\n\n/**\n * Check if value is a React component (function, class, forwardRef, memo, etc.)\n * NOT a React element (JSX)\n */\nconst isReactComponent = (value: unknown): value is ComponentType<any> => {\n // Function component or class component\n if (typeof value === 'function') return true\n\n // forwardRef, memo, lazy components are objects with $$typeof\n // but we need to exclude React elements which also have $$typeof\n if (\n typeof value === 'object' &&\n value !== null &&\n '$$typeof' in value\n ) {\n const symbolValue = (value as { $$typeof: symbol }).$$typeof\n\n // React elements have Symbol.for('react.element') - these are NOT components\n // They should be rendered as-is with <>{body}</>\n if (symbolValue === Symbol.for('react.element')) {\n return false\n }\n\n // forwardRef has Symbol.for('react.forward_ref')\n // memo has Symbol.for('react.memo')\n // lazy has Symbol.for('react.lazy')\n // These ARE components that need to be instantiated\n return true\n }\n\n return false\n}\n\n/**\n * DialogChild component\n * Renders the dialog body, handling both ReactNode and ComponentType\n * If body is a component, it will receive bodyProps\n */\nconst DialogChild: React.FC<{ body: DialogConfig['body']; bodyProps?: Record<string, any> }> = ({ body, bodyProps }) => {\n if (isReactComponent(body)) {\n const Component = body\n return <Component {...(bodyProps || {})} />\n }\n\n // Otherwise, render as ReactNode\n return <>{body}</>\n}\n\n/**\n * LysDialogProvider\n *\n * Provides dialog management with stack support using an injectable dialog component\n *\n * Features:\n * - Stack-based dialogs (dialogs can open on top of each other)\n * - Back button to return to previous dialog\n * - Close button to close all dialogs\n * - Backdrop click closes all dialogs\n * - Optional URL synchronization\n * - Injectable dialog component, loading fallback, back icon, and extra rendering\n */\nconst LysDialogProvider: React.FC<LysDialogProviderProps> = ({\n children,\n syncWithUrl = true,\n dialogComponent: DialogComponent,\n loadingFallback = null,\n backIcon = null,\n renderExtra\n}) => {\n const [state, dispatch] = useReducer(dialogReducer, initialDialogState)\n const urlQueries = syncWithUrl ? useUrlQueries() : null\n const dialogRefs = useRef<Map<string, DialogComponentRefInterface>>(new Map())\n const dialogRegistry = useRef<Map<string, Omit<DialogConfig, 'uniqueKey'>>>(new Map())\n const initializedFromUrl = useRef(false)\n\n // Get current dialog (last in stack)\n const current = useMemo(() => {\n return state.stack.length > 0 ? state.stack[state.stack.length - 1] : null\n }, [state.stack])\n\n // Check if we can go back\n const canGoBack = useMemo(() => {\n return state.stack.length > 1\n }, [state.stack])\n\n // Check if any dialog is open\n const isOpen = useMemo(() => {\n return state.stack.length > 0\n }, [state.stack])\n\n // Open a new dialog (push to stack)\n const open = useCallback((config: DialogConfig) => {\n dispatch({ type: \"PUSH\", payload: config })\n }, [])\n\n // Update an existing dialog's props or title\n const update = useCallback((uniqueKey: string, updates: Omit<DialogUpdatePayload, 'uniqueKey'>) => {\n dispatch({ type: \"UPDATE\", payload: { uniqueKey, ...updates } })\n }, [])\n\n // Close current dialog (pop from stack)\n const close = useCallback(() => {\n dispatch({ type: \"POP\" })\n }, [])\n\n // Alias for close\n const back = close\n\n // Close all dialogs (clear stack)\n const closeAll = useCallback(() => {\n dispatch({ type: \"CLEAR\" })\n }, [])\n\n // Register a dialog for deep linking\n const register = useCallback((uniqueKey: string, config: Omit<DialogConfig, 'uniqueKey'>) => {\n dialogRegistry.current.set(uniqueKey, config)\n\n // Return cleanup function\n return () => {\n dialogRegistry.current.delete(uniqueKey)\n }\n }, [])\n\n // Get expected dialog keys from URL\n const getExpectedKeys = useCallback((): string[] => {\n if (!syncWithUrl || !urlQueries) return []\n\n const stackParam = urlQueries.appliedParams.get(DIALOG_STACK_PARAM)\n if (!stackParam) return []\n\n return stackParam.split(',').filter(Boolean)\n }, [syncWithUrl, urlQueries])\n\n // Show/hide dialog based on current dialog\n useEffect(() => {\n if (current) {\n const ref = dialogRefs.current.get(current.uniqueKey)\n if (ref && ref.shown === null) {\n ref.show()\n }\n }\n }, [current])\n\n // Handle dialog hide event (when user closes it)\n const handleDialogHide = useCallback((uniqueKey: string) => {\n const ref = dialogRefs.current.get(uniqueKey)\n if (ref?.shown === false) {\n // Close all when dialog is manually closed\n closeAll()\n }\n }, [closeAll])\n\n // Sync stack with URL\n useEffect(() => {\n if (!syncWithUrl || !urlQueries) return\n\n // Don't sync URL until initialization is complete\n // This prevents clearing dStack param before we read it on mount\n if (!initializedFromUrl.current) return\n\n const stackParam = urlQueries.appliedParams.get(DIALOG_STACK_PARAM)\n\n // Filter dialogs that want URL synchronization (syncWithUrl !== false)\n const urlSyncedDialogs = state.stack.filter(d => d.syncWithUrl !== false)\n\n if (urlSyncedDialogs.length > 0) {\n // Update URL with current stack keys (only for dialogs with URL sync enabled)\n const stackKeys = urlSyncedDialogs.map(d => d.uniqueKey).join(\",\")\n if (stackParam !== stackKeys) {\n urlQueries.edit(DIALOG_STACK_PARAM, stackKeys)\n }\n } else {\n // Clear URL param when no dialogs want URL sync\n if (stackParam) {\n urlQueries.edit(DIALOG_STACK_PARAM, null)\n }\n }\n }, [state.stack, syncWithUrl, urlQueries])\n\n // Initialize stack from URL on mount\n useEffect(() => {\n if (!syncWithUrl || !urlQueries || initializedFromUrl.current) return\n\n const expectedKeys = getExpectedKeys()\n if (expectedKeys.length === 0) {\n initializedFromUrl.current = true\n return\n }\n\n // Wait for all dialogs to register themselves\n // This happens after children mount\n const checkInterval = setInterval(() => {\n const configs: DialogConfig[] = []\n\n for (const key of expectedKeys) {\n const config = dialogRegistry.current.get(key)\n if (config) {\n configs.push({ uniqueKey: key, ...config })\n }\n }\n\n // If all expected dialogs are registered, initialize stack\n if (configs.length === expectedKeys.length) {\n clearInterval(checkInterval)\n dispatch({ type: \"INIT\", payload: configs })\n initializedFromUrl.current = true\n }\n }, 50)\n\n // Cleanup: stop checking after 2 seconds\n const timeout = setTimeout(() => {\n clearInterval(checkInterval)\n initializedFromUrl.current = true\n }, 2000)\n\n return () => {\n clearInterval(checkInterval)\n clearTimeout(timeout)\n }\n }, [syncWithUrl, urlQueries, getExpectedKeys])\n\n // Context value\n const contextValue = useMemo(() => ({\n current,\n stack: state.stack,\n isOpen,\n canGoBack,\n open,\n update,\n close,\n back,\n closeAll,\n register,\n getExpectedKeys\n }), [current, state.stack, isOpen, canGoBack, open, update, close, back, closeAll, register, getExpectedKeys])\n\n // Build title with optional back button\n const dialogTitle = useMemo(() => {\n if (!current) return null\n\n return (\n <div className=\"d-flex align-items-center w-100\">\n {/* Back button (only visible when stack > 1) */}\n {canGoBack && (\n <button\n type=\"button\"\n className=\"btn btn-link text-decoration-none p-0 me-3\"\n onClick={close}\n aria-label=\"Back to previous dialog\"\n >\n {backIcon}\n </button>\n )}\n {/* Title */}\n <div className=\"flex-grow-1\">\n {current.title}\n </div>\n </div>\n )\n }, [current, canGoBack, close, backIcon])\n\n return (\n <LysDialogContext.Provider value={contextValue}>\n {/* Render only the current dialog */}\n {current && (\n <>\n <DialogComponent\n key={current.uniqueKey}\n ref={(ref) => {\n if (ref) {\n dialogRefs.current.set(current.uniqueKey, ref)\n // Monitor shown state\n if (ref.shown === false) {\n handleDialogHide(current.uniqueKey)\n }\n }\n }}\n id={`lys-dialog-${current.uniqueKey}`}\n title={dialogTitle ?? undefined}\n body={current.loading ? loadingFallback : (\n <DialogChild body={current.body} bodyProps={current.bodyProps} />\n )}\n size={current.size}\n placement={current.placement}\n backdrop={current.backdrop}\n />\n {renderExtra?.(current)}\n </>\n )}\n {children}\n </LysDialogContext.Provider>\n )\n}\n\nexport default LysDialogProvider\n","/**\n * @generated SignedSource<<181ab0892ed33a177cfebc96f2c700aa>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type ConnectedUserProviderLogoutMutation$variables = Record<PropertyKey, never>;\nexport type ConnectedUserProviderLogoutMutation$data = {\n readonly logout: {\n readonly succeed: boolean;\n };\n};\nexport type ConnectedUserProviderLogoutMutation = {\n response: ConnectedUserProviderLogoutMutation$data;\n variables: ConnectedUserProviderLogoutMutation$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LogoutNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"logout\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"succeed\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderLogoutMutation\",\n \"selections\": (v0/*: any*/),\n \"type\": \"Mutation\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderLogoutMutation\",\n \"selections\": (v0/*: any*/)\n },\n \"params\": {\n \"cacheID\": \"5a1db66cb1f48dc468c728f5386b992f\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderLogoutMutation\",\n \"operationKind\": \"mutation\",\n \"text\": \"mutation ConnectedUserProviderLogoutMutation {\\n logout {\\n succeed\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"6b47911be54a6725f5b5744856395d69\";\n\nexport default node;\n","/**\n * @generated SignedSource<<df4394fb203bc9d769f54a19ff82c88b>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type LoginInput = {\n login: string;\n password: string;\n};\nexport type ConnectedUserProviderLoginMutation$variables = {\n inputs: LoginInput;\n};\nexport type ConnectedUserProviderLoginMutation$data = {\n readonly login: {\n readonly accessTokenExpireIn: number;\n readonly success: boolean;\n readonly xsrfToken: string;\n };\n};\nexport type ConnectedUserProviderLoginMutation = {\n response: ConnectedUserProviderLoginMutation$data;\n variables: ConnectedUserProviderLoginMutation$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = [\n {\n \"defaultValue\": null,\n \"kind\": \"LocalArgument\",\n \"name\": \"inputs\"\n }\n],\nv1 = [\n {\n \"alias\": null,\n \"args\": [\n {\n \"kind\": \"Variable\",\n \"name\": \"inputs\",\n \"variableName\": \"inputs\"\n }\n ],\n \"concreteType\": \"LoginNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"login\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"success\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"accessTokenExpireIn\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"xsrfToken\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": (v0/*: any*/),\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderLoginMutation\",\n \"selections\": (v1/*: any*/),\n \"type\": \"Mutation\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": (v0/*: any*/),\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderLoginMutation\",\n \"selections\": (v1/*: any*/)\n },\n \"params\": {\n \"cacheID\": \"99e672b3c15baa2a34b730cc8794299f\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderLoginMutation\",\n \"operationKind\": \"mutation\",\n \"text\": \"mutation ConnectedUserProviderLoginMutation(\\n $inputs: LoginInput!\\n) {\\n login(inputs: $inputs) {\\n success\\n accessTokenExpireIn\\n xsrfToken\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"2a03da8b6fb25fbb7f5171fa53732b31\";\n\nexport default node;\n","/**\n * @generated SignedSource<<ef60feb678597d8526aef19f960a05e6>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type ConnectedUserProviderRefreshMutation$variables = Record<PropertyKey, never>;\nexport type ConnectedUserProviderRefreshMutation$data = {\n readonly refreshAccessToken: {\n readonly accessTokenExpireIn: number;\n readonly success: boolean;\n readonly xsrfToken: string;\n };\n};\nexport type ConnectedUserProviderRefreshMutation = {\n response: ConnectedUserProviderRefreshMutation$data;\n variables: ConnectedUserProviderRefreshMutation$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LoginNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"refreshAccessToken\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"success\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"accessTokenExpireIn\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"xsrfToken\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderRefreshMutation\",\n \"selections\": (v0/*: any*/),\n \"type\": \"Mutation\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderRefreshMutation\",\n \"selections\": (v0/*: any*/)\n },\n \"params\": {\n \"cacheID\": \"d8f0fefdfba04eb7d4aa3bee34d0991c\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderRefreshMutation\",\n \"operationKind\": \"mutation\",\n \"text\": \"mutation ConnectedUserProviderRefreshMutation {\\n refreshAccessToken {\\n success\\n accessTokenExpireIn\\n xsrfToken\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"acbdb2f87ce474c94ae5a7b4ca0769c8\";\n\nexport default node;\n","/**\n * @generated SignedSource<<656875e1bf06623a68fff1a35296db4e>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nimport { FragmentRefs } from \"relay-runtime\";\nexport type ConnectedUserProviderQuery$variables = Record<PropertyKey, never>;\nexport type ConnectedUserProviderQuery$data = {\n readonly connectedUser: {\n readonly \" $fragmentSpreads\": FragmentRefs<\"ConnectedUserFragment_user\">;\n } | null | undefined;\n};\nexport type ConnectedUserProviderQuery = {\n response: ConnectedUserProviderQuery$data;\n variables: ConnectedUserProviderQuery$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"id\",\n \"storageKey\": null\n},\nv1 = [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"code\",\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"connectedUser\",\n \"plural\": false,\n \"selections\": [\n {\n \"args\": null,\n \"kind\": \"FragmentSpread\",\n \"name\": \"ConnectedUserFragment_user\"\n }\n ],\n \"storageKey\": null\n }\n ],\n \"type\": \"Query\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"connectedUser\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"clientId\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserEmailAddressNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"emailAddress\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"address\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"createdAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"updatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"validatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastValidationRequestAt\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserStatusNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"status\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LanguageNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"language\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserPrivateDataNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"privateData\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"firstName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"GenderNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"gender\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n (v0/*: any*/)\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ]\n },\n \"params\": {\n \"cacheID\": \"654e16a74dc1101f903a371ee713c943\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderQuery\",\n \"operationKind\": \"query\",\n \"text\": \"query ConnectedUserProviderQuery {\\n connectedUser {\\n ...ConnectedUserFragment_user\\n id\\n }\\n}\\n\\nfragment ConnectedUserFragment_user on UserNode {\\n id\\n clientId\\n emailAddress {\\n id\\n address\\n createdAt\\n updatedAt\\n validatedAt\\n lastValidationRequestAt\\n }\\n status {\\n id\\n code\\n }\\n language {\\n id\\n code\\n }\\n privateData {\\n firstName\\n lastName\\n gender {\\n id\\n code\\n }\\n id\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"d5fbaec2a40f0880257954b852fe81fa\";\n\nexport default node;\n","import {useContext} from \"react\";\nimport {LocaleContext} from \"./index\";\nimport {LocaleContextInterface} from \"./types\";\n\n/**\n * Hook to access locale context\n */\nexport const useLocale = (): LocaleContextInterface => {\n const context = useContext(LocaleContext);\n\n if (!context) {\n throw new Error(\"useLocale must be used within LocaleProvider\");\n }\n\n return context;\n};\n","/**\n * @generated SignedSource<<01ac667780642633f84cf48ae783c749>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ReaderFragment } from 'relay-runtime';\nimport { FragmentRefs } from \"relay-runtime\";\nexport type ConnectedUserFragment_user$data = {\n readonly clientId: string | null | undefined;\n readonly emailAddress: {\n readonly address: string;\n readonly createdAt: any | null | undefined;\n readonly id: string;\n readonly lastValidationRequestAt: any | null | undefined;\n readonly updatedAt: any | null | undefined;\n readonly validatedAt: any | null | undefined;\n };\n readonly id: string;\n readonly language: {\n readonly code: string;\n readonly id: string;\n };\n readonly privateData: {\n readonly firstName: string | null | undefined;\n readonly gender: {\n readonly code: string;\n readonly id: string;\n } | null | undefined;\n readonly lastName: string | null | undefined;\n } | null | undefined;\n readonly status: {\n readonly code: string;\n readonly id: string;\n };\n readonly \" $fragmentType\": \"ConnectedUserFragment_user\";\n};\nexport type ConnectedUserFragment_user$key = {\n readonly \" $data\"?: ConnectedUserFragment_user$data;\n readonly \" $fragmentSpreads\": FragmentRefs<\"ConnectedUserFragment_user\">;\n};\n\nconst node: ReaderFragment = (function(){\nvar v0 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"id\",\n \"storageKey\": null\n},\nv1 = [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"code\",\n \"storageKey\": null\n }\n];\nreturn {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserFragment_user\",\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"clientId\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserEmailAddressNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"emailAddress\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"address\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"createdAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"updatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"validatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastValidationRequestAt\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserStatusNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"status\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LanguageNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"language\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserPrivateDataNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"privateData\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"firstName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"GenderNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"gender\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"type\": \"UserNode\",\n \"abstractKey\": null\n};\n})();\n\n(node as any).hash = \"be884da6a0b3dc538f08a2a609730684\";\n\nexport default node;\n","import {graphql} from \"react-relay\";\n\n/**\n * ConnectedUser fragment\n *\n * Defines all fields needed for the connected user across the application.\n * Used in:\n * - login mutation\n * - refreshAccessToken mutation\n *\n * Relay automatically updates the cache when this fragment is returned from mutations.\n * This fragment ensures consistency in user data structure and eliminates duplication.\n */\nexport const ConnectedUserFragment = graphql`\n fragment ConnectedUserFragment_user on UserNode {\n id\n clientId\n emailAddress {\n id\n address\n createdAt\n updatedAt\n validatedAt\n lastValidationRequestAt\n }\n status {\n id\n code\n }\n language {\n id\n code\n }\n privateData {\n firstName\n lastName\n gender {\n id\n code\n }\n }\n }\n`;\n","import {forwardRef, useCallback, useEffect, useRef, useState} from \"react\";\nimport {useMutation, graphql, useQueryLoader, usePreloadedQuery, useFragment} from \"react-relay\";\nimport type {PreloadedQuery} from \"react-relay\";\nimport {useIntl} from \"react-intl\";\nimport { ConnectedUserContext } from \"./hooks\";\nimport {ConnectedUserInterface, ConnectedUserProviderProps, ConnectedUserProviderRefInterface} from \"./types\";\nimport {useAlertMessages} from \"../AlertMessageProvider/hooks\";\nimport {useLocale} from \"../LocaleProvider/hooks\";\nimport {ConnectedUserFragment} from \"./ConnectedUserFragment\";\nimport type {ConnectedUserProviderQuery as ConnectedUserProviderQueryType} from \"./__generated__/ConnectedUserProviderQuery.graphql\";\nimport type {ConnectedUserProviderRefreshMutation} from \"./__generated__/ConnectedUserProviderRefreshMutation.graphql\";\nimport type {ConnectedUserProviderLoginMutation} from \"./__generated__/ConnectedUserProviderLoginMutation.graphql\";\nimport {clearRelayCache} from \"../../relay/RelayEnvironment\";\nimport {errorTranslations, isErrorKey} from \"../../i18n/errors\";\nimport type {RelayNetworkError} from \"../../types/relayTypes\";\n\n/**\n * Query definition for connected user\n */\nconst ConnectedUserProviderQueryNode = graphql`\n query ConnectedUserProviderQuery {\n connectedUser {\n ...ConnectedUserFragment_user\n }\n }\n`;\n\n/**\n * Refresh access token mutation (shared between outer and inner components)\n */\nconst RefreshMutationNode = graphql`mutation ConnectedUserProviderRefreshMutation {\n refreshAccessToken {\n success\n accessTokenExpireIn\n xsrfToken\n }\n}`;\n\n/**\n * Inner component that uses preloaded query\n */\nconst ConnectedUserProviderInner = forwardRef<ConnectedUserProviderRefInterface, ConnectedUserProviderProps & {\n queryRef: PreloadedQuery<ConnectedUserProviderQueryType>;\n onMutationSuccess: () => void;\n}>((props, ref) => {\n const {queryRef, onMutationSuccess} = props;\n\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const alertMessage = useAlertMessages();\n const intl = useIntl();\n const {updateLocale} = useLocale();\n\n /*******************************************************************************************************************\n * QUERIES\n ******************************************************************************************************************/\n\n /**\n * Fetch connected user from Relay cache\n * Automatically re-renders when cache is updated by mutations\n */\n const data = usePreloadedQuery(ConnectedUserProviderQueryNode, queryRef);\n\n /**\n * Read fragment data using useFragment\n * Fragment spread masks data - must use useFragment to access it\n */\n const user = useFragment(ConnectedUserFragment, data?.connectedUser ?? null) as ConnectedUserInterface | undefined;\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [accessTokenExpireIn, setAccessTokenExpireIn] = useState<number | undefined>(undefined)\n const [_webserviceBuffer, setWebserviceBuffer] = useState<(() => void)[]>([])\n const isRefreshInflightRef = useRef<boolean>(false)\n const refreshCallbacksRef = useRef<Array<() => void>>([])\n\n /*******************************************************************************************************************\n * MUTATIONS\n ******************************************************************************************************************/\n\n const [commitLogin, isLoginInflight] = useMutation<ConnectedUserProviderLoginMutation>(\n graphql`mutation ConnectedUserProviderLoginMutation($inputs: LoginInput!) {\n login(inputs: $inputs) {\n success\n accessTokenExpireIn\n xsrfToken\n }\n }`\n )\n\n const [commitRefresh] = useMutation<ConnectedUserProviderRefreshMutation>(RefreshMutationNode)\n\n const [commitLogout, isLogoutInflight] = useMutation(\n graphql`mutation ConnectedUserProviderLogoutMutation {\n logout {\n succeed\n }\n }`\n )\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Call refresh mutation\n * Used reactively when access token expires\n */\n const commitLysRefresh = useCallback(() => {\n // Prevent multiple simultaneous refresh calls\n if (isRefreshInflightRef.current) {\n return;\n }\n\n isRefreshInflightRef.current = true;\n\n commitRefresh({\n variables: {},\n onCompleted: (response, errors) => {\n isRefreshInflightRef.current = false;\n\n if (!errors || !errors?.length) {\n // Trigger refetch of connected user query\n onMutationSuccess();\n }\n setAccessTokenExpireIn(response.refreshAccessToken?.accessTokenExpireIn)\n },\n onError: (error: Error) => {\n isRefreshInflightRef.current = false;\n\n // Clear cache on refresh failure\n clearRelayCache();\n // Trigger refetch even on error to update UI\n onMutationSuccess();\n setAccessTokenExpireIn(undefined)\n\n // Report error to user\n const relayError = error as RelayNetworkError;\n if (relayError?.source?.errors) {\n const locale = intl.locale as \"en\" | \"fr\";\n relayError.source.errors.forEach((err) => {\n if (err.message !== \"WRONG_REFRESH_TOKEN_ERROR\") {\n if (!isErrorKey(err.message)) {\n console.error(\"Unhandled server error:\", err.message);\n }\n alertMessage.merge([{\n text: isErrorKey(err.message)\n ? errorTranslations[err.message][locale]\n : errorTranslations.UNKNOWN_ERROR[locale],\n level: \"CRITICAL\"\n }])\n }\n })\n } else {\n // Network error (CORS, connection failed, etc)\n alertMessage.merge([{\n text: error.message || \"NETWORK_ERROR\",\n level: \"CRITICAL\"\n }])\n }\n }\n })\n }, [commitRefresh, alertMessage, onMutationSuccess, intl.locale])\n\n /**\n * Call login mutation\n */\n const commitLysLogin = useCallback((login: string, password: string) => {\n commitLogin({\n variables: {\n inputs: {\n login,\n password\n }\n },\n onCompleted: (response, errors) => {\n if (!errors || !errors?.length) {\n // Trigger refetch of connected user query\n onMutationSuccess();\n }\n setAccessTokenExpireIn(response.login?.accessTokenExpireIn)\n },\n onError: (error: Error) => {\n const relayError = error as RelayNetworkError;\n relayError?.source?.errors?.forEach((err) => {\n alertMessage.merge([{\n text: err.message,\n level: \"CRITICAL\"\n }])\n })\n }\n })\n }, [commitLogin, alertMessage, onMutationSuccess])\n\n /**\n * Call logout mutation\n */\n const commitLysLogout = useCallback(() => {\n commitLogout({\n variables: {},\n onCompleted: () => {\n // Clear Relay cache\n clearRelayCache();\n // Trigger refetch of connected user query\n onMutationSuccess();\n setAccessTokenExpireIn(undefined)\n alertMessage.merge([{\n text: intl.formatMessage({id: \"lys.services.i18n.messages.logoutSuccess\"}),\n level: \"SUCCESS\"\n }])\n },\n onError: (error: Error) => {\n const relayError = error as RelayNetworkError;\n relayError?.source?.errors?.forEach((err) => {\n alertMessage.merge([{\n text: err.message,\n level: \"CRITICAL\"\n }])\n })\n }\n })\n }, [commitLogout, alertMessage, intl, onMutationSuccess])\n\n /**\n * Handle session expired (ACCESS_DENIED_ERROR)\n * Attempts to refresh token first, if that fails then disconnects\n * Supports multiple callbacks from different LysQueryProviders failing simultaneously\n * @param onRefreshSuccess Optional callback called after successful token refresh\n */\n const handleSessionExpired = useCallback((onRefreshSuccess?: () => void) => {\n // Store callback to be called when refresh completes\n // This allows multiple LysQueryProviders to register their callbacks\n if (onRefreshSuccess) {\n refreshCallbacksRef.current.push(onRefreshSuccess);\n }\n\n // Only start refresh if not already in flight\n if (!isRefreshInflightRef.current) {\n isRefreshInflightRef.current = true;\n\n commitRefresh({\n variables: {},\n onCompleted: (response, errors) => {\n isRefreshInflightRef.current = false;\n\n if (!errors || !errors?.length) {\n // Refresh succeeded - update expiration\n setAccessTokenExpireIn(response.refreshAccessToken?.accessTokenExpireIn)\n onMutationSuccess();\n // Call ALL registered callbacks to retry failed requests\n const callbacks = refreshCallbacksRef.current;\n refreshCallbacksRef.current = [];\n callbacks.forEach((cb) => {\n try {\n cb();\n } catch (error) {\n console.error('Error executing refresh callback:', error);\n }\n });\n } else {\n // Refresh failed - clear callbacks and disconnect user\n refreshCallbacksRef.current = [];\n clearRelayCache();\n onMutationSuccess();\n setAccessTokenExpireIn(undefined);\n alertMessage.merge([{\n text: intl.formatMessage({id: \"lys.services.i18n.messages.sessionExpired\"}),\n level: \"WARNING\"\n }]);\n }\n },\n onError: () => {\n isRefreshInflightRef.current = false;\n // Clear callbacks on error\n refreshCallbacksRef.current = [];\n\n // Refresh failed - disconnect user\n clearRelayCache();\n onMutationSuccess();\n setAccessTokenExpireIn(undefined);\n alertMessage.merge([{\n text: intl.formatMessage({id: \"lys.services.i18n.messages.sessionExpired\"}),\n level: \"WARNING\"\n }]);\n }\n })\n }\n }, [commitRefresh, onMutationSuccess, alertMessage, intl])\n\n /**\n * Push webservice to queue or execute immediately\n * Reactive refresh: if token expired, refresh then execute buffered requests\n */\n const push = useCallback((webservice: () => void) => {\n const timeStampSecondNow = Date.now() / 1000\n\n // Check if token is valid (with 5 second buffer)\n const isValid = accessTokenExpireIn !== undefined\n ? (accessTokenExpireIn - timeStampSecondNow > 5)\n : true // If no expiration info (public/unauthenticated), consider valid\n\n // Token valid and not refreshing -> execute immediately\n if (isValid && !isRefreshInflightRef.current) {\n webservice()\n return\n }\n\n // Token invalid and not refreshing -> trigger refresh\n if (!isValid && !isRefreshInflightRef.current) {\n commitLysRefresh()\n }\n\n // In all other cases -> buffer the webservice\n // (either refreshing or token invalid)\n setWebserviceBuffer(prev => [...prev, webservice])\n }, [accessTokenExpireIn, commitLysRefresh])\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n // Execute buffered webservices when token becomes valid after refresh\n useEffect(() => {\n const timeStampSecondNow = Date.now() / 1000\n const isValid = accessTokenExpireIn !== undefined\n ? (accessTokenExpireIn - timeStampSecondNow > 5)\n : true // If no expiration info (public/unauthenticated), consider valid\n\n if (isValid && !isRefreshInflightRef.current) {\n setWebserviceBuffer(currentBuffer => {\n if (currentBuffer.length > 0) {\n // Execute all buffered webservices\n currentBuffer.forEach((webservice) => {\n try {\n webservice()\n } catch (error) {\n console.error('Error executing buffered webservice:', error)\n }\n })\n }\n return [] // Clear buffer\n })\n }\n }, [accessTokenExpireIn])\n\n // Update locale when user language changes\n useEffect(() => {\n if (user?.language?.code) {\n updateLocale(user.language.code);\n }\n }, [user?.language?.code, updateLocale]);\n\n // Update reference\n useEffect(() => {\n const data = {\n language: user?.language?.code\n }\n\n if (typeof ref === 'function') {\n ref(data)\n } else if (ref) {\n ref.current = data\n }\n }, [user?.language?.code, ref])\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <ConnectedUserContext.Provider value={{\n user,\n push,\n logout: [commitLysLogout, isLogoutInflight],\n login: [commitLysLogin, isLoginInflight],\n refresh: [commitLysRefresh, false],\n handleSessionExpired\n }}>\n {props.children}\n </ConnectedUserContext.Provider>\n )\n})\n\nConnectedUserProviderInner.displayName = \"ConnectedUserProviderInner\";\n\n/**\n * Outer component that manages query loading\n *\n * On mount, attempts to refresh the access token before loading the user query.\n * This handles the case where a page reload occurs after the access token (short-lived JWT)\n * has expired but the refresh token (longer-lived, httpOnly cookie) is still valid.\n * Without this, the initial connectedUser query would fail with an expired JWT,\n * showing the login page even though the session is still valid.\n */\nconst ConnectedUserProvider = forwardRef<ConnectedUserProviderRefInterface, ConnectedUserProviderProps>((props, ref) => {\n const [queryRef, loadQuery] = useQueryLoader<ConnectedUserProviderQueryType>(ConnectedUserProviderQueryNode);\n // Tracks whether the initial query has been loaded (after mount refresh attempt)\n const queryLoadedRef = useRef(false);\n\n // Reuse the shared refresh mutation for the initial mount refresh\n const [commitInitialRefresh] = useMutation<ConnectedUserProviderRefreshMutation>(RefreshMutationNode);\n\n // On mount: attempt token refresh, then load user query\n useEffect(() => {\n if (queryLoadedRef.current) return;\n queryLoadedRef.current = true;\n\n commitInitialRefresh({\n variables: {},\n onCompleted: () => {\n // Refresh succeeded — load user query with fresh access token\n loadQuery({}, {fetchPolicy: 'network-only'});\n },\n onError: () => {\n // Refresh failed (no valid refresh token) — load query anyway\n // This will return null connectedUser, showing the login page\n loadQuery({}, {fetchPolicy: 'network-only'});\n },\n });\n }, [commitInitialRefresh, loadQuery]);\n\n // Callback to reload query after mutations (login, refresh, logout)\n const handleMutationSuccess = useCallback(() => {\n // Use store-and-network to use cache first, then refetch\n loadQuery({}, {fetchPolicy: 'store-and-network'});\n }, [loadQuery]);\n\n return queryRef ? (\n <ConnectedUserProviderInner\n ref={ref}\n queryRef={queryRef}\n onMutationSuccess={handleMutationSuccess}\n >\n {props.children}\n </ConnectedUserProviderInner>\n ) : null;\n});\n\nConnectedUserProvider.displayName = \"ConnectedUserProvider\";\n\nexport default ConnectedUserProvider\n","/**\n * @generated SignedSource<<b99811e5597cf9c9977b594fb31cbe59>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type WebserviceAccessProviderQuery$variables = Record<PropertyKey, never>;\nexport type WebserviceAccessProviderQuery$data = {\n readonly allAccessibleWebservices: {\n readonly edges: ReadonlyArray<{\n readonly node: {\n readonly code: string;\n readonly userAccessLevels: ReadonlyArray<{\n readonly code: string;\n }>;\n };\n }>;\n };\n};\nexport type WebserviceAccessProviderQuery = {\n response: WebserviceAccessProviderQuery$data;\n variables: WebserviceAccessProviderQuery$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"code\",\n \"storageKey\": null\n},\nv1 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"id\",\n \"storageKey\": null\n};\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"WebserviceAccessProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeListConnection\",\n \"kind\": \"LinkedField\",\n \"name\": \"allAccessibleWebservices\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeEdge\",\n \"kind\": \"LinkedField\",\n \"name\": \"edges\",\n \"plural\": true,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"node\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessLevelNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"userAccessLevels\",\n \"plural\": true,\n \"selections\": [\n (v0/*: any*/)\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"type\": \"Query\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"WebserviceAccessProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeListConnection\",\n \"kind\": \"LinkedField\",\n \"name\": \"allAccessibleWebservices\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeEdge\",\n \"kind\": \"LinkedField\",\n \"name\": \"edges\",\n \"plural\": true,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"node\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessLevelNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"userAccessLevels\",\n \"plural\": true,\n \"selections\": [\n (v0/*: any*/),\n (v1/*: any*/)\n ],\n \"storageKey\": null\n },\n (v1/*: any*/)\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ]\n },\n \"params\": {\n \"cacheID\": \"0eb745d5632c205d2b339ac945f97748\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"WebserviceAccessProviderQuery\",\n \"operationKind\": \"query\",\n \"text\": \"query WebserviceAccessProviderQuery {\\n allAccessibleWebservices {\\n edges {\\n node {\\n code\\n userAccessLevels {\\n code\\n id\\n }\\n id\\n }\\n }\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"fc09839e36fcabc6d7704f800685b5a2\";\n\nexport default node;\n","import {createContext, useCallback, useContext} from \"react\";\nimport {GraphQLTaggedNode} from \"relay-runtime\";\nimport {extractOperationNames, checkOperationsPermission as checkOperationsPermissionUtil} from \"../../tools/relayTools\";\n\n/**\n * Webservice access context\n */\nconst WebserviceAccessContext = createContext<{\n checkWebserviceAccess(webservice: string): boolean;\n getWebserviceAccessLevels(webservice: string): string[];\n}>({\n checkWebserviceAccess: () => {\n console.warn(\"WebserviceAccessProvider not initialized: checkWebserviceAccess\");\n return false;\n },\n getWebserviceAccessLevels: () => {\n console.warn(\"WebserviceAccessProvider not initialized: getWebserviceAccessLevels\");\n return [];\n }\n});\n\n/**\n * Hook to access webservice permissions\n *\n * Provides:\n * - checkWebserviceAccess(name): Check permission by webservice name (string)\n * - checkOperationsPermission(operation): Check permission by GraphQL operation (mutation/query)\n * - getWebserviceAccessLevels(name): Get access levels for a webservice\n */\nfunction useWebserviceAccess() {\n const {checkWebserviceAccess, getWebserviceAccessLevels} = useContext(WebserviceAccessContext);\n\n /**\n * Check permission for a GraphQL operation (mutation or query)\n * Extracts operation names from the GraphQL node and checks all permissions\n */\n const checkOperationsPermission = useCallback((operation: GraphQLTaggedNode): boolean => {\n const operationNames = extractOperationNames(operation);\n return checkOperationsPermissionUtil(operationNames, checkWebserviceAccess);\n }, [checkWebserviceAccess]);\n\n return {\n checkWebserviceAccess,\n checkOperationsPermission,\n getWebserviceAccessLevels\n };\n}\n\nexport {\n WebserviceAccessContext,\n useWebserviceAccess\n}\n","import {createComponentTranslations} from \"../../tools/translationTools\";\n\nconst translations = {\n errorTitle: {\n en: \"Permission System Error\",\n fr: \"Erreur du système de permissions\"\n },\n errorMessage: {\n en: \"Unable to load permission system. Please check your connection and try refreshing the page.\",\n fr: \"Impossible de charger le système de permissions. Veuillez vérifier votre connexion et rafraîchir la page.\"\n },\n loadingPermissions: {\n en: \"Loading permissions...\",\n fr: \"Chargement des permissions...\"\n }\n};\n\nconst {config, useTranslations} = createComponentTranslations(\n \"WebserviceAccessProvider\",\n translations\n);\n\nexport const webserviceAccessProviderConfig = config;\nexport const useWebserviceAccessProviderTranslations = useTranslations;\n","import * as React from \"react\";\nimport {Suspense, useCallback, useEffect, useMemo, useState} from \"react\";\nimport {graphql, usePreloadedQuery, useQueryLoader, PreloadedQuery} from \"react-relay\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {WebserviceAccessProviderProps} from \"./types\";\nimport {WebserviceAccessContext} from \"./hooks\";\nimport ErrorBoundaryProvider from \"../ErrorBoundaryProvider\";\nimport {WebserviceAccessProviderQuery} from \"./__generated__/WebserviceAccessProviderQuery.graphql\";\nimport {useWebserviceAccessProviderTranslations} from \"./translations\";\nimport {toSnakeCase} from \"../../tools/stringTools\";\n\nconst query = graphql`\n query WebserviceAccessProviderQuery {\n allAccessibleWebservices {\n edges {\n node {\n code\n userAccessLevels {\n code\n }\n }\n }\n }\n }\n`;\n\n/**\n * Type for webservice data with access levels\n */\ntype WebserviceData = {\n code: string;\n accessLevels: string[];\n};\n\n/**\n * Inner component that executes the query\n * Isolated so ErrorBoundary only catches query errors, not children errors\n */\nconst QueryExecutor: React.FC<{\n queryRef: PreloadedQuery<WebserviceAccessProviderQuery>;\n onData: (webservices: WebserviceData[]) => void;\n}> = ({queryRef, onData}) => {\n const data = usePreloadedQuery<WebserviceAccessProviderQuery>(query, queryRef);\n\n const webservicesData = useMemo(() => {\n return data?.allAccessibleWebservices?.edges\n ?.map((edge) => ({\n code: edge?.node?.code,\n accessLevels: edge?.node?.userAccessLevels?.map((level) => level.code) || []\n }))\n .filter((ws): ws is WebserviceData => ws.code !== null && ws.code !== undefined) || [];\n }, [data]);\n\n useEffect(() => {\n onData(webservicesData);\n }, [webservicesData, onData]);\n\n return null;\n};\n\nQueryExecutor.displayName = \"QueryExecutor\";\n\n/**\n * WebserviceAccess provider\n * Manages loading of accessible webservices for current user\n * Auto-reloads when user changes\n */\nconst WebserviceAccessProvider: React.ComponentType<WebserviceAccessProviderProps> = ({children}) => {\n const {user, handleSessionExpired} = useConnectedUserInfo();\n const {t} = useWebserviceAccessProviderTranslations();\n\n const [queryRef, loadQuery, disposeQuery] = useQueryLoader<WebserviceAccessProviderQuery>(query);\n const [hasError, setHasError] = useState(false);\n const [webservicesMap, setWebservicesMap] = useState<Map<string, string[]>>(new Map());\n\n // Load webservice accesses when user changes\n useEffect(() => {\n if (!hasError) {\n loadQuery({}, {fetchPolicy: \"network-only\"});\n } else {\n disposeQuery();\n }\n }, [user, loadQuery, disposeQuery, hasError]);\n\n // Callback when query data is received\n const handleQueryData = useCallback((webservicesData: WebserviceData[]) => {\n const newMap = new Map<string, string[]>();\n webservicesData.forEach((ws) => {\n newMap.set(ws.code, ws.accessLevels);\n });\n setWebservicesMap(newMap);\n }, []);\n\n // Error handler for query errors only\n const handleQueryError = useCallback((error: Error) => {\n const relayError = error as Error & {errors?: Array<{message: string}>};\n if (error.message === \"ACCESS_DENIED_ERROR\" ||\n (error.message?.includes(\"ACCESS_DENIED_ERROR\")) ||\n (relayError.errors?.some((e) => e.message === \"ACCESS_DENIED_ERROR\"))) {\n console.log(\"WebserviceAccessProvider: Session expired, redirecting to login\");\n handleSessionExpired();\n return;\n }\n console.error(\"WebserviceAccessProvider query failed - continuing without permissions:\", error);\n setHasError(true);\n }, [handleSessionExpired]);\n\n // Check webservice access\n const checkWebserviceAccess = useCallback((webserviceName: string) => {\n const snakeCaseName = toSnakeCase(webserviceName);\n return webservicesMap.has(snakeCaseName);\n }, [webservicesMap]);\n\n // Get access levels for a webservice\n const getWebserviceAccessLevels = useCallback((webserviceName: string): string[] => {\n const snakeCaseName = toSnakeCase(webserviceName);\n return webservicesMap.get(snakeCaseName) || [];\n }, [webservicesMap]);\n\n // Context value\n const contextValue = useMemo(() => ({\n checkWebserviceAccess,\n getWebserviceAccessLevels\n }), [checkWebserviceAccess, getWebserviceAccessLevels]);\n\n if (hasError) {\n return (\n <div style={{padding: '2rem', textAlign: 'center'}}>\n <h3>{t(\"errorTitle\")}</h3>\n <p>{t(\"errorMessage\")}</p>\n </div>\n );\n }\n\n return (\n <>\n {/* Query execution isolated in its own ErrorBoundary */}\n {queryRef && (\n <ErrorBoundaryProvider onError={handleQueryError}>\n <Suspense fallback={<div>{t(\"loadingPermissions\")}</div>}>\n <QueryExecutor queryRef={queryRef} onData={handleQueryData} />\n </Suspense>\n </ErrorBoundaryProvider>\n )}\n\n {/* Children rendered OUTSIDE the ErrorBoundary */}\n <WebserviceAccessContext.Provider value={contextValue}>\n {children}\n </WebserviceAccessContext.Provider>\n </>\n );\n};\n\nWebserviceAccessProvider.displayName = \"WebserviceAccessProvider\";\n\nexport default WebserviceAccessProvider;\n","import {createContext, useContext, useEffect, useState} from \"react\";\nimport {SignalContextValue, SignalHandler, SignalRefresh} from \"./types\";\n\n/**\n * Signal context with default no-op values\n */\nexport const SignalContext = createContext<SignalContextValue>({\n isConnected: false,\n error: null,\n subscribe: () => {\n console.warn(\"SignalProvider not initialized: subscribe\");\n return () => {};\n }\n});\n\n/**\n * Hook to access signal provider state\n */\nexport function useSignal(): SignalContextValue {\n return useContext(SignalContext);\n}\n\n/**\n * Hook to subscribe to signals with automatic cleanup\n *\n * @param handler - Function called when a signal is received\n * @param deps - Dependencies array for the handler (like useEffect)\n *\n * @example\n * ```tsx\n * useSignalSubscription((signal) => {\n * if (signal.signal === \"FINANCIAL_IMPORT_COMPLETED\") {\n * // Handle import completion\n * refetchData();\n * }\n * }, [refetchData]);\n * ```\n */\nexport function useSignalSubscription(\n handler: SignalHandler,\n deps: React.DependencyList = []\n): void {\n const {subscribe} = useSignal();\n\n useEffect(() => {\n const unsubscribe = subscribe(handler);\n return unsubscribe;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [subscribe, ...deps]);\n}\n\n/**\n * Hook that returns a version counter and params, incremented each time a matching signal is received.\n * Use version as a useEffect dependency to trigger query reloads on specific signals.\n * Use params to filter based on signal data before reloading.\n *\n * Matches on both signal.signal and signal.params.type_id for compatibility\n * with notification-wrapped signals.\n *\n * @param signalKeys - One or more signal names to listen for\n * @returns {SignalRefresh} version counter and params of the last matching signal\n *\n * @example\n * ```tsx\n * const {version, params} = useSignalRefresh(\"PORTFOLIO_ANALYSIS_COMPLETED\");\n *\n * useEffect(() => {\n * const data = params?.data as Record<string, unknown>;\n * if (version > 0 && data?.year === year && queryRef?.hasPermission) {\n * queryRef?.load();\n * }\n * }, [version]);\n * ```\n */\nexport function useSignalRefresh(...signalKeys: string[]): SignalRefresh {\n const [version, setVersion] = useState(0);\n const [params, setParams] = useState<Record<string, unknown> | null>(null);\n\n useSignalSubscription((signal) => {\n const typeId = signal.params?.type_id as string | undefined;\n if (signalKeys.includes(signal.signal) || (typeId && signalKeys.includes(typeId))) {\n setParams(signal.params);\n setVersion(v => v + 1);\n }\n }, signalKeys);\n\n return {version, params};\n}","import React, {useEffect, useRef, useState, useCallback, useMemo} from \"react\";\nimport {SignalContext} from \"./hooks\";\nimport {Signal, SignalHandler, SignalProviderProps} from \"./types\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\n\n/**\n * Decode Relay Global ID to extract raw UUID.\n * Relay IDs are base64 encoded strings in format \"NodeType:uuid\"\n */\nconst decodeRelayId = (relayId: string): string => {\n try {\n const decoded = atob(relayId);\n const parts = decoded.split(\":\");\n return parts.length > 1 ? parts[1] : relayId;\n } catch {\n return relayId;\n }\n};\n\n/**\n * SignalProvider component\n *\n * Provides real-time signal handling via Server-Sent Events (SSE).\n * Uses native EventSource API to connect to the SSE endpoint.\n *\n * Connection behavior:\n * - Connects only when a user is authenticated (user.id exists)\n * - Disconnects automatically when user logs out\n * - Non-blocking: errors don't crash the application\n * - Automatically reconnects on connection loss (handled by EventSource)\n *\n * Place this provider after ConnectedUserProvider and before ChatbotProvider\n * in the component tree.\n */\nconst SignalProvider: React.FC<SignalProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const {user} = useConnectedUserInfo();\n\n /*******************************************************************************************************************\n * REFS\n ******************************************************************************************************************/\n\n /**\n * EventSource instance\n */\n const eventSourceRef = useRef<EventSource | null>(null);\n\n /**\n * Set of registered signal handlers\n */\n const handlersRef = useRef<Set<SignalHandler>>(new Set());\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Dispatch a signal to all registered handlers\n */\n const dispatchSignal = useCallback((signal: Signal) => {\n handlersRef.current.forEach((handler) => {\n try {\n handler(signal);\n } catch (err) {\n console.error(\"[SignalProvider] Handler error:\", err);\n }\n });\n }, []);\n\n /**\n * Subscribe a handler to receive signals\n * Returns an unsubscribe function\n */\n const subscribe = useCallback((handler: SignalHandler): (() => void) => {\n handlersRef.current.add(handler);\n return () => {\n handlersRef.current.delete(handler);\n };\n }, []);\n\n /**\n * Stop the SSE connection\n */\n const stopConnection = useCallback(() => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close();\n eventSourceRef.current = null;\n }\n setIsConnected(false);\n setError(null);\n }, []);\n\n /**\n * Start the SSE connection\n */\n const startConnection = useCallback((userId: string) => {\n // Close existing connection if any\n stopConnection();\n\n // Decode Relay ID to get raw UUID for channel subscription\n const rawUserId = decodeRelayId(userId);\n const baseUrl = import.meta.env?.VITE_SSE_ENDPOINT as string || \"\";\n const url = `${baseUrl}/sse/signals?channel=user:${rawUserId}`;\n\n // Create EventSource with credentials for cookie auth\n const eventSource = new EventSource(url, {withCredentials: true});\n eventSourceRef.current = eventSource;\n\n eventSource.onopen = () => {\n setIsConnected(true);\n setError(null);\n };\n\n eventSource.onmessage = (event) => {\n try {\n const signal: Signal = JSON.parse(event.data);\n dispatchSignal(signal);\n } catch {\n // Ignore parse errors\n }\n };\n\n eventSource.onerror = () => {\n setError(new Error(\"SSE connection error\"));\n setIsConnected(false);\n // EventSource will automatically try to reconnect\n };\n }, [dispatchSignal, stopConnection]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Connect/disconnect based on user authentication state\n */\n useEffect(() => {\n if (user?.id) {\n // User is authenticated - start connection\n startConnection(user.id);\n } else {\n // User is not authenticated - stop connection\n stopConnection();\n }\n\n // Cleanup on unmount or user change\n return () => {\n stopConnection();\n };\n }, [user?.id, startConnection, stopConnection]);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n const contextValue = useMemo(() => ({\n isConnected,\n error,\n subscribe\n }), [isConnected, error, subscribe]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <SignalContext.Provider value={contextValue}>\n {children}\n </SignalContext.Provider>\n );\n};\n\nexport default SignalProvider;","import {createContext, useContext} from \"react\";\nimport {LysQueryContextType} from \"./types\";\nimport {OperationType} from \"relay-runtime\";\n\nconst LysQueryContext = createContext<LysQueryContextType>([\n undefined,\n () => {},\n]);\n\n/**\n * Hook to access query data and reload function from LysQueryProvider\n */\nfunction useLysQuery<TQuery extends OperationType = OperationType>(): LysQueryContextType<TQuery> {\n return useContext(LysQueryContext) as LysQueryContextType<TQuery>;\n}\n\nexport {\n LysQueryContext,\n useLysQuery\n};\n","import {useCallback, useEffect, useState} from \"react\";\nimport {useWebserviceAccess} from \"../WebserviceAccessProvider/hooks\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\n\ninterface AccessParameters {\n ownerIds: string[];\n}\n\n/**\n * Hook to check permission for a set of operations with OWNER access level handling.\n *\n * - If user has only OWNER access level for a webservice, check ownerIds\n * - If user has other access levels (ROLE, ORGANIZATION_ROLE, etc.), grant access\n * - Warn if OWNER is in access levels but accessParameters is not provided\n */\nexport function usePermissionCheck(\n operationNames: string[],\n accessParameters?: AccessParameters | null,\n providerName: string = \"Provider\"\n): boolean {\n const webserviceAccess = useWebserviceAccess();\n const connectedUserInfo = useConnectedUserInfo();\n\n const checkPermission = useCallback(() => {\n if (!operationNames.length) {\n return false;\n }\n\n return operationNames.every(operationName => {\n // First check if user has access to this webservice\n if (!webserviceAccess.checkWebserviceAccess(operationName)) {\n return false;\n }\n\n // Get access levels for this webservice\n const accessLevels = webserviceAccess.getWebserviceAccessLevels(operationName);\n\n // Check if OWNER is in the access levels\n const hasOwnerAccess = accessLevels.includes(\"OWNER\");\n\n // If OWNER is the only access level\n if (hasOwnerAccess && accessLevels.length === 1) {\n // accessParameters is required for OWNER-only access\n if (!accessParameters) {\n console.warn(\n `${providerName}: Operation \"${operationName}\" requires OWNER access but accessParameters is not defined. ` +\n `Please provide accessParameters={{ ownerIds: [...] }} to enable owner-based access control.`\n );\n return false;\n }\n\n // Check if connected user is in ownerIds\n const userId = connectedUserInfo.user?.id;\n if (!userId || !accessParameters.ownerIds.includes(userId)) {\n return false;\n }\n } else if (hasOwnerAccess && !accessParameters) {\n // OWNER is one of multiple access levels, but accessParameters not provided\n // User has access through other levels, but warn about missing owner config\n console.warn(\n `${providerName}: Operation \"${operationName}\" has OWNER access level but accessParameters is not defined. ` +\n `Owner-based access control will not work. Consider providing accessParameters={{ ownerIds: [...] }}.`\n );\n }\n\n // User has access (either through non-OWNER levels or passed OWNER check)\n return true;\n });\n }, [operationNames, webserviceAccess, accessParameters, connectedUserInfo.user?.id, providerName]);\n\n const [hasPermission, setHasPermission] = useState<boolean>(() => checkPermission());\n\n useEffect(() => {\n setHasPermission(checkPermission());\n }, [checkPermission]);\n\n return hasPermission;\n}\n","import {createContext, useContext} from \"react\";\nimport {ReactNode} from \"react\";\n\ninterface LysLoadingContextType {\n loadingFallback: ReactNode;\n}\n\nconst LysLoadingContext = createContext<LysLoadingContextType>({\n loadingFallback: null\n});\n\nexport const useLysLoadingFallback = (): ReactNode => {\n const {loadingFallback} = useContext(LysLoadingContext);\n return loadingFallback;\n};\n\nexport default LysLoadingContext;\n","import \"./styles.scss\";\nimport * as React from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState\n} from \"react\";\nimport {\n GraphQLTaggedNode,\n OperationType,\n} from \"relay-runtime\";\nimport {LysQueryProviderProps, LysQueryRefInterface} from \"./types\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {extractOperationNames} from \"../../tools/relayTools\";\nimport {useAlertMessages} from \"../AlertMessageProvider/hooks\";\nimport {AlertLevelType} from \"../AlertMessageProvider/types\";\nimport type {RelayNetworkError} from \"../../types/relayTypes\";\nimport {useRefreshSignal} from \"./RefreshSignalContext\";\nimport {PreloadedQuery, usePreloadedQuery, useQueryLoader} from \"react-relay\";\nimport {LysQueryContext} from \"./hooks\";\nimport ErrorBoundaryProvider from \"../ErrorBoundaryProvider\";\nimport {usePermissionCheck} from \"../hooks/usePermissionCheck\";\nimport {useLysLoadingFallback} from \"./LysLoadingContext\";\n\n/**\n * Extract node types from a GraphQL query\n * Traverses the query structure to find all concreteType values ending with \"Node\"\n */\nfunction extractNodeTypes(query: GraphQLTaggedNode): string[] {\n const nodeTypes = new Set<string>();\n\n const traverse = (obj: unknown): void => {\n if (!obj || typeof obj !== \"object\") return;\n\n if (\"concreteType\" in obj) {\n const concreteType = (obj as {concreteType: string}).concreteType;\n // Only include types ending with \"Node\" (not Connection, Edge, etc.)\n if (concreteType && concreteType.endsWith(\"Node\")) {\n nodeTypes.add(concreteType);\n }\n }\n\n // Traverse nested objects and arrays\n for (const value of Object.values(obj)) {\n if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (typeof value === \"object\") {\n traverse(value);\n }\n }\n };\n\n traverse(query);\n return Array.from(nodeTypes);\n}\n\n/**\n * Provider child component (mounted only when the query is loaded)\n * Extracts data from the preloaded query and passes it to parent\n */\nconst LysQueryProviderChild: React.ComponentType<{\n query: GraphQLTaggedNode;\n queryReference: PreloadedQuery<OperationType>;\n setData: (data: OperationType[\"response\"]) => void;\n}> = ({query, queryReference, setData}) => {\n const data = usePreloadedQuery(query, queryReference);\n\n useEffect(() => {\n setData(data);\n }, [setData, data]);\n\n return null;\n};\n\n/**\n * QueryErrorBoundary - Handles GraphQL query errors with session recovery\n *\n * Responsibilities:\n * - Catches errors thrown by Suspense/usePreloadedQuery via ErrorBoundaryProvider\n * - Categorizes errors: ACCESS_DENIED (session expired) vs GraphQL errors vs network errors\n * - Triggers session recovery with retry callback on ACCESS_DENIED\n * - Routes other errors to AlertMessageProvider\n * - Prevents duplicate error handling via errorProcessedRef\n * - Breaks ErrorBoundary re-render loops via hasError state\n */\nconst QueryErrorBoundary: React.ComponentType<{\n query: GraphQLTaggedNode;\n queryReference: PreloadedQuery<OperationType>;\n setData: (data: OperationType[\"response\"]) => void;\n reloadQuery: () => void;\n}> = ({query, queryReference, setData, reloadQuery}) => {\n const connectedUserInfo = useConnectedUserInfo();\n const alertMessage = useAlertMessages();\n\n // Prevent duplicate error handling (ErrorBoundary may call onError multiple times)\n const errorProcessedRef = useRef(false);\n\n // Break ErrorBoundary re-render loops: when true, unmounts the boundary entirely\n const [hasError, setHasError] = useState(false);\n\n const handleError = useCallback((error: RelayNetworkError) => {\n if (errorProcessedRef.current) {\n return;\n }\n errorProcessedRef.current = true;\n\n // Relay errors can have GraphQL errors in error.source.errors\n const gqlErrors = error?.source?.errors;\n\n // Check for ACCESS_DENIED_ERROR (session expiration)\n // - First in source.errors if available\n // - Then in error.message as fallback (Relay embeds error codes in message)\n const hasAccessDenied = gqlErrors?.some(\n (err) => err.message === \"ACCESS_DENIED_ERROR\"\n ) || error.message?.includes(\"ACCESS_DENIED_ERROR\");\n\n if (hasAccessDenied) {\n // CRITICAL: Set hasError to stop the ErrorBoundary render loop.\n // Without this, ErrorBoundary clears its state and re-renders children,\n // which throws the same error again causing an infinite loop.\n setHasError(true);\n\n // Handle session expiration - attempt token refresh\n // Pass retry callback to reload query after successful refresh\n connectedUserInfo.handleSessionExpired(() => {\n errorProcessedRef.current = false;\n setHasError(false);\n reloadQuery();\n });\n return;\n }\n\n // Display errors - prefer extracted GraphQL errors over raw message\n if (gqlErrors && gqlErrors.length > 0) {\n alertMessage.merge(\n gqlErrors.map((gqlError) => ({\n text: gqlError.message,\n level: (gqlError.severity || \"ERROR\") as AlertLevelType\n }))\n );\n } else {\n // Network or other errors - display original message\n alertMessage.merge([{\n text: error.message,\n level: \"CRITICAL\"\n }]);\n }\n\n setHasError(true);\n }, [connectedUserInfo, alertMessage, reloadQuery]);\n\n if (hasError) {\n return null;\n }\n\n return (\n <ErrorBoundaryProvider onError={handleError}>\n <React.Suspense fallback={null}>\n <LysQueryProviderChild\n query={query}\n queryReference={queryReference}\n setData={setData}\n />\n </React.Suspense>\n </ErrorBoundaryProvider>\n );\n};\n\n/**\n * LysQueryProvider - Manages GraphQL queries with permission checking\n *\n * Features:\n * - Automatic permission checking based on operation names\n * - Queue system for authenticated requests\n * - Error handling with QueryErrorBoundary\n * - Loading state management\n */\nfunction LysQueryProviderInner<TQuery extends OperationType = OperationType>(\n {\n query,\n initialQueryReference,\n parameters = {},\n options = {fetchPolicy: 'store-and-network'},\n accessParameters,\n children,\n as: Container = \"div\",\n loadingFallback\n }: LysQueryProviderProps<TQuery>,\n ref: React.Ref<LysQueryRefInterface<TQuery>>\n) {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const connectedUserInfo = useConnectedUserInfo();\n const refreshSignal = useRefreshSignal();\n const contextFallback = useLysLoadingFallback();\n const effectiveFallback = loadingFallback !== undefined ? loadingFallback : contextFallback;\n\n const [\n queryReference,\n loadQuery,\n disposeQuery\n ] = useQueryLoader(query, initialQueryReference);\n\n // Extract node types from query (memoized)\n const nodeTypes = useMemo(() => extractNodeTypes(query), [query]);\n\n // Extract operation names from query (memoized)\n const operationNames = useMemo(() => extractOperationNames(query), [query]);\n\n // Permission check via shared hook\n const hasPermission = usePermissionCheck(operationNames, accessParameters, \"LysQueryProvider\");\n\n // Track last processed refresh signal version\n const lastRefreshVersionRef = useRef(0);\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [data, setData] = useState<TQuery[\"response\"] | undefined>(undefined);\n const [load, setLoad] = useState<boolean>(false);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n const reloadQuery = useCallback(() => {\n disposeQuery();\n setLoad(true);\n }, [disposeQuery]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Load query when permission granted and load requested\n */\n useEffect(() => {\n if (hasPermission && load && !queryReference) {\n setLoad(false);\n connectedUserInfo.push(() => loadQuery(parameters, options));\n }\n }, [hasPermission, load, queryReference, connectedUserInfo.push, loadQuery, parameters, options]);\n\n /**\n * Handle refresh signal from ChatbotProvider\n * Reloads query when a refresh is triggered for any of this query's node types\n */\n useEffect(() => {\n // Check if this is a new signal we haven't processed yet\n if (refreshSignal.version > lastRefreshVersionRef.current) {\n // Check if any of our node types are in the refresh signal\n const shouldRefresh = nodeTypes.some(nodeType =>\n refreshSignal.nodes.includes(nodeType)\n );\n\n if (shouldRefresh) {\n lastRefreshVersionRef.current = refreshSignal.version;\n reloadQuery();\n }\n }\n }, [refreshSignal, nodeTypes, reloadQuery]);\n\n /**\n * Expose ref interface using useImperativeHandle\n */\n useImperativeHandle(ref, () => ({\n hasPermission,\n data,\n isLoading: load,\n load: reloadQuery\n }), [hasPermission, data, load, reloadQuery]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <LysQueryContext.Provider value={[data, reloadQuery]}>\n {hasPermission && (\n <Container className={Container === \"div\" ? \"lys-query-container\" : undefined}>\n {/* Loading indicator (only for block container) */}\n {Container === \"div\" && !queryReference && load && effectiveFallback}\n\n {/* Error boundary for GraphQL errors - isolated to query execution only */}\n {queryReference && (\n <QueryErrorBoundary\n query={query}\n queryReference={queryReference}\n setData={setData}\n reloadQuery={reloadQuery}\n />\n )}\n\n {/* Children wrapped in Suspense to catch useFragment suspensions */}\n <React.Suspense fallback={Container === \"div\" ? effectiveFallback : null}>\n {children}\n </React.Suspense>\n </Container>\n )}\n </LysQueryContext.Provider>\n );\n}\n\n// Cast to preserve generics with forwardRef\nconst LysQueryProvider = forwardRef(LysQueryProviderInner) as <TQuery extends OperationType = OperationType>(\n props: LysQueryProviderProps<TQuery> & { ref?: React.Ref<LysQueryRefInterface<TQuery>> }\n) => ReturnType<typeof LysQueryProviderInner>;\n\nexport default LysQueryProvider;\n","import {createContext, useContext} from \"react\";\nimport {UseMutationConfig} from \"react-relay\";\nimport {Disposable, MutationParameters} from \"relay-runtime\";\n\nconst LysMutationContext = createContext<[\n ((config: UseMutationConfig<MutationParameters>) => void) | null,\n boolean,\n Disposable | undefined\n]>([\n null,\n false,\n undefined\n]);\n\n/**\n * Hook to access mutation commit function and state from LysMutationProvider\n */\nfunction useLysMutation<TMutation extends MutationParameters = MutationParameters>(): [\n ((config: UseMutationConfig<TMutation>) => void) | null,\n boolean,\n Disposable | undefined\n] {\n return useContext(LysMutationContext) as [\n ((config: UseMutationConfig<TMutation>) => void) | null,\n boolean,\n Disposable | undefined\n ];\n}\n\nexport {\n LysMutationContext,\n useLysMutation\n};\n","import {forwardRef, useCallback, useImperativeHandle, useMemo, useState} from \"react\";\nimport {\n LysMutationProviderProps,\n LysMutationRefInterface\n} from \"./types\";\nimport {LysMutationContext} from \"./hooks\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {useMutation, UseMutationConfig} from \"react-relay\";\nimport {Disposable, MutationParameters, PayloadError} from \"relay-runtime\";\nimport {useAlertMessages} from \"../AlertMessageProvider/hooks\";\nimport {extractOperationNames} from \"../../tools/relayTools\";\nimport {usePermissionCheck} from \"../hooks/usePermissionCheck\";\nimport type {RelayNetworkError} from \"../../types/relayTypes\";\n\n/**\n * LysMutationProvider - Manages GraphQL mutations with permission checking\n *\n * Features:\n * - Automatic permission checking based on operation names\n * - Queue system for authenticated requests\n * - Error handling with AlertMessageProvider\n * - Conditional rendering based on permissions\n */\nconst LysMutationProvider = forwardRef<LysMutationRefInterface, LysMutationProviderProps>((props, ref) => {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const alertMessage = useAlertMessages();\n const connectedUserInfo = useConnectedUserInfo();\n const [commit, isInFlight] = useMutation(props.mutation, props.commitMutationFn);\n\n // Extract operation names from mutation (memoized)\n const operationNames = useMemo(() => extractOperationNames(props.mutation), [props.mutation]);\n\n // Permission check via shared hook\n const hasPermission = usePermissionCheck(operationNames, props.accessParameters, \"LysMutationProvider\");\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [disposable, setDisposable] = useState<Disposable | undefined>(undefined);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Mutation commit wrapper that adds error and success handling\n */\n const lysCommit = useCallback((config: UseMutationConfig<MutationParameters>) => {\n const lysConfig = {...config};\n\n lysConfig.onError = (error: RelayNetworkError) => {\n // Check for ACCESS_DENIED_ERROR to handle session expiration\n const hasAccessDenied = error?.source?.errors?.some(\n (err) => err.message === \"ACCESS_DENIED_ERROR\"\n );\n\n if (hasAccessDenied) {\n // Handle session expiration - redirect to login\n connectedUserInfo.handleSessionExpired();\n config.onError?.(error);\n return;\n }\n\n alertMessage.merge(\n error?.source?.errors?.map((err) => {\n let level: \"ERROR\" | \"CRITICAL\" = \"ERROR\";\n if (err.message === \"INTERNAL_ERROR\") {\n level = \"CRITICAL\";\n }\n return {\n text: err.message,\n level: level\n };\n }) ?? []\n );\n\n config.onError?.(error);\n };\n\n lysConfig.onCompleted = (response: MutationParameters[\"response\"], errors: PayloadError[] | null) => {\n config.onCompleted?.(response, errors);\n\n alertMessage.merge(\n errors?.map((error) => ({\n text: error.message,\n level: error.severity || \"ERROR\"\n })) ?? []\n );\n };\n\n const newDisposable = commit(lysConfig);\n setDisposable(newDisposable);\n }, [alertMessage, commit, connectedUserInfo.handleSessionExpired]);\n\n const pushCommit = useCallback((config: UseMutationConfig<MutationParameters>) => {\n connectedUserInfo.push(() => lysCommit(config));\n }, [connectedUserInfo.push, lysCommit]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Expose ref interface using useImperativeHandle\n */\n useImperativeHandle(ref, () => ({\n isInFlight,\n commit: hasPermission ? pushCommit : undefined,\n disposable: !isInFlight ? disposable : undefined\n }), [hasPermission, pushCommit, isInFlight, disposable]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <LysMutationContext.Provider\n value={[\n hasPermission ? pushCommit : null,\n isInFlight,\n !isInFlight ? disposable : undefined\n ]}\n >\n {(hasPermission || props.notPermissionDisplayType === \"show\") && props.children}\n </LysMutationContext.Provider>\n );\n});\n\nexport default LysMutationProvider;\n","import {createContext, useContext} from \"react\";\nimport {ClientContextValue} from \"./types\";\n\n/**\n * Client context\n */\nconst ClientContext = createContext<ClientContextValue>({\n clientId: null,\n setClientId: () => {\n console.warn(\"ClientProvider not initialized: setClientId\");\n },\n isLocked: false\n});\n\n/**\n * Hook to access the current client ID context.\n *\n * - For client users (user.clientId is set): returns the user's clientId, locked.\n * - For admin/super-admin users: returns the manually selected clientId, changeable.\n *\n * Must be used within ClientProvider.\n */\nfunction useClientId(): ClientContextValue {\n return useContext(ClientContext);\n}\n\nexport {\n ClientContext,\n useClientId\n};\n","import * as React from \"react\";\nimport {useCallback, useEffect, useMemo, useRef, useState} from \"react\";\nimport {useLocation} from \"react-router-dom\";\nimport {ClientContext} from \"./hooks\";\nimport {ClientProviderProps} from \"./types\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {useUrlQueries} from \"../UrlQueriesProvider/hooks\";\n\nconst SESSION_KEY = \"lys_clientId\";\nconst URL_PARAM_KEY = \"clientId\";\n\n/**\n * ClientProvider - Manages the current client ID selection\n *\n * Features:\n * - For client users: clientId is locked to user.clientId\n * - For admin users: clientId is selectable\n * - Persisted in sessionStorage (survives page navigation)\n * - Synced to URL query param (visible for debugging)\n * - Automatically clears on logout (user becomes undefined)\n *\n * Must be placed after ConnectedUserProvider and inside UrlQueriesProvider.\n */\nconst ClientProvider: React.ComponentType<ClientProviderProps> = ({children}) => {\n const {user} = useConnectedUserInfo();\n const {update: updateUrl, appliedParams} = useUrlQueries();\n const location = useLocation();\n\n const isLocked = !!user?.clientId;\n const prevUserRef = useRef(user);\n\n const [selectedClientId, setSelectedClientId] = useState<string | null>(() => {\n // URL param takes priority (e.g. shared link), then sessionStorage\n return appliedParams.get(URL_PARAM_KEY) || sessionStorage.getItem(SESSION_KEY);\n });\n\n /**\n * Clear selection on logout (user was defined, now undefined)\n */\n useEffect(() => {\n const wasLoggedIn = prevUserRef.current !== undefined;\n const isLoggedOut = user === undefined;\n prevUserRef.current = user;\n\n if (wasLoggedIn && isLoggedOut) {\n sessionStorage.removeItem(SESSION_KEY);\n setSelectedClientId(null);\n updateUrl({[URL_PARAM_KEY]: null});\n }\n }, [user, updateUrl]);\n\n /**\n * Sync clientId to URL on selection change or page navigation\n * Uses UrlQueriesProvider.update (same setSearchParams as other components)\n * to avoid conflicts when multiple params change in the same effect cycle\n *\n * Skip when no user is connected: avoids setSearchParams overriding\n * navigate('/login') in PrivateAppTemplate's redirect effect.\n */\n useEffect(() => {\n if (isLocked || !user) return;\n\n if (selectedClientId) {\n updateUrl({[URL_PARAM_KEY]: selectedClientId});\n } else {\n updateUrl({[URL_PARAM_KEY]: null});\n }\n }, [selectedClientId, location.pathname, isLocked, user, updateUrl]);\n\n /**\n * Resolved clientId: locked from user profile or manual selection\n */\n const clientId = useMemo(() => {\n if (user?.clientId) {\n return user.clientId;\n }\n return selectedClientId;\n }, [user?.clientId, selectedClientId]);\n\n /**\n * Update the selected client ID (persists to sessionStorage + URL)\n */\n const setClientId = useCallback((id: string | null) => {\n if (isLocked) return;\n if (id) {\n sessionStorage.setItem(SESSION_KEY, id);\n } else {\n sessionStorage.removeItem(SESSION_KEY);\n }\n setSelectedClientId(id);\n }, [isLocked]);\n\n const value = useMemo(() => ({\n clientId,\n setClientId,\n isLocked\n }), [clientId, setClientId, isLocked]);\n\n return (\n <ClientContext.Provider value={value}>\n {children}\n </ClientContext.Provider>\n );\n};\n\nClientProvider.displayName = \"ClientProvider\";\n\nexport default ClientProvider;","/**\n * Error message used to identify GraphQL errors\n */\nexport const GRAPHQL_ERROR = \"GraphQL Error\";\n"],"names":["React","config","node","ConnectedUserFragment","_ConnectedUserFragment_user","ConnectedUserProviderQueryNode","_ConnectedUserProviderQuery","RefreshMutationNode","_ConnectedUserProviderRefreshMutation","ConnectedUserProviderInner","forwardRef","props","ref","queryRef","onMutationSuccess","alertMessage","useAlertMessages","intl","useIntl","updateLocale","useLocale","data","usePreloadedQuery","user","useFragment","connectedUser","accessTokenExpireIn","setAccessTokenExpireIn","useState","_webserviceBuffer","setWebserviceBuffer","isRefreshInflightRef","useRef","refreshCallbacksRef","commitLogin","isLoginInflight","useMutation","_ConnectedUserProviderLoginMutation","commitRefresh","commitLogout","isLogoutInflight","_ConnectedUserProviderLogoutMutation","commitLysRefresh","useCallback","current","variables","onCompleted","response","errors","length","refreshAccessToken","onError","error","clearRelayCache","relayError","source","locale","forEach","err","message","isErrorKey","console","merge","text","errorTranslations","UNKNOWN_ERROR","level","commitLysLogin","login","password","inputs","commitLysLogout","formatMessage","id","handleSessionExpired","onRefreshSuccess","push","callbacks","cb","webservice","timeStampSecondNow","Date","now","isValid","prev","useEffect","currentBuffer","language","code","jsx","ConnectedUserContext","Provider","value","logout","refresh","children","displayName","ConnectedUserProvider","loadQuery","useQueryLoader","queryLoadedRef","commitInitialRefresh","fetchPolicy","handleMutationSuccess","checkOperationsPermission","checkOperationsPermissionUtil","query","_WebserviceAccessProviderQuery","QueryExecutor","onData","webservicesData","useMemo","allAccessibleWebservices","edges","map","edge","accessLevels","userAccessLevels","filter","ws","WebserviceAccessProvider","useConnectedUserInfo","t","useWebserviceAccessProviderTranslations","disposeQuery","hasError","setHasError","webservicesMap","setWebservicesMap","Map","handleQueryData","newMap","set","handleQueryError","includes","some","e","log","checkWebserviceAccess","webserviceName","snakeCaseName","toSnakeCase","has","getWebserviceAccessLevels","get","contextValue","jsxs","style","padding","textAlign","Fragment","ErrorBoundaryProvider","Suspense","fallback","WebserviceAccessContext","_a"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { I18nLocaleEnum } from "./types/index.js";
2
2
  import { c, a, b, e, l, n, t } from "./translationTools-CSKULpZZ.js";
3
3
  import { c as c2, e as e2, g, a as a2, b as b2, d, f, h, i, m, p, s, v } from "./routeTools-BVJY3epS.js";
4
- import { A, C, a as a3, b as b3, c as c3, E, F, G, L, d as d2, e as e3, f as f2, g as g2, P, R, S, U, W, u, h as h2, i as i2, j, k, l as l2, m as m2, n as n2, o, p as p2, q, r, s as s2, t as t2, v as v2, w, x, y } from "./constants-DEt8avUj.js";
4
+ import { A, C, a as a3, b as b3, c as c3, E, F, G, L, d as d2, e as e3, f as f2, g as g2, P, R, S, U, W, u, h as h2, i as i2, j, k, l as l2, m as m2, n as n2, o, p as p2, q, r, s as s2, t as t2, v as v2, w, x, y } from "./constants-U3LBcAa7.js";
5
5
  import { u as u2, a as a4 } from "./hooks-CvhFUowR.js";
6
6
  import { R as R2, c as c4, a as a5 } from "./RelayEnvironment-D880U9SM.js";
7
7
  import { P as P2 } from "./PublicAppTemplate-SRJ1HtD0.js";
@@ -20,6 +20,8 @@ export interface PageContextValue {
20
20
  context: PageContext;
21
21
  /** Set pageName and params (called by RouteProvider) */
22
22
  setPageContext: (pageName: string, params?: Record<string, PageContextParamValue>) => void;
23
+ /** Merge additional params into current context without replacing existing ones */
24
+ updatePageParams: (additionalParams: Record<string, PageContextParamValue>) => void;
23
25
  /** Clear all context */
24
26
  clearPageContext: () => void;
25
27
  }
@@ -1,4 +1,4 @@
1
- import { A, C, a, b, c, E, F, G, L, d, e, f, g, P, R, S, U, W, u, h, i, j, k, l, m, n, o, p, q, r, s, t, v, w, x, y } from "../constants-DEt8avUj.js";
1
+ import { A, C, a, b, c, E, F, G, L, d, e, f, g, P, R, S, U, W, u, h, i, j, k, l, m, n, o, p, q, r, s, t, v, w, x, y } from "../constants-U3LBcAa7.js";
2
2
  import { u as u2, a as a2 } from "../hooks-CvhFUowR.js";
3
3
  import { c as c2 } from "../RelayEnvironment-D880U9SM.js";
4
4
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runid-lys",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Frontend framework library for the lys ecosystem — providers, hooks, tools, and types for React applications",
5
5
  "keywords": [
6
6
  "react",
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants-DEt8avUj.js","sources":["../src/providers/ErrorBoundaryProvider/index.tsx","../src/providers/FilterLabelsProvider/hooks.ts","../src/providers/FilterLabelsProvider/index.tsx","../src/providers/PageContextProvider/hooks.ts","../src/providers/PageContextProvider/index.tsx","../src/providers/LysQueryProvider/RefreshSignalContext.ts","../src/providers/ChatbotProvider/index.tsx","../src/providers/UrlQueriesProvider/hooks.ts","../src/providers/UrlQueriesProvider/index.tsx","../src/providers/AlertMessageProvider/hooks.ts","../src/providers/AlertMessageProvider/index.tsx","../src/providers/LocaleProvider/index.tsx","../src/providers/LysDialogProvider/hooks.ts","../src/providers/LysDialogProvider/reducer.ts","../src/providers/LysDialogProvider/index.tsx","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderLogoutMutation.graphql.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderLoginMutation.graphql.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderRefreshMutation.graphql.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserProviderQuery.graphql.ts","../src/providers/LocaleProvider/hooks.ts","../src/providers/ConnectedUserProvider/__generated__/ConnectedUserFragment_user.graphql.ts","../src/providers/ConnectedUserProvider/ConnectedUserFragment.ts","../src/providers/ConnectedUserProvider/index.tsx","../src/providers/WebserviceAccessProvider/__generated__/WebserviceAccessProviderQuery.graphql.ts","../src/providers/WebserviceAccessProvider/hooks.ts","../src/providers/WebserviceAccessProvider/translations.ts","../src/providers/WebserviceAccessProvider/index.tsx","../src/providers/SignalProvider/hooks.ts","../src/providers/SignalProvider/index.tsx","../src/providers/LysQueryProvider/hooks.ts","../src/providers/hooks/usePermissionCheck.ts","../src/providers/LysQueryProvider/LysLoadingContext.ts","../src/providers/LysQueryProvider/index.tsx","../src/providers/LysMutationProvider/hooks.ts","../src/providers/LysMutationProvider/index.tsx","../src/providers/ClientProvider/hooks.ts","../src/providers/ClientProvider/index.tsx","../src/providers/LysQueryProvider/constants.ts"],"sourcesContent":["import React, {ReactNode} from \"react\";\n\ninterface Props {\n onError?: ((error: Error) => void) | undefined\n children: ReactNode\n fallback?: ReactNode\n}\n\ninterface State {\n hasError: boolean\n error: Error | null\n}\n\n/**\n * Error boundary component\n * Catches React rendering errors and calls onError callback\n *\n * Important: onError is called in componentDidCatch (not render) to allow\n * state updates in the callback without React warnings.\n */\nclass ErrorBoundaryProvider extends React.Component<Props, State> {\n state: State = {hasError: false, error: null};\n\n static getDerivedStateFromError(error: Error): State {\n // Update state so next render shows fallback UI\n return {hasError: true, error};\n }\n\n componentDidCatch(error: Error, _errorInfo: React.ErrorInfo) {\n // Call onError callback for side effects (logging, state updates, etc.)\n // This is the correct place for side effects, not render()\n if (this.props.onError) {\n this.props.onError(error);\n }\n }\n\n render() {\n const {children, fallback = null} = this.props;\n const {hasError} = this.state;\n\n // When there's an error, render fallback (or null) instead of children\n // This prevents the infinite loop where children keep throwing\n if (hasError) {\n return fallback;\n }\n\n return children;\n }\n}\n\nexport default ErrorBoundaryProvider\n","import {createContext, useContext} from \"react\";\n\n/**\n * Filter labels context type\n */\ninterface FilterLabelsContextType {\n /**\n * Set a label for a filter value\n */\n setLabel: (key: string, label: string) => void;\n\n /**\n * Get a label for a filter value (returns value if not found)\n */\n getLabel: (key: string) => string;\n}\n\n/**\n * Filter labels context\n */\nconst FilterLabelsContext = createContext<FilterLabelsContextType>({\n setLabel: () => {\n console.warn(\"FilterLabelsProvider not initialized: setLabel\");\n },\n getLabel: (key: string) => key\n});\n\n/**\n * Hook to access filter labels context\n */\nfunction useFilterLabels() {\n return useContext(FilterLabelsContext);\n}\n\nexport {\n FilterLabelsContext,\n useFilterLabels\n};\n","import React from \"react\";\nimport {FilterLabelsContext} from \"./hooks\";\n\n/**\n * LocalStorage key for persisting filter labels\n */\nconst STORAGE_KEY = \"lys-filter-labels\";\n\n/**\n * FilterLabelsProvider props\n */\ninterface FilterLabelsProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Load labels from localStorage\n */\nconst loadFromStorage = (): Record<string, string> => {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n return stored ? JSON.parse(stored) : {};\n } catch {\n return {};\n }\n};\n\n/**\n * Save a label to localStorage\n */\nconst saveLabel = (key: string, label: string): void => {\n try {\n const labels = loadFromStorage();\n labels[key] = label;\n localStorage.setItem(STORAGE_KEY, JSON.stringify(labels));\n } catch {\n // Ignore storage errors (quota exceeded, etc.)\n }\n};\n\n/**\n * Get a label from localStorage (returns the key itself if not found)\n */\nconst getLabel = (key: string): string => {\n const labels = loadFromStorage();\n return labels[key] || key;\n};\n\n/**\n * FilterLabelsProvider component\n *\n * Global provider that stores display labels for filter values.\n * Used to show human-readable labels in active filter badges\n * instead of raw values (IDs, codes, etc.).\n *\n * Labels are stored directly in localStorage (no React state).\n *\n * Usage:\n * - SelectElement calls setLabel(value, label) when selection changes\n * - SearchFilterFeature calls getLabel(value) to display the label\n */\nconst FilterLabelsProvider: React.FC<FilterLabelsProviderProps> = ({children}) => {\n return (\n <FilterLabelsContext.Provider value={{setLabel: saveLabel, getLabel}}>\n {children}\n </FilterLabelsContext.Provider>\n );\n};\n\nFilterLabelsProvider.displayName = \"FilterLabelsProvider\";\n\nexport default FilterLabelsProvider;\n","import {createContext, useContext, useMemo} from \"react\";\nimport {PageContext, PageContextValue} from \"./types\";\n\nexport const PageContextContext = createContext<PageContextValue | null>(null);\n\n/**\n * Default context value when PageContextProvider is not in the tree.\n * All functions are no-ops, allowing the app to work without the provider.\n */\nconst DEFAULT_CONTEXT: PageContext = {\n pageName: null,\n params: {}\n};\n\n/**\n * Hook to access page context.\n * Returns a working context even if PageContextProvider is not mounted.\n * This allows the app to function without the provider (graceful degradation).\n */\nexport const usePageContext = (): PageContextValue => {\n const context = useContext(PageContextContext);\n\n // Memoize fallback to avoid creating new objects on each render\n const fallback = useMemo<PageContextValue>(() => ({\n context: DEFAULT_CONTEXT,\n setPageContext: () => {},\n clearPageContext: () => {}\n }), []);\n\n return context ?? fallback;\n};\n","import React, {useState, useCallback, useMemo} from \"react\";\nimport {PageContextContext} from \"./hooks\";\nimport {PageContext, PageContextParamValue} from \"./types\";\n\ninterface PageContextProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * PageContextProvider component\n *\n * Provides page context tracking for chatbot context-aware features:\n * - Current page name (e.g., \"FinancialDashboardPage\")\n * - Page params (e.g., {companyId: \"123\", year: 2024})\n *\n * This context is sent to the chatbot to:\n * - Filter available tools by page\n * - Inject params into mutations for security\n * - Reduce AI hallucinations by providing explicit context\n *\n * Place this provider above ChatbotProvider in the component tree.\n */\nconst PageContextProvider: React.FC<PageContextProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [context, setContext] = useState<PageContext>({\n pageName: null,\n params: {}\n });\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Set the current page context (pageName + params).\n * Called by RouteProvider when route or URL params change.\n */\n const setPageContext = useCallback((\n pageName: string,\n params: Record<string, PageContextParamValue> = {}\n ) => {\n setContext({pageName, params});\n }, []);\n\n /**\n * Clear the page context.\n */\n const clearPageContext = useCallback(() => {\n setContext({pageName: null, params: {}});\n }, []);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n const contextValue = useMemo(() => ({\n context,\n setPageContext,\n clearPageContext\n }), [context, setPageContext, clearPageContext]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <PageContextContext.Provider value={contextValue}>\n {children}\n </PageContextContext.Provider>\n );\n};\n\nexport default PageContextProvider;\n","import {createContext, useContext} from \"react\";\n\nexport interface RefreshSignal {\n nodes: string[];\n version: number;\n}\n\nconst RefreshSignalContext = createContext<RefreshSignal>({nodes: [], version: 0});\n\nexport const useRefreshSignal = (): RefreshSignal => {\n return useContext(RefreshSignalContext);\n};\n\nexport default RefreshSignalContext;\n","import React, {useState, useCallback, useMemo} from \"react\";\nimport {ChatbotContext} from \"./hooks\";\nimport {ChatMessage, RefreshSignal} from \"./types\";\nimport RefreshSignalContext from \"../LysQueryProvider/RefreshSignalContext\";\n\ninterface ChatbotProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * ChatbotProvider component\n *\n * Provides global chatbot state management:\n * - Message history persistence across page navigation\n * - Conversation ID tracking\n * - Chatbot mode state (open/closed)\n *\n * Place this provider high in the component tree (above RouteProvider)\n * to ensure state persists across route changes.\n */\nconst ChatbotProvider: React.FC<ChatbotProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [conversationId, setConversationId] = useState<string | null>(null);\n const [isChatbotMode, setIsChatbotMode] = useState<boolean>(false);\n const [isChatbotEnabled, setIsChatbotEnabled] = useState<boolean>(true);\n const [isStreaming, setIsStreaming] = useState<boolean>(false);\n const [refreshSignal, setRefreshSignal] = useState<RefreshSignal>({nodes: [], version: 0});\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Add a single message to the conversation\n */\n const addMessage = useCallback((message: ChatMessage) => {\n setMessages(prev => [...prev, message]);\n }, []);\n\n /**\n * Append content to the last assistant message (for streaming)\n */\n const updateLastMessage = useCallback((contentDelta: string) => {\n setMessages(prev => {\n if (prev.length === 0) return prev;\n const last = prev[prev.length - 1];\n if (last.role !== \"assistant\") return prev;\n const updated = [...prev];\n updated[updated.length - 1] = {...last, content: last.content + contentDelta};\n return updated;\n });\n }, []);\n\n /**\n * Clear the conversation and reset state\n */\n const clearConversation = useCallback(() => {\n setMessages([]);\n setConversationId(null);\n }, []);\n\n /**\n * Trigger a refresh signal for the specified node types\n * LysQueryProvider instances listening to these nodes will refetch their data\n */\n const triggerRefresh = useCallback((nodes: string[]) => {\n setRefreshSignal(prev => ({\n nodes,\n version: prev.version + 1\n }));\n }, []);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n const contextValue = useMemo(() => ({\n messages,\n conversationId,\n isChatbotMode,\n isChatbotEnabled,\n isStreaming,\n refreshSignal,\n setMessages,\n setConversationId,\n setIsChatbotMode,\n setIsChatbotEnabled,\n setIsStreaming,\n addMessage,\n updateLastMessage,\n clearConversation,\n triggerRefresh\n }), [messages, conversationId, isChatbotMode, isChatbotEnabled, isStreaming, refreshSignal, addMessage, updateLastMessage, clearConversation, triggerRefresh]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <ChatbotContext.Provider value={contextValue}>\n <RefreshSignalContext.Provider value={refreshSignal}>\n {children}\n </RefreshSignalContext.Provider>\n </ChatbotContext.Provider>\n );\n};\n\nexport default ChatbotProvider;\n","import {createContext, useContext} from \"react\";\nimport {UrlQueryValue} from \"./types\";\n\nconst UrlQueriesContext = createContext<{\n hasStagedChanges: boolean;\n appliedParams: URLSearchParams;\n stagedParams: {[key: string]: UrlQueryValue};\n stage: (key: string, value: UrlQueryValue) => void;\n edit: (key: string, value: UrlQueryValue) => void;\n update: (data: {[key: string]: UrlQueryValue}) => void;\n apply: () => void;\n}>({\n hasStagedChanges: false,\n appliedParams: new URLSearchParams(),\n stagedParams: {},\n stage: () => console.error(\"stage not implemented\"),\n edit: () => console.error(\"edit not implemented\"),\n update: () => console.error(\"update not implemented\"),\n apply: () => console.error(\"apply not implemented\")\n});\n\n/**\n * Hook to access URL query parameters with staging support\n *\n * Features:\n * - appliedParams: Current URL search params\n * - stagedParams: Staged changes not yet applied to URL\n * - edit(): Apply a single change immediately to URL\n * - stage(): Stage a change without updating URL\n * - apply(): Apply all staged changes at once\n * - update(): Update multiple params directly\n * - hasStagedChanges: Whether there are unapplied staged changes\n */\nconst useUrlQueries = () => {\n return useContext(UrlQueriesContext);\n};\n\nexport {\n UrlQueriesContext,\n useUrlQueries,\n};\n","import * as React from \"react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState\n} from \"react\";\nimport {useSearchParams} from \"react-router-dom\";\nimport {UrlQueriesContext} from \"./hooks\";\nimport {UrlQueriesProviderProps, UrlQueryValue} from \"./types\";\n\n/**\n * UrlQueriesProvider - Manages URL query parameters with staging support\n *\n * Features:\n * - Synchronizes URL search params with React state\n * - Supports staged changes via stagedParams\n * - Type conversion (string → number/boolean)\n * - Batch updates with apply()\n *\n * Use cases:\n * - Filter bars: Stage multiple filter changes, apply all at once\n * - Form state: Keep form state in URL for sharing/bookmarking\n * - Pagination: Track page/limit in URL\n */\nconst UrlQueriesProvider: React.ComponentType<UrlQueriesProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const [searchParams, setSearchParams] = useSearchParams();\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [initialized, setInitialized] = useState<boolean>(false);\n const [stagedParams, setStagedParams] = useState<{[key: string]: UrlQueryValue}>({});\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n /**\n * Check if staged params differ from current URL\n */\n const hasStagedChanges: boolean = useMemo(() => {\n return Object.keys(stagedParams).some(key =>\n stagedParams[key]?.toString() !== searchParams.get(key)\n );\n }, [searchParams, stagedParams]);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Stage a change without updating URL\n * Useful for filter bars where user configures multiple filters before applying\n */\n const stage = useCallback((key: string, value: UrlQueryValue) => {\n setStagedParams(prev => {\n if (prev[key]?.toString() === value?.toString()) {\n return prev;\n }\n return {...prev, [key]: value};\n });\n }, []);\n\n /**\n * Apply change immediately to URL\n */\n const edit = useCallback((key: string, value: UrlQueryValue) => {\n stage(key, value);\n setSearchParams(prev => {\n if (value !== undefined && value !== null) {\n prev.set(key, value.toString());\n } else {\n prev.delete(key);\n }\n return prev;\n });\n }, [stage, setSearchParams]);\n\n /**\n * Apply all staged changes to URL\n */\n const apply = useCallback(() => {\n const newSearchParams = new URLSearchParams();\n\n Object.entries(stagedParams).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n newSearchParams.set(key, value.toString());\n }\n });\n\n setSearchParams(newSearchParams);\n }, [stagedParams, setSearchParams]);\n\n /**\n * Batched update: accumulates changes from multiple update() calls\n * within the same microtask and flushes them in a single setSearchParams call.\n *\n * Why batching is needed:\n * react-router's setSearchParams does NOT chain functional updates like React's\n * setState — each call gets the same `prev` snapshot. When multiple components\n * call update() in the same effect cycle (e.g. ClientProvider sets clientId while\n * DashboardFiltersFeature resets companyId), the last call would overwrite the first.\n * Batching via queueMicrotask merges all pending changes into one setSearchParams call.\n */\n const pendingUpdatesRef = useRef<{[key: string]: UrlQueryValue}>({});\n const flushScheduledRef = useRef(false);\n\n const update = useCallback((data: {[key: string]: UrlQueryValue}) => {\n Object.assign(pendingUpdatesRef.current, data);\n\n if (!flushScheduledRef.current) {\n flushScheduledRef.current = true;\n queueMicrotask(() => {\n flushScheduledRef.current = false;\n const pending = {...pendingUpdatesRef.current};\n pendingUpdatesRef.current = {};\n\n setSearchParams(prev => {\n const next = new URLSearchParams(prev);\n Object.entries(pending).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n next.set(key, value.toString());\n } else {\n next.delete(key);\n }\n });\n return next;\n });\n });\n }\n }, [setSearchParams]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Initialize stagedParams from URL on mount\n * Converts string values to appropriate types (number, boolean)\n */\n useEffect(() => {\n const newTmpParameters: {[key: string]: UrlQueryValue} = {};\n\n searchParams.forEach((value, key) => {\n // Convert to number if possible\n if (!isNaN(+value)) {\n newTmpParameters[key] = Number(value);\n }\n // Convert to boolean if \"true\" or \"false\"\n else if (value === \"true\" || value === \"false\") {\n newTmpParameters[key] = value === \"true\";\n }\n // Keep as string\n else {\n newTmpParameters[key] = value;\n }\n });\n\n if (Object.keys(newTmpParameters).length) {\n setStagedParams(newTmpParameters);\n }\n\n setInitialized(true);\n }, [searchParams]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <UrlQueriesContext.Provider\n value={{\n hasStagedChanges,\n appliedParams: searchParams,\n stagedParams,\n stage,\n edit,\n update,\n apply\n }}\n >\n {initialized && children}\n </UrlQueriesContext.Provider>\n );\n};\n\nexport default UrlQueriesProvider;\n","import {createContext, useContext} from \"react\";\nimport {AlertMessageInterface} from \"./types\";\n\n/**\n * Alert message context\n */\nconst AlertMessageContext = createContext<{\n merge(messages: AlertMessageInterface[]): void\n}>({\n merge: () => {\n console.warn(\"AlertMessageProvider not initialized\")\n }\n});\n\n/**\n * Hook to access alert messages\n */\nfunction useAlertMessages() {\n return useContext(AlertMessageContext)\n}\n\nexport {\n AlertMessageContext,\n useAlertMessages\n}\n","import * as React from \"react\";\nimport {useState, useCallback, useRef} from \"react\";\nimport {\n AlertMessageProviderProps,\n DatedAlertMessageType\n} from \"./types\";\nimport { AlertMessageContext } from \"./hooks\";\n\n/**\n * Alert message provider\n * Manages centralized alert/error display\n *\n * Requires an alertGenerator function to render alerts.\n */\nconst AlertMessageProvider: React.ComponentType<AlertMessageProviderProps> = (\n {\n children,\n alertGenerator,\n }) => {\n\n /*******************************************************************************************************************\n * STATES\n * ****************************************************************************************************************/\n\n const [messages, setMessages] = useState<DatedAlertMessageType[]>([])\n const messageIdCounter = useRef(0);\n\n /*******************************************************************************************************************\n * CALLBACKS\n * ****************************************************************************************************************/\n\n /**\n * Remove a message by index\n */\n const handleRemove = useCallback((index: number) => {\n setMessages(prev => prev.filter((_, i) => i !== index));\n }, []);\n\n /**\n * Merge new messages into the state\n */\n const handleMerge = useCallback((messages_: { text: string; level: string }[]) => {\n if (messages_.length > 0) {\n const datedMessages = messages_.map((message) => {\n // Log to console\n const logMethod = message.level === \"CRITICAL\" || message.level === \"ERROR\"\n ? console.error\n : message.level === \"WARNING\"\n ? console.warn\n : console.log;\n\n logMethod(`[${message.level}]`, message.text);\n\n // Generate unique ID\n messageIdCounter.current += 1;\n const uniqueId = `alert-${Date.now()}-${messageIdCounter.current}`;\n\n return {\n ...message,\n id: uniqueId,\n createdAt: new Date()\n }\n }) as DatedAlertMessageType[];\n setMessages(prev => [...prev, ...datedMessages]);\n }\n }, []);\n\n /*******************************************************************************************************************\n * RENDER\n * ****************************************************************************************************************/\n\n return(\n <>\n <AlertMessageContext.Provider value={{\n merge: handleMerge\n }}>\n {children}\n </AlertMessageContext.Provider>\n {alertGenerator(messages, handleRemove)}\n </>\n );\n};\n\nexport default AlertMessageProvider;\n","import React, {createContext, useState, useCallback, useMemo} from \"react\";\nimport {IntlProvider} from \"react-intl\";\nimport {LocaleProviderProps, LocaleContextInterface} from \"./types\";\n\n/**\n * LocaleProvider context\n */\nexport const LocaleContext = createContext<LocaleContextInterface | undefined>(undefined);\n\n/**\n * LocaleProvider component\n *\n * Wraps IntlProvider and provides a hook to dynamically change locale\n * Used by ConnectedUserProvider to update locale based on user's language preference\n */\nconst LocaleProvider: React.FC<LocaleProviderProps> = ({defaultLocale, messageSources, children}) => {\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [locale, setLocale] = useState<string>(defaultLocale);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Update locale\n */\n const updateLocale = useCallback((newLocale: string) => {\n setLocale(newLocale);\n }, []);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n /**\n * Get messages for the current locale from the provided message sources\n */\n const messages = useMemo(() => {\n return messageSources[locale] || {};\n }, [locale, messageSources]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <LocaleContext.Provider value={{locale, updateLocale}}>\n <IntlProvider locale={locale} messages={messages}>\n {children}\n </IntlProvider>\n </LocaleContext.Provider>\n );\n};\n\nexport default LocaleProvider;\n","import { createContext, useCallback, useContext, useEffect, useMemo, useRef } from \"react\"\nimport { ComponentType } from \"react\"\nimport { LysDialogContextValue, DialogSize, DialogPlacement } from \"./types\"\n\n/**\n * Default context value with error handlers\n */\nconst defaultContextValue: LysDialogContextValue = {\n current: null,\n stack: [],\n isOpen: false,\n canGoBack: false,\n open: () => {\n console.error(\"useLysDialog: open() called outside of LysDialogProvider\")\n },\n update: () => {\n console.error(\"useLysDialog: update() called outside of LysDialogProvider\")\n },\n close: () => {\n console.error(\"useLysDialog: close() called outside of LysDialogProvider\")\n },\n back: () => {\n console.error(\"useLysDialog: back() called outside of LysDialogProvider\")\n },\n closeAll: () => {\n console.error(\"useLysDialog: closeAll() called outside of LysDialogProvider\")\n },\n register: () => {\n console.error(\"useLysDialog: register() called outside of LysDialogProvider\")\n return () => {}\n },\n getExpectedKeys: () => {\n console.error(\"useLysDialog: getExpectedKeys() called outside of LysDialogProvider\")\n return []\n }\n}\n\n/**\n * Dialog context\n */\nexport const LysDialogContext = createContext<LysDialogContextValue>(defaultContextValue)\n\n/**\n * Hook to access dialog context\n *\n * Usage:\n * ```tsx\n * const dialog = useLysDialog()\n *\n * // Open a dialog\n * dialog.open({\n * uniqueKey: \"my-dialog\",\n * title: \"My Dialog\",\n * body: <div>Content</div>\n * })\n *\n * // Close current dialog (return to previous)\n * dialog.close()\n *\n * // Close all dialogs\n * dialog.closeAll()\n * ```\n */\nexport const useLysDialog = (): LysDialogContextValue => {\n return useContext(LysDialogContext)\n}\n\n/**\n * Configuration for useDialogWithUpdates hook\n */\nexport interface UseDialogWithUpdatesConfig<P extends Record<string, any>> {\n /**\n * Unique key for the dialog\n */\n uniqueKey: string\n\n /**\n * Dialog title\n */\n title: string\n\n /**\n * Body component (not JSX, the component itself)\n */\n body: ComponentType<P>\n\n /**\n * Props to pass to the body component\n * These will be automatically updated when they change\n */\n bodyProps: P\n\n /**\n * Dependencies array to trigger bodyProps updates\n * Only when these values change will the dialog be updated\n * This avoids infinite loops caused by unstable object references\n *\n * @example\n * // Update only when data or isLoading changes\n * deps: [data, isLoading]\n */\n deps?: React.DependencyList\n\n /**\n * Dialog size\n * @default \"md\"\n */\n size?: DialogSize\n\n /**\n * Dialog placement\n * @default \"end\"\n */\n placement?: DialogPlacement\n\n /**\n * Backdrop behavior\n * @default true\n */\n backdrop?: boolean | \"static\"\n\n /**\n * Enable URL synchronization\n * @default true\n */\n syncWithUrl?: boolean\n}\n\n/**\n * Return type for useDialogWithUpdates hook\n */\nexport interface UseDialogWithUpdatesReturn {\n /**\n * Open the dialog\n */\n open: () => void\n\n /**\n * Close the dialog\n */\n close: () => void\n\n /**\n * The unique key of the dialog\n */\n uniqueKey: string\n\n /**\n * Whether this dialog is currently open\n */\n isOpen: boolean\n}\n\n/**\n * Hook for dialog with automatic updates\n *\n * This hook encapsulates the pattern of opening a dialog and automatically\n * updating its bodyProps when they change. It eliminates the need to manually\n * write useEffect for dialog.update().\n *\n * Usage:\n * ```tsx\n * const myDialog = useDialogWithUpdates({\n * uniqueKey: \"my-dialog\",\n * title: \"My Dialog\",\n * body: MyDialogBody,\n * bodyProps: { data, isLoading, onSubmit }\n * });\n *\n * // Open the dialog\n * <button onClick={myDialog.open}>Open</button>\n *\n * // The dialog will automatically update when bodyProps change\n * ```\n */\nexport function useDialogWithUpdates<P extends Record<string, any>>(\n config: UseDialogWithUpdatesConfig<P>\n): UseDialogWithUpdatesReturn {\n const {open, update, close, current} = useLysDialog();\n const {uniqueKey, title, body, bodyProps, deps, size = \"md\", placement = \"end\", backdrop, syncWithUrl} = config;\n\n /**\n * Store bodyProps in a ref to always have the latest value\n * without causing re-renders in useCallback dependencies\n */\n const bodyPropsRef = useRef(bodyProps);\n bodyPropsRef.current = bodyProps;\n\n /**\n * Check if this dialog is currently open\n */\n const isOpen = useMemo(() => current?.uniqueKey === uniqueKey, [current?.uniqueKey, uniqueKey]);\n\n /**\n * Track if dialog was opened to prevent updates before first open\n */\n const wasOpenedRef = useRef(false);\n\n /**\n * Open the dialog\n */\n const handleOpen = useCallback(() => {\n wasOpenedRef.current = true;\n open({\n uniqueKey,\n title,\n body,\n bodyProps: bodyPropsRef.current,\n size,\n placement,\n backdrop,\n syncWithUrl\n });\n }, [open, uniqueKey, title, body, size, placement, backdrop, syncWithUrl]);\n\n /**\n * Close the dialog\n */\n const handleClose = useCallback(() => {\n close();\n }, [close]);\n\n /**\n * Auto-update bodyProps when deps change (only if dialog is currently open)\n * Uses wasOpenedRef to prevent updates before the dialog was ever opened\n * Uses ref to get latest bodyProps without causing infinite loops\n *\n * If deps is not provided, no automatic updates will occur\n */\n useEffect(() => {\n if (isOpen && wasOpenedRef.current) {\n update(uniqueKey, {bodyProps: bodyPropsRef.current});\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen, uniqueKey, update, ...(deps || [])]);\n\n return {\n open: handleOpen,\n close: handleClose,\n uniqueKey,\n isOpen\n };\n}","import { DialogState, DialogAction } from \"./types\"\n\n/**\n * Initial state for dialog reducer\n */\nexport const initialDialogState: DialogState = {\n stack: []\n}\n\n/**\n * Dialog reducer to manage stack of dialogs\n *\n * Actions:\n * - INIT: Initialize stack from URL (used on mount)\n * - PUSH: Add a new dialog to the stack\n * - POP: Remove the last dialog from the stack (back button)\n * - CLEAR: Remove all dialogs from the stack (close all)\n * - UPDATE: Update props or title of an existing dialog\n */\nexport function dialogReducer(state: DialogState, action: DialogAction): DialogState {\n switch (action.type) {\n case \"INIT\":\n // Initialize stack (used when restoring from URL)\n return {\n ...state,\n stack: action.payload\n }\n\n case \"PUSH\":\n // Add new dialog to stack\n return {\n ...state,\n stack: [...state.stack, action.payload]\n }\n\n case \"POP\":\n // Remove last dialog from stack\n if (state.stack.length === 0) {\n return state\n }\n return {\n ...state,\n stack: state.stack.slice(0, -1)\n }\n\n case \"CLEAR\":\n // Remove all dialogs\n return {\n ...state,\n stack: []\n }\n\n case \"UPDATE\":\n // Update an existing dialog's props, title, or loading state\n return {\n ...state,\n stack: state.stack.map(dialog => {\n if (dialog.uniqueKey === action.payload.uniqueKey) {\n return {\n ...dialog,\n ...(action.payload.title !== undefined && { title: action.payload.title }),\n ...(action.payload.bodyProps !== undefined && { bodyProps: action.payload.bodyProps }),\n ...(action.payload.loading !== undefined && { loading: action.payload.loading })\n }\n }\n return dialog\n })\n }\n\n default:\n return state\n }\n}","import { ComponentType, useCallback, useEffect, useMemo, useReducer, useRef } from \"react\"\nimport { LysDialogContext } from \"./hooks\"\nimport { DialogComponentRefInterface, DialogConfig, DialogUpdatePayload, LysDialogProviderProps } from \"./types\"\nimport { dialogReducer, initialDialogState } from \"./reducer\"\nimport { useUrlQueries } from \"../UrlQueriesProvider/hooks\"\n\nconst DIALOG_STACK_PARAM = \"dStack\"\n\n/**\n * Check if value is a React component (function, class, forwardRef, memo, etc.)\n * NOT a React element (JSX)\n */\nconst isReactComponent = (value: unknown): value is ComponentType<any> => {\n // Function component or class component\n if (typeof value === 'function') return true\n\n // forwardRef, memo, lazy components are objects with $$typeof\n // but we need to exclude React elements which also have $$typeof\n if (\n typeof value === 'object' &&\n value !== null &&\n '$$typeof' in value\n ) {\n const symbolValue = (value as { $$typeof: symbol }).$$typeof\n\n // React elements have Symbol.for('react.element') - these are NOT components\n // They should be rendered as-is with <>{body}</>\n if (symbolValue === Symbol.for('react.element')) {\n return false\n }\n\n // forwardRef has Symbol.for('react.forward_ref')\n // memo has Symbol.for('react.memo')\n // lazy has Symbol.for('react.lazy')\n // These ARE components that need to be instantiated\n return true\n }\n\n return false\n}\n\n/**\n * DialogChild component\n * Renders the dialog body, handling both ReactNode and ComponentType\n * If body is a component, it will receive bodyProps\n */\nconst DialogChild: React.FC<{ body: DialogConfig['body']; bodyProps?: Record<string, any> }> = ({ body, bodyProps }) => {\n if (isReactComponent(body)) {\n const Component = body\n return <Component {...(bodyProps || {})} />\n }\n\n // Otherwise, render as ReactNode\n return <>{body}</>\n}\n\n/**\n * LysDialogProvider\n *\n * Provides dialog management with stack support using an injectable dialog component\n *\n * Features:\n * - Stack-based dialogs (dialogs can open on top of each other)\n * - Back button to return to previous dialog\n * - Close button to close all dialogs\n * - Backdrop click closes all dialogs\n * - Optional URL synchronization\n * - Injectable dialog component, loading fallback, back icon, and extra rendering\n */\nconst LysDialogProvider: React.FC<LysDialogProviderProps> = ({\n children,\n syncWithUrl = true,\n dialogComponent: DialogComponent,\n loadingFallback = null,\n backIcon = null,\n renderExtra\n}) => {\n const [state, dispatch] = useReducer(dialogReducer, initialDialogState)\n const urlQueries = syncWithUrl ? useUrlQueries() : null\n const dialogRefs = useRef<Map<string, DialogComponentRefInterface>>(new Map())\n const dialogRegistry = useRef<Map<string, Omit<DialogConfig, 'uniqueKey'>>>(new Map())\n const initializedFromUrl = useRef(false)\n\n // Get current dialog (last in stack)\n const current = useMemo(() => {\n return state.stack.length > 0 ? state.stack[state.stack.length - 1] : null\n }, [state.stack])\n\n // Check if we can go back\n const canGoBack = useMemo(() => {\n return state.stack.length > 1\n }, [state.stack])\n\n // Check if any dialog is open\n const isOpen = useMemo(() => {\n return state.stack.length > 0\n }, [state.stack])\n\n // Open a new dialog (push to stack)\n const open = useCallback((config: DialogConfig) => {\n dispatch({ type: \"PUSH\", payload: config })\n }, [])\n\n // Update an existing dialog's props or title\n const update = useCallback((uniqueKey: string, updates: Omit<DialogUpdatePayload, 'uniqueKey'>) => {\n dispatch({ type: \"UPDATE\", payload: { uniqueKey, ...updates } })\n }, [])\n\n // Close current dialog (pop from stack)\n const close = useCallback(() => {\n dispatch({ type: \"POP\" })\n }, [])\n\n // Alias for close\n const back = close\n\n // Close all dialogs (clear stack)\n const closeAll = useCallback(() => {\n dispatch({ type: \"CLEAR\" })\n }, [])\n\n // Register a dialog for deep linking\n const register = useCallback((uniqueKey: string, config: Omit<DialogConfig, 'uniqueKey'>) => {\n dialogRegistry.current.set(uniqueKey, config)\n\n // Return cleanup function\n return () => {\n dialogRegistry.current.delete(uniqueKey)\n }\n }, [])\n\n // Get expected dialog keys from URL\n const getExpectedKeys = useCallback((): string[] => {\n if (!syncWithUrl || !urlQueries) return []\n\n const stackParam = urlQueries.appliedParams.get(DIALOG_STACK_PARAM)\n if (!stackParam) return []\n\n return stackParam.split(',').filter(Boolean)\n }, [syncWithUrl, urlQueries])\n\n // Show/hide dialog based on current dialog\n useEffect(() => {\n if (current) {\n const ref = dialogRefs.current.get(current.uniqueKey)\n if (ref && ref.shown === null) {\n ref.show()\n }\n }\n }, [current])\n\n // Handle dialog hide event (when user closes it)\n const handleDialogHide = useCallback((uniqueKey: string) => {\n const ref = dialogRefs.current.get(uniqueKey)\n if (ref?.shown === false) {\n // Close all when dialog is manually closed\n closeAll()\n }\n }, [closeAll])\n\n // Sync stack with URL\n useEffect(() => {\n if (!syncWithUrl || !urlQueries) return\n\n // Don't sync URL until initialization is complete\n // This prevents clearing dStack param before we read it on mount\n if (!initializedFromUrl.current) return\n\n const stackParam = urlQueries.appliedParams.get(DIALOG_STACK_PARAM)\n\n // Filter dialogs that want URL synchronization (syncWithUrl !== false)\n const urlSyncedDialogs = state.stack.filter(d => d.syncWithUrl !== false)\n\n if (urlSyncedDialogs.length > 0) {\n // Update URL with current stack keys (only for dialogs with URL sync enabled)\n const stackKeys = urlSyncedDialogs.map(d => d.uniqueKey).join(\",\")\n if (stackParam !== stackKeys) {\n urlQueries.edit(DIALOG_STACK_PARAM, stackKeys)\n }\n } else {\n // Clear URL param when no dialogs want URL sync\n if (stackParam) {\n urlQueries.edit(DIALOG_STACK_PARAM, null)\n }\n }\n }, [state.stack, syncWithUrl, urlQueries])\n\n // Initialize stack from URL on mount\n useEffect(() => {\n if (!syncWithUrl || !urlQueries || initializedFromUrl.current) return\n\n const expectedKeys = getExpectedKeys()\n if (expectedKeys.length === 0) {\n initializedFromUrl.current = true\n return\n }\n\n // Wait for all dialogs to register themselves\n // This happens after children mount\n const checkInterval = setInterval(() => {\n const configs: DialogConfig[] = []\n\n for (const key of expectedKeys) {\n const config = dialogRegistry.current.get(key)\n if (config) {\n configs.push({ uniqueKey: key, ...config })\n }\n }\n\n // If all expected dialogs are registered, initialize stack\n if (configs.length === expectedKeys.length) {\n clearInterval(checkInterval)\n dispatch({ type: \"INIT\", payload: configs })\n initializedFromUrl.current = true\n }\n }, 50)\n\n // Cleanup: stop checking after 2 seconds\n const timeout = setTimeout(() => {\n clearInterval(checkInterval)\n initializedFromUrl.current = true\n }, 2000)\n\n return () => {\n clearInterval(checkInterval)\n clearTimeout(timeout)\n }\n }, [syncWithUrl, urlQueries, getExpectedKeys])\n\n // Context value\n const contextValue = useMemo(() => ({\n current,\n stack: state.stack,\n isOpen,\n canGoBack,\n open,\n update,\n close,\n back,\n closeAll,\n register,\n getExpectedKeys\n }), [current, state.stack, isOpen, canGoBack, open, update, close, back, closeAll, register, getExpectedKeys])\n\n // Build title with optional back button\n const dialogTitle = useMemo(() => {\n if (!current) return null\n\n return (\n <div className=\"d-flex align-items-center w-100\">\n {/* Back button (only visible when stack > 1) */}\n {canGoBack && (\n <button\n type=\"button\"\n className=\"btn btn-link text-decoration-none p-0 me-3\"\n onClick={close}\n aria-label=\"Back to previous dialog\"\n >\n {backIcon}\n </button>\n )}\n {/* Title */}\n <div className=\"flex-grow-1\">\n {current.title}\n </div>\n </div>\n )\n }, [current, canGoBack, close, backIcon])\n\n return (\n <LysDialogContext.Provider value={contextValue}>\n {/* Render only the current dialog */}\n {current && (\n <>\n <DialogComponent\n key={current.uniqueKey}\n ref={(ref) => {\n if (ref) {\n dialogRefs.current.set(current.uniqueKey, ref)\n // Monitor shown state\n if (ref.shown === false) {\n handleDialogHide(current.uniqueKey)\n }\n }\n }}\n id={`lys-dialog-${current.uniqueKey}`}\n title={dialogTitle ?? undefined}\n body={current.loading ? loadingFallback : (\n <DialogChild body={current.body} bodyProps={current.bodyProps} />\n )}\n size={current.size}\n placement={current.placement}\n backdrop={current.backdrop}\n />\n {renderExtra?.(current)}\n </>\n )}\n {children}\n </LysDialogContext.Provider>\n )\n}\n\nexport default LysDialogProvider\n","/**\n * @generated SignedSource<<181ab0892ed33a177cfebc96f2c700aa>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type ConnectedUserProviderLogoutMutation$variables = Record<PropertyKey, never>;\nexport type ConnectedUserProviderLogoutMutation$data = {\n readonly logout: {\n readonly succeed: boolean;\n };\n};\nexport type ConnectedUserProviderLogoutMutation = {\n response: ConnectedUserProviderLogoutMutation$data;\n variables: ConnectedUserProviderLogoutMutation$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LogoutNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"logout\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"succeed\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderLogoutMutation\",\n \"selections\": (v0/*: any*/),\n \"type\": \"Mutation\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderLogoutMutation\",\n \"selections\": (v0/*: any*/)\n },\n \"params\": {\n \"cacheID\": \"5a1db66cb1f48dc468c728f5386b992f\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderLogoutMutation\",\n \"operationKind\": \"mutation\",\n \"text\": \"mutation ConnectedUserProviderLogoutMutation {\\n logout {\\n succeed\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"6b47911be54a6725f5b5744856395d69\";\n\nexport default node;\n","/**\n * @generated SignedSource<<df4394fb203bc9d769f54a19ff82c88b>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type LoginInput = {\n login: string;\n password: string;\n};\nexport type ConnectedUserProviderLoginMutation$variables = {\n inputs: LoginInput;\n};\nexport type ConnectedUserProviderLoginMutation$data = {\n readonly login: {\n readonly accessTokenExpireIn: number;\n readonly success: boolean;\n readonly xsrfToken: string;\n };\n};\nexport type ConnectedUserProviderLoginMutation = {\n response: ConnectedUserProviderLoginMutation$data;\n variables: ConnectedUserProviderLoginMutation$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = [\n {\n \"defaultValue\": null,\n \"kind\": \"LocalArgument\",\n \"name\": \"inputs\"\n }\n],\nv1 = [\n {\n \"alias\": null,\n \"args\": [\n {\n \"kind\": \"Variable\",\n \"name\": \"inputs\",\n \"variableName\": \"inputs\"\n }\n ],\n \"concreteType\": \"LoginNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"login\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"success\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"accessTokenExpireIn\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"xsrfToken\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": (v0/*: any*/),\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderLoginMutation\",\n \"selections\": (v1/*: any*/),\n \"type\": \"Mutation\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": (v0/*: any*/),\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderLoginMutation\",\n \"selections\": (v1/*: any*/)\n },\n \"params\": {\n \"cacheID\": \"99e672b3c15baa2a34b730cc8794299f\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderLoginMutation\",\n \"operationKind\": \"mutation\",\n \"text\": \"mutation ConnectedUserProviderLoginMutation(\\n $inputs: LoginInput!\\n) {\\n login(inputs: $inputs) {\\n success\\n accessTokenExpireIn\\n xsrfToken\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"2a03da8b6fb25fbb7f5171fa53732b31\";\n\nexport default node;\n","/**\n * @generated SignedSource<<ef60feb678597d8526aef19f960a05e6>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type ConnectedUserProviderRefreshMutation$variables = Record<PropertyKey, never>;\nexport type ConnectedUserProviderRefreshMutation$data = {\n readonly refreshAccessToken: {\n readonly accessTokenExpireIn: number;\n readonly success: boolean;\n readonly xsrfToken: string;\n };\n};\nexport type ConnectedUserProviderRefreshMutation = {\n response: ConnectedUserProviderRefreshMutation$data;\n variables: ConnectedUserProviderRefreshMutation$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LoginNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"refreshAccessToken\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"success\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"accessTokenExpireIn\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"xsrfToken\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderRefreshMutation\",\n \"selections\": (v0/*: any*/),\n \"type\": \"Mutation\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderRefreshMutation\",\n \"selections\": (v0/*: any*/)\n },\n \"params\": {\n \"cacheID\": \"d8f0fefdfba04eb7d4aa3bee34d0991c\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderRefreshMutation\",\n \"operationKind\": \"mutation\",\n \"text\": \"mutation ConnectedUserProviderRefreshMutation {\\n refreshAccessToken {\\n success\\n accessTokenExpireIn\\n xsrfToken\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"acbdb2f87ce474c94ae5a7b4ca0769c8\";\n\nexport default node;\n","/**\n * @generated SignedSource<<656875e1bf06623a68fff1a35296db4e>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nimport { FragmentRefs } from \"relay-runtime\";\nexport type ConnectedUserProviderQuery$variables = Record<PropertyKey, never>;\nexport type ConnectedUserProviderQuery$data = {\n readonly connectedUser: {\n readonly \" $fragmentSpreads\": FragmentRefs<\"ConnectedUserFragment_user\">;\n } | null | undefined;\n};\nexport type ConnectedUserProviderQuery = {\n response: ConnectedUserProviderQuery$data;\n variables: ConnectedUserProviderQuery$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"id\",\n \"storageKey\": null\n},\nv1 = [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"code\",\n \"storageKey\": null\n }\n];\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"connectedUser\",\n \"plural\": false,\n \"selections\": [\n {\n \"args\": null,\n \"kind\": \"FragmentSpread\",\n \"name\": \"ConnectedUserFragment_user\"\n }\n ],\n \"storageKey\": null\n }\n ],\n \"type\": \"Query\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"ConnectedUserProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"connectedUser\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"clientId\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserEmailAddressNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"emailAddress\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"address\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"createdAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"updatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"validatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastValidationRequestAt\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserStatusNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"status\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LanguageNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"language\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserPrivateDataNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"privateData\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"firstName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"GenderNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"gender\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n (v0/*: any*/)\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ]\n },\n \"params\": {\n \"cacheID\": \"654e16a74dc1101f903a371ee713c943\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"ConnectedUserProviderQuery\",\n \"operationKind\": \"query\",\n \"text\": \"query ConnectedUserProviderQuery {\\n connectedUser {\\n ...ConnectedUserFragment_user\\n id\\n }\\n}\\n\\nfragment ConnectedUserFragment_user on UserNode {\\n id\\n clientId\\n emailAddress {\\n id\\n address\\n createdAt\\n updatedAt\\n validatedAt\\n lastValidationRequestAt\\n }\\n status {\\n id\\n code\\n }\\n language {\\n id\\n code\\n }\\n privateData {\\n firstName\\n lastName\\n gender {\\n id\\n code\\n }\\n id\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"d5fbaec2a40f0880257954b852fe81fa\";\n\nexport default node;\n","import {useContext} from \"react\";\nimport {LocaleContext} from \"./index\";\nimport {LocaleContextInterface} from \"./types\";\n\n/**\n * Hook to access locale context\n */\nexport const useLocale = (): LocaleContextInterface => {\n const context = useContext(LocaleContext);\n\n if (!context) {\n throw new Error(\"useLocale must be used within LocaleProvider\");\n }\n\n return context;\n};\n","/**\n * @generated SignedSource<<01ac667780642633f84cf48ae783c749>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ReaderFragment } from 'relay-runtime';\nimport { FragmentRefs } from \"relay-runtime\";\nexport type ConnectedUserFragment_user$data = {\n readonly clientId: string | null | undefined;\n readonly emailAddress: {\n readonly address: string;\n readonly createdAt: any | null | undefined;\n readonly id: string;\n readonly lastValidationRequestAt: any | null | undefined;\n readonly updatedAt: any | null | undefined;\n readonly validatedAt: any | null | undefined;\n };\n readonly id: string;\n readonly language: {\n readonly code: string;\n readonly id: string;\n };\n readonly privateData: {\n readonly firstName: string | null | undefined;\n readonly gender: {\n readonly code: string;\n readonly id: string;\n } | null | undefined;\n readonly lastName: string | null | undefined;\n } | null | undefined;\n readonly status: {\n readonly code: string;\n readonly id: string;\n };\n readonly \" $fragmentType\": \"ConnectedUserFragment_user\";\n};\nexport type ConnectedUserFragment_user$key = {\n readonly \" $data\"?: ConnectedUserFragment_user$data;\n readonly \" $fragmentSpreads\": FragmentRefs<\"ConnectedUserFragment_user\">;\n};\n\nconst node: ReaderFragment = (function(){\nvar v0 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"id\",\n \"storageKey\": null\n},\nv1 = [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"code\",\n \"storageKey\": null\n }\n];\nreturn {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"ConnectedUserFragment_user\",\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"clientId\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserEmailAddressNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"emailAddress\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"address\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"createdAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"updatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"validatedAt\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastValidationRequestAt\",\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserStatusNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"status\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"LanguageNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"language\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"UserPrivateDataNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"privateData\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"firstName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"lastName\",\n \"storageKey\": null\n },\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"GenderNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"gender\",\n \"plural\": false,\n \"selections\": (v1/*: any*/),\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"type\": \"UserNode\",\n \"abstractKey\": null\n};\n})();\n\n(node as any).hash = \"be884da6a0b3dc538f08a2a609730684\";\n\nexport default node;\n","import {graphql} from \"react-relay\";\n\n/**\n * ConnectedUser fragment\n *\n * Defines all fields needed for the connected user across the application.\n * Used in:\n * - login mutation\n * - refreshAccessToken mutation\n *\n * Relay automatically updates the cache when this fragment is returned from mutations.\n * This fragment ensures consistency in user data structure and eliminates duplication.\n */\nexport const ConnectedUserFragment = graphql`\n fragment ConnectedUserFragment_user on UserNode {\n id\n clientId\n emailAddress {\n id\n address\n createdAt\n updatedAt\n validatedAt\n lastValidationRequestAt\n }\n status {\n id\n code\n }\n language {\n id\n code\n }\n privateData {\n firstName\n lastName\n gender {\n id\n code\n }\n }\n }\n`;\n","import {forwardRef, useCallback, useEffect, useRef, useState} from \"react\";\nimport {useMutation, graphql, useQueryLoader, usePreloadedQuery, useFragment} from \"react-relay\";\nimport type {PreloadedQuery} from \"react-relay\";\nimport {useIntl} from \"react-intl\";\nimport { ConnectedUserContext } from \"./hooks\";\nimport {ConnectedUserInterface, ConnectedUserProviderProps, ConnectedUserProviderRefInterface} from \"./types\";\nimport {useAlertMessages} from \"../AlertMessageProvider/hooks\";\nimport {useLocale} from \"../LocaleProvider/hooks\";\nimport {ConnectedUserFragment} from \"./ConnectedUserFragment\";\nimport type {ConnectedUserProviderQuery as ConnectedUserProviderQueryType} from \"./__generated__/ConnectedUserProviderQuery.graphql\";\nimport type {ConnectedUserProviderRefreshMutation} from \"./__generated__/ConnectedUserProviderRefreshMutation.graphql\";\nimport type {ConnectedUserProviderLoginMutation} from \"./__generated__/ConnectedUserProviderLoginMutation.graphql\";\nimport {clearRelayCache} from \"../../relay/RelayEnvironment\";\nimport {errorTranslations, isErrorKey} from \"../../i18n/errors\";\nimport type {RelayNetworkError} from \"../../types/relayTypes\";\n\n/**\n * Query definition for connected user\n */\nconst ConnectedUserProviderQueryNode = graphql`\n query ConnectedUserProviderQuery {\n connectedUser {\n ...ConnectedUserFragment_user\n }\n }\n`;\n\n/**\n * Refresh access token mutation (shared between outer and inner components)\n */\nconst RefreshMutationNode = graphql`mutation ConnectedUserProviderRefreshMutation {\n refreshAccessToken {\n success\n accessTokenExpireIn\n xsrfToken\n }\n}`;\n\n/**\n * Inner component that uses preloaded query\n */\nconst ConnectedUserProviderInner = forwardRef<ConnectedUserProviderRefInterface, ConnectedUserProviderProps & {\n queryRef: PreloadedQuery<ConnectedUserProviderQueryType>;\n onMutationSuccess: () => void;\n}>((props, ref) => {\n const {queryRef, onMutationSuccess} = props;\n\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const alertMessage = useAlertMessages();\n const intl = useIntl();\n const {updateLocale} = useLocale();\n\n /*******************************************************************************************************************\n * QUERIES\n ******************************************************************************************************************/\n\n /**\n * Fetch connected user from Relay cache\n * Automatically re-renders when cache is updated by mutations\n */\n const data = usePreloadedQuery(ConnectedUserProviderQueryNode, queryRef);\n\n /**\n * Read fragment data using useFragment\n * Fragment spread masks data - must use useFragment to access it\n */\n const user = useFragment(ConnectedUserFragment, data?.connectedUser ?? null) as ConnectedUserInterface | undefined;\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [accessTokenExpireIn, setAccessTokenExpireIn] = useState<number | undefined>(undefined)\n const [_webserviceBuffer, setWebserviceBuffer] = useState<(() => void)[]>([])\n const isRefreshInflightRef = useRef<boolean>(false)\n const refreshCallbacksRef = useRef<Array<() => void>>([])\n\n /*******************************************************************************************************************\n * MUTATIONS\n ******************************************************************************************************************/\n\n const [commitLogin, isLoginInflight] = useMutation<ConnectedUserProviderLoginMutation>(\n graphql`mutation ConnectedUserProviderLoginMutation($inputs: LoginInput!) {\n login(inputs: $inputs) {\n success\n accessTokenExpireIn\n xsrfToken\n }\n }`\n )\n\n const [commitRefresh] = useMutation<ConnectedUserProviderRefreshMutation>(RefreshMutationNode)\n\n const [commitLogout, isLogoutInflight] = useMutation(\n graphql`mutation ConnectedUserProviderLogoutMutation {\n logout {\n succeed\n }\n }`\n )\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Call refresh mutation\n * Used reactively when access token expires\n */\n const commitLysRefresh = useCallback(() => {\n // Prevent multiple simultaneous refresh calls\n if (isRefreshInflightRef.current) {\n return;\n }\n\n isRefreshInflightRef.current = true;\n\n commitRefresh({\n variables: {},\n onCompleted: (response, errors) => {\n isRefreshInflightRef.current = false;\n\n if (!errors || !errors?.length) {\n // Trigger refetch of connected user query\n onMutationSuccess();\n }\n setAccessTokenExpireIn(response.refreshAccessToken?.accessTokenExpireIn)\n },\n onError: (error: Error) => {\n isRefreshInflightRef.current = false;\n\n // Clear cache on refresh failure\n clearRelayCache();\n // Trigger refetch even on error to update UI\n onMutationSuccess();\n setAccessTokenExpireIn(undefined)\n\n // Report error to user\n const relayError = error as RelayNetworkError;\n if (relayError?.source?.errors) {\n const locale = intl.locale as \"en\" | \"fr\";\n relayError.source.errors.forEach((err) => {\n if (err.message !== \"WRONG_REFRESH_TOKEN_ERROR\") {\n if (!isErrorKey(err.message)) {\n console.error(\"Unhandled server error:\", err.message);\n }\n alertMessage.merge([{\n text: isErrorKey(err.message)\n ? errorTranslations[err.message][locale]\n : errorTranslations.UNKNOWN_ERROR[locale],\n level: \"CRITICAL\"\n }])\n }\n })\n } else {\n // Network error (CORS, connection failed, etc)\n alertMessage.merge([{\n text: error.message || \"NETWORK_ERROR\",\n level: \"CRITICAL\"\n }])\n }\n }\n })\n }, [commitRefresh, alertMessage, onMutationSuccess, intl.locale])\n\n /**\n * Call login mutation\n */\n const commitLysLogin = useCallback((login: string, password: string) => {\n commitLogin({\n variables: {\n inputs: {\n login,\n password\n }\n },\n onCompleted: (response, errors) => {\n if (!errors || !errors?.length) {\n // Trigger refetch of connected user query\n onMutationSuccess();\n }\n setAccessTokenExpireIn(response.login?.accessTokenExpireIn)\n },\n onError: (error: Error) => {\n const relayError = error as RelayNetworkError;\n relayError?.source?.errors?.forEach((err) => {\n alertMessage.merge([{\n text: err.message,\n level: \"CRITICAL\"\n }])\n })\n }\n })\n }, [commitLogin, alertMessage, onMutationSuccess])\n\n /**\n * Call logout mutation\n */\n const commitLysLogout = useCallback(() => {\n commitLogout({\n variables: {},\n onCompleted: () => {\n // Clear Relay cache\n clearRelayCache();\n // Trigger refetch of connected user query\n onMutationSuccess();\n setAccessTokenExpireIn(undefined)\n alertMessage.merge([{\n text: intl.formatMessage({id: \"lys.services.i18n.messages.logoutSuccess\"}),\n level: \"SUCCESS\"\n }])\n },\n onError: (error: Error) => {\n const relayError = error as RelayNetworkError;\n relayError?.source?.errors?.forEach((err) => {\n alertMessage.merge([{\n text: err.message,\n level: \"CRITICAL\"\n }])\n })\n }\n })\n }, [commitLogout, alertMessage, intl, onMutationSuccess])\n\n /**\n * Handle session expired (ACCESS_DENIED_ERROR)\n * Attempts to refresh token first, if that fails then disconnects\n * Supports multiple callbacks from different LysQueryProviders failing simultaneously\n * @param onRefreshSuccess Optional callback called after successful token refresh\n */\n const handleSessionExpired = useCallback((onRefreshSuccess?: () => void) => {\n // Store callback to be called when refresh completes\n // This allows multiple LysQueryProviders to register their callbacks\n if (onRefreshSuccess) {\n refreshCallbacksRef.current.push(onRefreshSuccess);\n }\n\n // Only start refresh if not already in flight\n if (!isRefreshInflightRef.current) {\n isRefreshInflightRef.current = true;\n\n commitRefresh({\n variables: {},\n onCompleted: (response, errors) => {\n isRefreshInflightRef.current = false;\n\n if (!errors || !errors?.length) {\n // Refresh succeeded - update expiration\n setAccessTokenExpireIn(response.refreshAccessToken?.accessTokenExpireIn)\n onMutationSuccess();\n // Call ALL registered callbacks to retry failed requests\n const callbacks = refreshCallbacksRef.current;\n refreshCallbacksRef.current = [];\n callbacks.forEach((cb) => {\n try {\n cb();\n } catch (error) {\n console.error('Error executing refresh callback:', error);\n }\n });\n } else {\n // Refresh failed - clear callbacks and disconnect user\n refreshCallbacksRef.current = [];\n clearRelayCache();\n onMutationSuccess();\n setAccessTokenExpireIn(undefined);\n alertMessage.merge([{\n text: intl.formatMessage({id: \"lys.services.i18n.messages.sessionExpired\"}),\n level: \"WARNING\"\n }]);\n }\n },\n onError: () => {\n isRefreshInflightRef.current = false;\n // Clear callbacks on error\n refreshCallbacksRef.current = [];\n\n // Refresh failed - disconnect user\n clearRelayCache();\n onMutationSuccess();\n setAccessTokenExpireIn(undefined);\n alertMessage.merge([{\n text: intl.formatMessage({id: \"lys.services.i18n.messages.sessionExpired\"}),\n level: \"WARNING\"\n }]);\n }\n })\n }\n }, [commitRefresh, onMutationSuccess, alertMessage, intl])\n\n /**\n * Push webservice to queue or execute immediately\n * Reactive refresh: if token expired, refresh then execute buffered requests\n */\n const push = useCallback((webservice: () => void) => {\n const timeStampSecondNow = Date.now() / 1000\n\n // Check if token is valid (with 5 second buffer)\n const isValid = accessTokenExpireIn !== undefined\n ? (accessTokenExpireIn - timeStampSecondNow > 5)\n : true // If no expiration info (public/unauthenticated), consider valid\n\n // Token valid and not refreshing -> execute immediately\n if (isValid && !isRefreshInflightRef.current) {\n webservice()\n return\n }\n\n // Token invalid and not refreshing -> trigger refresh\n if (!isValid && !isRefreshInflightRef.current) {\n commitLysRefresh()\n }\n\n // In all other cases -> buffer the webservice\n // (either refreshing or token invalid)\n setWebserviceBuffer(prev => [...prev, webservice])\n }, [accessTokenExpireIn, commitLysRefresh])\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n // Execute buffered webservices when token becomes valid after refresh\n useEffect(() => {\n const timeStampSecondNow = Date.now() / 1000\n const isValid = accessTokenExpireIn !== undefined\n ? (accessTokenExpireIn - timeStampSecondNow > 5)\n : true // If no expiration info (public/unauthenticated), consider valid\n\n if (isValid && !isRefreshInflightRef.current) {\n setWebserviceBuffer(currentBuffer => {\n if (currentBuffer.length > 0) {\n // Execute all buffered webservices\n currentBuffer.forEach((webservice) => {\n try {\n webservice()\n } catch (error) {\n console.error('Error executing buffered webservice:', error)\n }\n })\n }\n return [] // Clear buffer\n })\n }\n }, [accessTokenExpireIn])\n\n // Update locale when user language changes\n useEffect(() => {\n if (user?.language?.code) {\n updateLocale(user.language.code);\n }\n }, [user?.language?.code, updateLocale]);\n\n // Update reference\n useEffect(() => {\n const data = {\n language: user?.language?.code\n }\n\n if (typeof ref === 'function') {\n ref(data)\n } else if (ref) {\n ref.current = data\n }\n }, [user?.language?.code, ref])\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <ConnectedUserContext.Provider value={{\n user,\n push,\n logout: [commitLysLogout, isLogoutInflight],\n login: [commitLysLogin, isLoginInflight],\n refresh: [commitLysRefresh, false],\n handleSessionExpired\n }}>\n {props.children}\n </ConnectedUserContext.Provider>\n )\n})\n\nConnectedUserProviderInner.displayName = \"ConnectedUserProviderInner\";\n\n/**\n * Outer component that manages query loading\n *\n * On mount, attempts to refresh the access token before loading the user query.\n * This handles the case where a page reload occurs after the access token (short-lived JWT)\n * has expired but the refresh token (longer-lived, httpOnly cookie) is still valid.\n * Without this, the initial connectedUser query would fail with an expired JWT,\n * showing the login page even though the session is still valid.\n */\nconst ConnectedUserProvider = forwardRef<ConnectedUserProviderRefInterface, ConnectedUserProviderProps>((props, ref) => {\n const [queryRef, loadQuery] = useQueryLoader<ConnectedUserProviderQueryType>(ConnectedUserProviderQueryNode);\n // Tracks whether the initial query has been loaded (after mount refresh attempt)\n const queryLoadedRef = useRef(false);\n\n // Reuse the shared refresh mutation for the initial mount refresh\n const [commitInitialRefresh] = useMutation<ConnectedUserProviderRefreshMutation>(RefreshMutationNode);\n\n // On mount: attempt token refresh, then load user query\n useEffect(() => {\n if (queryLoadedRef.current) return;\n queryLoadedRef.current = true;\n\n commitInitialRefresh({\n variables: {},\n onCompleted: () => {\n // Refresh succeeded — load user query with fresh access token\n loadQuery({}, {fetchPolicy: 'network-only'});\n },\n onError: () => {\n // Refresh failed (no valid refresh token) — load query anyway\n // This will return null connectedUser, showing the login page\n loadQuery({}, {fetchPolicy: 'network-only'});\n },\n });\n }, [commitInitialRefresh, loadQuery]);\n\n // Callback to reload query after mutations (login, refresh, logout)\n const handleMutationSuccess = useCallback(() => {\n // Use store-and-network to use cache first, then refetch\n loadQuery({}, {fetchPolicy: 'store-and-network'});\n }, [loadQuery]);\n\n return queryRef ? (\n <ConnectedUserProviderInner\n ref={ref}\n queryRef={queryRef}\n onMutationSuccess={handleMutationSuccess}\n >\n {props.children}\n </ConnectedUserProviderInner>\n ) : null;\n});\n\nConnectedUserProvider.displayName = \"ConnectedUserProvider\";\n\nexport default ConnectedUserProvider\n","/**\n * @generated SignedSource<<b99811e5597cf9c9977b594fb31cbe59>>\n * @lightSyntaxTransform\n * @nogrep\n */\n\n/* tslint:disable */\n/* eslint-disable */\n// @ts-nocheck\n\nimport { ConcreteRequest } from 'relay-runtime';\nexport type WebserviceAccessProviderQuery$variables = Record<PropertyKey, never>;\nexport type WebserviceAccessProviderQuery$data = {\n readonly allAccessibleWebservices: {\n readonly edges: ReadonlyArray<{\n readonly node: {\n readonly code: string;\n readonly userAccessLevels: ReadonlyArray<{\n readonly code: string;\n }>;\n };\n }>;\n };\n};\nexport type WebserviceAccessProviderQuery = {\n response: WebserviceAccessProviderQuery$data;\n variables: WebserviceAccessProviderQuery$variables;\n};\n\nconst node: ConcreteRequest = (function(){\nvar v0 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"code\",\n \"storageKey\": null\n},\nv1 = {\n \"alias\": null,\n \"args\": null,\n \"kind\": \"ScalarField\",\n \"name\": \"id\",\n \"storageKey\": null\n};\nreturn {\n \"fragment\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Fragment\",\n \"metadata\": null,\n \"name\": \"WebserviceAccessProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeListConnection\",\n \"kind\": \"LinkedField\",\n \"name\": \"allAccessibleWebservices\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeEdge\",\n \"kind\": \"LinkedField\",\n \"name\": \"edges\",\n \"plural\": true,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"node\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessLevelNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"userAccessLevels\",\n \"plural\": true,\n \"selections\": [\n (v0/*: any*/)\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"type\": \"Query\",\n \"abstractKey\": null\n },\n \"kind\": \"Request\",\n \"operation\": {\n \"argumentDefinitions\": [],\n \"kind\": \"Operation\",\n \"name\": \"WebserviceAccessProviderQuery\",\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeListConnection\",\n \"kind\": \"LinkedField\",\n \"name\": \"allAccessibleWebservices\",\n \"plural\": false,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNodeEdge\",\n \"kind\": \"LinkedField\",\n \"name\": \"edges\",\n \"plural\": true,\n \"selections\": [\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessedWebserviceNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"node\",\n \"plural\": false,\n \"selections\": [\n (v0/*: any*/),\n {\n \"alias\": null,\n \"args\": null,\n \"concreteType\": \"AccessLevelNode\",\n \"kind\": \"LinkedField\",\n \"name\": \"userAccessLevels\",\n \"plural\": true,\n \"selections\": [\n (v0/*: any*/),\n (v1/*: any*/)\n ],\n \"storageKey\": null\n },\n (v1/*: any*/)\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ],\n \"storageKey\": null\n }\n ]\n },\n \"params\": {\n \"cacheID\": \"0eb745d5632c205d2b339ac945f97748\",\n \"id\": null,\n \"metadata\": {},\n \"name\": \"WebserviceAccessProviderQuery\",\n \"operationKind\": \"query\",\n \"text\": \"query WebserviceAccessProviderQuery {\\n allAccessibleWebservices {\\n edges {\\n node {\\n code\\n userAccessLevels {\\n code\\n id\\n }\\n id\\n }\\n }\\n }\\n}\\n\"\n }\n};\n})();\n\n(node as any).hash = \"fc09839e36fcabc6d7704f800685b5a2\";\n\nexport default node;\n","import {createContext, useCallback, useContext} from \"react\";\nimport {GraphQLTaggedNode} from \"relay-runtime\";\nimport {extractOperationNames, checkOperationsPermission as checkOperationsPermissionUtil} from \"../../tools/relayTools\";\n\n/**\n * Webservice access context\n */\nconst WebserviceAccessContext = createContext<{\n checkWebserviceAccess(webservice: string): boolean;\n getWebserviceAccessLevels(webservice: string): string[];\n}>({\n checkWebserviceAccess: () => {\n console.warn(\"WebserviceAccessProvider not initialized: checkWebserviceAccess\");\n return false;\n },\n getWebserviceAccessLevels: () => {\n console.warn(\"WebserviceAccessProvider not initialized: getWebserviceAccessLevels\");\n return [];\n }\n});\n\n/**\n * Hook to access webservice permissions\n *\n * Provides:\n * - checkWebserviceAccess(name): Check permission by webservice name (string)\n * - checkOperationsPermission(operation): Check permission by GraphQL operation (mutation/query)\n * - getWebserviceAccessLevels(name): Get access levels for a webservice\n */\nfunction useWebserviceAccess() {\n const {checkWebserviceAccess, getWebserviceAccessLevels} = useContext(WebserviceAccessContext);\n\n /**\n * Check permission for a GraphQL operation (mutation or query)\n * Extracts operation names from the GraphQL node and checks all permissions\n */\n const checkOperationsPermission = useCallback((operation: GraphQLTaggedNode): boolean => {\n const operationNames = extractOperationNames(operation);\n return checkOperationsPermissionUtil(operationNames, checkWebserviceAccess);\n }, [checkWebserviceAccess]);\n\n return {\n checkWebserviceAccess,\n checkOperationsPermission,\n getWebserviceAccessLevels\n };\n}\n\nexport {\n WebserviceAccessContext,\n useWebserviceAccess\n}\n","import {createComponentTranslations} from \"../../tools/translationTools\";\n\nconst translations = {\n errorTitle: {\n en: \"Permission System Error\",\n fr: \"Erreur du système de permissions\"\n },\n errorMessage: {\n en: \"Unable to load permission system. Please check your connection and try refreshing the page.\",\n fr: \"Impossible de charger le système de permissions. Veuillez vérifier votre connexion et rafraîchir la page.\"\n },\n loadingPermissions: {\n en: \"Loading permissions...\",\n fr: \"Chargement des permissions...\"\n }\n};\n\nconst {config, useTranslations} = createComponentTranslations(\n \"WebserviceAccessProvider\",\n translations\n);\n\nexport const webserviceAccessProviderConfig = config;\nexport const useWebserviceAccessProviderTranslations = useTranslations;\n","import * as React from \"react\";\nimport {Suspense, useCallback, useEffect, useMemo, useState} from \"react\";\nimport {graphql, usePreloadedQuery, useQueryLoader, PreloadedQuery} from \"react-relay\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {WebserviceAccessProviderProps} from \"./types\";\nimport {WebserviceAccessContext} from \"./hooks\";\nimport ErrorBoundaryProvider from \"../ErrorBoundaryProvider\";\nimport {WebserviceAccessProviderQuery} from \"./__generated__/WebserviceAccessProviderQuery.graphql\";\nimport {useWebserviceAccessProviderTranslations} from \"./translations\";\nimport {toSnakeCase} from \"../../tools/stringTools\";\n\nconst query = graphql`\n query WebserviceAccessProviderQuery {\n allAccessibleWebservices {\n edges {\n node {\n code\n userAccessLevels {\n code\n }\n }\n }\n }\n }\n`;\n\n/**\n * Type for webservice data with access levels\n */\ntype WebserviceData = {\n code: string;\n accessLevels: string[];\n};\n\n/**\n * Inner component that executes the query\n * Isolated so ErrorBoundary only catches query errors, not children errors\n */\nconst QueryExecutor: React.FC<{\n queryRef: PreloadedQuery<WebserviceAccessProviderQuery>;\n onData: (webservices: WebserviceData[]) => void;\n}> = ({queryRef, onData}) => {\n const data = usePreloadedQuery<WebserviceAccessProviderQuery>(query, queryRef);\n\n const webservicesData = useMemo(() => {\n return data?.allAccessibleWebservices?.edges\n ?.map((edge) => ({\n code: edge?.node?.code,\n accessLevels: edge?.node?.userAccessLevels?.map((level) => level.code) || []\n }))\n .filter((ws): ws is WebserviceData => ws.code !== null && ws.code !== undefined) || [];\n }, [data]);\n\n useEffect(() => {\n onData(webservicesData);\n }, [webservicesData, onData]);\n\n return null;\n};\n\nQueryExecutor.displayName = \"QueryExecutor\";\n\n/**\n * WebserviceAccess provider\n * Manages loading of accessible webservices for current user\n * Auto-reloads when user changes\n */\nconst WebserviceAccessProvider: React.ComponentType<WebserviceAccessProviderProps> = ({children}) => {\n const {user, handleSessionExpired} = useConnectedUserInfo();\n const {t} = useWebserviceAccessProviderTranslations();\n\n const [queryRef, loadQuery, disposeQuery] = useQueryLoader<WebserviceAccessProviderQuery>(query);\n const [hasError, setHasError] = useState(false);\n const [webservicesMap, setWebservicesMap] = useState<Map<string, string[]>>(new Map());\n\n // Load webservice accesses when user changes\n useEffect(() => {\n if (!hasError) {\n loadQuery({}, {fetchPolicy: \"network-only\"});\n } else {\n disposeQuery();\n }\n }, [user, loadQuery, disposeQuery, hasError]);\n\n // Callback when query data is received\n const handleQueryData = useCallback((webservicesData: WebserviceData[]) => {\n const newMap = new Map<string, string[]>();\n webservicesData.forEach((ws) => {\n newMap.set(ws.code, ws.accessLevels);\n });\n setWebservicesMap(newMap);\n }, []);\n\n // Error handler for query errors only\n const handleQueryError = useCallback((error: Error) => {\n const relayError = error as Error & {errors?: Array<{message: string}>};\n if (error.message === \"ACCESS_DENIED_ERROR\" ||\n (error.message?.includes(\"ACCESS_DENIED_ERROR\")) ||\n (relayError.errors?.some((e) => e.message === \"ACCESS_DENIED_ERROR\"))) {\n console.log(\"WebserviceAccessProvider: Session expired, redirecting to login\");\n handleSessionExpired();\n return;\n }\n console.error(\"WebserviceAccessProvider query failed - continuing without permissions:\", error);\n setHasError(true);\n }, [handleSessionExpired]);\n\n // Check webservice access\n const checkWebserviceAccess = useCallback((webserviceName: string) => {\n const snakeCaseName = toSnakeCase(webserviceName);\n return webservicesMap.has(snakeCaseName);\n }, [webservicesMap]);\n\n // Get access levels for a webservice\n const getWebserviceAccessLevels = useCallback((webserviceName: string): string[] => {\n const snakeCaseName = toSnakeCase(webserviceName);\n return webservicesMap.get(snakeCaseName) || [];\n }, [webservicesMap]);\n\n // Context value\n const contextValue = useMemo(() => ({\n checkWebserviceAccess,\n getWebserviceAccessLevels\n }), [checkWebserviceAccess, getWebserviceAccessLevels]);\n\n if (hasError) {\n return (\n <div style={{padding: '2rem', textAlign: 'center'}}>\n <h3>{t(\"errorTitle\")}</h3>\n <p>{t(\"errorMessage\")}</p>\n </div>\n );\n }\n\n return (\n <>\n {/* Query execution isolated in its own ErrorBoundary */}\n {queryRef && (\n <ErrorBoundaryProvider onError={handleQueryError}>\n <Suspense fallback={<div>{t(\"loadingPermissions\")}</div>}>\n <QueryExecutor queryRef={queryRef} onData={handleQueryData} />\n </Suspense>\n </ErrorBoundaryProvider>\n )}\n\n {/* Children rendered OUTSIDE the ErrorBoundary */}\n <WebserviceAccessContext.Provider value={contextValue}>\n {children}\n </WebserviceAccessContext.Provider>\n </>\n );\n};\n\nWebserviceAccessProvider.displayName = \"WebserviceAccessProvider\";\n\nexport default WebserviceAccessProvider;\n","import {createContext, useContext, useEffect, useState} from \"react\";\nimport {SignalContextValue, SignalHandler, SignalRefresh} from \"./types\";\n\n/**\n * Signal context with default no-op values\n */\nexport const SignalContext = createContext<SignalContextValue>({\n isConnected: false,\n error: null,\n subscribe: () => {\n console.warn(\"SignalProvider not initialized: subscribe\");\n return () => {};\n }\n});\n\n/**\n * Hook to access signal provider state\n */\nexport function useSignal(): SignalContextValue {\n return useContext(SignalContext);\n}\n\n/**\n * Hook to subscribe to signals with automatic cleanup\n *\n * @param handler - Function called when a signal is received\n * @param deps - Dependencies array for the handler (like useEffect)\n *\n * @example\n * ```tsx\n * useSignalSubscription((signal) => {\n * if (signal.signal === \"FINANCIAL_IMPORT_COMPLETED\") {\n * // Handle import completion\n * refetchData();\n * }\n * }, [refetchData]);\n * ```\n */\nexport function useSignalSubscription(\n handler: SignalHandler,\n deps: React.DependencyList = []\n): void {\n const {subscribe} = useSignal();\n\n useEffect(() => {\n const unsubscribe = subscribe(handler);\n return unsubscribe;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [subscribe, ...deps]);\n}\n\n/**\n * Hook that returns a version counter and params, incremented each time a matching signal is received.\n * Use version as a useEffect dependency to trigger query reloads on specific signals.\n * Use params to filter based on signal data before reloading.\n *\n * Matches on both signal.signal and signal.params.type_id for compatibility\n * with notification-wrapped signals.\n *\n * @param signalKeys - One or more signal names to listen for\n * @returns {SignalRefresh} version counter and params of the last matching signal\n *\n * @example\n * ```tsx\n * const {version, params} = useSignalRefresh(\"PORTFOLIO_ANALYSIS_COMPLETED\");\n *\n * useEffect(() => {\n * const data = params?.data as Record<string, unknown>;\n * if (version > 0 && data?.year === year && queryRef?.hasPermission) {\n * queryRef?.load();\n * }\n * }, [version]);\n * ```\n */\nexport function useSignalRefresh(...signalKeys: string[]): SignalRefresh {\n const [version, setVersion] = useState(0);\n const [params, setParams] = useState<Record<string, unknown> | null>(null);\n\n useSignalSubscription((signal) => {\n const typeId = signal.params?.type_id as string | undefined;\n if (signalKeys.includes(signal.signal) || (typeId && signalKeys.includes(typeId))) {\n setParams(signal.params);\n setVersion(v => v + 1);\n }\n }, signalKeys);\n\n return {version, params};\n}","import React, {useEffect, useRef, useState, useCallback, useMemo} from \"react\";\nimport {SignalContext} from \"./hooks\";\nimport {Signal, SignalHandler, SignalProviderProps} from \"./types\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\n\n/**\n * Decode Relay Global ID to extract raw UUID.\n * Relay IDs are base64 encoded strings in format \"NodeType:uuid\"\n */\nconst decodeRelayId = (relayId: string): string => {\n try {\n const decoded = atob(relayId);\n const parts = decoded.split(\":\");\n return parts.length > 1 ? parts[1] : relayId;\n } catch {\n return relayId;\n }\n};\n\n/**\n * SignalProvider component\n *\n * Provides real-time signal handling via Server-Sent Events (SSE).\n * Uses native EventSource API to connect to the SSE endpoint.\n *\n * Connection behavior:\n * - Connects only when a user is authenticated (user.id exists)\n * - Disconnects automatically when user logs out\n * - Non-blocking: errors don't crash the application\n * - Automatically reconnects on connection loss (handled by EventSource)\n *\n * Place this provider after ConnectedUserProvider and before ChatbotProvider\n * in the component tree.\n */\nconst SignalProvider: React.FC<SignalProviderProps> = ({children}) => {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const {user} = useConnectedUserInfo();\n\n /*******************************************************************************************************************\n * REFS\n ******************************************************************************************************************/\n\n /**\n * EventSource instance\n */\n const eventSourceRef = useRef<EventSource | null>(null);\n\n /**\n * Set of registered signal handlers\n */\n const handlersRef = useRef<Set<SignalHandler>>(new Set());\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Dispatch a signal to all registered handlers\n */\n const dispatchSignal = useCallback((signal: Signal) => {\n handlersRef.current.forEach((handler) => {\n try {\n handler(signal);\n } catch (err) {\n console.error(\"[SignalProvider] Handler error:\", err);\n }\n });\n }, []);\n\n /**\n * Subscribe a handler to receive signals\n * Returns an unsubscribe function\n */\n const subscribe = useCallback((handler: SignalHandler): (() => void) => {\n handlersRef.current.add(handler);\n return () => {\n handlersRef.current.delete(handler);\n };\n }, []);\n\n /**\n * Stop the SSE connection\n */\n const stopConnection = useCallback(() => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close();\n eventSourceRef.current = null;\n }\n setIsConnected(false);\n setError(null);\n }, []);\n\n /**\n * Start the SSE connection\n */\n const startConnection = useCallback((userId: string) => {\n // Close existing connection if any\n stopConnection();\n\n // Decode Relay ID to get raw UUID for channel subscription\n const rawUserId = decodeRelayId(userId);\n const baseUrl = import.meta.env?.VITE_SSE_ENDPOINT as string || \"\";\n const url = `${baseUrl}/sse/signals?channel=user:${rawUserId}`;\n\n // Create EventSource with credentials for cookie auth\n const eventSource = new EventSource(url, {withCredentials: true});\n eventSourceRef.current = eventSource;\n\n eventSource.onopen = () => {\n setIsConnected(true);\n setError(null);\n };\n\n eventSource.onmessage = (event) => {\n try {\n const signal: Signal = JSON.parse(event.data);\n dispatchSignal(signal);\n } catch {\n // Ignore parse errors\n }\n };\n\n eventSource.onerror = () => {\n setError(new Error(\"SSE connection error\"));\n setIsConnected(false);\n // EventSource will automatically try to reconnect\n };\n }, [dispatchSignal, stopConnection]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Connect/disconnect based on user authentication state\n */\n useEffect(() => {\n if (user?.id) {\n // User is authenticated - start connection\n startConnection(user.id);\n } else {\n // User is not authenticated - stop connection\n stopConnection();\n }\n\n // Cleanup on unmount or user change\n return () => {\n stopConnection();\n };\n }, [user?.id, startConnection, stopConnection]);\n\n /*******************************************************************************************************************\n * MEMOS\n ******************************************************************************************************************/\n\n const contextValue = useMemo(() => ({\n isConnected,\n error,\n subscribe\n }), [isConnected, error, subscribe]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <SignalContext.Provider value={contextValue}>\n {children}\n </SignalContext.Provider>\n );\n};\n\nexport default SignalProvider;","import {createContext, useContext} from \"react\";\nimport {LysQueryContextType} from \"./types\";\nimport {OperationType} from \"relay-runtime\";\n\nconst LysQueryContext = createContext<LysQueryContextType>([\n undefined,\n () => {},\n]);\n\n/**\n * Hook to access query data and reload function from LysQueryProvider\n */\nfunction useLysQuery<TQuery extends OperationType = OperationType>(): LysQueryContextType<TQuery> {\n return useContext(LysQueryContext) as LysQueryContextType<TQuery>;\n}\n\nexport {\n LysQueryContext,\n useLysQuery\n};\n","import {useCallback, useEffect, useState} from \"react\";\nimport {useWebserviceAccess} from \"../WebserviceAccessProvider/hooks\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\n\ninterface AccessParameters {\n ownerIds: string[];\n}\n\n/**\n * Hook to check permission for a set of operations with OWNER access level handling.\n *\n * - If user has only OWNER access level for a webservice, check ownerIds\n * - If user has other access levels (ROLE, ORGANIZATION_ROLE, etc.), grant access\n * - Warn if OWNER is in access levels but accessParameters is not provided\n */\nexport function usePermissionCheck(\n operationNames: string[],\n accessParameters?: AccessParameters | null,\n providerName: string = \"Provider\"\n): boolean {\n const webserviceAccess = useWebserviceAccess();\n const connectedUserInfo = useConnectedUserInfo();\n\n const checkPermission = useCallback(() => {\n if (!operationNames.length) {\n return false;\n }\n\n return operationNames.every(operationName => {\n // First check if user has access to this webservice\n if (!webserviceAccess.checkWebserviceAccess(operationName)) {\n return false;\n }\n\n // Get access levels for this webservice\n const accessLevels = webserviceAccess.getWebserviceAccessLevels(operationName);\n\n // Check if OWNER is in the access levels\n const hasOwnerAccess = accessLevels.includes(\"OWNER\");\n\n // If OWNER is the only access level\n if (hasOwnerAccess && accessLevels.length === 1) {\n // accessParameters is required for OWNER-only access\n if (!accessParameters) {\n console.warn(\n `${providerName}: Operation \"${operationName}\" requires OWNER access but accessParameters is not defined. ` +\n `Please provide accessParameters={{ ownerIds: [...] }} to enable owner-based access control.`\n );\n return false;\n }\n\n // Check if connected user is in ownerIds\n const userId = connectedUserInfo.user?.id;\n if (!userId || !accessParameters.ownerIds.includes(userId)) {\n return false;\n }\n } else if (hasOwnerAccess && !accessParameters) {\n // OWNER is one of multiple access levels, but accessParameters not provided\n // User has access through other levels, but warn about missing owner config\n console.warn(\n `${providerName}: Operation \"${operationName}\" has OWNER access level but accessParameters is not defined. ` +\n `Owner-based access control will not work. Consider providing accessParameters={{ ownerIds: [...] }}.`\n );\n }\n\n // User has access (either through non-OWNER levels or passed OWNER check)\n return true;\n });\n }, [operationNames, webserviceAccess, accessParameters, connectedUserInfo.user?.id, providerName]);\n\n const [hasPermission, setHasPermission] = useState<boolean>(() => checkPermission());\n\n useEffect(() => {\n setHasPermission(checkPermission());\n }, [checkPermission]);\n\n return hasPermission;\n}\n","import {createContext, useContext} from \"react\";\nimport {ReactNode} from \"react\";\n\ninterface LysLoadingContextType {\n loadingFallback: ReactNode;\n}\n\nconst LysLoadingContext = createContext<LysLoadingContextType>({\n loadingFallback: null\n});\n\nexport const useLysLoadingFallback = (): ReactNode => {\n const {loadingFallback} = useContext(LysLoadingContext);\n return loadingFallback;\n};\n\nexport default LysLoadingContext;\n","import \"./styles.scss\";\nimport * as React from \"react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState\n} from \"react\";\nimport {\n GraphQLTaggedNode,\n OperationType,\n} from \"relay-runtime\";\nimport {LysQueryProviderProps, LysQueryRefInterface} from \"./types\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {extractOperationNames} from \"../../tools/relayTools\";\nimport {useAlertMessages} from \"../AlertMessageProvider/hooks\";\nimport {AlertLevelType} from \"../AlertMessageProvider/types\";\nimport type {RelayNetworkError} from \"../../types/relayTypes\";\nimport {useRefreshSignal} from \"./RefreshSignalContext\";\nimport {PreloadedQuery, usePreloadedQuery, useQueryLoader} from \"react-relay\";\nimport {LysQueryContext} from \"./hooks\";\nimport ErrorBoundaryProvider from \"../ErrorBoundaryProvider\";\nimport {usePermissionCheck} from \"../hooks/usePermissionCheck\";\nimport {useLysLoadingFallback} from \"./LysLoadingContext\";\n\n/**\n * Extract node types from a GraphQL query\n * Traverses the query structure to find all concreteType values ending with \"Node\"\n */\nfunction extractNodeTypes(query: GraphQLTaggedNode): string[] {\n const nodeTypes = new Set<string>();\n\n const traverse = (obj: unknown): void => {\n if (!obj || typeof obj !== \"object\") return;\n\n if (\"concreteType\" in obj) {\n const concreteType = (obj as {concreteType: string}).concreteType;\n // Only include types ending with \"Node\" (not Connection, Edge, etc.)\n if (concreteType && concreteType.endsWith(\"Node\")) {\n nodeTypes.add(concreteType);\n }\n }\n\n // Traverse nested objects and arrays\n for (const value of Object.values(obj)) {\n if (Array.isArray(value)) {\n value.forEach(traverse);\n } else if (typeof value === \"object\") {\n traverse(value);\n }\n }\n };\n\n traverse(query);\n return Array.from(nodeTypes);\n}\n\n/**\n * Provider child component (mounted only when the query is loaded)\n * Extracts data from the preloaded query and passes it to parent\n */\nconst LysQueryProviderChild: React.ComponentType<{\n query: GraphQLTaggedNode;\n queryReference: PreloadedQuery<OperationType>;\n setData: (data: OperationType[\"response\"]) => void;\n}> = ({query, queryReference, setData}) => {\n const data = usePreloadedQuery(query, queryReference);\n\n useEffect(() => {\n setData(data);\n }, [setData, data]);\n\n return null;\n};\n\n/**\n * QueryErrorBoundary - Handles GraphQL query errors with session recovery\n *\n * Responsibilities:\n * - Catches errors thrown by Suspense/usePreloadedQuery via ErrorBoundaryProvider\n * - Categorizes errors: ACCESS_DENIED (session expired) vs GraphQL errors vs network errors\n * - Triggers session recovery with retry callback on ACCESS_DENIED\n * - Routes other errors to AlertMessageProvider\n * - Prevents duplicate error handling via errorProcessedRef\n * - Breaks ErrorBoundary re-render loops via hasError state\n */\nconst QueryErrorBoundary: React.ComponentType<{\n query: GraphQLTaggedNode;\n queryReference: PreloadedQuery<OperationType>;\n setData: (data: OperationType[\"response\"]) => void;\n reloadQuery: () => void;\n}> = ({query, queryReference, setData, reloadQuery}) => {\n const connectedUserInfo = useConnectedUserInfo();\n const alertMessage = useAlertMessages();\n\n // Prevent duplicate error handling (ErrorBoundary may call onError multiple times)\n const errorProcessedRef = useRef(false);\n\n // Break ErrorBoundary re-render loops: when true, unmounts the boundary entirely\n const [hasError, setHasError] = useState(false);\n\n const handleError = useCallback((error: RelayNetworkError) => {\n if (errorProcessedRef.current) {\n return;\n }\n errorProcessedRef.current = true;\n\n // Relay errors can have GraphQL errors in error.source.errors\n const gqlErrors = error?.source?.errors;\n\n // Check for ACCESS_DENIED_ERROR (session expiration)\n // - First in source.errors if available\n // - Then in error.message as fallback (Relay embeds error codes in message)\n const hasAccessDenied = gqlErrors?.some(\n (err) => err.message === \"ACCESS_DENIED_ERROR\"\n ) || error.message?.includes(\"ACCESS_DENIED_ERROR\");\n\n if (hasAccessDenied) {\n // CRITICAL: Set hasError to stop the ErrorBoundary render loop.\n // Without this, ErrorBoundary clears its state and re-renders children,\n // which throws the same error again causing an infinite loop.\n setHasError(true);\n\n // Handle session expiration - attempt token refresh\n // Pass retry callback to reload query after successful refresh\n connectedUserInfo.handleSessionExpired(() => {\n errorProcessedRef.current = false;\n setHasError(false);\n reloadQuery();\n });\n return;\n }\n\n // Display errors - prefer extracted GraphQL errors over raw message\n if (gqlErrors && gqlErrors.length > 0) {\n alertMessage.merge(\n gqlErrors.map((gqlError) => ({\n text: gqlError.message,\n level: (gqlError.severity || \"ERROR\") as AlertLevelType\n }))\n );\n } else {\n // Network or other errors - display original message\n alertMessage.merge([{\n text: error.message,\n level: \"CRITICAL\"\n }]);\n }\n\n setHasError(true);\n }, [connectedUserInfo, alertMessage, reloadQuery]);\n\n if (hasError) {\n return null;\n }\n\n return (\n <ErrorBoundaryProvider onError={handleError}>\n <React.Suspense fallback={null}>\n <LysQueryProviderChild\n query={query}\n queryReference={queryReference}\n setData={setData}\n />\n </React.Suspense>\n </ErrorBoundaryProvider>\n );\n};\n\n/**\n * LysQueryProvider - Manages GraphQL queries with permission checking\n *\n * Features:\n * - Automatic permission checking based on operation names\n * - Queue system for authenticated requests\n * - Error handling with QueryErrorBoundary\n * - Loading state management\n */\nfunction LysQueryProviderInner<TQuery extends OperationType = OperationType>(\n {\n query,\n initialQueryReference,\n parameters = {},\n options = {fetchPolicy: 'store-and-network'},\n accessParameters,\n children,\n as: Container = \"div\",\n loadingFallback\n }: LysQueryProviderProps<TQuery>,\n ref: React.Ref<LysQueryRefInterface<TQuery>>\n) {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const connectedUserInfo = useConnectedUserInfo();\n const refreshSignal = useRefreshSignal();\n const contextFallback = useLysLoadingFallback();\n const effectiveFallback = loadingFallback !== undefined ? loadingFallback : contextFallback;\n\n const [\n queryReference,\n loadQuery,\n disposeQuery\n ] = useQueryLoader(query, initialQueryReference);\n\n // Extract node types from query (memoized)\n const nodeTypes = useMemo(() => extractNodeTypes(query), [query]);\n\n // Extract operation names from query (memoized)\n const operationNames = useMemo(() => extractOperationNames(query), [query]);\n\n // Permission check via shared hook\n const hasPermission = usePermissionCheck(operationNames, accessParameters, \"LysQueryProvider\");\n\n // Track last processed refresh signal version\n const lastRefreshVersionRef = useRef(0);\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [data, setData] = useState<TQuery[\"response\"] | undefined>(undefined);\n const [load, setLoad] = useState<boolean>(false);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n const reloadQuery = useCallback(() => {\n disposeQuery();\n setLoad(true);\n }, [disposeQuery]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Load query when permission granted and load requested\n */\n useEffect(() => {\n if (hasPermission && load && !queryReference) {\n setLoad(false);\n connectedUserInfo.push(() => loadQuery(parameters, options));\n }\n }, [hasPermission, load, queryReference, connectedUserInfo.push, loadQuery, parameters, options]);\n\n /**\n * Handle refresh signal from ChatbotProvider\n * Reloads query when a refresh is triggered for any of this query's node types\n */\n useEffect(() => {\n // Check if this is a new signal we haven't processed yet\n if (refreshSignal.version > lastRefreshVersionRef.current) {\n // Check if any of our node types are in the refresh signal\n const shouldRefresh = nodeTypes.some(nodeType =>\n refreshSignal.nodes.includes(nodeType)\n );\n\n if (shouldRefresh) {\n lastRefreshVersionRef.current = refreshSignal.version;\n reloadQuery();\n }\n }\n }, [refreshSignal, nodeTypes, reloadQuery]);\n\n /**\n * Expose ref interface using useImperativeHandle\n */\n useImperativeHandle(ref, () => ({\n hasPermission,\n data,\n isLoading: load,\n load: reloadQuery\n }), [hasPermission, data, load, reloadQuery]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <LysQueryContext.Provider value={[data, reloadQuery]}>\n {hasPermission && (\n <Container className={Container === \"div\" ? \"lys-query-container\" : undefined}>\n {/* Loading indicator (only for block container) */}\n {Container === \"div\" && !queryReference && load && effectiveFallback}\n\n {/* Error boundary for GraphQL errors - isolated to query execution only */}\n {queryReference && (\n <QueryErrorBoundary\n query={query}\n queryReference={queryReference}\n setData={setData}\n reloadQuery={reloadQuery}\n />\n )}\n\n {/* Children wrapped in Suspense to catch useFragment suspensions */}\n <React.Suspense fallback={Container === \"div\" ? effectiveFallback : null}>\n {children}\n </React.Suspense>\n </Container>\n )}\n </LysQueryContext.Provider>\n );\n}\n\n// Cast to preserve generics with forwardRef\nconst LysQueryProvider = forwardRef(LysQueryProviderInner) as <TQuery extends OperationType = OperationType>(\n props: LysQueryProviderProps<TQuery> & { ref?: React.Ref<LysQueryRefInterface<TQuery>> }\n) => ReturnType<typeof LysQueryProviderInner>;\n\nexport default LysQueryProvider;\n","import {createContext, useContext} from \"react\";\nimport {UseMutationConfig} from \"react-relay\";\nimport {Disposable, MutationParameters} from \"relay-runtime\";\n\nconst LysMutationContext = createContext<[\n ((config: UseMutationConfig<MutationParameters>) => void) | null,\n boolean,\n Disposable | undefined\n]>([\n null,\n false,\n undefined\n]);\n\n/**\n * Hook to access mutation commit function and state from LysMutationProvider\n */\nfunction useLysMutation<TMutation extends MutationParameters = MutationParameters>(): [\n ((config: UseMutationConfig<TMutation>) => void) | null,\n boolean,\n Disposable | undefined\n] {\n return useContext(LysMutationContext) as [\n ((config: UseMutationConfig<TMutation>) => void) | null,\n boolean,\n Disposable | undefined\n ];\n}\n\nexport {\n LysMutationContext,\n useLysMutation\n};\n","import {forwardRef, useCallback, useImperativeHandle, useMemo, useState} from \"react\";\nimport {\n LysMutationProviderProps,\n LysMutationRefInterface\n} from \"./types\";\nimport {LysMutationContext} from \"./hooks\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {useMutation, UseMutationConfig} from \"react-relay\";\nimport {Disposable, MutationParameters, PayloadError} from \"relay-runtime\";\nimport {useAlertMessages} from \"../AlertMessageProvider/hooks\";\nimport {extractOperationNames} from \"../../tools/relayTools\";\nimport {usePermissionCheck} from \"../hooks/usePermissionCheck\";\nimport type {RelayNetworkError} from \"../../types/relayTypes\";\n\n/**\n * LysMutationProvider - Manages GraphQL mutations with permission checking\n *\n * Features:\n * - Automatic permission checking based on operation names\n * - Queue system for authenticated requests\n * - Error handling with AlertMessageProvider\n * - Conditional rendering based on permissions\n */\nconst LysMutationProvider = forwardRef<LysMutationRefInterface, LysMutationProviderProps>((props, ref) => {\n /*******************************************************************************************************************\n * HOOKS\n ******************************************************************************************************************/\n\n const alertMessage = useAlertMessages();\n const connectedUserInfo = useConnectedUserInfo();\n const [commit, isInFlight] = useMutation(props.mutation, props.commitMutationFn);\n\n // Extract operation names from mutation (memoized)\n const operationNames = useMemo(() => extractOperationNames(props.mutation), [props.mutation]);\n\n // Permission check via shared hook\n const hasPermission = usePermissionCheck(operationNames, props.accessParameters, \"LysMutationProvider\");\n\n /*******************************************************************************************************************\n * STATES\n ******************************************************************************************************************/\n\n const [disposable, setDisposable] = useState<Disposable | undefined>(undefined);\n\n /*******************************************************************************************************************\n * CALLBACKS\n ******************************************************************************************************************/\n\n /**\n * Mutation commit wrapper that adds error and success handling\n */\n const lysCommit = useCallback((config: UseMutationConfig<MutationParameters>) => {\n const lysConfig = {...config};\n\n lysConfig.onError = (error: RelayNetworkError) => {\n // Check for ACCESS_DENIED_ERROR to handle session expiration\n const hasAccessDenied = error?.source?.errors?.some(\n (err) => err.message === \"ACCESS_DENIED_ERROR\"\n );\n\n if (hasAccessDenied) {\n // Handle session expiration - redirect to login\n connectedUserInfo.handleSessionExpired();\n config.onError?.(error);\n return;\n }\n\n alertMessage.merge(\n error?.source?.errors?.map((err) => {\n let level: \"ERROR\" | \"CRITICAL\" = \"ERROR\";\n if (err.message === \"INTERNAL_ERROR\") {\n level = \"CRITICAL\";\n }\n return {\n text: err.message,\n level: level\n };\n }) ?? []\n );\n\n config.onError?.(error);\n };\n\n lysConfig.onCompleted = (response: MutationParameters[\"response\"], errors: PayloadError[] | null) => {\n config.onCompleted?.(response, errors);\n\n alertMessage.merge(\n errors?.map((error) => ({\n text: error.message,\n level: error.severity || \"ERROR\"\n })) ?? []\n );\n };\n\n const newDisposable = commit(lysConfig);\n setDisposable(newDisposable);\n }, [alertMessage, commit, connectedUserInfo.handleSessionExpired]);\n\n const pushCommit = useCallback((config: UseMutationConfig<MutationParameters>) => {\n connectedUserInfo.push(() => lysCommit(config));\n }, [connectedUserInfo.push, lysCommit]);\n\n /*******************************************************************************************************************\n * EFFECTS\n ******************************************************************************************************************/\n\n /**\n * Expose ref interface using useImperativeHandle\n */\n useImperativeHandle(ref, () => ({\n isInFlight,\n commit: hasPermission ? pushCommit : undefined,\n disposable: !isInFlight ? disposable : undefined\n }), [hasPermission, pushCommit, isInFlight, disposable]);\n\n /*******************************************************************************************************************\n * RENDER\n ******************************************************************************************************************/\n\n return (\n <LysMutationContext.Provider\n value={[\n hasPermission ? pushCommit : null,\n isInFlight,\n !isInFlight ? disposable : undefined\n ]}\n >\n {(hasPermission || props.notPermissionDisplayType === \"show\") && props.children}\n </LysMutationContext.Provider>\n );\n});\n\nexport default LysMutationProvider;\n","import {createContext, useContext} from \"react\";\nimport {ClientContextValue} from \"./types\";\n\n/**\n * Client context\n */\nconst ClientContext = createContext<ClientContextValue>({\n clientId: null,\n setClientId: () => {\n console.warn(\"ClientProvider not initialized: setClientId\");\n },\n isLocked: false\n});\n\n/**\n * Hook to access the current client ID context.\n *\n * - For client users (user.clientId is set): returns the user's clientId, locked.\n * - For admin/super-admin users: returns the manually selected clientId, changeable.\n *\n * Must be used within ClientProvider.\n */\nfunction useClientId(): ClientContextValue {\n return useContext(ClientContext);\n}\n\nexport {\n ClientContext,\n useClientId\n};\n","import * as React from \"react\";\nimport {useCallback, useEffect, useMemo, useRef, useState} from \"react\";\nimport {useLocation} from \"react-router-dom\";\nimport {ClientContext} from \"./hooks\";\nimport {ClientProviderProps} from \"./types\";\nimport {useConnectedUserInfo} from \"../ConnectedUserProvider/hooks\";\nimport {useUrlQueries} from \"../UrlQueriesProvider/hooks\";\n\nconst SESSION_KEY = \"lys_clientId\";\nconst URL_PARAM_KEY = \"clientId\";\n\n/**\n * ClientProvider - Manages the current client ID selection\n *\n * Features:\n * - For client users: clientId is locked to user.clientId\n * - For admin users: clientId is selectable\n * - Persisted in sessionStorage (survives page navigation)\n * - Synced to URL query param (visible for debugging)\n * - Automatically clears on logout (user becomes undefined)\n *\n * Must be placed after ConnectedUserProvider and inside UrlQueriesProvider.\n */\nconst ClientProvider: React.ComponentType<ClientProviderProps> = ({children}) => {\n const {user} = useConnectedUserInfo();\n const {update: updateUrl, appliedParams} = useUrlQueries();\n const location = useLocation();\n\n const isLocked = !!user?.clientId;\n const prevUserRef = useRef(user);\n\n const [selectedClientId, setSelectedClientId] = useState<string | null>(() => {\n // URL param takes priority (e.g. shared link), then sessionStorage\n return appliedParams.get(URL_PARAM_KEY) || sessionStorage.getItem(SESSION_KEY);\n });\n\n /**\n * Clear selection on logout (user was defined, now undefined)\n */\n useEffect(() => {\n const wasLoggedIn = prevUserRef.current !== undefined;\n const isLoggedOut = user === undefined;\n prevUserRef.current = user;\n\n if (wasLoggedIn && isLoggedOut) {\n sessionStorage.removeItem(SESSION_KEY);\n setSelectedClientId(null);\n updateUrl({[URL_PARAM_KEY]: null});\n }\n }, [user, updateUrl]);\n\n /**\n * Sync clientId to URL on selection change or page navigation\n * Uses UrlQueriesProvider.update (same setSearchParams as other components)\n * to avoid conflicts when multiple params change in the same effect cycle\n */\n useEffect(() => {\n if (isLocked) return;\n\n if (selectedClientId) {\n updateUrl({[URL_PARAM_KEY]: selectedClientId});\n } else {\n updateUrl({[URL_PARAM_KEY]: null});\n }\n }, [selectedClientId, location.pathname, isLocked, updateUrl]);\n\n /**\n * Resolved clientId: locked from user profile or manual selection\n */\n const clientId = useMemo(() => {\n if (user?.clientId) {\n return user.clientId;\n }\n return selectedClientId;\n }, [user?.clientId, selectedClientId]);\n\n /**\n * Update the selected client ID (persists to sessionStorage + URL)\n */\n const setClientId = useCallback((id: string | null) => {\n if (isLocked) return;\n if (id) {\n sessionStorage.setItem(SESSION_KEY, id);\n } else {\n sessionStorage.removeItem(SESSION_KEY);\n }\n setSelectedClientId(id);\n }, [isLocked]);\n\n const value = useMemo(() => ({\n clientId,\n setClientId,\n isLocked\n }), [clientId, setClientId, isLocked]);\n\n return (\n <ClientContext.Provider value={value}>\n {children}\n </ClientContext.Provider>\n );\n};\n\nClientProvider.displayName = \"ClientProvider\";\n\nexport default ClientProvider;","/**\n * Error message used to identify GraphQL errors\n */\nexport const GRAPHQL_ERROR = \"GraphQL Error\";\n"],"names":["React","config","node","ConnectedUserFragment","_ConnectedUserFragment_user","ConnectedUserProviderQueryNode","_ConnectedUserProviderQuery","RefreshMutationNode","_ConnectedUserProviderRefreshMutation","ConnectedUserProviderInner","forwardRef","props","ref","queryRef","onMutationSuccess","alertMessage","useAlertMessages","intl","useIntl","updateLocale","useLocale","data","usePreloadedQuery","user","useFragment","connectedUser","accessTokenExpireIn","setAccessTokenExpireIn","useState","_webserviceBuffer","setWebserviceBuffer","isRefreshInflightRef","useRef","refreshCallbacksRef","commitLogin","isLoginInflight","useMutation","_ConnectedUserProviderLoginMutation","commitRefresh","commitLogout","isLogoutInflight","_ConnectedUserProviderLogoutMutation","commitLysRefresh","useCallback","current","variables","onCompleted","response","errors","length","refreshAccessToken","onError","error","clearRelayCache","relayError","source","locale","forEach","err","message","isErrorKey","console","merge","text","errorTranslations","UNKNOWN_ERROR","level","commitLysLogin","login","password","inputs","commitLysLogout","formatMessage","id","handleSessionExpired","onRefreshSuccess","push","callbacks","cb","webservice","timeStampSecondNow","Date","now","isValid","prev","useEffect","currentBuffer","language","code","jsx","ConnectedUserContext","Provider","value","logout","refresh","children","displayName","ConnectedUserProvider","loadQuery","useQueryLoader","queryLoadedRef","commitInitialRefresh","fetchPolicy","handleMutationSuccess","checkOperationsPermission","checkOperationsPermissionUtil","query","_WebserviceAccessProviderQuery","QueryExecutor","onData","webservicesData","useMemo","allAccessibleWebservices","edges","map","edge","accessLevels","userAccessLevels","filter","ws","WebserviceAccessProvider","useConnectedUserInfo","t","useWebserviceAccessProviderTranslations","disposeQuery","hasError","setHasError","webservicesMap","setWebservicesMap","Map","handleQueryData","newMap","set","handleQueryError","includes","some","e","log","checkWebserviceAccess","webserviceName","snakeCaseName","toSnakeCase","has","getWebserviceAccessLevels","get","contextValue","jsxs","style","padding","textAlign","Fragment","ErrorBoundaryProvider","Suspense","fallback","WebserviceAccessContext","_a"],"mappings":";;;;;;;;;;;;;AAoBA,MAAM,8BAA8BA,eAAM,UAAwB;AAAA,EAAlE;AAAA;AACI,iCAAe,EAAC,UAAU,OAAO,OAAO,KAAA;AAAA;AAAA,EAExC,OAAO,yBAAyB,OAAqB;AAEjD,WAAO,EAAC,UAAU,MAAM,MAAA;AAAA,EAC5B;AAAA,EAEA,kBAAkB,OAAc,YAA6B;AAGzD,QAAI,KAAK,MAAM,SAAS;AACpB,WAAK,MAAM,QAAQ,KAAK;AAAA,IAC5B;AAAA,EACJ;AAAA,EAEA,SAAS;AACL,UAAM,EAAC,UAAU,WAAW,KAAA,IAAQ,KAAK;AACzC,UAAM,EAAC,aAAY,KAAK;AAIxB,QAAI,UAAU;AACV,aAAO;AAAA,IACX;AAEA,WAAO;AAAA,EACX;AACJ;AC5BA,MAAM,sBAAsB,cAAuC;AAAA,EAC/D,UAAU,MAAM;AACZ,YAAQ,KAAK,gDAAgD;AAAA,EACjE;AAAA,EACA,UAAU,CAAC,QAAgB;AAC/B,CAAC;AAKD,SAAS,kBAAkB;AACvB,SAAO,WAAW,mBAAmB;AACzC;AC1BA,MAAM,cAAc;AAYpB,MAAM,kBAAkB,MAA8B;AAClD,MAAI;AACA,UAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,WAAO,SAAS,KAAK,MAAM,MAAM,IAAI,CAAA;AAAA,EACzC,QAAQ;AACJ,WAAO,CAAA;AAAA,EACX;AACJ;AAKA,MAAM,YAAY,CAAC,KAAa,UAAwB;AACpD,MAAI;AACA,UAAM,SAAS,gBAAA;AACf,WAAO,GAAG,IAAI;AACd,iBAAa,QAAQ,aAAa,KAAK,UAAU,MAAM,CAAC;AAAA,EAC5D,QAAQ;AAAA,EAER;AACJ;AAKA,MAAM,WAAW,CAAC,QAAwB;AACtC,QAAM,SAAS,gBAAA;AACf,SAAO,OAAO,GAAG,KAAK;AAC1B;AAeA,MAAM,uBAA4D,CAAC,EAAC,eAAc;AAC9E,SACI,oBAAC,oBAAoB,UAApB,EAA6B,OAAO,EAAC,UAAU,WAAW,YACtD,UACL;AAER;AAEA,qBAAqB,cAAc;AClE5B,MAAM,qBAAqB,cAAuC,IAAI;AAM7E,MAAM,kBAA+B;AAAA,EACjC,UAAU;AAAA,EACV,QAAQ,CAAA;AACZ;AAOO,MAAM,iBAAiB,MAAwB;AAClD,QAAM,UAAU,WAAW,kBAAkB;AAG7C,QAAM,WAAW,QAA0B,OAAO;AAAA,IAC9C,SAAS;AAAA,IACT,gBAAgB,MAAM;AAAA,IAAC;AAAA,IACvB,kBAAkB,MAAM;AAAA,IAAC;AAAA,EAAA,IACzB,CAAA,CAAE;AAEN,SAAO,WAAW;AACtB;ACRA,MAAM,sBAA0D,CAAC,EAAC,eAAc;AAK5E,QAAM,CAAC,SAAS,UAAU,IAAI,SAAsB;AAAA,IAChD,UAAU;AAAA,IACV,QAAQ,CAAA;AAAA,EAAC,CACZ;AAUD,QAAM,iBAAiB,YAAY,CAC/B,UACA,SAAgD,CAAA,MAC/C;AACD,eAAW,EAAC,UAAU,QAAO;AAAA,EACjC,GAAG,CAAA,CAAE;AAKL,QAAM,mBAAmB,YAAY,MAAM;AACvC,eAAW,EAAC,UAAU,MAAM,QAAQ,CAAA,GAAG;AAAA,EAC3C,GAAG,CAAA,CAAE;AAML,QAAM,eAAe,QAAQ,OAAO;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,CAAC,SAAS,gBAAgB,gBAAgB,CAAC;AAM/C,6BACK,mBAAmB,UAAnB,EAA4B,OAAO,cAC/B,UACL;AAER;AClEA,MAAM,uBAAuB,cAA6B,EAAC,OAAO,CAAA,GAAI,SAAS,GAAE;AAE1E,MAAM,mBAAmB,MAAqB;AACjD,SAAO,WAAW,oBAAoB;AAC1C;ACSA,MAAM,kBAAkD,CAAC,EAAC,eAAc;AAKpE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,CAAA,CAAE;AAC1D,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAwB,IAAI;AACxE,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAkB,KAAK;AACjE,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAkB,IAAI;AACtE,QAAM,CAAC,aAAa,cAAc,IAAI,SAAkB,KAAK;AAC7D,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAwB,EAAC,OAAO,CAAA,GAAI,SAAS,GAAE;AASzF,QAAM,aAAa,YAAY,CAAC,YAAyB;AACrD,gBAAY,CAAA,SAAQ,CAAC,GAAG,MAAM,OAAO,CAAC;AAAA,EAC1C,GAAG,CAAA,CAAE;AAKL,QAAM,oBAAoB,YAAY,CAAC,iBAAyB;AAC5D,gBAAY,CAAA,SAAQ;AAChB,UAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,YAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,UAAI,KAAK,SAAS,YAAa,QAAO;AACtC,YAAM,UAAU,CAAC,GAAG,IAAI;AACxB,cAAQ,QAAQ,SAAS,CAAC,IAAI,EAAC,GAAG,MAAM,SAAS,KAAK,UAAU,aAAA;AAChE,aAAO;AAAA,IACX,CAAC;AAAA,EACL,GAAG,CAAA,CAAE;AAKL,QAAM,oBAAoB,YAAY,MAAM;AACxC,gBAAY,CAAA,CAAE;AACd,sBAAkB,IAAI;AAAA,EAC1B,GAAG,CAAA,CAAE;AAML,QAAM,iBAAiB,YAAY,CAAC,UAAoB;AACpD,qBAAiB,CAAA,UAAS;AAAA,MACtB;AAAA,MACA,SAAS,KAAK,UAAU;AAAA,IAAA,EAC1B;AAAA,EACN,GAAG,CAAA,CAAE;AAML,QAAM,eAAe,QAAQ,OAAO;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,CAAC,UAAU,gBAAgB,eAAe,kBAAkB,aAAa,eAAe,YAAY,mBAAmB,mBAAmB,cAAc,CAAC;AAM7J,SACI,oBAAC,eAAe,UAAf,EAAwB,OAAO,cAC5B,UAAA,oBAAC,qBAAqB,UAArB,EAA8B,OAAO,eACjC,UACL,GACJ;AAER;AC1GA,MAAM,oBAAoB,cAQvB;AAAA,EACC,kBAAkB;AAAA,EAClB,eAAe,IAAI,gBAAA;AAAA,EACnB,cAAc,CAAA;AAAA,EACd,OAAO,MAAM,QAAQ,MAAM,uBAAuB;AAAA,EAClD,MAAM,MAAM,QAAQ,MAAM,sBAAsB;AAAA,EAChD,QAAQ,MAAM,QAAQ,MAAM,wBAAwB;AAAA,EACpD,OAAO,MAAM,QAAQ,MAAM,uBAAuB;AACtD,CAAC;AAcD,MAAM,gBAAgB,MAAM;AACxB,SAAO,WAAW,iBAAiB;AACvC;ACTA,MAAM,qBAAmE,CAAC,EAAC,eAAc;AAKrF,QAAM,CAAC,cAAc,eAAe,IAAI,gBAAA;AAMxC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAkB,KAAK;AAC7D,QAAM,CAAC,cAAc,eAAe,IAAI,SAAyC,CAAA,CAAE;AASnF,QAAM,mBAA4B,QAAQ,MAAM;AAC5C,WAAO,OAAO,KAAK,YAAY,EAAE;AAAA,MAAK,CAAA,QAAA;;AAClC,mCAAa,GAAG,MAAhB,mBAAmB,gBAAe,aAAa,IAAI,GAAG;AAAA;AAAA,IAAA;AAAA,EAE9D,GAAG,CAAC,cAAc,YAAY,CAAC;AAU/B,QAAM,QAAQ,YAAY,CAAC,KAAa,UAAyB;AAC7D,oBAAgB,CAAA,SAAQ;;AACpB,YAAI,UAAK,GAAG,MAAR,mBAAW,iBAAe,+BAAO,aAAY;AAC7C,eAAO;AAAA,MACX;AACA,aAAO,EAAC,GAAG,MAAM,CAAC,GAAG,GAAG,MAAA;AAAA,IAC5B,CAAC;AAAA,EACL,GAAG,CAAA,CAAE;AAKL,QAAM,OAAO,YAAY,CAAC,KAAa,UAAyB;AAC5D,UAAM,KAAK,KAAK;AAChB,oBAAgB,CAAA,SAAQ;AACpB,UAAI,UAAU,UAAa,UAAU,MAAM;AACvC,aAAK,IAAI,KAAK,MAAM,SAAA,CAAU;AAAA,MAClC,OAAO;AACH,aAAK,OAAO,GAAG;AAAA,MACnB;AACA,aAAO;AAAA,IACX,CAAC;AAAA,EACL,GAAG,CAAC,OAAO,eAAe,CAAC;AAK3B,QAAM,QAAQ,YAAY,MAAM;AAC5B,UAAM,kBAAkB,IAAI,gBAAA;AAE5B,WAAO,QAAQ,YAAY,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACnD,UAAI,UAAU,UAAa,UAAU,MAAM;AACvC,wBAAgB,IAAI,KAAK,MAAM,SAAA,CAAU;AAAA,MAC7C;AAAA,IACJ,CAAC;AAED,oBAAgB,eAAe;AAAA,EACnC,GAAG,CAAC,cAAc,eAAe,CAAC;AAalC,QAAM,oBAAoB,OAAuC,EAAE;AACnE,QAAM,oBAAoB,OAAO,KAAK;AAEtC,QAAM,SAAS,YAAY,CAAC,SAAyC;AACjE,WAAO,OAAO,kBAAkB,SAAS,IAAI;AAE7C,QAAI,CAAC,kBAAkB,SAAS;AAC5B,wBAAkB,UAAU;AAC5B,qBAAe,MAAM;AACjB,0BAAkB,UAAU;AAC5B,cAAM,UAAU,EAAC,GAAG,kBAAkB,QAAA;AACtC,0BAAkB,UAAU,CAAA;AAE5B,wBAAgB,CAAA,SAAQ;AACpB,gBAAM,OAAO,IAAI,gBAAgB,IAAI;AACrC,iBAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC9C,gBAAI,UAAU,UAAa,UAAU,MAAM;AACvC,mBAAK,IAAI,KAAK,MAAM,SAAA,CAAU;AAAA,YAClC,OAAO;AACH,mBAAK,OAAO,GAAG;AAAA,YACnB;AAAA,UACJ,CAAC;AACD,iBAAO;AAAA,QACX,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAAA,EACJ,GAAG,CAAC,eAAe,CAAC;AAUpB,YAAU,MAAM;AACZ,UAAM,mBAAmD,CAAA;AAEzD,iBAAa,QAAQ,CAAC,OAAO,QAAQ;AAEjC,UAAI,CAAC,MAAM,CAAC,KAAK,GAAG;AAChB,yBAAiB,GAAG,IAAI,OAAO,KAAK;AAAA,MACxC,WAES,UAAU,UAAU,UAAU,SAAS;AAC5C,yBAAiB,GAAG,IAAI,UAAU;AAAA,MACtC,OAEK;AACD,yBAAiB,GAAG,IAAI;AAAA,MAC5B;AAAA,IACJ,CAAC;AAED,QAAI,OAAO,KAAK,gBAAgB,EAAE,QAAQ;AACtC,sBAAgB,gBAAgB;AAAA,IACpC;AAEA,mBAAe,IAAI;AAAA,EACvB,GAAG,CAAC,YAAY,CAAC;AAMjB,SACI;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACG,OAAO;AAAA,QACH;AAAA,QACA,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAGH,UAAA,eAAe;AAAA,IAAA;AAAA,EAAA;AAG5B;ACzLA,MAAM,sBAAsB,cAEzB;AAAA,EACC,OAAO,MAAM;AACT,YAAQ,KAAK,sCAAsC;AAAA,EACvD;AACJ,CAAC;AAKD,SAAS,mBAAmB;AACxB,SAAO,WAAW,mBAAmB;AACzC;ACLA,MAAM,uBAAuE,CACzE;AAAA,EACI;AAAA,EACA;AACJ,MAAM;AAMN,QAAM,CAAC,UAAU,WAAW,IAAI,SAAkC,CAAA,CAAE;AACpE,QAAM,mBAAmB,OAAO,CAAC;AASjC,QAAM,eAAe,YAAY,CAAC,UAAkB;AAChD,gBAAY,CAAA,SAAQ,KAAK,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC;AAAA,EAC1D,GAAG,CAAA,CAAE;AAKL,QAAM,cAAc,YAAY,CAAC,cAAiD;AAC9E,QAAI,UAAU,SAAS,GAAG;AACtB,YAAM,gBAAgB,UAAU,IAAI,CAAC,YAAY;AAE7C,cAAM,YAAY,QAAQ,UAAU,cAAc,QAAQ,UAAU,UAC9D,QAAQ,QACR,QAAQ,UAAU,YAClB,QAAQ,OACR,QAAQ;AAEd,kBAAU,IAAI,QAAQ,KAAK,KAAK,QAAQ,IAAI;AAG5C,yBAAiB,WAAW;AAC5B,cAAM,WAAW,SAAS,KAAK,KAAK,IAAI,iBAAiB,OAAO;AAEhE,eAAO;AAAA,UACH,GAAG;AAAA,UACH,IAAI;AAAA,UACJ,+BAAe,KAAA;AAAA,QAAK;AAAA,MAE5B,CAAC;AACD,kBAAY,UAAQ,CAAC,GAAG,MAAM,GAAG,aAAa,CAAC;AAAA,IACnD;AAAA,EACJ,GAAG,CAAA,CAAE;AAML,SACI,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA,oBAAC,oBAAoB,UAApB,EAA6B,OAAO;AAAA,MACjC,OAAO;AAAA,IAAA,GAEN,SAAA,CACL;AAAA,IACC,eAAe,UAAU,YAAY;AAAA,EAAA,GAC1C;AAER;AC1EO,MAAM,gBAAgB,cAAkD,MAAS;AAQxF,MAAM,iBAAgD,CAAC,EAAC,eAAe,gBAAgB,eAAc;AAKjG,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAiB,aAAa;AAS1D,QAAM,eAAe,YAAY,CAAC,cAAsB;AACpD,cAAU,SAAS;AAAA,EACvB,GAAG,CAAA,CAAE;AASL,QAAM,WAAW,QAAQ,MAAM;AAC3B,WAAO,eAAe,MAAM,KAAK,CAAA;AAAA,EACrC,GAAG,CAAC,QAAQ,cAAc,CAAC;AAM3B,SACI,oBAAC,cAAc,UAAd,EAAuB,OAAO,EAAC,QAAQ,aAAA,GACpC,UAAA,oBAAC,cAAA,EAAa,QAAgB,UACzB,UACL,GACJ;AAER;AChDA,MAAM,sBAA6C;AAAA,EAC/C,SAAS;AAAA,EACT,OAAO,CAAA;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,MAAM,MAAM;AACR,YAAQ,MAAM,0DAA0D;AAAA,EAC5E;AAAA,EACA,QAAQ,MAAM;AACV,YAAQ,MAAM,4DAA4D;AAAA,EAC9E;AAAA,EACA,OAAO,MAAM;AACT,YAAQ,MAAM,2DAA2D;AAAA,EAC7E;AAAA,EACA,MAAM,MAAM;AACR,YAAQ,MAAM,0DAA0D;AAAA,EAC5E;AAAA,EACA,UAAU,MAAM;AACZ,YAAQ,MAAM,8DAA8D;AAAA,EAChF;AAAA,EACA,UAAU,MAAM;AACZ,YAAQ,MAAM,8DAA8D;AAC5E,WAAO,MAAM;AAAA,IAAC;AAAA,EAClB;AAAA,EACA,iBAAiB,MAAM;AACnB,YAAQ,MAAM,qEAAqE;AACnF,WAAO,CAAA;AAAA,EACX;AACJ;AAKO,MAAM,mBAAmB,cAAqC,mBAAmB;AAuBjF,MAAM,eAAe,MAA6B;AACrD,SAAO,WAAW,gBAAgB;AACtC;AA8GO,SAAS,qBACZC,SAC0B;AAC1B,QAAM,EAAC,MAAM,QAAQ,OAAO,QAAA,IAAW,aAAA;AACvC,QAAM,EAAC,WAAW,OAAO,MAAM,WAAW,MAAM,OAAO,MAAM,YAAY,OAAO,UAAU,YAAA,IAAeA;AAMzG,QAAM,eAAe,OAAO,SAAS;AACrC,eAAa,UAAU;AAKvB,QAAM,SAAS,QAAQ,OAAM,mCAAS,eAAc,WAAW,CAAC,mCAAS,WAAW,SAAS,CAAC;AAK9F,QAAM,eAAe,OAAO,KAAK;AAKjC,QAAM,aAAa,YAAY,MAAM;AACjC,iBAAa,UAAU;AACvB,SAAK;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,aAAa;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACH;AAAA,EACL,GAAG,CAAC,MAAM,WAAW,OAAO,MAAM,MAAM,WAAW,UAAU,WAAW,CAAC;AAKzE,QAAM,cAAc,YAAY,MAAM;AAClC,UAAA;AAAA,EACJ,GAAG,CAAC,KAAK,CAAC;AASV,YAAU,MAAM;AACZ,QAAI,UAAU,aAAa,SAAS;AAChC,aAAO,WAAW,EAAC,WAAW,aAAa,SAAQ;AAAA,IACvD;AAAA,EAEJ,GAAG,CAAC,QAAQ,WAAW,QAAQ,GAAI,QAAQ,CAAA,CAAG,CAAC;AAE/C,SAAO;AAAA,IACH,MAAM;AAAA,IACN,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA;AAER;AC7OO,MAAM,qBAAkC;AAAA,EAC3C,OAAO,CAAA;AACX;AAYO,SAAS,cAAc,OAAoB,QAAmC;AACjF,UAAQ,OAAO,MAAA;AAAA,IACX,KAAK;AAED,aAAO;AAAA,QACH,GAAG;AAAA,QACH,OAAO,OAAO;AAAA,MAAA;AAAA,IAGtB,KAAK;AAED,aAAO;AAAA,QACH,GAAG;AAAA,QACH,OAAO,CAAC,GAAG,MAAM,OAAO,OAAO,OAAO;AAAA,MAAA;AAAA,IAG9C,KAAK;AAED,UAAI,MAAM,MAAM,WAAW,GAAG;AAC1B,eAAO;AAAA,MACX;AACA,aAAO;AAAA,QACH,GAAG;AAAA,QACH,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE;AAAA,MAAA;AAAA,IAGtC,KAAK;AAED,aAAO;AAAA,QACH,GAAG;AAAA,QACH,OAAO,CAAA;AAAA,MAAC;AAAA,IAGhB,KAAK;AAED,aAAO;AAAA,QACH,GAAG;AAAA,QACH,OAAO,MAAM,MAAM,IAAI,CAAA,WAAU;AAC7B,cAAI,OAAO,cAAc,OAAO,QAAQ,WAAW;AAC/C,mBAAO;AAAA,cACH,GAAG;AAAA,cACH,GAAI,OAAO,QAAQ,UAAU,UAAa,EAAE,OAAO,OAAO,QAAQ,MAAA;AAAA,cAClE,GAAI,OAAO,QAAQ,cAAc,UAAa,EAAE,WAAW,OAAO,QAAQ,UAAA;AAAA,cAC1E,GAAI,OAAO,QAAQ,YAAY,UAAa,EAAE,SAAS,OAAO,QAAQ,QAAA;AAAA,YAAQ;AAAA,UAEtF;AACA,iBAAO;AAAA,QACX,CAAC;AAAA,MAAA;AAAA,IAGT;AACI,aAAO;AAAA,EAAA;AAEnB;AClEA,MAAM,qBAAqB;AAM3B,MAAM,mBAAmB,CAAC,UAAgD;AAEtE,MAAI,OAAO,UAAU,WAAY,QAAO;AAIxC,MACI,OAAO,UAAU,YACjB,UAAU,QACV,cAAc,OAChB;AACE,UAAM,cAAe,MAA+B;AAIpD,QAAI,gBAAgB,OAAO,IAAI,eAAe,GAAG;AAC7C,aAAO;AAAA,IACX;AAMA,WAAO;AAAA,EACX;AAEA,SAAO;AACX;AAOA,MAAM,cAAyF,CAAC,EAAE,MAAM,gBAAgB;AACpH,MAAI,iBAAiB,IAAI,GAAG;AACxB,UAAM,YAAY;AAClB,WAAO,oBAAC,WAAA,EAAW,GAAI,aAAa,CAAA,EAAC,CAAI;AAAA,EAC7C;AAGA,yCAAU,UAAA,KAAA,CAAK;AACnB;AAeA,MAAM,oBAAsD,CAAC;AAAA,EACzD;AAAA,EACA,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX;AACJ,MAAM;AACF,QAAM,CAAC,OAAO,QAAQ,IAAI,WAAW,eAAe,kBAAkB;AACtE,QAAM,aAAa,cAAc,cAAA,IAAkB;AACnD,QAAM,aAAa,OAAiD,oBAAI,KAAK;AAC7E,QAAM,iBAAiB,OAAqD,oBAAI,KAAK;AACrF,QAAM,qBAAqB,OAAO,KAAK;AAGvC,QAAM,UAAU,QAAQ,MAAM;AAC1B,WAAO,MAAM,MAAM,SAAS,IAAI,MAAM,MAAM,MAAM,MAAM,SAAS,CAAC,IAAI;AAAA,EAC1E,GAAG,CAAC,MAAM,KAAK,CAAC;AAGhB,QAAM,YAAY,QAAQ,MAAM;AAC5B,WAAO,MAAM,MAAM,SAAS;AAAA,EAChC,GAAG,CAAC,MAAM,KAAK,CAAC;AAGhB,QAAM,SAAS,QAAQ,MAAM;AACzB,WAAO,MAAM,MAAM,SAAS;AAAA,EAChC,GAAG,CAAC,MAAM,KAAK,CAAC;AAGhB,QAAM,OAAO,YAAY,CAACA,YAAyB;AAC/C,aAAS,EAAE,MAAM,QAAQ,SAASA,SAAQ;AAAA,EAC9C,GAAG,CAAA,CAAE;AAGL,QAAM,SAAS,YAAY,CAAC,WAAmB,YAAoD;AAC/F,aAAS,EAAE,MAAM,UAAU,SAAS,EAAE,WAAW,GAAG,QAAA,GAAW;AAAA,EACnE,GAAG,CAAA,CAAE;AAGL,QAAM,QAAQ,YAAY,MAAM;AAC5B,aAAS,EAAE,MAAM,OAAO;AAAA,EAC5B,GAAG,CAAA,CAAE;AAGL,QAAM,OAAO;AAGb,QAAM,WAAW,YAAY,MAAM;AAC/B,aAAS,EAAE,MAAM,SAAS;AAAA,EAC9B,GAAG,CAAA,CAAE;AAGL,QAAM,WAAW,YAAY,CAAC,WAAmBA,YAA4C;AACzF,mBAAe,QAAQ,IAAI,WAAWA,OAAM;AAG5C,WAAO,MAAM;AACT,qBAAe,QAAQ,OAAO,SAAS;AAAA,IAC3C;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAM,kBAAkB,YAAY,MAAgB;AAChD,QAAI,CAAC,eAAe,CAAC,mBAAmB,CAAA;AAExC,UAAM,aAAa,WAAW,cAAc,IAAI,kBAAkB;AAClE,QAAI,CAAC,WAAY,QAAO,CAAA;AAExB,WAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO;AAAA,EAC/C,GAAG,CAAC,aAAa,UAAU,CAAC;AAG5B,YAAU,MAAM;AACZ,QAAI,SAAS;AACT,YAAM,MAAM,WAAW,QAAQ,IAAI,QAAQ,SAAS;AACpD,UAAI,OAAO,IAAI,UAAU,MAAM;AAC3B,YAAI,KAAA;AAAA,MACR;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,OAAO,CAAC;AAGZ,QAAM,mBAAmB,YAAY,CAAC,cAAsB;AACxD,UAAM,MAAM,WAAW,QAAQ,IAAI,SAAS;AAC5C,SAAI,2BAAK,WAAU,OAAO;AAEtB,eAAA;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACZ,QAAI,CAAC,eAAe,CAAC,WAAY;AAIjC,QAAI,CAAC,mBAAmB,QAAS;AAEjC,UAAM,aAAa,WAAW,cAAc,IAAI,kBAAkB;AAGlE,UAAM,mBAAmB,MAAM,MAAM,OAAO,CAAA,MAAK,EAAE,gBAAgB,KAAK;AAExE,QAAI,iBAAiB,SAAS,GAAG;AAE7B,YAAM,YAAY,iBAAiB,IAAI,CAAA,MAAK,EAAE,SAAS,EAAE,KAAK,GAAG;AACjE,UAAI,eAAe,WAAW;AAC1B,mBAAW,KAAK,oBAAoB,SAAS;AAAA,MACjD;AAAA,IACJ,OAAO;AAEH,UAAI,YAAY;AACZ,mBAAW,KAAK,oBAAoB,IAAI;AAAA,MAC5C;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,MAAM,OAAO,aAAa,UAAU,CAAC;AAGzC,YAAU,MAAM;AACZ,QAAI,CAAC,eAAe,CAAC,cAAc,mBAAmB,QAAS;AAE/D,UAAM,eAAe,gBAAA;AACrB,QAAI,aAAa,WAAW,GAAG;AAC3B,yBAAmB,UAAU;AAC7B;AAAA,IACJ;AAIA,UAAM,gBAAgB,YAAY,MAAM;AACpC,YAAM,UAA0B,CAAA;AAEhC,iBAAW,OAAO,cAAc;AAC5B,cAAMA,UAAS,eAAe,QAAQ,IAAI,GAAG;AAC7C,YAAIA,SAAQ;AACR,kBAAQ,KAAK,EAAE,WAAW,KAAK,GAAGA,SAAQ;AAAA,QAC9C;AAAA,MACJ;AAGA,UAAI,QAAQ,WAAW,aAAa,QAAQ;AACxC,sBAAc,aAAa;AAC3B,iBAAS,EAAE,MAAM,QAAQ,SAAS,SAAS;AAC3C,2BAAmB,UAAU;AAAA,MACjC;AAAA,IACJ,GAAG,EAAE;AAGL,UAAM,UAAU,WAAW,MAAM;AAC7B,oBAAc,aAAa;AAC3B,yBAAmB,UAAU;AAAA,IACjC,GAAG,GAAI;AAEP,WAAO,MAAM;AACT,oBAAc,aAAa;AAC3B,mBAAa,OAAO;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,aAAa,YAAY,eAAe,CAAC;AAG7C,QAAM,eAAe,QAAQ,OAAO;AAAA,IAChC;AAAA,IACA,OAAO,MAAM;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,CAAC,SAAS,MAAM,OAAO,QAAQ,WAAW,MAAM,QAAQ,OAAO,MAAM,UAAU,UAAU,eAAe,CAAC;AAG7G,QAAM,cAAc,QAAQ,MAAM;AAC9B,QAAI,CAAC,QAAS,QAAO;AAErB,WACI,qBAAC,OAAA,EAAI,WAAU,mCAEV,UAAA;AAAA,MAAA,aACG;AAAA,QAAC;AAAA,QAAA;AAAA,UACG,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS;AAAA,UACT,cAAW;AAAA,UAEV,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAIT,oBAAC,OAAA,EAAI,WAAU,eACV,kBAAQ,MAAA,CACb;AAAA,IAAA,GACJ;AAAA,EAER,GAAG,CAAC,SAAS,WAAW,OAAO,QAAQ,CAAC;AAExC,SACI,qBAAC,iBAAiB,UAAjB,EAA0B,OAAO,cAE7B,UAAA;AAAA,IAAA,WACG,qBAAA,UAAA,EACI,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAEG,KAAK,CAAC,QAAQ;AACV,gBAAI,KAAK;AACL,yBAAW,QAAQ,IAAI,QAAQ,WAAW,GAAG;AAE7C,kBAAI,IAAI,UAAU,OAAO;AACrB,iCAAiB,QAAQ,SAAS;AAAA,cACtC;AAAA,YACJ;AAAA,UACJ;AAAA,UACA,IAAI,cAAc,QAAQ,SAAS;AAAA,UACnC,OAAO,eAAe;AAAA,UACtB,MAAM,QAAQ,UAAU,kBACpB,oBAAC,aAAA,EAAY,MAAM,QAAQ,MAAM,WAAW,QAAQ,UAAA,CAAW;AAAA,UAEnE,MAAM,QAAQ;AAAA,UACd,WAAW,QAAQ;AAAA,UACnB,UAAU,QAAQ;AAAA,QAAA;AAAA,QAjBb,QAAQ;AAAA,MAAA;AAAA,MAmBhB,2CAAc;AAAA,IAAO,GAC1B;AAAA,IAEH;AAAA,EAAA,GACL;AAER;ACtRA,MAAMC,SAAyB,4BAAU;AACzC,MAAI,KAAK;AAAA,IACP;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,MAEF,cAAc;AAAA,IAAA;AAAA,EAChB;AAEF,SAAO;AAAA,IACL,YAAY;AAAA,MACV,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAe;AAAA,MACf,QAAQ;AAAA,MACR,eAAe;AAAA,IAAA;AAAA,IAEjB,QAAQ;AAAA,IACR,aAAa;AAAA,MACX,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAe;AAAA,IAAA;AAAA,IAEjB,UAAU;AAAA,MACR,WAAW;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,MACZ,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IAAA;AAAA,EACV;AAEF,GAAA;AAECA,OAAa,OAAO;ACzCrB,MAAMA,SAAyB,4BAAU;AACzC,MAAI,KAAK;AAAA,IACP;AAAA,MACE,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,QAAQ;AAAA,IAAA;AAAA,EACV,GAEF,KAAK;AAAA,IACH;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,QACN;AAAA,UACE,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,gBAAgB;AAAA,QAAA;AAAA,MAClB;AAAA,MAEF,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,QAEhB;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,QAEhB;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,MAEF,cAAc;AAAA,IAAA;AAAA,EAChB;AAEF,SAAO;AAAA,IACL,YAAY;AAAA,MACV,uBAAwB;AAAA,MACxB,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAe;AAAA,MACf,QAAQ;AAAA,MACR,eAAe;AAAA,IAAA;AAAA,IAEjB,QAAQ;AAAA,IACR,aAAa;AAAA,MACX,uBAAwB;AAAA,MACxB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAe;AAAA,IAAA;AAAA,IAEjB,UAAU;AAAA,MACR,WAAW;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,MACZ,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IAAA;AAAA,EACV;AAEF,GAAA;AAECA,OAAa,OAAO;AClFrB,MAAMA,SAAyB,4BAAU;AACzC,MAAI,KAAK;AAAA,IACP;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,QAEhB;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,QAEhB;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,MAEF,cAAc;AAAA,IAAA;AAAA,EAChB;AAEF,SAAO;AAAA,IACL,YAAY;AAAA,MACV,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAe;AAAA,MACf,QAAQ;AAAA,MACR,eAAe;AAAA,IAAA;AAAA,IAEjB,QAAQ;AAAA,IACR,aAAa;AAAA,MACX,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAe;AAAA,IAAA;AAAA,IAEjB,UAAU;AAAA,MACR,WAAW;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,MACZ,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IAAA;AAAA,EACV;AAEF,GAAA;AAECA,OAAa,OAAO;AChErB,MAAMA,SAAyB,4BAAU;AACzC,MAAI,KAAK;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,cAAc;AAAA,EAAA,GAEhB,KAAK;AAAA,IACF;AAAA,IACD;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAc;AAAA,IAAA;AAAA,EAChB;AAEF,SAAO;AAAA,IACL,YAAY;AAAA,MACV,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,cAAc;AAAA,YACZ;AAAA,cACE,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,QAAQ;AAAA,YAAA;AAAA,UACV;AAAA,UAEF,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,MAEF,QAAQ;AAAA,MACR,eAAe;AAAA,IAAA;AAAA,IAEjB,QAAQ;AAAA,IACR,aAAa;AAAA,MACX,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,cAAc;AAAA,YACX;AAAA,YACD;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,cAAc;AAAA,YAAA;AAAA,YAEhB;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAc;AAAA,gBACX;AAAA,gBACD;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,gBAEhB;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,gBAEhB;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,gBAEhB;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,gBAEhB;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,cAChB;AAAA,cAEF,cAAc;AAAA,YAAA;AAAA,YAEhB;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAe;AAAA,cACf,cAAc;AAAA,YAAA;AAAA,YAEhB;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAe;AAAA,cACf,cAAc;AAAA,YAAA;AAAA,YAEhB;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAc;AAAA,gBACZ;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,gBAEhB;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,cAAc;AAAA,gBAAA;AAAA,gBAEhB;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,gBAAgB;AAAA,kBAChB,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV,cAAe;AAAA,kBACf,cAAc;AAAA,gBAAA;AAAA,gBAEf;AAAA,cAAA;AAAA,cAEH,cAAc;AAAA,YAAA;AAAA,UAChB;AAAA,UAEF,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,IACF;AAAA,IAEF,UAAU;AAAA,MACR,WAAW;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,MACZ,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IAAA;AAAA,EACV;AAEF,GAAA;AAECA,OAAa,OAAO;AC1Md,MAAM,YAAY,MAA8B;AACnD,QAAM,UAAU,WAAW,aAAa;AAExC,MAAI,CAAC,SAAS;AACV,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAClE;AAEA,SAAO;AACX;AC+BA,MAAMA,SAAwB,4BAAU;AACxC,MAAI,KAAK;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,cAAc;AAAA,EAAA,GAEhB,KAAK;AAAA,IACF;AAAA,IACD;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAc;AAAA,IAAA;AAAA,EAChB;AAEF,SAAO;AAAA,IACL,uBAAuB,CAAA;AAAA,IACvB,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,cAAc;AAAA,MACX;AAAA,MACD;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,cAAc;AAAA,MAAA;AAAA,MAEhB;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,cAAc;AAAA,UACX;AAAA,UACD;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,QAChB;AAAA,QAEF,cAAc;AAAA,MAAA;AAAA,MAEhB;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,cAAe;AAAA,QACf,cAAc;AAAA,MAAA;AAAA,MAEhB;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,cAAe;AAAA,QACf,cAAc;AAAA,MAAA;AAAA,MAEhB;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,cAAc;AAAA,UACZ;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,cAAc;AAAA,UAAA;AAAA,UAEhB;AAAA,YACE,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,gBAAgB;AAAA,YAChB,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,UAAU;AAAA,YACV,cAAe;AAAA,YACf,cAAc;AAAA,UAAA;AAAA,QAChB;AAAA,QAEF,cAAc;AAAA,MAAA;AAAA,IAChB;AAAA,IAEF,QAAQ;AAAA,IACR,eAAe;AAAA,EAAA;AAEjB,GAAA;AAECA,OAAa,OAAO;AC7Kd,MAAMC,wBAAAC;ACMb,MAAMC,iCAAAC;AAWN,MAAMC,sBAAAC;AAWN,MAAMC,6BAA6BC,WAGhC,CAACC,OAAOC,QAAQ;;AACf,QAAM;AAAA,IAACC;AAAAA,IAAUC;AAAAA,EAAiB,IAAIH;AAMtC,QAAMI,eAAeC,iBAAA;AACrB,QAAMC,OAAOC,QAAA;AACb,QAAM;AAAA,IAACC;AAAAA,MAAgBC,UAAA;AAUvB,QAAMC,OAAOC,kBAAkBjB,gCAAgCQ,QAAQ;AAMvE,QAAMU,OAAOC,YAAYrB,wBAAuBkB,6BAAMI,kBAAiB,IAAI;AAM3E,QAAM,CAACC,qBAAqBC,sBAAsB,IAAIC,SAA6B,MAAS;AAC5F,QAAM,CAACC,mBAAmBC,mBAAmB,IAAIF,SAAyB,CAAA,CAAE;AAC5E,QAAMG,uBAAuBC,OAAgB,KAAK;AAClD,QAAMC,sBAAsBD,OAA0B,EAAE;AAMxD,QAAM,CAACE,aAAaC,eAAe,IAAIC,YAAAC,MAQvC;AAEA,QAAM,CAACC,aAAa,IAAIF,YAAkD7B,mBAAmB;AAE7F,QAAM,CAACgC,cAAcC,gBAAgB,IAAIJ,YAAAK,MAMzC;AAUA,QAAMC,mBAAmBC,YAAY,MAAM;AAEvC,QAAIZ,qBAAqBa,SAAS;AAC9B;AAAA,IACJ;AAEAb,yBAAqBa,UAAU;AAE/BN,kBAAc;AAAA,MACVO,WAAW,CAAA;AAAA,MACXC,aAAaA,CAACC,UAAUC,WAAW;;AAC/BjB,6BAAqBa,UAAU;AAE/B,YAAI,CAACI,UAAU,EAACA,iCAAQC,SAAQ;AAE5BnC,4BAAA;AAAA,QACJ;AACAa,gCAAuBoB,MAAAA,SAASG,uBAATH,gBAAAA,IAA6BrB,mBAAmB;AAAA,MAC3E;AAAA,MACAyB,SAAUC,WAAiB;;AACvBrB,6BAAqBa,UAAU;AAG/BS,wBAAA;AAEAvC,0BAAA;AACAa,+BAAuB,MAAS;AAGhC,cAAM2B,aAAaF;AACnB,aAAIE,MAAAA,yCAAYC,WAAZD,gBAAAA,IAAoBN,QAAQ;AAC5B,gBAAMQ,SAASvC,KAAKuC;AACpBF,qBAAWC,OAAOP,OAAOS,QAASC,SAAQ;AACtC,gBAAIA,IAAIC,YAAY,6BAA6B;AAC7C,kBAAI,CAACC,WAAWF,IAAIC,OAAO,GAAG;AAC1BE,wBAAQT,MAAM,2BAA2BM,IAAIC,OAAO;AAAA,cACxD;AACA5C,2BAAa+C,MAAM,CAAC;AAAA,gBAChBC,MAAMH,WAAWF,IAAIC,OAAO,IACtBK,kBAAkBN,IAAIC,OAAO,EAAEH,MAAM,IACrCQ,kBAAkBC,cAAcT,MAAM;AAAA,gBAC5CU,OAAO;AAAA,cACX,CAAC,CAAC;AAAA,YACN;AAAA,UACJ,CAAC;AAAA,QACL,OAAO;AAEHnD,uBAAa+C,MAAM,CAAC;AAAA,YAChBC,MAAMX,MAAMO,WAAW;AAAA,YACvBO,OAAO;AAAA,UACX,CAAC,CAAC;AAAA,QACN;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL,GAAG,CAAC5B,eAAevB,cAAcD,mBAAmBG,KAAKuC,MAAM,CAAC;AAKhE,QAAMW,iBAAiBxB,YAAY,CAACyB,OAAeC,aAAqB;AACpEnC,gBAAY;AAAA,MACRW,WAAW;AAAA,QACPyB,QAAQ;AAAA,UACJF;AAAAA,UACAC;AAAAA,QACJ;AAAA;MAEJvB,aAAaA,CAACC,UAAUC,WAAW;;AAC/B,YAAI,CAACA,UAAU,EAACA,iCAAQC,SAAQ;AAE5BnC,4BAAA;AAAA,QACJ;AACAa,gCAAuBoB,MAAAA,SAASqB,UAATrB,gBAAAA,IAAgBrB,mBAAmB;AAAA,MAC9D;AAAA,MACAyB,SAAUC,WAAiB;;AACvB,cAAME,aAAaF;AACnBE,SAAAA,OAAAA,MAAAA,yCAAYC,WAAZD,gBAAAA,IAAoBN,WAApBM,gBAAAA,IAA4BG,QAASC,SAAQ;AACzC3C,uBAAa+C,MAAM,CAAC;AAAA,YAChBC,MAAML,IAAIC;AAAAA,YACVO,OAAO;AAAA,UACX,CAAC,CAAC;AAAA,QACN;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL,GAAG,CAAChC,aAAanB,cAAcD,iBAAiB,CAAC;AAKjD,QAAMyD,kBAAkB5B,YAAY,MAAM;AACtCJ,iBAAa;AAAA,MACTM,WAAW,CAAA;AAAA,MACXC,aAAaA,MAAM;AAEfO,wBAAA;AAEAvC,0BAAA;AACAa,+BAAuB,MAAS;AAChCZ,qBAAa+C,MAAM,CAAC;AAAA,UAChBC,MAAM9C,KAAKuD,cAAc;AAAA,YAACC,IAAI;AAAA,UAA0C,CAAC;AAAA,UACzEP,OAAO;AAAA,QACX,CAAC,CAAC;AAAA,MACN;AAAA,MACAf,SAAUC,WAAiB;;AACvB,cAAME,aAAaF;AACnBE,SAAAA,OAAAA,MAAAA,yCAAYC,WAAZD,gBAAAA,IAAoBN,WAApBM,gBAAAA,IAA4BG,QAASC,SAAQ;AACzC3C,uBAAa+C,MAAM,CAAC;AAAA,YAChBC,MAAML,IAAIC;AAAAA,YACVO,OAAO;AAAA,UACX,CAAC,CAAC;AAAA,QACN;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL,GAAG,CAAC3B,cAAcxB,cAAcE,MAAMH,iBAAiB,CAAC;AAQxD,QAAM4D,uBAAuB/B,YAAagC,sBAAkC;AAGxE,QAAIA,kBAAkB;AAClB1C,0BAAoBW,QAAQgC,KAAKD,gBAAgB;AAAA,IACrD;AAGA,QAAI,CAAC5C,qBAAqBa,SAAS;AAC/Bb,2BAAqBa,UAAU;AAE/BN,oBAAc;AAAA,QACVO,WAAW,CAAA;AAAA,QACXC,aAAaA,CAACC,UAAUC,WAAW;;AAC/BjB,+BAAqBa,UAAU;AAE/B,cAAI,CAACI,UAAU,EAACA,iCAAQC,SAAQ;AAE5BtB,oCAAuBoB,MAAAA,SAASG,uBAATH,gBAAAA,IAA6BrB,mBAAmB;AACvEZ,8BAAA;AAEA,kBAAM+D,YAAY5C,oBAAoBW;AACtCX,gCAAoBW,UAAU,CAAA;AAC9BiC,sBAAUpB,QAASqB,QAAO;AACtB,kBAAI;AACAA,mBAAA;AAAA,cACJ,SAAS1B,OAAO;AACZS,wBAAQT,MAAM,qCAAqCA,KAAK;AAAA,cAC5D;AAAA,YACJ,CAAC;AAAA,UACL,OAAO;AAEHnB,gCAAoBW,UAAU,CAAA;AAC9BS,4BAAA;AACAvC,8BAAA;AACAa,mCAAuB,MAAS;AAChCZ,yBAAa+C,MAAM,CAAC;AAAA,cAChBC,MAAM9C,KAAKuD,cAAc;AAAA,gBAACC,IAAI;AAAA,cAA2C,CAAC;AAAA,cAC1EP,OAAO;AAAA,YACX,CAAC,CAAC;AAAA,UACN;AAAA,QACJ;AAAA,QACAf,SAASA,MAAM;AACXpB,+BAAqBa,UAAU;AAE/BX,8BAAoBW,UAAU,CAAA;AAG9BS,0BAAA;AACAvC,4BAAA;AACAa,iCAAuB,MAAS;AAChCZ,uBAAa+C,MAAM,CAAC;AAAA,YAChBC,MAAM9C,KAAKuD,cAAc;AAAA,cAACC,IAAI;AAAA,YAA2C,CAAC;AAAA,YAC1EP,OAAO;AAAA,UACX,CAAC,CAAC;AAAA,QACN;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ,GAAG,CAAC5B,eAAexB,mBAAmBC,cAAcE,IAAI,CAAC;AAMzD,QAAM2D,OAAOjC,YAAaoC,gBAA2B;AACjD,UAAMC,qBAAqBC,KAAKC,IAAA,IAAQ;AAGxC,UAAMC,UAAUzD,wBAAwB,SACjCA,sBAAsBsD,qBAAqB,IAC5C;AAGN,QAAIG,WAAW,CAACpD,qBAAqBa,SAAS;AAC1CmC,iBAAA;AACA;AAAA,IACJ;AAGA,QAAI,CAACI,WAAW,CAACpD,qBAAqBa,SAAS;AAC3CF,uBAAA;AAAA,IACJ;AAIAZ,wBAAoBsD,UAAQ,CAAC,GAAGA,MAAML,UAAU,CAAC;AAAA,EACrD,GAAG,CAACrD,qBAAqBgB,gBAAgB,CAAC;AAO1C2C,YAAU,MAAM;AACZ,UAAML,qBAAqBC,KAAKC,IAAA,IAAQ;AACxC,UAAMC,UAAUzD,wBAAwB,SACjCA,sBAAsBsD,qBAAqB,IAC5C;AAEN,QAAIG,WAAW,CAACpD,qBAAqBa,SAAS;AAC1Cd,0BAAoBwD,mBAAiB;AACjC,YAAIA,cAAcrC,SAAS,GAAG;AAE1BqC,wBAAc7B,QAASsB,gBAAe;AAClC,gBAAI;AACAA,yBAAA;AAAA,YACJ,SAAS3B,OAAO;AACZS,sBAAQT,MAAM,wCAAwCA,KAAK;AAAA,YAC/D;AAAA,UACJ,CAAC;AAAA,QACL;AACA,eAAO,CAAA;AAAA,MACX,CAAC;AAAA,IACL;AAAA,EACJ,GAAG,CAAC1B,mBAAmB,CAAC;AAGxB2D,YAAU,MAAM;;AACZ,SAAI9D,MAAAA,6BAAMgE,aAANhE,gBAAAA,IAAgBiE,MAAM;AACtBrE,mBAAaI,KAAKgE,SAASC,IAAI;AAAA,IACnC;AAAA,EACJ,GAAG,EAACjE,kCAAMgE,aAANhE,mBAAgBiE,MAAMrE,YAAY,CAAC;AAGvCkE,YAAU,MAAM;;AACZ,UAAMhE,QAAO;AAAA,MACTkE,WAAUhE,MAAAA,6BAAMgE,aAANhE,gBAAAA,IAAgBiE;AAAAA;AAG9B,QAAI,OAAO5E,QAAQ,YAAY;AAC3BA,UAAIS,KAAI;AAAA,IACZ,WAAWT,KAAK;AACZA,UAAIgC,UAAUvB;AAAAA,IAClB;AAAA,EACJ,GAAG,EAACE,kCAAMgE,aAANhE,mBAAgBiE,MAAM5E,GAAG,CAAC;AAM9B,SACI6E,oBAACC,qBAAqBC,UAArB;AAAA,IAA8BC,OAAO;AAAA,MAClCrE;AAAAA,MACAqD;AAAAA,MACAiB,QAAQ,CAACtB,iBAAiB/B,gBAAgB;AAAA,MAC1C4B,OAAO,CAACD,gBAAgBhC,eAAe;AAAA,MACvC2D,SAAS,CAACpD,kBAAkB,KAAK;AAAA,MACjCgC;AAAAA;IAECqB,gBAAMA;AAAAA,EAAA,CACX;AAER,CAAC;AAEDtF,2BAA2BuF,cAAc;AAWzC,MAAMC,wBAAwBvF,WAA0E,CAACC,OAAOC,QAAQ;AACpH,QAAM,CAACC,UAAUqF,SAAS,IAAIC,eAA+C9F,8BAA8B;AAE3G,QAAM+F,iBAAiBpE,OAAO,KAAK;AAGnC,QAAM,CAACqE,oBAAoB,IAAIjE,YAAkD7B,mBAAmB;AAGpG8E,YAAU,MAAM;AACZ,QAAIe,eAAexD,QAAS;AAC5BwD,mBAAexD,UAAU;AAEzByD,yBAAqB;AAAA,MACjBxD,WAAW,CAAA;AAAA,MACXC,aAAaA,MAAM;AAEfoD,kBAAU,CAAA,GAAI;AAAA,UAACI,aAAa;AAAA,QAAc,CAAC;AAAA,MAC/C;AAAA,MACAnD,SAASA,MAAM;AAGX+C,kBAAU,CAAA,GAAI;AAAA,UAACI,aAAa;AAAA,QAAc,CAAC;AAAA,MAC/C;AAAA,IACJ,CAAC;AAAA,EACL,GAAG,CAACD,sBAAsBH,SAAS,CAAC;AAGpC,QAAMK,wBAAwB5D,YAAY,MAAM;AAE5CuD,cAAU,CAAA,GAAI;AAAA,MAACI,aAAa;AAAA,IAAmB,CAAC;AAAA,EACpD,GAAG,CAACJ,SAAS,CAAC;AAEd,SAAOrF,WACH4E,oBAAChF,4BAAA;AAAA,IACGG;AAAAA,IACAC;AAAAA,IACAC,mBAAmByF;AAAAA,IAElBR,UAAApF,MAAMoF;AAAAA,GACX,IACA;AACR,CAAC;AAEDE,sBAAsBD,cAAc;AC7ZpC,MAAM,OAAyB,4BAAU;AACzC,MAAI,KAAK;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,cAAc;AAAA,EAAA,GAEhB,KAAK;AAAA,IACH,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,cAAc;AAAA,EAAA;AAEhB,SAAO;AAAA,IACL,YAAY;AAAA,MACV,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,cAAc;AAAA,YACZ;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAc;AAAA,gBACZ;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,gBAAgB;AAAA,kBAChB,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV,cAAc;AAAA,oBACX;AAAA,oBACD;AAAA,sBACE,SAAS;AAAA,sBACT,QAAQ;AAAA,sBACR,gBAAgB;AAAA,sBAChB,QAAQ;AAAA,sBACR,QAAQ;AAAA,sBACR,UAAU;AAAA,sBACV,cAAc;AAAA,wBACX;AAAA,sBAAA;AAAA,sBAEH,cAAc;AAAA,oBAAA;AAAA,kBAChB;AAAA,kBAEF,cAAc;AAAA,gBAAA;AAAA,cAChB;AAAA,cAEF,cAAc;AAAA,YAAA;AAAA,UAChB;AAAA,UAEF,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,MAEF,QAAQ;AAAA,MACR,eAAe;AAAA,IAAA;AAAA,IAEjB,QAAQ;AAAA,IACR,aAAa;AAAA,MACX,uBAAuB,CAAA;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAc;AAAA,QACZ;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,cAAc;AAAA,YACZ;AAAA,cACE,SAAS;AAAA,cACT,QAAQ;AAAA,cACR,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,QAAQ;AAAA,cACR,UAAU;AAAA,cACV,cAAc;AAAA,gBACZ;AAAA,kBACE,SAAS;AAAA,kBACT,QAAQ;AAAA,kBACR,gBAAgB;AAAA,kBAChB,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV,cAAc;AAAA,oBACX;AAAA,oBACD;AAAA,sBACE,SAAS;AAAA,sBACT,QAAQ;AAAA,sBACR,gBAAgB;AAAA,sBAChB,QAAQ;AAAA,sBACR,QAAQ;AAAA,sBACR,UAAU;AAAA,sBACV,cAAc;AAAA,wBACX;AAAA,wBACA;AAAA,sBAAA;AAAA,sBAEH,cAAc;AAAA,oBAAA;AAAA,oBAEf;AAAA,kBAAA;AAAA,kBAEH,cAAc;AAAA,gBAAA;AAAA,cAChB;AAAA,cAEF,cAAc;AAAA,YAAA;AAAA,UAChB;AAAA,UAEF,cAAc;AAAA,QAAA;AAAA,MAChB;AAAA,IACF;AAAA,IAEF,UAAU;AAAA,MACR,WAAW;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,MACZ,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IAAA;AAAA,EACV;AAEF,GAAA;AAEC,KAAa,OAAO;ACjKrB,MAAM,0BAA0B,cAG7B;AAAA,EACC,uBAAuB,MAAM;AACzB,YAAQ,KAAK,iEAAiE;AAC9E,WAAO;AAAA,EACX;AAAA,EACA,2BAA2B,MAAM;AAC7B,YAAQ,KAAK,qEAAqE;AAClF,WAAO,CAAA;AAAA,EACX;AACJ,CAAC;AAUD,SAAS,sBAAsB;AAC3B,QAAM,EAAC,uBAAuB,8BAA6B,WAAW,uBAAuB;AAM7F,QAAMQ,8BAA4B,YAAY,CAAC,cAA0C;AACrF,UAAM,iBAAiB,sBAAsB,SAAS;AACtD,WAAOC,0BAA8B,gBAAgB,qBAAqB;AAAA,EAC9E,GAAG,CAAC,qBAAqB,CAAC;AAE1B,SAAO;AAAA,IACH;AAAA,IAAA,2BACAD;AAAAA,IACA;AAAA,EAAA;AAER;AC5CA,MAAM,eAAe;AAAA,EACjB,YAAY;AAAA,IACR,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAAA,EAER,cAAc;AAAA,IACV,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAAA,EAER,oBAAoB;AAAA,IAChB,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAEZ;AAEA,MAAM,EAAC,QAAQ,gBAAA,IAAmB;AAAA,EAC9B;AAAA,EACA;AACJ;AAEO,MAAM,iCAAiC;AACvC,MAAM,0CAA0C;ACZvD,MAAME,QAAAC;AA2BN,MAAMC,gBAGDA,CAAC;AAAA,EAAC/F;AAAAA,EAAUgG;AAAM,MAAM;AACzB,QAAMxF,OAAOC,kBAAiDoF,OAAO7F,QAAQ;AAE7E,QAAMiG,kBAAkBC,QAAQ,MAAM;;AAClC,aAAO1F,wCAAM2F,6BAAN3F,mBAAgC4F,UAAhC5F,mBACD6F,IAAKC,UAAA;;AAAU;AAAA,QACb3B,OAAM2B,MAAAA,6BAAMjH,SAANiH,gBAAAA,IAAY3B;AAAAA,QAClB4B,gBAAcD,MAAAA,MAAAA,6BAAMjH,SAANiH,gBAAAA,IAAYE,qBAAZF,mBAA8BD,IAAKhD,WAAUA,MAAMsB,UAAS,CAAA;AAAA;OAE7E8B,OAAQC,QAA6BA,GAAG/B,SAAS,QAAQ+B,GAAG/B,SAAS,YAAc,CAAA;AAAA,EAC5F,GAAG,CAACnE,IAAI,CAAC;AAETgE,YAAU,MAAM;AACZwB,WAAOC,eAAe;AAAA,EAC1B,GAAG,CAACA,iBAAiBD,MAAM,CAAC;AAE5B,SAAO;AACX;AAEAD,cAAcZ,cAAc;AAO5B,MAAMwB,2BAA+EA,CAAC;AAAA,EAACzB;AAAQ,MAAM;AACjG,QAAM;AAAA,IAACxE;AAAAA,IAAMmD;AAAAA,MAAwB+C,qBAAA;AACrC,QAAM;AAAA,IAACC;AAAAA,MAAKC,wCAAA;AAEZ,QAAM,CAAC9G,UAAUqF,WAAW0B,YAAY,IAAIzB,eAA8CO,KAAK;AAC/F,QAAM,CAACmB,UAAUC,WAAW,IAAIlG,SAAS,KAAK;AAC9C,QAAM,CAACmG,gBAAgBC,iBAAiB,IAAIpG,SAAgC,oBAAIqG,KAAK;AAGrF5C,YAAU,MAAM;AACZ,QAAI,CAACwC,UAAU;AACX3B,gBAAU,CAAA,GAAI;AAAA,QAACI,aAAa;AAAA,MAAc,CAAC;AAAA,IAC/C,OAAO;AACHsB,mBAAA;AAAA,IACJ;AAAA,EACJ,GAAG,CAACrG,MAAM2E,WAAW0B,cAAcC,QAAQ,CAAC;AAG5C,QAAMK,kBAAkBvF,YAAamE,qBAAsC;AACvE,UAAMqB,6BAAaF,IAAA;AACnBnB,oBAAgBrD,QAAS8D,QAAO;AAC5BY,aAAOC,IAAIb,GAAG/B,MAAM+B,GAAGH,YAAY;AAAA,IACvC,CAAC;AACDY,sBAAkBG,MAAM;AAAA,EAC5B,GAAG,CAAA,CAAE;AAGL,QAAME,mBAAmB1F,YAAaS,WAAiB;;AACnD,UAAME,aAAaF;AACnB,QAAIA,MAAMO,YAAY,2BACjBP,WAAMO,YAANP,mBAAekF,SAAS,6BACxBhF,gBAAWN,WAAXM,mBAAmBiF,KAAMC,OAAMA,EAAE7E,YAAY,yBAAyB;AACvEE,cAAQ4E,IAAI,iEAAiE;AAC7E/D,2BAAA;AACA;AAAA,IACJ;AACAb,YAAQT,MAAM,2EAA2EA,KAAK;AAC9F0E,gBAAY,IAAI;AAAA,EACpB,GAAG,CAACpD,oBAAoB,CAAC;AAGzB,QAAMgE,wBAAwB/F,YAAagG,oBAA2B;AAClE,UAAMC,gBAAgBC,YAAYF,cAAc;AAChD,WAAOZ,eAAee,IAAIF,aAAa;AAAA,EAC3C,GAAG,CAACb,cAAc,CAAC;AAGnB,QAAMgB,4BAA4BpG,YAAagG,oBAAqC;AAChF,UAAMC,gBAAgBC,YAAYF,cAAc;AAChD,WAAOZ,eAAeiB,IAAIJ,aAAa,KAAK,CAAA;AAAA,EAChD,GAAG,CAACb,cAAc,CAAC;AAGnB,QAAMkB,eAAelC,QAAQ,OAAO;AAAA,IAChC2B;AAAAA,IACAK;AAAAA,EACJ,IAAI,CAACL,uBAAuBK,yBAAyB,CAAC;AAEtD,MAAIlB,UAAU;AACV,WACIqB,qBAAC;MAAIC,OAAO;AAAA,QAACC,SAAS;AAAA,QAAQC,WAAW;AAAA;MACrCtD,UAAA,CAAAN,oBAAC,MAAA;AAAA,QAAIM,UAAA2B,EAAE,YAAY;AAAA,MAAA,CAAE,GACrBjC,oBAAC,KAAA;AAAA,QAAGM,UAAA2B,EAAE,cAAc;AAAA,MAAA,CAAE,CAAA;AAAA,IAAA,CAC1B;AAAA,EAER;AAEA,SACIwB,qBAAAI,UAAA;AAAA,IAEKvD,UAAA,CAAAlF,gCACI0I,uBAAA;AAAA,MAAsBpG,SAASkF;AAAAA,MAC5BtC,UAAAN,oBAAC+D,UAAA;AAAA,QAASC,UAAUhE,oBAAC,OAAA;AAAA,UAAKM,YAAE,oBAAoB;AAAA,QAAA,CAAE;AAAA,QAC9CA,UAAAN,oBAACmB,eAAA;AAAA,UAAc/F;AAAAA,UAAoBgG,QAAQqB;AAAAA,SAAiB;AAAA,OAChE;AAAA,KACJ,uBAIHwB,wBAAwB/D,UAAxB;AAAA,MAAiCC,OAAOqD;AAAAA,MACpClD;AAAAA,IAAA,CACL,CAAA;AAAA,EAAA,CACJ;AAER;AAEAyB,yBAAyBxB,cAAc;ACnJhC,MAAM,gBAAgB,cAAkC;AAAA,EAC3D,aAAa;AAAA,EACb,OAAO;AAAA,EACP,WAAW,MAAM;AACb,YAAQ,KAAK,2CAA2C;AACxD,WAAO,MAAM;AAAA,IAAC;AAAA,EAClB;AACJ,CAAC;AAKM,SAAS,YAAgC;AAC5C,SAAO,WAAW,aAAa;AACnC;AAkBO,SAAS,sBACZ,SACA,OAA6B,IACzB;AACJ,QAAM,EAAC,UAAA,IAAa,UAAA;AAEpB,YAAU,MAAM;AACZ,UAAM,cAAc,UAAU,OAAO;AACrC,WAAO;AAAA,EAEX,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC;AAC3B;AAyBO,SAAS,oBAAoB,YAAqC;AACrE,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,CAAC;AACxC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAyC,IAAI;AAEzE,wBAAsB,CAAC,WAAW;;AAC9B,UAAM,UAAS,YAAO,WAAP,mBAAe;AAC9B,QAAI,WAAW,SAAS,OAAO,MAAM,KAAM,UAAU,WAAW,SAAS,MAAM,GAAI;AAC/E,gBAAU,OAAO,MAAM;AACvB,iBAAW,CAAA,MAAK,IAAI,CAAC;AAAA,IACzB;AAAA,EACJ,GAAG,UAAU;AAEb,SAAO,EAAC,SAAS,OAAA;AACrB;;AC9EA,MAAM,gBAAgB,CAAC,YAA4B;AAC/C,MAAI;AACA,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,WAAO,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI;AAAA,EACzC,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAiBA,MAAM,iBAAgD,CAAC,EAAC,eAAc;AAKlE,QAAM,EAAC,KAAA,IAAQ,qBAAA;AASf,QAAM,iBAAiB,OAA2B,IAAI;AAKtD,QAAM,cAAc,OAA2B,oBAAI,KAAK;AAMxD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AASrD,QAAM,iBAAiB,YAAY,CAAC,WAAmB;AACnD,gBAAY,QAAQ,QAAQ,CAAC,YAAY;AACrC,UAAI;AACA,gBAAQ,MAAM;AAAA,MAClB,SAAS,KAAK;AACV,gBAAQ,MAAM,mCAAmC,GAAG;AAAA,MACxD;AAAA,IACJ,CAAC;AAAA,EACL,GAAG,CAAA,CAAE;AAML,QAAM,YAAY,YAAY,CAAC,YAAyC;AACpE,gBAAY,QAAQ,IAAI,OAAO;AAC/B,WAAO,MAAM;AACT,kBAAY,QAAQ,OAAO,OAAO;AAAA,IACtC;AAAA,EACJ,GAAG,CAAA,CAAE;AAKL,QAAM,iBAAiB,YAAY,MAAM;AACrC,QAAI,eAAe,SAAS;AACxB,qBAAe,QAAQ,MAAA;AACvB,qBAAe,UAAU;AAAA,IAC7B;AACA,mBAAe,KAAK;AACpB,aAAS,IAAI;AAAA,EACjB,GAAG,CAAA,CAAE;AAKL,QAAM,kBAAkB,YAAY,CAAC,WAAmB;AAEpD,mBAAA;AAGA,UAAM,YAAY,cAAc,MAAM;AACtC,UAAM,WAAU,qEAAiB,sBAA+B;AAChE,UAAM,MAAM,GAAG,OAAO,6BAA6B,SAAS;AAG5D,UAAM,cAAc,IAAI,YAAY,KAAK,EAAC,iBAAiB,MAAK;AAChE,mBAAe,UAAU;AAEzB,gBAAY,SAAS,MAAM;AACvB,qBAAe,IAAI;AACnB,eAAS,IAAI;AAAA,IACjB;AAEA,gBAAY,YAAY,CAAC,UAAU;AAC/B,UAAI;AACA,cAAM,SAAiB,KAAK,MAAM,MAAM,IAAI;AAC5C,uBAAe,MAAM;AAAA,MACzB,QAAQ;AAAA,MAER;AAAA,IACJ;AAEA,gBAAY,UAAU,MAAM;AACxB,eAAS,IAAI,MAAM,sBAAsB,CAAC;AAC1C,qBAAe,KAAK;AAAA,IAExB;AAAA,EACJ,GAAG,CAAC,gBAAgB,cAAc,CAAC;AASnC,YAAU,MAAM;AACZ,QAAI,6BAAM,IAAI;AAEV,sBAAgB,KAAK,EAAE;AAAA,IAC3B,OAAO;AAEH,qBAAA;AAAA,IACJ;AAGA,WAAO,MAAM;AACT,qBAAA;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,6BAAM,IAAI,iBAAiB,cAAc,CAAC;AAM9C,QAAM,eAAe,QAAQ,OAAO;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,CAAC,aAAa,OAAO,SAAS,CAAC;AAMnC,6BACK,cAAc,UAAd,EAAuB,OAAO,cAC1B,UACL;AAER;AChLA,MAAM,kBAAkB,cAAmC;AAAA,EACvD;AAAA,EACA,MAAM;AAAA,EAAC;AACX,CAAC;AAKD,SAAS,cAAyF;AAC9F,SAAO,WAAW,eAAe;AACrC;ACCO,SAAS,mBACZ,gBACA,kBACA,eAAuB,YAChB;;AACP,QAAM,mBAAmB,oBAAA;AACzB,QAAM,oBAAoB,qBAAA;AAE1B,QAAM,kBAAkB,YAAY,MAAM;AACtC,QAAI,CAAC,eAAe,QAAQ;AACxB,aAAO;AAAA,IACX;AAEA,WAAO,eAAe,MAAM,CAAA,kBAAiB;;AAEzC,UAAI,CAAC,iBAAiB,sBAAsB,aAAa,GAAG;AACxD,eAAO;AAAA,MACX;AAGA,YAAM,eAAe,iBAAiB,0BAA0B,aAAa;AAG7E,YAAM,iBAAiB,aAAa,SAAS,OAAO;AAGpD,UAAI,kBAAkB,aAAa,WAAW,GAAG;AAE7C,YAAI,CAAC,kBAAkB;AACnB,kBAAQ;AAAA,YACJ,GAAG,YAAY,gBAAgB,aAAa;AAAA,UAAA;AAGhD,iBAAO;AAAA,QACX;AAGA,cAAM,UAAS2D,MAAA,kBAAkB,SAAlB,gBAAAA,IAAwB;AACvC,YAAI,CAAC,UAAU,CAAC,iBAAiB,SAAS,SAAS,MAAM,GAAG;AACxD,iBAAO;AAAA,QACX;AAAA,MACJ,WAAW,kBAAkB,CAAC,kBAAkB;AAG5C,gBAAQ;AAAA,UACJ,GAAG,YAAY,gBAAgB,aAAa;AAAA,QAAA;AAAA,MAGpD;AAGA,aAAO;AAAA,IACX,CAAC;AAAA,EACL,GAAG,CAAC,gBAAgB,kBAAkB,mBAAkB,uBAAkB,SAAlB,mBAAwB,IAAI,YAAY,CAAC;AAEjG,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAkB,MAAM,iBAAiB;AAEnF,YAAU,MAAM;AACZ,qBAAiB,iBAAiB;AAAA,EACtC,GAAG,CAAC,eAAe,CAAC;AAEpB,SAAO;AACX;ACtEA,MAAM,oBAAoB,cAAqC;AAAA,EAC3D,iBAAiB;AACrB,CAAC;AAEM,MAAM,wBAAwB,MAAiB;AAClD,QAAM,EAAC,gBAAA,IAAmB,WAAW,iBAAiB;AACtD,SAAO;AACX;ACkBA,SAAS,iBAAiBjD,QAAoC;AAC1D,QAAM,gCAAgB,IAAA;AAEtB,QAAM,WAAW,CAAC,QAAuB;AACrC,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AAErC,QAAI,kBAAkB,KAAK;AACvB,YAAM,eAAgB,IAA+B;AAErD,UAAI,gBAAgB,aAAa,SAAS,MAAM,GAAG;AAC/C,kBAAU,IAAI,YAAY;AAAA,MAC9B;AAAA,IACJ;AAGA,eAAW,SAAS,OAAO,OAAO,GAAG,GAAG;AACpC,UAAI,MAAM,QAAQ,KAAK,GAAG;AACtB,cAAM,QAAQ,QAAQ;AAAA,MAC1B,WAAW,OAAO,UAAU,UAAU;AAClC,iBAAS,KAAK;AAAA,MAClB;AAAA,IACJ;AAAA,EACJ;AAEA,WAASA,MAAK;AACd,SAAO,MAAM,KAAK,SAAS;AAC/B;AAMA,MAAM,wBAID,CAAC,EAAC,OAAAA,QAAO,gBAAgB,cAAa;AACvC,QAAM,OAAO,kBAAkBA,QAAO,cAAc;AAEpD,YAAU,MAAM;AACZ,YAAQ,IAAI;AAAA,EAChB,GAAG,CAAC,SAAS,IAAI,CAAC;AAElB,SAAO;AACX;AAaA,MAAM,qBAKD,CAAC,EAAC,OAAAA,QAAO,gBAAgB,SAAS,kBAAiB;AACpD,QAAM,oBAAoB,qBAAA;AAC1B,QAAM,eAAe,iBAAA;AAGrB,QAAM,oBAAoB,OAAO,KAAK;AAGtC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,QAAM,cAAc,YAAY,CAAC,UAA6B;;AAC1D,QAAI,kBAAkB,SAAS;AAC3B;AAAA,IACJ;AACA,sBAAkB,UAAU;AAG5B,UAAM,aAAY,oCAAO,WAAP,mBAAe;AAKjC,UAAM,mBAAkB,uCAAW;AAAA,MAC/B,CAAC,QAAQ,IAAI,YAAY;AAAA,YACxB,WAAM,YAAN,mBAAe,SAAS;AAE7B,QAAI,iBAAiB;AAIjB,kBAAY,IAAI;AAIhB,wBAAkB,qBAAqB,MAAM;AACzC,0BAAkB,UAAU;AAC5B,oBAAY,KAAK;AACjB,oBAAA;AAAA,MACJ,CAAC;AACD;AAAA,IACJ;AAGA,QAAI,aAAa,UAAU,SAAS,GAAG;AACnC,mBAAa;AAAA,QACT,UAAU,IAAI,CAAC,cAAc;AAAA,UACzB,MAAM,SAAS;AAAA,UACf,OAAQ,SAAS,YAAY;AAAA,QAAA,EAC/B;AAAA,MAAA;AAAA,IAEV,OAAO;AAEH,mBAAa,MAAM,CAAC;AAAA,QAChB,MAAM,MAAM;AAAA,QACZ,OAAO;AAAA,MAAA,CACV,CAAC;AAAA,IACN;AAEA,gBAAY,IAAI;AAAA,EACpB,GAAG,CAAC,mBAAmB,cAAc,WAAW,CAAC;AAEjD,MAAI,UAAU;AACV,WAAO;AAAA,EACX;AAEA,SACI,oBAAC,yBAAsB,SAAS,aAC5B,8BAAC,MAAM,UAAN,EAAe,UAAU,MACtB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,OAAAA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAAA,GAER,EAAA,CACJ;AAER;AAWA,SAAS,sBACL;AAAA,EACI,OAAAA;AAAA,EACA;AAAA,EACA,aAAa,CAAA;AAAA,EACb,UAAU,EAAC,aAAa,oBAAA;AAAA,EACxB;AAAA,EACA;AAAA,EACA,IAAI,YAAY;AAAA,EAChB;AACJ,GACA,KACF;AAKE,QAAM,oBAAoB,qBAAA;AAC1B,QAAM,gBAAgB,iBAAA;AACtB,QAAM,kBAAkB,sBAAA;AACxB,QAAM,oBAAoB,oBAAoB,SAAY,kBAAkB;AAE5E,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,eAAeA,QAAO,qBAAqB;AAG/C,QAAM,YAAY,QAAQ,MAAM,iBAAiBA,MAAK,GAAG,CAACA,MAAK,CAAC;AAGhE,QAAM,iBAAiB,QAAQ,MAAM,sBAAsBA,MAAK,GAAG,CAACA,MAAK,CAAC;AAG1E,QAAM,gBAAgB,mBAAmB,gBAAgB,kBAAkB,kBAAkB;AAG7F,QAAM,wBAAwB,OAAO,CAAC;AAMtC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAyC,MAAS;AAC1E,QAAM,CAAC,MAAM,OAAO,IAAI,SAAkB,KAAK;AAM/C,QAAM,cAAc,YAAY,MAAM;AAClC,iBAAA;AACA,YAAQ,IAAI;AAAA,EAChB,GAAG,CAAC,YAAY,CAAC;AASjB,YAAU,MAAM;AACZ,QAAI,iBAAiB,QAAQ,CAAC,gBAAgB;AAC1C,cAAQ,KAAK;AACb,wBAAkB,KAAK,MAAM,UAAU,YAAY,OAAO,CAAC;AAAA,IAC/D;AAAA,EACJ,GAAG,CAAC,eAAe,MAAM,gBAAgB,kBAAkB,MAAM,WAAW,YAAY,OAAO,CAAC;AAMhG,YAAU,MAAM;AAEZ,QAAI,cAAc,UAAU,sBAAsB,SAAS;AAEvD,YAAM,gBAAgB,UAAU;AAAA,QAAK,CAAA,aACjC,cAAc,MAAM,SAAS,QAAQ;AAAA,MAAA;AAGzC,UAAI,eAAe;AACf,8BAAsB,UAAU,cAAc;AAC9C,oBAAA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,eAAe,WAAW,WAAW,CAAC;AAK1C,sBAAoB,KAAK,OAAO;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,MAAM;AAAA,EAAA,IACN,CAAC,eAAe,MAAM,MAAM,WAAW,CAAC;AAM5C,6BACK,gBAAgB,UAAhB,EAAyB,OAAO,CAAC,MAAM,WAAW,GAC9C,UAAA,sCACI,WAAA,EAAU,WAAW,cAAc,QAAQ,wBAAwB,QAE/D,UAAA;AAAA,IAAA,cAAc,SAAS,CAAC,kBAAkB,QAAQ;AAAA,IAGlD,kBACG;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,OAAAA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAAA;AAAA,IAKR,oBAAC,MAAM,UAAN,EAAe,UAAU,cAAc,QAAQ,oBAAoB,MAC/D,SAAA,CACL;AAAA,EAAA,EAAA,CACJ,EAAA,CAER;AAER;AAGA,MAAM,mBAAmB,WAAW,qBAAqB;ACpTzD,MAAM,qBAAqB,cAIxB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAKD,SAAS,iBAIP;AACE,SAAO,WAAW,kBAAkB;AAKxC;ACJA,MAAM,sBAAsB,WAA8D,CAAC,OAAO,QAAQ;AAKtG,QAAM,eAAe,iBAAA;AACrB,QAAM,oBAAoB,qBAAA;AAC1B,QAAM,CAAC,QAAQ,UAAU,IAAI,YAAY,MAAM,UAAU,MAAM,gBAAgB;AAG/E,QAAM,iBAAiB,QAAQ,MAAM,sBAAsB,MAAM,QAAQ,GAAG,CAAC,MAAM,QAAQ,CAAC;AAG5F,QAAM,gBAAgB,mBAAmB,gBAAgB,MAAM,kBAAkB,qBAAqB;AAMtG,QAAM,CAAC,YAAY,aAAa,IAAI,SAAiC,MAAS;AAS9E,QAAM,YAAY,YAAY,CAACzG,YAAkD;AAC7E,UAAM,YAAY,EAAC,GAAGA,QAAA;AAEtB,cAAU,UAAU,CAAC,UAA6B;;AAE9C,YAAM,mBAAkB,0CAAO,WAAP,mBAAe,WAAf,mBAAuB;AAAA,QAC3C,CAAC,QAAQ,IAAI,YAAY;AAAA;AAG7B,UAAI,iBAAiB;AAEjB,0BAAkB,qBAAA;AAClB,cAAAA,QAAO,YAAP,wBAAAA,SAAiB;AACjB;AAAA,MACJ;AAEA,mBAAa;AAAA,UACT,0CAAO,WAAP,mBAAe,WAAf,mBAAuB,IAAI,CAAC,QAAQ;AAChC,cAAI,QAA8B;AAClC,cAAI,IAAI,YAAY,kBAAkB;AAClC,oBAAQ;AAAA,UACZ;AACA,iBAAO;AAAA,YACH,MAAM,IAAI;AAAA,YACV;AAAA,UAAA;AAAA,QAER,OAAM,CAAA;AAAA,MAAC;AAGX,YAAAA,QAAO,YAAP,wBAAAA,SAAiB;AAAA,IACrB;AAEA,cAAU,cAAc,CAAC,UAA0C,WAAkC;;AACjG,YAAAA,QAAO,gBAAP,wBAAAA,SAAqB,UAAU;AAE/B,mBAAa;AAAA,SACT,iCAAQ,IAAI,CAAC,WAAW;AAAA,UACpB,MAAM,MAAM;AAAA,UACZ,OAAO,MAAM,YAAY;AAAA,QAAA,QACtB,CAAA;AAAA,MAAC;AAAA,IAEhB;AAEA,UAAM,gBAAgB,OAAO,SAAS;AACtC,kBAAc,aAAa;AAAA,EAC/B,GAAG,CAAC,cAAc,QAAQ,kBAAkB,oBAAoB,CAAC;AAEjE,QAAM,aAAa,YAAY,CAACA,YAAkD;AAC9E,sBAAkB,KAAK,MAAM,UAAUA,OAAM,CAAC;AAAA,EAClD,GAAG,CAAC,kBAAkB,MAAM,SAAS,CAAC;AAStC,sBAAoB,KAAK,OAAO;AAAA,IAC5B;AAAA,IACA,QAAQ,gBAAgB,aAAa;AAAA,IACrC,YAAY,CAAC,aAAa,aAAa;AAAA,EAAA,IACvC,CAAC,eAAe,YAAY,YAAY,UAAU,CAAC;AAMvD,SACI;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACG,OAAO;AAAA,QACH,gBAAgB,aAAa;AAAA,QAC7B;AAAA,QACA,CAAC,aAAa,aAAa;AAAA,MAAA;AAAA,MAG7B,WAAA,iBAAiB,MAAM,6BAA6B,WAAW,MAAM;AAAA,IAAA;AAAA,EAAA;AAGnF,CAAC;AC5HD,MAAM,gBAAgB,cAAkC;AAAA,EACpD,UAAU;AAAA,EACV,aAAa,MAAM;AACf,YAAQ,KAAK,6CAA6C;AAAA,EAC9D;AAAA,EACA,UAAU;AACd,CAAC;AAUD,SAAS,cAAkC;AACvC,SAAO,WAAW,aAAa;AACnC;AChBA,MAAM,cAAc;AACpB,MAAM,gBAAgB;AActB,MAAM,iBAA2D,CAAC,EAAC,eAAc;AAC7E,QAAM,EAAC,KAAA,IAAQ,qBAAA;AACf,QAAM,EAAC,QAAQ,WAAW,cAAA,IAAiB,cAAA;AAC3C,QAAM,WAAW,YAAA;AAEjB,QAAM,WAAW,CAAC,EAAC,6BAAM;AACzB,QAAM,cAAc,OAAO,IAAI;AAE/B,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAwB,MAAM;AAE1E,WAAO,cAAc,IAAI,aAAa,KAAK,eAAe,QAAQ,WAAW;AAAA,EACjF,CAAC;AAKD,YAAU,MAAM;AACZ,UAAM,cAAc,YAAY,YAAY;AAC5C,UAAM,cAAc,SAAS;AAC7B,gBAAY,UAAU;AAEtB,QAAI,eAAe,aAAa;AAC5B,qBAAe,WAAW,WAAW;AACrC,0BAAoB,IAAI;AACxB,gBAAU,EAAC,CAAC,aAAa,GAAG,MAAK;AAAA,IACrC;AAAA,EACJ,GAAG,CAAC,MAAM,SAAS,CAAC;AAOpB,YAAU,MAAM;AACZ,QAAI,SAAU;AAEd,QAAI,kBAAkB;AAClB,gBAAU,EAAC,CAAC,aAAa,GAAG,kBAAiB;AAAA,IACjD,OAAO;AACH,gBAAU,EAAC,CAAC,aAAa,GAAG,MAAK;AAAA,IACrC;AAAA,EACJ,GAAG,CAAC,kBAAkB,SAAS,UAAU,UAAU,SAAS,CAAC;AAK7D,QAAM,WAAW,QAAQ,MAAM;AAC3B,QAAI,6BAAM,UAAU;AAChB,aAAO,KAAK;AAAA,IAChB;AACA,WAAO;AAAA,EACX,GAAG,CAAC,6BAAM,UAAU,gBAAgB,CAAC;AAKrC,QAAM,cAAc,YAAY,CAAC,OAAsB;AACnD,QAAI,SAAU;AACd,QAAI,IAAI;AACJ,qBAAe,QAAQ,aAAa,EAAE;AAAA,IAC1C,OAAO;AACH,qBAAe,WAAW,WAAW;AAAA,IACzC;AACA,wBAAoB,EAAE;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,QAAQ,QAAQ,OAAO;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACA,CAAC,UAAU,aAAa,QAAQ,CAAC;AAErC,SACI,oBAAC,cAAc,UAAd,EAAuB,OACnB,SAAA,CACL;AAER;AAEA,eAAe,cAAc;ACnGtB,MAAM,gBAAgB;"}