@semiont/react-ui 0.4.14 → 0.4.16

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.
Files changed (169) hide show
  1. package/README.md +18 -12
  2. package/dist/KnowledgeBaseSessionContext-BNNunwzO.d.mts +175 -0
  3. package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs → PdfAnnotationCanvas.client-CHDCGQBR.mjs} +3 -3
  4. package/dist/{ar-R4CRNXEF.mjs → ar-3W37O3R3.mjs} +9 -3
  5. package/dist/ar-3W37O3R3.mjs.map +1 -0
  6. package/dist/{bn-CZKGRHTA.mjs → bn-JZTJLMVE.mjs} +9 -3
  7. package/dist/bn-JZTJLMVE.mjs.map +1 -0
  8. package/dist/chunk-FAI3S4BM.mjs +865 -0
  9. package/dist/chunk-FAI3S4BM.mjs.map +1 -0
  10. package/dist/{chunk-HVMAGUFA.mjs → chunk-NOD3NCXE.mjs} +3 -1
  11. package/dist/chunk-NOD3NCXE.mjs.map +1 -0
  12. package/dist/{chunk-HNZOXH4L.mjs → chunk-OZICDVH7.mjs} +5 -3
  13. package/dist/chunk-OZICDVH7.mjs.map +1 -0
  14. package/dist/{chunk-BQJWOK4C.mjs → chunk-VN5NY4SN.mjs} +9 -8
  15. package/dist/chunk-VN5NY4SN.mjs.map +1 -0
  16. package/dist/{cs-4WIB2IHH.mjs → cs-XYHH7HNE.mjs} +9 -3
  17. package/dist/cs-XYHH7HNE.mjs.map +1 -0
  18. package/dist/{da-JWYEUYPX.mjs → da-MZKIECVT.mjs} +9 -3
  19. package/dist/da-MZKIECVT.mjs.map +1 -0
  20. package/dist/{de-GWUQZGER.mjs → de-AYXTMRQW.mjs} +9 -3
  21. package/dist/de-AYXTMRQW.mjs.map +1 -0
  22. package/dist/{el-DM2GT7P5.mjs → el-A6CVQWAW.mjs} +9 -3
  23. package/dist/el-A6CVQWAW.mjs.map +1 -0
  24. package/dist/{en-IUV4ZXKH.mjs → en-YPQQBI4T.mjs} +2 -2
  25. package/dist/{es-6LVQIM3D.mjs → es-M2HXLJGT.mjs} +9 -3
  26. package/dist/es-M2HXLJGT.mjs.map +1 -0
  27. package/dist/{fa-IRUJY3QI.mjs → fa-V6JZJDYP.mjs} +9 -3
  28. package/dist/fa-V6JZJDYP.mjs.map +1 -0
  29. package/dist/{fi-53FBOEVT.mjs → fi-ONDTZ5H7.mjs} +9 -3
  30. package/dist/fi-ONDTZ5H7.mjs.map +1 -0
  31. package/dist/{fr-Q5KY7QL6.mjs → fr-PAPV4H4G.mjs} +9 -3
  32. package/dist/fr-PAPV4H4G.mjs.map +1 -0
  33. package/dist/{he-HJNKULBY.mjs → he-F6VTLJLW.mjs} +9 -3
  34. package/dist/he-F6VTLJLW.mjs.map +1 -0
  35. package/dist/{hi-UYZ4X6CR.mjs → hi-CFUAV4BF.mjs} +9 -3
  36. package/dist/hi-CFUAV4BF.mjs.map +1 -0
  37. package/dist/{id-UAQMH6U2.mjs → id-NBKLCCI7.mjs} +9 -3
  38. package/dist/id-NBKLCCI7.mjs.map +1 -0
  39. package/dist/index.d.mts +141 -169
  40. package/dist/index.mjs +2394 -2116
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/{it-C7QEBNFA.mjs → it-SLSOWVVU.mjs} +9 -3
  43. package/dist/it-SLSOWVVU.mjs.map +1 -0
  44. package/dist/{ja-THS6AOSJ.mjs → ja-L5IG4ECE.mjs} +9 -3
  45. package/dist/ja-L5IG4ECE.mjs.map +1 -0
  46. package/dist/{ko-XKK3TWQG.mjs → ko-QYMTULKK.mjs} +9 -3
  47. package/dist/ko-QYMTULKK.mjs.map +1 -0
  48. package/dist/{ms-GSK7LIF7.mjs → ms-5DGSFKM2.mjs} +9 -3
  49. package/dist/ms-5DGSFKM2.mjs.map +1 -0
  50. package/dist/{nl-KUBWITGY.mjs → nl-VZPCGONO.mjs} +9 -3
  51. package/dist/nl-VZPCGONO.mjs.map +1 -0
  52. package/dist/{no-ECWZUHT6.mjs → no-MF6F352I.mjs} +9 -3
  53. package/dist/no-MF6F352I.mjs.map +1 -0
  54. package/dist/{pl-PLVWSZWS.mjs → pl-WIK72JUO.mjs} +9 -3
  55. package/dist/pl-WIK72JUO.mjs.map +1 -0
  56. package/dist/{pt-AL74ZTKB.mjs → pt-RRP5ZF6A.mjs} +9 -3
  57. package/dist/pt-RRP5ZF6A.mjs.map +1 -0
  58. package/dist/{ro-WTPHLHGS.mjs → ro-XHQLC3T7.mjs} +9 -3
  59. package/dist/ro-XHQLC3T7.mjs.map +1 -0
  60. package/dist/{sv-QCLI7SG4.mjs → sv-EWULDN6E.mjs} +9 -3
  61. package/dist/sv-EWULDN6E.mjs.map +1 -0
  62. package/dist/test-utils.d.mts +13 -62
  63. package/dist/test-utils.mjs +41 -22
  64. package/dist/test-utils.mjs.map +1 -1
  65. package/dist/{th-WCKVZU6U.mjs → th-TGOBHFG4.mjs} +9 -3
  66. package/dist/th-TGOBHFG4.mjs.map +1 -0
  67. package/dist/{tr-2CAFS2XS.mjs → tr-LMMPBMV7.mjs} +9 -3
  68. package/dist/tr-LMMPBMV7.mjs.map +1 -0
  69. package/dist/{uk-TDE4JLCY.mjs → uk-IPGRRJY6.mjs} +9 -3
  70. package/dist/uk-IPGRRJY6.mjs.map +1 -0
  71. package/dist/{vi-KKXZ4PCX.mjs → vi-Q676OJQS.mjs} +9 -3
  72. package/dist/vi-Q676OJQS.mjs.map +1 -0
  73. package/dist/{zh-VH4XN5PV.mjs → zh-F3MTWQDX.mjs} +9 -3
  74. package/dist/zh-F3MTWQDX.mjs.map +1 -0
  75. package/package.json +5 -3
  76. package/src/components/ProtectedErrorBoundary.tsx +95 -0
  77. package/src/components/__tests__/ProtectedErrorBoundary.test.tsx +197 -0
  78. package/src/components/modals/PermissionDeniedModal.tsx +140 -0
  79. package/src/components/modals/ReferenceWizardModal.tsx +3 -2
  80. package/src/components/modals/SessionExpiredModal.tsx +101 -0
  81. package/src/components/modals/__tests__/PermissionDeniedModal.test.tsx +150 -0
  82. package/src/components/modals/__tests__/SessionExpiredModal.test.tsx +115 -0
  83. package/src/components/resource/AnnotationHistory.tsx +5 -6
  84. package/src/components/resource/HistoryEvent.tsx +9 -8
  85. package/src/components/resource/__tests__/AnnotationHistory.test.tsx +33 -34
  86. package/src/components/resource/__tests__/HistoryEvent.test.tsx +18 -19
  87. package/src/components/resource/__tests__/event-formatting.test.ts +70 -94
  88. package/src/components/resource/event-formatting.ts +92 -56
  89. package/src/components/resource/panels/ReferenceEntry.tsx +7 -5
  90. package/src/components/resource/panels/ResourceInfoPanel.tsx +18 -6
  91. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +12 -12
  92. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +24 -0
  93. package/src/features/resource-compose/components/ResourceComposePage.tsx +10 -1
  94. package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +1 -1
  95. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +4 -4
  96. package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +5 -10
  97. package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +23 -54
  98. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +6 -6
  99. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +7 -19
  100. package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +1 -1
  101. package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +18 -44
  102. package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +6 -6
  103. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +26 -26
  104. package/src/styles/features/compose.css +63 -0
  105. package/translations/ar.json +6 -2
  106. package/translations/bn.json +6 -2
  107. package/translations/cs.json +6 -2
  108. package/translations/da.json +6 -2
  109. package/translations/de.json +6 -2
  110. package/translations/el.json +6 -2
  111. package/translations/en.json +2 -0
  112. package/translations/es.json +6 -2
  113. package/translations/fa.json +6 -2
  114. package/translations/fi.json +6 -2
  115. package/translations/fr.json +6 -2
  116. package/translations/he.json +6 -2
  117. package/translations/hi.json +6 -2
  118. package/translations/id.json +6 -2
  119. package/translations/it.json +6 -2
  120. package/translations/ja.json +6 -2
  121. package/translations/ko.json +6 -2
  122. package/translations/ms.json +6 -2
  123. package/translations/nl.json +6 -2
  124. package/translations/no.json +6 -2
  125. package/translations/pl.json +6 -2
  126. package/translations/pt.json +6 -2
  127. package/translations/ro.json +6 -2
  128. package/translations/sv.json +6 -2
  129. package/translations/th.json +6 -2
  130. package/translations/tr.json +6 -2
  131. package/translations/uk.json +6 -2
  132. package/translations/vi.json +6 -2
  133. package/translations/zh.json +6 -2
  134. package/dist/TranslationManager-CudgH3gw.d.mts +0 -107
  135. package/dist/ar-R4CRNXEF.mjs.map +0 -1
  136. package/dist/bn-CZKGRHTA.mjs.map +0 -1
  137. package/dist/chunk-BQJWOK4C.mjs.map +0 -1
  138. package/dist/chunk-HNZOXH4L.mjs.map +0 -1
  139. package/dist/chunk-HVMAGUFA.mjs.map +0 -1
  140. package/dist/chunk-OL5UST25.mjs +0 -413
  141. package/dist/chunk-OL5UST25.mjs.map +0 -1
  142. package/dist/cs-4WIB2IHH.mjs.map +0 -1
  143. package/dist/da-JWYEUYPX.mjs.map +0 -1
  144. package/dist/de-GWUQZGER.mjs.map +0 -1
  145. package/dist/el-DM2GT7P5.mjs.map +0 -1
  146. package/dist/es-6LVQIM3D.mjs.map +0 -1
  147. package/dist/fa-IRUJY3QI.mjs.map +0 -1
  148. package/dist/fi-53FBOEVT.mjs.map +0 -1
  149. package/dist/fr-Q5KY7QL6.mjs.map +0 -1
  150. package/dist/he-HJNKULBY.mjs.map +0 -1
  151. package/dist/hi-UYZ4X6CR.mjs.map +0 -1
  152. package/dist/id-UAQMH6U2.mjs.map +0 -1
  153. package/dist/it-C7QEBNFA.mjs.map +0 -1
  154. package/dist/ja-THS6AOSJ.mjs.map +0 -1
  155. package/dist/ko-XKK3TWQG.mjs.map +0 -1
  156. package/dist/ms-GSK7LIF7.mjs.map +0 -1
  157. package/dist/nl-KUBWITGY.mjs.map +0 -1
  158. package/dist/no-ECWZUHT6.mjs.map +0 -1
  159. package/dist/pl-PLVWSZWS.mjs.map +0 -1
  160. package/dist/pt-AL74ZTKB.mjs.map +0 -1
  161. package/dist/ro-WTPHLHGS.mjs.map +0 -1
  162. package/dist/sv-QCLI7SG4.mjs.map +0 -1
  163. package/dist/th-WCKVZU6U.mjs.map +0 -1
  164. package/dist/tr-2CAFS2XS.mjs.map +0 -1
  165. package/dist/uk-TDE4JLCY.mjs.map +0 -1
  166. package/dist/vi-KKXZ4PCX.mjs.map +0 -1
  167. package/dist/zh-VH4XN5PV.mjs.map +0 -1
  168. /package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs.map → PdfAnnotationCanvas.client-CHDCGQBR.mjs.map} +0 -0
  169. /package/dist/{en-IUV4ZXKH.mjs.map → en-YPQQBI4T.mjs.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/contexts/knowledge-base-session/storage.ts","../src/contexts/knowledge-base-session/notify.ts","../src/contexts/KnowledgeBaseSessionContext.tsx","../src/contexts/knowledge-base-session/refresh.ts","../src/components/Toast.tsx","../src/contexts/OpenResourcesContext.tsx","../src/contexts/TranslationContext.tsx"],"sourcesContent":["/**\n * Pure helpers for the KnowledgeBaseSession provider.\n *\n * Contains:\n * - localStorage shape and read/write helpers for KB list, active KB id,\n * and per-KB sessions\n * - JWT expiry parsing and \"is expired\" check\n * - URL/protocol helpers for KB instances\n * - The public `getKbSessionStatus(kbId)` helper that the KB-list UI uses\n * to color status dots without subscribing to context changes\n *\n * No React imports, no module-scoped state, no side effects beyond\n * localStorage. Splitting these out of the provider file makes them\n * unit-testable in isolation and keeps the React provider focused on\n * lifecycle and state.\n */\n\nimport type { KnowledgeBase, KbSessionStatus } from '../../types/knowledge-base';\n\n// ---------- Storage keys ----------\n\nconst SESSION_PREFIX = 'semiont.session.';\nexport const STORAGE_KEY = 'semiont.knowledgeBases';\nexport const ACTIVE_KEY = 'semiont.activeKnowledgeBaseId';\n\n/** Refresh the access token this many milliseconds before it expires. */\nexport const REFRESH_BEFORE_EXP_MS = 5 * 60 * 1000;\n\n/** The shape persisted to localStorage per KB. */\nexport interface StoredSession {\n access: string;\n refresh: string;\n}\n\nexport function sessionKey(kbId: string): string {\n return `${SESSION_PREFIX}${kbId}`;\n}\n\n// ---------- Per-KB session storage ----------\n\nexport function getStoredSession(kbId: string): StoredSession | null {\n const raw = localStorage.getItem(sessionKey(kbId));\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed.access === 'string' && typeof parsed.refresh === 'string') {\n return { access: parsed.access, refresh: parsed.refresh };\n }\n } catch {\n // malformed entry — treat as no session\n }\n return null;\n}\n\nexport function setStoredSession(kbId: string, session: StoredSession): void {\n localStorage.setItem(sessionKey(kbId), JSON.stringify(session));\n}\n\nexport function clearStoredSession(kbId: string): void {\n localStorage.removeItem(sessionKey(kbId));\n}\n\n// ---------- JWT helpers ----------\n\nexport function parseJwtExpiry(token: string): Date | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3 || !parts[1]) return null;\n const payload = JSON.parse(atob(parts[1])) as { exp?: number };\n if (!payload.exp) return null;\n return new Date(payload.exp * 1000);\n } catch {\n return null;\n }\n}\n\nexport function isJwtExpired(token: string): boolean {\n const expiry = parseJwtExpiry(token);\n if (!expiry) return true;\n return expiry.getTime() < Date.now();\n}\n\n// ---------- KB list storage ----------\n\nfunction migrateLegacyEntry(entry: any): KnowledgeBase {\n if (entry.host !== undefined) return entry as KnowledgeBase;\n // Legacy format: { id, label, backendUrl }\n try {\n const url = new URL(entry.backendUrl);\n return {\n id: entry.id,\n label: entry.label,\n host: url.hostname,\n port: parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80),\n protocol: url.protocol === 'https:' ? 'https' : 'http',\n email: '',\n };\n } catch {\n return {\n id: entry.id,\n label: entry.label || 'Unknown',\n host: 'localhost',\n port: 4000,\n protocol: 'http',\n email: '',\n };\n }\n}\n\nexport function loadKnowledgeBases(): KnowledgeBase[] {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return [];\n const entries = JSON.parse(raw) as any[];\n return entries.map(migrateLegacyEntry);\n } catch {\n return [];\n }\n}\n\nexport function saveKnowledgeBases(knowledgeBases: KnowledgeBase[]): void {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(knowledgeBases));\n}\n\n// ---------- Public pure helpers ----------\n\nexport function defaultProtocol(host: string): 'http' | 'https' {\n return host === 'localhost' || host === '127.0.0.1' ? 'http' : 'https';\n}\n\nexport function kbBackendUrl(kb: KnowledgeBase): string {\n return `${kb.protocol}://${kb.host}:${kb.port}`;\n}\n\n/**\n * Read the locally-stored credential status for a KB. Pure / synchronous —\n * does not subscribe to context changes. Used by KB-list UI to color status\n * dots without requiring re-renders on every tick.\n */\nexport function getKbSessionStatus(kbId: string): KbSessionStatus {\n const stored = getStoredSession(kbId);\n if (!stored) return 'signed-out';\n return isJwtExpired(stored.access) ? 'expired' : 'authenticated';\n}\n\nexport function generateKbId(): string {\n return crypto.randomUUID();\n}\n","/**\n * Module-scoped session-expired / permission-denied notifier.\n *\n * The provider registers itself with this module-scoped slot on mount and\n * unregisters on unmount via {@link registerAuthNotifyHandlers}. Code outside\n * the React tree (notably the React Query QueryCache.onError handler in app\n * providers) calls {@link notifySessionExpired} or {@link notifyPermissionDenied}\n * to reach the active provider.\n *\n * When no provider is mounted (e.g. on the landing page), these calls are\n * no-ops — there is nothing to notify.\n *\n * No React imports — this is plain module state. The provider effect that\n * calls `registerAuthNotifyHandlers` runs inside React but the module itself\n * is React-agnostic.\n */\n\ntype Notify = (message?: string) => void;\n\nlet activeOnSessionExpired: Notify | null = null;\nlet activeOnPermissionDenied: Notify | null = null;\n\nexport function notifySessionExpired(message?: string): void {\n activeOnSessionExpired?.(message);\n}\n\nexport function notifyPermissionDenied(message?: string): void {\n activeOnPermissionDenied?.(message);\n}\n\n/**\n * Install handlers for session-expired and permission-denied notifications.\n * Returns an unregister callback. Intended to be called from a React useEffect\n * with the cleanup callback returned from the effect.\n *\n * Only one provider is expected to be mounted at a time. If a second provider\n * mounts before the first unmounts, its handlers replace the previous ones —\n * the previous provider becomes deaf to notifications. In practice this only\n * happens during the brief window of a React StrictMode double-mount or a\n * test that mounts and unmounts multiple providers rapidly.\n */\nexport function registerAuthNotifyHandlers(handlers: {\n onSessionExpired: Notify;\n onPermissionDenied: Notify;\n}): () => void {\n activeOnSessionExpired = handlers.onSessionExpired;\n activeOnPermissionDenied = handlers.onPermissionDenied;\n return () => {\n activeOnSessionExpired = null;\n activeOnPermissionDenied = null;\n };\n}\n","/**\n * KnowledgeBaseSessionContext — single source of truth for \"which KB and\n * what's the session against it.\"\n *\n * This provider merges what used to be three separate concerns in the\n * frontend (KnowledgeBaseProvider + KnowledgeBaseAuthBridge + AuthProvider)\n * plus the library-side SessionProvider, into one coherent unit.\n *\n * Why merged: a session in this app is always a session against a specific\n * KB. There is no auth without a KB. Switching KBs means switching sessions\n * atomically.\n *\n * What it owns:\n * - The list of configured KBs (persisted to localStorage)\n * - Which KB is currently active (persisted to localStorage)\n * - The validated session (token + user) for the active KB\n * - The \"session expired\" and \"permission denied\" flags that drive the modals\n * - JWT expiry derivations (for the session-timer UI)\n * - Mount-time validation flow with manual 401 recovery\n * - Proactive refresh: a timer that fires before the access token expires\n * - Cross-tab sync: when another tab refreshes or signs out, this tab updates\n *\n * Implementation is split across the `knowledge-base-session/` directory:\n * - `storage.ts` — localStorage shape, JWT helpers, KB list helpers\n * - `refresh.ts` — `performRefresh` and the in-flight Promise dedup map\n * - `notify.ts` — module-scoped notify functions and the register helper\n *\n * Mounting: must be inside `EventBusProvider` and `TranslationProvider` (it\n * uses neither, but the modals it sits next to do). It does NOT depend on\n * any other library context. Mount it inside the protected layout boundary.\n */\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { SemiontApiClient, APIError } from '@semiont/api-client';\nimport { baseUrl, EventBus, accessToken } from '@semiont/core';\nimport type { components } from '@semiont/core';\nimport type {\n KnowledgeBase,\n NewKnowledgeBase,\n} from '../types/knowledge-base';\nimport {\n ACTIVE_KEY,\n REFRESH_BEFORE_EXP_MS,\n clearStoredSession,\n generateKbId,\n getStoredSession,\n isJwtExpired,\n kbBackendUrl,\n loadKnowledgeBases,\n parseJwtExpiry,\n saveKnowledgeBases,\n sessionKey,\n setStoredSession,\n} from './knowledge-base-session/storage';\nimport { performRefresh } from './knowledge-base-session/refresh';\nimport { registerAuthNotifyHandlers } from './knowledge-base-session/notify';\nimport type { StoredSession } from './knowledge-base-session/storage';\n\ntype UserInfo = components['schemas']['UserResponse'];\n\nexport interface AuthSession {\n token: string;\n user: UserInfo;\n}\n\n// Re-export the public surface so consumers can keep importing from this module\nexport {\n defaultProtocol,\n kbBackendUrl,\n getKbSessionStatus,\n} from './knowledge-base-session/storage';\nexport type { StoredSession } from './knowledge-base-session/storage';\nexport {\n notifySessionExpired,\n notifyPermissionDenied,\n} from './knowledge-base-session/notify';\n\n// ---------- Context value ----------\n\ninterface KnowledgeBaseSessionValue {\n // KB list\n knowledgeBases: KnowledgeBase[];\n activeKnowledgeBase: KnowledgeBase | null;\n\n // Session state for the active KB\n session: AuthSession | null;\n isLoading: boolean;\n\n // Derived auth fields (memoized off `session.user`)\n user: UserInfo | null;\n token: string | null;\n isAuthenticated: boolean;\n hasValidBackendToken: boolean;\n isFullyAuthenticated: boolean;\n displayName: string;\n avatarUrl: string | null;\n userDomain: string | undefined;\n isAdmin: boolean;\n isModerator: boolean;\n\n // JWT expiry (derived from session.token)\n expiresAt: Date | null;\n\n // Modal-driving flags\n sessionExpiredAt: number | null;\n sessionExpiredMessage: string | null;\n permissionDeniedAt: number | null;\n permissionDeniedMessage: string | null;\n\n // Mutations\n addKnowledgeBase: (kb: NewKnowledgeBase, access: string, refresh: string) => KnowledgeBase;\n removeKnowledgeBase: (id: string) => void;\n setActiveKnowledgeBase: (id: string) => void;\n updateKnowledgeBase: (id: string, updates: Partial<KnowledgeBase>) => void;\n /** Re-auth on an existing KB: store the new tokens and refresh the session. */\n signIn: (id: string, access: string, refresh: string) => void;\n /** Sign out of a KB: clear its stored tokens. If it's the active KB, clear in-memory session too. */\n signOut: (id: string) => void;\n\n /**\n * Refresh the active KB's access token. Returns the new access token, or\n * null if no refresh token is available or the refresh failed. Concurrent\n * calls deduplicate via an in-flight Promise per KB. Used by the api-client's\n * 401-recovery hook and by the proactive refresh timer.\n */\n refreshActive: () => Promise<string | null>;\n\n // Modal acks\n acknowledgeSessionExpired: () => void;\n acknowledgePermissionDenied: () => void;\n}\n\n/**\n * Raw context export. Exposed for test utilities that need to construct\n * a mock provider without going through localStorage and JWT validation.\n * Production code should always use {@link useKnowledgeBaseSession} instead.\n */\nexport const KnowledgeBaseSessionContext = createContext<KnowledgeBaseSessionValue | undefined>(undefined);\n\nexport type { KnowledgeBaseSessionValue };\n\n// ---------- Provider ----------\n\nexport function KnowledgeBaseSessionProvider({ children }: { children: React.ReactNode }) {\n // KB list and active selection\n const [knowledgeBases, setKnowledgeBases] = useState<KnowledgeBase[]>(() => loadKnowledgeBases());\n const [activeKnowledgeBaseId, setActiveKnowledgeBaseId] = useState<string | null>(() => {\n const saved = localStorage.getItem(ACTIVE_KEY);\n const loaded = loadKnowledgeBases();\n if (saved && loaded.some(kb => kb.id === saved)) return saved;\n return loaded[0]?.id ?? null;\n });\n\n // Session state for the active KB\n const [session, setSession] = useState<AuthSession | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(() => {\n const id = activeKnowledgeBaseId;\n if (!id) return false;\n const stored = getStoredSession(id);\n if (!stored) return false;\n // We'll either validate (if access fresh) or refresh (if refresh available)\n return !isJwtExpired(stored.access) || stored.refresh != null;\n });\n\n // Modal flags\n const [sessionExpiredAt, setSessionExpiredAt] = useState<number | null>(null);\n const [sessionExpiredMessage, setSessionExpiredMessage] = useState<string | null>(null);\n const [permissionDeniedAt, setPermissionDeniedAt] = useState<number | null>(null);\n const [permissionDeniedMessage, setPermissionDeniedMessage] = useState<string | null>(null);\n\n // Persist KB list and active id\n useEffect(() => {\n saveKnowledgeBases(knowledgeBases);\n }, [knowledgeBases]);\n\n useEffect(() => {\n if (activeKnowledgeBaseId) {\n localStorage.setItem(ACTIVE_KEY, activeKnowledgeBaseId);\n } else {\n localStorage.removeItem(ACTIVE_KEY);\n }\n }, [activeKnowledgeBaseId]);\n\n const activeKnowledgeBase = useMemo(\n () => knowledgeBases.find(kb => kb.id === activeKnowledgeBaseId) ?? null,\n [knowledgeBases, activeKnowledgeBaseId]\n );\n\n // Refs for cross-effect coordination\n const activeKbRef = useRef<KnowledgeBase | null>(activeKnowledgeBase);\n useEffect(() => {\n activeKbRef.current = activeKnowledgeBase;\n }, [activeKnowledgeBase]);\n\n const proactiveRefreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n /**\n * Schedule a one-shot timer that fires `REFRESH_BEFORE_EXP_MS` before the\n * given access token expires. Cancels any prior pending timer.\n */\n const scheduleProactiveRefresh = useCallback((accessTokenStr: string) => {\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n const expiresAt = parseJwtExpiry(accessTokenStr);\n if (!expiresAt) return;\n const refreshAt = expiresAt.getTime() - REFRESH_BEFORE_EXP_MS;\n const delay = Math.max(0, refreshAt - Date.now());\n proactiveRefreshTimerRef.current = setTimeout(() => {\n proactiveRefreshTimerRef.current = null;\n // Fire-and-forget: refreshActive captures activeKbRef and updates state\n refreshActiveRef.current?.();\n }, delay);\n }, []);\n\n // refreshActive needs to be stable across renders for the api-client wiring\n // and also needs to read fresh activeKnowledgeBase via the ref. We define\n // the function via a ref so callers can capture a stable reference.\n const refreshActiveRef = useRef<(() => Promise<string | null>) | null>(null);\n const refreshActive = useCallback(async (): Promise<string | null> => {\n const kb = activeKbRef.current;\n if (!kb) return null;\n const newAccess = await performRefresh(kb);\n if (newAccess) {\n // Update the in-memory session token so consumers see the new value\n setSession(prev => (prev ? { ...prev, token: newAccess } : prev));\n scheduleProactiveRefresh(newAccess);\n } else {\n // Refresh failed — surface the modal\n setSession(null);\n clearStoredSession(kb.id);\n setSessionExpiredMessage('Your session has expired. Please sign in again.');\n setSessionExpiredAt(Date.now());\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n }\n return newAccess;\n }, [scheduleProactiveRefresh]);\n refreshActiveRef.current = refreshActive;\n\n // Mount-time validation. This is the only 401-handling path that does NOT\n // go through the api-client's `tokenRefresher` hook. Two structural reasons:\n //\n // 1. ApiClientProvider hasn't mounted yet — the protected layout mounts\n // ApiClientProvider as a CHILD of this provider, so at validation time\n // the configured api-client (the one with `tokenRefresher`) doesn't\n // exist yet.\n //\n // 2. Even if it did, having the api-client silently recover would mean\n // this effect would never see the 401. But this effect is what BUILDS\n // the session — it needs to know whether validation succeeded so it\n // can either set `session = { token, user }` or surface the modal.\n //\n // So this effect uses a fresh throwaway api-client (no refresher) and\n // handles 401 manually: try one refresh, retry getMe with the new token,\n // surface the modal only if both fail. The duplication with the api-client's\n // beforeRetry hook is structural — do not try to consolidate them.\n useEffect(() => {\n if (!activeKnowledgeBase) {\n setSession(null);\n setIsLoading(false);\n return;\n }\n\n const stored = getStoredSession(activeKnowledgeBase.id);\n if (!stored) {\n setSession(null);\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n\n const validate = async (tokenToUse: string) => {\n const client = new SemiontApiClient({\n baseUrl: baseUrl(kbBackendUrl(activeKnowledgeBase)),\n eventBus: new EventBus(),\n });\n try {\n const data = await client.getMe({ auth: accessToken(tokenToUse) });\n if (cancelled) return;\n setSession({ token: tokenToUse, user: data as UserInfo });\n scheduleProactiveRefresh(tokenToUse);\n } catch (error) {\n if (cancelled) return;\n setSession(null);\n if (error instanceof APIError && error.status === 401) {\n // Try one refresh on 401 from getMe before surfacing the modal\n const refreshed = await performRefresh(activeKnowledgeBase);\n if (cancelled) return;\n if (refreshed) {\n return validate(refreshed);\n }\n clearStoredSession(activeKnowledgeBase.id);\n setSessionExpiredMessage('Your session has expired. Please sign in again.');\n setSessionExpiredAt(Date.now());\n }\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n };\n\n setIsLoading(true);\n\n if (isJwtExpired(stored.access)) {\n (async () => {\n const refreshed = await performRefresh(activeKnowledgeBase);\n if (cancelled) return;\n if (refreshed) {\n await validate(refreshed);\n } else {\n setSession(null);\n clearStoredSession(activeKnowledgeBase.id);\n setIsLoading(false);\n }\n })();\n } else {\n validate(stored.access);\n }\n\n return () => {\n cancelled = true;\n };\n }, [activeKnowledgeBase, scheduleProactiveRefresh]);\n\n // Cancel proactive refresh timer on unmount\n useEffect(() => {\n return () => {\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n };\n }, []);\n\n // Cross-tab sync: listen for storage events on the active KB's session key\n useEffect(() => {\n if (!activeKnowledgeBaseId) return;\n const watchKey = sessionKey(activeKnowledgeBaseId);\n const handler = (e: StorageEvent) => {\n if (e.key !== watchKey) return;\n if (!e.newValue) {\n // Token was cleared in another tab\n setSession(null);\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n return;\n }\n try {\n const parsed = JSON.parse(e.newValue) as StoredSession;\n if (typeof parsed.access === 'string') {\n // Update our in-memory session token (user info is unchanged)\n setSession(prev => (prev ? { ...prev, token: parsed.access } : prev));\n scheduleProactiveRefresh(parsed.access);\n }\n } catch {\n // Ignore malformed payloads\n }\n };\n window.addEventListener('storage', handler);\n return () => window.removeEventListener('storage', handler);\n }, [activeKnowledgeBaseId, scheduleProactiveRefresh]);\n\n // Register module-scoped notify handlers so the QueryCache 401/403 handlers\n // can reach the active provider instance. Returns a cleanup callback that\n // unregisters the handlers when the active KB id changes or the provider\n // unmounts.\n useEffect(() => {\n return registerAuthNotifyHandlers({\n onSessionExpired: (message) => {\n setSessionExpiredMessage(message ?? 'Your session has expired. Please sign in again.');\n setSessionExpiredAt(Date.now());\n setSession(null);\n if (activeKnowledgeBaseId) {\n clearStoredSession(activeKnowledgeBaseId);\n }\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n },\n onPermissionDenied: (message) => {\n setPermissionDeniedMessage(message ?? 'You do not have permission to perform this action.');\n setPermissionDeniedAt(Date.now());\n },\n });\n }, [activeKnowledgeBaseId]);\n\n // Mutations\n const addKnowledgeBase = useCallback((input: NewKnowledgeBase, access: string, refresh: string): KnowledgeBase => {\n const kb: KnowledgeBase = { id: generateKbId(), ...input };\n setStoredSession(kb.id, { access, refresh });\n setKnowledgeBases(prev => [...prev, kb]);\n setActiveKnowledgeBaseId(kb.id);\n return kb;\n }, []);\n\n const removeKnowledgeBase = useCallback((id: string) => {\n clearStoredSession(id);\n setKnowledgeBases(prev => {\n const remaining = prev.filter(kb => kb.id !== id);\n setActiveKnowledgeBaseId(activeId => activeId === id ? (remaining[0]?.id ?? null) : activeId);\n return remaining;\n });\n }, []);\n\n const setActiveKnowledgeBase = useCallback((id: string) => {\n setActiveKnowledgeBaseId(id);\n }, []);\n\n const updateKnowledgeBase = useCallback((id: string, updates: Partial<KnowledgeBase>) => {\n setKnowledgeBases(prev => prev.map(kb => kb.id === id ? { ...kb, ...updates } : kb));\n }, []);\n\n const signIn = useCallback((id: string, access: string, refresh: string) => {\n setStoredSession(id, { access, refresh });\n // Replace the matching KB with a fresh object so the activeKnowledgeBase\n // memo's `find()` returns a new reference, the validation effect re-runs,\n // and the new tokens get used.\n setKnowledgeBases(prev => prev.map(kb => kb.id === id ? { ...kb } : kb));\n setActiveKnowledgeBaseId(id);\n }, []);\n\n const signOut = useCallback((id: string) => {\n clearStoredSession(id);\n setActiveKnowledgeBaseId(activeId => {\n if (activeId === id) {\n setSession(null);\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n }\n return activeId;\n });\n // Bump the KB list so consumers reading kbStatus(id) see the change\n setKnowledgeBases(prev => [...prev]);\n }, []);\n\n const acknowledgeSessionExpired = useCallback(() => {\n setSessionExpiredAt(null);\n setSessionExpiredMessage(null);\n }, []);\n\n const acknowledgePermissionDenied = useCallback(() => {\n setPermissionDeniedAt(null);\n setPermissionDeniedMessage(null);\n }, []);\n\n // Tick state forces re-derivation of expiresAt-based fields once a minute,\n // so the session-timer UI updates without each consumer running its own interval.\n const [, setTick] = useState(0);\n useEffect(() => {\n const interval = setInterval(() => setTick(t => t + 1), 30_000);\n return () => clearInterval(interval);\n }, []);\n\n // Derived auth fields\n const value = useMemo<KnowledgeBaseSessionValue>(() => {\n const user = session?.user ?? null;\n const token = session?.token ?? null;\n const expiresAt = token ? parseJwtExpiry(token) : null;\n\n return {\n knowledgeBases,\n activeKnowledgeBase,\n session,\n isLoading,\n user,\n token,\n isAuthenticated: !!session,\n hasValidBackendToken: !!token,\n isFullyAuthenticated: !!session,\n displayName: user?.name ?? user?.email?.split('@')[0] ?? 'User',\n avatarUrl: user?.image ?? null,\n userDomain: user?.domain || user?.email?.split('@')[1],\n isAdmin: user?.isAdmin ?? false,\n isModerator: user?.isModerator ?? false,\n expiresAt,\n sessionExpiredAt,\n sessionExpiredMessage,\n permissionDeniedAt,\n permissionDeniedMessage,\n addKnowledgeBase,\n removeKnowledgeBase,\n setActiveKnowledgeBase,\n updateKnowledgeBase,\n signIn,\n signOut,\n refreshActive,\n acknowledgeSessionExpired,\n acknowledgePermissionDenied,\n };\n }, [\n knowledgeBases,\n activeKnowledgeBase,\n session,\n isLoading,\n sessionExpiredAt,\n sessionExpiredMessage,\n permissionDeniedAt,\n permissionDeniedMessage,\n addKnowledgeBase,\n removeKnowledgeBase,\n setActiveKnowledgeBase,\n updateKnowledgeBase,\n signIn,\n signOut,\n refreshActive,\n acknowledgeSessionExpired,\n acknowledgePermissionDenied,\n ]);\n\n return (\n <KnowledgeBaseSessionContext.Provider value={value}>\n {children}\n </KnowledgeBaseSessionContext.Provider>\n );\n}\n\n// ---------- Hook ----------\n\nexport function useKnowledgeBaseSession(): KnowledgeBaseSessionValue {\n const ctx = useContext(KnowledgeBaseSessionContext);\n if (!ctx) {\n throw new Error(\n 'useKnowledgeBaseSession requires KnowledgeBaseSessionProvider. ' +\n 'This component is rendered outside the auth boundary. ' +\n 'Move it into a protected layout.'\n );\n }\n return ctx;\n}\n","/**\n * Refresh-token coordination for the KnowledgeBaseSession provider.\n *\n * Module-scoped state: an in-flight Promise per KB so concurrent 401s for\n * the same KB deduplicate to a single network call. No React, no provider\n * dependency — the React provider calls `performRefresh(kb)` and the\n * api-client's `tokenRefresher` hook indirectly calls it via the provider's\n * `refreshActive` method.\n */\n\nimport { SemiontApiClient } from '@semiont/api-client';\nimport { baseUrl, EventBus, refreshToken as makeRefreshToken } from '@semiont/core';\nimport type { KnowledgeBase } from '../../types/knowledge-base';\nimport { getStoredSession, setStoredSession, kbBackendUrl } from './storage';\n\n/**\n * One in-flight refresh promise per KB. Ensures concurrent 401s for the same\n * KB deduplicate to a single network call.\n */\nconst inFlightRefreshes: Map<string, Promise<string | null>> = new Map();\n\n/**\n * Refresh the active KB's access token. Returns the new access token, or\n * null if no refresh token is available or the refresh failed.\n *\n * IMPORTANT: this constructs a fresh `SemiontApiClient` *without* a\n * `tokenRefresher`. Do not be tempted to reuse the configured client (e.g.\n * via `useApiClient()` from a layout): a refresh-call returning 401 would\n * recursively re-enter the refresher, calling `/api/tokens/refresh` again,\n * in an infinite loop. The throwaway client deliberately has no recovery\n * path — a 401 here propagates as `null` and surfaces the modal upstream.\n *\n * Concurrent calls for the same KB deduplicate via the in-flight Promise\n * Map keyed by `kb.id`, so simultaneous 401s on different requests trigger\n * only one network round-trip to `/api/tokens/refresh`.\n */\nexport async function performRefresh(kb: KnowledgeBase): Promise<string | null> {\n const existing = inFlightRefreshes.get(kb.id);\n if (existing) return existing;\n\n const promise = (async (): Promise<string | null> => {\n const stored = getStoredSession(kb.id);\n if (!stored) return null;\n\n const client = new SemiontApiClient({\n baseUrl: baseUrl(kbBackendUrl(kb)),\n eventBus: new EventBus(),\n });\n\n try {\n const response = await client.refreshToken(makeRefreshToken(stored.refresh));\n const newAccess = response.access_token;\n if (!newAccess) return null;\n setStoredSession(kb.id, { access: newAccess, refresh: stored.refresh });\n return newAccess;\n } catch {\n return null;\n }\n })();\n\n inFlightRefreshes.set(kb.id, promise);\n try {\n return await promise;\n } finally {\n inFlightRefreshes.delete(kb.id);\n }\n}\n","'use client';\n\nimport React, { useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport './Toast.css';\n\nexport type ToastType = 'success' | 'error' | 'info' | 'warning';\n\nexport interface ToastMessage {\n id: string;\n message: string;\n type: ToastType;\n duration?: number;\n}\n\ninterface ToastProps {\n toast: ToastMessage;\n onClose: (id: string) => void;\n}\n\nconst icons = {\n success: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n error: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n warning: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n ),\n info: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n ),\n};\n\nfunction Toast({ toast, onClose }: ToastProps) {\n useEffect(() => {\n const timer = setTimeout(() => {\n onClose(toast.id);\n }, toast.duration || 3000);\n\n return () => clearTimeout(timer);\n }, [toast, onClose]);\n\n return (\n <div\n className=\"semiont-toast\"\n data-variant={toast.type}\n role=\"alert\"\n >\n <div className=\"semiont-toast-icon-wrapper\">{icons[toast.type]}</div>\n <p className=\"semiont-toast-message\">{toast.message}</p>\n <button\n onClick={() => onClose(toast.id)}\n className=\"semiont-toast-close\"\n aria-label=\"Close\"\n >\n <svg className=\"semiont-toast-close-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n );\n}\n\ninterface ToastContainerProps {\n toasts: ToastMessage[];\n onClose: (id: string) => void;\n}\n\nexport function ToastContainer({ toasts, onClose }: ToastContainerProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n return () => setMounted(false);\n }, []);\n\n if (!mounted) return null;\n\n return createPortal(\n <div className=\"semiont-toast-container\">\n {toasts.map((toast) => (\n <Toast key={toast.id} toast={toast} onClose={onClose} />\n ))}\n </div>,\n document.body\n );\n}\n\n// Toast context and hook for global toast management\ninterface ToastContextType {\n showToast: (message: string, type?: ToastType, duration?: number) => void;\n showSuccess: (message: string, duration?: number) => void;\n showError: (message: string, duration?: number) => void;\n showWarning: (message: string, duration?: number) => void;\n showInfo: (message: string, duration?: number) => void;\n}\n\nconst ToastContext = React.createContext<ToastContextType | undefined>(undefined);\n\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\n const [toasts, setToasts] = useState<ToastMessage[]>([]);\n\n const showToast = React.useCallback((message: string, type: ToastType = 'info', duration?: number) => {\n const id = Date.now().toString();\n const newToast: ToastMessage = duration !== undefined\n ? { id, message, type, duration }\n : { id, message, type };\n setToasts((prev) => [...prev, newToast]);\n }, []);\n\n const showSuccess = React.useCallback((message: string, duration?: number) => showToast(message, 'success', duration), [showToast]);\n const showError = React.useCallback((message: string, duration?: number) => showToast(message, 'error', duration), [showToast]);\n const showWarning = React.useCallback((message: string, duration?: number) => showToast(message, 'warning', duration), [showToast]);\n const showInfo = React.useCallback((message: string, duration?: number) => showToast(message, 'info', duration), [showToast]);\n\n const handleClose = React.useCallback((id: string) => {\n setToasts((prev) => prev.filter((toast) => toast.id !== id));\n }, []);\n\n const contextValue = React.useMemo(\n () => ({ showToast, showSuccess, showError, showWarning, showInfo }),\n [showToast, showSuccess, showError, showWarning, showInfo]\n );\n\n return (\n <ToastContext.Provider value={contextValue}>\n {children}\n <ToastContainer toasts={toasts} onClose={handleClose} />\n </ToastContext.Provider>\n );\n}\n\nexport function useToast() {\n const context = React.useContext(ToastContext);\n if (context === undefined) {\n throw new Error('useToast must be used within a ToastProvider');\n }\n return context;\n}","'use client';\n\nimport React, { createContext, useContext } from 'react';\nimport type { OpenResourcesManager } from '../types/OpenResourcesManager';\n\nconst OpenResourcesContext = createContext<OpenResourcesManager | undefined>(undefined);\n\n/**\n * Provider Pattern: Accepts OpenResourcesManager implementation as prop\n * and makes it available to child components via Context.\n *\n * Apps provide their own implementation (localStorage, sessionStorage, database, etc.)\n * and pass it to this provider at the root level.\n *\n * @example\n * ```tsx\n * // In app root\n * const openResourcesManager = useOpenResourcesManager(); // App's implementation\n *\n * <OpenResourcesProvider openResourcesManager={openResourcesManager}>\n * <App />\n * </OpenResourcesProvider>\n * ```\n */\nexport function OpenResourcesProvider({\n openResourcesManager,\n children\n}: {\n openResourcesManager: OpenResourcesManager;\n children: React.ReactNode;\n}) {\n return (\n <OpenResourcesContext.Provider value={openResourcesManager}>\n {children}\n </OpenResourcesContext.Provider>\n );\n}\n\n/**\n * Hook to access OpenResourcesManager from Context\n * Components use this hook to access open resources functionality\n */\nexport function useOpenResources(): OpenResourcesManager {\n const context = useContext(OpenResourcesContext);\n if (context === undefined) {\n throw new Error('useOpenResources must be used within an OpenResourcesProvider');\n }\n return context;\n}","'use client';\n\nimport { createContext, useContext, ReactNode, useState, useEffect, useMemo } from 'react';\nimport type { TranslationManager } from '../types/TranslationManager';\n\n// Static import for default English only - always needed as fallback\nimport enTranslations from '../../translations/en.json';\n\nconst TranslationContext = createContext<TranslationManager | null>(null);\n\n// Cache for dynamically loaded translations\nconst translationCache = new Map<string, any>();\n\n/**\n * Process ICU MessageFormat plural syntax\n * Supports: {count, plural, =0 {text} =1 {text} other {text}}\n */\nfunction processPluralFormat(text: string, params: Record<string, any>): string {\n // Match {paramName, plural, ...} with proper brace counting\n const pluralMatch = text.match(/\\{(\\w+),\\s*plural,\\s*/);\n if (!pluralMatch) {\n return text;\n }\n\n const paramName = pluralMatch[1];\n const count = params[paramName];\n if (count === undefined) {\n return text;\n }\n\n // Find the matching closing brace by counting\n let startPos = pluralMatch[0].length;\n let braceCount = 1; // We're inside the first {\n let endPos = startPos;\n\n for (let i = startPos; i < text.length; i++) {\n if (text[i] === '{') braceCount++;\n else if (text[i] === '}') {\n braceCount--;\n if (braceCount === 0) {\n endPos = i;\n break;\n }\n }\n }\n\n const pluralCases = text.substring(startPos, endPos);\n\n // Parse plural cases: =0 {text} =1 {text} other {text}\n const cases: Record<string, string> = {};\n const caseRegex = /(?:=(\\d+)|(\\w+))\\s*\\{([^}]+)\\}/g;\n let caseMatch;\n\n while ((caseMatch = caseRegex.exec(pluralCases)) !== null) {\n const [, exactNumber, keyword, textContent] = caseMatch;\n const key = exactNumber !== undefined ? `=${exactNumber}` : keyword;\n cases[key] = textContent;\n }\n\n // Select appropriate case\n const exactMatch = cases[`=${count}`];\n if (exactMatch !== undefined) {\n const result = exactMatch.replace(/#/g, String(count));\n return text.substring(0, pluralMatch.index!) + result + text.substring(endPos + 1);\n }\n\n const otherCase = cases['other'];\n if (otherCase !== undefined) {\n const result = otherCase.replace(/#/g, String(count));\n return text.substring(0, pluralMatch.index!) + result + text.substring(endPos + 1);\n }\n\n return text;\n}\n\n// List of available locales (can be extended without importing all files)\nexport const AVAILABLE_LOCALES = [\n 'ar', // Arabic\n 'bn', // Bengali\n 'cs', // Czech\n 'da', // Danish\n 'de', // German\n 'el', // Greek\n 'en', // English\n 'es', // Spanish\n 'fa', // Persian/Farsi\n 'fi', // Finnish\n 'fr', // French\n 'he', // Hebrew\n 'hi', // Hindi\n 'id', // Indonesian\n 'it', // Italian\n 'ja', // Japanese\n 'ko', // Korean\n 'ms', // Malay\n 'nl', // Dutch\n 'no', // Norwegian\n 'pl', // Polish\n 'pt', // Portuguese\n 'ro', // Romanian\n 'sv', // Swedish\n 'th', // Thai\n 'tr', // Turkish\n 'uk', // Ukrainian\n 'vi', // Vietnamese\n 'zh', // Chinese\n] as const;\nexport type AvailableLocale = typeof AVAILABLE_LOCALES[number];\n\n// Lazy load translations for a specific locale\nasync function loadTranslations(locale: string): Promise<any> {\n // Check cache first\n if (translationCache.has(locale)) {\n return translationCache.get(locale);\n }\n\n // English is already loaded statically\n if (locale === 'en') {\n translationCache.set('en', enTranslations);\n return enTranslations;\n }\n\n try {\n // Dynamic import for all other locales\n const translations = await import(`../../translations/${locale}.json`);\n const translationData = translations.default || translations;\n translationCache.set(locale, translationData);\n return translationData;\n } catch (error) {\n console.error(`Failed to load translations for locale: ${locale}`, error);\n // Fall back to English\n return enTranslations;\n }\n}\n\n// Default English translation manager (using static import)\nconst defaultTranslationManager: TranslationManager = {\n t: (namespace: string, key: string, params?: Record<string, any>) => {\n const translations = enTranslations as Record<string, Record<string, string>>;\n const translation = translations[namespace]?.[key];\n\n if (!translation) {\n console.warn(`Translation not found for ${namespace}.${key}`);\n return `${namespace}.${key}`;\n }\n\n // Handle parameter interpolation and plural format\n if (params && typeof translation === 'string') {\n let result = translation;\n // First process plural format\n result = processPluralFormat(result, params);\n // Then handle simple parameter interpolation\n Object.entries(params).forEach(([paramKey, paramValue]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, 'g'), String(paramValue));\n });\n return result;\n }\n\n return translation;\n },\n};\n\nexport interface TranslationProviderProps {\n /**\n * Option 1: Provide a complete TranslationManager implementation\n */\n translationManager?: TranslationManager;\n\n /**\n * Option 2: Use built-in translations by specifying a locale\n * When adding new locales, just add the JSON file and update AVAILABLE_LOCALES\n */\n locale?: string;\n\n /**\n * Loading component to show while translations are being loaded\n * Only relevant when using dynamic locale loading\n */\n loadingComponent?: ReactNode;\n\n children: ReactNode;\n}\n\n/**\n * Provider for translation management with dynamic loading\n *\n * Three modes of operation:\n * 1. No provider: Components use default English strings\n * 2. With locale prop: Dynamically loads translations for that locale\n * 3. With translationManager: Use custom translation implementation\n */\nexport function TranslationProvider({\n translationManager,\n locale,\n loadingComponent = null,\n children,\n}: TranslationProviderProps) {\n const [loadedTranslations, setLoadedTranslations] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Load translations when locale changes\n useEffect(() => {\n if (locale && !translationManager) {\n setIsLoading(true);\n loadTranslations(locale)\n .then(translations => {\n setLoadedTranslations(translations);\n setIsLoading(false);\n })\n .catch(error => {\n console.error('Failed to load translations:', error);\n setLoadedTranslations(enTranslations); // Fall back to English\n setIsLoading(false);\n });\n }\n }, [locale, translationManager]);\n\n // Create translation manager from loaded translations\n const localeManager = useMemo<TranslationManager | null>(() => {\n if (!loadedTranslations) return null;\n\n return {\n t: (namespace: string, key: string, params?: Record<string, any>) => {\n const translation = loadedTranslations[namespace]?.[key];\n\n if (!translation) {\n console.warn(`Translation not found for ${namespace}.${key} in locale ${locale}`);\n return `${namespace}.${key}`;\n }\n\n // Handle parameter interpolation and plural format\n if (params && typeof translation === 'string') {\n let result = translation;\n // First process plural format\n result = processPluralFormat(result, params);\n // Then handle simple parameter interpolation\n Object.entries(params).forEach(([paramKey, paramValue]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, 'g'), String(paramValue));\n });\n return result;\n }\n\n return translation;\n },\n };\n }, [loadedTranslations, locale]);\n\n // If custom translation manager provided, use it\n if (translationManager) {\n return (\n <TranslationContext.Provider value={translationManager}>\n {children}\n </TranslationContext.Provider>\n );\n }\n\n // If locale provided and still loading, show loading component\n if (locale && isLoading) {\n return <>{loadingComponent}</>;\n }\n\n // If locale provided and translations loaded, use them\n if (locale && localeManager) {\n return (\n <TranslationContext.Provider value={localeManager}>\n {children}\n </TranslationContext.Provider>\n );\n }\n\n // Default: use English translations\n return (\n <TranslationContext.Provider value={defaultTranslationManager}>\n {children}\n </TranslationContext.Provider>\n );\n}\n\n/**\n * Hook to access translations within a namespace\n *\n * Works in three modes:\n * 1. Without provider: Returns default English translations\n * 2. With provider using locale: Returns dynamically loaded translations for that locale\n * 3. With custom provider: Uses the custom translation manager\n *\n * @param namespace - Translation namespace (e.g., 'Toolbar', 'ResourceViewer')\n * @returns Function to translate keys within the namespace\n */\nexport function useTranslations(namespace: string) {\n const context = useContext(TranslationContext);\n\n // If no context (no provider), use default English translations\n if (!context) {\n return (key: string, params?: Record<string, any>) => {\n const translations = enTranslations as Record<string, Record<string, string>>;\n const translation = translations[namespace]?.[key];\n\n if (!translation) {\n console.warn(`Translation not found for ${namespace}.${key}`);\n return `${namespace}.${key}`;\n }\n\n // Handle parameter interpolation and plural format\n if (params && typeof translation === 'string') {\n let result = translation;\n // First process plural format\n result = processPluralFormat(result, params);\n // Then handle simple parameter interpolation\n Object.entries(params).forEach(([paramKey, paramValue]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, 'g'), String(paramValue));\n });\n return result;\n }\n\n return translation;\n };\n }\n\n // Return a function that translates keys within this namespace\n return (key: string, params?: Record<string, any>) => context.t(namespace, key, params);\n}\n\n/**\n * Hook to preload translations for a locale\n * Useful for preloading translations before navigation\n */\nexport function usePreloadTranslations() {\n return {\n preload: async (locale: string) => {\n try {\n await loadTranslations(locale);\n return true;\n } catch (error) {\n console.error(`Failed to preload translations for ${locale}:`, error);\n return false;\n }\n },\n isLoaded: (locale: string) => translationCache.has(locale),\n };\n}"],"mappings":"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","names":["SemiontApiClient","baseUrl","EventBus","SemiontApiClient","baseUrl","EventBus","React","useEffect","useState","jsx","useEffect","useState","React","createContext","useContext","jsx","createContext","useContext","useState","useEffect","useMemo","jsx","createContext","useState","useEffect","useMemo","jsx","useContext"]}
@@ -18,6 +18,7 @@ var ResourceInfoPanel = {
18
18
  representation: "Representation",
19
19
  mediaType: "Media Type",
20
20
  byteSize: "Size",
21
+ storageUri: "Storage",
21
22
  clone: "Clone",
22
23
  cloneDescription: "Generate a shareable clone link for this resource",
23
24
  archive: "Archive",
@@ -75,6 +76,7 @@ var AnnotationHistory = {
75
76
  annotationRemoved: "Annotation Removed",
76
77
  annotationBodyUpdated: "Annotation Updated",
77
78
  jobEvent: "Job Event",
79
+ embeddingComputed: "Embedding Computed",
78
80
  justNow: "just now",
79
81
  minutesAgo: "{{count}}m ago",
80
82
  hoursAgo: "{{count}}h ago",
@@ -418,4 +420,4 @@ export {
418
420
  ReferenceWizard,
419
421
  en_default
420
422
  };
421
- //# sourceMappingURL=chunk-HVMAGUFA.mjs.map
423
+ //# sourceMappingURL=chunk-NOD3NCXE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../translations/en.json"],"sourcesContent":["{\n \"Toolbar\": {\n \"annotations\": \"Annotations\",\n \"history\": \"History\",\n \"resourceInfo\": \"Resource Info\",\n \"collaboration\": \"Collaboration\",\n \"userAccount\": \"User Account\",\n \"settings\": \"Settings\",\n \"knowledgeBase\": \"Knowledge Base\"\n },\n \"ResourceInfoPanel\": {\n \"title\": \"Resource Info\",\n \"locale\": \"Locale\",\n \"notSpecified\": \"Not specified\",\n \"entityTypeTags\": \"Entity Type Tags\",\n \"representation\": \"Representation\",\n \"mediaType\": \"Media Type\",\n \"byteSize\": \"Size\",\n \"storageUri\": \"Storage\",\n \"clone\": \"Clone\",\n \"cloneDescription\": \"Generate a shareable clone link for this resource\",\n \"archive\": \"Archive\",\n \"archiveDescription\": \"Move this resource to archived status\",\n \"unarchive\": \"Unarchive\",\n \"unarchiveDescription\": \"Restore this resource to active status\",\n \"provenance\": \"Provenance\",\n \"createdAt\": \"Created\",\n \"modifiedAt\": \"Modified\",\n \"creationMethod\": \"How created\",\n \"attributedTo\": \"Attributed to\",\n \"derivedFrom\": \"Derived from\",\n \"generatedBy\": \"Generated by\"\n },\n \"CollaborationPanel\": {\n \"title\": \"Collaboration\",\n \"connectionStatus\": \"Connection Status\",\n \"live\": \"Live\",\n \"disconnected\": \"Disconnected\",\n \"events\": \"{{count}} events\",\n \"lastSync\": \"Last sync:\",\n \"noActivity\": \"No activity yet\",\n \"justNow\": \"Just now\",\n \"secondsAgo\": \"{{count}} seconds ago\",\n \"minuteAgo\": \"1 minute ago\",\n \"minutesAgo\": \"{{count}} minutes ago\",\n \"hourAgo\": \"1 hour ago\",\n \"hoursAgo\": \"{{count}} hours ago\",\n \"realtimeActive\": \"Real-time updates are active\",\n \"reconnecting\": \"Reconnecting to server...\",\n \"sharing\": \"Sharing\",\n \"collaborationComingSoon\": \"Collaboration features coming soon\"\n },\n \"AnnotationHistory\": {\n \"history\": \"History\",\n \"loading\": \"Loading...\",\n \"user\": \"User\",\n \"method\": \"Method\",\n \"viewOriginal\": \"View original\",\n \"viewAnnotation\": \"View annotation: {{content}}\",\n \"resourceCreated\": \"Created Resource\",\n \"resourceCloned\": \"Cloned\",\n \"resourceArchived\": \"Archived\",\n \"resourceUnarchived\": \"Unarchived\",\n \"highlightAdded\": \"Highlight Added\",\n \"highlightRemoved\": \"Highlight Removed\",\n \"referenceCreated\": \"Reference Created\",\n \"referenceResolved\": \"Reference Resolved\",\n \"referenceDeleted\": \"Reference Deleted\",\n \"entitytagAdded\": \"Tag Added\",\n \"entitytagRemoved\": \"Tag Removed\",\n \"assessmentAdded\": \"Assessment Added\",\n \"assessmentRemoved\": \"Assessment Removed\",\n \"annotationAdded\": \"Annotation Added\",\n \"annotationRemoved\": \"Annotation Removed\",\n \"annotationBodyUpdated\": \"Annotation Updated\",\n \"jobEvent\": \"Job Event\",\n \"embeddingComputed\": \"Embedding Computed\",\n \"justNow\": \"just now\",\n \"minutesAgo\": \"{{count}}m ago\",\n \"hoursAgo\": \"{{count}}h ago\",\n \"daysAgo\": \"{{count}}d ago\"\n },\n \"CommentsPanel\": {\n \"title\": \"Comments\",\n \"noComments\": \"No comments yet. Select text and click Comment to add one.\",\n \"commentPlaceholder\": \"Type your comment here...\",\n \"save\": \"Save\",\n \"cancel\": \"Cancel\",\n \"edit\": \"Edit\",\n \"annotateComments\": \"Annotate Comments\",\n \"instructions\": \"Instructions\",\n \"optional\": \"(optional)\",\n \"instructionsPlaceholder\": \"e.g., Focus on technical terminology...\",\n \"annotate\": \"Annotate\",\n \"annotating\": \"Annotating...\",\n \"toneLabel\": \"Tone\",\n \"toneOptional\": \"(optional)\",\n \"toneScholarly\": \"Scholarly\",\n \"toneExplanatory\": \"Explanatory\",\n \"toneConversational\": \"Conversational\",\n \"toneTechnical\": \"Technical\",\n \"densityLabel\": \"Density\",\n \"densitySparse\": \"Sparse\",\n \"densityDense\": \"Dense\",\n \"fragmentSelected\": \"Fragment selected\",\n \"imageRegionSelected\": \"Image region selected\",\n \"closeProgress\": \"Close\"\n },\n \"HighlightPanel\": {\n \"title\": \"Highlights\",\n \"noHighlights\": \"No highlights yet. Use AI annotation to find important passages.\",\n \"annotateHighlights\": \"Annotate Highlights\",\n \"instructions\": \"Instructions\",\n \"optional\": \"(optional)\",\n \"instructionsPlaceholder\": \"e.g., Focus on key technical concepts...\",\n \"annotate\": \"Annotate\",\n \"annotating\": \"Annotating...\",\n \"cancel\": \"Cancel\",\n \"densityLabel\": \"Density\",\n \"densitySparse\": \"Sparse\",\n \"densityDense\": \"Dense\",\n \"closeProgress\": \"Close\"\n },\n \"AssessmentPanel\": {\n \"title\": \"Assessments\",\n \"noAssessments\": \"No assessments yet. Use AI annotation to evaluate passages.\",\n \"assessmentPlaceholder\": \"Type your assessment here...\",\n \"save\": \"Save\",\n \"cancel\": \"Cancel\",\n \"annotateAssessments\": \"Annotate Assessments\",\n \"instructions\": \"Instructions\",\n \"optional\": \"(optional)\",\n \"instructionsPlaceholder\": \"e.g., Evaluate claims for accuracy and evidence...\",\n \"annotate\": \"Annotate\",\n \"annotating\": \"Annotating...\",\n \"toneLabel\": \"Tone\",\n \"toneOptional\": \"(optional)\",\n \"toneAnalytical\": \"Analytical\",\n \"toneCritical\": \"Critical\",\n \"toneBalanced\": \"Balanced\",\n \"toneConstructive\": \"Constructive\",\n \"densityLabel\": \"Density\",\n \"densitySparse\": \"Sparse\",\n \"densityDense\": \"Dense\",\n \"fragmentSelected\": \"Fragment selected\",\n \"imageRegionSelected\": \"Image region selected\",\n \"closeProgress\": \"Close\"\n },\n \"TaggingPanel\": {\n \"title\": \"Tags\",\n \"noTags\": \"No tags yet. Use AI annotation to identify structural roles.\",\n \"annotateTags\": \"Annotate Tags\",\n \"selectSchema\": \"Select Framework\",\n \"schemaLegal\": \"Legal Analysis (IRAC)\",\n \"schemaScientific\": \"Scientific Paper (IMRAD)\",\n \"schemaArgument\": \"Argument Structure (Toulmin)\",\n \"selectCategories\": \"Select Categories\",\n \"categoryIssue\": \"Issue\",\n \"categoryRule\": \"Rule\",\n \"categoryApplication\": \"Application\",\n \"categoryConclusion\": \"Conclusion\",\n \"categoryIntroduction\": \"Introduction\",\n \"categoryMethods\": \"Methods\",\n \"categoryResults\": \"Results\",\n \"categoryDiscussion\": \"Discussion\",\n \"categoryClaim\": \"Claim\",\n \"categoryEvidence\": \"Evidence\",\n \"categoryWarrant\": \"Warrant\",\n \"categoryCounterargument\": \"Counterargument\",\n \"categoryRebuttal\": \"Rebuttal\",\n \"annotate\": \"Annotate\",\n \"annotating\": \"Annotating...\",\n \"cancel\": \"Cancel\",\n \"selectAll\": \"Select All\",\n \"deselectAll\": \"Deselect All\",\n \"categoriesSelected\": \"{count, plural, =0 {No categories selected} =1 {1 category selected} other {# categories selected}}\",\n \"createTagForSelection\": \"Create Tag for Selection\",\n \"selectCategory\": \"Select Category\",\n \"chooseCategory\": \"Choose a category...\",\n \"fragmentSelected\": \"Fragment selected\",\n \"imageRegionSelected\": \"Image region selected\"\n },\n \"UnifiedAnnotationsPanel\": {\n \"title\": \"Annotations\",\n \"statistics\": \"Statistics\",\n \"highlight\": \"Highlights\",\n \"reference\": \"References\",\n \"assessment\": \"Assessments\",\n \"comment\": \"Comments\",\n \"tag\": \"Tags\"\n },\n \"StatisticsPanel\": {\n \"title\": \"Statistics\",\n \"highlights\": \"Highlights\",\n \"comments\": \"Comments\",\n \"assessments\": \"Assessments\",\n \"tags\": \"Tags\",\n \"references\": \"References\",\n \"stub\": \"Stub\",\n \"resolved\": \"Resolved\",\n \"entityTypes\": \"Entity Types\"\n },\n \"ReferencesPanel\": {\n \"title\": \"References\",\n \"noReferences\": \"No references yet. Select text to create references to other resources.\",\n \"outgoingReferences\": \"Outgoing References\",\n \"incomingReferences\": \"Incoming References\",\n \"noIncomingReferences\": \"No incoming references\",\n \"stub\": \"Stub reference (not linked)\",\n \"resolved\": \"Resolved reference (linked)\",\n \"open\": \"Open\",\n \"unlink\": \"Unlink\",\n \"resolve\": \"Resolve Reference\",\n \"cancel\": \"Cancel\",\n \"createReference\": \"Create Reference\",\n \"entityTypesOptional\": \"Entity Types (Optional)\",\n \"fragmentSelected\": \"Fragment selected\",\n \"imageRegionSelected\": \"Image region selected\",\n \"annotateReferences\": \"Annotate References\",\n \"selectEntityTypes\": \"Entity types:\",\n \"select\": \"Select\",\n \"deselect\": \"Deselect\",\n \"noEntityTypes\": \"No entity types available\",\n \"typesSelected\": \"{count, plural, =1 {1 type selected} other {# types selected}}\",\n \"annotate\": \"Annotate\",\n \"annotating\": \"Annotating...\",\n \"includeDescriptiveReferences\": \"Include descriptive references\",\n \"descriptiveReferencesTooltip\": \"Also find phrases like 'the CEO', 'the tech giant', 'the physicist' (in addition to names)\",\n \"annotationProgressTitle\": \"Annotating Entity References\",\n \"cancelAnnotation\": \"Cancel annotation\",\n \"found\": \"{{count}} found\",\n \"complete\": \"Annotation complete!\",\n \"failed\": \"Annotation failed\",\n \"current\": \"Current: {{entityType}}\",\n \"closeProgress\": \"Close\",\n \"loading\": \"loading...\",\n \"loadingEllipsis\": \"Loading...\",\n \"untitledResource\": \"Untitled Resource\",\n \"noText\": \"No text\"\n },\n \"KeyboardShortcuts\": {\n \"title\": \"Keyboard Shortcuts\",\n \"closeDialog\": \"Close dialog\",\n \"or\": \"or\",\n \"navigationTitle\": \"Navigation\",\n \"navOpenSearch\": \"Open global search\",\n \"navOpenSearchAlt\": \"Open global search (alternative)\",\n \"navCreateResource\": \"Create new resource\",\n \"navCloseOverlays\": \"Close all overlays (double press)\",\n \"navShowHelp\": \"Show keyboard shortcuts help\",\n \"sidebarTitle\": \"Knowledge Sidebar\",\n \"sidebarCollapse\": \"Collapse sidebar\",\n \"sidebarExpand\": \"Expand sidebar\",\n \"sidebarPickup\": \"Pick up resource tab (when focused)\",\n \"sidebarMove\": \"Move resource tab (when dragging)\",\n \"sidebarDrop\": \"Drop resource tab (when dragging)\",\n \"sidebarCancel\": \"Cancel drag operation\",\n \"annotationsTitle\": \"Resource Annotations\",\n \"annotHighlight\": \"Create highlight from annotation (direct)\",\n \"annotReference\": \"Open reference popup for annotation\",\n \"annotDelete\": \"Delete focused annotation\",\n \"annotNavigate\": \"Navigate through annotations\",\n \"annotNavigateBack\": \"Navigate annotations backward\",\n \"listsTitle\": \"Lists & Grids\",\n \"listsFilterNav\": \"Navigate entity type filters\",\n \"listsGridNav\": \"Navigate resource grid\",\n \"listsJumpFirst\": \"Jump to first item\",\n \"listsJumpLast\": \"Jump to last item\",\n \"searchModalTitle\": \"In Search Modal\",\n \"searchNav\": \"Navigate search results\",\n \"searchSelect\": \"Select result\",\n \"searchClose\": \"Close search\",\n \"modalTitle\": \"Modal Controls\",\n \"modalClose\": \"Close active modal\",\n \"modalNavForward\": \"Navigate forward through buttons\",\n \"modalNavBackward\": \"Navigate backward through buttons\",\n \"modalActivate\": \"Activate focused button\",\n \"accessibilityTitle\": \"Accessibility\",\n \"a11ySkipLinks\": \"Navigate to skip links (when at page start)\",\n \"a11yFollowLink\": \"Follow skip link\",\n \"macNote\": \"Using Mac keyboard shortcuts. ⌘ is the Command key.\",\n \"windowsNote\": \"Using Windows/Linux keyboard shortcuts. Ctrl is the Control key.\",\n \"footerHint\": \"Press {{key}} anytime to show this help\",\n \"close\": \"Close\"\n },\n \"AnnotateToolbar\": {\n \"modeGroup\": \"Mode\",\n \"browse\": \"Browse\",\n \"annotate\": \"Annotate\",\n \"selectionGroup\": \"Motivation\",\n \"clickGroup\": \"Click\",\n \"shapeGroup\": \"Shape\",\n \"none\": \"None\",\n \"linking\": \"Reference\",\n \"highlighting\": \"Highlight\",\n \"assessing\": \"Assess\",\n \"commenting\": \"Comment\",\n \"tagging\": \"Tag\",\n \"detail\": \"Detail\",\n \"follow\": \"Follow\",\n \"deleting\": \"Delete\",\n \"jsonld\": \"JSON-LD\",\n \"rectangle\": \"Rectangle\",\n \"circle\": \"Circle\",\n \"polygon\": \"Polygon\"\n },\n \"CollapsibleResourceNavigation\": {\n \"title\": \"Navigation\",\n \"collapseSidebar\": \"Collapse sidebar\",\n \"expandSidebar\": \"Expand sidebar\",\n \"dragToReorder\": \"Drag to reorder\",\n \"dragToReorderDoc\": \"Drag to reorder {{name}}\",\n \"closeResource\": \"Close resource\",\n \"dragInstructions\": \"To reorder resources: Use Tab to navigate to a resource. Press Alt+Up arrow to move up or Alt+Down arrow to move down. For drag and drop: Press space bar to pick up the item. Use arrow keys to move it. Press space bar again to drop.\"\n },\n \"ResourceViewer\": {\n \"deleteConfirmationTitle\": \"Delete Annotation\",\n \"deleteConfirmationMessage\": \"Are you sure you want to delete this annotation? This action cannot be undone.\",\n \"deleteConfirmationCancel\": \"Cancel\",\n \"deleteConfirmationDelete\": \"Delete\"\n },\n \"Settings\": {\n \"title\": \"Settings\",\n \"lineNumbers\": \"Line Numbers\",\n \"lineNumbersVisible\": \"Visible\",\n \"lineNumbersHidden\": \"Hidden\",\n \"theme\": \"Theme\",\n \"themeLight\": \"Light\",\n \"themeDark\": \"Dark\",\n \"themeSystem\": \"System\",\n \"themeSystemActive\": \"System ({{mode}})\",\n \"themeModeActive\": \"Using {{mode}} mode\",\n \"language\": \"Language\",\n \"languageHint\": \"Change language in the main navigation\",\n \"languageChanging\": \"Changing language...\",\n \"hoverDelay\": \"Hover Delay\",\n \"hoverDelayFast\": \"Fast\",\n \"hoverDelaySlow\": \"Slow\",\n \"hoverDelayDescription\": \"{{delay}}ms delay before hover effects appear\"\n },\n \"AnnotateView\": {},\n \"ReferenceWizard\": {\n \"gatherTitle\": \"Gathered Context\",\n \"configureGenerationTitle\": \"Configure Generation\",\n \"configureSearchTitle\": \"Configure Search\",\n \"searchResultsTitle\": \"Search Results\",\n \"sourceContextLabel\": \"Annotation context in resource\",\n \"connectionsLabel\": \"Peer Annotations\",\n \"citedByLabel\": \"Resource Cited By\",\n \"userHintLabel\": \"Hint\",\n \"userHintPlaceholder\": \"Describe what this annotation refers to...\",\n \"loadingContext\": \"Gathering context...\",\n \"failedContext\": \"Failed to gather context\",\n \"cancel\": \"Cancel\",\n \"generate\": \"Generate\",\n \"compose\": \"Compose\",\n \"resolutionStrategyLabel\": \"Resolution Strategy\",\n \"back\": \"Back\",\n \"link\": \"Link\",\n \"score\": \"Score\",\n \"noResults\": \"No results found\",\n \"resourceTitle\": \"Resource Title\",\n \"resourceTitlePlaceholder\": \"Enter resource title...\",\n \"additionalInstructions\": \"Additional Instructions\",\n \"additionalInstructionsPlaceholder\": \"Enter additional instructions...\",\n \"language\": \"Language\",\n \"languageHelp\": \"Language for generated content\",\n \"creativity\": \"Creativity\",\n \"creativityFocused\": \"Focused\",\n \"creativityCreative\": \"Creative\",\n \"maxLength\": \"Max Length\",\n \"maxLengthHelp\": \"Maximum number of tokens\",\n \"maxResults\": \"Max Results\",\n \"semanticScoring\": \"Semantic Scoring\",\n \"semanticScoringHelp\": \"Use AI to score results by semantic relevance\",\n \"searching\": \"Searching...\",\n \"search\": \"Search\"\n }\n}"],"mappings":"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","names":[]}
@@ -29,6 +29,7 @@ import { jsx as jsx2 } from "react/jsx-runtime";
29
29
  var ApiClientContext = createContext2(void 0);
30
30
  function ApiClientProvider({
31
31
  baseUrl: url,
32
+ tokenRefresher,
32
33
  children
33
34
  }) {
34
35
  const eventBus = useEventBus();
@@ -37,9 +38,10 @@ function ApiClientProvider({
37
38
  baseUrl: baseUrl(url),
38
39
  eventBus,
39
40
  // Use no timeout in test environment to avoid AbortController issues with ky + vitest
40
- ...process.env.NODE_ENV !== "test" && { timeout: 3e4 }
41
+ ...process.env.NODE_ENV !== "test" && { timeout: 3e4 },
42
+ ...tokenRefresher && { tokenRefresher }
41
43
  }),
42
- [url, eventBus]
44
+ [url, eventBus, tokenRefresher]
43
45
  );
44
46
  return /* @__PURE__ */ jsx2(ApiClientContext.Provider, { value: client, children });
45
47
  }
@@ -57,4 +59,4 @@ export {
57
59
  ApiClientProvider,
58
60
  useApiClient
59
61
  };
60
- //# sourceMappingURL=chunk-HNZOXH4L.mjs.map
62
+ //# sourceMappingURL=chunk-OZICDVH7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/contexts/EventBusContext.tsx","../src/contexts/ApiClientContext.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useRef, type ReactNode } from 'react';\nimport { EventBus } from '@semiont/core';\n\nconst EventBusContext = createContext<EventBus | null>(null);\n\nexport interface EventBusProviderProps {\n children: ReactNode;\n}\n\n/**\n * Unified event bus provider for all application events.\n *\n * Each provider mount creates a fresh EventBus instance. This means:\n * - Workspace switches (which remount via key prop) get isolated buses\n * - Tests get isolation naturally — no resetEventBusForTesting needed\n *\n * Operation handlers (API calls triggered by events) are set up separately via\n * the useBindFlow hook, which should be called at the resource page level.\n */\nexport function EventBusProvider({ children }: EventBusProviderProps) {\n const eventBusRef = useRef<EventBus | null>(null);\n if (!eventBusRef.current) {\n eventBusRef.current = new EventBus();\n }\n const eventBus = eventBusRef.current;\n\n return (\n <EventBusContext.Provider value={eventBus}>\n {children}\n </EventBusContext.Provider>\n );\n}\n\n/**\n * Hook to access the unified event bus\n *\n * Use this everywhere instead of:\n * - useMakeMeaningEvents()\n * - useNavigationEvents()\n * - useGlobalSettingsEvents()\n *\n * @example\n * ```typescript\n * const eventBus = useEventBus();\n *\n * // Emit any event\n * eventBus.get('beckon:hover').next({ annotationId: '123' });\n * eventBus.get('browse:sidebar-toggle').next(undefined);\n * eventBus.get('settings:theme-changed').next({ theme: 'dark' });\n *\n * // Subscribe to any event\n * useEffect(() => {\n * const unsubscribe = eventBus.on('beckon:hover', ({ annotationId }) => {\n * console.log(annotationId);\n * });\n * return () => unsubscribe();\n * }, []);\n * ```\n */\nexport function useEventBus(): EventBus {\n const eventBus = useContext(EventBusContext);\n if (!eventBus) {\n throw new Error('useEventBus must be used within EventBusProvider');\n }\n return eventBus;\n}\n","'use client';\n\nimport { createContext, useContext, ReactNode, useMemo } from 'react';\nimport { baseUrl } from '@semiont/core';\nimport { SemiontApiClient, type TokenRefresher } from '@semiont/api-client';\nimport { useEventBus } from './EventBusContext';\n\nconst ApiClientContext = createContext<SemiontApiClient | undefined>(undefined);\n\nexport interface ApiClientProviderProps {\n baseUrl: string;\n /**\n * Optional 401-recovery hook. If provided, the api-client will retry\n * requests once with a fresh token when a 401 is encountered. The\n * frontend's protected layouts pass `useKnowledgeBaseSession().refreshActive`\n * here so the api-client can transparently recover from expired access tokens.\n */\n tokenRefresher?: TokenRefresher;\n children: ReactNode;\n}\n\n/**\n * Provider for API client — must be nested inside EventBusProvider.\n * The client is re-created when the baseUrl changes (workspace switch).\n * The EventBus is taken from EventBusContext so client and UI components\n * share the same workspace-scoped bus.\n */\nexport function ApiClientProvider({\n baseUrl: url,\n tokenRefresher,\n children,\n}: ApiClientProviderProps) {\n const eventBus = useEventBus();\n\n const client = useMemo(\n () => new SemiontApiClient({\n baseUrl: baseUrl(url),\n eventBus,\n // Use no timeout in test environment to avoid AbortController issues with ky + vitest\n ...(process.env.NODE_ENV !== 'test' && { timeout: 30000 }),\n ...(tokenRefresher && { tokenRefresher }),\n }),\n [url, eventBus, tokenRefresher]\n );\n\n return (\n <ApiClientContext.Provider value={client}>\n {children}\n </ApiClientContext.Provider>\n );\n}\n\n/**\n * Hook to access the stateless API client singleton\n * Must be used within an ApiClientProvider\n * @returns Stateless SemiontApiClient instance\n */\nexport function useApiClient(): SemiontApiClient {\n const context = useContext(ApiClientContext);\n\n if (context === undefined) {\n throw new Error('useApiClient must be used within an ApiClientProvider');\n }\n\n return context;\n}\n"],"mappings":";;;AAEA,SAAS,eAAe,YAAY,cAA8B;AAClE,SAAS,gBAAgB;AA0BrB;AAxBJ,IAAM,kBAAkB,cAA+B,IAAI;AAgBpD,SAAS,iBAAiB,EAAE,SAAS,GAA0B;AACpE,QAAM,cAAc,OAAwB,IAAI;AAChD,MAAI,CAAC,YAAY,SAAS;AACxB,gBAAY,UAAU,IAAI,SAAS;AAAA,EACrC;AACA,QAAM,WAAW,YAAY;AAE7B,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,UAC9B,UACH;AAEJ;AA4BO,SAAS,cAAwB;AACtC,QAAM,WAAW,WAAW,eAAe;AAC3C,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,SAAO;AACT;;;ACjEA,SAAS,iBAAAA,gBAAe,cAAAC,aAAuB,eAAe;AAC9D,SAAS,eAAe;AACxB,SAAS,wBAA6C;AA0ClD,gBAAAC,YAAA;AAvCJ,IAAM,mBAAmBC,eAA4C,MAAS;AAoBvE,SAAS,kBAAkB;AAAA,EAChC,SAAS;AAAA,EACT;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,WAAW,YAAY;AAE7B,QAAM,SAAS;AAAA,IACb,MAAM,IAAI,iBAAiB;AAAA,MACzB,SAAS,QAAQ,GAAG;AAAA,MACpB;AAAA;AAAA,MAEA,GAAI,QAAQ,IAAI,aAAa,UAAU,EAAE,SAAS,IAAM;AAAA,MACxD,GAAI,kBAAkB,EAAE,eAAe;AAAA,IACzC,CAAC;AAAA,IACD,CAAC,KAAK,UAAU,cAAc;AAAA,EAChC;AAEA,SACE,gBAAAD,KAAC,iBAAiB,UAAjB,EAA0B,OAAO,QAC/B,UACH;AAEJ;AAOO,SAAS,eAAiC;AAC/C,QAAM,UAAUE,YAAW,gBAAgB;AAE3C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEA,SAAO;AACT;","names":["createContext","useContext","jsx","createContext","useContext"]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  useApiClient,
4
4
  useEventBus
5
- } from "./chunk-HNZOXH4L.mjs";
5
+ } from "./chunk-OZICDVH7.mjs";
6
6
 
7
7
  // src/contexts/AuthTokenContext.tsx
8
8
  import { createContext, useContext } from "react";
@@ -158,7 +158,7 @@ function useHoverEmitter(annotationId, hoverDelayMs = HOVER_DELAY_MS) {
158
158
  return { onMouseEnter, onMouseLeave };
159
159
  }
160
160
  function useAttentionStream() {
161
- const client = useApiClient();
161
+ const semiont = useApiClient();
162
162
  const token = useAuthToken();
163
163
  const tokenRef = useRef2(token);
164
164
  useEffect2(() => {
@@ -168,12 +168,13 @@ function useAttentionStream() {
168
168
  useEffect2(() => {
169
169
  setStatus("connecting");
170
170
  try {
171
- const sub = client.flows.attentionStream(
172
- () => tokenRef.current ? accessToken(tokenRef.current) : void 0
173
- );
171
+ const stream = semiont.sse.attentionStream({
172
+ auth: tokenRef.current ? accessToken(tokenRef.current) : void 0,
173
+ eventBus: semiont.eventBus
174
+ });
174
175
  setStatus("connected");
175
176
  return () => {
176
- sub.unsubscribe();
177
+ stream.close();
177
178
  setStatus("disconnected");
178
179
  };
179
180
  } catch (error) {
@@ -181,7 +182,7 @@ function useAttentionStream() {
181
182
  setStatus("error");
182
183
  return;
183
184
  }
184
- }, [client]);
185
+ }, [semiont]);
185
186
  return { status };
186
187
  }
187
188
 
@@ -196,4 +197,4 @@ export {
196
197
  useHoverEmitter,
197
198
  useAttentionStream
198
199
  };
199
- //# sourceMappingURL=chunk-BQJWOK4C.mjs.map
200
+ //# sourceMappingURL=chunk-VN5NY4SN.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/contexts/AuthTokenContext.tsx","../src/contexts/useEventSubscription.ts","../src/hooks/useBeckonFlow.ts"],"sourcesContent":["'use client';\n\n/**\n * Auth Token Context - Manages authentication token lifecycle\n *\n * Simple approach: Just pass the token value through context.\n * When the token changes, context updates, components re-render.\n * No complex machinery needed.\n */\n\nimport { createContext, useContext, ReactNode } from 'react';\n\nconst AuthTokenContext = createContext<string | null | undefined>(undefined);\n\nexport interface AuthTokenProviderProps {\n token: string | null;\n children: ReactNode;\n}\n\n/**\n * Provider for auth token\n * Pass the current token value - React handles the rest\n */\nexport function AuthTokenProvider({\n token,\n children,\n}: AuthTokenProviderProps) {\n return (\n <AuthTokenContext.Provider value={token}>\n {children}\n </AuthTokenContext.Provider>\n );\n}\n\n/**\n * Hook to get current auth token\n *\n * Returns the current token value from context.\n * Re-renders automatically when token changes (normal React behavior).\n *\n * @returns Current access token (null if not authenticated)\n * @throws Error if used outside AuthTokenProvider\n */\nexport function useAuthToken(): string | null {\n const context = useContext(AuthTokenContext);\n\n if (context === undefined) {\n throw new Error('useAuthToken must be used within an AuthTokenProvider');\n }\n\n return context;\n}\n","import { useEffect, useRef, useMemo } from 'react';\nimport type { EventMap } from '@semiont/core';\nimport { useEventBus } from './EventBusContext';\n\n/**\n * Subscribe to an event bus event with automatic cleanup.\n *\n * This hook solves the \"stale closure\" problem by always using the latest\n * version of the handler without re-subscribing.\n *\n * @example\n * ```tsx\n * useEventSubscription('mark:create-ok', ({ annotationId }) => {\n * // This always uses the latest props/state\n * triggerSparkleAnimation(annotation.id);\n * });\n * ```\n */\nexport function useEventSubscription<K extends keyof EventMap>(\n eventName: K,\n handler: (payload: EventMap[K]) => void\n): void {\n const eventBus = useEventBus();\n\n // Store the latest handler in a ref to avoid stale closures\n const handlerRef = useRef(handler);\n\n // Update ref on every render (no re-subscription needed)\n useEffect(() => {\n handlerRef.current = handler;\n });\n\n // Subscribe once, using a stable wrapper that calls the current handler\n useEffect(() => {\n const stableHandler = (payload: EventMap[K]) => {\n handlerRef.current(payload);\n };\n\n // RxJS EventBus.get() returns Subject, subscribe returns Subscription\n const subscription = eventBus.get(eventName).subscribe(stableHandler);\n\n return () => {\n subscription.unsubscribe();\n };\n }, [eventName, eventBus]); // eventBus is stable, only re-subscribe if event name changes\n}\n\n/**\n * Subscribe to multiple events at once.\n *\n * @example\n * ```tsx\n * useEventSubscriptions({\n * 'mark:create-ok': ({ annotationId }) => handleCreated(annotationId),\n * 'mark:delete-ok': ({ annotationId }) => removeAnnotation(annotationId),\n * });\n * ```\n */\nexport function useEventSubscriptions(\n subscriptions: {\n [K in keyof EventMap]?: (payload: EventMap[K]) => void;\n }\n): void {\n const eventBus = useEventBus();\n\n // Store the latest handlers in refs\n const handlersRef = useRef(subscriptions);\n\n // Update refs on every render\n useEffect(() => {\n handlersRef.current = subscriptions;\n });\n\n // Get stable list of event names to subscribe to\n const eventNames = useMemo(\n () => Object.keys(subscriptions).sort(),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [Object.keys(subscriptions).sort().join(',')]\n );\n\n // Subscribe once per event - only re-subscribe if event names actually change\n useEffect(() => {\n const subscriptions: Array<{ unsubscribe: () => void }> = [];\n\n // Create stable wrappers for each subscription\n for (const eventName of eventNames) {\n const stableHandler = (payload: any) => {\n const currentHandler = handlersRef.current[eventName as keyof EventMap];\n if (currentHandler) {\n currentHandler(payload);\n } else {\n console.warn('[useEventSubscriptions] No current handler found for:', eventName);\n }\n };\n\n // RxJS EventBus.get() returns Subject, subscribe returns Subscription\n const subscription = eventBus.get(eventName as keyof EventMap).subscribe(stableHandler);\n subscriptions.push(subscription);\n }\n\n // Cleanup: unsubscribe from all subscriptions\n return () => {\n for (const subscription of subscriptions) {\n subscription.unsubscribe();\n }\n };\n }, [eventNames, eventBus]); // eventBus is stable singleton - never in deps; only re-subscribe if event names change\n}\n","/**\n * useBeckonFlow — Annotation attention / pointer coordination hook\n *\n * Manages which annotation currently has the user's attention:\n * - Hover state (hoveredAnnotationId)\n * - Hover → sparkle relay\n * - Click → focus relay\n *\n * Follows react-rxjs-guide.md Layer 2 pattern: Hook bridge that\n * subscribes to events and pushes values into React state.\n *\n * Note: beckon:sparkle visual effect (triggerSparkleAnimation) is owned by\n * ResourceViewerPage, which subscribes to beckon:sparkle and delegates to\n * ResourceAnnotationsContext. This hook emits the signal; it does not render the effect.\n *\n * @subscribes beckon:hover - Sets hoveredAnnotationId; emits beckon:sparkle\n * @subscribes browse:click - Emits beckon:focus (attention relay only)\n * @emits beckon:sparkle\n * @emits beckon:focus\n */\n\n/**\n * useHoverEmitter / createHoverHandlers — annotation hover emission utilities\n *\n * Centralises two hover quality-of-life behaviours:\n *\n * 1. currentHover guard — suppresses redundant emissions when the mouse\n * moves within the same annotation element (prevents event bus noise).\n *\n * 2. Debounce delay (HOVER_DELAY_MS) — a short timer before emitting\n * beckon:hover, so that transient pass-through movements (user dragging\n * the mouse across the panel to reach a button elsewhere) do not trigger\n * sparkle animations or cross-highlight effects.\n * The delay is cancelled immediately on mouseLeave, so leaving is always instant.\n *\n * Two forms are provided:\n *\n * useHoverEmitter(annotationId)\n * React hook. Returns { onMouseEnter, onMouseLeave } props for JSX elements.\n * Use in panel entries (HighlightEntry, CommentEntry, …).\n *\n * createHoverHandlers(emit)\n * Plain factory. Returns { handleMouseEnter(id), handleMouseLeave(), cleanup }.\n * Use inside useEffect / imperative setup code where hooks cannot be called\n * (BrowseView, CodeMirrorRenderer, AnnotationOverlay, PdfAnnotationCanvas).\n */\n\nimport { useState, useRef, useCallback, useEffect } from 'react';\nimport { accessToken } from '@semiont/core';\nimport { useEventBus } from '../contexts/EventBusContext';\nimport { useEventSubscriptions } from '../contexts/useEventSubscription';\nimport { useApiClient } from '../contexts/ApiClientContext';\nimport { useAuthToken } from '../contexts/AuthTokenContext';\nimport type { StreamStatus } from './useResourceEvents';\n\n// ─── useBeckonFlow ─────────────────────────────────────────────────────────\n\nexport interface BeckonFlowState {\n hoveredAnnotationId: string | null;\n}\n\nexport function useBeckonFlow(): BeckonFlowState {\n const eventBus = useEventBus();\n const [hoveredAnnotationId, setHoveredAnnotationId] = useState<string | null>(null);\n\n const handleAnnotationHover = useCallback(({ annotationId }: { annotationId: string | null }) => {\n setHoveredAnnotationId(annotationId);\n if (annotationId) {\n eventBus.get('beckon:sparkle').next({ annotationId });\n }\n }, []); // eventBus is stable singleton - never in deps\n\n const handleAnnotationClick = useCallback(({ annotationId }: { annotationId: string }) => {\n eventBus.get('beckon:focus').next({ annotationId });\n // Scroll to annotation handled by BrowseView via beckon:focus subscription\n }, []); // eventBus is stable singleton - never in deps\n\n useEventSubscriptions({\n 'beckon:hover': handleAnnotationHover,\n 'browse:click': handleAnnotationClick,\n });\n\n return { hoveredAnnotationId };\n}\n\n// ─── createHoverHandlers (use inside useEffect / imperative setup) ────────────\n\n/** Default milliseconds the mouse must dwell before beckon:hover is emitted. */\nexport const HOVER_DELAY_MS = 150;\n\ntype EmitHover = (annotationId: string | null) => void;\n\nexport interface HoverHandlers {\n /** Call with the annotation ID when the mouse enters an annotation element. */\n handleMouseEnter: (annotationId: string) => void;\n /** Call when the mouse leaves the annotation element. */\n handleMouseLeave: () => void;\n /** Cancel any pending timer — call in the useEffect cleanup. */\n cleanup: () => void;\n}\n\n/**\n * Creates hover handlers for imperative code (non-hook contexts).\n * @param emit - Callback to emit hover events\n * @param delayMs - Hover delay in milliseconds\n */\nexport function createHoverHandlers(emit: EmitHover, delayMs: number): HoverHandlers {\n let currentHover: string | null = null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const cancelTimer = () => {\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n const handleMouseEnter = (annotationId: string) => {\n if (currentHover === annotationId) return; // already hovering this one\n cancelTimer();\n timer = setTimeout(() => {\n timer = null;\n currentHover = annotationId;\n emit(annotationId);\n }, delayMs);\n };\n\n const handleMouseLeave = () => {\n cancelTimer();\n if (currentHover !== null) {\n currentHover = null;\n emit(null);\n }\n };\n\n return { handleMouseEnter, handleMouseLeave, cleanup: cancelTimer };\n}\n\n// ─── useHoverEmitter (use in JSX onMouseEnter / onMouseLeave props) ───────────\n\nexport interface HoverEmitterProps {\n onMouseEnter: () => void;\n onMouseLeave: () => void;\n}\n\n/**\n * React hook that returns onMouseEnter / onMouseLeave props for a single\n * annotation entry element.\n *\n * @param annotationId - The ID of the annotation this element represents.\n * @param hoverDelayMs - Hover delay in milliseconds (defaults to HOVER_DELAY_MS for panel entries)\n */\nexport function useHoverEmitter(annotationId: string, hoverDelayMs: number = HOVER_DELAY_MS): HoverEmitterProps {\n const eventBus = useEventBus();\n const currentHoverRef = useRef<string | null>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const onMouseEnter = useCallback(() => {\n if (currentHoverRef.current === annotationId) return;\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n currentHoverRef.current = annotationId;\n eventBus.get('beckon:hover').next({ annotationId });\n }, hoverDelayMs);\n }, [annotationId, hoverDelayMs]); // eventBus is stable singleton - never in deps\n\n const onMouseLeave = useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n if (currentHoverRef.current !== null) {\n currentHoverRef.current = null;\n eventBus.get('beckon:hover').next({ annotationId: null });\n }\n }, []); // eventBus is stable singleton - never in deps\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n }, []);\n\n return { onMouseEnter, onMouseLeave };\n}\n\n// ─── useAttentionStream ───────────────────────────────────────────────────────\n\n/**\n * Opens a participant-scoped SSE connection to receive cross-participant\n * beckon signals. Each incoming signal is emitted as beckon:focus on the\n * EventBus — the existing scroll/highlight machinery handles it automatically.\n *\n * Signals are ephemeral: delivered if connected, silently dropped if not.\n *\n * @example\n * ```tsx\n * // In your layout (render-nothing connector):\n * useAttentionStream();\n * ```\n */\nexport function useAttentionStream(): { status: StreamStatus } {\n const semiont = useApiClient();\n const token = useAuthToken();\n const tokenRef = useRef(token);\n useEffect(() => { tokenRef.current = token; });\n const [status, setStatus] = useState<StreamStatus>('disconnected');\n\n useEffect(() => {\n setStatus('connecting');\n try {\n const stream = semiont.sse.attentionStream({\n auth: tokenRef.current ? accessToken(tokenRef.current) : undefined,\n eventBus: semiont.eventBus,\n });\n setStatus('connected');\n return () => { stream.close(); setStatus('disconnected'); };\n } catch (error) {\n console.error('[AttentionStream] Failed to connect:', error);\n setStatus('error');\n return;\n }\n }, [semiont]);\n\n return { status };\n}\n"],"mappings":"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","names":["subscriptions","useRef","useEffect","useRef","useEffect"]}
@@ -31,7 +31,8 @@ var ResourceInfoPanel = {
31
31
  creationMethod: "Zp\u016Fsob vytvo\u0159en\xED",
32
32
  attributedTo: "P\u0159ips\xE1no",
33
33
  derivedFrom: "Odvozeno z",
34
- generatedBy: "Vygenerov\xE1no pomoc\xED"
34
+ generatedBy: "Vygenerov\xE1no pomoc\xED",
35
+ storageUri: "\xDAlo\u017Ei\u0161t\u011B"
35
36
  };
36
37
  var CollaborationPanel = {
37
38
  title: "Spolupr\xE1ce",
@@ -377,6 +378,9 @@ var ReferenceWizard = {
377
378
  searching: "Vyhled\xE1v\xE1n\xED...",
378
379
  search: "Hledat"
379
380
  };
381
+ var History = {
382
+ embeddingComputed: "Embedding vypo\u010Dten"
383
+ };
380
384
  var cs_default = {
381
385
  Toolbar,
382
386
  ResourceInfoPanel,
@@ -395,7 +399,8 @@ var cs_default = {
395
399
  ResourceViewer,
396
400
  Settings,
397
401
  AnnotateView,
398
- ReferenceWizard
402
+ ReferenceWizard,
403
+ History
399
404
  };
400
405
  export {
401
406
  AnnotateToolbar,
@@ -406,6 +411,7 @@ export {
406
411
  CollapsibleResourceNavigation,
407
412
  CommentsPanel,
408
413
  HighlightPanel,
414
+ History,
409
415
  KeyboardShortcuts,
410
416
  ReferenceWizard,
411
417
  ReferencesPanel,
@@ -418,4 +424,4 @@ export {
418
424
  UnifiedAnnotationsPanel,
419
425
  cs_default as default
420
426
  };
421
- //# sourceMappingURL=cs-4WIB2IHH.mjs.map
427
+ //# sourceMappingURL=cs-XYHH7HNE.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../translations/cs.json"],"sourcesContent":["{\n \"Toolbar\": {\n \"annotations\": \"Anotace\",\n \"history\": \"Historie\",\n \"resourceInfo\": \"Informace o zdroji\",\n \"collaboration\": \"Spolupráce\",\n \"userAccount\": \"Uživatelský účet\",\n \"settings\": \"Nastavení\",\n \"knowledgeBase\": \"Znalostní báze\"\n },\n \"ResourceInfoPanel\": {\n \"title\": \"Informace o zdroji\",\n \"locale\": \"Národní prostředí\",\n \"notSpecified\": \"Neuvedeno\",\n \"entityTypeTags\": \"Štítky typů entit\",\n \"representation\": \"Reprezentace\",\n \"mediaType\": \"Typ média\",\n \"byteSize\": \"Velikost\",\n \"clone\": \"Klonovat\",\n \"cloneDescription\": \"Vytvořit sdílitelný odkaz na klon tohoto zdroje\",\n \"archive\": \"Archivovat\",\n \"archiveDescription\": \"Přesunout tento zdroj do archivovaného stavu\",\n \"unarchive\": \"Obnovit z archivu\",\n \"unarchiveDescription\": \"Obnovit tento zdroj do aktivního stavu\",\n \"provenance\": \"Původ\",\n \"createdAt\": \"Vytvořeno\",\n \"modifiedAt\": \"Upraveno\",\n \"creationMethod\": \"Způsob vytvoření\",\n \"attributedTo\": \"Připsáno\",\n \"derivedFrom\": \"Odvozeno z\",\n \"generatedBy\": \"Vygenerováno pomocí\",\n \"storageUri\": \"Úložiště\"\n },\n \"CollaborationPanel\": {\n \"title\": \"Spolupráce\",\n \"connectionStatus\": \"Stav připojení\",\n \"live\": \"Živě\",\n \"disconnected\": \"Odpojeno\",\n \"events\": \"{{count}} událostí\",\n \"lastSync\": \"Poslední synchronizace:\",\n \"noActivity\": \"Zatím žádná aktivita\",\n \"justNow\": \"Právě teď\",\n \"secondsAgo\": \"Před {{count}} sekundami\",\n \"minuteAgo\": \"Před 1 minutou\",\n \"minutesAgo\": \"Před {{count}} minutami\",\n \"hourAgo\": \"Před 1 hodinou\",\n \"hoursAgo\": \"Před {{count}} hodinami\",\n \"realtimeActive\": \"Aktualizace v reálném čase jsou aktivní\",\n \"reconnecting\": \"Opětovné připojování k serveru...\",\n \"sharing\": \"Sdílení\",\n \"collaborationComingSoon\": \"Funkce spolupráce budou brzy k dispozici\"\n },\n \"AnnotationHistory\": {\n \"history\": \"Historie\",\n \"loading\": \"Načítání...\",\n \"user\": \"Uživatel\",\n \"method\": \"Metoda\",\n \"viewOriginal\": \"Zobrazit originál\",\n \"viewAnnotation\": \"Zobrazit anotaci: {{content}}\",\n \"resourceCreated\": \"Zdroj vytvořen\",\n \"resourceCloned\": \"Klonováno\",\n \"resourceArchived\": \"Archivováno\",\n \"resourceUnarchived\": \"Obnoveno z archivu\",\n \"highlightAdded\": \"Zvýraznění přidáno\",\n \"highlightRemoved\": \"Zvýraznění odebráno\",\n \"referenceCreated\": \"Reference vytvořena\",\n \"referenceResolved\": \"Reference vyřešena\",\n \"referenceDeleted\": \"Reference smazána\",\n \"entitytagAdded\": \"Štítek přidán\",\n \"entitytagRemoved\": \"Štítek odebrán\",\n \"assessmentAdded\": \"Hodnocení přidáno\",\n \"assessmentRemoved\": \"Hodnocení odebráno\",\n \"annotationAdded\": \"Anotace přidána\",\n \"annotationRemoved\": \"Anotace odebrána\",\n \"annotationBodyUpdated\": \"Anotace aktualizována\",\n \"jobEvent\": \"Událost úlohy\",\n \"justNow\": \"právě teď\",\n \"minutesAgo\": \"před {{count}} min\",\n \"hoursAgo\": \"před {{count}} hod\",\n \"daysAgo\": \"před {{count}} dny\"\n },\n \"CommentsPanel\": {\n \"title\": \"Komentáře\",\n \"noComments\": \"Zatím žádné komentáře. Vyberte text a kliknutím na Komentář přidejte nový.\",\n \"commentPlaceholder\": \"Sem napište svůj komentář...\",\n \"save\": \"Uložit\",\n \"cancel\": \"Zrušit\",\n \"edit\": \"Upravit\",\n \"annotateComments\": \"Anotovat komentáře\",\n \"instructions\": \"Pokyny\",\n \"optional\": \"(volitelné)\",\n \"instructionsPlaceholder\": \"např. Zaměřte se na odbornou terminologii...\",\n \"annotate\": \"Anotovat\",\n \"annotating\": \"Anotování...\",\n \"toneLabel\": \"Tón\",\n \"toneOptional\": \"(volitelné)\",\n \"toneScholarly\": \"Akademický\",\n \"toneExplanatory\": \"Vysvětlující\",\n \"toneConversational\": \"Konverzační\",\n \"toneTechnical\": \"Technický\",\n \"densityLabel\": \"Hustota\",\n \"densitySparse\": \"Řídká\",\n \"densityDense\": \"Hustá\",\n \"fragmentSelected\": \"Fragment vybrán\",\n \"imageRegionSelected\": \"Oblast obrázku vybrána\",\n \"closeProgress\": \"Zavřít\"\n },\n \"HighlightPanel\": {\n \"title\": \"Zvýraznění\",\n \"noHighlights\": \"Zatím žádná zvýraznění. Použijte AI anotaci pro nalezení důležitých pasáží.\",\n \"annotateHighlights\": \"Anotovat zvýraznění\",\n \"instructions\": \"Pokyny\",\n \"optional\": \"(volitelné)\",\n \"instructionsPlaceholder\": \"např. Zaměřte se na klíčové technické koncepty...\",\n \"annotate\": \"Anotovat\",\n \"annotating\": \"Anotování...\",\n \"cancel\": \"Zrušit\",\n \"densityLabel\": \"Hustota\",\n \"densitySparse\": \"Řídká\",\n \"densityDense\": \"Hustá\",\n \"closeProgress\": \"Zavřít\"\n },\n \"AssessmentPanel\": {\n \"title\": \"Hodnocení\",\n \"noAssessments\": \"Zatím žádná hodnocení. Použijte AI anotaci pro vyhodnocení pasáží.\",\n \"assessmentPlaceholder\": \"Sem napište své hodnocení...\",\n \"save\": \"Uložit\",\n \"cancel\": \"Zrušit\",\n \"annotateAssessments\": \"Anotovat hodnocení\",\n \"instructions\": \"Pokyny\",\n \"optional\": \"(volitelné)\",\n \"instructionsPlaceholder\": \"např. Vyhodnoťte tvrzení z hlediska přesnosti a důkazů...\",\n \"annotate\": \"Anotovat\",\n \"annotating\": \"Anotování...\",\n \"toneLabel\": \"Tón\",\n \"toneOptional\": \"(volitelné)\",\n \"toneAnalytical\": \"Analytický\",\n \"toneCritical\": \"Kritický\",\n \"toneBalanced\": \"Vyvážený\",\n \"toneConstructive\": \"Konstruktivní\",\n \"densityLabel\": \"Hustota\",\n \"densitySparse\": \"Řídká\",\n \"densityDense\": \"Hustá\",\n \"fragmentSelected\": \"Fragment vybrán\",\n \"imageRegionSelected\": \"Oblast obrázku vybrána\",\n \"closeProgress\": \"Zavřít\"\n },\n \"TaggingPanel\": {\n \"title\": \"Štítky\",\n \"noTags\": \"Zatím žádné štítky. Použijte AI anotaci pro identifikaci strukturálních rolí.\",\n \"annotateTags\": \"Anotovat štítky\",\n \"selectSchema\": \"Vybrat rámec\",\n \"schemaLegal\": \"Právní analýza (IRAC)\",\n \"schemaScientific\": \"Vědecký článek (IMRAD)\",\n \"schemaArgument\": \"Struktura argumentace (Toulmin)\",\n \"selectCategories\": \"Vybrat kategorie\",\n \"categoryIssue\": \"Otázka\",\n \"categoryRule\": \"Pravidlo\",\n \"categoryApplication\": \"Aplikace\",\n \"categoryConclusion\": \"Závěr\",\n \"categoryIntroduction\": \"Úvod\",\n \"categoryMethods\": \"Metody\",\n \"categoryResults\": \"Výsledky\",\n \"categoryDiscussion\": \"Diskuze\",\n \"categoryClaim\": \"Tvrzení\",\n \"categoryEvidence\": \"Důkaz\",\n \"categoryWarrant\": \"Odůvodnění\",\n \"categoryCounterargument\": \"Protiargument\",\n \"categoryRebuttal\": \"Vyvrácení\",\n \"annotate\": \"Anotovat\",\n \"annotating\": \"Anotování...\",\n \"cancel\": \"Zrušit\",\n \"selectAll\": \"Vybrat vše\",\n \"deselectAll\": \"Zrušit výběr\",\n \"categoriesSelected\": \"{count, plural, =0 {Žádné kategorie nevybrány} =1 {1 kategorie vybrána} other {# kategorií vybráno}}\",\n \"createTagForSelection\": \"Vytvořit štítek pro výběr\",\n \"selectCategory\": \"Vybrat kategorii\",\n \"chooseCategory\": \"Zvolte kategorii...\",\n \"fragmentSelected\": \"Fragment vybrán\",\n \"imageRegionSelected\": \"Oblast obrázku vybrána\"\n },\n \"UnifiedAnnotationsPanel\": {\n \"title\": \"Anotace\",\n \"statistics\": \"Statistiky\",\n \"highlight\": \"Zvýraznění\",\n \"reference\": \"Reference\",\n \"assessment\": \"Hodnocení\",\n \"comment\": \"Komentáře\",\n \"tag\": \"Štítky\"\n },\n \"StatisticsPanel\": {\n \"title\": \"Statistiky\",\n \"highlights\": \"Zvýraznění\",\n \"comments\": \"Komentáře\",\n \"assessments\": \"Hodnocení\",\n \"tags\": \"Štítky\",\n \"references\": \"Reference\",\n \"stub\": \"Neúplné\",\n \"resolved\": \"Vyřešené\",\n \"entityTypes\": \"Typy entit\"\n },\n \"ReferencesPanel\": {\n \"title\": \"Reference\",\n \"noReferences\": \"Zatím žádné reference. Vyberte text pro vytvoření referencí na jiné zdroje.\",\n \"outgoingReferences\": \"Odchozí reference\",\n \"incomingReferences\": \"Příchozí reference\",\n \"noIncomingReferences\": \"Žádné příchozí reference\",\n \"stub\": \"Neúplná reference (nepropojená)\",\n \"resolved\": \"Vyřešená reference (propojená)\",\n \"open\": \"Otevřít\",\n \"unlink\": \"Odpojit\",\n \"resolve\": \"Vyřešit referenci\",\n \"cancel\": \"Zrušit\",\n \"createReference\": \"Vytvořit referenci\",\n \"entityTypesOptional\": \"Typy entit (volitelné)\",\n \"fragmentSelected\": \"Fragment vybrán\",\n \"imageRegionSelected\": \"Oblast obrázku vybrána\",\n \"annotateReferences\": \"Anotovat reference\",\n \"selectEntityTypes\": \"Typy entit:\",\n \"select\": \"Vybrat\",\n \"deselect\": \"Zrušit výběr\",\n \"noEntityTypes\": \"Žádné typy entit nejsou k dispozici\",\n \"typesSelected\": \"{count, plural, =1 {1 typ vybrán} other {# typů vybráno}}\",\n \"annotate\": \"Anotovat\",\n \"annotating\": \"Anotování...\",\n \"includeDescriptiveReferences\": \"Zahrnout popisné reference\",\n \"descriptiveReferencesTooltip\": \"Najít také fráze jako 'generální ředitel', 'technologický gigant', 'fyzik' (kromě jmen)\",\n \"annotationProgressTitle\": \"Anotování referencí entit\",\n \"cancelAnnotation\": \"Zrušit anotaci\",\n \"found\": \"{{count}} nalezeno\",\n \"complete\": \"Anotace dokončena!\",\n \"failed\": \"Anotace selhala\",\n \"current\": \"Aktuální: {{entityType}}\",\n \"closeProgress\": \"Zavřít\",\n \"loading\": \"načítání...\",\n \"loadingEllipsis\": \"Načítání...\",\n \"untitledResource\": \"Zdroj bez názvu\",\n \"noText\": \"Žádný text\"\n },\n \"KeyboardShortcuts\": {\n \"title\": \"Klávesové zkratky\",\n \"closeDialog\": \"Zavřít dialog\",\n \"or\": \"nebo\",\n \"navigationTitle\": \"Navigace\",\n \"navOpenSearch\": \"Otevřít globální vyhledávání\",\n \"navOpenSearchAlt\": \"Otevřít globální vyhledávání (alternativní)\",\n \"navCreateResource\": \"Vytvořit nový zdroj\",\n \"navCloseOverlays\": \"Zavřít všechny překryvné panely (dvojité stisknutí)\",\n \"navShowHelp\": \"Zobrazit nápovědu klávesových zkratek\",\n \"sidebarTitle\": \"Postranní panel znalostí\",\n \"sidebarCollapse\": \"Sbalit postranní panel\",\n \"sidebarExpand\": \"Rozbalit postranní panel\",\n \"sidebarPickup\": \"Uchopit kartu zdroje (při zaměření)\",\n \"sidebarMove\": \"Přesunout kartu zdroje (při přetahování)\",\n \"sidebarDrop\": \"Upustit kartu zdroje (při přetahování)\",\n \"sidebarCancel\": \"Zrušit operaci přetahování\",\n \"annotationsTitle\": \"Anotace zdroje\",\n \"annotHighlight\": \"Vytvořit zvýraznění z anotace (přímo)\",\n \"annotReference\": \"Otevřít vyskakovací okno reference pro anotaci\",\n \"annotDelete\": \"Smazat zaměřenou anotaci\",\n \"annotNavigate\": \"Procházet anotace\",\n \"annotNavigateBack\": \"Procházet anotace zpětně\",\n \"listsTitle\": \"Seznamy a mřížky\",\n \"listsFilterNav\": \"Navigace ve filtrech typů entit\",\n \"listsGridNav\": \"Navigace v mřížce zdrojů\",\n \"listsJumpFirst\": \"Přeskočit na první položku\",\n \"listsJumpLast\": \"Přeskočit na poslední položku\",\n \"searchModalTitle\": \"V okně vyhledávání\",\n \"searchNav\": \"Procházet výsledky vyhledávání\",\n \"searchSelect\": \"Vybrat výsledek\",\n \"searchClose\": \"Zavřít vyhledávání\",\n \"modalTitle\": \"Ovládání modálních oken\",\n \"modalClose\": \"Zavřít aktivní modální okno\",\n \"modalNavForward\": \"Navigace vpřed přes tlačítka\",\n \"modalNavBackward\": \"Navigace zpět přes tlačítka\",\n \"modalActivate\": \"Aktivovat zaměřené tlačítko\",\n \"accessibilityTitle\": \"Přístupnost\",\n \"a11ySkipLinks\": \"Přejít na přeskočovací odkazy (na začátku stránky)\",\n \"a11yFollowLink\": \"Následovat přeskočovací odkaz\",\n \"macNote\": \"Používáte klávesové zkratky pro Mac. ⌘ je klávesa Command.\",\n \"windowsNote\": \"Používáte klávesové zkratky pro Windows/Linux. Ctrl je klávesa Control.\",\n \"footerHint\": \"Stiskněte {{key}} kdykoli pro zobrazení této nápovědy\",\n \"close\": \"Zavřít\"\n },\n \"AnnotateToolbar\": {\n \"modeGroup\": \"Režim\",\n \"browse\": \"Procházet\",\n \"annotate\": \"Anotovat\",\n \"selectionGroup\": \"Motivace\",\n \"clickGroup\": \"Kliknutí\",\n \"shapeGroup\": \"Tvar\",\n \"none\": \"Žádný\",\n \"linking\": \"Reference\",\n \"highlighting\": \"Zvýraznění\",\n \"assessing\": \"Hodnocení\",\n \"commenting\": \"Komentář\",\n \"tagging\": \"Štítek\",\n \"detail\": \"Detail\",\n \"follow\": \"Sledovat\",\n \"deleting\": \"Smazat\",\n \"jsonld\": \"JSON-LD\",\n \"rectangle\": \"Obdélník\",\n \"circle\": \"Kruh\",\n \"polygon\": \"Polygon\"\n },\n \"CollapsibleResourceNavigation\": {\n \"title\": \"Navigace\",\n \"collapseSidebar\": \"Sbalit postranní panel\",\n \"expandSidebar\": \"Rozbalit postranní panel\",\n \"dragToReorder\": \"Přetažením změnit pořadí\",\n \"dragToReorderDoc\": \"Přetažením změnit pořadí {{name}}\",\n \"closeResource\": \"Zavřít zdroj\",\n \"dragInstructions\": \"Pro změnu pořadí zdrojů: Použijte Tab pro přechod na zdroj. Stiskněte Alt+šipka nahoru pro posun nahoru nebo Alt+šipka dolů pro posun dolů. Pro přetažení: Stiskněte mezerník pro uchopení položky. Použijte šipky k jejímu přesunutí. Stiskněte mezerník znovu pro upuštění.\"\n },\n \"ResourceViewer\": {\n \"deleteConfirmationTitle\": \"Smazat anotaci\",\n \"deleteConfirmationMessage\": \"Opravdu chcete smazat tuto anotaci? Tuto akci nelze vrátit zpět.\",\n \"deleteConfirmationCancel\": \"Zrušit\",\n \"deleteConfirmationDelete\": \"Smazat\"\n },\n \"Settings\": {\n \"title\": \"Nastavení\",\n \"lineNumbers\": \"Čísla řádků\",\n \"lineNumbersVisible\": \"Viditelná\",\n \"lineNumbersHidden\": \"Skrytá\",\n \"theme\": \"Motiv\",\n \"themeLight\": \"Světlý\",\n \"themeDark\": \"Tmavý\",\n \"themeSystem\": \"Systémový\",\n \"themeSystemActive\": \"Systémový ({{mode}})\",\n \"themeModeActive\": \"Používá se režim {{mode}}\",\n \"language\": \"Jazyk\",\n \"languageHint\": \"Změňte jazyk v hlavní navigaci\",\n \"languageChanging\": \"Změna jazyka...\",\n \"hoverDelay\": \"Zpoždění při najetí\",\n \"hoverDelayFast\": \"Rychlé\",\n \"hoverDelaySlow\": \"Pomalé\",\n \"hoverDelayDescription\": \"{{delay}}ms zpoždění před zobrazením efektů při najetí\"\n },\n \"AnnotateView\": {},\n \"ReferenceWizard\": {\n \"gatherTitle\": \"Shromážděný kontext\",\n \"configureGenerationTitle\": \"Konfigurovat generování\",\n \"configureSearchTitle\": \"Konfigurovat hledání\",\n \"searchResultsTitle\": \"Výsledky hledání\",\n \"sourceContextLabel\": \"Kontext anotace v prostředku\",\n \"connectionsLabel\": \"Partnerské anotace\",\n \"citedByLabel\": \"Prostředek citován\",\n \"userHintLabel\": \"Nápověda\",\n \"userHintPlaceholder\": \"Popište, na co se tato anotace vztahuje...\",\n \"loadingContext\": \"Shromažďování kontextu...\",\n \"failedContext\": \"Nepodařilo se shromáždit kontext\",\n \"cancel\": \"Zrušit\",\n \"generate\": \"Generovat\",\n \"compose\": \"Sestavit\",\n \"resolutionStrategyLabel\": \"Strategie řešení\",\n \"back\": \"Zpět\",\n \"link\": \"Odkaz\",\n \"score\": \"Skóre\",\n \"noResults\": \"Žádné výsledky nenalezeny\",\n \"resourceTitle\": \"Název zdroje\",\n \"resourceTitlePlaceholder\": \"Zadejte název zdroje...\",\n \"additionalInstructions\": \"Další pokyny\",\n \"additionalInstructionsPlaceholder\": \"Zadejte další pokyny...\",\n \"language\": \"Jazyk\",\n \"languageHelp\": \"Jazyk generovaného obsahu\",\n \"creativity\": \"Kreativita\",\n \"creativityFocused\": \"Zaměřená\",\n \"creativityCreative\": \"Kreativní\",\n \"maxLength\": \"Maximální délka\",\n \"maxLengthHelp\": \"Maximální počet tokenů\",\n \"maxResults\": \"Maximální počet výsledků\",\n \"semanticScoring\": \"Sémantické hodnocení\",\n \"semanticScoringHelp\": \"Použít AI k hodnocení výsledků podle sémantické relevance\",\n \"searching\": \"Vyhledávání...\",\n \"search\": \"Hledat\"\n },\n \"History\": {\n \"embeddingComputed\": \"Embedding vypočten\"\n }\n}\n"],"mappings":"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","names":[]}
@@ -31,7 +31,8 @@ var ResourceInfoPanel = {
31
31
  creationMethod: "Oprettelsesmetode",
32
32
  attributedTo: "Tilskrevet",
33
33
  derivedFrom: "Afledt af",
34
- generatedBy: "Genereret af"
34
+ generatedBy: "Genereret af",
35
+ storageUri: "Lagring"
35
36
  };
36
37
  var CollaborationPanel = {
37
38
  title: "Samarbejde",
@@ -377,6 +378,9 @@ var ReferenceWizard = {
377
378
  searching: "S\xF8ger...",
378
379
  search: "S\xF8g"
379
380
  };
381
+ var History = {
382
+ embeddingComputed: "Embedding beregnet"
383
+ };
380
384
  var da_default = {
381
385
  Toolbar,
382
386
  ResourceInfoPanel,
@@ -395,7 +399,8 @@ var da_default = {
395
399
  ResourceViewer,
396
400
  Settings,
397
401
  AnnotateView,
398
- ReferenceWizard
402
+ ReferenceWizard,
403
+ History
399
404
  };
400
405
  export {
401
406
  AnnotateToolbar,
@@ -406,6 +411,7 @@ export {
406
411
  CollapsibleResourceNavigation,
407
412
  CommentsPanel,
408
413
  HighlightPanel,
414
+ History,
409
415
  KeyboardShortcuts,
410
416
  ReferenceWizard,
411
417
  ReferencesPanel,
@@ -418,4 +424,4 @@ export {
418
424
  UnifiedAnnotationsPanel,
419
425
  da_default as default
420
426
  };
421
- //# sourceMappingURL=da-JWYEUYPX.mjs.map
427
+ //# sourceMappingURL=da-MZKIECVT.mjs.map