commit caa95c66b6388118123cb6bc72febffaad39e27f Author: Adriano Caloiaro Date: Tue Nov 5 09:18:04 2024 -0700 initial commit diff --git a/.air.toml b/.air.toml new file mode 100644 index 0000000..ab308e9 --- /dev/null +++ b/.air.toml @@ -0,0 +1,45 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = [] + cmd = "go build -o ./tmp/frm cmd/dev_server/main.go" + delay = 100 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] + exclude_file = ["internal/db.go", "internal/models.go", "internal/sqlc_query.sql.go", "internal/copyfrom.go", "internal/queries.sql.go"] + exclude_regex = ["_test.go", ".*_templ.go", ".*_enumer.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "templ", "html", "js", "css", "sql", "yaml" ] + include_file = ["css/tailwind.css", "sqlc_query.sql", "sqlc.yaml"] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + post_cmd = [] + pre_cmd = [] + rerun = false + rerun_delay = 500 + send_interrupt = false + stop_on_error = false + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = true + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..1e2c758 --- /dev/null +++ b/.envrc @@ -0,0 +1,15 @@ +if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM=" +fi + +watch_file flake.nix +watch_file flake.lock +watch_file .env +watch_file go.mod +watch_file go.lock + +if ! use flake . --no-pure-eval +then + echo "devenv could not be built. The devenv environment was not loaded." >&2 +fi + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76f4270 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.direnv +.devenv +.pre-commit-config.yaml +.env +tmp diff --git a/README.md b/README.md new file mode 100644 index 0000000..9911d75 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# frm + +frm is an embeddable HTML form builder for Go. + +**This is a work in progress and not production-ready** + +## Usage + + + +## Inspiration + +This project is heavily inspired by [opnform](https://github.com/jhumanj/opnform). OpnForm is very good, and if you don't have an _embeddable in Go_ requirement, then you should consider OpnForm instead. diff --git a/cmd/dev_server/main.go b/cmd/dev_server/main.go new file mode 100644 index 0000000..f337c54 --- /dev/null +++ b/cmd/dev_server/main.go @@ -0,0 +1,84 @@ +package main + +import ( + "context" + "log/slog" + "net/http" + "os" + "time" + + "github.com/acaloiaro/frm" + "github.com/acaloiaro/frm/frmchi" + "github.com/go-chi/chi/v5" + "github.com/go-chi/httplog/v2" +) + +var ( + listenAddress = "0.0.0.0:3000" + requestLogger *httplog.Logger + logOptions *slog.HandlerOptions + logger *slog.Logger +) + +func initLogging() { + initAppLogger() + initRequestLogger() +} + +func initAppLogger() { + logLevel := os.Getenv("LOG_LEVEL") + logOptions = &slog.HandlerOptions{Level: slog.LevelDebug} + if logLevel == "INFO" { + logOptions.Level = slog.LevelInfo + } + + logger = slog.New(slog.NewTextHandler(os.Stdout, logOptions)) + +} + +func initRequestLogger() { + requestLogger = httplog.NewLogger("web", httplog.Options{ + LogLevel: logOptions.Level.Level().Level(), + Concise: true, + RequestHeaders: false, + MessageFieldName: "message", + TimeFieldFormat: time.RFC3339, + Tags: map[string]string{ + "env": "dev", + }, + QuietDownRoutes: []string{ + "/ping", + "/js/htmx.js", + "/js/htmx-response-targets.js", + "/js/hyperscript.js", + "/js/choices.min.js", + "/css/styles.css", + "/css/choices.min.css", + }, + QuietDownPeriod: 24 * 60 * 60 * time.Second, + }) +} + +func main() { + initLogging() + logger.Info("frm dev server started") + router := chi.NewRouter() + router.Use(httplog.RequestLogger(requestLogger)) + f := frm.New(frm.Args{ + PostgresURL: os.Getenv("DATABASE_URL"), + }) + err := f.Init(context.Background()) + if err != nil { + panic(err) + } + frmchi.Mount(f, router, "/frm") + s := &http.Server{ + Handler: router, + Addr: listenAddress, + ReadTimeout: time.Duration(10 * time.Second), + WriteTimeout: time.Duration(10 * time.Second), + } + err = s.ListenAndServe() + slog.Error("server exited", "error", err) + os.Exit(1) +} diff --git a/db/create_forms_test.go b/db/create_forms_test.go new file mode 100644 index 0000000..a3fbab6 --- /dev/null +++ b/db/create_forms_test.go @@ -0,0 +1,91 @@ +package db_test + +import ( + "context" + "fmt" + "os" + "reflect" + "testing" + + "github.com/acaloiaro/frm/internal" + "github.com/acaloiaro/frm/types" + "github.com/google/uuid" +) + +var ( + postgresURL = os.Getenv("DATABASE_URL") +) + +func TestCreateAndUpdateForm(t *testing.T) { + const nameUpdate = "Tell us about you" + fieldID := uuid.MustParse("1afd4bf9-42a4-4dfe-b359-d46a65ce5ba5") + fieldID2 := uuid.MustParse("2afd4bf9-42a4-4dfe-b359-d46a65ce5ba5") + fieldID3 := uuid.MustParse("3afd4bf9-42a4-4dfe-b359-d46a65ce5ba5") + fields := types.FormFields{ + fieldID.String(): types.FormField{ + ID: fieldID, + Label: "hello world", + Type: types.FormFieldTypeTextMultiple, + Required: true, + }, + } + updatedFields := types.FormFields{ + fieldID.String(): types.FormField{ + ID: fieldID, + Order: 1, + Label: "What's your name?", + Placeholder: "Tell us your name", + Type: types.FormFieldTypeTextSingle, + Required: true, + }, + fieldID2.String(): types.FormField{ + ID: fieldID2, + Order: 2, + Label: "What are your view on bears?", + Type: types.FormFieldTypeTextMultiple, + Placeholder: "Tell us how you generally feel about bears", + Required: false, + }, + fieldID3.String(): types.FormField{ + ID: fieldID3, + Order: 3, + Label: "Which type of bear is best?", + Placeholder: "Choose a bear", + Type: types.FormFieldTypeMultiSelect, + Options: []types.Option{ + {ID: uuid.New(), Label: "Black bear", Value: "Black bear", Selected: false}, + {ID: uuid.New(), Label: "Brown bear", Value: "Brown bear", Selected: false}, + {ID: uuid.New(), Label: "Blue bear", Value: "Blue bear", Selected: false}, + }, + Required: true, + }, + } + ctx := context.Background() + f, err := internal.Q(ctx, postgresURL).SaveForm(ctx, internal.SaveFormParams{ + ID: 1, + Name: "hello world", + Fields: fields, + }) + if err != nil { + t.Error(err) + return + } + + f, err = internal.Q(ctx, postgresURL).SaveForm(ctx, internal.SaveFormParams{ + ID: 1, + Name: nameUpdate, + Fields: updatedFields, + }) + if err != nil { + t.Error(err) + return + } + + if f.Name != nameUpdate { + t.Error(fmt.Errorf("name did not update: %s!=%s", f.Name, nameUpdate)) + } + + if !reflect.DeepEqual(f.Fields, updatedFields) { + t.Error(fmt.Errorf("fields did not update: %v!=%v", f.Fields, updatedFields)) + } +} diff --git a/db/migrations/20241105222317_add_forms_table.sql.down.sql b/db/migrations/20241105222317_add_forms_table.sql.down.sql new file mode 100644 index 0000000..6096c16 --- /dev/null +++ b/db/migrations/20241105222317_add_forms_table.sql.down.sql @@ -0,0 +1,2 @@ +DROP TABLE forms; +DROP SEQUENCE IF EXISTS forms_ids; diff --git a/db/migrations/20241105222317_add_forms_table.sql.up.sql b/db/migrations/20241105222317_add_forms_table.sql.up.sql new file mode 100644 index 0000000..aa52297 --- /dev/null +++ b/db/migrations/20241105222317_add_forms_table.sql.up.sql @@ -0,0 +1,20 @@ +-- Enable UUID generation +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- create the forms pk sequence +CREATE SEQUENCE form_ids START 1; + +-- the forms table contains all forms +-- workspaces are to separate form ownership +CREATE TABLE IF NOT EXISTS forms ( + id BIGINT PRIMARY KEY DEFAULT nextval('form_ids'), + workspace_id UUID NOT NULL DEFAULT uuid_generate_v4(), -- // workspace_id is used no namespace the form + name text not null, + fields jsonb default '{}' NOT NULL, + created_at timestamptz not null default timezone('utc', now()), + updated_at timestamptz not null default timezone('utc', now()) +); + +COMMENT ON table forms IS 'Form contains all the data necesary to render a form'; +COMMENT ON column forms.workspace_id IS 'a namespace for the form'; +COMMENT ON column forms.fields IS 'all form fields serialized to JSON, see types.FormFields for structure details'; diff --git a/db/migrations/default.go b/db/migrations/default.go new file mode 100644 index 0000000..91cca1c --- /dev/null +++ b/db/migrations/default.go @@ -0,0 +1,6 @@ +package migrations + +import "embed" + +//go:embed *.sql +var FS embed.FS diff --git a/db/queries.sql b/db/queries.sql new file mode 100644 index 0000000..5cdd6b2 --- /dev/null +++ b/db/queries.sql @@ -0,0 +1,19 @@ +-- name: ListForm :many + +SELECT * +FROM forms; + +-- name: GetForm :one + +SELECT * +FROM forms +WHERE id = @id; + +-- name: SaveForm :one + +INSERT INTO forms (id, name, fields) +VALUES (coalesce(nullif(@id, 0), nextval('form_ids'))::bigint, @name, @fields) ON conflict(id) DO +UPDATE +SET updated_at = timezone('utc', now()), + name = @name, + fields = @fields RETURNING *; diff --git a/env.sample b/env.sample new file mode 100644 index 0000000..e69de29 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..535ffa5 --- /dev/null +++ b/flake.lock @@ -0,0 +1,2252 @@ +{ + "nodes": { + "air": { + "inputs": { + "devenv": "devenv", + "gomod2nix": "gomod2nix", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_2" + }, + "locked": { + "lastModified": 1706646947, + "narHash": "sha256-/FqDfCOnMPrYqB+PI2oXDCdEl3MORWec9I+Dwiem4Ps=", + "owner": "acaloiaro", + "repo": "air", + "rev": "57f33b58e0fa9cb199e9bd7b549a225e5dfcfd7f", + "type": "github" + }, + "original": { + "owner": "acaloiaro", + "repo": "air", + "type": "github" + } + }, + "cachix": { + "inputs": { + "devenv": "devenv_3", + "flake-compat": [ + "devenv", + "flake-compat" + ], + "git-hooks": [ + "devenv", + "pre-commit-hooks" + ], + "nixpkgs": [ + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1726520618, + "narHash": "sha256-jOsaBmJ/EtX5t/vbylCdS7pWYcKGmWOKg4QKUzKr6dA=", + "owner": "cachix", + "repo": "cachix", + "rev": "695525f9086542dfb09fde0871dbf4174abbf634", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "cachix_2": { + "inputs": { + "devenv": "devenv_4", + "flake-compat": [ + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "cachix", + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "cachix_3": { + "inputs": { + "devenv": "devenv_6", + "flake-compat": [ + "ess", + "devenv", + "flake-compat" + ], + "git-hooks": [ + "ess", + "devenv", + "pre-commit-hooks" + ], + "nixpkgs": [ + "ess", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728113491, + "narHash": "sha256-L1C2Mo4sZfvk6Bq2z3VARudEI00gWMg7d1SIijvR0wk=", + "owner": "cachix", + "repo": "cachix", + "rev": "b8d4825e49372937e4e377bc4eef023301497a66", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "cachix_4": { + "inputs": { + "devenv": "devenv_7", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "git-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "pre-commit-hooks" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1726520618, + "narHash": "sha256-jOsaBmJ/EtX5t/vbylCdS7pWYcKGmWOKg4QKUzKr6dA=", + "owner": "cachix", + "repo": "cachix", + "rev": "695525f9086542dfb09fde0871dbf4174abbf634", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "cachix_5": { + "inputs": { + "devenv": "devenv_8", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "devenv": { + "inputs": { + "flake-compat": "flake-compat", + "nix": "nix", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1688058187, + "narHash": "sha256-ipDcc7qrucpJ0+0eYNlwnE+ISTcq4m03qW+CWUshRXI=", + "owner": "cachix", + "repo": "devenv", + "rev": "c8778e3dc30eb9043e218aaa3861d42d4992de77", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "v0.6.3", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat_3", + "nix": "nix_4", + "nixpkgs": "nixpkgs_4", + "pre-commit-hooks": "pre-commit-hooks_3" + }, + "locked": { + "lastModified": 1730745597, + "narHash": "sha256-q8DeziNnTBwqXpnAS1RWj4BMHz+NV+QBNGnRl+3jcEE=", + "owner": "cachix", + "repo": "devenv", + "rev": "7cfc04e544e67adf803c3634b53a911c670e046e", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_3": { + "inputs": { + "cachix": "cachix_2", + "flake-compat": [ + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_3", + "nixpkgs": [ + "devenv", + "cachix", + "nixpkgs" + ], + "pre-commit-hooks": [ + "devenv", + "cachix", + "git-hooks" + ] + }, + "locked": { + "lastModified": 1723156315, + "narHash": "sha256-0JrfahRMJ37Rf1i0iOOn+8Z4CLvbcGNwa2ChOAVrp/8=", + "owner": "cachix", + "repo": "devenv", + "rev": "ff5eb4f2accbcda963af67f1a1159e3f6c7f5f91", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_4": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_2", + "nixpkgs": "nixpkgs_2", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "devenv", + "cachix", + "devenv", + "cachix", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "python-rewrite", + "repo": "devenv", + "type": "github" + } + }, + "devenv_5": { + "inputs": { + "cachix": "cachix_3", + "flake-compat": "flake-compat_5", + "nix": "nix_8", + "nixpkgs": "nixpkgs_8", + "pre-commit-hooks": "pre-commit-hooks_6" + }, + "locked": { + "lastModified": 1728573431, + "narHash": "sha256-p37PxnHGgm6dfuYpYr4iV2AV+U5F44CAK8QAP4kkSxM=", + "owner": "cachix", + "repo": "devenv", + "rev": "151a82a27c8565774452d02c63d1a35c39563919", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_6": { + "inputs": { + "cachix": "cachix_4", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_7", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "nixpkgs" + ], + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "git-hooks" + ] + }, + "locked": { + "lastModified": 1727963652, + "narHash": "sha256-os0EDjn7QVXL6RtHNb9TrZLXVm2Tc5/nZKk3KpbTzd8=", + "owner": "cachix", + "repo": "devenv", + "rev": "cb0052e25dbcc8267b3026160dc73cddaac7d5fd", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_7": { + "inputs": { + "cachix": "cachix_5", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_6", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "nixpkgs" + ], + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "git-hooks" + ] + }, + "locked": { + "lastModified": 1723156315, + "narHash": "sha256-0JrfahRMJ37Rf1i0iOOn+8Z4CLvbcGNwa2ChOAVrp/8=", + "owner": "cachix", + "repo": "devenv", + "rev": "ff5eb4f2accbcda963af67f1a1159e3f6c7f5f91", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_8": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_5", + "nixpkgs": "nixpkgs_5", + "poetry2nix": "poetry2nix_2", + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "python-rewrite", + "repo": "devenv", + "type": "github" + } + }, + "ess": { + "inputs": { + "devenv": "devenv_5", + "gomod2nix": "gomod2nix_2", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_6" + }, + "locked": { + "lastModified": 1729888235, + "narHash": "sha256-TD8sAXjJ4kzNwr5vL5xQCFHDc7l0AnpCsKqhUDJRbdE=", + "owner": "acaloiaro", + "repo": "ess", + "rev": "d4e0e79e427f347d6ccc373f4fb69eae47444361", + "type": "github" + }, + "original": { + "owner": "acaloiaro", + "ref": "v2.13.0", + "repo": "ess", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "ess", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1727826117, + "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_10": { + "inputs": { + "systems": "systems_10" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_11": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_7": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_8": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_9": { + "inputs": { + "systems": "systems_7" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "air", + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_3": { + "inputs": { + "nixpkgs": [ + "ess", + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_4": { + "inputs": { + "nixpkgs": [ + "templ", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gomod2nix": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "air", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1705314449, + "narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "gomod2nix", + "type": "github" + } + }, + "gomod2nix_2": { + "inputs": { + "flake-utils": "flake-utils_8", + "nixpkgs": [ + "ess", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1705314449, + "narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "gomod2nix", + "type": "github" + } + }, + "gomod2nix_3": { + "inputs": { + "flake-utils": "flake-utils_9", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1729448365, + "narHash": "sha256-oquZeWTYWTr5IxfwEzgsxjtD8SSFZYLdO9DaQb70vNU=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "5d387097aa716f35dd99d848dc26d8d5b62a104c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "gomod2nix", + "type": "github" + } + }, + "gomod2nix_4": { + "inputs": { + "flake-utils": "flake-utils_10", + "nixpkgs": [ + "templ", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722589758, + "narHash": "sha256-sbbA8b6Q2vB/t/r1znHawoXLysCyD4L/6n6/RykiSnA=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "4e08ca09253ef996bd4c03afa383b23e35fe28a1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "gomod2nix", + "type": "github" + } + }, + "libgit2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "libgit2_2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "libgit2_3": { + "flake": false, + "locked": { + "lastModified": 1728334903, + "narHash": "sha256-PhX0Rve0//Ue0WP2XLJkjmrpiMRHQNgmwffyTXx+zHk=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "0da8e725f1ebacd8093aefe966e25ba71c3d995c", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": [ + "air", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1676545802, + "narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=", + "owner": "domenkozar", + "repo": "nix", + "rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "relaxed-flakes", + "repo": "nix", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-github-actions_2": { + "inputs": { + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix_3": { + "inputs": { + "flake-compat": [ + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_3" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix_4": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_3", + "nixpkgs-23-11": "nixpkgs-23-11", + "nixpkgs-regression": "nixpkgs-regression_4", + "pre-commit-hooks": "pre-commit-hooks_2" + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nix_5": { + "inputs": { + "flake-compat": "flake-compat_4", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_5" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix_6": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_6" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix_7": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "flake-parts": "flake-parts_2", + "libgit2": "libgit2_2", + "nixpkgs": "nixpkgs_6", + "nixpkgs-23-11": "nixpkgs-23-11_2", + "nixpkgs-regression": "nixpkgs-regression_7", + "pre-commit-hooks": "pre-commit-hooks_4" + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nix_8": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "flake-compat" + ], + "flake-parts": "flake-parts_3", + "libgit2": "libgit2_3", + "nixpkgs": "nixpkgs_7", + "nixpkgs-23-11": "nixpkgs-23-11_3", + "nixpkgs-regression": "nixpkgs-regression_8", + "pre-commit-hooks": "pre-commit-hooks_5" + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1678875422, + "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-23-11": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-23-11_2": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-23-11_3": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_2": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_3": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_4": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_5": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_6": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_7": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_8": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1720386169, + "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_3": { + "locked": { + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1706683685, + "narHash": "sha256-FtPPshEpxH/ewBOsdKBNhlsL2MLEFv1hEnQ19f/bFsQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5ad9903c16126a7d949101687af0aa589b1d7d3d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_11": { + "locked": { + "lastModified": 1724322575, + "narHash": "sha256-kRYwAdYsaICNb2WYcWtBFG6caSuT0v/vTAyR8ap0IR0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2a02822b466ffb9f1c02d07c5dd6b96d08b56c6b", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1716977621, + "narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1728573531, + "narHash": "sha256-WYerSn61NRVGaWlJaprHWDU9rGgMJVXlYZ+kmHB/gC8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1dfc201544fed6086383b4477d8d5c30055215c7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1716977621, + "narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1730768919, + "narHash": "sha256-8AKquNnnSaJRXZxc5YmF/WfmxiHX6MMZZasRP6RRQkE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a04d33c0c3f1a59a2c1cb0c6e34cd24500e5a1dc", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils_3", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "poetry2nix_2": { + "inputs": { + "flake-utils": "flake-utils_5", + "nix-github-actions": "nix-github-actions_2", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "air", + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "air", + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1686050334, + "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_2": { + "inputs": { + "flake-compat": [ + "devenv", + "nix" + ], + "flake-utils": "flake-utils_4", + "gitignore": [ + "devenv", + "nix" + ], + "nixpkgs": [ + "devenv", + "nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712897695, + "narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_3": { + "inputs": { + "flake-compat": [ + "devenv", + "flake-compat" + ], + "gitignore": "gitignore_2", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1726745158, + "narHash": "sha256-D5AegvGoEjt4rkKedmxlSEmC+nNLMBPWFxvmYnVLhjk=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "4e743a6920eab45e8ba0fbe49dc459f1423a4b74", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_4": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix" + ], + "flake-utils": "flake-utils_6", + "gitignore": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712897695, + "narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_5": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "nix" + ], + "gitignore": [ + "ess", + "devenv", + "nix" + ], + "nixpkgs": [ + "ess", + "devenv", + "nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "ess", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728580416, + "narHash": "sha256-nKttjKg6lE7O5S+wlBOkXsUGdOgVxZ8SWaCOyodW5so=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "4ebefcac44b5116cf5741be858245db769ddedd1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_6": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils_7", + "gitignore": "gitignore_3", + "nixpkgs": [ + "ess", + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_3" + }, + "locked": { + "lastModified": 1686050334, + "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "air": "air", + "devenv": "devenv_2", + "ess": "ess", + "gomod2nix": "gomod2nix_3", + "nixpkgs": "nixpkgs_9", + "systems": "systems_8", + "tailwindcss": "tailwindcss", + "templ": "templ" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_10": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_7": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_8": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_9": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "tailwindcss": { + "inputs": { + "nixpkgs": "nixpkgs_10", + "systems": "systems_9" + }, + "locked": { + "lastModified": 1730850516, + "narHash": "sha256-V79L9JZLhn78B11DN/ZrQ9beZiUgaOb0EYeQFtW78W8=", + "owner": "acaloiaro", + "repo": "tailwind-cli-extra", + "rev": "2ee50b55ea468ebbe39a98be3b221780aa32d3ee", + "type": "github" + }, + "original": { + "owner": "acaloiaro", + "repo": "tailwind-cli-extra", + "type": "github" + } + }, + "templ": { + "inputs": { + "gitignore": "gitignore_4", + "gomod2nix": "gomod2nix_4", + "nixpkgs": "nixpkgs_11", + "xc": "xc" + }, + "locked": { + "lastModified": 1730278073, + "narHash": "sha256-0KGht5IMbJV8KkXgT5qJxA9bcmWevzXXAVPMQTm0ccw=", + "owner": "a-h", + "repo": "templ", + "rev": "d9eefff2eeea5c78c938baf556d7ded6880e2fca", + "type": "github" + }, + "original": { + "owner": "a-h", + "ref": "v0.2.793", + "repo": "templ", + "type": "github" + } + }, + "xc": { + "inputs": { + "flake-utils": "flake-utils_11", + "nixpkgs": [ + "templ", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724404748, + "narHash": "sha256-p6rXzNiDm2uBvO1MLzC5pJp/0zRNzj/snBzZI0ce62s=", + "owner": "joerdav", + "repo": "xc", + "rev": "960ff9f109d47a19122cfb015721a76e3a0f23a2", + "type": "github" + }, + "original": { + "owner": "joerdav", + "repo": "xc", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..4158835 --- /dev/null +++ b/flake.nix @@ -0,0 +1,209 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + systems.url = "github:nix-systems/default"; + devenv.url = "github:cachix/devenv"; + tailwindcss.url = "github:acaloiaro/tailwind-cli-extra"; + gomod2nix = { + url = "github:nix-community/gomod2nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + ess = { + url = "github:acaloiaro/ess/v2.13.0"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + air = { + url = "github:acaloiaro/air"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + templ.url = "github:a-h/templ/v0.2.793"; + }; + + outputs = { + self, + nixpkgs, + devenv, + systems, + air, + gomod2nix, + tailwindcss, + ... + } @ inputs: let + pkgs = nixpkgs.legacyPackages."x86_64-linux"; + templ = system: inputs.templ.packages.${system}.templ; + forEachSystem = nixpkgs.lib.genAttrs (import systems); + in { + packages = forEachSystem (system: { + devenv-up = self.devShells.${system}.default.config.procfileScript; + }); + devShells = forEachSystem (system: let + config = self.devShells.${system}.default.config; + executeEss = ''${inputs.ess.packages.${system}.default}/bin/ess --skip-git-add''; + postgresPort = 5434; + in { + default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [ + { + languages = { + nix.enable = true; + go = { + enable = true; + package = pkgs.go_1_23; + }; + }; + + packages = with pkgs; [ + air.packages.${system}.default + go-migrate + gomod2nix.legacyPackages.${system}.gomod2nix + nixpacks + sqlc + postgresql + pre-commit + (templ system) + tailwindcss.packages.${system}.default + ]; + + enterShell = + #bash + '' + go install github.com/dmarkham/enumer@latest + export DATABASE_URL_NON_PGX="postgres://postgres:postgres@localhost:${toString postgresPort}/frm?sslmode=disable" + export DATABASE_URL="$DATABASE_URL_NON_PGX&pool_max_conns=100" + set +a + ${executeEss} + + + ## Fetch dependenies + HTMX_VERSION=2.0.3 + HYPERSCRIPT_VERSION=0.9.13 + CHOICES_DOT_JS_VERSION=11.0.2 + + if [ ! -f ./static/js/hyperscript.js ]; then + curl -sL --verbose "https://unpkg.com/hyperscript.org@$HYPERSCRIPT_VERSION" > ./static/js/hyperscript.js + fi + + if [ ! -f ./static/js/htmx.js ]; then + curl -sL --verbose "https://unpkg.com/htmx.org@$HTMX_VERSION" > ./static/js/htmx.js + fi + + if [ ! -f ./static/js/htmx-response-targets.js ]; then + curl -sL --verbose "https://unpkg.com/htmx.org/dist/ext/response-targets.js" > ./static/js/htmx-response-targets.js + fi + + if [ ! -f ./static/js/choices.min.js ]; then + curl -sL --verbose "https://unpkg.com/choices.js@$CHOICES_DOT_JS_VERSION/public/assets/scripts/choices.min.js" > ./static/js/choices.min.js + fi + + if [ ! -f ./static/css/choices.min.css ]; then + curl -sL --verbose "https://unpkg.com/choices.js@$CHOICES_DOT_JS_VERSION/public/assets/styles/choices.min.css" > ./static/css/choices.min.css + fi + + run-show-help + ''; + process.managers.process-compose.unixSocket.enable = true; + pre-commit.hooks.gomod2nix = { + enable = true; + always_run = true; + pass_filenames = false; + name = "gomod2nix"; + description = "Run gomod2nix before commit"; + entry = "${gomod2nix.legacyPackages.${system}.gomod2nix}/bin/gomod2nix"; + }; + + pre-commit.hooks.env-sample-sync = { + enable = true; + always_run = true; + pass_filenames = false; + name = "env-sample-sync"; + description = "Sync secrets to env.sample"; + entry = executeEss; + }; + + scripts = with pkgs; { + run-show-help = { + description = "Show this help text"; + exec = '' + echo + echo Helper scripts available: + echo + ${pkgs.gnused}/bin/sed -e 's| |XX|g' \ + -e 's|=| |' < 0 + if !isset { + continue + } + switch { + case fieldName == "required": + val := (len(fieldValues) > 1 && fieldValues[1] == "on") || (len(fieldValues) > 0 && fieldValues[0] == "on") + oldField := form.Fields[fieldID] + oldField.Required = val + updatedFields[fieldID] = oldField + case fieldName == "hidden": + val := (len(fieldValues) > 1 && fieldValues[1] == "on") || (len(fieldValues) > 0 && fieldValues[0] == "on") + oldField := form.Fields[fieldID] + oldField.Hidden = val + updatedFields[fieldID] = oldField + case fieldName == "label": + oldField := form.Fields[fieldID] + oldField.Label = fieldValues[0] + updatedFields[fieldID] = oldField + case fieldName == "placeholder": + oldField := form.Fields[fieldID] + oldField.Placeholder = fieldValues[0] + updatedFields[fieldID] = oldField + case fieldName == "options": + oldField := form.Fields[fieldID] + oldField.Options = toFormFieldOption(oldField, fieldValues) + updatedFields[fieldID] = oldField + case fieldGroup == ui.FieldGroupLogic && fieldName == ui.FieldLogicTargetFieldID: + targetFieldID, err := uuid.Parse(fieldValues[0]) + if err != nil { + continue + } + oldField := form.Fields[fieldID] + if oldField.Logic == nil { + oldField.Logic = &types.FieldLogic{} + } + oldField.Logic.TargetFieldID = targetFieldID + updatedFields[fieldID] = oldField + case fieldGroup == ui.FieldGroupLogic && fieldName == ui.FieldLogicTargetFieldValue: + oldField := form.Fields[fieldID] + if oldField.Logic == nil { + oldField.Logic = &types.FieldLogic{} + } + oldField.Logic.TriggerValues = fieldValues + updatedFields[fieldID] = oldField + case fieldGroup == ui.FieldGroupLogic && fieldName == ui.FieldLogicComparator: + oldField := form.Fields[fieldID] + if oldField.Logic == nil { + oldField.Logic = &types.FieldLogic{} + } + oldField.Logic.TriggerComparator, _ = types.FieldLogicComparatorString(fieldValues[0]) + updatedFields[fieldID] = oldField + case fieldGroup == ui.FieldGroupLogic && fieldName == types.FieldLogicTriggerShow.String(): + oldField := form.Fields[fieldID] + if oldField.Logic == nil { + oldField.Logic = &types.FieldLogic{} + } + if len(fieldValues) > 0 && fieldValues[0] == "on" { + oldField.Logic.TriggerActions = []types.FieldLogicTriggerAction{types.FieldLogicTriggerShow} + } + updatedFields[fieldID] = oldField + } + } + + form.Fields = updatedFields + form, err = internal.Q(ctx, f.PostgresURL).SaveForm(ctx, internal.SaveFormParams{ + ID: form.ID, + Name: form.Name, + Fields: updatedFields, + }) + if err != nil { + slog.Error("unable to save form", slog.Any("error", err)) + w.WriteHeader(http.StatusInternalServerError) + } + + // Re-render the form fields form UI + err = ui.FormFieldsForm((frm.Form)(form)).Render(ctx, w) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + // Re-render the form preview + err = ui.FormView((frm.Form)(form), true).Render(ctx, w) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + w.WriteHeader(http.StatusOK) + }) + + r.Delete("/{form_id}/fields/{field_id}", func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + formID, err := strconv.ParseInt(chi.URLParam(r, "form_id"), 10, 64) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + fieldID, err := uuid.Parse(chi.URLParam(r, "field_id")) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + form, err := internal.Q(ctx, f.PostgresURL).GetForm(ctx, formID) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + + updatedFields := form.Fields + delete(updatedFields, fmt.Sprint(fieldID)) + form.Fields = updatedFields + form, err = internal.Q(ctx, f.PostgresURL).SaveForm(ctx, internal.SaveFormParams{ + ID: form.ID, + Name: form.Name, + Fields: updatedFields, + }) + if err != nil { + slog.Error("unable to delete form field", slog.Any("error", err)) + w.WriteHeader(http.StatusInternalServerError) + } + + // Re-render the form fields form UI + err = ui.FormFieldsForm((frm.Form)(form)).Render(ctx, w) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + // Re-render the form preview + err = ui.FormView((frm.Form)(form), true).Render(ctx, w) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + // Re-render the configurator form + err = ui.FormFieldConfigurator((frm.Form)(form)).Render(ctx, w) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + } + + w.WriteHeader(http.StatusOK) + }) +} + +// toFormFieldOption takes a list of options sa strings and determines whether the string options represent new options +// being created, in which case an ID/value must be generated for the option, or if the option is amongst the existing +// options for the field being updated. +func toFormFieldOption(field types.FormField, options []string) types.FieldOptions { + fieldOptions := types.FieldOptions{} + for _, option := range options { + var id uuid.UUID + optionID, err := uuid.Parse(option) + if err != nil { + id = uuid.New() + fieldOptions = append(fieldOptions, types.Option{ + ID: id, + Value: id.String(), + Label: option, + }) + } else { + for _, opt := range field.Options { + if opt.ID == optionID { + fieldOptions = append(fieldOptions, opt) + } + } + } + } + + return fieldOptions +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..984aae1 --- /dev/null +++ b/go.mod @@ -0,0 +1,25 @@ +module github.com/acaloiaro/frm + +go 1.23.2 + +require ( + github.com/a-h/templ v0.2.793 + github.com/go-chi/chi/v5 v5.1.0 + github.com/go-chi/httplog/v2 v2.1.1 + github.com/golang-migrate/migrate/v4 v4.18.0 + github.com/google/uuid v1.6.0 + github.com/jackc/pgx/v5 v5.7.1 +) + +require ( + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/lib/pq v1.10.9 // indirect + go.uber.org/atomic v1.7.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/text v0.18.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..df50897 --- /dev/null +++ b/go.sum @@ -0,0 +1,99 @@ +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/a-h/templ v0.2.793 h1:Io+/ocnfGWYO4VHdR0zBbf39PQlnzVCVVD+wEEs6/qY= +github.com/a-h/templ v0.2.793/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dhui/dktest v0.4.2 h1:QVMkw1lN4UXli3xwh20AD/YvGcBEZufEfkfXKI06d2Q= +github.com/dhui/dktest v0.4.2/go.mod h1:zNK8IwktWzQRm6I/l2Wjp7MakiyaFWv4G1hjmodmMTs= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/httplog/v2 v2.1.1 h1:ojojiu4PIaoeJ/qAO4GWUxJqvYUTobeo7zmuHQJAxRk= +github.com/go-chi/httplog/v2 v2.1.1/go.mod h1:/XXdxicJsp4BA5fapgIC3VuTD+z0Z/VzukoB3VDc1YE= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-migrate/migrate/v4 v4.18.0 h1:X3ewdsmKVhsMx5RB3jojlqoNFiv4ToU48ZLX2sL4XZI= +github.com/golang-migrate/migrate/v4 v4.18.0/go.mod h1:c9zaf41tfUCT06GH9kw3iAsKhkkNEpHTirpKKNtoa5w= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= +github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gomod2nix.toml b/gomod2nix.toml new file mode 100644 index 0000000..f438999 --- /dev/null +++ b/gomod2nix.toml @@ -0,0 +1,51 @@ +schema = 3 + +[mod] + [mod."github.com/a-h/templ"] + version = "v0.2.793" + hash = "sha256-WThPVkb56osTrMJZf0WIoqbsM9DHGaZsG47MS0eoseA=" + [mod."github.com/go-chi/chi/v5"] + version = "v5.1.0" + hash = "sha256-DpVfbPlJe4zQNdBrirWq9Q37/awSu5zb3IJgcuyEED8=" + [mod."github.com/go-chi/httplog/v2"] + version = "v2.1.1" + hash = "sha256-bMpoHUSNk3Uds9NfrStwhDsdCONR4pJso9sVUhqfidk=" + [mod."github.com/golang-migrate/migrate/v4"] + version = "v4.18.0" + hash = "sha256-SVLDnZKTZ5IJvcDIqv8FEXVFbM2PgbPEVRMpFGhPUsM=" + [mod."github.com/google/uuid"] + version = "v1.6.0" + hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw=" + [mod."github.com/hashicorp/errwrap"] + version = "v1.1.0" + hash = "sha256-6lwuMQOfBq+McrViN3maJTIeh4f8jbEqvLy2c9FvvFw=" + [mod."github.com/hashicorp/go-multierror"] + version = "v1.1.1" + hash = "sha256-ANzPEUJIZIlToxR89Mn7Db73d9LGI51ssy7eNnUgmlA=" + [mod."github.com/jackc/pgpassfile"] + version = "v1.0.0" + hash = "sha256-H0nFbC34/3pZUFnuiQk9W7yvAMh6qJDrqvHp+akBPLM=" + [mod."github.com/jackc/pgservicefile"] + version = "v0.0.0-20240606120523-5a60cdf6a761" + hash = "sha256-ETpGsLAA2wcm5xJBayr/mZrCE1YsWbnkbSSX3ptrFn0=" + [mod."github.com/jackc/pgx/v5"] + version = "v5.7.1" + hash = "sha256-N0aiHG91gMztyWC3PAEG0JVd6B/yrcOCfdl0NzqCDXk=" + [mod."github.com/jackc/puddle/v2"] + version = "v2.2.2" + hash = "sha256-IUxdu4JYfsCh/qlz2SiUWu7EVPHhyooiVA4oaS2Z6yk=" + [mod."github.com/lib/pq"] + version = "v1.10.9" + hash = "sha256-Gl6dLtL+yk6UrTTWfas43aM4lP/pNa2l7+ITXnjQyKs=" + [mod."go.uber.org/atomic"] + version = "v1.7.0" + hash = "sha256-g83RSzO/5k8W3qyiIsrQbVq1F8qJGccdWEXTjkqUOfc=" + [mod."golang.org/x/crypto"] + version = "v0.27.0" + hash = "sha256-8HP4+gr4DbXI22GhdgZmCWr1ijtI9HNLsTcE0kltY9o=" + [mod."golang.org/x/sync"] + version = "v0.8.0" + hash = "sha256-usvF0z7gq1vsX58p4orX+8WHlv52pdXgaueXlwj2Wss=" + [mod."golang.org/x/text"] + version = "v0.18.0" + hash = "sha256-aNvJW4gQs+MTfdz6DZqyyHQS2GJ9W8L8qKPVODPn4+k=" diff --git a/handlers/handlers.go b/handlers/handlers.go new file mode 100644 index 0000000..253eb16 --- /dev/null +++ b/handlers/handlers.go @@ -0,0 +1,25 @@ +package handlers + +import ( + "context" + "net/http" +) + +type contextKey string + +const ( + MountPointContextKey contextKey = "mount_point_context_key" +) + +// AddMountPointContext adds the mount point where frm is mounted to the request context +func AddMountPointContext(mountPoint string) func(http.Handler) http.Handler { + return func(h http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + ctx = context.WithValue(ctx, MountPointContextKey, mountPoint) + h.ServeHTTP(w, r.Clone(ctx)) + } + + return http.HandlerFunc(fn) + } +} diff --git a/internal/db.go b/internal/db.go new file mode 100644 index 0000000..385af47 --- /dev/null +++ b/internal/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 + +package internal + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/default.go b/internal/default.go new file mode 100644 index 0000000..1c418da --- /dev/null +++ b/internal/default.go @@ -0,0 +1,148 @@ +package internal + +import ( + "context" + "errors" + "fmt" + "log/slog" + "strings" + + "github.com/acaloiaro/frm/db/migrations" + "github.com/golang-migrate/migrate/v4" + _ "github.com/golang-migrate/migrate/v4/database/postgres" + "github.com/golang-migrate/migrate/v4/source/iofs" + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" +) + +var pool *pgxpool.Pool + +// getPool returns a database pool for the specified connection string +func getPool(ctx context.Context, databaseURL string) (p *pgxpool.Pool, err error) { + if pool == nil { + var poolConfig *pgxpool.Config + poolConfig, err = pgxpool.ParseConfig(databaseURL) + if err != nil { + err = fmt.Errorf("invalid connection string: %v", err) + return + } + + err = InitializeDB(ctx, databaseURL) + if err != nil { + err = fmt.Errorf("database failed to initialize: %v", err) + return + } + + p, err = pgxpool.NewWithConfig(context.Background(), poolConfig) + if err != nil { + err = fmt.Errorf("invalid connection string: %v", err) + return + } + } else { + p = pool + } + return +} + +// Q returns a DBTX instance for querying the frm database +func Q(ctx context.Context, postgresURL string) *Queries { + p, err := getPool(ctx, postgresURL) + if err != nil { + slog.Error("database pool unavailable", "error", err) + return nil // TODO return a no-op DBTX to avoid NPEs + } + return New(p) +} + +// InitializeDB creates the application database if it doesn't exist and runs all migrations against it +// +// databaseUrl is the database URL string to connect to the database +func InitializeDB(ctx context.Context, postgresURL string) (err error) { + postgresURL, err = pgConnectionString(postgresURL, true) + if err != nil { + return fmt.Errorf("invalid connection string: %v", err) + } + + var cfg *pgx.ConnConfig + cfg, err = pgx.ParseConfig(postgresURL) + if err != nil { + return + } + + err = createIfNotExist(ctx, cfg) + if err != nil { + return + } + + err = runMigrations(postgresURL) + return +} + +// TODO not all users wil have permission to do this. Fail gracefully when user lacks permission +func createIfNotExist(ctx context.Context, cfg *pgx.ConnConfig) (err error) { + dbName := cfg.Database + cfg.Database = "" + cfg.RuntimeParams = nil + + conn, err := pgx.ConnectConfig(context.Background(), cfg) + if err != nil { + return + } + + var exists int + err = conn.QueryRow(ctx, "SELECT 1 FROM pg_database WHERE datname=$1", dbName).Scan(&exists) + if err != nil && !errors.Is(err, pgx.ErrNoRows) { + return fmt.Errorf("unable to create database: %w", err) + } + + if exists != 1 { + // note: prepared statements are not supported by pgx for CREATE DATABASE queries + _, err = conn.Exec(ctx, fmt.Sprintf("CREATE DATABASE %s", dbName)) + if err != nil && !errors.Is(err, pgx.ErrNoRows) { + return fmt.Errorf("unable to create database: %w", err) + } + } + return +} + +// runMigrations runs all available migrations if steps are unspecified ( 0 ), and runs either up steps or down steps +func runMigrations(postgresURL string) (err error) { + ms, err := iofs.New(migrations.FS, ".") + if err != nil { + panic(fmt.Sprintf("unable to run migrations: %v", err)) + } + + m, err := migrate.NewWithSourceInstance("iofs", ms, postgresURL) + if err != nil { + panic(fmt.Sprintf("unable to run migrations: %v", err)) + } + + // We don't need the migration tooling to hold it's connections to the DB once it has been completed. + defer m.Close() + + err = m.Up() + if err != nil && !errors.Is(err, migrate.ErrNoChange) { + err = fmt.Errorf("unable to run migrations!!!: %v", err) + } else { + err = nil + } + + return +} + +func pgConnectionString(postgresURL string, disableSSL bool, options ...string) (connString string, err error) { + var cfg *pgx.ConnConfig + cfg, err = pgx.ParseConfig(postgresURL) + if err != nil { + return + } + + options = append(options, "x-migrations-table=frm_migrations") + + if disableSSL { + options = append(options, "sslmode=disable") + } + + connString = fmt.Sprintf("postgres://%s:%s@%s:%d/%s?%s", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Database, strings.Join(options, "&")) + return +} diff --git a/internal/models.go b/internal/models.go new file mode 100644 index 0000000..4a80f5b --- /dev/null +++ b/internal/models.go @@ -0,0 +1,24 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 + +package internal + +import ( + "time" + + "github.com/acaloiaro/frm/types" + uuid "github.com/google/uuid" +) + +// Form contains all the data necesary to render a form +type Form struct { + ID int64 `json:"id"` + // a namespace for the form + WorkspaceID uuid.UUID `json:"workspace_id"` + Name string `json:"name"` + // all form fields serialized to JSON, see types.FormFields for structure details + Fields types.FormFields `json:"fields"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} diff --git a/internal/queries.sql.go b/internal/queries.sql.go new file mode 100644 index 0000000..f56e004 --- /dev/null +++ b/internal/queries.sql.go @@ -0,0 +1,113 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.27.0 +// source: queries.sql + +package internal + +import ( + "context" + + "github.com/acaloiaro/frm/types" +) + +const getForm = `-- name: GetForm :one + +SELECT id, workspace_id, name, fields, created_at, updated_at +FROM forms +WHERE id = $1 +` + +// GetForm +// +// SELECT id, workspace_id, name, fields, created_at, updated_at +// FROM forms +// WHERE id = $1 +func (q *Queries) GetForm(ctx context.Context, id int64) (Form, error) { + row := q.db.QueryRow(ctx, getForm, id) + var i Form + err := row.Scan( + &i.ID, + &i.WorkspaceID, + &i.Name, + &i.Fields, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} + +const listForm = `-- name: ListForm :many + +SELECT id, workspace_id, name, fields, created_at, updated_at +FROM forms +` + +// ListForm +// +// SELECT id, workspace_id, name, fields, created_at, updated_at +// FROM forms +func (q *Queries) ListForm(ctx context.Context) ([]Form, error) { + rows, err := q.db.Query(ctx, listForm) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Form + for rows.Next() { + var i Form + if err := rows.Scan( + &i.ID, + &i.WorkspaceID, + &i.Name, + &i.Fields, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const saveForm = `-- name: SaveForm :one + +INSERT INTO forms (id, name, fields) +VALUES (coalesce(nullif($1, 0), nextval('form_ids'))::bigint, $2, $3) ON conflict(id) DO +UPDATE +SET updated_at = timezone('utc', now()), + name = $2, + fields = $3 RETURNING id, workspace_id, name, fields, created_at, updated_at +` + +type SaveFormParams struct { + ID interface{} `json:"id"` + Name string `json:"name"` + Fields types.FormFields `json:"fields"` +} + +// SaveForm +// +// INSERT INTO forms (id, name, fields) +// VALUES (coalesce(nullif($1, 0), nextval('form_ids'))::bigint, $2, $3) ON conflict(id) DO +// UPDATE +// SET updated_at = timezone('utc', now()), +// name = $2, +// fields = $3 RETURNING id, workspace_id, name, fields, created_at, updated_at +func (q *Queries) SaveForm(ctx context.Context, arg SaveFormParams) (Form, error) { + row := q.db.QueryRow(ctx, saveForm, arg.ID, arg.Name, arg.Fields) + var i Form + err := row.Scan( + &i.ID, + &i.WorkspaceID, + &i.Name, + &i.Fields, + &i.CreatedAt, + &i.UpdatedAt, + ) + return i, err +} diff --git a/sqlc.yaml b/sqlc.yaml new file mode 100644 index 0000000..4362b84 --- /dev/null +++ b/sqlc.yaml @@ -0,0 +1,53 @@ +version: 2 +overrides: + go: + overrides: + - db_type: uuid + nullable: true + go_type: + import: github.com/google/uuid + package: uuid + type: UUID + # + # Note migrations must use `timestamptz` instead of `timestamp with time zone` due to https://github.com/sqlc-dev/sqlc/issues/2630 + # + - db_type: timestamptz + engine: postgresql + go_type: + import: time + type: Time + - db_type: timestamptz + nullable: true + engine: postgresql + go_type: + import: gopkg.in/guregu/null.v4 + package: null + type: Time + - db_type: pg_catalog.interval + engine: postgresql + go_type: + import: time + type: Duration + - column: forms.fields + go_type: + import: github.com/acaloiaro/frm/types + type: FormFields + - column: forms.workspace_id + go_type: + import: github.com/google/uuid + package: uuid + type: UUID + +sql: + - engine: postgresql + queries: db/queries.sql + schema: db/migrations + gen: + go: + package: internal + out: ./internal + sql_package: pgx/v5 + emit_pointers_for_null_types: true + emit_exported_queries: false + emit_json_tags: true + emit_sql_as_comment: true diff --git a/static/assets.go b/static/assets.go new file mode 100644 index 0000000..6926930 --- /dev/null +++ b/static/assets.go @@ -0,0 +1,6 @@ +package static + +import "embed" + +//go:embed js/* css/* +var Assets embed.FS diff --git a/static/css/choices.min.css b/static/css/choices.min.css new file mode 100644 index 0000000..cf79ea9 --- /dev/null +++ b/static/css/choices.min.css @@ -0,0 +1 @@ +.choices{position:relative;overflow:hidden;margin-bottom:24px;font-size:16px}.choices:focus{outline:0}.choices:last-child{margin-bottom:0}.choices.is-open{overflow:visible}.choices.is-disabled .choices__inner,.choices.is-disabled .choices__input{background-color:#eaeaea;cursor:not-allowed;-webkit-user-select:none;user-select:none}.choices.is-disabled .choices__item{cursor:not-allowed}.choices [hidden]{display:none!important}.choices[data-type*=select-one]{cursor:pointer}.choices[data-type*=select-one] .choices__inner{padding-bottom:7.5px}.choices[data-type*=select-one] .choices__input{display:block;width:100%;padding:10px;border-bottom:1px solid #ddd;background-color:#fff;margin:0}.choices[data-type*=select-one] .choices__button{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);padding:0;background-size:8px;position:absolute;top:50%;right:0;margin-top:-10px;margin-right:25px;height:20px;width:20px;border-radius:10em;opacity:.25}.choices[data-type*=select-one] .choices__button:focus,.choices[data-type*=select-one] .choices__button:hover{opacity:1}.choices[data-type*=select-one] .choices__button:focus{box-shadow:0 0 0 2px #005f75}.choices[data-type*=select-one] .choices__item[data-placeholder] .choices__button{display:none}.choices[data-type*=select-one]::after{content:"";height:0;width:0;border-style:solid;border-color:#333 transparent transparent;border-width:5px;position:absolute;right:11.5px;top:50%;margin-top:-2.5px;pointer-events:none}.choices[data-type*=select-one].is-open::after{border-color:transparent transparent #333;margin-top:-7.5px}.choices[data-type*=select-one][dir=rtl]::after{left:11.5px;right:auto}.choices[data-type*=select-one][dir=rtl] .choices__button{right:auto;left:0;margin-left:25px;margin-right:0}.choices[data-type*=select-multiple] .choices__inner,.choices[data-type*=text] .choices__inner{cursor:text}.choices[data-type*=select-multiple] .choices__button,.choices[data-type*=text] .choices__button{position:relative;display:inline-block;margin:0-4px 0 8px;padding-left:16px;border-left:1px solid #003642;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);background-size:8px;width:8px;line-height:1;opacity:.75;border-radius:0}.choices[data-type*=select-multiple] .choices__button:focus,.choices[data-type*=select-multiple] .choices__button:hover,.choices[data-type*=text] .choices__button:focus,.choices[data-type*=text] .choices__button:hover{opacity:1}.choices__inner{display:inline-block;vertical-align:top;width:100%;background-color:#f9f9f9;padding:7.5px 7.5px 3.75px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;min-height:44px;overflow:hidden}.is-focused .choices__inner,.is-open .choices__inner{border-color:#b7b7b7}.is-open .choices__inner{border-radius:2.5px 2.5px 0 0}.is-flipped.is-open .choices__inner{border-radius:0 0 2.5px 2.5px}.choices__list{margin:0;padding-left:0;list-style:none}.choices__list--single{display:inline-block;padding:4px 16px 4px 4px;width:100%}[dir=rtl] .choices__list--single{padding-right:4px;padding-left:16px}.choices__list--single .choices__item{width:100%}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;vertical-align:middle;border-radius:20px;padding:4px 10px;font-size:12px;font-weight:500;margin-right:3.75px;margin-bottom:3.75px;background-color:#005f75;border:1px solid #004a5c;color:#fff;word-break:break-all;box-sizing:border-box}.choices__list--multiple .choices__item[data-deletable]{padding-right:5px}[dir=rtl] .choices__list--multiple .choices__item{margin-right:0;margin-left:3.75px}.choices__list--multiple .choices__item.is-highlighted{background-color:#004a5c;border:1px solid #003642}.is-disabled .choices__list--multiple .choices__item{background-color:#aaa;border:1px solid #919191}.choices__list--dropdown,.choices__list[aria-expanded]{display:none;z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;border-bottom-left-radius:2.5px;border-bottom-right-radius:2.5px;overflow:hidden;word-break:break-all}.is-active.choices__list--dropdown,.is-active.choices__list[aria-expanded]{display:block}.is-open .choices__list--dropdown,.is-open .choices__list[aria-expanded]{border-color:#b7b7b7}.is-flipped .choices__list--dropdown,.is-flipped .choices__list[aria-expanded]{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__list--dropdown .choices__list,.choices__list[aria-expanded] .choices__list{position:relative;max-height:300px;overflow:auto;-webkit-overflow-scrolling:touch;will-change:scroll-position}.choices__list--dropdown .choices__item,.choices__list[aria-expanded] .choices__item{position:relative;padding:10px;font-size:14px}[dir=rtl] .choices__list--dropdown .choices__item,[dir=rtl] .choices__list[aria-expanded] .choices__item{text-align:right}@media (min-width:640px){.choices__list--dropdown .choices__item--selectable[data-select-text],.choices__list[aria-expanded] .choices__item--selectable[data-select-text]{padding-right:100px}.choices__list--dropdown .choices__item--selectable[data-select-text]::after,.choices__list[aria-expanded] .choices__item--selectable[data-select-text]::after{content:attr(data-select-text);font-size:12px;opacity:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}[dir=rtl] .choices__list--dropdown .choices__item--selectable[data-select-text],[dir=rtl] .choices__list[aria-expanded] .choices__item--selectable[data-select-text]{text-align:right;padding-left:100px;padding-right:10px}[dir=rtl] .choices__list--dropdown .choices__item--selectable[data-select-text]::after,[dir=rtl] .choices__list[aria-expanded] .choices__item--selectable[data-select-text]::after{right:auto;left:10px}}.choices__list--dropdown .choices__item--selectable.is-highlighted,.choices__list[aria-expanded] .choices__item--selectable.is-highlighted{background-color:#f2f2f2}.choices__list--dropdown .choices__item--selectable.is-highlighted::after,.choices__list[aria-expanded] .choices__item--selectable.is-highlighted::after{opacity:.5}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;user-select:none;opacity:.5}.choices__heading{font-weight:600;font-size:12px;padding:10px;border-bottom:1px solid #f7f7f7;color:gray}.choices__button{text-indent:-9999px;appearance:none;border:0;background-color:transparent;background-repeat:no-repeat;background-position:center;cursor:pointer}.choices__button:focus,.choices__input:focus{outline:0}.choices__input{display:inline-block;vertical-align:baseline;background-color:#f9f9f9;font-size:14px;margin-bottom:5px;border:0;border-radius:0;max-width:100%;padding:4px 0 4px 2px}.choices__input::-webkit-search-cancel-button,.choices__input::-webkit-search-decoration,.choices__input::-webkit-search-results-button,.choices__input::-webkit-search-results-decoration{display:none}.choices__input::-ms-clear,.choices__input::-ms-reveal{display:none;width:0;height:0}[dir=rtl] .choices__input{padding-right:2px;padding-left:0}.choices__placeholder{opacity:.5} \ No newline at end of file diff --git a/static/css/styles.css b/static/css/styles.css new file mode 100644 index 0000000..a4edeab --- /dev/null +++ b/static/css/styles.css @@ -0,0 +1,3065 @@ +/* +! tailwindcss v3.4.4 | 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: #d1d1d1; + /* 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: Helvetica, Arial, sans-serif; + /* 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: #888888; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #888888; + /* 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; +} + +[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: #fff; + border-color: #6d6d6d; + border-width: 1px; + border-radius: 0px; + padding-top: 0.5rem; + padding-right: 0.75rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + font-size: 1rem; + line-height: 1.5rem; + --tw-shadow: 0 0 #0000; +} + +[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --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); + border-color: #2563eb; +} + +input::-moz-placeholder, textarea::-moz-placeholder { + color: #6d6d6d; + opacity: 1; +} + +input::placeholder,textarea::placeholder { + color: #6d6d6d; + opacity: 1; +} + +::-webkit-datetime-edit-fields-wrapper { + padding: 0; +} + +::-webkit-date-and-time-value { + min-height: 1.5em; +} + +::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field { + padding-top: 0; + padding-bottom: 0; +} + +select { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236d6d6d' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); + background-position: right 0.5rem center; + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + padding-right: 2.5rem; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; +} + +[multiple] { + background-image: initial; + background-position: initial; + background-repeat: unset; + background-size: initial; + padding-right: 0.75rem; + -webkit-print-color-adjust: unset; + print-color-adjust: unset; +} + +[type='checkbox'],[type='radio'] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + display: inline-block; + vertical-align: middle; + background-origin: border-box; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-shrink: 0; + height: 1rem; + width: 1rem; + color: #2563eb; + background-color: #fff; + border-color: #6d6d6d; + border-width: 1px; + --tw-shadow: 0 0 #0000; +} + +[type='checkbox'] { + border-radius: 0px; +} + +[type='radio'] { + border-radius: 100%; +} + +[type='checkbox']:focus,[type='radio']:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 2px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --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(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); +} + +[type='checkbox']:checked,[type='radio']:checked { + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); +} + +[type='radio']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); +} + +[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='checkbox']:indeterminate { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e"); + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='file'] { + background: unset; + border-color: inherit; + border-width: 0; + border-radius: 0; + padding: 0; + font-size: unset; + line-height: inherit; +} + +[type='file']:focus { + outline: 1px solid ButtonText; + outline: 1px auto -webkit-focus-ring-color; +} + +:root, +[data-theme] { + background-color: var(--fallback-b1,oklch(var(--b1)/1)); + color: var(--fallback-bc,oklch(var(--bc)/1)); +} + +@supports not (color: oklch(0% 0 0)) { + :root { + color-scheme: light; + --fallback-p: #491eff; + --fallback-pc: #d4dbff; + --fallback-s: #ff41c7; + --fallback-sc: #fff9fc; + --fallback-a: #00cfbd; + --fallback-ac: #00100d; + --fallback-n: #2b3440; + --fallback-nc: #d7dde4; + --fallback-b1: #ffffff; + --fallback-b2: #e5e6e6; + --fallback-b3: #e5e6e6; + --fallback-bc: #1f2937; + --fallback-in: #00b3f0; + --fallback-inc: #000000; + --fallback-su: #00ca92; + --fallback-suc: #000000; + --fallback-wa: #ffc22d; + --fallback-wac: #000000; + --fallback-er: #ff6f70; + --fallback-erc: #000000; + } + + @media (prefers-color-scheme: dark) { + :root { + color-scheme: dark; + --fallback-p: #7582ff; + --fallback-pc: #050617; + --fallback-s: #ff71cf; + --fallback-sc: #190211; + --fallback-a: #00c7b5; + --fallback-ac: #000e0c; + --fallback-n: #2a323c; + --fallback-nc: #a6adbb; + --fallback-b1: #1d232a; + --fallback-b2: #191e24; + --fallback-b3: #15191e; + --fallback-bc: #a6adbb; + --fallback-in: #00b3f0; + --fallback-inc: #000000; + --fallback-su: #00ca92; + --fallback-suc: #000000; + --fallback-wa: #ffc22d; + --fallback-wac: #000000; + --fallback-er: #ff6f70; + --fallback-erc: #000000; + } + } +} + +html { + -webkit-tap-highlight-color: transparent; +} + +* { + scrollbar-color: color-mix(in oklch, currentColor 35%, transparent) transparent; +} + +*:hover { + scrollbar-color: color-mix(in oklch, currentColor 60%, transparent) transparent; +} + +:root { + color-scheme: light; + --in: 72.06% 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 84.71% 0.199 83.87; + --er: 71.76% 0.221 22.18; + --pc: 89.824% 0.06192 275.75; + --ac: 15.352% 0.0368 183.61; + --inc: 0% 0 0; + --suc: 0% 0 0; + --wac: 0% 0 0; + --erc: 0% 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 49.12% 0.3096 275.75; + --s: 69.71% 0.329 342.55; + --sc: 98.71% 0.0106 342.55; + --a: 76.76% 0.184 183.61; + --n: 32.1785% 0.02476 255.701624; + --nc: 89.4994% 0.011585 252.096176; + --b1: 100% 0 0; + --b2: 96.1151% 0 0; + --b3: 92.4169% 0.00108 197.137559; + --bc: 27.8078% 0.029596 256.847952; +} + +@media (prefers-color-scheme: dark) { + :root { + color-scheme: dark; + --in: 72.06% 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 84.71% 0.199 83.87; + --er: 71.76% 0.221 22.18; + --pc: 13.138% 0.0392 275.75; + --sc: 14.96% 0.052 342.55; + --ac: 14.902% 0.0334 183.61; + --inc: 0% 0 0; + --suc: 0% 0 0; + --wac: 0% 0 0; + --erc: 0% 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 65.69% 0.196 275.75; + --s: 74.8% 0.26 342.55; + --a: 74.51% 0.167 183.61; + --n: 31.3815% 0.021108 254.139175; + --nc: 74.6477% 0.0216 264.435964; + --b1: 25.3267% 0.015896 252.417568; + --b2: 23.2607% 0.013807 253.100675; + --b3: 21.1484% 0.01165 254.087939; + --bc: 74.6477% 0.0216 264.435964; + } +} + +[data-theme=light] { + color-scheme: light; + --in: 72.06% 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 84.71% 0.199 83.87; + --er: 71.76% 0.221 22.18; + --pc: 89.824% 0.06192 275.75; + --ac: 15.352% 0.0368 183.61; + --inc: 0% 0 0; + --suc: 0% 0 0; + --wac: 0% 0 0; + --erc: 0% 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 49.12% 0.3096 275.75; + --s: 69.71% 0.329 342.55; + --sc: 98.71% 0.0106 342.55; + --a: 76.76% 0.184 183.61; + --n: 32.1785% 0.02476 255.701624; + --nc: 89.4994% 0.011585 252.096176; + --b1: 100% 0 0; + --b2: 96.1151% 0 0; + --b3: 92.4169% 0.00108 197.137559; + --bc: 27.8078% 0.029596 256.847952; +} + +[data-theme=dark] { + color-scheme: dark; + --in: 72.06% 0.191 231.6; + --su: 64.8% 0.150 160; + --wa: 84.71% 0.199 83.87; + --er: 71.76% 0.221 22.18; + --pc: 13.138% 0.0392 275.75; + --sc: 14.96% 0.052 342.55; + --ac: 14.902% 0.0334 183.61; + --inc: 0% 0 0; + --suc: 0% 0 0; + --wac: 0% 0 0; + --erc: 0% 0 0; + --rounded-box: 1rem; + --rounded-btn: 0.5rem; + --rounded-badge: 1.9rem; + --animation-btn: 0.25s; + --animation-input: .2s; + --btn-focus-scale: 0.95; + --border-btn: 1px; + --tab-border: 1px; + --tab-radius: 0.5rem; + --p: 65.69% 0.196 275.75; + --s: 74.8% 0.26 342.55; + --a: 74.51% 0.167 183.61; + --n: 31.3815% 0.021108 254.139175; + --nc: 74.6477% 0.0216 264.435964; + --b1: 25.3267% 0.015896 252.417568; + --b2: 23.2607% 0.013807 253.100675; + --b3: 21.1484% 0.01165 254.087939; + --bc: 74.6477% 0.0216 264.435964; +} + +*, ::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: ; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.avatar.placeholder > div { + display: flex; + align-items: center; + justify-content: center; +} + +@media (hover:hover) { + .checkbox-primary:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + } + + .label a:hover { + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + } + + .tab:hover { + --tw-text-opacity: 1; + } + + .tabs-boxed :is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):hover, .tabs-boxed :is(input:checked):hover { + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); + } +} + +.btn { + display: inline-flex; + height: 3rem; + min-height: 3rem; + flex-shrink: 0; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-wrap: wrap; + align-items: center; + justify-content: center; + border-radius: var(--rounded-btn, 0.5rem); + border-color: transparent; + border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity)); + padding-left: 1rem; + padding-right: 1rem; + text-align: center; + font-size: 0.875rem; + line-height: 1em; + gap: 0.5rem; + font-weight: 600; + text-decoration-line: none; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0, 0, 0.2, 1); + border-width: var(--border-btn, 1px); + transition-property: color, background-color, border-color, opacity, box-shadow, transform; + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --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); + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); + background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity)); + --tw-bg-opacity: 1; + --tw-border-opacity: 1; +} + +.btn-disabled, + .btn[disabled], + .btn:disabled { + pointer-events: none; +} + +:where(.btn:is(input[type="checkbox"])), +:where(.btn:is(input[type="radio"])) { + width: auto; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.btn:is(input[type="checkbox"]):after, +.btn:is(input[type="radio"]):after { + --tw-content: attr(aria-label); + content: var(--tw-content); +} + +.checkbox { + flex-shrink: 0; + --chkbg: var(--fallback-bc,oklch(var(--bc)/1)); + --chkfg: var(--fallback-b1,oklch(var(--b1)/1)); + height: 1.5rem; + width: 1.5rem; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0.2; +} + +.dropdown { + position: relative; + display: inline-block; +} + +.dropdown > *:not(summary):focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.dropdown .dropdown-content { + position: absolute; +} + +.dropdown:is(:not(details)) .dropdown-content { + visibility: hidden; + opacity: 0; + transform-origin: top; + --tw-scale-x: .95; + --tw-scale-y: .95; + 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)); + 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-timing-function: cubic-bezier(0, 0, 0.2, 1); + transition-duration: 200ms; +} + +.dropdown.dropdown-open .dropdown-content, +.dropdown:not(.dropdown-hover):focus .dropdown-content, +.dropdown:focus-within .dropdown-content { + visibility: visible; + opacity: 1; +} + +@media (hover: hover) { + .dropdown.dropdown-hover:hover .dropdown-content { + visibility: visible; + opacity: 1; + } + + .btm-nav > *.disabled:hover, + .btm-nav > *[disabled]:hover { + pointer-events: none; + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; + } + + .btn:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity))); + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn:hover { + background-color: color-mix( + in oklab, + oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%, + black + ); + border-color: color-mix( + in oklab, + oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%, + black + ); + } + } + + @supports not (color: oklch(0% 0 0)) { + .btn:hover { + background-color: var(--btn-color, var(--fallback-b2)); + border-color: var(--btn-color, var(--fallback-b2)); + } + } + + .btn.glass:hover { + --glass-opacity: 25%; + --glass-border-opacity: 15%; + } + + .btn-disabled:hover, + .btn[disabled]:hover, + .btn:disabled:hover { + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.2; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; + } + + @supports (color: color-mix(in oklab, black, black)) { + .btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover { + background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black); + } + } + + .dropdown.dropdown-hover:hover .dropdown-content { + --tw-scale-x: 1; + --tw-scale-y: 1; + 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)); + } + + .tab[disabled], + .tab[disabled]:hover { + cursor: not-allowed; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; + } +} + +.dropdown:is(details) summary::-webkit-details-marker { + display: none; +} + +.footer { + display: grid; + width: 100%; + grid-auto-flow: row; + place-items: start; + -moz-column-gap: 1rem; + column-gap: 1rem; + row-gap: 2.5rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.footer > * { + display: grid; + place-items: start; + gap: 0.5rem; +} + +@media (min-width: 48rem) { + .footer { + grid-auto-flow: column; + } + + .footer-center { + grid-auto-flow: row dense; + } +} + +.label { + display: flex; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + align-items: center; + justify-content: space-between; + padding-left: 0.25rem; + padding-right: 0.25rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.input { + flex-shrink: 1; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 3rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: 1rem; + line-height: 2; + line-height: 1.5rem; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.input[type="number"]::-webkit-inner-spin-button, +.input-md[type="number"]::-webkit-inner-spin-button { + margin-top: -1rem; + margin-bottom: -1rem; + margin-inline-end: -1rem; +} + +.join { + display: inline-flex; + align-items: stretch; + border-radius: var(--rounded-btn, 0.5rem); +} + +.join :where(.join-item) { + border-start-end-radius: 0; + border-end-end-radius: 0; + border-end-start-radius: 0; + border-start-start-radius: 0; +} + +.join .join-item:not(:first-child):not(:last-child), + .join *:not(:first-child):not(:last-child) .join-item { + border-start-end-radius: 0; + border-end-end-radius: 0; + border-end-start-radius: 0; + border-start-start-radius: 0; +} + +.join .join-item:first-child:not(:last-child), + .join *:first-child:not(:last-child) .join-item { + border-start-end-radius: 0; + border-end-end-radius: 0; +} + +.join .dropdown .join-item:first-child:not(:last-child), + .join *:first-child:not(:last-child) .dropdown .join-item { + border-start-end-radius: inherit; + border-end-end-radius: inherit; +} + +.join :where(.join-item:first-child:not(:last-child)), + .join :where(*:first-child:not(:last-child) .join-item) { + border-end-start-radius: inherit; + border-start-start-radius: inherit; +} + +.join .join-item:last-child:not(:first-child), + .join *:last-child:not(:first-child) .join-item { + border-end-start-radius: 0; + border-start-start-radius: 0; +} + +.join :where(.join-item:last-child:not(:first-child)), + .join :where(*:last-child:not(:first-child) .join-item) { + border-start-end-radius: inherit; + border-end-end-radius: inherit; +} + +@supports not selector(:has(*)) { + :where(.join *) { + border-radius: inherit; + } +} + +@supports selector(:has(*)) { + :where(.join *:has(.join-item)) { + border-radius: inherit; + } +} + +.link { + cursor: pointer; + text-decoration-line: underline; +} + +.menu li.disabled { + cursor: not-allowed; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + color: var(--fallback-bc,oklch(var(--bc)/0.3)); +} + +.mockup-browser { + position: relative; + overflow: hidden; + overflow-x: auto; + border-radius: var(--rounded-box, 1rem); +} + +.mockup-browser pre[data-prefix]:before { + content: attr(data-prefix); + display: inline-block; + text-align: right; +} + +.range { + height: 1.5rem; + width: 100%; + cursor: pointer; + -moz-appearance: none; + appearance: none; + -webkit-appearance: none; + --range-shdw: var(--fallback-bc,oklch(var(--bc)/1)); + overflow: hidden; + border-radius: var(--rounded-box, 1rem); + background-color: transparent; +} + +.range:focus { + outline: none; +} + +.select { + display: inline-flex; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 3rem; + min-height: 3rem; + padding-inline-start: 1rem; + padding-inline-end: 2.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), + linear-gradient(135deg, currentColor 50%, transparent 50%); + background-position: calc(100% - 20px) calc(1px + 50%), + calc(100% - 16.1px) calc(1px + 50%); + background-size: 4px 4px, + 4px 4px; + background-repeat: no-repeat; +} + +.select[multiple] { + height: auto; +} + +.tabs { + display: grid; + align-items: flex-end; +} + +.tabs-lifted:has(.tab-content[class^="rounded-"]) + .tab:first-child:not(:is(.tab-active, [aria-selected="true"])), .tabs-lifted:has(.tab-content[class*=" rounded-"]) + .tab:first-child:not(:is(.tab-active, [aria-selected="true"])) { + border-bottom-color: transparent; +} + +.tab { + position: relative; + grid-row-start: 1; + display: inline-flex; + height: 2rem; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + flex-wrap: wrap; + align-items: center; + justify-content: center; + text-align: center; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + --tab-padding: 1rem; + --tw-text-opacity: 0.5; + --tab-color: var(--fallback-bc,oklch(var(--bc)/1)); + --tab-bg: var(--fallback-b1,oklch(var(--b1)/1)); + --tab-border-color: var(--fallback-b3,oklch(var(--b3)/1)); + color: var(--tab-color); + padding-inline-start: var(--tab-padding, 1rem); + padding-inline-end: var(--tab-padding, 1rem); +} + +.tab:is(input[type="radio"]) { + width: auto; + border-bottom-right-radius: 0px; + border-bottom-left-radius: 0px; +} + +.tab:is(input[type="radio"]):after { + --tw-content: attr(aria-label); + content: var(--tw-content); +} + +.tab:not(input):empty { + cursor: default; + grid-column-start: span 9999; +} + +:checked + .tab-content:nth-child(2), + :is(.tab-active, [aria-selected="true"]) + .tab-content:nth-child(2) { + border-start-start-radius: 0px; +} + +input.tab:checked + .tab-content, +:is(.tab-active, [aria-selected="true"]) + .tab-content { + display: block; +} + +.textarea { + min-height: 3rem; + flex-shrink: 1; + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + border-radius: var(--rounded-btn, 0.5rem); + border-width: 1px; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); +} + +.toggle { + flex-shrink: 0; + --tglbg: var(--fallback-b1,oklch(var(--b1)/1)); + --handleoffset: 1.5rem; + --handleoffsetcalculator: calc(var(--handleoffset) * -1); + --togglehandleborder: 0 0; + height: 1.5rem; + width: 3rem; + cursor: pointer; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: var(--rounded-badge, 1.9rem); + border-width: 1px; + border-color: currentColor; + background-color: currentColor; + color: var(--fallback-bc,oklch(var(--bc)/0.5)); + transition: background, + box-shadow var(--animation-input, 0.2s) ease-out; + box-shadow: var(--handleoffsetcalculator) 0 0 2px var(--tglbg) inset, + 0 0 0 2px var(--tglbg) inset, + var(--togglehandleborder); +} + +.btm-nav > *.disabled, + .btm-nav > *[disabled] { + pointer-events: none; + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.btm-nav > * .label { + font-size: 1rem; + line-height: 1.5rem; +} + +@media (prefers-reduced-motion: no-preference) { + .btn { + animation: button-pop var(--animation-btn, 0.25s) ease-out; + } +} + +.btn:active:hover, + .btn:active:focus { + animation: button-pop 0s ease-out; + transform: scale(var(--btn-focus-scale, 0.97)); +} + +@supports not (color: oklch(0% 0 0)) { + .btn { + background-color: var(--btn-color, var(--fallback-b2)); + border-color: var(--btn-color, var(--fallback-b2)); + } +} + +.btn:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; +} + +.btn.glass { + --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); + outline-color: currentColor; +} + +.btn.glass.btn-active { + --glass-opacity: 25%; + --glass-border-opacity: 15%; +} + +.btn.btn-disabled, + .btn[disabled], + .btn:disabled { + --tw-border-opacity: 0; + background-color: var(--fallback-n,oklch(var(--n)/var(--tw-bg-opacity))); + --tw-bg-opacity: 0.2; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.btn:is(input[type="checkbox"]:checked), +.btn:is(input[type="radio"]:checked) { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +.btn:is(input[type="checkbox"]:checked):focus-visible, .btn:is(input[type="radio"]:checked):focus-visible { + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +@keyframes button-pop { + 0% { + transform: scale(var(--btn-focus-scale, 0.98)); + } + + 40% { + transform: scale(1.02); + } + + 100% { + transform: scale(1); + } +} + +.checkbox:focus { + box-shadow: none; +} + +.checkbox:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/1)); +} + +.checkbox:disabled { + border-width: 0px; + cursor: not-allowed; + border-color: transparent; + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + opacity: 0.2; +} + +.checkbox:checked, + .checkbox[aria-checked="true"] { + background-repeat: no-repeat; + animation: checkmark var(--animation-input, 0.2s) ease-out; + background-color: var(--chkbg); + background-image: linear-gradient(-45deg, transparent 65%, var(--chkbg) 65.99%), + linear-gradient(45deg, transparent 75%, var(--chkbg) 75.99%), + linear-gradient(-45deg, var(--chkbg) 40%, transparent 40.99%), + linear-gradient( + 45deg, + var(--chkbg) 30%, + var(--chkfg) 30.99%, + var(--chkfg) 40%, + transparent 40.99% + ), + linear-gradient(-45deg, var(--chkfg) 50%, var(--chkbg) 50.99%); +} + +.checkbox:indeterminate { + --tw-bg-opacity: 1; + background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity))); + background-repeat: no-repeat; + animation: checkmark var(--animation-input, 0.2s) ease-out; + background-image: linear-gradient(90deg, transparent 80%, var(--chkbg) 80%), + linear-gradient(-90deg, transparent 80%, var(--chkbg) 80%), + linear-gradient(0deg, var(--chkbg) 43%, var(--chkfg) 43%, var(--chkfg) 57%, var(--chkbg) 57%); +} + +.checkbox-primary { + --chkbg: var(--fallback-p,oklch(var(--p)/1)); + --chkfg: var(--fallback-pc,oklch(var(--pc)/1)); + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); +} + +.checkbox-primary:focus-visible { + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} + +.checkbox-primary:checked, + .checkbox-primary[aria-checked="true"] { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +@keyframes checkmark { + 0% { + background-position-y: 5px; + } + + 50% { + background-position-y: -2px; + } + + 100% { + background-position-y: 0; + } +} + +.dropdown.dropdown-open .dropdown-content, +.dropdown:focus .dropdown-content, +.dropdown:focus-within .dropdown-content { + --tw-scale-x: 1; + --tw-scale-y: 1; + 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)); +} + +.input input { + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + background-color: transparent; +} + +.input input:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.input[list]::-webkit-calendar-picker-indicator { + line-height: 1em; +} + +.input:focus, + .input:focus-within { + box-shadow: none; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.input:has(> input[disabled]), + .input-disabled, + .input:disabled, + .input[disabled] { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + color: var(--fallback-bc,oklch(var(--bc)/0.4)); +} + +.input:has(> input[disabled])::-moz-placeholder, .input-disabled::-moz-placeholder, .input:disabled::-moz-placeholder, .input[disabled]::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.input:has(> input[disabled])::placeholder, + .input-disabled::placeholder, + .input:disabled::placeholder, + .input[disabled]::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.input:has(> input[disabled]) > input[disabled] { + cursor: not-allowed; +} + +.input::-webkit-date-and-time-value { + text-align: inherit; +} + +.join > :where(*:not(:first-child)) { + margin-top: 0px; + margin-bottom: 0px; + margin-inline-start: -1px; +} + +.join > :where(*:not(:first-child)):is(.btn) { + margin-inline-start: calc(var(--border-btn) * -1); +} + +.link:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.link:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; +} + +.mockup-phone .display { + overflow: hidden; + border-radius: 40px; + margin-top: -25px; +} + +.mockup-browser .mockup-browser-toolbar { + margin-top: 0.75rem; + margin-bottom: 0.75rem; + display: inline-flex; + width: 100%; + align-items: center; + padding-right: 1.4em; +} + +.mockup-browser .mockup-browser-toolbar:where([dir="rtl"], [dir="rtl"] *) { + flex-direction: row-reverse; +} + +.mockup-browser .mockup-browser-toolbar:before { + content: ""; + margin-right: 4.8rem; + display: inline-block; + aspect-ratio: 1 / 1; + height: 0.75rem; + border-radius: 9999px; + opacity: 0.3; + box-shadow: 1.4em 0, + 2.8em 0, + 4.2em 0; +} + +.mockup-browser .mockup-browser-toolbar .input { + position: relative; + margin-left: auto; + margin-right: auto; + display: block; + height: 1.75rem; + width: 24rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + padding-left: 2rem; + direction: ltr; +} + +.mockup-browser .mockup-browser-toolbar .input:before { + content: ""; + position: absolute; + left: 0.5rem; + top: 50%; + aspect-ratio: 1 / 1; + height: 0.75rem; + --tw-translate-y: -50%; + 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)); + border-radius: 9999px; + border-width: 2px; + border-color: currentColor; + opacity: 0.6; +} + +.mockup-browser .mockup-browser-toolbar .input:after { + content: ""; + position: absolute; + left: 1.25rem; + top: 50%; + height: 0.5rem; + --tw-translate-y: 25%; + --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)); + border-radius: 9999px; + border-width: 1px; + border-color: currentColor; + opacity: 0.6; +} + +@keyframes modal-pop { + 0% { + opacity: 0; + } +} + +@keyframes progress-loading { + 50% { + background-position-x: -115%; + } +} + +@keyframes radiomark { + 0% { + box-shadow: 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset; + } + + 50% { + box-shadow: 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 3px var(--fallback-b1,oklch(var(--b1)/1)) inset; + } + + 100% { + box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset, + 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset; + } +} + +.range:focus-visible::-webkit-slider-thumb { + --focus-shadow: 0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset, 0 0 0 2rem var(--range-shdw) inset; +} + +.range:focus-visible::-moz-range-thumb { + --focus-shadow: 0 0 0 6px var(--fallback-b1,oklch(var(--b1)/1)) inset, 0 0 0 2rem var(--range-shdw) inset; +} + +.range::-webkit-slider-runnable-track { + height: 0.5rem; + width: 100%; + border-radius: var(--rounded-box, 1rem); + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); +} + +.range::-moz-range-track { + height: 0.5rem; + width: 100%; + border-radius: var(--rounded-box, 1rem); + background-color: var(--fallback-bc,oklch(var(--bc)/0.1)); +} + +.range::-webkit-slider-thumb { + position: relative; + height: 1.5rem; + width: 1.5rem; + border-radius: var(--rounded-box, 1rem); + border-style: none; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + appearance: none; + -webkit-appearance: none; + top: 50%; + color: var(--range-shdw); + transform: translateY(-50%); + --filler-size: 100rem; + --filler-offset: 0.6rem; + box-shadow: 0 0 0 3px var(--range-shdw) inset, + var(--focus-shadow, 0 0), + calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size); +} + +.range::-moz-range-thumb { + position: relative; + height: 1.5rem; + width: 1.5rem; + border-radius: var(--rounded-box, 1rem); + border-style: none; + --tw-bg-opacity: 1; + background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity))); + top: 50%; + color: var(--range-shdw); + --filler-size: 100rem; + --filler-offset: 0.5rem; + box-shadow: 0 0 0 3px var(--range-shdw) inset, + var(--focus-shadow, 0 0), + calc(var(--filler-size) * -1 - var(--filler-offset)) 0 0 var(--filler-size); +} + +@keyframes rating-pop { + 0% { + transform: translateY(-0.125em); + } + + 40% { + transform: translateY(-0.125em); + } + + 100% { + transform: translateY(0); + } +} + +.select:focus { + box-shadow: none; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.select-disabled, + .select:disabled, + .select[disabled] { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + color: var(--fallback-bc,oklch(var(--bc)/0.4)); +} + +.select-disabled::-moz-placeholder, .select:disabled::-moz-placeholder, .select[disabled]::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.select-disabled::placeholder, + .select:disabled::placeholder, + .select[disabled]::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.select-multiple, + .select[multiple], + .select[size].select:not([size="1"]) { + background-image: none; + padding-right: 1rem; +} + +[dir="rtl"] .select { + background-position: calc(0% + 12px) calc(1px + 50%), + calc(0% + 16px) calc(1px + 50%); +} + +@keyframes skeleton { + from { + background-position: 150%; + } + + to { + background-position: -50%; + } +} + +.tabs-lifted > .tab:focus-visible { + border-end-end-radius: 0; + border-end-start-radius: 0; +} + +.tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]), .tab:is(input:checked) { + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 1; + --tw-text-opacity: 1; +} + +.tab:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.tab:focus-visible { + outline: 2px solid currentColor; + outline-offset: -5px; +} + +.tab-disabled, + .tab[disabled] { + cursor: not-allowed; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + --tw-text-opacity: 0.2; +} + +.tabs-bordered > .tab { + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + --tw-border-opacity: 0.2; + border-style: solid; + border-bottom-width: calc(var(--tab-border, 1px) + 1px); +} + +.tabs-lifted > .tab { + border: var(--tab-border, 1px) solid transparent; + border-width: 0 0 var(--tab-border, 1px) 0; + border-start-start-radius: var(--tab-radius, 0.5rem); + border-start-end-radius: var(--tab-radius, 0.5rem); + border-bottom-color: var(--tab-border-color); + padding-inline-start: var(--tab-padding, 1rem); + padding-inline-end: var(--tab-padding, 1rem); + padding-top: var(--tab-border, 1px); +} + +.tabs-lifted > .tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]), .tabs-lifted > .tab:is(input:checked) { + background-color: var(--tab-bg); + border-width: var(--tab-border, 1px) var(--tab-border, 1px) 0 var(--tab-border, 1px); + border-inline-start-color: var(--tab-border-color); + border-inline-end-color: var(--tab-border-color); + border-top-color: var(--tab-border-color); + padding-inline-start: calc(var(--tab-padding, 1rem) - var(--tab-border, 1px)); + padding-inline-end: calc(var(--tab-padding, 1rem) - var(--tab-border, 1px)); + padding-bottom: var(--tab-border, 1px); + padding-top: 0; +} + +.tabs-lifted > .tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):before, .tabs-lifted > .tab:is(input:checked):before { + z-index: 1; + content: ""; + display: block; + position: absolute; + width: calc(100% + var(--tab-radius, 0.5rem) * 2); + height: var(--tab-radius, 0.5rem); + bottom: 0; + background-size: var(--tab-radius, 0.5rem); + background-position: top left, + top right; + background-repeat: no-repeat; + --tab-grad: calc(69% - var(--tab-border, 1px)); + --radius-start: radial-gradient( + circle at top left, + transparent var(--tab-grad), + var(--tab-border-color) calc(var(--tab-grad) + 0.25px), + var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)), + var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px) + ); + --radius-end: radial-gradient( + circle at top right, + transparent var(--tab-grad), + var(--tab-border-color) calc(var(--tab-grad) + 0.25px), + var(--tab-border-color) calc(var(--tab-grad) + var(--tab-border, 1px)), + var(--tab-bg) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.25px) + ); + background-image: var(--radius-start), var(--radius-end); +} + +.tabs-lifted > .tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):first-child:before, .tabs-lifted > .tab:is(input:checked):first-child:before { + background-image: var(--radius-end); + background-position: top right; +} + +[dir="rtl"] .tabs-lifted > .tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):first-child:before, [dir="rtl"] .tabs-lifted > .tab:is(input:checked):first-child:before { + background-image: var(--radius-start); + background-position: top left; +} + +.tabs-lifted > .tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):last-child:before, .tabs-lifted > .tab:is(input:checked):last-child:before { + background-image: var(--radius-start); + background-position: top left; +} + +[dir="rtl"] .tabs-lifted > .tab:is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):last-child:before, [dir="rtl"] .tabs-lifted > .tab:is(input:checked):last-child:before { + background-image: var(--radius-end); + background-position: top right; +} + +.tabs-lifted + > :is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]) + + .tabs-lifted + :is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]):before, .tabs-lifted > .tab:is(input:checked) + .tabs-lifted .tab:is(input:checked):before { + background-image: var(--radius-end); + background-position: top right; +} + +.tabs-boxed { + border-radius: var(--rounded-btn, 0.5rem); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + padding: 0.25rem; +} + +.tabs-boxed .tab { + border-radius: var(--rounded-btn, 0.5rem); +} + +.tabs-boxed :is(.tab-active, [aria-selected="true"]):not(.tab-disabled):not([disabled]), .tabs-boxed :is(input:checked) { + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} + +.textarea:focus { + box-shadow: none; + border-color: var(--fallback-bc,oklch(var(--bc)/0.2)); + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.textarea-disabled, + .textarea:disabled, + .textarea[disabled] { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); + color: var(--fallback-bc,oklch(var(--bc)/0.4)); +} + +.textarea-disabled::-moz-placeholder, .textarea:disabled::-moz-placeholder, .textarea[disabled]::-moz-placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +.textarea-disabled::placeholder, + .textarea:disabled::placeholder, + .textarea[disabled]::placeholder { + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity))); + --tw-placeholder-opacity: 0.2; +} + +@keyframes toast-pop { + 0% { + transform: scale(0.9); + opacity: 0; + } + + 100% { + transform: scale(1); + opacity: 1; + } +} + +[dir="rtl"] .toggle { + --handleoffsetcalculator: calc(var(--handleoffset) * 1); +} + +.toggle:focus-visible { + outline-style: solid; + outline-width: 2px; + outline-offset: 2px; + outline-color: var(--fallback-bc,oklch(var(--bc)/0.2)); +} + +.toggle:hover { + background-color: currentColor; +} + +.toggle:checked, + .toggle[aria-checked="true"] { + background-image: none; + --handleoffsetcalculator: var(--handleoffset); + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); +} + +[dir="rtl"] .toggle:checked, [dir="rtl"] .toggle[aria-checked="true"] { + --handleoffsetcalculator: calc(var(--handleoffset) * -1); +} + +.toggle:indeterminate { + --tw-text-opacity: 1; + color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity))); + box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset, + calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset, + 0 0 0 2px var(--tglbg) inset; +} + +[dir="rtl"] .toggle:indeterminate { + box-shadow: calc(var(--handleoffset) / 2) 0 0 2px var(--tglbg) inset, + calc(var(--handleoffset) / -2) 0 0 2px var(--tglbg) inset, + 0 0 0 2px var(--tglbg) inset; +} + +.toggle:disabled { + cursor: not-allowed; + --tw-border-opacity: 1; + border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity))); + background-color: transparent; + opacity: 0.3; + --togglehandleborder: 0 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset, + var(--handleoffsetcalculator) 0 0 3px var(--fallback-bc,oklch(var(--bc)/1)) inset; +} + +.artboard.phone-1.horizontal, + .artboard.phone-1.artboard-horizontal { + width: 568px; + height: 320px; +} + +.artboard.phone-2.horizontal, + .artboard.phone-2.artboard-horizontal { + width: 667px; + height: 375px; +} + +.artboard.phone-3.horizontal, + .artboard.phone-3.artboard-horizontal { + width: 736px; + height: 414px; +} + +.artboard.phone-4.horizontal, + .artboard.phone-4.artboard-horizontal { + width: 812px; + height: 375px; +} + +.artboard.phone-5.horizontal, + .artboard.phone-5.artboard-horizontal { + width: 896px; + height: 414px; +} + +.artboard.phone-6.horizontal, + .artboard.phone-6.artboard-horizontal { + width: 1024px; + height: 320px; +} + +.btn-sm { + height: 2rem; + min-height: 2rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + font-size: 0.875rem; +} + +.btn-square:where(.btn-sm) { + height: 2rem; + width: 2rem; + padding: 0px; +} + +.btn-circle:where(.btn-sm) { + height: 2rem; + width: 2rem; + border-radius: 9999px; + padding: 0px; +} + +.join.join-vertical { + flex-direction: column; +} + +.join.join-vertical .join-item:first-child:not(:last-child), + .join.join-vertical *:first-child:not(:last-child) .join-item { + border-end-start-radius: 0; + border-end-end-radius: 0; + border-start-start-radius: inherit; + border-start-end-radius: inherit; +} + +.join.join-vertical .join-item:last-child:not(:first-child), + .join.join-vertical *:last-child:not(:first-child) .join-item { + border-start-start-radius: 0; + border-start-end-radius: 0; + border-end-start-radius: inherit; + border-end-end-radius: inherit; +} + +.join.join-horizontal { + flex-direction: row; +} + +.join.join-horizontal .join-item:first-child:not(:last-child), + .join.join-horizontal *:first-child:not(:last-child) .join-item { + border-end-end-radius: 0; + border-start-end-radius: 0; + border-end-start-radius: inherit; + border-start-start-radius: inherit; +} + +.join.join-horizontal .join-item:last-child:not(:first-child), + .join.join-horizontal *:last-child:not(:first-child) .join-item { + border-end-start-radius: 0; + border-start-start-radius: 0; + border-end-end-radius: inherit; + border-start-end-radius: inherit; +} + +.tabs-md :where(.tab) { + height: 2rem; + font-size: 0.875rem; + line-height: 1.25rem; + line-height: 2; + --tab-padding: 1rem; +} + +.tabs-lg :where(.tab) { + height: 3rem; + font-size: 1.125rem; + line-height: 1.75rem; + line-height: 2; + --tab-padding: 1.25rem; +} + +.tabs-sm :where(.tab) { + height: 1.5rem; + font-size: 0.875rem; + line-height: .75rem; + --tab-padding: 0.75rem; +} + +.tabs-xs :where(.tab) { + height: 1.25rem; + font-size: 0.75rem; + line-height: .75rem; + --tab-padding: 0.5rem; +} + +.join.join-vertical > :where(*:not(:first-child)) { + margin-left: 0px; + margin-right: 0px; + margin-top: -1px; +} + +.join.join-vertical > :where(*:not(:first-child)):is(.btn) { + margin-top: calc(var(--border-btn) * -1); +} + +.join.join-horizontal > :where(*:not(:first-child)) { + margin-top: 0px; + margin-bottom: 0px; + margin-inline-start: -1px; +} + +.join.join-horizontal > :where(*:not(:first-child)):is(.btn) { + margin-inline-start: calc(var(--border-btn) * -1); +} + +.relative { + position: relative; +} + +.bottom-0 { + bottom: 0px; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.my-1 { + margin-top: 0.25rem; + margin-bottom: 0.25rem; +} + +.my-1\.5 { + margin-top: 0.375rem; + margin-bottom: 0.375rem; +} + +.-mt-0 { + margin-top: -0px; +} + +.-mt-0\.5 { + margin-top: -0.125rem; +} + +.-mt-1 { + margin-top: -0.25rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.ml-2 { + margin-left: 0.5rem; +} + +.mr-1 { + margin-right: 0.25rem; +} + +.block { + display: block; +} + +.inline { + display: inline; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.grid { + display: grid; +} + +.hidden { + display: none; +} + +.h-12 { + height: 3rem; +} + +.h-4 { + height: 1rem; +} + +.h-5 { + height: 1.25rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-auto { + height: auto; +} + +.h-full { + height: 100%; +} + +.h-screen { + height: 100vh; +} + +.min-h-6 { + min-height: 1.5rem; +} + +.w-1\/2 { + width: 50%; +} + +.w-1\/3 { + width: 33.333333%; +} + +.w-1\/4 { + width: 25%; +} + +.w-4 { + width: 1rem; +} + +.w-5 { + width: 1.25rem; +} + +.w-full { + width: 100%; +} + +.min-w-16 { + min-width: 4rem; +} + +.min-w-max { + min-width: -moz-max-content; + min-width: max-content; +} + +.max-w-72 { + max-width: 18rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.flex-shrink-0 { + flex-shrink: 0; +} + +.flex-grow { + flex-grow: 1; +} + +.cursor-move { + cursor: move; +} + +.cursor-pointer { + cursor: pointer; +} + +.resize-y { + resize: vertical; +} + +.appearance-none { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.flex-col { + flex-direction: column; +} + +.items-center { + align-items: center; +} + +.items-stretch { + align-items: stretch; +} + +.justify-center { + justify-content: center; +} + +.gap-1 { + gap: 0.25rem; +} + +.gap-2 { + gap: 0.5rem; +} + +.gap-3 { + gap: 0.75rem; +} + +.gap-5 { + gap: 1.25rem; +} + +.gap-x-0 { + -moz-column-gap: 0px; + column-gap: 0px; +} + +.gap-x-0\.5 { + -moz-column-gap: 0.125rem; + column-gap: 0.125rem; +} + +.gap-x-1 { + -moz-column-gap: 0.25rem; + column-gap: 0.25rem; +} + +.gap-x-1\.5 { + -moz-column-gap: 0.375rem; + column-gap: 0.375rem; +} + +.gap-x-2 { + -moz-column-gap: 0.5rem; + column-gap: 0.5rem; +} + +.divide-y > :not([hidden]) ~ :not([hidden]) { + --tw-divide-y-reverse: 0; + border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); + border-bottom-width: calc(1px * var(--tw-divide-y-reverse)); +} + +.place-self-center { + place-self: center; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.overscroll-auto { + overscroll-behavior: auto; +} + +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.rounded { + border-radius: 0.25rem; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.border { + border-width: 1px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-t { + border-top-width: 1px; +} + +.border-base-300 { + --tw-border-opacity: 1; + border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity))); +} + +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(176 176 176 / var(--tw-border-opacity)); +} + +.bg-base-200 { + --tw-bg-opacity: 1; + background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity))); +} + +.bg-blue-100 { + --tw-bg-opacity: 1; + background-color: rgb(219 234 254 / var(--tw-bg-opacity)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(231 231 231 / var(--tw-bg-opacity)); +} + +.bg-gray-50 { + --tw-bg-opacity: 1; + background-color: rgb(246 246 246 / var(--tw-bg-opacity)); +} + +.bg-primary-500 { + --tw-bg-opacity: 1; + background-color: rgb(0 159 255 / var(--tw-bg-opacity)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.p-0 { + padding: 0px; +} + +.p-0\.5 { + padding: 0.125rem; +} + +.p-1 { + padding: 0.25rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-4 { + padding: 1rem; +} + +.px-1 { + padding-left: 0.25rem; + padding-right: 0.25rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-6 { + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +.px-8 { + padding-left: 2rem; + padding-right: 2rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-1\.5 { + padding-top: 0.375rem; + padding-bottom: 0.375rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.pb-2 { + padding-bottom: 0.5rem; +} + +.pb-3 { + padding-bottom: 0.75rem; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pr-1 { + padding-right: 0.25rem; +} + +.pt-3 { + padding-top: 0.75rem; +} + +.text-center { + text-align: center; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-5xl { + font-size: 3rem; + line-height: 1; +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-black { + font-weight: 900; +} + +.font-bold { + font-weight: 700; +} + +.font-medium { + font-weight: 500; +} + +.uppercase { + text-transform: uppercase; +} + +.text-black { + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} + +.text-blue-900 { + --tw-text-opacity: 1; + color: rgb(30 58 138 / var(--tw-text-opacity)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(109 109 109 / var(--tw-text-opacity)); +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(76 76 76 / var(--tw-text-opacity)); +} + +.text-gray-800 { + --tw-text-opacity: 1; + color: rgb(69 69 69 / var(--tw-text-opacity)); +} + +.text-inherit { + color: inherit; +} + +.text-red-500 { + --tw-text-opacity: 1; + color: rgb(255 119 119 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.placeholder-gray-400::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(136 136 136 / var(--tw-placeholder-opacity)); +} + +.placeholder-gray-400::placeholder { + --tw-placeholder-opacity: 1; + color: rgb(136 136 136 / var(--tw-placeholder-opacity)); +} + +.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); +} + +.filter { + 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); +} + +.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; +} + +.\[--fallback-p\:white\] { + --fallback-p: white; +} + +.\[--fallback-pc\:black\] { + --fallback-pc: black; +} + +/* +globally kill the tailwind ring by default +*/ + +input { + --tw-ring-shadow: 0 0 #000 !important; +} + +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(231 231 231 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-200:hover { + --tw-bg-opacity: 1; + background-color: rgb(209 209 209 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-50:hover { + --tw-bg-opacity: 1; + background-color: rgb(246 246 246 / var(--tw-bg-opacity)); +} + +.hover\:bg-primary-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(0 117 255 / var(--tw-bg-opacity)); +} + +.hover\:text-gray-800:hover { + --tw-text-opacity: 1; + color: rgb(69 69 69 / var(--tw-text-opacity)); +} + +.focus\:border-transparent:focus { + border-color: transparent; +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:ring-2: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(2px + 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\:ring-opacity-100:focus { + --tw-ring-opacity: 1; +} + +.focus-visible\:outline:focus-visible { + outline-style: solid; +} + +.focus-visible\:outline-2:focus-visible { + outline-width: 2px; +} + +.focus-visible\:outline-offset-2:focus-visible { + outline-offset: 2px; +} + +.focus-visible\:outline-primary-500:focus-visible { + outline-color: #009fff; +} + +.disabled\:cursor-not-allowed:disabled { + cursor: not-allowed; +} + +.disabled\:bg-primary-500:disabled { + --tw-bg-opacity: 1; + background-color: rgb(0 159 255 / var(--tw-bg-opacity)); +} + +.disabled\:opacity-75:disabled { + opacity: 0.75; +} + +.aria-disabled\:cursor-not-allowed[aria-disabled="true"] { + cursor: not-allowed; +} + +.aria-disabled\:bg-primary-500[aria-disabled="true"] { + --tw-bg-opacity: 1; + background-color: rgb(0 159 255 / var(--tw-bg-opacity)); +} + +.aria-disabled\:opacity-75[aria-disabled="true"] { + opacity: 0.75; +} + +.dark\:border-gray-600:is(.dark *) { + --tw-border-opacity: 1; + border-color: rgb(93 93 93 / var(--tw-border-opacity)); +} + +.dark\:bg-gray-800:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(69 69 69 / var(--tw-bg-opacity)); +} + +.dark\:bg-primary-400:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(38 198 255 / var(--tw-bg-opacity)); +} + +.dark\:text-gray-300:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(176 176 176 / var(--tw-text-opacity)); +} + +.dark\:text-gray-900:is(.dark *) { + --tw-text-opacity: 1; + color: rgb(61 61 61 / var(--tw-text-opacity)); +} + +.dark\:placeholder-gray-500:is(.dark *)::-moz-placeholder { + --tw-placeholder-opacity: 1; + color: rgb(109 109 109 / var(--tw-placeholder-opacity)); +} + +.dark\:placeholder-gray-500:is(.dark *)::placeholder { + --tw-placeholder-opacity: 1; + color: rgb(109 109 109 / var(--tw-placeholder-opacity)); +} + +.dark\:hover\:bg-gray-800:hover:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(69 69 69 / var(--tw-bg-opacity)); +} + +.dark\:hover\:bg-primary-500:hover:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(0 159 255 / var(--tw-bg-opacity)); +} + +.dark\:focus-visible\:outline-primary-400:focus-visible:is(.dark *) { + outline-color: #26c6ff; +} + +.dark\:disabled\:bg-primary-400:disabled:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(38 198 255 / var(--tw-bg-opacity)); +} + +.dark\:aria-disabled\:bg-primary-400[aria-disabled="true"]:is(.dark *) { + --tw-bg-opacity: 1; + background-color: rgb(38 198 255 / var(--tw-bg-opacity)); +} + +@media (min-width: 768px) { + .md\:flex { + display: flex; + } + + .md\:px-4 { + padding-left: 1rem; + padding-right: 1rem; + } +} + +@media print { + .print\:hidden { + display: none; + } +} \ No newline at end of file diff --git a/static/js/choices.min.js b/static/js/choices.min.js new file mode 100644 index 0000000..295be67 --- /dev/null +++ b/static/js/choices.min.js @@ -0,0 +1,2 @@ +/*! choices.js v11.0.2 | © 2024 Josh Johnson | https://github.com/jshjohnson/Choices#readme */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Choices=t()}(this,(function(){"use strict";var e=function(t,i){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])},e(t,i)};function t(t,i){if("function"!=typeof i&&null!==i)throw new TypeError("Class extends value "+String(i)+" is not a constructor or null");function n(){this.constructor=t}e(t,i),t.prototype=null===i?Object.create(i):(n.prototype=i.prototype,new n)}var i=function(){return i=Object.assign||function(e){for(var t,i=1,n=arguments.length;i/g,">").replace(/=0&&!window.matchMedia("(min-height: ".concat(e+1,"px)")).matches:"top"===this.position&&(i=!0),i},e.prototype.setActiveDescendant=function(e){this.element.setAttribute("aria-activedescendant",e)},e.prototype.removeActiveDescendant=function(){this.element.removeAttribute("aria-activedescendant")},e.prototype.open=function(e,t){F(this.element,this.classNames.openState),this.element.setAttribute("aria-expanded","true"),this.isOpen=!0,this.shouldFlip(e,t)&&(F(this.element,this.classNames.flippedState),this.isFlipped=!0)},e.prototype.close=function(){D(this.element,this.classNames.openState),this.element.setAttribute("aria-expanded","false"),this.removeActiveDescendant(),this.isOpen=!1,this.isFlipped&&(D(this.element,this.classNames.flippedState),this.isFlipped=!1)},e.prototype.addFocusState=function(){F(this.element,this.classNames.focusState)},e.prototype.removeFocusState=function(){D(this.element,this.classNames.focusState)},e.prototype.enable=function(){D(this.element,this.classNames.disabledState),this.element.removeAttribute("aria-disabled"),this.type===_&&this.element.setAttribute("tabindex","0"),this.isDisabled=!1},e.prototype.disable=function(){F(this.element,this.classNames.disabledState),this.element.setAttribute("aria-disabled","true"),this.type===_&&this.element.setAttribute("tabindex","-1"),this.isDisabled=!0},e.prototype.wrap=function(e){var t=this.element,i=e.parentNode;i&&(e.nextSibling?i.insertBefore(t,e.nextSibling):i.appendChild(t)),t.appendChild(e)},e.prototype.unwrap=function(e){var t=this.element,i=t.parentNode;i&&(i.insertBefore(e,t),i.removeChild(t))},e.prototype.addLoadingState=function(){F(this.element,this.classNames.loadingState),this.element.setAttribute("aria-busy","true"),this.isLoading=!0},e.prototype.removeLoadingState=function(){D(this.element,this.classNames.loadingState),this.element.removeAttribute("aria-busy"),this.isLoading=!1},e}(),K=function(){function e(e){var t=e.element,i=e.type,n=e.classNames,s=e.preventPaste;this.element=t,this.type=i,this.classNames=n,this.preventPaste=s,this.isFocussed=this.element.isEqualNode(document.activeElement),this.isDisabled=t.disabled,this._onPaste=this._onPaste.bind(this),this._onInput=this._onInput.bind(this),this._onFocus=this._onFocus.bind(this),this._onBlur=this._onBlur.bind(this)}return Object.defineProperty(e.prototype,"placeholder",{set:function(e){this.element.placeholder=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"value",{get:function(){return this.element.value},set:function(e){this.element.value=e},enumerable:!1,configurable:!0}),e.prototype.addEventListeners=function(){var e=this.element;e.addEventListener("paste",this._onPaste),e.addEventListener("input",this._onInput,{passive:!0}),e.addEventListener("focus",this._onFocus,{passive:!0}),e.addEventListener("blur",this._onBlur,{passive:!0})},e.prototype.removeEventListeners=function(){var e=this.element;e.removeEventListener("input",this._onInput),e.removeEventListener("paste",this._onPaste),e.removeEventListener("focus",this._onFocus),e.removeEventListener("blur",this._onBlur)},e.prototype.enable=function(){this.element.removeAttribute("disabled"),this.isDisabled=!1},e.prototype.disable=function(){this.element.setAttribute("disabled",""),this.isDisabled=!0},e.prototype.focus=function(){this.isFocussed||this.element.focus()},e.prototype.blur=function(){this.isFocussed&&this.element.blur()},e.prototype.clear=function(e){return void 0===e&&(e=!0),this.element.value="",e&&this.setWidth(),this},e.prototype.setWidth=function(){var e=this.element;e.style.minWidth="".concat(e.placeholder.length+1,"ch"),e.style.width="".concat(e.value.length+1,"ch")},e.prototype.setActiveDescendant=function(e){this.element.setAttribute("aria-activedescendant",e)},e.prototype.removeActiveDescendant=function(){this.element.removeAttribute("aria-activedescendant")},e.prototype._onInput=function(){this.type!==_&&this.setWidth()},e.prototype._onPaste=function(e){this.preventPaste&&e.preventDefault()},e.prototype._onFocus=function(){this.isFocussed=!0},e.prototype._onBlur=function(){this.isFocussed=!1},e}(),B=function(){function e(e){this.element=e.element,this.scrollPos=this.element.scrollTop,this.height=this.element.offsetHeight}return e.prototype.prepend=function(e){var t=this.element.firstElementChild;t?this.element.insertBefore(e,t):this.element.append(e)},e.prototype.scrollToTop=function(){this.element.scrollTop=0},e.prototype.scrollToChildElement=function(e,t){var i=this;if(e){var n=t>0?this.element.scrollTop+(e.offsetTop+e.offsetHeight)-(this.element.scrollTop+this.element.offsetHeight):e.offsetTop;requestAnimationFrame((function(){i._animateScroll(n,t)}))}},e.prototype._scrollDown=function(e,t,i){var n=(i-e)/t;this.element.scrollTop=e+(n>1?n:1)},e.prototype._scrollUp=function(e,t,i){var n=(e-i)/t;this.element.scrollTop=e-(n>1?n:1)},e.prototype._animateScroll=function(e,t){var i=this,n=this.element.scrollTop,s=!1;t>0?(this._scrollDown(n,4,e),ne&&(s=!0)),s&&requestAnimationFrame((function(){i._animateScroll(e,t)}))},e}(),V=function(){function e(e){var t=e.classNames;this.element=e.element,this.classNames=t,this.isDisabled=!1}return Object.defineProperty(e.prototype,"isActive",{get:function(){return"active"===this.element.dataset.choice},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"dir",{get:function(){return this.element.dir},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"value",{get:function(){return this.element.value},set:function(e){this.element.setAttribute("value",e),this.element.value=e},enumerable:!1,configurable:!0}),e.prototype.conceal=function(){var e=this.element;F(e,this.classNames.input),e.hidden=!0,e.tabIndex=-1;var t=e.getAttribute("style");t&&e.setAttribute("data-choice-orig-style",t),e.setAttribute("data-choice","active")},e.prototype.reveal=function(){var e=this.element;D(e,this.classNames.input),e.hidden=!1,e.removeAttribute("tabindex");var t=e.getAttribute("data-choice-orig-style");t?(e.removeAttribute("data-choice-orig-style"),e.setAttribute("style",t)):e.removeAttribute("style"),e.removeAttribute("data-choice")},e.prototype.enable=function(){this.element.removeAttribute("disabled"),this.element.disabled=!1,this.isDisabled=!1},e.prototype.disable=function(){this.element.setAttribute("disabled",""),this.element.disabled=!0,this.isDisabled=!0},e.prototype.triggerEvent=function(e,t){var i;void 0===(i=t||{})&&(i=null),this.element.dispatchEvent(new CustomEvent(e,{detail:i,bubbles:!0,cancelable:!0}))},e}(),H=function(e){function i(){return null!==e&&e.apply(this,arguments)||this}return t(i,e),i}(V),$=function(e,t){return void 0===t&&(t=!0),void 0===e?t:!!e},q=function(e){if("string"==typeof e&&(e=e.split(" ").filter((function(e){return e.length}))),Array.isArray(e)&&e.length)return e},W=function(e,t){if("string"==typeof e)return W({value:e,label:e},!1);var i=e;if("choices"in i){if(!t)throw new TypeError("optGroup is not allowed");var n=i,s=n.choices.map((function(e){return W(e,!1)}));return{id:0,label:O(n.label)||n.value,active:!!s.length,disabled:!!n.disabled,choices:s}}var o=i;return{id:0,group:null,score:0,rank:0,value:o.value,label:o.label||o.value,active:$(o.active),selected:$(o.selected,!1),disabled:$(o.disabled,!1),placeholder:$(o.placeholder,!1),highlighted:!1,labelClass:q(o.labelClass),labelDescription:o.labelDescription,customProperties:o.customProperties}},U=function(e){return"SELECT"===e.tagName},G=function(e){function i(t){var i=t.template,n=t.extractPlaceholder,s=e.call(this,{element:t.element,classNames:t.classNames})||this;return s.template=i,s.extractPlaceholder=n,s}return t(i,e),Object.defineProperty(i.prototype,"placeholderOption",{get:function(){return this.element.querySelector('option[value=""]')||this.element.querySelector("option[placeholder]")},enumerable:!1,configurable:!0}),i.prototype.addOptions=function(e){var t=this,i=document.createDocumentFragment();e.forEach((function(e){var n=e;if(!n.element){var s=t.template(n);i.appendChild(s),n.element=s}})),this.element.appendChild(i)},i.prototype.optionsAsChoices=function(){var e=this,t=[];return this.element.querySelectorAll(":scope > option, :scope > optgroup").forEach((function(i){!function(e){return"OPTION"===e.tagName}(i)?function(e){return"OPTGROUP"===e.tagName}(i)&&t.push(e._optgroupToChoice(i)):t.push(e._optionToChoice(i))})),t},i.prototype._optionToChoice=function(e){return!e.hasAttribute("value")&&e.hasAttribute("placeholder")&&(e.setAttribute("value",""),e.value=""),{id:0,group:null,score:0,rank:0,value:e.value,label:e.innerHTML,element:e,active:!0,selected:this.extractPlaceholder?e.selected:e.hasAttribute("selected"),disabled:e.disabled,highlighted:!1,placeholder:this.extractPlaceholder&&(!e.value||e.hasAttribute("placeholder")),labelClass:void 0!==e.dataset.labelClass?q(e.dataset.labelClass):void 0,labelDescription:void 0!==e.dataset.labelDescription?e.dataset.labelDescription:void 0,customProperties:P(e.dataset.customProperties)}},i.prototype._optgroupToChoice=function(e){var t=this,i=e.querySelectorAll("option"),n=Array.from(i).map((function(e){return t._optionToChoice(e)}));return{id:0,label:e.label||"",element:e,active:!!n.length,disabled:e.disabled,choices:n}},i}(V),z={items:[],choices:[],silent:!1,renderChoiceLimit:-1,maxItemCount:-1,closeDropdownOnSelect:"auto",singleModeForMultiSelect:!1,addChoices:!1,addItems:!0,addItemFilter:function(e){return!!e&&""!==e},removeItems:!0,removeItemButton:!1,removeItemButtonAlignLeft:!1,editItems:!1,allowHTML:!1,allowHtmlUserInput:!1,duplicateItemsAllowed:!0,delimiter:",",paste:!0,searchEnabled:!0,searchChoices:!0,searchFloor:1,searchResultLimit:4,searchFields:["label","value"],position:"auto",resetScrollPosition:!0,shouldSort:!0,shouldSortItems:!1,sorter:function(e,t){var i=e.label,n=t.label,s=void 0===n?t.value:n;return O(void 0===i?e.value:i).localeCompare(O(s),[],{sensitivity:"base",ignorePunctuation:!0,numeric:!0})},shadowRoot:null,placeholder:!0,placeholderValue:null,searchPlaceholderValue:null,prependValue:null,appendValue:null,renderSelectedChoices:"auto",loadingText:"Loading...",noResultsText:"No results found",noChoicesText:"No choices to choose from",itemSelectText:"Press to select",uniqueItemText:"Only unique values can be added",customAddItemText:"Only values matching specific conditions can be added",addItemText:function(e){return'Press Enter to add "'.concat(e,'"')},removeItemIconText:function(){return"Remove item"},removeItemLabelText:function(e){return"Remove item: ".concat(e)},maxItemText:function(e){return"Only ".concat(e," values can be added")},valueComparer:function(e,t){return e===t},fuseOptions:{includeScore:!0},labelId:"",callbackOnInit:null,callbackOnCreateTemplates:null,classNames:{containerOuter:["choices"],containerInner:["choices__inner"],input:["choices__input"],inputCloned:["choices__input--cloned"],list:["choices__list"],listItems:["choices__list--multiple"],listSingle:["choices__list--single"],listDropdown:["choices__list--dropdown"],item:["choices__item"],itemSelectable:["choices__item--selectable"],itemDisabled:["choices__item--disabled"],itemChoice:["choices__item--choice"],description:["choices__description"],placeholder:["choices__placeholder"],group:["choices__group"],groupHeading:["choices__heading"],button:["choices__button"],activeState:["is-active"],focusState:["is-focused"],openState:["is-open"],disabledState:["is-disabled"],highlightedState:["is-highlighted"],selectedState:["is-selected"],flippedState:["is-flipped"],loadingState:["is-loading"],notice:["choices__notice"],addChoice:["choices__item--selectable","add-choice"],noResults:["has-no-results"],noChoices:["has-no-choices"]},appendGroupInSearch:!1},J=function(e){var t=e.itemEl;t&&(t.remove(),e.itemEl=void 0)},X={groups:function(e,t){var i=e,n=!0;switch(t.type){case l:i.push(t.group);break;case h:i=[];break;default:n=!1}return{state:i,update:n}},items:function(e,t,i){var n=e,s=!0;switch(t.type){case u:t.item.selected=!0,(o=t.item.element)&&(o.selected=!0,o.setAttribute("selected","")),n.push(t.item);break;case d:var o;if(t.item.selected=!1,o=t.item.element){o.selected=!1,o.removeAttribute("selected");var c=o.parentElement;c&&U(c)&&c.type===_&&(c.value="")}J(t.item),n=n.filter((function(e){return e.id!==t.item.id}));break;case r:J(t.choice),n=n.filter((function(e){return e.id!==t.choice.id}));break;case p:var a=t.highlighted,h=n.find((function(e){return e.id===t.item.id}));h&&h.highlighted!==a&&(h.highlighted=a,i&&function(e,t,i){var n=e.itemEl;n&&(D(n,i),F(n,t))}(h,a?i.classNames.highlightedState:i.classNames.selectedState,a?i.classNames.selectedState:i.classNames.highlightedState));break;default:s=!1}return{state:n,update:s}},choices:function(e,t,i){var n=e,s=!0;switch(t.type){case o:n.push(t.choice);break;case r:t.choice.choiceEl=void 0,t.choice.group&&(t.choice.group.choices=t.choice.group.choices.filter((function(e){return e.id!==t.choice.id}))),n=n.filter((function(e){return e.id!==t.choice.id}));break;case u:case d:t.item.choiceEl=void 0;break;case c:var l=[];t.results.forEach((function(e){l[e.item.id]=e})),n.forEach((function(e){var t=l[e.id];void 0!==t?(e.score=t.score,e.rank=t.rank,e.active=!0):(e.score=0,e.rank=0,e.active=!1),i&&i.appendGroupInSearch&&(e.choiceEl=void 0)}));break;case a:n.forEach((function(e){e.active=t.active,i&&i.appendGroupInSearch&&(e.choiceEl=void 0)}));break;case h:n=[];break;default:s=!1}return{state:n,update:s}}},Q=function(){function e(e){this._state=this.defaultState,this._listeners=[],this._txn=0,this._context=e}return Object.defineProperty(e.prototype,"defaultState",{get:function(){return{groups:[],items:[],choices:[]}},enumerable:!1,configurable:!0}),e.prototype.changeSet=function(e){return{groups:e,items:e,choices:e}},e.prototype.reset=function(){this._state=this.defaultState;var e=this.changeSet(!0);this._txn?this._changeSet=e:this._listeners.forEach((function(t){return t(e)}))},e.prototype.subscribe=function(e){return this._listeners.push(e),this},e.prototype.dispatch=function(e){var t=this,i=this._state,n=!1,s=this._changeSet||this.changeSet(!1);Object.keys(X).forEach((function(o){var r=X[o](i[o],e,t._context);r.update&&(n=!0,s[o]=!0,i[o]=r.state)})),n&&(this._txn?this._changeSet=s:this._listeners.forEach((function(e){return e(s)})))},e.prototype.withTxn=function(e){this._txn++;try{e()}finally{if(this._txn=Math.max(0,this._txn-1),!this._txn){var t=this._changeSet;t&&(this._changeSet=void 0,this._listeners.forEach((function(e){return e(t)})))}}},Object.defineProperty(e.prototype,"state",{get:function(){return this._state},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"items",{get:function(){return this.state.items},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"highlightedActiveItems",{get:function(){return this.items.filter((function(e){return!e.disabled&&e.active&&e.highlighted}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"choices",{get:function(){return this.state.choices},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"activeChoices",{get:function(){return this.choices.filter((function(e){return e.active}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"searchableChoices",{get:function(){return this.choices.filter((function(e){return!e.disabled&&!e.placeholder}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"groups",{get:function(){return this.state.groups},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"activeGroups",{get:function(){var e=this;return this.state.groups.filter((function(t){var i=t.active&&!t.disabled,n=e.state.choices.some((function(e){return e.active&&!e.disabled}));return i&&n}),[])},enumerable:!1,configurable:!0}),e.prototype.inTxn=function(){return this._txn>0},e.prototype.getChoiceById=function(e){return this.activeChoices.find((function(t){return t.id===e}))},e.prototype.getGroupById=function(e){return this.groups.find((function(t){return t.id===e}))},e}(),Y="no-choices",Z="no-results",ee="add-choice";function te(e,t,i){return(t=function(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var i=t.call(e,"string");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function ie(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,n)}return i}function ne(e){for(var t=1;t`Missing ${e} property in key`,de=e=>`Property 'weight' in key '${e}' must be a positive integer`,pe=Object.prototype.hasOwnProperty;class fe{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach((e=>{let i=me(e);this._keys.push(i),this._keyMap[i.id]=i,t+=i.weight})),this._keys.forEach((e=>{e.weight/=t}))}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function me(e){let t=null,i=null,n=null,s=1,o=null;if(oe(e)||se(e))n=e,t=ge(e),i=ve(e);else{if(!pe.call(e,"name"))throw new Error(ue("name"));const r=e.name;if(n=r,pe.call(e,"weight")&&(s=e.weight,s<=0))throw new Error(de(r));t=ge(r),i=ve(r),o=e.getFn}return{path:t,id:i,weight:s,src:n,getFn:o}}function ge(e){return se(e)?e:e.split(".")}function ve(e){return se(e)?e.join("."):e}const _e={useExtendedSearch:!1,getFn:function(e,t){let i=[],n=!1;const s=(e,t,o)=>{if(ae(e))if(t[o]){const r=e[t[o]];if(!ae(r))return;if(o===t.length-1&&(oe(r)||re(r)||function(e){return!0===e||!1===e||function(e){return ce(e)&&null!==e}(e)&&"[object Boolean]"==le(e)}(r)))i.push(function(e){return null==e?"":function(e){if("string"==typeof e)return e;let t=e+"";return"0"==t&&1/e==-1/0?"-0":t}(e)}(r));else if(se(r)){n=!0;for(let e=0,i=r.length;ee.score===t.score?e.idx{this._keysMap[e.id]=t}))}create(){!this.isCreated&&this.docs.length&&(this.isCreated=!0,oe(this.docs[0])?this.docs.forEach(((e,t)=>{this._addString(e,t)})):this.docs.forEach(((e,t)=>{this._addObject(e,t)})),this.norm.clear())}add(e){const t=this.size();oe(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,i=this.size();t{let s=t.getFn?t.getFn(e):this.getFn(e,t.path);if(ae(s))if(se(s)){let e=[];const t=[{nestedArrIndex:-1,value:s}];for(;t.length;){const{nestedArrIndex:i,value:n}=t.pop();if(ae(n))if(oe(n)&&!he(n)){let t={v:n,i:i,n:this.norm.get(n)};e.push(t)}else se(n)&&n.forEach(((e,i)=>{t.push({nestedArrIndex:i,value:e})}))}i.$[n]=e}else if(oe(s)&&!he(s)){let e={v:s,n:this.norm.get(s)};i.$[n]=e}})),this.records.push(i)}toJSON(){return{keys:this.keys,records:this.records}}}function Ce(e,t,{getFn:i=ye.getFn,fieldNormWeight:n=ye.fieldNormWeight}={}){const s=new Ee({getFn:i,fieldNormWeight:n});return s.setKeys(e.map(me)),s.setSources(t),s.create(),s}function Se(e,{errors:t=0,currentLocation:i=0,expectedLocation:n=0,distance:s=ye.distance,ignoreLocation:o=ye.ignoreLocation}={}){const r=t/e.length;if(o)return r;const c=Math.abs(n-i);return s?r+c/s:c?1:r}const we=32;function Ie(e){let t={};for(let i=0,n=e.length;i{this.chunks.push({pattern:e,alphabet:Ie(e),startIndex:t})},l=this.pattern.length;if(l>we){let e=0;const t=l%we,i=l-t;for(;e{const{isMatch:f,score:m,indices:g}=function(e,t,i,{location:n=ye.location,distance:s=ye.distance,threshold:o=ye.threshold,findAllMatches:r=ye.findAllMatches,minMatchCharLength:c=ye.minMatchCharLength,includeMatches:a=ye.includeMatches,ignoreLocation:h=ye.ignoreLocation}={}){if(t.length>we)throw new Error("Pattern length exceeds max of 32.");const l=t.length,u=e.length,d=Math.max(0,Math.min(n,u));let p=o,f=d;const m=c>1||a,g=m?Array(u):[];let v;for(;(v=e.indexOf(t,f))>-1;){let e=Se(t,{currentLocation:v,expectedLocation:d,distance:s,ignoreLocation:h});if(p=Math.min(e,p),f=v+l,m){let e=0;for(;e=a;o-=1){let r=o-1,c=i[e.charAt(r)];if(m&&(g[r]=+!!c),C[o]=(C[o+1]<<1|1)&c,n&&(C[o]|=(_[o+1]|_[o])<<1|1|_[o+1]),C[o]&E&&(y=Se(t,{errors:n,currentLocation:r,expectedLocation:d,distance:s,ignoreLocation:h}),y<=p)){if(p=y,f=r,f<=d)break;a=Math.max(1,2*d-f)}}if(Se(t,{errors:n+1,currentLocation:d,expectedLocation:d,distance:s,ignoreLocation:h})>p)break;_=C}const C={isMatch:f>=0,score:Math.max(.001,y)};if(m){const e=function(e=[],t=ye.minMatchCharLength){let i=[],n=-1,s=-1,o=0;for(let r=e.length;o=t&&i.push([n,s]),n=-1)}return e[o-1]&&o-n>=t&&i.push([n,o-1]),i}(g,c);e.length?a&&(C.indices=e):C.isMatch=!1}return C}(e,t,d,{location:n+p,distance:s,threshold:o,findAllMatches:r,minMatchCharLength:c,includeMatches:i,ignoreLocation:a});f&&(u=!0),l+=m,f&&g&&(h=[...h,...g])}));let d={isMatch:u,score:u?l/this.chunks.length:1};return u&&i&&(d.indices=h),d}}class Ae{constructor(e){this.pattern=e}static isMultiMatch(e){return Oe(e,this.multiRegex)}static isSingleMatch(e){return Oe(e,this.singleRegex)}search(){}}function Oe(e,t){const i=e.match(t);return i?i[1]:null}class Le extends Ae{constructor(e,{location:t=ye.location,threshold:i=ye.threshold,distance:n=ye.distance,includeMatches:s=ye.includeMatches,findAllMatches:o=ye.findAllMatches,minMatchCharLength:r=ye.minMatchCharLength,isCaseSensitive:c=ye.isCaseSensitive,ignoreLocation:a=ye.ignoreLocation}={}){super(e),this._bitapSearch=new xe(e,{location:t,threshold:i,distance:n,includeMatches:s,findAllMatches:o,minMatchCharLength:r,isCaseSensitive:c,ignoreLocation:a})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class Me extends Ae{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let t,i=0;const n=[],s=this.pattern.length;for(;(t=e.indexOf(this.pattern,i))>-1;)i=t+s,n.push([t,i-1]);const o=!!n.length;return{isMatch:o,score:o?0:1,indices:n}}}const Te=[class extends Ae{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},Me,class extends Ae{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},class extends Ae{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},class extends Ae{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},class extends Ae{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}},class extends Ae{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},Le],Ne=Te.length,ke=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,Fe=new Set([Le.type,Me.type]);const De=[];function Pe(e,t){for(let i=0,n=De.length;i!(!e[je]&&!e.$or),Be=e=>({[je]:Object.keys(e).map((t=>({[t]:e[t]})))});function Ve(e,t,{auto:i=!0}={}){const n=e=>{let s=Object.keys(e);const o=(e=>!!e[Re])(e);if(!o&&s.length>1&&!Ke(e))return n(Be(e));if((e=>!se(e)&&ce(e)&&!Ke(e))(e)){const n=o?e[Re]:s[0],r=o?e.$val:e[n];if(!oe(r))throw new Error((e=>`Invalid value for key ${e}`)(n));const c={keyId:ve(n),pattern:r};return i&&(c.searcher=Pe(r,t)),c}let r={children:[],operator:s[0]};return s.forEach((t=>{const i=e[t];se(i)&&i.forEach((e=>{r.children.push(n(e))}))})),r};return Ke(e)||(e=Be(e)),n(e)}function He(e,t){const i=e.matches;t.matches=[],ae(i)&&i.forEach((e=>{if(!ae(e.indices)||!e.indices.length)return;const{indices:i,value:n}=e;let s={indices:i,value:n};e.key&&(s.key=e.key.src),e.idx>-1&&(s.refIndex=e.idx),t.matches.push(s)}))}function $e(e,t){t.score=e.score}class qe{constructor(e,t={},i){this.options=ne(ne({},ye),t),this._keyStore=new fe(this.options.keys),this.setCollection(e,i)}setCollection(e,t){if(this._docs=e,t&&!(t instanceof Ee))throw new Error("Incorrect 'index' type");this._myIndex=t||Ce(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){ae(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){const t=[];for(let i=0,n=this._docs.length;i{let i=1;e.matches.forEach((({key:e,norm:n,score:s})=>{const o=e?e.weight:null;i*=Math.pow(0===s&&o?Number.EPSILON:s,(o||1)*(t?1:n))})),e.score=i}))}(c,{ignoreFieldNorm:r}),s&&c.sort(o),re(t)&&t>-1&&(c=c.slice(0,t)),function(e,t,{includeMatches:i=ye.includeMatches,includeScore:n=ye.includeScore}={}){const s=[];return i&&s.push(He),n&&s.push($e),e.map((e=>{const{idx:i}=e,n={item:t[i],refIndex:i};return s.length&&s.forEach((t=>{t(e,n)})),n}))}(c,this._docs,{includeMatches:i,includeScore:n})}_searchStringList(e){const t=Pe(e,this.options),{records:i}=this._myIndex,n=[];return i.forEach((({v:e,i:i,n:s})=>{if(!ae(e))return;const{isMatch:o,score:r,indices:c}=t.searchIn(e);o&&n.push({item:e,idx:i,matches:[{score:r,value:e,norm:s,indices:c}]})})),n}_searchLogical(e){const t=Ve(e,this.options),i=(e,t,n)=>{if(!e.children){const{keyId:i,searcher:s}=e,o=this._findMatches({key:this._keyStore.get(i),value:this._myIndex.getValueForItemAtKeyId(t,i),searcher:s});return o&&o.length?[{idx:n,item:t,matches:o}]:[]}const s=[];for(let o=0,r=e.children.length;o{if(ae(e)){let r=i(t,e,o);r.length&&(n[o]||(n[o]={idx:o,item:e,matches:[]},s.push(n[o])),r.forEach((({matches:e})=>{n[o].matches.push(...e)})))}})),s}_searchObjectList(e){const t=Pe(e,this.options),{keys:i,records:n}=this._myIndex,s=[];return n.forEach((({$:e,i:n})=>{if(!ae(e))return;let o=[];i.forEach(((i,n)=>{o.push(...this._findMatches({key:i,value:e[n],searcher:t}))})),o.length&&s.push({idx:n,item:e,matches:o})})),s}_findMatches({key:e,value:t,searcher:i}){if(!ae(t))return[];let n=[];if(se(t))t.forEach((({v:t,i:s,n:o})=>{if(!ae(t))return;const{isMatch:r,score:c,indices:a}=i.searchIn(t);r&&n.push({score:c,key:e,value:t,idx:s,norm:o,indices:a})}));else{const{v:s,n:o}=t,{isMatch:r,score:c,indices:a}=i.searchIn(s);r&&n.push({score:c,key:e,value:s,norm:o,indices:a})}return n}}qe.version="7.0.0",qe.createIndex=Ce,qe.parseIndex=function(e,{getFn:t=ye.getFn,fieldNormWeight:i=ye.fieldNormWeight}={}){const{keys:n,records:s}=e,o=new Ee({getFn:t,fieldNormWeight:i});return o.setKeys(n),o.setIndexRecords(s),o},qe.config=ye,qe.parseQuery=Ve,function(...e){De.push(...e)}(class{constructor(e,{isCaseSensitive:t=ye.isCaseSensitive,includeMatches:i=ye.includeMatches,minMatchCharLength:n=ye.minMatchCharLength,ignoreLocation:s=ye.ignoreLocation,findAllMatches:o=ye.findAllMatches,location:r=ye.location,threshold:c=ye.threshold,distance:a=ye.distance}={}){this.query=null,this.options={isCaseSensitive:t,includeMatches:i,minMatchCharLength:n,findAllMatches:o,ignoreLocation:s,location:r,threshold:c,distance:a},this.pattern=t?e:e.toLowerCase(),this.query=function(e,t={}){return e.split("|").map((e=>{let i=e.trim().split(ke).filter((e=>e&&!!e.trim())),n=[];for(let e=0,s=i.length;e element"),this)},e.prototype.removeChoice=function(e){var t=this._store.choices.find((function(t){return t.value===e}));return t?(this._clearNotice(),this._store.dispatch(b(t)),this._searcher.reset(),t.selected&&this.passedElement.triggerEvent(m,this._getChoiceForOutput(t)),this):this},e.prototype.clearChoices=function(){var e=this;return this._store.withTxn((function(){e._store.choices.forEach((function(t){t.selected||e._store.dispatch(b(t))}))})),this._searcher.reset(),this},e.prototype.clearStore=function(e){return void 0===e&&(e=!0),this._stopSearch(),e&&this.passedElement.element.replaceChildren(""),this.itemList.element.replaceChildren(""),this.choiceList.element.replaceChildren(""),this._store.reset(),this._lastAddedChoiceId=0,this._lastAddedGroupId=0,this._searcher.reset(),this},e.prototype.clearInput=function(){return this.input.clear(!this._isSelectOneElement),this._stopSearch(),this},e.prototype._validateConfig=function(){var e,t,i,n=this.config,s=(e=z,t=Object.keys(n).sort(),i=Object.keys(e).sort(),t.filter((function(e){return i.indexOf(e)<0})));s.length&&console.warn("Unknown config option(s) passed",s.join(", ")),n.allowHTML&&n.allowHtmlUserInput&&(n.addItems&&console.warn("Warning: allowHTML/allowHtmlUserInput/addItems all being true is strongly not recommended and may lead to XSS attacks"),n.addChoices&&console.warn("Warning: allowHTML/allowHtmlUserInput/addChoices all being true is strongly not recommended and may lead to XSS attacks"))},e.prototype._render=function(e){void 0===e&&(e={choices:!0,groups:!0,items:!0}),this._store.inTxn()||(this._isSelectElement&&(e.choices||e.groups)&&this._renderChoices(),e.items&&this._renderItems())},e.prototype._renderChoices=function(){var e=this;if(this._canAddItems()){var t=this.config,i=this._isSearching,n=this._store,s=n.activeGroups,o=n.activeChoices,r=0;if(i&&t.searchResultLimit>0?r=t.searchResultLimit:t.renderChoiceLimit>0&&(r=t.renderChoiceLimit),this._isSelectElement){var c=o.filter((function(e){return!e.element}));c.length&&this.passedElement.addOptions(c)}var a=document.createDocumentFragment(),h=function(e){return e.filter((function(e){return!e.placeholder&&(i?!!e.rank:t.renderSelectedChoices||!e.selected)}))},l=!1,u=function(n,s,o){i?n.sort(T):t.shouldSort&&n.sort(t.sorter);var c=n.length;c=!s&&r&&c>r?r:c,c--,n.every((function(n,s){var r=n.choiceEl||e._templates.choice(t,n,t.itemSelectText,o);return n.choiceEl=r,a.appendChild(r),n.disabled||!i&&n.selected||(l=!0),s1){var h=i.querySelector(k(n.classNames.placeholder));h&&h.remove()}else a||(c=!0,r(W({selected:!0,value:"",label:n.placeholderValue||"",placeholder:!0},!1)))}c&&(i.append(s),n.shouldSortItems&&!this._isSelectOneElement&&(t.sort(n.sorter),t.forEach((function(e){var t=o(e);t&&(t.remove(),s.append(t))})),i.append(s))),this._isTextElement&&(this.passedElement.value=t.map((function(e){return e.value})).join(n.delimiter))},e.prototype._displayNotice=function(e,t,i){void 0===i&&(i=!0);var n=this._notice;n&&(n.type===t&&n.text===e||n.type===ee&&(t===Z||t===Y))?i&&this.showDropdown(!0):(this._clearNotice(),this._notice=e?{text:e,type:t}:void 0,this._renderNotice(),i&&e&&this.showDropdown(!0))},e.prototype._clearNotice=function(){if(this._notice){var e=this.choiceList.element.querySelector(k(this.config.classNames.notice));e&&e.remove(),this._notice=void 0}},e.prototype._renderNotice=function(e){var t=this._notice;if(t){var i=this._templates.notice(this.config,t.text,t.type);e?e.append(i):this.choiceList.prepend(i)}},e.prototype._getChoiceForOutput=function(e,t){return{id:e.id,highlighted:e.highlighted,labelClass:e.labelClass,labelDescription:e.labelDescription,customProperties:e.customProperties,disabled:e.disabled,active:e.active,label:e.label,placeholder:e.placeholder,value:e.value,groupValue:e.group?e.group.label:void 0,element:e.element,keyCode:t}},e.prototype._triggerChange=function(e){null!=e&&this.passedElement.triggerEvent("change",{value:e})},e.prototype._handleButtonAction=function(e){var t=this,i=this._store.items;if(i.length&&this.config.removeItems&&this.config.removeItemButton){var n=e&&Qe(e.parentElement),s=n&&i.find((function(e){return e.id===n}));s&&this._store.withTxn((function(){if(t._removeItem(s),t._triggerChange(s.value),t._isSelectOneElement&&!t._hasNonChoicePlaceholder){var e=t._store.choices.reverse().find((function(e){return!e.disabled&&e.placeholder}));e&&(t._addItem(e),t.unhighlightAll(),e.value&&t._triggerChange(e.value))}}))}},e.prototype._handleItemAction=function(e,t){var i=this;void 0===t&&(t=!1);var n=this._store.items;if(n.length&&this.config.removeItems&&!this._isSelectOneElement){var s=Qe(e);s&&(n.forEach((function(e){e.id!==s||e.highlighted?!t&&e.highlighted&&i.unhighlightItem(e):i.highlightItem(e)})),this.input.focus())}},e.prototype._handleChoiceAction=function(e){var t=this,i=Qe(e),n=i&&this._store.getChoiceById(i);if(!n||n.disabled)return!1;var s=this.dropdown.isActive;if(!n.selected){if(!this._canAddItems())return!0;this._store.withTxn((function(){t._addItem(n,!0,!0),t.clearInput(),t.unhighlightAll()})),this._triggerChange(n.value)}return s&&this.config.closeDropdownOnSelect&&(this.hideDropdown(!0),this.containerOuter.element.focus()),!0},e.prototype._handleBackspace=function(e){var t=this.config;if(t.removeItems&&e.length){var i=e[e.length-1],n=e.some((function(e){return e.highlighted}));t.editItems&&!n&&i?(this.input.value=i.value,this.input.setWidth(),this._removeItem(i),this._triggerChange(i.value)):(n||this.highlightItem(i,!1),this.removeHighlightedItems(!0))}},e.prototype._loadChoices=function(){var e,t=this.config;if(this._isTextElement){if(this._presetChoices=t.items.map((function(e){return W(e,!1)})),this.passedElement.value){var i=this.passedElement.value.split(t.delimiter).map((function(e){return W(e,!1)}));this._presetChoices=this._presetChoices.concat(i)}this._presetChoices.forEach((function(e){e.selected=!0}))}else if(this._isSelectElement){this._presetChoices=t.choices.map((function(e){return W(e,!0)}));var n=this.passedElement.optionsAsChoices();n&&(e=this._presetChoices).push.apply(e,n)}},e.prototype._handleLoadingState=function(e){void 0===e&&(e=!0);var t=this.itemList.element;e?(this.disable(),this.containerOuter.addLoadingState(),this._isSelectOneElement?t.replaceChildren(this._templates.placeholder(this.config,this.config.loadingText)):this.input.placeholder=this.config.loadingText):(this.enable(),this.containerOuter.removeLoadingState(),this._isSelectOneElement?(t.replaceChildren(""),this._render()):this.input.placeholder=this._placeholderValue||"")},e.prototype._handleSearch=function(e){if(this.input.isFocussed)if(null!=e&&e.length>=this.config.searchFloor){var t=this.config.searchChoices?this._searchChoices(e):0;null!==t&&this.passedElement.triggerEvent(f,{value:e,resultCount:t})}else this._store.choices.some((function(e){return!e.active}))&&this._stopSearch()},e.prototype._canAddItems=function(){var e=this.config,t=e.maxItemCount,i=e.maxItemText;return!(!e.singleModeForMultiSelect&&t>0&&t<=this._store.items.length&&(this.choiceList.element.replaceChildren(""),this._displayNotice("function"==typeof i?i(t):i,ee),1))},e.prototype._canCreateItem=function(e){var t=this.config,i=!0,n="";if(i&&"function"==typeof t.addItemFilter&&!t.addItemFilter(e)&&(i=!1,n=x(t.customAddItemText,e)),i){var s=this._store.choices.find((function(i){return t.valueComparer(i.value,e)}));if(this._isSelectElement){if(s)return this._displayNotice("",ee),!1}else this._isTextElement&&!t.duplicateItemsAllowed&&s&&(i=!1,n=x(t.uniqueItemText,e))}return i&&(n=x(t.addItemText,e)),n&&this._displayNotice(n,ee),i},e.prototype._searchChoices=function(e){var t=e.trim().replace(/\s{2,}/," ");if(!t.length||t===this._currentValue)return null;var i=this._searcher;i.isEmptyIndex()&&i.index(this._store.searchableChoices);var n=i.search(t);this._currentValue=t,this._highlightPosition=0,this._isSearching=!0;var s=this._notice;return(s&&s.type)!==ee&&(n.length?this._clearNotice():this._displayNotice(A(this.config.noResultsText),Z)),this._store.dispatch(function(e){return{type:c,results:e}}(n)),n.length},e.prototype._stopSearch=function(){this._isSearching&&(this._currentValue="",this._isSearching=!1,this._clearNotice(),this._store.dispatch({type:a,active:!0}),this.passedElement.triggerEvent(f,{value:"",resultCount:0}))},e.prototype._addEventListeners=function(){var e=this._docRoot,t=this.containerOuter.element,i=this.input.element;e.addEventListener("touchend",this._onTouchEnd,!0),t.addEventListener("keydown",this._onKeyDown,!0),t.addEventListener("mousedown",this._onMouseDown,!0),e.addEventListener("click",this._onClick,{passive:!0}),e.addEventListener("touchmove",this._onTouchMove,{passive:!0}),this.dropdown.element.addEventListener("mouseover",this._onMouseOver,{passive:!0}),this._isSelectOneElement&&(t.addEventListener("focus",this._onFocus,{passive:!0}),t.addEventListener("blur",this._onBlur,{passive:!0})),i.addEventListener("keyup",this._onKeyUp,{passive:!0}),i.addEventListener("input",this._onInput,{passive:!0}),i.addEventListener("focus",this._onFocus,{passive:!0}),i.addEventListener("blur",this._onBlur,{passive:!0}),i.form&&i.form.addEventListener("reset",this._onFormReset,{passive:!0}),this.input.addEventListeners()},e.prototype._removeEventListeners=function(){var e=this._docRoot,t=this.containerOuter.element,i=this.input.element;e.removeEventListener("touchend",this._onTouchEnd,!0),t.removeEventListener("keydown",this._onKeyDown,!0),t.removeEventListener("mousedown",this._onMouseDown,!0),e.removeEventListener("click",this._onClick),e.removeEventListener("touchmove",this._onTouchMove),this.dropdown.element.removeEventListener("mouseover",this._onMouseOver),this._isSelectOneElement&&(t.removeEventListener("focus",this._onFocus),t.removeEventListener("blur",this._onBlur)),i.removeEventListener("keyup",this._onKeyUp),i.removeEventListener("input",this._onInput),i.removeEventListener("focus",this._onFocus),i.removeEventListener("blur",this._onBlur),i.form&&i.form.removeEventListener("reset",this._onFormReset),this.input.removeEventListeners()},e.prototype._onKeyDown=function(e){var t=e.keyCode,i=this.dropdown.isActive,n=1===e.key.length||2===e.key.length&&e.key.charCodeAt(0)>=55296||"Unidentified"===e.key;switch(this._isTextElement||i||(this.showDropdown(),!this.input.isFocussed&&n&&(this.input.value+=e.key," "===e.key&&e.preventDefault())),t){case 65:return this._onSelectKey(e,this.itemList.element.hasChildNodes());case 13:return this._onEnterKey(e,i);case 27:return this._onEscapeKey(e,i);case 38:case 33:case 40:case 34:return this._onDirectionKey(e,i);case 8:case 46:return this._onDeleteKey(e,this._store.items,this.input.isFocussed)}},e.prototype._onKeyUp=function(){this._canSearch=this.config.searchEnabled},e.prototype._onInput=function(){var e=this.input.value;e?this._canAddItems()&&(this._canSearch&&this._handleSearch(e),this._canAddUserChoices&&(this._canCreateItem(e),this._isSelectElement&&(this._highlightPosition=0,this._highlightChoice()))):this._isTextElement?this.hideDropdown(!0):this._stopSearch()},e.prototype._onSelectKey=function(e,t){(e.ctrlKey||e.metaKey)&&t&&(this._canSearch=!1,this.config.removeItems&&!this.input.value&&this.input.element===document.activeElement&&this.highlightAll())},e.prototype._onEnterKey=function(e,t){var i=this,n=this.input.value,s=e.target;if(e.preventDefault(),s&&s.hasAttribute("data-button"))this._handleButtonAction(s);else if(t){var o=this.dropdown.element.querySelector(k(this.config.classNames.highlightedState));if(!o||!this._handleChoiceAction(o))if(s&&n){if(this._canAddItems()){var r=!1;this._store.withTxn((function(){if(!(r=i._findAndSelectChoiceByValue(n,!0))){if(!i._canAddUserChoices)return;if(!i._canCreateItem(n))return;var e=w(n),t=i.config.allowHtmlUserInput||e===n?n:{escaped:e,raw:n};i._addChoice(W({value:t,label:t,selected:!0},!1),!0,!0),r=!0}i.clearInput(),i.unhighlightAll()})),r&&(this._triggerChange(n),this.config.closeDropdownOnSelect&&this.hideDropdown(!0))}}else this.hideDropdown(!0)}else(this._isSelectElement||this._notice)&&this.showDropdown()},e.prototype._onEscapeKey=function(e,t){t&&(e.stopPropagation(),this.hideDropdown(!0),this.containerOuter.element.focus())},e.prototype._onDirectionKey=function(e,t){var i,n,s,o=e.keyCode;if(t||this._isSelectOneElement){this.showDropdown(),this._canSearch=!1;var r=40===o||34===o?1:-1,c=void 0;if(e.metaKey||34===o||33===o)c=this.dropdown.element.querySelector(r>0?"".concat(Ye,":last-of-type"):Ye);else{var a=this.dropdown.element.querySelector(k(this.config.classNames.highlightedState));c=a?function(e,t,i){void 0===i&&(i=1);for(var n="".concat(i>0?"next":"previous","ElementSibling"),s=e[n];s;){if(s.matches(t))return s;s=s[n]}return null}(a,Ye,r):this.dropdown.element.querySelector(Ye)}c&&(i=c,n=this.choiceList.element,void 0===(s=r)&&(s=1),(s>0?n.scrollTop+n.offsetHeight>=i.offsetTop+i.offsetHeight:i.offsetTop>=n.scrollTop)||this.choiceList.scrollToChildElement(c,r),this._highlightChoice(c)),e.preventDefault()}},e.prototype._onDeleteKey=function(e,t,i){this._isSelectOneElement||e.target.value||!i||(this._handleBackspace(t),e.preventDefault())},e.prototype._onTouchMove=function(){this._wasTap&&(this._wasTap=!1)},e.prototype._onTouchEnd=function(e){var t=(e||e.touches[0]).target;this._wasTap&&this.containerOuter.element.contains(t)&&((t===this.containerOuter.element||t===this.containerInner.element)&&(this._isTextElement?this.input.focus():this._isSelectMultipleElement&&this.showDropdown()),e.stopPropagation()),this._wasTap=!0},e.prototype._onMouseDown=function(e){var t=e.target;if(t instanceof HTMLElement){if(Je&&this.choiceList.element.contains(t)){var i=this.choiceList.element.firstElementChild;this._isScrollingOnIe="ltr"===this._direction?e.offsetX>=i.offsetWidth:e.offsetXthis._highlightPosition?t[this._highlightPosition]:t[t.length-1])||(i=t[0]),F(i,n),i.setAttribute("aria-selected","true"),this.passedElement.triggerEvent("highlightChoice",{el:i}),this.dropdown.isActive&&(this.input.setActiveDescendant(i.id),this.containerOuter.setActiveDescendant(i.id))}},e.prototype._addItem=function(e,t,i){if(void 0===t&&(t=!0),void 0===i&&(i=!1),!e.id)throw new TypeError("item.id must be set before _addItem is called for a choice/item");(this.config.singleModeForMultiSelect||this._isSelectOneElement)&&this.removeActiveItems(e.id),this._store.dispatch(function(e){return{type:u,item:e}}(e)),t&&(this.passedElement.triggerEvent("addItem",this._getChoiceForOutput(e)),i&&this.passedElement.triggerEvent("choice",this._getChoiceForOutput(e)))},e.prototype._removeItem=function(e){e.id&&(this._store.dispatch(E(e)),this.passedElement.triggerEvent(m,this._getChoiceForOutput(e)))},e.prototype._addChoice=function(e,t,i){if(void 0===t&&(t=!0),void 0===i&&(i=!1),e.id)throw new TypeError("Can not re-add a choice which has already been added");var n=this.config;if(!this._isSelectElement&&n.duplicateItemsAllowed||!this._store.choices.find((function(t){return n.valueComparer(t.value,e.value)}))){this._lastAddedChoiceId++,e.id=this._lastAddedChoiceId,e.elementId="".concat(this._baseId,"-").concat(this._idNames.itemChoice,"-").concat(e.id);var s=n.prependValue,r=n.appendValue;s&&(e.value=s+e.value),r&&(e.value+=r.toString()),(s||r)&&e.element&&(e.element.value=e.value),this._clearNotice(),this._store.dispatch(function(e){return{type:o,choice:e}}(e)),e.selected&&this._addItem(e,t,i)}},e.prototype._addGroup=function(e,t){var i=this;if(void 0===t&&(t=!0),e.id)throw new TypeError("Can not re-add a group which has already been added");this._store.dispatch(function(e){return{type:l,group:e}}(e)),e.choices&&(this._lastAddedGroupId++,e.id=this._lastAddedGroupId,e.choices.forEach((function(n){n.group=e,e.disabled&&(n.disabled=!0),i._addChoice(n,t)})))},e.prototype._createTemplates=function(){var e=this,t=this.config.callbackOnCreateTemplates,i={};"function"==typeof t&&(i=t.call(this,I,L,N));var n={};Object.keys(this._templates).forEach((function(t){n[t]=t in i?i[t].bind(e):e._templates[t].bind(e)})),this._templates=n},e.prototype._createElements=function(){var e=this._templates,t=this.config,i=this._isSelectOneElement,n=t.position,s=t.classNames,o=this._elementType;this.containerOuter=new R({element:e.containerOuter(t,this._direction,this._isSelectElement,i,t.searchEnabled,o,t.labelId),classNames:s,type:o,position:n}),this.containerInner=new R({element:e.containerInner(t),classNames:s,type:o,position:n}),this.input=new K({element:e.input(t,this._placeholderValue),classNames:s,type:o,preventPaste:!t.paste}),this.choiceList=new B({element:e.choiceList(t,i)}),this.itemList=new B({element:e.itemList(t,i)}),this.dropdown=new j({element:e.dropdown(t),classNames:s,type:o})},e.prototype._createStructure=function(){var e=this,t=e.containerInner,i=e.containerOuter,n=e.passedElement,s=this.dropdown.element;n.conceal(),t.wrap(n.element),i.wrap(t.element),this._isSelectOneElement?this.input.placeholder=this.config.searchPlaceholderValue||"":(this._placeholderValue&&(this.input.placeholder=this._placeholderValue),this.input.setWidth()),i.element.appendChild(t.element),i.element.appendChild(s),t.element.appendChild(this.itemList.element),s.appendChild(this.choiceList.element),this._isSelectOneElement?this.config.searchEnabled&&s.insertBefore(this.input.element,s.firstChild):t.element.appendChild(this.input.element),this._highlightPosition=0,this._isSearching=!1},e.prototype._initStore=function(){var e=this;this._store.subscribe(this._render).withTxn((function(){e._addPredefinedChoices(e._presetChoices,e._isSelectOneElement&&!e._hasNonChoicePlaceholder,!1)})),(!this._store.choices.length||this._isSelectOneElement&&this._hasNonChoicePlaceholder)&&this._render()},e.prototype._addPredefinedChoices=function(e,t,i){var n=this;void 0===t&&(t=!1),void 0===i&&(i=!0),t&&-1===e.findIndex((function(e){return e.selected}))&&e.some((function(e){return!e.disabled&&!("choices"in e)&&(e.selected=!0,!0)})),e.forEach((function(e){"choices"in e?n._isSelectElement&&n._addGroup(e,i):n._addChoice(e,i)}))},e.prototype._findAndSelectChoiceByValue=function(e,t){var i=this;void 0===t&&(t=!1);var n=this._store.choices.find((function(t){return i.config.valueComparer(t.value,e)}));return!(!n||n.disabled||n.selected||(this._addItem(n,!0,t),0))},e.prototype._generatePlaceholderValue=function(){var e=this.config;if(!e.placeholder)return null;if(this._hasNonChoicePlaceholder)return e.placeholderValue;if(this._isSelectElement){var t=this.passedElement.placeholderOption;return t?t.text:null}return null},e.prototype._warnChoicesInitFailed=function(e){if(!this.config.silent){if(!this.initialised)throw new TypeError("".concat(e," called on a non-initialised instance of Choices"));if(!this.initialisedOK)throw new TypeError("".concat(e," called for an element which has multiple instances of Choices initialised on it"))}},e.version="11.0.2",e}()})); diff --git a/static/js/htmx-response-targets.js b/static/js/htmx-response-targets.js new file mode 100644 index 0000000..dd6fd41 --- /dev/null +++ b/static/js/htmx-response-targets.js @@ -0,0 +1,130 @@ +(function(){ + + /** @type {import("../htmx").HtmxInternalApi} */ + var api; + + var attrPrefix = 'hx-target-'; + + // IE11 doesn't support string.startsWith + function startsWith(str, prefix) { + return str.substring(0, prefix.length) === prefix + } + + /** + * @param {HTMLElement} elt + * @param {number} respCode + * @returns {HTMLElement | null} + */ + function getRespCodeTarget(elt, respCodeNumber) { + if (!elt || !respCodeNumber) return null; + + var respCode = respCodeNumber.toString(); + + // '*' is the original syntax, as the obvious character for a wildcard. + // The 'x' alternative was added for maximum compatibility with HTML + // templating engines, due to ambiguity around which characters are + // supported in HTML attributes. + // + // Start with the most specific possible attribute and generalize from + // there. + var attrPossibilities = [ + respCode, + + respCode.substr(0, 2) + '*', + respCode.substr(0, 2) + 'x', + + respCode.substr(0, 1) + '*', + respCode.substr(0, 1) + 'x', + respCode.substr(0, 1) + '**', + respCode.substr(0, 1) + 'xx', + + '*', + 'x', + '***', + 'xxx', + ]; + if (startsWith(respCode, '4') || startsWith(respCode, '5')) { + attrPossibilities.push('error'); + } + + for (var i = 0; i < attrPossibilities.length; i++) { + var attr = attrPrefix + attrPossibilities[i]; + var attrValue = api.getClosestAttributeValue(elt, attr); + if (attrValue) { + if (attrValue === "this") { + return api.findThisElement(elt, attr); + } else { + return api.querySelectorExt(elt, attrValue); + } + } + } + + return null; + } + + /** @param {Event} evt */ + function handleErrorFlag(evt) { + if (evt.detail.isError) { + if (htmx.config.responseTargetUnsetsError) { + evt.detail.isError = false; + } + } else if (htmx.config.responseTargetSetsError) { + evt.detail.isError = true; + } + } + + htmx.defineExtension('response-targets', { + + /** @param {import("../htmx").HtmxInternalApi} apiRef */ + init: function (apiRef) { + api = apiRef; + + if (htmx.config.responseTargetUnsetsError === undefined) { + htmx.config.responseTargetUnsetsError = true; + } + if (htmx.config.responseTargetSetsError === undefined) { + htmx.config.responseTargetSetsError = false; + } + if (htmx.config.responseTargetPrefersExisting === undefined) { + htmx.config.responseTargetPrefersExisting = false; + } + if (htmx.config.responseTargetPrefersRetargetHeader === undefined) { + htmx.config.responseTargetPrefersRetargetHeader = true; + } + }, + + /** + * @param {string} name + * @param {Event} evt + */ + onEvent: function (name, evt) { + if (name === "htmx:beforeSwap" && + evt.detail.xhr && + evt.detail.xhr.status !== 200) { + if (evt.detail.target) { + if (htmx.config.responseTargetPrefersExisting) { + evt.detail.shouldSwap = true; + handleErrorFlag(evt); + return true; + } + if (htmx.config.responseTargetPrefersRetargetHeader && + evt.detail.xhr.getAllResponseHeaders().match(/HX-Retarget:/i)) { + evt.detail.shouldSwap = true; + handleErrorFlag(evt); + return true; + } + } + if (!evt.detail.requestConfig) { + return true; + } + var target = getRespCodeTarget(evt.detail.requestConfig.elt, evt.detail.xhr.status); + if (target) { + handleErrorFlag(evt); + evt.detail.shouldSwap = true; + evt.detail.target = target; + } + return true; + } + } + }); +})(); diff --git a/static/js/htmx.js b/static/js/htmx.js new file mode 100644 index 0000000..423cf01 --- /dev/null +++ b/static/js/htmx.js @@ -0,0 +1 @@ +var htmx=function(){"use strict";const Q={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(e,t){const n=cn(e,t||"post");return n.values},remove:null,addClass:null,removeClass:null,toggleClass:null,takeClass:null,swap:null,defineExtension:null,removeExtension:null,logAll:null,logNone:null,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,allowScriptTags:true,inlineScriptNonce:"",inlineStyleNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",scrollBehavior:"instant",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false,methodsThatUseUrlParams:["get","delete"],selfRequestsOnly:true,ignoreTitle:false,scrollIntoViewOnBoost:true,triggerSpecsCache:null,disableInheritance:false,responseHandling:[{code:"204",swap:false},{code:"[23]..",swap:true},{code:"[45]..",swap:false,error:true}],allowNestedOobSwaps:true},parseInterval:null,_:null,version:"2.0.3"};Q.onLoad=j;Q.process=kt;Q.on=ye;Q.off=be;Q.trigger=de;Q.ajax=Rn;Q.find=r;Q.findAll=x;Q.closest=g;Q.remove=z;Q.addClass=K;Q.removeClass=G;Q.toggleClass=W;Q.takeClass=Z;Q.swap=$e;Q.defineExtension=Fn;Q.removeExtension=Bn;Q.logAll=V;Q.logNone=_;Q.parseInterval=h;Q._=e;const n={addTriggerHandler:St,bodyContains:le,canAccessLocalStorage:B,findThisElement:Se,filterValues:dn,swap:$e,hasAttribute:s,getAttributeValue:te,getClosestAttributeValue:re,getClosestMatch:i,getExpressionVars:En,getHeaders:fn,getInputValues:cn,getInternalData:ie,getSwapSpecification:gn,getTriggerSpecs:st,getTarget:Ee,makeFragment:P,mergeObjects:ce,makeSettleInfo:xn,oobSwap:He,querySelectorExt:ae,settleImmediately:Kt,shouldCancel:dt,triggerEvent:de,triggerErrorEvent:fe,withExtensions:Ft};const o=["get","post","put","delete","patch"];const R=o.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");function h(e){if(e==undefined){return undefined}let t=NaN;if(e.slice(-2)=="ms"){t=parseFloat(e.slice(0,-2))}else if(e.slice(-1)=="s"){t=parseFloat(e.slice(0,-1))*1e3}else if(e.slice(-1)=="m"){t=parseFloat(e.slice(0,-1))*1e3*60}else{t=parseFloat(e)}return isNaN(t)?undefined:t}function ee(e,t){return e instanceof Element&&e.getAttribute(t)}function s(e,t){return!!e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function te(e,t){return ee(e,t)||ee(e,"data-"+t)}function c(e){const t=e.parentElement;if(!t&&e.parentNode instanceof ShadowRoot)return e.parentNode;return t}function ne(){return document}function m(e,t){return e.getRootNode?e.getRootNode({composed:t}):ne()}function i(e,t){while(e&&!t(e)){e=c(e)}return e||null}function H(e,t,n){const r=te(t,n);const o=te(t,"hx-disinherit");var i=te(t,"hx-inherit");if(e!==t){if(Q.config.disableInheritance){if(i&&(i==="*"||i.split(" ").indexOf(n)>=0)){return r}else{return null}}if(o&&(o==="*"||o.split(" ").indexOf(n)>=0)){return"unset"}}return r}function re(t,n){let r=null;i(t,function(e){return!!(r=H(t,ue(e),n))});if(r!=="unset"){return r}}function d(e,t){const n=e instanceof Element&&(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector);return!!n&&n.call(e,t)}function T(e){const t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;const n=t.exec(e);if(n){return n[1].toLowerCase()}else{return""}}function q(e){const t=new DOMParser;return t.parseFromString(e,"text/html")}function L(e,t){while(t.childNodes.length>0){e.append(t.childNodes[0])}}function N(e){const t=ne().createElement("script");se(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(Q.config.inlineScriptNonce){t.nonce=Q.config.inlineScriptNonce}return t}function A(e){return e.matches("script")&&(e.type==="text/javascript"||e.type==="module"||e.type==="")}function I(e){Array.from(e.querySelectorAll("script")).forEach(e=>{if(A(e)){const t=N(e);const n=e.parentNode;try{n.insertBefore(t,e)}catch(e){C(e)}finally{e.remove()}}})}function P(e){const t=e.replace(/]*)?>[\s\S]*?<\/head>/i,"");const n=T(t);let r;if(n==="html"){r=new DocumentFragment;const i=q(e);L(r,i.body);r.title=i.title}else if(n==="body"){r=new DocumentFragment;const i=q(t);L(r,i.body);r.title=i.title}else{const i=q('");r=i.querySelector("template").content;r.title=i.title;var o=r.querySelector("title");if(o&&o.parentNode===r){o.remove();r.title=o.innerText}}if(r){if(Q.config.allowScriptTags){I(r)}else{r.querySelectorAll("script").forEach(e=>e.remove())}}return r}function oe(e){if(e){e()}}function t(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function k(e){return typeof e==="function"}function D(e){return t(e,"Object")}function ie(e){const t="htmx-internal-data";let n=e[t];if(!n){n=e[t]={}}return n}function M(t){const n=[];if(t){for(let e=0;e=0}function le(e){const t=e.getRootNode&&e.getRootNode();if(t&&t instanceof window.ShadowRoot){return ne().body.contains(t.host)}else{return ne().body.contains(e)}}function F(e){return e.trim().split(/\s+/)}function ce(e,t){for(const n in t){if(t.hasOwnProperty(n)){e[n]=t[n]}}return e}function S(e){try{return JSON.parse(e)}catch(e){C(e);return null}}function B(){const e="htmx:localStorageTest";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function U(t){try{const e=new URL(t);if(e){t=e.pathname+e.search}if(!/^\/$/.test(t)){t=t.replace(/\/+$/,"")}return t}catch(e){return t}}function e(e){return vn(ne().body,function(){return eval(e)})}function j(t){const e=Q.on("htmx:load",function(e){t(e.detail.elt)});return e}function V(){Q.logger=function(e,t,n){if(console){console.log(t,e,n)}}}function _(){Q.logger=null}function r(e,t){if(typeof e!=="string"){return e.querySelector(t)}else{return r(ne(),e)}}function x(e,t){if(typeof e!=="string"){return e.querySelectorAll(t)}else{return x(ne(),e)}}function E(){return window}function z(e,t){e=y(e);if(t){E().setTimeout(function(){z(e);e=null},t)}else{c(e).removeChild(e)}}function ue(e){return e instanceof Element?e:null}function $(e){return e instanceof HTMLElement?e:null}function J(e){return typeof e==="string"?e:null}function f(e){return e instanceof Element||e instanceof Document||e instanceof DocumentFragment?e:null}function K(e,t,n){e=ue(y(e));if(!e){return}if(n){E().setTimeout(function(){K(e,t);e=null},n)}else{e.classList&&e.classList.add(t)}}function G(e,t,n){let r=ue(y(e));if(!r){return}if(n){E().setTimeout(function(){G(r,t);r=null},n)}else{if(r.classList){r.classList.remove(t);if(r.classList.length===0){r.removeAttribute("class")}}}}function W(e,t){e=y(e);e.classList.toggle(t)}function Z(e,t){e=y(e);se(e.parentElement.children,function(e){G(e,t)});K(ue(e),t)}function g(e,t){e=ue(y(e));if(e&&e.closest){return e.closest(t)}else{do{if(e==null||d(e,t)){return e}}while(e=e&&ue(c(e)));return null}}function l(e,t){return e.substring(0,t.length)===t}function Y(e,t){return e.substring(e.length-t.length)===t}function ge(e){const t=e.trim();if(l(t,"<")&&Y(t,"/>")){return t.substring(1,t.length-2)}else{return t}}function p(e,t,n){e=y(e);if(t.indexOf("closest ")===0){return[g(ue(e),ge(t.substr(8)))]}else if(t.indexOf("find ")===0){return[r(f(e),ge(t.substr(5)))]}else if(t==="next"){return[ue(e).nextElementSibling]}else if(t.indexOf("next ")===0){return[pe(e,ge(t.substr(5)),!!n)]}else if(t==="previous"){return[ue(e).previousElementSibling]}else if(t.indexOf("previous ")===0){return[me(e,ge(t.substr(9)),!!n)]}else if(t==="document"){return[document]}else if(t==="window"){return[window]}else if(t==="body"){return[document.body]}else if(t==="root"){return[m(e,!!n)]}else if(t==="host"){return[e.getRootNode().host]}else if(t.indexOf("global ")===0){return p(e,t.slice(7),true)}else{return M(f(m(e,!!n)).querySelectorAll(ge(t)))}}var pe=function(t,e,n){const r=f(m(t,n)).querySelectorAll(e);for(let e=0;e=0;e--){const o=r[e];if(o.compareDocumentPosition(t)===Node.DOCUMENT_POSITION_FOLLOWING){return o}}};function ae(e,t){if(typeof e!=="string"){return p(e,t)[0]}else{return p(ne().body,e)[0]}}function y(e,t){if(typeof e==="string"){return r(f(t)||document,e)}else{return e}}function xe(e,t,n,r){if(k(t)){return{target:ne().body,event:J(e),listener:t,options:n}}else{return{target:y(e),event:J(t),listener:n,options:r}}}function ye(t,n,r,o){Vn(function(){const e=xe(t,n,r,o);e.target.addEventListener(e.event,e.listener,e.options)});const e=k(n);return e?n:r}function be(t,n,r){Vn(function(){const e=xe(t,n,r);e.target.removeEventListener(e.event,e.listener)});return k(n)?n:r}const ve=ne().createElement("output");function we(e,t){const n=re(e,t);if(n){if(n==="this"){return[Se(e,t)]}else{const r=p(e,n);if(r.length===0){C('The selector "'+n+'" on '+t+" returned no matches!");return[ve]}else{return r}}}}function Se(e,t){return ue(i(e,function(e){return te(ue(e),t)!=null}))}function Ee(e){const t=re(e,"hx-target");if(t){if(t==="this"){return Se(e,"hx-target")}else{return ae(e,t)}}else{const n=ie(e);if(n.boosted){return ne().body}else{return e}}}function Ce(t){const n=Q.config.attributesToSettle;for(let e=0;e0){s=e.substr(0,e.indexOf(":"));n=e.substr(e.indexOf(":")+1,e.length)}else{s=e}o.removeAttribute("hx-swap-oob");o.removeAttribute("data-hx-swap-oob");const r=p(t,n,false);if(r){se(r,function(e){let t;const n=o.cloneNode(true);t=ne().createDocumentFragment();t.appendChild(n);if(!Re(s,e)){t=f(n)}const r={shouldSwap:true,target:e,fragment:t};if(!de(e,"htmx:oobBeforeSwap",r))return;e=r.target;if(r.shouldSwap){qe(t);_e(s,e,e,t,i);Te()}se(i.elts,function(e){de(e,"htmx:oobAfterSwap",r)})});o.parentNode.removeChild(o)}else{o.parentNode.removeChild(o);fe(ne().body,"htmx:oobErrorNoTarget",{content:o})}return e}function Te(){const e=r("#--htmx-preserve-pantry--");if(e){for(const t of[...e.children]){const n=r("#"+t.id);n.parentNode.moveBefore(t,n);n.remove()}e.remove()}}function qe(e){se(x(e,"[hx-preserve], [data-hx-preserve]"),function(e){const t=te(e,"id");const n=ne().getElementById(t);if(n!=null){if(e.moveBefore){let e=r("#--htmx-preserve-pantry--");if(e==null){ne().body.insertAdjacentHTML("afterend","
");e=r("#--htmx-preserve-pantry--")}e.moveBefore(n,null)}else{e.parentNode.replaceChild(n,e)}}})}function Le(l,e,c){se(e.querySelectorAll("[id]"),function(t){const n=ee(t,"id");if(n&&n.length>0){const r=n.replace("'","\\'");const o=t.tagName.replace(":","\\:");const e=f(l);const i=e&&e.querySelector(o+"[id='"+r+"']");if(i&&i!==e){const s=t.cloneNode();Oe(t,i);c.tasks.push(function(){Oe(t,s)})}}})}function Ne(e){return function(){G(e,Q.config.addedClass);kt(ue(e));Ae(f(e));de(e,"htmx:load")}}function Ae(e){const t="[autofocus]";const n=$(d(e,t)?e:e.querySelector(t));if(n!=null){n.focus()}}function u(e,t,n,r){Le(e,n,r);while(n.childNodes.length>0){const o=n.firstChild;K(ue(o),Q.config.addedClass);e.insertBefore(o,t);if(o.nodeType!==Node.TEXT_NODE&&o.nodeType!==Node.COMMENT_NODE){r.tasks.push(Ne(o))}}}function Ie(e,t){let n=0;while(n0}function $e(e,t,r,o){if(!o){o={}}e=y(e);const i=o.contextElement?m(o.contextElement,false):ne();const n=document.activeElement;let s={};try{s={elt:n,start:n?n.selectionStart:null,end:n?n.selectionEnd:null}}catch(e){}const l=xn(e);if(r.swapStyle==="textContent"){e.textContent=t}else{let n=P(t);l.title=n.title;if(o.selectOOB){const u=o.selectOOB.split(",");for(let t=0;t0){E().setTimeout(c,r.settleDelay)}else{c()}}function Je(e,t,n){const r=e.getResponseHeader(t);if(r.indexOf("{")===0){const o=S(r);for(const i in o){if(o.hasOwnProperty(i)){let e=o[i];if(D(e)){n=e.target!==undefined?e.target:n}else{e={value:e}}de(n,i,e)}}}else{const s=r.split(",");for(let e=0;e0){const s=o[0];if(s==="]"){e--;if(e===0){if(n===null){t=t+"true"}o.shift();t+=")})";try{const l=vn(r,function(){return Function(t)()},function(){return true});l.source=t;return l}catch(e){fe(ne().body,"htmx:syntax:error",{error:e,source:t});return null}}}else if(s==="["){e++}if(tt(s,n,i)){t+="(("+i+"."+s+") ? ("+i+"."+s+") : (window."+s+"))"}else{t=t+s}n=o.shift()}}}function w(e,t){let n="";while(e.length>0&&!t.test(e[0])){n+=e.shift()}return n}function rt(e){let t;if(e.length>0&&Ye.test(e[0])){e.shift();t=w(e,Qe).trim();e.shift()}else{t=w(e,b)}return t}const ot="input, textarea, select";function it(e,t,n){const r=[];const o=et(t);do{w(o,v);const l=o.length;const c=w(o,/[,\[\s]/);if(c!==""){if(c==="every"){const u={trigger:"every"};w(o,v);u.pollInterval=h(w(o,/[,\[\s]/));w(o,v);var i=nt(e,o,"event");if(i){u.eventFilter=i}r.push(u)}else{const a={trigger:c};var i=nt(e,o,"event");if(i){a.eventFilter=i}w(o,v);while(o.length>0&&o[0]!==","){const f=o.shift();if(f==="changed"){a.changed=true}else if(f==="once"){a.once=true}else if(f==="consume"){a.consume=true}else if(f==="delay"&&o[0]===":"){o.shift();a.delay=h(w(o,b))}else if(f==="from"&&o[0]===":"){o.shift();if(Ye.test(o[0])){var s=rt(o)}else{var s=w(o,b);if(s==="closest"||s==="find"||s==="next"||s==="previous"){o.shift();const d=rt(o);if(d.length>0){s+=" "+d}}}a.from=s}else if(f==="target"&&o[0]===":"){o.shift();a.target=rt(o)}else if(f==="throttle"&&o[0]===":"){o.shift();a.throttle=h(w(o,b))}else if(f==="queue"&&o[0]===":"){o.shift();a.queue=w(o,b)}else if(f==="root"&&o[0]===":"){o.shift();a[f]=rt(o)}else if(f==="threshold"&&o[0]===":"){o.shift();a[f]=w(o,b)}else{fe(e,"htmx:syntax:error",{token:o.shift()})}w(o,v)}r.push(a)}}if(o.length===l){fe(e,"htmx:syntax:error",{token:o.shift()})}w(o,v)}while(o[0]===","&&o.shift());if(n){n[t]=r}return r}function st(e){const t=te(e,"hx-trigger");let n=[];if(t){const r=Q.config.triggerSpecsCache;n=r&&r[t]||it(e,t,r)}if(n.length>0){return n}else if(d(e,"form")){return[{trigger:"submit"}]}else if(d(e,'input[type="button"], input[type="submit"]')){return[{trigger:"click"}]}else if(d(e,ot)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function lt(e){ie(e).cancelled=true}function ct(e,t,n){const r=ie(e);r.timeout=E().setTimeout(function(){if(le(e)&&r.cancelled!==true){if(!gt(n,e,Mt("hx:poll:trigger",{triggerSpec:n,target:e}))){t(e)}ct(e,t,n)}},n.pollInterval)}function ut(e){return location.hostname===e.hostname&&ee(e,"href")&&ee(e,"href").indexOf("#")!==0}function at(e){return g(e,Q.config.disableSelector)}function ft(t,n,e){if(t instanceof HTMLAnchorElement&&ut(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"&&String(ee(t,"method")).toLowerCase()!=="dialog"){n.boosted=true;let r,o;if(t.tagName==="A"){r="get";o=ee(t,"href")}else{const i=ee(t,"method");r=i?i.toLowerCase():"get";o=ee(t,"action");if(r==="get"&&o.includes("?")){o=o.replace(/\?[^#]+/,"")}}e.forEach(function(e){pt(t,function(e,t){const n=ue(e);if(at(n)){a(n);return}he(r,o,n,t)},n,e,true)})}}function dt(e,t){const n=ue(t);if(!n){return false}if(e.type==="submit"||e.type==="click"){if(n.tagName==="FORM"){return true}if(d(n,'input[type="submit"], button')&&g(n,"form")!==null){return true}if(n instanceof HTMLAnchorElement&&n.href&&(n.getAttribute("href")==="#"||n.getAttribute("href").indexOf("#")!==0)){return true}}return false}function ht(e,t){return ie(e).boosted&&e instanceof HTMLAnchorElement&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function gt(e,t,n){const r=e.eventFilter;if(r){try{return r.call(t,n)!==true}catch(e){const o=r.source;fe(ne().body,"htmx:eventFilter:error",{error:e,source:o});return true}}return false}function pt(l,c,e,u,a){const f=ie(l);let t;if(u.from){t=p(l,u.from)}else{t=[l]}if(u.changed){if(!("lastValue"in f)){f.lastValue=new WeakMap}t.forEach(function(e){if(!f.lastValue.has(u)){f.lastValue.set(u,new WeakMap)}f.lastValue.get(u).set(e,e.value)})}se(t,function(i){const s=function(e){if(!le(l)){i.removeEventListener(u.trigger,s);return}if(ht(l,e)){return}if(a||dt(e,l)){e.preventDefault()}if(gt(u,l,e)){return}const t=ie(e);t.triggerSpec=u;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(l)<0){t.handledFor.push(l);if(u.consume){e.stopPropagation()}if(u.target&&e.target){if(!d(ue(e.target),u.target)){return}}if(u.once){if(f.triggeredOnce){return}else{f.triggeredOnce=true}}if(u.changed){const n=event.target;const r=n.value;const o=f.lastValue.get(u);if(o.has(n)&&o.get(n)===r){return}o.set(n,r)}if(f.delayed){clearTimeout(f.delayed)}if(f.throttle){return}if(u.throttle>0){if(!f.throttle){de(l,"htmx:trigger");c(l,e);f.throttle=E().setTimeout(function(){f.throttle=null},u.throttle)}}else if(u.delay>0){f.delayed=E().setTimeout(function(){de(l,"htmx:trigger");c(l,e)},u.delay)}else{de(l,"htmx:trigger");c(l,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:u.trigger,listener:s,on:i});i.addEventListener(u.trigger,s)})}let mt=false;let xt=null;function yt(){if(!xt){xt=function(){mt=true};window.addEventListener("scroll",xt);window.addEventListener("resize",xt);setInterval(function(){if(mt){mt=false;se(ne().querySelectorAll("[hx-trigger*='revealed'],[data-hx-trigger*='revealed']"),function(e){bt(e)})}},200)}}function bt(e){if(!s(e,"data-hx-revealed")&&X(e)){e.setAttribute("data-hx-revealed","true");const t=ie(e);if(t.initHash){de(e,"revealed")}else{e.addEventListener("htmx:afterProcessNode",function(){de(e,"revealed")},{once:true})}}}function vt(e,t,n,r){const o=function(){if(!n.loaded){n.loaded=true;t(e)}};if(r>0){E().setTimeout(o,r)}else{o()}}function wt(t,n,e){let i=false;se(o,function(r){if(s(t,"hx-"+r)){const o=te(t,"hx-"+r);i=true;n.path=o;n.verb=r;e.forEach(function(e){St(t,e,n,function(e,t){const n=ue(e);if(g(n,Q.config.disableSelector)){a(n);return}he(r,o,n,t)})})}});return i}function St(r,e,t,n){if(e.trigger==="revealed"){yt();pt(r,n,t,e);bt(ue(r))}else if(e.trigger==="intersect"){const o={};if(e.root){o.root=ae(r,e.root)}if(e.threshold){o.threshold=parseFloat(e.threshold)}const i=new IntersectionObserver(function(t){for(let e=0;e0){t.polling=true;ct(ue(r),n,e)}else{pt(r,n,t,e)}}function Et(e){const t=ue(e);if(!t){return false}const n=t.attributes;for(let e=0;e", "+e).join(""));return o}else{return[]}}function Tt(e){const t=g(ue(e.target),"button, input[type='submit']");const n=Lt(e);if(n){n.lastButtonClicked=t}}function qt(e){const t=Lt(e);if(t){t.lastButtonClicked=null}}function Lt(e){const t=g(ue(e.target),"button, input[type='submit']");if(!t){return}const n=y("#"+ee(t,"form"),t.getRootNode())||g(t,"form");if(!n){return}return ie(n)}function Nt(e){e.addEventListener("click",Tt);e.addEventListener("focusin",Tt);e.addEventListener("focusout",qt)}function At(t,e,n){const r=ie(t);if(!Array.isArray(r.onHandlers)){r.onHandlers=[]}let o;const i=function(e){vn(t,function(){if(at(t)){return}if(!o){o=new Function("event",n)}o.call(t,e)})};t.addEventListener(e,i);r.onHandlers.push({event:e,listener:i})}function It(t){ke(t);for(let e=0;eQ.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){fe(ne().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Vt(t){if(!B()){return null}t=U(t);const n=S(localStorage.getItem("htmx-history-cache"))||[];for(let e=0;e=200&&this.status<400){de(ne().body,"htmx:historyCacheMissLoad",i);const e=P(this.response);const t=e.querySelector("[hx-history-elt],[data-hx-history-elt]")||e;const n=Ut();const r=xn(n);kn(e.title);qe(e);Ve(n,t,r);Te();Kt(r.tasks);Bt=o;de(ne().body,"htmx:historyRestore",{path:o,cacheMiss:true,serverResponse:this.response})}else{fe(ne().body,"htmx:historyCacheMissLoadError",i)}};e.send()}function Wt(e){zt();e=e||location.pathname+location.search;const t=Vt(e);if(t){const n=P(t.content);const r=Ut();const o=xn(r);kn(t.title);qe(n);Ve(r,n,o);Te();Kt(o.tasks);E().setTimeout(function(){window.scrollTo(0,t.scroll)},0);Bt=e;de(ne().body,"htmx:historyRestore",{path:e,item:t})}else{if(Q.config.refreshOnHistoryMiss){window.location.reload(true)}else{Gt(e)}}}function Zt(e){let t=we(e,"hx-indicator");if(t==null){t=[e]}se(t,function(e){const t=ie(e);t.requestCount=(t.requestCount||0)+1;e.classList.add.call(e.classList,Q.config.requestClass)});return t}function Yt(e){let t=we(e,"hx-disabled-elt");if(t==null){t=[]}se(t,function(e){const t=ie(e);t.requestCount=(t.requestCount||0)+1;e.setAttribute("disabled","");e.setAttribute("data-disabled-by-htmx","")});return t}function Qt(e,t){se(e.concat(t),function(e){const t=ie(e);t.requestCount=(t.requestCount||1)-1});se(e,function(e){const t=ie(e);if(t.requestCount===0){e.classList.remove.call(e.classList,Q.config.requestClass)}});se(t,function(e){const t=ie(e);if(t.requestCount===0){e.removeAttribute("disabled");e.removeAttribute("data-disabled-by-htmx")}})}function en(t,n){for(let e=0;en.indexOf(e)<0)}else{e=e.filter(e=>e!==n)}r.delete(t);se(e,e=>r.append(t,e))}}function on(t,n,r,o,i){if(o==null||en(t,o)){return}else{t.push(o)}if(tn(o)){const s=ee(o,"name");let e=o.value;if(o instanceof HTMLSelectElement&&o.multiple){e=M(o.querySelectorAll("option:checked")).map(function(e){return e.value})}if(o instanceof HTMLInputElement&&o.files){e=M(o.files)}nn(s,e,n);if(i){sn(o,r)}}if(o instanceof HTMLFormElement){se(o.elements,function(e){if(t.indexOf(e)>=0){rn(e.name,e.value,n)}else{t.push(e)}if(i){sn(e,r)}});new FormData(o).forEach(function(e,t){if(e instanceof File&&e.name===""){return}nn(t,e,n)})}}function sn(e,t){const n=e;if(n.willValidate){de(n,"htmx:validation:validate");if(!n.checkValidity()){t.push({elt:n,message:n.validationMessage,validity:n.validity});de(n,"htmx:validation:failed",{message:n.validationMessage,validity:n.validity})}}}function ln(n,e){for(const t of e.keys()){n.delete(t)}e.forEach(function(e,t){n.append(t,e)});return n}function cn(e,t){const n=[];const r=new FormData;const o=new FormData;const i=[];const s=ie(e);if(s.lastButtonClicked&&!le(s.lastButtonClicked)){s.lastButtonClicked=null}let l=e instanceof HTMLFormElement&&e.noValidate!==true||te(e,"hx-validate")==="true";if(s.lastButtonClicked){l=l&&s.lastButtonClicked.formNoValidate!==true}if(t!=="get"){on(n,o,i,g(e,"form"),l)}on(n,r,i,e,l);if(s.lastButtonClicked||e.tagName==="BUTTON"||e.tagName==="INPUT"&&ee(e,"type")==="submit"){const u=s.lastButtonClicked||e;const a=ee(u,"name");nn(a,u.value,o)}const c=we(e,"hx-include");se(c,function(e){on(n,r,i,ue(e),l);if(!d(e,"form")){se(f(e).querySelectorAll(ot),function(e){on(n,r,i,e,l)})}});ln(r,o);return{errors:i,formData:r,values:Nn(r)}}function un(e,t,n){if(e!==""){e+="&"}if(String(n)==="[object Object]"){n=JSON.stringify(n)}const r=encodeURIComponent(n);e+=encodeURIComponent(t)+"="+r;return e}function an(e){e=qn(e);let n="";e.forEach(function(e,t){n=un(n,t,e)});return n}function fn(e,t,n){const r={"HX-Request":"true","HX-Trigger":ee(e,"id"),"HX-Trigger-Name":ee(e,"name"),"HX-Target":te(t,"id"),"HX-Current-URL":ne().location.href};bn(e,"hx-headers",false,r);if(n!==undefined){r["HX-Prompt"]=n}if(ie(e).boosted){r["HX-Boosted"]="true"}return r}function dn(n,e){const t=re(e,"hx-params");if(t){if(t==="none"){return new FormData}else if(t==="*"){return n}else if(t.indexOf("not ")===0){se(t.substr(4).split(","),function(e){e=e.trim();n.delete(e)});return n}else{const r=new FormData;se(t.split(","),function(t){t=t.trim();if(n.has(t)){n.getAll(t).forEach(function(e){r.append(t,e)})}});return r}}else{return n}}function hn(e){return!!ee(e,"href")&&ee(e,"href").indexOf("#")>=0}function gn(e,t){const n=t||re(e,"hx-swap");const r={swapStyle:ie(e).boosted?"innerHTML":Q.config.defaultSwapStyle,swapDelay:Q.config.defaultSwapDelay,settleDelay:Q.config.defaultSettleDelay};if(Q.config.scrollIntoViewOnBoost&&ie(e).boosted&&!hn(e)){r.show="top"}if(n){const s=F(n);if(s.length>0){for(let e=0;e0?o.join(":"):null;r.scroll=u;r.scrollTarget=i}else if(l.indexOf("show:")===0){const a=l.substr(5);var o=a.split(":");const f=o.pop();var i=o.length>0?o.join(":"):null;r.show=f;r.showTarget=i}else if(l.indexOf("focus-scroll:")===0){const d=l.substr("focus-scroll:".length);r.focusScroll=d=="true"}else if(e==0){r.swapStyle=l}else{C("Unknown modifier in hx-swap: "+l)}}}}return r}function pn(e){return re(e,"hx-encoding")==="multipart/form-data"||d(e,"form")&&ee(e,"enctype")==="multipart/form-data"}function mn(t,n,r){let o=null;Ft(n,function(e){if(o==null){o=e.encodeParameters(t,r,n)}});if(o!=null){return o}else{if(pn(n)){return ln(new FormData,qn(r))}else{return an(r)}}}function xn(e){return{tasks:[],elts:[e]}}function yn(e,t){const n=e[0];const r=e[e.length-1];if(t.scroll){var o=null;if(t.scrollTarget){o=ue(ae(n,t.scrollTarget))}if(t.scroll==="top"&&(n||o)){o=o||n;o.scrollTop=0}if(t.scroll==="bottom"&&(r||o)){o=o||r;o.scrollTop=o.scrollHeight}}if(t.show){var o=null;if(t.showTarget){let e=t.showTarget;if(t.showTarget==="window"){e="body"}o=ue(ae(n,e))}if(t.show==="top"&&(n||o)){o=o||n;o.scrollIntoView({block:"start",behavior:Q.config.scrollBehavior})}if(t.show==="bottom"&&(r||o)){o=o||r;o.scrollIntoView({block:"end",behavior:Q.config.scrollBehavior})}}}function bn(r,e,o,i){if(i==null){i={}}if(r==null){return i}const s=te(r,e);if(s){let e=s.trim();let t=o;if(e==="unset"){return null}if(e.indexOf("javascript:")===0){e=e.substr(11);t=true}else if(e.indexOf("js:")===0){e=e.substr(3);t=true}if(e.indexOf("{")!==0){e="{"+e+"}"}let n;if(t){n=vn(r,function(){return Function("return ("+e+")")()},{})}else{n=S(e)}for(const l in n){if(n.hasOwnProperty(l)){if(i[l]==null){i[l]=n[l]}}}}return bn(ue(c(r)),e,o,i)}function vn(e,t,n){if(Q.config.allowEval){return t()}else{fe(e,"htmx:evalDisallowedError");return n}}function wn(e,t){return bn(e,"hx-vars",true,t)}function Sn(e,t){return bn(e,"hx-vals",false,t)}function En(e){return ce(wn(e),Sn(e))}function Cn(t,n,r){if(r!==null){try{t.setRequestHeader(n,r)}catch(e){t.setRequestHeader(n,encodeURIComponent(r));t.setRequestHeader(n+"-URI-AutoEncoded","true")}}}function On(t){if(t.responseURL&&typeof URL!=="undefined"){try{const e=new URL(t.responseURL);return e.pathname+e.search}catch(e){fe(ne().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function O(e,t){return t.test(e.getAllResponseHeaders())}function Rn(t,n,r){t=t.toLowerCase();if(r){if(r instanceof Element||typeof r==="string"){return he(t,n,null,null,{targetOverride:y(r)||ve,returnPromise:true})}else{let e=y(r.target);if(r.target&&!e||!e&&!y(r.source)){e=ve}return he(t,n,y(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:e,swapOverride:r.swap,select:r.select,returnPromise:true})}}else{return he(t,n,null,null,{returnPromise:true})}}function Hn(e){const t=[];while(e){t.push(e);e=e.parentElement}return t}function Tn(e,t,n){let r;let o;if(typeof URL==="function"){o=new URL(t,document.location.href);const i=document.location.origin;r=i===o.origin}else{o=t;r=l(t,document.location.origin)}if(Q.config.selfRequestsOnly){if(!r){return false}}return de(e,"htmx:validateUrl",ce({url:o,sameHost:r},n))}function qn(e){if(e instanceof FormData)return e;const t=new FormData;for(const n in e){if(e.hasOwnProperty(n)){if(e[n]&&typeof e[n].forEach==="function"){e[n].forEach(function(e){t.append(n,e)})}else if(typeof e[n]==="object"&&!(e[n]instanceof Blob)){t.append(n,JSON.stringify(e[n]))}else{t.append(n,e[n])}}}return t}function Ln(r,o,e){return new Proxy(e,{get:function(t,e){if(typeof e==="number")return t[e];if(e==="length")return t.length;if(e==="push"){return function(e){t.push(e);r.append(o,e)}}if(typeof t[e]==="function"){return function(){t[e].apply(t,arguments);r.delete(o);t.forEach(function(e){r.append(o,e)})}}if(t[e]&&t[e].length===1){return t[e][0]}else{return t[e]}},set:function(e,t,n){e[t]=n;r.delete(o);e.forEach(function(e){r.append(o,e)});return true}})}function Nn(r){return new Proxy(r,{get:function(e,t){if(typeof t==="symbol"){return Reflect.get(e,t)}if(t==="toJSON"){return()=>Object.fromEntries(r)}if(t in e){if(typeof e[t]==="function"){return function(){return r[t].apply(r,arguments)}}else{return e[t]}}const n=r.getAll(t);if(n.length===0){return undefined}else if(n.length===1){return n[0]}else{return Ln(e,t,n)}},set:function(t,n,e){if(typeof n!=="string"){return false}t.delete(n);if(e&&typeof e.forEach==="function"){e.forEach(function(e){t.append(n,e)})}else if(typeof e==="object"&&!(e instanceof Blob)){t.append(n,JSON.stringify(e))}else{t.append(n,e)}return true},deleteProperty:function(e,t){if(typeof t==="string"){e.delete(t)}return true},ownKeys:function(e){return Reflect.ownKeys(Object.fromEntries(e))},getOwnPropertyDescriptor:function(e,t){return Reflect.getOwnPropertyDescriptor(Object.fromEntries(e),t)}})}function he(t,n,r,o,i,D){let s=null;let l=null;i=i!=null?i:{};if(i.returnPromise&&typeof Promise!=="undefined"){var e=new Promise(function(e,t){s=e;l=t})}if(r==null){r=ne().body}const M=i.handler||Dn;const X=i.select||null;if(!le(r)){oe(s);return e}const c=i.targetOverride||ue(Ee(r));if(c==null||c==ve){fe(r,"htmx:targetError",{target:te(r,"hx-target")});oe(l);return e}let u=ie(r);const a=u.lastButtonClicked;if(a){const L=ee(a,"formaction");if(L!=null){n=L}const N=ee(a,"formmethod");if(N!=null){if(N.toLowerCase()!=="dialog"){t=N}}}const f=re(r,"hx-confirm");if(D===undefined){const K=function(e){return he(t,n,r,o,i,!!e)};const G={target:c,elt:r,path:n,verb:t,triggeringEvent:o,etc:i,issueRequest:K,question:f};if(de(r,"htmx:confirm",G)===false){oe(s);return e}}let d=r;let h=re(r,"hx-sync");let g=null;let F=false;if(h){const A=h.split(":");const I=A[0].trim();if(I==="this"){d=Se(r,"hx-sync")}else{d=ue(ae(r,I))}h=(A[1]||"drop").trim();u=ie(d);if(h==="drop"&&u.xhr&&u.abortable!==true){oe(s);return e}else if(h==="abort"){if(u.xhr){oe(s);return e}else{F=true}}else if(h==="replace"){de(d,"htmx:abort")}else if(h.indexOf("queue")===0){const W=h.split(" ");g=(W[1]||"last").trim()}}if(u.xhr){if(u.abortable){de(d,"htmx:abort")}else{if(g==null){if(o){const P=ie(o);if(P&&P.triggerSpec&&P.triggerSpec.queue){g=P.triggerSpec.queue}}if(g==null){g="last"}}if(u.queuedRequests==null){u.queuedRequests=[]}if(g==="first"&&u.queuedRequests.length===0){u.queuedRequests.push(function(){he(t,n,r,o,i)})}else if(g==="all"){u.queuedRequests.push(function(){he(t,n,r,o,i)})}else if(g==="last"){u.queuedRequests=[];u.queuedRequests.push(function(){he(t,n,r,o,i)})}oe(s);return e}}const p=new XMLHttpRequest;u.xhr=p;u.abortable=F;const m=function(){u.xhr=null;u.abortable=false;if(u.queuedRequests!=null&&u.queuedRequests.length>0){const e=u.queuedRequests.shift();e()}};const B=re(r,"hx-prompt");if(B){var x=prompt(B);if(x===null||!de(r,"htmx:prompt",{prompt:x,target:c})){oe(s);m();return e}}if(f&&!D){if(!confirm(f)){oe(s);m();return e}}let y=fn(r,c,x);if(t!=="get"&&!pn(r)){y["Content-Type"]="application/x-www-form-urlencoded"}if(i.headers){y=ce(y,i.headers)}const U=cn(r,t);let b=U.errors;const j=U.formData;if(i.values){ln(j,qn(i.values))}const V=qn(En(r));const v=ln(j,V);let w=dn(v,r);if(Q.config.getCacheBusterParam&&t==="get"){w.set("org.htmx.cache-buster",ee(c,"id")||"true")}if(n==null||n===""){n=ne().location.href}const S=bn(r,"hx-request");const _=ie(r).boosted;let E=Q.config.methodsThatUseUrlParams.indexOf(t)>=0;const C={boosted:_,useUrlParams:E,formData:w,parameters:Nn(w),unfilteredFormData:v,unfilteredParameters:Nn(v),headers:y,target:c,verb:t,errors:b,withCredentials:i.credentials||S.credentials||Q.config.withCredentials,timeout:i.timeout||S.timeout||Q.config.timeout,path:n,triggeringEvent:o};if(!de(r,"htmx:configRequest",C)){oe(s);m();return e}n=C.path;t=C.verb;y=C.headers;w=qn(C.parameters);b=C.errors;E=C.useUrlParams;if(b&&b.length>0){de(r,"htmx:validation:halted",C);oe(s);m();return e}const z=n.split("#");const $=z[0];const O=z[1];let R=n;if(E){R=$;const Z=!w.keys().next().done;if(Z){if(R.indexOf("?")<0){R+="?"}else{R+="&"}R+=an(w);if(O){R+="#"+O}}}if(!Tn(r,R,C)){fe(r,"htmx:invalidPath",C);oe(l);return e}p.open(t.toUpperCase(),R,true);p.overrideMimeType("text/html");p.withCredentials=C.withCredentials;p.timeout=C.timeout;if(S.noHeaders){}else{for(const k in y){if(y.hasOwnProperty(k)){const Y=y[k];Cn(p,k,Y)}}}const H={xhr:p,target:c,requestConfig:C,etc:i,boosted:_,select:X,pathInfo:{requestPath:n,finalRequestPath:R,responsePath:null,anchor:O}};p.onload=function(){try{const t=Hn(r);H.pathInfo.responsePath=On(p);M(r,H);if(H.keepIndicators!==true){Qt(T,q)}de(r,"htmx:afterRequest",H);de(r,"htmx:afterOnLoad",H);if(!le(r)){let e=null;while(t.length>0&&e==null){const n=t.shift();if(le(n)){e=n}}if(e){de(e,"htmx:afterRequest",H);de(e,"htmx:afterOnLoad",H)}}oe(s);m()}catch(e){fe(r,"htmx:onLoadError",ce({error:e},H));throw e}};p.onerror=function(){Qt(T,q);fe(r,"htmx:afterRequest",H);fe(r,"htmx:sendError",H);oe(l);m()};p.onabort=function(){Qt(T,q);fe(r,"htmx:afterRequest",H);fe(r,"htmx:sendAbort",H);oe(l);m()};p.ontimeout=function(){Qt(T,q);fe(r,"htmx:afterRequest",H);fe(r,"htmx:timeout",H);oe(l);m()};if(!de(r,"htmx:beforeRequest",H)){oe(s);m();return e}var T=Zt(r);var q=Yt(r);se(["loadstart","loadend","progress","abort"],function(t){se([p,p.upload],function(e){e.addEventListener(t,function(e){de(r,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});de(r,"htmx:beforeSend",H);const J=E?null:mn(p,r,w);p.send(J);return e}function An(e,t){const n=t.xhr;let r=null;let o=null;if(O(n,/HX-Push:/i)){r=n.getResponseHeader("HX-Push");o="push"}else if(O(n,/HX-Push-Url:/i)){r=n.getResponseHeader("HX-Push-Url");o="push"}else if(O(n,/HX-Replace-Url:/i)){r=n.getResponseHeader("HX-Replace-Url");o="replace"}if(r){if(r==="false"){return{}}else{return{type:o,path:r}}}const i=t.pathInfo.finalRequestPath;const s=t.pathInfo.responsePath;const l=re(e,"hx-push-url");const c=re(e,"hx-replace-url");const u=ie(e).boosted;let a=null;let f=null;if(l){a="push";f=l}else if(c){a="replace";f=c}else if(u){a="push";f=s||i}if(f){if(f==="false"){return{}}if(f==="true"){f=s||i}if(t.pathInfo.anchor&&f.indexOf("#")===-1){f=f+"#"+t.pathInfo.anchor}return{type:a,path:f}}else{return{}}}function In(e,t){var n=new RegExp(e.code);return n.test(t.toString(10))}function Pn(e){for(var t=0;t0){E().setTimeout(e,x.swapDelay)}else{e()}}if(f){fe(o,"htmx:responseError",ce({error:"Response Status Error Code "+s.status+" from "+i.pathInfo.requestPath},i))}}const Mn={};function Xn(){return{init:function(e){return null},getSelectors:function(){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,n){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,n,r){return false},encodeParameters:function(e,t,n){return null}}}function Fn(e,t){if(t.init){t.init(n)}Mn[e]=ce(Xn(),t)}function Bn(e){delete Mn[e]}function Un(e,n,r){if(n==undefined){n=[]}if(e==undefined){return n}if(r==undefined){r=[]}const t=te(e,"hx-ext");if(t){se(t.split(","),function(e){e=e.replace(/ /g,"");if(e.slice(0,7)=="ignore:"){r.push(e.slice(7));return}if(r.indexOf(e)<0){const t=Mn[e];if(t&&n.indexOf(t)<0){n.push(t)}}})}return Un(ue(c(e)),n,r)}var jn=false;ne().addEventListener("DOMContentLoaded",function(){jn=true});function Vn(e){if(jn||ne().readyState==="complete"){e()}else{ne().addEventListener("DOMContentLoaded",e)}}function _n(){if(Q.config.includeIndicatorStyles!==false){const e=Q.config.inlineStyleNonce?` nonce="${Q.config.inlineStyleNonce}"`:"";ne().head.insertAdjacentHTML("beforeend"," ."+Q.config.indicatorClass+"{opacity:0} ."+Q.config.requestClass+" ."+Q.config.indicatorClass+"{opacity:1; transition: opacity 200ms ease-in;} ."+Q.config.requestClass+"."+Q.config.indicatorClass+"{opacity:1; transition: opacity 200ms ease-in;} ")}}function zn(){const e=ne().querySelector('meta[name="htmx-config"]');if(e){return S(e.content)}else{return null}}function $n(){const e=zn();if(e){Q.config=ce(Q.config,e)}}Vn(function(){$n();_n();let e=ne().body;kt(e);const t=ne().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){const t=e.target;const n=ie(t);if(n&&n.xhr){n.xhr.abort()}});const n=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(e){if(e.state&&e.state.htmx){Wt();se(t,function(e){de(e,"htmx:restored",{document:ne(),triggerEvent:de})})}else{if(n){n(e)}}};E().setTimeout(function(){de(e,"htmx:load",{});e=null},0)});return Q}(); \ No newline at end of file diff --git a/static/js/hyperscript.js b/static/js/hyperscript.js new file mode 100644 index 0000000..810c119 --- /dev/null +++ b/static/js/hyperscript.js @@ -0,0 +1 @@ +(function(e,t){const r=t(e);if(typeof exports==="object"&&typeof exports["nodeName"]!=="string"){module.exports=r}else{e["_hyperscript"]=r;if("document"in e)e["_hyperscript"].browserInit()}})(typeof self!=="undefined"?self:this,(e=>{"use strict";const t={dynamicResolvers:[function(e,t){if(e==="Fixed"){return Number(t).toFixed()}else if(e.indexOf("Fixed:")===0){let r=e.split(":")[1];return Number(t).toFixed(parseInt(r))}}],String:function(e){if(e.toString){return e.toString()}else{return""+e}},Int:function(e){return parseInt(e)},Float:function(e){return parseFloat(e)},Number:function(e){return Number(e)},Date:function(e){return new Date(e)},Array:function(e){return Array.from(e)},JSON:function(e){return JSON.stringify(e)},Object:function(e){if(e instanceof String){e=e.toString()}if(typeof e==="string"){return JSON.parse(e)}else{return Object.assign({},e)}}};const r={attributes:"_, script, data-script",defaultTransition:"all 500ms ease-in",disableSelector:"[disable-scripting], [data-disable-scripting]",hideShowStrategies:{},conversions:t};class n{static OP_TABLE={"+":"PLUS","-":"MINUS","*":"MULTIPLY","/":"DIVIDE",".":"PERIOD","..":"ELLIPSIS","\\":"BACKSLASH",":":"COLON","%":"PERCENT","|":"PIPE","!":"EXCLAMATION","?":"QUESTION","#":"POUND","&":"AMPERSAND",$:"DOLLAR",";":"SEMI",",":"COMMA","(":"L_PAREN",")":"R_PAREN","<":"L_ANG",">":"R_ANG","<=":"LTE_ANG",">=":"GTE_ANG","==":"EQ","===":"EQQ","!=":"NEQ","!==":"NEQQ","{":"L_BRACE","}":"R_BRACE","[":"L_BRACKET","]":"R_BRACKET","=":"EQUALS"};static isValidCSSClassChar(e){return n.isAlpha(e)||n.isNumeric(e)||e==="-"||e==="_"||e===":"}static isValidCSSIDChar(e){return n.isAlpha(e)||n.isNumeric(e)||e==="-"||e==="_"||e===":"}static isWhitespace(e){return e===" "||e==="\t"||n.isNewline(e)}static positionString(e){return"[Line: "+e.line+", Column: "+e.column+"]"}static isNewline(e){return e==="\r"||e==="\n"}static isNumeric(e){return e>="0"&&e<="9"}static isAlpha(e){return e>="a"&&e<="z"||e>="A"&&e<="Z"}static isIdentifierChar(e,t){return e==="_"||e==="$"}static isReservedChar(e){return e==="`"||e==="^"}static isValidSingleQuoteStringStart(e){if(e.length>0){var t=e[e.length-1];if(t.type==="IDENTIFIER"||t.type==="CLASS_REF"||t.type==="ID_REF"){return false}if(t.op&&(t.value===">"||t.value===")")){return false}}return true}static tokenize(e,t){var r=[];var a=e;var o=0;var s=0;var u=1;var l="";var c=0;function f(){return t&&c===0}while(o=0){return this.consumeToken()}}requireToken(e,t){var r=this.matchToken(e,t);if(r){return r}else{this.raiseError(this,"Expected '"+e+"' but found '"+this.currentToken().value+"'")}}peekToken(e,t,r){t=t||0;r=r||"IDENTIFIER";if(this.tokens[t]&&this.tokens[t].value===e&&this.tokens[t].type===r){return this.tokens[t]}}matchToken(e,t){if(this.follows.indexOf(e)!==-1){return}t=t||"IDENTIFIER";if(this.currentToken()&&this.currentToken().value===e&&this.currentToken().type===t){return this.consumeToken()}}consumeToken(){var e=this.tokens.shift();this.consumed.push(e);this._lastConsumed=e;this.consumeWhitespace();return e}consumeUntil(e,t){var r=[];var n=this.token(0,true);while((t==null||n.type!==t)&&(e==null||n.value!==e)&&n.type!=="EOF"){var i=this.tokens.shift();this.consumed.push(i);r.push(n);n=this.token(0,true)}this.consumeWhitespace();return r}lastWhitespace(){if(this.consumed[this.consumed.length-1]&&this.consumed[this.consumed.length-1].type==="WHITESPACE"){return this.consumed[this.consumed.length-1].value}else{return""}}consumeUntilWhitespace(){return this.consumeUntil(null,"WHITESPACE")}hasMore(){return this.tokens.length>0}token(e,t){var r;var n=0;do{if(!t){while(this.tokens[n]&&this.tokens[n].type==="WHITESPACE"){n++}}r=this.tokens[n];e--;n++}while(e>-1);if(r){return r}else{return{type:"EOF",value:"<<>>"}}}currentToken(){return this.token(0)}lastMatch(){return this._lastConsumed}static sourceFor=function(){return this.programSource.substring(this.startToken.start,this.endToken.end)};static lineFor=function(){return this.programSource.split("\n")[this.startToken.line-1]};follows=[];pushFollow(e){this.follows.push(e)}popFollow(){this.follows.pop()}clearFollows(){var e=this.follows;this.follows=[];return e}restoreFollows(e){this.follows=e}}class a{constructor(e){this.runtime=e;this.possessivesDisabled=false;this.addGrammarElement("feature",(function(e,t,r){if(r.matchOpToken("(")){var n=e.requireElement("feature",r);r.requireOpToken(")");return n}var i=e.FEATURES[r.currentToken().value||""];if(i){return i(e,t,r)}}));this.addGrammarElement("command",(function(e,t,r){if(r.matchOpToken("(")){const t=e.requireElement("command",r);r.requireOpToken(")");return t}var n=e.COMMANDS[r.currentToken().value||""];let i;if(n){i=n(e,t,r)}else if(r.currentToken().type==="IDENTIFIER"){i=e.parseElement("pseudoCommand",r)}if(i){return e.parseElement("indirectStatement",r,i)}return i}));this.addGrammarElement("commandList",(function(e,t,r){if(r.hasMore()){var n=e.parseElement("command",r);if(n){r.matchToken("then");const t=e.parseElement("commandList",r);if(t)n.next=t;return n}}return{type:"emptyCommandListCommand",op:function(e){return t.findNext(this,e)},execute:function(e){return t.unifiedExec(this,e)}}}));this.addGrammarElement("leaf",(function(e,t,r){var n=e.parseAnyOf(e.LEAF_EXPRESSIONS,r);if(n==null){return e.parseElement("symbol",r)}return n}));this.addGrammarElement("indirectExpression",(function(e,t,r,n){for(var i=0;i{this.unifiedExec(e,t)})).catch((e=>{this.unifiedExec({op:function(){throw e}},t)}));return}else if(r===o.HALT){if(t.meta.finallyHandler&&!t.meta.handlingFinally){t.meta.handlingFinally=true;e=t.meta.finallyHandler}else{if(t.meta.onHalt){t.meta.onHalt()}if(t.meta.currentException){if(t.meta.reject){t.meta.reject(t.meta.currentException);return}else{throw t.meta.currentException}}else{return}}}else{e=r}}}unifiedEval(e,t){var r=[t];var n=false;var i=false;if(e.args){for(var a=0;a{r=this.wrapArrays(r);Promise.all(r).then((function(r){if(i){this.unwrapAsyncs(r)}try{var a=e.op.apply(e,r);t(a)}catch(e){n(e)}})).catch((function(e){n(e)}))}))}else{if(i){this.unwrapAsyncs(r)}return e.op.apply(e,r)}}_scriptAttrs=null;getScriptAttributes(){if(this._scriptAttrs==null){this._scriptAttrs=r.attributes.replace(/ /g,"").split(",")}return this._scriptAttrs}getScript(e){for(var t=0;t{this.initElement(e,e instanceof HTMLScriptElement&&e.type==="text/hyperscript"?document.body:e)}))}}initElement(e,t){if(e.closest&&e.closest(r.disableSelector)){return}var n=this.getInternalData(e);if(!n.initialized){var i=this.getScript(e);if(i){try{n.initialized=true;n.script=i;const r=this.lexer,s=this.parser;var a=r.tokenize(i);var o=s.parseHyperScript(a);if(!o)return;o.apply(t||e,e);setTimeout((()=>{this.triggerEvent(t||e,"load",{hyperscript:true})}),1)}catch(t){this.triggerEvent(e,"exception",{error:t});console.error("hyperscript errors were found on the following element:",e,"\n\n",t.message,t.stack)}}}}internalDataMap=new WeakMap;getInternalData(e){var t=this.internalDataMap.get(e);if(typeof t==="undefined"){this.internalDataMap.set(e,t={})}return t}typeCheck(e,t,r){if(e==null&&r){return true}var n=Object.prototype.toString.call(e).slice(8,-1);return n===t}getElementScope(e){var t=e.meta&&e.meta.owner;if(t){var r=this.getInternalData(t);var n="elementScope";if(e.meta.feature&&e.meta.feature.behavior){n=e.meta.feature.behavior+"Scope"}var i=h(r,n);return i}else{return{}}}isReservedWord(e){return["meta","it","result","locals","event","target","detail","sender","body"].includes(e)}isHyperscriptContext(e){return e instanceof f}resolveSymbol(t,r,n){if(t==="me"||t==="my"||t==="I"){return r.me}if(t==="it"||t==="its"||t==="result"){return r.result}if(t==="you"||t==="your"||t==="yourself"){return r.you}else{if(n==="global"){return e[t]}else if(n==="element"){var i=this.getElementScope(r);return i[t]}else if(n==="local"){return r.locals[t]}else{if(r.meta&&r.meta.context){var a=r.meta.context[t];if(typeof a!=="undefined"){return a}if(r.meta.context.detail){a=r.meta.context.detail[t];if(typeof a!=="undefined"){return a}}}if(this.isHyperscriptContext(r)&&!this.isReservedWord(t)){var o=r.locals[t]}else{var o=r[t]}if(typeof o!=="undefined"){return o}else{var i=this.getElementScope(r);o=i[t];if(typeof o!=="undefined"){return o}else{return e[t]}}}}}setSymbol(t,r,n,i){if(n==="global"){e[t]=i}else if(n==="element"){var a=this.getElementScope(r);a[t]=i}else if(n==="local"){r.locals[t]=i}else{if(this.isHyperscriptContext(r)&&!this.isReservedWord(t)&&typeof r.locals[t]!=="undefined"){r.locals[t]=i}else{var a=this.getElementScope(r);var o=a[t];if(typeof o!=="undefined"){a[t]=i}else{if(this.isHyperscriptContext(r)&&!this.isReservedWord(t)){r.locals[t]=i}else{r[t]=i}}}}}findNext(e,t){if(e){if(e.resolveNext){return e.resolveNext(t)}else if(e.next){return e.next}else{return this.findNext(e.parent,t)}}}flatGet(e,t,r){if(e!=null){var n=r(e,t);if(typeof n!=="undefined"){return n}if(this.shouldAutoIterate(e)){var i=[];for(var a of e){var o=r(a,t);i.push(o)}return i}}}resolveProperty(e,t){return this.flatGet(e,t,((e,t)=>e[t]))}resolveAttribute(e,t){return this.flatGet(e,t,((e,t)=>e.getAttribute&&e.getAttribute(t)))}resolveStyle(e,t){return this.flatGet(e,t,((e,t)=>e.style&&e.style[t]))}resolveComputedStyle(e,t){return this.flatGet(e,t,((e,t)=>getComputedStyle(e).getPropertyValue(t)))}assignToNamespace(t,r,n,i){let a;if(typeof document!=="undefined"&&t===document.body){a=e}else{a=this.getHyperscriptFeatures(t)}var o;while((o=r.shift())!==undefined){var s=a[o];if(s==null){s={};a[o]=s}a=s}a[n]=i}getHyperTrace(e,t){var r=[];var n=e;while(n.meta.caller){n=n.meta.caller}if(n.meta.traceMap){return n.meta.traceMap.get(t,r)}}registerHyperTrace(e,t){var r=[];var n=null;while(e!=null){r.push(e);n=e;e=e.meta.caller}if(n.meta.traceMap==null){n.meta.traceMap=new Map}if(!n.meta.traceMap.get(t)){var i={trace:r,print:function(e){e=e||console.error;e("hypertrace /// ");var t=0;for(var n=0;n",i.meta.feature.displayName.padEnd(t+2),"-",i.meta.owner)}}};n.meta.traceMap.set(t,i)}}escapeSelector(e){return e.replace(/:/g,(function(e){return"\\"+e}))}nullCheck(e,t){if(e==null){throw new Error("'"+t.sourceFor()+"' is null")}}isEmpty(e){return e==undefined||e.length===0}doesExist(e){if(e==null){return false}if(this.shouldAutoIterate(e)){for(const t of e){return true}return false}return true}getRootNode(e){if(e&&e instanceof Node){var t=e.getRootNode();if(t instanceof Document||t instanceof ShadowRoot)return t}return document}getEventQueueFor(e,t){let r=this.getInternalData(e);var n=r.eventQueues;if(n==null){n=new Map;r.eventQueues=n}var i=n.get(t);if(i==null){i={queue:[],executing:false};n.set(t,i)}return i}beepValueToConsole(e,t,r){if(this.triggerEvent(e,"hyperscript:beep",{element:e,expression:t,value:r})){var n;if(r){if(r instanceof m){n="ElementCollection"}else if(r.constructor){n=r.constructor.name}else{n="unknown"}}else{n="object (null)"}var a=r;if(n==="String"){a='"'+a+'"'}else if(r instanceof m){a=Array.from(r)}console.log("///_ BEEP! The expression ("+i.sourceFor.call(t).replace("beep! ","")+") evaluates to:",a,"of type "+n)}}hyperscriptUrl="document"in e&&document.currentScript?document.currentScript.src:null}function s(){let e=document.cookie.split("; ").map((e=>{let t=e.split("=");return{name:t[0],value:decodeURIComponent(t[1])}}));return e}function u(e){document.cookie=e+"=;expires=Thu, 01 Jan 1970 00:00:00 GMT"}function l(){for(const e of s()){u(e.name)}}const c=new Proxy({},{get(e,t){if(t==="then"||t==="asyncWrapper"){return null}else if(t==="length"){return s().length}else if(t==="clear"){return u}else if(t==="clearAll"){return l}else if(typeof t==="string"){if(!isNaN(t)){return s()[parseInt(t)]}else{let e=document.cookie.split("; ").find((e=>e.startsWith(t+"=")))?.split("=")[1];if(e){return decodeURIComponent(e)}}}else if(t===Symbol.iterator){return s()[t]}},set(e,t,r){var n=null;if("string"===typeof r){n=encodeURIComponent(r);n+=";samesite=lax"}else{n=encodeURIComponent(r.value);if(r.expires){n+=";expires="+r.maxAge}if(r.maxAge){n+=";max-age="+r.maxAge}if(r.partitioned){n+=";partitioned="+r.partitioned}if(r.path){n+=";path="+r.path}if(r.samesite){n+=";samesite="+r.path}if(r.secure){n+=";secure="+r.path}}document.cookie=t+"="+n;return true}});class f{constructor(t,r,n,i,a){this.meta={parser:a.parser,lexer:a.lexer,runtime:a,owner:t,feature:r,iterators:{},ctx:this};this.locals={cookies:c};this.me=n,this.you=undefined;this.result=undefined;this.event=i;this.target=i?i.target:null;this.detail=i?i.detail:null;this.sender=i?i.detail?i.detail.sender:null:null;this.body="document"in e?document.body:null;a.addFeatures(t,this)}}class m{constructor(e,t,r){this._css=e;this.relativeToElement=t;this.escape=r;this[p]=true}get css(){if(this.escape){return o.prototype.escapeSelector(this._css)}else{return this._css}}get className(){return this._css.substr(1)}get id(){return this.className()}contains(e){for(let t of this){if(t.contains(e)){return true}}return false}get length(){return this.selectMatches().length}[Symbol.iterator](){let e=this.selectMatches();return e[Symbol.iterator]()}selectMatches(){let e=o.prototype.getRootNode(this.relativeToElement).querySelectorAll(this.css);return e}}const p=Symbol();function h(e,t){var r=e[t];if(r){return r}else{var n={};e[t]=n;return n}}function v(e){try{return JSON.parse(e)}catch(e){d(e);return null}}function d(e){if(console.error){console.error(e)}else if(console.log){console.log("ERROR: ",e)}}function E(e,t){return new(e.bind.apply(e,[e].concat(t)))}function T(t){t.addLeafExpression("parenthesized",(function(e,t,r){if(r.matchOpToken("(")){var n=r.clearFollows();try{var i=e.requireElement("expression",r)}finally{r.restoreFollows(n)}r.requireOpToken(")");return i}}));t.addLeafExpression("string",(function(e,t,r){var i=r.matchTokenType("STRING");if(!i)return;var a=i.value;var o;if(i.template){var s=n.tokenize(a,true);o=e.parseStringTemplate(s)}else{o=[]}return{type:"string",token:i,args:o,op:function(e){var t="";for(var r=1;re instanceof Element))}get css(){let e="",t=0;for(const r of this.templateParts){if(r instanceof Element){e+="[data-hs-query-id='"+t+++"']"}else e+=r}return e}[Symbol.iterator](){this.elements.forEach(((e,t)=>e.dataset.hsQueryId=t));const e=super[Symbol.iterator]();this.elements.forEach((e=>e.removeAttribute("data-hs-query-id")));return e}}t.addLeafExpression("queryRef",(function(e,t,i){var a=i.matchOpToken("<");if(!a)return;var o=i.consumeUntil("/");i.requireOpToken("/");i.requireOpToken(">");var s=o.map((function(e){if(e.type==="STRING"){return'"'+e.value+'"'}else{return e.value}})).join("");var u,l,c;if(s.indexOf("$")>=0){u=true;l=n.tokenize(s,true);c=e.parseStringTemplate(l)}return{type:"queryRef",css:s,args:c,op:function(e,...t){if(u){return new r(s,e.me,t)}else{return new m(s,e.me)}},evaluate:function(e){return t.unifiedEval(this,e)}}}));t.addLeafExpression("attributeRef",(function(e,t,r){var n=r.matchTokenType("ATTRIBUTE_REF");if(!n)return;if(!n.value)return;var i=n.value;if(i.indexOf("[")===0){var a=i.substring(2,i.length-1)}else{var a=i.substring(1)}var o="["+a+"]";var s=a.split("=");var u=s[0];var l=s[1];if(l){if(l.indexOf('"')===0){l=l.substring(1,l.length-1)}}return{type:"attributeRef",name:u,css:o,value:l,op:function(e){var t=e.you||e.me;if(t){return t.getAttribute(u)}},evaluate:function(e){return t.unifiedEval(this,e)}}}));t.addLeafExpression("styleRef",(function(e,t,r){var n=r.matchTokenType("STYLE_REF");if(!n)return;if(!n.value)return;var i=n.value.substr(1);if(i.startsWith("computed-")){i=i.substr("computed-".length);return{type:"computedStyleRef",name:i,op:function(e){var r=e.you||e.me;if(r){return t.resolveComputedStyle(r,i)}},evaluate:function(e){return t.unifiedEval(this,e)}}}else{return{type:"styleRef",name:i,op:function(e){var r=e.you||e.me;if(r){return t.resolveStyle(r,i)}},evaluate:function(e){return t.unifiedEval(this,e)}}}}));t.addGrammarElement("objectKey",(function(e,t,r){var n;if(n=r.matchTokenType("STRING")){return{type:"objectKey",key:n.value,evaluate:function(){return n.value}}}else if(r.matchOpToken("[")){var i=e.parseElement("expression",r);r.requireOpToken("]");return{type:"objectKey",expr:i,args:[i],op:function(e,t){return t},evaluate:function(e){return t.unifiedEval(this,e)}}}else{var a="";do{n=r.matchTokenType("IDENTIFIER")||r.matchOpToken("-");if(n)a+=n.value}while(n);return{type:"objectKey",key:a,evaluate:function(){return a}}}}));t.addLeafExpression("objectLiteral",(function(e,t,r){if(!r.matchOpToken("{"))return;var n=[];var i=[];if(!r.matchOpToken("}")){do{var a=e.requireElement("objectKey",r);r.requireOpToken(":");var o=e.requireElement("expression",r);i.push(o);n.push(a)}while(r.matchOpToken(","));r.requireOpToken("}")}return{type:"objectLiteral",args:[n,i],op:function(e,t,r){var n={};for(var i=0;i");var a=e.requireElement("expression",r);return{type:"blockLiteral",args:n,expr:a,evaluate:function(e){var t=function(){for(var t=0;t=0;a--){var o=i[a];if(o.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return o}}if(n){return i[i.length-1]}};var l=function(e,t,r,n){var i=[];o.prototype.forEach(t,(function(t){if(t.matches(r)||t===e){i.push(t)}}));for(var a=0;a","<=",">=","==","===","!=","!==");var a=i?i.value:null;var o=true;var s=false;if(a==null){if(r.matchToken("is")||r.matchToken("am")){if(r.matchToken("not")){if(r.matchToken("in")){a="not in"}else if(r.matchToken("a")){a="not a";s=true}else if(r.matchToken("empty")){a="not empty";o=false}else{if(r.matchToken("really")){a="!=="}else{a="!="}if(r.matchToken("equal")){r.matchToken("to")}}}else if(r.matchToken("in")){a="in"}else if(r.matchToken("a")){a="a";s=true}else if(r.matchToken("empty")){a="empty";o=false}else if(r.matchToken("less")){r.requireToken("than");if(r.matchToken("or")){r.requireToken("equal");r.requireToken("to");a="<="}else{a="<"}}else if(r.matchToken("greater")){r.requireToken("than");if(r.matchToken("or")){r.requireToken("equal");r.requireToken("to");a=">="}else{a=">"}}else{if(r.matchToken("really")){a="==="}else{a="=="}if(r.matchToken("equal")){r.matchToken("to")}}}else if(r.matchToken("equals")){a="=="}else if(r.matchToken("really")){r.requireToken("equals");a="==="}else if(r.matchToken("exist")||r.matchToken("exists")){a="exist";o=false}else if(r.matchToken("matches")||r.matchToken("match")){a="match"}else if(r.matchToken("contains")||r.matchToken("contain")){a="contain"}else if(r.matchToken("includes")||r.matchToken("include")){a="include"}else if(r.matchToken("do")||r.matchToken("does")){r.requireToken("not");if(r.matchToken("matches")||r.matchToken("match")){a="not match"}else if(r.matchToken("contains")||r.matchToken("contain")){a="not contain"}else if(r.matchToken("exist")||r.matchToken("exist")){a="not exist";o=false}else if(r.matchToken("include")){a="not include"}else{e.raiseParseError(r,"Expected matches or contains")}}}if(a){var u,l,c;if(s){u=r.requireTokenType("IDENTIFIER");l=!r.matchOpToken("!")}else if(o){c=e.requireElement("mathExpression",r);if(a==="match"||a==="not match"){c=c.css?c.css:c}}var m=n;n={type:"comparisonOperator",operator:a,typeName:u,nullOk:l,lhs:n,rhs:c,args:[n,c],op:function(e,r,n){if(a==="=="){return r==n}else if(a==="!="){return r!=n}if(a==="==="){return r===n}else if(a==="!=="){return r!==n}if(a==="match"){return r!=null&&p(m,r,n)}if(a==="not match"){return r==null||!p(m,r,n)}if(a==="in"){return n!=null&&f(c,n,r)}if(a==="not in"){return n==null||!f(c,n,r)}if(a==="contain"){return r!=null&&f(m,r,n)}if(a==="not contain"){return r==null||!f(m,r,n)}if(a==="include"){return r!=null&&f(m,r,n)}if(a==="not include"){return r==null||!f(m,r,n)}if(a==="==="){return r===n}else if(a==="!=="){return r!==n}else if(a==="<"){return r"){return r>n}else if(a==="<="){return r<=n}else if(a===">="){return r>=n}else if(a==="empty"){return t.isEmpty(r)}else if(a==="not empty"){return!t.isEmpty(r)}else if(a==="exist"){return t.doesExist(r)}else if(a==="not exist"){return!t.doesExist(r)}else if(a==="a"){return t.typeCheck(r,u.value,l)}else if(a==="not a"){return!t.typeCheck(r,u.value,l)}else{throw"Unknown comparison : "+a}},evaluate:function(e){return t.unifiedEval(this,e)}}}return n}));t.addGrammarElement("comparisonExpression",(function(e,t,r){return e.parseAnyOf(["comparisonOperator","mathExpression"],r)}));t.addGrammarElement("logicalOperator",(function(e,t,r){var n=e.parseElement("comparisonExpression",r);var i,a=null;i=r.matchToken("and")||r.matchToken("or");while(i){a=a||i;if(a.value!==i.value){e.raiseParseError(r,"You must parenthesize logical operations with different operators")}var o=e.requireElement("comparisonExpression",r);const s=i.value;n={type:"logicalOperator",operator:s,lhs:n,rhs:o,args:[n,o],op:function(e,t,r){if(s==="and"){return t&&r}else{return t||r}},evaluate:function(e){return t.unifiedEval(this,e)}};i=r.matchToken("and")||r.matchToken("or")}return n}));t.addGrammarElement("logicalExpression",(function(e,t,r){return e.parseAnyOf(["logicalOperator","mathExpression"],r)}));t.addGrammarElement("asyncExpression",(function(e,t,r){if(r.matchToken("async")){var n=e.requireElement("logicalExpression",r);var i={type:"asyncExpression",value:n,evaluate:function(e){return{asyncWrapper:true,value:this.value.evaluate(e)}}};return i}else{return e.parseElement("logicalExpression",r)}}));t.addGrammarElement("expression",(function(e,t,r){r.matchToken("the");return e.parseElement("asyncExpression",r)}));t.addGrammarElement("assignableExpression",(function(e,t,r){r.matchToken("the");var n=e.parseElement("primaryExpression",r);if(n&&(n.type==="symbol"||n.type==="ofExpression"||n.type==="propertyAccess"||n.type==="attributeRefAccess"||n.type==="attributeRef"||n.type==="styleRef"||n.type==="arrayIndex"||n.type==="possessive")){return n}else{e.raiseParseError(r,"A target expression must be writable. The expression type '"+(n&&n.type)+"' is not.")}return n}));t.addGrammarElement("hyperscript",(function(e,t,r){var n=[];if(r.hasMore()){while(e.featureStart(r.currentToken())||r.currentToken().value==="("){var i=e.requireElement("feature",r);n.push(i);r.matchToken("end")}}return{type:"hyperscript",features:n,apply:function(e,t,r){for(const i of n){i.install(e,t,r)}}}}));var v=function(e){var t=[];if(e.token(0).value==="("&&(e.token(1).value===")"||e.token(2).value===","||e.token(2).value===")")){e.matchOpToken("(");do{t.push(e.requireTokenType("IDENTIFIER"))}while(e.matchOpToken(","));e.requireOpToken(")")}return t};t.addFeature("on",(function(e,t,r){if(!r.matchToken("on"))return;var n=false;if(r.matchToken("every")){n=true}var i=[];var a=null;do{var o=e.requireElement("eventName",r,"Expected event name");var s=o.evaluate();if(a){a=a+" or "+s}else{a="on "+s}var u=v(r);var l=null;if(r.matchOpToken("[")){l=e.requireElement("expression",r);r.requireOpToken("]")}var c,f,m;if(r.currentToken().type==="NUMBER"){var p=r.consumeToken();if(!p.value)return;c=parseInt(p.value);if(r.matchToken("to")){var h=r.consumeToken();if(!h.value)return;f=parseInt(h.value)}else if(r.matchToken("and")){m=true;r.requireToken("on")}}var d,E;if(s==="intersection"){d={};if(r.matchToken("with")){d["with"]=e.requireElement("expression",r).evaluate()}if(r.matchToken("having")){do{if(r.matchToken("margin")){d["rootMargin"]=e.requireElement("stringLike",r).evaluate()}else if(r.matchToken("threshold")){d["threshold"]=e.requireElement("expression",r).evaluate()}else{e.raiseParseError(r,"Unknown intersection config specification")}}while(r.matchToken("and"))}}else if(s==="mutation"){E={};if(r.matchToken("of")){do{if(r.matchToken("anything")){E["attributes"]=true;E["subtree"]=true;E["characterData"]=true;E["childList"]=true}else if(r.matchToken("childList")){E["childList"]=true}else if(r.matchToken("attributes")){E["attributes"]=true;E["attributeOldValue"]=true}else if(r.matchToken("subtree")){E["subtree"]=true}else if(r.matchToken("characterData")){E["characterData"]=true;E["characterDataOldValue"]=true}else if(r.currentToken().type==="ATTRIBUTE_REF"){var T=r.consumeToken();if(E["attributeFilter"]==null){E["attributeFilter"]=[]}if(T.value.indexOf("@")==0){E["attributeFilter"].push(T.value.substring(1))}else{e.raiseParseError(r,"Only shorthand attribute references are allowed here")}}else{e.raiseParseError(r,"Unknown mutation config specification")}}while(r.matchToken("or"))}else{E["attributes"]=true;E["characterData"]=true;E["childList"]=true}}var y=null;var k=false;if(r.matchToken("from")){if(r.matchToken("elsewhere")){k=true}else{r.pushFollow("or");try{y=e.requireElement("expression",r)}finally{r.popFollow()}if(!y){e.raiseParseError(r,'Expected either target value or "elsewhere".')}}}if(y===null&&k===false&&r.matchToken("elsewhere")){k=true}if(r.matchToken("in")){var x=e.parseElement("unaryExpression",r)}if(r.matchToken("debounced")){r.requireToken("at");var g=e.requireElement("unaryExpression",r);var b=g.evaluate({})}else if(r.matchToken("throttled")){r.requireToken("at");var g=e.requireElement("unaryExpression",r);var w=g.evaluate({})}i.push({execCount:0,every:n,on:s,args:u,filter:l,from:y,inExpr:x,elsewhere:k,startCount:c,endCount:f,unbounded:m,debounceTime:b,throttleTime:w,mutationSpec:E,intersectionSpec:d,debounced:undefined,lastExec:undefined})}while(r.matchToken("or"));var S=true;if(!n){if(r.matchToken("queue")){if(r.matchToken("all")){var N=true;var S=false}else if(r.matchToken("first")){var q=true}else if(r.matchToken("none")){var I=true}else{r.requireToken("last")}}}var C=e.requireElement("commandList",r);e.ensureTerminated(C);var R,A;if(r.matchToken("catch")){R=r.requireTokenType("IDENTIFIER").value;A=e.requireElement("commandList",r);e.ensureTerminated(A)}if(r.matchToken("finally")){var L=e.requireElement("commandList",r);e.ensureTerminated(L)}var O={displayName:a,events:i,start:C,every:n,execCount:0,errorHandler:A,errorSymbol:R,execute:function(e){let r=t.getEventQueueFor(e.me,O);if(r.executing&&n===false){if(I||q&&r.queue.length>0){return}if(S){r.queue.length=0}r.queue.push(e);return}O.execCount++;r.executing=true;e.meta.onHalt=function(){r.executing=false;var e=r.queue.shift();if(e){setTimeout((function(){O.execute(e)}),1)}};e.meta.reject=function(r){console.error(r.message?r.message:r);var n=t.getHyperTrace(e,r);if(n){n.print()}t.triggerEvent(e.me,"exception",{error:r})};C.execute(e)},install:function(e,r){for(const r of O.events){var n;if(r.elsewhere){n=[document]}else if(r.from){n=r.from.evaluate(t.makeContext(e,O,e,null))}else{n=[e]}t.implicitLoop(n,(function(n){var i=r.on;if(n==null){console.warn("'%s' feature ignored because target does not exists:",a,e);return}if(r.mutationSpec){i="hyperscript:mutation";const e=new MutationObserver((function(e,r){if(!O.executing){t.triggerEvent(n,i,{mutationList:e,observer:r})}}));e.observe(n,r.mutationSpec)}if(r.intersectionSpec){i="hyperscript:intersection";const e=new IntersectionObserver((function(r){for(const o of r){var a={observer:e};a=Object.assign(a,o);a["intersecting"]=o.isIntersecting;t.triggerEvent(n,i,a)}}),r.intersectionSpec);e.observe(n)}var o=n.addEventListener||n.on;o.call(n,i,(function a(o){if(typeof Node!=="undefined"&&e instanceof Node&&n!==e&&!e.isConnected){n.removeEventListener(i,a);return}var s=t.makeContext(e,O,e,o);if(r.elsewhere&&e.contains(o.target)){return}if(r.from){s.result=n}for(const e of r.args){let t=s.event[e.value];if(t!==undefined){s.locals[e.value]=t}else if("detail"in s.event){s.locals[e.value]=s.event["detail"][e.value]}}s.meta.errorHandler=A;s.meta.errorSymbol=R;s.meta.finallyHandler=L;if(r.filter){var u=s.meta.context;s.meta.context=s.event;try{var l=r.filter.evaluate(s);if(l){}else{return}}finally{s.meta.context=u}}if(r.inExpr){var c=o.target;while(true){if(c.matches&&c.matches(r.inExpr.css)){s.result=c;break}else{c=c.parentElement;if(c==null){return}}}}r.execCount++;if(r.startCount){if(r.endCount){if(r.execCountr.endCount){return}}else if(r.unbounded){if(r.execCount{var a=false;for(const s of i){var o=n=>{e.result=n;if(s.args){for(const t of s.args){e.locals[t.value]=n[t.value]||(n.detail?n.detail[t.value]:null)}}if(!a){a=true;r(t.findNext(this,e))}};if(s.name){n.addEventListener(s.name,o,{once:true})}else if(s.time!=null){setTimeout(o,s.time,s.time)}}}))}};return n}else{var s;if(r.matchToken("a")){r.requireToken("tick");s=0}else{s=e.requireElement("expression",r)}n={type:"waitCmd",time:s,args:[s],op:function(e,r){return new Promise((n=>{setTimeout((()=>{n(t.findNext(this,e))}),r)}))},execute:function(e){return t.unifiedExec(this,e)}};return n}}));t.addGrammarElement("dotOrColonPath",(function(e,t,r){var n=r.matchTokenType("IDENTIFIER");if(n){var i=[n.value];var a=r.matchOpToken(".")||r.matchOpToken(":");if(a){do{i.push(r.requireTokenType("IDENTIFIER","NUMBER").value)}while(r.matchOpToken(a.value))}return{type:"dotOrColonPath",path:i,evaluate:function(){return i.join(a?a.value:"")}}}}));t.addGrammarElement("eventName",(function(e,t,r){var n;if(n=r.matchTokenType("STRING")){return{evaluate:function(){return n.value}}}return e.parseElement("dotOrColonPath",r)}));function d(e,t,r,n){var i=t.requireElement("eventName",n);var a=t.parseElement("namedArgumentList",n);if(e==="send"&&n.matchToken("to")||e==="trigger"&&n.matchToken("on")){var o=t.requireElement("expression",n)}else{var o=t.requireElement("implicitMeTarget",n)}var s={eventName:i,details:a,to:o,args:[o,i,a],op:function(e,t,n,i){r.nullCheck(t,o);r.implicitLoop(t,(function(t){r.triggerEvent(t,n,i,e.me)}));return r.findNext(s,e)}};return s}t.addCommand("trigger",(function(e,t,r){if(r.matchToken("trigger")){return d("trigger",e,t,r)}}));t.addCommand("send",(function(e,t,r){if(r.matchToken("send")){return d("send",e,t,r)}}));var T=function(e,t,r,n){if(n){if(e.commandBoundary(r.currentToken())){e.raiseParseError(r,"'return' commands must return a value. If you do not wish to return a value, use 'exit' instead.")}else{var i=e.requireElement("expression",r)}}var a={value:i,args:[i],op:function(e,r){var n=e.meta.resolve;e.meta.returned=true;e.meta.returnValue=r;if(n){if(r){n(r)}else{n()}}return t.HALT}};return a};t.addCommand("return",(function(e,t,r){if(r.matchToken("return")){return T(e,t,r,true)}}));t.addCommand("exit",(function(e,t,r){if(r.matchToken("exit")){return T(e,t,r,false)}}));t.addCommand("halt",(function(e,t,r){if(r.matchToken("halt")){if(r.matchToken("the")){r.requireToken("event");if(r.matchOpToken("'")){r.requireToken("s")}var n=true}if(r.matchToken("bubbling")){var i=true}else if(r.matchToken("default")){var a=true}var o=T(e,t,r,false);var s={keepExecuting:true,bubbling:i,haltDefault:a,exit:o,op:function(e){if(e.event){if(i){e.event.stopPropagation()}else if(a){e.event.preventDefault()}else{e.event.stopPropagation();e.event.preventDefault()}if(n){return t.findNext(this,e)}else{return o}}}};return s}}));t.addCommand("log",(function(e,t,r){if(!r.matchToken("log"))return;var n=[e.parseElement("expression",r)];while(r.matchOpToken(",")){n.push(e.requireElement("expression",r))}if(r.matchToken("with")){var i=e.requireElement("expression",r)}var a={exprs:n,withExpr:i,args:[i,n],op:function(e,r,n){if(r){r.apply(null,n)}else{console.log.apply(null,n)}return t.findNext(this,e)}};return a}));t.addCommand("beep!",(function(e,t,r){if(!r.matchToken("beep!"))return;var n=[e.parseElement("expression",r)];while(r.matchOpToken(",")){n.push(e.requireElement("expression",r))}var i={exprs:n,args:[n],op:function(e,r){for(let i=0;i{if(!r.matchToken("pick"))return;r.matchToken("the");if(r.matchToken("item")||r.matchToken("items")||r.matchToken("character")||r.matchToken("characters")){const n=g(e,t,r);r.requireToken("from");const i=e.requireElement("expression",r);return{args:[i,n.from,n.to],op(e,r,i,a){if(n.toEnd)a=r.length;if(!n.includeStart)i++;if(n.includeEnd)a++;if(a==null||a==undefined)a=i+1;e.result=r.slice(i,a);return t.findNext(this,e)}}}if(r.matchToken("match")){r.matchToken("of");const n=e.parseElement("expression",r);let i="";if(r.matchOpToken("|")){i=r.requireToken("identifier").value}r.requireToken("from");const a=e.parseElement("expression",r);return{args:[a,n],op(e,r,n){e.result=new RegExp(n,i).exec(r);return t.findNext(this,e)}}}if(r.matchToken("matches")){r.matchToken("of");const n=e.parseElement("expression",r);let i="gu";if(r.matchOpToken("|")){i="g"+r.requireToken("identifier").value.replace("g","")}console.log("flags",i);r.requireToken("from");const a=e.parseElement("expression",r);return{args:[a,n],op(e,r,n){e.result=new w(n,i,r);return t.findNext(this,e)}}}}));t.addCommand("increment",(function(e,t,r){if(!r.matchToken("increment"))return;var n;var i=e.parseElement("assignableExpression",r);if(r.matchToken("by")){n=e.requireElement("expression",r)}var a={type:"implicitIncrementOp",target:i,args:[i,n],op:function(e,t,r){t=t?parseFloat(t):0;r=n?parseFloat(r):1;var i=t+r;e.result=i;return i},evaluate:function(e){return t.unifiedEval(this,e)}};return k(e,t,r,i,a)}));t.addCommand("decrement",(function(e,t,r){if(!r.matchToken("decrement"))return;var n;var i=e.parseElement("assignableExpression",r);if(r.matchToken("by")){n=e.requireElement("expression",r)}var a={type:"implicitDecrementOp",target:i,args:[i,n],op:function(e,t,r){t=t?parseFloat(t):0;r=n?parseFloat(r):1;var i=t-r;e.result=i;return i},evaluate:function(e){return t.unifiedEval(this,e)}};return k(e,t,r,i,a)}));function S(e,t){var r="text";var n;e.matchToken("a")||e.matchToken("an");if(e.matchToken("json")||e.matchToken("Object")){r="json"}else if(e.matchToken("response")){r="response"}else if(e.matchToken("html")){r="html"}else if(e.matchToken("text")){}else{n=t.requireElement("dotOrColonPath",e).evaluate()}return{type:r,conversion:n}}t.addCommand("fetch",(function(e,t,r){if(!r.matchToken("fetch"))return;var n=e.requireElement("stringLike",r);if(r.matchToken("as")){var i=S(r,e)}if(r.matchToken("with")&&r.currentToken().value!=="{"){var a=e.parseElement("nakedNamedArgumentList",r)}else{var a=e.parseElement("objectLiteral",r)}if(i==null&&r.matchToken("as")){i=S(r,e)}var o=i?i.type:"text";var s=i?i.conversion:null;var u={url:n,argExpressions:a,args:[n,a],op:function(e,r,n){var i=n||{};i["sender"]=e.me;i["headers"]=i["headers"]||{};var a=new AbortController;let l=e.me.addEventListener("fetch:abort",(function(){a.abort()}),{once:true});i["signal"]=a.signal;t.triggerEvent(e.me,"hyperscript:beforeFetch",i);t.triggerEvent(e.me,"fetch:beforeRequest",i);n=i;var c=false;if(n.timeout){setTimeout((function(){if(!c){a.abort()}}),n.timeout)}return fetch(r,n).then((function(r){let n={response:r};t.triggerEvent(e.me,"fetch:afterResponse",n);r=n.response;if(o==="response"){e.result=r;t.triggerEvent(e.me,"fetch:afterRequest",{result:r});c=true;return t.findNext(u,e)}if(o==="json"){return r.json().then((function(r){e.result=r;t.triggerEvent(e.me,"fetch:afterRequest",{result:r});c=true;return t.findNext(u,e)}))}return r.text().then((function(r){if(s)r=t.convertValue(r,s);if(o==="html")r=t.convertValue(r,"Fragment");e.result=r;t.triggerEvent(e.me,"fetch:afterRequest",{result:r});c=true;return t.findNext(u,e)}))})).catch((function(r){t.triggerEvent(e.me,"fetch:error",{reason:r});throw r})).finally((function(){e.me.removeEventListener("fetch:abort",l)}))}};return u}))}function y(e){e.addCommand("settle",(function(e,t,r){if(r.matchToken("settle")){if(!e.commandBoundary(r.currentToken())){var n=e.requireElement("expression",r)}else{var n=e.requireElement("implicitMeTarget",r)}var i={type:"settleCmd",args:[n],op:function(e,r){t.nullCheck(r,n);var a=null;var o=false;var s=false;var u=new Promise((function(e){a=e}));r.addEventListener("transitionstart",(function(){s=true}),{once:true});setTimeout((function(){if(!s&&!o){a(t.findNext(i,e))}}),500);r.addEventListener("transitionend",(function(){if(!o){a(t.findNext(i,e))}}),{once:true});return u},execute:function(e){return t.unifiedExec(this,e)}};return i}}));e.addCommand("add",(function(e,t,r){if(r.matchToken("add")){var n=e.parseElement("classRef",r);var i=null;var a=null;if(n==null){i=e.parseElement("attributeRef",r);if(i==null){a=e.parseElement("styleLiteral",r);if(a==null){e.raiseParseError(r,"Expected either a class reference or attribute expression")}}}else{var o=[n];while(n=e.parseElement("classRef",r)){o.push(n)}}if(r.matchToken("to")){var s=e.requireElement("expression",r)}else{var s=e.requireElement("implicitMeTarget",r)}if(r.matchToken("when")){if(a){e.raiseParseError(r,"Only class and properties are supported with a when clause")}var u=e.requireElement("expression",r)}if(o){return{classRefs:o,to:s,args:[s,o],op:function(e,r,n){t.nullCheck(r,s);t.forEach(n,(function(n){t.implicitLoop(r,(function(r){if(u){e.result=r;let i=t.evaluateNoPromise(u,e);if(i){if(r instanceof Element)r.classList.add(n.className)}else{if(r instanceof Element)r.classList.remove(n.className)}e.result=null}else{if(r instanceof Element)r.classList.add(n.className)}}))}));return t.findNext(this,e)}}}else if(i){return{type:"addCmd",attributeRef:i,to:s,args:[s],op:function(e,r,n){t.nullCheck(r,s);t.implicitLoop(r,(function(r){if(u){e.result=r;let n=t.evaluateNoPromise(u,e);if(n){r.setAttribute(i.name,i.value)}else{r.removeAttribute(i.name)}e.result=null}else{r.setAttribute(i.name,i.value)}}));return t.findNext(this,e)},execute:function(e){return t.unifiedExec(this,e)}}}else{return{type:"addCmd",cssDeclaration:a,to:s,args:[s,a],op:function(e,r,n){t.nullCheck(r,s);t.implicitLoop(r,(function(e){e.style.cssText+=n}));return t.findNext(this,e)},execute:function(e){return t.unifiedExec(this,e)}}}}}));e.addGrammarElement("styleLiteral",(function(e,t,r){if(!r.matchOpToken("{"))return;var n=[""];var i=[];while(r.hasMore()){if(r.matchOpToken("\\")){r.consumeToken()}else if(r.matchOpToken("}")){break}else if(r.matchToken("$")){var a=r.matchOpToken("{");var o=e.parseElement("expression",r);if(a)r.requireOpToken("}");i.push(o);n.push("")}else{var s=r.consumeToken();n[n.length-1]+=r.source.substring(s.start,s.end)}n[n.length-1]+=r.lastWhitespace()}return{type:"styleLiteral",args:[i],op:function(e,t){var r="";n.forEach((function(e,n){r+=e;if(n in t)r+=t[n]}));return r},evaluate:function(e){return t.unifiedEval(this,e)}}}));e.addCommand("remove",(function(e,t,r){if(r.matchToken("remove")){var n=e.parseElement("classRef",r);var i=null;var a=null;if(n==null){i=e.parseElement("attributeRef",r);if(i==null){a=e.parseElement("expression",r);if(a==null){e.raiseParseError(r,"Expected either a class reference, attribute expression or value expression")}}}else{var o=[n];while(n=e.parseElement("classRef",r)){o.push(n)}}if(r.matchToken("from")){var s=e.requireElement("expression",r)}else{if(a==null){var s=e.requireElement("implicitMeTarget",r)}}if(a){return{elementExpr:a,from:s,args:[a,s],op:function(e,r,n){t.nullCheck(r,a);t.implicitLoop(r,(function(e){if(e.parentElement&&(n==null||n.contains(e))){e.parentElement.removeChild(e)}}));return t.findNext(this,e)}}}else{return{classRefs:o,attributeRef:i,elementExpr:a,from:s,args:[o,s],op:function(e,r,n){t.nullCheck(n,s);if(r){t.forEach(r,(function(e){t.implicitLoop(n,(function(t){t.classList.remove(e.className)}))}))}else{t.implicitLoop(n,(function(e){e.removeAttribute(i.name)}))}return t.findNext(this,e)}}}}}));e.addCommand("toggle",(function(e,t,r){if(r.matchToken("toggle")){r.matchAnyToken("the","my");if(r.currentToken().type==="STYLE_REF"){let t=r.consumeToken();var n=t.value.substr(1);var a=true;var o=i(e,r,n);if(r.matchToken("of")){r.pushFollow("with");try{var s=e.requireElement("expression",r)}finally{r.popFollow()}}else{var s=e.requireElement("implicitMeTarget",r)}}else if(r.matchToken("between")){var u=true;var l=e.parseElement("classRef",r);r.requireToken("and");var c=e.requireElement("classRef",r)}else{var l=e.parseElement("classRef",r);var f=null;if(l==null){f=e.parseElement("attributeRef",r);if(f==null){e.raiseParseError(r,"Expected either a class reference or attribute expression")}}else{var m=[l];while(l=e.parseElement("classRef",r)){m.push(l)}}}if(a!==true){if(r.matchToken("on")){var s=e.requireElement("expression",r)}else{var s=e.requireElement("implicitMeTarget",r)}}if(r.matchToken("for")){var p=e.requireElement("expression",r)}else if(r.matchToken("until")){var h=e.requireElement("dotOrColonPath",r,"Expected event name");if(r.matchToken("from")){var v=e.requireElement("expression",r)}}var d={classRef:l,classRef2:c,classRefs:m,attributeRef:f,on:s,time:p,evt:h,from:v,toggle:function(e,r,n,i){t.nullCheck(e,s);if(a){t.implicitLoop(e,(function(e){o("toggle",e)}))}else if(u){t.implicitLoop(e,(function(e){if(e.classList.contains(r.className)){e.classList.remove(r.className);e.classList.add(n.className)}else{e.classList.add(r.className);e.classList.remove(n.className)}}))}else if(i){t.forEach(i,(function(r){t.implicitLoop(e,(function(e){e.classList.toggle(r.className)}))}))}else{t.implicitLoop(e,(function(e){if(e.hasAttribute(f.name)){e.removeAttribute(f.name)}else{e.setAttribute(f.name,f.value)}}))}},args:[s,p,h,v,l,c,m],op:function(e,r,n,i,a,o,s,u){if(n){return new Promise((function(i){d.toggle(r,o,s,u);setTimeout((function(){d.toggle(r,o,s,u);i(t.findNext(d,e))}),n)}))}else if(i){return new Promise((function(n){var l=a||e.me;l.addEventListener(i,(function(){d.toggle(r,o,s,u);n(t.findNext(d,e))}),{once:true});d.toggle(r,o,s,u)}))}else{this.toggle(r,o,s,u);return t.findNext(d,e)}}};return d}}));var t={display:function(r,n,i){if(i){n.style.display=i}else if(r==="toggle"){if(getComputedStyle(n).display==="none"){t.display("show",n,i)}else{t.display("hide",n,i)}}else if(r==="hide"){const t=e.runtime.getInternalData(n);if(t.originalDisplay==null){t.originalDisplay=n.style.display}n.style.display="none"}else{const t=e.runtime.getInternalData(n);if(t.originalDisplay&&t.originalDisplay!=="none"){n.style.display=t.originalDisplay}else{n.style.removeProperty("display")}}},visibility:function(e,r,n){if(n){r.style.visibility=n}else if(e==="toggle"){if(getComputedStyle(r).visibility==="hidden"){t.visibility("show",r,n)}else{t.visibility("hide",r,n)}}else if(e==="hide"){r.style.visibility="hidden"}else{r.style.visibility="visible"}},opacity:function(e,r,n){if(n){r.style.opacity=n}else if(e==="toggle"){if(getComputedStyle(r).opacity==="0"){t.opacity("show",r,n)}else{t.opacity("hide",r,n)}}else if(e==="hide"){r.style.opacity="0"}else{r.style.opacity="1"}}};var n=function(e,t,r){var n;var i=r.currentToken();if(i.value==="when"||i.value==="with"||e.commandBoundary(i)){n=e.parseElement("implicitMeTarget",r)}else{n=e.parseElement("expression",r)}return n};var i=function(e,n,i){var a=r.defaultHideShowStrategy;var o=t;if(r.hideShowStrategies){o=Object.assign(o,r.hideShowStrategies)}i=i||a||"display";var s=o[i];if(s==null){e.raiseParseError(n,"Unknown show/hide strategy : "+i)}return s};e.addCommand("hide",(function(e,t,r){if(r.matchToken("hide")){var a=n(e,t,r);var o=null;if(r.matchToken("with")){o=r.requireTokenType("IDENTIFIER","STYLE_REF").value;if(o.indexOf("*")===0){o=o.substr(1)}}var s=i(e,r,o);return{target:a,args:[a],op:function(e,r){t.nullCheck(r,a);t.implicitLoop(r,(function(e){s("hide",e)}));return t.findNext(this,e)}}}}));e.addCommand("show",(function(e,t,r){if(r.matchToken("show")){var a=n(e,t,r);var o=null;if(r.matchToken("with")){o=r.requireTokenType("IDENTIFIER","STYLE_REF").value;if(o.indexOf("*")===0){o=o.substr(1)}}var s=null;if(r.matchOpToken(":")){var u=r.consumeUntilWhitespace();r.matchTokenType("WHITESPACE");s=u.map((function(e){return e.value})).join("")}if(r.matchToken("when")){var l=e.requireElement("expression",r)}var c=i(e,r,o);return{target:a,when:l,args:[a],op:function(e,r){t.nullCheck(r,a);t.implicitLoop(r,(function(r){if(l){e.result=r;let n=t.evaluateNoPromise(l,e);if(n){c("show",r,s)}else{c("hide",r)}e.result=null}else{c("show",r,s)}}));return t.findNext(this,e)}}}}));e.addCommand("take",(function(e,t,r){if(r.matchToken("take")){let u=null;let l=[];while(u=e.parseElement("classRef",r)){l.push(u)}var n=null;var i=null;let c=l.length>0;if(!c){n=e.parseElement("attributeRef",r);if(n==null){e.raiseParseError(r,"Expected either a class reference or attribute expression")}if(r.matchToken("with")){i=e.requireElement("expression",r)}}if(r.matchToken("from")){var a=e.requireElement("expression",r)}if(r.matchToken("for")){var o=e.requireElement("expression",r)}else{var o=e.requireElement("implicitMeTarget",r)}if(c){var s={classRefs:l,from:a,forElt:o,args:[l,a,o],op:function(e,r,n,i){t.nullCheck(i,o);t.implicitLoop(r,(function(e){var r=e.className;if(n){t.implicitLoop(n,(function(e){e.classList.remove(r)}))}else{t.implicitLoop(e,(function(e){e.classList.remove(r)}))}t.implicitLoop(i,(function(e){e.classList.add(r)}))}));return t.findNext(this,e)}};return s}else{var s={attributeRef:n,from:a,forElt:o,args:[a,o,i],op:function(e,r,i,s){t.nullCheck(r,a);t.nullCheck(i,o);t.implicitLoop(r,(function(e){if(!s){e.removeAttribute(n.name)}else{e.setAttribute(n.name,s)}}));t.implicitLoop(i,(function(e){e.setAttribute(n.name,n.value||"")}));return t.findNext(this,e)}};return s}}}));function a(t,r,n,i){if(n!=null){var a=t.resolveSymbol(n,r)}else{var a=r}if(a instanceof Element||a instanceof HTMLDocument){while(a.firstChild)a.removeChild(a.firstChild);a.append(e.runtime.convertValue(i,"Fragment"));t.processNode(a)}else{if(n!=null){t.setSymbol(n,r,null,i)}else{throw"Don't know how to put a value into "+typeof r}}}e.addCommand("put",(function(e,t,r){if(r.matchToken("put")){var n=e.requireElement("expression",r);var i=r.matchAnyToken("into","before","after");if(i==null&&r.matchToken("at")){r.matchToken("the");i=r.matchAnyToken("start","end");r.requireToken("of")}if(i==null){e.raiseParseError(r,"Expected one of 'into', 'before', 'at start of', 'at end of', 'after'")}var o=e.requireElement("expression",r);var s=i.value;var u=false;var l=false;var c=null;var f=null;if(o.type==="arrayIndex"&&s==="into"){u=true;f=o.prop;c=o.root}else if(o.prop&&o.root&&s==="into"){f=o.prop.value;c=o.root}else if(o.type==="symbol"&&s==="into"){l=true;f=o.name}else if(o.type==="attributeRef"&&s==="into"){var m=true;f=o.name;c=e.requireElement("implicitMeTarget",r)}else if(o.type==="styleRef"&&s==="into"){var p=true;f=o.name;c=e.requireElement("implicitMeTarget",r)}else if(o.attribute&&s==="into"){var m=o.attribute.type==="attributeRef";var p=o.attribute.type==="styleRef";f=o.attribute.name;c=o.root}else{c=o}var h={target:o,operation:s,symbolWrite:l,value:n,args:[c,f,n],op:function(e,r,n,i){if(l){a(t,e,n,i)}else{t.nullCheck(r,c);if(s==="into"){if(m){t.implicitLoop(r,(function(e){e.setAttribute(n,i)}))}else if(p){t.implicitLoop(r,(function(e){e.style[n]=i}))}else if(u){r[n]=i}else{t.implicitLoop(r,(function(e){a(t,e,n,i)}))}}else{var o=s==="before"?Element.prototype.before:s==="after"?Element.prototype.after:s==="start"?Element.prototype.prepend:s==="end"?Element.prototype.append:Element.prototype.append;t.implicitLoop(r,(function(e){o.call(e,i instanceof Node?i:t.convertValue(i,"Fragment"));if(e.parentElement){t.processNode(e.parentElement)}else{t.processNode(e)}}))}}return t.findNext(this,e)}};return h}}));function o(e,t,r){var n;if(r.matchToken("the")||r.matchToken("element")||r.matchToken("elements")||r.currentToken().type==="CLASS_REF"||r.currentToken().type==="ID_REF"||r.currentToken().op&&r.currentToken().value==="<"){e.possessivesDisabled=true;try{n=e.parseElement("expression",r)}finally{delete e.possessivesDisabled}if(r.matchOpToken("'")){r.requireToken("s")}}else if(r.currentToken().type==="IDENTIFIER"&&r.currentToken().value==="its"){var i=r.matchToken("its");n={type:"pseudopossessiveIts",token:i,name:i.value,evaluate:function(e){return t.resolveSymbol("it",e)}}}else{r.matchToken("my")||r.matchToken("me");n=e.parseElement("implicitMeTarget",r)}return n}e.addCommand("transition",(function(e,t,n){if(n.matchToken("transition")){var i=o(e,t,n);var a=[];var s=[];var u=[];var l=n.currentToken();while(!e.commandBoundary(l)&&l.value!=="over"&&l.value!=="using"){if(n.currentToken().type==="STYLE_REF"){let e=n.consumeToken();let t=e.value.substr(1);a.push({type:"styleRefValue",evaluate:function(){return t}})}else{a.push(e.requireElement("stringLike",n))}if(n.matchToken("from")){s.push(e.requireElement("expression",n))}else{s.push(null)}n.requireToken("to");if(n.matchToken("initial")){u.push({type:"initial_literal",evaluate:function(){return"initial"}})}else{u.push(e.requireElement("expression",n))}l=n.currentToken()}if(n.matchToken("over")){var c=e.requireElement("expression",n)}else if(n.matchToken("using")){var f=e.requireElement("expression",n)}var m={to:u,args:[i,a,s,u,f,c],op:function(e,n,a,o,s,u,l){t.nullCheck(n,i);var c=[];t.implicitLoop(n,(function(e){var n=new Promise((function(n,i){var c=e.style.transition;if(l){e.style.transition="all "+l+"ms ease-in"}else if(u){e.style.transition=u}else{e.style.transition=r.defaultTransition}var f=t.getInternalData(e);var m=getComputedStyle(e);var p={};for(var h=0;he.forEach((e=>S(e))))).then((()=>n((function(){a();k.processNode(document.documentElement);e.document.addEventListener("htmx:load",(function(e){k.processNode(e.detail.elt)}))}))));function n(e){if(document.readyState!=="loading"){setTimeout(e)}else{document.addEventListener("DOMContentLoaded",e)}}function i(){var e=document.querySelector('meta[name="htmx-config"]');if(e){return v(e.content)}else{return null}}function a(){var e=i();if(e){Object.assign(r,e)}}}const S=Object.assign(b,{config:r,use(e){e(S)},internals:{lexer:x,parser:g,runtime:k,Lexer:n,Tokens:i,Parser:a,Runtime:o},ElementCollection:m,addFeature:g.addFeature.bind(g),addCommand:g.addCommand.bind(g),addLeafExpression:g.addLeafExpression.bind(g),addIndirectExpression:g.addIndirectExpression.bind(g),evaluate:k.evaluate.bind(k),parse:k.parse.bind(k),processNode:k.processNode.bind(k),version:"0.9.13",browserInit:w});return S})); diff --git a/types.go b/types.go new file mode 100644 index 0000000..bc5f18c --- /dev/null +++ b/types.go @@ -0,0 +1,20 @@ +package frm + +import ( + "encoding/json" + + "github.com/acaloiaro/frm/internal" +) + +// Form is a form +type Form internal.Form + +// JSON returns the form's JSON-seralized string representation +func (f Form) JSON() string { + b, err := json.Marshal(f) + if err != nil { + return "" + } + + return string(b) +} diff --git a/types/fieldlogiccomparator_enumer.go b/types/fieldlogiccomparator_enumer.go new file mode 100644 index 0000000..d8ec9fe --- /dev/null +++ b/types/fieldlogiccomparator_enumer.go @@ -0,0 +1,108 @@ +// Code generated by "enumer -type FieldLogicComparator -trimprefix FieldLogicComparator -transform=snake -json -text"; DO NOT EDIT. + +package types + +import ( + "encoding/json" + "fmt" + "strings" +) + +const _FieldLogicComparatorName = "equalcontains" + +var _FieldLogicComparatorIndex = [...]uint8{0, 5, 13} + +const _FieldLogicComparatorLowerName = "equalcontains" + +func (i FieldLogicComparator) String() string { + if i < 0 || i >= FieldLogicComparator(len(_FieldLogicComparatorIndex)-1) { + return fmt.Sprintf("FieldLogicComparator(%d)", i) + } + return _FieldLogicComparatorName[_FieldLogicComparatorIndex[i]:_FieldLogicComparatorIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _FieldLogicComparatorNoOp() { + var x [1]struct{} + _ = x[FieldLogicComparatorEqual-(0)] + _ = x[FieldLogicComparatorContains-(1)] +} + +var _FieldLogicComparatorValues = []FieldLogicComparator{FieldLogicComparatorEqual, FieldLogicComparatorContains} + +var _FieldLogicComparatorNameToValueMap = map[string]FieldLogicComparator{ + _FieldLogicComparatorName[0:5]: FieldLogicComparatorEqual, + _FieldLogicComparatorLowerName[0:5]: FieldLogicComparatorEqual, + _FieldLogicComparatorName[5:13]: FieldLogicComparatorContains, + _FieldLogicComparatorLowerName[5:13]: FieldLogicComparatorContains, +} + +var _FieldLogicComparatorNames = []string{ + _FieldLogicComparatorName[0:5], + _FieldLogicComparatorName[5:13], +} + +// FieldLogicComparatorString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func FieldLogicComparatorString(s string) (FieldLogicComparator, error) { + if val, ok := _FieldLogicComparatorNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _FieldLogicComparatorNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to FieldLogicComparator values", s) +} + +// FieldLogicComparatorValues returns all values of the enum +func FieldLogicComparatorValues() []FieldLogicComparator { + return _FieldLogicComparatorValues +} + +// FieldLogicComparatorStrings returns a slice of all String values of the enum +func FieldLogicComparatorStrings() []string { + strs := make([]string, len(_FieldLogicComparatorNames)) + copy(strs, _FieldLogicComparatorNames) + return strs +} + +// IsAFieldLogicComparator returns "true" if the value is listed in the enum definition. "false" otherwise +func (i FieldLogicComparator) IsAFieldLogicComparator() bool { + for _, v := range _FieldLogicComparatorValues { + if i == v { + return true + } + } + return false +} + +// MarshalJSON implements the json.Marshaler interface for FieldLogicComparator +func (i FieldLogicComparator) MarshalJSON() ([]byte, error) { + return json.Marshal(i.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for FieldLogicComparator +func (i *FieldLogicComparator) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return fmt.Errorf("FieldLogicComparator should be a string, got %s", data) + } + + var err error + *i, err = FieldLogicComparatorString(s) + return err +} + +// MarshalText implements the encoding.TextMarshaler interface for FieldLogicComparator +func (i FieldLogicComparator) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface for FieldLogicComparator +func (i *FieldLogicComparator) UnmarshalText(text []byte) error { + var err error + *i, err = FieldLogicComparatorString(string(text)) + return err +} diff --git a/types/fieldlogictriggeraction_enumer.go b/types/fieldlogictriggeraction_enumer.go new file mode 100644 index 0000000..4c0fa54 --- /dev/null +++ b/types/fieldlogictriggeraction_enumer.go @@ -0,0 +1,104 @@ +// Code generated by "enumer -type FieldLogicTriggerAction -trimprefix FieldLogicTriggerAction -transform=snake -json -text"; DO NOT EDIT. + +package types + +import ( + "encoding/json" + "fmt" + "strings" +) + +const _FieldLogicTriggerActionName = "field_logic_trigger_show" + +var _FieldLogicTriggerActionIndex = [...]uint8{0, 24} + +const _FieldLogicTriggerActionLowerName = "field_logic_trigger_show" + +func (i FieldLogicTriggerAction) String() string { + if i < 0 || i >= FieldLogicTriggerAction(len(_FieldLogicTriggerActionIndex)-1) { + return fmt.Sprintf("FieldLogicTriggerAction(%d)", i) + } + return _FieldLogicTriggerActionName[_FieldLogicTriggerActionIndex[i]:_FieldLogicTriggerActionIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _FieldLogicTriggerActionNoOp() { + var x [1]struct{} + _ = x[FieldLogicTriggerShow-(0)] +} + +var _FieldLogicTriggerActionValues = []FieldLogicTriggerAction{FieldLogicTriggerShow} + +var _FieldLogicTriggerActionNameToValueMap = map[string]FieldLogicTriggerAction{ + _FieldLogicTriggerActionName[0:24]: FieldLogicTriggerShow, + _FieldLogicTriggerActionLowerName[0:24]: FieldLogicTriggerShow, +} + +var _FieldLogicTriggerActionNames = []string{ + _FieldLogicTriggerActionName[0:24], +} + +// FieldLogicTriggerActionString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func FieldLogicTriggerActionString(s string) (FieldLogicTriggerAction, error) { + if val, ok := _FieldLogicTriggerActionNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _FieldLogicTriggerActionNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to FieldLogicTriggerAction values", s) +} + +// FieldLogicTriggerActionValues returns all values of the enum +func FieldLogicTriggerActionValues() []FieldLogicTriggerAction { + return _FieldLogicTriggerActionValues +} + +// FieldLogicTriggerActionStrings returns a slice of all String values of the enum +func FieldLogicTriggerActionStrings() []string { + strs := make([]string, len(_FieldLogicTriggerActionNames)) + copy(strs, _FieldLogicTriggerActionNames) + return strs +} + +// IsAFieldLogicTriggerAction returns "true" if the value is listed in the enum definition. "false" otherwise +func (i FieldLogicTriggerAction) IsAFieldLogicTriggerAction() bool { + for _, v := range _FieldLogicTriggerActionValues { + if i == v { + return true + } + } + return false +} + +// MarshalJSON implements the json.Marshaler interface for FieldLogicTriggerAction +func (i FieldLogicTriggerAction) MarshalJSON() ([]byte, error) { + return json.Marshal(i.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for FieldLogicTriggerAction +func (i *FieldLogicTriggerAction) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return fmt.Errorf("FieldLogicTriggerAction should be a string, got %s", data) + } + + var err error + *i, err = FieldLogicTriggerActionString(s) + return err +} + +// MarshalText implements the encoding.TextMarshaler interface for FieldLogicTriggerAction +func (i FieldLogicTriggerAction) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface for FieldLogicTriggerAction +func (i *FieldLogicTriggerAction) UnmarshalText(text []byte) error { + var err error + *i, err = FieldLogicTriggerActionString(string(text)) + return err +} diff --git a/types/formfieldtype_enumer.go b/types/formfieldtype_enumer.go new file mode 100644 index 0000000..8b445f1 --- /dev/null +++ b/types/formfieldtype_enumer.go @@ -0,0 +1,104 @@ +// Code generated by "enumer -type FormFieldType -trimprefix FormFieldType -transform=snake -json"; DO NOT EDIT. + +package types + +import ( + "encoding/json" + "fmt" + "strings" +) + +const _FormFieldTypeName = "text_singletext_multiplesingle_selectmulti_select" + +var _FormFieldTypeIndex = [...]uint8{0, 11, 24, 37, 49} + +const _FormFieldTypeLowerName = "text_singletext_multiplesingle_selectmulti_select" + +func (i FormFieldType) String() string { + if i < 0 || i >= FormFieldType(len(_FormFieldTypeIndex)-1) { + return fmt.Sprintf("FormFieldType(%d)", i) + } + return _FormFieldTypeName[_FormFieldTypeIndex[i]:_FormFieldTypeIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _FormFieldTypeNoOp() { + var x [1]struct{} + _ = x[FormFieldTypeTextSingle-(0)] + _ = x[FormFieldTypeTextMultiple-(1)] + _ = x[FormFieldTypeSingleSelect-(2)] + _ = x[FormFieldTypeMultiSelect-(3)] +} + +var _FormFieldTypeValues = []FormFieldType{FormFieldTypeTextSingle, FormFieldTypeTextMultiple, FormFieldTypeSingleSelect, FormFieldTypeMultiSelect} + +var _FormFieldTypeNameToValueMap = map[string]FormFieldType{ + _FormFieldTypeName[0:11]: FormFieldTypeTextSingle, + _FormFieldTypeLowerName[0:11]: FormFieldTypeTextSingle, + _FormFieldTypeName[11:24]: FormFieldTypeTextMultiple, + _FormFieldTypeLowerName[11:24]: FormFieldTypeTextMultiple, + _FormFieldTypeName[24:37]: FormFieldTypeSingleSelect, + _FormFieldTypeLowerName[24:37]: FormFieldTypeSingleSelect, + _FormFieldTypeName[37:49]: FormFieldTypeMultiSelect, + _FormFieldTypeLowerName[37:49]: FormFieldTypeMultiSelect, +} + +var _FormFieldTypeNames = []string{ + _FormFieldTypeName[0:11], + _FormFieldTypeName[11:24], + _FormFieldTypeName[24:37], + _FormFieldTypeName[37:49], +} + +// FormFieldTypeString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func FormFieldTypeString(s string) (FormFieldType, error) { + if val, ok := _FormFieldTypeNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _FormFieldTypeNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to FormFieldType values", s) +} + +// FormFieldTypeValues returns all values of the enum +func FormFieldTypeValues() []FormFieldType { + return _FormFieldTypeValues +} + +// FormFieldTypeStrings returns a slice of all String values of the enum +func FormFieldTypeStrings() []string { + strs := make([]string, len(_FormFieldTypeNames)) + copy(strs, _FormFieldTypeNames) + return strs +} + +// IsAFormFieldType returns "true" if the value is listed in the enum definition. "false" otherwise +func (i FormFieldType) IsAFormFieldType() bool { + for _, v := range _FormFieldTypeValues { + if i == v { + return true + } + } + return false +} + +// MarshalJSON implements the json.Marshaler interface for FormFieldType +func (i FormFieldType) MarshalJSON() ([]byte, error) { + return json.Marshal(i.String()) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for FormFieldType +func (i *FormFieldType) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return fmt.Errorf("FormFieldType should be a string, got %s", data) + } + + var err error + *i, err = FormFieldTypeString(s) + return err +} diff --git a/types/types.go b/types/types.go new file mode 100644 index 0000000..cbb9cf6 --- /dev/null +++ b/types/types.go @@ -0,0 +1,138 @@ +package types + +import ( + "encoding/json" + + "github.com/google/uuid" +) + +// FormFieldType enum enumerates all possible form field types +// +//go:generate enumer -type FormFieldType -trimprefix FormFieldType -transform=snake -json +type FormFieldType int + +const ( + FormFieldTypeTextSingle FormFieldType = iota // single line of text + FormFieldTypeTextMultiple // multiple lines of text + FormFieldTypeSingleSelect // single-select dropdown + FormFieldTypeMultiSelect // multi-select dropdown +) + +// FieldLogicComparator enum enumerates all possible form field logic comparators +// +//go:generate enumer -type FieldLogicComparator -trimprefix FieldLogicComparator -transform=snake -json -text +type FieldLogicComparator int + +const ( + FieldLogicComparatorEqual FieldLogicComparator = iota // target field value is equal to the subject value + FieldLogicComparatorContains // target field value contains the subject value +) + +// FieldLogicTriggerAction enum enumerates all possible field logic trigger actions +// +//go:generate enumer -type FieldLogicTriggerAction -trimprefix FieldLogicTriggerAction -transform=snake -json -text +type FieldLogicTriggerAction int + +const ( + FieldLogicTriggerShow FieldLogicTriggerAction = iota // show the field in the to the user +) + +// FormFields is a collection of form fields associated with a Form +// +// The underlying type is a map, where keys are form field IDs and values are the corresponding form field +type FormFields map[string]FormField + +// FieldOptions are options for single or multi-selector fields +type FieldOptions []Option + +// FormField is a field associated with a form +type FormField struct { + ID uuid.UUID `json:"id"` // field's unique id + Order int `json:"order"` // order in which the field appears on forms + Label string `json:"label"` // field's label (name) + Logic *FieldLogic `json:"logic"` // UI logic for this field + Options FieldOptions `json:"options"` // single/multi-select options + Placeholder string `json:"placeholder"` // placeholder value + Required bool `json:"required"` // whether the field is required + Hidden bool `json:"hidden"` // whether the field is hidden + Type FormFieldType `json:"type"` // field type +} + +// FieldLogic defines logic associated with a field +type FieldLogic struct { + TargetFieldID uuid.UUID `json:"target_field_id"` // ID of the field to monitor for logic evaluation + TriggerComparator FieldLogicComparator `json:"field_comparator"` // comparator to use evaluating target field's value with trigger values + TriggerValues []string `json:"trigger_values"` // values that target field's value is compared with + TriggerActions FieldLogicTriggerActions `json:"actions"` // actions to take when the field comparator evaluates true +} + +type FieldLogicTriggerActions []FieldLogicTriggerAction + +// Contains determines whether FieldLogicTriggerActions contains some other trigger action +func (f FieldLogicTriggerActions) Contains(a FieldLogicTriggerAction) bool { + for _, ta := range f { + if ta == a { + return true + } + } + return false +} + +func (f *FieldLogic) Configured() bool { + return f.TargetFieldID != uuid.Nil && len(f.TriggerValues) > 0 && len(f.TriggerActions) > 0 +} + +// Option is a select option (single and multi) +type Option struct { + ID uuid.UUID `json:"id"` + Value string `json:"value"` + Label string `json:"label"` + Selected bool `json:"-"` + Disabled bool `json:"-"` +} + +// FormFieldSortByOrder implements sort.Interface for []FormField based on +// the Order field. +type FormFieldSortByOrder []FormField + +func (f FormFieldSortByOrder) Len() int { return len(f) } +func (f FormFieldSortByOrder) Swap(i, j int) { f[i], f[j] = f[j], f[i] } +func (f FormFieldSortByOrder) Less(i, j int) bool { return f[i].Order < f[j].Order } + +// MarshalJSON implements the json.Marshaler interface for FormFieldType +func (f FormField) MarshalJSON() ([]byte, error) { + id := uuid.Nil + if f.ID != id { + id = f.ID + } + + d := struct { + ID uuid.UUID `json:"id"` // field's unique id + Order int `json:"order"` // order in which the field appears on forms + Label string `json:"label"` // field's label (name) + Logic *FieldLogic `json:"logic"` + Options FieldOptions `json:"options"` // single/multi-select options + Placeholder string `json:"placeholder"` // placeholder value + Required bool `json:"required"` // whether the field is required + Hidden bool `json:"hidden"` // whether the field is hidden + Type FormFieldType `json:"type"` // field type + }{ + + ID: id, + Order: f.Order, + Label: f.Label, + Options: f.Options, + Placeholder: f.Placeholder, + Required: f.Required, + Hidden: f.Hidden, + Type: f.Type, + } + + if f.Logic != nil && f.Logic.Configured() { + d.Logic = f.Logic + } else { + d.Logic = nil + } + + return json.Marshal(d) +} diff --git a/ui/common.templ b/ui/common.templ new file mode 100644 index 0000000..5bab5fe --- /dev/null +++ b/ui/common.templ @@ -0,0 +1,914 @@ +package ui + +import ( + "fmt" + "strings" + "context" + "github.com/acaloiaro/frm" + "github.com/acaloiaro/frm/ui/selector" + "github.com/acaloiaro/frm/handlers" + "sort" + "github.com/acaloiaro/frm/types" + "encoding/json" + "github.com/google/uuid" + "slices" +) + +var loadDependenciesOnce = templ.NewOnceHandle() + +// General settings +const ( + ApplicationName = "frm" +) + +// Application DOM events +const ( + // FieldsFormEvent is the event triggered when any of a form's fields have been updated in the UI. When triggered, + // the fields form pushes updates from the UI to the draft form on the backend. + FieldsFormUpdateEvent = "fields-form-updated" + // FormSettingsEvent is the event triggered when any of a form's settings have been updated in the UI. When triggered, + // the fields form pushes updates from the UI to the draft form on the backend. + FormSettingsUpdateEvent = "form-settings-updated" + // LogicConfiguratorTargetFieldSelected is the event triggered when a form field is selected as a the target for field logic + LogicConfiguratorTargetFieldSelected = "logic-configurator-target-field-selected" +) + +// Field groups +const ( + FieldGroupLogic = "logic" +) + +// Logic field group form field names +const ( + // FieldLogicChosenFieldID is the name of a HTML form field. The value of the form field with this name represents the field that was chosen as the target for field-specific logic. + // + // TODO: provide an example + FieldLogicTargetFieldID = "target_field_id" + // FieldLogicChosenField is the name of a HTML form field. The value of the form field represents the boolean comparator to be used to evaluate the chosen field against its field value. + // + // TODO: provide an example + FieldLogicComparator = "comparator" + // FieldLogicChosenFieldValue is the name of a HTML Form field. The value of the form field represents the value that the target field's value is compared against when deciding whether or not to display a field in the UI. + // + // TODO: provide an example + FieldLogicTargetFieldValue = "target_field_value" +) + +templ HeroIcon(style string, name string) { + +} + +type buttonArgs struct { + Type string // button type, e.g. 'button' or 'submit' + Label string // the label to show + Classes []string // additional css classes to apply to the button +} + +templ button(args buttonArgs, attrs templ.Attributes) { + +} + +templ mutedButton(args buttonArgs, attrs templ.Attributes) { +
+ { children... } + { args.Label } +
+} + +// FormBuilderNavTitle renders the title of the form in the nav bar. This is a separate template so that the title can be updated when settings change, without updating, and losing the state of, the rest of the nav bar +templ FormBuilderNavTitle(form frm.Form) { +
+

+ { form.Name } +

+
+} + +// FormBuilderNav is the top-of-the-page navigation bar +templ FormBuilderNav(form frm.Form) { +
+
+
+ @mutedButton(buttonArgs{Label: "Build", Classes: []string{"cursor-pointer tab-active [--fallback-p:white] [--fallback-pc:black] place-self-center"}}, templ.Attributes{ + "role": "tab", + "tabindex": 0, + "_": "on click take .tab-active from .tab-active then add .hidden to .active-section then take .active-section for #form-fields then remove .hidden from #form-fields", + }) + @mutedButton(buttonArgs{Label: "Settings", Classes: []string{"cursor-pointer [--fallback-p:white] [--fallback-pc:black] place-self-center"}}, templ.Attributes{ + "role": "tab", + "tabindex": 2, + "_": "on click take .tab-active from .tab-active then add .hidden to .active-section take .active-section for #settings-main then remove .hidden from #settings-main", + }) +
+
+ @FormBuilderNavTitle(form) +
+
+ +
+
+ +
+
+
+} + +// SafePath returns mountpoint-aware SafeURL paths for the given path +func SafePath(ctx context.Context, path string) templ.SafeURL { + return templ.SafeURL(fmt.Sprintf("%s%s", ctx.Value(handlers.MountPointContextKey).(string), path)) +} + +// Path returns mountpoint-aware string paths for the given path +func Path(ctx context.Context, path string) string { + return fmt.Sprintf("%s%s", ctx.Value(handlers.MountPointContextKey).(string), path) +} + +// head simply provides the element +templ head(pageTitle string) { + + { ApplicationName } :: { pageTitle } + + + @loadDependenciesOnce.Once() { + + + + + + + + + + } + +} + +templ footer() { + //
+} + +// App is the primary app with all chrome +templ App(pageTitle string) { + + + @head(pageTitle) + +
+
+ { children... } +
+ @footer() + + +} + +// Builder is the primary form builder UI, surrounded by the app chrome +templ Builder(form frm.Form) { + @App("Form builder") { +
+ @FormBuilderNav(form) +
+ + @builderColumnLeft(form) + + @FormPreview(form) + + @builderColumnRight(form) +
+
+ } +} + +// FormSettings is the UI for configuring form-level settings. +templ FormSettings(form frm.Form) { + +} + +// builderColumnLeft is the left-hand panel of the form builder UI +templ builderColumnLeft(form frm.Form) { +
+ @FormFields(form) + @FormSettings(form) +
+} + +// FormPreview previews a frm.Form +templ FormPreview(form frm.Form) { +
+
+
+
https://your-form-domain.com/form
+
+
+ @FormView(form, true) +
+
+
+} + +templ FieldTypeIcon(fieldType types.FormFieldType) { +
+ switch int(fieldType) { + case int(types.FormFieldTypeTextSingle), int(types.FormFieldTypeTextMultiple): + @HeroIcon("solid", "bars-3-bottom-left") + case int(types.FormFieldTypeSingleSelect), int(types.FormFieldTypeMultiSelect): + @HeroIcon("solid", "chevron-up-down") + } +
+} + +// FormFields lists a form's fields as a sortable list, that when re-sorted, updates the fields' sort order in the form +templ FormFields(form frm.Form) { +
+ @FormFieldsForm(form) +
+} + +templ FormFieldsForm(form frm.Form) { +
+ @button(buttonArgs{ + Label: "Add field", + Classes: []string{"flex-grow", "justify-center", "uppercase"}, + }, templ.Attributes{ + "_": "on click toggle .hidden on .active-configurator then take .active-configurator from .active-configurator for #configure-add-field then remove .hidden from #configure-add-field", + }) { + @HeroIcon("solid", "plus") + } +
+
+
+ for _, field := range sortFields(form.Fields) { +
+ +
+ + +
+
+

{ field.Label }

+
+
+
+ if field.Required { +
+ +
+ } +
+ @HeroIcon("solid", "bars-3") +
+
+
+ } +
+
+
+} + +templ requiredFieldIndicator() { + * +} + +// fieldTypeToDefaultValuesJSON converts field types to their devault values. +// This function takes a fieldType and converts it to the default values for that field type, +// and encodes it as a JSON string. +func fieldTypeToDefaultValuesJSON(fieldType types.FormFieldType) string { + label := "" + placeholder := "" + switch int(fieldType) { + case int(types.FormFieldTypeTextSingle), int(types.FormFieldTypeTextMultiple): + label = "New Text Field" + placeholder = "Enter some text" + case int(types.FormFieldTypeSingleSelect): + label = "New Single Select Field" + placeholder = "Choose An Item" + case int(types.FormFieldTypeMultiSelect): + label = "New Multi Select Field" + placeholder = "Choose Items" + } + + field := types.FormField{ + Label: label, + Placeholder: placeholder, + Required: false, + Hidden: false, + Type: fieldType, + } + json, err := json.Marshal(field) + if err != nil { + return "" + } + return string(json) +} + +// builerColumnRight is the right-hand panel of the form build UI, used for adding and configuring fields +templ builderColumnRight(form frm.Form) { +
+ + @FormFieldConfigurator(form) +
+} + +func formUrl[T string | templ.SafeURL](ctx context.Context, form frm.Form, path ...string) T { + p := "" + if len(path) == 1 { + p = path[0] + } + return T(Path(ctx, fmt.Sprintf("/%d%s", form.ID, p))) +} + +templ FormFieldConfigurator(form frm.Form) { +
+ for _, field := range sortFields(form.Fields) { + + } +
+} + +templ fieldSettingsConfiguration(form frm.Form, field types.FormField) { +
+ + + +
+ + @requiredFieldIndicator() +
+ +
+ +
+ + if field.Type == types.FormFieldTypeSingleSelect || field.Type == types.FormFieldTypeMultiSelect { +
+ +
+ @selector.Selector(selector.SelectArgs{ + ID: fieldName(field, "", "options"), + Name: fieldName(field, "", "options"), + Placeholder: "Add, remove, or create new options", + Multiple: true, + EditItems: true, + Options: toSelectorOpts(field.Options, true), + SelectionChangeEvent: FieldsFormUpdateEvent, + }) + } +
+ +
+ 's checked to false + end + then trigger '%s'`, + fieldName(field, "","hidden"), FieldsFormUpdateEvent) } + /> +
+ +
+ 's checked to false + end + then trigger '%s'`, + fieldName(field, "","required"), FieldsFormUpdateEvent) } + /> +
+ +
+ @button(buttonArgs{Type: "button", Label: "Delete field"}, templ.Attributes{ + "data-hx-delete": formUrl[string](ctx, form, fmt.Sprintf("/fields/%s", field.ID)), + "data-hx-trigger": "click", + "data-hx-confirm": "Are you sure?", + }) +
+} + +templ fieldLogicConfiguration(form frm.Form, field types.FormField) { + +} + +// comparatorOptionsFor returns the comparators available for a logic field given its Type +func comparatorOptionsFor(field types.FormField) (options selector.FieldOptions) { + switch field.Type { + default: + options = selector.FieldOptions{ + selector.Option{ + Value: fmt.Sprint(types.FieldLogicComparatorEqual), + Label: "Equal to =", + Selected: field.Logic != nil && field.Logic.TriggerComparator == types.FieldLogicComparatorEqual, + }, + selector.Option{ + Value: fmt.Sprint(types.FieldLogicComparatorContains), + Label: "Contains", + Selected: field.Logic != nil && field.Logic.TriggerComparator == types.FieldLogicComparatorContains, + }, + } + } + + return +} + +// LogicConfiguratorStepThree returns HTML input elments appropriate for choosing values for `targetField` in the logic configurator. +// +// field: the field being configured +// targetField: the target field chosen as the logic target +templ LogicConfiguratorStepThree(form frm.Form, field types.FormField, targetField types.FormField) { + switch targetField.Type { + case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect: + @selector.Selector(selector.SelectArgs{ + ID: fmt.Sprintf("%s-logic-chosen-field-value", field.ID.String()), + Label: "", + Name: fieldName(field, FieldGroupLogic, FieldLogicTargetFieldValue), + Options: fieldOptionsAsSelectorOptions(form, targetField), + Placeholder: "Choose a value", + SelectionChangeEvent: FieldsFormUpdateEvent, + }) + case types.FormFieldTypeTextSingle, types.FormFieldTypeTextMultiple: + + } +} + +// fieldsAsSelector returns all of a form's fields as selector.Options to be used in a selector.Selector dropdown +// fieldID is the ID of the field for which the options are being rendered +func fieldsAsSelectorOptions(form frm.Form, fieldID uuid.UUID) (options []selector.Option) { + for _, field := range form.Fields { + // fields should not show themselves as options + if field.ID == fieldID { + continue + } + selected := false + for _, f := range form.Fields { + if f.Logic != nil && f.Logic.TargetFieldID == field.ID { + selected = true + } + } + options = append(options, selector.Option{ + ID: field.ID, + Label: field.Label, + Value: field.ID.String(), + Selected: selected, + }) + } + return +} + +// fieldOptionsAsSelectorOptions returns all of a field's FieldOptions as selector.Options +func fieldOptionsAsSelectorOptions(form frm.Form, field types.FormField) (options []selector.Option) { + for _, option := range field.Options { + selected := false + for _, f := range form.Fields { + if f.Logic != nil && slices.Contains(f.Logic.TriggerValues, option.ID.String()) { + selected = true + } + } + options = append(options, selector.Option{ + ID: option.ID, + Label: option.Label, + Value: option.ID.String(), + Selected: selected, + }) + } + return +} +func fieldName(field types.FormField, group, name string) string { + if group == "" { + return fmt.Sprintf("[%s]%s", field.ID.String(), name) + } + + return fmt.Sprintf("[%s][%s]%s", field.ID.String(), group, name) +} + +// formFieldTypeLabel is the UI label for FormFieldTypes, e.g. 'text_single' -> "Single line text" +templ formFieldTypeLabel(fieldType types.FormFieldType) { +
+ @FieldTypeIcon(types.FormFieldType(fieldType)) + +
+} + +templ fieldLabel(field types.FormField) { + +} + +// ViewerMetdata contains data needed by the viewer component. It is rendered to JSON and accessed via Javascript. +type ViewerMetadata struct { + Form frm.Form `json:"form"` +} + +func (v ViewerMetadata) JSON() string { + b, err := json.Marshal(v) + if err != nil { + return "{}" + } + + return string(b) +} + +// FormView renders forms +templ FormView(form frm.Form, isPreview bool) { +
+
+

+ { form.Name } +

+
+ for _, field := range sortFields(form.Fields) { + + } +
+ @button(buttonArgs{ + Label: "submit", + Type: "submit", + Classes: []string{"flex-grow", "justify-center", "uppercase"}, + }, templ.Attributes{ + "type": "submit", + "data-hx-post": fmt.Sprintf("/%d", form.ID), + "data-hx-trigger": "click", + "data-hx-swap": "none", + "disabled": true, + }, + ) +
+
+} + +func toSelectorOpts(opts []types.Option, selectAll bool) (sopts []selector.Option) { + for _, opt := range opts { + if selectAll { + opt.Selected = true + } + sopts = append(sopts, (selector.Option)(opt)) + } + + return +} + +// toFrmFields converts frm.FormFields (map[string]frm.FormField) --> []frm.FormField +func toFrmFields(fields types.FormFields) (ffields []types.FormField) { + for _, field := range fields { + ffields = append(ffields, (types.FormField)(field)) + } + return +} + +// sort form fields by Order +func sortFields(fields types.FormFields) (sorted []types.FormField) { + sorted = toFrmFields(fields) + sort.Sort(types.FormFieldSortByOrder(sorted)) + return +} diff --git a/ui/common_templ.go b/ui/common_templ.go new file mode 100644 index 0000000..9a2d0d6 --- /dev/null +++ b/ui/common_templ.go @@ -0,0 +1,2730 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.793 +package ui + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +import ( + "context" + "encoding/json" + "fmt" + "github.com/acaloiaro/frm" + "github.com/acaloiaro/frm/handlers" + "github.com/acaloiaro/frm/types" + "github.com/acaloiaro/frm/ui/selector" + "github.com/google/uuid" + "slices" + "sort" + "strings" +) + +var loadDependenciesOnce = templ.NewOnceHandle() + +// General settings +const ( + ApplicationName = "frm" +) + +// Application DOM events +const ( + // FieldsFormEvent is the event triggered when any of a form's fields have been updated in the UI. When triggered, + // the fields form pushes updates from the UI to the draft form on the backend. + FieldsFormUpdateEvent = "fields-form-updated" + // FormSettingsEvent is the event triggered when any of a form's settings have been updated in the UI. When triggered, + // the fields form pushes updates from the UI to the draft form on the backend. + FormSettingsUpdateEvent = "form-settings-updated" + // LogicConfiguratorTargetFieldSelected is the event triggered when a form field is selected as a the target for field logic + LogicConfiguratorTargetFieldSelected = "logic-configurator-target-field-selected" +) + +// Field groups +const ( + FieldGroupLogic = "logic" +) + +// Logic field group form field names +const ( + // FieldLogicChosenFieldID is the name of a HTML form field. The value of the form field with this name represents the field that was chosen as the target for field-specific logic. + // + // TODO: provide an example + FieldLogicTargetFieldID = "target_field_id" + // FieldLogicChosenField is the name of a HTML form field. The value of the form field represents the boolean comparator to be used to evaluate the chosen field against its field value. + // + // TODO: provide an example + FieldLogicComparator = "comparator" + // FieldLogicChosenFieldValue is the name of a HTML Form field. The value of the form field represents the value that the target field's value is compared against when deciding whether or not to display a field in the UI. + // + // TODO: provide an example + FieldLogicTargetFieldValue = "target_field_value" +) + +func HeroIcon(style string, name string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("https://unpkg.com/heroicons/20/%s/%s.svg", style, name)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 58, Col: 85} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +type buttonArgs struct { + Type string // button type, e.g. 'button' or 'submit' + Label string // the label to show + Classes []string // additional css classes to apply to the button +} + +func button(args buttonArgs, attrs templ.Attributes) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + var templ_7745c5c3_Var4 = []any{fmt.Sprintf("focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:cursor-not-allowed aria-disabled:opacity-75 flex-shrink-0 font-medium rounded-md text-sm gap-x-1.5 shadow-sm text-white dark:text-gray-900 bg-primary-500 hover:bg-primary-600 disabled:bg-primary-500 aria-disabled:bg-primary-500 dark:bg-primary-400 dark:hover:bg-primary-500 dark:disabled:bg-primary-400 dark:aria-disabled:bg-primary-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 dark:focus-visible:outline-primary-400 inline-flex items-center px-8 md:px-4 py-2 %s", strings.Join(args.Classes, " "))} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var4).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(args.Label) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 70, Col: 14} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func mutedButton(args buttonArgs, attrs templ.Attributes) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + var templ_7745c5c3_Var8 = []any{fmt.Sprintf("btn btn-sm text-black text-md bg-gray-50 focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:cursor-not-allowed aria-disabled:opacity-75 flex-shrink-0 font-medium rounded-md gap-x-1.5 shadow-sm dark:text-gray-900 bg-gray-100 hover:bg-gray-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 dark:focus-visible:outline-primary-400 inline-flex items-center px-8 md:px-4 py-2 %s", strings.Join(args.Classes, " "))} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var8).String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 1, Col: 0} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var7.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(args.Label) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 77, Col: 14} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// FormBuilderNavTitle renders the title of the form in the nav bar. This is a separate template so that the title can be updated when settings change, without updating, and losing the state of, the rest of the nav bar +func FormBuilderNavTitle(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var11 := templ.GetChildren(ctx) + if templ_7745c5c3_Var11 == nil { + templ_7745c5c3_Var11 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 85, Col: 14} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// FormBuilderNav is the top-of-the-page navigation bar +func FormBuilderNav(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var13 := templ.GetChildren(ctx) + if templ_7745c5c3_Var13 == nil { + templ_7745c5c3_Var13 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = mutedButton(buttonArgs{Label: "Build", Classes: []string{"cursor-pointer tab-active [--fallback-p:white] [--fallback-pc:black] place-self-center"}}, templ.Attributes{ + "role": "tab", + "tabindex": 0, + "_": "on click take .tab-active from .tab-active then add .hidden to .active-section then take .active-section for #form-fields then remove .hidden from #form-fields", + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = mutedButton(buttonArgs{Label: "Settings", Classes: []string{"cursor-pointer [--fallback-p:white] [--fallback-pc:black] place-self-center"}}, templ.Attributes{ + "role": "tab", + "tabindex": 2, + "_": "on click take .tab-active from .tab-active then add .hidden to .active-section take .active-section for #settings-main then remove .hidden from #settings-main", + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormBuilderNavTitle(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// SafePath returns mountpoint-aware SafeURL paths for the given path +func SafePath(ctx context.Context, path string) templ.SafeURL { + return templ.SafeURL(fmt.Sprintf("%s%s", ctx.Value(handlers.MountPointContextKey).(string), path)) +} + +// Path returns mountpoint-aware string paths for the given path +func Path(ctx context.Context, path string) string { + return fmt.Sprintf("%s%s", ctx.Value(handlers.MountPointContextKey).(string), path) +} + +// head simply provides the element +func head(pageTitle string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var14 := templ.GetChildren(ctx) + if templ_7745c5c3_Var14 == nil { + templ_7745c5c3_Var14 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(ApplicationName) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 135, Col: 26} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var16 string + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(pageTitle) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 135, Col: 43} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var17 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, "/css/styles.css")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 139, Col: 44} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, "/js/htmx.js")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 140, Col: 64} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var20 string + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 140, Col: 94} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 22) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var21 string + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, "/js/htmx-response-targets.js")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 141, Col: 81} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 23) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var22 string + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 141, Col: 111} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 24) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var23 string + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, "/js/hyperscript.js")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 142, Col: 71} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 25) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var24 string + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 142, Col: 101} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 26) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var25 string + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, "/js/choices.min.js")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 143, Col: 71} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 27) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var26 string + templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 143, Col: 101} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 28) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var27 string + templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 144, Col: 130} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 29) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var28 string + templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 145, Col: 119} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 30) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var29 string + templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, "/css/choices.min.css")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 229, Col: 66} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 31) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var30 string + templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(templ.GetNonce(ctx)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 229, Col: 96} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 32) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = loadDependenciesOnce.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var17), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 33) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func footer() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var31 := templ.GetChildren(ctx) + if templ_7745c5c3_Var31 == nil { + templ_7745c5c3_Var31 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + return templ_7745c5c3_Err + }) +} + +// App is the primary app with all chrome +func App(pageTitle string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var32 := templ.GetChildren(ctx) + if templ_7745c5c3_Var32 == nil { + templ_7745c5c3_Var32 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 34) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = head(pageTitle).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 35) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ_7745c5c3_Var32.Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 36) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = footer().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 37) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// Builder is the primary form builder UI, surrounded by the app chrome +func Builder(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var33 := templ.GetChildren(ctx) + if templ_7745c5c3_Var33 == nil { + templ_7745c5c3_Var33 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var34 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 38) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormBuilderNav(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 39) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = builderColumnLeft(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 40) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormPreview(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 41) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = builderColumnRight(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 42) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = App("Form builder").Render(templ.WithChildren(ctx, templ_7745c5c3_Var34), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// FormSettings is the UI for configuring form-level settings. +func FormSettings(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var35 := templ.GetChildren(ctx) + if templ_7745c5c3_Var35 == nil { + templ_7745c5c3_Var35 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 43) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var36 string + templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(formUrl[string](ctx, form, "/settings")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 275, Col: 56} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 44) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var37 string + templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(FormSettingsUpdateEvent) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 276, Col: 44} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 45) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = requiredFieldIndicator().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 46) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var38 string + templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 290, Col: 21} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 47) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var39 string + templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 600ms trigger '%s'", FormSettingsUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 293, Col: 88} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 48) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// builderColumnLeft is the left-hand panel of the form builder UI +func builderColumnLeft(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var40 := templ.GetChildren(ctx) + if templ_7745c5c3_Var40 == nil { + templ_7745c5c3_Var40 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 49) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormFields(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormSettings(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 50) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// FormPreview previews a frm.Form +func FormPreview(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var41 := templ.GetChildren(ctx) + if templ_7745c5c3_Var41 == nil { + templ_7745c5c3_Var41 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 51) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormView(form, true).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 52) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func FieldTypeIcon(fieldType types.FormFieldType) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var42 := templ.GetChildren(ctx) + if templ_7745c5c3_Var42 == nil { + templ_7745c5c3_Var42 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 53) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + switch int(fieldType) { + case int(types.FormFieldTypeTextSingle), int(types.FormFieldTypeTextMultiple): + templ_7745c5c3_Err = HeroIcon("solid", "bars-3-bottom-left").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case int(types.FormFieldTypeSingleSelect), int(types.FormFieldTypeMultiSelect): + templ_7745c5c3_Err = HeroIcon("solid", "chevron-up-down").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 54) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// FormFields lists a form's fields as a sortable list, that when re-sorted, updates the fields' sort order in the form +func FormFields(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var43 := templ.GetChildren(ctx) + if templ_7745c5c3_Var43 == nil { + templ_7745c5c3_Var43 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 55) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormFieldsForm(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 56) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func FormFieldsForm(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var44 := templ.GetChildren(ctx) + if templ_7745c5c3_Var44 == nil { + templ_7745c5c3_Var44 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 57) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Var45 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = HeroIcon("solid", "plus").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) + templ_7745c5c3_Err = button(buttonArgs{ + Label: "Add field", + Classes: []string{"flex-grow", "justify-center", "uppercase"}, + }, templ.Attributes{ + "_": "on click toggle .hidden on .active-configurator then take .active-configurator from .active-configurator for #configure-add-field then remove .hidden from #configure-add-field", + }).Render(templ.WithChildren(ctx, templ_7745c5c3_Var45), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 58) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var46 string + templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, fmt.Sprintf("/%d/fields/order", form.ID))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 351, Col: 68} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 59) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, field := range sortFields(form.Fields) { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 60) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var47 string + templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 360, Col: 65} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 61) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var48 string + templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on click add .hidden to .active-configurator then take .active-configurator from .active-configurator for #configure-%s then remove .hidden from #configure-%s", field.ID.String(), field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 366, Col: 223} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 62) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var49 string + templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(field.Label) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 370, Col: 65} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 63) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Required { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 64) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 65) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = HeroIcon("solid", "bars-3").Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 66) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 67) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func requiredFieldIndicator() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var50 := templ.GetChildren(ctx) + if templ_7745c5c3_Var50 == nil { + templ_7745c5c3_Var50 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 68) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// fieldTypeToDefaultValuesJSON converts field types to their devault values. +// This function takes a fieldType and converts it to the default values for that field type, +// and encodes it as a JSON string. +func fieldTypeToDefaultValuesJSON(fieldType types.FormFieldType) string { + label := "" + placeholder := "" + switch int(fieldType) { + case int(types.FormFieldTypeTextSingle), int(types.FormFieldTypeTextMultiple): + label = "New Text Field" + placeholder = "Enter some text" + case int(types.FormFieldTypeSingleSelect): + label = "New Single Select Field" + placeholder = "Choose An Item" + case int(types.FormFieldTypeMultiSelect): + label = "New Multi Select Field" + placeholder = "Choose Items" + } + + field := types.FormField{ + Label: label, + Placeholder: placeholder, + Required: false, + Hidden: false, + Type: fieldType, + } + json, err := json.Marshal(field) + if err != nil { + return "" + } + return string(json) +} + +// builerColumnRight is the right-hand panel of the form build UI, used for adding and configuring fields +func builderColumnRight(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var51 := templ.GetChildren(ctx) + if templ_7745c5c3_Var51 == nil { + templ_7745c5c3_Var51 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 69) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for i, fieldType := range types.FormFieldTypeValues() { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 70) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var52 string + templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(i)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 438, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 71) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var53 string + templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, fmt.Sprintf("/%d/fields", form.ID))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 441, Col: 68} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 72) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var54 string + templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(`{"field_type": "%s"}`, fieldType)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 443, Col: 69} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 73) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = formFieldTypeLabel(types.FormFieldType(fieldType)).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 74) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 75) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FormFieldConfigurator(form).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 76) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func formUrl[T string | templ.SafeURL](ctx context.Context, form frm.Form, path ...string) T { + p := "" + if len(path) == 1 { + p = path[0] + } + return T(Path(ctx, fmt.Sprintf("/%d%s", form.ID, p))) +} + +func FormFieldConfigurator(form frm.Form) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var55 := templ.GetChildren(ctx) + if templ_7745c5c3_Var55 == nil { + templ_7745c5c3_Var55 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 77) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var56 string + templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(formUrl[string](ctx, form, "/fields")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 468, Col: 53} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 78) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var57 string + templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(FieldsFormUpdateEvent) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 469, Col: 41} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 79) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, field := range sortFields(form.Fields) { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 80) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var58 string + templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("configure-%s", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 474, Col: 59} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 81) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = formFieldTypeLabel(types.FormFieldType(field.Type)).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 82) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var59 string + templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("configurator-tabs-%s", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 478, Col: 68} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 83) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = mutedButton(buttonArgs{Label: "Settings", Classes: []string{"cursor-pointer tab-active [--fallback-p:white] [--fallback-pc:black] place-self-center w-1/2"}}, templ.Attributes{ + "role": "tab", + "tabindex": 1, + "_": fmt.Sprintf("on click take .tab-active from <#configurator-tabs-%s .tab-active/> then add .hidden to #field-%s-logic then take .active-configurator-section from #field-%s-logic for #%s then remove .hidden from #%s", field.ID.String(), field.ID.String(), field.ID.String(), fmt.Sprintf("field-%s-settings", field.ID.String()), fmt.Sprintf("field-%s-settings", field.ID.String())), + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = mutedButton(buttonArgs{Label: "Logic", Classes: []string{"cursor-pointer [--fallback-p:white] [--fallback-pc:black] place-self-center w-1/2"}}, templ.Attributes{ + "role": "tab", + "tabindex": 2, + "_": fmt.Sprintf("on click take .tab-active from <#configurator-tabs-%s .tab-active/> then add .hidden to #field-%s-settings then take .active-configurator-section from #field-%s-settings for #%s then remove .hidden from #%s", field.ID.String(), field.ID.String(), field.ID.String(), fmt.Sprintf("field-%s-logic", field.ID.String()), fmt.Sprintf("field-%s-logic", field.ID.String())), + // "_": fmt.Sprintf("on click take .tab-active from <#configurator-tabs .tab-active/> then add .hidden to .active-form-fields-section then take .active-form-fields-section for #%s then remove .hidden from #%s", fmt.Sprintf("field-%s-logic", field.ID.String()), fmt.Sprintf("field-%s-logic", field.ID.String())), + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 84) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = fieldSettingsConfiguration(form, field).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 85) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = fieldLogicConfiguration(form, field).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 86) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 87) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func fieldSettingsConfiguration(form frm.Form, field types.FormField) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var60 := templ.GetChildren(ctx) + if templ_7745c5c3_Var60 == nil { + templ_7745c5c3_Var60 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 88) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var61 string + templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("field-%s-settings", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 503, Col: 62} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 89) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var62 string + templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "required")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 504, Col: 48} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 90) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var63 string + templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(field.Required)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 504, Col: 99} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var63)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 91) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var64 string + templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "hidden")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 505, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var64)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 92) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var65 string + templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(field.Hidden)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 505, Col: 95} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 93) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var66 string + templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "field_type")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 506, Col: 50} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var66)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 94) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var67 string + templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint(field.Type)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 506, Col: 97} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var67)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 95) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var68 string + templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "label")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 508, Col: 45} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 96) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = requiredFieldIndicator().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 97) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var69 string + templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "label")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 514, Col: 37} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var69)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 98) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var70 string + templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "label")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 515, Col: 39} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var70)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 99) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var71 string + templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.JoinStringErrs(field.Label) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 518, Col: 22} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var71)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 100) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var72 string + templ_7745c5c3_Var72, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 600ms trigger '%s'", FieldsFormUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 520, Col: 85} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var72)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 101) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var73 string + templ_7745c5c3_Var73, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "placeholder")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 523, Col: 51} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var73)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 102) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var74 string + templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "placeholder")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 528, Col: 43} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var74)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 103) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var75 string + templ_7745c5c3_Var75, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "placeholder")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 529, Col: 45} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var75)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 104) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var76 string + templ_7745c5c3_Var76, templ_7745c5c3_Err = templ.JoinStringErrs(field.Placeholder) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 532, Col: 28} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var76)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 105) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var77 string + templ_7745c5c3_Var77, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 600ms trigger '%s'", FieldsFormUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 534, Col: 85} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var77)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 106) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Type == types.FormFieldTypeSingleSelect || field.Type == types.FormFieldTypeMultiSelect { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 107) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var78 string + templ_7745c5c3_Var78, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "options")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 538, Col: 48} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var78)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 108) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = selector.Selector(selector.SelectArgs{ + ID: fieldName(field, "", "options"), + Name: fieldName(field, "", "options"), + Placeholder: "Add, remove, or create new options", + Multiple: true, + EditItems: true, + Options: toSelectorOpts(field.Options, true), + SelectionChangeEvent: FieldsFormUpdateEvent, + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 109) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var79 string + templ_7745c5c3_Var79, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "required")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 553, Col: 48} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var79)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 110) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var80 string + templ_7745c5c3_Var80, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "required")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 558, Col: 40} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var80)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 111) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var81 string + templ_7745c5c3_Var81, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "required")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 559, Col: 42} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var81)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 112) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Required { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 113) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 114) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var82 string + templ_7745c5c3_Var82, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(` + on click + if my.checked + set 's checked to false + end + then trigger '%s'`, + fieldName(field, "", "hidden"), FieldsFormUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 571, Col: 59} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var82)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 115) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var83 string + templ_7745c5c3_Var83, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "hidden")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 574, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var83)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 116) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var84 string + templ_7745c5c3_Var84, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "hidden")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 579, Col: 38} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var84)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 117) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var85 string + templ_7745c5c3_Var85, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, "", "hidden")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 580, Col: 40} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var85)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 118) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Hidden { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 119) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 120) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var86 string + templ_7745c5c3_Var86, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(` + on click + if my.checked + set 's checked to false + end + then trigger '%s'`, + fieldName(field, "", "required"), FieldsFormUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 592, Col: 61} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var86)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 121) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = button(buttonArgs{Type: "button", Label: "Delete field"}, templ.Attributes{ + "data-hx-delete": formUrl[string](ctx, form, fmt.Sprintf("/fields/%s", field.ID)), + "data-hx-trigger": "click", + "data-hx-confirm": "Are you sure?", + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 122) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func fieldLogicConfiguration(form frm.Form, field types.FormField) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var87 := templ.GetChildren(ctx) + if templ_7745c5c3_Var87 == nil { + templ_7745c5c3_Var87 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 123) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var88 string + templ_7745c5c3_Var88, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("field-%s-logic", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 608, Col: 59} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var88)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 124) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var89 string + templ_7745c5c3_Var89, templ_7745c5c3_Err = templ.JoinStringErrs(Path(ctx, fmt.Sprintf("/%d/logic_configurator/%s/step3", form.ID, field.ID.String()))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 611, Col: 103} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var89)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 125) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var90 string + templ_7745c5c3_Var90, templ_7745c5c3_Err = templ.JoinStringErrs(LogicConfiguratorTargetFieldSelected) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 612, Col: 58} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var90)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 126) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var91 string + templ_7745c5c3_Var91, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("#logic-field-value-chooser-%s", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 614, Col: 84} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var91)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 127) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = selector.Selector(selector.SelectArgs{ + ID: fmt.Sprintf("field-%s-logic-config-field-chooser", field.ID.String()), + Name: fieldName(field, FieldGroupLogic, FieldLogicTargetFieldID), + Placeholder: "Choose a field", + Options: fieldsAsSelectorOptions(form, field.ID), + SearchDisabled: true, + SelectionChangeEvent: LogicConfiguratorTargetFieldSelected, + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 128) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = selector.Selector(selector.SelectArgs{ + ID: fmt.Sprintf("field-%s-logic-config-condition-chooser", field.ID.String()), + Name: fieldName(field, FieldGroupLogic, FieldLogicComparator), + Placeholder: "Choose a condition", + Options: comparatorOptionsFor(field), + SearchDisabled: true, + SelectionChangeEvent: FieldsFormUpdateEvent, + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 129) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var92 string + templ_7745c5c3_Var92, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("logic-field-value-chooser-%s", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 639, Col: 71} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var92)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 130) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Logic != nil && field.Logic.TargetFieldID != uuid.Nil { + templ_7745c5c3_Err = LogicConfiguratorStepThree(form, field, form.Fields[field.Logic.TargetFieldID.String()]).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 131) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var93 string + templ_7745c5c3_Var93, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s-logic-action", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 649, Col: 58} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var93)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 132) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var94 string + templ_7745c5c3_Var94, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, FieldGroupLogic, types.FieldLogicTriggerShow.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 652, Col: 82} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var94)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 133) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Logic != nil && field.Logic.TriggerActions.Contains(types.FieldLogicTriggerShow) { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 134) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 135) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var95 string + templ_7745c5c3_Var95, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(` + on click + trigger '%s'`, + FieldsFormUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 659, Col: 28} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var95)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 136) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var96 string + templ_7745c5c3_Var96, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s-logic-action", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 661, Col: 65} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var96)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 137) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// comparatorOptionsFor returns the comparators available for a logic field given its Type +func comparatorOptionsFor(field types.FormField) (options selector.FieldOptions) { + switch field.Type { + default: + options = selector.FieldOptions{ + selector.Option{ + Value: fmt.Sprint(types.FieldLogicComparatorEqual), + Label: "Equal to =", + Selected: field.Logic != nil && field.Logic.TriggerComparator == types.FieldLogicComparatorEqual, + }, + selector.Option{ + Value: fmt.Sprint(types.FieldLogicComparatorContains), + Label: "Contains", + Selected: field.Logic != nil && field.Logic.TriggerComparator == types.FieldLogicComparatorContains, + }, + } + } + + return +} + +// LogicConfiguratorStepThree returns HTML input elments appropriate for choosing values for `targetField` in the logic configurator. +// +// field: the field being configured +// targetField: the target field chosen as the logic target +func LogicConfiguratorStepThree(form frm.Form, field types.FormField, targetField types.FormField) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var97 := templ.GetChildren(ctx) + if templ_7745c5c3_Var97 == nil { + templ_7745c5c3_Var97 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + switch targetField.Type { + case types.FormFieldTypeMultiSelect, types.FormFieldTypeSingleSelect: + templ_7745c5c3_Err = selector.Selector(selector.SelectArgs{ + ID: fmt.Sprintf("%s-logic-chosen-field-value", field.ID.String()), + Label: "", + Name: fieldName(field, FieldGroupLogic, FieldLogicTargetFieldValue), + Options: fieldOptionsAsSelectorOptions(form, targetField), + Placeholder: "Choose a value", + SelectionChangeEvent: FieldsFormUpdateEvent, + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case types.FormFieldTypeTextSingle, types.FormFieldTypeTextMultiple: + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 138) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var98 string + templ_7745c5c3_Var98, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%s-logic-chosen-field-value", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 704, Col: 70} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var98)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 139) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var99 string + templ_7745c5c3_Var99, templ_7745c5c3_Err = templ.JoinStringErrs(fieldName(field, FieldGroupLogic, FieldLogicTargetFieldValue)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 705, Col: 72} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var99)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 140) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Logic != nil && field.Logic.TriggerValues[0] != "" { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 141) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var100 string + templ_7745c5c3_Var100, templ_7745c5c3_Err = templ.JoinStringErrs(field.Logic.TriggerValues[0]) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 710, Col: 41} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var100)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 142) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 143) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var101 string + templ_7745c5c3_Var101, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 600ms trigger '%s'", FieldsFormUpdateEvent)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 712, Col: 86} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var101)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 144) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + return templ_7745c5c3_Err + }) +} + +// fieldsAsSelector returns all of a form's fields as selector.Options to be used in a selector.Selector dropdown +// fieldID is the ID of the field for which the options are being rendered +func fieldsAsSelectorOptions(form frm.Form, fieldID uuid.UUID) (options []selector.Option) { + for _, field := range form.Fields { + // fields should not show themselves as options + if field.ID == fieldID { + continue + } + selected := false + for _, f := range form.Fields { + if f.Logic != nil && f.Logic.TargetFieldID == field.ID { + selected = true + } + } + options = append(options, selector.Option{ + ID: field.ID, + Label: field.Label, + Value: field.ID.String(), + Selected: selected, + }) + } + return +} + +// fieldOptionsAsSelectorOptions returns all of a field's FieldOptions as selector.Options +func fieldOptionsAsSelectorOptions(form frm.Form, field types.FormField) (options []selector.Option) { + for _, option := range field.Options { + selected := false + for _, f := range form.Fields { + if f.Logic != nil && slices.Contains(f.Logic.TriggerValues, option.ID.String()) { + selected = true + } + } + options = append(options, selector.Option{ + ID: option.ID, + Label: option.Label, + Value: option.ID.String(), + Selected: selected, + }) + } + return +} +func fieldName(field types.FormField, group, name string) string { + if group == "" { + return fmt.Sprintf("[%s]%s", field.ID.String(), name) + } + + return fmt.Sprintf("[%s][%s]%s", field.ID.String(), group, name) +} + +// formFieldTypeLabel is the UI label for FormFieldTypes, e.g. 'text_single' -> "Single line text" +func formFieldTypeLabel(fieldType types.FormFieldType) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var102 := templ.GetChildren(ctx) + if templ_7745c5c3_Var102 == nil { + templ_7745c5c3_Var102 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 145) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = FieldTypeIcon(types.FormFieldType(fieldType)).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 146) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + switch int(fieldType) { + case int(types.FormFieldTypeTextSingle): + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 147) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case int(types.FormFieldTypeTextMultiple): + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 148) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case int(types.FormFieldTypeSingleSelect): + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 149) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case int(types.FormFieldTypeMultiSelect): + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 150) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + default: + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 151) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 152) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func fieldLabel(field types.FormField) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var103 := templ.GetChildren(ctx) + if templ_7745c5c3_Var103 == nil { + templ_7745c5c3_Var103 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 153) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var104 string + templ_7745c5c3_Var104, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 791, Col: 31} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var104)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 154) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var105 string + templ_7745c5c3_Var105, templ_7745c5c3_Err = templ.JoinStringErrs(field.Label) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 792, Col: 15} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var105)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 155) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Required { + templ_7745c5c3_Err = requiredFieldIndicator().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 156) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +// ViewerMetdata contains data needed by the viewer component. It is rendered to JSON and accessed via Javascript. +type ViewerMetadata struct { + Form frm.Form `json:"form"` +} + +func (v ViewerMetadata) JSON() string { + b, err := json.Marshal(v) + if err != nil { + return "{}" + } + + return string(b) +} + +// FormView renders forms +func FormView(form frm.Form, isPreview bool) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var106 := templ.GetChildren(ctx) + if templ_7745c5c3_Var106 == nil { + templ_7745c5c3_Var106 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 157) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var107 string + templ_7745c5c3_Var107, templ_7745c5c3_Err = templ.JoinStringErrs(ViewerMetadata{Form: form}.JSON()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 818, Col: 48} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var107)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 158) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var108 string + templ_7745c5c3_Var108, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 821, Col: 14} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var108)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 159) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var109 templ.SafeURL = templ.SafeURL(fmt.Sprintf("/%d", form.ID)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var109))) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 160) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, field := range sortFields(form.Fields) { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 161) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var110 string + templ_7745c5c3_Var110, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("field-container-%s", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 829, Col: 62} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var110)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 162) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Hidden { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 163) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 164) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 165) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + switch field.Type { + case types.FormFieldTypeTextSingle: + templ_7745c5c3_Err = fieldLabel(field).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 166) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var111 string + templ_7745c5c3_Var111, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 840, Col: 30} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var111)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 167) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var112 string + templ_7745c5c3_Var112, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 841, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var112)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 168) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var113 string + templ_7745c5c3_Var113, templ_7745c5c3_Err = templ.JoinStringErrs(field.Placeholder) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 842, Col: 39} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var113)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 169) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var114 string + templ_7745c5c3_Var114, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 250ms trigger field_change(field_id: '%s', value: my.value)", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 845, Col: 127} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var114)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 170) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case types.FormFieldTypeTextMultiple: + templ_7745c5c3_Err = fieldLabel(field).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 171) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var115 string + templ_7745c5c3_Var115, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 850, Col: 30} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var115)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 172) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var116 string + templ_7745c5c3_Var116, templ_7745c5c3_Err = templ.JoinStringErrs(field.ID.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 851, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var116)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 173) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var117 string + templ_7745c5c3_Var117, templ_7745c5c3_Err = templ.JoinStringErrs(field.Placeholder) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 854, Col: 39} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var117)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 174) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var118 string + templ_7745c5c3_Var118, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("on keyup debounced at 250ms trigger field_change(field_id: '%s', value: my.value)", field.ID.String())) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/common.templ`, Line: 857, Col: 127} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var118)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 175) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + case types.FormFieldTypeSingleSelect, types.FormFieldTypeMultiSelect: + templ_7745c5c3_Err = selector.Selector(selector.SelectArgs{ + ID: field.ID.String(), + Name: field.ID.String(), + Label: field.Label, + Required: field.Required, + Placeholder: field.Placeholder, + Multiple: field.Type == types.FormFieldTypeMultiSelect, + Options: toSelectorOpts(field.Options, false), + Hyperscript: fmt.Sprintf("on change trigger field_change(field_id: '%s', value: my.value)", field.ID.String()), + }).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 176) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 177) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = button(buttonArgs{ + Label: "submit", + Type: "submit", + Classes: []string{"flex-grow", "justify-center", "uppercase"}, + }, templ.Attributes{ + "type": "submit", + "data-hx-post": fmt.Sprintf("/%d", form.ID), + "data-hx-trigger": "click", + "data-hx-swap": "none", + "disabled": true, + }, + ).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 178) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func toSelectorOpts(opts []types.Option, selectAll bool) (sopts []selector.Option) { + for _, opt := range opts { + if selectAll { + opt.Selected = true + } + sopts = append(sopts, (selector.Option)(opt)) + } + + return +} + +// toFrmFields converts frm.FormFields (map[string]frm.FormField) --> []frm.FormField +func toFrmFields(fields types.FormFields) (ffields []types.FormField) { + for _, field := range fields { + ffields = append(ffields, (types.FormField)(field)) + } + return +} + +// sort form fields by Order +func sortFields(fields types.FormFields) (sorted []types.FormField) { + sorted = toFrmFields(fields) + sort.Sort(types.FormFieldSortByOrder(sorted)) + return +} + +var _ = templruntime.GeneratedTemplate diff --git a/ui/common_templ.txt b/ui/common_templ.txt new file mode 100644 index 0000000..ef92868 --- /dev/null +++ b/ui/common_templ.txt @@ -0,0 +1,178 @@ + + +
+
+

+

+
+
+
+ + :: + + + + +
+
+ +
+
+ + +
+
+
+
+
+
https://your-form-domain.com/form
+
+
+
+
+
+
+
+

+

+
+
+
+
+* +
Add field
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+

Choose an action

+ +
+
+ +

+

+
+ + +
+
+
diff --git a/ui/css/tailwind.css b/ui/css/tailwind.css new file mode 100644 index 0000000..9f7d13a --- /dev/null +++ b/ui/css/tailwind.css @@ -0,0 +1,10 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* +globally kill the tailwind ring by default +*/ +input { + --tw-ring-shadow: 0 0 #000 !important; +} \ No newline at end of file diff --git a/ui/selector/selector.templ b/ui/selector/selector.templ new file mode 100644 index 0000000..f622781 --- /dev/null +++ b/ui/selector/selector.templ @@ -0,0 +1,238 @@ +// package selector provides a single and multi-slect HTML element powered by Choices.js +package selector + +import ( + "fmt" + "encoding/json" + "github.com/google/uuid" +) + +type FieldOptions []Option + +// Option is a select option +type Option struct { + ID uuid.UUID `json:"id"` + Value string `json:"value"` + Label string `json:"label"` + Selected bool `json:"selected"` + Disabled bool `json:"disabled"` +} + +// ContentID is the HTML element ID where content for this option is rendered when OptionsContent is rendered +func (i Option) ContentID() string { + return fmt.Sprintf("option-%s-content", i.ID) +} + +// SelectArgs are the arguments used to initialize selector.Selector +// +// ID: element ID for the element +// +// LabelClass: The CSS class(es) for the