@douglasneuroinformatics/libui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +165 -0
- package/README.md +53 -0
- package/dist/chunk-57KC6SAE.js +11 -0
- package/dist/chunk-57KC6SAE.js.map +1 -0
- package/dist/components/index.d.ts +311 -0
- package/dist/components/index.js +82 -0
- package/dist/components/index.js.map +1 -0
- package/dist/hooks/index.d.ts +74 -0
- package/dist/hooks/index.js +285 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/i18n.d.ts +52 -0
- package/dist/i18n.js +94 -0
- package/dist/i18n.js.map +1 -0
- package/dist/styles/globals.css +80 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -0
- package/package.json +111 -0
- package/tailwind.config.cjs +117 -0
- package/tailwind.config.d.cts +7 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Promisable } from 'type-fest';
|
|
2
|
+
import { RefObject, useEffect, Dispatch, SetStateAction } from 'react';
|
|
3
|
+
import * as zustand from 'zustand';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Used to trigger downloads of arbitrary data to the client
|
|
7
|
+
* @returns A function to invoke the download
|
|
8
|
+
*/
|
|
9
|
+
declare function useDownload(): (filename: string, fetchData: () => Promisable<string>) => Promise<void>;
|
|
10
|
+
|
|
11
|
+
declare function useEventCallback<Args extends unknown[], R>(fn: (...args: Args) => R): (...args: Args) => R;
|
|
12
|
+
|
|
13
|
+
declare function useEventListener<K extends keyof MediaQueryListEventMap>(eventName: K, handler: (event: MediaQueryListEventMap[K]) => void, element: RefObject<MediaQueryList>, options?: AddEventListenerOptions | boolean): void;
|
|
14
|
+
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: AddEventListenerOptions | boolean): void;
|
|
15
|
+
declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLDivElement>(eventName: K, handler: (event: HTMLElementEventMap[K]) => void, element: RefObject<T>, options?: AddEventListenerOptions | boolean): void;
|
|
16
|
+
declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document>, options?: AddEventListenerOptions | boolean): void;
|
|
17
|
+
|
|
18
|
+
declare function useInterval(callback: () => void, delay: null | number): void;
|
|
19
|
+
|
|
20
|
+
declare const useIsomorphicLayoutEffect: typeof useEffect;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the result of an arbitrary CSS media query
|
|
24
|
+
*
|
|
25
|
+
* @param query - the CSS media query
|
|
26
|
+
* @returns a boolean indicating the result of the query
|
|
27
|
+
* @example
|
|
28
|
+
* // true if the viewport is at least 768px wide
|
|
29
|
+
* const matches = useMediaQuery('(min-width: 768px)')
|
|
30
|
+
*/
|
|
31
|
+
declare function useMediaQuery(query: string): boolean;
|
|
32
|
+
|
|
33
|
+
type NotificationInterface = {
|
|
34
|
+
id: number;
|
|
35
|
+
message?: string;
|
|
36
|
+
title?: string;
|
|
37
|
+
type: 'error' | 'info' | 'success' | 'warning';
|
|
38
|
+
variant?: 'critical' | 'standard';
|
|
39
|
+
};
|
|
40
|
+
type NotificationsStore = {
|
|
41
|
+
addNotification: (notification: Omit<NotificationInterface, 'id'>) => void;
|
|
42
|
+
dismissNotification: (id: number) => void;
|
|
43
|
+
notifications: NotificationInterface[];
|
|
44
|
+
};
|
|
45
|
+
declare const useNotificationsStore: zustand.UseBoundStore<zustand.StoreApi<NotificationsStore>>;
|
|
46
|
+
|
|
47
|
+
type Handler = (event: MouseEvent) => void;
|
|
48
|
+
declare function useOnClickOutside<T extends HTMLElement = HTMLElement>(ref: RefObject<T>, handler: Handler, mouseEvent?: 'mousedown' | 'mouseup'): void;
|
|
49
|
+
|
|
50
|
+
declare global {
|
|
51
|
+
interface WindowEventMap {
|
|
52
|
+
'session-storage': CustomEvent;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
type SetValue<T> = Dispatch<SetStateAction<T>>;
|
|
56
|
+
declare function useSessionStorage<T>(key: string, initialValue: T): [T, SetValue<T>];
|
|
57
|
+
|
|
58
|
+
type Theme = 'dark' | 'light';
|
|
59
|
+
type UpdateTheme = (theme: Theme) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the current theme and a function to update the current theme
|
|
62
|
+
*
|
|
63
|
+
* The reason the implementation of this hook is rather convoluted is for
|
|
64
|
+
* cases where the theme is updated outside this hook
|
|
65
|
+
*/
|
|
66
|
+
declare function useTheme(): readonly [Theme, UpdateTheme];
|
|
67
|
+
|
|
68
|
+
type WindowSize = {
|
|
69
|
+
height: number;
|
|
70
|
+
width: number;
|
|
71
|
+
};
|
|
72
|
+
declare function useWindowSize(): WindowSize;
|
|
73
|
+
|
|
74
|
+
export { type NotificationInterface, type NotificationsStore, type Theme, type WindowSize, useDownload, useEventCallback, useEventListener, useInterval, useIsomorphicLayoutEffect, useMediaQuery, useNotificationsStore, useOnClickOutside, useSessionStorage, useTheme, useWindowSize };
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// src/hooks/useDownload.ts
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
|
|
4
|
+
// src/hooks/useNotificationsStore.ts
|
|
5
|
+
import { create } from "zustand";
|
|
6
|
+
var useNotificationsStore = create((set) => ({
|
|
7
|
+
addNotification: (notification) => {
|
|
8
|
+
set((state) => ({
|
|
9
|
+
notifications: [...state.notifications, { id: Date.now(), ...notification }]
|
|
10
|
+
}));
|
|
11
|
+
},
|
|
12
|
+
dismissNotification: (id) => {
|
|
13
|
+
set((state) => ({
|
|
14
|
+
notifications: state.notifications.filter((notification) => notification.id !== id)
|
|
15
|
+
}));
|
|
16
|
+
},
|
|
17
|
+
notifications: []
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
// src/hooks/useDownload.ts
|
|
21
|
+
function useDownload() {
|
|
22
|
+
const notifications = useNotificationsStore();
|
|
23
|
+
const [data, setData] = useState(null);
|
|
24
|
+
const [filename, setFilename] = useState(null);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (data && filename) {
|
|
27
|
+
const anchor = document.createElement("a");
|
|
28
|
+
document.body.appendChild(anchor);
|
|
29
|
+
const blob = new Blob([data], { type: "text/plain" });
|
|
30
|
+
const url = URL.createObjectURL(blob);
|
|
31
|
+
anchor.href = url;
|
|
32
|
+
anchor.download = filename;
|
|
33
|
+
anchor.click();
|
|
34
|
+
URL.revokeObjectURL(url);
|
|
35
|
+
anchor.remove();
|
|
36
|
+
setData(null);
|
|
37
|
+
setFilename(null);
|
|
38
|
+
}
|
|
39
|
+
}, [data, filename]);
|
|
40
|
+
return async (filename2, fetchData) => {
|
|
41
|
+
try {
|
|
42
|
+
const data2 = await fetchData();
|
|
43
|
+
setData(data2);
|
|
44
|
+
setFilename(filename2);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
const message = error instanceof Error ? error.message : "An unknown error occurred";
|
|
47
|
+
notifications.addNotification({
|
|
48
|
+
message,
|
|
49
|
+
title: "Error",
|
|
50
|
+
type: "error"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/hooks/useEventCallback.ts
|
|
57
|
+
import { useCallback, useRef } from "react";
|
|
58
|
+
|
|
59
|
+
// src/hooks/useIsomorphicLayoutEffect.ts
|
|
60
|
+
import { useEffect as useEffect2, useLayoutEffect } from "react";
|
|
61
|
+
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect2;
|
|
62
|
+
|
|
63
|
+
// src/hooks/useEventCallback.ts
|
|
64
|
+
function useEventCallback(fn) {
|
|
65
|
+
const ref = useRef(() => {
|
|
66
|
+
throw new Error("Cannot call an event handler while rendering.");
|
|
67
|
+
});
|
|
68
|
+
useIsomorphicLayoutEffect(() => {
|
|
69
|
+
ref.current = fn;
|
|
70
|
+
}, [fn]);
|
|
71
|
+
return useCallback((...args) => ref.current(...args), [ref]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/hooks/useEventListener.ts
|
|
75
|
+
import { useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
76
|
+
function useEventListener(eventName, handler, element, options) {
|
|
77
|
+
const savedHandler = useRef2(handler);
|
|
78
|
+
useIsomorphicLayoutEffect(() => {
|
|
79
|
+
savedHandler.current = handler;
|
|
80
|
+
}, [handler]);
|
|
81
|
+
useEffect3(() => {
|
|
82
|
+
const targetElement = element?.current ?? window;
|
|
83
|
+
if (!(targetElement && targetElement.addEventListener))
|
|
84
|
+
return;
|
|
85
|
+
const listener = (event) => savedHandler.current(event);
|
|
86
|
+
targetElement.addEventListener(eventName, listener, options);
|
|
87
|
+
return () => {
|
|
88
|
+
targetElement.removeEventListener(eventName, listener, options);
|
|
89
|
+
};
|
|
90
|
+
}, [eventName, element, options]);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/hooks/useInterval.ts
|
|
94
|
+
import { useEffect as useEffect4, useRef as useRef3 } from "react";
|
|
95
|
+
function useInterval(callback, delay) {
|
|
96
|
+
const savedCallback = useRef3(callback);
|
|
97
|
+
useIsomorphicLayoutEffect(() => {
|
|
98
|
+
savedCallback.current = callback;
|
|
99
|
+
}, [callback]);
|
|
100
|
+
useEffect4(() => {
|
|
101
|
+
if (!delay && delay !== 0) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const id = setInterval(() => savedCallback.current(), delay);
|
|
105
|
+
return () => clearInterval(id);
|
|
106
|
+
}, [delay]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/hooks/useMediaQuery.ts
|
|
110
|
+
import { useEffect as useEffect5, useState as useState2 } from "react";
|
|
111
|
+
function useMediaQuery(query) {
|
|
112
|
+
const getMatches = (query2) => {
|
|
113
|
+
if (typeof window !== "undefined") {
|
|
114
|
+
return window.matchMedia(query2).matches;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
};
|
|
118
|
+
const [matches, setMatches] = useState2(getMatches(query));
|
|
119
|
+
function handleChange() {
|
|
120
|
+
setMatches(getMatches(query));
|
|
121
|
+
}
|
|
122
|
+
useEffect5(() => {
|
|
123
|
+
const matchMedia = window.matchMedia(query);
|
|
124
|
+
handleChange();
|
|
125
|
+
if (matchMedia.addListener) {
|
|
126
|
+
matchMedia.addListener(handleChange);
|
|
127
|
+
} else {
|
|
128
|
+
matchMedia.addEventListener("change", handleChange);
|
|
129
|
+
}
|
|
130
|
+
return () => {
|
|
131
|
+
if (matchMedia.removeListener) {
|
|
132
|
+
matchMedia.removeListener(handleChange);
|
|
133
|
+
} else {
|
|
134
|
+
matchMedia.removeEventListener("change", handleChange);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}, [query]);
|
|
138
|
+
return matches;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/hooks/useOnClickOutside.ts
|
|
142
|
+
import "react";
|
|
143
|
+
function useOnClickOutside(ref, handler, mouseEvent = "mousedown") {
|
|
144
|
+
useEventListener(mouseEvent, (event) => {
|
|
145
|
+
const el = ref.current;
|
|
146
|
+
if (!el || el.contains(event.target)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
handler(event);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/hooks/useSessionStorage.ts
|
|
154
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useState as useState3 } from "react";
|
|
155
|
+
function parseJSON(value) {
|
|
156
|
+
try {
|
|
157
|
+
return value === "undefined" ? void 0 : JSON.parse(value ?? "");
|
|
158
|
+
} catch {
|
|
159
|
+
return void 0;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function useSessionStorage(key, initialValue) {
|
|
163
|
+
const readValue = useCallback2(() => {
|
|
164
|
+
if (typeof window === "undefined") {
|
|
165
|
+
return initialValue;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const item = window.sessionStorage.getItem(key);
|
|
169
|
+
return item ? parseJSON(item) : initialValue;
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.warn(`Error reading sessionStorage key \u201C${key}\u201D:`, error);
|
|
172
|
+
return initialValue;
|
|
173
|
+
}
|
|
174
|
+
}, [initialValue, key]);
|
|
175
|
+
const [storedValue, setStoredValue] = useState3(readValue);
|
|
176
|
+
const setValue = useEventCallback((value) => {
|
|
177
|
+
if (typeof window == "undefined") {
|
|
178
|
+
console.warn(`Tried setting sessionStorage key \u201C${key}\u201D even though environment is not a client`);
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const newValue = value instanceof Function ? value(storedValue) : value;
|
|
182
|
+
window.sessionStorage.setItem(key, JSON.stringify(newValue));
|
|
183
|
+
setStoredValue(newValue);
|
|
184
|
+
window.dispatchEvent(new Event("session-storage"));
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.warn(`Error setting sessionStorage key \u201C${key}\u201D:`, error);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
useEffect6(() => {
|
|
190
|
+
setStoredValue(readValue());
|
|
191
|
+
}, []);
|
|
192
|
+
const handleStorageChange = useCallback2(
|
|
193
|
+
(event) => {
|
|
194
|
+
if (event.key && event.key !== key) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
setStoredValue(readValue());
|
|
198
|
+
},
|
|
199
|
+
[key, readValue]
|
|
200
|
+
);
|
|
201
|
+
useEventListener("storage", handleStorageChange);
|
|
202
|
+
useEventListener("session-storage", handleStorageChange);
|
|
203
|
+
return [storedValue, setValue];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// src/hooks/useTheme.ts
|
|
207
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useState as useState4 } from "react";
|
|
208
|
+
var THEME_ATTRIBUTE = "data-mode";
|
|
209
|
+
var THEME_KEY = "theme";
|
|
210
|
+
function useTheme() {
|
|
211
|
+
const [theme, setTheme] = useState4(() => {
|
|
212
|
+
if (typeof window === "undefined") {
|
|
213
|
+
return "light";
|
|
214
|
+
}
|
|
215
|
+
const savedTheme = window.localStorage.getItem(THEME_KEY);
|
|
216
|
+
let initialTheme;
|
|
217
|
+
if (savedTheme === "dark" || savedTheme === "light") {
|
|
218
|
+
initialTheme = savedTheme;
|
|
219
|
+
} else {
|
|
220
|
+
initialTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
221
|
+
}
|
|
222
|
+
document.documentElement.setAttribute(THEME_ATTRIBUTE, initialTheme);
|
|
223
|
+
return initialTheme;
|
|
224
|
+
});
|
|
225
|
+
useEffect7(() => {
|
|
226
|
+
const observer = new MutationObserver((mutations) => {
|
|
227
|
+
mutations.forEach((mutation) => {
|
|
228
|
+
if (mutation.attributeName === THEME_ATTRIBUTE) {
|
|
229
|
+
const updatedTheme = mutation.target.getAttribute(THEME_ATTRIBUTE);
|
|
230
|
+
if (updatedTheme === "light" || updatedTheme === "dark") {
|
|
231
|
+
window.localStorage.setItem(THEME_KEY, updatedTheme);
|
|
232
|
+
setTheme(updatedTheme);
|
|
233
|
+
} else {
|
|
234
|
+
console.error(`Unexpected value for 'data-mode' attribute: ${updatedTheme}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
observer.observe(document.documentElement, {
|
|
240
|
+
attributes: true
|
|
241
|
+
});
|
|
242
|
+
return () => observer.disconnect();
|
|
243
|
+
}, []);
|
|
244
|
+
const updateTheme = useCallback3(
|
|
245
|
+
(theme2) => {
|
|
246
|
+
document.documentElement.setAttribute(THEME_ATTRIBUTE, theme2);
|
|
247
|
+
},
|
|
248
|
+
[document.documentElement]
|
|
249
|
+
);
|
|
250
|
+
return [theme, updateTheme];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/hooks/useWindowSize.ts
|
|
254
|
+
import { useState as useState5 } from "react";
|
|
255
|
+
function useWindowSize() {
|
|
256
|
+
const [windowSize, setWindowSize] = useState5({
|
|
257
|
+
height: 0,
|
|
258
|
+
width: 0
|
|
259
|
+
});
|
|
260
|
+
const handleSize = () => {
|
|
261
|
+
setWindowSize({
|
|
262
|
+
height: window.innerHeight,
|
|
263
|
+
width: window.innerWidth
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
useEventListener("resize", handleSize);
|
|
267
|
+
useIsomorphicLayoutEffect(() => {
|
|
268
|
+
handleSize();
|
|
269
|
+
}, []);
|
|
270
|
+
return windowSize;
|
|
271
|
+
}
|
|
272
|
+
export {
|
|
273
|
+
useDownload,
|
|
274
|
+
useEventCallback,
|
|
275
|
+
useEventListener,
|
|
276
|
+
useInterval,
|
|
277
|
+
useIsomorphicLayoutEffect,
|
|
278
|
+
useMediaQuery,
|
|
279
|
+
useNotificationsStore,
|
|
280
|
+
useOnClickOutside,
|
|
281
|
+
useSessionStorage,
|
|
282
|
+
useTheme,
|
|
283
|
+
useWindowSize
|
|
284
|
+
};
|
|
285
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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\nexport const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? 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\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 (typeof window !== 'undefined') {\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 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (matchMedia.addListener) {\n matchMedia.addListener(handleChange);\n } else {\n matchMedia.addEventListener('change', handleChange);\n }\n\n return () => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (matchMedia.removeListener) {\n matchMedia.removeListener(handleChange);\n } else {\n matchMedia.removeEventListener('change', handleChange);\n }\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 { type Dispatch, type SetStateAction, useCallback, useEffect, useState } from 'react';\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\ntype SetValue<T> = Dispatch<SetStateAction<T>>;\n\n// A wrapper for \"JSON.parse()\"\" to support \"undefined\" value\nfunction parseJSON<T>(value: null | string): T | undefined {\n try {\n return value === 'undefined' ? undefined : (JSON.parse(value ?? '') as T);\n } catch {\n return undefined;\n }\n}\n\nexport function useSessionStorage<T>(key: string, initialValue: T): [T, SetValue<T>] {\n // Get from session storage then\n // parse stored json or return initialValue\n const readValue = useCallback((): T => {\n // Prevent build error \"window is undefined\" but keep keep working\n if (typeof window === 'undefined') {\n return initialValue;\n }\n\n try {\n const item = window.sessionStorage.getItem(key);\n return item ? (parseJSON(item) as T) : initialValue;\n } catch (error) {\n console.warn(`Error reading sessionStorage key “${key}”:`, error);\n return initialValue;\n }\n }, [initialValue, key]);\n\n // State to store our value\n // Pass initial state function to useState so logic is only executed once\n const [storedValue, setStoredValue] = useState<T>(readValue);\n\n // Return a wrapped version of useState's setter function that ...\n // ... persists the new value to sessionStorage.\n const setValue: SetValue<T> = useEventCallback((value) => {\n // Prevent build error \"window is undefined\" but keeps working\n if (typeof window == 'undefined') {\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(storedValue) : value;\n\n // Save to session storage\n window.sessionStorage.setItem(key, JSON.stringify(newValue));\n\n // Save state\n setStoredValue(newValue);\n\n // We dispatch a custom event so every useSessionStorage hook are notified\n window.dispatchEvent(new Event('session-storage'));\n } catch (error) {\n console.warn(`Error setting sessionStorage key “${key}”:`, error);\n }\n });\n\n useEffect(() => {\n setStoredValue(readValue());\n }, []);\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\ntype Theme = 'dark' | 'light';\n\ntype UpdateTheme = (theme: Theme) => void;\n\nconst THEME_ATTRIBUTE = 'data-mode';\nconst THEME_KEY = 'theme';\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 (typeof window === 'undefined') {\n return 'light';\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('(prefers-color-scheme: dark)').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 { 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","useRef","useRef","useEffect","useEffect","useRef","useRef","useEffect","useEffect","useState","query","useCallback","useEffect","useState","useCallback","useState","useEffect","useCallback","useEffect","useState","theme","useState","useState"]}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { i18n as i18n$1 } from 'i18next';
|
|
2
|
+
|
|
3
|
+
declare const defaultNS = "translations";
|
|
4
|
+
declare const resources: {
|
|
5
|
+
readonly en: {
|
|
6
|
+
readonly translations: {
|
|
7
|
+
readonly 'datetime.days': readonly ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
8
|
+
readonly 'datetime.months': readonly ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
9
|
+
readonly 'form.append': "Append";
|
|
10
|
+
readonly 'form.errors.required': "This field is required";
|
|
11
|
+
readonly 'form.errors.unknown': "Unknown error";
|
|
12
|
+
readonly 'form.radio.labels.false': "False";
|
|
13
|
+
readonly 'form.radio.labels.true': "True";
|
|
14
|
+
readonly 'form.remove': "Remove";
|
|
15
|
+
readonly 'form.reset': "Clear";
|
|
16
|
+
readonly 'form.submit': "Submit";
|
|
17
|
+
readonly 'notifications.types.error': "Error";
|
|
18
|
+
readonly 'notifications.types.info': "Info";
|
|
19
|
+
readonly 'notifications.types.success': "Success";
|
|
20
|
+
readonly 'notifications.types.warning': "Warning";
|
|
21
|
+
readonly 'searchBar.placeholder': "Search...";
|
|
22
|
+
readonly 'table.pagination.info': "Showing {{first}} to {{last}} of {{total}} results";
|
|
23
|
+
readonly 'table.pagination.next': "Next";
|
|
24
|
+
readonly 'table.pagination.previous': "Previous";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
readonly fr: {
|
|
28
|
+
readonly translations: {
|
|
29
|
+
readonly 'datetime.days': readonly ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"];
|
|
30
|
+
readonly 'datetime.months': readonly ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
|
|
31
|
+
readonly 'form.append': "Ajouter";
|
|
32
|
+
readonly 'form.errors.required': "Ce champ est obligatoire";
|
|
33
|
+
readonly 'form.errors.unknown': "Erreur inconnue";
|
|
34
|
+
readonly 'form.radio.labels.false': "Faux";
|
|
35
|
+
readonly 'form.radio.labels.true': "Vrai";
|
|
36
|
+
readonly 'form.remove': "Supprimer";
|
|
37
|
+
readonly 'form.reset': "Réinitialiser";
|
|
38
|
+
readonly 'form.submit': "Soumettre";
|
|
39
|
+
readonly 'notifications.types.error': "Erreur";
|
|
40
|
+
readonly 'notifications.types.info': "Attention";
|
|
41
|
+
readonly 'notifications.types.success': "Succès";
|
|
42
|
+
readonly 'notifications.types.warning': "Avertissement";
|
|
43
|
+
readonly 'searchBar.placeholder': "Rechercher...";
|
|
44
|
+
readonly 'table.pagination.info': "Affichage de {{first}} à {{last}} sur {{total}} résultats";
|
|
45
|
+
readonly 'table.pagination.next': "Suivante";
|
|
46
|
+
readonly 'table.pagination.previous': "Précédente";
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
declare const i18n: i18n$1;
|
|
51
|
+
|
|
52
|
+
export { i18n as default, defaultNS, resources };
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/i18n.ts
|
|
2
|
+
import { createInstance } from "i18next";
|
|
3
|
+
import { initReactI18next } from "react-i18next";
|
|
4
|
+
var defaultNS = "translations";
|
|
5
|
+
var resources = {
|
|
6
|
+
en: {
|
|
7
|
+
translations: {
|
|
8
|
+
"datetime.days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
|
|
9
|
+
"datetime.months": [
|
|
10
|
+
"January",
|
|
11
|
+
"February",
|
|
12
|
+
"March",
|
|
13
|
+
"April",
|
|
14
|
+
"May",
|
|
15
|
+
"June",
|
|
16
|
+
"July",
|
|
17
|
+
"August",
|
|
18
|
+
"September",
|
|
19
|
+
"October",
|
|
20
|
+
"November",
|
|
21
|
+
"December"
|
|
22
|
+
],
|
|
23
|
+
"form.append": "Append",
|
|
24
|
+
"form.errors.required": "This field is required",
|
|
25
|
+
"form.errors.unknown": "Unknown error",
|
|
26
|
+
"form.radio.labels.false": "False",
|
|
27
|
+
"form.radio.labels.true": "True",
|
|
28
|
+
"form.remove": "Remove",
|
|
29
|
+
"form.reset": "Clear",
|
|
30
|
+
"form.submit": "Submit",
|
|
31
|
+
"notifications.types.error": "Error",
|
|
32
|
+
"notifications.types.info": "Info",
|
|
33
|
+
"notifications.types.success": "Success",
|
|
34
|
+
"notifications.types.warning": "Warning",
|
|
35
|
+
"searchBar.placeholder": "Search...",
|
|
36
|
+
"table.pagination.info": "Showing {{first}} to {{last}} of {{total}} results",
|
|
37
|
+
"table.pagination.next": "Next",
|
|
38
|
+
"table.pagination.previous": "Previous"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
fr: {
|
|
42
|
+
translations: {
|
|
43
|
+
"datetime.days": ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"],
|
|
44
|
+
"datetime.months": [
|
|
45
|
+
"Janvier",
|
|
46
|
+
"F\xE9vrier",
|
|
47
|
+
"Mars",
|
|
48
|
+
"Avril",
|
|
49
|
+
"Mai",
|
|
50
|
+
"Juin",
|
|
51
|
+
"Juillet",
|
|
52
|
+
"Ao\xFBt",
|
|
53
|
+
"Septembre",
|
|
54
|
+
"Octobre",
|
|
55
|
+
"Novembre",
|
|
56
|
+
"D\xE9cembre"
|
|
57
|
+
],
|
|
58
|
+
"form.append": "Ajouter",
|
|
59
|
+
"form.errors.required": "Ce champ est obligatoire",
|
|
60
|
+
"form.errors.unknown": "Erreur inconnue",
|
|
61
|
+
"form.radio.labels.false": "Faux",
|
|
62
|
+
"form.radio.labels.true": "Vrai",
|
|
63
|
+
"form.remove": "Supprimer",
|
|
64
|
+
"form.reset": "R\xE9initialiser",
|
|
65
|
+
"form.submit": "Soumettre",
|
|
66
|
+
"notifications.types.error": "Erreur",
|
|
67
|
+
"notifications.types.info": "Attention",
|
|
68
|
+
"notifications.types.success": "Succ\xE8s",
|
|
69
|
+
"notifications.types.warning": "Avertissement",
|
|
70
|
+
"searchBar.placeholder": "Rechercher...",
|
|
71
|
+
"table.pagination.info": "Affichage de {{first}} \xE0 {{last}} sur {{total}} r\xE9sultats",
|
|
72
|
+
"table.pagination.next": "Suivante",
|
|
73
|
+
"table.pagination.previous": "Pr\xE9c\xE9dente"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var i18n = createInstance({
|
|
78
|
+
defaultNS,
|
|
79
|
+
fallbackLng: "en",
|
|
80
|
+
interpolation: {
|
|
81
|
+
escapeValue: false
|
|
82
|
+
},
|
|
83
|
+
resources,
|
|
84
|
+
returnObjects: true,
|
|
85
|
+
supportedLngs: ["en", "fr"]
|
|
86
|
+
});
|
|
87
|
+
void i18n.use(initReactI18next).init();
|
|
88
|
+
var i18n_default = i18n;
|
|
89
|
+
export {
|
|
90
|
+
i18n_default as default,
|
|
91
|
+
defaultNS,
|
|
92
|
+
resources
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=i18n.js.map
|
package/dist/i18n.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n.ts"],"sourcesContent":["import { type i18n as I18n, createInstance } from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\nconst defaultNS = 'translations';\n\nconst resources = {\n en: {\n translations: {\n 'datetime.days': ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\n 'datetime.months': [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December'\n ],\n 'form.append': 'Append',\n 'form.errors.required': 'This field is required',\n 'form.errors.unknown': 'Unknown error',\n 'form.radio.labels.false': 'False',\n 'form.radio.labels.true': 'True',\n 'form.remove': 'Remove',\n 'form.reset': 'Clear',\n 'form.submit': 'Submit',\n 'notifications.types.error': 'Error',\n 'notifications.types.info': 'Info',\n 'notifications.types.success': 'Success',\n 'notifications.types.warning': 'Warning',\n 'searchBar.placeholder': 'Search...',\n 'table.pagination.info': 'Showing {{first}} to {{last}} of {{total}} results',\n 'table.pagination.next': 'Next',\n 'table.pagination.previous': 'Previous'\n }\n },\n fr: {\n translations: {\n 'datetime.days': ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'],\n 'datetime.months': [\n 'Janvier',\n 'Février',\n 'Mars',\n 'Avril',\n 'Mai',\n 'Juin',\n 'Juillet',\n 'Août',\n 'Septembre',\n 'Octobre',\n 'Novembre',\n 'Décembre'\n ],\n 'form.append': 'Ajouter',\n 'form.errors.required': 'Ce champ est obligatoire',\n 'form.errors.unknown': 'Erreur inconnue',\n 'form.radio.labels.false': 'Faux',\n 'form.radio.labels.true': 'Vrai',\n 'form.remove': 'Supprimer',\n 'form.reset': 'Réinitialiser',\n 'form.submit': 'Soumettre',\n 'notifications.types.error': 'Erreur',\n 'notifications.types.info': 'Attention',\n 'notifications.types.success': 'Succès',\n 'notifications.types.warning': 'Avertissement',\n 'searchBar.placeholder': 'Rechercher...',\n 'table.pagination.info': 'Affichage de {{first}} à {{last}} sur {{total}} résultats',\n 'table.pagination.next': 'Suivante',\n 'table.pagination.previous': 'Précédente'\n }\n }\n} as const;\n\nconst i18n = createInstance({\n defaultNS,\n fallbackLng: 'en',\n interpolation: {\n escapeValue: false\n },\n resources,\n returnObjects: true,\n supportedLngs: ['en', 'fr']\n}) as I18n;\n\nvoid i18n.use(initReactI18next).init();\n\nexport { defaultNS, resources };\n\nexport default i18n;\n"],"mappings":";AAAA,SAA4B,sBAAsB;AAClD,SAAS,wBAAwB;AAEjC,IAAM,YAAY;AAElB,IAAM,YAAY;AAAA,EAChB,IAAI;AAAA,IACF,cAAc;AAAA,MACZ,iBAAiB,CAAC,UAAU,UAAU,WAAW,aAAa,YAAY,UAAU,UAAU;AAAA,MAC9F,mBAAmB;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,eAAe;AAAA,MACf,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,2BAA2B;AAAA,MAC3B,0BAA0B;AAAA,MAC1B,eAAe;AAAA,MACf,cAAc;AAAA,MACd,eAAe;AAAA,MACf,6BAA6B;AAAA,MAC7B,4BAA4B;AAAA,MAC5B,+BAA+B;AAAA,MAC/B,+BAA+B;AAAA,MAC/B,yBAAyB;AAAA,MACzB,yBAAyB;AAAA,MACzB,yBAAyB;AAAA,MACzB,6BAA6B;AAAA,IAC/B;AAAA,EACF;AAAA,EACA,IAAI;AAAA,IACF,cAAc;AAAA,MACZ,iBAAiB,CAAC,YAAY,SAAS,SAAS,YAAY,SAAS,YAAY,QAAQ;AAAA,MACzF,mBAAmB;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,eAAe;AAAA,MACf,wBAAwB;AAAA,MACxB,uBAAuB;AAAA,MACvB,2BAA2B;AAAA,MAC3B,0BAA0B;AAAA,MAC1B,eAAe;AAAA,MACf,cAAc;AAAA,MACd,eAAe;AAAA,MACf,6BAA6B;AAAA,MAC7B,4BAA4B;AAAA,MAC5B,+BAA+B;AAAA,MAC/B,+BAA+B;AAAA,MAC/B,yBAAyB;AAAA,MACzB,yBAAyB;AAAA,MACzB,yBAAyB;AAAA,MACzB,6BAA6B;AAAA,IAC/B;AAAA,EACF;AACF;AAEA,IAAM,OAAO,eAAe;AAAA,EAC1B;AAAA,EACA,aAAa;AAAA,EACb,eAAe;AAAA,IACb,aAAa;AAAA,EACf;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,eAAe,CAAC,MAAM,IAAI;AAC5B,CAAC;AAED,KAAK,KAAK,IAAI,gBAAgB,EAAE,KAAK;AAIrC,IAAO,eAAQ;","names":[]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer base {
|
|
6
|
+
:root {
|
|
7
|
+
--background: theme(colors.slate.100);
|
|
8
|
+
--foreground: theme(colors.slate.900);
|
|
9
|
+
|
|
10
|
+
--muted: theme(colors.slate.200);
|
|
11
|
+
--muted-foreground: theme(colors.slate.700);
|
|
12
|
+
|
|
13
|
+
--accent: theme(colors.slate.200);
|
|
14
|
+
--accent-foreground: theme(colors.slate.700);
|
|
15
|
+
|
|
16
|
+
--popover: theme(colors.white);
|
|
17
|
+
--popover-foreground: theme(colors.slate.900);
|
|
18
|
+
|
|
19
|
+
--border: theme(colors.slate.300);
|
|
20
|
+
--input: theme(colors.slate.300);
|
|
21
|
+
|
|
22
|
+
--card: theme(colors.white);
|
|
23
|
+
--card-foreground: theme(colors.slate.900);
|
|
24
|
+
|
|
25
|
+
--primary: theme(colors.slate.800);
|
|
26
|
+
--primary-foreground: theme(colors.slate.100);
|
|
27
|
+
|
|
28
|
+
--secondary: theme(colors.slate.50);
|
|
29
|
+
--secondary-foreground: theme(colors.slate.900);
|
|
30
|
+
|
|
31
|
+
--destructive: theme(colors.red.600);
|
|
32
|
+
--destructive-foreground: theme(colors.white);
|
|
33
|
+
|
|
34
|
+
--ring: theme(colors.sky.500);
|
|
35
|
+
|
|
36
|
+
--radius: 0.5rem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[data-mode='dark'] {
|
|
40
|
+
--background: theme(colors.slate.900);
|
|
41
|
+
--foreground: theme(colors.slate.100);
|
|
42
|
+
|
|
43
|
+
--muted: theme(colors.slate.800);
|
|
44
|
+
--muted-foreground: theme(colors.slate.300);
|
|
45
|
+
|
|
46
|
+
--accent: theme(colors.slate.800);
|
|
47
|
+
--accent-foreground: theme(colors.slate.300);
|
|
48
|
+
|
|
49
|
+
--popover: theme(colors.slate.800);
|
|
50
|
+
--popover-foreground: theme(colors.slate.100);
|
|
51
|
+
|
|
52
|
+
--border: theme(colors.slate.700);
|
|
53
|
+
--input: theme(colors.slate.700);
|
|
54
|
+
|
|
55
|
+
--card: theme(colors.slate.800);
|
|
56
|
+
--card-foreground: theme(colors.slate.100);
|
|
57
|
+
|
|
58
|
+
--primary: theme(colors.sky.700);
|
|
59
|
+
--primary-foreground: theme(colors.slate.100);
|
|
60
|
+
|
|
61
|
+
--secondary: theme(colors.slate.800);
|
|
62
|
+
--secondary-foreground: theme(colors.slate.100);
|
|
63
|
+
|
|
64
|
+
--ring: theme(colors.slate.800);
|
|
65
|
+
|
|
66
|
+
--radius: 0.5rem;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@layer base {
|
|
71
|
+
* {
|
|
72
|
+
@apply border-border;
|
|
73
|
+
}
|
|
74
|
+
body {
|
|
75
|
+
@apply bg-background text-foreground;
|
|
76
|
+
font-feature-settings:
|
|
77
|
+
'rlig' 1,
|
|
78
|
+
'calt' 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|