diff --git a/frontend/packages/ui/.storybook/main.ts b/frontend/packages/ui/.storybook/main.ts new file mode 100644 index 00000000..b66e7ae4 --- /dev/null +++ b/frontend/packages/ui/.storybook/main.ts @@ -0,0 +1,42 @@ +import type { StorybookConfig } from '@storybook/react-vite'; +import { vanillaExtractPlugin as veEsbuildPlugin } from '@vanilla-extract/esbuild-plugin'; +import { vanillaExtractPlugin as veVitePlugin } from '@vanilla-extract/vite-plugin'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + viteFinal: async (config) => { + const { mergeConfig } = await import('vite'); + const filename = fileURLToPath(import.meta.url); + const dirname = path.dirname(filename); + + return mergeConfig( + config, + { + plugins: [veVitePlugin()], + optimizeDeps: { + esbuildOptions: { + plugins: [veEsbuildPlugin({ runtime: true })], + }, + }, + resolve: { + alias: { + '@': path.resolve(dirname, '../src'), + '@hooks': path.resolve(dirname, '../src/hooks'), + '@components': path.resolve(dirname, '../src/components'), + }, + }, + }); + }, +}; +export default config; diff --git a/frontend/packages/ui/.storybook/preview.ts b/frontend/packages/ui/.storybook/preview.ts new file mode 100644 index 00000000..3792e452 --- /dev/null +++ b/frontend/packages/ui/.storybook/preview.ts @@ -0,0 +1,16 @@ +import '@endolphin/theme/css'; + +import type { Preview } from '@storybook/react'; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/frontend/packages/ui/package.json b/frontend/packages/ui/package.json index dee142cf..50c0a78e 100644 --- a/frontend/packages/ui/package.json +++ b/frontend/packages/ui/package.json @@ -11,7 +11,9 @@ "scripts": { "build": "tsup --clean", "start": "tsup --watch", - "test": "vitest" + "test": "vitest", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "publishConfig": { "access": "public" diff --git a/frontend/packages/ui/src/hooks/useGroup.ts b/frontend/packages/ui/src/hooks/useGroup.ts index 53c7f595..02fe0f6a 100644 --- a/frontend/packages/ui/src/hooks/useGroup.ts +++ b/frontend/packages/ui/src/hooks/useGroup.ts @@ -1,4 +1,4 @@ -import { useEffect, useReducer } from 'react'; +import { useReducer } from 'react'; type State = { checkedList: Set; @@ -36,10 +36,7 @@ const reducer = (state: State, action: Action): State => { } case 'INIT': { - return { - checkedList: new Set(action.defaultCheckedList), - isAllChecked: action.defaultCheckedList.length === action.itemIds.length, - }; + return initializeState(action.defaultCheckedList, action.itemIds); } default: @@ -47,6 +44,11 @@ const reducer = (state: State, action: Action): State => { } }; +const initializeState = (defaultCheckedList: number[], itemIds: number[]): State => ({ + checkedList: new Set(defaultCheckedList), + isAllChecked: defaultCheckedList.length === itemIds.length, +}); + interface GroupStateProps { defaultCheckedList?: number[]; itemIds: number[]; @@ -65,15 +67,7 @@ export const useGroup = ({ defaultCheckedList = [], itemIds, }: GroupStateProps): GroupStateReturn => { - const [state, dispatch] = useReducer( - reducer, { - checkedList: new Set(defaultCheckedList), - isAllChecked: defaultCheckedList.length === itemIds.length, - }); - - useEffect(() => { - dispatch({ type: 'INIT', defaultCheckedList, itemIds }); - }, [defaultCheckedList, itemIds]); + const [state, dispatch] = useReducer(reducer, initializeState(defaultCheckedList, itemIds)); const handleToggleCheck = (id: number) => { dispatch({ type: 'TOGGLE_ITEM', id, itemIds }); diff --git a/frontend/packages/ui/src/index.ts b/frontend/packages/ui/src/index.ts index b1fceab1..d27965be 100644 --- a/frontend/packages/ui/src/index.ts +++ b/frontend/packages/ui/src/index.ts @@ -16,4 +16,5 @@ export { Tab } from './components/Tab'; export { Text } from './components/Text'; export { Toggle } from './components/Toggle'; export { default as Tooltip } from './components/Tooltip'; +export { useCheckbox } from './hooks/useCheckbox'; export { useGroupContext, useUnsafeGroupContext } from '@components/Group/GroupContext'; \ No newline at end of file