package components import ( "github.com/mikestefanello/pagoda/pkg/form" "github.com/mikestefanello/pagoda/pkg/ui" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) type ( InputFieldParams struct { Form form.Form FormField string Name string InputType string Label string Value string Placeholder string Help string } FileFieldParams struct { Name string Label string Help string } OptionsParams struct { Form form.Form FormField string Name string Label string Value string Options []Choice Help string } Choice struct { Value string Label string } TextareaFieldParams struct { Form form.Form FormField string Name string Label string Value string Help string } CheckboxParams struct { Form form.Form FormField string Name string Label string Checked bool } ) func ControlGroup(controls ...Node) Node { return Div( Class("mt-2 flex gap-2"), Group(controls), ) } func TextareaField(el TextareaFieldParams) Node { return Fieldset( el.Label, Textarea( Class("textarea h-24 w-2/3 "+formFieldStatusClass(el.Form, el.FormField)), ID(el.Name), Name(el.Name), Text(el.Value), ), Help(el.Help), formFieldErrors(el.Form, el.FormField), ) } func Radios(el OptionsParams) Node { buttons := make(Group, len(el.Options)) for i, opt := range el.Options { id := "radio-" + el.Name + "-" + opt.Value buttons[i] = Div( Class("mb-2"), Input( ID(id), Type("radio"), Name(el.Name), Value(opt.Value), Class("radio mr-1 "+formFieldStatusClass(el.Form, el.FormField)), If(el.Value == opt.Value, Checked()), ), Label( Text(opt.Label), For(id), ), ) } return Fieldset( el.Label, buttons, formFieldErrors(el.Form, el.FormField), ) } func SelectList(el OptionsParams) Node { buttons := make(Group, len(el.Options)) for i, opt := range el.Options { buttons[i] = Option( Text(opt.Label), Value(opt.Value), If(opt.Value == el.Value, Attr("selected")), ) } return Fieldset( el.Label, Select( Class("select "+formFieldStatusClass(el.Form, el.FormField)), buttons, ), Help(el.Help), formFieldErrors(el.Form, el.FormField), ) } func Checkbox(el CheckboxParams) Node { return Div( Label( Class("label"), Input( Class("checkbox"), Type("checkbox"), Name(el.Name), If(el.Checked, Checked()), Value("true"), ), Text(" "+el.Label), ), formFieldErrors(el.Form, el.FormField), ) } func InputField(el InputFieldParams) Node { return Fieldset( el.Label, Input( ID(el.Name), Name(el.Name), Type(el.InputType), Class("input "+formFieldStatusClass(el.Form, el.FormField)), Value(el.Value), If(el.Placeholder != "", Placeholder(el.Placeholder)), ), Help(el.Help), formFieldErrors(el.Form, el.FormField), ) } func Help(text string) Node { return If(len(text) > 0, Div( Class("label"), Text(text), )) } func Fieldset(label string, els ...Node) Node { return FieldSet( Class("fieldset"), If(len(label) > 0, Legend( Class("fieldset-legend"), Text(label), )), Group(els), ) } func FileField(el FileFieldParams) Node { return Fieldset( el.Label, Input( Type("file"), Class("file-input"), Name(el.Name), ), Help(el.Help), ) } func formFieldStatusClass(fm form.Form, formField string) string { switch { case fm == nil: return "" case !fm.IsSubmitted(): return "" case fm.FieldHasErrors(formField): return "input-error" default: return "input-success" } } func formFieldErrors(fm form.Form, field string) Node { if fm == nil { return nil } errs := fm.GetFieldErrors(field) if len(errs) == 0 { return nil } g := make(Group, len(errs)) for i, err := range errs { g[i] = Div( Class("text-error"), Text(err), ) } return g } func CSRF(r *ui.Request) Node { return Input( Type("hidden"), Name("csrf"), Value(r.CSRF), ) } func FormButton(color Color, label string) Node { return Button( Class("btn "+buttonColor(color)), Text(label), ) } func ButtonLink(color Color, href, label string) Node { return A( Href(href), Class("btn "+buttonColor(color)), Text(label), ) } func buttonColor(color Color) string { // Only colors being used are included so unused styles are not compiled. switch color { case ColorPrimary: return "btn-primary" case ColorInfo: return "btn-info" case ColorAccent: return "btn-accent" case ColorError: return "btn-error" case ColorLink: return "btn-link" default: return "" } }