@semiont/react-ui 0.4.13 → 0.4.15

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 (52) hide show
  1. package/README.md +18 -12
  2. package/dist/KnowledgeBaseSessionContext-CpYaCbnC.d.mts +174 -0
  3. package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs → PdfAnnotationCanvas.client-CHDCGQBR.mjs} +3 -3
  4. package/dist/{chunk-HNZOXH4L.mjs → chunk-OZICDVH7.mjs} +5 -3
  5. package/dist/chunk-OZICDVH7.mjs.map +1 -0
  6. package/dist/chunk-R2U7P4TK.mjs +865 -0
  7. package/dist/chunk-R2U7P4TK.mjs.map +1 -0
  8. package/dist/{chunk-BQJWOK4C.mjs → chunk-VN5NY4SN.mjs} +9 -8
  9. package/dist/chunk-VN5NY4SN.mjs.map +1 -0
  10. package/dist/index.d.mts +147 -171
  11. package/dist/index.mjs +2215 -1961
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/test-utils.d.mts +13 -62
  14. package/dist/test-utils.mjs +40 -21
  15. package/dist/test-utils.mjs.map +1 -1
  16. package/package.json +5 -3
  17. package/src/components/ProtectedErrorBoundary.tsx +95 -0
  18. package/src/components/Toolbar.tsx +13 -13
  19. package/src/components/__tests__/ProtectedErrorBoundary.test.tsx +197 -0
  20. package/src/components/modals/PermissionDeniedModal.tsx +140 -0
  21. package/src/components/modals/ReferenceWizardModal.tsx +3 -2
  22. package/src/components/modals/SessionExpiredModal.tsx +101 -0
  23. package/src/components/modals/__tests__/PermissionDeniedModal.test.tsx +150 -0
  24. package/src/components/modals/__tests__/SessionExpiredModal.test.tsx +115 -0
  25. package/src/components/resource/AnnotationHistory.tsx +5 -6
  26. package/src/components/resource/HistoryEvent.tsx +7 -7
  27. package/src/components/resource/__tests__/AnnotationHistory.test.tsx +33 -34
  28. package/src/components/resource/__tests__/HistoryEvent.test.tsx +17 -19
  29. package/src/components/resource/__tests__/event-formatting.test.ts +70 -94
  30. package/src/components/resource/event-formatting.ts +56 -56
  31. package/src/components/resource/panels/CollaborationPanel.tsx +9 -1
  32. package/src/components/resource/panels/ReferenceEntry.tsx +7 -5
  33. package/src/components/resource/panels/ResourceInfoPanel.tsx +8 -6
  34. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +12 -12
  35. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +1 -0
  36. package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +1 -1
  37. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +4 -4
  38. package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +5 -10
  39. package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +23 -54
  40. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +6 -6
  41. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +7 -19
  42. package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +1 -1
  43. package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +18 -44
  44. package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +6 -6
  45. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +31 -26
  46. package/src/styles/patterns/panels-base.css +12 -0
  47. package/dist/TranslationManager-CudgH3gw.d.mts +0 -107
  48. package/dist/chunk-BQJWOK4C.mjs.map +0 -1
  49. package/dist/chunk-HNZOXH4L.mjs.map +0 -1
  50. package/dist/chunk-OL5UST25.mjs +0 -413
  51. package/dist/chunk-OL5UST25.mjs.map +0 -1
  52. /package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs.map → PdfAnnotationCanvas.client-CHDCGQBR.mjs.map} +0 -0
@@ -1,413 +0,0 @@
1
- 'use client';
2
- import {
3
- en_default
4
- } from "./chunk-HVMAGUFA.mjs";
5
- import {
6
- __glob
7
- } from "./chunk-D4GAAQMM.mjs";
8
-
9
- // src/contexts/SessionContext.tsx
10
- import { createContext, useContext } from "react";
11
- import { jsx } from "react/jsx-runtime";
12
- var SessionContext = createContext(null);
13
- function SessionProvider({
14
- sessionManager,
15
- children
16
- }) {
17
- return /* @__PURE__ */ jsx(SessionContext.Provider, { value: sessionManager, children });
18
- }
19
- function useSessionContext() {
20
- const context = useContext(SessionContext);
21
- if (!context) {
22
- throw new Error("useSessionContext must be used within SessionProvider");
23
- }
24
- return context;
25
- }
26
-
27
- // src/components/Toast.tsx
28
- import React, { useEffect, useState } from "react";
29
- import { createPortal } from "react-dom";
30
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
31
- var icons = {
32
- success: /* @__PURE__ */ jsx2("svg", { className: "semiont-toast-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
33
- error: /* @__PURE__ */ jsx2("svg", { className: "semiont-toast-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }),
34
- warning: /* @__PURE__ */ jsx2("svg", { className: "semiont-toast-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("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" }) }),
35
- info: /* @__PURE__ */ jsx2("svg", { className: "semiont-toast-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("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" }) })
36
- };
37
- function Toast({ toast, onClose }) {
38
- useEffect(() => {
39
- const timer = setTimeout(() => {
40
- onClose(toast.id);
41
- }, toast.duration || 3e3);
42
- return () => clearTimeout(timer);
43
- }, [toast, onClose]);
44
- return /* @__PURE__ */ jsxs(
45
- "div",
46
- {
47
- className: "semiont-toast",
48
- "data-variant": toast.type,
49
- role: "alert",
50
- children: [
51
- /* @__PURE__ */ jsx2("div", { className: "semiont-toast-icon-wrapper", children: icons[toast.type] }),
52
- /* @__PURE__ */ jsx2("p", { className: "semiont-toast-message", children: toast.message }),
53
- /* @__PURE__ */ jsx2(
54
- "button",
55
- {
56
- onClick: () => onClose(toast.id),
57
- className: "semiont-toast-close",
58
- "aria-label": "Close",
59
- children: /* @__PURE__ */ jsx2("svg", { className: "semiont-toast-close-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx2("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
60
- }
61
- )
62
- ]
63
- }
64
- );
65
- }
66
- function ToastContainer({ toasts, onClose }) {
67
- const [mounted, setMounted] = useState(false);
68
- useEffect(() => {
69
- setMounted(true);
70
- return () => setMounted(false);
71
- }, []);
72
- if (!mounted) return null;
73
- return createPortal(
74
- /* @__PURE__ */ jsx2("div", { className: "semiont-toast-container", children: toasts.map((toast) => /* @__PURE__ */ jsx2(Toast, { toast, onClose }, toast.id)) }),
75
- document.body
76
- );
77
- }
78
- var ToastContext = React.createContext(void 0);
79
- function ToastProvider({ children }) {
80
- const [toasts, setToasts] = useState([]);
81
- const showToast = React.useCallback((message, type = "info", duration) => {
82
- const id = Date.now().toString();
83
- const newToast = duration !== void 0 ? { id, message, type, duration } : { id, message, type };
84
- setToasts((prev) => [...prev, newToast]);
85
- }, []);
86
- const showSuccess = React.useCallback((message, duration) => showToast(message, "success", duration), [showToast]);
87
- const showError = React.useCallback((message, duration) => showToast(message, "error", duration), [showToast]);
88
- const showWarning = React.useCallback((message, duration) => showToast(message, "warning", duration), [showToast]);
89
- const showInfo = React.useCallback((message, duration) => showToast(message, "info", duration), [showToast]);
90
- const handleClose = React.useCallback((id) => {
91
- setToasts((prev) => prev.filter((toast) => toast.id !== id));
92
- }, []);
93
- const contextValue = React.useMemo(
94
- () => ({ showToast, showSuccess, showError, showWarning, showInfo }),
95
- [showToast, showSuccess, showError, showWarning, showInfo]
96
- );
97
- return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: contextValue, children: [
98
- children,
99
- /* @__PURE__ */ jsx2(ToastContainer, { toasts, onClose: handleClose })
100
- ] });
101
- }
102
- function useToast() {
103
- const context = React.useContext(ToastContext);
104
- if (context === void 0) {
105
- throw new Error("useToast must be used within a ToastProvider");
106
- }
107
- return context;
108
- }
109
-
110
- // src/contexts/OpenResourcesContext.tsx
111
- import { createContext as createContext2, useContext as useContext2 } from "react";
112
- import { jsx as jsx3 } from "react/jsx-runtime";
113
- var OpenResourcesContext = createContext2(void 0);
114
- function OpenResourcesProvider({
115
- openResourcesManager,
116
- children
117
- }) {
118
- return /* @__PURE__ */ jsx3(OpenResourcesContext.Provider, { value: openResourcesManager, children });
119
- }
120
- function useOpenResources() {
121
- const context = useContext2(OpenResourcesContext);
122
- if (context === void 0) {
123
- throw new Error("useOpenResources must be used within an OpenResourcesProvider");
124
- }
125
- return context;
126
- }
127
-
128
- // src/contexts/TranslationContext.tsx
129
- import { createContext as createContext3, useContext as useContext3, useState as useState2, useEffect as useEffect2, useMemo } from "react";
130
- import { Fragment, jsx as jsx4 } from "react/jsx-runtime";
131
-
132
- // import("../../translations/**/*.json") in src/contexts/TranslationContext.tsx
133
- var globImport_translations_json = __glob({
134
- "../../translations/ar.json": () => import("./ar-R4CRNXEF.mjs"),
135
- "../../translations/bn.json": () => import("./bn-CZKGRHTA.mjs"),
136
- "../../translations/cs.json": () => import("./cs-4WIB2IHH.mjs"),
137
- "../../translations/da.json": () => import("./da-JWYEUYPX.mjs"),
138
- "../../translations/de.json": () => import("./de-GWUQZGER.mjs"),
139
- "../../translations/el.json": () => import("./el-DM2GT7P5.mjs"),
140
- "../../translations/en.json": () => import("./en-IUV4ZXKH.mjs"),
141
- "../../translations/es.json": () => import("./es-6LVQIM3D.mjs"),
142
- "../../translations/fa.json": () => import("./fa-IRUJY3QI.mjs"),
143
- "../../translations/fi.json": () => import("./fi-53FBOEVT.mjs"),
144
- "../../translations/fr.json": () => import("./fr-Q5KY7QL6.mjs"),
145
- "../../translations/he.json": () => import("./he-HJNKULBY.mjs"),
146
- "../../translations/hi.json": () => import("./hi-UYZ4X6CR.mjs"),
147
- "../../translations/id.json": () => import("./id-UAQMH6U2.mjs"),
148
- "../../translations/it.json": () => import("./it-C7QEBNFA.mjs"),
149
- "../../translations/ja.json": () => import("./ja-THS6AOSJ.mjs"),
150
- "../../translations/ko.json": () => import("./ko-XKK3TWQG.mjs"),
151
- "../../translations/ms.json": () => import("./ms-GSK7LIF7.mjs"),
152
- "../../translations/nl.json": () => import("./nl-KUBWITGY.mjs"),
153
- "../../translations/no.json": () => import("./no-ECWZUHT6.mjs"),
154
- "../../translations/pl.json": () => import("./pl-PLVWSZWS.mjs"),
155
- "../../translations/pt.json": () => import("./pt-AL74ZTKB.mjs"),
156
- "../../translations/ro.json": () => import("./ro-WTPHLHGS.mjs"),
157
- "../../translations/sv.json": () => import("./sv-QCLI7SG4.mjs"),
158
- "../../translations/th.json": () => import("./th-WCKVZU6U.mjs"),
159
- "../../translations/tr.json": () => import("./tr-2CAFS2XS.mjs"),
160
- "../../translations/uk.json": () => import("./uk-TDE4JLCY.mjs"),
161
- "../../translations/vi.json": () => import("./vi-KKXZ4PCX.mjs"),
162
- "../../translations/zh.json": () => import("./zh-VH4XN5PV.mjs")
163
- });
164
-
165
- // src/contexts/TranslationContext.tsx
166
- var TranslationContext = createContext3(null);
167
- var translationCache = /* @__PURE__ */ new Map();
168
- function processPluralFormat(text, params) {
169
- const pluralMatch = text.match(/\{(\w+),\s*plural,\s*/);
170
- if (!pluralMatch) {
171
- return text;
172
- }
173
- const paramName = pluralMatch[1];
174
- const count = params[paramName];
175
- if (count === void 0) {
176
- return text;
177
- }
178
- let startPos = pluralMatch[0].length;
179
- let braceCount = 1;
180
- let endPos = startPos;
181
- for (let i = startPos; i < text.length; i++) {
182
- if (text[i] === "{") braceCount++;
183
- else if (text[i] === "}") {
184
- braceCount--;
185
- if (braceCount === 0) {
186
- endPos = i;
187
- break;
188
- }
189
- }
190
- }
191
- const pluralCases = text.substring(startPos, endPos);
192
- const cases = {};
193
- const caseRegex = /(?:=(\d+)|(\w+))\s*\{([^}]+)\}/g;
194
- let caseMatch;
195
- while ((caseMatch = caseRegex.exec(pluralCases)) !== null) {
196
- const [, exactNumber, keyword, textContent] = caseMatch;
197
- const key = exactNumber !== void 0 ? `=${exactNumber}` : keyword;
198
- cases[key] = textContent;
199
- }
200
- const exactMatch = cases[`=${count}`];
201
- if (exactMatch !== void 0) {
202
- const result = exactMatch.replace(/#/g, String(count));
203
- return text.substring(0, pluralMatch.index) + result + text.substring(endPos + 1);
204
- }
205
- const otherCase = cases["other"];
206
- if (otherCase !== void 0) {
207
- const result = otherCase.replace(/#/g, String(count));
208
- return text.substring(0, pluralMatch.index) + result + text.substring(endPos + 1);
209
- }
210
- return text;
211
- }
212
- var AVAILABLE_LOCALES = [
213
- "ar",
214
- // Arabic
215
- "bn",
216
- // Bengali
217
- "cs",
218
- // Czech
219
- "da",
220
- // Danish
221
- "de",
222
- // German
223
- "el",
224
- // Greek
225
- "en",
226
- // English
227
- "es",
228
- // Spanish
229
- "fa",
230
- // Persian/Farsi
231
- "fi",
232
- // Finnish
233
- "fr",
234
- // French
235
- "he",
236
- // Hebrew
237
- "hi",
238
- // Hindi
239
- "id",
240
- // Indonesian
241
- "it",
242
- // Italian
243
- "ja",
244
- // Japanese
245
- "ko",
246
- // Korean
247
- "ms",
248
- // Malay
249
- "nl",
250
- // Dutch
251
- "no",
252
- // Norwegian
253
- "pl",
254
- // Polish
255
- "pt",
256
- // Portuguese
257
- "ro",
258
- // Romanian
259
- "sv",
260
- // Swedish
261
- "th",
262
- // Thai
263
- "tr",
264
- // Turkish
265
- "uk",
266
- // Ukrainian
267
- "vi",
268
- // Vietnamese
269
- "zh"
270
- // Chinese
271
- ];
272
- async function loadTranslations(locale) {
273
- if (translationCache.has(locale)) {
274
- return translationCache.get(locale);
275
- }
276
- if (locale === "en") {
277
- translationCache.set("en", en_default);
278
- return en_default;
279
- }
280
- try {
281
- const translations = await globImport_translations_json(`../../translations/${locale}.json`);
282
- const translationData = translations.default || translations;
283
- translationCache.set(locale, translationData);
284
- return translationData;
285
- } catch (error) {
286
- console.error(`Failed to load translations for locale: ${locale}`, error);
287
- return en_default;
288
- }
289
- }
290
- var defaultTranslationManager = {
291
- t: (namespace, key, params) => {
292
- const translations = en_default;
293
- const translation = translations[namespace]?.[key];
294
- if (!translation) {
295
- console.warn(`Translation not found for ${namespace}.${key}`);
296
- return `${namespace}.${key}`;
297
- }
298
- if (params && typeof translation === "string") {
299
- let result = translation;
300
- result = processPluralFormat(result, params);
301
- Object.entries(params).forEach(([paramKey, paramValue]) => {
302
- result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
303
- });
304
- return result;
305
- }
306
- return translation;
307
- }
308
- };
309
- function TranslationProvider({
310
- translationManager,
311
- locale,
312
- loadingComponent = null,
313
- children
314
- }) {
315
- const [loadedTranslations, setLoadedTranslations] = useState2(null);
316
- const [isLoading, setIsLoading] = useState2(false);
317
- useEffect2(() => {
318
- if (locale && !translationManager) {
319
- setIsLoading(true);
320
- loadTranslations(locale).then((translations) => {
321
- setLoadedTranslations(translations);
322
- setIsLoading(false);
323
- }).catch((error) => {
324
- console.error("Failed to load translations:", error);
325
- setLoadedTranslations(en_default);
326
- setIsLoading(false);
327
- });
328
- }
329
- }, [locale, translationManager]);
330
- const localeManager = useMemo(() => {
331
- if (!loadedTranslations) return null;
332
- return {
333
- t: (namespace, key, params) => {
334
- const translation = loadedTranslations[namespace]?.[key];
335
- if (!translation) {
336
- console.warn(`Translation not found for ${namespace}.${key} in locale ${locale}`);
337
- return `${namespace}.${key}`;
338
- }
339
- if (params && typeof translation === "string") {
340
- let result = translation;
341
- result = processPluralFormat(result, params);
342
- Object.entries(params).forEach(([paramKey, paramValue]) => {
343
- result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
344
- });
345
- return result;
346
- }
347
- return translation;
348
- }
349
- };
350
- }, [loadedTranslations, locale]);
351
- if (translationManager) {
352
- return /* @__PURE__ */ jsx4(TranslationContext.Provider, { value: translationManager, children });
353
- }
354
- if (locale && isLoading) {
355
- return /* @__PURE__ */ jsx4(Fragment, { children: loadingComponent });
356
- }
357
- if (locale && localeManager) {
358
- return /* @__PURE__ */ jsx4(TranslationContext.Provider, { value: localeManager, children });
359
- }
360
- return /* @__PURE__ */ jsx4(TranslationContext.Provider, { value: defaultTranslationManager, children });
361
- }
362
- function useTranslations(namespace) {
363
- const context = useContext3(TranslationContext);
364
- if (!context) {
365
- return (key, params) => {
366
- const translations = en_default;
367
- const translation = translations[namespace]?.[key];
368
- if (!translation) {
369
- console.warn(`Translation not found for ${namespace}.${key}`);
370
- return `${namespace}.${key}`;
371
- }
372
- if (params && typeof translation === "string") {
373
- let result = translation;
374
- result = processPluralFormat(result, params);
375
- Object.entries(params).forEach(([paramKey, paramValue]) => {
376
- result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
377
- });
378
- return result;
379
- }
380
- return translation;
381
- };
382
- }
383
- return (key, params) => context.t(namespace, key, params);
384
- }
385
- function usePreloadTranslations() {
386
- return {
387
- preload: async (locale) => {
388
- try {
389
- await loadTranslations(locale);
390
- return true;
391
- } catch (error) {
392
- console.error(`Failed to preload translations for ${locale}:`, error);
393
- return false;
394
- }
395
- },
396
- isLoaded: (locale) => translationCache.has(locale)
397
- };
398
- }
399
-
400
- export {
401
- SessionProvider,
402
- useSessionContext,
403
- ToastContainer,
404
- ToastProvider,
405
- useToast,
406
- OpenResourcesProvider,
407
- useOpenResources,
408
- AVAILABLE_LOCALES,
409
- TranslationProvider,
410
- useTranslations,
411
- usePreloadTranslations
412
- };
413
- //# sourceMappingURL=chunk-OL5UST25.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/contexts/SessionContext.tsx","../src/components/Toast.tsx","../src/contexts/OpenResourcesContext.tsx","../src/contexts/TranslationContext.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, ReactNode } from 'react';\nimport type { SessionManager } from '../types/SessionManager';\n\nconst SessionContext = createContext<SessionManager | null>(null);\n\n/**\n * Provider Pattern: Accepts SessionManager implementation as prop\n * and makes it available to child components via Context.\n *\n * Apps provide their own implementation (next-auth, custom auth, etc.)\n * and pass it to this provider at the root level.\n *\n * @example\n * ```tsx\n * // In app root\n * const sessionManager = useSessionManager(); // App's implementation\n *\n * <SessionProvider sessionManager={sessionManager}>\n * <App />\n * </SessionProvider>\n * ```\n */\nexport function SessionProvider({\n sessionManager,\n children\n}: {\n sessionManager: SessionManager;\n children: ReactNode;\n}) {\n return (\n <SessionContext.Provider value={sessionManager}>\n {children}\n </SessionContext.Provider>\n );\n}\n\n/**\n * Hook to access SessionManager from Context\n * Components use this hook to access session state and expiry information\n */\nexport function useSessionContext() {\n const context = useContext(SessionContext);\n if (!context) {\n throw new Error('useSessionContext must be used within SessionProvider');\n }\n return context;\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":["jsx","createContext","useContext","jsx","createContext","useContext","useState","useEffect","jsx","createContext","useState","useEffect","jsx","useContext"]}