11"use client"
22
33import type React from "react"
4- import { BgFill , FillStyle , RoughStyle , StrokeEdge , StrokeFill , StrokeStyle , StrokeWidth , ToolType } from "@/types/canvas"
4+ import { cn } from "@/lib/utils" ;
5+ import { BgFill , FillStyle , FontFamily , FontSize , RoughStyle , StrokeEdge , StrokeFill , StrokeStyle , StrokeWidth , TextAlign , ToolType } from "@/types/canvas"
6+ import { fillStyleIcons , fillStyleLabels , fontFamilyIcons , fontFamilyLabels , fontSizeIcons , fontSizeLabels , roughStyleIcons , roughStyleLabels , strokeEdgeIcons , strokeEdgeLabels , strokeStyleIcons , strokeStyleLabels , textAlignIcons , textAlignLabels } from "@/config/canvasTypeMappings" ;
7+ import { Input } from "./ui/input" ;
58import { ColorBoard } from "./color-board"
69import ItemLabel from "./ItemLabel" ;
7- import { Input } from "./ui/input" ;
8- import { cn } from "@/lib/utils" ;
9- import { fillStyleIcons , fillStyleLabels , roughStyleIcons , roughStyleLabels , strokeEdgeIcons , strokeEdgeLabels , strokeStyleIcons , strokeStyleLabels } from "@/config/canvasTypeMappings" ;
1010
1111interface StyleConfiguratorProps {
1212 activeTool : ToolType ;
@@ -24,6 +24,12 @@ interface StyleConfiguratorProps {
2424 setRoughStyle : React . Dispatch < React . SetStateAction < RoughStyle > > ;
2525 fillStyle : FillStyle ;
2626 setFillStyle : React . Dispatch < React . SetStateAction < FillStyle > > ;
27+ fontFamily : FontFamily ;
28+ setFontFamily : React . Dispatch < React . SetStateAction < FontFamily > > ;
29+ fontSize : FontSize ;
30+ setFontSize : React . Dispatch < React . SetStateAction < FontSize > > ;
31+ textAlign : TextAlign ;
32+ setTextAlign : React . Dispatch < React . SetStateAction < TextAlign > > ;
2733 isMobile ?: boolean
2834}
2935
@@ -43,6 +49,12 @@ export function StyleConfigurator({
4349 setRoughStyle,
4450 fillStyle,
4551 setFillStyle,
52+ fontFamily,
53+ setFontFamily,
54+ fontSize,
55+ setFontSize,
56+ textAlign,
57+ setTextAlign,
4658 isMobile
4759} : StyleConfiguratorProps ) {
4860
@@ -51,6 +63,9 @@ export function StyleConfigurator({
5163 const edgeStyleOptions : StrokeStyle [ ] = [ "solid" , "dashed" , "dotted" ]
5264 const roughStyleOptions : RoughStyle [ ] = [ 0 , 1 , 2 ]
5365 const fillStyleOptions : FillStyle [ ] = [ 'hachure' , 'cross-hatch' , 'dashed' , 'dots' , 'zigzag' , 'zigzag-line' , 'solid' ]
66+ const fontFamilyOptions : FontFamily [ ] = [ 'hand-drawn' , 'normal' , 'code' ]
67+ const fontSizeOptions : FontSize [ ] = [ 'Small' , 'Medium' , 'Large' ]
68+ const textAlignOptions : TextAlign [ ] = [ 'left' , 'center' , 'right' ]
5469
5570 if ( activeTool === "eraser" || activeTool === "grab" || activeTool === "selection" ) {
5671 return ;
@@ -61,7 +76,7 @@ export function StyleConfigurator({
6176 isMobile ? "" : "absolute top-full w-56 h-[calc(100vh-150px)] bg-background dark:bg-w-bg rounded-lg Island"
6277 ) } >
6378 < h2 className = "sr-only" > Selected shape actions</ h2 >
64- < div className = "flex flex-col gap-y-3" >
79+ < div className = "ColorBoard flex flex-col gap-y-3" >
6580 < ColorBoard
6681 mode = "Shape"
6782 bgFill = { bgFill }
@@ -71,22 +86,8 @@ export function StyleConfigurator({
7186 activeTool = { activeTool }
7287 />
7388
74- < div className = "" >
75- < ItemLabel label = "Stroke width" />
76- < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
77- { lineThicknessOptions . map ( ( sw , index ) => (
78- < StrokeWidthSelector
79- key = { index }
80- strokeWidth = { strokeWidth }
81- strokeWidthProp = { sw }
82- onClick = { ( ) => setStrokeWidth ( sw ) }
83- />
84- ) ) }
85- </ div >
86- </ div >
87-
88- { ( activeTool === "rectangle" || activeTool === "diamond" || activeTool === 'ellipse' ) && (
89- < div className = "" >
89+ { ( activeTool === "rectangle" || activeTool === 'ellipse' || activeTool === "diamond" || activeTool === 'line' || activeTool === 'pen' ) && (
90+ < div className = "Fill-Style-Selector" >
9091 < ItemLabel label = "Fill" />
9192 < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
9293 { fillStyleOptions . map ( ( fs , index ) => (
@@ -101,8 +102,24 @@ export function StyleConfigurator({
101102 </ div >
102103 ) }
103104
105+ { ( activeTool !== "text" ) && (
106+ < div className = "Stroke-Width-Selector" >
107+ < ItemLabel label = "Stroke width" />
108+ < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
109+ { lineThicknessOptions . map ( ( sw , index ) => (
110+ < StrokeWidthSelector
111+ key = { index }
112+ strokeWidth = { strokeWidth }
113+ strokeWidthProp = { sw }
114+ onClick = { ( ) => setStrokeWidth ( sw ) }
115+ />
116+ ) ) }
117+ </ div >
118+ </ div >
119+ ) }
120+
104121 { ( activeTool === "rectangle" || activeTool === "diamond" ) && (
105- < div className = "" >
122+ < div className = "Edge-Style-Selector " >
106123 < ItemLabel label = "Edges" />
107124 < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
108125 { edgeRoundnessOptions . map ( ( sw , index ) => (
@@ -117,39 +134,131 @@ export function StyleConfigurator({
117134 </ div >
118135 ) }
119136
120- < div className = "" >
121- < ItemLabel label = "Sloppiness" />
122- < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
123- { roughStyleOptions . map ( ( rs , index ) => (
124- < RoughStyleSelector
125- key = { index }
126- roughStyle = { roughStyle }
127- roughStyleProp = { rs }
128- onClick = { ( ) => setRoughStyle ( rs ) }
129- />
130- ) ) }
131- </ div >
132- </ div >
133-
134- < div className = "" >
135- < ItemLabel label = "Stroke Style" />
136- < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
137- { edgeStyleOptions . map ( ( sw , index ) => (
138- < StrokeStyleSelector
139- key = { index }
140- strokeStyle = { strokeStyle }
141- strokeStyleProp = { sw }
142- onClick = { ( ) => setStrokeStyle ( sw ) }
143- />
144- ) ) }
145- </ div >
146- </ div >
137+ { ( activeTool !== "pen" && activeTool !== 'text' ) && (
138+ < >
139+ < div className = "Rough-Style-Selector" >
140+ < ItemLabel label = "Sloppiness" />
141+ < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
142+ { roughStyleOptions . map ( ( rs , index ) => (
143+ < RoughStyleSelector
144+ key = { index }
145+ roughStyle = { roughStyle }
146+ roughStyleProp = { rs }
147+ onClick = { ( ) => setRoughStyle ( rs ) }
148+ />
149+ ) ) }
150+ </ div >
151+ </ div >
152+
153+ < div className = "Stroke-Style-Selector" >
154+ < ItemLabel label = "Stroke Style" />
155+ < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
156+ { edgeStyleOptions . map ( ( sw , index ) => (
157+ < StrokeStyleSelector
158+ key = { index }
159+ strokeStyle = { strokeStyle }
160+ strokeStyleProp = { sw }
161+ onClick = { ( ) => setStrokeStyle ( sw ) }
162+ />
163+ ) ) }
164+ </ div >
165+ </ div >
166+ </ >
167+ ) }
168+
169+ { ( activeTool === "text" ) && (
170+ < >
171+ < div className = "Font-Family-Selector" >
172+ < ItemLabel label = "Font family" />
173+ < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
174+ { fontFamilyOptions . map ( ( ff , index ) => (
175+ < FontFamilySelector
176+ key = { index }
177+ fontFamily = { fontFamily }
178+ fontFamilyProp = { ff }
179+ onClick = { ( ) => setFontFamily ( ff ) }
180+ />
181+ ) ) }
182+ </ div >
183+ </ div >
184+
185+ < div className = "Font-Size-Selector" >
186+ < ItemLabel label = "Font size" />
187+ < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
188+ { fontSizeOptions . map ( ( fs , index ) => (
189+ < FontSizeSelector
190+ key = { index }
191+ fontSize = { fontSize }
192+ fontSizeProp = { fs }
193+ onClick = { ( ) => setFontSize ( fs ) }
194+ />
195+ ) ) }
196+ </ div >
197+ </ div >
198+
199+ < div className = "Text-Align-Selector" >
200+ < ItemLabel label = "Text align" />
201+ < div className = "flex flex-wrap gap-x-2 gap-y-2 items-center py-1" >
202+ { textAlignOptions . map ( ( a , index ) => (
203+ < TextAlignSelector
204+ key = { index }
205+ textAlign = { textAlign }
206+ textAlignProp = { a }
207+ onClick = { ( ) => setTextAlign ( a ) }
208+ />
209+ ) ) }
210+ </ div >
211+ </ div >
212+ </ >
213+ ) }
147214 </ div >
148215 </ section >
149216 </ >
150217 )
151218}
152219
220+ const TextAlignSelector = ( { textAlign, textAlignProp, onClick } : { textAlign : TextAlign , textAlignProp : TextAlign , onClick ?: ( ) => void } ) => {
221+ return (
222+ < label className = { cn ( "active flex justify-center items-center w-8 h-8 p-0 box-border border border-default-border-color rounded-lg cursor-pointer bg-light-btn-bg2 text-text-primary-color dark:bg-w-button-hover-bg dark:hover:bg-tool-btn-bg-hover-dark dark:text-text-primary-color dark:border-w-button-hover-bg focus-within:shadow-shadow-tool-focus" ,
223+ textAlign === textAlignProp ? 'bg-selected-tool-bg-light dark:bg-selected-tool-bg-dark dark:border-selected-tool-bg-dark' : ''
224+ ) }
225+ title = { textAlignLabels [ textAlignProp ] }
226+ onClick = { onClick }
227+ >
228+ < Input type = "radio" checked = { textAlign === textAlignProp } onChange = { ( ) => onClick ?.( ) } name = "textAlign" className = "opacity-0 absolute pointer-events-none" />
229+ { textAlignIcons [ textAlignProp ] }
230+ </ label >
231+ )
232+ }
233+
234+ const FontSizeSelector = ( { fontSize, fontSizeProp, onClick } : { fontSize : FontSize , fontSizeProp : FontSize , onClick ?: ( ) => void } ) => {
235+ return (
236+ < label className = { cn ( "active flex justify-center items-center w-8 h-8 p-0 box-border border border-default-border-color rounded-lg cursor-pointer bg-light-btn-bg2 text-text-primary-color dark:bg-w-button-hover-bg dark:hover:bg-tool-btn-bg-hover-dark dark:text-text-primary-color dark:border-w-button-hover-bg focus-within:shadow-shadow-tool-focus" ,
237+ fontSize === fontSizeProp ? 'bg-selected-tool-bg-light dark:bg-selected-tool-bg-dark dark:border-selected-tool-bg-dark' : ''
238+ ) }
239+ title = { fontSizeLabels [ fontSizeProp ] }
240+ onClick = { onClick }
241+ >
242+ < Input type = "radio" checked = { fontSize === fontSizeProp } onChange = { ( ) => onClick ?.( ) } name = "fontSize" className = "opacity-0 absolute pointer-events-none" />
243+ { fontSizeIcons [ fontSizeProp ] }
244+ </ label >
245+ )
246+ }
247+
248+ const FontFamilySelector = ( { fontFamily, fontFamilyProp, onClick } : { fontFamily : FontFamily , fontFamilyProp : FontFamily , onClick ?: ( ) => void } ) => {
249+ return (
250+ < label className = { cn ( "active flex justify-center items-center w-8 h-8 p-0 box-border border border-default-border-color rounded-lg cursor-pointer bg-light-btn-bg2 text-text-primary-color dark:bg-w-button-hover-bg dark:hover:bg-tool-btn-bg-hover-dark dark:text-text-primary-color dark:border-w-button-hover-bg focus-within:shadow-shadow-tool-focus" ,
251+ fontFamily === fontFamilyProp ? 'bg-selected-tool-bg-light dark:bg-selected-tool-bg-dark dark:border-selected-tool-bg-dark' : ''
252+ ) }
253+ title = { fontFamilyLabels [ fontFamilyProp ] }
254+ onClick = { onClick }
255+ >
256+ < Input type = "radio" checked = { fontFamily === fontFamilyProp } onChange = { ( ) => onClick ?.( ) } name = "fontFamily" className = "opacity-0 absolute pointer-events-none" />
257+ { fontFamilyIcons [ fontFamilyProp ] }
258+ </ label >
259+ )
260+ }
261+
153262const StrokeWidthSelector = ( { strokeWidth, strokeWidthProp, onClick } : { strokeWidth : StrokeWidth , strokeWidthProp : StrokeWidth , onClick ?: ( ) => void } ) => {
154263 return (
155264 < label className = { cn ( "active flex justify-center items-center w-8 h-8 p-0 box-border border border-default-border-color rounded-lg cursor-pointer bg-light-btn-bg2 text-text-primary-color dark:bg-w-button-hover-bg dark:hover:bg-tool-btn-bg-hover-dark dark:text-text-primary-color dark:border-w-button-hover-bg focus-within:shadow-shadow-tool-focus" ,
0 commit comments