@@ -7,6 +7,7 @@ import { Toaster } from "@courselit/components-library";
77import { AppDispatch , AppState } from "@courselit/state-management" ;
88import { Tooltip } from "@courselit/components-library" ;
99import { Button } from "@/components/ui/button" ;
10+ import convert , { HSL } from "color-convert" ;
1011
1112interface TemplateProps {
1213 layout : WidgetInstance [ ] ;
@@ -20,6 +21,211 @@ interface TemplateProps {
2021 onMoveWidgetDown ?: ( index : number ) => void ;
2122 dispatch ?: AppDispatch ;
2223 state : Partial < AppState > ;
24+ id ?: string ;
25+ colorMode ?: "light" | "dark" ;
26+ }
27+
28+ const Template = ( props : TemplateProps ) => {
29+ const {
30+ layout,
31+ pageData,
32+ editing = false ,
33+ onEditClick,
34+ children,
35+ childrenOnTop = false ,
36+ onAddWidgetBelow,
37+ onMoveWidgetUp,
38+ onMoveWidgetDown,
39+ dispatch,
40+ state,
41+ id,
42+ colorMode,
43+ } = props ;
44+ const theme =
45+ colorMode === "dark"
46+ ? state . theme ?. theme ?. colors ?. dark
47+ : state . theme ?. theme ?. colors ?. light ;
48+
49+ if ( ! layout ) return < > </ > ;
50+ const footer = layout . filter (
51+ ( widget ) => widget . name === Footer . metadata . name ,
52+ ) [ 0 ] ;
53+ const header = layout . filter (
54+ ( widget ) => widget . name === Header . metadata . name ,
55+ ) [ 0 ] ;
56+ const widgetsWithoutHeaderAndFooter = layout . filter (
57+ ( widget ) =>
58+ ! [ Header . metadata . name , Footer . metadata . name ] . includes ( widget . name ) ,
59+ ) ;
60+ const pageWidgets = widgetsWithoutHeaderAndFooter . map (
61+ ( item : any , index : number ) => (
62+ < EditableWidget
63+ item = { item }
64+ key = { item . widgetId }
65+ editing = { editing }
66+ onEditClick = { onEditClick }
67+ pageData = { pageData }
68+ allowsWidgetAddition = { true }
69+ allowsUpwardMovement = { index !== 0 }
70+ allowsDownwardMovement = {
71+ widgetsWithoutHeaderAndFooter . length - 1 !== index
72+ }
73+ onAddWidgetBelow = { onAddWidgetBelow }
74+ onMoveWidgetDown = { onMoveWidgetDown }
75+ onMoveWidgetUp = { onMoveWidgetUp }
76+ index = { index + 1 }
77+ dispatch = { dispatch }
78+ state = { state }
79+ />
80+ ) ,
81+ ) ;
82+
83+ return (
84+ < div className = "flex flex-col font-primary" id = { id } >
85+ { header && (
86+ < EditableWidget
87+ item = { header }
88+ editing = { editing }
89+ pageData = { pageData }
90+ onEditClick = { onEditClick }
91+ allowsWidgetAddition = { true }
92+ onAddWidgetBelow = { onAddWidgetBelow }
93+ onMoveWidgetDown = { onMoveWidgetDown }
94+ onMoveWidgetUp = { onMoveWidgetUp }
95+ index = { 0 }
96+ dispatch = { dispatch }
97+ state = { state }
98+ />
99+ ) }
100+ { childrenOnTop && (
101+ < Fragment >
102+ { children }
103+ { pageWidgets }
104+ </ Fragment >
105+ ) }
106+ { ! childrenOnTop && (
107+ < Fragment >
108+ { pageWidgets }
109+ { children }
110+ </ Fragment >
111+ ) }
112+ { footer && (
113+ < EditableWidget
114+ item = { footer }
115+ pageData = { pageData }
116+ editing = { editing }
117+ onEditClick = { onEditClick }
118+ index = { layout . length - 1 }
119+ dispatch = { dispatch }
120+ state = { state }
121+ />
122+ ) }
123+ < Toaster />
124+ < style jsx > { `
125+ #${ id } {
126+ --background: ${ theme ?. background
127+ ? formatHSL (
128+ convert . hex . hsl (
129+ theme . background ?. replace ( "#" , "" ) ,
130+ ) ,
131+ )
132+ : "" } ;
133+ --foreground: ${ theme ?. foreground
134+ ? formatHSL (
135+ convert . hex . hsl (
136+ theme . foreground ?. replace ( "#" , "" ) ,
137+ ) ,
138+ )
139+ : "" } ;
140+ --card: ${ theme ?. card
141+ ? formatHSL (
142+ convert . hex . hsl ( theme . card ?. replace ( "#" , "" ) ) ,
143+ )
144+ : "" } ;
145+ --card-foreground: ${ theme ?. cardForeground
146+ ? formatHSL (
147+ convert . hex . hsl (
148+ theme . cardForeground ?. replace ( "#" , "" ) ,
149+ ) ,
150+ )
151+ : "" } ;
152+ --primary: ${ theme ?. primary
153+ ? formatHSL (
154+ convert . hex . hsl ( theme . primary ?. replace ( "#" , "" ) ) ,
155+ )
156+ : "" } ;
157+ --primary-foreground: ${ theme ?. primaryForeground
158+ ? formatHSL (
159+ convert . hex . hsl (
160+ theme . primaryForeground ?. replace ( "#" , "" ) ,
161+ ) ,
162+ )
163+ : "" } ;
164+ --secondary: ${ theme ?. secondary
165+ ? formatHSL (
166+ convert . hex . hsl (
167+ theme . secondary ?. replace ( "#" , "" ) ,
168+ ) ,
169+ )
170+ : "" } ;
171+ --secondary-foreground: ${ theme ?. secondaryForeground
172+ ? formatHSL (
173+ convert . hex . hsl (
174+ theme . secondaryForeground ?. replace ( "#" , "" ) ,
175+ ) ,
176+ )
177+ : "" } ;
178+ --muted: ${ theme ?. muted
179+ ? formatHSL (
180+ convert . hex . hsl ( theme . muted ?. replace ( "#" , "" ) ) ,
181+ )
182+ : "" } ;
183+ --muted-foreground: ${ theme ?. mutedForeground
184+ ? formatHSL (
185+ convert . hex . hsl (
186+ theme . mutedForeground ?. replace ( "#" , "" ) ,
187+ ) ,
188+ )
189+ : "" } ;
190+ --accent: ${ theme ?. accent
191+ ? formatHSL (
192+ convert . hex . hsl ( theme . accent ?. replace ( "#" , "" ) ) ,
193+ )
194+ : "" } ;
195+ --accent-foreground: ${ theme ?. accentForeground
196+ ? formatHSL (
197+ convert . hex . hsl (
198+ theme . accentForeground ?. replace ( "#" , "" ) ,
199+ ) ,
200+ )
201+ : "" } ;
202+ --border: ${ theme ?. border
203+ ? formatHSL (
204+ convert . hex . hsl ( theme . border ?. replace ( "#" , "" ) ) ,
205+ )
206+ : "" } ;
207+ --destructive: ${ theme ?. destructive
208+ ? formatHSL (
209+ convert . hex . hsl (
210+ theme . destructive ?. replace ( "#" , "" ) ,
211+ ) ,
212+ )
213+ : "" } ;
214+ --input: ${ theme ?. input
215+ ? formatHSL (
216+ convert . hex . hsl ( theme . input ?. replace ( "#" , "" ) ) ,
217+ )
218+ : "" } ;
219+ }
220+ ` } </ style >
221+ </ div >
222+ ) ;
223+ } ;
224+
225+ export default Template ;
226+
227+ function formatHSL ( hsl : HSL ) : string {
228+ return `${ hsl [ 0 ] } ${ hsl [ 1 ] } % ${ hsl [ 2 ] } %` ;
23229}
24230
25231const EditableWidget = ( {
@@ -133,97 +339,3 @@ const EditableWidget = ({
133339 />
134340 ) ;
135341} ;
136-
137- const Template = ( props : TemplateProps ) => {
138- const {
139- layout,
140- pageData,
141- editing = false ,
142- onEditClick,
143- children,
144- childrenOnTop = false ,
145- onAddWidgetBelow,
146- onMoveWidgetUp,
147- onMoveWidgetDown,
148- dispatch,
149- state,
150- } = props ;
151- if ( ! layout ) return < > </ > ;
152- const footer = layout . filter (
153- ( widget ) => widget . name === Footer . metadata . name ,
154- ) [ 0 ] ;
155- const header = layout . filter (
156- ( widget ) => widget . name === Header . metadata . name ,
157- ) [ 0 ] ;
158- const widgetsWithoutHeaderAndFooter = layout . filter (
159- ( widget ) =>
160- ! [ Header . metadata . name , Footer . metadata . name ] . includes ( widget . name ) ,
161- ) ;
162- const pageWidgets = widgetsWithoutHeaderAndFooter . map (
163- ( item : any , index : number ) => (
164- < EditableWidget
165- item = { item }
166- key = { item . widgetId }
167- editing = { editing }
168- onEditClick = { onEditClick }
169- pageData = { pageData }
170- allowsWidgetAddition = { true }
171- allowsUpwardMovement = { index !== 0 }
172- allowsDownwardMovement = {
173- widgetsWithoutHeaderAndFooter . length - 1 !== index
174- }
175- onAddWidgetBelow = { onAddWidgetBelow }
176- onMoveWidgetDown = { onMoveWidgetDown }
177- onMoveWidgetUp = { onMoveWidgetUp }
178- index = { index + 1 }
179- dispatch = { dispatch }
180- state = { state }
181- />
182- ) ,
183- ) ;
184- return (
185- < div className = "flex flex-col font-primary" >
186- { header && (
187- < EditableWidget
188- item = { header }
189- editing = { editing }
190- pageData = { pageData }
191- onEditClick = { onEditClick }
192- allowsWidgetAddition = { true }
193- onAddWidgetBelow = { onAddWidgetBelow }
194- onMoveWidgetDown = { onMoveWidgetDown }
195- onMoveWidgetUp = { onMoveWidgetUp }
196- index = { 0 }
197- dispatch = { dispatch }
198- state = { state }
199- />
200- ) }
201- { childrenOnTop && (
202- < Fragment >
203- { children }
204- { pageWidgets }
205- </ Fragment >
206- ) }
207- { ! childrenOnTop && (
208- < Fragment >
209- { pageWidgets }
210- { children }
211- </ Fragment >
212- ) }
213- { footer && (
214- < EditableWidget
215- item = { footer }
216- pageData = { pageData }
217- editing = { editing }
218- onEditClick = { onEditClick }
219- index = { layout . length - 1 }
220- dispatch = { dispatch }
221- state = { state }
222- />
223- ) }
224- < Toaster />
225- </ div >
226- ) ;
227- } ;
228-
229- export default Template ;
0 commit comments