diff --git a/front/src/components/organisms/event/venueedit/palette/ColorPalette.tsx b/front/src/components/organisms/event/venueedit/palette/ColorPalette.tsx index 03dda2d..23f3139 100644 --- a/front/src/components/organisms/event/venueedit/palette/ColorPalette.tsx +++ b/front/src/components/organisms/event/venueedit/palette/ColorPalette.tsx @@ -5,23 +5,21 @@ import ColorButton from '@/components/organisms/event/venueedit/palette/ColorBut import { Color } from 'react-color' import ToggleToEraseButton from '@/components/organisms/event/venueedit/palette/ToggleToEraseButton' import { useSubToolSelection } from '@/hooks/event/venueedit/useSubToolSelection' +import { useSelectedColor } from '@/hooks/event/venueedit/submenu/useSelectedColor' interface ColorPaletteProps { colors: Color[] - selectedColor: Color - onColorSelect: (color: Color) => void onAddColor?: (color: Color) => void onDeleteColor: (color: Color) => void } export default function ColorPalette({ colors, - selectedColor, - onColorSelect, onAddColor, onDeleteColor, }: Readonly) { const { toggleToGenerateTool, isDrawingTool } = useSubToolSelection() + const { selectedColor, updateSelectedColor } = useSelectedColor() return (
@@ -30,7 +28,7 @@ export default function ColorPalette({ key={color.toString()} color={color} isSelected={isDrawingTool && selectedColor === color} - onClick={() => {onColorSelect(color); toggleToGenerateTool()}} // 色の変更とツールを変更を同時に行う + onClick={() => {updateSelectedColor(color); toggleToGenerateTool()}} // 色の変更とツールを変更を同時に行う onDelete={() => onDeleteColor(color)} /> ))} diff --git a/front/src/components/organisms/event/venueedit/palette/ColorSingleSelector.tsx b/front/src/components/organisms/event/venueedit/palette/ColorSingleSelector.tsx index d407350..510e3bb 100644 --- a/front/src/components/organisms/event/venueedit/palette/ColorSingleSelector.tsx +++ b/front/src/components/organisms/event/venueedit/palette/ColorSingleSelector.tsx @@ -6,30 +6,25 @@ import ColorPickerDialog from '@/components/organisms/event/venueedit/palette/Co import ToggleToGenerateButton from '@/components/organisms/event/venueedit/palette/ToggleToGenerateButton' import ToggleToEraseButton from '@/components/organisms/event/venueedit/palette/ToggleToEraseButton' import { useSubToolSelection } from '@/hooks/event/venueedit/useSubToolSelection' +import { useSelectedColor } from '@/hooks/event/venueedit/submenu/useSelectedColor' -interface ColorSingleSelectorProps { - selectedColor: Color - selectedColorBackGround: Color - setSelectedColor: (color: Color) => void - setSelectedColorBackGround: (color: Color) => void -} - -export default function ColorSingleSelector({ - selectedColor, - selectedColorBackGround, - setSelectedColor, - setSelectedColorBackGround, -}: Readonly) { +export default function ColorSingleSelector() { const { isDrawingTool } = useSubToolSelection() + const { + selectedColor, + updateSelectedColor, + selectedColorBackGround, + updateSelectedColorBackGround + } = useSelectedColor() const [isTextColorOpen, setIsTextColorOpen] = useState(false) const [isBackgroundColorOpen, setIsBackgroundColorOpen] = useState(false) const handleTextColorChange = (hex: string) => { - setSelectedColor(hex as Color) + updateSelectedColor(hex as Color) } const handleBackgroundColorChange = (hex: string) => { - setSelectedColorBackGround(hex as Color) + updateSelectedColorBackGround(hex as Color) } return ( diff --git a/front/src/components/templates/event/venueedit/VenueEditorTemplate.tsx b/front/src/components/templates/event/venueedit/VenueEditorTemplate.tsx index 6774005..9150ec0 100644 --- a/front/src/components/templates/event/venueedit/VenueEditorTemplate.tsx +++ b/front/src/components/templates/event/venueedit/VenueEditorTemplate.tsx @@ -20,11 +20,7 @@ interface Props { */ export default function VenueEditorTemplate({ eventVenueEditViewModel }: Readonly) { const { - selectedColor, - setSelectedColor, colorPalette, - selectedColorBackGround, - setSelectedColorBackGround, addColor, removeColor } = useColorPalette() @@ -47,8 +43,6 @@ export default function VenueEditorTemplate({ eventVenueEditViewModel }: Readonl saveImageAction, isPendingForSave } = useCanvasDraw({ - selectedColor, - selectedColorBackGround, eventVenueEditViewModel, }) @@ -76,10 +70,6 @@ export default function VenueEditorTemplate({ eventVenueEditViewModel }: Readonl
void; - selectedColorBackGround: Color; - setSelectedColorBackGround: (color: Color) => void; colorPalette: Color[]; onAddColor: (color: Color) => void; onDeleteColor: (color: Color) => void; } export default function VenueToolSubMenu({ - selectedColor, - setSelectedColor, - selectedColorBackGround, - setSelectedColorBackGround, colorPalette, onAddColor, onDeleteColor @@ -34,20 +26,13 @@ export default function VenueToolSubMenu({
{isPixelTool && ( )} {isTextTool && ( - + )} diff --git a/front/src/hooks/event/venueedit/submenu/useColorPalette.ts b/front/src/hooks/event/venueedit/submenu/useColorPalette.ts index 3692c67..1a44e96 100644 --- a/front/src/hooks/event/venueedit/submenu/useColorPalette.ts +++ b/front/src/hooks/event/venueedit/submenu/useColorPalette.ts @@ -1,16 +1,13 @@ import { Color } from 'react-color' -import { useState, Dispatch, SetStateAction } from 'react' +import { useState } from 'react' import { DEFAULT_COLORS } from '@/lib/event/venueedit/constants' +import { useSelectedColor } from './useSelectedColor' /** * useColorPaletteフックの戻り値の型定義 */ interface UseColorPaletteReturn { - selectedColor: Color colorPalette: Color[] - setSelectedColor: Dispatch> - selectedColorBackGround: Color - setSelectedColorBackGround: Dispatch> addColor: (color: Color) => void removeColor: (color: Color) => void resetColors: () => void @@ -21,9 +18,9 @@ interface UseColorPaletteReturn { * @returns カラーパレットの状態と操作関数 */ export const useColorPalette = (): UseColorPaletteReturn => { - const [selectedColor, setSelectedColor] = useState(DEFAULT_COLORS[0]) - const [selectedColorBackGround, setSelectedColorBackGround] = useState(DEFAULT_COLORS[1]) const [colorPalette, setColorPalette] = useState(DEFAULT_COLORS) + const { updateSelectedColor, selectedColor } = useSelectedColor() + /** * 新しい色を追加する @@ -33,7 +30,7 @@ export const useColorPalette = (): UseColorPaletteReturn => { // 重複チェック if (colorPalette.includes(color)) return setColorPalette([...colorPalette, color]) - setSelectedColor(color) // 追加した色を選択状態にする + updateSelectedColor(color) } /** @@ -42,9 +39,8 @@ export const useColorPalette = (): UseColorPaletteReturn => { */ const removeColor = (color: Color) => { setColorPalette(colorPalette.filter(c => c !== color)) - // 削除した色が選択されていた場合、最初の色を選択 if (selectedColor === color) { - setSelectedColor(colorPalette[0]) + updateSelectedColor(colorPalette[0]) } } @@ -53,15 +49,11 @@ export const useColorPalette = (): UseColorPaletteReturn => { */ const resetColors = () => { setColorPalette(DEFAULT_COLORS) - setSelectedColor(DEFAULT_COLORS[0]) + updateSelectedColor(DEFAULT_COLORS[0]) } return { - selectedColor, colorPalette, - setSelectedColor, - selectedColorBackGround, - setSelectedColorBackGround, addColor, removeColor, resetColors diff --git a/front/src/hooks/event/venueedit/submenu/useSelectedColor.ts b/front/src/hooks/event/venueedit/submenu/useSelectedColor.ts new file mode 100644 index 0000000..b076d9c --- /dev/null +++ b/front/src/hooks/event/venueedit/submenu/useSelectedColor.ts @@ -0,0 +1,38 @@ +import { useAtomValue, useSetAtom } from 'jotai' +import { useCallback } from 'react' +import { Color } from 'react-color' +import { + selectedColorAtom, + selectedColorBackGroundAtom, + colorActionAtom +} from '@/store/event/venueedit/color' + +/** + * 選択色の状態と操作を管理するカスタムフック + */ +export const useSelectedColor = () => { + // Atomから状態を読み取る + const selectedColor = useAtomValue(selectedColorAtom) + const selectedColorBackGround = useAtomValue(selectedColorBackGroundAtom) + + // 更新用のdispatch関数を取得 + const dispatch = useSetAtom(colorActionAtom) + + // 各アクションに対応するコールバック関数を定義 + const updateSelectedColor = useCallback( + (color: Color) => dispatch({ type: 'SET_SELECTED_COLOR', color }), + [dispatch] + ) + + const updateSelectedColorBackGround = useCallback( + (color: Color) => dispatch({ type: 'SET_BACKGROUND_COLOR', color }), + [dispatch] + ) + + return { + selectedColor, + updateSelectedColor, + selectedColorBackGround, + updateSelectedColorBackGround, + } +} \ No newline at end of file diff --git a/front/src/hooks/event/venueedit/tool/cell/useCircleDraw.ts b/front/src/hooks/event/venueedit/tool/cell/useCircleDraw.ts index d979d7f..425ccfe 100644 --- a/front/src/hooks/event/venueedit/tool/cell/useCircleDraw.ts +++ b/front/src/hooks/event/venueedit/tool/cell/useCircleDraw.ts @@ -2,11 +2,11 @@ import { useCallback } from 'react' import { Color } from 'react-color' import { useCellEditableTool } from '@/hooks/event/venueedit/tool/cell/useCellEditableTool' import { TextState } from '@/types/event/state' +import { useSelectedColor } from '@/hooks/event/venueedit/submenu/useSelectedColor' interface Props { canvasRef: React.RefObject numPixel: number - selectedColor: Color setPixelColorState: React.Dispatch> pixelColorState: (Color | null)[][] setCircleColorState: React.Dispatch> @@ -14,7 +14,8 @@ interface Props { textState: TextState[] } -export const useCircleDraw = ({ canvasRef, numPixel, selectedColor, setCircleColorState, pixelColorState, circleColorState, textState }: Props) => { +export const useCircleDraw = ({ canvasRef, numPixel, setCircleColorState, pixelColorState, circleColorState, textState }: Props) => { + const { selectedColor } = useSelectedColor() const updateCircleState = useCallback((x: number, y: number) => { const newState = [...circleColorState] newState[y] = [...newState[y]] diff --git a/front/src/hooks/event/venueedit/tool/cell/usePixelDraw.ts b/front/src/hooks/event/venueedit/tool/cell/usePixelDraw.ts index 504a762..ab0d480 100644 --- a/front/src/hooks/event/venueedit/tool/cell/usePixelDraw.ts +++ b/front/src/hooks/event/venueedit/tool/cell/usePixelDraw.ts @@ -2,11 +2,11 @@ import { useCallback } from 'react' import { Color } from 'react-color' import { useCellEditableTool } from '@/hooks/event/venueedit/tool/cell/useCellEditableTool' import { TextState } from '@/types/event/state' +import { useSelectedColor } from '@/hooks/event/venueedit/submenu/useSelectedColor' interface Props { canvasRef: React.RefObject numPixel: number - selectedColor: Color setPixelColorState: React.Dispatch> pixelColorState: (Color | null)[][] setCircleColorState: React.Dispatch> @@ -14,7 +14,8 @@ interface Props { textState: TextState[] } -export const usePixelDraw = ({ canvasRef, numPixel, selectedColor, setPixelColorState, pixelColorState, circleColorState, textState }: Props) => { +export const usePixelDraw = ({ canvasRef, numPixel, setPixelColorState, pixelColorState, circleColorState, textState }: Props) => { + const { selectedColor } = useSelectedColor() const updatePixelState = useCallback((x: number, y: number) => { const newState = [...pixelColorState] newState[y] = [...newState[y]] diff --git a/front/src/hooks/event/venueedit/tool/select/dialog/useTextDialog.ts b/front/src/hooks/event/venueedit/tool/select/dialog/useTextDialog.ts index 0484af8..8400b63 100644 --- a/front/src/hooks/event/venueedit/tool/select/dialog/useTextDialog.ts +++ b/front/src/hooks/event/venueedit/tool/select/dialog/useTextDialog.ts @@ -1,12 +1,11 @@ -import { useEffect, useState } from 'react' +import { useEffect, useState, useCallback } from 'react' import { Position, TextState } from '@/types/event/state' import { Color } from 'react-color' +import { useSelectedColor } from '@/hooks/event/venueedit/submenu/useSelectedColor' interface TextDialogProps { textState: TextState[] setTextState: React.Dispatch> - selectedColor: Color - selectedColorBackGround?: Color isDialogModalOpen: boolean setIsDialogModalOpen: (isOpen: boolean) => void } @@ -14,11 +13,10 @@ interface TextDialogProps { export const useTextDialog = ({ textState, setTextState, - selectedColor, - selectedColorBackGround, isDialogModalOpen, setIsDialogModalOpen, }: TextDialogProps) => { + const { selectedColor, selectedColorBackGround } = useSelectedColor() const [isTextDialogOpen, setIsTextDialogOpen] = useState(false) const [currentText, setCurrentText] = useState('') const [textPosition, setTextPosition] = useState({ @@ -38,7 +36,7 @@ export const useTextDialog = ({ setIsTextDialogOpen(isDialogModalOpen) }, [isDialogModalOpen]) - const handleTextAdd = () => { + const handleTextAdd = useCallback(() => { const newTextState: TextState[] = [...textState, { text: currentText, textColor: selectedColor, @@ -52,7 +50,7 @@ export const useTextDialog = ({ }] setTextState(newTextState) setIsTextDialogOpen(false) - } + }, [currentText, selectedColor, selectedColorBackGround, textState, textPosition, setTextState, setIsTextDialogOpen]) return { isTextDialogOpen, @@ -62,7 +60,5 @@ export const useTextDialog = ({ textPosition, setTextPosition, handleTextAdd, - selectedColor, - selectedColorBackGround, } -} \ No newline at end of file +} diff --git a/front/src/hooks/event/venueedit/tool/select/useTextAdd.ts b/front/src/hooks/event/venueedit/tool/select/useTextAdd.ts index 4c621fd..02ae815 100644 --- a/front/src/hooks/event/venueedit/tool/select/useTextAdd.ts +++ b/front/src/hooks/event/venueedit/tool/select/useTextAdd.ts @@ -8,8 +8,6 @@ interface Props { canvasRef: React.RefObject numPixel: number draggingColor: string - selectedColor: Color - selectedColorBackGround?: Color textState: TextState[] setTextState: React.Dispatch> isDialogModalOpen: boolean @@ -20,8 +18,6 @@ export const useTextAdd = ({ canvasRef, numPixel, draggingColor, - selectedColor, - selectedColorBackGround, textState, setTextState, isDialogModalOpen, @@ -38,8 +34,6 @@ export const useTextAdd = ({ setTextPosition, handleTextAdd, } = useTextDialog({ - selectedColor, - selectedColorBackGround, textState, setTextState, isDialogModalOpen, diff --git a/front/src/hooks/event/venueedit/tool/useToolSelect.ts b/front/src/hooks/event/venueedit/tool/useToolSelect.ts index 679d5dc..dffefcd 100644 --- a/front/src/hooks/event/venueedit/tool/useToolSelect.ts +++ b/front/src/hooks/event/venueedit/tool/useToolSelect.ts @@ -10,8 +10,6 @@ import { TextState } from '@/types/event/state' import { useSubToolSelection } from '@/hooks/event/venueedit/useSubToolSelection' interface Props { - selectedColor: Color - selectedColorBackGround?: Color canvasRef: React.RefObject numPixel: number setPixelColorState: React.Dispatch> @@ -34,8 +32,6 @@ type ToolHandlers = { } export const useToolSelect = ({ - selectedColor, - selectedColorBackGround, canvasRef, numPixel, setPixelColorState, @@ -54,7 +50,6 @@ export const useToolSelect = ({ const pixelDraw = usePixelDraw({ canvasRef, numPixel, - selectedColor, setPixelColorState, pixelColorState, setCircleColorState, @@ -75,7 +70,6 @@ export const useToolSelect = ({ const circleDraw = useCircleDraw({ canvasRef, numPixel, - selectedColor, setPixelColorState, pixelColorState, setCircleColorState, @@ -97,8 +91,6 @@ export const useToolSelect = ({ canvasRef, numPixel, draggingColor: '#FFFF00', - selectedColor, - selectedColorBackGround, textState, setTextState, isDialogModalOpen, diff --git a/front/src/hooks/event/venueedit/useCanvasDraw.ts b/front/src/hooks/event/venueedit/useCanvasDraw.ts index 632c8e5..3b38be4 100644 --- a/front/src/hooks/event/venueedit/useCanvasDraw.ts +++ b/front/src/hooks/event/venueedit/useCanvasDraw.ts @@ -12,19 +12,14 @@ import { useInitialState } from '@/hooks/event/venueedit/useInitialState'; * @param selectedColor 選択された色 */ interface Props { - selectedColor: Color; - selectedColorBackGround?: Color; eventVenueEditViewModel: EventVenueEditViewModel; } /** * キャンバスの描画を管理するフック - * @param selectedColor 選択された色 * @returns キャンバスの参照、キャンバスのサイズ、セルの座標を取得する関数、描画関数 */ export const useCanvasDraw = ({ - selectedColor, - selectedColorBackGround, eventVenueEditViewModel }: Props) => { @@ -74,8 +69,6 @@ export const useCanvasDraw = ({ textPosition, setTextPosition, handleTextAdd } = useToolSelect({ - selectedColor, - selectedColorBackGround, canvasRef, numPixel, setPixelColorState, diff --git a/front/src/store/event/venueedit/color.ts b/front/src/store/event/venueedit/color.ts new file mode 100644 index 0000000..513ddfe --- /dev/null +++ b/front/src/store/event/venueedit/color.ts @@ -0,0 +1,31 @@ +import { atom } from 'jotai' +import { Color } from 'react-color' +import { DEFAULT_COLORS } from '@/lib/event/venueedit/constants' + +// アクションの型を定義 +export type ColorAction = + | { type: 'SET_SELECTED_COLOR'; color: Color } + | { type: 'SET_BACKGROUND_COLOR'; color: Color } + +// 状態を保持するプライベートなベースatom +const _selectedColorAtom = atom(DEFAULT_COLORS[0]); +const _selectedColorBackGroundAtom = atom(DEFAULT_COLORS[1]); + +// 読み取り専用のatom +export const selectedColorAtom = atom((get) => get(_selectedColorAtom)); +export const selectedColorBackGroundAtom = atom((get) => get(_selectedColorBackGroundAtom)); + +// 更新ロジックをカプセル化した書き込み専用atom +export const colorActionAtom = atom( + null, + (get, set, action: ColorAction) => { + switch (action.type) { + case 'SET_SELECTED_COLOR': + set(_selectedColorAtom, action.color); + break; + case 'SET_BACKGROUND_COLOR': + set(_selectedColorBackGroundAtom, action.color); + break; + } + } +);