From d735f6e4728efe92eb087b8837c15eb9dc876b68 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 16 Jul 2025 16:43:26 +0200 Subject: [PATCH 001/122] init --- form/field.go | 172 +++++++++++++++++++++++++++++++++++++++ form/field_input.go | 8 ++ form/field_subform.go | 11 +++ form/form.go | 117 ++++++++++++++++++++++++++ form/option.go | 6 ++ go.mod | 3 + main.go | 77 ++++++++++++++++++ theme/html5.go | 27 ++++++ theme/renderer.go | 90 ++++++++++++++++++++ util/inspect.go | 30 +++++++ validation/constraint.go | 5 ++ validation/error.go | 3 + validation/notblank.go | 46 +++++++++++ validation/validation.go | 13 +++ 14 files changed, 608 insertions(+) create mode 100644 form/field.go create mode 100644 form/field_input.go create mode 100644 form/field_subform.go create mode 100644 form/form.go create mode 100644 form/option.go create mode 100644 go.mod create mode 100644 main.go create mode 100644 theme/html5.go create mode 100644 theme/renderer.go create mode 100644 util/inspect.go create mode 100644 validation/constraint.go create mode 100644 validation/error.go create mode 100644 validation/notblank.go create mode 100644 validation/validation.go diff --git a/form/field.go b/form/field.go new file mode 100644 index 0000000..540de16 --- /dev/null +++ b/form/field.go @@ -0,0 +1,172 @@ +package form + +import ( + "gitnet.fr/deblan/go-form/util" + "gitnet.fr/deblan/go-form/validation" +) + +func FieldValidation(f *Field) bool { + if len(f.Children) > 0 { + isValid := true + + for _, c := range f.Children { + isChildValid, errs := validation.Validate(c.Data, c.Constraints) + + if len(errs) > 0 { + c.Errors = errs + } + + isValid = isValid && isChildValid + } + + return isValid + } else { + isValid, errs := validation.Validate(f.Data, f.Constraints) + f.Errors = []validation.Error{} + + if len(errs) > 0 { + f.Errors = errs + } + + return isValid + } +} + +type Field struct { + Name string + Widget string + Data any + Options []*Option + Children []*Field + Constraints []validation.Constraint + Errors []validation.Error + PrepareView func() map[string]any + BeforeBind func(data any) (any, error) + Validate func(f *Field) bool +} + +func NewField(name, widget string) *Field { + f := &Field{ + Name: name, + Widget: widget, + Data: nil, + } + + f.PrepareView = func() map[string]any { + m := make(map[string]any) + + return m + } + + f.BeforeBind = func(data any) (any, error) { + return data, nil + } + + f.Validate = FieldValidation + + return f +} + +func (f *Field) HasOption(name string) bool { + for _, option := range f.Options { + if option.Name == name { + return true + } + } + + return false +} + +func (f *Field) GetOption(name string) *Option { + for _, option := range f.Options { + if option.Name == name { + return option + } + } + + return nil +} + +func (f *Field) WithOptions(options ...Option) *Field { + for _, option := range options { + if f.HasOption(option.Name) { + f.GetOption(option.Name).Value = option.Value + } else { + f.Options = append(f.Options, &option) + } + } + + return f +} + +func (f *Field) WithConstraints(constraints ...validation.Constraint) *Field { + for _, constraint := range constraints { + f.Constraints = append(f.Constraints, constraint) + } + + return f +} + +func (f *Field) Add(children ...*Field) *Field { + for _, child := range children { + f.Children = append(f.Children, child) + } + + return f +} + +func (f *Field) HasChild(name string) bool { + for _, child := range f.Children { + if name == child.Name { + return true + } + } + + return false +} + +func (f *Field) GetChild(name string) *Field { + var result *Field + + for _, child := range f.Children { + if name == child.Name { + result = child + + break + } + } + + return result +} + +func (f *Field) Bind(data any) error { + if len(f.Children) == 0 { + f.Data = data + + return nil + } + + data, err := f.BeforeBind(data) + + if err != nil { + return err + } + + props, err := util.InspectStruct(data) + + if err != nil { + return err + } + + for key, value := range props { + if f.HasChild(key) { + err = f.GetChild(key).Bind(value) + + if err != nil { + return err + } + } + } + + return nil +} diff --git a/form/field_input.go b/form/field_input.go new file mode 100644 index 0000000..dc7206f --- /dev/null +++ b/form/field_input.go @@ -0,0 +1,8 @@ +package form + +func NewFieldText(name string) *Field { + f := NewField(name, "input"). + WithOptions(Option{Name: "type", Value: "text"}) + + return f +} diff --git a/form/field_subform.go b/form/field_subform.go new file mode 100644 index 0000000..9c5f21c --- /dev/null +++ b/form/field_subform.go @@ -0,0 +1,11 @@ +package form + +func NewFieldSubForm(name string) *Field { + f := NewField(name, "sub_form") + + return f +} + +func NewSubForm(name string) *Field { + return NewFieldSubForm(name) +} diff --git a/form/form.go b/form/form.go new file mode 100644 index 0000000..9cbf600 --- /dev/null +++ b/form/form.go @@ -0,0 +1,117 @@ +package form + +import ( + "net/http" + + "gitnet.fr/deblan/go-form/util" + "gitnet.fr/deblan/go-form/validation" +) + +type Form struct { + Fields []*Field + Errors []validation.Error + Method string + Action string + Name string + Options []Option +} + +func NewForm(fields ...*Field) *Form { + f := new(Form) + f.Method = "POST" + f.Add(fields...) + + return f +} + +func (f *Form) Add(fields ...*Field) { + for _, field := range fields { + f.Fields = append(f.Fields, field) + } +} + +func (f *Form) HasField(name string) bool { + for _, field := range f.Fields { + if name == field.Name { + return true + } + } + + return false +} + +func (f *Form) GetField(name string) *Field { + var result *Field + + for _, field := range f.Fields { + if name == field.Name { + result = field + break + } + } + + return result +} + +func (f *Form) WithMethod(v string) *Form { + f.Method = v + + return f +} + +func (f *Form) WithName(v string) *Form { + f.Name = v + + return f +} + +func (f *Form) WithAction(v string) *Form { + f.Action = v + + return f +} + +func (f *Form) WithOptions(options ...Option) *Form { + for _, option := range options { + f.Options = append(f.Options, option) + } + + return f +} + +func (f *Form) IsValid() bool { + isValid := true + + for _, field := range f.Fields { + fieldIsValid := field.Validate(field) + isValid = isValid && fieldIsValid + } + + return isValid +} + +func (f *Form) Bind(data any) error { + props, err := util.InspectStruct(data) + + if err != nil { + return err + } + + for key, value := range props { + if f.HasField(key) { + err = f.GetField(key).Bind(value) + + if err != nil { + return err + } + } + } + + return nil +} + +func (f *Form) HandleRequest(req http.Request) { + if f.Method == "POST" { + // data := req.PostForm + } +} diff --git a/form/option.go b/form/option.go new file mode 100644 index 0000000..c811db1 --- /dev/null +++ b/form/option.go @@ -0,0 +1,6 @@ +package form + +type Option struct { + Name string + Value any +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f28e114 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module gitnet.fr/deblan/go-form + +go 1.23.0 diff --git a/main.go b/main.go new file mode 100644 index 0000000..71d87b2 --- /dev/null +++ b/main.go @@ -0,0 +1,77 @@ +package main + +import ( + "fmt" + + "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/theme" + "gitnet.fr/deblan/go-form/validation" +) + +func main() { + type Address struct { + Street string + City string + ZipCode uint + } + + type Person struct { + Name string + Address Address + } + + data := new(Person) + data.Name = "" + data.Address = Address{ + Street: "rue des camélias", + City: "", + ZipCode: 39700, + } + + f := form.NewForm( + form.NewFieldText("Name"). + WithOptions( + form.Option{Name: "required", Value: true}, + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewSubForm("Address"). + Add( + form.NewFieldText("Street"), + form.NewFieldText("City"). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldText("ZipCode"), + ), + ).WithMethod("POST").WithAction("") + + f.Bind(data) + + fmt.Printf("%+v\n", f.IsValid()) + + render := theme.NewRenderer(theme.Html5) + v := render.RenderForm(f) + + fmt.Print(v) + + // r, e := theme.RenderForm(f, theme.Html5) + + // fmt.Printf("%+v\n", e) + // fmt.Printf("%+v\n", r) + + // fmt.Printf("%+v\n", e) + // + // fmt.Printf("%+v\n", f) + // + // for _, field := range f.Fields { + // fmt.Printf("%+v\n", *field) + // + // if len(field.Children) > 0 { + // for _, c := range field.Children { + // fmt.Printf("C %+v\n", *c) + // } + // } + // } +} diff --git a/theme/html5.go b/theme/html5.go new file mode 100644 index 0000000..9b50f39 --- /dev/null +++ b/theme/html5.go @@ -0,0 +1,27 @@ +package theme + +var Html5 = map[string]string{ + "form": `
+ {{ form_error .Form nil }} + {{ .Content }} +
`, + "label": ``, + "input": ``, + "sub_form": ` + {{ form_label .Field }} + + {{ range $field := .Field.Children }} + {{ form_row $field }} + {{ end }} + `, + "error": `
+ {{ range $error := .Errors }} + {{ $error }}
+ {{ end }} +
`, + "row": `
+ {{ form_label .Field }} + {{ form_error nil .Field }} + {{ form_widget .Field }} +
`, +} diff --git a/theme/renderer.go b/theme/renderer.go new file mode 100644 index 0000000..a0fc09c --- /dev/null +++ b/theme/renderer.go @@ -0,0 +1,90 @@ +package theme + +import ( + "bytes" + "html/template" + + "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/validation" +) + +type Renderer struct { + Theme map[string]string +} + +func NewRenderer(theme map[string]string) *Renderer { + r := new(Renderer) + r.Theme = theme + + return r +} + +func (r *Renderer) RenderForm(form *form.Form) template.HTML { + content := "" + + for _, field := range form.Fields { + content = content + string(r.RenderRow(field)) + } + + return r.Render("form", r.Theme["form"], map[string]any{ + "Form": form, + "Content": template.HTML(content), + }) +} + +func (r *Renderer) RenderRow(field *form.Field) template.HTML { + return r.Render("row", r.Theme["row"], map[string]any{ + "Field": field, + }) +} + +func (r *Renderer) RenderLabel(field *form.Field) template.HTML { + return r.Render("label", r.Theme["label"], map[string]any{ + "Field": field, + }) +} + +func (r *Renderer) RenderWidget(field *form.Field) template.HTML { + return r.Render("widget", r.Theme[field.Widget], map[string]any{ + "Field": field, + }) +} + +func (r *Renderer) RenderError(form *form.Form, field *form.Field) template.HTML { + var errors []validation.Error + + if field != nil { + errors = field.Errors + } + + if form != nil { + errors = form.Errors + } + + return r.Render("error", r.Theme["error"], map[string]any{ + "Errors": errors, + }) +} + +func (r *Renderer) Render(name, tpl string, args any) template.HTML { + t, err := template.New(name).Funcs(template.FuncMap{ + "form": r.RenderForm, + "form_row": r.RenderRow, + "form_label": r.RenderLabel, + "form_widget": r.RenderWidget, + "form_error": r.RenderError, + }).Parse(tpl) + + if err != nil { + return template.HTML(err.Error()) + } + + var buf bytes.Buffer + err = t.Execute(&buf, args) + + if err != nil { + return template.HTML(err.Error()) + } + + return template.HTML(buf.String()) +} diff --git a/util/inspect.go b/util/inspect.go new file mode 100644 index 0000000..6cb1bf7 --- /dev/null +++ b/util/inspect.go @@ -0,0 +1,30 @@ +package util + +import ( + "errors" + "reflect" +) + +func InspectStruct(input interface{}) (map[string]interface{}, error) { + val := reflect.ValueOf(input) + + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + + if val.Kind() != reflect.Struct { + return nil, errors.New("Invalid type") + } + + result := make(map[string]interface{}) + + typ := val.Type() + for i := 0; i < val.NumField(); i++ { + field := typ.Field(i) + value := val.Field(i) + + result[field.Name] = value.Interface() + } + + return result, nil +} diff --git a/validation/constraint.go b/validation/constraint.go new file mode 100644 index 0000000..5c42183 --- /dev/null +++ b/validation/constraint.go @@ -0,0 +1,5 @@ +package validation + +type Constraint interface { + Validate(data any) []Error +} diff --git a/validation/error.go b/validation/error.go new file mode 100644 index 0000000..078a221 --- /dev/null +++ b/validation/error.go @@ -0,0 +1,3 @@ +package validation + +type Error string diff --git a/validation/notblank.go b/validation/notblank.go new file mode 100644 index 0000000..250ea31 --- /dev/null +++ b/validation/notblank.go @@ -0,0 +1,46 @@ +package validation + +import ( + "fmt" + "reflect" +) + +type NotBlank struct { +} + +func (c NotBlank) Validate(data any) []Error { + isValid := true + errors := []Error{} + + fmt.Printf("%+v\n", data) + + t := reflect.TypeOf(data) + + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + if data == nil { + isValid = false + } else if t.Kind() == reflect.Bool { + if data == false { + isValid = false + } + } else if t.Kind() == reflect.Array { + if len(data.([]interface{})) == 0 { + isValid = false + } + } else if t.Kind() == reflect.String { + if len(data.(string)) == 0 { + isValid = false + } + } else { + fmt.Printf("d=%+v\n", data) + } + + if !isValid { + errors = append(errors, Error("This value should be blank")) + } + + return errors +} diff --git a/validation/validation.go b/validation/validation.go new file mode 100644 index 0000000..b824d14 --- /dev/null +++ b/validation/validation.go @@ -0,0 +1,13 @@ +package validation + +func Validate(data any, constraints []Constraint) (bool, []Error) { + errs := []Error{} + + for _, constraint := range constraints { + for _, e := range constraint.Validate(data) { + errs = append(errs, e) + } + } + + return len(errs) == 0, errs +} From 3894fb31e96c8ba11a144cd18158b3005c4e902b Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 16 Jul 2025 19:04:31 +0200 Subject: [PATCH 002/122] feat: improve form rendering --- .gitignore | 1 + example/address.go | 48 ++++++++++++++++++++++++ form/field.go | 29 +++++++++++++++ form/field_input.go | 18 +++++++++ form/field_textarea.go | 5 +++ form/form.go | 83 +++++++++++++++++++++++++++++++++++++----- main.go | 77 ++++++++++++++------------------------- theme/html5.go | 63 ++++++++++++++++++++++---------- theme/renderer.go | 65 +++++++++++++++++++++++++++++---- validation/notblank.go | 6 +-- 10 files changed, 303 insertions(+), 92 deletions(-) create mode 100644 .gitignore create mode 100644 example/address.go create mode 100644 form/field_textarea.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5bebc6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/go-form diff --git a/example/address.go b/example/address.go new file mode 100644 index 0000000..61bd796 --- /dev/null +++ b/example/address.go @@ -0,0 +1,48 @@ +package example + +import ( + "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/validation" +) + +func CreateAddressForm() *form.Form { + return form.NewForm( + form.NewFieldText("Name"). + WithOptions( + form.Option{Name: "label", Value: "Name"}, + form.Option{Name: "required", Value: true}, + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewSubForm("Address"). + WithOptions(form.Option{Name: "label", Value: "Address"}). + Add( + form.NewFieldTextarea("Street"). + WithOptions(form.Option{Name: "label", Value: "Street"}). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldText("City"). + WithOptions(form.Option{Name: "label", Value: "City"}). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldNumber("ZipCode"). + WithOptions(form.Option{Name: "label", Value: "Zip code"}). + WithConstraints( + validation.NotBlank{}, + ), + ), + form.NewSubmit("submit"), + ). + End(). + WithMethod("POST"). + // WithMethod("GET"). + WithAction("/"). + WithOptions( + form.Option{Name: "attr", Value: map[string]string{ + "id": "my-form", + }}, + ) +} diff --git a/form/field.go b/form/field.go index 540de16..3d755f1 100644 --- a/form/field.go +++ b/form/field.go @@ -1,6 +1,9 @@ package form import ( + "fmt" + "strings" + "gitnet.fr/deblan/go-form/util" "gitnet.fr/deblan/go-form/validation" ) @@ -43,6 +46,8 @@ type Field struct { PrepareView func() map[string]any BeforeBind func(data any) (any, error) Validate func(f *Field) bool + Form *Form + Parent *Field } func NewField(name, widget string) *Field { @@ -109,6 +114,7 @@ func (f *Field) WithConstraints(constraints ...validation.Constraint) *Field { func (f *Field) Add(children ...*Field) *Field { for _, child := range children { + child.Parent = f f.Children = append(f.Children, child) } @@ -139,6 +145,29 @@ func (f *Field) GetChild(name string) *Field { return result } +func (f *Field) GetName() string { + var name string + + if f.Form != nil && f.Form.Name != "" { + name = fmt.Sprintf("%s[%s]", f.Form.Name, f.Name) + } else if f.Parent != nil { + name = fmt.Sprintf("%s[%s]", f.Parent.GetName(), f.Name) + } else { + name = f.Name + } + + return name +} + +func (f *Field) GetId() string { + name := f.GetName() + name = strings.ReplaceAll(name, "[", "-") + name = strings.ReplaceAll(name, "]", "") + name = strings.ToLower(name) + + return name +} + func (f *Field) Bind(data any) error { if len(f.Children) == 0 { f.Data = data diff --git a/form/field_input.go b/form/field_input.go index dc7206f..3c9e2d1 100644 --- a/form/field_input.go +++ b/form/field_input.go @@ -6,3 +6,21 @@ func NewFieldText(name string) *Field { return f } + +func NewFieldNumber(name string) *Field { + f := NewField(name, "input"). + WithOptions(Option{Name: "type", Value: "number"}) + + return f +} + +func NewSubmit(name string) *Field { + f := NewField(name, "input"). + WithOptions( + Option{Name: "type", Value: "submit"}, + ) + + f.Data = "Submit" + + return f +} diff --git a/form/field_textarea.go b/form/field_textarea.go new file mode 100644 index 0000000..c32f704 --- /dev/null +++ b/form/field_textarea.go @@ -0,0 +1,5 @@ +package form + +func NewFieldTextarea(name string) *Field { + return NewField(name, "textarea") +} diff --git a/form/form.go b/form/form.go index 9cbf600..4405304 100644 --- a/form/form.go +++ b/form/form.go @@ -2,34 +2,75 @@ package form import ( "net/http" + "net/url" "gitnet.fr/deblan/go-form/util" "gitnet.fr/deblan/go-form/validation" ) type Form struct { - Fields []*Field - Errors []validation.Error - Method string - Action string - Name string - Options []Option + Fields []*Field + GlobalFields []*Field + Errors []validation.Error + Method string + Action string + Name string + Options []*Option + RequestData *url.Values } func NewForm(fields ...*Field) *Form { f := new(Form) f.Method = "POST" + f.Name = "form" f.Add(fields...) return f } +func (f *Form) HasOption(name string) bool { + for _, option := range f.Options { + if option.Name == name { + return true + } + } + + return false +} + +func (f *Form) GetOption(name string) *Option { + for _, option := range f.Options { + if option.Name == name { + return option + } + } + + return nil +} + func (f *Form) Add(fields ...*Field) { for _, field := range fields { + field.Form = f f.Fields = append(f.Fields, field) } } +func (f *Form) End() *Form { + for _, c := range f.Fields { + f.AddGlobalField(c) + } + + return f +} + +func (f *Form) AddGlobalField(field *Field) { + f.GlobalFields = append(f.GlobalFields, field) + + for _, c := range field.Children { + f.AddGlobalField(c) + } +} + func (f *Form) HasField(name string) bool { for _, field := range f.Fields { if name == field.Name { @@ -73,7 +114,7 @@ func (f *Form) WithAction(v string) *Form { func (f *Form) WithOptions(options ...Option) *Form { for _, option := range options { - f.Options = append(f.Options, option) + f.Options = append(f.Options, &option) } return f @@ -110,8 +151,30 @@ func (f *Form) Bind(data any) error { return nil } -func (f *Form) HandleRequest(req http.Request) { - if f.Method == "POST" { - // data := req.PostForm +func (f *Form) HandleRequest(req *http.Request) { + var data url.Values + + if f.Method != "GET" { + req.ParseForm() + data = req.Form + } else { + data = req.URL.Query() + } + + isSubmitted := false + + for _, c := range f.GlobalFields { + if data.Has(c.GetName()) { + isSubmitted = true + c.Bind(data.Get(c.GetName())) + } + } + + if isSubmitted { + f.RequestData = &data } } + +func (f *Form) IsSubmitted() bool { + return f.RequestData != nil +} diff --git a/main.go b/main.go index 71d87b2..8ce6fc5 100644 --- a/main.go +++ b/main.go @@ -2,10 +2,11 @@ package main import ( "fmt" + "log" + "net/http" - "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/example" "gitnet.fr/deblan/go-form/theme" - "gitnet.fr/deblan/go-form/validation" ) func main() { @@ -20,58 +21,34 @@ func main() { Address Address } - data := new(Person) - data.Name = "" - data.Address = Address{ - Street: "rue des camélias", - City: "", - ZipCode: 39700, - } + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + data := new(Person) + data.Name = "" + data.Address = Address{ + Street: "rue des camélias", + City: "", + ZipCode: 39700, + } - f := form.NewForm( - form.NewFieldText("Name"). - WithOptions( - form.Option{Name: "required", Value: true}, - ). - WithConstraints( - validation.NotBlank{}, - ), - form.NewSubForm("Address"). - Add( - form.NewFieldText("Street"), - form.NewFieldText("City"). - WithConstraints( - validation.NotBlank{}, - ), - form.NewFieldText("ZipCode"), - ), - ).WithMethod("POST").WithAction("") + f := example.CreateAddressForm() + f.Bind(data) - f.Bind(data) + if r.Method == f.Method { + f.HandleRequest(r) - fmt.Printf("%+v\n", f.IsValid()) + if f.IsSubmitted() && f.IsValid() { + fmt.Printf("%+v\n", "OK") + } else { + fmt.Printf("%+v\n", "KO") + } + } - render := theme.NewRenderer(theme.Html5) - v := render.RenderForm(f) + render := theme.NewRenderer(theme.Html5) + v := render.RenderForm(f) - fmt.Print(v) + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.Write([]byte(v)) + }) - // r, e := theme.RenderForm(f, theme.Html5) - - // fmt.Printf("%+v\n", e) - // fmt.Printf("%+v\n", r) - - // fmt.Printf("%+v\n", e) - // - // fmt.Printf("%+v\n", f) - // - // for _, field := range f.Fields { - // fmt.Printf("%+v\n", *field) - // - // if len(field.Children) > 0 { - // for _, c := range field.Children { - // fmt.Printf("C %+v\n", *c) - // } - // } - // } + log.Fatal(http.ListenAndServe(":1122", nil)) } diff --git a/theme/html5.go b/theme/html5.go index 9b50f39..1d100ac 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -1,27 +1,52 @@ package theme var Html5 = map[string]string{ - "form": `
- {{ form_error .Form nil }} - {{ .Content }} -
`, - "label": ``, - "input": ``, - "sub_form": ` - {{ form_label .Field }} + "form": `
+ {{- form_error .Form nil -}} - {{ range $field := .Field.Children }} - {{ form_row $field }} - {{ end }} + {{- range $field := .Form.Fields -}} + {{- form_row $field -}} + {{- end -}} +
`, + "attributes": `{{ range $key, $value := .Attributes }}{{ $key }}="{{ $value }}"{{ end }}`, + // "attributes": `{{ if gt (len .Attributes) 0 }} + // {{ range $key, $value := .Attributes }} + // {{ $key }}="{{ $value }}" + // {{ end }} + // {{ end }}`, + "label": ` + {{ if .Field.HasOption "label" }} + {{ $label := (.Field.GetOption "label").Value }} + + {{- if ne $label "" -}} + + {{- end -}} + {{- end -}} + `, + "input": ` + {{ $type := .Field.GetOption "type" }} + + `, + "textarea": ` + + `, + "sub_form": ` + {{- range $field := .Field.Children -}} + {{- form_row $field -}} + {{- end -}} + `, + "error": ` + {{- if gt (len .Errors) 0 -}} + + {{- end -}} `, - "error": `
- {{ range $error := .Errors }} - {{ $error }}
- {{ end }} -
`, "row": `
- {{ form_label .Field }} - {{ form_error nil .Field }} - {{ form_widget .Field }} + {{- form_label .Field -}} + {{- form_error nil .Field -}} + {{- form_widget .Field -}}
`, } diff --git a/theme/renderer.go b/theme/renderer.go index a0fc09c..6a89a5a 100644 --- a/theme/renderer.go +++ b/theme/renderer.go @@ -20,15 +20,8 @@ func NewRenderer(theme map[string]string) *Renderer { } func (r *Renderer) RenderForm(form *form.Form) template.HTML { - content := "" - - for _, field := range form.Fields { - content = content + string(r.RenderRow(field)) - } - return r.Render("form", r.Theme["form"], map[string]any{ - "Form": form, - "Content": template.HTML(content), + "Form": form, }) } @@ -66,6 +59,59 @@ func (r *Renderer) RenderError(form *form.Form, field *form.Field) template.HTML }) } +func (r *Renderer) RenderLabelAttr(field *form.Field) template.HTMLAttr { + var attributes map[string]string + + if field.HasOption("label_attr") { + attributes = field.GetOption("label_attr").Value.(map[string]string) + } + + return r.RenderAttr("label_attr", r.Theme["attributes"], map[string]any{ + "Attributes": attributes, + }) +} + +func (r *Renderer) RenderWidgetAttr(field *form.Field) template.HTMLAttr { + var attributes map[string]string + + if field.HasOption("attr") { + attributes = field.GetOption("attr").Value.(map[string]string) + } + + return r.RenderAttr("widget_attr", r.Theme["attributes"], map[string]any{ + "Attributes": attributes, + }) +} + +func (r *Renderer) RenderFormAttr(form *form.Form) template.HTMLAttr { + var attributes map[string]string + + if form.HasOption("attr") { + attributes = form.GetOption("attr").Value.(map[string]string) + } + + return r.RenderAttr("form_attr", r.Theme["attributes"], map[string]any{ + "Attributes": attributes, + }) +} + +func (r *Renderer) RenderAttr(name, tpl string, args any) template.HTMLAttr { + t, err := template.New(name).Parse(tpl) + + if err != nil { + return template.HTMLAttr("") + } + + var buf bytes.Buffer + err = t.Execute(&buf, args) + + if err != nil { + return template.HTMLAttr("") + } + + return template.HTMLAttr(buf.String()) +} + func (r *Renderer) Render(name, tpl string, args any) template.HTML { t, err := template.New(name).Funcs(template.FuncMap{ "form": r.RenderForm, @@ -73,6 +119,9 @@ func (r *Renderer) Render(name, tpl string, args any) template.HTML { "form_label": r.RenderLabel, "form_widget": r.RenderWidget, "form_error": r.RenderError, + "form_attr": r.RenderFormAttr, + "widget_attr": r.RenderWidgetAttr, + "label_attr": r.RenderLabelAttr, }).Parse(tpl) if err != nil { diff --git a/validation/notblank.go b/validation/notblank.go index 250ea31..e14ede7 100644 --- a/validation/notblank.go +++ b/validation/notblank.go @@ -1,7 +1,6 @@ package validation import ( - "fmt" "reflect" ) @@ -11,9 +10,6 @@ type NotBlank struct { func (c NotBlank) Validate(data any) []Error { isValid := true errors := []Error{} - - fmt.Printf("%+v\n", data) - t := reflect.TypeOf(data) if t.Kind() == reflect.Ptr { @@ -35,7 +31,7 @@ func (c NotBlank) Validate(data any) []Error { isValid = false } } else { - fmt.Printf("d=%+v\n", data) + errors = append(errors, Error("This value can not be processed")) } if !isValid { From cef8567ad3867bbe9830f943eed9fd3850867c47 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 16 Jul 2025 22:37:15 +0200 Subject: [PATCH 003/122] feat: add data binding feat: add help --- example/address.go | 21 +++++++++++++-------- form/field.go | 41 ++++++++++++++++++++++++++++++++++++----- form/field_input.go | 14 +++++++++++--- form/form.go | 23 ++++++++++++++++++----- form/option.go | 7 +++++++ go.mod | 2 ++ go.sum | 2 ++ main.go | 7 ++----- theme/html5.go | 25 +++++++++++++++---------- theme/renderer.go | 42 ++++++++++++++++++++++++++++++++++-------- 10 files changed, 140 insertions(+), 44 deletions(-) create mode 100644 go.sum diff --git a/example/address.go b/example/address.go index 61bd796..ef58cf6 100644 --- a/example/address.go +++ b/example/address.go @@ -9,27 +9,31 @@ func CreateAddressForm() *form.Form { return form.NewForm( form.NewFieldText("Name"). WithOptions( - form.Option{Name: "label", Value: "Name"}, - form.Option{Name: "required", Value: true}, + form.NewOption("label", "Name"), + form.NewOption("required", true), + form.NewOption("help", "A help!"), ). WithConstraints( validation.NotBlank{}, ), form.NewSubForm("Address"). - WithOptions(form.Option{Name: "label", Value: "Address"}). + WithOptions(form.NewOption("label", "Address")). Add( form.NewFieldTextarea("Street"). - WithOptions(form.Option{Name: "label", Value: "Street"}). + WithOptions(form.NewOption("label", "Street")). WithConstraints( validation.NotBlank{}, ), form.NewFieldText("City"). - WithOptions(form.Option{Name: "label", Value: "City"}). + WithOptions(form.NewOption("label", "City")). WithConstraints( validation.NotBlank{}, ), form.NewFieldNumber("ZipCode"). - WithOptions(form.Option{Name: "label", Value: "Zip code"}). + WithOptions( + form.NewOption("label", "Zip code"), + form.NewOption("help", "A field help"), + ). WithConstraints( validation.NotBlank{}, ), @@ -41,8 +45,9 @@ func CreateAddressForm() *form.Form { // WithMethod("GET"). WithAction("/"). WithOptions( - form.Option{Name: "attr", Value: map[string]string{ + form.NewOption("attr", map[string]string{ "id": "my-form", - }}, + }), + form.NewOption("help", "A form help!"), ) } diff --git a/form/field.go b/form/field.go index 3d755f1..b96980e 100644 --- a/form/field.go +++ b/form/field.go @@ -44,6 +44,7 @@ type Field struct { Constraints []validation.Constraint Errors []validation.Error PrepareView func() map[string]any + BeforeMount func(data any) (any, error) BeforeBind func(data any) (any, error) Validate func(f *Field) bool Form *Form @@ -63,6 +64,10 @@ func NewField(name, widget string) *Field { return m } + f.BeforeMount = func(data any) (any, error) { + return data, nil + } + f.BeforeBind = func(data any) (any, error) { return data, nil } @@ -92,12 +97,12 @@ func (f *Field) GetOption(name string) *Option { return nil } -func (f *Field) WithOptions(options ...Option) *Field { +func (f *Field) WithOptions(options ...*Option) *Field { for _, option := range options { if f.HasOption(option.Name) { f.GetOption(option.Name).Value = option.Value } else { - f.Options = append(f.Options, &option) + f.Options = append(f.Options, option) } } @@ -168,14 +173,14 @@ func (f *Field) GetId() string { return name } -func (f *Field) Bind(data any) error { +func (f *Field) Mount(data any) error { if len(f.Children) == 0 { f.Data = data return nil } - data, err := f.BeforeBind(data) + data, err := f.BeforeMount(data) if err != nil { return err @@ -189,7 +194,7 @@ func (f *Field) Bind(data any) error { for key, value := range props { if f.HasChild(key) { - err = f.GetChild(key).Bind(value) + err = f.GetChild(key).Mount(value) if err != nil { return err @@ -199,3 +204,29 @@ func (f *Field) Bind(data any) error { return nil } + +func (f *Field) Bind(data map[string]any, key *string) error { + if len(f.Children) == 0 { + v, err := f.BeforeBind(f.Data) + + if err != nil { + return err + } + + if key != nil { + data[*key] = v + } else { + data[f.Name] = v + } + + return nil + } + + data[f.Name] = make(map[string]any) + + for _, child := range f.Children { + child.Bind(data[f.Name].(map[string]any), key) + } + + return nil +} diff --git a/form/field_input.go b/form/field_input.go index 3c9e2d1..2b5ee58 100644 --- a/form/field_input.go +++ b/form/field_input.go @@ -1,15 +1,23 @@ package form +import ( + "github.com/spf13/cast" +) + func NewFieldText(name string) *Field { f := NewField(name, "input"). - WithOptions(Option{Name: "type", Value: "text"}) + WithOptions(NewOption("type", "text")) return f } func NewFieldNumber(name string) *Field { f := NewField(name, "input"). - WithOptions(Option{Name: "type", Value: "number"}) + WithOptions(NewOption("type", "number")) + + f.BeforeBind = func(data any) (any, error) { + return cast.ToFloat64(data), nil + } return f } @@ -17,7 +25,7 @@ func NewFieldNumber(name string) *Field { func NewSubmit(name string) *Field { f := NewField(name, "input"). WithOptions( - Option{Name: "type", Value: "submit"}, + NewOption("type", "submit"), ) f.Data = "Submit" diff --git a/form/form.go b/form/form.go index 4405304..3c218af 100644 --- a/form/form.go +++ b/form/form.go @@ -1,6 +1,7 @@ package form import ( + "encoding/json" "net/http" "net/url" @@ -112,9 +113,9 @@ func (f *Form) WithAction(v string) *Form { return f } -func (f *Form) WithOptions(options ...Option) *Form { +func (f *Form) WithOptions(options ...*Option) *Form { for _, option := range options { - f.Options = append(f.Options, &option) + f.Options = append(f.Options, option) } return f @@ -131,7 +132,7 @@ func (f *Form) IsValid() bool { return isValid } -func (f *Form) Bind(data any) error { +func (f *Form) Mount(data any) error { props, err := util.InspectStruct(data) if err != nil { @@ -140,7 +141,7 @@ func (f *Form) Bind(data any) error { for key, value := range props { if f.HasField(key) { - err = f.GetField(key).Bind(value) + err = f.GetField(key).Mount(value) if err != nil { return err @@ -151,6 +152,18 @@ func (f *Form) Bind(data any) error { return nil } +func (f *Form) Bind(data any) error { + toBind := make(map[string]any) + + for _, field := range f.Fields { + field.Bind(toBind, nil) + } + + j, _ := json.Marshal(toBind) + + return json.Unmarshal(j, data) +} + func (f *Form) HandleRequest(req *http.Request) { var data url.Values @@ -166,7 +179,7 @@ func (f *Form) HandleRequest(req *http.Request) { for _, c := range f.GlobalFields { if data.Has(c.GetName()) { isSubmitted = true - c.Bind(data.Get(c.GetName())) + c.Mount(data.Get(c.GetName())) } } diff --git a/form/option.go b/form/option.go index c811db1..db9b86a 100644 --- a/form/option.go +++ b/form/option.go @@ -4,3 +4,10 @@ type Option struct { Name string Value any } + +func NewOption(name string, value any) *Option { + return &Option{ + Name: name, + Value: value, + } +} diff --git a/go.mod b/go.mod index f28e114..4377854 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module gitnet.fr/deblan/go-form go 1.23.0 + +require github.com/spf13/cast v1.9.2 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a02d85d --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= +github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= diff --git a/main.go b/main.go index 8ce6fc5..7b70eaa 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "log" "net/http" @@ -31,15 +30,13 @@ func main() { } f := example.CreateAddressForm() - f.Bind(data) + f.Mount(data) if r.Method == f.Method { f.HandleRequest(r) if f.IsSubmitted() && f.IsValid() { - fmt.Printf("%+v\n", "OK") - } else { - fmt.Printf("%+v\n", "KO") + f.Bind(&data) } } diff --git a/theme/html5.go b/theme/html5.go index 1d100ac..4ea7d60 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -4,42 +4,46 @@ var Html5 = map[string]string{ "form": `
{{- form_error .Form nil -}} + {{- form_help .Form -}} + {{- range $field := .Form.Fields -}} {{- form_row $field -}} {{- end -}}
`, "attributes": `{{ range $key, $value := .Attributes }}{{ $key }}="{{ $value }}"{{ end }}`, - // "attributes": `{{ if gt (len .Attributes) 0 }} - // {{ range $key, $value := .Attributes }} - // {{ $key }}="{{ $value }}" - // {{ end }} - // {{ end }}`, + "help": ` + {{- if gt (len .Help) 0 -}} +
{{ .Help }}
+ {{- end -}} + `, "label": ` {{ if .Field.HasOption "label" }} {{ $label := (.Field.GetOption "label").Value }} {{- if ne $label "" -}} - + {{- end -}} {{- end -}} `, "input": ` {{ $type := .Field.GetOption "type" }} - + `, "textarea": ` - + `, "sub_form": ` + {{ form_widget_help .Field }} + {{- range $field := .Field.Children -}} {{- form_row $field -}} {{- end -}} `, "error": ` {{- if gt (len .Errors) 0 -}} -
    +
      {{- range $error := .Errors -}} -
    • {{- $error -}}
    • +
    • {{- $error -}}
    • {{- end -}}
    {{- end -}} @@ -48,5 +52,6 @@ var Html5 = map[string]string{ {{- form_label .Field -}} {{- form_error nil .Field -}} {{- form_widget .Field -}} + {{- form_widget_help .Field -}} `, } diff --git a/theme/renderer.go b/theme/renderer.go index 6a89a5a..08e841c 100644 --- a/theme/renderer.go +++ b/theme/renderer.go @@ -95,6 +95,30 @@ func (r *Renderer) RenderFormAttr(form *form.Form) template.HTMLAttr { }) } +func (r *Renderer) RenderFormHelp(form *form.Form) template.HTML { + var help string + + if form.HasOption("help") { + help = form.GetOption("help").Value.(string) + } + + return r.Render("help", r.Theme["help"], map[string]any{ + "Help": help, + }) +} + +func (r *Renderer) RenderWidgetHelp(field *form.Field) template.HTML { + var help string + + if field.HasOption("help") { + help = field.GetOption("help").Value.(string) + } + + return r.Render("help", r.Theme["help"], map[string]any{ + "Help": help, + }) +} + func (r *Renderer) RenderAttr(name, tpl string, args any) template.HTMLAttr { t, err := template.New(name).Parse(tpl) @@ -114,14 +138,16 @@ func (r *Renderer) RenderAttr(name, tpl string, args any) template.HTMLAttr { func (r *Renderer) Render(name, tpl string, args any) template.HTML { t, err := template.New(name).Funcs(template.FuncMap{ - "form": r.RenderForm, - "form_row": r.RenderRow, - "form_label": r.RenderLabel, - "form_widget": r.RenderWidget, - "form_error": r.RenderError, - "form_attr": r.RenderFormAttr, - "widget_attr": r.RenderWidgetAttr, - "label_attr": r.RenderLabelAttr, + "form": r.RenderForm, + "form_row": r.RenderRow, + "form_label": r.RenderLabel, + "form_widget": r.RenderWidget, + "form_error": r.RenderError, + "form_attr": r.RenderFormAttr, + "form_widget_attr": r.RenderWidgetAttr, + "form_label_attr": r.RenderLabelAttr, + "form_help": r.RenderFormHelp, + "form_widget_help": r.RenderWidgetHelp, }).Parse(tpl) if err != nil { From b7c2ddeebf515974010f806cf7f5cbd4311a2a12 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Thu, 17 Jul 2025 23:11:36 +0200 Subject: [PATCH 004/122] feat: add fields (choice, checkbox, date) feat: replace json encoding with mapstructure feat: improve notblank constraint feat: add mail contraint feat: add template for fields --- example/address.go | 53 --------------- example/form.go | 135 ++++++++++++++++++++++++++++++++++++++ form/field.go | 40 ++++++++++-- form/field_checkbox.go | 32 +++++++++ form/field_choice.go | 137 +++++++++++++++++++++++++++++++++++++++ form/field_input.go | 35 ++++++++-- form/field_input_date.go | 90 +++++++++++++++++++++++++ form/form.go | 20 ++++-- go.mod | 5 +- go.sum | 2 + main.go | 94 +++++++++++++++++++++++---- theme/html5.go | 76 ++++++++++++++++++++-- theme/renderer.go | 19 +++++- validation/mail.go | 25 +++++++ validation/notblank.go | 51 ++++++++++----- 15 files changed, 702 insertions(+), 112 deletions(-) delete mode 100644 example/address.go create mode 100644 example/form.go create mode 100644 form/field_checkbox.go create mode 100644 form/field_choice.go create mode 100644 form/field_input_date.go create mode 100644 validation/mail.go diff --git a/example/address.go b/example/address.go deleted file mode 100644 index ef58cf6..0000000 --- a/example/address.go +++ /dev/null @@ -1,53 +0,0 @@ -package example - -import ( - "gitnet.fr/deblan/go-form/form" - "gitnet.fr/deblan/go-form/validation" -) - -func CreateAddressForm() *form.Form { - return form.NewForm( - form.NewFieldText("Name"). - WithOptions( - form.NewOption("label", "Name"), - form.NewOption("required", true), - form.NewOption("help", "A help!"), - ). - WithConstraints( - validation.NotBlank{}, - ), - form.NewSubForm("Address"). - WithOptions(form.NewOption("label", "Address")). - Add( - form.NewFieldTextarea("Street"). - WithOptions(form.NewOption("label", "Street")). - WithConstraints( - validation.NotBlank{}, - ), - form.NewFieldText("City"). - WithOptions(form.NewOption("label", "City")). - WithConstraints( - validation.NotBlank{}, - ), - form.NewFieldNumber("ZipCode"). - WithOptions( - form.NewOption("label", "Zip code"), - form.NewOption("help", "A field help"), - ). - WithConstraints( - validation.NotBlank{}, - ), - ), - form.NewSubmit("submit"), - ). - End(). - WithMethod("POST"). - // WithMethod("GET"). - WithAction("/"). - WithOptions( - form.NewOption("attr", map[string]string{ - "id": "my-form", - }), - form.NewOption("help", "A form help!"), - ) -} diff --git a/example/form.go b/example/form.go new file mode 100644 index 0000000..3767dc3 --- /dev/null +++ b/example/form.go @@ -0,0 +1,135 @@ +package example + +import ( + "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/validation" +) + +type Tag struct { + Name string +} + +type Post struct { + Tags []Tag + Tags2 []Tag + Tags3 Tag + Tag Tag +} + +func CreateExampleForm2() *form.Form { + tags := []Tag{Tag{"tag1"}, Tag{"tag2"}, Tag{"tag3"}} + + choices := form.NewChoices(tags). + WithLabelBuilder(func(key int, item any) string { + return item.(Tag).Name + }) + + return form.NewForm( + form.NewFieldChoice("Tag"). + WithOptions( + form.NewOption("choices", choices), + form.NewOption("label", "Tag"), + form.NewOption("required", true), + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldChoice("Tags"). + WithSlice(). + WithOptions( + form.NewOption("choices", choices), + form.NewOption("label", "Tags"), + form.NewOption("multiple", true), + form.NewOption("required", true), + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldChoice("Tags2"). + WithSlice(). + WithOptions( + form.NewOption("choices", choices), + form.NewOption("label", "Tags"), + form.NewOption("multiple", true), + form.NewOption("expanded", true), + form.NewOption("required", true), + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldChoice("Tag3"). + WithOptions( + form.NewOption("choices", choices), + form.NewOption("label", "Tag"), + form.NewOption("expanded", true), + ), + form.NewSubmit("submit"), + ). + End(). + WithMethod("POST"). + WithAction("/") +} + +func CreateExampleForm() *form.Form { + return form.NewForm( + form.NewFieldText("Name"). + WithOptions( + form.NewOption("label", "Name"), + form.NewOption("required", true), + form.NewOption("help", "A help!"), + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldDate("Date").WithOptions(form.NewOption("label", "Date")), + // form.NewFieldDatetime("DateTime").WithOptions(form.NewOption("label", "DateTime")), + form.NewFieldDatetimeLocal("DateTime").WithOptions(form.NewOption("label", "DateTimeLocal")), + form.NewFieldTime("Time").WithOptions(form.NewOption("label", "Time")), + form.NewFieldCheckbox("Checkbox").WithOptions(form.NewOption("label", "Checkbox")), + form.NewSubForm("Address"). + WithOptions(form.NewOption("label", "Address")). + Add( + form.NewFieldTextarea("Street"). + WithOptions(form.NewOption("label", "Street")). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldText("City"). + WithOptions(form.NewOption("label", "City")). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldNumber("ZipCode"). + WithOptions( + form.NewOption("label", "Zip code"), + form.NewOption("help", "A field help"), + ). + WithConstraints( + validation.NotBlank{}, + ), + form.NewFieldRange("Foo"). + WithOptions( + form.NewOption("label", "Foo"), + ), + form.NewFieldMail("Email"). + WithOptions( + form.NewOption("label", "Email"), + ). + WithConstraints( + validation.NotBlank{}, + validation.Mail{}, + ), + ), + form.NewSubmit("submit"), + ). + End(). + WithMethod("POST"). + // WithMethod("GET"). + WithAction("/"). + WithOptions( + form.NewOption("attr", map[string]string{ + "id": "my-form", + }), + form.NewOption("help", "A form help!"), + ) +} diff --git a/form/field.go b/form/field.go index b96980e..0e184d3 100644 --- a/form/field.go +++ b/form/field.go @@ -13,6 +13,7 @@ func FieldValidation(f *Field) bool { isValid := true for _, c := range f.Children { + c.ResetErrors() isChildValid, errs := validation.Validate(c.Data, c.Constraints) if len(errs) > 0 { @@ -24,8 +25,8 @@ func FieldValidation(f *Field) bool { return isValid } else { + f.ResetErrors() isValid, errs := validation.Validate(f.Data, f.Constraints) - f.Errors = []validation.Error{} if len(errs) > 0 { f.Errors = errs @@ -47,6 +48,7 @@ type Field struct { BeforeMount func(data any) (any, error) BeforeBind func(data any) (any, error) Validate func(f *Field) bool + IsSlice bool Form *Form Parent *Field } @@ -109,6 +111,18 @@ func (f *Field) WithOptions(options ...*Option) *Field { return f } +func (f *Field) ResetErrors() *Field { + f.Errors = []validation.Error{} + + return f +} + +func (f *Field) WithSlice() *Field { + f.IsSlice = true + + return f +} + func (f *Field) WithConstraints(constraints ...validation.Constraint) *Field { for _, constraint := range constraints { f.Constraints = append(f.Constraints, constraint) @@ -117,6 +131,18 @@ func (f *Field) WithConstraints(constraints ...validation.Constraint) *Field { return f } +func (f *Field) WithBeforeMount(callback func(data any) (any, error)) *Field { + f.BeforeMount = callback + + return f +} + +func (f *Field) WithBeforeBind(callback func(data any) (any, error)) *Field { + f.BeforeBind = callback + + return f +} + func (f *Field) Add(children ...*Field) *Field { for _, child := range children { child.Parent = f @@ -174,18 +200,18 @@ func (f *Field) GetId() string { } func (f *Field) Mount(data any) error { - if len(f.Children) == 0 { - f.Data = data - - return nil - } - data, err := f.BeforeMount(data) if err != nil { return err } + if len(f.Children) == 0 { + f.Data = data + + return nil + } + props, err := util.InspectStruct(data) if err != nil { diff --git a/form/field_checkbox.go b/form/field_checkbox.go new file mode 100644 index 0000000..7fc3947 --- /dev/null +++ b/form/field_checkbox.go @@ -0,0 +1,32 @@ +package form + +import ( + "github.com/spf13/cast" +) + +func NewFieldCheckbox(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "checkbox")). + WithBeforeMount(func(data any) (any, error) { + switch data.(type) { + case string: + data = data == "1" + case bool: + return data, nil + } + + return cast.ToInt(data), nil + }). + WithBeforeBind(func(data any) (any, error) { + switch data.(type) { + case string: + return data == "1", nil + case bool: + return data, nil + } + + return cast.ToBool(data), nil + }) + + return f +} diff --git a/form/field_choice.go b/form/field_choice.go new file mode 100644 index 0000000..3040b8b --- /dev/null +++ b/form/field_choice.go @@ -0,0 +1,137 @@ +package form + +import ( + "reflect" + + "github.com/spf13/cast" +) + +type Choice struct { + Value string + Label string + Data any +} + +func (c Choice) Match(value string) bool { + return c.Value == value +} + +type Choices struct { + Data any + ValueBuilder func(key int, item any) string + LabelBuilder func(key int, item any) string +} + +func (c *Choices) Match(f *Field, value string) bool { + if f.IsSlice { + v := reflect.ValueOf(f.Data) + + for key, _ := range c.GetChoices() { + for i := 0; i < v.Len(); i++ { + item := v.Index(i).Interface() + + switch item.(type) { + case string: + if item == value { + return true + } + default: + if c.ValueBuilder(key, item) == value { + return true + } + } + } + } + + return false + } + + return f.Data == value +} + +func (c *Choices) WithValueBuilder(builder func(key int, item any) string) *Choices { + c.ValueBuilder = builder + + return c +} + +func (c *Choices) WithLabelBuilder(builder func(key int, item any) string) *Choices { + c.LabelBuilder = builder + + return c +} + +func (c *Choices) GetChoices() []Choice { + choices := []Choice{} + + v := reflect.ValueOf(c.Data) + + switch v.Kind() { + case reflect.Slice, reflect.Array, reflect.String, reflect.Map: + for i := 0; i < v.Len(); i++ { + choices = append(choices, Choice{ + Value: c.ValueBuilder(i, v.Index(i).Interface()), + Label: c.LabelBuilder(i, v.Index(i).Interface()), + Data: v.Index(i).Interface(), + }) + } + } + + return choices +} + +func NewChoices(items any) *Choices { + builder := func(key int, item any) string { + return cast.ToString(key) + } + + choices := Choices{ + ValueBuilder: builder, + LabelBuilder: builder, + Data: items, + } + + return &choices +} + +func NewFieldChoice(name string) *Field { + f := NewField(name, "choice"). + WithOptions( + NewOption("choices", &Choices{}), + NewOption("expanded", false), + NewOption("multiple", false), + NewOption("empty_choice_label", ""), + ) + + f.WithBeforeBind(func(data any) (any, error) { + choices := f.GetOption("choices").Value.(*Choices) + + switch data.(type) { + case string: + v := data.(string) + for _, c := range choices.GetChoices() { + if c.Match(v) { + return c.Data, nil + } + } + case []string: + v := reflect.ValueOf(data) + var res []interface{} + + for _, choice := range choices.GetChoices() { + for i := 0; i < v.Len(); i++ { + item := v.Index(i).Interface().(string) + if choice.Match(item) { + res = append(res, choice.Data) + } + } + } + + return res, nil + } + + return data, nil + }) + + return f +} diff --git a/form/field_input.go b/form/field_input.go index 2b5ee58..0996d1e 100644 --- a/form/field_input.go +++ b/form/field_input.go @@ -13,20 +13,41 @@ func NewFieldText(name string) *Field { func NewFieldNumber(name string) *Field { f := NewField(name, "input"). - WithOptions(NewOption("type", "number")) + WithOptions(NewOption("type", "number")). + WithBeforeBind(func(data any) (any, error) { + return cast.ToFloat64(data), nil + }) - f.BeforeBind = func(data any) (any, error) { - return cast.ToFloat64(data), nil - } + return f +} + +func NewFieldMail(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "email")) + + return f +} + +func NewFieldRange(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "range")). + WithBeforeBind(func(data any) (any, error) { + return cast.ToFloat64(data), nil + }) + + return f +} + +func NewFieldPassword(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "password")) return f } func NewSubmit(name string) *Field { f := NewField(name, "input"). - WithOptions( - NewOption("type", "submit"), - ) + WithOptions(NewOption("type", "submit")) f.Data = "Submit" diff --git a/form/field_input_date.go b/form/field_input_date.go new file mode 100644 index 0000000..5a4a257 --- /dev/null +++ b/form/field_input_date.go @@ -0,0 +1,90 @@ +package form + +import ( + "fmt" + "time" +) + +func DateBeforeMount(data any, format string) (any, error) { + if data == nil { + return nil, nil + } + + switch data.(type) { + case string: + return data, nil + case time.Time: + return data.(time.Time).Format(format), nil + case *time.Time: + v := data.(*time.Time) + if v != nil { + return v.Format(format), nil + } + } + + return data, nil +} + +func NewFieldDate(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "date")). + WithBeforeMount(func(data any) (any, error) { + return DateBeforeMount(data, "2006-01-02") + }). + WithBeforeBind(func(data any) (any, error) { + return time.Parse(time.DateOnly, data.(string)) + }) + + return f +} + +func NewFieldDatetime(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "datetime")). + WithBeforeMount(func(data any) (any, error) { + return DateBeforeMount(data, "2006-01-02 15:04") + }). + WithBeforeBind(func(data any) (any, error) { + return time.Parse("2006-01-02T15:04", data.(string)) + }) + + return f +} + +func NewFieldDatetimeLocal(name string) *Field { + f := NewField(name, "input"). + WithOptions( + NewOption("type", "datetime-local"), + ). + WithBeforeMount(func(data any) (any, error) { + return DateBeforeMount(data, "2006-01-02 15:04") + }). + WithBeforeBind(func(data any) (any, error) { + a, b := time.Parse("2006-01-02T15:04", data.(string)) + + return a, b + }) + + return f +} + +func NewFieldTime(name string) *Field { + f := NewField(name, "input"). + WithOptions(NewOption("type", "time")). + WithBeforeMount(func(data any) (any, error) { + return DateBeforeMount(data, "15:04") + }). + WithBeforeBind(func(data any) (any, error) { + if data != nil { + v := data.(string) + + if len(v) > 0 { + return time.Parse(time.TimeOnly, fmt.Sprintf("%s:00", v)) + } + } + + return nil, nil + }) + + return f +} diff --git a/form/form.go b/form/form.go index 3c218af..139d5aa 100644 --- a/form/form.go +++ b/form/form.go @@ -1,10 +1,10 @@ package form import ( - "encoding/json" "net/http" "net/url" + "github.com/mitchellh/mapstructure" "gitnet.fr/deblan/go-form/util" "gitnet.fr/deblan/go-form/validation" ) @@ -49,6 +49,12 @@ func (f *Form) GetOption(name string) *Option { return nil } +func (f *Form) ResetErrors() *Form { + f.Errors = []validation.Error{} + + return f +} + func (f *Form) Add(fields ...*Field) { for _, field := range fields { field.Form = f @@ -123,6 +129,7 @@ func (f *Form) WithOptions(options ...*Option) *Form { func (f *Form) IsValid() bool { isValid := true + f.ResetErrors() for _, field := range f.Fields { fieldIsValid := field.Validate(field) @@ -159,9 +166,7 @@ func (f *Form) Bind(data any) error { field.Bind(toBind, nil) } - j, _ := json.Marshal(toBind) - - return json.Unmarshal(j, data) + return mapstructure.Decode(toBind, data) } func (f *Form) HandleRequest(req *http.Request) { @@ -179,7 +184,12 @@ func (f *Form) HandleRequest(req *http.Request) { for _, c := range f.GlobalFields { if data.Has(c.GetName()) { isSubmitted = true - c.Mount(data.Get(c.GetName())) + + if c.IsSlice { + c.Mount(data[c.GetName()]) + } else { + c.Mount(data.Get(c.GetName())) + } } } diff --git a/go.mod b/go.mod index 4377854..938ce07 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module gitnet.fr/deblan/go-form go 1.23.0 -require github.com/spf13/cast v1.9.2 // indirect +require ( + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/spf13/cast v1.9.2 // indirect +) diff --git a/go.sum b/go.sum index a02d85d..9bdda7b 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= diff --git a/main.go b/main.go index 7b70eaa..8bb8c85 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,11 @@ package main import ( + "fmt" + "html/template" "log" "net/http" + "time" "gitnet.fr/deblan/go-form/example" "gitnet.fr/deblan/go-form/theme" @@ -15,21 +18,37 @@ func main() { ZipCode uint } - type Person struct { - Name string - Address Address + type Foo struct { + Name string + Address Address + Date time.Time + DateTime time.Time + Time time.Time + Checkbox bool } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - data := new(Person) - data.Name = "" - data.Address = Address{ - Street: "rue des camélias", - City: "", - ZipCode: 39700, + // now := time.Now() + // data := new(Foo) + // data.Name = "" + // data.Date = now + // data.DateTime = now + // data.Time = now + // data.Address = Address{ + // Street: "", + // City: "", + // ZipCode: 39700, + // } + // + // f := example.CreateExampleForm() + // f.Mount(data) + + data := example.Post{ + // Tags: []example.Tag{example.Tag{"tag1"}, example.Tag{"tag2"}, example.Tag{"tag3"}}, + Tag: example.Tag{"tag1"}, } - f := example.CreateAddressForm() + f := example.CreateExampleForm2() f.Mount(data) if r.Method == f.Method { @@ -37,14 +56,65 @@ func main() { if f.IsSubmitted() && f.IsValid() { f.Bind(&data) + fmt.Printf("BIND=%+v\n", data) } } render := theme.NewRenderer(theme.Html5) - v := render.RenderForm(f) + + tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(` + + + + + Form + + + + {{ form .Form }} + + + `) w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.Write([]byte(v)) + tpl.Execute(w, map[string]any{ + "Form": f, + // "Post": data, + }) }) log.Fatal(http.ListenAndServe(":1122", nil)) diff --git a/theme/html5.go b/theme/html5.go index 4ea7d60..2e1055a 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -26,18 +26,70 @@ var Html5 = map[string]string{ {{- end -}} `, "input": ` - {{ $type := .Field.GetOption "type" }} - + {{- $type := .Field.GetOption "type" -}} + {{- $checked := and (eq (.Field.GetOption "type").Value "checkbox") (.Field.Data) -}} + {{- $required := and (.Field.HasOption "required") (.Field.GetOption "required").Value -}} + {{- $value := .Field.Data -}} + + {{- if eq $type.Value "checkbox" -}} + {{- $value = 1 -}} + {{- end -}} + + `, "textarea": ` `, - "sub_form": ` - {{ form_widget_help .Field }} + "choice": ` + {{- $required := and (.Field.HasOption "required") (.Field.GetOption "required").Value -}} + {{- $isExpanded := (.Field.GetOption "expanded").Value -}} + {{- $isMultiple := (.Field.GetOption "multiple").Value -}} + {{- $emptyChoiceLabel := (.Field.GetOption "empty_choice_label").Value -}} + {{- $choices := (.Field.GetOption "choices").Value -}} + {{- $field := .Field -}} + {{- $keyAdd := 0 -}} - {{- range $field := .Field.Children -}} - {{- form_row $field -}} + {{- if and (not $required) (not $isMultiple) -}} + {{- $keyAdd = 1 -}} {{- end -}} + + {{- if $isExpanded -}} + {{- if and (not $required) (not $isMultiple) -}} + + + {{- end -}} + + {{- range $key, $choice := $choices.GetChoices -}} + + + {{- end -}} + {{- else -}} + + {{- end -}} + `, + "sub_form": ` +
    + {{ if .Field.HasOption "label" }} + {{ $label := (.Field.GetOption "label").Value }} + + {{- if ne $label "" -}} + {{ $label }} + {{- end -}} + {{- end -}} + + {{ form_widget_help .Field }} + + {{- range $field := .Field.Children -}} + {{- form_row $field -}} + {{- end -}} +
    `, "error": ` {{- if gt (len .Errors) 0 -}} @@ -49,9 +101,19 @@ var Html5 = map[string]string{ {{- end -}} `, "row": `
    - {{- form_label .Field -}} + {{ $labelAfterWidget := and (.Field.HasOption "type") (eq (.Field.GetOption "type").Value "checkbox") }} + + {{ if and (eq (len .Field.Children) 0) (not $labelAfterWidget) }} + {{- form_label .Field -}} + {{ end }} + {{- form_error nil .Field -}} {{- form_widget .Field -}} + + {{ if and (eq (len .Field.Children) 0) ($labelAfterWidget) }} + {{- form_label .Field -}} + {{ end }} + {{- form_widget_help .Field -}}
    `, } diff --git a/theme/renderer.go b/theme/renderer.go index 08e841c..d43edc7 100644 --- a/theme/renderer.go +++ b/theme/renderer.go @@ -4,6 +4,7 @@ import ( "bytes" "html/template" + "github.com/spf13/cast" "gitnet.fr/deblan/go-form/form" "gitnet.fr/deblan/go-form/validation" ) @@ -136,8 +137,8 @@ func (r *Renderer) RenderAttr(name, tpl string, args any) template.HTMLAttr { return template.HTMLAttr(buf.String()) } -func (r *Renderer) Render(name, tpl string, args any) template.HTML { - t, err := template.New(name).Funcs(template.FuncMap{ +func (r *Renderer) FuncMap() template.FuncMap { + return template.FuncMap{ "form": r.RenderForm, "form_row": r.RenderRow, "form_label": r.RenderLabel, @@ -148,7 +149,19 @@ func (r *Renderer) Render(name, tpl string, args any) template.HTML { "form_label_attr": r.RenderLabelAttr, "form_help": r.RenderFormHelp, "form_widget_help": r.RenderWidgetHelp, - }).Parse(tpl) + "sum": func(values ...any) float64 { + res := float64(0) + for _, value := range values { + res += cast.ToFloat64(value) + } + + return res + }, + } +} + +func (r *Renderer) Render(name, tpl string, args any) template.HTML { + t, err := template.New(name).Funcs(r.FuncMap()).Parse(tpl) if err != nil { return template.HTML(err.Error()) diff --git a/validation/mail.go b/validation/mail.go new file mode 100644 index 0000000..d999dc7 --- /dev/null +++ b/validation/mail.go @@ -0,0 +1,25 @@ +package validation + +import "net/mail" + +type Mail struct { +} + +func (c Mail) Validate(data any) []Error { + errors := []Error{} + + notBlank := NotBlank{} + nbErrs := notBlank.Validate(data) + + if len(nbErrs) > 0 { + return errors + } + + _, err := mail.ParseAddress(data.(string)) + + if err != nil { + errors = append(errors, Error("This value is not a valid email address.")) + } + + return errors +} diff --git a/validation/notblank.go b/validation/notblank.go index e14ede7..45460b9 100644 --- a/validation/notblank.go +++ b/validation/notblank.go @@ -2,6 +2,8 @@ package validation import ( "reflect" + + "github.com/spf13/cast" ) type NotBlank struct { @@ -9,33 +11,48 @@ type NotBlank struct { func (c NotBlank) Validate(data any) []Error { isValid := true + label := "This value should not be blank." errors := []Error{} + + if data == nil { + errors = append(errors, Error(label)) + + return errors + } + t := reflect.TypeOf(data) if t.Kind() == reflect.Ptr { t = t.Elem() } - if data == nil { - isValid = false - } else if t.Kind() == reflect.Bool { - if data == false { - isValid = false - } - } else if t.Kind() == reflect.Array { - if len(data.([]interface{})) == 0 { - isValid = false - } - } else if t.Kind() == reflect.String { - if len(data.(string)) == 0 { - isValid = false - } - } else { - errors = append(errors, Error("This value can not be processed")) + switch t.Kind() { + case reflect.Bool: + isValid = data == false + case reflect.Array: + case reflect.Slice: + isValid = reflect.ValueOf(data).Len() > 0 + case reflect.String: + isValid = len(data.(string)) > 0 + case reflect.Float32: + case reflect.Float64: + case reflect.Int: + case reflect.Int16: + case reflect.Int32: + case reflect.Int64: + case reflect.Int8: + case reflect.Uint: + case reflect.Uint16: + case reflect.Uint32: + case reflect.Uint64: + case reflect.Uint8: + isValid = cast.ToFloat64(data.(string)) == float64(0) + default: + errors = append(errors, Error("This value can not be processed.")) } if !isValid { - errors = append(errors, Error("This value should be blank")) + errors = append(errors, Error(label)) } return errors From f2abb4326151466d5fbbe8019def2e64a5609afb Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 20 Jul 2025 15:21:30 +0200 Subject: [PATCH 005/122] feat: add constraints (length, range, regex) --- validation/length.go | 95 ++++++++++++++++++++++++++++++++++++++++ validation/range.go | 102 +++++++++++++++++++++++++++++++++++++++++++ validation/regex.go | 64 +++++++++++++++++++++++++++ 3 files changed, 261 insertions(+) create mode 100644 validation/length.go create mode 100644 validation/range.go create mode 100644 validation/regex.go diff --git a/validation/length.go b/validation/length.go new file mode 100644 index 0000000..d54bd0d --- /dev/null +++ b/validation/length.go @@ -0,0 +1,95 @@ +package validation + +import ( + "reflect" + "strings" + + "github.com/spf13/cast" +) + +type Length struct { + Min *int + Max *int + MinMessage string + MaxMessage string + ExactMessage string + TypeErrorMessage string +} + +func NewLength() Length { + return Length{ + MinMessage: "This value is too short (min: {{ min }}).", + MaxMessage: "This value is too long (max: {{ max }}).", + ExactMessage: "This value is not valid (expected: {{ min }}).", + TypeErrorMessage: "This value can not be processed.", + } +} + +func (c Length) WithMin(v int) Length { + c.Min = &v + + return c +} + +func (c Length) WithMax(v int) Length { + c.Max = &v + + return c +} + +func (c Length) WithExact(v int) Length { + c.Min = &v + c.Max = &v + + return c +} + +func (c Length) Validate(data any) []Error { + if c.Min == nil && c.Max == nil { + return []Error{} + } + + errors := []Error{} + + t := reflect.TypeOf(data) + + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + var size *int + + switch t.Kind() { + case reflect.Array: + case reflect.Slice: + s := reflect.ValueOf(data).Len() + size = &s + case reflect.String: + s := len(data.(string)) + size = &s + + default: + errors = append(errors, Error(c.TypeErrorMessage)) + } + + if size != nil { + if c.Max != nil && c.Min != nil { + if *c.Max == *c.Min && *size != *c.Max { + errors = append(errors, Error(c.BuildMessage(c.ExactMessage))) + } + } else if c.Min != nil && *size < *c.Min { + errors = append(errors, Error(c.BuildMessage(c.MinMessage))) + } else if c.Max != nil && *size > *c.Max { + errors = append(errors, Error(c.BuildMessage(c.MaxMessage))) + } + } + + return errors +} + +func (c *Length) BuildMessage(message string) string { + message = strings.ReplaceAll(message, "{{ min }}", cast.ToString(c.Min)) + message = strings.ReplaceAll(message, "{{ max }}", cast.ToString(c.Max)) + + return message +} diff --git a/validation/range.go b/validation/range.go new file mode 100644 index 0000000..0bbdb65 --- /dev/null +++ b/validation/range.go @@ -0,0 +1,102 @@ +package validation + +import ( + "reflect" + "strings" + + "github.com/spf13/cast" +) + +type Range struct { + Min *float64 + Max *float64 + MinMessage string + MaxMessage string + RangeMessage string + TypeErrorMessage string +} + +func NewRange() Range { + return Range{ + MinMessage: "This value must be greater than or equal to {{ min }}.", + MaxMessage: "This value must be less than or equal to {{ max }}.", + RangeMessage: "This value should be between {{ min }} and {{ max }}.", + TypeErrorMessage: "This value can not be processed.", + } +} + +func (c Range) WithMin(v float64) Range { + c.Min = &v + + return c +} + +func (c Range) WithMax(v float64) Range { + c.Max = &v + + return c +} + +func (c Range) WithRange(vMin, vMax float64) Range { + c.Min = &vMin + c.Max = &vMax + + return c +} + +func (c Range) Validate(data any) []Error { + if c.Min == nil && c.Max == nil { + return []Error{} + } + + errors := []Error{} + + t := reflect.TypeOf(data) + + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + switch t.Kind() { + case reflect.Float32: + case reflect.Float64: + case reflect.Int: + case reflect.Int16: + case reflect.Int32: + case reflect.Int64: + case reflect.Int8: + case reflect.Uint: + case reflect.Uint16: + case reflect.Uint32: + case reflect.Uint64: + case reflect.Uint8: + case reflect.String: + isValidMin := c.Min == nil || *c.Min <= cast.ToFloat64(data.(string)) + isValidMax := c.Max == nil || *c.Max >= cast.ToFloat64(data.(string)) + + if !isValidMin || !isValidMax { + errors = append(errors, Error(c.BuildMessage())) + } + default: + errors = append(errors, Error(c.TypeErrorMessage)) + } + + return errors +} + +func (c *Range) BuildMessage() string { + var message string + + if c.Min != nil && c.Max == nil { + message = c.MinMessage + } else if c.Max != nil && c.Min == nil { + message = c.MaxMessage + } else { + message = c.RangeMessage + } + + message = strings.ReplaceAll(message, "{{ min }}", cast.ToString(c.Min)) + message = strings.ReplaceAll(message, "{{ max }}", cast.ToString(c.Max)) + + return message +} diff --git a/validation/regex.go b/validation/regex.go new file mode 100644 index 0000000..5dc6f8e --- /dev/null +++ b/validation/regex.go @@ -0,0 +1,64 @@ +package validation + +import ( + "reflect" + "regexp" +) + +type Regex struct { + Message string + TypeErrorMessage string + Match bool + Expression string +} + +func NewRegex(expr string) Regex { + return Regex{ + Message: "This value is not valid.", + TypeErrorMessage: "This value can not be processed.", + Match: true, + Expression: expr, + } +} + +func (c Regex) MustMatch() Regex { + c.Match = true + + return c +} + +func (c Regex) MustNotMatch() Regex { + c.Match = false + + return c +} + +func (c Regex) Validate(data any) []Error { + errors := []Error{} + notBlank := NotBlank{} + nbErrs := notBlank.Validate(data) + + if len(nbErrs) > 0 { + return errors + } + + t := reflect.TypeOf(data) + + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + + switch t.Kind() { + case reflect.String: + matched, _ := regexp.MatchString(c.Expression, data.(string)) + + if !matched && c.Match || matched && !c.Match { + errors = append(errors, Error(c.Message)) + } + + default: + errors = append(errors, Error(c.TypeErrorMessage)) + } + + return errors +} From 287acfc4d2454f95cc75a404580e16a16f0af991 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 20 Jul 2025 15:21:46 +0200 Subject: [PATCH 006/122] feat: add csrf input --- form/field_input_csrf.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 form/field_input_csrf.go diff --git a/form/field_input_csrf.go b/form/field_input_csrf.go new file mode 100644 index 0000000..0b25ece --- /dev/null +++ b/form/field_input_csrf.go @@ -0,0 +1,8 @@ +package form + +func NewFieldCsrf(name string) *Field { + f := NewFieldHidden(name). + WithFixedName() + + return f +} From 1f232437dbeca22f7ee76d397d82b340c240dc58 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 20 Jul 2025 15:22:00 +0200 Subject: [PATCH 007/122] feat: add boostrap5 theme --- theme/bootstrap5.go | 140 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 theme/bootstrap5.go diff --git a/theme/bootstrap5.go b/theme/bootstrap5.go new file mode 100644 index 0000000..34d697e --- /dev/null +++ b/theme/bootstrap5.go @@ -0,0 +1,140 @@ +package theme + +var Bootstrap5 = map[string]string{ + "form": `
    + {{- form_error .Form nil -}} + + {{- form_help .Form -}} + + {{- range $field := .Form.Fields -}} + {{- form_row $field -}} + {{- end -}} +
    `, + "attributes": `{{ range $key, $value := .Attributes }}{{ $key }}="{{ $value }}"{{ end }}`, + "help": ` + {{- if gt (len .Help) 0 -}} +
    {{ .Help }}
    + {{- end -}} + `, + "label": ` + {{ if .Field.HasOption "label" }} + {{ $label := (.Field.GetOption "label").Value }} + + {{- if ne $label "" -}} + + {{- end -}} + {{- end -}} + `, + "input": ` + {{- $type := .Field.GetOption "type" -}} + {{- $checked := and (eq (.Field.GetOption "type").Value "checkbox") (.Field.Data) -}} + {{- $required := and (.Field.HasOption "required") (.Field.GetOption "required").Value -}} + {{- $value := .Field.Data -}} + {{- $class := "form-control" }} + + {{- if eq $type.Value "checkbox" -}} + {{- $value = 1 -}} + {{- end -}} + + {{- if or (eq $type.Value "checkbox") (eq $type.Value "radio") -}} + {{- $class = "form-check-input" -}} + {{- end -}} + + {{- if eq $type.Value "range" -}} + {{- $class = "form-range" -}} + {{- end -}} + + {{- if or (eq $type.Value "submit") (eq $type.Value "reset") (eq $type.Value "button") -}} + {{- $class = "" -}} + + {{ if .Field.HasOption "attr" }} + {{ $class = (.Field.GetOption "attr").Value.attr.class }} + {{ end }} + {{- end -}} + + + `, + "textarea": ` + + `, + "choice": ` + {{- $required := and (.Field.HasOption "required") (.Field.GetOption "required").Value -}} + {{- $isExpanded := (.Field.GetOption "expanded").Value -}} + {{- $isMultiple := (.Field.GetOption "multiple").Value -}} + {{- $emptyChoiceLabel := (.Field.GetOption "empty_choice_label").Value -}} + {{- $choices := (.Field.GetOption "choices").Value -}} + {{- $field := .Field -}} + {{- $keyAdd := 0 -}} + + {{- if and (not $required) (not $isMultiple) -}} + {{- $keyAdd = 1 -}} + {{- end -}} + + {{- if $isExpanded -}} + {{- if and (not $required) (not $isMultiple) -}} +
    + + +
    + {{- end -}} + + {{- range $key, $choice := $choices.GetChoices -}} +
    + + +
    + {{- end -}} + {{- else -}} + + {{- end -}} + `, + "sub_form": ` +
    + {{ if .Field.HasOption "label" }} + {{ $label := (.Field.GetOption "label").Value }} + + {{- if ne $label "" -}} + {{ $label }} + {{- end -}} + {{- end -}} + + {{ form_widget_help .Field }} + + {{- range $field := .Field.Children -}} + {{- form_row $field -}} + {{- end -}} +
    + `, + "error": ` + {{- if gt (len .Errors) 0 -}} +
    + {{- range $error := .Errors -}} +
    {{- $error -}}
    + {{- end -}} +
    + {{- end -}} + `, + "row": `
    + {{ $labelAfterWidget := and (.Field.HasOption "type") (eq (.Field.GetOption "type").Value "checkbox") }} + + {{ if and (eq (len .Field.Children) 0) (not $labelAfterWidget) }} + {{- form_label .Field -}} + {{ end }} + + {{- form_widget .Field -}} + {{- form_error nil .Field -}} + + {{ if and (eq (len .Field.Children) 0) ($labelAfterWidget) }} + {{- form_label .Field -}} + {{ end }} + + {{- form_widget_help .Field -}} +
    `, +} From f533cd60d5d39a450376d6b9746ff62d085a88d0 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 20 Jul 2025 15:22:42 +0200 Subject: [PATCH 008/122] feat: improve templates --- theme/renderer.go | 13 +++++++++++++ validation/mail.go | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/theme/renderer.go b/theme/renderer.go index d43edc7..7037965 100644 --- a/theme/renderer.go +++ b/theme/renderer.go @@ -96,6 +96,18 @@ func (r *Renderer) RenderFormAttr(form *form.Form) template.HTMLAttr { }) } +func (r *Renderer) RenderRowAttr(field *form.Field) template.HTMLAttr { + var attributes map[string]string + + if field.HasOption("row_attr") { + attributes = field.GetOption("row_attr").Value.(map[string]string) + } + + return r.RenderAttr("raw_attr", r.Theme["attributes"], map[string]any{ + "Attributes": attributes, + }) +} + func (r *Renderer) RenderFormHelp(form *form.Form) template.HTML { var help string @@ -147,6 +159,7 @@ func (r *Renderer) FuncMap() template.FuncMap { "form_attr": r.RenderFormAttr, "form_widget_attr": r.RenderWidgetAttr, "form_label_attr": r.RenderLabelAttr, + "form_row_attr": r.RenderRowAttr, "form_help": r.RenderFormHelp, "form_widget_help": r.RenderWidgetHelp, "sum": func(values ...any) float64 { diff --git a/validation/mail.go b/validation/mail.go index d999dc7..ddc4504 100644 --- a/validation/mail.go +++ b/validation/mail.go @@ -3,6 +3,13 @@ package validation import "net/mail" type Mail struct { + Message string +} + +func NewMail() Mail { + return Mail{ + Message: "This value is not a valid email address.", + } } func (c Mail) Validate(data any) []Error { @@ -18,7 +25,7 @@ func (c Mail) Validate(data any) []Error { _, err := mail.ParseAddress(data.(string)) if err != nil { - errors = append(errors, Error("This value is not a valid email address.")) + errors = append(errors, Error(c.Message)) } return errors From 72be88a928ca55e8d2cf4d6ee850d0d6272a7af9 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 20 Jul 2025 15:22:49 +0200 Subject: [PATCH 009/122] feat: improve templates --- theme/html5.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/theme/html5.go b/theme/html5.go index 2e1055a..0ea3d62 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -56,7 +56,7 @@ var Html5 = map[string]string{ {{- if $isExpanded -}} {{- if and (not $required) (not $isMultiple) -}} - + {{- end -}} {{- range $key, $choice := $choices.GetChoices -}} @@ -65,7 +65,7 @@ var Html5 = map[string]string{ {{- end -}} {{- else -}} + + CTRL K + + + +
    +
      +
      + + + + + +GitHub + + + + +
      +
      + + + + + +
      +
      +
      +

      Categories

      +
      +
      + +
      +
      + +
      +
      +
      +
      + +
      +

      + + + + + + diff --git a/public/categories/index.xml b/public/categories/index.xml new file mode 100644 index 0000000..86eab3b --- /dev/null +++ b/public/categories/index.xml @@ -0,0 +1,18 @@ + + + deblan/go-form – Categories + http://localhost:1313/categories/ + Recent content in Categories on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + diff --git a/public/css/compiled/main.css b/public/css/compiled/main.css new file mode 100644 index 0000000..c482e48 --- /dev/null +++ b/public/css/compiled/main.css @@ -0,0 +1,3637 @@ +/* +! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com +*//* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; /* 1 */ + border-width: 0; /* 2 */ + border-style: solid; /* 2 */ + border-color: #e5e7eb; /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -moz-tab-size: 4; /* 3 */ + -o-tab-size: 4; + tab-size: 4; /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ + font-feature-settings: normal; /* 5 */ + font-variation-settings: normal; /* 6 */ + -webkit-tap-highlight-color: transparent; /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; /* 1 */ + line-height: inherit; /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; /* 1 */ + color: inherit; /* 2 */ + border-top-width: 1px; /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ + font-feature-settings: normal; /* 2 */ + font-variation-settings: normal; /* 3 */ + font-size: 1em; /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; /* 1 */ + border-color: inherit; /* 2 */ + border-collapse: collapse; /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-feature-settings: inherit; /* 1 */ + font-variation-settings: inherit; /* 1 */ + font-size: 100%; /* 1 */ + font-weight: inherit; /* 1 */ + line-height: inherit; /* 1 */ + letter-spacing: inherit; /* 1 */ + color: inherit; /* 1 */ + margin: 0; /* 2 */ + padding: 0; /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; /* 1 */ + background-color: transparent; /* 2 */ + background-image: none; /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; /* 1 */ + vertical-align: middle; /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} +.hx-sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} +.hx-pointer-events-none { + pointer-events: none; +} +.hx-fixed { + position: fixed; +} +.hx-absolute { + position: absolute; +} +.hx-relative { + position: relative; +} +.hx-sticky { + position: sticky; +} +.hx-inset-0 { + inset: 0px; +} +.hx-inset-x-0 { + left: 0px; + right: 0px; +} +.hx-inset-y-0 { + top: 0px; + bottom: 0px; +} +.hx-bottom-0 { + bottom: 0px; +} +.hx-left-\[24px\] { + left: 24px; +} +.hx-left-\[36px\] { + left: 36px; +} +.hx-right-0 { + right: 0px; +} +.hx-top-0 { + top: 0px; +} +.hx-top-16 { + top: 4rem; +} +.hx-top-8 { + top: 2rem; +} +.hx-top-\[40\%\] { + top: 40%; +} +.hx-top-full { + top: 100%; +} +.hx-z-10 { + z-index: 10; +} +.hx-z-20 { + z-index: 20; +} +.hx-z-\[-1\] { + z-index: -1; +} +.hx-order-last { + order: 9999; +} +.hx-m-\[11px\] { + margin: 11px; +} +.hx-mx-1 { + margin-left: 0.25rem; + margin-right: 0.25rem; +} +.hx-mx-4 { + margin-left: 1rem; + margin-right: 1rem; +} +.hx-mx-auto { + margin-left: auto; + margin-right: auto; +} +.hx-my-1\.5 { + margin-top: 0.375rem; + margin-bottom: 0.375rem; +} +.hx-my-2 { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} +.-hx-mb-0\.5 { + margin-bottom: -0.125rem; +} +.-hx-ml-2 { + margin-left: -0.5rem; +} +.-hx-mr-2 { + margin-right: -0.5rem; +} +.-hx-mt-20 { + margin-top: -5rem; +} +.hx-mb-10 { + margin-bottom: 2.5rem; +} +.hx-mb-12 { + margin-bottom: 3rem; +} +.hx-mb-16 { + margin-bottom: 4rem; +} +.hx-mb-2 { + margin-bottom: 0.5rem; +} +.hx-mb-4 { + margin-bottom: 1rem; +} +.hx-mb-6 { + margin-bottom: 1.5rem; +} +.hx-mb-8 { + margin-bottom: 2rem; +} +.hx-ml-4 { + margin-left: 1rem; +} +.hx-mr-1 { + margin-right: 0.25rem; +} +.hx-mr-2 { + margin-right: 0.5rem; +} +.hx-mt-1 { + margin-top: 0.25rem; +} +.hx-mt-1\.5 { + margin-top: 0.375rem; +} +.hx-mt-12 { + margin-top: 3rem; +} +.hx-mt-16 { + margin-top: 4rem; +} +.hx-mt-2 { + margin-top: 0.5rem; +} +.hx-mt-4 { + margin-top: 1rem; +} +.hx-mt-5 { + margin-top: 1.25rem; +} +.hx-mt-6 { + margin-top: 1.5rem; +} +.hx-mt-8 { + margin-top: 2rem; +} +.hx-line-clamp-3 { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 3; +} +.hx-block { + display: block; +} +.hx-inline-block { + display: inline-block; +} +.hx-inline { + display: inline; +} +.hx-flex { + display: flex; +} +.hx-inline-flex { + display: inline-flex; +} +.hx-grid { + display: grid; +} +.hx-hidden { + display: none; +} +.hx-aspect-auto { + aspect-ratio: auto; +} +.hx-h-0 { + height: 0px; +} +.hx-h-16 { + height: 4rem; +} +.hx-h-2 { + height: 0.5rem; +} +.hx-h-3\.5 { + height: 0.875rem; +} +.hx-h-4 { + height: 1rem; +} +.hx-h-5 { + height: 1.25rem; +} +.hx-h-7 { + height: 1.75rem; +} +.hx-h-\[18px\] { + height: 18px; +} +.hx-h-full { + height: 100%; +} +.hx-max-h-64 { + max-height: 16rem; +} +.hx-max-h-\[calc\(100vh-var\(--navbar-height\)-env\(safe-area-inset-bottom\)\)\] { + max-height: calc(100vh - var(--navbar-height) - env(safe-area-inset-bottom)); +} +.hx-max-h-\[min\(calc\(50vh-11rem-env\(safe-area-inset-bottom\)\)\,400px\)\] { + max-height: min(calc(50vh - 11rem - env(safe-area-inset-bottom)),400px); +} +.hx-min-h-\[100px\] { + min-height: 100px; +} +.hx-min-h-\[calc\(100vh-var\(--navbar-height\)\)\] { + min-height: calc(100vh - var(--navbar-height)); +} +.hx-w-2 { + width: 0.5rem; +} +.hx-w-3\.5 { + width: 0.875rem; +} +.hx-w-4 { + width: 1rem; +} +.hx-w-64 { + width: 16rem; +} +.hx-w-\[110\%\] { + width: 110%; +} +.hx-w-\[180\%\] { + width: 180%; +} +.hx-w-full { + width: 100%; +} +.hx-w-max { + width: -moz-max-content; + width: max-content; +} +.hx-w-screen { + width: 100vw; +} +.hx-min-w-0 { + min-width: 0px; +} +.hx-min-w-\[18px\] { + min-width: 18px; +} +.hx-min-w-\[24px\] { + min-width: 24px; +} +.hx-min-w-full { + min-width: 100%; +} +.hx-max-w-6xl { + max-width: 72rem; +} +.hx-max-w-\[50\%\] { + max-width: 50%; +} +.hx-max-w-\[90rem\] { + max-width: 90rem; +} +.hx-max-w-\[min\(calc\(100vw-2rem\)\,calc\(100\%\+20rem\)\)\] { + max-width: min(calc(100vw - 2rem),calc(100% + 20rem)); +} +.hx-max-w-none { + max-width: none; +} +.hx-max-w-screen-xl { + max-width: 1280px; +} +.hx-shrink-0 { + flex-shrink: 0; +} +.hx-grow { + flex-grow: 1; +} +.hx-origin-center { + transform-origin: center; +} +.hx-cursor-default { + cursor: default; +} +.hx-cursor-pointer { + cursor: pointer; +} +.hx-select-none { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} +.hx-scroll-my-6 { + scroll-margin-top: 1.5rem; + scroll-margin-bottom: 1.5rem; +} +.hx-scroll-py-6 { + scroll-padding-top: 1.5rem; + scroll-padding-bottom: 1.5rem; +} +.hx-list-none { + list-style-type: none; +} +.hx-appearance-none { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.hx-grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} +.hx-flex-col { + flex-direction: column; +} +.hx-flex-wrap { + flex-wrap: wrap; +} +.hx-items-start { + align-items: flex-start; +} +.hx-items-center { + align-items: center; +} +.hx-justify-start { + justify-content: flex-start; +} +.hx-justify-end { + justify-content: flex-end; +} +.hx-justify-center { + justify-content: center; +} +.hx-justify-between { + justify-content: space-between; +} +.hx-justify-items-start { + justify-items: start; +} +.hx-gap-1 { + gap: 0.25rem; +} +.hx-gap-2 { + gap: 0.5rem; +} +.hx-gap-4 { + gap: 1rem; +} +.hx-gap-x-1\.5 { + -moz-column-gap: 0.375rem; + column-gap: 0.375rem; +} +.hx-gap-y-2 { + row-gap: 0.5rem; +} +.hx-overflow-auto { + overflow: auto; +} +.hx-overflow-hidden { + overflow: hidden; +} +.hx-overflow-x-auto { + overflow-x: auto; +} +.hx-overflow-y-auto { + overflow-y: auto; +} +.hx-overflow-x-hidden { + overflow-x: hidden; +} +.hx-overflow-y-hidden { + overflow-y: hidden; +} +.hx-overscroll-contain { + overscroll-behavior: contain; +} +.hx-overscroll-x-contain { + overscroll-behavior-x: contain; +} +.hx-text-ellipsis { + text-overflow: ellipsis; +} +.hx-whitespace-nowrap { + white-space: nowrap; +} +.hx-break-words { + overflow-wrap: break-word; +} +.hx-rounded { + border-radius: 0.25rem; +} +.hx-rounded-3xl { + border-radius: 1.5rem; +} +.hx-rounded-full { + border-radius: 9999px; +} +.hx-rounded-lg { + border-radius: 0.5rem; +} +.hx-rounded-md { + border-radius: 0.375rem; +} +.hx-rounded-sm { + border-radius: 0.125rem; +} +.hx-rounded-xl { + border-radius: 0.75rem; +} +.hx-rounded-t { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.hx-border { + border-width: 1px; +} +.hx-border-b { + border-bottom-width: 1px; +} +.hx-border-b-2 { + border-bottom-width: 2px; +} +.hx-border-t { + border-top-width: 1px; +} +.hx-border-amber-200 { + --tw-border-opacity: 1; + border-color: rgb(253 230 138 / var(--tw-border-opacity)); +} +.hx-border-black\/5 { + border-color: rgb(0 0 0 / 0.05); +} +.hx-border-blue-200 { + --tw-border-opacity: 1; + border-color: rgb(191 219 254 / var(--tw-border-opacity)); +} +.hx-border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} +.hx-border-gray-500 { + --tw-border-opacity: 1; + border-color: rgb(107 114 128 / var(--tw-border-opacity)); +} +.hx-border-green-200 { + --tw-border-opacity: 1; + border-color: rgb(187 247 208 / var(--tw-border-opacity)); +} +.hx-border-indigo-200 { + --tw-border-opacity: 1; + border-color: rgb(199 210 254 / var(--tw-border-opacity)); +} +.hx-border-orange-100 { + --tw-border-opacity: 1; + border-color: rgb(255 237 213 / var(--tw-border-opacity)); +} +.hx-border-red-200 { + --tw-border-opacity: 1; + border-color: rgb(254 202 202 / var(--tw-border-opacity)); +} +.hx-border-transparent { + border-color: transparent; +} +.hx-border-yellow-100 { + --tw-border-opacity: 1; + border-color: rgb(254 249 195 / var(--tw-border-opacity)); +} +.hx-bg-amber-100 { + --tw-bg-opacity: 1; + background-color: rgb(254 243 199 / var(--tw-bg-opacity)); +} +.hx-bg-black\/80 { + background-color: rgb(0 0 0 / 0.8); +} +.hx-bg-black\/\[\.05\] { + background-color: rgb(0 0 0 / .05); +} +.hx-bg-blue-100 { + --tw-bg-opacity: 1; + background-color: rgb(219 234 254 / var(--tw-bg-opacity)); +} +.hx-bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} +.hx-bg-green-100 { + --tw-bg-opacity: 1; + background-color: rgb(220 252 231 / var(--tw-bg-opacity)); +} +.hx-bg-indigo-100 { + --tw-bg-opacity: 1; + background-color: rgb(224 231 255 / var(--tw-bg-opacity)); +} +.hx-bg-neutral-50 { + --tw-bg-opacity: 1; + background-color: rgb(250 250 250 / var(--tw-bg-opacity)); +} +.hx-bg-orange-50 { + --tw-bg-opacity: 1; + background-color: rgb(255 247 237 / var(--tw-bg-opacity)); +} +.hx-bg-primary-100 { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / var(--tw-bg-opacity)); +} +.hx-bg-primary-400 { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 16) / var(--tw-bg-opacity)); +} +.hx-bg-primary-600 { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-bg-opacity)); +} +.hx-bg-primary-700\/5 { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); +} +.hx-bg-red-100 { + --tw-bg-opacity: 1; + background-color: rgb(254 226 226 / var(--tw-bg-opacity)); +} +.hx-bg-transparent { + background-color: transparent; +} +.hx-bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} +.hx-bg-yellow-50 { + --tw-bg-opacity: 1; + background-color: rgb(254 252 232 / var(--tw-bg-opacity)); +} +.hx-bg-gradient-to-r { + background-image: linear-gradient(to right, var(--tw-gradient-stops)); +} +.hx-from-gray-900 { + --tw-gradient-from: #111827 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} +.hx-to-gray-600 { + --tw-gradient-to: #4b5563 var(--tw-gradient-to-position); +} +.hx-bg-clip-text { + -webkit-background-clip: text; + background-clip: text; +} +.hx-p-0\.5 { + padding: 0.125rem; +} +.hx-p-1 { + padding: 0.25rem; +} +.hx-p-1\.5 { + padding: 0.375rem; +} +.hx-p-2 { + padding: 0.5rem; +} +.hx-p-4 { + padding: 1rem; +} +.hx-p-6 { + padding: 1.5rem; +} +.hx-px-1\.5 { + padding-left: 0.375rem; + padding-right: 0.375rem; +} +.hx-px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} +.hx-px-2\.5 { + padding-left: 0.625rem; + padding-right: 0.625rem; +} +.hx-px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} +.hx-px-4 { + padding-left: 1rem; + padding-right: 1rem; +} +.hx-px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} +.hx-py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} +.hx-py-1\.5 { + padding-top: 0.375rem; + padding-bottom: 0.375rem; +} +.hx-py-12 { + padding-top: 3rem; + padding-bottom: 3rem; +} +.hx-py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.hx-py-2\.5 { + padding-top: 0.625rem; + padding-bottom: 0.625rem; +} +.hx-py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} +.hx-py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} +.hx-pb-8 { + padding-bottom: 2rem; +} +.hx-pb-\[env\(safe-area-inset-bottom\)\] { + padding-bottom: env(safe-area-inset-bottom); +} +.hx-pb-px { + padding-bottom: 1px; +} +.hx-pl-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\] { + padding-left: max(env(safe-area-inset-left),1.5rem); +} +.hx-pr-2 { + padding-right: 0.5rem; +} +.hx-pr-4 { + padding-right: 1rem; +} +.hx-pr-\[calc\(env\(safe-area-inset-right\)-1\.5rem\)\] { + padding-right: calc(env(safe-area-inset-right) - 1.5rem); +} +.hx-pr-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\] { + padding-right: max(env(safe-area-inset-left),1.5rem); +} +.hx-pr-\[max\(env\(safe-area-inset-right\)\,1\.5rem\)\] { + padding-right: max(env(safe-area-inset-right),1.5rem); +} +.hx-pt-4 { + padding-top: 1rem; +} +.hx-pt-6 { + padding-top: 1.5rem; +} +.hx-pt-8 { + padding-top: 2rem; +} +.hx-text-left { + text-align: left; +} +.hx-text-center { + text-align: center; +} +.hx-align-middle { + vertical-align: middle; +} +.hx-align-text-bottom { + vertical-align: text-bottom; +} +.hx-align-\[-2\.5px\] { + vertical-align: -2.5px; +} +.hx-font-mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} +.hx-text-2xl { + font-size: 1.5rem; +} +.hx-text-4xl { + font-size: 2.25rem; +} +.hx-text-\[\.65rem\] { + font-size: .65rem; +} +.hx-text-\[10px\] { + font-size: 10px; +} +.hx-text-base { + font-size: 1rem; +} +.hx-text-lg { + font-size: 1.125rem; +} +.hx-text-sm { + font-size: .875rem; +} +.hx-text-xl { + font-size: 1.25rem; +} +.hx-text-xs { + font-size: .75rem; +} +.hx-font-bold { + font-weight: 700; +} +.hx-font-extrabold { + font-weight: 800; +} +.hx-font-medium { + font-weight: 500; +} +.hx-font-normal { + font-weight: 400; +} +.hx-font-semibold { + font-weight: 600; +} +.hx-capitalize { + text-transform: capitalize; +} +.hx-leading-5 { + line-height: 1.25rem; +} +.hx-leading-6 { + line-height: 1.5rem; +} +.hx-leading-7 { + line-height: 1.75rem; +} +.hx-leading-none { + line-height: 1; +} +.hx-leading-tight { + line-height: 1.25; +} +.hx-tracking-tight { + letter-spacing: -0.015em; +} +.hx-text-\[color\:hsl\(var\(--primary-hue\)\,100\%\,50\%\)\] { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) 100% 50% / var(--tw-text-opacity)); +} +.hx-text-amber-900 { + --tw-text-opacity: 1; + color: rgb(120 53 15 / var(--tw-text-opacity)); +} +.hx-text-blue-900 { + --tw-text-opacity: 1; + color: rgb(30 58 138 / var(--tw-text-opacity)); +} +.hx-text-current { + color: currentColor; +} +.hx-text-gray-100 { + --tw-text-opacity: 1; + color: rgb(243 244 246 / var(--tw-text-opacity)); +} +.hx-text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} +.hx-text-gray-600 { + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} +.hx-text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} +.hx-text-gray-800 { + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity)); +} +.hx-text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} +.hx-text-green-900 { + --tw-text-opacity: 1; + color: rgb(20 83 45 / var(--tw-text-opacity)); +} +.hx-text-indigo-900 { + --tw-text-opacity: 1; + color: rgb(49 46 129 / var(--tw-text-opacity)); +} +.hx-text-orange-800 { + --tw-text-opacity: 1; + color: rgb(154 52 18 / var(--tw-text-opacity)); +} +.hx-text-primary-800 { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / var(--tw-text-opacity)); +} +.hx-text-red-900 { + --tw-text-opacity: 1; + color: rgb(127 29 29 / var(--tw-text-opacity)); +} +.hx-text-slate-900 { + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +.hx-text-transparent { + color: transparent; +} +.hx-text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} +.hx-text-yellow-900 { + --tw-text-opacity: 1; + color: rgb(113 63 18 / var(--tw-text-opacity)); +} +.hx-underline { + text-decoration-line: underline; +} +.hx-no-underline { + text-decoration-line: none; +} +.hx-decoration-from-font { + text-decoration-thickness: from-font; +} +.hx-underline-offset-2 { + text-underline-offset: 2px; +} +.hx-opacity-0 { + opacity: 0; +} +.hx-opacity-50 { + opacity: 0.5; +} +.hx-opacity-80 { + opacity: 0.8; +} +.hx-shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-\[0_-12px_16px_\#fff\] { + --tw-shadow: 0 -12px 16px #fff; + --tw-shadow-colored: 0 -12px 16px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-\[0_-12px_16px_white\] { + --tw-shadow: 0 -12px 16px white; + --tw-shadow-colored: 0 -12px 16px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-\[0_2px_4px_rgba\(0\,0\,0\,\.02\)\,0_1px_0_rgba\(0\,0\,0\,\.06\)\] { + --tw-shadow: 0 2px 4px rgba(0,0,0,.02),0 1px 0 rgba(0,0,0,.06); + --tw-shadow-colored: 0 2px 4px var(--tw-shadow-color), 0 1px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-lg { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-sm { + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-xl { + --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hx-shadow-gray-100 { + --tw-shadow-color: #f3f4f6; + --tw-shadow: var(--tw-shadow-colored); +} +.hx-ring-1 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} +.hx-ring-black\/5 { + --tw-ring-color: rgb(0 0 0 / 0.05); +} +.hx-transition { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.hx-transition-all { + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.hx-transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.hx-transition-opacity { + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.hx-transition-transform { + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.hx-duration-200 { + transition-duration: 200ms; +} +.hx-duration-75 { + transition-duration: 75ms; +} +.hx-ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); +} +.\[-webkit-tap-highlight-color\:transparent\] { + -webkit-tap-highlight-color: transparent; +} +.\[-webkit-touch-callout\:none\] { + -webkit-touch-callout: none; +} +.\[counter-reset\:step\] { + counter-reset: step; +} +.\[hyphens\:auto\] { + -webkit-hyphens: auto; + hyphens: auto; +} +.\[transition\:background-color_1\.5s_ease\] { + transition: background-color 1.5s ease; +} +.\[word-break\:break-word\] { + word-break: break-word; +} +.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 0.5rem; + font-size: 2.25rem; + font-weight: 700; + letter-spacing: -0.015em; + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 2.5rem; + border-bottom-width: 1px; + border-color: rgb(229 229 229 / 0.7); + padding-bottom: 0.25rem; + font-size: 1.875rem; + font-weight: 600; + letter-spacing: -0.015em; + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +@media (prefers-contrast: more) { + + .content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)) { + --tw-border-opacity: 1; + border-color: rgb(163 163 163 / var(--tw-border-opacity)); + } +} +.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.1); + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +@media (prefers-contrast: more) { + + .content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(163 163 163 / var(--tw-border-opacity)); + } +} +.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 2rem; + font-size: 1.5rem; + font-weight: 600; + letter-spacing: -0.015em; + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 2rem; + font-size: 1.25rem; + font-weight: 600; + letter-spacing: -0.015em; + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 2rem; + font-size: 1.125rem; + font-weight: 600; + letter-spacing: -0.015em; + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 2rem; + font-size: 1rem; + font-weight: 600; + letter-spacing: -0.015em; + --tw-text-opacity: 1; + color: rgb(15 23 42 / var(--tw-text-opacity)); +} +.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 1.5rem; + line-height: 1.75rem; +} +.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { + margin-top: 0px; +} +.content :where(a):not(:where([class~=not-prose],[class~=not-prose] *)) { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); + text-decoration-line: underline; + text-decoration-thickness: from-font; + text-underline-position: from-font; +} +.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 1.5rem; + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); + font-style: italic; + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} +.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { + margin-top: 0px; +} +.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity)); + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="ltr"], [dir="ltr"] *) { + border-left-width: 2px; + padding-left: 1.5rem; +} +.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="rtl"], [dir="rtl"] *) { + border-right-width: 2px; + padding-right: 1.5rem; +} +.content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { + margin-bottom: 1rem; + overflow-x: auto; + border-radius: 0.75rem; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); + padding-top: 1rem; + padding-bottom: 1rem; + font-size: .9em; + font-weight: 500; + -webkit-font-smoothing: auto; + -moz-osx-font-smoothing: auto; +} +@media (prefers-contrast: more) { + + .content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { + border-width: 1px; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 24) / 0.2); + --tw-contrast: contrast(1.5); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + } +} +.content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); +} +@media (prefers-contrast: more) { + + .content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.4); + } +} +.content :where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)) { + overflow-wrap: break-word; + border-radius: 0.375rem; + border-width: 1px; + border-color: rgb(0 0 0 / var(--tw-border-opacity)); + --tw-border-opacity: 0.04; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); + --tw-bg-opacity: 0.03; + padding-top: 0.125rem; + padding-bottom: 0.125rem; + padding-left: .25em; + padding-right: .25em; + font-size: .9em; +} +.content :where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + border-color: rgb(255 255 255 / 0.1); + background-color: rgb(255 255 255 / 0.1); +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) { + margin-top: 1.5rem; + display: block; + overflow-x: auto; + padding: 0px; +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)):first-child { + margin-top: 0px; +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr { + margin: 0px; + border-top-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); + padding: 0px; +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr:nth-child(even) { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr:is(html[class~="dark"] *):nth-child(even) { + background-color: rgb(75 85 99 / 0.2); +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) th { + margin: 0px; + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + font-weight: 600; +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) th:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) td { + margin: 0px; + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) td:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); +} +.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 1.5rem; + list-style-type: decimal; +} +.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { + margin-top: 0px; +} +.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="ltr"], [dir="ltr"] *) { + margin-left: 1.5rem; +} +.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="rtl"], [dir="rtl"] *) { + margin-right: 1.5rem; +} +.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) li { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} +.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 1.5rem; + list-style-type: disc; +} +.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { + margin-top: 0px; +} +.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="ltr"], [dir="ltr"] *) { + margin-left: 1.5rem; +} +.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="rtl"], [dir="rtl"] *) { + margin-right: 1.5rem; +} +.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) li { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} +/* This CSS rule targets the first nested unordered (ul) or ordered (ol) list + inside the list item (li) of any parent ul or ol. + The rule sets the top margin of the selected list to zero. */ +.content :where(ul, ol) > li > :where(ul, ol):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-top: 0px; +} +.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)) { + overflow-wrap: break-word; + border-radius: 0.375rem; + border-width: 1px; + border-color: rgb(0 0 0 / var(--tw-border-opacity)); + --tw-border-opacity: 0.04; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); + --tw-bg-opacity: 0.03; + padding-top: 0.125rem; + padding-bottom: 0.125rem; + padding-left: .25em; + padding-right: .25em; + font-size: .9em; +} +.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + border-color: rgb(255 255 255 / 0.1); + background-color: rgb(255 255 255 / 0.1); +} +.content :where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { + border-radius: 0px; + background-color: transparent; +} +.content :where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { + background-color: transparent; +} +.content :where(img):not(:where([class~=not-prose],[class~=not-prose] *)) { + margin-left: auto; + margin-right: auto; + margin-top: 1rem; + margin-bottom: 1rem; + border-radius: 0.375rem; +} +.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption { + margin-top: 0.5rem; + display: block; + text-align: center; + font-size: .875rem; + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} +.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +/* Definition list */ +.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dt { + margin-top: 1.5rem; + font-weight: 600; +} +.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dd { + margin-top: 0.5rem; + margin-bottom: 0.5rem; + padding-inline-start: 1.5rem; +} +.content .footnotes { + margin-top: 3rem; + font-size: .875rem; +} +.subheading-anchor { + opacity: 0; + transition-property: opacity; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.subheading-anchor:where([dir="ltr"], [dir="ltr"] *) { + margin-left: 0.25rem; +} +.subheading-anchor:where([dir="rtl"], [dir="rtl"] *) { + margin-right: 0.25rem; +} +span:target + .subheading-anchor, + :hover > .subheading-anchor, + .subheading-anchor:focus { + opacity: 1; +} +span + .subheading-anchor, + :hover > .subheading-anchor { + text-decoration-line: none !important; +} +.subheading-anchor:after { + padding-left: 0.25rem; + padding-right: 0.25rem; + --tw-content: '#'; + content: var(--tw-content); + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} +.subheading-anchor:is(html[class~="dark"] *):after { + --tw-text-opacity: 1; + color: rgb(64 64 64 / var(--tw-text-opacity)); +} +span:target + .subheading-anchor:after { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +span:target + .subheading-anchor:is(html[class~="dark"] *):after { + --tw-text-opacity: 1; + color: rgb(115 115 115 / var(--tw-text-opacity)); +} +article details > summary::-webkit-details-marker { + display: none; +} +article details > summary::before { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='hx-h-5 hx-w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); + height: 1.2em; + width: 1.2em; + vertical-align: -4px; + padding: 0 0.6em; + } +:lang(fa) ol { + list-style-type: persian; +} +/* Code syntax highlight */ +/* Light theme for syntax highlight */ +/* Generated using `hugo gen chromastyles --style=github` */ +.highlight { + /* Background .bg { background-color: #ffffff; } */ + /* PreWrapper .chroma { background-color: #ffffff; } */ + /* Other .chroma .x { } */ + /* CodeLine .chroma .cl { } */ + /* LineTableTD .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } */ + /* LineTable .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } */ + /* LineHighlight .chroma .hl { background-color: #ffffcc } */ + /* LineNumbersTable .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } */ + /* LineNumbers .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } */ + /* Name .chroma .n { } */ + /* NameFunctionMagic .chroma .fm { } */ + /* NameOther .chroma .nx { } */ + /* NameProperty .chroma .py { } */ + /* NameVariableMagic .chroma .vm { } */ + /* Literal .chroma .l { } */ + /* LiteralDate .chroma .ld { } */ + /* Punctuation .chroma .p { } */ + /* Generic .chroma .g { } */ +} +/* Error */ +.highlight .chroma .err { color: #a61717; background-color: #e3d2d2 } +/* LineLink */ +.highlight .chroma .lnlinks { outline: none; text-decoration: none; color: inherit } +/* Line */ +.highlight .chroma .line { display: flex; } +/* Keyword */ +.highlight .chroma .k { color: #000000; font-weight: bold } +/* KeywordConstant */ +.highlight .chroma .kc { color: #000000; font-weight: bold } +/* KeywordDeclaration */ +.highlight .chroma .kd { color: #000000; font-weight: bold } +/* KeywordNamespace */ +.highlight .chroma .kn { color: #000000; font-weight: bold } +/* KeywordPseudo */ +.highlight .chroma .kp { color: #000000; font-weight: bold } +/* KeywordReserved */ +.highlight .chroma .kr { color: #000000; font-weight: bold } +/* KeywordType */ +.highlight .chroma .kt { color: #445588; font-weight: bold } +/* NameAttribute */ +.highlight .chroma .na { color: #008080 } +/* NameBuiltin */ +.highlight .chroma .nb { color: #0086b3 } +/* NameBuiltinPseudo */ +.highlight .chroma .bp { color: #999999 } +/* NameClass */ +.highlight .chroma .nc { color: #445588; font-weight: bold } +/* NameConstant */ +.highlight .chroma .no { color: #008080 } +/* NameDecorator */ +.highlight .chroma .nd { color: #3c5d5d; font-weight: bold } +/* NameEntity */ +.highlight .chroma .ni { color: #800080 } +/* NameException */ +.highlight .chroma .ne { color: #990000; font-weight: bold } +/* NameFunction */ +.highlight .chroma .nf { color: #990000; font-weight: bold } +/* NameLabel */ +.highlight .chroma .nl { color: #990000; font-weight: bold } +/* NameNamespace */ +.highlight .chroma .nn { color: #555555 } +/* NameTag */ +.highlight .chroma .nt { color: #000080 } +/* NameVariable */ +.highlight .chroma .nv { color: #008080 } +/* NameVariableClass */ +.highlight .chroma .vc { color: #008080 } +/* NameVariableGlobal */ +.highlight .chroma .vg { color: #008080 } +/* NameVariableInstance */ +.highlight .chroma .vi { color: #008080 } +/* LiteralString */ +.highlight .chroma .s { color: #dd1144 } +/* LiteralStringAffix */ +.highlight .chroma .sa { color: #dd1144 } +/* LiteralStringBacktick */ +.highlight .chroma .sb { color: #dd1144 } +/* LiteralStringChar */ +.highlight .chroma .sc { color: #dd1144 } +/* LiteralStringDelimiter */ +.highlight .chroma .dl { color: #dd1144 } +/* LiteralStringDoc */ +.highlight .chroma .sd { color: #dd1144 } +/* LiteralStringDouble */ +.highlight .chroma .s2 { color: #dd1144 } +/* LiteralStringEscape */ +.highlight .chroma .se { color: #dd1144 } +/* LiteralStringHeredoc */ +.highlight .chroma .sh { color: #dd1144 } +/* LiteralStringInterpol */ +.highlight .chroma .si { color: #dd1144 } +/* LiteralStringOther */ +.highlight .chroma .sx { color: #dd1144 } +/* LiteralStringRegex */ +.highlight .chroma .sr { color: #009926 } +/* LiteralStringSingle */ +.highlight .chroma .s1 { color: #dd1144 } +/* LiteralStringSymbol */ +.highlight .chroma .ss { color: #990073 } +/* LiteralNumber */ +.highlight .chroma .m { color: #009999 } +/* LiteralNumberBin */ +.highlight .chroma .mb { color: #009999 } +/* LiteralNumberFloat */ +.highlight .chroma .mf { color: #009999 } +/* LiteralNumberHex */ +.highlight .chroma .mh { color: #009999 } +/* LiteralNumberInteger */ +.highlight .chroma .mi { color: #009999 } +/* LiteralNumberIntegerLong */ +.highlight .chroma .il { color: #009999 } +/* LiteralNumberOct */ +.highlight .chroma .mo { color: #009999 } +/* Operator */ +.highlight .chroma .o { color: #000000; font-weight: bold } +/* OperatorWord */ +.highlight .chroma .ow { color: #000000; font-weight: bold } +/* Comment */ +.highlight .chroma .c { color: #999988; font-style: italic } +/* CommentHashbang */ +.highlight .chroma .ch { color: #999988; font-style: italic } +/* CommentMultiline */ +.highlight .chroma .cm { color: #999988; font-style: italic } +/* CommentSingle */ +.highlight .chroma .c1 { color: #999988; font-style: italic } +/* CommentSpecial */ +.highlight .chroma .cs { color: #999999; font-weight: bold; font-style: italic } +/* CommentPreproc */ +.highlight .chroma .cp { color: #999999; font-weight: bold; font-style: italic } +/* CommentPreprocFile */ +.highlight .chroma .cpf { color: #999999; font-weight: bold; font-style: italic } +/* GenericDeleted */ +.highlight .chroma .gd { color: #000000; background-color: #ffdddd } +/* GenericEmph */ +.highlight .chroma .ge { color: #000000; font-style: italic } +/* GenericError */ +.highlight .chroma .gr { color: #aa0000 } +/* GenericHeading */ +.highlight .chroma .gh { color: #999999 } +/* GenericInserted */ +.highlight .chroma .gi { color: #000000; background-color: #ddffdd } +/* GenericOutput */ +.highlight .chroma .go { color: #888888 } +/* GenericPrompt */ +.highlight .chroma .gp { color: #555555 } +/* GenericStrong */ +.highlight .chroma .gs { font-weight: bold } +/* GenericSubheading */ +.highlight .chroma .gu { color: #aaaaaa } +/* GenericTraceback */ +.highlight .chroma .gt { color: #aa0000 } +/* GenericUnderline */ +.highlight .chroma .gl { text-decoration: underline } +/* TextWhitespace */ +.highlight .chroma .w { color: #bbbbbb } +.dark .highlight { + /* Background .bg { color: #c9d1d9; background-color: #0d1117; } + /* PreWrapper .chroma { color: #c9d1d9; background-color: #0d1117; } */ + /* LineTableTD .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } */ + /* LineTable .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } */ + /* LineHighlight .chroma .hl { background-color: #ffffcc } */ + /* LineNumbersTable .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #64686c } */ + /* LineNumbers .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #6e7681 } */ +} +/* Other */ +.dark .highlight .chroma .x { } +/* Error */ +.dark .highlight .chroma .err { color: #f85149 } +/* CodeLine */ +.dark .highlight .chroma .cl { } +/* LineLink */ +.dark .highlight .chroma .lnlinks { outline: none; text-decoration: none; color: inherit } +/* Line */ +.dark .highlight .chroma .line { display: flex; } +/* Keyword */ +.dark .highlight .chroma .k { color: #ff7b72 } +/* KeywordConstant */ +.dark .highlight .chroma .kc { color: #79c0ff } +/* KeywordDeclaration */ +.dark .highlight .chroma .kd { color: #ff7b72 } +/* KeywordNamespace */ +.dark .highlight .chroma .kn { color: #ff7b72 } +/* KeywordPseudo */ +.dark .highlight .chroma .kp { color: #79c0ff } +/* KeywordReserved */ +.dark .highlight .chroma .kr { color: #ff7b72 } +/* KeywordType */ +.dark .highlight .chroma .kt { color: #ff7b72 } +/* Name */ +.dark .highlight .chroma .n { } +/* NameAttribute */ +.dark .highlight .chroma .na { } +/* NameBuiltin */ +.dark .highlight .chroma .nb { } +/* NameBuiltinPseudo */ +.dark .highlight .chroma .bp { } +/* NameClass */ +.dark .highlight .chroma .nc { color: #f0883e; font-weight: bold } +/* NameConstant */ +.dark .highlight .chroma .no { color: #79c0ff; font-weight: bold } +/* NameDecorator */ +.dark .highlight .chroma .nd { color: #d2a8ff; font-weight: bold } +/* NameEntity */ +.dark .highlight .chroma .ni { color: #ffa657 } +/* NameException */ +.dark .highlight .chroma .ne { color: #f0883e; font-weight: bold } +/* NameFunction */ +.dark .highlight .chroma .nf { color: #d2a8ff; font-weight: bold } +/* NameFunctionMagic */ +.dark .highlight .chroma .fm { } +/* NameLabel */ +.dark .highlight .chroma .nl { color: #79c0ff; font-weight: bold } +/* NameNamespace */ +.dark .highlight .chroma .nn { color: #ff7b72 } +/* NameOther */ +.dark .highlight .chroma .nx { } +/* NameProperty */ +.dark .highlight .chroma .py { color: #79c0ff } +/* NameTag */ +.dark .highlight .chroma .nt { color: #7ee787 } +/* NameVariable */ +.dark .highlight .chroma .nv { color: #79c0ff } +/* NameVariableClass */ +.dark .highlight .chroma .vc { } +/* NameVariableGlobal */ +.dark .highlight .chroma .vg { } +/* NameVariableInstance */ +.dark .highlight .chroma .vi { } +/* NameVariableMagic */ +.dark .highlight .chroma .vm { } +/* Literal */ +.dark .highlight .chroma .l { color: #a5d6ff } +/* LiteralDate */ +.dark .highlight .chroma .ld { color: #79c0ff } +/* LiteralString */ +.dark .highlight .chroma .s { color: #a5d6ff } +/* LiteralStringAffix */ +.dark .highlight .chroma .sa { color: #79c0ff } +/* LiteralStringBacktick */ +.dark .highlight .chroma .sb { color: #a5d6ff } +/* LiteralStringChar */ +.dark .highlight .chroma .sc { color: #a5d6ff } +/* LiteralStringDelimiter */ +.dark .highlight .chroma .dl { color: #79c0ff } +/* LiteralStringDoc */ +.dark .highlight .chroma .sd { color: #a5d6ff } +/* LiteralStringDouble */ +.dark .highlight .chroma .s2 { color: #a5d6ff } +/* LiteralStringEscape */ +.dark .highlight .chroma .se { color: #79c0ff } +/* LiteralStringHeredoc */ +.dark .highlight .chroma .sh { color: #79c0ff } +/* LiteralStringInterpol */ +.dark .highlight .chroma .si { color: #a5d6ff } +/* LiteralStringOther */ +.dark .highlight .chroma .sx { color: #a5d6ff } +/* LiteralStringRegex */ +.dark .highlight .chroma .sr { color: #79c0ff } +/* LiteralStringSingle */ +.dark .highlight .chroma .s1 { color: #a5d6ff } +/* LiteralStringSymbol */ +.dark .highlight .chroma .ss { color: #a5d6ff } +/* LiteralNumber */ +.dark .highlight .chroma .m { color: #a5d6ff } +/* LiteralNumberBin */ +.dark .highlight .chroma .mb { color: #a5d6ff } +/* LiteralNumberFloat */ +.dark .highlight .chroma .mf { color: #a5d6ff } +/* LiteralNumberHex */ +.dark .highlight .chroma .mh { color: #a5d6ff } +/* LiteralNumberInteger */ +.dark .highlight .chroma .mi { color: #a5d6ff } +/* LiteralNumberIntegerLong */ +.dark .highlight .chroma .il { color: #a5d6ff } +/* LiteralNumberOct */ +.dark .highlight .chroma .mo { color: #a5d6ff } +/* Operator */ +.dark .highlight .chroma .o { color: #ff7b72; font-weight: bold } +/* OperatorWord */ +.dark .highlight .chroma .ow { color: #ff7b72; font-weight: bold } +/* Punctuation */ +.dark .highlight .chroma .p { } +/* Comment */ +.dark .highlight .chroma .c { color: #8b949e; font-style: italic } +/* CommentHashbang */ +.dark .highlight .chroma .ch { color: #8b949e; font-style: italic } +/* CommentMultiline */ +.dark .highlight .chroma .cm { color: #8b949e; font-style: italic } +/* CommentSingle */ +.dark .highlight .chroma .c1 { color: #8b949e; font-style: italic } +/* CommentSpecial */ +.dark .highlight .chroma .cs { color: #8b949e; font-weight: bold; font-style: italic } +/* CommentPreproc */ +.dark .highlight .chroma .cp { color: #8b949e; font-weight: bold; font-style: italic } +/* CommentPreprocFile */ +.dark .highlight .chroma .cpf { color: #8b949e; font-weight: bold; font-style: italic } +/* Generic */ +.dark .highlight .chroma .g { } +/* GenericDeleted */ +.dark .highlight .chroma .gd { color: #ffa198; background-color: #490202 } +/* GenericEmph */ +.dark .highlight .chroma .ge { color: inherit; font-style: italic } +/* GenericError */ +.dark .highlight .chroma .gr { color: #ffa198 } +/* GenericHeading */ +.dark .highlight .chroma .gh { color: #79c0ff; font-weight: bold } +/* GenericInserted */ +.dark .highlight .chroma .gi { color: #56d364; background-color: #0f5323 } +/* GenericOutput */ +.dark .highlight .chroma .go { color: #8b949e } +/* GenericPrompt */ +.dark .highlight .chroma .gp { color: #8b949e } +/* GenericStrong */ +.dark .highlight .chroma .gs { font-weight: bold } +/* GenericSubheading */ +.dark .highlight .chroma .gu { color: #79c0ff } +/* GenericTraceback */ +.dark .highlight .chroma .gt { color: #ff7b72 } +/* GenericUnderline */ +.dark .highlight .chroma .gl { text-decoration: underline } +/* TextWhitespace */ +.dark .highlight .chroma .w { color: #6e7681 } +.hextra-code-block { + font-size: .9em; + line-height: 1.25rem; +} +.hextra-code-block pre { + overflow-x: auto; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); + font-size: .9em; + font-weight: 500; + -webkit-font-smoothing: auto; + -moz-osx-font-smoothing: auto; +} +@media (prefers-contrast: more) { + + .hextra-code-block pre { + border-width: 1px; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 24) / 0.2); + --tw-contrast: contrast(1.5); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); + } +} +.hextra-code-block pre:is(html[class~="dark"] *) { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); +} +@media (prefers-contrast: more) { + + .hextra-code-block pre:is(html[class~="dark"] *) { + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.4); + } +} +.hextra-code-block .filename { + position: absolute; + top: 0px; + z-index: 1; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + border-top-left-radius: 0.75rem; + border-top-right-radius: 0.75rem; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: .75rem; + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} +.hextra-code-block .filename:is(html[class~="dark"] *) { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} +.hextra-code-block .filename + pre:not(.lntable pre) { + /* Override padding for code blocks with filename but no highlight */ + padding-top: 3rem; + } +.hextra-code-block pre:not(.lntable pre) { + margin-bottom: 1rem; + border-radius: 0.75rem; + padding-left: 1rem; + padding-right: 1rem; + padding-top: 1rem; + padding-bottom: 1rem; +} +.hextra-code-block div:nth-of-type(2) pre { + padding-top: 3rem; + padding-bottom: 1rem; +} +.chroma .lntable { + margin: 0px; + display: block; + width: auto; + overflow: auto; + border-radius: 0.75rem; +} +.chroma .lntable pre { + padding-top: 1rem; + padding-bottom: 1rem; +} +.chroma .ln, + .chroma .lnt:not(.hl > .lnt), + .chroma .hl:not(.line) { + min-width: 2.6rem; + padding-left: 1rem; + padding-right: 1rem; + --tw-text-opacity: 1; + color: rgb(82 82 82 / var(--tw-text-opacity)); +} +.chroma .ln:is(html[class~="dark"] *), + .chroma .lnt:not(.hl > .lnt):is(html[class~="dark"] *), + .chroma .hl:not(.line):is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(212 212 212 / var(--tw-text-opacity)); +} +.chroma .lntd { + padding: 0px; + vertical-align: top; +} +.chroma .lntd:last-of-type { + width: 100%; +} +/* LineHighlight */ +.chroma .hl { + display: block; + width: 100%; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / 0.1); +} +.hextra-cards { + grid-template-columns: repeat(auto-fill, minmax(max(250px, calc((100% - 1rem * 2) / var(--hextra-cards-grid-cols))), 1fr)); +} +.hextra-card { + position: relative; +} +.hextra-card img { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} +.hextra-card:hover svg { + color: currentColor; +} +.hextra-card svg { + width: 1.5rem; + color: #00000033; + transition: color 0.3s ease; +} +.hextra-card p { + margin-top: 0.5rem; + position: relative; +} +.dark .hextra-card svg { + color: #ffffff66; +} +.dark .hextra-card:hover svg { + color: currentColor; +} +.hextra-card-tag { + position: absolute; + top: 5px; + right: 5px; + z-index: 10; +} +.steps h3 { + counter-increment: step; +} +.steps h3:before { + position: absolute; + height: 33px; + width: 33px; + border-width: 4px; + --tw-border-opacity: 1; + border-color: rgb(255 255 255 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} +.steps h3:is(html[class~="dark"] *):before { + --tw-border-opacity: 1; + border-color: rgb(17 17 17 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(38 38 38 / var(--tw-bg-opacity)); +} +.steps h3:before { + border-radius: 9999px; + text-align: center; + text-indent: -1px; + font-size: 1rem; + font-weight: 400; + --tw-text-opacity: 1; + color: rgb(163 163 163 / var(--tw-text-opacity)); + margin-top: 3px; +} +.steps h3:where([dir="ltr"], [dir="ltr"] *):before { + margin-left: -41px; +} +.steps h3:where([dir="rtl"], [dir="rtl"] *):before { + margin-right: -44px; +} +.steps h3:before { + content: counter(step); + } +:lang(fa) .steps h3:before { + content: counter(step, persian); + } +.search-wrapper li { + margin-left: 0.625rem; + margin-right: 0.625rem; + overflow-wrap: break-word; + border-radius: 0.375rem; + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity)); +} +@media (prefers-contrast: more) { + + .search-wrapper li { + border-width: 1px; + border-color: transparent; + } +} +.search-wrapper li:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} +.search-wrapper li a { + display: block; + scroll-margin: 3rem; + padding-left: 0.625rem; + padding-right: 0.625rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.search-wrapper li .title { + font-size: 1rem; + font-weight: 600; + line-height: 1.25rem; +} +.search-wrapper li .active { + border-radius: 0.375rem; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / 0.1); +} +@media (prefers-contrast: more) { + + .search-wrapper li .active { + --tw-border-opacity: 1; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); + } +} +.search-wrapper .no-result { + display: block; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + padding: 2rem; + text-align: center; + font-size: .875rem; + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +.search-wrapper .prefix { + margin-left: 0.625rem; + margin-right: 0.625rem; + margin-bottom: 0.5rem; + margin-top: 1.5rem; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + border-bottom-width: 1px; + border-color: rgb(0 0 0 / 0.1); + padding-left: 0.625rem; + padding-right: 0.625rem; + padding-bottom: 0.375rem; + font-size: .75rem; + font-weight: 600; + text-transform: uppercase; + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} +.search-wrapper .prefix:first-child { + margin-top: 0px; +} +@media (prefers-contrast: more) { + + .search-wrapper .prefix { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); + } +} +.search-wrapper .prefix:is(html[class~="dark"] *) { + border-color: rgb(255 255 255 / 0.2); + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} +@media (prefers-contrast: more) { + + .search-wrapper .prefix:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(249 250 251 / var(--tw-border-opacity)); + --tw-text-opacity: 1; + color: rgb(249 250 251 / var(--tw-text-opacity)); + } +} +.search-wrapper .excerpt { + margin-top: 0.25rem; + overflow: hidden; + text-overflow: ellipsis; + font-size: .875rem; + line-height: 1.35rem; + --tw-text-opacity: 1; + color: rgb(75 85 99 / var(--tw-text-opacity)); +} +.search-wrapper .excerpt:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +@media (prefers-contrast: more) { + + .search-wrapper .excerpt:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(249 250 251 / var(--tw-text-opacity)); + } +} +.search-wrapper .excerpt { + display: -webkit-box; + line-clamp: 1; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + } +.search-wrapper .match { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); +} +@media (max-width: 767px) { + .sidebar-container { + position: fixed; + top: 0px; + bottom: 0px; + z-index: 15; + width: 100%; + overscroll-behavior: contain; + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + padding-top: calc(var(--navbar-height)); + } + .sidebar-container:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(17 17 17 / var(--tw-bg-opacity)); + } + .sidebar-container { + transition: transform 0.8s cubic-bezier(0.52, 0.16, 0.04, 1); + will-change: transform, opacity; + contain: layout style; + backface-visibility: hidden; + } +} +.sidebar-container li > div { + height: 0px; +} +.sidebar-container li.open > div { + height: auto; + padding-top: 0.25rem; +} +.sidebar-container li.open > a > span > svg > path { + --tw-rotate: 90deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +nav .search-wrapper { + display: none; +} +@media (min-width: 768px) { + + nav .search-wrapper { + display: inline-block; + } +} +@supports ( + ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) +) { + .nav-container-blur { + background-color: rgb(255 255 255 / .85); + --tw-backdrop-blur: blur(12px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + } + .nav-container-blur:is(html[class~="dark"] *) { + background-color: rgb(17 17 17 / 0.8) !important; + } +} +.hamburger-menu svg g { + transform-origin: center; + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1); +} +.hamburger-menu svg path { + opacity: 1; + transition: + transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s, + opacity 0.2s ease 0.2s; + } +.hamburger-menu svg.open path { + transition: + transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), + opacity 0s ease 0.2s; + } +.hamburger-menu svg.open g { + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s; + } +.hamburger-menu svg.open > path { + opacity: 0; +} +.hamburger-menu svg.open > g:nth-of-type(1) { + --tw-rotate: 45deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.hamburger-menu svg.open > g:nth-of-type(1) path { + transform: translate3d(0, 4px, 0); + } +.hamburger-menu svg.open > g:nth-of-type(2) { + --tw-rotate: -45deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.hamburger-menu svg.open > g:nth-of-type(2) path { + transform: translate3d(0, -4px, 0); + } +.hextra-scrollbar, .hextra-scrollbar * { + scrollbar-width: thin; /* Firefox */ + scrollbar-color: oklch(55.55% 0 0 / 40%) transparent; /* Firefox */ + + scrollbar-gutter: stable; +} +.hextra-scrollbar::-webkit-scrollbar, .hextra-scrollbar *::-webkit-scrollbar { + height: 0.75rem; + width: 0.75rem; +} +.hextra-scrollbar::-webkit-scrollbar-track, .hextra-scrollbar *::-webkit-scrollbar-track { + background-color: transparent; +} +.hextra-scrollbar::-webkit-scrollbar-thumb, .hextra-scrollbar *::-webkit-scrollbar-thumb { + border-radius: 10px; +} +.hextra-scrollbar:hover::-webkit-scrollbar-thumb, .hextra-scrollbar *:hover::-webkit-scrollbar-thumb { + border: 3px solid transparent; + background-color: var(--tw-shadow-color); + background-clip: content-box; + --tw-shadow-color: rgb(115 115 115 / 0.2); + --tw-shadow: var(--tw-shadow-colored); + } +.hextra-scrollbar:hover::-webkit-scrollbar-thumb:hover, .hextra-scrollbar *:hover::-webkit-scrollbar-thumb:hover { + --tw-shadow-color: rgb(115 115 115 / 0.4); + --tw-shadow: var(--tw-shadow-colored); +} +@supports ( + ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) +) { + .hextra-code-copy-btn { + --tw-bg-opacity: .85; + --tw-backdrop-blur: blur(12px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + } + .hextra-code-copy-btn:is(html[class~="dark"] *) { + --tw-bg-opacity: 0.8; + } +} +@media (min-width: 1024px) { +.hextra-feature-grid { + grid-template-columns: repeat(var(--hextra-feature-grid-cols), minmax(0, 1fr)) +} + } +.hextra-jupyter-code-cell { + scrollbar-gutter: auto; + margin-top: 1.5rem; +} +.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container { + overflow: hidden; + font-size: .75rem; +} +.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs { + max-height: 50vh; + overflow: auto; +} +.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs pre { + max-width: 100%; + overflow: auto; + font-size: .75rem; +} +.hextra-badge { + display: inline-flex; + align-items: center; +} +html { + font-size: 1rem; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-feature-settings: "rlig" 1, "calt" 1, "ss01" 1; + -webkit-tap-highlight-color: transparent; +} +body { + width: 100%; + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} +body:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(17 17 17 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(243 244 246 / var(--tw-text-opacity)); +} +:root { + --primary-hue: 212deg; + --primary-saturation: 100%; + --primary-lightness: 50%; + --navbar-height: 4rem; + --menu-height: 3.75rem; +} +.dark { + --primary-hue: 204deg; + --primary-saturation: 100%; + --primary-lightness: 50%; +} +.placeholder\:hx-text-gray-500::-moz-placeholder { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} +.placeholder\:hx-text-gray-500::placeholder { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} +.before\:hx-pointer-events-none::before { + content: var(--tw-content); + pointer-events: none; +} +.before\:hx-absolute::before { + content: var(--tw-content); + position: absolute; +} +.before\:hx-inset-0::before { + content: var(--tw-content); + inset: 0px; +} +.before\:hx-inset-y-1::before { + content: var(--tw-content); + top: 0.25rem; + bottom: 0.25rem; +} +.before\:hx-mr-1::before { + content: var(--tw-content); + margin-right: 0.25rem; +} +.before\:hx-inline-block::before { + content: var(--tw-content); + display: inline-block; +} +.before\:hx-w-px::before { + content: var(--tw-content); + width: 1px; +} +.before\:hx-bg-gray-200::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} +.before\:hx-opacity-25::before { + content: var(--tw-content); + opacity: 0.25; +} +.before\:hx-transition-transform::before { + content: var(--tw-content); + transition-property: transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.before\:hx-content-\[\'\#\'\]::before { + --tw-content: '#'; + content: var(--tw-content); +} +.before\:hx-content-\[\'\'\]::before { + --tw-content: ''; + content: var(--tw-content); +} +.before\:hx-content-\[\\\"\\\"\]::before { + --tw-content: \"\"; + content: var(--tw-content); +} +.first\:hx-mt-0:first-child { + margin-top: 0px; +} +.last-of-type\:hx-mb-0:last-of-type { + margin-bottom: 0px; +} +.hover\:hx-border-gray-200:hover { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} +.hover\:hx-border-gray-300:hover { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} +.hover\:hx-border-gray-400:hover { + --tw-border-opacity: 1; + border-color: rgb(156 163 175 / var(--tw-border-opacity)); +} +.hover\:hx-border-gray-900:hover { + --tw-border-opacity: 1; + border-color: rgb(17 24 39 / var(--tw-border-opacity)); +} +.hover\:hx-bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} +.hover\:hx-bg-gray-800\/5:hover { + background-color: rgb(31 41 55 / 0.05); +} +.hover\:hx-bg-primary-50:hover { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 47) / var(--tw-bg-opacity)); +} +.hover\:hx-bg-primary-700:hover { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / var(--tw-bg-opacity)); +} +.hover\:hx-bg-slate-50:hover { + --tw-bg-opacity: 1; + background-color: rgb(248 250 252 / var(--tw-bg-opacity)); +} +.hover\:hx-text-black:hover { + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} +.hover\:hx-text-gray-800:hover { + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity)); +} +.hover\:hx-text-gray-900:hover { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} +.hover\:hx-text-primary-600:hover { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); +} +.hover\:hx-opacity-60:hover { + opacity: 0.6; +} +.hover\:hx-opacity-75:hover { + opacity: 0.75; +} +.hover\:hx-shadow-lg:hover { + --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hover\:hx-shadow-md:hover { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.hover\:hx-shadow-gray-100:hover { + --tw-shadow-color: #f3f4f6; + --tw-shadow: var(--tw-shadow-colored); +} +.focus\:hx-bg-white:focus { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} +.focus\:hx-outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} +.focus\:hx-ring-4:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} +.focus\:hx-ring-primary-300:focus { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / var(--tw-ring-opacity)); +} +.active\:hx-bg-gray-400\/20:active { + background-color: rgb(156 163 175 / 0.2); +} +.active\:hx-opacity-50:active { + opacity: 0.5; +} +.active\:hx-shadow-sm:active { + --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.active\:hx-shadow-gray-200:active { + --tw-shadow-color: #e5e7eb; + --tw-shadow: var(--tw-shadow-colored); +} +.hx-group[open] .group-open\:before\:hx-rotate-90::before { + content: var(--tw-content); + --tw-rotate: 90deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.hx-group:hover .group-hover\:hx-underline { + text-decoration-line: underline; +} +.hx-group\/code:hover .group-hover\/code\:hx-opacity-100 { + opacity: 1; +} +.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-block { + display: block; +} +.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-hidden { + display: none; +} +.data-\[state\=selected\]\:hx-block[data-state="selected"] { + display: block; +} +.data-\[state\=closed\]\:hx-hidden[data-state="closed"] { + display: none; +} +.data-\[state\=open\]\:hx-hidden[data-state="open"] { + display: none; +} +.data-\[state\=selected\]\:hx-border-primary-500[data-state="selected"] { + --tw-border-opacity: 1; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); +} +.data-\[state\=selected\]\:hx-text-primary-600[data-state="selected"] { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); +} +.hx-group[data-theme="dark"] .group-data-\[theme\=dark\]\:hx-hidden { + display: none; +} +.hx-group[data-theme="light"] .group-data-\[theme\=light\]\:hx-hidden { + display: none; +} +@media (prefers-contrast: more) { + + .contrast-more\:hx-border { + border-width: 1px; + } + + .contrast-more\:hx-border-t { + border-top-width: 1px; + } + + .contrast-more\:hx-border-current { + border-color: currentColor; + } + + .contrast-more\:hx-border-gray-800 { + --tw-border-opacity: 1; + border-color: rgb(31 41 55 / var(--tw-border-opacity)); + } + + .contrast-more\:hx-border-gray-900 { + --tw-border-opacity: 1; + border-color: rgb(17 24 39 / var(--tw-border-opacity)); + } + + .contrast-more\:hx-border-neutral-400 { + --tw-border-opacity: 1; + border-color: rgb(163 163 163 / var(--tw-border-opacity)); + } + + .contrast-more\:hx-border-primary-500 { + --tw-border-opacity: 1; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); + } + + .contrast-more\:hx-border-transparent { + border-color: transparent; + } + + .contrast-more\:hx-font-bold { + font-weight: 700; + } + + .contrast-more\:hx-text-current { + color: currentColor; + } + + .contrast-more\:hx-text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); + } + + .contrast-more\:hx-text-gray-800 { + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity)); + } + + .contrast-more\:hx-text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); + } + + .contrast-more\:hx-underline { + text-decoration-line: underline; + } + + .contrast-more\:hx-shadow-\[0_0_0_1px_\#000\] { + --tw-shadow: 0 0 0 1px #000; + --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .contrast-more\:hx-shadow-none { + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .contrast-more\:hover\:hx-border-gray-900:hover { + --tw-border-opacity: 1; + border-color: rgb(17 24 39 / var(--tw-border-opacity)); + } +} +.dark\:hx-block:is(html[class~="dark"] *) { + display: block; +} +.dark\:hx-hidden:is(html[class~="dark"] *) { + display: none; +} +.dark\:hx-border-amber-200\/30:is(html[class~="dark"] *) { + border-color: rgb(253 230 138 / 0.3); +} +.dark\:hx-border-blue-200\/30:is(html[class~="dark"] *) { + border-color: rgb(191 219 254 / 0.3); +} +.dark\:hx-border-gray-100\/20:is(html[class~="dark"] *) { + border-color: rgb(243 244 246 / 0.2); +} +.dark\:hx-border-gray-400:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(156 163 175 / var(--tw-border-opacity)); +} +.dark\:hx-border-green-200\/30:is(html[class~="dark"] *) { + border-color: rgb(187 247 208 / 0.3); +} +.dark\:hx-border-indigo-200\/30:is(html[class~="dark"] *) { + border-color: rgb(199 210 254 / 0.3); +} +.dark\:hx-border-neutral-700:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(64 64 64 / var(--tw-border-opacity)); +} +.dark\:hx-border-neutral-800:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(38 38 38 / var(--tw-border-opacity)); +} +.dark\:hx-border-orange-400\/30:is(html[class~="dark"] *) { + border-color: rgb(251 146 60 / 0.3); +} +.dark\:hx-border-red-200\/30:is(html[class~="dark"] *) { + border-color: rgb(254 202 202 / 0.3); +} +.dark\:hx-border-white\/10:is(html[class~="dark"] *) { + border-color: rgb(255 255 255 / 0.1); +} +.dark\:hx-border-yellow-200\/30:is(html[class~="dark"] *) { + border-color: rgb(254 240 138 / 0.3); +} +.dark\:hx-bg-amber-900\/30:is(html[class~="dark"] *) { + background-color: rgb(120 53 15 / 0.3); +} +.dark\:hx-bg-black\/60:is(html[class~="dark"] *) { + background-color: rgb(0 0 0 / 0.6); +} +.dark\:hx-bg-blue-900\/30:is(html[class~="dark"] *) { + background-color: rgb(30 58 138 / 0.3); +} +.dark\:hx-bg-dark:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(17 17 17 / var(--tw-bg-opacity)); +} +.dark\:hx-bg-dark\/50:is(html[class~="dark"] *) { + background-color: rgb(17 17 17 / 0.5); +} +.dark\:hx-bg-gray-50\/10:is(html[class~="dark"] *) { + background-color: rgb(249 250 251 / 0.1); +} +.dark\:hx-bg-green-900\/30:is(html[class~="dark"] *) { + background-color: rgb(20 83 45 / 0.3); +} +.dark\:hx-bg-indigo-900\/30:is(html[class~="dark"] *) { + background-color: rgb(49 46 129 / 0.3); +} +.dark\:hx-bg-neutral-800:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(38 38 38 / var(--tw-bg-opacity)); +} +.dark\:hx-bg-neutral-900:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(23 23 23 / var(--tw-bg-opacity)); +} +.dark\:hx-bg-orange-400\/20:is(html[class~="dark"] *) { + background-color: rgb(251 146 60 / 0.2); +} +.dark\:hx-bg-primary-300\/10:is(html[class~="dark"] *) { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); +} +.dark\:hx-bg-primary-400\/10:is(html[class~="dark"] *) { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 16) / 0.1); +} +.dark\:hx-bg-primary-600:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-bg-opacity)); +} +.dark\:hx-bg-red-900\/30:is(html[class~="dark"] *) { + background-color: rgb(127 29 29 / 0.3); +} +.dark\:hx-bg-yellow-700\/30:is(html[class~="dark"] *) { + background-color: rgb(161 98 7 / 0.3); +} +.dark\:hx-from-gray-100:is(html[class~="dark"] *) { + --tw-gradient-from: #f3f4f6 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(243 244 246 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} +.dark\:hx-to-gray-400:is(html[class~="dark"] *) { + --tw-gradient-to: #9ca3af var(--tw-gradient-to-position); +} +.dark\:hx-text-amber-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(253 230 138 / var(--tw-text-opacity)); +} +.dark\:hx-text-blue-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(191 219 254 / var(--tw-text-opacity)); +} +.dark\:hx-text-gray-100:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(243 244 246 / var(--tw-text-opacity)); +} +.dark\:hx-text-gray-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} +.dark\:hx-text-gray-300:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} +.dark\:hx-text-gray-400:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +.dark\:hx-text-gray-50:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(249 250 251 / var(--tw-text-opacity)); +} +.dark\:hx-text-green-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(187 247 208 / var(--tw-text-opacity)); +} +.dark\:hx-text-indigo-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(199 210 254 / var(--tw-text-opacity)); +} +.dark\:hx-text-neutral-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(229 229 229 / var(--tw-text-opacity)); +} +.dark\:hx-text-neutral-400:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(163 163 163 / var(--tw-text-opacity)); +} +.dark\:hx-text-orange-300:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(253 186 116 / var(--tw-text-opacity)); +} +.dark\:hx-text-primary-600:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); +} +.dark\:hx-text-red-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(254 202 202 / var(--tw-text-opacity)); +} +.dark\:hx-text-slate-100:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(241 245 249 / var(--tw-text-opacity)); +} +.dark\:hx-text-yellow-200:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(254 240 138 / var(--tw-text-opacity)); +} +.dark\:hx-opacity-80:is(html[class~="dark"] *) { + opacity: 0.8; +} +.dark\:hx-shadow-\[0_-12px_16px_\#111\]:is(html[class~="dark"] *) { + --tw-shadow: 0 -12px 16px #111; + --tw-shadow-colored: 0 -12px 16px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.dark\:hx-shadow-\[0_-1px_0_rgba\(255\2c 255\2c 255\2c \.1\)_inset\]:is(html[class~="dark"] *) { + --tw-shadow: 0 -1px 0 rgba(255,255,255,.1) inset; + --tw-shadow-colored: inset 0 -1px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.dark\:hx-shadow-none:is(html[class~="dark"] *) { + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.dark\:hx-ring-white\/20:is(html[class~="dark"] *) { + --tw-ring-color: rgb(255 255 255 / 0.2); +} +.dark\:placeholder\:hx-text-gray-400:is(html[class~="dark"] *)::-moz-placeholder { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +.dark\:placeholder\:hx-text-gray-400:is(html[class~="dark"] *)::placeholder { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} +.dark\:before\:hx-bg-neutral-800:is(html[class~="dark"] *)::before { + content: var(--tw-content); + --tw-bg-opacity: 1; + background-color: rgb(38 38 38 / var(--tw-bg-opacity)); +} +.dark\:before\:hx-invert:is(html[class~="dark"] *)::before { + content: var(--tw-content); + --tw-invert: invert(100%); + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); +} +.dark\:hover\:hx-border-gray-100:hover:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); +} +.dark\:hover\:hx-border-gray-600:hover:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); +} +.dark\:hover\:hx-border-neutral-500:hover:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(115 115 115 / var(--tw-border-opacity)); +} +.dark\:hover\:hx-border-neutral-700:hover:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(64 64 64 / var(--tw-border-opacity)); +} +.dark\:hover\:hx-border-neutral-800:hover:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(38 38 38 / var(--tw-border-opacity)); +} +.dark\:hover\:hx-bg-gray-100\/5:hover:is(html[class~="dark"] *) { + background-color: rgb(243 244 246 / 0.05); +} +.dark\:hover\:hx-bg-neutral-700:hover:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(64 64 64 / var(--tw-bg-opacity)); +} +.dark\:hover\:hx-bg-neutral-800:hover:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(38 38 38 / var(--tw-bg-opacity)); +} +.dark\:hover\:hx-bg-neutral-900:hover:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(23 23 23 / var(--tw-bg-opacity)); +} +.dark\:hover\:hx-bg-primary-100\/5:hover:is(html[class~="dark"] *) { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.05); +} +.dark\:hover\:hx-bg-primary-700:hover:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / var(--tw-bg-opacity)); +} +.hover\:dark\:hx-bg-primary-500\/10:is(html[class~="dark"] *):hover { + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / 0.1); +} +.dark\:hover\:hx-text-gray-100:hover:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(243 244 246 / var(--tw-text-opacity)); +} +.dark\:hover\:hx-text-gray-200:hover:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} +.dark\:hover\:hx-text-gray-300:hover:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} +.dark\:hover\:hx-text-gray-50:hover:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(249 250 251 / var(--tw-text-opacity)); +} +.dark\:hover\:hx-text-neutral-50:hover:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(250 250 250 / var(--tw-text-opacity)); +} +.dark\:hover\:hx-text-white:hover:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} +.hover\:dark\:hx-text-primary-600:is(html[class~="dark"] *):hover { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); +} +.dark\:hover\:hx-shadow-none:hover:is(html[class~="dark"] *) { + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} +.dark\:focus\:hx-bg-dark:focus:is(html[class~="dark"] *) { + --tw-bg-opacity: 1; + background-color: rgb(17 17 17 / var(--tw-bg-opacity)); +} +.dark\:focus\:hx-ring-primary-800:focus:is(html[class~="dark"] *) { + --tw-ring-opacity: 1; + --tw-ring-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / var(--tw-ring-opacity)); +} +.data-\[state\=selected\]\:dark\:hx-border-primary-500:is(html[class~="dark"] *)[data-state="selected"] { + --tw-border-opacity: 1; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); +} +.data-\[state\=selected\]\:dark\:hx-text-primary-600:is(html[class~="dark"] *)[data-state="selected"] { + --tw-text-opacity: 1; + color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); +} +@media (prefers-contrast: more) { + + .contrast-more\:dark\:hx-border-current:is(html[class~="dark"] *) { + border-color: currentColor; + } + + .contrast-more\:dark\:hx-border-gray-50:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(249 250 251 / var(--tw-border-opacity)); + } + + .contrast-more\:dark\:hx-border-neutral-400:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(163 163 163 / var(--tw-border-opacity)); + } + + .contrast-more\:dark\:hx-border-primary-500:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); + } + + .dark\:contrast-more\:hx-border-neutral-400:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(163 163 163 / var(--tw-border-opacity)); + } + + .contrast-more\:dark\:hx-text-current:is(html[class~="dark"] *) { + color: currentColor; + } + + .contrast-more\:dark\:hx-text-gray-100:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(243 244 246 / var(--tw-text-opacity)); + } + + .contrast-more\:dark\:hx-text-gray-300:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); + } + + .contrast-more\:dark\:hx-text-gray-50:is(html[class~="dark"] *) { + --tw-text-opacity: 1; + color: rgb(249 250 251 / var(--tw-text-opacity)); + } + + .contrast-more\:dark\:hx-shadow-\[0_0_0_1px_\#fff\]:is(html[class~="dark"] *) { + --tw-shadow: 0 0 0 1px #fff; + --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .contrast-more\:dark\:hx-shadow-none:is(html[class~="dark"] *) { + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .contrast-more\:dark\:hover\:hx-border-gray-50:hover:is(html[class~="dark"] *) { + --tw-border-opacity: 1; + border-color: rgb(249 250 251 / var(--tw-border-opacity)); + } +} +@media not all and (min-width: 1280px) { + + .max-xl\:hx-hidden { + display: none; + } +} +@media not all and (min-width: 1024px) { + + .max-lg\:hx-min-h-\[340px\] { + min-height: 340px; + } +} +@media not all and (min-width: 768px) { + + .max-md\:hx-hidden { + display: none; + } + + .max-md\:hx-min-h-\[340px\] { + min-height: 340px; + } + + .max-md\:\[transform\:translate3d\(0\2c -100\%\2c 0\)\] { + transform: translate3d(0,-100%,0); + } +} +@media not all and (min-width: 640px) { + + .max-sm\:hx-grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } +} +@media (min-width: 640px) { + + .sm\:hx-block { + display: block; + } + + .sm\:hx-flex { + display: flex; + } + + .sm\:hx-w-\[110\%\] { + width: 110%; + } + + .sm\:hx-items-start { + align-items: flex-start; + } + + .sm\:hx-text-xl { + font-size: 1.25rem; + } + + @media not all and (min-width: 1024px) { + + .sm\:max-lg\:hx-grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } +} +@media (min-width: 768px) { + + .md\:hx-sticky { + position: sticky; + } + + .md\:hx-top-16 { + top: 4rem; + } + + .md\:hx-inline-block { + display: inline-block; + } + + .md\:hx-hidden { + display: none; + } + + .md\:hx-aspect-\[1\.1\/1\] { + aspect-ratio: 1.1/1; + } + + .md\:hx-h-\[calc\(100vh-var\(--navbar-height\)-var\(--menu-height\)\)\] { + height: calc(100vh - var(--navbar-height) - var(--menu-height)); + } + + .md\:hx-max-h-\[min\(calc\(100vh-5rem-env\(safe-area-inset-bottom\)\)\2c 400px\)\] { + max-height: min(calc(100vh - 5rem - env(safe-area-inset-bottom)),400px); + } + + .md\:hx-w-64 { + width: 16rem; + } + + .md\:hx-shrink-0 { + flex-shrink: 0; + } + + .md\:hx-grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .md\:hx-justify-start { + justify-content: flex-start; + } + + .md\:hx-self-start { + align-self: flex-start; + } + + .md\:hx-px-12 { + padding-left: 3rem; + padding-right: 3rem; + } + + .md\:hx-pt-12 { + padding-top: 3rem; + } + + .md\:hx-text-5xl { + font-size: 3rem; + } + + .md\:hx-text-lg { + font-size: 1.125rem; + } + + .md\:hx-text-sm { + font-size: .875rem; + } +} +@media (min-width: 1024px) { + + .lg\:hx-grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} +@media (min-width: 1280px) { + + .xl\:hx-block { + display: block; + } + + .xl\:hx-grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} +.ltr\:hx-right-1\.5:where([dir="ltr"], [dir="ltr"] *) { + right: 0.375rem; +} +.ltr\:hx-right-3:where([dir="ltr"], [dir="ltr"] *) { + right: 0.75rem; +} +.ltr\:hx--mr-4:where([dir="ltr"], [dir="ltr"] *) { + margin-right: -1rem; +} +.ltr\:hx-ml-1:where([dir="ltr"], [dir="ltr"] *) { + margin-left: 0.25rem; +} +.ltr\:hx-ml-3:where([dir="ltr"], [dir="ltr"] *) { + margin-left: 0.75rem; +} +.ltr\:hx-ml-auto:where([dir="ltr"], [dir="ltr"] *) { + margin-left: auto; +} +.ltr\:hx-mr-auto:where([dir="ltr"], [dir="ltr"] *) { + margin-right: auto; +} +.ltr\:hx-rotate-180:where([dir="ltr"], [dir="ltr"] *) { + --tw-rotate: 180deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.ltr\:hx-border-l:where([dir="ltr"], [dir="ltr"] *) { + border-left-width: 1px; +} +.ltr\:hx-pl-12:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 3rem; +} +.ltr\:hx-pl-16:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 4rem; +} +.ltr\:hx-pl-3:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 0.75rem; +} +.ltr\:hx-pl-4:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 1rem; +} +.ltr\:hx-pl-5:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 1.25rem; +} +.ltr\:hx-pl-6:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 1.5rem; +} +.ltr\:hx-pl-8:where([dir="ltr"], [dir="ltr"] *) { + padding-left: 2rem; +} +.ltr\:hx-pr-0:where([dir="ltr"], [dir="ltr"] *) { + padding-right: 0px; +} +.ltr\:hx-pr-2:where([dir="ltr"], [dir="ltr"] *) { + padding-right: 0.5rem; +} +.ltr\:hx-pr-4:where([dir="ltr"], [dir="ltr"] *) { + padding-right: 1rem; +} +.ltr\:hx-pr-9:where([dir="ltr"], [dir="ltr"] *) { + padding-right: 2.25rem; +} +.ltr\:hx-text-right:where([dir="ltr"], [dir="ltr"] *) { + text-align: right; +} +.ltr\:before\:hx-left-0:where([dir="ltr"], [dir="ltr"] *)::before { + content: var(--tw-content); + left: 0px; +} +@media (min-width: 768px) { + + .ltr\:md\:hx-left-auto:where([dir="ltr"], [dir="ltr"] *) { + left: auto; + } +} +.rtl\:hx-left-1\.5:where([dir="rtl"], [dir="rtl"] *) { + left: 0.375rem; +} +.rtl\:hx-left-3:where([dir="rtl"], [dir="rtl"] *) { + left: 0.75rem; +} +.rtl\:hx--ml-4:where([dir="rtl"], [dir="rtl"] *) { + margin-left: -1rem; +} +.rtl\:hx-ml-auto:where([dir="rtl"], [dir="rtl"] *) { + margin-left: auto; +} +.rtl\:hx-mr-1:where([dir="rtl"], [dir="rtl"] *) { + margin-right: 0.25rem; +} +.rtl\:hx-mr-3:where([dir="rtl"], [dir="rtl"] *) { + margin-right: 0.75rem; +} +.rtl\:hx-mr-auto:where([dir="rtl"], [dir="rtl"] *) { + margin-right: auto; +} +.rtl\:-hx-rotate-180:where([dir="rtl"], [dir="rtl"] *) { + --tw-rotate: -180deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +.rtl\:hx-border-r:where([dir="rtl"], [dir="rtl"] *) { + border-right-width: 1px; +} +.rtl\:hx-pl-2:where([dir="rtl"], [dir="rtl"] *) { + padding-left: 0.5rem; +} +.rtl\:hx-pl-4:where([dir="rtl"], [dir="rtl"] *) { + padding-left: 1rem; +} +.rtl\:hx-pl-9:where([dir="rtl"], [dir="rtl"] *) { + padding-left: 2.25rem; +} +.rtl\:hx-pr-12:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 3rem; +} +.rtl\:hx-pr-16:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 4rem; +} +.rtl\:hx-pr-3:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 0.75rem; +} +.rtl\:hx-pr-4:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 1rem; +} +.rtl\:hx-pr-5:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 1.25rem; +} +.rtl\:hx-pr-6:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 1.5rem; +} +.rtl\:hx-pr-8:where([dir="rtl"], [dir="rtl"] *) { + padding-right: 2rem; +} +.rtl\:hx-text-left:where([dir="rtl"], [dir="rtl"] *) { + text-align: left; +} +.rtl\:before\:hx-right-0:where([dir="rtl"], [dir="rtl"] *)::before { + content: var(--tw-content); + right: 0px; +} +.rtl\:before\:hx-rotate-180:where([dir="rtl"], [dir="rtl"] *)::before { + content: var(--tw-content); + --tw-rotate: 180deg; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} +@media (min-width: 768px) { + + .rtl\:md\:hx-right-auto:where([dir="rtl"], [dir="rtl"] *) { + right: auto; + } +} +@media print { + + .print\:hx-hidden { + display: none; + } + + .print\:hx-bg-transparent { + background-color: transparent; + } +} diff --git a/public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css b/public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css new file mode 100644 index 0000000..823130e --- /dev/null +++ b/public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css @@ -0,0 +1 @@ +*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::before,::after{--tw-content:''}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.hx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.hx-pointer-events-none{pointer-events:none}.hx-fixed{position:fixed}.hx-absolute{position:absolute}.hx-relative{position:relative}.hx-sticky{position:sticky}.hx-inset-0{inset:0}.hx-inset-x-0{left:0;right:0}.hx-inset-y-0{top:0;bottom:0}.hx-bottom-0{bottom:0}.hx-left-\[24px\]{left:24px}.hx-left-\[36px\]{left:36px}.hx-right-0{right:0}.hx-top-0{top:0}.hx-top-16{top:4rem}.hx-top-8{top:2rem}.hx-top-\[40\%\]{top:40%}.hx-top-full{top:100%}.hx-z-10{z-index:10}.hx-z-20{z-index:20}.hx-z-\[-1\]{z-index:-1}.hx-order-last{order:9999}.hx-m-\[11px\]{margin:11px}.hx-mx-1{margin-left:.25rem;margin-right:.25rem}.hx-mx-4{margin-left:1rem;margin-right:1rem}.hx-mx-auto{margin-left:auto;margin-right:auto}.hx-my-1\.5{margin-top:.375rem;margin-bottom:.375rem}.hx-my-2{margin-top:.5rem;margin-bottom:.5rem}.-hx-mb-0\.5{margin-bottom:-.125rem}.-hx-ml-2{margin-left:-.5rem}.-hx-mr-2{margin-right:-.5rem}.-hx-mt-20{margin-top:-5rem}.hx-mb-10{margin-bottom:2.5rem}.hx-mb-12{margin-bottom:3rem}.hx-mb-16{margin-bottom:4rem}.hx-mb-2{margin-bottom:.5rem}.hx-mb-4{margin-bottom:1rem}.hx-mb-6{margin-bottom:1.5rem}.hx-mb-8{margin-bottom:2rem}.hx-ml-4{margin-left:1rem}.hx-mr-1{margin-right:.25rem}.hx-mr-2{margin-right:.5rem}.hx-mt-1{margin-top:.25rem}.hx-mt-1\.5{margin-top:.375rem}.hx-mt-12{margin-top:3rem}.hx-mt-16{margin-top:4rem}.hx-mt-2{margin-top:.5rem}.hx-mt-4{margin-top:1rem}.hx-mt-5{margin-top:1.25rem}.hx-mt-6{margin-top:1.5rem}.hx-mt-8{margin-top:2rem}.hx-line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.hx-block{display:block}.hx-inline-block{display:inline-block}.hx-inline{display:inline}.hx-flex{display:flex}.hx-inline-flex{display:inline-flex}.hx-grid{display:grid}.hx-hidden{display:none}.hx-aspect-auto{aspect-ratio:auto}.hx-h-0{height:0}.hx-h-16{height:4rem}.hx-h-2{height:.5rem}.hx-h-3\.5{height:.875rem}.hx-h-4{height:1rem}.hx-h-5{height:1.25rem}.hx-h-7{height:1.75rem}.hx-h-\[18px\]{height:18px}.hx-h-full{height:100%}.hx-max-h-64{max-height:16rem}.hx-max-h-\[calc\(100vh-var\(--navbar-height\)-env\(safe-area-inset-bottom\)\)\]{max-height:calc(100vh - var(--navbar-height) - env(safe-area-inset-bottom))}.hx-max-h-\[min\(calc\(50vh-11rem-env\(safe-area-inset-bottom\)\)\,400px\)\]{max-height:min(calc(50vh - 11rem - env(safe-area-inset-bottom)),400px)}.hx-min-h-\[100px\]{min-height:100px}.hx-min-h-\[calc\(100vh-var\(--navbar-height\)\)\]{min-height:calc(100vh - var(--navbar-height))}.hx-w-2{width:.5rem}.hx-w-3\.5{width:.875rem}.hx-w-4{width:1rem}.hx-w-64{width:16rem}.hx-w-\[110\%\]{width:110%}.hx-w-\[180\%\]{width:180%}.hx-w-full{width:100%}.hx-w-max{width:-moz-max-content;width:max-content}.hx-w-screen{width:100vw}.hx-min-w-0{min-width:0}.hx-min-w-\[18px\]{min-width:18px}.hx-min-w-\[24px\]{min-width:24px}.hx-min-w-full{min-width:100%}.hx-max-w-6xl{max-width:72rem}.hx-max-w-\[50\%\]{max-width:50%}.hx-max-w-\[90rem\]{max-width:90rem}.hx-max-w-\[min\(calc\(100vw-2rem\)\,calc\(100\%\+20rem\)\)\]{max-width:min(calc(100vw - 2rem),calc(100% + 20rem))}.hx-max-w-none{max-width:none}.hx-max-w-screen-xl{max-width:1280px}.hx-shrink-0{flex-shrink:0}.hx-grow{flex-grow:1}.hx-origin-center{transform-origin:center}.hx-cursor-default{cursor:default}.hx-cursor-pointer{cursor:pointer}.hx-select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.hx-scroll-my-6{scroll-margin-top:1.5rem;scroll-margin-bottom:1.5rem}.hx-scroll-py-6{scroll-padding-top:1.5rem;scroll-padding-bottom:1.5rem}.hx-list-none{list-style-type:none}.hx-appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.hx-grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.hx-flex-col{flex-direction:column}.hx-flex-wrap{flex-wrap:wrap}.hx-items-start{align-items:flex-start}.hx-items-center{align-items:center}.hx-justify-start{justify-content:flex-start}.hx-justify-end{justify-content:flex-end}.hx-justify-center{justify-content:center}.hx-justify-between{justify-content:space-between}.hx-justify-items-start{justify-items:start}.hx-gap-1{gap:.25rem}.hx-gap-2{gap:.5rem}.hx-gap-4{gap:1rem}.hx-gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.hx-gap-y-2{row-gap:.5rem}.hx-overflow-auto{overflow:auto}.hx-overflow-hidden{overflow:hidden}.hx-overflow-x-auto{overflow-x:auto}.hx-overflow-y-auto{overflow-y:auto}.hx-overflow-x-hidden{overflow-x:hidden}.hx-overflow-y-hidden{overflow-y:hidden}.hx-overscroll-contain{overscroll-behavior:contain}.hx-overscroll-x-contain{overscroll-behavior-x:contain}.hx-text-ellipsis{text-overflow:ellipsis}.hx-whitespace-nowrap{white-space:nowrap}.hx-break-words{overflow-wrap:break-word}.hx-rounded{border-radius:.25rem}.hx-rounded-3xl{border-radius:1.5rem}.hx-rounded-full{border-radius:9999px}.hx-rounded-lg{border-radius:.5rem}.hx-rounded-md{border-radius:.375rem}.hx-rounded-sm{border-radius:.125rem}.hx-rounded-xl{border-radius:.75rem}.hx-rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.hx-border{border-width:1px}.hx-border-b{border-bottom-width:1px}.hx-border-b-2{border-bottom-width:2px}.hx-border-t{border-top-width:1px}.hx-border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity))}.hx-border-black\/5{border-color:rgb(0 0 0/5%)}.hx-border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity))}.hx-border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.hx-border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}.hx-border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity))}.hx-border-indigo-200{--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}.hx-border-orange-100{--tw-border-opacity:1;border-color:rgb(255 237 213/var(--tw-border-opacity))}.hx-border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity))}.hx-border-transparent{border-color:transparent}.hx-border-yellow-100{--tw-border-opacity:1;border-color:rgb(254 249 195/var(--tw-border-opacity))}.hx-bg-amber-100{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity))}.hx-bg-black\/80{background-color:rgb(0 0 0/.8)}.hx-bg-black\/\[\.05\]{background-color:rgb(0 0 0/5%)}.hx-bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity))}.hx-bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hx-bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity))}.hx-bg-indigo-100{--tw-bg-opacity:1;background-color:rgb(224 231 255/var(--tw-bg-opacity))}.hx-bg-neutral-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity))}.hx-bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity))}.hx-bg-primary-100{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/var(--tw-bg-opacity))}.hx-bg-primary-400{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 16)/var(--tw-bg-opacity))}.hx-bg-primary-600{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-bg-opacity))}.hx-bg-primary-700\/5{background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05)}.hx-bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.hx-bg-transparent{background-color:transparent}.hx-bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hx-bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity))}.hx-bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.hx-from-gray-900{--tw-gradient-from:#111827 var(--tw-gradient-from-position);--tw-gradient-to:rgb(17 24 39 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.hx-to-gray-600{--tw-gradient-to:#4b5563 var(--tw-gradient-to-position)}.hx-bg-clip-text{-webkit-background-clip:text;background-clip:text}.hx-p-0\.5{padding:.125rem}.hx-p-1{padding:.25rem}.hx-p-1\.5{padding:.375rem}.hx-p-2{padding:.5rem}.hx-p-4{padding:1rem}.hx-p-6{padding:1.5rem}.hx-px-1\.5{padding-left:.375rem;padding-right:.375rem}.hx-px-2{padding-left:.5rem;padding-right:.5rem}.hx-px-2\.5{padding-left:.625rem;padding-right:.625rem}.hx-px-3{padding-left:.75rem;padding-right:.75rem}.hx-px-4{padding-left:1rem;padding-right:1rem}.hx-px-6{padding-left:1.5rem;padding-right:1.5rem}.hx-py-1{padding-top:.25rem;padding-bottom:.25rem}.hx-py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.hx-py-12{padding-top:3rem;padding-bottom:3rem}.hx-py-2{padding-top:.5rem;padding-bottom:.5rem}.hx-py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.hx-py-3{padding-top:.75rem;padding-bottom:.75rem}.hx-py-4{padding-top:1rem;padding-bottom:1rem}.hx-pb-8{padding-bottom:2rem}.hx-pb-\[env\(safe-area-inset-bottom\)\]{padding-bottom:env(safe-area-inset-bottom)}.hx-pb-px{padding-bottom:1px}.hx-pl-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\]{padding-left:max(env(safe-area-inset-left),1.5rem)}.hx-pr-2{padding-right:.5rem}.hx-pr-4{padding-right:1rem}.hx-pr-\[calc\(env\(safe-area-inset-right\)-1\.5rem\)\]{padding-right:calc(env(safe-area-inset-right) - 1.5rem)}.hx-pr-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\]{padding-right:max(env(safe-area-inset-left),1.5rem)}.hx-pr-\[max\(env\(safe-area-inset-right\)\,1\.5rem\)\]{padding-right:max(env(safe-area-inset-right),1.5rem)}.hx-pt-4{padding-top:1rem}.hx-pt-6{padding-top:1.5rem}.hx-pt-8{padding-top:2rem}.hx-text-left{text-align:left}.hx-text-center{text-align:center}.hx-align-middle{vertical-align:middle}.hx-align-text-bottom{vertical-align:text-bottom}.hx-align-\[-2\.5px\]{vertical-align:-2.5px}.hx-font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace}.hx-text-2xl{font-size:1.5rem}.hx-text-4xl{font-size:2.25rem}.hx-text-\[\.65rem\]{font-size:.65rem}.hx-text-\[10px\]{font-size:10px}.hx-text-base{font-size:1rem}.hx-text-lg{font-size:1.125rem}.hx-text-sm{font-size:.875rem}.hx-text-xl{font-size:1.25rem}.hx-text-xs{font-size:.75rem}.hx-font-bold{font-weight:700}.hx-font-extrabold{font-weight:800}.hx-font-medium{font-weight:500}.hx-font-normal{font-weight:400}.hx-font-semibold{font-weight:600}.hx-capitalize{text-transform:capitalize}.hx-leading-5{line-height:1.25rem}.hx-leading-6{line-height:1.5rem}.hx-leading-7{line-height:1.75rem}.hx-leading-none{line-height:1}.hx-leading-tight{line-height:1.25}.hx-tracking-tight{letter-spacing:-.015em}.hx-text-\[color\:hsl\(var\(--primary-hue\)\,100\%\,50\%\)\]{--tw-text-opacity:1;color:hsl(var(--primary-hue) 100% 50%/var(--tw-text-opacity))}.hx-text-amber-900{--tw-text-opacity:1;color:rgb(120 53 15/var(--tw-text-opacity))}.hx-text-blue-900{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity))}.hx-text-current{color:currentColor}.hx-text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.hx-text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.hx-text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hx-text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hx-text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hx-text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hx-text-green-900{--tw-text-opacity:1;color:rgb(20 83 45/var(--tw-text-opacity))}.hx-text-indigo-900{--tw-text-opacity:1;color:rgb(49 46 129/var(--tw-text-opacity))}.hx-text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity))}.hx-text-primary-800{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 32)/var(--tw-text-opacity))}.hx-text-red-900{--tw-text-opacity:1;color:rgb(127 29 29/var(--tw-text-opacity))}.hx-text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.hx-text-transparent{color:transparent}.hx-text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hx-text-yellow-900{--tw-text-opacity:1;color:rgb(113 63 18/var(--tw-text-opacity))}.hx-underline{text-decoration-line:underline}.hx-no-underline{text-decoration-line:none}.hx-decoration-from-font{text-decoration-thickness:from-font}.hx-underline-offset-2{text-underline-offset:2px}.hx-opacity-0{opacity:0}.hx-opacity-50{opacity:.5}.hx-opacity-80{opacity:.8}.hx-shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-\[0_-12px_16px_\#fff\]{--tw-shadow:0 -12px 16px #fff;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-\[0_-12px_16px_white\]{--tw-shadow:0 -12px 16px white;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-\[0_2px_4px_rgba\(0\,0\,0\,\.02\)\,0_1px_0_rgba\(0\,0\,0\,\.06\)\]{--tw-shadow:0 2px 4px rgba(0,0,0,.02),0 1px 0 rgba(0,0,0,.06);--tw-shadow-colored:0 2px 4px var(--tw-shadow-color), 0 1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-sm{--tw-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-xl{--tw-shadow:0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-gray-100{--tw-shadow-color:#f3f4f6;--tw-shadow:var(--tw-shadow-colored)}.hx-ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hx-ring-black\/5{--tw-ring-color:rgb(0 0 0 / 0.05)}.hx-transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-duration-200{transition-duration:200ms}.hx-duration-75{transition-duration:75ms}.hx-ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.\[-webkit-tap-highlight-color\:transparent\]{-webkit-tap-highlight-color:transparent}.\[-webkit-touch-callout\:none\]{-webkit-touch-callout:none}.\[counter-reset\:step\]{counter-reset:step}.\[hyphens\:auto\]{-webkit-hyphens:auto;hyphens:auto}.\[transition\:background-color_1\.5s_ease\]{transition:background-color 1.5s ease}.\[word-break\:break-word\]{word-break:break-word}.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5rem;font-size:2.25rem;font-weight:700;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2.5rem;border-bottom-width:1px;border-color:rgb(229 229 229/.7);padding-bottom:.25rem;font-size:1.875rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}@media(prefers-contrast:more){.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}}.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.1);--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}@media(prefers-contrast:more){.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}}.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1.5rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1.25rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1.125rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;line-height:1.75rem}.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity));text-decoration-line:underline;text-decoration-thickness:from-font;text-underline-position:from-font}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));font-style:italic;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=ltr],[dir=ltr] *){border-left-width:2px;padding-left:1.5rem}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=rtl],[dir=rtl] *){border-right-width:2px;padding-right:1.5rem}.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)){margin-bottom:1rem;overflow-x:auto;border-radius:.75rem;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05);padding-top:1rem;padding-bottom:1rem;font-size:.9em;font-weight:500;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}@media(prefers-contrast:more){.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)){border-width:1px;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 24)/.2);--tw-contrast:contrast(1.5);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}}.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1)}@media(prefers-contrast:more){.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.4)}}.content :where(code):not(:where(.hextra-code-block code,[class~=not-prose],[class~=not-prose] *)){overflow-wrap:break-word;border-radius:.375rem;border-width:1px;border-color:rgb(0 0 0/var(--tw-border-opacity));--tw-border-opacity:0.04;background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:0.03;padding-top:.125rem;padding-bottom:.125rem;padding-left:.25em;padding-right:.25em;font-size:.9em}.content :where(code):not(:where(.hextra-code-block code,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:rgb(255 255 255/.1);background-color:rgb(255 255 255/.1)}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;display:block;overflow-x:auto;padding:0}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr{margin:0;border-top-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding:0}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr:nth-child(even){--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr:is(html[class~=dark] *):nth-child(even){background-color:rgb(75 85 99/.2)}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) th{margin:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem;font-weight:600}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) th:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) td{margin:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) td:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;list-style-type:decimal}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=ltr],[dir=ltr] *){margin-left:1.5rem}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=rtl],[dir=rtl] *){margin-right:1.5rem}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) li{margin-top:.5rem;margin-bottom:.5rem}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;list-style-type:disc}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=ltr],[dir=ltr] *){margin-left:1.5rem}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=rtl],[dir=rtl] *){margin-right:1.5rem}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) li{margin-top:.5rem;margin-bottom:.5rem}.content :where(ul,ol)>li>:where(ul,ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){overflow-wrap:break-word;border-radius:.375rem;border-width:1px;border-color:rgb(0 0 0/var(--tw-border-opacity));--tw-border-opacity:0.04;background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:0.03;padding-top:.125rem;padding-bottom:.125rem;padding-left:.25em;padding-right:.25em;font-size:.9em}.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:rgb(255 255 255/.1);background-color:rgb(255 255 255/.1)}.content :where(pre.mermaid):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)){border-radius:0;background-color:transparent}.content :where(pre.mermaid):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){background-color:transparent}.content :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-left:auto;margin-right:auto;margin-top:1rem;margin-bottom:1rem;border-radius:.375rem}.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption{margin-top:.5rem;display:block;text-align:center;font-size:.875rem;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dt{margin-top:1.5rem;font-weight:600}.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dd{margin-top:.5rem;margin-bottom:.5rem;padding-inline-start:1.5rem}.content .footnotes{margin-top:3rem;font-size:.875rem}.subheading-anchor{opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.subheading-anchor:where([dir=ltr],[dir=ltr] *){margin-left:.25rem}.subheading-anchor:where([dir=rtl],[dir=rtl] *){margin-right:.25rem}span:target+.subheading-anchor,:hover>.subheading-anchor,.subheading-anchor:focus{opacity:1}span+.subheading-anchor,:hover>.subheading-anchor{text-decoration-line:none !important}.subheading-anchor:after{padding-left:.25rem;padding-right:.25rem;--tw-content:'#';content:var(--tw-content);--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.subheading-anchor:is(html[class~=dark] *):after{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}span:target+.subheading-anchor:after{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}span:target+.subheading-anchor:is(html[class~=dark] *):after{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity))}article details>summary::-webkit-details-marker{display:none}article details>summary::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='hx-h-5 hx-w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E");height:1.2em;width:1.2em;vertical-align:-4px;padding:0 .6em}:lang(fa) ol{list-style-type:persian}.highlight{}.highlight .chroma .err{color:#a61717;background-color:#e3d2d2}.highlight .chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.highlight .chroma .line{display:flex}.highlight .chroma .k{color:#000;font-weight:700}.highlight .chroma .kc{color:#000;font-weight:700}.highlight .chroma .kd{color:#000;font-weight:700}.highlight .chroma .kn{color:#000;font-weight:700}.highlight .chroma .kp{color:#000;font-weight:700}.highlight .chroma .kr{color:#000;font-weight:700}.highlight .chroma .kt{color:#458;font-weight:700}.highlight .chroma .na{color:teal}.highlight .chroma .nb{color:#0086b3}.highlight .chroma .bp{color:#999}.highlight .chroma .nc{color:#458;font-weight:700}.highlight .chroma .no{color:teal}.highlight .chroma .nd{color:#3c5d5d;font-weight:700}.highlight .chroma .ni{color:purple}.highlight .chroma .ne{color:#900;font-weight:700}.highlight .chroma .nf{color:#900;font-weight:700}.highlight .chroma .nl{color:#900;font-weight:700}.highlight .chroma .nn{color:#555}.highlight .chroma .nt{color:navy}.highlight .chroma .nv{color:teal}.highlight .chroma .vc{color:teal}.highlight .chroma .vg{color:teal}.highlight .chroma .vi{color:teal}.highlight .chroma .s{color:#d14}.highlight .chroma .sa{color:#d14}.highlight .chroma .sb{color:#d14}.highlight .chroma .sc{color:#d14}.highlight .chroma .dl{color:#d14}.highlight .chroma .sd{color:#d14}.highlight .chroma .s2{color:#d14}.highlight .chroma .se{color:#d14}.highlight .chroma .sh{color:#d14}.highlight .chroma .si{color:#d14}.highlight .chroma .sx{color:#d14}.highlight .chroma .sr{color:#009926}.highlight .chroma .s1{color:#d14}.highlight .chroma .ss{color:#990073}.highlight .chroma .m{color:#099}.highlight .chroma .mb{color:#099}.highlight .chroma .mf{color:#099}.highlight .chroma .mh{color:#099}.highlight .chroma .mi{color:#099}.highlight .chroma .il{color:#099}.highlight .chroma .mo{color:#099}.highlight .chroma .o{color:#000;font-weight:700}.highlight .chroma .ow{color:#000;font-weight:700}.highlight .chroma .c{color:#998;font-style:italic}.highlight .chroma .ch{color:#998;font-style:italic}.highlight .chroma .cm{color:#998;font-style:italic}.highlight .chroma .c1{color:#998;font-style:italic}.highlight .chroma .cs{color:#999;font-weight:700;font-style:italic}.highlight .chroma .cp{color:#999;font-weight:700;font-style:italic}.highlight .chroma .cpf{color:#999;font-weight:700;font-style:italic}.highlight .chroma .gd{color:#000;background-color:#fdd}.highlight .chroma .ge{color:#000;font-style:italic}.highlight .chroma .gr{color:#a00}.highlight .chroma .gh{color:#999}.highlight .chroma .gi{color:#000;background-color:#dfd}.highlight .chroma .go{color:#888}.highlight .chroma .gp{color:#555}.highlight .chroma .gs{font-weight:700}.highlight .chroma .gu{color:#aaa}.highlight .chroma .gt{color:#a00}.highlight .chroma .gl{text-decoration:underline}.highlight .chroma .w{color:#bbb}.dark .highlight{}.dark .highlight .chroma .x{}.dark .highlight .chroma .err{color:#f85149}.dark .highlight .chroma .cl{}.dark .highlight .chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.dark .highlight .chroma .line{display:flex}.dark .highlight .chroma .k{color:#ff7b72}.dark .highlight .chroma .kc{color:#79c0ff}.dark .highlight .chroma .kd{color:#ff7b72}.dark .highlight .chroma .kn{color:#ff7b72}.dark .highlight .chroma .kp{color:#79c0ff}.dark .highlight .chroma .kr{color:#ff7b72}.dark .highlight .chroma .kt{color:#ff7b72}.dark .highlight .chroma .n{}.dark .highlight .chroma .na{}.dark .highlight .chroma .nb{}.dark .highlight .chroma .bp{}.dark .highlight .chroma .nc{color:#f0883e;font-weight:700}.dark .highlight .chroma .no{color:#79c0ff;font-weight:700}.dark .highlight .chroma .nd{color:#d2a8ff;font-weight:700}.dark .highlight .chroma .ni{color:#ffa657}.dark .highlight .chroma .ne{color:#f0883e;font-weight:700}.dark .highlight .chroma .nf{color:#d2a8ff;font-weight:700}.dark .highlight .chroma .fm{}.dark .highlight .chroma .nl{color:#79c0ff;font-weight:700}.dark .highlight .chroma .nn{color:#ff7b72}.dark .highlight .chroma .nx{}.dark .highlight .chroma .py{color:#79c0ff}.dark .highlight .chroma .nt{color:#7ee787}.dark .highlight .chroma .nv{color:#79c0ff}.dark .highlight .chroma .vc{}.dark .highlight .chroma .vg{}.dark .highlight .chroma .vi{}.dark .highlight .chroma .vm{}.dark .highlight .chroma .l{color:#a5d6ff}.dark .highlight .chroma .ld{color:#79c0ff}.dark .highlight .chroma .s{color:#a5d6ff}.dark .highlight .chroma .sa{color:#79c0ff}.dark .highlight .chroma .sb{color:#a5d6ff}.dark .highlight .chroma .sc{color:#a5d6ff}.dark .highlight .chroma .dl{color:#79c0ff}.dark .highlight .chroma .sd{color:#a5d6ff}.dark .highlight .chroma .s2{color:#a5d6ff}.dark .highlight .chroma .se{color:#79c0ff}.dark .highlight .chroma .sh{color:#79c0ff}.dark .highlight .chroma .si{color:#a5d6ff}.dark .highlight .chroma .sx{color:#a5d6ff}.dark .highlight .chroma .sr{color:#79c0ff}.dark .highlight .chroma .s1{color:#a5d6ff}.dark .highlight .chroma .ss{color:#a5d6ff}.dark .highlight .chroma .m{color:#a5d6ff}.dark .highlight .chroma .mb{color:#a5d6ff}.dark .highlight .chroma .mf{color:#a5d6ff}.dark .highlight .chroma .mh{color:#a5d6ff}.dark .highlight .chroma .mi{color:#a5d6ff}.dark .highlight .chroma .il{color:#a5d6ff}.dark .highlight .chroma .mo{color:#a5d6ff}.dark .highlight .chroma .o{color:#ff7b72;font-weight:700}.dark .highlight .chroma .ow{color:#ff7b72;font-weight:700}.dark .highlight .chroma .p{}.dark .highlight .chroma .c{color:#8b949e;font-style:italic}.dark .highlight .chroma .ch{color:#8b949e;font-style:italic}.dark .highlight .chroma .cm{color:#8b949e;font-style:italic}.dark .highlight .chroma .c1{color:#8b949e;font-style:italic}.dark .highlight .chroma .cs{color:#8b949e;font-weight:700;font-style:italic}.dark .highlight .chroma .cp{color:#8b949e;font-weight:700;font-style:italic}.dark .highlight .chroma .cpf{color:#8b949e;font-weight:700;font-style:italic}.dark .highlight .chroma .g{}.dark .highlight .chroma .gd{color:#ffa198;background-color:#490202}.dark .highlight .chroma .ge{color:inherit;font-style:italic}.dark .highlight .chroma .gr{color:#ffa198}.dark .highlight .chroma .gh{color:#79c0ff;font-weight:700}.dark .highlight .chroma .gi{color:#56d364;background-color:#0f5323}.dark .highlight .chroma .go{color:#8b949e}.dark .highlight .chroma .gp{color:#8b949e}.dark .highlight .chroma .gs{font-weight:700}.dark .highlight .chroma .gu{color:#79c0ff}.dark .highlight .chroma .gt{color:#ff7b72}.dark .highlight .chroma .gl{text-decoration:underline}.dark .highlight .chroma .w{color:#6e7681}.hextra-code-block{font-size:.9em;line-height:1.25rem}.hextra-code-block pre{overflow-x:auto;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05);font-size:.9em;font-weight:500;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}@media(prefers-contrast:more){.hextra-code-block pre{border-width:1px;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 24)/.2);--tw-contrast:contrast(1.5);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}}.hextra-code-block pre:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1)}@media(prefers-contrast:more){.hextra-code-block pre:is(html[class~=dark] *){border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.4)}}.hextra-code-block .filename{position:absolute;top:0;z-index:1;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-top-left-radius:.75rem;border-top-right-radius:.75rem;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;padding-right:1rem;font-size:.75rem;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hextra-code-block .filename:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1);--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.hextra-code-block .filename+pre:not(.lntable pre){padding-top:3rem}.hextra-code-block pre:not(.lntable pre){margin-bottom:1rem;border-radius:.75rem;padding-left:1rem;padding-right:1rem;padding-top:1rem;padding-bottom:1rem}.hextra-code-block div:nth-of-type(2) pre{padding-top:3rem;padding-bottom:1rem}.chroma .lntable{margin:0;display:block;width:auto;overflow:auto;border-radius:.75rem}.chroma .lntable pre{padding-top:1rem;padding-bottom:1rem}.chroma .ln,.chroma .lnt:not(.hl>.lnt),.chroma .hl:not(.line){min-width:2.6rem;padding-left:1rem;padding-right:1rem;--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity))}.chroma .ln:is(html[class~=dark] *),.chroma .lnt:not(.hl>.lnt):is(html[class~=dark] *),.chroma .hl:not(.line):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(212 212 212/var(--tw-text-opacity))}.chroma .lntd{padding:0;vertical-align:top}.chroma .lntd:last-of-type{width:100%}.chroma .hl{display:block;width:100%;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 32)/.1)}.hextra-cards{grid-template-columns:repeat(auto-fill,minmax(max(250px,calc((100% - 1rem * 2)/var(--hextra-cards-grid-cols))),1fr))}.hextra-card{position:relative}.hextra-card img{-webkit-user-select:none;-moz-user-select:none;user-select:none}.hextra-card:hover svg{color:currentColor}.hextra-card svg{width:1.5rem;color:#0003;transition:color .3s ease}.hextra-card p{margin-top:.5rem;position:relative}.dark .hextra-card svg{color:#fff6}.dark .hextra-card:hover svg{color:currentColor}.hextra-card-tag{position:absolute;top:5px;right:5px;z-index:10}.steps h3{counter-increment:step}.steps h3:before{position:absolute;height:33px;width:33px;border-width:4px;--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.steps h3:is(html[class~=dark] *):before{--tw-border-opacity:1;border-color:rgb(17 17 17/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.steps h3:before{border-radius:9999px;text-align:center;text-indent:-1px;font-size:1rem;font-weight:400;--tw-text-opacity:1;color:rgb(163 163 163/var(--tw-text-opacity));margin-top:3px}.steps h3:where([dir=ltr],[dir=ltr] *):before{margin-left:-41px}.steps h3:where([dir=rtl],[dir=rtl] *):before{margin-right:-44px}.steps h3:before{content:counter(step)}:lang(fa) .steps h3:before{content:counter(step,persian)}.search-wrapper li{margin-left:.625rem;margin-right:.625rem;overflow-wrap:break-word;border-radius:.375rem;--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}@media(prefers-contrast:more){.search-wrapper li{border-width:1px;border-color:transparent}}.search-wrapper li:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.search-wrapper li a{display:block;scroll-margin:3rem;padding-left:.625rem;padding-right:.625rem;padding-top:.5rem;padding-bottom:.5rem}.search-wrapper li .title{font-size:1rem;font-weight:600;line-height:1.25rem}.search-wrapper li .active{border-radius:.375rem;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/.1)}@media(prefers-contrast:more){.search-wrapper li .active{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}}.search-wrapper .no-result{display:block;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:2rem;text-align:center;font-size:.875rem;--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.search-wrapper .prefix{margin-left:.625rem;margin-right:.625rem;margin-bottom:.5rem;margin-top:1.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;border-bottom-width:1px;border-color:rgb(0 0 0/.1);padding-left:.625rem;padding-right:.625rem;padding-bottom:.375rem;font-size:.75rem;font-weight:600;text-transform:uppercase;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.search-wrapper .prefix:first-child{margin-top:0}@media(prefers-contrast:more){.search-wrapper .prefix{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}}.search-wrapper .prefix:is(html[class~=dark] *){border-color:rgb(255 255 255/.2);--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}@media(prefers-contrast:more){.search-wrapper .prefix:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}}.search-wrapper .excerpt{margin-top:.25rem;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;line-height:1.35rem;--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.search-wrapper .excerpt:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}@media(prefers-contrast:more){.search-wrapper .excerpt:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}}.search-wrapper .excerpt{display:-webkit-box;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical}.search-wrapper .match{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}@media(max-width:767px){.sidebar-container{position:fixed;top:0;bottom:0;z-index:15;width:100%;overscroll-behavior:contain;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding-top:calc(var(--navbar-height))}.sidebar-container:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.sidebar-container{transition:transform .8s cubic-bezier(.52,.16,.04,1);will-change:transform,opacity;contain:layout style;backface-visibility:hidden}}.sidebar-container li>div{height:0}.sidebar-container li.open>div{height:auto;padding-top:.25rem}.sidebar-container li.open>a>span>svg>path{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}nav .search-wrapper{display:none}@media(min-width:768px){nav .search-wrapper{display:inline-block}}@supports(((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px)))){.nav-container-blur{background-color:rgb(255 255 255/.85);--tw-backdrop-blur:blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.nav-container-blur:is(html[class~=dark] *){background-color:rgb(17 17 17/.8) !important}}.hamburger-menu svg g{transform-origin:center;transition:transform .2s cubic-bezier(.25,1,.5,1)}.hamburger-menu svg path{opacity:1;transition:transform .2s cubic-bezier(.25,1,.5,1).2s,opacity .2s ease .2s}.hamburger-menu svg.open path{transition:transform .2s cubic-bezier(.25,1,.5,1),opacity 0s ease .2s}.hamburger-menu svg.open g{transition:transform .2s cubic-bezier(.25,1,.5,1).2s}.hamburger-menu svg.open>path{opacity:0}.hamburger-menu svg.open>g:nth-of-type(1){--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hamburger-menu svg.open>g:nth-of-type(1) path{transform:translate3d(0,4px,0)}.hamburger-menu svg.open>g:nth-of-type(2){--tw-rotate:-45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hamburger-menu svg.open>g:nth-of-type(2) path{transform:translate3d(0,-4px,0)}.hextra-scrollbar,.hextra-scrollbar *{scrollbar-width:thin;scrollbar-color:oklch(55.55% 0 0/40%)transparent;scrollbar-gutter:stable}.hextra-scrollbar::-webkit-scrollbar,.hextra-scrollbar *::-webkit-scrollbar{height:.75rem;width:.75rem}.hextra-scrollbar::-webkit-scrollbar-track,.hextra-scrollbar *::-webkit-scrollbar-track{background-color:transparent}.hextra-scrollbar::-webkit-scrollbar-thumb,.hextra-scrollbar *::-webkit-scrollbar-thumb{border-radius:10px}.hextra-scrollbar:hover::-webkit-scrollbar-thumb,.hextra-scrollbar *:hover::-webkit-scrollbar-thumb{border:3px solid transparent;background-color:var(--tw-shadow-color);background-clip:content-box;--tw-shadow-color:rgb(115 115 115 / 0.2);--tw-shadow:var(--tw-shadow-colored)}.hextra-scrollbar:hover::-webkit-scrollbar-thumb:hover,.hextra-scrollbar *:hover::-webkit-scrollbar-thumb:hover{--tw-shadow-color:rgb(115 115 115 / 0.4);--tw-shadow:var(--tw-shadow-colored)}@supports(((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px)))){.hextra-code-copy-btn{--tw-bg-opacity:.85;--tw-backdrop-blur:blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.hextra-code-copy-btn:is(html[class~=dark] *){--tw-bg-opacity:0.8}}@media(min-width:1024px){.hextra-feature-grid{grid-template-columns:repeat(var(--hextra-feature-grid-cols),minmax(0,1fr))}}.hextra-jupyter-code-cell{scrollbar-gutter:auto;margin-top:1.5rem}.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container{overflow:hidden;font-size:.75rem}.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs{max-height:50vh;overflow:auto}.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs pre{max-width:100%;overflow:auto;font-size:.75rem}.hextra-badge{display:inline-flex;align-items:center}html{font-size:1rem;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:"rlig" 1,"calt" 1,"ss01" 1;-webkit-tap-highlight-color:transparent}body{width:100%;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}body:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:root{--primary-hue:212deg;--primary-saturation:100%;--primary-lightness:50%;--navbar-height:4rem;--menu-height:3.75rem}.dark{--primary-hue:204deg;--primary-saturation:100%;--primary-lightness:50%}.placeholder\:hx-text-gray-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.placeholder\:hx-text-gray-500::placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.before\:hx-pointer-events-none::before{content:var(--tw-content);pointer-events:none}.before\:hx-absolute::before{content:var(--tw-content);position:absolute}.before\:hx-inset-0::before{content:var(--tw-content);inset:0}.before\:hx-inset-y-1::before{content:var(--tw-content);top:.25rem;bottom:.25rem}.before\:hx-mr-1::before{content:var(--tw-content);margin-right:.25rem}.before\:hx-inline-block::before{content:var(--tw-content);display:inline-block}.before\:hx-w-px::before{content:var(--tw-content);width:1px}.before\:hx-bg-gray-200::before{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.before\:hx-opacity-25::before{content:var(--tw-content);opacity:.25}.before\:hx-transition-transform::before{content:var(--tw-content);transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.before\:hx-content-\[\'\#\'\]::before{--tw-content:'#';content:var(--tw-content)}.before\:hx-content-\[\'\'\]::before{--tw-content:'';content:var(--tw-content)}.before\:hx-content-\[\\\"\\\"\]::before{--tw-content:\"\";content:var(--tw-content)}.first\:hx-mt-0:first-child{margin-top:0}.last-of-type\:hx-mb-0:last-of-type{margin-bottom:0}.hover\:hx-border-gray-200:hover{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.hover\:hx-border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:hx-border-gray-400:hover{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.hover\:hx-border-gray-900:hover{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.hover\:hx-bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:hx-bg-gray-800\/5:hover{background-color:rgb(31 41 55/5%)}.hover\:hx-bg-primary-50:hover{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 47)/var(--tw-bg-opacity))}.hover\:hx-bg-primary-700:hover{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/var(--tw-bg-opacity))}.hover\:hx-bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity))}.hover\:hx-text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.hover\:hx-text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:hx-text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:hx-text-primary-600:hover{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.hover\:hx-opacity-60:hover{opacity:.6}.hover\:hx-opacity-75:hover{opacity:.75}.hover\:hx-shadow-lg:hover{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:hx-shadow-md:hover{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:hx-shadow-gray-100:hover{--tw-shadow-color:#f3f4f6;--tw-shadow:var(--tw-shadow-colored)}.focus\:hx-bg-white:focus{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.focus\:hx-outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:hx-ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:hx-ring-primary-300:focus{--tw-ring-opacity:1;--tw-ring-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / var(--tw-ring-opacity))}.active\:hx-bg-gray-400\/20:active{background-color:rgb(156 163 175/.2)}.active\:hx-opacity-50:active{opacity:.5}.active\:hx-shadow-sm:active{--tw-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.active\:hx-shadow-gray-200:active{--tw-shadow-color:#e5e7eb;--tw-shadow:var(--tw-shadow-colored)}.hx-group[open] .group-open\:before\:hx-rotate-90::before{content:var(--tw-content);--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hx-group:hover .group-hover\:hx-underline{text-decoration-line:underline}.hx-group\/code:hover .group-hover\/code\:hx-opacity-100{opacity:1}.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-block{display:block}.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-hidden{display:none}.data-\[state\=selected\]\:hx-block[data-state=selected]{display:block}.data-\[state\=closed\]\:hx-hidden[data-state=closed]{display:none}.data-\[state\=open\]\:hx-hidden[data-state=open]{display:none}.data-\[state\=selected\]\:hx-border-primary-500[data-state=selected]{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.data-\[state\=selected\]\:hx-text-primary-600[data-state=selected]{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.hx-group[data-theme=dark] .group-data-\[theme\=dark\]\:hx-hidden{display:none}.hx-group[data-theme=light] .group-data-\[theme\=light\]\:hx-hidden{display:none}@media(prefers-contrast:more){.contrast-more\:hx-border{border-width:1px}.contrast-more\:hx-border-t{border-top-width:1px}.contrast-more\:hx-border-current{border-color:initial}.contrast-more\:hx-border-gray-800{--tw-border-opacity:1;border-color:rgb(31 41 55/var(--tw-border-opacity))}.contrast-more\:hx-border-gray-900{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.contrast-more\:hx-border-neutral-400{--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.contrast-more\:hx-border-primary-500{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.contrast-more\:hx-border-transparent{border-color:transparent}.contrast-more\:hx-font-bold{font-weight:700}.contrast-more\:hx-text-current{color:currentColor}.contrast-more\:hx-text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.contrast-more\:hx-text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.contrast-more\:hx-text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.contrast-more\:hx-underline{text-decoration-line:underline}.contrast-more\:hx-shadow-\[0_0_0_1px_\#000\]{--tw-shadow:0 0 0 1px #000;--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:hx-shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:hover\:hx-border-gray-900:hover{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}}.dark\:hx-block:is(html[class~=dark] *){display:block}.dark\:hx-hidden:is(html[class~=dark] *){display:none}.dark\:hx-border-amber-200\/30:is(html[class~=dark] *){border-color:rgb(253 230 138/.3)}.dark\:hx-border-blue-200\/30:is(html[class~=dark] *){border-color:rgb(191 219 254/.3)}.dark\:hx-border-gray-100\/20:is(html[class~=dark] *){border-color:rgb(243 244 246/.2)}.dark\:hx-border-gray-400:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.dark\:hx-border-green-200\/30:is(html[class~=dark] *){border-color:rgb(187 247 208/.3)}.dark\:hx-border-indigo-200\/30:is(html[class~=dark] *){border-color:rgb(199 210 254/.3)}.dark\:hx-border-neutral-700:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(64 64 64/var(--tw-border-opacity))}.dark\:hx-border-neutral-800:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark\:hx-border-orange-400\/30:is(html[class~=dark] *){border-color:rgb(251 146 60/.3)}.dark\:hx-border-red-200\/30:is(html[class~=dark] *){border-color:rgb(254 202 202/.3)}.dark\:hx-border-white\/10:is(html[class~=dark] *){border-color:rgb(255 255 255/.1)}.dark\:hx-border-yellow-200\/30:is(html[class~=dark] *){border-color:rgb(254 240 138/.3)}.dark\:hx-bg-amber-900\/30:is(html[class~=dark] *){background-color:rgb(120 53 15/.3)}.dark\:hx-bg-black\/60:is(html[class~=dark] *){background-color:rgb(0 0 0/.6)}.dark\:hx-bg-blue-900\/30:is(html[class~=dark] *){background-color:rgb(30 58 138/.3)}.dark\:hx-bg-dark:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark\:hx-bg-dark\/50:is(html[class~=dark] *){background-color:rgb(17 17 17/.5)}.dark\:hx-bg-gray-50\/10:is(html[class~=dark] *){background-color:rgb(249 250 251/.1)}.dark\:hx-bg-green-900\/30:is(html[class~=dark] *){background-color:rgb(20 83 45/.3)}.dark\:hx-bg-indigo-900\/30:is(html[class~=dark] *){background-color:rgb(49 46 129/.3)}.dark\:hx-bg-neutral-800:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark\:hx-bg-neutral-900:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.dark\:hx-bg-orange-400\/20:is(html[class~=dark] *){background-color:rgb(251 146 60/.2)}.dark\:hx-bg-primary-300\/10:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1)}.dark\:hx-bg-primary-400\/10:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 16)/.1)}.dark\:hx-bg-primary-600:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-bg-opacity))}.dark\:hx-bg-red-900\/30:is(html[class~=dark] *){background-color:rgb(127 29 29/.3)}.dark\:hx-bg-yellow-700\/30:is(html[class~=dark] *){background-color:rgb(161 98 7/.3)}.dark\:hx-from-gray-100:is(html[class~=dark] *){--tw-gradient-from:#f3f4f6 var(--tw-gradient-from-position);--tw-gradient-to:rgb(243 244 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.dark\:hx-to-gray-400:is(html[class~=dark] *){--tw-gradient-to:#9ca3af var(--tw-gradient-to-position)}.dark\:hx-text-amber-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(253 230 138/var(--tw-text-opacity))}.dark\:hx-text-blue-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity))}.dark\:hx-text-gray-100:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark\:hx-text-gray-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark\:hx-text-gray-300:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark\:hx-text-gray-400:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:hx-text-gray-50:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark\:hx-text-green-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity))}.dark\:hx-text-indigo-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(199 210 254/var(--tw-text-opacity))}.dark\:hx-text-neutral-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}.dark\:hx-text-neutral-400:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(163 163 163/var(--tw-text-opacity))}.dark\:hx-text-orange-300:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity))}.dark\:hx-text-primary-600:is(html[class~=dark] *){--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.dark\:hx-text-red-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity))}.dark\:hx-text-slate-100:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.dark\:hx-text-yellow-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity))}.dark\:hx-opacity-80:is(html[class~=dark] *){opacity:.8}.dark\:hx-shadow-\[0_-12px_16px_\#111\]:is(html[class~=dark] *){--tw-shadow:0 -12px 16px #111;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:hx-shadow-\[0_-1px_0_rgba\(255\2c 255\2c 255\2c \.1\)_inset\]:is(html[class~=dark] *){--tw-shadow:0 -1px 0 rgba(255,255,255,.1) inset;--tw-shadow-colored:inset 0 -1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:hx-shadow-none:is(html[class~=dark] *){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:hx-ring-white\/20:is(html[class~=dark] *){--tw-ring-color:rgb(255 255 255 / 0.2)}.dark\:placeholder\:hx-text-gray-400:is(html[class~=dark] *)::-moz-placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:placeholder\:hx-text-gray-400:is(html[class~=dark] *)::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:before\:hx-bg-neutral-800:is(html[class~=dark] *)::before{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark\:before\:hx-invert:is(html[class~=dark] *)::before{content:var(--tw-content);--tw-invert:invert(100%);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.dark\:hover\:hx-border-gray-100:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.dark\:hover\:hx-border-gray-600:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.dark\:hover\:hx-border-neutral-500:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(115 115 115/var(--tw-border-opacity))}.dark\:hover\:hx-border-neutral-700:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(64 64 64/var(--tw-border-opacity))}.dark\:hover\:hx-border-neutral-800:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark\:hover\:hx-bg-gray-100\/5:hover:is(html[class~=dark] *){background-color:rgb(243 244 246/5%)}.dark\:hover\:hx-bg-neutral-700:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(64 64 64/var(--tw-bg-opacity))}.dark\:hover\:hx-bg-neutral-800:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark\:hover\:hx-bg-neutral-900:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.dark\:hover\:hx-bg-primary-100\/5:hover:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.05)}.dark\:hover\:hx-bg-primary-700:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/var(--tw-bg-opacity))}.hover\:dark\:hx-bg-primary-500\/10:is(html[class~=dark] *):hover{background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/.1)}.dark\:hover\:hx-text-gray-100:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark\:hover\:hx-text-gray-200:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark\:hover\:hx-text-gray-300:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark\:hover\:hx-text-gray-50:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark\:hover\:hx-text-neutral-50:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(250 250 250/var(--tw-text-opacity))}.dark\:hover\:hx-text-white:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hover\:dark\:hx-text-primary-600:is(html[class~=dark] *):hover{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.dark\:hover\:hx-shadow-none:hover:is(html[class~=dark] *){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:focus\:hx-bg-dark:focus:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark\:focus\:hx-ring-primary-800:focus:is(html[class~=dark] *){--tw-ring-opacity:1;--tw-ring-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / var(--tw-ring-opacity))}.data-\[state\=selected\]\:dark\:hx-border-primary-500:is(html[class~=dark] *)[data-state=selected]{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.data-\[state\=selected\]\:dark\:hx-text-primary-600:is(html[class~=dark] *)[data-state=selected]{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}@media(prefers-contrast:more){.contrast-more\:dark\:hx-border-current:is(html[class~=dark] *){border-color:initial}.contrast-more\:dark\:hx-border-gray-50:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.contrast-more\:dark\:hx-border-neutral-400:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.contrast-more\:dark\:hx-border-primary-500:is(html[class~=dark] *){--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.dark\:contrast-more\:hx-border-neutral-400:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.contrast-more\:dark\:hx-text-current:is(html[class~=dark] *){color:currentColor}.contrast-more\:dark\:hx-text-gray-100:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.contrast-more\:dark\:hx-text-gray-300:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.contrast-more\:dark\:hx-text-gray-50:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.contrast-more\:dark\:hx-shadow-\[0_0_0_1px_\#fff\]:is(html[class~=dark] *){--tw-shadow:0 0 0 1px #fff;--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:dark\:hx-shadow-none:is(html[class~=dark] *){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:dark\:hover\:hx-border-gray-50:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}}@media not all and (min-width:1280px){.max-xl\:hx-hidden{display:none}}@media not all and (min-width:1024px){.max-lg\:hx-min-h-\[340px\]{min-height:340px}}@media not all and (min-width:768px){.max-md\:hx-hidden{display:none}.max-md\:hx-min-h-\[340px\]{min-height:340px}.max-md\:\[transform\:translate3d\(0\2c -100\%\2c 0\)\]{transform:translate3d(0,-100%,0)}}@media not all and (min-width:640px){.max-sm\:hx-grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}}@media(min-width:640px){.sm\:hx-block{display:block}.sm\:hx-flex{display:flex}.sm\:hx-w-\[110\%\]{width:110%}.sm\:hx-items-start{align-items:flex-start}.sm\:hx-text-xl{font-size:1.25rem}@media not all and (min-width:1024px){.sm\:max-lg\:hx-grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}}@media(min-width:768px){.md\:hx-sticky{position:sticky}.md\:hx-top-16{top:4rem}.md\:hx-inline-block{display:inline-block}.md\:hx-hidden{display:none}.md\:hx-aspect-\[1\.1\/1\]{aspect-ratio:1.1/1}.md\:hx-h-\[calc\(100vh-var\(--navbar-height\)-var\(--menu-height\)\)\]{height:calc(100vh - var(--navbar-height) - var(--menu-height))}.md\:hx-max-h-\[min\(calc\(100vh-5rem-env\(safe-area-inset-bottom\)\)\2c 400px\)\]{max-height:min(calc(100vh - 5rem - env(safe-area-inset-bottom)),400px)}.md\:hx-w-64{width:16rem}.md\:hx-shrink-0{flex-shrink:0}.md\:hx-grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:hx-justify-start{justify-content:flex-start}.md\:hx-self-start{align-self:flex-start}.md\:hx-px-12{padding-left:3rem;padding-right:3rem}.md\:hx-pt-12{padding-top:3rem}.md\:hx-text-5xl{font-size:3rem}.md\:hx-text-lg{font-size:1.125rem}.md\:hx-text-sm{font-size:.875rem}}@media(min-width:1024px){.lg\:hx-grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:1280px){.xl\:hx-block{display:block}.xl\:hx-grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}.ltr\:hx-right-1\.5:where([dir=ltr],[dir=ltr] *){right:.375rem}.ltr\:hx-right-3:where([dir=ltr],[dir=ltr] *){right:.75rem}.ltr\:hx--mr-4:where([dir=ltr],[dir=ltr] *){margin-right:-1rem}.ltr\:hx-ml-1:where([dir=ltr],[dir=ltr] *){margin-left:.25rem}.ltr\:hx-ml-3:where([dir=ltr],[dir=ltr] *){margin-left:.75rem}.ltr\:hx-ml-auto:where([dir=ltr],[dir=ltr] *){margin-left:auto}.ltr\:hx-mr-auto:where([dir=ltr],[dir=ltr] *){margin-right:auto}.ltr\:hx-rotate-180:where([dir=ltr],[dir=ltr] *){--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.ltr\:hx-border-l:where([dir=ltr],[dir=ltr] *){border-left-width:1px}.ltr\:hx-pl-12:where([dir=ltr],[dir=ltr] *){padding-left:3rem}.ltr\:hx-pl-16:where([dir=ltr],[dir=ltr] *){padding-left:4rem}.ltr\:hx-pl-3:where([dir=ltr],[dir=ltr] *){padding-left:.75rem}.ltr\:hx-pl-4:where([dir=ltr],[dir=ltr] *){padding-left:1rem}.ltr\:hx-pl-5:where([dir=ltr],[dir=ltr] *){padding-left:1.25rem}.ltr\:hx-pl-6:where([dir=ltr],[dir=ltr] *){padding-left:1.5rem}.ltr\:hx-pl-8:where([dir=ltr],[dir=ltr] *){padding-left:2rem}.ltr\:hx-pr-0:where([dir=ltr],[dir=ltr] *){padding-right:0}.ltr\:hx-pr-2:where([dir=ltr],[dir=ltr] *){padding-right:.5rem}.ltr\:hx-pr-4:where([dir=ltr],[dir=ltr] *){padding-right:1rem}.ltr\:hx-pr-9:where([dir=ltr],[dir=ltr] *){padding-right:2.25rem}.ltr\:hx-text-right:where([dir=ltr],[dir=ltr] *){text-align:right}.ltr\:before\:hx-left-0:where([dir=ltr],[dir=ltr] *)::before{content:var(--tw-content);left:0}@media(min-width:768px){.ltr\:md\:hx-left-auto:where([dir=ltr],[dir=ltr] *){left:auto}}.rtl\:hx-left-1\.5:where([dir=rtl],[dir=rtl] *){left:.375rem}.rtl\:hx-left-3:where([dir=rtl],[dir=rtl] *){left:.75rem}.rtl\:hx--ml-4:where([dir=rtl],[dir=rtl] *){margin-left:-1rem}.rtl\:hx-ml-auto:where([dir=rtl],[dir=rtl] *){margin-left:auto}.rtl\:hx-mr-1:where([dir=rtl],[dir=rtl] *){margin-right:.25rem}.rtl\:hx-mr-3:where([dir=rtl],[dir=rtl] *){margin-right:.75rem}.rtl\:hx-mr-auto:where([dir=rtl],[dir=rtl] *){margin-right:auto}.rtl\:-hx-rotate-180:where([dir=rtl],[dir=rtl] *){--tw-rotate:-180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.rtl\:hx-border-r:where([dir=rtl],[dir=rtl] *){border-right-width:1px}.rtl\:hx-pl-2:where([dir=rtl],[dir=rtl] *){padding-left:.5rem}.rtl\:hx-pl-4:where([dir=rtl],[dir=rtl] *){padding-left:1rem}.rtl\:hx-pl-9:where([dir=rtl],[dir=rtl] *){padding-left:2.25rem}.rtl\:hx-pr-12:where([dir=rtl],[dir=rtl] *){padding-right:3rem}.rtl\:hx-pr-16:where([dir=rtl],[dir=rtl] *){padding-right:4rem}.rtl\:hx-pr-3:where([dir=rtl],[dir=rtl] *){padding-right:.75rem}.rtl\:hx-pr-4:where([dir=rtl],[dir=rtl] *){padding-right:1rem}.rtl\:hx-pr-5:where([dir=rtl],[dir=rtl] *){padding-right:1.25rem}.rtl\:hx-pr-6:where([dir=rtl],[dir=rtl] *){padding-right:1.5rem}.rtl\:hx-pr-8:where([dir=rtl],[dir=rtl] *){padding-right:2rem}.rtl\:hx-text-left:where([dir=rtl],[dir=rtl] *){text-align:left}.rtl\:before\:hx-right-0:where([dir=rtl],[dir=rtl] *)::before{content:var(--tw-content);right:0}.rtl\:before\:hx-rotate-180:where([dir=rtl],[dir=rtl] *)::before{content:var(--tw-content);--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}@media(min-width:768px){.rtl\:md\:hx-right-auto:where([dir=rtl],[dir=rtl] *){right:auto}}@media print{.print\:hx-hidden{display:none}.print\:hx-bg-transparent{background-color:transparent}} \ No newline at end of file diff --git a/public/css/custom.css b/public/css/custom.css new file mode 100644 index 0000000..e69de29 diff --git a/public/css/custom.min.e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css b/public/css/custom.min.e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css new file mode 100644 index 0000000..e69de29 diff --git a/public/docs/01-introduction/index.html b/public/docs/01-introduction/index.html new file mode 100644 index 0000000..40f1c74 --- /dev/null +++ b/public/docs/01-introduction/index.html @@ -0,0 +1,328 @@ + + + + + + + + + + + + +Introduction – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      +
      Documentation
      +
      + +
      +

      Introduction

      +

      Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.

      +

      go-form is heavily influenced by Symfony Form. It includes:

      +
        +
      • A form builder based on fields declarations and independent of structs
      • +
      • Validation based on constraints
      • +
      • Data mounting to populate a form from a struct instance
      • +
      • Data binding to populate a struct instance from a submitted form
      • +
      • Form renderer with customizable themes
      • +
      +

      Questions or Feedback? +

      + +
      fmt.Sprintf("foo")
      + +
      +
      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/02-installation/index.html b/public/docs/02-installation/index.html new file mode 100644 index 0000000..f75c605 --- /dev/null +++ b/public/docs/02-installation/index.html @@ -0,0 +1,252 @@ + + + + + + + + + + + + +Installation – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/button/index.html b/public/docs/button/index.html new file mode 100644 index 0000000..494d61e --- /dev/null +++ b/public/docs/button/index.html @@ -0,0 +1,467 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/constraints/index.html b/public/docs/constraints/index.html new file mode 100644 index 0000000..c761209 --- /dev/null +++ b/public/docs/constraints/index.html @@ -0,0 +1,552 @@ + + + + + + + + + + + + +Constraints – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      +
      Constraints
      +
      + +
      +

      Constraints

      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/constraints/index.xml b/public/docs/constraints/index.xml new file mode 100644 index 0000000..dcc34a3 --- /dev/null +++ b/public/docs/constraints/index.xml @@ -0,0 +1,18 @@ + + + deblan/go-form – Constraints + http://localhost:1313/docs/constraints/ + Recent content in Constraints on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + diff --git a/public/docs/field/date/date/index.html b/public/docs/field/date/date/index.html new file mode 100644 index 0000000..24ea0fe --- /dev/null +++ b/public/docs/field/date/date/index.html @@ -0,0 +1,464 @@ + + + + + + + + + + + + +Date – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/date/datetime/index.html b/public/docs/field/date/datetime/index.html new file mode 100644 index 0000000..e81c6e3 --- /dev/null +++ b/public/docs/field/date/datetime/index.html @@ -0,0 +1,468 @@ + + + + + + + + + + + + +Datetime – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/date/index.html b/public/docs/field/date/index.html new file mode 100644 index 0000000..26496a4 --- /dev/null +++ b/public/docs/field/date/index.html @@ -0,0 +1,455 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/date/index.xml b/public/docs/field/date/index.xml new file mode 100644 index 0000000..e8ee8b2 --- /dev/null +++ b/public/docs/field/date/index.xml @@ -0,0 +1,57 @@ + + + deblan/go-form – + http://localhost:1313/docs/field/date/ + Recent content on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Date + http://localhost:1313/docs/field/date/date/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/date/date/ + + + + + + + + + Datetime + http://localhost:1313/docs/field/date/datetime/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/date/datetime/ + + + + + + + + + Time + http://localhost:1313/docs/field/date/time/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/date/time/ + + + + + + + + + diff --git a/public/docs/field/date/time/index.html b/public/docs/field/date/time/index.html new file mode 100644 index 0000000..a272036 --- /dev/null +++ b/public/docs/field/date/time/index.html @@ -0,0 +1,464 @@ + + + + + + + + + + + + +Time – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/index.html b/public/docs/field/index.html new file mode 100644 index 0000000..f760ecf --- /dev/null +++ b/public/docs/field/index.html @@ -0,0 +1,452 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/index.xml b/public/docs/field/index.xml new file mode 100644 index 0000000..97425df --- /dev/null +++ b/public/docs/field/index.xml @@ -0,0 +1,49 @@ + + + deblan/go-form – + http://localhost:1313/docs/field/ + Recent content on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Input + http://localhost:1313/docs/field/input/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + + http://localhost:1313/docs/field/date/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/date/ + + + + + + + + + diff --git a/public/docs/field/input/hidden/index.html b/public/docs/field/input/hidden/index.html new file mode 100644 index 0000000..825a09e --- /dev/null +++ b/public/docs/field/input/hidden/index.html @@ -0,0 +1,464 @@ + + + + + + + + + + + + +Hidden – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/input/index.html b/public/docs/field/input/index.html new file mode 100644 index 0000000..68a11a4 --- /dev/null +++ b/public/docs/field/input/index.html @@ -0,0 +1,461 @@ + + + + + + + + + + + + +Input – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/input/index.xml b/public/docs/field/input/index.xml new file mode 100644 index 0000000..a3d7aea --- /dev/null +++ b/public/docs/field/input/index.xml @@ -0,0 +1,121 @@ + + + deblan/go-form – Input + http://localhost:1313/docs/field/input/ + Recent content in Input on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Hidden + http://localhost:1313/docs/field/input/hidden/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/hidden/ + + + + + + + + + Mail + http://localhost:1313/docs/field/input/mail/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/mail/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Number + http://localhost:1313/docs/field/input/number/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/number/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Password + http://localhost:1313/docs/field/input/password/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/password/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Range + http://localhost:1313/docs/field/input/range/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/range/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Text + http://localhost:1313/docs/field/input/text/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/field/input/text/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + diff --git a/public/docs/field/input/mail/index.html b/public/docs/field/input/mail/index.html new file mode 100644 index 0000000..b0aacf8 --- /dev/null +++ b/public/docs/field/input/mail/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + +Mail – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/input/number/index.html b/public/docs/field/input/number/index.html new file mode 100644 index 0000000..e35ddda --- /dev/null +++ b/public/docs/field/input/number/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + +Number – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/input/password/index.html b/public/docs/field/input/password/index.html new file mode 100644 index 0000000..2484c46 --- /dev/null +++ b/public/docs/field/input/password/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + +Password – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/input/range/index.html b/public/docs/field/input/range/index.html new file mode 100644 index 0000000..ba260dd --- /dev/null +++ b/public/docs/field/input/range/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + +Range – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/input/text/index.html b/public/docs/field/input/text/index.html new file mode 100644 index 0000000..6ed4142 --- /dev/null +++ b/public/docs/field/input/text/index.html @@ -0,0 +1,474 @@ + + + + + + + + + + + + +Text – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/field/text/index.html b/public/docs/field/text/index.html new file mode 100644 index 0000000..768359e --- /dev/null +++ b/public/docs/field/text/index.html @@ -0,0 +1,311 @@ + + + + + + + + + + + + +Text – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/button/index.html b/public/docs/fields/button/index.html new file mode 100644 index 0000000..5250cb6 --- /dev/null +++ b/public/docs/fields/button/index.html @@ -0,0 +1,561 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/date/date/index.html b/public/docs/fields/date/date/index.html new file mode 100644 index 0000000..38b5231 --- /dev/null +++ b/public/docs/fields/date/date/index.html @@ -0,0 +1,464 @@ + + + + + + + + + + + + +Date – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/date/datetime/index.html b/public/docs/fields/date/datetime/index.html new file mode 100644 index 0000000..67cdac7 --- /dev/null +++ b/public/docs/fields/date/datetime/index.html @@ -0,0 +1,468 @@ + + + + + + + + + + + + +Datetime – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/date/index.html b/public/docs/fields/date/index.html new file mode 100644 index 0000000..25b15c9 --- /dev/null +++ b/public/docs/fields/date/index.html @@ -0,0 +1,455 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/date/index.xml b/public/docs/fields/date/index.xml new file mode 100644 index 0000000..4895401 --- /dev/null +++ b/public/docs/fields/date/index.xml @@ -0,0 +1,57 @@ + + + deblan/go-form – + http://localhost:1313/docs/fields/date/ + Recent content on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Date + http://localhost:1313/docs/fields/date/date/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/date/date/ + + + + + + + + + Datetime + http://localhost:1313/docs/fields/date/datetime/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/date/datetime/ + + + + + + + + + Time + http://localhost:1313/docs/fields/date/time/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/date/time/ + + + + + + + + + diff --git a/public/docs/fields/date/time/index.html b/public/docs/fields/date/time/index.html new file mode 100644 index 0000000..bd0c000 --- /dev/null +++ b/public/docs/fields/date/time/index.html @@ -0,0 +1,464 @@ + + + + + + + + + + + + +Time – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/index.html b/public/docs/fields/index.html new file mode 100644 index 0000000..60af09b --- /dev/null +++ b/public/docs/fields/index.html @@ -0,0 +1,552 @@ + + + + + + + + + + + + +Input – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/index.xml b/public/docs/fields/index.xml new file mode 100644 index 0000000..e97f0bb --- /dev/null +++ b/public/docs/fields/index.xml @@ -0,0 +1,62 @@ + + + deblan/go-form – Input + http://localhost:1313/docs/fields/ + Recent content in Input on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Input + http://localhost:1313/docs/fields/input/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + + http://localhost:1313/docs/fields/button/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/button/ + + + + + + + + + + http://localhost:1313/docs/fields/textarea/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/textarea/ + + + + + + + + + diff --git a/public/docs/fields/input/date/index.html b/public/docs/fields/input/date/index.html new file mode 100644 index 0000000..8122eff --- /dev/null +++ b/public/docs/fields/input/date/index.html @@ -0,0 +1,568 @@ + + + + + + + + + + + + +Date – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/datetime/index.html b/public/docs/fields/input/datetime/index.html new file mode 100644 index 0000000..fe09d6e --- /dev/null +++ b/public/docs/fields/input/datetime/index.html @@ -0,0 +1,568 @@ + + + + + + + + + + + + +Datetime – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/hidden/index.html b/public/docs/fields/input/hidden/index.html new file mode 100644 index 0000000..13f7ae5 --- /dev/null +++ b/public/docs/fields/input/hidden/index.html @@ -0,0 +1,564 @@ + + + + + + + + + + + + +Hidden – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/index.html b/public/docs/fields/input/index.html new file mode 100644 index 0000000..ff57912 --- /dev/null +++ b/public/docs/fields/input/index.html @@ -0,0 +1,561 @@ + + + + + + + + + + + + +Input – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/index.xml b/public/docs/fields/input/index.xml new file mode 100644 index 0000000..fd062a4 --- /dev/null +++ b/public/docs/fields/input/index.xml @@ -0,0 +1,160 @@ + + + deblan/go-form – Input + http://localhost:1313/docs/fields/input/ + Recent content in Input on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Hidden + http://localhost:1313/docs/fields/input/hidden/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/hidden/ + + + + + + + + + Date + http://localhost:1313/docs/fields/input/date/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/date/ + + + + + + + + + Datetime + http://localhost:1313/docs/fields/input/datetime/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/datetime/ + + + + + + + + + Mail + http://localhost:1313/docs/fields/input/mail/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/mail/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Number + http://localhost:1313/docs/fields/input/number/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/number/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Password + http://localhost:1313/docs/fields/input/password/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/password/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Range + http://localhost:1313/docs/fields/input/range/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/range/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Text + http://localhost:1313/docs/fields/input/text/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/text/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Time + http://localhost:1313/docs/fields/input/time/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/time/ + + + + + + + + + diff --git a/public/docs/fields/input/mail/index.html b/public/docs/fields/input/mail/index.html new file mode 100644 index 0000000..aea61c4 --- /dev/null +++ b/public/docs/fields/input/mail/index.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + +Mail – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/number/index.html b/public/docs/fields/input/number/index.html new file mode 100644 index 0000000..2295584 --- /dev/null +++ b/public/docs/fields/input/number/index.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + +Number – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/password/index.html b/public/docs/fields/input/password/index.html new file mode 100644 index 0000000..664dec8 --- /dev/null +++ b/public/docs/fields/input/password/index.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + +Password – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/range/index.html b/public/docs/fields/input/range/index.html new file mode 100644 index 0000000..87e2874 --- /dev/null +++ b/public/docs/fields/input/range/index.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + +Range – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/text/index.html b/public/docs/fields/input/text/index.html new file mode 100644 index 0000000..3fd2b3a --- /dev/null +++ b/public/docs/fields/input/text/index.html @@ -0,0 +1,578 @@ + + + + + + + + + + + + +Text – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/input/time/index.html b/public/docs/fields/input/time/index.html new file mode 100644 index 0000000..6c5221a --- /dev/null +++ b/public/docs/fields/input/time/index.html @@ -0,0 +1,564 @@ + + + + + + + + + + + + +Time – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/fields/textarea/index.html b/public/docs/fields/textarea/index.html new file mode 100644 index 0000000..932c691 --- /dev/null +++ b/public/docs/fields/textarea/index.html @@ -0,0 +1,561 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/form/bind/index.html b/public/docs/form/bind/index.html new file mode 100644 index 0000000..67a4c9f --- /dev/null +++ b/public/docs/form/bind/index.html @@ -0,0 +1,650 @@ + + + + + + + + + + + + +Bind – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      + +
      + Form +
      Bind
      +
      + +
      +

      Bind

      +
      + +
      import (
      +	"net/http"
      +
      +    "gitnet.fr/deblan/go-form/form"
      +)
      +
      +type Person struct {
      +    Name string
      +    Age  int
      +}
      +
      +func createForm() *form.Form {
      +    f := form.NewForm()
      +
      +    // do stuff
      +
      +    return f
      +}
      +
      +http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
      +    alice := Person{
      +        Name: "Alice",
      +        Age:  42,
      +    }
      +
      +    myForm := createForm()
      +
      +    if r.Method == myForm.Method {
      +        myForm.HandleRequest(r)
      +
      +        if myForm.IsSubmitted() && myForm.IsValid() {
      +            myForm.Bind(&data)
      +        }
      +    }
      +})
      + +
      +
      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/form/index.html b/public/docs/form/index.html new file mode 100644 index 0000000..ff946ed --- /dev/null +++ b/public/docs/form/index.html @@ -0,0 +1,668 @@ + + + + + + + + + + + + +Form – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      +
      Form
      +
      + +
      +

      Form

      +

      A form is a struct containing:

      +
        +
      • Fields
      • +
      • Options
      • +
      • Method
      • +
      • Action
      • +
      +

      Import +

      + +
      import (
      +	"net/http"
      +
      +    "gitnet.fr/deblan/go-form/form"
      +)
      + +
      +
      +

      Usage +

      + +
      // Let's create a new form
      +// You can pass *form.Field as arguments
      +myForm := form.NewForm(field1, field2, ...)
      +
      +// Add somes fields
      +myForm.Add(field3, field4, ...)
      +
      +// Set the method
      +// <form method="POST" ...>
      +myForm.WithMethod(http.MethodPost)
      +
      +// Define the action
      +// <form action="/" ...>
      +myForm.WithAction("/")
      +
      +// Set a name
      +myForm.WithName("myForm")
      +
      +// Add options
      +myForm.WithOptions(option1, option2, ...)
      +
      +// When all fields are added, call End()
      +myForm.End()
      + +
      +
      +

      Attributes +

      Some options are natively supported in go-form themes.

      +
      + +
      myForm.WithOptions(
      +    form.NewOption("help", "A help for the form"),
      +    // <form data-foo="bar" data-bar="bar" ...
      +    form.NewOption("attr", map[string]string{
      +        "data-foo": "foo",
      +        "data-bar": "bar",
      +    }),
      +)
      + +
      +
      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/form/index.xml b/public/docs/form/index.xml new file mode 100644 index 0000000..2a88460 --- /dev/null +++ b/public/docs/form/index.xml @@ -0,0 +1,113 @@ + + + deblan/go-form – Form + http://localhost:1313/docs/form/ + Recent content in Form on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Mount + http://localhost:1313/docs/form/mount/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/form/mount/ + + + + <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> + +<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// Assuming 2 fields named &#34;Name&#34; and &#34;Age&#34; exist</span> +</span></span><span class="line"><span class="cl"><span class="nx">myForm</span><span class="p">.</span><span class="nf">Mount</span><span class="p">(</span><span class="nx">alice</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> + <button + class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" + title="Copy code" + > + <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> + <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> + </button> +</div> +</div> + + + + + + Bind + http://localhost:1313/docs/form/bind/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/form/bind/ + + + + <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> + +<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;net/http&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;gitnet.fr/deblan/go-form/form&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">createForm</span><span class="p">()</span> <span class="o">*</span><span class="nx">form</span><span class="p">.</span><span class="nx">Form</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">f</span> <span class="o">:=</span> <span class="nx">form</span><span class="p">.</span><span class="nf">NewForm</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// do stuff</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">f</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nx">http</span><span class="p">.</span><span class="nf">HandleFunc</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">w</span> <span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span> <span class="nx">r</span> <span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span> <span class="o">:=</span> <span class="nf">createForm</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Method</span> <span class="o">==</span> <span class="nx">myForm</span><span class="p">.</span><span class="nx">Method</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">HandleRequest</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsSubmitted</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsValid</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">Bind</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">})</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> + <button + class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" + title="Copy code" + > + <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> + <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> + </button> +</div> +</div> + + + + + + diff --git a/public/docs/form/mount/index.html b/public/docs/form/mount/index.html new file mode 100644 index 0000000..fcd9a48 --- /dev/null +++ b/public/docs/form/mount/index.html @@ -0,0 +1,604 @@ + + + + + + + + + + + + +Mount – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      + +
      + Form +
      Mount
      +
      + +
      +

      Mount

      +
      + +
      type Person struct {
      +    Name string
      +    Age  int
      +}
      +
      +alice := Person{
      +    Name: "Alice",
      +    Age:  42,
      +}
      +
      +// Assuming 2 fields named "Name" and "Age" exist
      +myForm.Mount(alice)
      + +
      +
      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/index.html b/public/docs/index.html new file mode 100644 index 0000000..ff191fb --- /dev/null +++ b/public/docs/index.html @@ -0,0 +1,608 @@ + + + + + + + + + + + + +Introduction – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      Documentation
      +
      + +
      +

      Introduction

      +

      Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.

      +

      go-form is heavily influenced by Symfony Form. It includes:

      +
        +
      • A form builder based on fields declarations and independent of structs
      • +
      • Validation based on constraints
      • +
      • Data mounting to populate a form from a struct instance
      • +
      • Data binding to populate a struct instance from a submitted form
      • +
      • Form renderer with customizable themes
      • +
      +

      Questions or Feedback? +

      + +
      fmt.Sprintf("foo")
      + +
      +
      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/index.xml b/public/docs/index.xml new file mode 100644 index 0000000..860ea90 --- /dev/null +++ b/public/docs/index.xml @@ -0,0 +1,307 @@ + + + deblan/go-form – Introduction + http://localhost:1313/docs/ + Recent content in Introduction on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + Mount + http://localhost:1313/docs/form/mount/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/form/mount/ + + + + <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> + +<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="c1">// Assuming 2 fields named &#34;Name&#34; and &#34;Age&#34; exist</span> +</span></span><span class="line"><span class="cl"><span class="nx">myForm</span><span class="p">.</span><span class="nf">Mount</span><span class="p">(</span><span class="nx">alice</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> + <button + class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" + title="Copy code" + > + <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> + <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> + </button> +</div> +</div> + + + + + + Bind + http://localhost:1313/docs/form/bind/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/form/bind/ + + + + <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> + +<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;net/http&#34;</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="s">&#34;gitnet.fr/deblan/go-form/form&#34;</span> +</span></span><span class="line"><span class="cl"><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">createForm</span><span class="p">()</span> <span class="o">*</span><span class="nx">form</span><span class="p">.</span><span class="nx">Form</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">f</span> <span class="o">:=</span> <span class="nx">form</span><span class="p">.</span><span class="nf">NewForm</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="c1">// do stuff</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">f</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="nx">http</span><span class="p">.</span><span class="nf">HandleFunc</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">w</span> <span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span> <span class="nx">r</span> <span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span> <span class="o">:=</span> <span class="nf">createForm</span><span class="p">()</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Method</span> <span class="o">==</span> <span class="nx">myForm</span><span class="p">.</span><span class="nx">Method</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">HandleRequest</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsSubmitted</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsValid</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">Bind</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">data</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"><span class="p">})</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> + <button + class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" + title="Copy code" + > + <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> + <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> + </button> +</div> +</div> + + + + + + Hidden + http://localhost:1313/docs/fields/input/hidden/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/hidden/ + + + + + + + + + Installation + http://localhost:1313/docs/installation/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/installation/ + + + + <h1>Installation</h1> + + + + + + http://localhost:1313/docs/fields/button/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/button/ + + + + + + + + + + http://localhost:1313/docs/fields/textarea/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/textarea/ + + + + + + + + + + http://localhost:1313/docs/rendering/theming/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/rendering/theming/ + + + + + + + + + Date + http://localhost:1313/docs/fields/input/date/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/date/ + + + + + + + + + Datetime + http://localhost:1313/docs/fields/input/datetime/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/datetime/ + + + + + + + + + Mail + http://localhost:1313/docs/fields/input/mail/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/mail/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Number + http://localhost:1313/docs/fields/input/number/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/number/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Password + http://localhost:1313/docs/fields/input/password/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/password/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Range + http://localhost:1313/docs/fields/input/range/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/range/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Text + http://localhost:1313/docs/fields/input/text/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/text/ + + + + <table> + <tr> + <td>ok</td> + </tr> +</table> + + + + + + Time + http://localhost:1313/docs/fields/input/time/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/fields/input/time/ + + + + + + + + + diff --git a/public/docs/installation/index.html b/public/docs/installation/index.html new file mode 100644 index 0000000..3e30d1b --- /dev/null +++ b/public/docs/installation/index.html @@ -0,0 +1,557 @@ + + + + + + + + + + + + +Installation – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      +
      Installation
      +
      + +
      +

      Installation

      +

      Installation

      +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/introduction/index.html b/public/docs/introduction/index.html new file mode 100644 index 0000000..f9d25fa --- /dev/null +++ b/public/docs/introduction/index.html @@ -0,0 +1,368 @@ + + + + + + + + + + + + +Introduction – deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + +
      +
      + +
      +
      Introduction
      +
      + +
      +

      Introduction

      +

      Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.

      +

      go-form is heavily influenced by Symfony Form. It includes:

      +
        +
      • A form builder based on fields declarations and independent of structs
      • +
      • Validation based on constraints
      • +
      • Data mounting to populate a form from a struct instance
      • +
      • Data binding to populate a struct instance from a submitted form
      • +
      • Form renderer with customizable themes
      • +
      +

      Questions or Feedback? +

      + +
      fmt.Sprintf("foo")
      + +
      +
      + +
      +
      + + +
      +
      +
      + +
      + + + + + + diff --git a/public/docs/rendering/index.html b/public/docs/rendering/index.html new file mode 100644 index 0000000..b13e171 --- /dev/null +++ b/public/docs/rendering/index.html @@ -0,0 +1,552 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/docs/rendering/index.xml b/public/docs/rendering/index.xml new file mode 100644 index 0000000..7f83048 --- /dev/null +++ b/public/docs/rendering/index.xml @@ -0,0 +1,31 @@ + + + deblan/go-form – + http://localhost:1313/docs/rendering/ + Recent content on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + + + http://localhost:1313/docs/rendering/theming/ + Mon, 01 Jan 0001 00:00:00 +0000 + + http://localhost:1313/docs/rendering/theming/ + + + + + + + + + diff --git a/public/docs/rendering/theming/index.html b/public/docs/rendering/theming/index.html new file mode 100644 index 0000000..2654d02 --- /dev/null +++ b/public/docs/rendering/theming/index.html @@ -0,0 +1,557 @@ + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + +
      + +
      + + + + + + diff --git a/public/en.search-data.json b/public/en.search-data.json new file mode 100644 index 0000000..083da43 --- /dev/null +++ b/public/en.search-data.json @@ -0,0 +1 @@ +{"/docs/":{"data":{"":"Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.\ngo-form is heavily influenced by Symfony Form. It includes:\nA form builder based on fields declarations and independent of structs Validation based on constraints Data mounting to populate a form from a struct instance Data binding to populate a struct instance from a submitted form Form renderer with customizable themes ","questions-or-feedback#Questions or Feedback?":" fmt.Sprintf(\"foo\") "},"title":"Documentation"},"/docs/fields/input/":{"data":{"":" ok "},"title":"Input"},"/docs/fields/input/mail/":{"data":{"":" ok "},"title":"Mail"},"/docs/fields/input/number/":{"data":{"":" ok "},"title":"Number"},"/docs/fields/input/password/":{"data":{"":" ok "},"title":"Password"},"/docs/fields/input/range/":{"data":{"":" ok "},"title":"Range"},"/docs/fields/input/text/":{"data":{"":" ok "},"title":"Text"},"/docs/form/":{"data":{"":"Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.\ngo-form is heavily influenced by Symfony Form. It includes:\nA form builder based on fields declarations and independent of structs Validation based on constraints Data mounting to populate a form from a struct instance Data binding to populate a struct instance from a submitted form Form renderer with customizable themes ","questions-or-feedback#Questions or Feedback?":" fmt.Sprintf(\"foo\") "},"title":"Form"},"/docs/installation/":{"data":{"installation#Installation":"Installation"},"title":"Installation"}} \ No newline at end of file diff --git a/public/en.search.js b/public/en.search.js new file mode 100644 index 0000000..6e1bdfb --- /dev/null +++ b/public/en.search.js @@ -0,0 +1,437 @@ +// Search functionality using FlexSearch. + +// Change shortcut key to cmd+k on Mac, iPad or iPhone. +document.addEventListener("DOMContentLoaded", function () { + if (/iPad|iPhone|Macintosh/.test(navigator.userAgent)) { + // select the kbd element under the .search-wrapper class + const keys = document.querySelectorAll(".search-wrapper kbd"); + keys.forEach(key => { + key.innerHTML = 'K'; + }); + } +}); + +// Render the search data as JSON. +// +// +// +// + +(function () { + const searchDataURL = '/en.search-data.json'; + + const inputElements = document.querySelectorAll('.search-input'); + for (const el of inputElements) { + el.addEventListener('focus', init); + el.addEventListener('keyup', search); + el.addEventListener('keydown', handleKeyDown); + el.addEventListener('input', handleInputChange); + } + + const shortcutElements = document.querySelectorAll('.search-wrapper kbd'); + + function setShortcutElementsOpacity(opacity) { + shortcutElements.forEach(el => { + el.style.opacity = opacity; + }); + } + + function handleInputChange(e) { + const opacity = e.target.value.length > 0 ? 0 : 100; + setShortcutElementsOpacity(opacity); + } + + // Get the search wrapper, input, and results elements. + function getActiveSearchElement() { + const inputs = Array.from(document.querySelectorAll('.search-wrapper')).filter(el => el.clientHeight > 0); + if (inputs.length === 1) { + return { + wrapper: inputs[0], + inputElement: inputs[0].querySelector('.search-input'), + resultsElement: inputs[0].querySelector('.search-results') + }; + } + return undefined; + } + + const INPUTS = ['input', 'select', 'button', 'textarea'] + + // Focus the search input when pressing ctrl+k/cmd+k or /. + document.addEventListener('keydown', function (e) { + const { inputElement } = getActiveSearchElement(); + if (!inputElement) return; + + const activeElement = document.activeElement; + const tagName = activeElement && activeElement.tagName; + if ( + inputElement === activeElement || + !tagName || + INPUTS.includes(tagName) || + (activeElement && activeElement.isContentEditable)) + return; + + if ( + e.key === '/' || + (e.key === 'k' && + (e.metaKey /* for Mac */ || /* for non-Mac */ e.ctrlKey)) + ) { + e.preventDefault(); + inputElement.focus(); + } else if (e.key === 'Escape' && inputElement.value) { + inputElement.blur(); + } + }); + + // Dismiss the search results when clicking outside the search box. + document.addEventListener('mousedown', function (e) { + const { inputElement, resultsElement } = getActiveSearchElement(); + if (!inputElement || !resultsElement) return; + if ( + e.target !== inputElement && + e.target !== resultsElement && + !resultsElement.contains(e.target) + ) { + setShortcutElementsOpacity(100); + hideSearchResults(); + } + }); + + // Get the currently active result and its index. + function getActiveResult() { + const { resultsElement } = getActiveSearchElement(); + if (!resultsElement) return { result: undefined, index: -1 }; + + const result = resultsElement.querySelector('.active'); + if (!result) return { result: undefined, index: -1 }; + + const index = parseInt(result.dataset.index, 10); + return { result, index }; + } + + // Set the active result by index. + function setActiveResult(index) { + const { resultsElement } = getActiveSearchElement(); + if (!resultsElement) return; + + const { result: activeResult } = getActiveResult(); + activeResult && activeResult.classList.remove('active'); + const result = resultsElement.querySelector(`[data-index="${index}"]`); + if (result) { + result.classList.add('active'); + result.focus(); + } + } + + // Get the number of search results from the DOM. + function getResultsLength() { + const { resultsElement } = getActiveSearchElement(); + if (!resultsElement) return 0; + return resultsElement.dataset.count; + } + + // Finish the search by hiding the results and clearing the input. + function finishSearch() { + const { inputElement } = getActiveSearchElement(); + if (!inputElement) return; + hideSearchResults(); + inputElement.value = ''; + inputElement.blur(); + } + + function hideSearchResults() { + const { resultsElement } = getActiveSearchElement(); + if (!resultsElement) return; + resultsElement.classList.add('hx-hidden'); + } + + // Handle keyboard events. + function handleKeyDown(e) { + const { inputElement } = getActiveSearchElement(); + if (!inputElement) return; + + const resultsLength = getResultsLength(); + const { result: activeResult, index: activeIndex } = getActiveResult(); + + switch (e.key) { + case 'ArrowUp': + e.preventDefault(); + if (activeIndex > 0) setActiveResult(activeIndex - 1); + break; + case 'ArrowDown': + e.preventDefault(); + if (activeIndex + 1 < resultsLength) setActiveResult(activeIndex + 1); + break; + case 'Enter': + e.preventDefault(); + if (activeResult) { + activeResult.click(); + } + finishSearch(); + case 'Escape': + e.preventDefault(); + hideSearchResults(); + // Clear the input when pressing escape + inputElement.value = ''; + inputElement.dispatchEvent(new Event('input')); + // Remove focus from the input + inputElement.blur(); + break; + } + } + + // Initializes the search. + function init(e) { + e.target.removeEventListener('focus', init); + if (!(window.pageIndex && window.sectionIndex)) { + preloadIndex(); + } + } + + /** + * Preloads the search index by fetching data and adding it to the FlexSearch index. + * @returns {Promise} A promise that resolves when the index is preloaded. + */ + async function preloadIndex() { + const tokenize = 'forward'; + + const isCJK = () => { + const lang = document.documentElement.lang || "en"; + return lang.startsWith("zh") || lang.startsWith("ja") || lang.startsWith("ko"); + } + + const encodeCJK = (str) => str.replace(/[\x00-\x7F]/g, "").split(""); + const encodeDefault = (str) => (""+str).toLocaleLowerCase().split(/[\p{Z}\p{S}\p{P}\p{C}]+/u); + const encodeFunction = isCJK() ? encodeCJK : encodeDefault; + + window.pageIndex = new FlexSearch.Document({ + tokenize, + encode: encodeFunction, + cache: 100, + document: { + id: 'id', + store: ['title', 'crumb'], + index: "content" + } + }); + + window.sectionIndex = new FlexSearch.Document({ + tokenize, + encode: encodeFunction, + cache: 100, + document: { + id: 'id', + store: ['title', 'content', 'url', 'display', 'crumb'], + index: "content", + tag: 'pageId' + } + }); + + const resp = await fetch(searchDataURL); + const data = await resp.json(); + let pageId = 0; + for (const route in data) { + let pageContent = ''; + ++pageId; + const urlParts = route.split('/').filter(x => x != "" && !x.startsWith('#')); + + let crumb = ''; + let searchUrl = '/' + for (let i = 0; i < urlParts.length; i++) { + const urlPart = urlParts[i]; + searchUrl += urlPart + '/' + + const crumbData = data[searchUrl]; + if (!crumbData) { + console.warn('Excluded page', searchUrl, '- will not be included for search result breadcrumb for', route); + continue; + } + + let title = data[searchUrl].title; + if (title == "_index") { + title = urlPart.split("-").map(x => x).join(" "); + } + crumb += title; + + if (i < urlParts.length - 1) { + crumb += ' > '; + } + } + + for (const heading in data[route].data) { + const [hash, text] = heading.split('#'); + const url = route.trimEnd('/') + (hash ? '#' + hash : ''); + const title = text || data[route].title; + + const content = data[route].data[heading] || ''; + const paragraphs = content.split('\n').filter(Boolean); + + sectionIndex.add({ + id: url, + url, + title, + crumb, + pageId: `page_${pageId}`, + content: title, + ...(paragraphs[0] && { display: paragraphs[0] }) + }); + + for (let i = 0; i < paragraphs.length; i++) { + sectionIndex.add({ + id: `${url}_${i}`, + url, + title, + crumb, + pageId: `page_${pageId}`, + content: paragraphs[i] + }); + } + + pageContent += ` ${title} ${content}`; + } + + window.pageIndex.add({ + id: pageId, + title: data[route].title, + crumb, + content: pageContent + }); + + } + } + + /** + * Performs a search based on the provided query and displays the results. + * @param {Event} e - The event object. + */ + function search(e) { + const query = e.target.value; + if (!e.target.value) { + hideSearchResults(); + return; + } + + const { resultsElement } = getActiveSearchElement(); + while (resultsElement.firstChild) { + resultsElement.removeChild(resultsElement.firstChild); + } + resultsElement.classList.remove('hx-hidden'); + + const pageResults = window.pageIndex.search(query, 5, { enrich: true, suggest: true })[0]?.result || []; + + const results = []; + const pageTitleMatches = {}; + + for (let i = 0; i < pageResults.length; i++) { + const result = pageResults[i]; + pageTitleMatches[i] = 0; + + // Show the top 5 results for each page + const sectionResults = window.sectionIndex.search(query, 5, { enrich: true, suggest: true, tag: `page_${result.id}` })[0]?.result || []; + let isFirstItemOfPage = true + const occurred = {} + + for (let j = 0; j < sectionResults.length; j++) { + const { doc } = sectionResults[j] + const isMatchingTitle = doc.display !== undefined + if (isMatchingTitle) { + pageTitleMatches[i]++ + } + const { url, title } = doc + const content = doc.display || doc.content + + if (occurred[url + '@' + content]) continue + occurred[url + '@' + content] = true + results.push({ + _page_rk: i, + _section_rk: j, + route: url, + prefix: isFirstItemOfPage ? result.doc.crumb : undefined, + children: { title, content } + }) + isFirstItemOfPage = false + } + } + const sortedResults = results + .sort((a, b) => { + // Sort by number of matches in the title. + if (a._page_rk === b._page_rk) { + return a._section_rk - b._section_rk + } + if (pageTitleMatches[a._page_rk] !== pageTitleMatches[b._page_rk]) { + return pageTitleMatches[b._page_rk] - pageTitleMatches[a._page_rk] + } + return a._page_rk - b._page_rk + }) + .map(res => ({ + id: `${res._page_rk}_${res._section_rk}`, + route: res.route, + prefix: res.prefix, + children: res.children + })); + displayResults(sortedResults, query); + } + + /** + * Displays the search results on the page. + * + * @param {Array} results - The array of search results. + * @param {string} query - The search query. + */ + function displayResults(results, query) { + const { resultsElement } = getActiveSearchElement(); + if (!resultsElement) return; + + if (!results.length) { + resultsElement.innerHTML = `No results found.`; + return; + } + + // Highlight the query in the result text. + function highlightMatches(text, query) { + const escapedQuery = query.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); + const regex = new RegExp(escapedQuery, 'gi'); + return text.replace(regex, (match) => `${match}`); + } + + // Create a DOM element from the HTML string. + function createElement(str) { + const div = document.createElement('div'); + div.innerHTML = str.trim(); + return div.firstChild; + } + + function handleMouseMove(e) { + const target = e.target.closest('a'); + if (target) { + const active = resultsElement.querySelector('a.active'); + if (active) { + active.classList.remove('active'); + } + target.classList.add('active'); + } + } + + const fragment = document.createDocumentFragment(); + for (let i = 0; i < results.length; i++) { + const result = results[i]; + if (result.prefix) { + fragment.appendChild(createElement(` +
      ${result.prefix}
      `)); + } + let li = createElement(` +
    • + +
      `+ highlightMatches(result.children.title, query) + `
      ` + + (result.children.content ? + `
      ` + highlightMatches(result.children.content, query) + `
      ` : '') + ` +
      +
    • `); + li.addEventListener('mousemove', handleMouseMove); + li.addEventListener('keydown', handleKeyDown); + li.querySelector('a').addEventListener('click', finishSearch); + fragment.appendChild(li); + } + resultsElement.appendChild(fragment); + resultsElement.dataset.count = results.length; + } +})(); diff --git a/public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js b/public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js new file mode 100644 index 0000000..db3c3e3 --- /dev/null +++ b/public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js @@ -0,0 +1,8 @@ +document.addEventListener("DOMContentLoaded",function(){if(/iPad|iPhone|Macintosh/.test(navigator.userAgent)){const e=document.querySelectorAll(".search-wrapper kbd");e.forEach(e=>{e.innerHTML='K'})}}),function(){const h="/en.search-data.json",u=document.querySelectorAll(".search-input");for(const e of u)e.addEventListener("focus",o),e.addEventListener("keyup",p),e.addEventListener("keydown",n),e.addEventListener("input",m);const d=document.querySelectorAll(".search-wrapper kbd");function a(e){d.forEach(t=>{t.style.opacity=e})}function m(e){const t=e.target.value.length>0?0:100;a(t)}function e(){const e=Array.from(document.querySelectorAll(".search-wrapper")).filter(e=>e.clientHeight>0);return e.length===1?{wrapper:e[0],inputElement:e[0].querySelector(".search-input"),resultsElement:e[0].querySelector(".search-results")}:0[0]}const l=["input","select","button","textarea"];document.addEventListener("keydown",function(t){const{inputElement:n}=e();if(!n)return;const s=document.activeElement,o=s&&s.tagName;if(n===s||!o||l.includes(o)||s&&s.isContentEditable)return;t.key==="/"||t.key==="k"&&(t.metaKey||t.ctrlKey)?(t.preventDefault(),n.focus()):t.key==="Escape"&&n.value&&n.blur()}),document.addEventListener("mousedown",function(n){const{inputElement:o,resultsElement:s}=e();if(!o||!s)return;n.target!==o&&n.target!==s&&!s.contains(n.target)&&(a(100),t())});function r(){const{resultsElement:n}=e();if(!n)return{result:0[0],index:-1};const t=n.querySelector(".active");if(!t)return{result:0[0],index:-1};const s=parseInt(t.dataset.index,10);return{result:t,index:s}}function s(t){const{resultsElement:s}=e();if(!s)return;const{result:o}=r();o&&o.classList.remove("active");const n=s.querySelector(`[data-index="${t}"]`);n&&(n.classList.add("active"),n.focus())}function c(){const{resultsElement:t}=e();return t?t.dataset.count:0}function i(){const{inputElement:n}=e();if(!n)return;t(),n.value="",n.blur()}function t(){const{resultsElement:t}=e();if(!t)return;t.classList.add("hx-hidden")}function n(n){const{inputElement:o}=e();if(!o)return;const d=c(),{result:l,index:a}=r();switch(n.key){case"ArrowUp":n.preventDefault(),a>0&&s(a-1);break;case"ArrowDown":n.preventDefault(),a+1{const e=document.documentElement.lang||"en";return e.startsWith("zh")||e.startsWith("ja")||e.startsWith("ko")},i=e=>e.replace(/[\x00-\x7F]/g,"").split(""),a=e=>(""+e).toLocaleLowerCase().split(/[\p{Z}\p{S}\p{P}\p{C}]+/u),s=o()?i:a;window.pageIndex=new FlexSearch.Document({tokenize:n,encode:s,cache:100,document:{id:"id",store:["title","crumb"],index:"content"}}),window.sectionIndex=new FlexSearch.Document({tokenize:n,encode:s,cache:100,document:{id:"id",store:["title","content","url","display","crumb"],index:"content",tag:"pageId"}});const r=await fetch(h),e=await r.json();let t=0;for(const n in e){let a="";++t;const i=n.split("/").filter(e=>e!=""&&!e.startsWith("#"));let s="",o="/";for(let t=0;te).join(" ")),s+=a,t ")}for(const c in e[n].data){const[l,u]=c.split("#"),o=n.trimEnd("/")+(l?"#"+l:""),i=u||e[n].title,d=e[n].data[c]||"",r=d.split(` +`).filter(Boolean);sectionIndex.add({id:o,url:o,title:i,crumb:s,pageId:`page_${t}`,content:i,...r[0]&&{display:r[0]}});for(let e=0;ee._page_rk===t._page_rk?e._section_rk-t._section_rk:s[e._page_rk]!==s[t._page_rk]?s[t._page_rk]-s[e._page_rk]:e._page_rk-t._page_rk).map(e=>({id:`${e._page_rk}_${e._section_rk}`,route:e.route,prefix:e.prefix,children:e.children}));g(c,i)}function g(t,s){const{resultsElement:o}=e();if(!o)return;if(!t.length){o.innerHTML=`No results found.`;return}function r(e,t){const n=t.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&"),s=new RegExp(n,"gi");return e.replace(s,e=>`${e}`)}function c(e){const t=document.createElement("div");return t.innerHTML=e.trim(),t.firstChild}function l(e){const t=e.target.closest("a");if(t){const e=o.querySelector("a.active");e&&e.classList.remove("active"),t.classList.add("active")}}const a=document.createDocumentFragment();for(let o=0;o${e.prefix}`));let d=c(` +
    • + +
      `+r(e.children.title,s)+`
      `+(e.children.content?`
      `+r(e.children.content,s)+`
      `:"")+` +
      +
    • `);d.addEventListener("mousemove",l),d.addEventListener("keydown",n),d.querySelector("a").addEventListener("click",i),a.appendChild(d)}o.appendChild(a),o.dataset.count=t.length}}() \ No newline at end of file diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..0f2dd2b2eb092162cc3cb22473ae565ddf2db9c7 GIT binary patch literal 340 zcmV-a0jvIrP)Px$4oO5oR5(wi(?2VQVHC&l&%^2k$bi`8-++`7#UP56mmo8oO4ltUkH`0000 literal 0 HcmV?d00001 diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..5c1aea58495d1cfb77aac38b4f5ce0ae14ce6a6f GIT binary patch literal 753 zcmVPx%t4TybR9Hvt*Gs5Xbri?(&+Q?o^Z=zm1S7&Q(q7P@Ng)|dgc2QPnnNi=DNKz5 z5qeOdq~ zid!3;U&PyZAAdA~Gy&XzWq1eo;urkg;50UYJcn0s6#openG9e7cH*gGycZjBr2*hZ zyj-B8`YG1qhkka00G`B0xUCrFPVd8|rj(Z7Z^8*YTt5Gbr}0IveLsNNIE^_q<+b>* zW$;SvaeR(sBys`w$=p2O840b;fdZxs8lktQ}S{Q#o0uspedoF5^0 zOjF3|kayu5ENTl7>g^*2ugsstfi3`Zk^9T@`7b0dA*W9vx5~iXC1n$y%m^gY@EtC< z1xO9-DgA$hxZ|c9u%pWr1RyQQ9Rm>F6Blx`|L@NK2o`CV4(LQM-$}l>E zY(JH3!n+*-p26W-x6MRN7i=6xiLRRUxs3&i)xXdikds{>Cj zr%w^x-jIRpjc;N%ervk2rVRAjXG_X}T8*q-bxEJkzzJlwpH|WppmLfqy{69}lN4U3 j-C + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..553fa15d0e22126b2d923b442890cae56d724b40 GIT binary patch literal 15406 zcmeI1Tc{OP7=XvD(?v^9S(>RG3G7s)#{x+Z3N0Tjvd{;^m!m=iiAhk|Lq%`B8D(Zg zMi?SikW||3LAq!~H-j_~?9{Oov@9{vEbIGlFBw;J_RQ?d(PIDbF*9ra_5W-C>-MkN zNirZAm<%17aP3I$Iz34yB}vlJaqPLXJxNwl*40&cKQ2i&U6>@D=um|k$I7|%w+zPN z>iJsk?W3&t*(dhR7GOsFO9oK#K3Lzr&JxFlV`LRP z5b-R}_P=ASnmA6nAw7P*x6H9!R0gA1%ls*7zae^^Sm}Tp!1bvm|EmbFt0YTdV+HRm zb1pSgMq>PVa6X4UAY3hb0fs}P(_SBpKH_~IjEzq z`;~RetSzV?mvP*^4dHjXhF<~~2luUD$F*MDd9nnBP{->w@b{Dz_nUVhZObv7C+Rx2zpp(p z&yMdW!eIz)c-O)lai0$Qj-7hfl;tUVU*`Ds_16{sLtMvOP^UOw_JY4j+j$cFJBJ!2 zi!oHj{{i%ijMbv;YeUi8u;}mq1>JLt8ZV&dT-XXl{Tr)?3fL{GG8e@%@mJSZ z&JB5XjN4jB+j4Es6X#v}j9~rlyh<7Gucs{J0@`p-D>|p$E8R0g+ij2IsHhmP&mq*` z&%Jwk88K&Y{SP)=$ImQaz`1^Zs-8B?WonU-f0;|!4(Ft6Q#Fj6`=%NMvIcuY3I0jdOIcV(v2xaExBca(c0S8NAV+HTKpe3yc{HG$|cM=C~ zH?+Q!5QLVrBG7*k@QmT~Gv5*K&x2E4+G*e-*bF;iPlaBtn_wXn&Gk_27cn0;w$s6O z`+rBALxgAFeF!ta@7?vDK`>F5n0HQtRbYM<+L?DX?=@d?Y_-A3kP$e20?hxb#k{ZI zVx3)J{yiG{L+o$DW-+lwz2v5S} zC9&_;!$HuNHeZK1;M{1W*uRc(&o?1vUY)OF;4E-1l)*a2`$b6GbRMk%?ba)vu_l3M zuCx#Djn`DDS4Lr=2V(nMDbshY=RC*ZMA!ncZO`w^p;p^eJwfi|Dg8Yp_|x}<6EurI zcs6|+(%%|_-ES!GEN&`S(>38u2=>F(v*$9X70ES8o6%U*LOhH9`Xa_ zW&bCkN-__!V*dr@9nffT5BI;I5c_a-O`czavlSV({5^BQcr`<=#%R38`8%Ge!Pz?M zgcx`|3U9zbXqFh4N5FBP_Weo?4sC1N#`io=uE9>(Dz5tS@38e+e{m+++R(aUR?Z=Gp#+dfM;$+YbFL z#%n#)+x~6XsAd1F_xIWds~gaMzbU&nYOg=#8l3HgdgE{XuV5_nmze**2KsJ9`wwBq zIeZ2*Tg+)^LwX;sXa0s5m~&p$9&rOG*cE}{2-)# zo6D3HbEdQn?;S@|pjmTyIJW)n75iO5Sy?e>b?=I8y+_%Ivc?MNo0~iZu|NBLUV-|t zif0D*uGroI$~^Biava&8H^FX*{q<7jS*onKXDx#`m(~6z7zK?I&n~MV?r&r7oErqS zh-YWd&~Z!-Q}!SLP(jTon% zDb_%IzJ8gq3!v71uSc?Mteb68m>K?1Ipacnnv2wvOwi z-*KC + + diff --git a/public/images/logo-dark.svg b/public/images/logo-dark.svg new file mode 100644 index 0000000..2857264 --- /dev/null +++ b/public/images/logo-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/logo.svg b/public/images/logo.svg new file mode 100644 index 0000000..1ed7daf --- /dev/null +++ b/public/images/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..f7131d8 --- /dev/null +++ b/public/index.html @@ -0,0 +1,448 @@ + + + + + + + + + + + + + +deblan/go-form + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + +
      + +
      +

      + + + + + + diff --git a/public/index.xml b/public/index.xml new file mode 100644 index 0000000..27ad978 --- /dev/null +++ b/public/index.xml @@ -0,0 +1,17 @@ + + + deblan/go-form – Welcome! + http://localhost:1313/ + Recent content in Welcome! on deblan/go-form + Hugo -- gohugo.io + en-us + + + + + + + + + + diff --git a/public/js/main.js b/public/js/main.js new file mode 100644 index 0000000..7d34dbb --- /dev/null +++ b/public/js/main.js @@ -0,0 +1,320 @@ +// Light / Dark theme toggle +(function () { + const defaultTheme = 'system' + + const themeToggleButtons = document.querySelectorAll(".theme-toggle"); + + // Change the icons of the buttons based on previous settings or system theme + if ( + localStorage.getItem("color-theme") === "dark" || + (!("color-theme" in localStorage) && + ((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark")) + ) { + themeToggleButtons.forEach((el) => el.dataset.theme = "dark"); + } else { + themeToggleButtons.forEach((el) => el.dataset.theme = "light"); + } + + // Add click event handler to the buttons + themeToggleButtons.forEach((el) => { + el.addEventListener("click", function () { + if (localStorage.getItem("color-theme")) { + if (localStorage.getItem("color-theme") === "light") { + setDarkTheme(); + localStorage.setItem("color-theme", "dark"); + } else { + setLightTheme(); + localStorage.setItem("color-theme", "light"); + } + } else { + if (document.documentElement.classList.contains("dark")) { + setLightTheme(); + localStorage.setItem("color-theme", "light"); + } else { + setDarkTheme(); + localStorage.setItem("color-theme", "dark"); + } + } + el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"; + }); + }); + + // Listen for system theme changes + window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { + if (defaultTheme === "system" && !("color-theme" in localStorage)) { + e.matches ? setDarkTheme() : setLightTheme(); + themeToggleButtons.forEach((el) => + el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light" + ); + } + }); +})(); + +; +// Hamburger menu for mobile navigation + +document.addEventListener('DOMContentLoaded', function () { + const menu = document.querySelector('.hamburger-menu'); + const overlay = document.querySelector('.mobile-menu-overlay'); + const sidebarContainer = document.querySelector('.sidebar-container'); + + // Initialize the overlay + const overlayClasses = ['hx-fixed', 'hx-inset-0', 'hx-z-10', 'hx-bg-black/80', 'dark:hx-bg-black/60']; + overlay.classList.add('hx-bg-transparent'); + overlay.classList.remove("hx-hidden", ...overlayClasses); + + function toggleMenu() { + // Toggle the hamburger menu + menu.querySelector('svg').classList.toggle('open'); + + // When the menu is open, we want to show the navigation sidebar + sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,-100%,0)]'); + sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,0,0)]'); + + // When the menu is open, we want to prevent the body from scrolling + document.body.classList.toggle('hx-overflow-hidden'); + document.body.classList.toggle('md:hx-overflow-auto'); + } + + function hideOverlay() { + // Hide the overlay + overlay.classList.remove(...overlayClasses); + overlay.classList.add('hx-bg-transparent'); + } + + menu.addEventListener('click', (e) => { + e.preventDefault(); + toggleMenu(); + + if (overlay.classList.contains('hx-bg-transparent')) { + // Show the overlay + overlay.classList.add(...overlayClasses); + overlay.classList.remove('hx-bg-transparent'); + } else { + // Hide the overlay + hideOverlay(); + } + }); + + overlay.addEventListener('click', (e) => { + e.preventDefault(); + toggleMenu(); + + // Hide the overlay + hideOverlay(); + }); + + // Select all anchor tags in the sidebar container + const sidebarLinks = sidebarContainer.querySelectorAll('a'); + + // Add click event listener to each anchor tag + sidebarLinks.forEach(link => { + link.addEventListener('click', (e) => { + // Check if the href attribute contains a hash symbol (links to a heading) + if (link.getAttribute('href') && link.getAttribute('href').startsWith('#')) { + // Only dismiss overlay on mobile view + if (window.innerWidth < 768) { + toggleMenu(); + hideOverlay(); + } + } + }); + }); +}); + +; +// Copy button for code blocks + +document.addEventListener('DOMContentLoaded', function () { + const getCopyIcon = () => { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.innerHTML = ` + + `; + svg.setAttribute('fill', 'none'); + svg.setAttribute('viewBox', '0 0 24 24'); + svg.setAttribute('stroke', 'currentColor'); + svg.setAttribute('stroke-width', '2'); + return svg; + } + + const getSuccessIcon = () => { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.innerHTML = ` + + `; + svg.setAttribute('fill', 'none'); + svg.setAttribute('viewBox', '0 0 24 24'); + svg.setAttribute('stroke', 'currentColor'); + svg.setAttribute('stroke-width', '2'); + return svg; + } + + document.querySelectorAll('.hextra-code-copy-btn').forEach(function (button) { + // Add copy and success icons + button.querySelector('.copy-icon')?.appendChild(getCopyIcon()); + button.querySelector('.success-icon')?.appendChild(getSuccessIcon()); + + // Add click event listener for copy button + button.addEventListener('click', function (e) { + e.preventDefault(); + // Get the code target + const target = button.parentElement.previousElementSibling; + let codeElement; + if (target.tagName === 'CODE') { + codeElement = target; + } else { + // Select the last code element in case line numbers are present + const codeElements = target.querySelectorAll('code'); + codeElement = codeElements[codeElements.length - 1]; + } + if (codeElement) { + let code = codeElement.innerText; + // Replace double newlines with single newlines in the innerText + // as each line inside has trailing newline '\n' + if ("lang" in codeElement.dataset) { + code = code.replace(/\n\n/g, '\n'); + } + navigator.clipboard.writeText(code).then(function () { + button.classList.add('copied'); + setTimeout(function () { + button.classList.remove('copied'); + }, 1000); + }).catch(function (err) { + console.error('Failed to copy text: ', err); + }); + } else { + console.error('Target element not found'); + } + }); + }); +}); + +; +document.querySelectorAll('.hextra-tabs-toggle').forEach(function (button) { + button.addEventListener('click', function (e) { + // set parent tabs to unselected + const tabs = Array.from(e.target.parentElement.querySelectorAll('.hextra-tabs-toggle')); + tabs.map(tab => tab.dataset.state = ''); + + // set current tab to selected + e.target.dataset.state = 'selected'; + + // set all panels to unselected + const panelsContainer = e.target.parentElement.parentElement.nextElementSibling; + Array.from(panelsContainer.children).forEach(function (panel) { + panel.dataset.state = ''; + }); + + const panelId = e.target.getAttribute('aria-controls'); + const panel = panelsContainer.querySelector(`#${panelId}`); + panel.dataset.state = 'selected'; + }); +}); + +; +(function () { + const languageSwitchers = document.querySelectorAll('.language-switcher'); + languageSwitchers.forEach((switcher) => { + switcher.addEventListener('click', (e) => { + e.preventDefault(); + switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open'; + const optionsElement = switcher.nextElementSibling; + optionsElement.classList.toggle('hx-hidden'); + + // Calculate position of language options element + const switcherRect = switcher.getBoundingClientRect(); + const translateY = switcherRect.top - window.innerHeight - 15; + optionsElement.style.transform = `translate3d(${switcherRect.left}px, ${translateY}px, 0)`; + optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`; + }); + }); + + // Dismiss language switcher when clicking outside + document.addEventListener('click', (e) => { + if (e.target.closest('.language-switcher') === null) { + languageSwitchers.forEach((switcher) => { + switcher.dataset.state = 'closed'; + const optionsElement = switcher.nextElementSibling; + optionsElement.classList.add('hx-hidden'); + }); + } + }); +})(); + +; +// Script for filetree shortcode collapsing/expanding folders used in the theme +// ====================================================================== +document.addEventListener("DOMContentLoaded", function () { + const folders = document.querySelectorAll(".hextra-filetree-folder"); + folders.forEach(function (folder) { + folder.addEventListener("click", function () { + Array.from(folder.children).forEach(function (el) { + el.dataset.state = el.dataset.state === "open" ? "closed" : "open"; + }); + folder.nextElementSibling.dataset.state = folder.nextElementSibling.dataset.state === "open" ? "closed" : "open"; + }); + }); +}); + +; +document.addEventListener("DOMContentLoaded", function () { + scrollToActiveItem(); + enableCollapsibles(); +}); + +function enableCollapsibles() { + const buttons = document.querySelectorAll(".hextra-sidebar-collapsible-button"); + buttons.forEach(function (button) { + button.addEventListener("click", function (e) { + e.preventDefault(); + const list = button.parentElement.parentElement; + if (list) { + list.classList.toggle("open") + } + }); + }); +} + +function scrollToActiveItem() { + const sidebarScrollbar = document.querySelector("aside.sidebar-container > .hextra-scrollbar"); + const activeItems = document.querySelectorAll(".sidebar-active-item"); + const visibleActiveItem = Array.from(activeItems).find(function (activeItem) { + return activeItem.getBoundingClientRect().height > 0; + }); + + if (!visibleActiveItem) { + return; + } + + const yOffset = visibleActiveItem.clientHeight; + const yDistance = visibleActiveItem.getBoundingClientRect().top - sidebarScrollbar.getBoundingClientRect().top; + sidebarScrollbar.scrollTo({ + behavior: "instant", + top: yDistance - yOffset + }); +} + +; +// Back to top button + +document.addEventListener("DOMContentLoaded", function () { + const backToTop = document.querySelector("#backToTop"); + if (backToTop) { + document.addEventListener("scroll", (e) => { + if (window.scrollY > 300) { + backToTop.classList.remove("hx-opacity-0"); + } else { + backToTop.classList.add("hx-opacity-0"); + } + }); + } +}); + +function scrollUp() { + window.scroll({ + top: 0, + left: 0, + behavior: "smooth", + }); +} diff --git a/public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js b/public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js new file mode 100644 index 0000000..3ed1b78 --- /dev/null +++ b/public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js @@ -0,0 +1,6 @@ +(function(){const t="system",e=document.querySelectorAll(".theme-toggle");localStorage.getItem("color-theme")==="dark"||!("color-theme"in localStorage)&&(window.matchMedia("(prefers-color-scheme: dark)").matches&&t==="system"||t==="dark")?e.forEach(e=>e.dataset.theme="dark"):e.forEach(e=>e.dataset.theme="light"),e.forEach(e=>{e.addEventListener("click",function(){localStorage.getItem("color-theme")?localStorage.getItem("color-theme")==="light"?(setDarkTheme(),localStorage.setItem("color-theme","dark")):(setLightTheme(),localStorage.setItem("color-theme","light")):document.documentElement.classList.contains("dark")?(setLightTheme(),localStorage.setItem("color-theme","light")):(setDarkTheme(),localStorage.setItem("color-theme","dark")),e.dataset.theme=document.documentElement.classList.contains("dark")?"dark":"light"})}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",n=>{t==="system"&&!("color-theme"in localStorage)&&(n.matches?setDarkTheme():setLightTheme(),e.forEach(e=>e.dataset.theme=document.documentElement.classList.contains("dark")?"dark":"light"))})})(),document.addEventListener("DOMContentLoaded",function(){const i=document.querySelector(".hamburger-menu"),e=document.querySelector(".mobile-menu-overlay"),t=document.querySelector(".sidebar-container"),n=["hx-fixed","hx-inset-0","hx-z-10","hx-bg-black/80","dark:hx-bg-black/60"];e.classList.add("hx-bg-transparent"),e.classList.remove("hx-hidden",...n);function s(){i.querySelector("svg").classList.toggle("open"),t.classList.toggle("max-md:[transform:translate3d(0,-100%,0)]"),t.classList.toggle("max-md:[transform:translate3d(0,0,0)]"),document.body.classList.toggle("hx-overflow-hidden"),document.body.classList.toggle("md:hx-overflow-auto")}function o(){e.classList.remove(...n),e.classList.add("hx-bg-transparent")}i.addEventListener("click",t=>{t.preventDefault(),s(),e.classList.contains("hx-bg-transparent")?(e.classList.add(...n),e.classList.remove("hx-bg-transparent")):o()}),e.addEventListener("click",e=>{e.preventDefault(),s(),o()});const a=t.querySelectorAll("a");a.forEach(e=>{e.addEventListener("click",t=>{e.getAttribute("href")&&e.getAttribute("href").startsWith("#")&&window.innerWidth<768&&(s(),o())})})}),document.addEventListener("DOMContentLoaded",function(){const e=()=>{const e=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.innerHTML=` + + `,e.setAttribute("fill","none"),e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","2"),e},t=()=>{const e=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.innerHTML=` + + `,e.setAttribute("fill","none"),e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","2"),e};document.querySelectorAll(".hextra-code-copy-btn").forEach(function(n){n.querySelector(".copy-icon")?.appendChild(e()),n.querySelector(".success-icon")?.appendChild(t()),n.addEventListener("click",function(e){e.preventDefault();const s=n.parentElement.previousElementSibling;let t;if(s.tagName==="CODE")t=s;else{const e=s.querySelectorAll("code");t=e[e.length-1]}if(t){let e=t.innerText;"lang"in t.dataset&&(e=e.replace(/\n\n/g,` +`)),navigator.clipboard.writeText(e).then(function(){n.classList.add("copied"),setTimeout(function(){n.classList.remove("copied")},1e3)}).catch(function(e){console.error("Failed to copy text: ",e)})}else console.error("Target element not found")})})}),document.querySelectorAll(".hextra-tabs-toggle").forEach(function(e){e.addEventListener("click",function(e){const n=Array.from(e.target.parentElement.querySelectorAll(".hextra-tabs-toggle"));n.map(e=>e.dataset.state=""),e.target.dataset.state="selected";const t=e.target.parentElement.parentElement.nextElementSibling;Array.from(t.children).forEach(function(e){e.dataset.state=""});const s=e.target.getAttribute("aria-controls"),o=t.querySelector(`#${s}`);o.dataset.state="selected"})}),function(){const e=document.querySelectorAll(".language-switcher");e.forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),e.dataset.state=e.dataset.state==="open"?"closed":"open";const n=e.nextElementSibling;n.classList.toggle("hx-hidden");const s=e.getBoundingClientRect(),o=s.top-window.innerHeight-15;n.style.transform=`translate3d(${s.left}px, ${o}px, 0)`,n.style.minWidth=`${Math.max(s.width,50)}px`})}),document.addEventListener("click",t=>{t.target.closest(".language-switcher")===null&&e.forEach(e=>{e.dataset.state="closed";const t=e.nextElementSibling;t.classList.add("hx-hidden")})})}(),document.addEventListener("DOMContentLoaded",function(){const e=document.querySelectorAll(".hextra-filetree-folder");e.forEach(function(e){e.addEventListener("click",function(){Array.from(e.children).forEach(function(e){e.dataset.state=e.dataset.state==="open"?"closed":"open"}),e.nextElementSibling.dataset.state=e.nextElementSibling.dataset.state==="open"?"closed":"open"})})}),document.addEventListener("DOMContentLoaded",function(){scrollToActiveItem(),enableCollapsibles()});function enableCollapsibles(){const e=document.querySelectorAll(".hextra-sidebar-collapsible-button");e.forEach(function(e){e.addEventListener("click",function(t){t.preventDefault();const n=e.parentElement.parentElement;n&&n.classList.toggle("open")})})}function scrollToActiveItem(){const t=document.querySelector("aside.sidebar-container > .hextra-scrollbar"),n=document.querySelectorAll(".sidebar-active-item"),e=Array.from(n).find(function(e){return e.getBoundingClientRect().height>0});if(!e)return;const s=e.clientHeight,o=e.getBoundingClientRect().top-t.getBoundingClientRect().top;t.scrollTo({behavior:"instant",top:o-s})}document.addEventListener("DOMContentLoaded",function(){const e=document.querySelector("#backToTop");e&&document.addEventListener("scroll",t=>{window.scrollY>300?e.classList.remove("hx-opacity-0"):e.classList.add("hx-opacity-0")})});function scrollUp(){window.scroll({top:0,left:0,behavior:"smooth"})} \ No newline at end of file diff --git a/public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js b/public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js new file mode 100644 index 0000000..4ebf76e --- /dev/null +++ b/public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js @@ -0,0 +1,39 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/flexsearch@0.7.31/dist/flexsearch.bundle.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/**! + * FlexSearch.js v0.7.31 (Bundle) + * Copyright 2018-2022 Nextapps GmbH + * Author: Thomas Wilkerling + * Licence: Apache-2.0 + * https://github.com/nextapps-de/flexsearch + */ +(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var t;function u(a){return"undefined"!==typeof a?a:!0}function aa(a){const b=Array(a);for(let c=0;c=this.B&&(w||!n[l])){var f=L(q,d,r),g="";switch(this.G){case "full":if(2f;h--)if(h-f>=this.B){var k=L(q,d,r,e,f);g=l.substring(f,h);M(this,n,g,k,a,c)}break}case "reverse":if(1=this.B&&M(this,n, +g,L(q,d,r,e,h),a,c);g=""}case "forward":if(1=this.B&&M(this,n,g,f,a,c);break}default:if(this.C&&(f=Math.min(f/this.C(b,l,r)|0,q-1)),M(this,n,l,f,a,c),w&&1=this.B&&!e[l]){e[l]=1;const p=this.l&&l>f;M(this,m,p?f:l,L(g+(d/2>g?0:1),d,r,h-1,k-1),a,c,p?l:f)}}}}this.m||(this.register[a]=1)}}return this}; +function L(a,b,c,d,e){return c&&1=this.B&&!c[q])if(this.s||f||this.map[q])k[w++]=q,c[q]=1;else return d;a=k;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1=d)))break;if(n){if(f)return ta(k,d,0);b[b.length]=k;return}}return!c&&k}function ta(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} +function ua(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}t.contain=function(a){return!!this.register[a]};t.update=function(a,b){return this.remove(a).add(a,b)}; +t.remove=function(a,b){const c=this.register[a];if(c){if(this.m)for(let d=0,e;db||c)e=e.slice(c,c+b);d&&(e=za.call(this,e));return{tag:a,result:e}}}function za(a){const b=Array(a.length);for(let c=0,d;c + + + http://localhost:1313/docs/form/mount/ + + http://localhost:1313/docs/form/bind/ + + http://localhost:1313/docs/fields/input/hidden/ + + http://localhost:1313/docs/installation/ + + http://localhost:1313/docs/form/ + + http://localhost:1313/docs/fields/ + + http://localhost:1313/docs/fields/input/ + + http://localhost:1313/docs/constraints/ + + http://localhost:1313/docs/fields/button/ + + http://localhost:1313/docs/fields/textarea/ + + http://localhost:1313/docs/rendering/ + + http://localhost:1313/docs/rendering/theming/ + + http://localhost:1313/categories/ + + http://localhost:1313/docs/fields/input/date/ + + http://localhost:1313/docs/fields/input/datetime/ + + http://localhost:1313/docs/ + + http://localhost:1313/docs/fields/input/mail/ + + http://localhost:1313/docs/fields/input/number/ + + http://localhost:1313/docs/fields/input/password/ + + http://localhost:1313/docs/fields/input/range/ + + http://localhost:1313/tags/ + + http://localhost:1313/docs/fields/input/text/ + + http://localhost:1313/docs/fields/input/time/ + + http://localhost:1313/ + + From 7e429de2e0d32d8e2d211ea631c4955f3015f06d Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 21 Jul 2025 09:04:07 +0200 Subject: [PATCH 026/122] feat: ci --- .woodpecker.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index dfe0ba6..b9b8401 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,6 +1,7 @@ steps: Build: image: gitnet.fr/deblan/hugo + pull: true environments: HUGO_BASEURL: https://deblan.gitnet.page/go-form/ HUGO_ENVIRONMENT: production @@ -20,7 +21,7 @@ steps: - rm * -fr - mv /tmp/public/* . - git add . - - git commit -m "Build ${CI_BUILD_NUMBER}" + - git commit -m "Build doc ${CI_BUILD_NUMBER}" "Push pages": image: appleboy/drone-git-push From 035569a82f1c6ae8e4d3a263ab4e527bff609e7e Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 21 Jul 2025 09:17:47 +0200 Subject: [PATCH 027/122] fix: conf --- .woodpecker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index b9b8401..f0404c8 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -3,7 +3,7 @@ steps: image: gitnet.fr/deblan/hugo pull: true environments: - HUGO_BASEURL: https://deblan.gitnet.page/go-form/ + HUGO_BASEURL: https://deblan.gitnet.page/go-form HUGO_ENVIRONMENT: production commands: - hugo build From a312e271b23cedfcb7c10478123fb28017f57d80 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 21 Jul 2025 09:19:46 +0200 Subject: [PATCH 028/122] fix: conf --- .woodpecker.yml | 1 - hugo.yaml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index f0404c8..20f8c95 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -3,7 +3,6 @@ steps: image: gitnet.fr/deblan/hugo pull: true environments: - HUGO_BASEURL: https://deblan.gitnet.page/go-form HUGO_ENVIRONMENT: production commands: - hugo build diff --git a/hugo.yaml b/hugo.yaml index 5a35edb..4f31507 100644 --- a/hugo.yaml +++ b/hugo.yaml @@ -1,3 +1,4 @@ +baseURL: https://deblan.gitnet.page/go-form/ languageCode: en-us title: deblan/go-form From 61631040b9ae2725188b5e486e3de9eb0612f9ab Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 21 Jul 2025 22:36:16 +0200 Subject: [PATCH 029/122] remove build --- public/404.html | 39 - public/android-chrome-192x192.png | Bin 7296 -> 0 bytes public/android-chrome-512x512.png | Bin 27677 -> 0 bytes public/apple-touch-icon.png | Bin 6521 -> 0 bytes public/categories/index.html | 373 -- public/categories/index.xml | 18 - public/css/compiled/main.css | 3637 ----------------- ...c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css | 1 - public/css/custom.css | 0 ...6fb92427ae41e4649b934ca495991b7852b855.css | 0 public/docs/01-introduction/index.html | 328 -- public/docs/02-installation/index.html | 252 -- public/docs/button/index.html | 467 --- public/docs/constraints/index.html | 552 --- public/docs/constraints/index.xml | 18 - public/docs/field/date/date/index.html | 464 --- public/docs/field/date/datetime/index.html | 468 --- public/docs/field/date/index.html | 455 --- public/docs/field/date/index.xml | 57 - public/docs/field/date/time/index.html | 464 --- public/docs/field/index.html | 452 -- public/docs/field/index.xml | 49 - public/docs/field/input/hidden/index.html | 464 --- public/docs/field/input/index.html | 461 --- public/docs/field/input/index.xml | 121 - public/docs/field/input/mail/index.html | 478 --- public/docs/field/input/number/index.html | 478 --- public/docs/field/input/password/index.html | 478 --- public/docs/field/input/range/index.html | 478 --- public/docs/field/input/text/index.html | 474 --- public/docs/field/text/index.html | 311 -- public/docs/fields/button/index.html | 561 --- public/docs/fields/date/date/index.html | 464 --- public/docs/fields/date/datetime/index.html | 468 --- public/docs/fields/date/index.html | 455 --- public/docs/fields/date/index.xml | 57 - public/docs/fields/date/time/index.html | 464 --- public/docs/fields/index.html | 552 --- public/docs/fields/index.xml | 62 - public/docs/fields/input/date/index.html | 568 --- public/docs/fields/input/datetime/index.html | 568 --- public/docs/fields/input/hidden/index.html | 564 --- public/docs/fields/input/index.html | 561 --- public/docs/fields/input/index.xml | 160 - public/docs/fields/input/mail/index.html | 578 --- public/docs/fields/input/number/index.html | 578 --- public/docs/fields/input/password/index.html | 578 --- public/docs/fields/input/range/index.html | 578 --- public/docs/fields/input/text/index.html | 578 --- public/docs/fields/input/time/index.html | 564 --- public/docs/fields/textarea/index.html | 561 --- public/docs/form/bind/index.html | 650 --- public/docs/form/index.html | 668 --- public/docs/form/index.xml | 113 - public/docs/form/mount/index.html | 604 --- public/docs/index.html | 608 --- public/docs/index.xml | 307 -- public/docs/installation/index.html | 557 --- public/docs/introduction/index.html | 368 -- public/docs/rendering/index.html | 552 --- public/docs/rendering/index.xml | 31 - public/docs/rendering/theming/index.html | 557 --- public/en.search-data.json | 1 - public/en.search.js | 437 -- ...86d6474e66bd5acdbbe01e8bac129f5ef345a88.js | 8 - public/favicon-16x16.png | Bin 340 -> 0 bytes public/favicon-32x32.png | Bin 753 -> 0 bytes public/favicon-dark.svg | 13 - public/favicon.ico | Bin 15406 -> 0 bytes public/favicon.svg | 13 - public/images/logo-dark.svg | 3 - public/images/logo.svg | 3 - public/index.html | 448 -- public/index.xml | 17 - public/js/main.js | 320 -- ...57fd229d7edc19c0ef1a285396eb292d9ca9842.js | 6 - ...c7a56b39327d475e2e3a8f550416be3a9134327.js | 39 - public/robots.txt | 1 - public/site.webmanifest | 20 - public/sitemap.xml | 53 - 80 files changed, 27753 deletions(-) delete mode 100644 public/404.html delete mode 100644 public/android-chrome-192x192.png delete mode 100644 public/android-chrome-512x512.png delete mode 100644 public/apple-touch-icon.png delete mode 100644 public/categories/index.html delete mode 100644 public/categories/index.xml delete mode 100644 public/css/compiled/main.css delete mode 100644 public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css delete mode 100644 public/css/custom.css delete mode 100644 public/css/custom.min.e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css delete mode 100644 public/docs/01-introduction/index.html delete mode 100644 public/docs/02-installation/index.html delete mode 100644 public/docs/button/index.html delete mode 100644 public/docs/constraints/index.html delete mode 100644 public/docs/constraints/index.xml delete mode 100644 public/docs/field/date/date/index.html delete mode 100644 public/docs/field/date/datetime/index.html delete mode 100644 public/docs/field/date/index.html delete mode 100644 public/docs/field/date/index.xml delete mode 100644 public/docs/field/date/time/index.html delete mode 100644 public/docs/field/index.html delete mode 100644 public/docs/field/index.xml delete mode 100644 public/docs/field/input/hidden/index.html delete mode 100644 public/docs/field/input/index.html delete mode 100644 public/docs/field/input/index.xml delete mode 100644 public/docs/field/input/mail/index.html delete mode 100644 public/docs/field/input/number/index.html delete mode 100644 public/docs/field/input/password/index.html delete mode 100644 public/docs/field/input/range/index.html delete mode 100644 public/docs/field/input/text/index.html delete mode 100644 public/docs/field/text/index.html delete mode 100644 public/docs/fields/button/index.html delete mode 100644 public/docs/fields/date/date/index.html delete mode 100644 public/docs/fields/date/datetime/index.html delete mode 100644 public/docs/fields/date/index.html delete mode 100644 public/docs/fields/date/index.xml delete mode 100644 public/docs/fields/date/time/index.html delete mode 100644 public/docs/fields/index.html delete mode 100644 public/docs/fields/index.xml delete mode 100644 public/docs/fields/input/date/index.html delete mode 100644 public/docs/fields/input/datetime/index.html delete mode 100644 public/docs/fields/input/hidden/index.html delete mode 100644 public/docs/fields/input/index.html delete mode 100644 public/docs/fields/input/index.xml delete mode 100644 public/docs/fields/input/mail/index.html delete mode 100644 public/docs/fields/input/number/index.html delete mode 100644 public/docs/fields/input/password/index.html delete mode 100644 public/docs/fields/input/range/index.html delete mode 100644 public/docs/fields/input/text/index.html delete mode 100644 public/docs/fields/input/time/index.html delete mode 100644 public/docs/fields/textarea/index.html delete mode 100644 public/docs/form/bind/index.html delete mode 100644 public/docs/form/index.html delete mode 100644 public/docs/form/index.xml delete mode 100644 public/docs/form/mount/index.html delete mode 100644 public/docs/index.html delete mode 100644 public/docs/index.xml delete mode 100644 public/docs/installation/index.html delete mode 100644 public/docs/introduction/index.html delete mode 100644 public/docs/rendering/index.html delete mode 100644 public/docs/rendering/index.xml delete mode 100644 public/docs/rendering/theming/index.html delete mode 100644 public/en.search-data.json delete mode 100644 public/en.search.js delete mode 100644 public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js delete mode 100644 public/favicon-16x16.png delete mode 100644 public/favicon-32x32.png delete mode 100644 public/favicon-dark.svg delete mode 100644 public/favicon.ico delete mode 100644 public/favicon.svg delete mode 100644 public/images/logo-dark.svg delete mode 100644 public/images/logo.svg delete mode 100644 public/index.html delete mode 100644 public/index.xml delete mode 100644 public/js/main.js delete mode 100644 public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js delete mode 100644 public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js delete mode 100644 public/robots.txt delete mode 100644 public/site.webmanifest delete mode 100644 public/sitemap.xml diff --git a/public/404.html b/public/404.html deleted file mode 100644 index 0639133..0000000 --- a/public/404.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -
      - -

      - 404

      -
      -

      This page could not be found. -

      -
      -
      - - - diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png deleted file mode 100644 index 7f0493c7efdff87df4aa2b69907e5e139aa65d2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7296 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 aw1?3)!!yhudWBvfMZiGM6jh_+9P@twy3z#z diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png deleted file mode 100644 index faea4c2fdfc9d9e28b87c2aab2c24bac43a74c8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27677 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 T^_}^rr2t^}jPF+HJdXJvBP!h= diff --git a/public/categories/index.html b/public/categories/index.html deleted file mode 100644 index 872f870..0000000 --- a/public/categories/index.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - -Categories – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      -
      -

      Categories

      -
      -
      - -
      -
      - -
      -
      -
      -
      - -
      -

      - - - - - - diff --git a/public/categories/index.xml b/public/categories/index.xml deleted file mode 100644 index 86eab3b..0000000 --- a/public/categories/index.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - deblan/go-form – Categories - http://localhost:1313/categories/ - Recent content in Categories on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - diff --git a/public/css/compiled/main.css b/public/css/compiled/main.css deleted file mode 100644 index c482e48..0000000 --- a/public/css/compiled/main.css +++ /dev/null @@ -1,3637 +0,0 @@ -/* -! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com -*//* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { - box-sizing: border-box; /* 1 */ - border-width: 0; /* 2 */ - border-style: solid; /* 2 */ - border-color: #e5e7eb; /* 2 */ -} - -::before, -::after { - --tw-content: ''; -} - -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -6. Use the user's configured `sans` font-variation-settings by default. -7. Disable tap highlights on iOS -*/ - -html, -:host { - line-height: 1.5; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ - -moz-tab-size: 4; /* 3 */ - -o-tab-size: 4; - tab-size: 4; /* 3 */ - font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ - font-feature-settings: normal; /* 5 */ - font-variation-settings: normal; /* 6 */ - -webkit-tap-highlight-color: transparent; /* 7 */ -} - -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - -body { - margin: 0; /* 1 */ - line-height: inherit; /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; /* 1 */ - color: inherit; /* 2 */ - border-top-width: 1px; /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font-family by default. -2. Use the user's configured `mono` font-feature-settings by default. -3. Use the user's configured `mono` font-variation-settings by default. -4. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ - font-feature-settings: normal; /* 2 */ - font-variation-settings: normal; /* 3 */ - font-size: 1em; /* 4 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; /* 1 */ - border-color: inherit; /* 2 */ - border-collapse: collapse; /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; /* 1 */ - font-feature-settings: inherit; /* 1 */ - font-variation-settings: inherit; /* 1 */ - font-size: 100%; /* 1 */ - font-weight: inherit; /* 1 */ - line-height: inherit; /* 1 */ - letter-spacing: inherit; /* 1 */ - color: inherit; /* 1 */ - margin: 0; /* 2 */ - padding: 0; /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -input:where([type='button']), -input:where([type='reset']), -input:where([type='submit']) { - -webkit-appearance: button; /* 1 */ - background-color: transparent; /* 2 */ - background-image: none; /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type='search'] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Reset default styling for dialogs. -*/ -dialog { - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::-moz-placeholder, textarea::-moz-placeholder { - opacity: 1; /* 1 */ - color: #9ca3af; /* 2 */ -} - -input::placeholder, -textarea::placeholder { - opacity: 1; /* 1 */ - color: #9ca3af; /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; /* 1 */ - vertical-align: middle; /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ -[hidden] { - display: none; -} - -*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} - -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; -} -.hx-sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} -.hx-pointer-events-none { - pointer-events: none; -} -.hx-fixed { - position: fixed; -} -.hx-absolute { - position: absolute; -} -.hx-relative { - position: relative; -} -.hx-sticky { - position: sticky; -} -.hx-inset-0 { - inset: 0px; -} -.hx-inset-x-0 { - left: 0px; - right: 0px; -} -.hx-inset-y-0 { - top: 0px; - bottom: 0px; -} -.hx-bottom-0 { - bottom: 0px; -} -.hx-left-\[24px\] { - left: 24px; -} -.hx-left-\[36px\] { - left: 36px; -} -.hx-right-0 { - right: 0px; -} -.hx-top-0 { - top: 0px; -} -.hx-top-16 { - top: 4rem; -} -.hx-top-8 { - top: 2rem; -} -.hx-top-\[40\%\] { - top: 40%; -} -.hx-top-full { - top: 100%; -} -.hx-z-10 { - z-index: 10; -} -.hx-z-20 { - z-index: 20; -} -.hx-z-\[-1\] { - z-index: -1; -} -.hx-order-last { - order: 9999; -} -.hx-m-\[11px\] { - margin: 11px; -} -.hx-mx-1 { - margin-left: 0.25rem; - margin-right: 0.25rem; -} -.hx-mx-4 { - margin-left: 1rem; - margin-right: 1rem; -} -.hx-mx-auto { - margin-left: auto; - margin-right: auto; -} -.hx-my-1\.5 { - margin-top: 0.375rem; - margin-bottom: 0.375rem; -} -.hx-my-2 { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} -.-hx-mb-0\.5 { - margin-bottom: -0.125rem; -} -.-hx-ml-2 { - margin-left: -0.5rem; -} -.-hx-mr-2 { - margin-right: -0.5rem; -} -.-hx-mt-20 { - margin-top: -5rem; -} -.hx-mb-10 { - margin-bottom: 2.5rem; -} -.hx-mb-12 { - margin-bottom: 3rem; -} -.hx-mb-16 { - margin-bottom: 4rem; -} -.hx-mb-2 { - margin-bottom: 0.5rem; -} -.hx-mb-4 { - margin-bottom: 1rem; -} -.hx-mb-6 { - margin-bottom: 1.5rem; -} -.hx-mb-8 { - margin-bottom: 2rem; -} -.hx-ml-4 { - margin-left: 1rem; -} -.hx-mr-1 { - margin-right: 0.25rem; -} -.hx-mr-2 { - margin-right: 0.5rem; -} -.hx-mt-1 { - margin-top: 0.25rem; -} -.hx-mt-1\.5 { - margin-top: 0.375rem; -} -.hx-mt-12 { - margin-top: 3rem; -} -.hx-mt-16 { - margin-top: 4rem; -} -.hx-mt-2 { - margin-top: 0.5rem; -} -.hx-mt-4 { - margin-top: 1rem; -} -.hx-mt-5 { - margin-top: 1.25rem; -} -.hx-mt-6 { - margin-top: 1.5rem; -} -.hx-mt-8 { - margin-top: 2rem; -} -.hx-line-clamp-3 { - overflow: hidden; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 3; -} -.hx-block { - display: block; -} -.hx-inline-block { - display: inline-block; -} -.hx-inline { - display: inline; -} -.hx-flex { - display: flex; -} -.hx-inline-flex { - display: inline-flex; -} -.hx-grid { - display: grid; -} -.hx-hidden { - display: none; -} -.hx-aspect-auto { - aspect-ratio: auto; -} -.hx-h-0 { - height: 0px; -} -.hx-h-16 { - height: 4rem; -} -.hx-h-2 { - height: 0.5rem; -} -.hx-h-3\.5 { - height: 0.875rem; -} -.hx-h-4 { - height: 1rem; -} -.hx-h-5 { - height: 1.25rem; -} -.hx-h-7 { - height: 1.75rem; -} -.hx-h-\[18px\] { - height: 18px; -} -.hx-h-full { - height: 100%; -} -.hx-max-h-64 { - max-height: 16rem; -} -.hx-max-h-\[calc\(100vh-var\(--navbar-height\)-env\(safe-area-inset-bottom\)\)\] { - max-height: calc(100vh - var(--navbar-height) - env(safe-area-inset-bottom)); -} -.hx-max-h-\[min\(calc\(50vh-11rem-env\(safe-area-inset-bottom\)\)\,400px\)\] { - max-height: min(calc(50vh - 11rem - env(safe-area-inset-bottom)),400px); -} -.hx-min-h-\[100px\] { - min-height: 100px; -} -.hx-min-h-\[calc\(100vh-var\(--navbar-height\)\)\] { - min-height: calc(100vh - var(--navbar-height)); -} -.hx-w-2 { - width: 0.5rem; -} -.hx-w-3\.5 { - width: 0.875rem; -} -.hx-w-4 { - width: 1rem; -} -.hx-w-64 { - width: 16rem; -} -.hx-w-\[110\%\] { - width: 110%; -} -.hx-w-\[180\%\] { - width: 180%; -} -.hx-w-full { - width: 100%; -} -.hx-w-max { - width: -moz-max-content; - width: max-content; -} -.hx-w-screen { - width: 100vw; -} -.hx-min-w-0 { - min-width: 0px; -} -.hx-min-w-\[18px\] { - min-width: 18px; -} -.hx-min-w-\[24px\] { - min-width: 24px; -} -.hx-min-w-full { - min-width: 100%; -} -.hx-max-w-6xl { - max-width: 72rem; -} -.hx-max-w-\[50\%\] { - max-width: 50%; -} -.hx-max-w-\[90rem\] { - max-width: 90rem; -} -.hx-max-w-\[min\(calc\(100vw-2rem\)\,calc\(100\%\+20rem\)\)\] { - max-width: min(calc(100vw - 2rem),calc(100% + 20rem)); -} -.hx-max-w-none { - max-width: none; -} -.hx-max-w-screen-xl { - max-width: 1280px; -} -.hx-shrink-0 { - flex-shrink: 0; -} -.hx-grow { - flex-grow: 1; -} -.hx-origin-center { - transform-origin: center; -} -.hx-cursor-default { - cursor: default; -} -.hx-cursor-pointer { - cursor: pointer; -} -.hx-select-none { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} -.hx-scroll-my-6 { - scroll-margin-top: 1.5rem; - scroll-margin-bottom: 1.5rem; -} -.hx-scroll-py-6 { - scroll-padding-top: 1.5rem; - scroll-padding-bottom: 1.5rem; -} -.hx-list-none { - list-style-type: none; -} -.hx-appearance-none { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} -.hx-grid-cols-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); -} -.hx-flex-col { - flex-direction: column; -} -.hx-flex-wrap { - flex-wrap: wrap; -} -.hx-items-start { - align-items: flex-start; -} -.hx-items-center { - align-items: center; -} -.hx-justify-start { - justify-content: flex-start; -} -.hx-justify-end { - justify-content: flex-end; -} -.hx-justify-center { - justify-content: center; -} -.hx-justify-between { - justify-content: space-between; -} -.hx-justify-items-start { - justify-items: start; -} -.hx-gap-1 { - gap: 0.25rem; -} -.hx-gap-2 { - gap: 0.5rem; -} -.hx-gap-4 { - gap: 1rem; -} -.hx-gap-x-1\.5 { - -moz-column-gap: 0.375rem; - column-gap: 0.375rem; -} -.hx-gap-y-2 { - row-gap: 0.5rem; -} -.hx-overflow-auto { - overflow: auto; -} -.hx-overflow-hidden { - overflow: hidden; -} -.hx-overflow-x-auto { - overflow-x: auto; -} -.hx-overflow-y-auto { - overflow-y: auto; -} -.hx-overflow-x-hidden { - overflow-x: hidden; -} -.hx-overflow-y-hidden { - overflow-y: hidden; -} -.hx-overscroll-contain { - overscroll-behavior: contain; -} -.hx-overscroll-x-contain { - overscroll-behavior-x: contain; -} -.hx-text-ellipsis { - text-overflow: ellipsis; -} -.hx-whitespace-nowrap { - white-space: nowrap; -} -.hx-break-words { - overflow-wrap: break-word; -} -.hx-rounded { - border-radius: 0.25rem; -} -.hx-rounded-3xl { - border-radius: 1.5rem; -} -.hx-rounded-full { - border-radius: 9999px; -} -.hx-rounded-lg { - border-radius: 0.5rem; -} -.hx-rounded-md { - border-radius: 0.375rem; -} -.hx-rounded-sm { - border-radius: 0.125rem; -} -.hx-rounded-xl { - border-radius: 0.75rem; -} -.hx-rounded-t { - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; -} -.hx-border { - border-width: 1px; -} -.hx-border-b { - border-bottom-width: 1px; -} -.hx-border-b-2 { - border-bottom-width: 2px; -} -.hx-border-t { - border-top-width: 1px; -} -.hx-border-amber-200 { - --tw-border-opacity: 1; - border-color: rgb(253 230 138 / var(--tw-border-opacity)); -} -.hx-border-black\/5 { - border-color: rgb(0 0 0 / 0.05); -} -.hx-border-blue-200 { - --tw-border-opacity: 1; - border-color: rgb(191 219 254 / var(--tw-border-opacity)); -} -.hx-border-gray-200 { - --tw-border-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-border-opacity)); -} -.hx-border-gray-500 { - --tw-border-opacity: 1; - border-color: rgb(107 114 128 / var(--tw-border-opacity)); -} -.hx-border-green-200 { - --tw-border-opacity: 1; - border-color: rgb(187 247 208 / var(--tw-border-opacity)); -} -.hx-border-indigo-200 { - --tw-border-opacity: 1; - border-color: rgb(199 210 254 / var(--tw-border-opacity)); -} -.hx-border-orange-100 { - --tw-border-opacity: 1; - border-color: rgb(255 237 213 / var(--tw-border-opacity)); -} -.hx-border-red-200 { - --tw-border-opacity: 1; - border-color: rgb(254 202 202 / var(--tw-border-opacity)); -} -.hx-border-transparent { - border-color: transparent; -} -.hx-border-yellow-100 { - --tw-border-opacity: 1; - border-color: rgb(254 249 195 / var(--tw-border-opacity)); -} -.hx-bg-amber-100 { - --tw-bg-opacity: 1; - background-color: rgb(254 243 199 / var(--tw-bg-opacity)); -} -.hx-bg-black\/80 { - background-color: rgb(0 0 0 / 0.8); -} -.hx-bg-black\/\[\.05\] { - background-color: rgb(0 0 0 / .05); -} -.hx-bg-blue-100 { - --tw-bg-opacity: 1; - background-color: rgb(219 234 254 / var(--tw-bg-opacity)); -} -.hx-bg-gray-100 { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity)); -} -.hx-bg-green-100 { - --tw-bg-opacity: 1; - background-color: rgb(220 252 231 / var(--tw-bg-opacity)); -} -.hx-bg-indigo-100 { - --tw-bg-opacity: 1; - background-color: rgb(224 231 255 / var(--tw-bg-opacity)); -} -.hx-bg-neutral-50 { - --tw-bg-opacity: 1; - background-color: rgb(250 250 250 / var(--tw-bg-opacity)); -} -.hx-bg-orange-50 { - --tw-bg-opacity: 1; - background-color: rgb(255 247 237 / var(--tw-bg-opacity)); -} -.hx-bg-primary-100 { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / var(--tw-bg-opacity)); -} -.hx-bg-primary-400 { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 16) / var(--tw-bg-opacity)); -} -.hx-bg-primary-600 { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-bg-opacity)); -} -.hx-bg-primary-700\/5 { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); -} -.hx-bg-red-100 { - --tw-bg-opacity: 1; - background-color: rgb(254 226 226 / var(--tw-bg-opacity)); -} -.hx-bg-transparent { - background-color: transparent; -} -.hx-bg-white { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); -} -.hx-bg-yellow-50 { - --tw-bg-opacity: 1; - background-color: rgb(254 252 232 / var(--tw-bg-opacity)); -} -.hx-bg-gradient-to-r { - background-image: linear-gradient(to right, var(--tw-gradient-stops)); -} -.hx-from-gray-900 { - --tw-gradient-from: #111827 var(--tw-gradient-from-position); - --tw-gradient-to: rgb(17 24 39 / 0) var(--tw-gradient-to-position); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} -.hx-to-gray-600 { - --tw-gradient-to: #4b5563 var(--tw-gradient-to-position); -} -.hx-bg-clip-text { - -webkit-background-clip: text; - background-clip: text; -} -.hx-p-0\.5 { - padding: 0.125rem; -} -.hx-p-1 { - padding: 0.25rem; -} -.hx-p-1\.5 { - padding: 0.375rem; -} -.hx-p-2 { - padding: 0.5rem; -} -.hx-p-4 { - padding: 1rem; -} -.hx-p-6 { - padding: 1.5rem; -} -.hx-px-1\.5 { - padding-left: 0.375rem; - padding-right: 0.375rem; -} -.hx-px-2 { - padding-left: 0.5rem; - padding-right: 0.5rem; -} -.hx-px-2\.5 { - padding-left: 0.625rem; - padding-right: 0.625rem; -} -.hx-px-3 { - padding-left: 0.75rem; - padding-right: 0.75rem; -} -.hx-px-4 { - padding-left: 1rem; - padding-right: 1rem; -} -.hx-px-6 { - padding-left: 1.5rem; - padding-right: 1.5rem; -} -.hx-py-1 { - padding-top: 0.25rem; - padding-bottom: 0.25rem; -} -.hx-py-1\.5 { - padding-top: 0.375rem; - padding-bottom: 0.375rem; -} -.hx-py-12 { - padding-top: 3rem; - padding-bottom: 3rem; -} -.hx-py-2 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} -.hx-py-2\.5 { - padding-top: 0.625rem; - padding-bottom: 0.625rem; -} -.hx-py-3 { - padding-top: 0.75rem; - padding-bottom: 0.75rem; -} -.hx-py-4 { - padding-top: 1rem; - padding-bottom: 1rem; -} -.hx-pb-8 { - padding-bottom: 2rem; -} -.hx-pb-\[env\(safe-area-inset-bottom\)\] { - padding-bottom: env(safe-area-inset-bottom); -} -.hx-pb-px { - padding-bottom: 1px; -} -.hx-pl-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\] { - padding-left: max(env(safe-area-inset-left),1.5rem); -} -.hx-pr-2 { - padding-right: 0.5rem; -} -.hx-pr-4 { - padding-right: 1rem; -} -.hx-pr-\[calc\(env\(safe-area-inset-right\)-1\.5rem\)\] { - padding-right: calc(env(safe-area-inset-right) - 1.5rem); -} -.hx-pr-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\] { - padding-right: max(env(safe-area-inset-left),1.5rem); -} -.hx-pr-\[max\(env\(safe-area-inset-right\)\,1\.5rem\)\] { - padding-right: max(env(safe-area-inset-right),1.5rem); -} -.hx-pt-4 { - padding-top: 1rem; -} -.hx-pt-6 { - padding-top: 1.5rem; -} -.hx-pt-8 { - padding-top: 2rem; -} -.hx-text-left { - text-align: left; -} -.hx-text-center { - text-align: center; -} -.hx-align-middle { - vertical-align: middle; -} -.hx-align-text-bottom { - vertical-align: text-bottom; -} -.hx-align-\[-2\.5px\] { - vertical-align: -2.5px; -} -.hx-font-mono { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; -} -.hx-text-2xl { - font-size: 1.5rem; -} -.hx-text-4xl { - font-size: 2.25rem; -} -.hx-text-\[\.65rem\] { - font-size: .65rem; -} -.hx-text-\[10px\] { - font-size: 10px; -} -.hx-text-base { - font-size: 1rem; -} -.hx-text-lg { - font-size: 1.125rem; -} -.hx-text-sm { - font-size: .875rem; -} -.hx-text-xl { - font-size: 1.25rem; -} -.hx-text-xs { - font-size: .75rem; -} -.hx-font-bold { - font-weight: 700; -} -.hx-font-extrabold { - font-weight: 800; -} -.hx-font-medium { - font-weight: 500; -} -.hx-font-normal { - font-weight: 400; -} -.hx-font-semibold { - font-weight: 600; -} -.hx-capitalize { - text-transform: capitalize; -} -.hx-leading-5 { - line-height: 1.25rem; -} -.hx-leading-6 { - line-height: 1.5rem; -} -.hx-leading-7 { - line-height: 1.75rem; -} -.hx-leading-none { - line-height: 1; -} -.hx-leading-tight { - line-height: 1.25; -} -.hx-tracking-tight { - letter-spacing: -0.015em; -} -.hx-text-\[color\:hsl\(var\(--primary-hue\)\,100\%\,50\%\)\] { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) 100% 50% / var(--tw-text-opacity)); -} -.hx-text-amber-900 { - --tw-text-opacity: 1; - color: rgb(120 53 15 / var(--tw-text-opacity)); -} -.hx-text-blue-900 { - --tw-text-opacity: 1; - color: rgb(30 58 138 / var(--tw-text-opacity)); -} -.hx-text-current { - color: currentColor; -} -.hx-text-gray-100 { - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); -} -.hx-text-gray-500 { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} -.hx-text-gray-600 { - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity)); -} -.hx-text-gray-700 { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); -} -.hx-text-gray-800 { - --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity)); -} -.hx-text-gray-900 { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); -} -.hx-text-green-900 { - --tw-text-opacity: 1; - color: rgb(20 83 45 / var(--tw-text-opacity)); -} -.hx-text-indigo-900 { - --tw-text-opacity: 1; - color: rgb(49 46 129 / var(--tw-text-opacity)); -} -.hx-text-orange-800 { - --tw-text-opacity: 1; - color: rgb(154 52 18 / var(--tw-text-opacity)); -} -.hx-text-primary-800 { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / var(--tw-text-opacity)); -} -.hx-text-red-900 { - --tw-text-opacity: 1; - color: rgb(127 29 29 / var(--tw-text-opacity)); -} -.hx-text-slate-900 { - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -.hx-text-transparent { - color: transparent; -} -.hx-text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} -.hx-text-yellow-900 { - --tw-text-opacity: 1; - color: rgb(113 63 18 / var(--tw-text-opacity)); -} -.hx-underline { - text-decoration-line: underline; -} -.hx-no-underline { - text-decoration-line: none; -} -.hx-decoration-from-font { - text-decoration-thickness: from-font; -} -.hx-underline-offset-2 { - text-underline-offset: 2px; -} -.hx-opacity-0 { - opacity: 0; -} -.hx-opacity-50 { - opacity: 0.5; -} -.hx-opacity-80 { - opacity: 0.8; -} -.hx-shadow { - --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-\[0_-12px_16px_\#fff\] { - --tw-shadow: 0 -12px 16px #fff; - --tw-shadow-colored: 0 -12px 16px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-\[0_-12px_16px_white\] { - --tw-shadow: 0 -12px 16px white; - --tw-shadow-colored: 0 -12px 16px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-\[0_2px_4px_rgba\(0\,0\,0\,\.02\)\,0_1px_0_rgba\(0\,0\,0\,\.06\)\] { - --tw-shadow: 0 2px 4px rgba(0,0,0,.02),0 1px 0 rgba(0,0,0,.06); - --tw-shadow-colored: 0 2px 4px var(--tw-shadow-color), 0 1px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-lg { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-sm { - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-xl { - --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hx-shadow-gray-100 { - --tw-shadow-color: #f3f4f6; - --tw-shadow: var(--tw-shadow-colored); -} -.hx-ring-1 { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} -.hx-ring-black\/5 { - --tw-ring-color: rgb(0 0 0 / 0.05); -} -.hx-transition { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.hx-transition-all { - transition-property: all; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.hx-transition-colors { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.hx-transition-opacity { - transition-property: opacity; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.hx-transition-transform { - transition-property: transform; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.hx-duration-200 { - transition-duration: 200ms; -} -.hx-duration-75 { - transition-duration: 75ms; -} -.hx-ease-in { - transition-timing-function: cubic-bezier(0.4, 0, 1, 1); -} -.\[-webkit-tap-highlight-color\:transparent\] { - -webkit-tap-highlight-color: transparent; -} -.\[-webkit-touch-callout\:none\] { - -webkit-touch-callout: none; -} -.\[counter-reset\:step\] { - counter-reset: step; -} -.\[hyphens\:auto\] { - -webkit-hyphens: auto; - hyphens: auto; -} -.\[transition\:background-color_1\.5s_ease\] { - transition: background-color 1.5s ease; -} -.\[word-break\:break-word\] { - word-break: break-word; -} -.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 0.5rem; - font-size: 2.25rem; - font-weight: 700; - letter-spacing: -0.015em; - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 2.5rem; - border-bottom-width: 1px; - border-color: rgb(229 229 229 / 0.7); - padding-bottom: 0.25rem; - font-size: 1.875rem; - font-weight: 600; - letter-spacing: -0.015em; - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -@media (prefers-contrast: more) { - - .content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)) { - --tw-border-opacity: 1; - border-color: rgb(163 163 163 / var(--tw-border-opacity)); - } -} -.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.1); - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -@media (prefers-contrast: more) { - - .content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(163 163 163 / var(--tw-border-opacity)); - } -} -.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 2rem; - font-size: 1.5rem; - font-weight: 600; - letter-spacing: -0.015em; - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 2rem; - font-size: 1.25rem; - font-weight: 600; - letter-spacing: -0.015em; - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 2rem; - font-size: 1.125rem; - font-weight: 600; - letter-spacing: -0.015em; - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 2rem; - font-size: 1rem; - font-weight: 600; - letter-spacing: -0.015em; - --tw-text-opacity: 1; - color: rgb(15 23 42 / var(--tw-text-opacity)); -} -.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 1.5rem; - line-height: 1.75rem; -} -.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { - margin-top: 0px; -} -.content :where(a):not(:where([class~=not-prose],[class~=not-prose] *)) { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); - text-decoration-line: underline; - text-decoration-thickness: from-font; - text-underline-position: from-font; -} -.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 1.5rem; - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); - font-style: italic; - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); -} -.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { - margin-top: 0px; -} -.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(55 65 81 / var(--tw-border-opacity)); - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="ltr"], [dir="ltr"] *) { - border-left-width: 2px; - padding-left: 1.5rem; -} -.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="rtl"], [dir="rtl"] *) { - border-right-width: 2px; - padding-right: 1.5rem; -} -.content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { - margin-bottom: 1rem; - overflow-x: auto; - border-radius: 0.75rem; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); - padding-top: 1rem; - padding-bottom: 1rem; - font-size: .9em; - font-weight: 500; - -webkit-font-smoothing: auto; - -moz-osx-font-smoothing: auto; -} -@media (prefers-contrast: more) { - - .content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { - border-width: 1px; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 24) / 0.2); - --tw-contrast: contrast(1.5); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); - } -} -.content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); -} -@media (prefers-contrast: more) { - - .content :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.4); - } -} -.content :where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)) { - overflow-wrap: break-word; - border-radius: 0.375rem; - border-width: 1px; - border-color: rgb(0 0 0 / var(--tw-border-opacity)); - --tw-border-opacity: 0.04; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); - --tw-bg-opacity: 0.03; - padding-top: 0.125rem; - padding-bottom: 0.125rem; - padding-left: .25em; - padding-right: .25em; - font-size: .9em; -} -.content :where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - border-color: rgb(255 255 255 / 0.1); - background-color: rgb(255 255 255 / 0.1); -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) { - margin-top: 1.5rem; - display: block; - overflow-x: auto; - padding: 0px; -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)):first-child { - margin-top: 0px; -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr { - margin: 0px; - border-top-width: 1px; - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); - padding: 0px; -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr:nth-child(even) { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity)); -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) tr:is(html[class~="dark"] *):nth-child(even) { - background-color: rgb(75 85 99 / 0.2); -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) th { - margin: 0px; - border-width: 1px; - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - font-weight: 600; -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) th:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) td { - margin: 0px; - border-width: 1px; - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); - padding-left: 1rem; - padding-right: 1rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} -.content :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) td:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); -} -.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 1.5rem; - list-style-type: decimal; -} -.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { - margin-top: 0px; -} -.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="ltr"], [dir="ltr"] *) { - margin-left: 1.5rem; -} -.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="rtl"], [dir="rtl"] *) { - margin-right: 1.5rem; -} -.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) li { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} -.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 1.5rem; - list-style-type: disc; -} -.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):first-child { - margin-top: 0px; -} -.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="ltr"], [dir="ltr"] *) { - margin-left: 1.5rem; -} -.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir="rtl"], [dir="rtl"] *) { - margin-right: 1.5rem; -} -.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) li { - margin-top: 0.5rem; - margin-bottom: 0.5rem; -} -/* This CSS rule targets the first nested unordered (ul) or ordered (ol) list - inside the list item (li) of any parent ul or ol. - The rule sets the top margin of the selected list to zero. */ -.content :where(ul, ol) > li > :where(ul, ol):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-top: 0px; -} -.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)) { - overflow-wrap: break-word; - border-radius: 0.375rem; - border-width: 1px; - border-color: rgb(0 0 0 / var(--tw-border-opacity)); - --tw-border-opacity: 0.04; - background-color: rgb(0 0 0 / var(--tw-bg-opacity)); - --tw-bg-opacity: 0.03; - padding-top: 0.125rem; - padding-bottom: 0.125rem; - padding-left: .25em; - padding-right: .25em; - font-size: .9em; -} -.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - border-color: rgb(255 255 255 / 0.1); - background-color: rgb(255 255 255 / 0.1); -} -.content :where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { - border-radius: 0px; - background-color: transparent; -} -.content :where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)):is(html[class~="dark"] *) { - background-color: transparent; -} -.content :where(img):not(:where([class~=not-prose],[class~=not-prose] *)) { - margin-left: auto; - margin-right: auto; - margin-top: 1rem; - margin-bottom: 1rem; - border-radius: 0.375rem; -} -.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption { - margin-top: 0.5rem; - display: block; - text-align: center; - font-size: .875rem; - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} -.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -/* Definition list */ -.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dt { - margin-top: 1.5rem; - font-weight: 600; -} -.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dd { - margin-top: 0.5rem; - margin-bottom: 0.5rem; - padding-inline-start: 1.5rem; -} -.content .footnotes { - margin-top: 3rem; - font-size: .875rem; -} -.subheading-anchor { - opacity: 0; - transition-property: opacity; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.subheading-anchor:where([dir="ltr"], [dir="ltr"] *) { - margin-left: 0.25rem; -} -.subheading-anchor:where([dir="rtl"], [dir="rtl"] *) { - margin-right: 0.25rem; -} -span:target + .subheading-anchor, - :hover > .subheading-anchor, - .subheading-anchor:focus { - opacity: 1; -} -span + .subheading-anchor, - :hover > .subheading-anchor { - text-decoration-line: none !important; -} -.subheading-anchor:after { - padding-left: 0.25rem; - padding-right: 0.25rem; - --tw-content: '#'; - content: var(--tw-content); - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} -.subheading-anchor:is(html[class~="dark"] *):after { - --tw-text-opacity: 1; - color: rgb(64 64 64 / var(--tw-text-opacity)); -} -span:target + .subheading-anchor:after { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -span:target + .subheading-anchor:is(html[class~="dark"] *):after { - --tw-text-opacity: 1; - color: rgb(115 115 115 / var(--tw-text-opacity)); -} -article details > summary::-webkit-details-marker { - display: none; -} -article details > summary::before { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='hx-h-5 hx-w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); - height: 1.2em; - width: 1.2em; - vertical-align: -4px; - padding: 0 0.6em; - } -:lang(fa) ol { - list-style-type: persian; -} -/* Code syntax highlight */ -/* Light theme for syntax highlight */ -/* Generated using `hugo gen chromastyles --style=github` */ -.highlight { - /* Background .bg { background-color: #ffffff; } */ - /* PreWrapper .chroma { background-color: #ffffff; } */ - /* Other .chroma .x { } */ - /* CodeLine .chroma .cl { } */ - /* LineTableTD .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } */ - /* LineTable .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } */ - /* LineHighlight .chroma .hl { background-color: #ffffcc } */ - /* LineNumbersTable .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } */ - /* LineNumbers .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } */ - /* Name .chroma .n { } */ - /* NameFunctionMagic .chroma .fm { } */ - /* NameOther .chroma .nx { } */ - /* NameProperty .chroma .py { } */ - /* NameVariableMagic .chroma .vm { } */ - /* Literal .chroma .l { } */ - /* LiteralDate .chroma .ld { } */ - /* Punctuation .chroma .p { } */ - /* Generic .chroma .g { } */ -} -/* Error */ -.highlight .chroma .err { color: #a61717; background-color: #e3d2d2 } -/* LineLink */ -.highlight .chroma .lnlinks { outline: none; text-decoration: none; color: inherit } -/* Line */ -.highlight .chroma .line { display: flex; } -/* Keyword */ -.highlight .chroma .k { color: #000000; font-weight: bold } -/* KeywordConstant */ -.highlight .chroma .kc { color: #000000; font-weight: bold } -/* KeywordDeclaration */ -.highlight .chroma .kd { color: #000000; font-weight: bold } -/* KeywordNamespace */ -.highlight .chroma .kn { color: #000000; font-weight: bold } -/* KeywordPseudo */ -.highlight .chroma .kp { color: #000000; font-weight: bold } -/* KeywordReserved */ -.highlight .chroma .kr { color: #000000; font-weight: bold } -/* KeywordType */ -.highlight .chroma .kt { color: #445588; font-weight: bold } -/* NameAttribute */ -.highlight .chroma .na { color: #008080 } -/* NameBuiltin */ -.highlight .chroma .nb { color: #0086b3 } -/* NameBuiltinPseudo */ -.highlight .chroma .bp { color: #999999 } -/* NameClass */ -.highlight .chroma .nc { color: #445588; font-weight: bold } -/* NameConstant */ -.highlight .chroma .no { color: #008080 } -/* NameDecorator */ -.highlight .chroma .nd { color: #3c5d5d; font-weight: bold } -/* NameEntity */ -.highlight .chroma .ni { color: #800080 } -/* NameException */ -.highlight .chroma .ne { color: #990000; font-weight: bold } -/* NameFunction */ -.highlight .chroma .nf { color: #990000; font-weight: bold } -/* NameLabel */ -.highlight .chroma .nl { color: #990000; font-weight: bold } -/* NameNamespace */ -.highlight .chroma .nn { color: #555555 } -/* NameTag */ -.highlight .chroma .nt { color: #000080 } -/* NameVariable */ -.highlight .chroma .nv { color: #008080 } -/* NameVariableClass */ -.highlight .chroma .vc { color: #008080 } -/* NameVariableGlobal */ -.highlight .chroma .vg { color: #008080 } -/* NameVariableInstance */ -.highlight .chroma .vi { color: #008080 } -/* LiteralString */ -.highlight .chroma .s { color: #dd1144 } -/* LiteralStringAffix */ -.highlight .chroma .sa { color: #dd1144 } -/* LiteralStringBacktick */ -.highlight .chroma .sb { color: #dd1144 } -/* LiteralStringChar */ -.highlight .chroma .sc { color: #dd1144 } -/* LiteralStringDelimiter */ -.highlight .chroma .dl { color: #dd1144 } -/* LiteralStringDoc */ -.highlight .chroma .sd { color: #dd1144 } -/* LiteralStringDouble */ -.highlight .chroma .s2 { color: #dd1144 } -/* LiteralStringEscape */ -.highlight .chroma .se { color: #dd1144 } -/* LiteralStringHeredoc */ -.highlight .chroma .sh { color: #dd1144 } -/* LiteralStringInterpol */ -.highlight .chroma .si { color: #dd1144 } -/* LiteralStringOther */ -.highlight .chroma .sx { color: #dd1144 } -/* LiteralStringRegex */ -.highlight .chroma .sr { color: #009926 } -/* LiteralStringSingle */ -.highlight .chroma .s1 { color: #dd1144 } -/* LiteralStringSymbol */ -.highlight .chroma .ss { color: #990073 } -/* LiteralNumber */ -.highlight .chroma .m { color: #009999 } -/* LiteralNumberBin */ -.highlight .chroma .mb { color: #009999 } -/* LiteralNumberFloat */ -.highlight .chroma .mf { color: #009999 } -/* LiteralNumberHex */ -.highlight .chroma .mh { color: #009999 } -/* LiteralNumberInteger */ -.highlight .chroma .mi { color: #009999 } -/* LiteralNumberIntegerLong */ -.highlight .chroma .il { color: #009999 } -/* LiteralNumberOct */ -.highlight .chroma .mo { color: #009999 } -/* Operator */ -.highlight .chroma .o { color: #000000; font-weight: bold } -/* OperatorWord */ -.highlight .chroma .ow { color: #000000; font-weight: bold } -/* Comment */ -.highlight .chroma .c { color: #999988; font-style: italic } -/* CommentHashbang */ -.highlight .chroma .ch { color: #999988; font-style: italic } -/* CommentMultiline */ -.highlight .chroma .cm { color: #999988; font-style: italic } -/* CommentSingle */ -.highlight .chroma .c1 { color: #999988; font-style: italic } -/* CommentSpecial */ -.highlight .chroma .cs { color: #999999; font-weight: bold; font-style: italic } -/* CommentPreproc */ -.highlight .chroma .cp { color: #999999; font-weight: bold; font-style: italic } -/* CommentPreprocFile */ -.highlight .chroma .cpf { color: #999999; font-weight: bold; font-style: italic } -/* GenericDeleted */ -.highlight .chroma .gd { color: #000000; background-color: #ffdddd } -/* GenericEmph */ -.highlight .chroma .ge { color: #000000; font-style: italic } -/* GenericError */ -.highlight .chroma .gr { color: #aa0000 } -/* GenericHeading */ -.highlight .chroma .gh { color: #999999 } -/* GenericInserted */ -.highlight .chroma .gi { color: #000000; background-color: #ddffdd } -/* GenericOutput */ -.highlight .chroma .go { color: #888888 } -/* GenericPrompt */ -.highlight .chroma .gp { color: #555555 } -/* GenericStrong */ -.highlight .chroma .gs { font-weight: bold } -/* GenericSubheading */ -.highlight .chroma .gu { color: #aaaaaa } -/* GenericTraceback */ -.highlight .chroma .gt { color: #aa0000 } -/* GenericUnderline */ -.highlight .chroma .gl { text-decoration: underline } -/* TextWhitespace */ -.highlight .chroma .w { color: #bbbbbb } -.dark .highlight { - /* Background .bg { color: #c9d1d9; background-color: #0d1117; } - /* PreWrapper .chroma { color: #c9d1d9; background-color: #0d1117; } */ - /* LineTableTD .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } */ - /* LineTable .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } */ - /* LineHighlight .chroma .hl { background-color: #ffffcc } */ - /* LineNumbersTable .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #64686c } */ - /* LineNumbers .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #6e7681 } */ -} -/* Other */ -.dark .highlight .chroma .x { } -/* Error */ -.dark .highlight .chroma .err { color: #f85149 } -/* CodeLine */ -.dark .highlight .chroma .cl { } -/* LineLink */ -.dark .highlight .chroma .lnlinks { outline: none; text-decoration: none; color: inherit } -/* Line */ -.dark .highlight .chroma .line { display: flex; } -/* Keyword */ -.dark .highlight .chroma .k { color: #ff7b72 } -/* KeywordConstant */ -.dark .highlight .chroma .kc { color: #79c0ff } -/* KeywordDeclaration */ -.dark .highlight .chroma .kd { color: #ff7b72 } -/* KeywordNamespace */ -.dark .highlight .chroma .kn { color: #ff7b72 } -/* KeywordPseudo */ -.dark .highlight .chroma .kp { color: #79c0ff } -/* KeywordReserved */ -.dark .highlight .chroma .kr { color: #ff7b72 } -/* KeywordType */ -.dark .highlight .chroma .kt { color: #ff7b72 } -/* Name */ -.dark .highlight .chroma .n { } -/* NameAttribute */ -.dark .highlight .chroma .na { } -/* NameBuiltin */ -.dark .highlight .chroma .nb { } -/* NameBuiltinPseudo */ -.dark .highlight .chroma .bp { } -/* NameClass */ -.dark .highlight .chroma .nc { color: #f0883e; font-weight: bold } -/* NameConstant */ -.dark .highlight .chroma .no { color: #79c0ff; font-weight: bold } -/* NameDecorator */ -.dark .highlight .chroma .nd { color: #d2a8ff; font-weight: bold } -/* NameEntity */ -.dark .highlight .chroma .ni { color: #ffa657 } -/* NameException */ -.dark .highlight .chroma .ne { color: #f0883e; font-weight: bold } -/* NameFunction */ -.dark .highlight .chroma .nf { color: #d2a8ff; font-weight: bold } -/* NameFunctionMagic */ -.dark .highlight .chroma .fm { } -/* NameLabel */ -.dark .highlight .chroma .nl { color: #79c0ff; font-weight: bold } -/* NameNamespace */ -.dark .highlight .chroma .nn { color: #ff7b72 } -/* NameOther */ -.dark .highlight .chroma .nx { } -/* NameProperty */ -.dark .highlight .chroma .py { color: #79c0ff } -/* NameTag */ -.dark .highlight .chroma .nt { color: #7ee787 } -/* NameVariable */ -.dark .highlight .chroma .nv { color: #79c0ff } -/* NameVariableClass */ -.dark .highlight .chroma .vc { } -/* NameVariableGlobal */ -.dark .highlight .chroma .vg { } -/* NameVariableInstance */ -.dark .highlight .chroma .vi { } -/* NameVariableMagic */ -.dark .highlight .chroma .vm { } -/* Literal */ -.dark .highlight .chroma .l { color: #a5d6ff } -/* LiteralDate */ -.dark .highlight .chroma .ld { color: #79c0ff } -/* LiteralString */ -.dark .highlight .chroma .s { color: #a5d6ff } -/* LiteralStringAffix */ -.dark .highlight .chroma .sa { color: #79c0ff } -/* LiteralStringBacktick */ -.dark .highlight .chroma .sb { color: #a5d6ff } -/* LiteralStringChar */ -.dark .highlight .chroma .sc { color: #a5d6ff } -/* LiteralStringDelimiter */ -.dark .highlight .chroma .dl { color: #79c0ff } -/* LiteralStringDoc */ -.dark .highlight .chroma .sd { color: #a5d6ff } -/* LiteralStringDouble */ -.dark .highlight .chroma .s2 { color: #a5d6ff } -/* LiteralStringEscape */ -.dark .highlight .chroma .se { color: #79c0ff } -/* LiteralStringHeredoc */ -.dark .highlight .chroma .sh { color: #79c0ff } -/* LiteralStringInterpol */ -.dark .highlight .chroma .si { color: #a5d6ff } -/* LiteralStringOther */ -.dark .highlight .chroma .sx { color: #a5d6ff } -/* LiteralStringRegex */ -.dark .highlight .chroma .sr { color: #79c0ff } -/* LiteralStringSingle */ -.dark .highlight .chroma .s1 { color: #a5d6ff } -/* LiteralStringSymbol */ -.dark .highlight .chroma .ss { color: #a5d6ff } -/* LiteralNumber */ -.dark .highlight .chroma .m { color: #a5d6ff } -/* LiteralNumberBin */ -.dark .highlight .chroma .mb { color: #a5d6ff } -/* LiteralNumberFloat */ -.dark .highlight .chroma .mf { color: #a5d6ff } -/* LiteralNumberHex */ -.dark .highlight .chroma .mh { color: #a5d6ff } -/* LiteralNumberInteger */ -.dark .highlight .chroma .mi { color: #a5d6ff } -/* LiteralNumberIntegerLong */ -.dark .highlight .chroma .il { color: #a5d6ff } -/* LiteralNumberOct */ -.dark .highlight .chroma .mo { color: #a5d6ff } -/* Operator */ -.dark .highlight .chroma .o { color: #ff7b72; font-weight: bold } -/* OperatorWord */ -.dark .highlight .chroma .ow { color: #ff7b72; font-weight: bold } -/* Punctuation */ -.dark .highlight .chroma .p { } -/* Comment */ -.dark .highlight .chroma .c { color: #8b949e; font-style: italic } -/* CommentHashbang */ -.dark .highlight .chroma .ch { color: #8b949e; font-style: italic } -/* CommentMultiline */ -.dark .highlight .chroma .cm { color: #8b949e; font-style: italic } -/* CommentSingle */ -.dark .highlight .chroma .c1 { color: #8b949e; font-style: italic } -/* CommentSpecial */ -.dark .highlight .chroma .cs { color: #8b949e; font-weight: bold; font-style: italic } -/* CommentPreproc */ -.dark .highlight .chroma .cp { color: #8b949e; font-weight: bold; font-style: italic } -/* CommentPreprocFile */ -.dark .highlight .chroma .cpf { color: #8b949e; font-weight: bold; font-style: italic } -/* Generic */ -.dark .highlight .chroma .g { } -/* GenericDeleted */ -.dark .highlight .chroma .gd { color: #ffa198; background-color: #490202 } -/* GenericEmph */ -.dark .highlight .chroma .ge { color: inherit; font-style: italic } -/* GenericError */ -.dark .highlight .chroma .gr { color: #ffa198 } -/* GenericHeading */ -.dark .highlight .chroma .gh { color: #79c0ff; font-weight: bold } -/* GenericInserted */ -.dark .highlight .chroma .gi { color: #56d364; background-color: #0f5323 } -/* GenericOutput */ -.dark .highlight .chroma .go { color: #8b949e } -/* GenericPrompt */ -.dark .highlight .chroma .gp { color: #8b949e } -/* GenericStrong */ -.dark .highlight .chroma .gs { font-weight: bold } -/* GenericSubheading */ -.dark .highlight .chroma .gu { color: #79c0ff } -/* GenericTraceback */ -.dark .highlight .chroma .gt { color: #ff7b72 } -/* GenericUnderline */ -.dark .highlight .chroma .gl { text-decoration: underline } -/* TextWhitespace */ -.dark .highlight .chroma .w { color: #6e7681 } -.hextra-code-block { - font-size: .9em; - line-height: 1.25rem; -} -.hextra-code-block pre { - overflow-x: auto; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); - font-size: .9em; - font-weight: 500; - -webkit-font-smoothing: auto; - -moz-osx-font-smoothing: auto; -} -@media (prefers-contrast: more) { - - .hextra-code-block pre { - border-width: 1px; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 24) / 0.2); - --tw-contrast: contrast(1.5); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); - } -} -.hextra-code-block pre:is(html[class~="dark"] *) { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); -} -@media (prefers-contrast: more) { - - .hextra-code-block pre:is(html[class~="dark"] *) { - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.4); - } -} -.hextra-code-block .filename { - position: absolute; - top: 0px; - z-index: 1; - width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - border-top-left-radius: 0.75rem; - border-top-right-radius: 0.75rem; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / 0.05); - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - padding-right: 1rem; - font-size: .75rem; - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); -} -.hextra-code-block .filename:is(html[class~="dark"] *) { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); - --tw-text-opacity: 1; - color: rgb(229 231 235 / var(--tw-text-opacity)); -} -.hextra-code-block .filename + pre:not(.lntable pre) { - /* Override padding for code blocks with filename but no highlight */ - padding-top: 3rem; - } -.hextra-code-block pre:not(.lntable pre) { - margin-bottom: 1rem; - border-radius: 0.75rem; - padding-left: 1rem; - padding-right: 1rem; - padding-top: 1rem; - padding-bottom: 1rem; -} -.hextra-code-block div:nth-of-type(2) pre { - padding-top: 3rem; - padding-bottom: 1rem; -} -.chroma .lntable { - margin: 0px; - display: block; - width: auto; - overflow: auto; - border-radius: 0.75rem; -} -.chroma .lntable pre { - padding-top: 1rem; - padding-bottom: 1rem; -} -.chroma .ln, - .chroma .lnt:not(.hl > .lnt), - .chroma .hl:not(.line) { - min-width: 2.6rem; - padding-left: 1rem; - padding-right: 1rem; - --tw-text-opacity: 1; - color: rgb(82 82 82 / var(--tw-text-opacity)); -} -.chroma .ln:is(html[class~="dark"] *), - .chroma .lnt:not(.hl > .lnt):is(html[class~="dark"] *), - .chroma .hl:not(.line):is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(212 212 212 / var(--tw-text-opacity)); -} -.chroma .lntd { - padding: 0px; - vertical-align: top; -} -.chroma .lntd:last-of-type { - width: 100%; -} -/* LineHighlight */ -.chroma .hl { - display: block; - width: 100%; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / 0.1); -} -.hextra-cards { - grid-template-columns: repeat(auto-fill, minmax(max(250px, calc((100% - 1rem * 2) / var(--hextra-cards-grid-cols))), 1fr)); -} -.hextra-card { - position: relative; -} -.hextra-card img { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} -.hextra-card:hover svg { - color: currentColor; -} -.hextra-card svg { - width: 1.5rem; - color: #00000033; - transition: color 0.3s ease; -} -.hextra-card p { - margin-top: 0.5rem; - position: relative; -} -.dark .hextra-card svg { - color: #ffffff66; -} -.dark .hextra-card:hover svg { - color: currentColor; -} -.hextra-card-tag { - position: absolute; - top: 5px; - right: 5px; - z-index: 10; -} -.steps h3 { - counter-increment: step; -} -.steps h3:before { - position: absolute; - height: 33px; - width: 33px; - border-width: 4px; - --tw-border-opacity: 1; - border-color: rgb(255 255 255 / var(--tw-border-opacity)); - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity)); -} -.steps h3:is(html[class~="dark"] *):before { - --tw-border-opacity: 1; - border-color: rgb(17 17 17 / var(--tw-border-opacity)); - --tw-bg-opacity: 1; - background-color: rgb(38 38 38 / var(--tw-bg-opacity)); -} -.steps h3:before { - border-radius: 9999px; - text-align: center; - text-indent: -1px; - font-size: 1rem; - font-weight: 400; - --tw-text-opacity: 1; - color: rgb(163 163 163 / var(--tw-text-opacity)); - margin-top: 3px; -} -.steps h3:where([dir="ltr"], [dir="ltr"] *):before { - margin-left: -41px; -} -.steps h3:where([dir="rtl"], [dir="rtl"] *):before { - margin-right: -44px; -} -.steps h3:before { - content: counter(step); - } -:lang(fa) .steps h3:before { - content: counter(step, persian); - } -.search-wrapper li { - margin-left: 0.625rem; - margin-right: 0.625rem; - overflow-wrap: break-word; - border-radius: 0.375rem; - --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity)); -} -@media (prefers-contrast: more) { - - .search-wrapper li { - border-width: 1px; - border-color: transparent; - } -} -.search-wrapper li:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} -.search-wrapper li a { - display: block; - scroll-margin: 3rem; - padding-left: 0.625rem; - padding-right: 0.625rem; - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} -.search-wrapper li .title { - font-size: 1rem; - font-weight: 600; - line-height: 1.25rem; -} -.search-wrapper li .active { - border-radius: 0.375rem; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / 0.1); -} -@media (prefers-contrast: more) { - - .search-wrapper li .active { - --tw-border-opacity: 1; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); - } -} -.search-wrapper .no-result { - display: block; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - padding: 2rem; - text-align: center; - font-size: .875rem; - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -.search-wrapper .prefix { - margin-left: 0.625rem; - margin-right: 0.625rem; - margin-bottom: 0.5rem; - margin-top: 1.5rem; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - border-bottom-width: 1px; - border-color: rgb(0 0 0 / 0.1); - padding-left: 0.625rem; - padding-right: 0.625rem; - padding-bottom: 0.375rem; - font-size: .75rem; - font-weight: 600; - text-transform: uppercase; - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} -.search-wrapper .prefix:first-child { - margin-top: 0px; -} -@media (prefers-contrast: more) { - - .search-wrapper .prefix { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); - } -} -.search-wrapper .prefix:is(html[class~="dark"] *) { - border-color: rgb(255 255 255 / 0.2); - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} -@media (prefers-contrast: more) { - - .search-wrapper .prefix:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(249 250 251 / var(--tw-border-opacity)); - --tw-text-opacity: 1; - color: rgb(249 250 251 / var(--tw-text-opacity)); - } -} -.search-wrapper .excerpt { - margin-top: 0.25rem; - overflow: hidden; - text-overflow: ellipsis; - font-size: .875rem; - line-height: 1.35rem; - --tw-text-opacity: 1; - color: rgb(75 85 99 / var(--tw-text-opacity)); -} -.search-wrapper .excerpt:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -@media (prefers-contrast: more) { - - .search-wrapper .excerpt:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(249 250 251 / var(--tw-text-opacity)); - } -} -.search-wrapper .excerpt { - display: -webkit-box; - line-clamp: 1; - -webkit-line-clamp: 1; - -webkit-box-orient: vertical; - } -.search-wrapper .match { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); -} -@media (max-width: 767px) { - .sidebar-container { - position: fixed; - top: 0px; - bottom: 0px; - z-index: 15; - width: 100%; - overscroll-behavior: contain; - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); - padding-top: calc(var(--navbar-height)); - } - .sidebar-container:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(17 17 17 / var(--tw-bg-opacity)); - } - .sidebar-container { - transition: transform 0.8s cubic-bezier(0.52, 0.16, 0.04, 1); - will-change: transform, opacity; - contain: layout style; - backface-visibility: hidden; - } -} -.sidebar-container li > div { - height: 0px; -} -.sidebar-container li.open > div { - height: auto; - padding-top: 0.25rem; -} -.sidebar-container li.open > a > span > svg > path { - --tw-rotate: 90deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -nav .search-wrapper { - display: none; -} -@media (min-width: 768px) { - - nav .search-wrapper { - display: inline-block; - } -} -@supports ( - ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) -) { - .nav-container-blur { - background-color: rgb(255 255 255 / .85); - --tw-backdrop-blur: blur(12px); - -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); - backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); - } - .nav-container-blur:is(html[class~="dark"] *) { - background-color: rgb(17 17 17 / 0.8) !important; - } -} -.hamburger-menu svg g { - transform-origin: center; - transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1); -} -.hamburger-menu svg path { - opacity: 1; - transition: - transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s, - opacity 0.2s ease 0.2s; - } -.hamburger-menu svg.open path { - transition: - transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), - opacity 0s ease 0.2s; - } -.hamburger-menu svg.open g { - transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s; - } -.hamburger-menu svg.open > path { - opacity: 0; -} -.hamburger-menu svg.open > g:nth-of-type(1) { - --tw-rotate: 45deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -.hamburger-menu svg.open > g:nth-of-type(1) path { - transform: translate3d(0, 4px, 0); - } -.hamburger-menu svg.open > g:nth-of-type(2) { - --tw-rotate: -45deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -.hamburger-menu svg.open > g:nth-of-type(2) path { - transform: translate3d(0, -4px, 0); - } -.hextra-scrollbar, .hextra-scrollbar * { - scrollbar-width: thin; /* Firefox */ - scrollbar-color: oklch(55.55% 0 0 / 40%) transparent; /* Firefox */ - - scrollbar-gutter: stable; -} -.hextra-scrollbar::-webkit-scrollbar, .hextra-scrollbar *::-webkit-scrollbar { - height: 0.75rem; - width: 0.75rem; -} -.hextra-scrollbar::-webkit-scrollbar-track, .hextra-scrollbar *::-webkit-scrollbar-track { - background-color: transparent; -} -.hextra-scrollbar::-webkit-scrollbar-thumb, .hextra-scrollbar *::-webkit-scrollbar-thumb { - border-radius: 10px; -} -.hextra-scrollbar:hover::-webkit-scrollbar-thumb, .hextra-scrollbar *:hover::-webkit-scrollbar-thumb { - border: 3px solid transparent; - background-color: var(--tw-shadow-color); - background-clip: content-box; - --tw-shadow-color: rgb(115 115 115 / 0.2); - --tw-shadow: var(--tw-shadow-colored); - } -.hextra-scrollbar:hover::-webkit-scrollbar-thumb:hover, .hextra-scrollbar *:hover::-webkit-scrollbar-thumb:hover { - --tw-shadow-color: rgb(115 115 115 / 0.4); - --tw-shadow: var(--tw-shadow-colored); -} -@supports ( - ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) -) { - .hextra-code-copy-btn { - --tw-bg-opacity: .85; - --tw-backdrop-blur: blur(12px); - -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); - backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); - } - .hextra-code-copy-btn:is(html[class~="dark"] *) { - --tw-bg-opacity: 0.8; - } -} -@media (min-width: 1024px) { -.hextra-feature-grid { - grid-template-columns: repeat(var(--hextra-feature-grid-cols), minmax(0, 1fr)) -} - } -.hextra-jupyter-code-cell { - scrollbar-gutter: auto; - margin-top: 1.5rem; -} -.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container { - overflow: hidden; - font-size: .75rem; -} -.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs { - max-height: 50vh; - overflow: auto; -} -.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs pre { - max-width: 100%; - overflow: auto; - font-size: .75rem; -} -.hextra-badge { - display: inline-flex; - align-items: center; -} -html { - font-size: 1rem; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-feature-settings: "rlig" 1, "calt" 1, "ss01" 1; - -webkit-tap-highlight-color: transparent; -} -body { - width: 100%; - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); -} -body:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(17 17 17 / var(--tw-bg-opacity)); - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); -} -:root { - --primary-hue: 212deg; - --primary-saturation: 100%; - --primary-lightness: 50%; - --navbar-height: 4rem; - --menu-height: 3.75rem; -} -.dark { - --primary-hue: 204deg; - --primary-saturation: 100%; - --primary-lightness: 50%; -} -.placeholder\:hx-text-gray-500::-moz-placeholder { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} -.placeholder\:hx-text-gray-500::placeholder { - --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); -} -.before\:hx-pointer-events-none::before { - content: var(--tw-content); - pointer-events: none; -} -.before\:hx-absolute::before { - content: var(--tw-content); - position: absolute; -} -.before\:hx-inset-0::before { - content: var(--tw-content); - inset: 0px; -} -.before\:hx-inset-y-1::before { - content: var(--tw-content); - top: 0.25rem; - bottom: 0.25rem; -} -.before\:hx-mr-1::before { - content: var(--tw-content); - margin-right: 0.25rem; -} -.before\:hx-inline-block::before { - content: var(--tw-content); - display: inline-block; -} -.before\:hx-w-px::before { - content: var(--tw-content); - width: 1px; -} -.before\:hx-bg-gray-200::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity)); -} -.before\:hx-opacity-25::before { - content: var(--tw-content); - opacity: 0.25; -} -.before\:hx-transition-transform::before { - content: var(--tw-content); - transition-property: transform; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} -.before\:hx-content-\[\'\#\'\]::before { - --tw-content: '#'; - content: var(--tw-content); -} -.before\:hx-content-\[\'\'\]::before { - --tw-content: ''; - content: var(--tw-content); -} -.before\:hx-content-\[\\\"\\\"\]::before { - --tw-content: \"\"; - content: var(--tw-content); -} -.first\:hx-mt-0:first-child { - margin-top: 0px; -} -.last-of-type\:hx-mb-0:last-of-type { - margin-bottom: 0px; -} -.hover\:hx-border-gray-200:hover { - --tw-border-opacity: 1; - border-color: rgb(229 231 235 / var(--tw-border-opacity)); -} -.hover\:hx-border-gray-300:hover { - --tw-border-opacity: 1; - border-color: rgb(209 213 219 / var(--tw-border-opacity)); -} -.hover\:hx-border-gray-400:hover { - --tw-border-opacity: 1; - border-color: rgb(156 163 175 / var(--tw-border-opacity)); -} -.hover\:hx-border-gray-900:hover { - --tw-border-opacity: 1; - border-color: rgb(17 24 39 / var(--tw-border-opacity)); -} -.hover\:hx-bg-gray-100:hover { - --tw-bg-opacity: 1; - background-color: rgb(243 244 246 / var(--tw-bg-opacity)); -} -.hover\:hx-bg-gray-800\/5:hover { - background-color: rgb(31 41 55 / 0.05); -} -.hover\:hx-bg-primary-50:hover { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 47) / var(--tw-bg-opacity)); -} -.hover\:hx-bg-primary-700:hover { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / var(--tw-bg-opacity)); -} -.hover\:hx-bg-slate-50:hover { - --tw-bg-opacity: 1; - background-color: rgb(248 250 252 / var(--tw-bg-opacity)); -} -.hover\:hx-text-black:hover { - --tw-text-opacity: 1; - color: rgb(0 0 0 / var(--tw-text-opacity)); -} -.hover\:hx-text-gray-800:hover { - --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity)); -} -.hover\:hx-text-gray-900:hover { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); -} -.hover\:hx-text-primary-600:hover { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); -} -.hover\:hx-opacity-60:hover { - opacity: 0.6; -} -.hover\:hx-opacity-75:hover { - opacity: 0.75; -} -.hover\:hx-shadow-lg:hover { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hover\:hx-shadow-md:hover { - --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.hover\:hx-shadow-gray-100:hover { - --tw-shadow-color: #f3f4f6; - --tw-shadow: var(--tw-shadow-colored); -} -.focus\:hx-bg-white:focus { - --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity)); -} -.focus\:hx-outline-none:focus { - outline: 2px solid transparent; - outline-offset: 2px; -} -.focus\:hx-ring-4:focus { - --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); - --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color); - box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); -} -.focus\:hx-ring-primary-300:focus { - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / var(--tw-ring-opacity)); -} -.active\:hx-bg-gray-400\/20:active { - background-color: rgb(156 163 175 / 0.2); -} -.active\:hx-opacity-50:active { - opacity: 0.5; -} -.active\:hx-shadow-sm:active { - --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.active\:hx-shadow-gray-200:active { - --tw-shadow-color: #e5e7eb; - --tw-shadow: var(--tw-shadow-colored); -} -.hx-group[open] .group-open\:before\:hx-rotate-90::before { - content: var(--tw-content); - --tw-rotate: 90deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -.hx-group:hover .group-hover\:hx-underline { - text-decoration-line: underline; -} -.hx-group\/code:hover .group-hover\/code\:hx-opacity-100 { - opacity: 1; -} -.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-block { - display: block; -} -.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-hidden { - display: none; -} -.data-\[state\=selected\]\:hx-block[data-state="selected"] { - display: block; -} -.data-\[state\=closed\]\:hx-hidden[data-state="closed"] { - display: none; -} -.data-\[state\=open\]\:hx-hidden[data-state="open"] { - display: none; -} -.data-\[state\=selected\]\:hx-border-primary-500[data-state="selected"] { - --tw-border-opacity: 1; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); -} -.data-\[state\=selected\]\:hx-text-primary-600[data-state="selected"] { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); -} -.hx-group[data-theme="dark"] .group-data-\[theme\=dark\]\:hx-hidden { - display: none; -} -.hx-group[data-theme="light"] .group-data-\[theme\=light\]\:hx-hidden { - display: none; -} -@media (prefers-contrast: more) { - - .contrast-more\:hx-border { - border-width: 1px; - } - - .contrast-more\:hx-border-t { - border-top-width: 1px; - } - - .contrast-more\:hx-border-current { - border-color: currentColor; - } - - .contrast-more\:hx-border-gray-800 { - --tw-border-opacity: 1; - border-color: rgb(31 41 55 / var(--tw-border-opacity)); - } - - .contrast-more\:hx-border-gray-900 { - --tw-border-opacity: 1; - border-color: rgb(17 24 39 / var(--tw-border-opacity)); - } - - .contrast-more\:hx-border-neutral-400 { - --tw-border-opacity: 1; - border-color: rgb(163 163 163 / var(--tw-border-opacity)); - } - - .contrast-more\:hx-border-primary-500 { - --tw-border-opacity: 1; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); - } - - .contrast-more\:hx-border-transparent { - border-color: transparent; - } - - .contrast-more\:hx-font-bold { - font-weight: 700; - } - - .contrast-more\:hx-text-current { - color: currentColor; - } - - .contrast-more\:hx-text-gray-700 { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); - } - - .contrast-more\:hx-text-gray-800 { - --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity)); - } - - .contrast-more\:hx-text-gray-900 { - --tw-text-opacity: 1; - color: rgb(17 24 39 / var(--tw-text-opacity)); - } - - .contrast-more\:hx-underline { - text-decoration-line: underline; - } - - .contrast-more\:hx-shadow-\[0_0_0_1px_\#000\] { - --tw-shadow: 0 0 0 1px #000; - --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - } - - .contrast-more\:hx-shadow-none { - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - } - - .contrast-more\:hover\:hx-border-gray-900:hover { - --tw-border-opacity: 1; - border-color: rgb(17 24 39 / var(--tw-border-opacity)); - } -} -.dark\:hx-block:is(html[class~="dark"] *) { - display: block; -} -.dark\:hx-hidden:is(html[class~="dark"] *) { - display: none; -} -.dark\:hx-border-amber-200\/30:is(html[class~="dark"] *) { - border-color: rgb(253 230 138 / 0.3); -} -.dark\:hx-border-blue-200\/30:is(html[class~="dark"] *) { - border-color: rgb(191 219 254 / 0.3); -} -.dark\:hx-border-gray-100\/20:is(html[class~="dark"] *) { - border-color: rgb(243 244 246 / 0.2); -} -.dark\:hx-border-gray-400:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(156 163 175 / var(--tw-border-opacity)); -} -.dark\:hx-border-green-200\/30:is(html[class~="dark"] *) { - border-color: rgb(187 247 208 / 0.3); -} -.dark\:hx-border-indigo-200\/30:is(html[class~="dark"] *) { - border-color: rgb(199 210 254 / 0.3); -} -.dark\:hx-border-neutral-700:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(64 64 64 / var(--tw-border-opacity)); -} -.dark\:hx-border-neutral-800:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(38 38 38 / var(--tw-border-opacity)); -} -.dark\:hx-border-orange-400\/30:is(html[class~="dark"] *) { - border-color: rgb(251 146 60 / 0.3); -} -.dark\:hx-border-red-200\/30:is(html[class~="dark"] *) { - border-color: rgb(254 202 202 / 0.3); -} -.dark\:hx-border-white\/10:is(html[class~="dark"] *) { - border-color: rgb(255 255 255 / 0.1); -} -.dark\:hx-border-yellow-200\/30:is(html[class~="dark"] *) { - border-color: rgb(254 240 138 / 0.3); -} -.dark\:hx-bg-amber-900\/30:is(html[class~="dark"] *) { - background-color: rgb(120 53 15 / 0.3); -} -.dark\:hx-bg-black\/60:is(html[class~="dark"] *) { - background-color: rgb(0 0 0 / 0.6); -} -.dark\:hx-bg-blue-900\/30:is(html[class~="dark"] *) { - background-color: rgb(30 58 138 / 0.3); -} -.dark\:hx-bg-dark:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(17 17 17 / var(--tw-bg-opacity)); -} -.dark\:hx-bg-dark\/50:is(html[class~="dark"] *) { - background-color: rgb(17 17 17 / 0.5); -} -.dark\:hx-bg-gray-50\/10:is(html[class~="dark"] *) { - background-color: rgb(249 250 251 / 0.1); -} -.dark\:hx-bg-green-900\/30:is(html[class~="dark"] *) { - background-color: rgb(20 83 45 / 0.3); -} -.dark\:hx-bg-indigo-900\/30:is(html[class~="dark"] *) { - background-color: rgb(49 46 129 / 0.3); -} -.dark\:hx-bg-neutral-800:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(38 38 38 / var(--tw-bg-opacity)); -} -.dark\:hx-bg-neutral-900:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(23 23 23 / var(--tw-bg-opacity)); -} -.dark\:hx-bg-orange-400\/20:is(html[class~="dark"] *) { - background-color: rgb(251 146 60 / 0.2); -} -.dark\:hx-bg-primary-300\/10:is(html[class~="dark"] *) { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); -} -.dark\:hx-bg-primary-400\/10:is(html[class~="dark"] *) { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 16) / 0.1); -} -.dark\:hx-bg-primary-600:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-bg-opacity)); -} -.dark\:hx-bg-red-900\/30:is(html[class~="dark"] *) { - background-color: rgb(127 29 29 / 0.3); -} -.dark\:hx-bg-yellow-700\/30:is(html[class~="dark"] *) { - background-color: rgb(161 98 7 / 0.3); -} -.dark\:hx-from-gray-100:is(html[class~="dark"] *) { - --tw-gradient-from: #f3f4f6 var(--tw-gradient-from-position); - --tw-gradient-to: rgb(243 244 246 / 0) var(--tw-gradient-to-position); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} -.dark\:hx-to-gray-400:is(html[class~="dark"] *) { - --tw-gradient-to: #9ca3af var(--tw-gradient-to-position); -} -.dark\:hx-text-amber-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(253 230 138 / var(--tw-text-opacity)); -} -.dark\:hx-text-blue-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(191 219 254 / var(--tw-text-opacity)); -} -.dark\:hx-text-gray-100:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); -} -.dark\:hx-text-gray-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(229 231 235 / var(--tw-text-opacity)); -} -.dark\:hx-text-gray-300:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} -.dark\:hx-text-gray-400:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -.dark\:hx-text-gray-50:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(249 250 251 / var(--tw-text-opacity)); -} -.dark\:hx-text-green-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(187 247 208 / var(--tw-text-opacity)); -} -.dark\:hx-text-indigo-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(199 210 254 / var(--tw-text-opacity)); -} -.dark\:hx-text-neutral-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(229 229 229 / var(--tw-text-opacity)); -} -.dark\:hx-text-neutral-400:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(163 163 163 / var(--tw-text-opacity)); -} -.dark\:hx-text-orange-300:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(253 186 116 / var(--tw-text-opacity)); -} -.dark\:hx-text-primary-600:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); -} -.dark\:hx-text-red-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(254 202 202 / var(--tw-text-opacity)); -} -.dark\:hx-text-slate-100:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(241 245 249 / var(--tw-text-opacity)); -} -.dark\:hx-text-yellow-200:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(254 240 138 / var(--tw-text-opacity)); -} -.dark\:hx-opacity-80:is(html[class~="dark"] *) { - opacity: 0.8; -} -.dark\:hx-shadow-\[0_-12px_16px_\#111\]:is(html[class~="dark"] *) { - --tw-shadow: 0 -12px 16px #111; - --tw-shadow-colored: 0 -12px 16px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.dark\:hx-shadow-\[0_-1px_0_rgba\(255\2c 255\2c 255\2c \.1\)_inset\]:is(html[class~="dark"] *) { - --tw-shadow: 0 -1px 0 rgba(255,255,255,.1) inset; - --tw-shadow-colored: inset 0 -1px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.dark\:hx-shadow-none:is(html[class~="dark"] *) { - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.dark\:hx-ring-white\/20:is(html[class~="dark"] *) { - --tw-ring-color: rgb(255 255 255 / 0.2); -} -.dark\:placeholder\:hx-text-gray-400:is(html[class~="dark"] *)::-moz-placeholder { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -.dark\:placeholder\:hx-text-gray-400:is(html[class~="dark"] *)::placeholder { - --tw-text-opacity: 1; - color: rgb(156 163 175 / var(--tw-text-opacity)); -} -.dark\:before\:hx-bg-neutral-800:is(html[class~="dark"] *)::before { - content: var(--tw-content); - --tw-bg-opacity: 1; - background-color: rgb(38 38 38 / var(--tw-bg-opacity)); -} -.dark\:before\:hx-invert:is(html[class~="dark"] *)::before { - content: var(--tw-content); - --tw-invert: invert(100%); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} -.dark\:hover\:hx-border-gray-100:hover:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(243 244 246 / var(--tw-border-opacity)); -} -.dark\:hover\:hx-border-gray-600:hover:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(75 85 99 / var(--tw-border-opacity)); -} -.dark\:hover\:hx-border-neutral-500:hover:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(115 115 115 / var(--tw-border-opacity)); -} -.dark\:hover\:hx-border-neutral-700:hover:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(64 64 64 / var(--tw-border-opacity)); -} -.dark\:hover\:hx-border-neutral-800:hover:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(38 38 38 / var(--tw-border-opacity)); -} -.dark\:hover\:hx-bg-gray-100\/5:hover:is(html[class~="dark"] *) { - background-color: rgb(243 244 246 / 0.05); -} -.dark\:hover\:hx-bg-neutral-700:hover:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(64 64 64 / var(--tw-bg-opacity)); -} -.dark\:hover\:hx-bg-neutral-800:hover:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(38 38 38 / var(--tw-bg-opacity)); -} -.dark\:hover\:hx-bg-neutral-900:hover:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(23 23 23 / var(--tw-bg-opacity)); -} -.dark\:hover\:hx-bg-primary-100\/5:hover:is(html[class~="dark"] *) { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44) / 0.05); -} -.dark\:hover\:hx-bg-primary-700:hover:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39) / var(--tw-bg-opacity)); -} -.hover\:dark\:hx-bg-primary-500\/10:is(html[class~="dark"] *):hover { - background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / 0.1); -} -.dark\:hover\:hx-text-gray-100:hover:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); -} -.dark\:hover\:hx-text-gray-200:hover:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(229 231 235 / var(--tw-text-opacity)); -} -.dark\:hover\:hx-text-gray-300:hover:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); -} -.dark\:hover\:hx-text-gray-50:hover:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(249 250 251 / var(--tw-text-opacity)); -} -.dark\:hover\:hx-text-neutral-50:hover:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(250 250 250 / var(--tw-text-opacity)); -} -.dark\:hover\:hx-text-white:hover:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} -.hover\:dark\:hx-text-primary-600:is(html[class~="dark"] *):hover { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); -} -.dark\:hover\:hx-shadow-none:hover:is(html[class~="dark"] *) { - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} -.dark\:focus\:hx-bg-dark:focus:is(html[class~="dark"] *) { - --tw-bg-opacity: 1; - background-color: rgb(17 17 17 / var(--tw-bg-opacity)); -} -.dark\:focus\:hx-ring-primary-800:focus:is(html[class~="dark"] *) { - --tw-ring-opacity: 1; - --tw-ring-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / var(--tw-ring-opacity)); -} -.data-\[state\=selected\]\:dark\:hx-border-primary-500:is(html[class~="dark"] *)[data-state="selected"] { - --tw-border-opacity: 1; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); -} -.data-\[state\=selected\]\:dark\:hx-text-primary-600:is(html[class~="dark"] *)[data-state="selected"] { - --tw-text-opacity: 1; - color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45) / var(--tw-text-opacity)); -} -@media (prefers-contrast: more) { - - .contrast-more\:dark\:hx-border-current:is(html[class~="dark"] *) { - border-color: currentColor; - } - - .contrast-more\:dark\:hx-border-gray-50:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(249 250 251 / var(--tw-border-opacity)); - } - - .contrast-more\:dark\:hx-border-neutral-400:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(163 163 163 / var(--tw-border-opacity)); - } - - .contrast-more\:dark\:hx-border-primary-500:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 50) / var(--tw-border-opacity)); - } - - .dark\:contrast-more\:hx-border-neutral-400:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(163 163 163 / var(--tw-border-opacity)); - } - - .contrast-more\:dark\:hx-text-current:is(html[class~="dark"] *) { - color: currentColor; - } - - .contrast-more\:dark\:hx-text-gray-100:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(243 244 246 / var(--tw-text-opacity)); - } - - .contrast-more\:dark\:hx-text-gray-300:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); - } - - .contrast-more\:dark\:hx-text-gray-50:is(html[class~="dark"] *) { - --tw-text-opacity: 1; - color: rgb(249 250 251 / var(--tw-text-opacity)); - } - - .contrast-more\:dark\:hx-shadow-\[0_0_0_1px_\#fff\]:is(html[class~="dark"] *) { - --tw-shadow: 0 0 0 1px #fff; - --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - } - - .contrast-more\:dark\:hx-shadow-none:is(html[class~="dark"] *) { - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); - } - - .contrast-more\:dark\:hover\:hx-border-gray-50:hover:is(html[class~="dark"] *) { - --tw-border-opacity: 1; - border-color: rgb(249 250 251 / var(--tw-border-opacity)); - } -} -@media not all and (min-width: 1280px) { - - .max-xl\:hx-hidden { - display: none; - } -} -@media not all and (min-width: 1024px) { - - .max-lg\:hx-min-h-\[340px\] { - min-height: 340px; - } -} -@media not all and (min-width: 768px) { - - .max-md\:hx-hidden { - display: none; - } - - .max-md\:hx-min-h-\[340px\] { - min-height: 340px; - } - - .max-md\:\[transform\:translate3d\(0\2c -100\%\2c 0\)\] { - transform: translate3d(0,-100%,0); - } -} -@media not all and (min-width: 640px) { - - .max-sm\:hx-grid-cols-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } -} -@media (min-width: 640px) { - - .sm\:hx-block { - display: block; - } - - .sm\:hx-flex { - display: flex; - } - - .sm\:hx-w-\[110\%\] { - width: 110%; - } - - .sm\:hx-items-start { - align-items: flex-start; - } - - .sm\:hx-text-xl { - font-size: 1.25rem; - } - - @media not all and (min-width: 1024px) { - - .sm\:max-lg\:hx-grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - } -} -@media (min-width: 768px) { - - .md\:hx-sticky { - position: sticky; - } - - .md\:hx-top-16 { - top: 4rem; - } - - .md\:hx-inline-block { - display: inline-block; - } - - .md\:hx-hidden { - display: none; - } - - .md\:hx-aspect-\[1\.1\/1\] { - aspect-ratio: 1.1/1; - } - - .md\:hx-h-\[calc\(100vh-var\(--navbar-height\)-var\(--menu-height\)\)\] { - height: calc(100vh - var(--navbar-height) - var(--menu-height)); - } - - .md\:hx-max-h-\[min\(calc\(100vh-5rem-env\(safe-area-inset-bottom\)\)\2c 400px\)\] { - max-height: min(calc(100vh - 5rem - env(safe-area-inset-bottom)),400px); - } - - .md\:hx-w-64 { - width: 16rem; - } - - .md\:hx-shrink-0 { - flex-shrink: 0; - } - - .md\:hx-grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .md\:hx-justify-start { - justify-content: flex-start; - } - - .md\:hx-self-start { - align-self: flex-start; - } - - .md\:hx-px-12 { - padding-left: 3rem; - padding-right: 3rem; - } - - .md\:hx-pt-12 { - padding-top: 3rem; - } - - .md\:hx-text-5xl { - font-size: 3rem; - } - - .md\:hx-text-lg { - font-size: 1.125rem; - } - - .md\:hx-text-sm { - font-size: .875rem; - } -} -@media (min-width: 1024px) { - - .lg\:hx-grid-cols-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } -} -@media (min-width: 1280px) { - - .xl\:hx-block { - display: block; - } - - .xl\:hx-grid-cols-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } -} -.ltr\:hx-right-1\.5:where([dir="ltr"], [dir="ltr"] *) { - right: 0.375rem; -} -.ltr\:hx-right-3:where([dir="ltr"], [dir="ltr"] *) { - right: 0.75rem; -} -.ltr\:hx--mr-4:where([dir="ltr"], [dir="ltr"] *) { - margin-right: -1rem; -} -.ltr\:hx-ml-1:where([dir="ltr"], [dir="ltr"] *) { - margin-left: 0.25rem; -} -.ltr\:hx-ml-3:where([dir="ltr"], [dir="ltr"] *) { - margin-left: 0.75rem; -} -.ltr\:hx-ml-auto:where([dir="ltr"], [dir="ltr"] *) { - margin-left: auto; -} -.ltr\:hx-mr-auto:where([dir="ltr"], [dir="ltr"] *) { - margin-right: auto; -} -.ltr\:hx-rotate-180:where([dir="ltr"], [dir="ltr"] *) { - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -.ltr\:hx-border-l:where([dir="ltr"], [dir="ltr"] *) { - border-left-width: 1px; -} -.ltr\:hx-pl-12:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 3rem; -} -.ltr\:hx-pl-16:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 4rem; -} -.ltr\:hx-pl-3:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 0.75rem; -} -.ltr\:hx-pl-4:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 1rem; -} -.ltr\:hx-pl-5:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 1.25rem; -} -.ltr\:hx-pl-6:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 1.5rem; -} -.ltr\:hx-pl-8:where([dir="ltr"], [dir="ltr"] *) { - padding-left: 2rem; -} -.ltr\:hx-pr-0:where([dir="ltr"], [dir="ltr"] *) { - padding-right: 0px; -} -.ltr\:hx-pr-2:where([dir="ltr"], [dir="ltr"] *) { - padding-right: 0.5rem; -} -.ltr\:hx-pr-4:where([dir="ltr"], [dir="ltr"] *) { - padding-right: 1rem; -} -.ltr\:hx-pr-9:where([dir="ltr"], [dir="ltr"] *) { - padding-right: 2.25rem; -} -.ltr\:hx-text-right:where([dir="ltr"], [dir="ltr"] *) { - text-align: right; -} -.ltr\:before\:hx-left-0:where([dir="ltr"], [dir="ltr"] *)::before { - content: var(--tw-content); - left: 0px; -} -@media (min-width: 768px) { - - .ltr\:md\:hx-left-auto:where([dir="ltr"], [dir="ltr"] *) { - left: auto; - } -} -.rtl\:hx-left-1\.5:where([dir="rtl"], [dir="rtl"] *) { - left: 0.375rem; -} -.rtl\:hx-left-3:where([dir="rtl"], [dir="rtl"] *) { - left: 0.75rem; -} -.rtl\:hx--ml-4:where([dir="rtl"], [dir="rtl"] *) { - margin-left: -1rem; -} -.rtl\:hx-ml-auto:where([dir="rtl"], [dir="rtl"] *) { - margin-left: auto; -} -.rtl\:hx-mr-1:where([dir="rtl"], [dir="rtl"] *) { - margin-right: 0.25rem; -} -.rtl\:hx-mr-3:where([dir="rtl"], [dir="rtl"] *) { - margin-right: 0.75rem; -} -.rtl\:hx-mr-auto:where([dir="rtl"], [dir="rtl"] *) { - margin-right: auto; -} -.rtl\:-hx-rotate-180:where([dir="rtl"], [dir="rtl"] *) { - --tw-rotate: -180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -.rtl\:hx-border-r:where([dir="rtl"], [dir="rtl"] *) { - border-right-width: 1px; -} -.rtl\:hx-pl-2:where([dir="rtl"], [dir="rtl"] *) { - padding-left: 0.5rem; -} -.rtl\:hx-pl-4:where([dir="rtl"], [dir="rtl"] *) { - padding-left: 1rem; -} -.rtl\:hx-pl-9:where([dir="rtl"], [dir="rtl"] *) { - padding-left: 2.25rem; -} -.rtl\:hx-pr-12:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 3rem; -} -.rtl\:hx-pr-16:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 4rem; -} -.rtl\:hx-pr-3:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 0.75rem; -} -.rtl\:hx-pr-4:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 1rem; -} -.rtl\:hx-pr-5:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 1.25rem; -} -.rtl\:hx-pr-6:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 1.5rem; -} -.rtl\:hx-pr-8:where([dir="rtl"], [dir="rtl"] *) { - padding-right: 2rem; -} -.rtl\:hx-text-left:where([dir="rtl"], [dir="rtl"] *) { - text-align: left; -} -.rtl\:before\:hx-right-0:where([dir="rtl"], [dir="rtl"] *)::before { - content: var(--tw-content); - right: 0px; -} -.rtl\:before\:hx-rotate-180:where([dir="rtl"], [dir="rtl"] *)::before { - content: var(--tw-content); - --tw-rotate: 180deg; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} -@media (min-width: 768px) { - - .rtl\:md\:hx-right-auto:where([dir="rtl"], [dir="rtl"] *) { - right: auto; - } -} -@media print { - - .print\:hx-hidden { - display: none; - } - - .print\:hx-bg-transparent { - background-color: transparent; - } -} diff --git a/public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css b/public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css deleted file mode 100644 index 823130e..0000000 --- a/public/css/compiled/main.min.e0bb0f28123bf084d555fc9253c6d2aa1443b2dfcde6044741a207eabdc3ddb8.css +++ /dev/null @@ -1 +0,0 @@ -*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::before,::after{--tw-content:''}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.hx-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.hx-pointer-events-none{pointer-events:none}.hx-fixed{position:fixed}.hx-absolute{position:absolute}.hx-relative{position:relative}.hx-sticky{position:sticky}.hx-inset-0{inset:0}.hx-inset-x-0{left:0;right:0}.hx-inset-y-0{top:0;bottom:0}.hx-bottom-0{bottom:0}.hx-left-\[24px\]{left:24px}.hx-left-\[36px\]{left:36px}.hx-right-0{right:0}.hx-top-0{top:0}.hx-top-16{top:4rem}.hx-top-8{top:2rem}.hx-top-\[40\%\]{top:40%}.hx-top-full{top:100%}.hx-z-10{z-index:10}.hx-z-20{z-index:20}.hx-z-\[-1\]{z-index:-1}.hx-order-last{order:9999}.hx-m-\[11px\]{margin:11px}.hx-mx-1{margin-left:.25rem;margin-right:.25rem}.hx-mx-4{margin-left:1rem;margin-right:1rem}.hx-mx-auto{margin-left:auto;margin-right:auto}.hx-my-1\.5{margin-top:.375rem;margin-bottom:.375rem}.hx-my-2{margin-top:.5rem;margin-bottom:.5rem}.-hx-mb-0\.5{margin-bottom:-.125rem}.-hx-ml-2{margin-left:-.5rem}.-hx-mr-2{margin-right:-.5rem}.-hx-mt-20{margin-top:-5rem}.hx-mb-10{margin-bottom:2.5rem}.hx-mb-12{margin-bottom:3rem}.hx-mb-16{margin-bottom:4rem}.hx-mb-2{margin-bottom:.5rem}.hx-mb-4{margin-bottom:1rem}.hx-mb-6{margin-bottom:1.5rem}.hx-mb-8{margin-bottom:2rem}.hx-ml-4{margin-left:1rem}.hx-mr-1{margin-right:.25rem}.hx-mr-2{margin-right:.5rem}.hx-mt-1{margin-top:.25rem}.hx-mt-1\.5{margin-top:.375rem}.hx-mt-12{margin-top:3rem}.hx-mt-16{margin-top:4rem}.hx-mt-2{margin-top:.5rem}.hx-mt-4{margin-top:1rem}.hx-mt-5{margin-top:1.25rem}.hx-mt-6{margin-top:1.5rem}.hx-mt-8{margin-top:2rem}.hx-line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.hx-block{display:block}.hx-inline-block{display:inline-block}.hx-inline{display:inline}.hx-flex{display:flex}.hx-inline-flex{display:inline-flex}.hx-grid{display:grid}.hx-hidden{display:none}.hx-aspect-auto{aspect-ratio:auto}.hx-h-0{height:0}.hx-h-16{height:4rem}.hx-h-2{height:.5rem}.hx-h-3\.5{height:.875rem}.hx-h-4{height:1rem}.hx-h-5{height:1.25rem}.hx-h-7{height:1.75rem}.hx-h-\[18px\]{height:18px}.hx-h-full{height:100%}.hx-max-h-64{max-height:16rem}.hx-max-h-\[calc\(100vh-var\(--navbar-height\)-env\(safe-area-inset-bottom\)\)\]{max-height:calc(100vh - var(--navbar-height) - env(safe-area-inset-bottom))}.hx-max-h-\[min\(calc\(50vh-11rem-env\(safe-area-inset-bottom\)\)\,400px\)\]{max-height:min(calc(50vh - 11rem - env(safe-area-inset-bottom)),400px)}.hx-min-h-\[100px\]{min-height:100px}.hx-min-h-\[calc\(100vh-var\(--navbar-height\)\)\]{min-height:calc(100vh - var(--navbar-height))}.hx-w-2{width:.5rem}.hx-w-3\.5{width:.875rem}.hx-w-4{width:1rem}.hx-w-64{width:16rem}.hx-w-\[110\%\]{width:110%}.hx-w-\[180\%\]{width:180%}.hx-w-full{width:100%}.hx-w-max{width:-moz-max-content;width:max-content}.hx-w-screen{width:100vw}.hx-min-w-0{min-width:0}.hx-min-w-\[18px\]{min-width:18px}.hx-min-w-\[24px\]{min-width:24px}.hx-min-w-full{min-width:100%}.hx-max-w-6xl{max-width:72rem}.hx-max-w-\[50\%\]{max-width:50%}.hx-max-w-\[90rem\]{max-width:90rem}.hx-max-w-\[min\(calc\(100vw-2rem\)\,calc\(100\%\+20rem\)\)\]{max-width:min(calc(100vw - 2rem),calc(100% + 20rem))}.hx-max-w-none{max-width:none}.hx-max-w-screen-xl{max-width:1280px}.hx-shrink-0{flex-shrink:0}.hx-grow{flex-grow:1}.hx-origin-center{transform-origin:center}.hx-cursor-default{cursor:default}.hx-cursor-pointer{cursor:pointer}.hx-select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.hx-scroll-my-6{scroll-margin-top:1.5rem;scroll-margin-bottom:1.5rem}.hx-scroll-py-6{scroll-padding-top:1.5rem;scroll-padding-bottom:1.5rem}.hx-list-none{list-style-type:none}.hx-appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.hx-grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.hx-flex-col{flex-direction:column}.hx-flex-wrap{flex-wrap:wrap}.hx-items-start{align-items:flex-start}.hx-items-center{align-items:center}.hx-justify-start{justify-content:flex-start}.hx-justify-end{justify-content:flex-end}.hx-justify-center{justify-content:center}.hx-justify-between{justify-content:space-between}.hx-justify-items-start{justify-items:start}.hx-gap-1{gap:.25rem}.hx-gap-2{gap:.5rem}.hx-gap-4{gap:1rem}.hx-gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.hx-gap-y-2{row-gap:.5rem}.hx-overflow-auto{overflow:auto}.hx-overflow-hidden{overflow:hidden}.hx-overflow-x-auto{overflow-x:auto}.hx-overflow-y-auto{overflow-y:auto}.hx-overflow-x-hidden{overflow-x:hidden}.hx-overflow-y-hidden{overflow-y:hidden}.hx-overscroll-contain{overscroll-behavior:contain}.hx-overscroll-x-contain{overscroll-behavior-x:contain}.hx-text-ellipsis{text-overflow:ellipsis}.hx-whitespace-nowrap{white-space:nowrap}.hx-break-words{overflow-wrap:break-word}.hx-rounded{border-radius:.25rem}.hx-rounded-3xl{border-radius:1.5rem}.hx-rounded-full{border-radius:9999px}.hx-rounded-lg{border-radius:.5rem}.hx-rounded-md{border-radius:.375rem}.hx-rounded-sm{border-radius:.125rem}.hx-rounded-xl{border-radius:.75rem}.hx-rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.hx-border{border-width:1px}.hx-border-b{border-bottom-width:1px}.hx-border-b-2{border-bottom-width:2px}.hx-border-t{border-top-width:1px}.hx-border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity))}.hx-border-black\/5{border-color:rgb(0 0 0/5%)}.hx-border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity))}.hx-border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.hx-border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}.hx-border-green-200{--tw-border-opacity:1;border-color:rgb(187 247 208/var(--tw-border-opacity))}.hx-border-indigo-200{--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}.hx-border-orange-100{--tw-border-opacity:1;border-color:rgb(255 237 213/var(--tw-border-opacity))}.hx-border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity))}.hx-border-transparent{border-color:transparent}.hx-border-yellow-100{--tw-border-opacity:1;border-color:rgb(254 249 195/var(--tw-border-opacity))}.hx-bg-amber-100{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity))}.hx-bg-black\/80{background-color:rgb(0 0 0/.8)}.hx-bg-black\/\[\.05\]{background-color:rgb(0 0 0/5%)}.hx-bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity))}.hx-bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hx-bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity))}.hx-bg-indigo-100{--tw-bg-opacity:1;background-color:rgb(224 231 255/var(--tw-bg-opacity))}.hx-bg-neutral-50{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity))}.hx-bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity))}.hx-bg-primary-100{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/var(--tw-bg-opacity))}.hx-bg-primary-400{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 16)/var(--tw-bg-opacity))}.hx-bg-primary-600{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-bg-opacity))}.hx-bg-primary-700\/5{background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05)}.hx-bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.hx-bg-transparent{background-color:transparent}.hx-bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hx-bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity))}.hx-bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.hx-from-gray-900{--tw-gradient-from:#111827 var(--tw-gradient-from-position);--tw-gradient-to:rgb(17 24 39 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.hx-to-gray-600{--tw-gradient-to:#4b5563 var(--tw-gradient-to-position)}.hx-bg-clip-text{-webkit-background-clip:text;background-clip:text}.hx-p-0\.5{padding:.125rem}.hx-p-1{padding:.25rem}.hx-p-1\.5{padding:.375rem}.hx-p-2{padding:.5rem}.hx-p-4{padding:1rem}.hx-p-6{padding:1.5rem}.hx-px-1\.5{padding-left:.375rem;padding-right:.375rem}.hx-px-2{padding-left:.5rem;padding-right:.5rem}.hx-px-2\.5{padding-left:.625rem;padding-right:.625rem}.hx-px-3{padding-left:.75rem;padding-right:.75rem}.hx-px-4{padding-left:1rem;padding-right:1rem}.hx-px-6{padding-left:1.5rem;padding-right:1.5rem}.hx-py-1{padding-top:.25rem;padding-bottom:.25rem}.hx-py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.hx-py-12{padding-top:3rem;padding-bottom:3rem}.hx-py-2{padding-top:.5rem;padding-bottom:.5rem}.hx-py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.hx-py-3{padding-top:.75rem;padding-bottom:.75rem}.hx-py-4{padding-top:1rem;padding-bottom:1rem}.hx-pb-8{padding-bottom:2rem}.hx-pb-\[env\(safe-area-inset-bottom\)\]{padding-bottom:env(safe-area-inset-bottom)}.hx-pb-px{padding-bottom:1px}.hx-pl-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\]{padding-left:max(env(safe-area-inset-left),1.5rem)}.hx-pr-2{padding-right:.5rem}.hx-pr-4{padding-right:1rem}.hx-pr-\[calc\(env\(safe-area-inset-right\)-1\.5rem\)\]{padding-right:calc(env(safe-area-inset-right) - 1.5rem)}.hx-pr-\[max\(env\(safe-area-inset-left\)\,1\.5rem\)\]{padding-right:max(env(safe-area-inset-left),1.5rem)}.hx-pr-\[max\(env\(safe-area-inset-right\)\,1\.5rem\)\]{padding-right:max(env(safe-area-inset-right),1.5rem)}.hx-pt-4{padding-top:1rem}.hx-pt-6{padding-top:1.5rem}.hx-pt-8{padding-top:2rem}.hx-text-left{text-align:left}.hx-text-center{text-align:center}.hx-align-middle{vertical-align:middle}.hx-align-text-bottom{vertical-align:text-bottom}.hx-align-\[-2\.5px\]{vertical-align:-2.5px}.hx-font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace}.hx-text-2xl{font-size:1.5rem}.hx-text-4xl{font-size:2.25rem}.hx-text-\[\.65rem\]{font-size:.65rem}.hx-text-\[10px\]{font-size:10px}.hx-text-base{font-size:1rem}.hx-text-lg{font-size:1.125rem}.hx-text-sm{font-size:.875rem}.hx-text-xl{font-size:1.25rem}.hx-text-xs{font-size:.75rem}.hx-font-bold{font-weight:700}.hx-font-extrabold{font-weight:800}.hx-font-medium{font-weight:500}.hx-font-normal{font-weight:400}.hx-font-semibold{font-weight:600}.hx-capitalize{text-transform:capitalize}.hx-leading-5{line-height:1.25rem}.hx-leading-6{line-height:1.5rem}.hx-leading-7{line-height:1.75rem}.hx-leading-none{line-height:1}.hx-leading-tight{line-height:1.25}.hx-tracking-tight{letter-spacing:-.015em}.hx-text-\[color\:hsl\(var\(--primary-hue\)\,100\%\,50\%\)\]{--tw-text-opacity:1;color:hsl(var(--primary-hue) 100% 50%/var(--tw-text-opacity))}.hx-text-amber-900{--tw-text-opacity:1;color:rgb(120 53 15/var(--tw-text-opacity))}.hx-text-blue-900{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity))}.hx-text-current{color:currentColor}.hx-text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.hx-text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.hx-text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hx-text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hx-text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hx-text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hx-text-green-900{--tw-text-opacity:1;color:rgb(20 83 45/var(--tw-text-opacity))}.hx-text-indigo-900{--tw-text-opacity:1;color:rgb(49 46 129/var(--tw-text-opacity))}.hx-text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity))}.hx-text-primary-800{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 32)/var(--tw-text-opacity))}.hx-text-red-900{--tw-text-opacity:1;color:rgb(127 29 29/var(--tw-text-opacity))}.hx-text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.hx-text-transparent{color:transparent}.hx-text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hx-text-yellow-900{--tw-text-opacity:1;color:rgb(113 63 18/var(--tw-text-opacity))}.hx-underline{text-decoration-line:underline}.hx-no-underline{text-decoration-line:none}.hx-decoration-from-font{text-decoration-thickness:from-font}.hx-underline-offset-2{text-underline-offset:2px}.hx-opacity-0{opacity:0}.hx-opacity-50{opacity:.5}.hx-opacity-80{opacity:.8}.hx-shadow{--tw-shadow:0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-\[0_-12px_16px_\#fff\]{--tw-shadow:0 -12px 16px #fff;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-\[0_-12px_16px_white\]{--tw-shadow:0 -12px 16px white;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-\[0_2px_4px_rgba\(0\,0\,0\,\.02\)\,0_1px_0_rgba\(0\,0\,0\,\.06\)\]{--tw-shadow:0 2px 4px rgba(0,0,0,.02),0 1px 0 rgba(0,0,0,.06);--tw-shadow-colored:0 2px 4px var(--tw-shadow-color), 0 1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-sm{--tw-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-xl{--tw-shadow:0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hx-shadow-gray-100{--tw-shadow-color:#f3f4f6;--tw-shadow:var(--tw-shadow-colored)}.hx-ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hx-ring-black\/5{--tw-ring-color:rgb(0 0 0 / 0.05)}.hx-transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.hx-duration-200{transition-duration:200ms}.hx-duration-75{transition-duration:75ms}.hx-ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.\[-webkit-tap-highlight-color\:transparent\]{-webkit-tap-highlight-color:transparent}.\[-webkit-touch-callout\:none\]{-webkit-touch-callout:none}.\[counter-reset\:step\]{counter-reset:step}.\[hyphens\:auto\]{-webkit-hyphens:auto;hyphens:auto}.\[transition\:background-color_1\.5s_ease\]{transition:background-color 1.5s ease}.\[word-break\:break-word\]{word-break:break-word}.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5rem;font-size:2.25rem;font-weight:700;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2.5rem;border-bottom-width:1px;border-color:rgb(229 229 229/.7);padding-bottom:.25rem;font-size:1.875rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}@media(prefers-contrast:more){.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}}.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.1);--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}@media(prefers-contrast:more){.content :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}}.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1.5rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1.25rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1.125rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2rem;font-size:1rem;font-weight:600;letter-spacing:-.015em;--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.content :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;line-height:1.75rem}.content :where(p):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity));text-decoration-line:underline;text-decoration-thickness:from-font;text-underline-position:from-font}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));font-style:italic;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=ltr],[dir=ltr] *){border-left-width:2px;padding-left:1.5rem}.content :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=rtl],[dir=rtl] *){border-right-width:2px;padding-right:1.5rem}.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)){margin-bottom:1rem;overflow-x:auto;border-radius:.75rem;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05);padding-top:1rem;padding-bottom:1rem;font-size:.9em;font-weight:500;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}@media(prefers-contrast:more){.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)){border-width:1px;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 24)/.2);--tw-contrast:contrast(1.5);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}}.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1)}@media(prefers-contrast:more){.content :where(pre):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.4)}}.content :where(code):not(:where(.hextra-code-block code,[class~=not-prose],[class~=not-prose] *)){overflow-wrap:break-word;border-radius:.375rem;border-width:1px;border-color:rgb(0 0 0/var(--tw-border-opacity));--tw-border-opacity:0.04;background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:0.03;padding-top:.125rem;padding-bottom:.125rem;padding-left:.25em;padding-right:.25em;font-size:.9em}.content :where(code):not(:where(.hextra-code-block code,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:rgb(255 255 255/.1);background-color:rgb(255 255 255/.1)}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;display:block;overflow-x:auto;padding:0}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr{margin:0;border-top-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding:0}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr:nth-child(even){--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) tr:is(html[class~=dark] *):nth-child(even){background-color:rgb(75 85 99/.2)}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) th{margin:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem;font-weight:600}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) th:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) td{margin:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem}.content :where(table):not(:where(.hextra-code-block table,[class~=not-prose],[class~=not-prose] *)) td:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;list-style-type:decimal}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=ltr],[dir=ltr] *){margin-left:1.5rem}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=rtl],[dir=rtl] *){margin-right:1.5rem}.content :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) li{margin-top:.5rem;margin-bottom:.5rem}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.5rem;list-style-type:disc}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):first-child{margin-top:0}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=ltr],[dir=ltr] *){margin-left:1.5rem}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):where([dir=rtl],[dir=rtl] *){margin-right:1.5rem}.content :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) li{margin-top:.5rem;margin-bottom:.5rem}.content :where(ul,ol)>li>:where(ul,ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){overflow-wrap:break-word;border-radius:.375rem;border-width:1px;border-color:rgb(0 0 0/var(--tw-border-opacity));--tw-border-opacity:0.04;background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:0.03;padding-top:.125rem;padding-bottom:.125rem;padding-left:.25em;padding-right:.25em;font-size:.9em}.content :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){border-color:rgb(255 255 255/.1);background-color:rgb(255 255 255/.1)}.content :where(pre.mermaid):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)){border-radius:0;background-color:transparent}.content :where(pre.mermaid):not(:where(.hextra-code-block pre,[class~=not-prose],[class~=not-prose] *)):is(html[class~=dark] *){background-color:transparent}.content :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-left:auto;margin-right:auto;margin-top:1rem;margin-bottom:1rem;border-radius:.375rem}.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption{margin-top:.5rem;display:block;text-align:center;font-size:.875rem;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.content :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) figcaption:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dt{margin-top:1.5rem;font-weight:600}.content :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) dd{margin-top:.5rem;margin-bottom:.5rem;padding-inline-start:1.5rem}.content .footnotes{margin-top:3rem;font-size:.875rem}.subheading-anchor{opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.subheading-anchor:where([dir=ltr],[dir=ltr] *){margin-left:.25rem}.subheading-anchor:where([dir=rtl],[dir=rtl] *){margin-right:.25rem}span:target+.subheading-anchor,:hover>.subheading-anchor,.subheading-anchor:focus{opacity:1}span+.subheading-anchor,:hover>.subheading-anchor{text-decoration-line:none !important}.subheading-anchor:after{padding-left:.25rem;padding-right:.25rem;--tw-content:'#';content:var(--tw-content);--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.subheading-anchor:is(html[class~=dark] *):after{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}span:target+.subheading-anchor:after{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}span:target+.subheading-anchor:is(html[class~=dark] *):after{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity))}article details>summary::-webkit-details-marker{display:none}article details>summary::before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='hx-h-5 hx-w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E");height:1.2em;width:1.2em;vertical-align:-4px;padding:0 .6em}:lang(fa) ol{list-style-type:persian}.highlight{}.highlight .chroma .err{color:#a61717;background-color:#e3d2d2}.highlight .chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.highlight .chroma .line{display:flex}.highlight .chroma .k{color:#000;font-weight:700}.highlight .chroma .kc{color:#000;font-weight:700}.highlight .chroma .kd{color:#000;font-weight:700}.highlight .chroma .kn{color:#000;font-weight:700}.highlight .chroma .kp{color:#000;font-weight:700}.highlight .chroma .kr{color:#000;font-weight:700}.highlight .chroma .kt{color:#458;font-weight:700}.highlight .chroma .na{color:teal}.highlight .chroma .nb{color:#0086b3}.highlight .chroma .bp{color:#999}.highlight .chroma .nc{color:#458;font-weight:700}.highlight .chroma .no{color:teal}.highlight .chroma .nd{color:#3c5d5d;font-weight:700}.highlight .chroma .ni{color:purple}.highlight .chroma .ne{color:#900;font-weight:700}.highlight .chroma .nf{color:#900;font-weight:700}.highlight .chroma .nl{color:#900;font-weight:700}.highlight .chroma .nn{color:#555}.highlight .chroma .nt{color:navy}.highlight .chroma .nv{color:teal}.highlight .chroma .vc{color:teal}.highlight .chroma .vg{color:teal}.highlight .chroma .vi{color:teal}.highlight .chroma .s{color:#d14}.highlight .chroma .sa{color:#d14}.highlight .chroma .sb{color:#d14}.highlight .chroma .sc{color:#d14}.highlight .chroma .dl{color:#d14}.highlight .chroma .sd{color:#d14}.highlight .chroma .s2{color:#d14}.highlight .chroma .se{color:#d14}.highlight .chroma .sh{color:#d14}.highlight .chroma .si{color:#d14}.highlight .chroma .sx{color:#d14}.highlight .chroma .sr{color:#009926}.highlight .chroma .s1{color:#d14}.highlight .chroma .ss{color:#990073}.highlight .chroma .m{color:#099}.highlight .chroma .mb{color:#099}.highlight .chroma .mf{color:#099}.highlight .chroma .mh{color:#099}.highlight .chroma .mi{color:#099}.highlight .chroma .il{color:#099}.highlight .chroma .mo{color:#099}.highlight .chroma .o{color:#000;font-weight:700}.highlight .chroma .ow{color:#000;font-weight:700}.highlight .chroma .c{color:#998;font-style:italic}.highlight .chroma .ch{color:#998;font-style:italic}.highlight .chroma .cm{color:#998;font-style:italic}.highlight .chroma .c1{color:#998;font-style:italic}.highlight .chroma .cs{color:#999;font-weight:700;font-style:italic}.highlight .chroma .cp{color:#999;font-weight:700;font-style:italic}.highlight .chroma .cpf{color:#999;font-weight:700;font-style:italic}.highlight .chroma .gd{color:#000;background-color:#fdd}.highlight .chroma .ge{color:#000;font-style:italic}.highlight .chroma .gr{color:#a00}.highlight .chroma .gh{color:#999}.highlight .chroma .gi{color:#000;background-color:#dfd}.highlight .chroma .go{color:#888}.highlight .chroma .gp{color:#555}.highlight .chroma .gs{font-weight:700}.highlight .chroma .gu{color:#aaa}.highlight .chroma .gt{color:#a00}.highlight .chroma .gl{text-decoration:underline}.highlight .chroma .w{color:#bbb}.dark .highlight{}.dark .highlight .chroma .x{}.dark .highlight .chroma .err{color:#f85149}.dark .highlight .chroma .cl{}.dark .highlight .chroma .lnlinks{outline:none;text-decoration:none;color:inherit}.dark .highlight .chroma .line{display:flex}.dark .highlight .chroma .k{color:#ff7b72}.dark .highlight .chroma .kc{color:#79c0ff}.dark .highlight .chroma .kd{color:#ff7b72}.dark .highlight .chroma .kn{color:#ff7b72}.dark .highlight .chroma .kp{color:#79c0ff}.dark .highlight .chroma .kr{color:#ff7b72}.dark .highlight .chroma .kt{color:#ff7b72}.dark .highlight .chroma .n{}.dark .highlight .chroma .na{}.dark .highlight .chroma .nb{}.dark .highlight .chroma .bp{}.dark .highlight .chroma .nc{color:#f0883e;font-weight:700}.dark .highlight .chroma .no{color:#79c0ff;font-weight:700}.dark .highlight .chroma .nd{color:#d2a8ff;font-weight:700}.dark .highlight .chroma .ni{color:#ffa657}.dark .highlight .chroma .ne{color:#f0883e;font-weight:700}.dark .highlight .chroma .nf{color:#d2a8ff;font-weight:700}.dark .highlight .chroma .fm{}.dark .highlight .chroma .nl{color:#79c0ff;font-weight:700}.dark .highlight .chroma .nn{color:#ff7b72}.dark .highlight .chroma .nx{}.dark .highlight .chroma .py{color:#79c0ff}.dark .highlight .chroma .nt{color:#7ee787}.dark .highlight .chroma .nv{color:#79c0ff}.dark .highlight .chroma .vc{}.dark .highlight .chroma .vg{}.dark .highlight .chroma .vi{}.dark .highlight .chroma .vm{}.dark .highlight .chroma .l{color:#a5d6ff}.dark .highlight .chroma .ld{color:#79c0ff}.dark .highlight .chroma .s{color:#a5d6ff}.dark .highlight .chroma .sa{color:#79c0ff}.dark .highlight .chroma .sb{color:#a5d6ff}.dark .highlight .chroma .sc{color:#a5d6ff}.dark .highlight .chroma .dl{color:#79c0ff}.dark .highlight .chroma .sd{color:#a5d6ff}.dark .highlight .chroma .s2{color:#a5d6ff}.dark .highlight .chroma .se{color:#79c0ff}.dark .highlight .chroma .sh{color:#79c0ff}.dark .highlight .chroma .si{color:#a5d6ff}.dark .highlight .chroma .sx{color:#a5d6ff}.dark .highlight .chroma .sr{color:#79c0ff}.dark .highlight .chroma .s1{color:#a5d6ff}.dark .highlight .chroma .ss{color:#a5d6ff}.dark .highlight .chroma .m{color:#a5d6ff}.dark .highlight .chroma .mb{color:#a5d6ff}.dark .highlight .chroma .mf{color:#a5d6ff}.dark .highlight .chroma .mh{color:#a5d6ff}.dark .highlight .chroma .mi{color:#a5d6ff}.dark .highlight .chroma .il{color:#a5d6ff}.dark .highlight .chroma .mo{color:#a5d6ff}.dark .highlight .chroma .o{color:#ff7b72;font-weight:700}.dark .highlight .chroma .ow{color:#ff7b72;font-weight:700}.dark .highlight .chroma .p{}.dark .highlight .chroma .c{color:#8b949e;font-style:italic}.dark .highlight .chroma .ch{color:#8b949e;font-style:italic}.dark .highlight .chroma .cm{color:#8b949e;font-style:italic}.dark .highlight .chroma .c1{color:#8b949e;font-style:italic}.dark .highlight .chroma .cs{color:#8b949e;font-weight:700;font-style:italic}.dark .highlight .chroma .cp{color:#8b949e;font-weight:700;font-style:italic}.dark .highlight .chroma .cpf{color:#8b949e;font-weight:700;font-style:italic}.dark .highlight .chroma .g{}.dark .highlight .chroma .gd{color:#ffa198;background-color:#490202}.dark .highlight .chroma .ge{color:inherit;font-style:italic}.dark .highlight .chroma .gr{color:#ffa198}.dark .highlight .chroma .gh{color:#79c0ff;font-weight:700}.dark .highlight .chroma .gi{color:#56d364;background-color:#0f5323}.dark .highlight .chroma .go{color:#8b949e}.dark .highlight .chroma .gp{color:#8b949e}.dark .highlight .chroma .gs{font-weight:700}.dark .highlight .chroma .gu{color:#79c0ff}.dark .highlight .chroma .gt{color:#ff7b72}.dark .highlight .chroma .gl{text-decoration:underline}.dark .highlight .chroma .w{color:#6e7681}.hextra-code-block{font-size:.9em;line-height:1.25rem}.hextra-code-block pre{overflow-x:auto;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05);font-size:.9em;font-weight:500;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}@media(prefers-contrast:more){.hextra-code-block pre{border-width:1px;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 24)/.2);--tw-contrast:contrast(1.5);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}}.hextra-code-block pre:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1)}@media(prefers-contrast:more){.hextra-code-block pre:is(html[class~=dark] *){border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.4)}}.hextra-code-block .filename{position:absolute;top:0;z-index:1;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-top-left-radius:.75rem;border-top-right-radius:.75rem;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/.05);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;padding-right:1rem;font-size:.75rem;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hextra-code-block .filename:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1);--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.hextra-code-block .filename+pre:not(.lntable pre){padding-top:3rem}.hextra-code-block pre:not(.lntable pre){margin-bottom:1rem;border-radius:.75rem;padding-left:1rem;padding-right:1rem;padding-top:1rem;padding-bottom:1rem}.hextra-code-block div:nth-of-type(2) pre{padding-top:3rem;padding-bottom:1rem}.chroma .lntable{margin:0;display:block;width:auto;overflow:auto;border-radius:.75rem}.chroma .lntable pre{padding-top:1rem;padding-bottom:1rem}.chroma .ln,.chroma .lnt:not(.hl>.lnt),.chroma .hl:not(.line){min-width:2.6rem;padding-left:1rem;padding-right:1rem;--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity))}.chroma .ln:is(html[class~=dark] *),.chroma .lnt:not(.hl>.lnt):is(html[class~=dark] *),.chroma .hl:not(.line):is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(212 212 212/var(--tw-text-opacity))}.chroma .lntd{padding:0;vertical-align:top}.chroma .lntd:last-of-type{width:100%}.chroma .hl{display:block;width:100%;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 32)/.1)}.hextra-cards{grid-template-columns:repeat(auto-fill,minmax(max(250px,calc((100% - 1rem * 2)/var(--hextra-cards-grid-cols))),1fr))}.hextra-card{position:relative}.hextra-card img{-webkit-user-select:none;-moz-user-select:none;user-select:none}.hextra-card:hover svg{color:currentColor}.hextra-card svg{width:1.5rem;color:#0003;transition:color .3s ease}.hextra-card p{margin-top:.5rem;position:relative}.dark .hextra-card svg{color:#fff6}.dark .hextra-card:hover svg{color:currentColor}.hextra-card-tag{position:absolute;top:5px;right:5px;z-index:10}.steps h3{counter-increment:step}.steps h3:before{position:absolute;height:33px;width:33px;border-width:4px;--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.steps h3:is(html[class~=dark] *):before{--tw-border-opacity:1;border-color:rgb(17 17 17/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.steps h3:before{border-radius:9999px;text-align:center;text-indent:-1px;font-size:1rem;font-weight:400;--tw-text-opacity:1;color:rgb(163 163 163/var(--tw-text-opacity));margin-top:3px}.steps h3:where([dir=ltr],[dir=ltr] *):before{margin-left:-41px}.steps h3:where([dir=rtl],[dir=rtl] *):before{margin-right:-44px}.steps h3:before{content:counter(step)}:lang(fa) .steps h3:before{content:counter(step,persian)}.search-wrapper li{margin-left:.625rem;margin-right:.625rem;overflow-wrap:break-word;border-radius:.375rem;--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}@media(prefers-contrast:more){.search-wrapper li{border-width:1px;border-color:transparent}}.search-wrapper li:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.search-wrapper li a{display:block;scroll-margin:3rem;padding-left:.625rem;padding-right:.625rem;padding-top:.5rem;padding-bottom:.5rem}.search-wrapper li .title{font-size:1rem;font-weight:600;line-height:1.25rem}.search-wrapper li .active{border-radius:.375rem;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/.1)}@media(prefers-contrast:more){.search-wrapper li .active{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}}.search-wrapper .no-result{display:block;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:2rem;text-align:center;font-size:.875rem;--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.search-wrapper .prefix{margin-left:.625rem;margin-right:.625rem;margin-bottom:.5rem;margin-top:1.5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;border-bottom-width:1px;border-color:rgb(0 0 0/.1);padding-left:.625rem;padding-right:.625rem;padding-bottom:.375rem;font-size:.75rem;font-weight:600;text-transform:uppercase;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.search-wrapper .prefix:first-child{margin-top:0}@media(prefers-contrast:more){.search-wrapper .prefix{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}}.search-wrapper .prefix:is(html[class~=dark] *){border-color:rgb(255 255 255/.2);--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}@media(prefers-contrast:more){.search-wrapper .prefix:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}}.search-wrapper .excerpt{margin-top:.25rem;overflow:hidden;text-overflow:ellipsis;font-size:.875rem;line-height:1.35rem;--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.search-wrapper .excerpt:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}@media(prefers-contrast:more){.search-wrapper .excerpt:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}}.search-wrapper .excerpt{display:-webkit-box;line-clamp:1;-webkit-line-clamp:1;-webkit-box-orient:vertical}.search-wrapper .match{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}@media(max-width:767px){.sidebar-container{position:fixed;top:0;bottom:0;z-index:15;width:100%;overscroll-behavior:contain;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding-top:calc(var(--navbar-height))}.sidebar-container:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.sidebar-container{transition:transform .8s cubic-bezier(.52,.16,.04,1);will-change:transform,opacity;contain:layout style;backface-visibility:hidden}}.sidebar-container li>div{height:0}.sidebar-container li.open>div{height:auto;padding-top:.25rem}.sidebar-container li.open>a>span>svg>path{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}nav .search-wrapper{display:none}@media(min-width:768px){nav .search-wrapper{display:inline-block}}@supports(((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px)))){.nav-container-blur{background-color:rgb(255 255 255/.85);--tw-backdrop-blur:blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.nav-container-blur:is(html[class~=dark] *){background-color:rgb(17 17 17/.8) !important}}.hamburger-menu svg g{transform-origin:center;transition:transform .2s cubic-bezier(.25,1,.5,1)}.hamburger-menu svg path{opacity:1;transition:transform .2s cubic-bezier(.25,1,.5,1).2s,opacity .2s ease .2s}.hamburger-menu svg.open path{transition:transform .2s cubic-bezier(.25,1,.5,1),opacity 0s ease .2s}.hamburger-menu svg.open g{transition:transform .2s cubic-bezier(.25,1,.5,1).2s}.hamburger-menu svg.open>path{opacity:0}.hamburger-menu svg.open>g:nth-of-type(1){--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hamburger-menu svg.open>g:nth-of-type(1) path{transform:translate3d(0,4px,0)}.hamburger-menu svg.open>g:nth-of-type(2){--tw-rotate:-45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hamburger-menu svg.open>g:nth-of-type(2) path{transform:translate3d(0,-4px,0)}.hextra-scrollbar,.hextra-scrollbar *{scrollbar-width:thin;scrollbar-color:oklch(55.55% 0 0/40%)transparent;scrollbar-gutter:stable}.hextra-scrollbar::-webkit-scrollbar,.hextra-scrollbar *::-webkit-scrollbar{height:.75rem;width:.75rem}.hextra-scrollbar::-webkit-scrollbar-track,.hextra-scrollbar *::-webkit-scrollbar-track{background-color:transparent}.hextra-scrollbar::-webkit-scrollbar-thumb,.hextra-scrollbar *::-webkit-scrollbar-thumb{border-radius:10px}.hextra-scrollbar:hover::-webkit-scrollbar-thumb,.hextra-scrollbar *:hover::-webkit-scrollbar-thumb{border:3px solid transparent;background-color:var(--tw-shadow-color);background-clip:content-box;--tw-shadow-color:rgb(115 115 115 / 0.2);--tw-shadow:var(--tw-shadow-colored)}.hextra-scrollbar:hover::-webkit-scrollbar-thumb:hover,.hextra-scrollbar *:hover::-webkit-scrollbar-thumb:hover{--tw-shadow-color:rgb(115 115 115 / 0.4);--tw-shadow:var(--tw-shadow-colored)}@supports(((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px)))){.hextra-code-copy-btn{--tw-bg-opacity:.85;--tw-backdrop-blur:blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.hextra-code-copy-btn:is(html[class~=dark] *){--tw-bg-opacity:0.8}}@media(min-width:1024px){.hextra-feature-grid{grid-template-columns:repeat(var(--hextra-feature-grid-cols),minmax(0,1fr))}}.hextra-jupyter-code-cell{scrollbar-gutter:auto;margin-top:1.5rem}.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container{overflow:hidden;font-size:.75rem}.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs{max-height:50vh;overflow:auto}.hextra-jupyter-code-cell .hextra-jupyter-code-cell-outputs-container .hextra-jupyter-code-cell-outputs pre{max-width:100%;overflow:auto;font-size:.75rem}.hextra-badge{display:inline-flex;align-items:center}html{font-size:1rem;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:"rlig" 1,"calt" 1,"ss01" 1;-webkit-tap-highlight-color:transparent}body{width:100%;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}body:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:root{--primary-hue:212deg;--primary-saturation:100%;--primary-lightness:50%;--navbar-height:4rem;--menu-height:3.75rem}.dark{--primary-hue:204deg;--primary-saturation:100%;--primary-lightness:50%}.placeholder\:hx-text-gray-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.placeholder\:hx-text-gray-500::placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.before\:hx-pointer-events-none::before{content:var(--tw-content);pointer-events:none}.before\:hx-absolute::before{content:var(--tw-content);position:absolute}.before\:hx-inset-0::before{content:var(--tw-content);inset:0}.before\:hx-inset-y-1::before{content:var(--tw-content);top:.25rem;bottom:.25rem}.before\:hx-mr-1::before{content:var(--tw-content);margin-right:.25rem}.before\:hx-inline-block::before{content:var(--tw-content);display:inline-block}.before\:hx-w-px::before{content:var(--tw-content);width:1px}.before\:hx-bg-gray-200::before{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.before\:hx-opacity-25::before{content:var(--tw-content);opacity:.25}.before\:hx-transition-transform::before{content:var(--tw-content);transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.before\:hx-content-\[\'\#\'\]::before{--tw-content:'#';content:var(--tw-content)}.before\:hx-content-\[\'\'\]::before{--tw-content:'';content:var(--tw-content)}.before\:hx-content-\[\\\"\\\"\]::before{--tw-content:\"\";content:var(--tw-content)}.first\:hx-mt-0:first-child{margin-top:0}.last-of-type\:hx-mb-0:last-of-type{margin-bottom:0}.hover\:hx-border-gray-200:hover{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.hover\:hx-border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:hx-border-gray-400:hover{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.hover\:hx-border-gray-900:hover{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.hover\:hx-bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:hx-bg-gray-800\/5:hover{background-color:rgb(31 41 55/5%)}.hover\:hx-bg-primary-50:hover{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 47)/var(--tw-bg-opacity))}.hover\:hx-bg-primary-700:hover{--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/var(--tw-bg-opacity))}.hover\:hx-bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity))}.hover\:hx-text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.hover\:hx-text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:hx-text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:hx-text-primary-600:hover{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.hover\:hx-opacity-60:hover{opacity:.6}.hover\:hx-opacity-75:hover{opacity:.75}.hover\:hx-shadow-lg:hover{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:hx-shadow-md:hover{--tw-shadow:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:hx-shadow-gray-100:hover{--tw-shadow-color:#f3f4f6;--tw-shadow:var(--tw-shadow-colored)}.focus\:hx-bg-white:focus{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.focus\:hx-outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:hx-ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:hx-ring-primary-300:focus{--tw-ring-opacity:1;--tw-ring-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / var(--tw-ring-opacity))}.active\:hx-bg-gray-400\/20:active{background-color:rgb(156 163 175/.2)}.active\:hx-opacity-50:active{opacity:.5}.active\:hx-shadow-sm:active{--tw-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.active\:hx-shadow-gray-200:active{--tw-shadow-color:#e5e7eb;--tw-shadow:var(--tw-shadow-colored)}.hx-group[open] .group-open\:before\:hx-rotate-90::before{content:var(--tw-content);--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hx-group:hover .group-hover\:hx-underline{text-decoration-line:underline}.hx-group\/code:hover .group-hover\/code\:hx-opacity-100{opacity:1}.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-block{display:block}.hx-group\/copybtn.copied .group-\[\.copied\]\/copybtn\:hx-hidden{display:none}.data-\[state\=selected\]\:hx-block[data-state=selected]{display:block}.data-\[state\=closed\]\:hx-hidden[data-state=closed]{display:none}.data-\[state\=open\]\:hx-hidden[data-state=open]{display:none}.data-\[state\=selected\]\:hx-border-primary-500[data-state=selected]{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.data-\[state\=selected\]\:hx-text-primary-600[data-state=selected]{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.hx-group[data-theme=dark] .group-data-\[theme\=dark\]\:hx-hidden{display:none}.hx-group[data-theme=light] .group-data-\[theme\=light\]\:hx-hidden{display:none}@media(prefers-contrast:more){.contrast-more\:hx-border{border-width:1px}.contrast-more\:hx-border-t{border-top-width:1px}.contrast-more\:hx-border-current{border-color:initial}.contrast-more\:hx-border-gray-800{--tw-border-opacity:1;border-color:rgb(31 41 55/var(--tw-border-opacity))}.contrast-more\:hx-border-gray-900{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.contrast-more\:hx-border-neutral-400{--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.contrast-more\:hx-border-primary-500{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.contrast-more\:hx-border-transparent{border-color:transparent}.contrast-more\:hx-font-bold{font-weight:700}.contrast-more\:hx-text-current{color:currentColor}.contrast-more\:hx-text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.contrast-more\:hx-text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.contrast-more\:hx-text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.contrast-more\:hx-underline{text-decoration-line:underline}.contrast-more\:hx-shadow-\[0_0_0_1px_\#000\]{--tw-shadow:0 0 0 1px #000;--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:hx-shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:hover\:hx-border-gray-900:hover{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}}.dark\:hx-block:is(html[class~=dark] *){display:block}.dark\:hx-hidden:is(html[class~=dark] *){display:none}.dark\:hx-border-amber-200\/30:is(html[class~=dark] *){border-color:rgb(253 230 138/.3)}.dark\:hx-border-blue-200\/30:is(html[class~=dark] *){border-color:rgb(191 219 254/.3)}.dark\:hx-border-gray-100\/20:is(html[class~=dark] *){border-color:rgb(243 244 246/.2)}.dark\:hx-border-gray-400:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.dark\:hx-border-green-200\/30:is(html[class~=dark] *){border-color:rgb(187 247 208/.3)}.dark\:hx-border-indigo-200\/30:is(html[class~=dark] *){border-color:rgb(199 210 254/.3)}.dark\:hx-border-neutral-700:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(64 64 64/var(--tw-border-opacity))}.dark\:hx-border-neutral-800:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark\:hx-border-orange-400\/30:is(html[class~=dark] *){border-color:rgb(251 146 60/.3)}.dark\:hx-border-red-200\/30:is(html[class~=dark] *){border-color:rgb(254 202 202/.3)}.dark\:hx-border-white\/10:is(html[class~=dark] *){border-color:rgb(255 255 255/.1)}.dark\:hx-border-yellow-200\/30:is(html[class~=dark] *){border-color:rgb(254 240 138/.3)}.dark\:hx-bg-amber-900\/30:is(html[class~=dark] *){background-color:rgb(120 53 15/.3)}.dark\:hx-bg-black\/60:is(html[class~=dark] *){background-color:rgb(0 0 0/.6)}.dark\:hx-bg-blue-900\/30:is(html[class~=dark] *){background-color:rgb(30 58 138/.3)}.dark\:hx-bg-dark:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark\:hx-bg-dark\/50:is(html[class~=dark] *){background-color:rgb(17 17 17/.5)}.dark\:hx-bg-gray-50\/10:is(html[class~=dark] *){background-color:rgb(249 250 251/.1)}.dark\:hx-bg-green-900\/30:is(html[class~=dark] *){background-color:rgb(20 83 45/.3)}.dark\:hx-bg-indigo-900\/30:is(html[class~=dark] *){background-color:rgb(49 46 129/.3)}.dark\:hx-bg-neutral-800:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark\:hx-bg-neutral-900:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.dark\:hx-bg-orange-400\/20:is(html[class~=dark] *){background-color:rgb(251 146 60/.2)}.dark\:hx-bg-primary-300\/10:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 27)/.1)}.dark\:hx-bg-primary-400\/10:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 16)/.1)}.dark\:hx-bg-primary-600:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-bg-opacity))}.dark\:hx-bg-red-900\/30:is(html[class~=dark] *){background-color:rgb(127 29 29/.3)}.dark\:hx-bg-yellow-700\/30:is(html[class~=dark] *){background-color:rgb(161 98 7/.3)}.dark\:hx-from-gray-100:is(html[class~=dark] *){--tw-gradient-from:#f3f4f6 var(--tw-gradient-from-position);--tw-gradient-to:rgb(243 244 246 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.dark\:hx-to-gray-400:is(html[class~=dark] *){--tw-gradient-to:#9ca3af var(--tw-gradient-to-position)}.dark\:hx-text-amber-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(253 230 138/var(--tw-text-opacity))}.dark\:hx-text-blue-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity))}.dark\:hx-text-gray-100:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark\:hx-text-gray-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark\:hx-text-gray-300:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark\:hx-text-gray-400:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:hx-text-gray-50:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark\:hx-text-green-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity))}.dark\:hx-text-indigo-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(199 210 254/var(--tw-text-opacity))}.dark\:hx-text-neutral-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}.dark\:hx-text-neutral-400:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(163 163 163/var(--tw-text-opacity))}.dark\:hx-text-orange-300:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity))}.dark\:hx-text-primary-600:is(html[class~=dark] *){--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.dark\:hx-text-red-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity))}.dark\:hx-text-slate-100:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity))}.dark\:hx-text-yellow-200:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity))}.dark\:hx-opacity-80:is(html[class~=dark] *){opacity:.8}.dark\:hx-shadow-\[0_-12px_16px_\#111\]:is(html[class~=dark] *){--tw-shadow:0 -12px 16px #111;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:hx-shadow-\[0_-1px_0_rgba\(255\2c 255\2c 255\2c \.1\)_inset\]:is(html[class~=dark] *){--tw-shadow:0 -1px 0 rgba(255,255,255,.1) inset;--tw-shadow-colored:inset 0 -1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:hx-shadow-none:is(html[class~=dark] *){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:hx-ring-white\/20:is(html[class~=dark] *){--tw-ring-color:rgb(255 255 255 / 0.2)}.dark\:placeholder\:hx-text-gray-400:is(html[class~=dark] *)::-moz-placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:placeholder\:hx-text-gray-400:is(html[class~=dark] *)::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark\:before\:hx-bg-neutral-800:is(html[class~=dark] *)::before{content:var(--tw-content);--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark\:before\:hx-invert:is(html[class~=dark] *)::before{content:var(--tw-content);--tw-invert:invert(100%);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.dark\:hover\:hx-border-gray-100:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.dark\:hover\:hx-border-gray-600:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.dark\:hover\:hx-border-neutral-500:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(115 115 115/var(--tw-border-opacity))}.dark\:hover\:hx-border-neutral-700:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(64 64 64/var(--tw-border-opacity))}.dark\:hover\:hx-border-neutral-800:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark\:hover\:hx-bg-gray-100\/5:hover:is(html[class~=dark] *){background-color:rgb(243 244 246/5%)}.dark\:hover\:hx-bg-neutral-700:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(64 64 64/var(--tw-bg-opacity))}.dark\:hover\:hx-bg-neutral-800:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark\:hover\:hx-bg-neutral-900:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.dark\:hover\:hx-bg-primary-100\/5:hover:is(html[class~=dark] *){background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness))/50) * 44)/.05)}.dark\:hover\:hx-bg-primary-700:hover:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 39)/var(--tw-bg-opacity))}.hover\:dark\:hx-bg-primary-500\/10:is(html[class~=dark] *):hover{background-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/.1)}.dark\:hover\:hx-text-gray-100:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark\:hover\:hx-text-gray-200:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark\:hover\:hx-text-gray-300:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark\:hover\:hx-text-gray-50:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark\:hover\:hx-text-neutral-50:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(250 250 250/var(--tw-text-opacity))}.dark\:hover\:hx-text-white:hover:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hover\:dark\:hx-text-primary-600:is(html[class~=dark] *):hover{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}.dark\:hover\:hx-shadow-none:hover:is(html[class~=dark] *){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dark\:focus\:hx-bg-dark:focus:is(html[class~=dark] *){--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark\:focus\:hx-ring-primary-800:focus:is(html[class~=dark] *){--tw-ring-opacity:1;--tw-ring-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32) / var(--tw-ring-opacity))}.data-\[state\=selected\]\:dark\:hx-border-primary-500:is(html[class~=dark] *)[data-state=selected]{--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.data-\[state\=selected\]\:dark\:hx-text-primary-600:is(html[class~=dark] *)[data-state=selected]{--tw-text-opacity:1;color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 45)/var(--tw-text-opacity))}@media(prefers-contrast:more){.contrast-more\:dark\:hx-border-current:is(html[class~=dark] *){border-color:initial}.contrast-more\:dark\:hx-border-gray-50:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.contrast-more\:dark\:hx-border-neutral-400:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.contrast-more\:dark\:hx-border-primary-500:is(html[class~=dark] *){--tw-border-opacity:1;border-color:hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness)/50) * 50)/var(--tw-border-opacity))}.dark\:contrast-more\:hx-border-neutral-400:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.contrast-more\:dark\:hx-text-current:is(html[class~=dark] *){color:currentColor}.contrast-more\:dark\:hx-text-gray-100:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.contrast-more\:dark\:hx-text-gray-300:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.contrast-more\:dark\:hx-text-gray-50:is(html[class~=dark] *){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.contrast-more\:dark\:hx-shadow-\[0_0_0_1px_\#fff\]:is(html[class~=dark] *){--tw-shadow:0 0 0 1px #fff;--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:dark\:hx-shadow-none:is(html[class~=dark] *){--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.contrast-more\:dark\:hover\:hx-border-gray-50:hover:is(html[class~=dark] *){--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}}@media not all and (min-width:1280px){.max-xl\:hx-hidden{display:none}}@media not all and (min-width:1024px){.max-lg\:hx-min-h-\[340px\]{min-height:340px}}@media not all and (min-width:768px){.max-md\:hx-hidden{display:none}.max-md\:hx-min-h-\[340px\]{min-height:340px}.max-md\:\[transform\:translate3d\(0\2c -100\%\2c 0\)\]{transform:translate3d(0,-100%,0)}}@media not all and (min-width:640px){.max-sm\:hx-grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}}@media(min-width:640px){.sm\:hx-block{display:block}.sm\:hx-flex{display:flex}.sm\:hx-w-\[110\%\]{width:110%}.sm\:hx-items-start{align-items:flex-start}.sm\:hx-text-xl{font-size:1.25rem}@media not all and (min-width:1024px){.sm\:max-lg\:hx-grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}}@media(min-width:768px){.md\:hx-sticky{position:sticky}.md\:hx-top-16{top:4rem}.md\:hx-inline-block{display:inline-block}.md\:hx-hidden{display:none}.md\:hx-aspect-\[1\.1\/1\]{aspect-ratio:1.1/1}.md\:hx-h-\[calc\(100vh-var\(--navbar-height\)-var\(--menu-height\)\)\]{height:calc(100vh - var(--navbar-height) - var(--menu-height))}.md\:hx-max-h-\[min\(calc\(100vh-5rem-env\(safe-area-inset-bottom\)\)\2c 400px\)\]{max-height:min(calc(100vh - 5rem - env(safe-area-inset-bottom)),400px)}.md\:hx-w-64{width:16rem}.md\:hx-shrink-0{flex-shrink:0}.md\:hx-grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:hx-justify-start{justify-content:flex-start}.md\:hx-self-start{align-self:flex-start}.md\:hx-px-12{padding-left:3rem;padding-right:3rem}.md\:hx-pt-12{padding-top:3rem}.md\:hx-text-5xl{font-size:3rem}.md\:hx-text-lg{font-size:1.125rem}.md\:hx-text-sm{font-size:.875rem}}@media(min-width:1024px){.lg\:hx-grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:1280px){.xl\:hx-block{display:block}.xl\:hx-grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}.ltr\:hx-right-1\.5:where([dir=ltr],[dir=ltr] *){right:.375rem}.ltr\:hx-right-3:where([dir=ltr],[dir=ltr] *){right:.75rem}.ltr\:hx--mr-4:where([dir=ltr],[dir=ltr] *){margin-right:-1rem}.ltr\:hx-ml-1:where([dir=ltr],[dir=ltr] *){margin-left:.25rem}.ltr\:hx-ml-3:where([dir=ltr],[dir=ltr] *){margin-left:.75rem}.ltr\:hx-ml-auto:where([dir=ltr],[dir=ltr] *){margin-left:auto}.ltr\:hx-mr-auto:where([dir=ltr],[dir=ltr] *){margin-right:auto}.ltr\:hx-rotate-180:where([dir=ltr],[dir=ltr] *){--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.ltr\:hx-border-l:where([dir=ltr],[dir=ltr] *){border-left-width:1px}.ltr\:hx-pl-12:where([dir=ltr],[dir=ltr] *){padding-left:3rem}.ltr\:hx-pl-16:where([dir=ltr],[dir=ltr] *){padding-left:4rem}.ltr\:hx-pl-3:where([dir=ltr],[dir=ltr] *){padding-left:.75rem}.ltr\:hx-pl-4:where([dir=ltr],[dir=ltr] *){padding-left:1rem}.ltr\:hx-pl-5:where([dir=ltr],[dir=ltr] *){padding-left:1.25rem}.ltr\:hx-pl-6:where([dir=ltr],[dir=ltr] *){padding-left:1.5rem}.ltr\:hx-pl-8:where([dir=ltr],[dir=ltr] *){padding-left:2rem}.ltr\:hx-pr-0:where([dir=ltr],[dir=ltr] *){padding-right:0}.ltr\:hx-pr-2:where([dir=ltr],[dir=ltr] *){padding-right:.5rem}.ltr\:hx-pr-4:where([dir=ltr],[dir=ltr] *){padding-right:1rem}.ltr\:hx-pr-9:where([dir=ltr],[dir=ltr] *){padding-right:2.25rem}.ltr\:hx-text-right:where([dir=ltr],[dir=ltr] *){text-align:right}.ltr\:before\:hx-left-0:where([dir=ltr],[dir=ltr] *)::before{content:var(--tw-content);left:0}@media(min-width:768px){.ltr\:md\:hx-left-auto:where([dir=ltr],[dir=ltr] *){left:auto}}.rtl\:hx-left-1\.5:where([dir=rtl],[dir=rtl] *){left:.375rem}.rtl\:hx-left-3:where([dir=rtl],[dir=rtl] *){left:.75rem}.rtl\:hx--ml-4:where([dir=rtl],[dir=rtl] *){margin-left:-1rem}.rtl\:hx-ml-auto:where([dir=rtl],[dir=rtl] *){margin-left:auto}.rtl\:hx-mr-1:where([dir=rtl],[dir=rtl] *){margin-right:.25rem}.rtl\:hx-mr-3:where([dir=rtl],[dir=rtl] *){margin-right:.75rem}.rtl\:hx-mr-auto:where([dir=rtl],[dir=rtl] *){margin-right:auto}.rtl\:-hx-rotate-180:where([dir=rtl],[dir=rtl] *){--tw-rotate:-180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.rtl\:hx-border-r:where([dir=rtl],[dir=rtl] *){border-right-width:1px}.rtl\:hx-pl-2:where([dir=rtl],[dir=rtl] *){padding-left:.5rem}.rtl\:hx-pl-4:where([dir=rtl],[dir=rtl] *){padding-left:1rem}.rtl\:hx-pl-9:where([dir=rtl],[dir=rtl] *){padding-left:2.25rem}.rtl\:hx-pr-12:where([dir=rtl],[dir=rtl] *){padding-right:3rem}.rtl\:hx-pr-16:where([dir=rtl],[dir=rtl] *){padding-right:4rem}.rtl\:hx-pr-3:where([dir=rtl],[dir=rtl] *){padding-right:.75rem}.rtl\:hx-pr-4:where([dir=rtl],[dir=rtl] *){padding-right:1rem}.rtl\:hx-pr-5:where([dir=rtl],[dir=rtl] *){padding-right:1.25rem}.rtl\:hx-pr-6:where([dir=rtl],[dir=rtl] *){padding-right:1.5rem}.rtl\:hx-pr-8:where([dir=rtl],[dir=rtl] *){padding-right:2rem}.rtl\:hx-text-left:where([dir=rtl],[dir=rtl] *){text-align:left}.rtl\:before\:hx-right-0:where([dir=rtl],[dir=rtl] *)::before{content:var(--tw-content);right:0}.rtl\:before\:hx-rotate-180:where([dir=rtl],[dir=rtl] *)::before{content:var(--tw-content);--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}@media(min-width:768px){.rtl\:md\:hx-right-auto:where([dir=rtl],[dir=rtl] *){right:auto}}@media print{.print\:hx-hidden{display:none}.print\:hx-bg-transparent{background-color:transparent}} \ No newline at end of file diff --git a/public/css/custom.css b/public/css/custom.css deleted file mode 100644 index e69de29..0000000 diff --git a/public/css/custom.min.e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css b/public/css/custom.min.e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css deleted file mode 100644 index e69de29..0000000 diff --git a/public/docs/01-introduction/index.html b/public/docs/01-introduction/index.html deleted file mode 100644 index 40f1c74..0000000 --- a/public/docs/01-introduction/index.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - - -Introduction – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      -
      Documentation
      -
      - -
      -

      Introduction

      -

      Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.

      -

      go-form is heavily influenced by Symfony Form. It includes:

      -
        -
      • A form builder based on fields declarations and independent of structs
      • -
      • Validation based on constraints
      • -
      • Data mounting to populate a form from a struct instance
      • -
      • Data binding to populate a struct instance from a submitted form
      • -
      • Form renderer with customizable themes
      • -
      -

      Questions or Feedback? -

      - -
      fmt.Sprintf("foo")
      - -
      -
      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/02-installation/index.html b/public/docs/02-installation/index.html deleted file mode 100644 index f75c605..0000000 --- a/public/docs/02-installation/index.html +++ /dev/null @@ -1,252 +0,0 @@ - - - - - - - - - - - - -Installation – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/button/index.html b/public/docs/button/index.html deleted file mode 100644 index 494d61e..0000000 --- a/public/docs/button/index.html +++ /dev/null @@ -1,467 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/constraints/index.html b/public/docs/constraints/index.html deleted file mode 100644 index c761209..0000000 --- a/public/docs/constraints/index.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - - - - - - -Constraints – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      -
      Constraints
      -
      - -
      -

      Constraints

      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/constraints/index.xml b/public/docs/constraints/index.xml deleted file mode 100644 index dcc34a3..0000000 --- a/public/docs/constraints/index.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - deblan/go-form – Constraints - http://localhost:1313/docs/constraints/ - Recent content in Constraints on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - diff --git a/public/docs/field/date/date/index.html b/public/docs/field/date/date/index.html deleted file mode 100644 index 24ea0fe..0000000 --- a/public/docs/field/date/date/index.html +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - - -Date – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/date/datetime/index.html b/public/docs/field/date/datetime/index.html deleted file mode 100644 index e81c6e3..0000000 --- a/public/docs/field/date/datetime/index.html +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - -Datetime – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/date/index.html b/public/docs/field/date/index.html deleted file mode 100644 index 26496a4..0000000 --- a/public/docs/field/date/index.html +++ /dev/null @@ -1,455 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/date/index.xml b/public/docs/field/date/index.xml deleted file mode 100644 index e8ee8b2..0000000 --- a/public/docs/field/date/index.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - deblan/go-form – - http://localhost:1313/docs/field/date/ - Recent content on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Date - http://localhost:1313/docs/field/date/date/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/date/date/ - - - - - - - - - Datetime - http://localhost:1313/docs/field/date/datetime/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/date/datetime/ - - - - - - - - - Time - http://localhost:1313/docs/field/date/time/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/date/time/ - - - - - - - - - diff --git a/public/docs/field/date/time/index.html b/public/docs/field/date/time/index.html deleted file mode 100644 index a272036..0000000 --- a/public/docs/field/date/time/index.html +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - - -Time – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/index.html b/public/docs/field/index.html deleted file mode 100644 index f760ecf..0000000 --- a/public/docs/field/index.html +++ /dev/null @@ -1,452 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/index.xml b/public/docs/field/index.xml deleted file mode 100644 index 97425df..0000000 --- a/public/docs/field/index.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - deblan/go-form – - http://localhost:1313/docs/field/ - Recent content on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Input - http://localhost:1313/docs/field/input/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - - http://localhost:1313/docs/field/date/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/date/ - - - - - - - - - diff --git a/public/docs/field/input/hidden/index.html b/public/docs/field/input/hidden/index.html deleted file mode 100644 index 825a09e..0000000 --- a/public/docs/field/input/hidden/index.html +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - - -Hidden – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/input/index.html b/public/docs/field/input/index.html deleted file mode 100644 index 68a11a4..0000000 --- a/public/docs/field/input/index.html +++ /dev/null @@ -1,461 +0,0 @@ - - - - - - - - - - - - -Input – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/input/index.xml b/public/docs/field/input/index.xml deleted file mode 100644 index a3d7aea..0000000 --- a/public/docs/field/input/index.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - deblan/go-form – Input - http://localhost:1313/docs/field/input/ - Recent content in Input on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Hidden - http://localhost:1313/docs/field/input/hidden/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/hidden/ - - - - - - - - - Mail - http://localhost:1313/docs/field/input/mail/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/mail/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Number - http://localhost:1313/docs/field/input/number/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/number/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Password - http://localhost:1313/docs/field/input/password/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/password/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Range - http://localhost:1313/docs/field/input/range/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/range/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Text - http://localhost:1313/docs/field/input/text/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/field/input/text/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - diff --git a/public/docs/field/input/mail/index.html b/public/docs/field/input/mail/index.html deleted file mode 100644 index b0aacf8..0000000 --- a/public/docs/field/input/mail/index.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - - - - - - - - -Mail – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/input/number/index.html b/public/docs/field/input/number/index.html deleted file mode 100644 index e35ddda..0000000 --- a/public/docs/field/input/number/index.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - - - - - - - - -Number – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/input/password/index.html b/public/docs/field/input/password/index.html deleted file mode 100644 index 2484c46..0000000 --- a/public/docs/field/input/password/index.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - - - - - - - - -Password – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/input/range/index.html b/public/docs/field/input/range/index.html deleted file mode 100644 index ba260dd..0000000 --- a/public/docs/field/input/range/index.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - - - - - - - - -Range – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/input/text/index.html b/public/docs/field/input/text/index.html deleted file mode 100644 index 6ed4142..0000000 --- a/public/docs/field/input/text/index.html +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - - - - - - -Text – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/field/text/index.html b/public/docs/field/text/index.html deleted file mode 100644 index 768359e..0000000 --- a/public/docs/field/text/index.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - -Text – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/button/index.html b/public/docs/fields/button/index.html deleted file mode 100644 index 5250cb6..0000000 --- a/public/docs/fields/button/index.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/date/date/index.html b/public/docs/fields/date/date/index.html deleted file mode 100644 index 38b5231..0000000 --- a/public/docs/fields/date/date/index.html +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - - -Date – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/date/datetime/index.html b/public/docs/fields/date/datetime/index.html deleted file mode 100644 index 67cdac7..0000000 --- a/public/docs/fields/date/datetime/index.html +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - -Datetime – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/date/index.html b/public/docs/fields/date/index.html deleted file mode 100644 index 25b15c9..0000000 --- a/public/docs/fields/date/index.html +++ /dev/null @@ -1,455 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/date/index.xml b/public/docs/fields/date/index.xml deleted file mode 100644 index 4895401..0000000 --- a/public/docs/fields/date/index.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - deblan/go-form – - http://localhost:1313/docs/fields/date/ - Recent content on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Date - http://localhost:1313/docs/fields/date/date/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/date/date/ - - - - - - - - - Datetime - http://localhost:1313/docs/fields/date/datetime/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/date/datetime/ - - - - - - - - - Time - http://localhost:1313/docs/fields/date/time/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/date/time/ - - - - - - - - - diff --git a/public/docs/fields/date/time/index.html b/public/docs/fields/date/time/index.html deleted file mode 100644 index bd0c000..0000000 --- a/public/docs/fields/date/time/index.html +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - - -Time – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/index.html b/public/docs/fields/index.html deleted file mode 100644 index 60af09b..0000000 --- a/public/docs/fields/index.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - - - - - - -Input – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/index.xml b/public/docs/fields/index.xml deleted file mode 100644 index e97f0bb..0000000 --- a/public/docs/fields/index.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - deblan/go-form – Input - http://localhost:1313/docs/fields/ - Recent content in Input on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Input - http://localhost:1313/docs/fields/input/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - - http://localhost:1313/docs/fields/button/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/button/ - - - - - - - - - - http://localhost:1313/docs/fields/textarea/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/textarea/ - - - - - - - - - diff --git a/public/docs/fields/input/date/index.html b/public/docs/fields/input/date/index.html deleted file mode 100644 index 8122eff..0000000 --- a/public/docs/fields/input/date/index.html +++ /dev/null @@ -1,568 +0,0 @@ - - - - - - - - - - - - -Date – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/datetime/index.html b/public/docs/fields/input/datetime/index.html deleted file mode 100644 index fe09d6e..0000000 --- a/public/docs/fields/input/datetime/index.html +++ /dev/null @@ -1,568 +0,0 @@ - - - - - - - - - - - - -Datetime – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/hidden/index.html b/public/docs/fields/input/hidden/index.html deleted file mode 100644 index 13f7ae5..0000000 --- a/public/docs/fields/input/hidden/index.html +++ /dev/null @@ -1,564 +0,0 @@ - - - - - - - - - - - - -Hidden – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/index.html b/public/docs/fields/input/index.html deleted file mode 100644 index ff57912..0000000 --- a/public/docs/fields/input/index.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - - - - - - - - - -Input – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/index.xml b/public/docs/fields/input/index.xml deleted file mode 100644 index fd062a4..0000000 --- a/public/docs/fields/input/index.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - deblan/go-form – Input - http://localhost:1313/docs/fields/input/ - Recent content in Input on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Hidden - http://localhost:1313/docs/fields/input/hidden/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/hidden/ - - - - - - - - - Date - http://localhost:1313/docs/fields/input/date/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/date/ - - - - - - - - - Datetime - http://localhost:1313/docs/fields/input/datetime/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/datetime/ - - - - - - - - - Mail - http://localhost:1313/docs/fields/input/mail/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/mail/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Number - http://localhost:1313/docs/fields/input/number/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/number/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Password - http://localhost:1313/docs/fields/input/password/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/password/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Range - http://localhost:1313/docs/fields/input/range/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/range/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Text - http://localhost:1313/docs/fields/input/text/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/text/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Time - http://localhost:1313/docs/fields/input/time/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/time/ - - - - - - - - - diff --git a/public/docs/fields/input/mail/index.html b/public/docs/fields/input/mail/index.html deleted file mode 100644 index aea61c4..0000000 --- a/public/docs/fields/input/mail/index.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - -Mail – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/number/index.html b/public/docs/fields/input/number/index.html deleted file mode 100644 index 2295584..0000000 --- a/public/docs/fields/input/number/index.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - -Number – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/password/index.html b/public/docs/fields/input/password/index.html deleted file mode 100644 index 664dec8..0000000 --- a/public/docs/fields/input/password/index.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - -Password – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/range/index.html b/public/docs/fields/input/range/index.html deleted file mode 100644 index 87e2874..0000000 --- a/public/docs/fields/input/range/index.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - -Range – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/text/index.html b/public/docs/fields/input/text/index.html deleted file mode 100644 index 3fd2b3a..0000000 --- a/public/docs/fields/input/text/index.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - -Text – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/input/time/index.html b/public/docs/fields/input/time/index.html deleted file mode 100644 index 6c5221a..0000000 --- a/public/docs/fields/input/time/index.html +++ /dev/null @@ -1,564 +0,0 @@ - - - - - - - - - - - - -Time – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/fields/textarea/index.html b/public/docs/fields/textarea/index.html deleted file mode 100644 index 932c691..0000000 --- a/public/docs/fields/textarea/index.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/form/bind/index.html b/public/docs/form/bind/index.html deleted file mode 100644 index 67a4c9f..0000000 --- a/public/docs/form/bind/index.html +++ /dev/null @@ -1,650 +0,0 @@ - - - - - - - - - - - - -Bind – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      - -
      - Form -
      Bind
      -
      - -
      -

      Bind

      -
      - -
      import (
      -	"net/http"
      -
      -    "gitnet.fr/deblan/go-form/form"
      -)
      -
      -type Person struct {
      -    Name string
      -    Age  int
      -}
      -
      -func createForm() *form.Form {
      -    f := form.NewForm()
      -
      -    // do stuff
      -
      -    return f
      -}
      -
      -http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
      -    alice := Person{
      -        Name: "Alice",
      -        Age:  42,
      -    }
      -
      -    myForm := createForm()
      -
      -    if r.Method == myForm.Method {
      -        myForm.HandleRequest(r)
      -
      -        if myForm.IsSubmitted() && myForm.IsValid() {
      -            myForm.Bind(&data)
      -        }
      -    }
      -})
      - -
      -
      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/form/index.html b/public/docs/form/index.html deleted file mode 100644 index ff946ed..0000000 --- a/public/docs/form/index.html +++ /dev/null @@ -1,668 +0,0 @@ - - - - - - - - - - - - -Form – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      -
      Form
      -
      - -
      -

      Form

      -

      A form is a struct containing:

      -
        -
      • Fields
      • -
      • Options
      • -
      • Method
      • -
      • Action
      • -
      -

      Import -

      - -
      import (
      -	"net/http"
      -
      -    "gitnet.fr/deblan/go-form/form"
      -)
      - -
      -
      -

      Usage -

      - -
      // Let's create a new form
      -// You can pass *form.Field as arguments
      -myForm := form.NewForm(field1, field2, ...)
      -
      -// Add somes fields
      -myForm.Add(field3, field4, ...)
      -
      -// Set the method
      -// <form method="POST" ...>
      -myForm.WithMethod(http.MethodPost)
      -
      -// Define the action
      -// <form action="/" ...>
      -myForm.WithAction("/")
      -
      -// Set a name
      -myForm.WithName("myForm")
      -
      -// Add options
      -myForm.WithOptions(option1, option2, ...)
      -
      -// When all fields are added, call End()
      -myForm.End()
      - -
      -
      -

      Attributes -

      Some options are natively supported in go-form themes.

      -
      - -
      myForm.WithOptions(
      -    form.NewOption("help", "A help for the form"),
      -    // <form data-foo="bar" data-bar="bar" ...
      -    form.NewOption("attr", map[string]string{
      -        "data-foo": "foo",
      -        "data-bar": "bar",
      -    }),
      -)
      - -
      -
      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/form/index.xml b/public/docs/form/index.xml deleted file mode 100644 index 2a88460..0000000 --- a/public/docs/form/index.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - deblan/go-form – Form - http://localhost:1313/docs/form/ - Recent content in Form on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Mount - http://localhost:1313/docs/form/mount/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/form/mount/ - - - - <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> - -<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="c1">// Assuming 2 fields named &#34;Name&#34; and &#34;Age&#34; exist</span> -</span></span><span class="line"><span class="cl"><span class="nx">myForm</span><span class="p">.</span><span class="nf">Mount</span><span class="p">(</span><span class="nx">alice</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> - <button - class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" - title="Copy code" - > - <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> - <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> - </button> -</div> -</div> - - - - - - Bind - http://localhost:1313/docs/form/bind/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/form/bind/ - - - - <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> - -<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span> -</span></span><span class="line"><span class="cl"> <span class="s">&#34;net/http&#34;</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="s">&#34;gitnet.fr/deblan/go-form/form&#34;</span> -</span></span><span class="line"><span class="cl"><span class="p">)</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">createForm</span><span class="p">()</span> <span class="o">*</span><span class="nx">form</span><span class="p">.</span><span class="nx">Form</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">f</span> <span class="o">:=</span> <span class="nx">form</span><span class="p">.</span><span class="nf">NewForm</span><span class="p">()</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="c1">// do stuff</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">f</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="nx">http</span><span class="p">.</span><span class="nf">HandleFunc</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">w</span> <span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span> <span class="nx">r</span> <span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"> <span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span> <span class="o">:=</span> <span class="nf">createForm</span><span class="p">()</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Method</span> <span class="o">==</span> <span class="nx">myForm</span><span class="p">.</span><span class="nx">Method</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">HandleRequest</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsSubmitted</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsValid</span><span class="p">()</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">Bind</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">data</span><span class="p">)</span> -</span></span><span class="line"><span class="cl"> <span class="p">}</span> -</span></span><span class="line"><span class="cl"> <span class="p">}</span> -</span></span><span class="line"><span class="cl"><span class="p">})</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> - <button - class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" - title="Copy code" - > - <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> - <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> - </button> -</div> -</div> - - - - - - diff --git a/public/docs/form/mount/index.html b/public/docs/form/mount/index.html deleted file mode 100644 index fcd9a48..0000000 --- a/public/docs/form/mount/index.html +++ /dev/null @@ -1,604 +0,0 @@ - - - - - - - - - - - - -Mount – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      - -
      - Form -
      Mount
      -
      - -
      -

      Mount

      -
      - -
      type Person struct {
      -    Name string
      -    Age  int
      -}
      -
      -alice := Person{
      -    Name: "Alice",
      -    Age:  42,
      -}
      -
      -// Assuming 2 fields named "Name" and "Age" exist
      -myForm.Mount(alice)
      - -
      -
      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/index.html b/public/docs/index.html deleted file mode 100644 index ff191fb..0000000 --- a/public/docs/index.html +++ /dev/null @@ -1,608 +0,0 @@ - - - - - - - - - - - - -Introduction – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      Documentation
      -
      - -
      -

      Introduction

      -

      Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.

      -

      go-form is heavily influenced by Symfony Form. It includes:

      -
        -
      • A form builder based on fields declarations and independent of structs
      • -
      • Validation based on constraints
      • -
      • Data mounting to populate a form from a struct instance
      • -
      • Data binding to populate a struct instance from a submitted form
      • -
      • Form renderer with customizable themes
      • -
      -

      Questions or Feedback? -

      - -
      fmt.Sprintf("foo")
      - -
      -
      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/index.xml b/public/docs/index.xml deleted file mode 100644 index 860ea90..0000000 --- a/public/docs/index.xml +++ /dev/null @@ -1,307 +0,0 @@ - - - deblan/go-form – Introduction - http://localhost:1313/docs/ - Recent content in Introduction on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - Mount - http://localhost:1313/docs/form/mount/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/form/mount/ - - - - <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> - -<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="c1">// Assuming 2 fields named &#34;Name&#34; and &#34;Age&#34; exist</span> -</span></span><span class="line"><span class="cl"><span class="nx">myForm</span><span class="p">.</span><span class="nf">Mount</span><span class="p">(</span><span class="nx">alice</span><span class="p">)</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> - <button - class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" - title="Copy code" - > - <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> - <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> - </button> -</div> -</div> - - - - - - Bind - http://localhost:1313/docs/form/bind/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/form/bind/ - - - - <div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code"> - -<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span> -</span></span><span class="line"><span class="cl"> <span class="s">&#34;net/http&#34;</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="s">&#34;gitnet.fr/deblan/go-form/form&#34;</span> -</span></span><span class="line"><span class="cl"><span class="p">)</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span> <span class="kt">string</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span> <span class="kt">int</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">createForm</span><span class="p">()</span> <span class="o">*</span><span class="nx">form</span><span class="p">.</span><span class="nx">Form</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">f</span> <span class="o">:=</span> <span class="nx">form</span><span class="p">.</span><span class="nf">NewForm</span><span class="p">()</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="c1">// do stuff</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">f</span> -</span></span><span class="line"><span class="cl"><span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"><span class="nx">http</span><span class="p">.</span><span class="nf">HandleFunc</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">w</span> <span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span> <span class="nx">r</span> <span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">alice</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Alice&#34;</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"> <span class="nx">Age</span><span class="p">:</span> <span class="mi">42</span><span class="p">,</span> -</span></span><span class="line"><span class="cl"> <span class="p">}</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span> <span class="o">:=</span> <span class="nf">createForm</span><span class="p">()</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">r</span><span class="p">.</span><span class="nx">Method</span> <span class="o">==</span> <span class="nx">myForm</span><span class="p">.</span><span class="nx">Method</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">HandleRequest</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span> -</span></span><span class="line"><span class="cl"> -</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsSubmitted</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="nx">myForm</span><span class="p">.</span><span class="nf">IsValid</span><span class="p">()</span> <span class="p">{</span> -</span></span><span class="line"><span class="cl"> <span class="nx">myForm</span><span class="p">.</span><span class="nf">Bind</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">data</span><span class="p">)</span> -</span></span><span class="line"><span class="cl"> <span class="p">}</span> -</span></span><span class="line"><span class="cl"> <span class="p">}</span> -</span></span><span class="line"><span class="cl"><span class="p">})</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0"> - <button - class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50" - title="Copy code" - > - <div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div> - <div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div> - </button> -</div> -</div> - - - - - - Hidden - http://localhost:1313/docs/fields/input/hidden/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/hidden/ - - - - - - - - - Installation - http://localhost:1313/docs/installation/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/installation/ - - - - <h1>Installation</h1> - - - - - - http://localhost:1313/docs/fields/button/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/button/ - - - - - - - - - - http://localhost:1313/docs/fields/textarea/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/textarea/ - - - - - - - - - - http://localhost:1313/docs/rendering/theming/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/rendering/theming/ - - - - - - - - - Date - http://localhost:1313/docs/fields/input/date/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/date/ - - - - - - - - - Datetime - http://localhost:1313/docs/fields/input/datetime/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/datetime/ - - - - - - - - - Mail - http://localhost:1313/docs/fields/input/mail/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/mail/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Number - http://localhost:1313/docs/fields/input/number/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/number/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Password - http://localhost:1313/docs/fields/input/password/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/password/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Range - http://localhost:1313/docs/fields/input/range/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/range/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Text - http://localhost:1313/docs/fields/input/text/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/text/ - - - - <table> - <tr> - <td>ok</td> - </tr> -</table> - - - - - - Time - http://localhost:1313/docs/fields/input/time/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/fields/input/time/ - - - - - - - - - diff --git a/public/docs/installation/index.html b/public/docs/installation/index.html deleted file mode 100644 index 3e30d1b..0000000 --- a/public/docs/installation/index.html +++ /dev/null @@ -1,557 +0,0 @@ - - - - - - - - - - - - -Installation – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      -
      Installation
      -
      - -
      -

      Installation

      -

      Installation

      -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/introduction/index.html b/public/docs/introduction/index.html deleted file mode 100644 index f9d25fa..0000000 --- a/public/docs/introduction/index.html +++ /dev/null @@ -1,368 +0,0 @@ - - - - - - - - - - - - -Introduction – deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - -
      -
      - -
      -
      Introduction
      -
      - -
      -

      Introduction

      -

      Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.

      -

      go-form is heavily influenced by Symfony Form. It includes:

      -
        -
      • A form builder based on fields declarations and independent of structs
      • -
      • Validation based on constraints
      • -
      • Data mounting to populate a form from a struct instance
      • -
      • Data binding to populate a struct instance from a submitted form
      • -
      • Form renderer with customizable themes
      • -
      -

      Questions or Feedback? -

      - -
      fmt.Sprintf("foo")
      - -
      -
      - -
      -
      - - -
      -
      -
      - -
      - - - - - - diff --git a/public/docs/rendering/index.html b/public/docs/rendering/index.html deleted file mode 100644 index b13e171..0000000 --- a/public/docs/rendering/index.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/docs/rendering/index.xml b/public/docs/rendering/index.xml deleted file mode 100644 index 7f83048..0000000 --- a/public/docs/rendering/index.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - deblan/go-form – - http://localhost:1313/docs/rendering/ - Recent content on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - - - http://localhost:1313/docs/rendering/theming/ - Mon, 01 Jan 0001 00:00:00 +0000 - - http://localhost:1313/docs/rendering/theming/ - - - - - - - - - diff --git a/public/docs/rendering/theming/index.html b/public/docs/rendering/theming/index.html deleted file mode 100644 index 2654d02..0000000 --- a/public/docs/rendering/theming/index.html +++ /dev/null @@ -1,557 +0,0 @@ - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - - - - - -
      - -
      - - - - - - diff --git a/public/en.search-data.json b/public/en.search-data.json deleted file mode 100644 index 083da43..0000000 --- a/public/en.search-data.json +++ /dev/null @@ -1 +0,0 @@ -{"/docs/":{"data":{"":"Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.\ngo-form is heavily influenced by Symfony Form. It includes:\nA form builder based on fields declarations and independent of structs Validation based on constraints Data mounting to populate a form from a struct instance Data binding to populate a struct instance from a submitted form Form renderer with customizable themes ","questions-or-feedback#Questions or Feedback?":" fmt.Sprintf(\"foo\") "},"title":"Documentation"},"/docs/fields/input/":{"data":{"":" ok "},"title":"Input"},"/docs/fields/input/mail/":{"data":{"":" ok "},"title":"Mail"},"/docs/fields/input/number/":{"data":{"":" ok "},"title":"Number"},"/docs/fields/input/password/":{"data":{"":" ok "},"title":"Password"},"/docs/fields/input/range/":{"data":{"":" ok "},"title":"Range"},"/docs/fields/input/text/":{"data":{"":" ok "},"title":"Text"},"/docs/form/":{"data":{"":"Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. go-form includes a powerful form feature that provides all these features.\ngo-form is heavily influenced by Symfony Form. It includes:\nA form builder based on fields declarations and independent of structs Validation based on constraints Data mounting to populate a form from a struct instance Data binding to populate a struct instance from a submitted form Form renderer with customizable themes ","questions-or-feedback#Questions or Feedback?":" fmt.Sprintf(\"foo\") "},"title":"Form"},"/docs/installation/":{"data":{"installation#Installation":"Installation"},"title":"Installation"}} \ No newline at end of file diff --git a/public/en.search.js b/public/en.search.js deleted file mode 100644 index 6e1bdfb..0000000 --- a/public/en.search.js +++ /dev/null @@ -1,437 +0,0 @@ -// Search functionality using FlexSearch. - -// Change shortcut key to cmd+k on Mac, iPad or iPhone. -document.addEventListener("DOMContentLoaded", function () { - if (/iPad|iPhone|Macintosh/.test(navigator.userAgent)) { - // select the kbd element under the .search-wrapper class - const keys = document.querySelectorAll(".search-wrapper kbd"); - keys.forEach(key => { - key.innerHTML = 'K'; - }); - } -}); - -// Render the search data as JSON. -// -// -// -// - -(function () { - const searchDataURL = '/en.search-data.json'; - - const inputElements = document.querySelectorAll('.search-input'); - for (const el of inputElements) { - el.addEventListener('focus', init); - el.addEventListener('keyup', search); - el.addEventListener('keydown', handleKeyDown); - el.addEventListener('input', handleInputChange); - } - - const shortcutElements = document.querySelectorAll('.search-wrapper kbd'); - - function setShortcutElementsOpacity(opacity) { - shortcutElements.forEach(el => { - el.style.opacity = opacity; - }); - } - - function handleInputChange(e) { - const opacity = e.target.value.length > 0 ? 0 : 100; - setShortcutElementsOpacity(opacity); - } - - // Get the search wrapper, input, and results elements. - function getActiveSearchElement() { - const inputs = Array.from(document.querySelectorAll('.search-wrapper')).filter(el => el.clientHeight > 0); - if (inputs.length === 1) { - return { - wrapper: inputs[0], - inputElement: inputs[0].querySelector('.search-input'), - resultsElement: inputs[0].querySelector('.search-results') - }; - } - return undefined; - } - - const INPUTS = ['input', 'select', 'button', 'textarea'] - - // Focus the search input when pressing ctrl+k/cmd+k or /. - document.addEventListener('keydown', function (e) { - const { inputElement } = getActiveSearchElement(); - if (!inputElement) return; - - const activeElement = document.activeElement; - const tagName = activeElement && activeElement.tagName; - if ( - inputElement === activeElement || - !tagName || - INPUTS.includes(tagName) || - (activeElement && activeElement.isContentEditable)) - return; - - if ( - e.key === '/' || - (e.key === 'k' && - (e.metaKey /* for Mac */ || /* for non-Mac */ e.ctrlKey)) - ) { - e.preventDefault(); - inputElement.focus(); - } else if (e.key === 'Escape' && inputElement.value) { - inputElement.blur(); - } - }); - - // Dismiss the search results when clicking outside the search box. - document.addEventListener('mousedown', function (e) { - const { inputElement, resultsElement } = getActiveSearchElement(); - if (!inputElement || !resultsElement) return; - if ( - e.target !== inputElement && - e.target !== resultsElement && - !resultsElement.contains(e.target) - ) { - setShortcutElementsOpacity(100); - hideSearchResults(); - } - }); - - // Get the currently active result and its index. - function getActiveResult() { - const { resultsElement } = getActiveSearchElement(); - if (!resultsElement) return { result: undefined, index: -1 }; - - const result = resultsElement.querySelector('.active'); - if (!result) return { result: undefined, index: -1 }; - - const index = parseInt(result.dataset.index, 10); - return { result, index }; - } - - // Set the active result by index. - function setActiveResult(index) { - const { resultsElement } = getActiveSearchElement(); - if (!resultsElement) return; - - const { result: activeResult } = getActiveResult(); - activeResult && activeResult.classList.remove('active'); - const result = resultsElement.querySelector(`[data-index="${index}"]`); - if (result) { - result.classList.add('active'); - result.focus(); - } - } - - // Get the number of search results from the DOM. - function getResultsLength() { - const { resultsElement } = getActiveSearchElement(); - if (!resultsElement) return 0; - return resultsElement.dataset.count; - } - - // Finish the search by hiding the results and clearing the input. - function finishSearch() { - const { inputElement } = getActiveSearchElement(); - if (!inputElement) return; - hideSearchResults(); - inputElement.value = ''; - inputElement.blur(); - } - - function hideSearchResults() { - const { resultsElement } = getActiveSearchElement(); - if (!resultsElement) return; - resultsElement.classList.add('hx-hidden'); - } - - // Handle keyboard events. - function handleKeyDown(e) { - const { inputElement } = getActiveSearchElement(); - if (!inputElement) return; - - const resultsLength = getResultsLength(); - const { result: activeResult, index: activeIndex } = getActiveResult(); - - switch (e.key) { - case 'ArrowUp': - e.preventDefault(); - if (activeIndex > 0) setActiveResult(activeIndex - 1); - break; - case 'ArrowDown': - e.preventDefault(); - if (activeIndex + 1 < resultsLength) setActiveResult(activeIndex + 1); - break; - case 'Enter': - e.preventDefault(); - if (activeResult) { - activeResult.click(); - } - finishSearch(); - case 'Escape': - e.preventDefault(); - hideSearchResults(); - // Clear the input when pressing escape - inputElement.value = ''; - inputElement.dispatchEvent(new Event('input')); - // Remove focus from the input - inputElement.blur(); - break; - } - } - - // Initializes the search. - function init(e) { - e.target.removeEventListener('focus', init); - if (!(window.pageIndex && window.sectionIndex)) { - preloadIndex(); - } - } - - /** - * Preloads the search index by fetching data and adding it to the FlexSearch index. - * @returns {Promise} A promise that resolves when the index is preloaded. - */ - async function preloadIndex() { - const tokenize = 'forward'; - - const isCJK = () => { - const lang = document.documentElement.lang || "en"; - return lang.startsWith("zh") || lang.startsWith("ja") || lang.startsWith("ko"); - } - - const encodeCJK = (str) => str.replace(/[\x00-\x7F]/g, "").split(""); - const encodeDefault = (str) => (""+str).toLocaleLowerCase().split(/[\p{Z}\p{S}\p{P}\p{C}]+/u); - const encodeFunction = isCJK() ? encodeCJK : encodeDefault; - - window.pageIndex = new FlexSearch.Document({ - tokenize, - encode: encodeFunction, - cache: 100, - document: { - id: 'id', - store: ['title', 'crumb'], - index: "content" - } - }); - - window.sectionIndex = new FlexSearch.Document({ - tokenize, - encode: encodeFunction, - cache: 100, - document: { - id: 'id', - store: ['title', 'content', 'url', 'display', 'crumb'], - index: "content", - tag: 'pageId' - } - }); - - const resp = await fetch(searchDataURL); - const data = await resp.json(); - let pageId = 0; - for (const route in data) { - let pageContent = ''; - ++pageId; - const urlParts = route.split('/').filter(x => x != "" && !x.startsWith('#')); - - let crumb = ''; - let searchUrl = '/' - for (let i = 0; i < urlParts.length; i++) { - const urlPart = urlParts[i]; - searchUrl += urlPart + '/' - - const crumbData = data[searchUrl]; - if (!crumbData) { - console.warn('Excluded page', searchUrl, '- will not be included for search result breadcrumb for', route); - continue; - } - - let title = data[searchUrl].title; - if (title == "_index") { - title = urlPart.split("-").map(x => x).join(" "); - } - crumb += title; - - if (i < urlParts.length - 1) { - crumb += ' > '; - } - } - - for (const heading in data[route].data) { - const [hash, text] = heading.split('#'); - const url = route.trimEnd('/') + (hash ? '#' + hash : ''); - const title = text || data[route].title; - - const content = data[route].data[heading] || ''; - const paragraphs = content.split('\n').filter(Boolean); - - sectionIndex.add({ - id: url, - url, - title, - crumb, - pageId: `page_${pageId}`, - content: title, - ...(paragraphs[0] && { display: paragraphs[0] }) - }); - - for (let i = 0; i < paragraphs.length; i++) { - sectionIndex.add({ - id: `${url}_${i}`, - url, - title, - crumb, - pageId: `page_${pageId}`, - content: paragraphs[i] - }); - } - - pageContent += ` ${title} ${content}`; - } - - window.pageIndex.add({ - id: pageId, - title: data[route].title, - crumb, - content: pageContent - }); - - } - } - - /** - * Performs a search based on the provided query and displays the results. - * @param {Event} e - The event object. - */ - function search(e) { - const query = e.target.value; - if (!e.target.value) { - hideSearchResults(); - return; - } - - const { resultsElement } = getActiveSearchElement(); - while (resultsElement.firstChild) { - resultsElement.removeChild(resultsElement.firstChild); - } - resultsElement.classList.remove('hx-hidden'); - - const pageResults = window.pageIndex.search(query, 5, { enrich: true, suggest: true })[0]?.result || []; - - const results = []; - const pageTitleMatches = {}; - - for (let i = 0; i < pageResults.length; i++) { - const result = pageResults[i]; - pageTitleMatches[i] = 0; - - // Show the top 5 results for each page - const sectionResults = window.sectionIndex.search(query, 5, { enrich: true, suggest: true, tag: `page_${result.id}` })[0]?.result || []; - let isFirstItemOfPage = true - const occurred = {} - - for (let j = 0; j < sectionResults.length; j++) { - const { doc } = sectionResults[j] - const isMatchingTitle = doc.display !== undefined - if (isMatchingTitle) { - pageTitleMatches[i]++ - } - const { url, title } = doc - const content = doc.display || doc.content - - if (occurred[url + '@' + content]) continue - occurred[url + '@' + content] = true - results.push({ - _page_rk: i, - _section_rk: j, - route: url, - prefix: isFirstItemOfPage ? result.doc.crumb : undefined, - children: { title, content } - }) - isFirstItemOfPage = false - } - } - const sortedResults = results - .sort((a, b) => { - // Sort by number of matches in the title. - if (a._page_rk === b._page_rk) { - return a._section_rk - b._section_rk - } - if (pageTitleMatches[a._page_rk] !== pageTitleMatches[b._page_rk]) { - return pageTitleMatches[b._page_rk] - pageTitleMatches[a._page_rk] - } - return a._page_rk - b._page_rk - }) - .map(res => ({ - id: `${res._page_rk}_${res._section_rk}`, - route: res.route, - prefix: res.prefix, - children: res.children - })); - displayResults(sortedResults, query); - } - - /** - * Displays the search results on the page. - * - * @param {Array} results - The array of search results. - * @param {string} query - The search query. - */ - function displayResults(results, query) { - const { resultsElement } = getActiveSearchElement(); - if (!resultsElement) return; - - if (!results.length) { - resultsElement.innerHTML = `No results found.`; - return; - } - - // Highlight the query in the result text. - function highlightMatches(text, query) { - const escapedQuery = query.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); - const regex = new RegExp(escapedQuery, 'gi'); - return text.replace(regex, (match) => `${match}`); - } - - // Create a DOM element from the HTML string. - function createElement(str) { - const div = document.createElement('div'); - div.innerHTML = str.trim(); - return div.firstChild; - } - - function handleMouseMove(e) { - const target = e.target.closest('a'); - if (target) { - const active = resultsElement.querySelector('a.active'); - if (active) { - active.classList.remove('active'); - } - target.classList.add('active'); - } - } - - const fragment = document.createDocumentFragment(); - for (let i = 0; i < results.length; i++) { - const result = results[i]; - if (result.prefix) { - fragment.appendChild(createElement(` -
      ${result.prefix}
      `)); - } - let li = createElement(` -
    • - -
      `+ highlightMatches(result.children.title, query) + `
      ` + - (result.children.content ? - `
      ` + highlightMatches(result.children.content, query) + `
      ` : '') + ` -
      -
    • `); - li.addEventListener('mousemove', handleMouseMove); - li.addEventListener('keydown', handleKeyDown); - li.querySelector('a').addEventListener('click', finishSearch); - fragment.appendChild(li); - } - resultsElement.appendChild(fragment); - resultsElement.dataset.count = results.length; - } -})(); diff --git a/public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js b/public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js deleted file mode 100644 index db3c3e3..0000000 --- a/public/en.search.min.7918d81999396a56d9ff1b7a986d6474e66bd5acdbbe01e8bac129f5ef345a88.js +++ /dev/null @@ -1,8 +0,0 @@ -document.addEventListener("DOMContentLoaded",function(){if(/iPad|iPhone|Macintosh/.test(navigator.userAgent)){const e=document.querySelectorAll(".search-wrapper kbd");e.forEach(e=>{e.innerHTML='K'})}}),function(){const h="/en.search-data.json",u=document.querySelectorAll(".search-input");for(const e of u)e.addEventListener("focus",o),e.addEventListener("keyup",p),e.addEventListener("keydown",n),e.addEventListener("input",m);const d=document.querySelectorAll(".search-wrapper kbd");function a(e){d.forEach(t=>{t.style.opacity=e})}function m(e){const t=e.target.value.length>0?0:100;a(t)}function e(){const e=Array.from(document.querySelectorAll(".search-wrapper")).filter(e=>e.clientHeight>0);return e.length===1?{wrapper:e[0],inputElement:e[0].querySelector(".search-input"),resultsElement:e[0].querySelector(".search-results")}:0[0]}const l=["input","select","button","textarea"];document.addEventListener("keydown",function(t){const{inputElement:n}=e();if(!n)return;const s=document.activeElement,o=s&&s.tagName;if(n===s||!o||l.includes(o)||s&&s.isContentEditable)return;t.key==="/"||t.key==="k"&&(t.metaKey||t.ctrlKey)?(t.preventDefault(),n.focus()):t.key==="Escape"&&n.value&&n.blur()}),document.addEventListener("mousedown",function(n){const{inputElement:o,resultsElement:s}=e();if(!o||!s)return;n.target!==o&&n.target!==s&&!s.contains(n.target)&&(a(100),t())});function r(){const{resultsElement:n}=e();if(!n)return{result:0[0],index:-1};const t=n.querySelector(".active");if(!t)return{result:0[0],index:-1};const s=parseInt(t.dataset.index,10);return{result:t,index:s}}function s(t){const{resultsElement:s}=e();if(!s)return;const{result:o}=r();o&&o.classList.remove("active");const n=s.querySelector(`[data-index="${t}"]`);n&&(n.classList.add("active"),n.focus())}function c(){const{resultsElement:t}=e();return t?t.dataset.count:0}function i(){const{inputElement:n}=e();if(!n)return;t(),n.value="",n.blur()}function t(){const{resultsElement:t}=e();if(!t)return;t.classList.add("hx-hidden")}function n(n){const{inputElement:o}=e();if(!o)return;const d=c(),{result:l,index:a}=r();switch(n.key){case"ArrowUp":n.preventDefault(),a>0&&s(a-1);break;case"ArrowDown":n.preventDefault(),a+1{const e=document.documentElement.lang||"en";return e.startsWith("zh")||e.startsWith("ja")||e.startsWith("ko")},i=e=>e.replace(/[\x00-\x7F]/g,"").split(""),a=e=>(""+e).toLocaleLowerCase().split(/[\p{Z}\p{S}\p{P}\p{C}]+/u),s=o()?i:a;window.pageIndex=new FlexSearch.Document({tokenize:n,encode:s,cache:100,document:{id:"id",store:["title","crumb"],index:"content"}}),window.sectionIndex=new FlexSearch.Document({tokenize:n,encode:s,cache:100,document:{id:"id",store:["title","content","url","display","crumb"],index:"content",tag:"pageId"}});const r=await fetch(h),e=await r.json();let t=0;for(const n in e){let a="";++t;const i=n.split("/").filter(e=>e!=""&&!e.startsWith("#"));let s="",o="/";for(let t=0;te).join(" ")),s+=a,t ")}for(const c in e[n].data){const[l,u]=c.split("#"),o=n.trimEnd("/")+(l?"#"+l:""),i=u||e[n].title,d=e[n].data[c]||"",r=d.split(` -`).filter(Boolean);sectionIndex.add({id:o,url:o,title:i,crumb:s,pageId:`page_${t}`,content:i,...r[0]&&{display:r[0]}});for(let e=0;ee._page_rk===t._page_rk?e._section_rk-t._section_rk:s[e._page_rk]!==s[t._page_rk]?s[t._page_rk]-s[e._page_rk]:e._page_rk-t._page_rk).map(e=>({id:`${e._page_rk}_${e._section_rk}`,route:e.route,prefix:e.prefix,children:e.children}));g(c,i)}function g(t,s){const{resultsElement:o}=e();if(!o)return;if(!t.length){o.innerHTML=`No results found.`;return}function r(e,t){const n=t.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&"),s=new RegExp(n,"gi");return e.replace(s,e=>`${e}`)}function c(e){const t=document.createElement("div");return t.innerHTML=e.trim(),t.firstChild}function l(e){const t=e.target.closest("a");if(t){const e=o.querySelector("a.active");e&&e.classList.remove("active"),t.classList.add("active")}}const a=document.createDocumentFragment();for(let o=0;o${e.prefix}`));let d=c(` -
    • - -
      `+r(e.children.title,s)+`
      `+(e.children.content?`
      `+r(e.children.content,s)+`
      `:"")+` -
      -
    • `);d.addEventListener("mousemove",l),d.addEventListener("keydown",n),d.querySelector("a").addEventListener("click",i),a.appendChild(d)}o.appendChild(a),o.dataset.count=t.length}}() \ No newline at end of file diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png deleted file mode 100644 index 0f2dd2b2eb092162cc3cb22473ae565ddf2db9c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340 zcmV-a0jvIrP)Px$4oO5oR5(wi(?2VQVHC&l&%^2k$bi`8-++`7#UP56mmo8oO4ltUkH`0000 diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index 5c1aea58495d1cfb77aac38b4f5ce0ae14ce6a6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmVPx%t4TybR9Hvt*Gs5Xbri?(&+Q?o^Z=zm1S7&Q(q7P@Ng)|dgc2QPnnNi=DNKz5 z5qeOdq~ zid!3;U&PyZAAdA~Gy&XzWq1eo;urkg;50UYJcn0s6#openG9e7cH*gGycZjBr2*hZ zyj-B8`YG1qhkka00G`B0xUCrFPVd8|rj(Z7Z^8*YTt5Gbr}0IveLsNNIE^_q<+b>* zW$;SvaeR(sBys`w$=p2O840b;fdZxs8lktQ}S{Q#o0uspedoF5^0 zOjF3|kayu5ENTl7>g^*2ugsstfi3`Zk^9T@`7b0dA*W9vx5~iXC1n$y%m^gY@EtC< z1xO9-DgA$hxZ|c9u%pWr1RyQQ9Rm>F6Blx`|L@NK2o`CV4(LQM-$}l>E zY(JH3!n+*-p26W-x6MRN7i=6xiLRRUxs3&i)xXdikds{>Cj zr%w^x-jIRpjc;N%ervk2rVRAjXG_X}T8*q-bxEJkzzJlwpH|WppmLfqy{69}lN4U3 j-C - - diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 553fa15d0e22126b2d923b442890cae56d724b40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 zcmeI1Tc{OP7=XvD(?v^9S(>RG3G7s)#{x+Z3N0Tjvd{;^m!m=iiAhk|Lq%`B8D(Zg zMi?SikW||3LAq!~H-j_~?9{Oov@9{vEbIGlFBw;J_RQ?d(PIDbF*9ra_5W-C>-MkN zNirZAm<%17aP3I$Iz34yB}vlJaqPLXJxNwl*40&cKQ2i&U6>@D=um|k$I7|%w+zPN z>iJsk?W3&t*(dhR7GOsFO9oK#K3Lzr&JxFlV`LRP z5b-R}_P=ASnmA6nAw7P*x6H9!R0gA1%ls*7zae^^Sm}Tp!1bvm|EmbFt0YTdV+HRm zb1pSgMq>PVa6X4UAY3hb0fs}P(_SBpKH_~IjEzq z`;~RetSzV?mvP*^4dHjXhF<~~2luUD$F*MDd9nnBP{->w@b{Dz_nUVhZObv7C+Rx2zpp(p z&yMdW!eIz)c-O)lai0$Qj-7hfl;tUVU*`Ds_16{sLtMvOP^UOw_JY4j+j$cFJBJ!2 zi!oHj{{i%ijMbv;YeUi8u;}mq1>JLt8ZV&dT-XXl{Tr)?3fL{GG8e@%@mJSZ z&JB5XjN4jB+j4Es6X#v}j9~rlyh<7Gucs{J0@`p-D>|p$E8R0g+ij2IsHhmP&mq*` z&%Jwk88K&Y{SP)=$ImQaz`1^Zs-8B?WonU-f0;|!4(Ft6Q#Fj6`=%NMvIcuY3I0jdOIcV(v2xaExBca(c0S8NAV+HTKpe3yc{HG$|cM=C~ zH?+Q!5QLVrBG7*k@QmT~Gv5*K&x2E4+G*e-*bF;iPlaBtn_wXn&Gk_27cn0;w$s6O z`+rBALxgAFeF!ta@7?vDK`>F5n0HQtRbYM<+L?DX?=@d?Y_-A3kP$e20?hxb#k{ZI zVx3)J{yiG{L+o$DW-+lwz2v5S} zC9&_;!$HuNHeZK1;M{1W*uRc(&o?1vUY)OF;4E-1l)*a2`$b6GbRMk%?ba)vu_l3M zuCx#Djn`DDS4Lr=2V(nMDbshY=RC*ZMA!ncZO`w^p;p^eJwfi|Dg8Yp_|x}<6EurI zcs6|+(%%|_-ES!GEN&`S(>38u2=>F(v*$9X70ES8o6%U*LOhH9`Xa_ zW&bCkN-__!V*dr@9nffT5BI;I5c_a-O`czavlSV({5^BQcr`<=#%R38`8%Ge!Pz?M zgcx`|3U9zbXqFh4N5FBP_Weo?4sC1N#`io=uE9>(Dz5tS@38e+e{m+++R(aUR?Z=Gp#+dfM;$+YbFL z#%n#)+x~6XsAd1F_xIWds~gaMzbU&nYOg=#8l3HgdgE{XuV5_nmze**2KsJ9`wwBq zIeZ2*Tg+)^LwX;sXa0s5m~&p$9&rOG*cE}{2-)# zo6D3HbEdQn?;S@|pjmTyIJW)n75iO5Sy?e>b?=I8y+_%Ivc?MNo0~iZu|NBLUV-|t zif0D*uGroI$~^Biava&8H^FX*{q<7jS*onKXDx#`m(~6z7zK?I&n~MV?r&r7oErqS zh-YWd&~Z!-Q}!SLP(jTon% zDb_%IzJ8gq3!v71uSc?Mteb68m>K?1Ipacnnv2wvOwi z-*KC - - diff --git a/public/images/logo-dark.svg b/public/images/logo-dark.svg deleted file mode 100644 index 2857264..0000000 --- a/public/images/logo-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/images/logo.svg b/public/images/logo.svg deleted file mode 100644 index 1ed7daf..0000000 --- a/public/images/logo.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/index.html b/public/index.html deleted file mode 100644 index f7131d8..0000000 --- a/public/index.html +++ /dev/null @@ -1,448 +0,0 @@ - - - - - - - - - - - - - -deblan/go-form - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      - - -
      - -
      -

      - - - - - - diff --git a/public/index.xml b/public/index.xml deleted file mode 100644 index 27ad978..0000000 --- a/public/index.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - deblan/go-form – Welcome! - http://localhost:1313/ - Recent content in Welcome! on deblan/go-form - Hugo -- gohugo.io - en-us - - - - - - - - - - diff --git a/public/js/main.js b/public/js/main.js deleted file mode 100644 index 7d34dbb..0000000 --- a/public/js/main.js +++ /dev/null @@ -1,320 +0,0 @@ -// Light / Dark theme toggle -(function () { - const defaultTheme = 'system' - - const themeToggleButtons = document.querySelectorAll(".theme-toggle"); - - // Change the icons of the buttons based on previous settings or system theme - if ( - localStorage.getItem("color-theme") === "dark" || - (!("color-theme" in localStorage) && - ((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark")) - ) { - themeToggleButtons.forEach((el) => el.dataset.theme = "dark"); - } else { - themeToggleButtons.forEach((el) => el.dataset.theme = "light"); - } - - // Add click event handler to the buttons - themeToggleButtons.forEach((el) => { - el.addEventListener("click", function () { - if (localStorage.getItem("color-theme")) { - if (localStorage.getItem("color-theme") === "light") { - setDarkTheme(); - localStorage.setItem("color-theme", "dark"); - } else { - setLightTheme(); - localStorage.setItem("color-theme", "light"); - } - } else { - if (document.documentElement.classList.contains("dark")) { - setLightTheme(); - localStorage.setItem("color-theme", "light"); - } else { - setDarkTheme(); - localStorage.setItem("color-theme", "dark"); - } - } - el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"; - }); - }); - - // Listen for system theme changes - window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { - if (defaultTheme === "system" && !("color-theme" in localStorage)) { - e.matches ? setDarkTheme() : setLightTheme(); - themeToggleButtons.forEach((el) => - el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light" - ); - } - }); -})(); - -; -// Hamburger menu for mobile navigation - -document.addEventListener('DOMContentLoaded', function () { - const menu = document.querySelector('.hamburger-menu'); - const overlay = document.querySelector('.mobile-menu-overlay'); - const sidebarContainer = document.querySelector('.sidebar-container'); - - // Initialize the overlay - const overlayClasses = ['hx-fixed', 'hx-inset-0', 'hx-z-10', 'hx-bg-black/80', 'dark:hx-bg-black/60']; - overlay.classList.add('hx-bg-transparent'); - overlay.classList.remove("hx-hidden", ...overlayClasses); - - function toggleMenu() { - // Toggle the hamburger menu - menu.querySelector('svg').classList.toggle('open'); - - // When the menu is open, we want to show the navigation sidebar - sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,-100%,0)]'); - sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,0,0)]'); - - // When the menu is open, we want to prevent the body from scrolling - document.body.classList.toggle('hx-overflow-hidden'); - document.body.classList.toggle('md:hx-overflow-auto'); - } - - function hideOverlay() { - // Hide the overlay - overlay.classList.remove(...overlayClasses); - overlay.classList.add('hx-bg-transparent'); - } - - menu.addEventListener('click', (e) => { - e.preventDefault(); - toggleMenu(); - - if (overlay.classList.contains('hx-bg-transparent')) { - // Show the overlay - overlay.classList.add(...overlayClasses); - overlay.classList.remove('hx-bg-transparent'); - } else { - // Hide the overlay - hideOverlay(); - } - }); - - overlay.addEventListener('click', (e) => { - e.preventDefault(); - toggleMenu(); - - // Hide the overlay - hideOverlay(); - }); - - // Select all anchor tags in the sidebar container - const sidebarLinks = sidebarContainer.querySelectorAll('a'); - - // Add click event listener to each anchor tag - sidebarLinks.forEach(link => { - link.addEventListener('click', (e) => { - // Check if the href attribute contains a hash symbol (links to a heading) - if (link.getAttribute('href') && link.getAttribute('href').startsWith('#')) { - // Only dismiss overlay on mobile view - if (window.innerWidth < 768) { - toggleMenu(); - hideOverlay(); - } - } - }); - }); -}); - -; -// Copy button for code blocks - -document.addEventListener('DOMContentLoaded', function () { - const getCopyIcon = () => { - const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - svg.innerHTML = ` - - `; - svg.setAttribute('fill', 'none'); - svg.setAttribute('viewBox', '0 0 24 24'); - svg.setAttribute('stroke', 'currentColor'); - svg.setAttribute('stroke-width', '2'); - return svg; - } - - const getSuccessIcon = () => { - const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - svg.innerHTML = ` - - `; - svg.setAttribute('fill', 'none'); - svg.setAttribute('viewBox', '0 0 24 24'); - svg.setAttribute('stroke', 'currentColor'); - svg.setAttribute('stroke-width', '2'); - return svg; - } - - document.querySelectorAll('.hextra-code-copy-btn').forEach(function (button) { - // Add copy and success icons - button.querySelector('.copy-icon')?.appendChild(getCopyIcon()); - button.querySelector('.success-icon')?.appendChild(getSuccessIcon()); - - // Add click event listener for copy button - button.addEventListener('click', function (e) { - e.preventDefault(); - // Get the code target - const target = button.parentElement.previousElementSibling; - let codeElement; - if (target.tagName === 'CODE') { - codeElement = target; - } else { - // Select the last code element in case line numbers are present - const codeElements = target.querySelectorAll('code'); - codeElement = codeElements[codeElements.length - 1]; - } - if (codeElement) { - let code = codeElement.innerText; - // Replace double newlines with single newlines in the innerText - // as each line inside has trailing newline '\n' - if ("lang" in codeElement.dataset) { - code = code.replace(/\n\n/g, '\n'); - } - navigator.clipboard.writeText(code).then(function () { - button.classList.add('copied'); - setTimeout(function () { - button.classList.remove('copied'); - }, 1000); - }).catch(function (err) { - console.error('Failed to copy text: ', err); - }); - } else { - console.error('Target element not found'); - } - }); - }); -}); - -; -document.querySelectorAll('.hextra-tabs-toggle').forEach(function (button) { - button.addEventListener('click', function (e) { - // set parent tabs to unselected - const tabs = Array.from(e.target.parentElement.querySelectorAll('.hextra-tabs-toggle')); - tabs.map(tab => tab.dataset.state = ''); - - // set current tab to selected - e.target.dataset.state = 'selected'; - - // set all panels to unselected - const panelsContainer = e.target.parentElement.parentElement.nextElementSibling; - Array.from(panelsContainer.children).forEach(function (panel) { - panel.dataset.state = ''; - }); - - const panelId = e.target.getAttribute('aria-controls'); - const panel = panelsContainer.querySelector(`#${panelId}`); - panel.dataset.state = 'selected'; - }); -}); - -; -(function () { - const languageSwitchers = document.querySelectorAll('.language-switcher'); - languageSwitchers.forEach((switcher) => { - switcher.addEventListener('click', (e) => { - e.preventDefault(); - switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open'; - const optionsElement = switcher.nextElementSibling; - optionsElement.classList.toggle('hx-hidden'); - - // Calculate position of language options element - const switcherRect = switcher.getBoundingClientRect(); - const translateY = switcherRect.top - window.innerHeight - 15; - optionsElement.style.transform = `translate3d(${switcherRect.left}px, ${translateY}px, 0)`; - optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`; - }); - }); - - // Dismiss language switcher when clicking outside - document.addEventListener('click', (e) => { - if (e.target.closest('.language-switcher') === null) { - languageSwitchers.forEach((switcher) => { - switcher.dataset.state = 'closed'; - const optionsElement = switcher.nextElementSibling; - optionsElement.classList.add('hx-hidden'); - }); - } - }); -})(); - -; -// Script for filetree shortcode collapsing/expanding folders used in the theme -// ====================================================================== -document.addEventListener("DOMContentLoaded", function () { - const folders = document.querySelectorAll(".hextra-filetree-folder"); - folders.forEach(function (folder) { - folder.addEventListener("click", function () { - Array.from(folder.children).forEach(function (el) { - el.dataset.state = el.dataset.state === "open" ? "closed" : "open"; - }); - folder.nextElementSibling.dataset.state = folder.nextElementSibling.dataset.state === "open" ? "closed" : "open"; - }); - }); -}); - -; -document.addEventListener("DOMContentLoaded", function () { - scrollToActiveItem(); - enableCollapsibles(); -}); - -function enableCollapsibles() { - const buttons = document.querySelectorAll(".hextra-sidebar-collapsible-button"); - buttons.forEach(function (button) { - button.addEventListener("click", function (e) { - e.preventDefault(); - const list = button.parentElement.parentElement; - if (list) { - list.classList.toggle("open") - } - }); - }); -} - -function scrollToActiveItem() { - const sidebarScrollbar = document.querySelector("aside.sidebar-container > .hextra-scrollbar"); - const activeItems = document.querySelectorAll(".sidebar-active-item"); - const visibleActiveItem = Array.from(activeItems).find(function (activeItem) { - return activeItem.getBoundingClientRect().height > 0; - }); - - if (!visibleActiveItem) { - return; - } - - const yOffset = visibleActiveItem.clientHeight; - const yDistance = visibleActiveItem.getBoundingClientRect().top - sidebarScrollbar.getBoundingClientRect().top; - sidebarScrollbar.scrollTo({ - behavior: "instant", - top: yDistance - yOffset - }); -} - -; -// Back to top button - -document.addEventListener("DOMContentLoaded", function () { - const backToTop = document.querySelector("#backToTop"); - if (backToTop) { - document.addEventListener("scroll", (e) => { - if (window.scrollY > 300) { - backToTop.classList.remove("hx-opacity-0"); - } else { - backToTop.classList.add("hx-opacity-0"); - } - }); - } -}); - -function scrollUp() { - window.scroll({ - top: 0, - left: 0, - behavior: "smooth", - }); -} diff --git a/public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js b/public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js deleted file mode 100644 index 3ed1b78..0000000 --- a/public/js/main.min.0942239592f0795dc7213dd1057fd229d7edc19c0ef1a285396eb292d9ca9842.js +++ /dev/null @@ -1,6 +0,0 @@ -(function(){const t="system",e=document.querySelectorAll(".theme-toggle");localStorage.getItem("color-theme")==="dark"||!("color-theme"in localStorage)&&(window.matchMedia("(prefers-color-scheme: dark)").matches&&t==="system"||t==="dark")?e.forEach(e=>e.dataset.theme="dark"):e.forEach(e=>e.dataset.theme="light"),e.forEach(e=>{e.addEventListener("click",function(){localStorage.getItem("color-theme")?localStorage.getItem("color-theme")==="light"?(setDarkTheme(),localStorage.setItem("color-theme","dark")):(setLightTheme(),localStorage.setItem("color-theme","light")):document.documentElement.classList.contains("dark")?(setLightTheme(),localStorage.setItem("color-theme","light")):(setDarkTheme(),localStorage.setItem("color-theme","dark")),e.dataset.theme=document.documentElement.classList.contains("dark")?"dark":"light"})}),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",n=>{t==="system"&&!("color-theme"in localStorage)&&(n.matches?setDarkTheme():setLightTheme(),e.forEach(e=>e.dataset.theme=document.documentElement.classList.contains("dark")?"dark":"light"))})})(),document.addEventListener("DOMContentLoaded",function(){const i=document.querySelector(".hamburger-menu"),e=document.querySelector(".mobile-menu-overlay"),t=document.querySelector(".sidebar-container"),n=["hx-fixed","hx-inset-0","hx-z-10","hx-bg-black/80","dark:hx-bg-black/60"];e.classList.add("hx-bg-transparent"),e.classList.remove("hx-hidden",...n);function s(){i.querySelector("svg").classList.toggle("open"),t.classList.toggle("max-md:[transform:translate3d(0,-100%,0)]"),t.classList.toggle("max-md:[transform:translate3d(0,0,0)]"),document.body.classList.toggle("hx-overflow-hidden"),document.body.classList.toggle("md:hx-overflow-auto")}function o(){e.classList.remove(...n),e.classList.add("hx-bg-transparent")}i.addEventListener("click",t=>{t.preventDefault(),s(),e.classList.contains("hx-bg-transparent")?(e.classList.add(...n),e.classList.remove("hx-bg-transparent")):o()}),e.addEventListener("click",e=>{e.preventDefault(),s(),o()});const a=t.querySelectorAll("a");a.forEach(e=>{e.addEventListener("click",t=>{e.getAttribute("href")&&e.getAttribute("href").startsWith("#")&&window.innerWidth<768&&(s(),o())})})}),document.addEventListener("DOMContentLoaded",function(){const e=()=>{const e=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.innerHTML=` - - `,e.setAttribute("fill","none"),e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","2"),e},t=()=>{const e=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.innerHTML=` - - `,e.setAttribute("fill","none"),e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","2"),e};document.querySelectorAll(".hextra-code-copy-btn").forEach(function(n){n.querySelector(".copy-icon")?.appendChild(e()),n.querySelector(".success-icon")?.appendChild(t()),n.addEventListener("click",function(e){e.preventDefault();const s=n.parentElement.previousElementSibling;let t;if(s.tagName==="CODE")t=s;else{const e=s.querySelectorAll("code");t=e[e.length-1]}if(t){let e=t.innerText;"lang"in t.dataset&&(e=e.replace(/\n\n/g,` -`)),navigator.clipboard.writeText(e).then(function(){n.classList.add("copied"),setTimeout(function(){n.classList.remove("copied")},1e3)}).catch(function(e){console.error("Failed to copy text: ",e)})}else console.error("Target element not found")})})}),document.querySelectorAll(".hextra-tabs-toggle").forEach(function(e){e.addEventListener("click",function(e){const n=Array.from(e.target.parentElement.querySelectorAll(".hextra-tabs-toggle"));n.map(e=>e.dataset.state=""),e.target.dataset.state="selected";const t=e.target.parentElement.parentElement.nextElementSibling;Array.from(t.children).forEach(function(e){e.dataset.state=""});const s=e.target.getAttribute("aria-controls"),o=t.querySelector(`#${s}`);o.dataset.state="selected"})}),function(){const e=document.querySelectorAll(".language-switcher");e.forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),e.dataset.state=e.dataset.state==="open"?"closed":"open";const n=e.nextElementSibling;n.classList.toggle("hx-hidden");const s=e.getBoundingClientRect(),o=s.top-window.innerHeight-15;n.style.transform=`translate3d(${s.left}px, ${o}px, 0)`,n.style.minWidth=`${Math.max(s.width,50)}px`})}),document.addEventListener("click",t=>{t.target.closest(".language-switcher")===null&&e.forEach(e=>{e.dataset.state="closed";const t=e.nextElementSibling;t.classList.add("hx-hidden")})})}(),document.addEventListener("DOMContentLoaded",function(){const e=document.querySelectorAll(".hextra-filetree-folder");e.forEach(function(e){e.addEventListener("click",function(){Array.from(e.children).forEach(function(e){e.dataset.state=e.dataset.state==="open"?"closed":"open"}),e.nextElementSibling.dataset.state=e.nextElementSibling.dataset.state==="open"?"closed":"open"})})}),document.addEventListener("DOMContentLoaded",function(){scrollToActiveItem(),enableCollapsibles()});function enableCollapsibles(){const e=document.querySelectorAll(".hextra-sidebar-collapsible-button");e.forEach(function(e){e.addEventListener("click",function(t){t.preventDefault();const n=e.parentElement.parentElement;n&&n.classList.toggle("open")})})}function scrollToActiveItem(){const t=document.querySelector("aside.sidebar-container > .hextra-scrollbar"),n=document.querySelectorAll(".sidebar-active-item"),e=Array.from(n).find(function(e){return e.getBoundingClientRect().height>0});if(!e)return;const s=e.clientHeight,o=e.getBoundingClientRect().top-t.getBoundingClientRect().top;t.scrollTo({behavior:"instant",top:o-s})}document.addEventListener("DOMContentLoaded",function(){const e=document.querySelector("#backToTop");e&&document.addEventListener("scroll",t=>{window.scrollY>300?e.classList.remove("hx-opacity-0"):e.classList.add("hx-opacity-0")})});function scrollUp(){window.scroll({top:0,left:0,behavior:"smooth"})} \ No newline at end of file diff --git a/public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js b/public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js deleted file mode 100644 index 4ebf76e..0000000 --- a/public/lib/flexsearch/flexsearch.bundle.min.0425860527cc9968f9f049421c7a56b39327d475e2e3a8f550416be3a9134327.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Skipped minification because the original files appears to be already minified. - * Original file: /npm/flexsearch@0.7.31/dist/flexsearch.bundle.js - * - * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files - */ -/**! - * FlexSearch.js v0.7.31 (Bundle) - * Copyright 2018-2022 Nextapps GmbH - * Author: Thomas Wilkerling - * Licence: Apache-2.0 - * https://github.com/nextapps-de/flexsearch - */ -(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var t;function u(a){return"undefined"!==typeof a?a:!0}function aa(a){const b=Array(a);for(let c=0;c=this.B&&(w||!n[l])){var f=L(q,d,r),g="";switch(this.G){case "full":if(2f;h--)if(h-f>=this.B){var k=L(q,d,r,e,f);g=l.substring(f,h);M(this,n,g,k,a,c)}break}case "reverse":if(1=this.B&&M(this,n, -g,L(q,d,r,e,h),a,c);g=""}case "forward":if(1=this.B&&M(this,n,g,f,a,c);break}default:if(this.C&&(f=Math.min(f/this.C(b,l,r)|0,q-1)),M(this,n,l,f,a,c),w&&1=this.B&&!e[l]){e[l]=1;const p=this.l&&l>f;M(this,m,p?f:l,L(g+(d/2>g?0:1),d,r,h-1,k-1),a,c,p?l:f)}}}}this.m||(this.register[a]=1)}}return this}; -function L(a,b,c,d,e){return c&&1=this.B&&!c[q])if(this.s||f||this.map[q])k[w++]=q,c[q]=1;else return d;a=k;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1=d)))break;if(n){if(f)return ta(k,d,0);b[b.length]=k;return}}return!c&&k}function ta(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} -function ua(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}t.contain=function(a){return!!this.register[a]};t.update=function(a,b){return this.remove(a).add(a,b)}; -t.remove=function(a,b){const c=this.register[a];if(c){if(this.m)for(let d=0,e;db||c)e=e.slice(c,c+b);d&&(e=za.call(this,e));return{tag:a,result:e}}}function za(a){const b=Array(a.length);for(let c=0,d;c - - - http://localhost:1313/docs/form/mount/ - - http://localhost:1313/docs/form/bind/ - - http://localhost:1313/docs/fields/input/hidden/ - - http://localhost:1313/docs/installation/ - - http://localhost:1313/docs/form/ - - http://localhost:1313/docs/fields/ - - http://localhost:1313/docs/fields/input/ - - http://localhost:1313/docs/constraints/ - - http://localhost:1313/docs/fields/button/ - - http://localhost:1313/docs/fields/textarea/ - - http://localhost:1313/docs/rendering/ - - http://localhost:1313/docs/rendering/theming/ - - http://localhost:1313/categories/ - - http://localhost:1313/docs/fields/input/date/ - - http://localhost:1313/docs/fields/input/datetime/ - - http://localhost:1313/docs/ - - http://localhost:1313/docs/fields/input/mail/ - - http://localhost:1313/docs/fields/input/number/ - - http://localhost:1313/docs/fields/input/password/ - - http://localhost:1313/docs/fields/input/range/ - - http://localhost:1313/tags/ - - http://localhost:1313/docs/fields/input/text/ - - http://localhost:1313/docs/fields/input/time/ - - http://localhost:1313/ - - From fcde3eb16fd8a032cddff3b7eab17ab44ba9c02c Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 21 Jul 2025 22:36:40 +0200 Subject: [PATCH 030/122] add doc --- .gitignore | 2 + content/docs/Installation.md | 4 +- content/docs/fields/_index.md | 48 ++++++++++- content/docs/fields/input/_index.md | 11 --- content/docs/fields/input/text.md | 50 ++++++++++-- content/docs/form/_index.md | 65 --------------- content/docs/form/bind.md | 43 ---------- content/docs/form/mount.md | 20 ----- content/docs/workflow/_index.md | 120 ++++++++++++++++++++++++++++ hugo.yaml | 6 +- 10 files changed, 221 insertions(+), 148 deletions(-) create mode 100644 .gitignore delete mode 100644 content/docs/fields/input/_index.md delete mode 100644 content/docs/form/_index.md delete mode 100644 content/docs/form/bind.md delete mode 100644 content/docs/form/mount.md create mode 100644 content/docs/workflow/_index.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f1befd --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/public +/.hugo_build.lock diff --git a/content/docs/Installation.md b/content/docs/Installation.md index 67b1d02..cb641b4 100644 --- a/content/docs/Installation.md +++ b/content/docs/Installation.md @@ -4,4 +4,6 @@ title: Installation weight: 2 --- -# Installation +```golang +go get gitnet.fr/deblan/go-form +``` diff --git a/content/docs/fields/_index.md b/content/docs/fields/_index.md index 677d37e..ae7d331 100644 --- a/content/docs/fields/_index.md +++ b/content/docs/fields/_index.md @@ -1,5 +1,49 @@ --- -linkTitle: Input -title: Input +linkTitle: Fields +title: Fields weight: 3 --- + +The documentation of field is realised with this program. + +```golang {hl_lines=[12,13]} +import ( + "bytes" + "fmt" + "html/template" + + "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/theme" +) + +func main() { + myForm := form.NewForm( + // the documented field here + // form.NewField... + ). + WithName("form"). + End() + + render := theme.NewRenderer(theme.Html5) + tpl, _ := template.New("example").Funcs(render.FuncMap()).Parse(`{{- form .Form -}}`) + + var buffer bytes.Buffer + + tpl.Execute(&buffer, map[string]any{ + "Form": myForm, + }) + + fmt.Print(buffer.String()) +} +``` + +## Common options + +| Name | type | description | Info | +| ---- | ---- | ---- | ---- | +| `required` | `bool` | Add `required="true"` | Does not apply a constraint | +| `attr` | `map[string]string` | List of extra attributes of the field | | +| `row_attr` | `map[string]string` | List of extra attributes of the field's top container | | +| `label` | `string` | The label of the field | Usually show before the field | +| `label_attr` | `map[string]string` | List of extra attributes of the label | | +| `help` | `string` | Helper of the field | | diff --git a/content/docs/fields/input/_index.md b/content/docs/fields/input/_index.md deleted file mode 100644 index b92c9fb..0000000 --- a/content/docs/fields/input/_index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -linkTitle: Input -title: Input -weight: 3 ---- - - - - - -
      ok
      diff --git a/content/docs/fields/input/text.md b/content/docs/fields/input/text.md index f83dd1f..5badb2b 100644 --- a/content/docs/fields/input/text.md +++ b/content/docs/fields/input/text.md @@ -1,10 +1,50 @@ --- linkTitle: Text title: Text +weight: 1 --- - - - - -
      ok
      +## Basic example + +{{< tabs items="GO,Result" >}} + {{< tab >}} +```golang +form.NewFieldText("Name") +``` + {{< /tab >}} + {{< tab >}} +```html +
      +
      + +
      +
      +``` + {{< /tab >}} +{{< /tabs >}} + +## Fully featured example + +{{< tabs items="GO,Result" >}} + {{< tab >}} +```golang +form.NewFieldText("Name"). + WithOptions( + form.NewOption("label", "Name"), + form.NewOption("required", true), + form.NewOption("attr", map[string]string{"data-foo": "foo"}), + form.NewOption("row_attr", map[string]string{"data-bar": "bar"}), + ) +``` + {{< /tab >}} + {{< tab >}} +```html +
      +
      + + +
      +
      +``` + {{< /tab >}} +{{< /tabs >}} diff --git a/content/docs/form/_index.md b/content/docs/form/_index.md deleted file mode 100644 index e73ab96..0000000 --- a/content/docs/form/_index.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -linkTitle: Form -title: Form -weight: 3 ---- - -A form is a struct containing: - -* Fields -* Options -* Method -* Action - -## Import - -```golang -import ( - "net/http" - - "gitnet.fr/deblan/go-form/form" -) -``` - -## Usage - -```golang -// Let's create a new form -// You can pass *form.Field as arguments -myForm := form.NewForm(field1, field2, ...) - -// Add somes fields -myForm.Add(field3, field4, ...) - -// Set the method -//
      -myForm.WithMethod(http.MethodPost) - -// Define the action -// -myForm.WithAction("/") - -// Set a name -myForm.WithName("myForm") - -// Add options -myForm.WithOptions(option1, option2, ...) - -// When all fields are added, call End() -myForm.End() -``` - -## Attributes - -Some options are natively supported in go-form themes. - -```golang -myForm.WithOptions( - form.NewOption("help", "A help for the form"), - // +myForm.WithMethod(http.MethodPost) + +// Define the action +// +myForm.WithAction("/") + +// Set a name +myForm.WithName("myForm") + +// Add options +myForm.WithOptions(option1, option2, ...) + +// When all fields are added, call End() +myForm.End() +``` + +#### Attributes + +Some options are natively supported in go-form themes. + +```golang +myForm.WithOptions( + form.NewOption("help", "A help for the form"), + // Date: Tue, 22 Jul 2025 06:55:36 +0200 Subject: [PATCH 031/122] ci: fix build --- .woodpecker.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 20f8c95..c04fa41 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -13,8 +13,6 @@ steps: - mv public /tmp/ - git config --global user.email ci@gitnet.fr - git config --global user.name CI - - git add . - - git commit -m build -a - git fetch --no-tags origin +refs/heads/pages - git switch pages - rm * -fr From d697ad0b00b502cc483e45609ecd93d310f56721 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Tue, 22 Jul 2025 16:18:24 +0200 Subject: [PATCH 032/122] add form --- content/docs/_index.md | 8 -- content/docs/fields/_index.md | 2 +- content/docs/form/_index.md | 251 ++++++++++++++++++++++++++++++++++ 3 files changed, 252 insertions(+), 9 deletions(-) create mode 100644 content/docs/form/_index.md diff --git a/content/docs/_index.md b/content/docs/_index.md index 6a08dee..74d7218 100644 --- a/content/docs/_index.md +++ b/content/docs/_index.md @@ -13,14 +13,6 @@ Creating and processing HTML forms is hard and repetitive. You need to deal with * Data binding to populate a struct instance from a submitted form * Form renderer with customizable themes - - -## Questions or Feedback? - -```golang -fmt.Sprintf("foo") -``` - diff --git a/content/docs/fields/_index.md b/content/docs/fields/_index.md index 00af9ea..63fb9be 100644 --- a/content/docs/fields/_index.md +++ b/content/docs/fields/_index.md @@ -12,9 +12,9 @@ A field represents a field in a form. func NewFieldCheckbox(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=checkbox] @@ -24,11 +24,11 @@ Generates an input[type=checkbox] func NewFieldChoice(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates inputs (checkbox or radio) or selects @@ -39,11 +39,11 @@ Generates inputs (checkbox or radio) or selects func NewFieldCsrf(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} ### Date @@ -51,11 +51,11 @@ field := form.NewFieldCsrf("Foo") func NewFieldDate(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=date] with default transformers @@ -65,11 +65,11 @@ Generates an input[type=date] with default transformers func NewFieldDatetime(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=datetime] with default transformers @@ -79,11 +79,11 @@ Generates an input[type=datetime] with default transformers func NewFieldDatetimeLocal(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=datetime-local] with default transformers @@ -93,11 +93,11 @@ Generates an input[type=datetime-local] with default transformers func NewFieldHidden(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=hidden] @@ -107,11 +107,11 @@ Generates an input[type=hidden] func NewFieldMail(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=email] @@ -121,11 +121,11 @@ Generates an input[type=email] func NewFieldNumber(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=number] with default transformers @@ -135,11 +135,11 @@ Generates an input[type=number] with default transformers func NewFieldPassword(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=password] @@ -149,11 +149,11 @@ Generates an input[type=password] func NewFieldRange(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=range] @@ -163,11 +163,11 @@ Generates an input[type=range] func NewFieldSubForm(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Alias: @@ -183,11 +183,11 @@ Generates a sub form func NewFieldText(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=text] @@ -197,11 +197,11 @@ Generates an input[type=text] func NewFieldTextarea(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates a textarea @@ -211,11 +211,11 @@ Generates a textarea func NewFieldTime(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=time] with default transformers @@ -225,11 +225,11 @@ Generates an input[type=time] with default transformers func NewSubmit(name string) *Field ``` -{{% gpfield %}} +{{% goplay-field %}} -{{% /gpfield %}} +{{% /goplay-field %}} Generates an input[type=submit] diff --git a/content/docs/rendering/_index.md b/content/docs/rendering/_index.md index 4651543..34ab249 100644 --- a/content/docs/rendering/_index.md +++ b/content/docs/rendering/_index.md @@ -10,7 +10,8 @@ Here is a simple example that displays a form: ```golang myForm := form.NewForm(...) -render := theme.NewRenderer(theme.Html5) +render := theme.NewRenderer(theme.Bootstrap5) + tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(` @@ -22,18 +23,39 @@ tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(` `) +b := new(strings.Builder) + tpl.Execute(w, map[string]any{ "Form": myForm, }) -tpl, _ := template.New("example").Funcs(render.FuncMap()).Parse("{{ form_widget .Form }}") - -b := new(strings.Builder) -tpl.Execute(b, map[string]any{"Form": f}) - fmt.Println(b.String()) ``` +{{% goplay-auto-import-main %}} + +{{% /goplay-auto-import-main %}} + Other helper functions are available to render specific parts of the form: - `form_errors`: displays the form's global errors diff --git a/layouts/shortcodes/goplay.html b/layouts/shortcodes/goplay.html deleted file mode 100644 index 3cbe76e..0000000 --- a/layouts/shortcodes/goplay.html +++ /dev/null @@ -1,81 +0,0 @@ -{{ $id := md5 .Inner }} {{ .Inner }} - -
      -
      - - - -
      - - - - diff --git a/layouts/shortcodes/gpfield.html b/layouts/shortcodes/gpfield.html deleted file mode 100644 index 5762a16..0000000 --- a/layouts/shortcodes/gpfield.html +++ /dev/null @@ -1,143 +0,0 @@ -{{ $id := md5 .Inner }} {{ .Inner }} - -
      -Test me - -
      -
      - - - -
      -
      - - - - From 8ad775682d287427e2078cc83f78b0d29c067bd5 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 18:13:18 +0200 Subject: [PATCH 075/122] add playground --- assets/css/custom.css | 60 +++++++++ layouts/partials/custom/footer.html | 1 + .../shortcodes/goplay-auto-import-main.html | 28 ++++ layouts/shortcodes/goplay-field.html | 28 ++++ static/js/custom.js | 126 ++++++++++++++++++ 5 files changed, 243 insertions(+) create mode 100644 assets/css/custom.css create mode 100644 layouts/partials/custom/footer.html create mode 100644 layouts/shortcodes/goplay-auto-import-main.html create mode 100644 layouts/shortcodes/goplay-field.html create mode 100644 static/js/custom.js diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..202c701 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,60 @@ +.hidden { + display: none; +} + +.hugo-goplay-summary { + cursor: pointer; +} + +.hugo-goplay-textarea { + padding: 1rem; + width: 100%; + border-radius: 4px; + margin: 10px 0; + background-color: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27) / 0.1); + font-family: monospace; +} + +.hugo-goplay-result pre { + padding: 1rem; +} + +.hugo-goplay-result code { + background: none !important; + border: 0 !important; +} + +.hugo-goplay-result .system { + color: green; +} + +.hugo-goplay-result .stderr { + color: red; +} + +.hugo-goplay-toolbox { + display: flex; + justify-content: flex-start; + margin-bottom: 2rem; +} + +.hugo-goplay-toolbox .hugo-goplay-button { + font-size: 13px; + font-weight: bold; + border: 1px solid var(--primary); + padding: 0.15rem 0.75rem; + border-radius: 4px; + margin-left: 0.5rem; + color: var(--primary); + background-color: var(--theme); +} + +.hugo-goplay-toolbox .hugo-goplay-button:hover { + border: 1px solid var(--theme); + color: var(--theme); + background-color: var(--primary); +} + +.hugo-goplay-toolbox .hugo-goplay-button:first-child { + margin-left: 0; +} diff --git a/layouts/partials/custom/footer.html b/layouts/partials/custom/footer.html new file mode 100644 index 0000000..092814c --- /dev/null +++ b/layouts/partials/custom/footer.html @@ -0,0 +1 @@ + diff --git a/layouts/shortcodes/goplay-auto-import-main.html b/layouts/shortcodes/goplay-auto-import-main.html new file mode 100644 index 0000000..4f61f13 --- /dev/null +++ b/layouts/shortcodes/goplay-auto-import-main.html @@ -0,0 +1,28 @@ +{{ $id := md5 .Inner }} {{ .Inner }} + +
      + Test me + +
      +
      + + + +
      +
      + + diff --git a/layouts/shortcodes/goplay-field.html b/layouts/shortcodes/goplay-field.html new file mode 100644 index 0000000..d31bb7b --- /dev/null +++ b/layouts/shortcodes/goplay-field.html @@ -0,0 +1,28 @@ +{{ $id := md5 .Inner }} {{ .Inner }} + +
      + Test me + +
      +
      + + + +
      +
      + + diff --git a/static/js/custom.js b/static/js/custom.js new file mode 100644 index 0000000..3b7f770 --- /dev/null +++ b/static/js/custom.js @@ -0,0 +1,126 @@ +function normalizeCode(code) { + return code + .trim() + .replace(/^```go/, '') + .replace(/^```/, '') + .replace(/```$/, '') + .replace(/<([^>]+)>/g, '') + .trim() +} + +function updatePlaygroundView(goplay, id, code) { + const textarea = document.getElementById(`textarea-${id}`) + + textarea.value = code + textarea.style.height = textarea.scrollHeight + 'px'; + textarea.style.overflowY = 'hidden'; + + textarea.addEventListener('input', function() { + this.style.height = 'auto'; + this.style.height = this.scrollHeight + 'px'; + }) + + const toolRun = document.getElementById(`hugo-goplay-tool-${id}-run`) + const toolTry = document.getElementById(`hugo-goplay-tool-${id}-try`) + const toolShare = document.getElementById(`hugo-goplay-tool-${id}-share`) + + toolRun.addEventListener('click', () => { + const parent = document.getElementById(id) + const pre = document.createElement('pre') + const container = document.createElement('code') + + container.classList.add('text') + pre.appendChild(container) + parent.replaceChildren(pre) + + goplay.renderCompile(container, textarea.value); + }); + + [toolTry, toolShare].forEach((v) => { + v.addEventListener('click', async () => { + const shareUrl = await goplay.share(code) + window.open(shareUrl, '_blank').focus(); + }) + }); +} + +function createFieldPlayground(goplay, id, code) { + code = createFieldPlaygroundCode(code) + + updatePlaygroundView(goplay, id, code) +} + +function createPlaygroundWithAutoImportMail(goplay, id, code) { + let lines = normalizeCode(code).split("\n") + let results = ["package main", ""] + let imports = [] + let body = [] + + lines.forEach((line) => { + if (line.substr(0, 7) === '@import') { + imports.push(' ' + line.replace('@import', '').trim()) + } else { + body.push(" " + line) + } + }) + + if (imports.length > 0) { + results.push("import (") + + imports.forEach((v) => { + results.push(v) + }) + + results.push(")", "") + } + + results.push("func main() {") + + body.forEach((v, i) => { + if (i == 0 && v.trim() == "") { + return + } + + results.push(v) + }) + + results.push("}", "") + + updatePlaygroundView(goplay, id, results.join("\n")) +} + +function createFieldPlaygroundCode(code) { + code = normalizeCode(code) + let lines = code.split("\n"); + + for (let i in lines) { + lines[i] = [' ', lines[i]].join('') + } + + code = lines.join("\n"); + + return `package main + +import ( + 'fmt' + 'html/template' + 'strings' + + 'gitnet.fr/deblan/go-form/form' + 'gitnet.fr/deblan/go-form/theme' +) + +func main() { +${code} + + r(form.NewForm(field)) +} + +func r(f *form.Form) { + render := theme.NewRenderer(theme.Html5) + tpl, _ := template.New('example').Funcs(render.FuncMap()).Parse(\`{{ form_widget (.Form.GetField "Foo") }}\`) + b := new(strings.Builder) + tpl.Execute(b, map[string]any{"Form": f}) + fmt.Println(b.String()) +}` +} From 01eaa8a95c89c0a78d12c039250124d3b3007956 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 18:15:00 +0200 Subject: [PATCH 076/122] add playground --- content/docs/rendering/_index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/content/docs/rendering/_index.md b/content/docs/rendering/_index.md index 34ab249..4d4ce01 100644 --- a/content/docs/rendering/_index.md +++ b/content/docs/rendering/_index.md @@ -38,7 +38,6 @@ fmt.Println(b.String()) @import "net/http" @import @import "gitnet.fr/deblan/go-form/example" -@import "gitnet.fr/deblan/go-form/form" @import "gitnet.fr/deblan/go-form/theme" form := example.CreateDataForm() @@ -49,7 +48,7 @@ tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(`{{ form .Form }}`) b := new(strings.Builder) tpl.Execute(w, map[string]any{ - "Form": myForm, + "Form": form, }) fmt.Println(b.String()) From 3102ac457414f2408c0db2404d2e27469dd14a45 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 18:16:19 +0200 Subject: [PATCH 077/122] add playground --- content/docs/rendering/_index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/docs/rendering/_index.md b/content/docs/rendering/_index.md index 4d4ce01..dcd6781 100644 --- a/content/docs/rendering/_index.md +++ b/content/docs/rendering/_index.md @@ -35,7 +35,7 @@ fmt.Println(b.String()) {{% goplay-auto-import-main %}} {{% /goplay-auto-import-main %}} From 092dc890817d5bf1dd419de2901fbd3c18eb14d6 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 18:17:08 +0200 Subject: [PATCH 078/122] add playground --- content/docs/rendering/_index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/docs/rendering/_index.md b/content/docs/rendering/_index.md index dcd6781..5263fe0 100644 --- a/content/docs/rendering/_index.md +++ b/content/docs/rendering/_index.md @@ -34,6 +34,7 @@ fmt.Println(b.String()) {{% goplay-auto-import-main %}} {{% /goplay-auto-import-main %}} From 1751d55fe4e85a47d5d98a0a5987ced0a95c34f7 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 21:48:19 +0200 Subject: [PATCH 080/122] feat(rendering): add comments --- content/docs/rendering/_index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/docs/rendering/_index.md b/content/docs/rendering/_index.md index 4c66cc4..4bc00d3 100644 --- a/content/docs/rendering/_index.md +++ b/content/docs/rendering/_index.md @@ -43,7 +43,8 @@ fmt.Println(b.String()) @import "gitnet.fr/deblan/go-form/theme" form := example.CreateDataForm() -render := theme.NewRenderer(theme.Bootstrap5) +render := theme.NewRenderer(theme.Html5) +// render := theme.NewRenderer(theme.Bootstrap5) tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(`{{ form .Form }}`) From fa5582ee4f83364b808aef80c921f7246a5b5db2 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 21:53:24 +0200 Subject: [PATCH 081/122] fix(theme): checkbox is check on nil value --- theme/html5.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/html5.go b/theme/html5.go index a5803a9..2a85aee 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -185,7 +185,7 @@ var Html5 = CreateTheme(func() map[string]RenderFunc { ID(field.GetId()), Type(fieldType), Value(value), - If(fieldType == "checkbox" && field.Data != false, Checked()), + If(fieldType == "checkbox" && field.Data != nil && field.Data != false, Checked()), If(field.HasOption("required") && field.GetOption("required").AsBool(), Required()), parent["input_attributes"](parent, field), ) From 2296b945b221229e8b298929fd4135dafcf98842 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 21:53:43 +0200 Subject: [PATCH 082/122] feat(example): remove boostrap classes --- example/form.go | 53 +------------------------------------------------ 1 file changed, 1 insertion(+), 52 deletions(-) diff --git a/example/form.go b/example/form.go index d945a99..458f33b 100644 --- a/example/form.go +++ b/example/form.go @@ -64,9 +64,6 @@ func CreateDataForm() *form.Form { WithOptions( form.NewOption("label", "Bytes"), form.NewOption("required", true), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithBeforeMount(func(data any) (any, error) { return cast.ToString(data), nil @@ -81,9 +78,6 @@ func CreateDataForm() *form.Form { WithOptions( form.NewOption("label", "Text"), form.NewOption("help", "Must contain 'deblan'"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithConstraints( validation.NewRegex(`deblan`), @@ -91,9 +85,6 @@ func CreateDataForm() *form.Form { form.NewFieldCheckbox("Checkbox"). WithOptions( form.NewOption("label", "Checkbox"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), form.NewSubForm("Inputs"). WithOptions( @@ -103,9 +94,6 @@ func CreateDataForm() *form.Form { form.NewFieldNumber("Number"). WithOptions( form.NewOption("label", "Number"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithConstraints( validation.NewRange().WithRange(1, 20), @@ -114,16 +102,10 @@ func CreateDataForm() *form.Form { form.NewFieldRange("Range"). WithOptions( form.NewOption("label", "Range"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), form.NewFieldMail("Mail"). WithOptions( form.NewOption("label", "Mail"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithConstraints( validation.Mail{}, @@ -131,9 +113,6 @@ func CreateDataForm() *form.Form { form.NewFieldPassword("Password"). WithOptions( form.NewOption("label", "Password"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithConstraints( validation.NewLength().WithMin(10), @@ -147,30 +126,18 @@ func CreateDataForm() *form.Form { form.NewFieldDate("Date"). WithOptions( form.NewOption("label", "Date"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), form.NewFieldDatetime("DateTime"). WithOptions( form.NewOption("label", "Datetime"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), form.NewFieldDatetimeLocal("DateTimeLocal"). WithOptions( form.NewOption("label", "DateTime local"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), form.NewFieldTime("Time"). WithOptions( form.NewOption("label", "Time"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), ), form.NewSubForm("Choices"). @@ -180,9 +147,6 @@ func CreateDataForm() *form.Form { WithOptions( form.NewOption("choices", itemsChoices), form.NewOption("label", "Select"), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithConstraints( validation.NewNotBlank(), @@ -192,9 +156,6 @@ func CreateDataForm() *form.Form { form.NewOption("choices", itemsChoices), form.NewOption("label", "Select (expanded)"), form.NewOption("expanded", true), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), form.NewFieldChoice("MultipleSelect"). WithSlice(). @@ -202,9 +163,6 @@ func CreateDataForm() *form.Form { form.NewOption("choices", itemsChoices), form.NewOption("label", "Multiple select"), form.NewOption("multiple", true), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ). WithConstraints( validation.NewNotBlank(), @@ -217,9 +175,6 @@ func CreateDataForm() *form.Form { form.NewOption("label", "Multiple select (expanded)"), form.NewOption("expanded", true), form.NewOption("multiple", true), - form.NewOption("row_attr", form.Attrs{ - "class": "col-12 mb-3", - }), ), ), form.NewFieldCsrf("_csrf_token").WithData("my-token"), @@ -232,13 +187,7 @@ func CreateDataForm() *form.Form { ). End(). WithOptions( - form.NewOption("help", "form help"), - form.NewOption("help_attr", form.Attrs{ - "class": "btn btn-primary", - }), - form.NewOption("attr", form.Attrs{ - "class": "row", - }), + form.NewOption("help", "Form help"), ). WithMethod(http.MethodPost). WithAction("/") From 6963fbad79f7060ce04ec4be89902451d1c8b01b Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 21:54:54 +0200 Subject: [PATCH 083/122] update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 195158a..d2c0db3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ## [Unreleased] +## v1.1.2 + +### Added + +- chore(example): remove boostrap classes + +### Fixed + +- fix(theme): checkbox is check on nil value + ## v1.1.1 ### Fixed From 45674ba0543d9b5bdb5c877b6ed956be6f9e7473 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 21:58:06 +0200 Subject: [PATCH 084/122] fix(goplay): replace quotes --- static/js/custom.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/static/js/custom.js b/static/js/custom.js index 3b7f770..1322d0d 100644 --- a/static/js/custom.js +++ b/static/js/custom.js @@ -102,12 +102,12 @@ function createFieldPlaygroundCode(code) { return `package main import ( - 'fmt' - 'html/template' - 'strings' + "fmt" + "html/template" + "strings" - 'gitnet.fr/deblan/go-form/form' - 'gitnet.fr/deblan/go-form/theme' + "gitnet.fr/deblan/go-form/form" + "gitnet.fr/deblan/go-form/theme" ) func main() { From 5f51ef354fdfdf86cd5170888758c80b3ec2d2f6 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 21:59:23 +0200 Subject: [PATCH 085/122] fix(goplay): replace quotes --- static/js/custom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/custom.js b/static/js/custom.js index 1322d0d..e8d886e 100644 --- a/static/js/custom.js +++ b/static/js/custom.js @@ -118,7 +118,7 @@ ${code} func r(f *form.Form) { render := theme.NewRenderer(theme.Html5) - tpl, _ := template.New('example').Funcs(render.FuncMap()).Parse(\`{{ form_widget (.Form.GetField "Foo") }}\`) + tpl, _ := template.New("example").Funcs(render.FuncMap()).Parse(\`{{ form_widget (.Form.GetField "Foo") }}\`) b := new(strings.Builder) tpl.Execute(b, map[string]any{"Form": f}) fmt.Println(b.String()) From 73efea4329adebf852eba9794ce5e8dacd125183 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 28 Jul 2025 22:02:53 +0200 Subject: [PATCH 086/122] feat(goplay): set readonly textarea --- layouts/shortcodes/goplay-auto-import-main.html | 2 +- layouts/shortcodes/goplay-field.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/layouts/shortcodes/goplay-auto-import-main.html b/layouts/shortcodes/goplay-auto-import-main.html index 4f61f13..adc4f0b 100644 --- a/layouts/shortcodes/goplay-auto-import-main.html +++ b/layouts/shortcodes/goplay-auto-import-main.html @@ -2,7 +2,7 @@
      Test me - +
      -
      - Data -
      {{ .Dump }}
      -
      + + + + + +
      +
      {{ .Dump }}
      +
      +
      + JSON +
      {{ .Json }}
      +
      +
      {{ form .Form }} @@ -105,9 +120,12 @@ func main() { var dump godump.Dumper dump.Theme = godump.Theme{} + j, _ := json.MarshalIndent(f, " ", " ") + w.Header().Set("Content-Type", "text/html; charset=utf-8") tpl.Execute(w, map[string]any{ "Form": f, + "Json": string(j), "Dump": template.HTML(dump.Sprint(data)), }) }) diff --git a/theme/html5.go b/theme/html5.go index a441e48..a709e4e 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -1,6 +1,7 @@ package theme import ( + "bytes" "fmt" "github.com/spf13/cast" @@ -348,6 +349,53 @@ var Html5 = CreateTheme(func() map[string]RenderFunc { ) } + theme["collection"] = func(parent map[string]RenderFunc, args ...any) Node { + field := args[0].(*form.Field) + + var prototype string + + if opt := field.GetOption("form"); opt != nil { + if val, ok := opt.Value.(*form.Form); ok { + var buffer bytes.Buffer + dest := form.NewFieldSubForm(field.Name) + + for _, c := range val.Fields { + child := c.Copy() + child.NamePrefix = "[__name__]" + dest.Add(child) + } + + fieldPrototype := parent["form_row"](parent, dest) + fieldPrototype.Render(&buffer) + + prototype = buffer.String() + } + } + + field.WithOptions(form.NewOption("prototype", prototype)) + field.Widget = "collection_build" + + return Div( + Attr("data-prototype", prototype), + parent["form_widget"](parent, field), + ) + } + + theme["collection_build"] = func(parent map[string]RenderFunc, args ...any) Node { + field := args[0].(*form.Field) + prototype := field.GetOption("prototype").AsString() + var items []Node + + for _, child := range field.Children { + items = append(items, parent["form_row"](parent, child)) + } + + return Div( + Attr("data-prototype", prototype), + Group(items), + ) + } + theme["form_widget"] = func(parent map[string]RenderFunc, args ...any) Node { field := args[0].(*form.Field) diff --git a/util/collection.go b/util/collection.go new file mode 100644 index 0000000..7ee4d66 --- /dev/null +++ b/util/collection.go @@ -0,0 +1,96 @@ +package util + +import ( + "regexp" + "strings" + + "github.com/spf13/cast" +) + +type CollectionValue struct { + Name string + Value string + Children map[string]*CollectionValue +} + +type Collection struct { + Children map[int]*CollectionValue +} + +func NewCollection() *Collection { + return &Collection{ + Children: make(map[int]*CollectionValue), + } +} + +func NewCollectionValue(name string) *CollectionValue { + return &CollectionValue{ + Name: name, + Children: make(map[string]*CollectionValue), + } +} + +func (c *Collection) Add(indexes []string, value string) { + firstIndex := cast.ToInt(indexes[0]) + size := len(indexes) + child := c.Children[firstIndex] + + if child == nil { + child = NewCollectionValue(indexes[0]) + c.Children[firstIndex] = child + } + + child.Add(indexes[1:size], value, nil) +} + +func (c *Collection) Slice() []any { + var result []any + + for _, child := range c.Children { + result = append(result, child.Map()) + } + + return result +} + +func (c *CollectionValue) Map() any { + if len(c.Children) == 0 { + return c.Value + } + + results := make(map[string]any) + + for _, child := range c.Children { + results[child.Name] = child.Map() + } + + return results +} + +func (c *CollectionValue) Add(indexes []string, value string, lastChild *CollectionValue) { + size := len(indexes) + + if size > 0 { + firstIndex := indexes[0] + child := c.Children[firstIndex] + + child = NewCollectionValue(indexes[0]) + c.Children[firstIndex] = child + + child.Add(indexes[1:size], value, child) + } else { + lastChild.Value = value + } +} + +func ExtractDataIndexes(value string) []string { + re := regexp.MustCompile(`\[[^\]]+\]`) + items := re.FindAll([]byte(value), -1) + var results []string + + for _, i := range items { + results = append(results, strings.Trim(string(i), "[]")) + } + + return results +} diff --git a/util/inspect.go b/util/inspect.go index 17c0839..22fa4f4 100644 --- a/util/inspect.go +++ b/util/inspect.go @@ -29,6 +29,10 @@ func InspectStruct(input interface{}) (map[string]interface{}, error) { val = val.Elem() } + if val.Kind() == reflect.Map { + return input.(map[string]interface{}), nil + } + if val.Kind() != reflect.Struct { return nil, errors.New("Invalid type") } From 97f5cf321560b7abd32bd58a77d590aa54f94cf9 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 26 Sep 2025 17:49:39 +0200 Subject: [PATCH 115/122] [WIP] feat: handle collection in form rendering, mount and bind --- form/field.go | 41 ++++++++++++++++++++++++++++++---------- form/field_collection.go | 33 +++++++++++++++++++------------- form/form.go | 11 +++-------- main.go | 30 +++++++++++++++++++++++++++-- theme/html5.go | 5 +---- 5 files changed, 83 insertions(+), 37 deletions(-) diff --git a/form/field.go b/form/field.go index dee37bf..b4484df 100644 --- a/form/field.go +++ b/form/field.go @@ -21,20 +21,13 @@ import ( "slices" "strings" + "github.com/yassinebenaid/godump" "gitnet.fr/deblan/go-form/util" "gitnet.fr/deblan/go-form/validation" ) // Generic function for field.Validation func FieldValidation(f *Field) bool { - // if f.IsCollection { - // if formOption := f.GetOption("form"); formOption != nil { - // if formValue, ok := formOption.Value.(*Form); ok { - // godump.Dump(formValue) - // } - // } - // } - if len(f.Children) > 0 { isValid := true @@ -47,6 +40,10 @@ func FieldValidation(f *Field) bool { } isValid = isValid && isChildValid + + for _, sc := range c.Children { + isValid = isValid && FieldValidation(sc) + } } return isValid @@ -115,6 +112,7 @@ func NewField(name, widget string) *Field { func (f *Field) Copy() *Field { return &Field{ Name: f.Name, + Form: f.Form, Widget: f.Widget, Options: f.Options, Constraints: f.Constraints, @@ -332,7 +330,7 @@ func (f *Field) Mount(data any) error { } // Bind the data into the given map -func (f *Field) Bind(data map[string]any, key *string) error { +func (f *Field) Bind(data map[string]any, key *string, parentIsSlice bool) error { if len(f.Children) == 0 { v, err := f.BeforeBind(f.Data) @@ -352,7 +350,30 @@ func (f *Field) Bind(data map[string]any, key *string) error { data[f.Name] = make(map[string]any) for _, child := range f.Children { - child.Bind(data[f.Name].(map[string]any), key) + child.Bind(data[f.Name].(map[string]any), key, f.IsCollection) + } + + if f.IsCollection { + var nextData []any + values := data[f.Name].(map[string]any) + var keys []string + + for key, _ := range values { + keys = append(keys, key) + } + + slices.Sort(keys) + + for _, key := range keys { + for valueKey, value := range values { + if valueKey == key { + godump.Dump([]string{valueKey, key}) + nextData = append(nextData, value) + } + } + } + + data[f.Name] = nextData } return nil diff --git a/form/field_collection.go b/form/field_collection.go index 436ea27..52b8e02 100644 --- a/form/field_collection.go +++ b/form/field_collection.go @@ -41,22 +41,29 @@ func NewFieldCollection(name string) *Field { slice := reflect.ValueOf(data) for i := 0; i < slice.Len(); i++ { - form := src.Copy() - form.Mount(slice.Index(i).Interface()) + name := fmt.Sprintf("%d", i) + value := slice.Index(i).Interface() - field := f.Copy() - field.Widget = "sub_form" - field.Name = fmt.Sprintf("%d", i) - field.Add(form.Fields...) - field. - RemoveOption("form"). - RemoveOption("label") + if f.HasChild(name) { + f.GetChild(name).Mount(value) + } else { + form := src.Copy() + form.Mount(value) - for _, c := range field.Children { - c.NamePrefix = fmt.Sprintf("[%d]", i) + field := f.Copy() + field.Widget = "sub_form" + field.Name = name + field.Add(form.Fields...) + field. + RemoveOption("form"). + RemoveOption("label") + + for _, c := range field.Children { + c.NamePrefix = fmt.Sprintf("[%d]", i) + } + + f.Add(field) } - - f.Add(field) } } } diff --git a/form/form.go b/form/form.go index b96df95..c17da05 100644 --- a/form/form.go +++ b/form/form.go @@ -25,7 +25,6 @@ import ( "strings" "github.com/mitchellh/mapstructure" - "github.com/yassinebenaid/godump" "gitnet.fr/deblan/go-form/util" "gitnet.fr/deblan/go-form/validation" ) @@ -110,10 +109,8 @@ func (f *Form) End() *Form { func (f *Form) AddGlobalField(field *Field) { f.GlobalFields = append(f.GlobalFields, field) - if field.Widget != "collection" { - for _, c := range field.Children { - f.AddGlobalField(c) - } + for _, c := range field.Children { + f.AddGlobalField(c) } } @@ -221,11 +218,9 @@ func (f *Form) Bind(data any) error { toBind := make(map[string]any) for _, field := range f.Fields { - field.Bind(toBind, nil) + field.Bind(toBind, nil, false) } - godump.Dump(toBind) - return mapstructure.Decode(toBind, data) } diff --git a/main.go b/main.go index da58d53..7c4e97a 100644 --- a/main.go +++ b/main.go @@ -16,8 +16,6 @@ func main() { data := example.ExampleData{} data.Collection = []example.CollectionItem{ {"Value a 1", "Value b 1"}, - {"Value a 2", "Value b 2"}, - {"Value a 3", "Value b 3"}, } f := example.CreateDataForm() @@ -113,6 +111,34 @@ func main() { {{ form .Form }} + + `) diff --git a/theme/html5.go b/theme/html5.go index a709e4e..a4728e0 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -375,10 +375,7 @@ var Html5 = CreateTheme(func() map[string]RenderFunc { field.WithOptions(form.NewOption("prototype", prototype)) field.Widget = "collection_build" - return Div( - Attr("data-prototype", prototype), - parent["form_widget"](parent, field), - ) + return parent["form_widget"](parent, field) } theme["collection_build"] = func(parent map[string]RenderFunc, args ...any) Node { From b9c5f6a2fd77130d02b5cc0d2a908047564a1bca Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 16:30:27 +0200 Subject: [PATCH 116/122] fix(collection): always validate fields when another field is invalid" --- form/field.go | 10 ++++------ form/field_choice.go | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/form/field.go b/form/field.go index b4484df..f1558c2 100644 --- a/form/field.go +++ b/form/field.go @@ -21,13 +21,12 @@ import ( "slices" "strings" - "github.com/yassinebenaid/godump" "gitnet.fr/deblan/go-form/util" "gitnet.fr/deblan/go-form/validation" ) // Generic function for field.Validation -func FieldValidation(f *Field) bool { +func DefaultFieldValidation(f *Field) bool { if len(f.Children) > 0 { isValid := true @@ -39,10 +38,10 @@ func FieldValidation(f *Field) bool { c.Errors = errs } - isValid = isValid && isChildValid + isValid = isChildValid && isValid for _, sc := range c.Children { - isValid = isValid && FieldValidation(sc) + isValid = DefaultFieldValidation(sc) && isValid } } @@ -104,7 +103,7 @@ func NewField(name, widget string) *Field { NewOption("help_attr", Attrs{}), ) - f.Validate = FieldValidation + f.Validate = DefaultFieldValidation return f } @@ -367,7 +366,6 @@ func (f *Field) Bind(data map[string]any, key *string, parentIsSlice bool) error for _, key := range keys { for valueKey, value := range values { if valueKey == key { - godump.Dump([]string{valueKey, key}) nextData = append(nextData, value) } } diff --git a/form/field_choice.go b/form/field_choice.go index 70d2545..16c06fc 100644 --- a/form/field_choice.go +++ b/form/field_choice.go @@ -145,7 +145,7 @@ func NewFieldChoice(name string) *Field { ) f.Validate = func(field *Field) bool { - isValid := FieldValidation(field) + isValid := field.Validate(field) if len(validation.NewNotBlank().Validate(field.Data)) == 0 { choices := field.GetOption("choices").Value.(*Choices) From 1d40aa6b09135368915c10216dcb11dce98bb05c Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 18:13:43 +0200 Subject: [PATCH 117/122] refactor: refactor the example --- example.go | 76 +++++++++++++ example/form.go | 32 +++--- example/view/bootstrap.html | 113 +++++++++++++++++++ example/view/html5.html | 133 ++++++++++++++++++++++ main.go | 219 ------------------------------------ 5 files changed, 338 insertions(+), 235 deletions(-) create mode 100644 example.go create mode 100644 example/view/bootstrap.html create mode 100644 example/view/html5.html delete mode 100644 main.go diff --git a/example.go b/example.go new file mode 100644 index 0000000..2aa6727 --- /dev/null +++ b/example.go @@ -0,0 +1,76 @@ +package main + +import ( + "embed" + "encoding/json" + "html/template" + "log" + "net/http" + + "github.com/yassinebenaid/godump" + "gitnet.fr/deblan/go-form/example" + "gitnet.fr/deblan/go-form/theme" +) + +//go:embed example/view/*.html +var templates embed.FS + +func handler(view, action string, formRenderer *theme.Renderer, w http.ResponseWriter, r *http.Request) { + entity := example.ExampleData{} + form := example.CreateDataForm(action) + + form.Mount(entity) + + if r.Method == form.Method { + form.HandleRequest(r) + + if form.IsSubmitted() && form.IsValid() { + form.Bind(&entity) + } + } + + content, _ := templates.ReadFile(view) + + formAsJson, _ := json.MarshalIndent(form, " ", " ") + + tpl, _ := template.New("page"). + Funcs(formRenderer.FuncMap()). + Parse(string(content)) + + w.Header().Set("Content-Type", "text/html; charset=utf-8") + + var dump godump.Dumper + dump.Theme = godump.Theme{} + + tpl.Execute(w, map[string]any{ + "isSubmitted": form.IsSubmitted(), + "isValid": form.IsValid(), + "form": form, + "json": string(formAsJson), + "dump": template.HTML(dump.Sprint(entity)), + }) +} + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + handler( + "example/view/html5.html", + "/", + theme.NewRenderer(theme.Html5), + w, + r, + ) + }) + + http.HandleFunc("/bootstrap", func(w http.ResponseWriter, r *http.Request) { + handler( + "example/view/bootstrap.html", + "/bootstrap", + theme.NewRenderer(theme.Bootstrap5), + w, + r, + ) + }) + + log.Fatal(http.ListenAndServe(":1122", nil)) +} diff --git a/example/form.go b/example/form.go index 4fd035c..8c516ba 100644 --- a/example/form.go +++ b/example/form.go @@ -50,7 +50,7 @@ type CollectionItem struct { ValueB string } -func CreateDataForm() *form.Form { +func CreateDataForm(action string) *form.Form { items := []Item{ Item{Id: 1, Name: "Item 1"}, Item{Id: 2, Name: "Item 2"}, @@ -66,19 +66,6 @@ func CreateDataForm() *form.Form { }) return form.NewForm( - form.NewFieldCollection("Collection"). - WithOptions( - form.NewOption("label", "Collection"), - form.NewOption("form", form.NewForm( - form.NewFieldText("ValueA"). - WithOptions(form.NewOption("label", "Value A")). - WithConstraints( - validation.NewNotBlank(), - ), - form.NewFieldText("ValueB"). - WithOptions(form.NewOption("label", "Value B")), - )), - ), form.NewFieldText("Bytes"). WithOptions( form.NewOption("label", "Bytes"), @@ -196,6 +183,19 @@ func CreateDataForm() *form.Form { form.NewOption("multiple", true), ), ), + form.NewFieldCollection("Collection"). + WithOptions( + form.NewOption("label", "Collection"), + form.NewOption("form", form.NewForm( + form.NewFieldText("ValueA"). + WithOptions(form.NewOption("label", "Value A")). + WithConstraints( + validation.NewNotBlank(), + ), + form.NewFieldText("ValueB"). + WithOptions(form.NewOption("label", "Value B")), + )), + ), form.NewFieldCsrf("_csrf_token").WithData("my-token"), form.NewSubmit("submit"). WithOptions( @@ -206,8 +206,8 @@ func CreateDataForm() *form.Form { ). End(). WithOptions( - form.NewOption("help", "Form help"), + form.NewOption("help", "Form global help"), ). WithMethod(http.MethodPost). - WithAction("/") + WithAction(action) } diff --git a/example/view/bootstrap.html b/example/view/bootstrap.html new file mode 100644 index 0000000..7b848f1 --- /dev/null +++ b/example/view/bootstrap.html @@ -0,0 +1,113 @@ + + + + + Form with Bootstrap + + + + +
      +
      + Debug view +
      + Submitted: + {{ .isSubmitted }} +
      +
      + Valid: + {{ .isValid }} +
      + +
      + Dump of data +
      {{ .dump }}
      +
      + +
      + Form as JSON +
      {{ .json }}
      +
      +
      + + {{if .isValid}} +
      The form is valid!
      + {{else}} +
      The form is invalid!
      + {{end}} + + {{ form .form }} +
      + + + + diff --git a/example/view/html5.html b/example/view/html5.html new file mode 100644 index 0000000..90c33fb --- /dev/null +++ b/example/view/html5.html @@ -0,0 +1,133 @@ + + + + + Form HTML5 (with Pico) + + + + + + + + +
      + Debug view + +
      + Submitted: + {{ .isSubmitted }} +
      +
      + Valid: + {{ .isValid }} +
      + +
      + Dump of data +
      {{ .dump }}
      +
      + +
      + Form as JSON +
      {{ .json }}
      +
      + +
      + + {{if .isValid}} +

      The form is valid!

      + {{else}} +

      The form is invalid!

      + {{end}} + + {{ form .form }} + + + + + diff --git a/main.go b/main.go deleted file mode 100644 index 7c4e97a..0000000 --- a/main.go +++ /dev/null @@ -1,219 +0,0 @@ -package main - -import ( - "encoding/json" - "html/template" - "log" - "net/http" - - "github.com/yassinebenaid/godump" - "gitnet.fr/deblan/go-form/example" - "gitnet.fr/deblan/go-form/theme" -) - -func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - data := example.ExampleData{} - data.Collection = []example.CollectionItem{ - {"Value a 1", "Value b 1"}, - } - - f := example.CreateDataForm() - f.Mount(data) - - if r.Method == f.Method { - f.HandleRequest(r) - - if f.IsSubmitted() && f.IsValid() { - f.Bind(&data) - // godump.Dump(data) - } - } - - render := theme.NewRenderer(theme.Html5) - - tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(` - - - - - Form - - - -
      -
      - Submitted - {{ .Form.IsSubmitted }} -
      -
      - Valid - {{ .Form.IsValid }} -
      - - - - - -
      -
      {{ .Dump }}
      -
      -
      - JSON -
      {{ .Json }}
      -
      -
      -
      - - {{ form .Form }} - - - - - `) - - var dump godump.Dumper - dump.Theme = godump.Theme{} - - j, _ := json.MarshalIndent(f, " ", " ") - - w.Header().Set("Content-Type", "text/html; charset=utf-8") - tpl.Execute(w, map[string]any{ - "Form": f, - "Json": string(j), - "Dump": template.HTML(dump.Sprint(data)), - }) - }) - - http.HandleFunc("/bootstrap", func(w http.ResponseWriter, r *http.Request) { - data := example.ExampleData{} - - f := example.CreateDataForm() - f.WithAction("/bootstrap") - f.Mount(data) - - if r.Method == f.Method { - f.HandleRequest(r) - - if f.IsSubmitted() && f.IsValid() { - f.Bind(&data) - godump.Dump(data) - } - } - - render := theme.NewRenderer(theme.Bootstrap5) - - tpl, _ := template.New("page").Funcs(render.FuncMap()).Parse(` - - - - - Form - - - -
      -
      -
      - Submitted - {{ .Form.IsSubmitted }} -
      -
      - Valid - {{ .Form.IsValid }} -
      -
      - Data -
      {{ .Dump }}
      -
      -
      - - {{ form .Form }} -
      - - - `) - - var dump godump.Dumper - dump.Theme = godump.Theme{} - - w.Header().Set("Content-Type", "text/html; charset=utf-8") - tpl.Execute(w, map[string]any{ - "Form": f, - "Dump": template.HTML(dump.Sprint(data)), - }) - }) - - log.Fatal(http.ListenAndServe(":1122", nil)) -} From bec0acd2f2e333e7317eb36cfc1211f09c43fb5f Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 18:14:08 +0200 Subject: [PATCH 118/122] feat(theme/html5): add classes for help and errors html nodes --- theme/html5.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/theme/html5.go b/theme/html5.go index a4728e0..2d7889e 100644 --- a/theme/html5.go +++ b/theme/html5.go @@ -59,6 +59,7 @@ var Html5 = CreateTheme(func() map[string]RenderFunc { } return Ul( + Class("gf-errors"), Group(result), ) } @@ -94,6 +95,7 @@ var Html5 = CreateTheme(func() map[string]RenderFunc { } return Div( + Class("gf-help"), Text(help), extra, ) @@ -452,6 +454,7 @@ var Html5 = CreateTheme(func() map[string]RenderFunc { form := args[0].(*form.Form) return Form( + Class("gf-form"), Action(form.Action), Method(form.Method), parent["form_attributes"](parent, form), From 7373b1921235164584cd9a9d292118a61012d3e6 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 18:15:23 +0200 Subject: [PATCH 119/122] doc: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f052f98..12a7ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## [Unreleased] +### Added + +- feat: add collection widget + ## v1.4.0 ### Added From f70f0a1f9d191307163268fe864aa5476eedc6ed Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 23:23:13 +0200 Subject: [PATCH 120/122] feat(example): add theme picker --- example.go | 25 ++++++++++++++---------- example/form.go | 38 +++++++++++++++++++++++++++++++++++++ example/view/bootstrap.html | 12 +++++++++--- example/view/html5.html | 9 +++++++-- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/example.go b/example.go index 2aa6727..91918d4 100644 --- a/example.go +++ b/example.go @@ -17,21 +17,24 @@ var templates embed.FS func handler(view, action string, formRenderer *theme.Renderer, w http.ResponseWriter, r *http.Request) { entity := example.ExampleData{} - form := example.CreateDataForm(action) + entityForm := example.CreateDataForm(action) + entityForm.Mount(entity) - form.Mount(entity) + style := example.NewTheme(action) + styleForm := example.CreateThemeSelectorForm() + styleForm.Mount(style) - if r.Method == form.Method { - form.HandleRequest(r) + if r.Method == entityForm.Method { + entityForm.HandleRequest(r) - if form.IsSubmitted() && form.IsValid() { - form.Bind(&entity) + if entityForm.IsSubmitted() && entityForm.IsValid() { + entityForm.Bind(&entity) } } content, _ := templates.ReadFile(view) - formAsJson, _ := json.MarshalIndent(form, " ", " ") + formAsJson, _ := json.MarshalIndent(entityForm, " ", " ") tpl, _ := template.New("page"). Funcs(formRenderer.FuncMap()). @@ -43,9 +46,10 @@ func handler(view, action string, formRenderer *theme.Renderer, w http.ResponseW dump.Theme = godump.Theme{} tpl.Execute(w, map[string]any{ - "isSubmitted": form.IsSubmitted(), - "isValid": form.IsValid(), - "form": form, + "isSubmitted": entityForm.IsSubmitted(), + "isValid": entityForm.IsValid(), + "form": entityForm, + "styleForm": styleForm, "json": string(formAsJson), "dump": template.HTML(dump.Sprint(entity)), }) @@ -72,5 +76,6 @@ func main() { ) }) + log.Println("Browse: http://localhost:1122") log.Fatal(http.ListenAndServe(":1122", nil)) } diff --git a/example/form.go b/example/form.go index 8c516ba..fc6e8bf 100644 --- a/example/form.go +++ b/example/form.go @@ -50,6 +50,10 @@ type CollectionItem struct { ValueB string } +type Theme struct { + Value string `field:"lowerCamel"` +} + func CreateDataForm(action string) *form.Form { items := []Item{ Item{Id: 1, Name: "Item 1"}, @@ -211,3 +215,37 @@ func CreateDataForm(action string) *form.Form { WithMethod(http.MethodPost). WithAction(action) } + +func NewTheme(value string) *Theme { + return &Theme{Value: value} +} + +func CreateThemeSelectorForm() *form.Form { + choices := form.NewChoices([]map[string]string{ + map[string]string{"value": "/", "label": "Html5"}, + map[string]string{"value": "/bootstrap", "label": "Bootstrap5"}, + }) + + choices.LabelBuilder = func(key int, item any) string { + return item.(map[string]string)["label"] + } + + choices.ValueBuilder = func(key int, item any) string { + return item.(map[string]string)["value"] + } + + return form.NewForm( + form.NewFieldChoice("value"). + WithOptions( + form.NewOption("choices", choices), + form.NewOption("label", "Select a theme"), + form.NewOption("required", true), + form.NewOption("attr", form.Attrs{ + "onchange": "document.location.href = this.value", + }), + ), + ). + End(). + WithName(""). + WithMethod(http.MethodGet) +} diff --git a/example/view/bootstrap.html b/example/view/bootstrap.html index 7b848f1..23543fd 100644 --- a/example/view/bootstrap.html +++ b/example/view/bootstrap.html @@ -2,11 +2,12 @@ - Form with Bootstrap + Demo of go-form with Bootstrap -
      +
      + {{ form_widget (.styleForm.GetField "value") }} +
      + +

      Demo of go-form with Bootstrap

      +
      Debug view
      diff --git a/example/view/html5.html b/example/view/html5.html index 90c33fb..88db2d8 100644 --- a/example/view/html5.html +++ b/example/view/html5.html @@ -2,7 +2,7 @@ - Form HTML5 (with Pico) + Demo of go-form (pure HTML5 and Pico) @@ -41,7 +41,12 @@ } - + + {{ form_widget (.styleForm.GetField "value") }} +
      + +

      Demo of go-form (pure HTML5 and Pico)

      +
      Debug view From fe5d84d200a2e7dd53d2b46870fd7f31656d4813 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 23:24:42 +0200 Subject: [PATCH 121/122] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12a7ade..ba56fe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,11 @@ ## [Unreleased] +## v1.5.0 + ### Added - feat: add collection widget +- feat: refactoring and improvement of example ## v1.4.0 From f451d69d702b350f7361de930153b88f4638015f Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Wed, 1 Oct 2025 23:30:16 +0200 Subject: [PATCH 122/122] doc: add documentation of functions and licence --- form/field.go | 2 ++ form/field_collection.go | 10 +++++----- form/form.go | 1 + util/collection.go | 15 +++++++++++++++ util/transformer.go | 15 +++++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/form/field.go b/form/field.go index f1558c2..fe63326 100644 --- a/form/field.go +++ b/form/field.go @@ -158,6 +158,7 @@ func (f *Field) WithOptions(options ...*Option) *Field { return f } +// Remove an option if exists func (f *Field) RemoveOption(name string) *Field { var options []*Option @@ -377,6 +378,7 @@ func (f *Field) Bind(data map[string]any, key *string, parentIsSlice bool) error return nil } +// Generates a tree of errors func (f *Field) ErrorsTree(tree map[string]any, key *string) { var index string diff --git a/form/field_collection.go b/form/field_collection.go index 52b8e02..3f3ece1 100644 --- a/form/field_collection.go +++ b/form/field_collection.go @@ -1,10 +1,5 @@ package form -import ( - "fmt" - "reflect" -) - // @license GNU AGPL version 3 or any later version // // This program is free software: you can redistribute it and/or modify @@ -20,6 +15,11 @@ import ( // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +import ( + "fmt" + "reflect" +) + // Generates a sub form func NewFieldCollection(name string) *Field { f := NewField(name, "collection"). diff --git a/form/form.go b/form/form.go index c17da05..04016d3 100644 --- a/form/form.go +++ b/form/form.go @@ -293,6 +293,7 @@ func (f *Form) IsSubmitted() bool { return f.RequestData != nil } +// Generates a tree of errors func (f *Form) ErrorsTree() map[string]any { errors := make(map[string]any) diff --git a/util/collection.go b/util/collection.go index 7ee4d66..f0aa649 100644 --- a/util/collection.go +++ b/util/collection.go @@ -1,5 +1,20 @@ package util +// @license GNU AGPL version 3 or any later version +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + import ( "regexp" "strings" diff --git a/util/transformer.go b/util/transformer.go index 743b117..a942fa1 100644 --- a/util/transformer.go +++ b/util/transformer.go @@ -1,5 +1,20 @@ package util +// @license GNU AGPL version 3 or any later version +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + import ( "fmt" "net/url"