@douglasneuroinformatics/libui 1.5.0 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-IP3LSCUG.js +129 -0
- package/dist/chunk-IP3LSCUG.js.map +1 -0
- package/dist/components/index.d.ts +1674 -347
- package/dist/components/index.js +3549 -31
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.d.ts +8 -1
- package/dist/hooks/index.js +26 -119
- package/dist/hooks/index.js.map +1 -1
- package/dist/i18n.js +105 -69
- package/dist/i18n.js.map +1 -1
- package/package.json +54 -40
- package/tailwind.config.cjs +2 -0
- package/dist/douglasneuroinformatics-libui-1.5.0.tgz +0 -0
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Promisable } from 'type-fest';
|
|
2
|
+
import * as react from 'react';
|
|
2
3
|
import { RefObject, useEffect, Dispatch, SetStateAction } from 'react';
|
|
3
4
|
import * as zustand from 'zustand';
|
|
4
5
|
|
|
@@ -19,6 +20,12 @@ declare function useInterval(callback: () => void, delay: null | number): void;
|
|
|
19
20
|
|
|
20
21
|
declare const useIsomorphicLayoutEffect: typeof useEffect;
|
|
21
22
|
|
|
23
|
+
/** @deprecated */
|
|
24
|
+
declare function useLegacyStepper(): {
|
|
25
|
+
index: number;
|
|
26
|
+
updateIndex: react.Dispatch<"decrement" | "increment">;
|
|
27
|
+
};
|
|
28
|
+
|
|
22
29
|
/**
|
|
23
30
|
* Get the result of an arbitrary CSS media query
|
|
24
31
|
*
|
|
@@ -107,4 +114,4 @@ type WindowSize = {
|
|
|
107
114
|
};
|
|
108
115
|
declare function useWindowSize(): WindowSize;
|
|
109
116
|
|
|
110
|
-
export { DEFAULT_THEME, type NotificationInterface, type NotificationsStore, SYS_DARK_MEDIA_QUERY, THEME_ATTRIBUTE, THEME_KEY, type Theme, type WindowSize, useDownload, useEventCallback, useEventListener, useInterval, useIsomorphicLayoutEffect, useMediaQuery, useNotificationsStore, useOnClickOutside, useSessionStorage, useTheme, useWindowSize };
|
|
117
|
+
export { DEFAULT_THEME, type NotificationInterface, type NotificationsStore, SYS_DARK_MEDIA_QUERY, THEME_ATTRIBUTE, THEME_KEY, type Theme, type WindowSize, useDownload, useEventCallback, useEventListener, useInterval, useIsomorphicLayoutEffect, useLegacyStepper, useMediaQuery, useNotificationsStore, useOnClickOutside, useSessionStorage, useTheme, useWindowSize };
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_THEME,
|
|
3
|
+
LegacyStepperContext,
|
|
4
|
+
SYS_DARK_MEDIA_QUERY,
|
|
5
|
+
THEME_ATTRIBUTE,
|
|
6
|
+
THEME_KEY,
|
|
7
|
+
useEventListener,
|
|
8
|
+
useIsomorphicLayoutEffect,
|
|
9
|
+
useNotificationsStore,
|
|
10
|
+
useTheme,
|
|
11
|
+
useWindowSize
|
|
12
|
+
} from "../chunk-IP3LSCUG.js";
|
|
1
13
|
import {
|
|
2
14
|
isBrowser
|
|
3
15
|
} from "../chunk-PAAJ5AH3.js";
|
|
4
16
|
|
|
5
17
|
// src/hooks/useDownload.ts
|
|
6
18
|
import { useEffect, useState } from "react";
|
|
7
|
-
|
|
8
|
-
// src/hooks/useNotificationsStore.ts
|
|
9
|
-
import { create } from "zustand";
|
|
10
|
-
var useNotificationsStore = create((set) => ({
|
|
11
|
-
addNotification: (notification) => {
|
|
12
|
-
set((state) => ({
|
|
13
|
-
notifications: [...state.notifications, { id: Date.now(), ...notification }]
|
|
14
|
-
}));
|
|
15
|
-
},
|
|
16
|
-
dismissNotification: (id) => {
|
|
17
|
-
set((state) => ({
|
|
18
|
-
notifications: state.notifications.filter((notification) => notification.id !== id)
|
|
19
|
-
}));
|
|
20
|
-
},
|
|
21
|
-
notifications: []
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
// src/hooks/useDownload.ts
|
|
25
19
|
function useDownload() {
|
|
26
20
|
const notifications = useNotificationsStore();
|
|
27
21
|
const [data, setData] = useState(null);
|
|
@@ -59,12 +53,6 @@ function useDownload() {
|
|
|
59
53
|
|
|
60
54
|
// src/hooks/useEventCallback.ts
|
|
61
55
|
import { useCallback, useRef } from "react";
|
|
62
|
-
|
|
63
|
-
// src/hooks/useIsomorphicLayoutEffect.ts
|
|
64
|
-
import { useEffect as useEffect2, useLayoutEffect } from "react";
|
|
65
|
-
var useIsomorphicLayoutEffect = isBrowser() ? useLayoutEffect : useEffect2;
|
|
66
|
-
|
|
67
|
-
// src/hooks/useEventCallback.ts
|
|
68
56
|
function useEventCallback(fn) {
|
|
69
57
|
const ref = useRef(() => {
|
|
70
58
|
throw new Error("Cannot call an event handler while rendering.");
|
|
@@ -75,33 +63,14 @@ function useEventCallback(fn) {
|
|
|
75
63
|
return useCallback((...args) => ref.current(...args), [ref]);
|
|
76
64
|
}
|
|
77
65
|
|
|
78
|
-
// src/hooks/useEventListener.ts
|
|
79
|
-
import { useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
80
|
-
function useEventListener(eventName, handler, element, options) {
|
|
81
|
-
const savedHandler = useRef2(handler);
|
|
82
|
-
useIsomorphicLayoutEffect(() => {
|
|
83
|
-
savedHandler.current = handler;
|
|
84
|
-
}, [handler]);
|
|
85
|
-
useEffect3(() => {
|
|
86
|
-
const targetElement = element?.current ?? window;
|
|
87
|
-
if (!(targetElement && targetElement.addEventListener))
|
|
88
|
-
return;
|
|
89
|
-
const listener = (event) => savedHandler.current(event);
|
|
90
|
-
targetElement.addEventListener(eventName, listener, options);
|
|
91
|
-
return () => {
|
|
92
|
-
targetElement.removeEventListener(eventName, listener, options);
|
|
93
|
-
};
|
|
94
|
-
}, [eventName, element, options]);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
66
|
// src/hooks/useInterval.ts
|
|
98
|
-
import { useEffect as
|
|
67
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
99
68
|
function useInterval(callback, delay) {
|
|
100
|
-
const savedCallback =
|
|
69
|
+
const savedCallback = useRef2(callback);
|
|
101
70
|
useIsomorphicLayoutEffect(() => {
|
|
102
71
|
savedCallback.current = callback;
|
|
103
72
|
}, [callback]);
|
|
104
|
-
|
|
73
|
+
useEffect2(() => {
|
|
105
74
|
if (!delay && delay !== 0) {
|
|
106
75
|
return;
|
|
107
76
|
}
|
|
@@ -110,8 +79,14 @@ function useInterval(callback, delay) {
|
|
|
110
79
|
}, [delay]);
|
|
111
80
|
}
|
|
112
81
|
|
|
82
|
+
// src/hooks/useLegacyStepper.ts
|
|
83
|
+
import { useContext } from "react";
|
|
84
|
+
function useLegacyStepper() {
|
|
85
|
+
return useContext(LegacyStepperContext);
|
|
86
|
+
}
|
|
87
|
+
|
|
113
88
|
// src/hooks/useMediaQuery.ts
|
|
114
|
-
import { useEffect as
|
|
89
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
115
90
|
function useMediaQuery(query) {
|
|
116
91
|
const getMatches = (query2) => {
|
|
117
92
|
if (isBrowser()) {
|
|
@@ -123,7 +98,7 @@ function useMediaQuery(query) {
|
|
|
123
98
|
function handleChange() {
|
|
124
99
|
setMatches(getMatches(query));
|
|
125
100
|
}
|
|
126
|
-
|
|
101
|
+
useEffect3(() => {
|
|
127
102
|
const matchMedia = window.matchMedia(query);
|
|
128
103
|
handleChange();
|
|
129
104
|
matchMedia.addEventListener("change", handleChange);
|
|
@@ -147,7 +122,7 @@ function useOnClickOutside(ref, handler, mouseEvent = "mousedown") {
|
|
|
147
122
|
}
|
|
148
123
|
|
|
149
124
|
// src/hooks/useSessionStorage.ts
|
|
150
|
-
import { useCallback as useCallback2, useEffect as
|
|
125
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useState as useState3 } from "react";
|
|
151
126
|
function useSessionStorage(key, initialValue, options = {}) {
|
|
152
127
|
const { initializeWithValue = true } = options;
|
|
153
128
|
const serializer = useCallback2(
|
|
@@ -206,7 +181,7 @@ function useSessionStorage(key, initialValue, options = {}) {
|
|
|
206
181
|
console.warn(`Error setting sessionStorage key \u201C${key}\u201D:`, error);
|
|
207
182
|
}
|
|
208
183
|
});
|
|
209
|
-
|
|
184
|
+
useEffect4(() => {
|
|
210
185
|
setStoredValue(readValue());
|
|
211
186
|
}, [key]);
|
|
212
187
|
const handleStorageChange = useCallback2(
|
|
@@ -222,75 +197,6 @@ function useSessionStorage(key, initialValue, options = {}) {
|
|
|
222
197
|
useEventListener("session-storage", handleStorageChange);
|
|
223
198
|
return [storedValue, setValue];
|
|
224
199
|
}
|
|
225
|
-
|
|
226
|
-
// src/hooks/useTheme.ts
|
|
227
|
-
import { useCallback as useCallback3, useEffect as useEffect7, useState as useState4 } from "react";
|
|
228
|
-
var DEFAULT_THEME = "light";
|
|
229
|
-
var THEME_ATTRIBUTE = "data-mode";
|
|
230
|
-
var THEME_KEY = "theme";
|
|
231
|
-
var SYS_DARK_MEDIA_QUERY = "(prefers-color-scheme: dark)";
|
|
232
|
-
function useTheme() {
|
|
233
|
-
const [theme, setTheme] = useState4(() => {
|
|
234
|
-
if (!isBrowser()) {
|
|
235
|
-
return DEFAULT_THEME;
|
|
236
|
-
}
|
|
237
|
-
const savedTheme = window.localStorage.getItem(THEME_KEY);
|
|
238
|
-
let initialTheme;
|
|
239
|
-
if (savedTheme === "dark" || savedTheme === "light") {
|
|
240
|
-
initialTheme = savedTheme;
|
|
241
|
-
} else {
|
|
242
|
-
initialTheme = window.matchMedia(SYS_DARK_MEDIA_QUERY).matches ? "dark" : "light";
|
|
243
|
-
}
|
|
244
|
-
document.documentElement.setAttribute(THEME_ATTRIBUTE, initialTheme);
|
|
245
|
-
return initialTheme;
|
|
246
|
-
});
|
|
247
|
-
useEffect7(() => {
|
|
248
|
-
const observer = new MutationObserver((mutations) => {
|
|
249
|
-
mutations.forEach((mutation) => {
|
|
250
|
-
if (mutation.attributeName === THEME_ATTRIBUTE) {
|
|
251
|
-
const updatedTheme = mutation.target.getAttribute(THEME_ATTRIBUTE);
|
|
252
|
-
if (updatedTheme === "light" || updatedTheme === "dark") {
|
|
253
|
-
window.localStorage.setItem(THEME_KEY, updatedTheme);
|
|
254
|
-
setTheme(updatedTheme);
|
|
255
|
-
} else {
|
|
256
|
-
console.error(`Unexpected value for 'data-mode' attribute: ${updatedTheme}`);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
observer.observe(document.documentElement, {
|
|
262
|
-
attributes: true
|
|
263
|
-
});
|
|
264
|
-
return () => observer.disconnect();
|
|
265
|
-
}, []);
|
|
266
|
-
const updateTheme = useCallback3(
|
|
267
|
-
(theme2) => {
|
|
268
|
-
document.documentElement.setAttribute(THEME_ATTRIBUTE, theme2);
|
|
269
|
-
},
|
|
270
|
-
[document.documentElement]
|
|
271
|
-
);
|
|
272
|
-
return [theme, updateTheme];
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// src/hooks/useWindowSize.ts
|
|
276
|
-
import { useState as useState5 } from "react";
|
|
277
|
-
function useWindowSize() {
|
|
278
|
-
const [windowSize, setWindowSize] = useState5({
|
|
279
|
-
height: 0,
|
|
280
|
-
width: 0
|
|
281
|
-
});
|
|
282
|
-
const handleSize = () => {
|
|
283
|
-
setWindowSize({
|
|
284
|
-
height: window.innerHeight,
|
|
285
|
-
width: window.innerWidth
|
|
286
|
-
});
|
|
287
|
-
};
|
|
288
|
-
useEventListener("resize", handleSize);
|
|
289
|
-
useIsomorphicLayoutEffect(() => {
|
|
290
|
-
handleSize();
|
|
291
|
-
}, []);
|
|
292
|
-
return windowSize;
|
|
293
|
-
}
|
|
294
200
|
export {
|
|
295
201
|
DEFAULT_THEME,
|
|
296
202
|
SYS_DARK_MEDIA_QUERY,
|
|
@@ -301,6 +207,7 @@ export {
|
|
|
301
207
|
useEventListener,
|
|
302
208
|
useInterval,
|
|
303
209
|
useIsomorphicLayoutEffect,
|
|
210
|
+
useLegacyStepper,
|
|
304
211
|
useMediaQuery,
|
|
305
212
|
useNotificationsStore,
|
|
306
213
|
useOnClickOutside,
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useDownload.ts","../../src/hooks/useNotificationsStore.ts","../../src/hooks/useEventCallback.ts","../../src/hooks/useIsomorphicLayoutEffect.ts","../../src/hooks/useEventListener.ts","../../src/hooks/useInterval.ts","../../src/hooks/useMediaQuery.ts","../../src/hooks/useOnClickOutside.ts","../../src/hooks/useSessionStorage.ts","../../src/hooks/useTheme.ts","../../src/hooks/useWindowSize.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport type { Promisable } from 'type-fest';\n\nimport { useNotificationsStore } from './useNotificationsStore';\n\n/**\n * Used to trigger downloads of arbitrary data to the client\n * @returns A function to invoke the download\n */\nexport function useDownload() {\n const notifications = useNotificationsStore();\n const [data, setData] = useState<null | string>(null);\n const [filename, setFilename] = useState<null | string>(null);\n\n useEffect(() => {\n if (data && filename) {\n const anchor = document.createElement('a');\n document.body.appendChild(anchor);\n const blob = new Blob([data], { type: 'text/plain' });\n const url = URL.createObjectURL(blob);\n anchor.href = url;\n anchor.download = filename;\n anchor.click();\n URL.revokeObjectURL(url);\n anchor.remove();\n setData(null);\n setFilename(null);\n }\n }, [data, filename]);\n\n return async (filename: string, fetchData: () => Promisable<string>) => {\n try {\n const data = await fetchData();\n setData(data);\n setFilename(filename);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'An unknown error occurred';\n notifications.addNotification({\n message,\n title: 'Error',\n type: 'error'\n });\n }\n };\n}\n","import { create } from 'zustand';\n\nexport type NotificationInterface = {\n id: number;\n message?: string;\n title?: string;\n type: 'error' | 'info' | 'success' | 'warning';\n variant?: 'critical' | 'standard';\n};\n\nexport type NotificationsStore = {\n addNotification: (notification: Omit<NotificationInterface, 'id'>) => void;\n dismissNotification: (id: number) => void;\n notifications: NotificationInterface[];\n};\n\nexport const useNotificationsStore = create<NotificationsStore>((set) => ({\n addNotification: (notification) => {\n set((state) => ({\n notifications: [...state.notifications, { id: Date.now(), ...notification }]\n }));\n },\n dismissNotification: (id) => {\n set((state) => ({\n notifications: state.notifications.filter((notification) => notification.id !== id)\n }));\n },\n notifications: []\n}));\n","import { useCallback, useRef } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\nexport function useEventCallback<Args extends unknown[], R>(fn: (...args: Args) => R) {\n const ref = useRef<typeof fn>(() => {\n throw new Error('Cannot call an event handler while rendering.');\n });\n\n useIsomorphicLayoutEffect(() => {\n ref.current = fn;\n }, [fn]);\n\n return useCallback((...args: Args) => ref.current(...args), [ref]);\n}\n","import { useEffect, useLayoutEffect } from 'react';\n\nimport { isBrowser } from '@/utils';\n\nexport const useIsomorphicLayoutEffect = isBrowser() ? useLayoutEffect : useEffect;\n","import { type RefObject, useEffect, useRef } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\n// MediaQueryList Event based useEventListener interface\nfunction useEventListener<K extends keyof MediaQueryListEventMap>(\n eventName: K,\n handler: (event: MediaQueryListEventMap[K]) => void,\n element: RefObject<MediaQueryList>,\n options?: AddEventListenerOptions | boolean\n): void;\n\n// Window Event based useEventListener interface\nfunction useEventListener<K extends keyof WindowEventMap>(\n eventName: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: undefined,\n options?: AddEventListenerOptions | boolean\n): void;\n\n// Element Event based useEventListener interface\nfunction useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLDivElement>(\n eventName: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: RefObject<T>,\n options?: AddEventListenerOptions | boolean\n): void;\n\n// Document Event based useEventListener interface\nfunction useEventListener<K extends keyof DocumentEventMap>(\n eventName: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: RefObject<Document>,\n options?: AddEventListenerOptions | boolean\n): void;\n\nfunction useEventListener<\n KW extends keyof WindowEventMap,\n KH extends keyof HTMLElementEventMap,\n KM extends keyof MediaQueryListEventMap,\n T extends HTMLElement | MediaQueryList | void = void\n>(\n eventName: KH | KM | KW,\n handler: (event: Event | HTMLElementEventMap[KH] | MediaQueryListEventMap[KM] | WindowEventMap[KW]) => void,\n element?: RefObject<T>,\n options?: AddEventListenerOptions | boolean\n) {\n // Create a ref that stores handler\n const savedHandler = useRef(handler);\n\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n // Define the listening target\n const targetElement: T | Window = element?.current ?? window;\n\n if (!(targetElement && targetElement.addEventListener)) return;\n\n // Create event listener that calls handler function stored in ref\n const listener: typeof handler = (event) => savedHandler.current(event);\n\n targetElement.addEventListener(eventName, listener, options);\n\n // Remove event listener on cleanup\n return () => {\n targetElement.removeEventListener(eventName, listener, options);\n };\n }, [eventName, element, options]);\n}\n\nexport { useEventListener };\n","import { useEffect, useRef } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\nexport function useInterval(callback: () => void, delay: null | number) {\n const savedCallback = useRef(callback);\n\n // Remember the latest callback if it changes.\n useIsomorphicLayoutEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the interval.\n useEffect(() => {\n // Don't schedule if no delay is specified.\n // Note: 0 is a valid value for delay.\n if (!delay && delay !== 0) {\n return;\n }\n\n const id = setInterval(() => savedCallback.current(), delay);\n\n return () => clearInterval(id);\n }, [delay]);\n}\n","import { useEffect, useState } from 'react';\n\nimport { isBrowser } from '@/utils';\n\n/**\n * Get the result of an arbitrary CSS media query\n *\n * @param query - the CSS media query\n * @returns a boolean indicating the result of the query\n * @example\n * // true if the viewport is at least 768px wide\n * const matches = useMediaQuery('(min-width: 768px)')\n */\nexport function useMediaQuery(query: string): boolean {\n const getMatches = (query: string): boolean => {\n // Prevents SSR issues\n if (isBrowser()) {\n return window.matchMedia(query).matches;\n }\n return false;\n };\n\n const [matches, setMatches] = useState<boolean>(getMatches(query));\n\n function handleChange() {\n setMatches(getMatches(query));\n }\n\n useEffect(() => {\n const matchMedia = window.matchMedia(query);\n\n // Triggered at the first client-side load and if query changes\n handleChange();\n\n matchMedia.addEventListener('change', handleChange);\n\n return () => {\n matchMedia.removeEventListener('change', handleChange);\n };\n }, [query]);\n\n return matches;\n}\n","import { type RefObject } from 'react';\n\nimport { useEventListener } from './useEventListener';\n\ntype Handler = (event: MouseEvent) => void;\n\nexport function useOnClickOutside<T extends HTMLElement = HTMLElement>(\n ref: RefObject<T>,\n handler: Handler,\n mouseEvent: 'mousedown' | 'mouseup' = 'mousedown'\n): void {\n useEventListener(mouseEvent, (event) => {\n const el = ref.current;\n\n // Do nothing if clicking ref's element or descendent elements\n if (!el || el.contains(event.target as Node)) {\n return;\n }\n\n handler(event);\n });\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Dispatch, SetStateAction } from 'react';\n\nimport { isBrowser } from '@/utils';\n\nimport { useEventCallback } from './useEventCallback';\nimport { useEventListener } from './useEventListener';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface WindowEventMap {\n 'session-storage': CustomEvent;\n }\n}\n\n/**\n * Represents the options for customizing the behavior of serialization and deserialization.\n * @template T - The type of the state to be stored in session storage.\n */\ntype UseSessionStorageOptions<T> = {\n /** A function to deserialize the stored value. */\n deserializer?: (value: string) => T;\n /**\n * If `true` (default), the hook will initialize reading the session storage. In SSR, you should set it to `false`, returning the initial value initially.\n * @default true\n */\n initializeWithValue?: boolean;\n /** A function to serialize the value before storing it. */\n serializer?: (value: T) => string;\n};\n\n/**\n * Custom hook that uses session storage to persist state across page reloads.\n * @template T - The type of the state to be stored in session storage.\n * @param {string} key - The key under which the value will be stored in session storage.\n * @param {T | (() => T)} initialValue - The initial value of the state or a function that returns the initial value.\n * @param {?UseSessionStorageOptions<T>} [options] - Options for customizing the behavior of serialization and deserialization (optional).\n * @returns {[T, Dispatch<SetStateAction<T>>]} A tuple containing the stored value and a function to set the value.\n * @public\n * @example\n * ```tsx\n * const [count, setCount] = useSessionStorage('count', 0);\n * // Access the `count` value and the `setCount` function to update it.\n * ```\n */\nexport function useSessionStorage<T>(\n key: string,\n initialValue: (() => T) | T,\n options: UseSessionStorageOptions<T> = {}\n): [T, Dispatch<SetStateAction<T>>] {\n const { initializeWithValue = true } = options;\n\n const serializer = useCallback<(value: T) => string>(\n (value) => {\n if (options.serializer) {\n return options.serializer(value);\n }\n return JSON.stringify(value);\n },\n [options]\n );\n\n const deserializer = useCallback<(value: string) => T>(\n (value) => {\n if (options.deserializer) {\n return options.deserializer(value);\n }\n // Support 'undefined' as a value\n if (value === 'undefined') {\n return undefined as unknown as T;\n }\n\n const defaultValue = initialValue instanceof Function ? initialValue() : initialValue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch (err) {\n console.error(`Error parsing JSON: ${(err as Error).message}`);\n return defaultValue;\n }\n\n return parsed as T;\n },\n [options, initialValue]\n );\n\n // Get from session storage then\n // parse stored json or return initialValue\n const readValue = useCallback((): T => {\n const initialValueToUse = initialValue instanceof Function ? initialValue() : initialValue;\n\n // Prevent build error \"window is undefined\" but keep keep working\n if (!isBrowser()) {\n return initialValueToUse;\n }\n const raw = window.sessionStorage.getItem(key);\n return raw ? deserializer(raw) : initialValueToUse;\n }, [initialValue, key, deserializer]);\n\n const [storedValue, setStoredValue] = useState(() => {\n if (initializeWithValue) {\n return readValue();\n }\n\n return initialValue instanceof Function ? initialValue() : initialValue;\n });\n\n // Return a wrapped version of useState's setter function that ...\n // ... persists the new value to sessionStorage.\n const setValue: Dispatch<SetStateAction<T>> = useEventCallback((value) => {\n // Prevent build error \"window is undefined\" but keeps working\n if (!isBrowser()) {\n console.warn(`Tried setting sessionStorage key “${key}” even though environment is not a client`);\n }\n\n try {\n // Allow value to be a function so we have the same API as useState\n const newValue = value instanceof Function ? value(readValue()) : value;\n\n // Save to session storage\n window.sessionStorage.setItem(key, serializer(newValue));\n\n // Save state\n setStoredValue(newValue);\n\n // We dispatch a custom event so every similar useSessionStorage hook is notified\n window.dispatchEvent(new StorageEvent('session-storage', { key }));\n } catch (error) {\n console.warn(`Error setting sessionStorage key “${key}”:`, error);\n }\n });\n\n useEffect(() => {\n setStoredValue(readValue());\n }, [key]);\n\n const handleStorageChange = useCallback(\n (event: CustomEvent | StorageEvent) => {\n if ((event as StorageEvent).key && (event as StorageEvent).key !== key) {\n return;\n }\n setStoredValue(readValue());\n },\n [key, readValue]\n );\n\n // this only works for other documents, not the current one\n useEventListener('storage', handleStorageChange);\n\n // this is a custom event, triggered in writeValueToSessionStorage\n // See: useSessionStorage()\n useEventListener('session-storage', handleStorageChange);\n\n return [storedValue, setValue];\n}\n","import { useCallback, useEffect, useState } from 'react';\n\nimport { isBrowser } from '../utils';\n\ntype Theme = 'dark' | 'light';\n\ntype UpdateTheme = (theme: Theme) => void;\n\n/** @private */\nconst DEFAULT_THEME: Theme = 'light';\n\n/** @private */\nconst THEME_ATTRIBUTE = 'data-mode';\n\n/** @private */\nconst THEME_KEY = 'theme';\n\n/** @private */\nconst SYS_DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)';\n\n/**\n * Returns the current theme and a function to update the current theme\n *\n * The reason the implementation of this hook is rather convoluted is for\n * cases where the theme is updated outside this hook\n */\nfunction useTheme(): readonly [Theme, UpdateTheme] {\n // Initial theme value is based on the value saved in local storage or the system theme\n const [theme, setTheme] = useState<Theme>(() => {\n if (!isBrowser()) {\n return DEFAULT_THEME;\n }\n const savedTheme = window.localStorage.getItem(THEME_KEY);\n let initialTheme: Theme;\n if (savedTheme === 'dark' || savedTheme === 'light') {\n initialTheme = savedTheme;\n } else {\n initialTheme = window.matchMedia(SYS_DARK_MEDIA_QUERY).matches ? 'dark' : 'light';\n }\n document.documentElement.setAttribute(THEME_ATTRIBUTE, initialTheme);\n return initialTheme;\n });\n\n useEffect(() => {\n const observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n if (mutation.attributeName === THEME_ATTRIBUTE) {\n const updatedTheme = (mutation.target as HTMLHtmlElement).getAttribute(THEME_ATTRIBUTE);\n if (updatedTheme === 'light' || updatedTheme === 'dark') {\n window.localStorage.setItem(THEME_KEY, updatedTheme);\n setTheme(updatedTheme);\n } else {\n console.error(`Unexpected value for 'data-mode' attribute: ${updatedTheme}`);\n }\n }\n });\n });\n observer.observe(document.documentElement, {\n attributes: true\n });\n return () => observer.disconnect();\n }, []);\n\n // When the user wants to change the theme\n const updateTheme = useCallback(\n (theme: Theme) => {\n document.documentElement.setAttribute(THEME_ATTRIBUTE, theme);\n },\n [document.documentElement]\n );\n\n return [theme, updateTheme] as const;\n}\n\nexport { DEFAULT_THEME, SYS_DARK_MEDIA_QUERY, THEME_ATTRIBUTE, THEME_KEY, type Theme, useTheme };\n","import { useState } from 'react';\n\nimport { useEventListener } from './useEventListener';\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\nexport type WindowSize = {\n height: number;\n width: number;\n};\n\nexport function useWindowSize(): WindowSize {\n const [windowSize, setWindowSize] = useState<WindowSize>({\n height: 0,\n width: 0\n });\n\n const handleSize = () => {\n setWindowSize({\n height: window.innerHeight,\n width: window.innerWidth\n });\n };\n\n useEventListener('resize', handleSize);\n\n // Set size at the first client-side load\n useIsomorphicLayoutEffect(() => {\n handleSize();\n }, []);\n\n return windowSize;\n}\n"],"mappings":"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","names":["filename","data","useEffect","useEffect","useEffect","useRef","useRef","useEffect","useEffect","useRef","useRef","useEffect","useEffect","useState","query","useState","useEffect","useCallback","useEffect","useState","useCallback","useState","useEffect","useCallback","useEffect","useState","useState","useEffect","useCallback","theme","useState","useState"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useDownload.ts","../../src/hooks/useEventCallback.ts","../../src/hooks/useInterval.ts","../../src/hooks/useLegacyStepper.ts","../../src/hooks/useMediaQuery.ts","../../src/hooks/useOnClickOutside.ts","../../src/hooks/useSessionStorage.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport type { Promisable } from 'type-fest';\n\nimport { useNotificationsStore } from './useNotificationsStore';\n\n/**\n * Used to trigger downloads of arbitrary data to the client\n * @returns A function to invoke the download\n */\nexport function useDownload() {\n const notifications = useNotificationsStore();\n const [data, setData] = useState<null | string>(null);\n const [filename, setFilename] = useState<null | string>(null);\n\n useEffect(() => {\n if (data && filename) {\n const anchor = document.createElement('a');\n document.body.appendChild(anchor);\n const blob = new Blob([data], { type: 'text/plain' });\n const url = URL.createObjectURL(blob);\n anchor.href = url;\n anchor.download = filename;\n anchor.click();\n URL.revokeObjectURL(url);\n anchor.remove();\n setData(null);\n setFilename(null);\n }\n }, [data, filename]);\n\n return async (filename: string, fetchData: () => Promisable<string>) => {\n try {\n const data = await fetchData();\n setData(data);\n setFilename(filename);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'An unknown error occurred';\n notifications.addNotification({\n message,\n title: 'Error',\n type: 'error'\n });\n }\n };\n}\n","import { useCallback, useRef } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\nexport function useEventCallback<Args extends unknown[], R>(fn: (...args: Args) => R) {\n const ref = useRef<typeof fn>(() => {\n throw new Error('Cannot call an event handler while rendering.');\n });\n\n useIsomorphicLayoutEffect(() => {\n ref.current = fn;\n }, [fn]);\n\n return useCallback((...args: Args) => ref.current(...args), [ref]);\n}\n","import { useEffect, useRef } from 'react';\n\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';\n\nexport function useInterval(callback: () => void, delay: null | number) {\n const savedCallback = useRef(callback);\n\n // Remember the latest callback if it changes.\n useIsomorphicLayoutEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the interval.\n useEffect(() => {\n // Don't schedule if no delay is specified.\n // Note: 0 is a valid value for delay.\n if (!delay && delay !== 0) {\n return;\n }\n\n const id = setInterval(() => savedCallback.current(), delay);\n\n return () => clearInterval(id);\n }, [delay]);\n}\n","import { useContext } from 'react';\n\nimport { LegacyStepperContext } from '@/context/LegacyStepperContext';\n\n/** @deprecated */\nexport function useLegacyStepper() {\n return useContext(LegacyStepperContext);\n}\n","import { useEffect, useState } from 'react';\n\nimport { isBrowser } from '@/utils';\n\n/**\n * Get the result of an arbitrary CSS media query\n *\n * @param query - the CSS media query\n * @returns a boolean indicating the result of the query\n * @example\n * // true if the viewport is at least 768px wide\n * const matches = useMediaQuery('(min-width: 768px)')\n */\nexport function useMediaQuery(query: string): boolean {\n const getMatches = (query: string): boolean => {\n // Prevents SSR issues\n if (isBrowser()) {\n return window.matchMedia(query).matches;\n }\n return false;\n };\n\n const [matches, setMatches] = useState<boolean>(getMatches(query));\n\n function handleChange() {\n setMatches(getMatches(query));\n }\n\n useEffect(() => {\n const matchMedia = window.matchMedia(query);\n\n // Triggered at the first client-side load and if query changes\n handleChange();\n\n matchMedia.addEventListener('change', handleChange);\n\n return () => {\n matchMedia.removeEventListener('change', handleChange);\n };\n }, [query]);\n\n return matches;\n}\n","import { type RefObject } from 'react';\n\nimport { useEventListener } from './useEventListener';\n\ntype Handler = (event: MouseEvent) => void;\n\nexport function useOnClickOutside<T extends HTMLElement = HTMLElement>(\n ref: RefObject<T>,\n handler: Handler,\n mouseEvent: 'mousedown' | 'mouseup' = 'mousedown'\n): void {\n useEventListener(mouseEvent, (event) => {\n const el = ref.current;\n\n // Do nothing if clicking ref's element or descendent elements\n if (!el || el.contains(event.target as Node)) {\n return;\n }\n\n handler(event);\n });\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Dispatch, SetStateAction } from 'react';\n\nimport { isBrowser } from '@/utils';\n\nimport { useEventCallback } from './useEventCallback';\nimport { useEventListener } from './useEventListener';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface WindowEventMap {\n 'session-storage': CustomEvent;\n }\n}\n\n/**\n * Represents the options for customizing the behavior of serialization and deserialization.\n * @template T - The type of the state to be stored in session storage.\n */\ntype UseSessionStorageOptions<T> = {\n /** A function to deserialize the stored value. */\n deserializer?: (value: string) => T;\n /**\n * If `true` (default), the hook will initialize reading the session storage. In SSR, you should set it to `false`, returning the initial value initially.\n * @default true\n */\n initializeWithValue?: boolean;\n /** A function to serialize the value before storing it. */\n serializer?: (value: T) => string;\n};\n\n/**\n * Custom hook that uses session storage to persist state across page reloads.\n * @template T - The type of the state to be stored in session storage.\n * @param {string} key - The key under which the value will be stored in session storage.\n * @param {T | (() => T)} initialValue - The initial value of the state or a function that returns the initial value.\n * @param {?UseSessionStorageOptions<T>} [options] - Options for customizing the behavior of serialization and deserialization (optional).\n * @returns {[T, Dispatch<SetStateAction<T>>]} A tuple containing the stored value and a function to set the value.\n * @public\n * @example\n * ```tsx\n * const [count, setCount] = useSessionStorage('count', 0);\n * // Access the `count` value and the `setCount` function to update it.\n * ```\n */\nexport function useSessionStorage<T>(\n key: string,\n initialValue: (() => T) | T,\n options: UseSessionStorageOptions<T> = {}\n): [T, Dispatch<SetStateAction<T>>] {\n const { initializeWithValue = true } = options;\n\n const serializer = useCallback<(value: T) => string>(\n (value) => {\n if (options.serializer) {\n return options.serializer(value);\n }\n return JSON.stringify(value);\n },\n [options]\n );\n\n const deserializer = useCallback<(value: string) => T>(\n (value) => {\n if (options.deserializer) {\n return options.deserializer(value);\n }\n // Support 'undefined' as a value\n if (value === 'undefined') {\n return undefined as unknown as T;\n }\n\n const defaultValue = initialValue instanceof Function ? initialValue() : initialValue;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch (err) {\n console.error(`Error parsing JSON: ${(err as Error).message}`);\n return defaultValue;\n }\n\n return parsed as T;\n },\n [options, initialValue]\n );\n\n // Get from session storage then\n // parse stored json or return initialValue\n const readValue = useCallback((): T => {\n const initialValueToUse = initialValue instanceof Function ? initialValue() : initialValue;\n\n // Prevent build error \"window is undefined\" but keep keep working\n if (!isBrowser()) {\n return initialValueToUse;\n }\n const raw = window.sessionStorage.getItem(key);\n return raw ? deserializer(raw) : initialValueToUse;\n }, [initialValue, key, deserializer]);\n\n const [storedValue, setStoredValue] = useState(() => {\n if (initializeWithValue) {\n return readValue();\n }\n\n return initialValue instanceof Function ? initialValue() : initialValue;\n });\n\n // Return a wrapped version of useState's setter function that ...\n // ... persists the new value to sessionStorage.\n const setValue: Dispatch<SetStateAction<T>> = useEventCallback((value) => {\n // Prevent build error \"window is undefined\" but keeps working\n if (!isBrowser()) {\n console.warn(`Tried setting sessionStorage key “${key}” even though environment is not a client`);\n }\n\n try {\n // Allow value to be a function so we have the same API as useState\n const newValue = value instanceof Function ? value(readValue()) : value;\n\n // Save to session storage\n window.sessionStorage.setItem(key, serializer(newValue));\n\n // Save state\n setStoredValue(newValue);\n\n // We dispatch a custom event so every similar useSessionStorage hook is notified\n window.dispatchEvent(new StorageEvent('session-storage', { key }));\n } catch (error) {\n console.warn(`Error setting sessionStorage key “${key}”:`, error);\n }\n });\n\n useEffect(() => {\n setStoredValue(readValue());\n }, [key]);\n\n const handleStorageChange = useCallback(\n (event: CustomEvent | StorageEvent) => {\n if ((event as StorageEvent).key && (event as StorageEvent).key !== key) {\n return;\n }\n setStoredValue(readValue());\n },\n [key, readValue]\n );\n\n // this only works for other documents, not the current one\n useEventListener('storage', handleStorageChange);\n\n // this is a custom event, triggered in writeValueToSessionStorage\n // See: useSessionStorage()\n useEventListener('session-storage', handleStorageChange);\n\n return [storedValue, setValue];\n}\n"],"mappings":"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","names":["filename","data","useEffect","useRef","useRef","useEffect","useEffect","useState","query","useState","useEffect","useCallback","useEffect","useState","useCallback","useState","useEffect"]}
|
package/dist/i18n.js
CHANGED
|
@@ -6,10 +6,26 @@ import { initReactI18next } from "react-i18next";
|
|
|
6
6
|
// src/translations/libui.json
|
|
7
7
|
var libui_default = {
|
|
8
8
|
days: {
|
|
9
|
+
friday: {
|
|
10
|
+
en: "Friday",
|
|
11
|
+
fr: "Vendredi"
|
|
12
|
+
},
|
|
9
13
|
monday: {
|
|
10
14
|
en: "Monday",
|
|
11
15
|
fr: "Lundi"
|
|
12
16
|
},
|
|
17
|
+
saturday: {
|
|
18
|
+
en: "Saturday",
|
|
19
|
+
fr: "Samedi"
|
|
20
|
+
},
|
|
21
|
+
sunday: {
|
|
22
|
+
en: "Sunday",
|
|
23
|
+
fr: "Dimanche"
|
|
24
|
+
},
|
|
25
|
+
thursday: {
|
|
26
|
+
en: "Thursday",
|
|
27
|
+
fr: "Jeudi"
|
|
28
|
+
},
|
|
13
29
|
tuesday: {
|
|
14
30
|
en: "Tuesday",
|
|
15
31
|
fr: "Mardi"
|
|
@@ -17,104 +33,124 @@ var libui_default = {
|
|
|
17
33
|
wednesday: {
|
|
18
34
|
en: "Wednesday",
|
|
19
35
|
fr: "Mercredi"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
form: {
|
|
39
|
+
append: {
|
|
40
|
+
en: "Append",
|
|
41
|
+
fr: "Ajouter"
|
|
20
42
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
43
|
+
radioLabels: {
|
|
44
|
+
false: {
|
|
45
|
+
en: "False",
|
|
46
|
+
fr: "Faux"
|
|
47
|
+
},
|
|
48
|
+
true: {
|
|
49
|
+
en: "True",
|
|
50
|
+
fr: "Vrai"
|
|
51
|
+
}
|
|
24
52
|
},
|
|
25
|
-
|
|
26
|
-
en: "
|
|
27
|
-
fr: "
|
|
53
|
+
remove: {
|
|
54
|
+
en: "Remove",
|
|
55
|
+
fr: "Supprimer"
|
|
28
56
|
},
|
|
29
|
-
|
|
30
|
-
en: "
|
|
31
|
-
fr: "
|
|
57
|
+
required: {
|
|
58
|
+
en: "This field is required",
|
|
59
|
+
fr: "Ce champ est obligatoire"
|
|
32
60
|
},
|
|
33
|
-
|
|
34
|
-
en: "
|
|
35
|
-
fr: "
|
|
61
|
+
reset: {
|
|
62
|
+
en: "Reset",
|
|
63
|
+
fr: "R\xE9initialiser"
|
|
64
|
+
},
|
|
65
|
+
submit: {
|
|
66
|
+
en: "Submit",
|
|
67
|
+
fr: "Soumettre"
|
|
36
68
|
}
|
|
37
69
|
},
|
|
38
70
|
months: {
|
|
39
|
-
|
|
40
|
-
en: "
|
|
41
|
-
fr: "
|
|
71
|
+
april: {
|
|
72
|
+
en: "April",
|
|
73
|
+
fr: "Avril"
|
|
74
|
+
},
|
|
75
|
+
august: {
|
|
76
|
+
en: "August",
|
|
77
|
+
fr: "Ao\xFBt"
|
|
78
|
+
},
|
|
79
|
+
december: {
|
|
80
|
+
en: "December",
|
|
81
|
+
fr: "D\xE9cembre"
|
|
42
82
|
},
|
|
43
83
|
february: {
|
|
44
84
|
en: "February",
|
|
45
85
|
fr: "F\xE9vrier"
|
|
46
86
|
},
|
|
47
|
-
|
|
48
|
-
en: "
|
|
49
|
-
fr: "
|
|
50
|
-
},
|
|
51
|
-
april: {
|
|
52
|
-
en: "April",
|
|
53
|
-
fr: "Avril"
|
|
87
|
+
january: {
|
|
88
|
+
en: "January",
|
|
89
|
+
fr: "Janvier"
|
|
54
90
|
},
|
|
55
|
-
|
|
56
|
-
en: "
|
|
57
|
-
fr: "
|
|
91
|
+
july: {
|
|
92
|
+
en: "July",
|
|
93
|
+
fr: "Juillet"
|
|
58
94
|
},
|
|
59
95
|
june: {
|
|
60
96
|
en: "June",
|
|
61
97
|
fr: "Juin"
|
|
62
98
|
},
|
|
63
|
-
|
|
64
|
-
en: "
|
|
65
|
-
fr: "
|
|
99
|
+
march: {
|
|
100
|
+
en: "March",
|
|
101
|
+
fr: "Mars"
|
|
66
102
|
},
|
|
67
|
-
|
|
68
|
-
en: "
|
|
69
|
-
fr: "
|
|
103
|
+
may: {
|
|
104
|
+
en: "May",
|
|
105
|
+
fr: "Mai"
|
|
70
106
|
},
|
|
71
|
-
|
|
72
|
-
en: "
|
|
73
|
-
fr: "
|
|
107
|
+
november: {
|
|
108
|
+
en: "November",
|
|
109
|
+
fr: "Novembre"
|
|
74
110
|
},
|
|
75
111
|
october: {
|
|
76
112
|
en: "October",
|
|
77
113
|
fr: "Octobre"
|
|
78
114
|
},
|
|
79
|
-
|
|
80
|
-
en: "
|
|
81
|
-
fr: "
|
|
82
|
-
},
|
|
83
|
-
december: {
|
|
84
|
-
en: "December",
|
|
85
|
-
fr: "D\xE9cembre"
|
|
115
|
+
september: {
|
|
116
|
+
en: "September",
|
|
117
|
+
fr: "Septembre"
|
|
86
118
|
}
|
|
87
119
|
},
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
required: {
|
|
94
|
-
en: "This field is required",
|
|
95
|
-
fr: "Ce champ est obligatoire"
|
|
96
|
-
},
|
|
97
|
-
remove: {
|
|
98
|
-
en: "Remove",
|
|
99
|
-
fr: "Supprimer"
|
|
100
|
-
},
|
|
101
|
-
radioLabels: {
|
|
102
|
-
true: {
|
|
103
|
-
en: "True",
|
|
104
|
-
fr: "Vrai"
|
|
120
|
+
notifications: {
|
|
121
|
+
types: {
|
|
122
|
+
error: {
|
|
123
|
+
en: "Error",
|
|
124
|
+
fr: "Erreur"
|
|
105
125
|
},
|
|
106
|
-
|
|
107
|
-
en: "
|
|
108
|
-
fr: "
|
|
126
|
+
info: {
|
|
127
|
+
en: "Info",
|
|
128
|
+
fr: "Attention"
|
|
129
|
+
},
|
|
130
|
+
success: {
|
|
131
|
+
en: "Success",
|
|
132
|
+
fr: "Succ\xE8s"
|
|
133
|
+
},
|
|
134
|
+
warning: {
|
|
135
|
+
en: "Warning",
|
|
136
|
+
fr: "Avertissement"
|
|
109
137
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
pagination: {
|
|
141
|
+
next: {
|
|
142
|
+
en: "Next",
|
|
143
|
+
fr: "Suivant"
|
|
144
|
+
},
|
|
145
|
+
previous: {
|
|
146
|
+
en: "Previous",
|
|
147
|
+
fr: "Pr\xE9c\xE9dent"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
searchBar: {
|
|
151
|
+
placeholder: {
|
|
152
|
+
en: "Search...",
|
|
153
|
+
fr: "Rechercher..."
|
|
118
154
|
}
|
|
119
155
|
}
|
|
120
156
|
};
|
package/dist/i18n.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/i18n.ts","../src/translations/libui.json"],"sourcesContent":["import { type i18n as I18n, createInstance } from 'i18next';\nimport { mapValues } from 'lodash-es';\nimport { initReactI18next } from 'react-i18next';\nimport type { EmptyObject, ValueOf } from 'type-fest';\n\nimport libui from './translations/libui.json';\n\nconst defaultNS = 'libui' as const;\nconst supportedLngs = ['en', 'fr'] as const;\n\ntype DefaultNS = typeof defaultNS;\ntype Language = (typeof supportedLngs)[number];\n\ntype TranslationsDef = Record<string, Record<string, unknown>>;\n\ntype TranslatedResource<T = EmptyObject> = {\n [K in keyof T]: T[K] extends Record<string, unknown>\n ? T[K] extends Record<Language, unknown>\n ? ValueOf<T[K]>\n : TranslatedResource<T[K]>\n : T[K];\n};\n\nfunction transformTranslations<T extends Record<string, any>>(translations: T, locale: string) {\n const isPlainObject = Object.getPrototypeOf(translations) === Object.prototype;\n if (!isPlainObject) {\n throw new Error('Invalid format of translations: must be plain object');\n }\n const result: Record<string, unknown> = {};\n for (const key in translations) {\n const value = translations[key];\n if (Object.hasOwn(value, locale)) {\n result[key] = value[locale as keyof typeof value];\n } else {\n result[key] = transformTranslations(value, locale);\n }\n }\n return result;\n}\n\nfunction createResourcesForLanguage<T extends TranslationsDef>(translations: T, locale: Language) {\n return mapValues(translations, (value) => transformTranslations(value, locale));\n}\n\nfunction createResources<T extends TranslationsDef>(translations: T) {\n return {\n en: createResourcesForLanguage(translations, 'en'),\n fr: createResourcesForLanguage(translations, 'fr')\n } as TranslatedResource<T>;\n}\n\nconst resources = createResources({ libui });\n\nconst i18n = createInstance({\n defaultNS,\n fallbackLng: 'en' satisfies Language,\n interpolation: {\n escapeValue: false\n },\n lng: 'en' satisfies Language,\n resources,\n returnObjects: true,\n supportedLngs\n}) as I18n;\n\nawait i18n.use(initReactI18next).init();\n\nexport default i18n;\n\nexport type { DefaultNS, Language, TranslatedResource };\n","{\n \"days\": {\n \"
|
|
1
|
+
{"version":3,"sources":["../src/i18n.ts","../src/translations/libui.json"],"sourcesContent":["import { type i18n as I18n, createInstance } from 'i18next';\nimport { mapValues } from 'lodash-es';\nimport { initReactI18next } from 'react-i18next';\nimport type { EmptyObject, ValueOf } from 'type-fest';\n\nimport libui from './translations/libui.json';\n\nconst defaultNS = 'libui' as const;\nconst supportedLngs = ['en', 'fr'] as const;\n\ntype DefaultNS = typeof defaultNS;\ntype Language = (typeof supportedLngs)[number];\n\ntype TranslationsDef = Record<string, Record<string, unknown>>;\n\ntype TranslatedResource<T = EmptyObject> = {\n [K in keyof T]: T[K] extends Record<string, unknown>\n ? T[K] extends Record<Language, unknown>\n ? ValueOf<T[K]>\n : TranslatedResource<T[K]>\n : T[K];\n};\n\nfunction transformTranslations<T extends Record<string, any>>(translations: T, locale: string) {\n const isPlainObject = Object.getPrototypeOf(translations) === Object.prototype;\n if (!isPlainObject) {\n throw new Error('Invalid format of translations: must be plain object');\n }\n const result: Record<string, unknown> = {};\n for (const key in translations) {\n const value = translations[key];\n if (Object.hasOwn(value, locale)) {\n result[key] = value[locale as keyof typeof value];\n } else {\n result[key] = transformTranslations(value, locale);\n }\n }\n return result;\n}\n\nfunction createResourcesForLanguage<T extends TranslationsDef>(translations: T, locale: Language) {\n return mapValues(translations, (value) => transformTranslations(value, locale));\n}\n\nfunction createResources<T extends TranslationsDef>(translations: T) {\n return {\n en: createResourcesForLanguage(translations, 'en'),\n fr: createResourcesForLanguage(translations, 'fr')\n } as TranslatedResource<T>;\n}\n\nconst resources = createResources({ libui });\n\nconst i18n = createInstance({\n defaultNS,\n fallbackLng: 'en' satisfies Language,\n interpolation: {\n escapeValue: false\n },\n lng: 'en' satisfies Language,\n resources,\n returnObjects: true,\n supportedLngs\n}) as I18n;\n\nawait i18n.use(initReactI18next).init();\n\nexport default i18n;\n\nexport type { DefaultNS, Language, TranslatedResource };\n","{\n \"days\": {\n \"friday\": {\n \"en\": \"Friday\",\n \"fr\": \"Vendredi\"\n },\n \"monday\": {\n \"en\": \"Monday\",\n \"fr\": \"Lundi\"\n },\n \"saturday\": {\n \"en\": \"Saturday\",\n \"fr\": \"Samedi\"\n },\n \"sunday\": {\n \"en\": \"Sunday\",\n \"fr\": \"Dimanche\"\n },\n \"thursday\": {\n \"en\": \"Thursday\",\n \"fr\": \"Jeudi\"\n },\n \"tuesday\": {\n \"en\": \"Tuesday\",\n \"fr\": \"Mardi\"\n },\n \"wednesday\": {\n \"en\": \"Wednesday\",\n \"fr\": \"Mercredi\"\n }\n },\n \"form\": {\n \"append\": {\n \"en\": \"Append\",\n \"fr\": \"Ajouter\"\n },\n \"radioLabels\": {\n \"false\": {\n \"en\": \"False\",\n \"fr\": \"Faux\"\n },\n \"true\": {\n \"en\": \"True\",\n \"fr\": \"Vrai\"\n }\n },\n \"remove\": {\n \"en\": \"Remove\",\n \"fr\": \"Supprimer\"\n },\n \"required\": {\n \"en\": \"This field is required\",\n \"fr\": \"Ce champ est obligatoire\"\n },\n \"reset\": {\n \"en\": \"Reset\",\n \"fr\": \"Réinitialiser\"\n },\n \"submit\": {\n \"en\": \"Submit\",\n \"fr\": \"Soumettre\"\n }\n },\n \"months\": {\n \"april\": {\n \"en\": \"April\",\n \"fr\": \"Avril\"\n },\n \"august\": {\n \"en\": \"August\",\n \"fr\": \"Août\"\n },\n \"december\": {\n \"en\": \"December\",\n \"fr\": \"Décembre\"\n },\n \"february\": {\n \"en\": \"February\",\n \"fr\": \"Février\"\n },\n \"january\": {\n \"en\": \"January\",\n \"fr\": \"Janvier\"\n },\n \"july\": {\n \"en\": \"July\",\n \"fr\": \"Juillet\"\n },\n \"june\": {\n \"en\": \"June\",\n \"fr\": \"Juin\"\n },\n \"march\": {\n \"en\": \"March\",\n \"fr\": \"Mars\"\n },\n \"may\": {\n \"en\": \"May\",\n \"fr\": \"Mai\"\n },\n \"november\": {\n \"en\": \"November\",\n \"fr\": \"Novembre\"\n },\n \"october\": {\n \"en\": \"October\",\n \"fr\": \"Octobre\"\n },\n \"september\": {\n \"en\": \"September\",\n \"fr\": \"Septembre\"\n }\n },\n \"notifications\": {\n \"types\": {\n \"error\": {\n \"en\": \"Error\",\n \"fr\": \"Erreur\"\n },\n \"info\": {\n \"en\": \"Info\",\n \"fr\": \"Attention\"\n },\n \"success\": {\n \"en\": \"Success\",\n \"fr\": \"Succès\"\n },\n \"warning\": {\n \"en\": \"Warning\",\n \"fr\": \"Avertissement\"\n }\n }\n },\n \"pagination\": {\n \"next\": {\n \"en\": \"Next\",\n \"fr\": \"Suivant\"\n },\n \"previous\": {\n \"en\": \"Previous\",\n \"fr\": \"Précédent\"\n }\n },\n \"searchBar\": {\n \"placeholder\": {\n \"en\": \"Search...\",\n \"fr\": \"Rechercher...\"\n }\n }\n}\n"],"mappings":"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","names":[]}
|