diff --git a/src/components/Viewport/Viewport.stories.tsx b/src/components/Viewport/Viewport.stories.tsx
index 66fb6a7..36ffddf 100644
--- a/src/components/Viewport/Viewport.stories.tsx
+++ b/src/components/Viewport/Viewport.stories.tsx
@@ -37,7 +37,7 @@ export const Viewport = () => {
const App = () => {
const [arr, setArr] = useState(Array.from(Array(5)));
- const {setMode, resetSizes, setSizes} = useViewport();
+ const {setMode, setSizes} = useViewport();
return (
{
diff --git a/src/plugin/index.ts b/src/plugin/index.ts
index 5ba2e11..3383d12 100644
--- a/src/plugin/index.ts
+++ b/src/plugin/index.ts
@@ -36,7 +36,7 @@ export default definePlugin((options: PluginOptions = {}) => {
let styleBuilder: BuilderContract;
return {
- name: "adnbn-ui",
+ name: "addon-ui",
startup: ({config}) => {
const {srcDir, appsDir, sharedDir, app, appSrcDir} = config;
const normalizeThemeDir = path.normalize(themeDir).split(path.sep);
diff --git a/src/providers/theme/ThemeProvider.tsx b/src/providers/theme/ThemeProvider.tsx
index 1c05051..6a41698 100644
--- a/src/providers/theme/ThemeProvider.tsx
+++ b/src/providers/theme/ThemeProvider.tsx
@@ -1,11 +1,12 @@
-import React, {FC, PropsWithChildren, useCallback, useEffect, useState} from "react";
-import {getBrowser} from "adnbn";
+import React, {FC, PropsWithChildren, useCallback, useEffect, useMemo, useState} from "react";
import {ThemeContext} from "./context";
import {Theme, ThemeStorageContract} from "../../types/theme";
import {Config} from "../../types/config";
+import ThemeStorage from "./ThemeStorage";
+
const isDarkMedia = () => window?.matchMedia("(prefers-color-scheme: dark)")?.matches;
const isValid = (theme: Theme | undefined): theme is Theme => {
@@ -13,22 +14,29 @@ const isValid = (theme: Theme | undefined): theme is Theme => {
};
export interface ThemeProviderProps extends Pick {
- storage?: ThemeStorageContract;
- view?: string;
+ storage?: ThemeStorageContract | true;
}
-const ThemeProvider: FC> = ({children, components, storage, view}) => {
+const ThemeProvider: FC> = ({children, components, storage}) => {
const [theme, setTheme] = useState(() => (isDarkMedia() ? Theme.Dark : Theme.Light));
+ const currentStorage: ThemeStorageContract | undefined = useMemo(() => {
+ if (!storage) return;
+
+ if (storage === true) return new ThemeStorage();
+
+ return storage;
+ }, [storage]);
+
const changeTheme = useCallback(
(theme: Theme) => {
- if (storage) {
- storage.change(theme).catch(e => console.error("ThemeProvider: set theme to storage error", e));
+ if (currentStorage) {
+ currentStorage.change(theme).catch(e => console.error("ThemeProvider: set theme to storage error", e));
} else {
setTheme(theme);
}
},
- [storage]
+ [currentStorage]
);
const toggleTheme = useCallback(() => {
@@ -36,31 +44,20 @@ const ThemeProvider: FC> = ({children, com
}, [theme, changeTheme]);
useEffect(() => {
- if (!storage) return;
+ if (!currentStorage) return;
- storage
+ currentStorage
.get()
.then(newTheme => isValid(newTheme) && setTheme(newTheme))
.catch(e => console.error("ThemeProvider: get theme from storage error", e));
- const unsubscribe = storage.watch(newTheme => isValid(newTheme) && setTheme(newTheme));
+ const unsubscribe = currentStorage.watch(newTheme => isValid(newTheme) && setTheme(newTheme));
return () => unsubscribe();
- }, [storage]);
+ }, [currentStorage]);
useEffect(() => {
- const html = document.querySelector("html");
- if (html) {
- html.setAttribute("theme", theme);
-
- view && html.setAttribute("view", view);
-
- try {
- html.setAttribute("browser", getBrowser());
- } catch (e) {
- console.error("ThemeProvider: get browser error", e);
- }
- }
+ document.querySelector("html")?.setAttribute("theme", theme);
}, [theme]);
return (
diff --git a/src/providers/theme/ThemeStorage.tsx b/src/providers/theme/ThemeStorage.tsx
index 2f8a769..af89dea 100644
--- a/src/providers/theme/ThemeStorage.tsx
+++ b/src/providers/theme/ThemeStorage.tsx
@@ -1,14 +1,21 @@
-import {Storage} from "@addon-core/storage";
+import {Storage, StorageProvider} from "@addon-core/storage";
import {Theme, ThemeStorageContract} from "../../types/theme";
+export type ThemeStorageState = Record;
+
export default class implements ThemeStorageContract {
- private readonly storage = new Storage>({
+ protected storage: StorageProvider = new Storage({
area: "local",
namespace: "addon-ui",
});
- private readonly key = "theme";
+ protected key: string = "theme";
+
+ constructor(storage?: StorageProvider, key?: string) {
+ this.storage = storage ? storage : this.storage;
+ this.key = key ? key : this.key;
+ }
public async get(): Promise {
return await this.storage.get(this.key);
diff --git a/src/providers/theme/index.ts b/src/providers/theme/index.ts
index 2a96847..01ce551 100644
--- a/src/providers/theme/index.ts
+++ b/src/providers/theme/index.ts
@@ -1,3 +1,3 @@
-export {default as ThemeProvider} from "./ThemeProvider";
-export {default as ThemeStorage} from "./ThemeStorage";
+export {default as ThemeProvider, type ThemeProviderProps} from "./ThemeProvider";
+export {default as ThemeStorage, type ThemeStorageState} from "./ThemeStorage";
export {useTheme, useComponentProps} from "./context";
diff --git a/src/providers/ui/UIProvider.tsx b/src/providers/ui/UIProvider.tsx
index 4194c5b..f6e633d 100644
--- a/src/providers/ui/UIProvider.tsx
+++ b/src/providers/ui/UIProvider.tsx
@@ -1,9 +1,12 @@
-import React, {FC, PropsWithChildren, useMemo, useRef} from "react";
+import React, {FC, PropsWithChildren, useEffect, useMemo} from "react";
+import {getBrowser} from "adnbn";
+
import {merge} from "ts-deepmerge";
-import {ExtraProvider, IconsProvider, ThemeProvider, ThemeStorage} from "../index";
+import {ExtraProvider} from "../extra";
+import {IconsProvider} from "../icons";
+import {ThemeProvider, ThemeProviderProps} from "../theme";
-import {ThemeStorageContract} from "../../types/theme";
import {ComponentsProps, Config, ExtraProps, Icons} from "../../types/config";
import "./styles/default.scss";
@@ -12,22 +15,18 @@ import "addon-ui-style.scss";
import config from "addon-ui-config";
-export type UIProviderProps = Partial & {
+export interface UIProviderProps extends Partial, Pick {
view?: string;
-};
+}
const UIProvider: FC> = ({
children,
components = {},
extra = {},
icons = {},
+ storage,
view,
}) => {
- const storageRef = useRef(null);
-
- if (!storageRef.current) {
- storageRef.current = new ThemeStorage();
- }
const componentsProps = useMemo(() => merge(config.components || {}, components), [components]);
@@ -35,8 +34,18 @@ const UIProvider: FC> = ({
const svgIcons = useMemo(() => merge(config.icons || {}, icons), [icons]);
+ useEffect(() => {
+ const html = document.querySelector("html");
+ if (html) {
+ if (view) {
+ html.setAttribute("view", view);
+ }
+ html.setAttribute("browser", getBrowser());
+ }
+ }, [view]);
+
return (
-
+
{children}