diff --git a/src/config-context.interface.ts b/src/config-context.interface.ts new file mode 100644 index 0000000..39eae90 --- /dev/null +++ b/src/config-context.interface.ts @@ -0,0 +1,34 @@ +export type IBaseConfig = { value: TConfigValueType }; + +type IConfigWithFilters = ( + | { browser: string } + | { platform: string } + | { os: string } + | { engine: string } +) & + IBaseConfig; + +type IConfigFilters = [ + IBaseConfig, + ...IConfigWithFilters[] +]; + +/** + * A strongly typed `userConfig` object required to create the `IConfig` object. + */ +export type IUserConfig = { + [K in keyof TConfig]: IConfigFilters; +}; + +/** + * A type-safe object of the config parameters and corresponding values returned by the `useConfig` hook. + */ +export type IConfig = { + [K in keyof TConfig]: IBaseConfig["value"]; +}; + +/** + * A dynamic type to infer the filters of a specific config parameter. + */ +export type IDynamicConfigFilters = + IUserConfig[Extract]; diff --git a/src/config-context.tsx b/src/config-context.tsx new file mode 100644 index 0000000..80db043 --- /dev/null +++ b/src/config-context.tsx @@ -0,0 +1,28 @@ +import type { + IConfig, + IDynamicConfigFilters, + IUserConfig, +} from "./config-context.interface"; + +// TODO: move to utils +const getBaseConfig = ( + configFilters: IDynamicConfigFilters +) => + configFilters.find( + (configValue) => + Object.keys(configValue).length === 1 && "value" in configValue + )!; + +export function createConfig( + userConfig: IUserConfig +) { + console.log("createConfig"); + const configValues: IConfig = {} as IConfig; + for (const key in userConfig) { + const configFilters = userConfig[key]; + const baseConfig = getBaseConfig(configFilters); + configValues[key] = baseConfig.value; + } + + return () => configValues; +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..bc94574 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,19 @@ +import { createConfig } from "./config-context"; +import { Browser } from "./enums"; + +export const useConfig = createConfig({ + showButton: [ + { + value: true, + }, + { + browser: Browser.Chrome, + value: false, + }, + ], + enableModernUi: [ + { + value: 33, + }, + ], +}); diff --git a/src/index.tsx b/src/index.tsx index e6b9641..2397f7a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,8 +1,41 @@ import React from "react"; import ReactDOM from "react-dom/client"; +import { useConfig } from "./config"; + +const App = () => ( +
+ +
+ +
+ +
+); + +const Component1 = () => { + const _config = useConfig(); + console.log("", _config); + return Component 1; +}; + +const Component2 = () => { + const _config = useConfig(); + console.log("", _config); + return Component 2; +}; + +const Component3 = () => { + const [counter, setCounter] = React.useState(0); + + const _config = useConfig(); + const onClick = () => setCounter(counter + 1); + + console.log("", _config); + return ; +}; const root = ReactDOM.createRoot( document.getElementById("root") as HTMLElement ); -root.render(
hi
); +root.render(); diff --git a/src/project-config.ts b/src/project-config.ts new file mode 100644 index 0000000..e69de29