@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.
@@ -0,0 +1,129 @@
1
+ import {
2
+ isBrowser
3
+ } from "./chunk-PAAJ5AH3.js";
4
+
5
+ // src/hooks/useIsomorphicLayoutEffect.ts
6
+ import { useEffect, useLayoutEffect } from "react";
7
+ var useIsomorphicLayoutEffect = isBrowser() ? useLayoutEffect : useEffect;
8
+
9
+ // src/hooks/useEventListener.ts
10
+ import { useEffect as useEffect2, useRef } from "react";
11
+ function useEventListener(eventName, handler, element, options) {
12
+ const savedHandler = useRef(handler);
13
+ useIsomorphicLayoutEffect(() => {
14
+ savedHandler.current = handler;
15
+ }, [handler]);
16
+ useEffect2(() => {
17
+ const targetElement = element?.current ?? window;
18
+ if (!(targetElement && targetElement.addEventListener))
19
+ return;
20
+ const listener = (event) => savedHandler.current(event);
21
+ targetElement.addEventListener(eventName, listener, options);
22
+ return () => {
23
+ targetElement.removeEventListener(eventName, listener, options);
24
+ };
25
+ }, [eventName, element, options]);
26
+ }
27
+
28
+ // src/hooks/useWindowSize.ts
29
+ import { useState } from "react";
30
+ function useWindowSize() {
31
+ const [windowSize, setWindowSize] = useState({
32
+ height: 0,
33
+ width: 0
34
+ });
35
+ const handleSize = () => {
36
+ setWindowSize({
37
+ height: window.innerHeight,
38
+ width: window.innerWidth
39
+ });
40
+ };
41
+ useEventListener("resize", handleSize);
42
+ useIsomorphicLayoutEffect(() => {
43
+ handleSize();
44
+ }, []);
45
+ return windowSize;
46
+ }
47
+
48
+ // src/hooks/useTheme.ts
49
+ import { useCallback, useEffect as useEffect3, useState as useState2 } from "react";
50
+ var DEFAULT_THEME = "light";
51
+ var THEME_ATTRIBUTE = "data-mode";
52
+ var THEME_KEY = "theme";
53
+ var SYS_DARK_MEDIA_QUERY = "(prefers-color-scheme: dark)";
54
+ function useTheme() {
55
+ const [theme, setTheme] = useState2(() => {
56
+ if (!isBrowser()) {
57
+ return DEFAULT_THEME;
58
+ }
59
+ const savedTheme = window.localStorage.getItem(THEME_KEY);
60
+ let initialTheme;
61
+ if (savedTheme === "dark" || savedTheme === "light") {
62
+ initialTheme = savedTheme;
63
+ } else {
64
+ initialTheme = window.matchMedia(SYS_DARK_MEDIA_QUERY).matches ? "dark" : "light";
65
+ }
66
+ document.documentElement.setAttribute(THEME_ATTRIBUTE, initialTheme);
67
+ return initialTheme;
68
+ });
69
+ useEffect3(() => {
70
+ const observer = new MutationObserver((mutations) => {
71
+ mutations.forEach((mutation) => {
72
+ if (mutation.attributeName === THEME_ATTRIBUTE) {
73
+ const updatedTheme = mutation.target.getAttribute(THEME_ATTRIBUTE);
74
+ if (updatedTheme === "light" || updatedTheme === "dark") {
75
+ window.localStorage.setItem(THEME_KEY, updatedTheme);
76
+ setTheme(updatedTheme);
77
+ } else {
78
+ console.error(`Unexpected value for 'data-mode' attribute: ${updatedTheme}`);
79
+ }
80
+ }
81
+ });
82
+ });
83
+ observer.observe(document.documentElement, {
84
+ attributes: true
85
+ });
86
+ return () => observer.disconnect();
87
+ }, []);
88
+ const updateTheme = useCallback(
89
+ (theme2) => {
90
+ document.documentElement.setAttribute(THEME_ATTRIBUTE, theme2);
91
+ },
92
+ [document.documentElement]
93
+ );
94
+ return [theme, updateTheme];
95
+ }
96
+
97
+ // src/hooks/useNotificationsStore.ts
98
+ import { create } from "zustand";
99
+ var useNotificationsStore = create((set) => ({
100
+ addNotification: (notification) => {
101
+ set((state) => ({
102
+ notifications: [...state.notifications, { id: Date.now(), ...notification }]
103
+ }));
104
+ },
105
+ dismissNotification: (id) => {
106
+ set((state) => ({
107
+ notifications: state.notifications.filter((notification) => notification.id !== id)
108
+ }));
109
+ },
110
+ notifications: []
111
+ }));
112
+
113
+ // src/context/LegacyStepperContext.tsx
114
+ import { createContext } from "react";
115
+ var LegacyStepperContext = createContext(null);
116
+
117
+ export {
118
+ LegacyStepperContext,
119
+ useIsomorphicLayoutEffect,
120
+ useEventListener,
121
+ useWindowSize,
122
+ DEFAULT_THEME,
123
+ THEME_ATTRIBUTE,
124
+ THEME_KEY,
125
+ SYS_DARK_MEDIA_QUERY,
126
+ useTheme,
127
+ useNotificationsStore
128
+ };
129
+ //# sourceMappingURL=chunk-IP3LSCUG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useIsomorphicLayoutEffect.ts","../src/hooks/useEventListener.ts","../src/hooks/useWindowSize.ts","../src/hooks/useTheme.ts","../src/hooks/useNotificationsStore.ts","../src/context/LegacyStepperContext.tsx"],"sourcesContent":["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 { 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","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 { 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 React, { createContext } from 'react';\n\n/** @deprecated */\nexport const LegacyStepperContext = createContext<{\n index: number;\n updateIndex: React.Dispatch<'decrement' | 'increment'>;\n}>(null!);\n"],"mappings":"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","names":["useEffect","useEffect","useEffect","useState","useState","useEffect","theme"]}