From f7ad3aac951efbb38f6ef4e4aed6d2f0271362a0 Mon Sep 17 00:00:00 2001 From: mei Date: Mon, 27 Jul 2026 08:48:56 +0800 Subject: [PATCH] feat(web): visual rule builder with geo, CIDR and wildcard pickers The rule editor no longer requires writing expr by hand. Conditions are rows of field + operator + values joined with AND or OR, each row negatable, and the generated expression is shown live and validated by the engine before a rule is accepted. Raw expression and YAML editing are still available. Fields cover the connection (protocol, source/destination IP and port), domains (TLS SNI, QUIC SNI, DNS query name), HTTP (host, path, method, User-Agent) and protocol detection. Operators cover CIDR membership, GeoIP countries, GeoSite categories, port ranges, wildcards, substrings and regular expressions. Multiple values in a row are OR-ed, so one row holds a whole domain or country list. Wildcards compile to the cheapest expression that matches them: *.x.com becomes endsWith, x.* startsWith, *ad* contains, and only a star in the middle falls back to a regular expression. Values are validated as they are typed, including a hint when a star is used with an operator that would match it literally. Country and category pickers are backed by the databases the engine actually loaded, via a new GET /api/v1/geo endpoint (cached, loaded on demand) built on new listing methods in the geo package. Country names and flags come from Intl.DisplayNames, so no name table is shipped. Note that the v2geo format has no AS numbers; the provider groups it does contain (cloudflare, google, telegram, ...) are listed alongside the countries. Opening an existing rule parses its expression back into conditions. Anything the builder cannot represent opens in the expression editor with a warning rather than being rewritten. ruleset/expr_test.go pins the canonical expressions the builder generates and compiles them with the real engine, and the devserver now uses the real ruleset compiler so the same errors show up during frontend work. Co-Authored-By: Claude Opus 5 --- .gitignore | 4 + README.ja.md | 4 + README.md | 5 + README.zh.md | 4 + cmd/web.go | 29 ++ ruleset/builtins/geo/geo_matcher.go | 64 ++++ ruleset/expr_test.go | 76 +++++ web/README.md | 49 ++- web/api.go | 23 ++ web/devserver/main.go | 84 ++++- ...-CHLlPReV.js => AnalyzersView-Bm4Tu3Lm.js} | 4 +- ...e_type_script_setup_true_lang-i2F91fYk.js} | 2 +- ...e_type_script_setup_true_lang-BHtPbA-o.js} | 2 +- web/dist/assets/Collection-BaXBMWO5.js | 1 + web/dist/assets/Collection-D-pf6tmY.js | 1 - ...-BnrlcswN.js => DashboardView-BD4i_GCA.js} | 2 +- ...e_type_script_setup_true_lang-JeqwaMaY.js} | 2 +- web/dist/assets/EventsView-Blmx8SEw.js | 16 + web/dist/assets/EventsView-DvVZcEec.js | 21 -- ...e_type_script_setup_true_lang-Bd1uxkqS.js} | 9 +- ...e_type_script_setup_true_lang-CPDhGTO6.js} | 2 +- web/dist/assets/RulesView-SxOStRNP.js | 36 -- web/dist/assets/RulesView-f8xcsZeo.js | 46 +++ ...e_type_script_setup_true_lang-CONzBLld.js} | 4 +- ...w-CQy8Fv4M.js => SettingsView-AGyc2AVS.js} | 4 +- ...ue_type_script_setup_true_lang-C9uTg8Ty.js | 1 - ...ue_type_script_setup_true_lang-DG3HTLWx.js | 1 + ...ue_type_script_setup_true_lang-DTNukDpV.js | 1 - ...ue_type_script_setup_true_lang-_qQ6JBVg.js | 1 + web/dist/assets/index-BKPz7Obh.js | 106 ++++++ web/dist/assets/index-CNsDVyYx.css | 1 - web/dist/assets/index-D3ZCYstt.js | 106 ------ web/dist/assets/index-DDyrZ70V.css | 1 + web/dist/index.html | 4 +- .../src/components/rule/ConditionRow.vue | 236 +++++++++++++ .../src/components/rule/GeoPicker.vue | 199 +++++++++++ .../src/components/rule/RuleBuilder.vue | 96 ++++++ web/frontend/src/components/ui/TagsInput.vue | 73 ++++ web/frontend/src/components/ui/index.ts | 1 + web/frontend/src/composables/useGeo.ts | 35 ++ web/frontend/src/i18n/en.ts | 79 ++++- web/frontend/src/i18n/zh.ts | 77 ++++- web/frontend/src/lib/api.ts | 2 + web/frontend/src/lib/geo.ts | 41 +++ web/frontend/src/lib/rule/compile.ts | 113 ++++++ web/frontend/src/lib/rule/fields.ts | 126 +++++++ web/frontend/src/lib/rule/parse.ts | 322 ++++++++++++++++++ web/frontend/src/lib/rule/types.ts | 35 ++ web/frontend/src/lib/rule/validate.ts | 76 +++++ web/frontend/src/lib/types.ts | 13 + web/frontend/src/views/RulesView.vue | 133 +++++++- web/server.go | 34 ++ 52 files changed, 2191 insertions(+), 216 deletions(-) create mode 100644 ruleset/expr_test.go rename web/dist/assets/{AnalyzersView-CHLlPReV.js => AnalyzersView-Bm4Tu3Lm.js} (87%) rename web/dist/assets/{Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js => Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js} (87%) rename web/dist/assets/{CardTitle.vue_vue_type_script_setup_true_lang-BcE23HB-.js => CardTitle.vue_vue_type_script_setup_true_lang-BHtPbA-o.js} (92%) create mode 100644 web/dist/assets/Collection-BaXBMWO5.js delete mode 100644 web/dist/assets/Collection-D-pf6tmY.js rename web/dist/assets/{DashboardView-BnrlcswN.js => DashboardView-BD4i_GCA.js} (96%) rename web/dist/assets/{EventItem.vue_vue_type_script_setup_true_lang-DS497KtL.js => EventItem.vue_vue_type_script_setup_true_lang-JeqwaMaY.js} (92%) create mode 100644 web/dist/assets/EventsView-Blmx8SEw.js delete mode 100644 web/dist/assets/EventsView-DvVZcEec.js rename web/dist/assets/{Modal.vue_vue_type_script_setup_true_lang-gNNtNPLv.js => Modal.vue_vue_type_script_setup_true_lang-Bd1uxkqS.js} (73%) rename web/dist/assets/{PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js => PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js} (90%) delete mode 100644 web/dist/assets/RulesView-SxOStRNP.js create mode 100644 web/dist/assets/RulesView-f8xcsZeo.js rename web/dist/assets/{Select.vue_vue_type_script_setup_true_lang-C15l-n0X.js => Select.vue_vue_type_script_setup_true_lang-CONzBLld.js} (98%) rename web/dist/assets/{SettingsView-CQy8Fv4M.js => SettingsView-AGyc2AVS.js} (79%) delete mode 100644 web/dist/assets/Skeleton.vue_vue_type_script_setup_true_lang-C9uTg8Ty.js create mode 100644 web/dist/assets/Skeleton.vue_vue_type_script_setup_true_lang-DG3HTLWx.js delete mode 100644 web/dist/assets/TabsTrigger.vue_vue_type_script_setup_true_lang-DTNukDpV.js create mode 100644 web/dist/assets/TabsTrigger.vue_vue_type_script_setup_true_lang-_qQ6JBVg.js create mode 100644 web/dist/assets/index-BKPz7Obh.js delete mode 100644 web/dist/assets/index-CNsDVyYx.css delete mode 100644 web/dist/assets/index-D3ZCYstt.js create mode 100644 web/dist/assets/index-DDyrZ70V.css create mode 100644 web/frontend/src/components/rule/ConditionRow.vue create mode 100644 web/frontend/src/components/rule/GeoPicker.vue create mode 100644 web/frontend/src/components/rule/RuleBuilder.vue create mode 100644 web/frontend/src/components/ui/TagsInput.vue create mode 100644 web/frontend/src/composables/useGeo.ts create mode 100644 web/frontend/src/lib/geo.ts create mode 100644 web/frontend/src/lib/rule/compile.ts create mode 100644 web/frontend/src/lib/rule/fields.ts create mode 100644 web/frontend/src/lib/rule/parse.ts create mode 100644 web/frontend/src/lib/rule/types.ts create mode 100644 web/frontend/src/lib/rule/validate.ts diff --git a/.gitignore b/.gitignore index ec71154..d985f34 100644 --- a/.gitignore +++ b/.gitignore @@ -209,6 +209,10 @@ $RECYCLE.BIN/ # Internal tools not ready for public use yet tools/flowseq/ +### Geo databases downloaded at runtime ### +geoip.dat +geosite.dat + ### Web UI ### # The built UI in web/dist IS committed, since it is embedded into the binary. web/frontend/node_modules/ diff --git a/README.ja.md b/README.ja.md index 21edeb6..16d141c 100644 --- a/README.ja.md +++ b/README.ja.md @@ -37,6 +37,10 @@ OpenGFW にはオプションのウェブダッシュボードが同梱されて アナライザのプロパティを含むイベントフィード、そしてルールを検証してホットリロードできるルールエディタが利用できます。 スマートフォンでもデスクトップでも使えるレスポンシブ対応です。 +ルールは条件のリストとして作成できます。フィールド(SNI、DNS 名、HTTP Host、IP、ポート、検出されたプロトコル)と +条件(ワイルドカード、CIDR、GeoIP の国、GeoSite カテゴリ、範囲、正規表現)、そして 1 つ以上の値を選ぶだけです。 +もちろん expr 式や YAML を直接編集することもできます。 + 設定ファイルで有効にします: ```yaml diff --git a/README.md b/README.md index ca0ac11..7509667 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,11 @@ OpenGFW ships with an optional web dashboard: live traffic statistics, a real-ti feed with per-stream analyzer properties, and a rule editor that validates and hot reloads the ruleset. It works on phones as well as on desktops. +Rules can be written as a list of conditions — pick a field (SNI, DNS name, HTTP host, +IP, port, detected protocol), an operator (wildcard, CIDR, GeoIP country, GeoSite +category, range, regex) and one or more values — or as raw expr expressions and YAML. +Countries and site categories are picked from the geo databases the engine loaded. + Enable it in your config file: ```yaml diff --git a/README.zh.md b/README.zh.md index 14413c5..ddfedb4 100644 --- a/README.zh.md +++ b/README.zh.md @@ -36,6 +36,10 @@ Telegram 群组: https://t.me/OpGFW OpenGFW 内置了一个可选的 Web 控制面板:实时流量统计、带解析器属性的实时事件流,以及可以校验并热加载规则的规则编辑器。 界面同时适配手机和桌面浏览器。 +规则既可以用条件列表来写——选择字段(SNI、DNS 域名、HTTP Host、IP、端口、识别到的协议)、 +条件(通配符、CIDR、GeoIP 国家/地区、GeoSite 分类、端口区间、正则)以及一个或多个值—— +也可以直接编写 expr 表达式或 YAML。国家/地区与站点分类直接从引擎加载的 geo 数据库中选择。 + 在配置文件中启用: ```yaml diff --git a/cmd/web.go b/cmd/web.go index d7fbffa..ae2fba6 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -13,6 +13,7 @@ import ( "github.com/apernet/OpenGFW/engine" "github.com/apernet/OpenGFW/modifier" "github.com/apernet/OpenGFW/ruleset" + "github.com/apernet/OpenGFW/ruleset/builtins/geo" "github.com/apernet/OpenGFW/web" "go.uber.org/zap" @@ -197,6 +198,7 @@ func startWebServer(ctx context.Context, config *cliConfig, rm *ruleManager) err Rules: rm, Meta: webMeta(), Info: func() web.Info { return webInfo(config, rm) }, + Geo: func() web.GeoData { return webGeoData(config) }, Logf: func(format string, args ...interface{}) { logger.Info(fmt.Sprintf(format, args...)) }, @@ -266,6 +268,33 @@ func webInfo(config *cliConfig, rm *ruleManager) web.Info { } } +// webGeoData lists what the configured geo databases contain, so that the rule +// builder can offer a picker instead of a free text field. Loading the files is +// expensive, but the web server only calls this on demand and caches the result. +func webGeoData(config *cliConfig) web.GeoData { + matcher := geo.NewGeoMatcher(config.Ruleset.GeoSite, config.Ruleset.GeoIp) + var data web.GeoData + if entries, err := matcher.ListGeoIP(); err != nil { + data.IPError = err.Error() + } else { + for _, e := range entries { + data.IP = append(data.IP, web.GeoEntry{Code: e.Code, Count: e.CIDRs}) + } + } + if entries, err := matcher.ListGeoSite(); err != nil { + data.SiteError = err.Error() + } else { + for _, e := range entries { + data.Site = append(data.Site, web.GeoEntry{ + Code: e.Code, + Count: e.Domains, + Attributes: e.Attributes, + }) + } + } + return data +} + // hubInfo converts engine stream info into the shape the hub understands. func hubInfo(info ruleset.StreamInfo) web.StreamInfo { return web.StreamInfo{ diff --git a/ruleset/builtins/geo/geo_matcher.go b/ruleset/builtins/geo/geo_matcher.go index 1bb0f30..ab20abb 100644 --- a/ruleset/builtins/geo/geo_matcher.go +++ b/ruleset/builtins/geo/geo_matcher.go @@ -2,6 +2,7 @@ package geo import ( "net" + "sort" "strings" "sync" ) @@ -97,6 +98,69 @@ func (g *GeoMatcher) LoadGeoSite() error { return err } +// GeoIPEntry describes one entry of a GeoIP database. +type GeoIPEntry struct { + // Code is the lowercase key to pass to geoip(), usually a country code. + Code string + // CIDRs is the number of networks the entry covers. + CIDRs int +} + +// GeoSiteEntry describes one entry of a GeoSite database. +type GeoSiteEntry struct { + // Code is the lowercase key to pass to geosite(). + Code string + // Attributes are the suffixes usable as `code@attribute`. + Attributes []string + // Domains is the number of domain rules the entry covers. + Domains int +} + +// ListGeoIP returns every entry of the GeoIP database, sorted by code. +// It is meant for UIs that let the user pick a country instead of typing one. +func (g *GeoMatcher) ListGeoIP() ([]GeoIPEntry, error) { + gMap, err := g.geoLoader.LoadGeoIP() + if err != nil { + return nil, err + } + entries := make([]GeoIPEntry, 0, len(gMap)) + for code, list := range gMap { + entries = append(entries, GeoIPEntry{Code: code, CIDRs: len(list.GetCidr())}) + } + sort.Slice(entries, func(i, j int) bool { return entries[i].Code < entries[j].Code }) + return entries, nil +} + +// ListGeoSite returns every entry of the GeoSite database, sorted by code, +// including the attributes each entry supports. +func (g *GeoMatcher) ListGeoSite() ([]GeoSiteEntry, error) { + gMap, err := g.geoLoader.LoadGeoSite() + if err != nil { + return nil, err + } + entries := make([]GeoSiteEntry, 0, len(gMap)) + for code, list := range gMap { + attrSet := make(map[string]struct{}) + for _, domain := range list.GetDomain() { + for _, attr := range domain.GetAttribute() { + attrSet[strings.ToLower(attr.GetKey())] = struct{}{} + } + } + attrs := make([]string, 0, len(attrSet)) + for attr := range attrSet { + attrs = append(attrs, attr) + } + sort.Strings(attrs) + entries = append(entries, GeoSiteEntry{ + Code: code, + Attributes: attrs, + Domains: len(list.GetDomain()), + }) + } + sort.Slice(entries, func(i, j int) bool { return entries[i].Code < entries[j].Code }) + return entries, nil +} + func (g *GeoMatcher) LoadGeoIP() error { _, err := g.geoLoader.LoadGeoIP() return err diff --git a/ruleset/expr_test.go b/ruleset/expr_test.go new file mode 100644 index 0000000..356df88 --- /dev/null +++ b/ruleset/expr_test.go @@ -0,0 +1,76 @@ +package ruleset + +import ( + "context" + "net" + "strings" + "testing" + + "github.com/apernet/OpenGFW/analyzer" + "github.com/apernet/OpenGFW/analyzer/tcp" + "github.com/apernet/OpenGFW/analyzer/udp" + "github.com/apernet/OpenGFW/modifier" + modUDP "github.com/apernet/OpenGFW/modifier/udp" +) + +// builderExpressions are the canonical expressions produced by the visual rule +// builder of the web UI (see web/frontend/src/lib/rule/compile.ts). They are +// pinned here so that a change to the expression language, the analyzers or the +// built-in functions cannot silently break the builder. +var builderExpressions = []string{ + // Domain or subdomain, single and multiple values + `(string(tls?.req?.sni) == "example.com" || string(tls?.req?.sni) endsWith ".example.com")`, + `((string(tls?.req?.sni) == "example.com" || string(tls?.req?.sni) endsWith ".example.com") || (string(tls?.req?.sni) == "evil.test" || string(tls?.req?.sni) endsWith ".evil.test")) && proto == "tcp"`, + // CIDR and GeoIP, including negation + `(cidr(ip.dst, "10.0.0.0/8") || cidr(ip.dst, "fd00::/8")) || !(geoip(ip.dst, "cn") || geoip(ip.dst, "hk"))`, + // Port equality and ranges + `(port.dst >= 1000 && port.dst <= 2000) && (port.src == 80 || port.src == 443)`, + // Wildcards over DNS questions + `any(dns?.questions ?? [], {(string(.name) endsWith ".ads.com" || string(.name) startsWith "x.")})`, + // GeoSite over DNS questions + `any(dns?.questions ?? [], {geosite(string(.name), "category-ads-all")})`, + // HTTP fields: negation, regular expressions and header lookups + `!(string(http?.req?.headers?.host) contains "tracker") && string(http?.req?.path) matches "^/api/v\\d+/" && string(get(http?.req?.headers, "user-agent")) startsWith "curl"`, + // Protocol detection + `(ssh != nil || trojan != nil)`, + // Wildcard edge cases: "any value" and a star in the middle + `string(quic?.req?.sni) != "" && string(tls?.req?.sni) matches "^www\\..*\\.com$" && ip.src == "1.2.3.4" && string(http?.req?.method) == "POST"`, +} + +func TestCompileBuilderExpressions(t *testing.T) { + analyzers := []analyzer.Analyzer{ + &tcp.FETAnalyzer{}, &tcp.HTTPAnalyzer{}, &tcp.SocksAnalyzer{}, &tcp.SSHAnalyzer{}, + &tcp.TLSAnalyzer{}, &tcp.TrojanAnalyzer{}, &udp.DNSAnalyzer{}, &udp.OpenVPNAnalyzer{}, + &udp.QUICAnalyzer{}, &udp.WireGuardAnalyzer{}, + } + modifiers := []modifier.Modifier{&modUDP.DNSModifier{}} + config := &BuiltinConfig{ + Logger: nopLogger{}, + // Point at a file that does not exist: expressions still have to + // compile, only loading the database is expected to fail. + GeoSiteFilename: "testdata/missing-geosite.dat", + GeoIpFilename: "testdata/missing-geoip.dat", + ProtectedDialContext: func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, address) + }, + } + + for _, expr := range builderExpressions { + rules := []ExprRule{{Name: "test", Action: "block", Expr: expr}} + _, err := CompileExprRules(rules, analyzers, modifiers, config) + if err == nil { + continue + } + // geoip()/geosite() need a database, which this test does not ship. + // Reaching the initialization step means the expression itself is fine. + if strings.Contains(err.Error(), "failed to initialize function") { + continue + } + t.Errorf("expression failed to compile: %s\n %v", expr, err) + } +} + +type nopLogger struct{} + +func (nopLogger) Log(StreamInfo, string) {} +func (nopLogger) MatchError(StreamInfo, string, error) {} diff --git a/web/README.md b/web/README.md index 69eba4b..60243e1 100644 --- a/web/README.md +++ b/web/README.md @@ -8,8 +8,9 @@ the OpenGFW binary and served by the `web` package. blocked destinations and triggered rules - **Events** — real-time feed of verdicts, rule logs and errors with filters and a detail view showing raw analyzer properties -- **Rules** — visual rule editor and a raw YAML editor, both validated by the engine - itself; saving writes the rule file and hot reloads the running engine +- **Rules** — a visual condition builder, a raw expression editor and a YAML editor, + all validated by the engine itself; saving writes the rule file and hot reloads the + running engine - **Analyzers** — which analyzers are compiled in and how much traffic each one saw - **Settings** — theme (light/dark/system), language (English/中文) and instance info @@ -30,6 +31,49 @@ web: If `secret` is empty a random password is generated and printed to the log on startup. +## Rule builder + +Rules are still plain expr expressions in the rule file; the builder is only a way to +write them without memorising the syntax. Conditions are rows of *field + operator + +values*, joined with AND or OR, each row negatable: + +| Field group | Fields | +| ----------- | --------------------------------------------------------------- | +| Connection | transport protocol, source/destination IP, source/destination port | +| Domain | TLS SNI, QUIC SNI, DNS query name | +| HTTP | Host, path, method, User-Agent | +| Protocol | detected protocol (any analyzer) | + +Operators cover the things rules usually need: + +| Operator | Generated expression | +| ----------------------- | ---------------------------------------------------------- | +| domain or subdomain of | `(S == "x.com" \|\| S endsWith ".x.com")` | +| matches wildcard | `*.x.com` → `endsWith`, `x.*` → `startsWith`, `*ad*` → `contains`, `a.*.c` → `matches` | +| in CIDR | `cidr(ip.dst, "10.0.0.0/8")`, validated as you type | +| in GeoIP country | `geoip(ip.dst, "cn")`, picked from the loaded database | +| in GeoSite category | `geosite(string(.name), "category-ads-all@cn")` | +| in range | `(port.dst >= 1000 && port.dst <= 2000)` | +| is / contains / starts / ends / regex | the matching expr operator | + +Multiple values in one row are OR-ed together, so one row can hold a whole domain or +country list. The generated expression is shown live and validated by the engine before +the rule is accepted. + +Opening an existing rule parses its expression back into conditions. Anything the +builder cannot represent — hand written expressions, functions like `lookup()` — opens +in the expression editor with a warning instead of being rewritten. + +The GeoIP picker lists whatever the configured `geoip.dat` contains: country codes plus, +with the default Loyalsoldier database, provider groups such as `cloudflare`, `google` +and `telegram`. Matching by AS number is not something the v2geo data format supports, +so use those groups or an explicit CIDR list instead. + +`web/frontend/src/lib/rule/` holds the whole thing: `fields.ts` (catalog), `compile.ts` +(builder → expr), `parse.ts` (expr → builder) and `validate.ts`. The canonical +expressions are pinned in `ruleset/expr_test.go`, which compiles them with the real +engine. + ## Layout ``` @@ -83,6 +127,7 @@ endpoints only accept the bearer token, which makes them immune to CSRF. | `POST` | `/logout` | invalidate the current session | | `GET` | `/info` | version, platform and engine configuration | | `GET` | `/meta` | available analyzers, modifiers, actions, functions | +| `GET` | `/geo` | GeoIP/GeoSite entries for the rule builder pickers | | `GET` | `/metrics` | counters, time series and top N lists | | `GET` | `/events?limit=` | recent events from the ring buffer | | `GET` | `/live` | server-sent events: `event` and `metrics` frames | diff --git a/web/api.go b/web/api.go index f697e26..943045e 100644 --- a/web/api.go +++ b/web/api.go @@ -204,6 +204,29 @@ func (s *Server) handleLive(w http.ResponseWriter, r *http.Request) { } } +// GET /api/v1/geo - the entries of the configured geo databases. +func (s *Server) handleGeo(w http.ResponseWriter, r *http.Request) { + if !methodAllowed(w, r, http.MethodGet) { + return + } + if s.config.Geo == nil { + writeJSON(w, http.StatusOK, GeoData{ + IPError: "geo databases are unavailable", + SiteError: "geo databases are unavailable", + }) + return + } + s.geoMu.Lock() + defer s.geoMu.Unlock() + fresh := s.geoCache != nil && time.Since(s.geoLoaded) < geoCacheTTL + if !fresh || r.URL.Query().Get("reload") == "1" { + data := s.config.Geo() + s.geoCache = &data + s.geoLoaded = time.Now() + } + writeJSON(w, http.StatusOK, s.geoCache) +} + type rulesRequest struct { Raw string `json:"raw"` Rules []Rule `json:"rules"` diff --git a/web/devserver/main.go b/web/devserver/main.go index 7920df5..cd95d56 100644 --- a/web/devserver/main.go +++ b/web/devserver/main.go @@ -13,13 +13,22 @@ import ( "fmt" "log" "math/rand" + "net" "os" "os/signal" "runtime" "syscall" "time" + "github.com/apernet/OpenGFW/analyzer" + "github.com/apernet/OpenGFW/analyzer/tcp" + "github.com/apernet/OpenGFW/analyzer/udp" + "github.com/apernet/OpenGFW/modifier" + modUDP "github.com/apernet/OpenGFW/modifier/udp" + "github.com/apernet/OpenGFW/ruleset" + "github.com/apernet/OpenGFW/ruleset/builtins/geo" "github.com/apernet/OpenGFW/web" + "gopkg.in/yaml.v3" ) @@ -64,6 +73,7 @@ func main() { }, } }, + Geo: geoData, Logf: log.Printf, }) if err != nil { @@ -161,8 +171,9 @@ func generate(ctx context.Context, hub *web.Hub) { } } -// memoryRules is an in-memory web.RuleManager: it validates the YAML shape but -// does not compile expressions, which is enough for UI work. +// memoryRules is an in-memory web.RuleManager. Rules are compiled with the real +// ruleset compiler and the real analyzers, so expression errors show up here +// exactly like they would in the engine; only the "apply" step is faked. type memoryRules struct { raw string rules []web.Rule @@ -209,21 +220,68 @@ func (m *memoryRules) Apply(raw string) ([]web.Rule, error) { return rules, nil } +var ( + analyzers = []analyzer.Analyzer{ + &tcp.FETAnalyzer{}, &tcp.HTTPAnalyzer{}, &tcp.SocksAnalyzer{}, &tcp.SSHAnalyzer{}, + &tcp.TLSAnalyzer{}, &tcp.TrojanAnalyzer{}, &udp.DNSAnalyzer{}, &udp.OpenVPNAnalyzer{}, + &udp.QUICAnalyzer{}, &udp.WireGuardAnalyzer{}, + } + modifiers = []modifier.Modifier{&modUDP.DNSModifier{}} +) + +// parse compiles rules the same way the engine does. func parse(raw string) ([]web.Rule, error) { - var rules []web.Rule - if err := yaml.Unmarshal([]byte(raw), &rules); err != nil { + exprRules, err := ruleset.ExprRulesFromYAMLBytes([]byte(raw)) + if err != nil { + return nil, fmt.Errorf("failed to parse rules: %w", err) + } + _, err = ruleset.CompileExprRules(exprRules, analyzers, modifiers, &ruleset.BuiltinConfig{ + Logger: nopRulesetLogger{}, + GeoSiteFilename: os.Getenv("OPENGFW_GEOSITE"), + GeoIpFilename: os.Getenv("OPENGFW_GEOIP"), + ProtectedDialContext: func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, network, address) + }, + }) + if err != nil { return nil, err } - for i, r := range rules { - if r.Name == "" { - return nil, fmt.Errorf("rule #%d has no name", i+1) + out := make([]web.Rule, 0, len(exprRules)) + for _, r := range exprRules { + wr := web.Rule{Name: r.Name, Action: r.Action, Log: r.Log, Expr: r.Expr} + if r.Modifier.Name != "" { + wr.Modifier = &web.RuleModifier{Name: r.Modifier.Name, Args: r.Modifier.Args} } - if r.Expr == "" { - return nil, fmt.Errorf("rule %q has no expression", r.Name) - } - if r.Action == "" && !r.Log { - return nil, fmt.Errorf("rule %q must have at least one of action or log", r.Name) + out = append(out, wr) + } + return out, nil +} + +type nopRulesetLogger struct{} + +func (nopRulesetLogger) Log(ruleset.StreamInfo, string) {} +func (nopRulesetLogger) MatchError(ruleset.StreamInfo, string, error) {} + +// geoData lists the geo databases, if they are available in the working +// directory (or wherever OPENGFW_GEOIP / OPENGFW_GEOSITE point). +func geoData() web.GeoData { + matcher := geo.NewGeoMatcher(os.Getenv("OPENGFW_GEOSITE"), os.Getenv("OPENGFW_GEOIP")) + var data web.GeoData + if entries, err := matcher.ListGeoIP(); err != nil { + data.IPError = err.Error() + } else { + for _, e := range entries { + data.IP = append(data.IP, web.GeoEntry{Code: e.Code, Count: e.CIDRs}) } } - return rules, nil + if entries, err := matcher.ListGeoSite(); err != nil { + data.SiteError = err.Error() + } else { + for _, e := range entries { + data.Site = append(data.Site, web.GeoEntry{ + Code: e.Code, Count: e.Domains, Attributes: e.Attributes, + }) + } + } + return data } diff --git a/web/dist/assets/AnalyzersView-CHLlPReV.js b/web/dist/assets/AnalyzersView-Bm4Tu3Lm.js similarity index 87% rename from web/dist/assets/AnalyzersView-CHLlPReV.js rename to web/dist/assets/AnalyzersView-Bm4Tu3Lm.js index e0f1090..c0d24b3 100644 --- a/web/dist/assets/AnalyzersView-CHLlPReV.js +++ b/web/dist/assets/AnalyzersView-Bm4Tu3Lm.js @@ -1,4 +1,4 @@ -import{_ as b}from"./PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js";import{_ as y}from"./Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js";import{c as M,d as B,K as L,M as j,a as o,p as t,u as e,l as r,F as f,r as p,b as u,w as s,_ as g,m as F,g as v,o as n,h,t as l,k as i,j as N,q}from"./index-D3ZCYstt.js";import{_ as k,a as x,b as z,c as w}from"./CardTitle.vue_vue_type_script_setup_true_lang-BcE23HB-.js";import{_ as A}from"./Skeleton.vue_vue_type_script_setup_true_lang-C9uTg8Ty.js";import{c as C}from"./format-B6sc_rZ4.js";/** +import{_ as b}from"./PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js";import{_ as y}from"./Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js";import{c as M,d as B,O as L,$ as j,a as o,p as t,u as e,l as r,F as f,r as p,b as u,w as s,_ as g,m as F,g as v,o as n,h,t as l,k as i,j as N,q}from"./index-BKPz7Obh.js";import{_ as k,a as x,b as z,c as w}from"./CardTitle.vue_vue_type_script_setup_true_lang-BHtPbA-o.js";import{_ as A}from"./Skeleton.vue_vue_type_script_setup_true_lang-DG3HTLWx.js";import{c as C}from"./format-B6sc_rZ4.js";/** * @license lucide-vue-next v0.469.0 - ISC * * This source code is licensed under the ISC license. @@ -8,4 +8,4 @@ import{_ as b}from"./PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js" * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const I=M("SquareFunctionIcon",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["path",{d:"M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3",key:"m1af9g"}],["path",{d:"M9 11.2h5.7",key:"3zgcl2"}]]),S={key:0,class:"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4"},Z={class:"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4"},E={class:"flex items-center justify-between gap-2"},K={class:"truncate font-mono text-sm font-medium"},T={class:"mt-2 text-xl font-semibold tabular-nums"},G={class:"text-muted-foreground text-xs"},H={class:"mt-3 grid gap-3 md:grid-cols-2"},J={key:0,class:"text-muted-foreground text-xs"},Y=B({__name:"AnalyzersView",setup(O){const{metrics:V}=q(),c=F(null);L(async()=>{try{c.value=await j.meta()}catch{c.value={analyzers:[],modifiers:[],actions:[],functions:[]}}});const _=v(()=>{var m;const d=new Map;for(const a of((m=V.value)==null?void 0:m.analyzers)??[])d.set(a.name,a.count);return d}),$=v(()=>{var d;return[...((d=c.value)==null?void 0:d.analyzers)??[]].sort((m,a)=>(_.value.get(a.name)??0)-(_.value.get(m.name)??0))});return(d,m)=>(n(),o("div",null,[t(b,{title:e(r)("analyzers.title"),description:e(r)("analyzers.subtitle")},null,8,["title","description"]),c.value?(n(),o(f,{key:1},[u("div",Z,[(n(!0),o(f,null,p($.value,a=>(n(),h(e(g),{key:a.name,class:"p-3.5 sm:p-4"},{default:s(()=>[u("div",E,[u("span",K,l(a.name),1),t(e(y),{variant:a.proto==="udp"?"udp":"tcp",class:"uppercase"},{default:s(()=>[i(l(a.proto),1)]),_:2},1032,["variant"])]),u("p",T,l(e(C)(_.value.get(a.name)??0)),1),u("p",G,l(e(r)("analyzers.hits")),1)]),_:2},1024))),128))]),u("div",H,[t(e(g),null,{default:s(()=>[t(e(k),null,{default:s(()=>[t(e(x),{class:"flex items-center gap-2"},{default:s(()=>[t(e(D),{class:"size-4"}),i(" "+l(e(r)("analyzers.modifiers")),1)]),_:1}),t(e(z),null,{default:s(()=>[i(l(e(r)("analyzers.modifiersDesc")),1)]),_:1})]),_:1}),t(e(w),{class:"flex flex-wrap gap-1.5"},{default:s(()=>[(n(!0),o(f,null,p(c.value.modifiers,a=>(n(),h(e(y),{key:a,variant:"secondary",class:"font-mono"},{default:s(()=>[i(l(a),1)]),_:2},1024))),128)),c.value.modifiers.length?N("",!0):(n(),o("span",J,"—"))]),_:1})]),_:1}),t(e(g),null,{default:s(()=>[t(e(k),null,{default:s(()=>[t(e(x),{class:"flex items-center gap-2"},{default:s(()=>[t(e(I),{class:"size-4"}),i(" "+l(e(r)("analyzers.functions")),1)]),_:1}),t(e(z),null,{default:s(()=>[i(l(e(r)("analyzers.functionsDesc")),1)]),_:1})]),_:1}),t(e(w),{class:"flex flex-wrap gap-1.5"},{default:s(()=>[(n(!0),o(f,null,p(c.value.functions,a=>(n(),h(e(y),{key:a,variant:"secondary",class:"font-mono"},{default:s(()=>[i(l(a)+"() ",1)]),_:2},1024))),128))]),_:1})]),_:1})])],64)):(n(),o("div",S,[(n(),o(f,null,p(8,a=>t(e(A),{key:a,class:"h-24"})),64))]))]))}});export{Y as default}; + */const I=M("SquareFunctionIcon",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["path",{d:"M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3",key:"m1af9g"}],["path",{d:"M9 11.2h5.7",key:"3zgcl2"}]]),S={key:0,class:"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4"},Z={class:"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4"},E={class:"flex items-center justify-between gap-2"},O={class:"truncate font-mono text-sm font-medium"},T={class:"mt-2 text-xl font-semibold tabular-nums"},G={class:"text-muted-foreground text-xs"},H={class:"mt-3 grid gap-3 md:grid-cols-2"},J={key:0,class:"text-muted-foreground text-xs"},Y=B({__name:"AnalyzersView",setup(K){const{metrics:V}=q(),c=F(null);L(async()=>{try{c.value=await j.meta()}catch{c.value={analyzers:[],modifiers:[],actions:[],functions:[]}}});const _=v(()=>{var m;const d=new Map;for(const a of((m=V.value)==null?void 0:m.analyzers)??[])d.set(a.name,a.count);return d}),$=v(()=>{var d;return[...((d=c.value)==null?void 0:d.analyzers)??[]].sort((m,a)=>(_.value.get(a.name)??0)-(_.value.get(m.name)??0))});return(d,m)=>(n(),o("div",null,[t(b,{title:e(r)("analyzers.title"),description:e(r)("analyzers.subtitle")},null,8,["title","description"]),c.value?(n(),o(f,{key:1},[u("div",Z,[(n(!0),o(f,null,p($.value,a=>(n(),h(e(g),{key:a.name,class:"p-3.5 sm:p-4"},{default:s(()=>[u("div",E,[u("span",O,l(a.name),1),t(e(y),{variant:a.proto==="udp"?"udp":"tcp",class:"uppercase"},{default:s(()=>[i(l(a.proto),1)]),_:2},1032,["variant"])]),u("p",T,l(e(C)(_.value.get(a.name)??0)),1),u("p",G,l(e(r)("analyzers.hits")),1)]),_:2},1024))),128))]),u("div",H,[t(e(g),null,{default:s(()=>[t(e(k),null,{default:s(()=>[t(e(x),{class:"flex items-center gap-2"},{default:s(()=>[t(e(D),{class:"size-4"}),i(" "+l(e(r)("analyzers.modifiers")),1)]),_:1}),t(e(z),null,{default:s(()=>[i(l(e(r)("analyzers.modifiersDesc")),1)]),_:1})]),_:1}),t(e(w),{class:"flex flex-wrap gap-1.5"},{default:s(()=>[(n(!0),o(f,null,p(c.value.modifiers,a=>(n(),h(e(y),{key:a,variant:"secondary",class:"font-mono"},{default:s(()=>[i(l(a),1)]),_:2},1024))),128)),c.value.modifiers.length?N("",!0):(n(),o("span",J,"—"))]),_:1})]),_:1}),t(e(g),null,{default:s(()=>[t(e(k),null,{default:s(()=>[t(e(x),{class:"flex items-center gap-2"},{default:s(()=>[t(e(I),{class:"size-4"}),i(" "+l(e(r)("analyzers.functions")),1)]),_:1}),t(e(z),null,{default:s(()=>[i(l(e(r)("analyzers.functionsDesc")),1)]),_:1})]),_:1}),t(e(w),{class:"flex flex-wrap gap-1.5"},{default:s(()=>[(n(!0),o(f,null,p(c.value.functions,a=>(n(),h(e(y),{key:a,variant:"secondary",class:"font-mono"},{default:s(()=>[i(l(a)+"() ",1)]),_:2},1024))),128))]),_:1})]),_:1})])],64)):(n(),o("div",S,[(n(),o(f,null,p(8,a=>t(e(A),{key:a,class:"h-24"})),64))]))]))}});export{Y as default}; diff --git a/web/dist/assets/Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js b/web/dist/assets/Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js similarity index 87% rename from web/dist/assets/Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js rename to web/dist/assets/Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js index 345c84e..2142038 100644 --- a/web/dist/assets/Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js +++ b/web/dist/assets/Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js @@ -1 +1 @@ -import{d as o,a as n,e as d,u as e,f as s,H as l,o as p,a0 as c}from"./index-D3ZCYstt.js";const b=c("inline-flex items-center justify-center gap-1 rounded-md border px-1.5 py-0.5 text-[11px] font-medium whitespace-nowrap tabular-nums",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground",secondary:"border-transparent bg-secondary text-secondary-foreground",outline:"text-foreground",muted:"border-transparent bg-muted text-muted-foreground",allow:"border-allow/25 bg-allow/12 text-allow",block:"border-block/25 bg-block/12 text-block",drop:"border-drop/25 bg-drop/12 text-drop",modify:"border-modify/25 bg-modify/12 text-modify",log:"border-log/25 bg-log/12 text-log",tcp:"border-tcp/25 bg-tcp/12 text-tcp",udp:"border-udp/25 bg-udp/12 text-udp"}},defaultVariants:{variant:"default"}}),g=o({__name:"Badge",props:{variant:{},class:{}},setup(t){const r=t;return(a,u)=>(p(),n("span",{class:d(e(s)(e(b)({variant:r.variant}),r.class))},[l(a.$slots,"default")],2))}});export{g as _}; +import{d as o,a as n,e as d,u as e,f as s,H as l,o as p,a8 as c}from"./index-BKPz7Obh.js";const b=c("inline-flex items-center justify-center gap-1 rounded-md border px-1.5 py-0.5 text-[11px] font-medium whitespace-nowrap tabular-nums",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground",secondary:"border-transparent bg-secondary text-secondary-foreground",outline:"text-foreground",muted:"border-transparent bg-muted text-muted-foreground",allow:"border-allow/25 bg-allow/12 text-allow",block:"border-block/25 bg-block/12 text-block",drop:"border-drop/25 bg-drop/12 text-drop",modify:"border-modify/25 bg-modify/12 text-modify",log:"border-log/25 bg-log/12 text-log",tcp:"border-tcp/25 bg-tcp/12 text-tcp",udp:"border-udp/25 bg-udp/12 text-udp"}},defaultVariants:{variant:"default"}}),g=o({__name:"Badge",props:{variant:{},class:{}},setup(t){const r=t;return(a,u)=>(p(),n("span",{class:d(e(s)(e(b)({variant:r.variant}),r.class))},[l(a.$slots,"default")],2))}});export{g as _}; diff --git a/web/dist/assets/CardTitle.vue_vue_type_script_setup_true_lang-BcE23HB-.js b/web/dist/assets/CardTitle.vue_vue_type_script_setup_true_lang-BHtPbA-o.js similarity index 92% rename from web/dist/assets/CardTitle.vue_vue_type_script_setup_true_lang-BcE23HB-.js rename to web/dist/assets/CardTitle.vue_vue_type_script_setup_true_lang-BHtPbA-o.js index 4950dc3..24546cd 100644 --- a/web/dist/assets/CardTitle.vue_vue_type_script_setup_true_lang-BcE23HB-.js +++ b/web/dist/assets/CardTitle.vue_vue_type_script_setup_true_lang-BHtPbA-o.js @@ -1 +1 @@ -import{d as a,o as n,a as r,e as c,u as o,f as p,H as l}from"./index-D3ZCYstt.js";const u=a({__name:"CardContent",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("div",{class:c(o(p)("px-4 pb-4 sm:px-5 sm:pb-5",e.class))},[l(t.$slots,"default")],2))}}),d=a({__name:"CardDescription",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("p",{class:c(o(p)("text-muted-foreground text-xs sm:text-sm",e.class))},[l(t.$slots,"default")],2))}}),f=a({__name:"CardHeader",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("div",{class:c(o(p)("flex flex-col gap-1 px-4 pt-4 pb-3 sm:px-5 sm:pt-5",e.class))},[l(t.$slots,"default")],2))}}),i=a({__name:"CardTitle",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("h3",{class:c(o(p)("text-sm leading-none font-semibold tracking-tight sm:text-base",e.class))},[l(t.$slots,"default")],2))}});export{f as _,i as a,d as b,u as c}; +import{d as a,o as n,a as r,e as c,u as o,f as p,H as l}from"./index-BKPz7Obh.js";const u=a({__name:"CardContent",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("div",{class:c(o(p)("px-4 pb-4 sm:px-5 sm:pb-5",e.class))},[l(t.$slots,"default")],2))}}),d=a({__name:"CardDescription",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("p",{class:c(o(p)("text-muted-foreground text-xs sm:text-sm",e.class))},[l(t.$slots,"default")],2))}}),f=a({__name:"CardHeader",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("div",{class:c(o(p)("flex flex-col gap-1 px-4 pt-4 pb-3 sm:px-5 sm:pt-5",e.class))},[l(t.$slots,"default")],2))}}),i=a({__name:"CardTitle",props:{class:{}},setup(s){const e=s;return(t,m)=>(n(),r("h3",{class:c(o(p)("text-sm leading-none font-semibold tracking-tight sm:text-base",e.class))},[l(t.$slots,"default")],2))}});export{f as _,i as a,d as b,u as c}; diff --git a/web/dist/assets/Collection-BaXBMWO5.js b/web/dist/assets/Collection-BaXBMWO5.js new file mode 100644 index 0000000..c2fc0ca --- /dev/null +++ b/web/dist/assets/Collection-BaXBMWO5.js @@ -0,0 +1 @@ +import{aB as h,aC as x,m as v,g as p,aD as R,al as S,d as g,aj as b,ap as w,aE as y,x as P,aF as k}from"./index-BKPz7Obh.js";function D(e,l){const t=typeof e=="string"&&!l?`${e}Context`:l,o=Symbol(t);return[a=>{const c=h(o,a);if(c||c===null)return c;throw new Error(`Injection \`${o.toString()}\` not found. Component must be used within ${Array.isArray(e)?`one of the following components: ${e.join(", ")}`:`\`${e}\``}`)},a=>(x(o,a),a)]}function _(){let e=document.activeElement;if(e==null)return null;for(;e!=null&&e.shadowRoot!=null&&e.shadowRoot.activeElement!=null;)e=e.shadowRoot.activeElement;return e}const[A]=D("ConfigProvider");function z(e){const l=A({dir:v("ltr")});return p(()=>{var t;return(e==null?void 0:e.value)||((t=l.dir)==null?void 0:t.value)||"ltr"})}function K(e,l="reka"){var n;let t;const o=A({useId:void 0});return o.useId?t=o.useId():t=(n=R)==null?void 0:n(),l?`${l}-${t}`:t}function I(){const e=v(),l=p(()=>{var t,o;return["#text","#comment"].includes((t=e.value)==null?void 0:t.$el.nodeName)?(o=e.value)==null?void 0:o.$el.nextElementSibling:S(e)});return{primitiveElement:e,currentElement:l}}const $="data-reka-collection-item";function q(e={}){const{key:l="",isProvider:t=!1}=e,o=`${l}CollectionProvider`;let n;if(t){const u=v(new Map);n={collectionRef:v(),itemMap:u},x(o,n)}else n=h(o);const C=(u=!1)=>{const r=n.collectionRef.value;if(!r)return[];const f=Array.from(r.querySelectorAll(`[${$}]`)),m=new Map(f.map((i,E)=>[i,E])),d=Array.from(n.itemMap.value.values()).sort((i,E)=>(m.get(i.ref)??-1)-(m.get(E.ref)??-1));return u?d:d.filter(i=>i.ref.dataset.disabled!=="")},a=g({name:"CollectionSlot",inheritAttrs:!1,setup(u,{slots:r,attrs:f}){const{primitiveElement:m,currentElement:s}=I();return P(s,()=>{n.collectionRef.value=s.value}),()=>w(y,{ref:m,...f},r)}}),c=g({name:"CollectionItem",inheritAttrs:!1,props:{value:{validator:()=>!0}},setup(u,{slots:r,attrs:f}){const{primitiveElement:m,currentElement:s}=I();return b(d=>{if(s.value){const i=k(s.value);n.itemMap.value.set(i,{ref:s.value,value:u.value}),d(()=>n.itemMap.value.delete(i))}}),()=>w(y,{...f,[$]:"",ref:m},r)}}),M=p(()=>Array.from(n.itemMap.value.values())),j=p(()=>n.itemMap.value.size);return{getItems:C,reactiveItems:M,itemMapSize:j,CollectionSlot:a,CollectionItem:c}}export{q as a,z as b,D as c,K as d,_ as g,A as i,I as u}; diff --git a/web/dist/assets/Collection-D-pf6tmY.js b/web/dist/assets/Collection-D-pf6tmY.js deleted file mode 100644 index c9970c7..0000000 --- a/web/dist/assets/Collection-D-pf6tmY.js +++ /dev/null @@ -1 +0,0 @@ -import{ax as I,ay as $,m as v,g as p,az as j,af as S,d as C,ad as b,ak as g,aA as w,x as k,aB as P}from"./index-D3ZCYstt.js";function T(e,i){const t=typeof e=="string"&&!i?`${e}Context`:i,o=Symbol(t);return[a=>{const c=I(o,a);if(c||c===null)return c;throw new Error(`Injection \`${o.toString()}\` not found. Component must be used within ${Array.isArray(e)?`one of the following components: ${e.join(", ")}`:`\`${e}\``}`)},a=>($(o,a),a)]}function D(){let e=document.activeElement;if(e==null)return null;for(;e!=null&&e.shadowRoot!=null&&e.shadowRoot.activeElement!=null;)e=e.shadowRoot.activeElement;return e}const[h]=T("ConfigProvider");function _(e){const i=h({dir:v("ltr")});return p(()=>{var t;return(e==null?void 0:e.value)||((t=i.dir)==null?void 0:t.value)||"ltr"})}function K(e,i="reka"){var n;let t;const o=h({useId:void 0});return o.useId?t=o.useId():t=(n=j)==null?void 0:n(),i?`${i}-${t}`:t}function x(){const e=v(),i=p(()=>{var t,o;return["#text","#comment"].includes((t=e.value)==null?void 0:t.$el.nodeName)?(o=e.value)==null?void 0:o.$el.nextElementSibling:S(e)});return{primitiveElement:e,currentElement:i}}const A="data-reka-collection-item";function q(e={}){const{key:i="",isProvider:t=!1}=e,o=`${i}CollectionProvider`;let n;if(t){const u=v(new Map);n={collectionRef:v(),itemMap:u},$(o,n)}else n=I(o);const y=(u=!1)=>{const r=n.collectionRef.value;if(!r)return[];const f=Array.from(r.querySelectorAll(`[${A}]`)),m=new Map(f.map((l,E)=>[l,E])),d=Array.from(n.itemMap.value.values()).sort((l,E)=>(m.get(l.ref)??-1)-(m.get(E.ref)??-1));return u?d:d.filter(l=>l.ref.dataset.disabled!=="")},a=C({name:"CollectionSlot",inheritAttrs:!1,setup(u,{slots:r,attrs:f}){const{primitiveElement:m,currentElement:s}=x();return k(s,()=>{n.collectionRef.value=s.value}),()=>g(w,{ref:m,...f},r)}}),c=C({name:"CollectionItem",inheritAttrs:!1,props:{value:{validator:()=>!0}},setup(u,{slots:r,attrs:f}){const{primitiveElement:m,currentElement:s}=x();return b(d=>{if(s.value){const l=P(s.value);n.itemMap.value.set(l,{ref:s.value,value:u.value}),d(()=>n.itemMap.value.delete(l))}}),()=>g(w,{...f,[A]:"",ref:m},r)}}),M=p(()=>Array.from(n.itemMap.value.values())),R=p(()=>n.itemMap.value.size);return{getItems:y,reactiveItems:M,itemMapSize:R,CollectionSlot:a,CollectionItem:c}}export{_ as a,q as b,T as c,K as d,D as g,h as i,x as u}; diff --git a/web/dist/assets/DashboardView-BnrlcswN.js b/web/dist/assets/DashboardView-BD4i_GCA.js similarity index 96% rename from web/dist/assets/DashboardView-BnrlcswN.js rename to web/dist/assets/DashboardView-BD4i_GCA.js index f5e13e1..e48400a 100644 --- a/web/dist/assets/DashboardView-BnrlcswN.js +++ b/web/dist/assets/DashboardView-BD4i_GCA.js @@ -1,4 +1,4 @@ -import{c as A,d as H,o as c,a as r,F as w,r as M,b as l,n as q,e as C,u as e,f as W,t as n,g as b,h as X,w as u,_ as z,i as ee,j as S,k as v,l as s,m as Q,p as t,T as te,q as le,s as se,v as ae}from"./index-D3ZCYstt.js";import{c as y,t as oe,p as ne,d as ue}from"./format-B6sc_rZ4.js";import{A as ce,_ as de}from"./EventItem.vue_vue_type_script_setup_true_lang-DS497KtL.js";import{_ as re}from"./PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js";import{_ as j,a as P,b as Z,c as T}from"./CardTitle.vue_vue_type_script_setup_true_lang-BcE23HB-.js";import{_ as ie}from"./Skeleton.vue_vue_type_script_setup_true_lang-C9uTg8Ty.js";import{_ as me,a as pe,b as G}from"./TabsTrigger.vue_vue_type_script_setup_true_lang-DTNukDpV.js";import"./Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js";import"./Collection-D-pf6tmY.js";/** +import{c as A,d as H,o as c,a as r,F as w,r as M,b as l,n as q,e as C,u as e,f as W,t as n,g as b,h as X,w as u,_ as z,i as ee,j as S,k as v,l as s,m as Q,p as t,T as te,q as le,s as se,v as ae}from"./index-BKPz7Obh.js";import{c as y,t as oe,p as ne,d as ue}from"./format-B6sc_rZ4.js";import{A as ce,_ as de}from"./EventItem.vue_vue_type_script_setup_true_lang-JeqwaMaY.js";import{_ as re}from"./PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js";import{_ as j,a as P,b as Z,c as T}from"./CardTitle.vue_vue_type_script_setup_true_lang-BHtPbA-o.js";import{_ as ie}from"./Skeleton.vue_vue_type_script_setup_true_lang-DG3HTLWx.js";import{_ as me,a as pe,b as G}from"./TabsTrigger.vue_vue_type_script_setup_true_lang-_qQ6JBVg.js";import"./Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js";import"./Collection-BaXBMWO5.js";/** * @license lucide-vue-next v0.469.0 - ISC * * This source code is licensed under the ISC license. diff --git a/web/dist/assets/EventItem.vue_vue_type_script_setup_true_lang-DS497KtL.js b/web/dist/assets/EventItem.vue_vue_type_script_setup_true_lang-JeqwaMaY.js similarity index 92% rename from web/dist/assets/EventItem.vue_vue_type_script_setup_true_lang-DS497KtL.js rename to web/dist/assets/EventItem.vue_vue_type_script_setup_true_lang-JeqwaMaY.js index 387be7e..42810af 100644 --- a/web/dist/assets/EventItem.vue_vue_type_script_setup_true_lang-DS497KtL.js +++ b/web/dist/assets/EventItem.vue_vue_type_script_setup_true_lang-JeqwaMaY.js @@ -1,4 +1,4 @@ -import{_ as a}from"./Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js";import{c as h,d as x,o,h as m,u as t,w as c,k as i,t as n,g as v,l as d,a as k,b as r,p,j as f}from"./index-D3ZCYstt.js";import{t as b,e as _}from"./format-B6sc_rZ4.js";/** +import{_ as a}from"./Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js";import{c as h,d as x,o,h as m,u as t,w as c,k as i,t as n,g as v,l as d,a as k,b as r,p,j as f}from"./index-BKPz7Obh.js";import{t as b,e as _}from"./format-B6sc_rZ4.js";/** * @license lucide-vue-next v0.469.0 - ISC * * This source code is licensed under the ISC license. diff --git a/web/dist/assets/EventsView-Blmx8SEw.js b/web/dist/assets/EventsView-Blmx8SEw.js new file mode 100644 index 0000000..0786c87 --- /dev/null +++ b/web/dist/assets/EventsView-Blmx8SEw.js @@ -0,0 +1,16 @@ +import{_ as D,a as F}from"./EventItem.vue_vue_type_script_setup_true_lang-JeqwaMaY.js";import{_ as J}from"./PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js";import{_ as N}from"./Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js";import{c as V,d as A,x as M,a as i,p as r,w as c,u as e,l as t,b as l,y as G,t as s,j as p,_ as H,m as f,g as _,o as n,s as g,h as P,k,F as x,r as S,z as T,A as K,q as Q}from"./index-BKPz7Obh.js";import{S as R,_ as W,T as X}from"./Modal.vue_vue_type_script_setup_true_lang-Bd1uxkqS.js";import{_ as O}from"./Select.vue_vue_type_script_setup_true_lang-CONzBLld.js";import{a as Y,e as U}from"./format-B6sc_rZ4.js";import"./Collection-BaXBMWO5.js";/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Z=V("CopyIcon",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ee=V("PauseIcon",[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1",key:"zuxfzm"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1",key:"1okwgv"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const te=V("PlayIcon",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]),se={class:"hidden sm:inline"},le={class:"hidden sm:inline"},ae={class:"mb-3 flex flex-col gap-2 sm:flex-row"},oe={class:"relative flex-1"},ne={class:"grid grid-cols-2 gap-2 sm:flex"},re={key:0,class:"text-muted-foreground mb-2 flex items-center justify-between gap-2 text-xs"},ue={key:0},ie={key:0,class:"flex flex-col"},de={key:1,class:"text-muted-foreground py-12 text-center text-sm"},ce={key:0,class:"flex flex-col gap-3 text-sm"},ve={class:"flex flex-wrap items-center gap-2"},me={class:"text-muted-foreground text-xs"},pe={class:"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-xs sm:text-sm"},fe={class:"text-muted-foreground"},_e={class:"font-mono break-all"},xe={class:"text-muted-foreground"},he={class:"font-mono break-all"},ye={class:"text-muted-foreground"},ge={class:"font-mono break-all"},ke={class:"text-muted-foreground"},be={class:"font-mono break-all"},we={class:"text-muted-foreground"},Ce={class:"break-all"},Pe={class:"text-muted-foreground"},Ve={class:"text-destructive break-all"},ze={class:"text-muted-foreground mb-1.5 text-xs font-medium"},$e={key:0,class:"flex flex-col gap-2"},Ie={class:"border-b px-2.5 py-1.5 text-xs font-medium"},Le={class:"overflow-x-auto px-2.5 py-2 font-mono text-[11px] leading-relaxed"},Ne={key:1,class:"text-muted-foreground text-xs"},Fe=A({__name:"EventsView",setup(Se){const{events:b}=Q(),v=f(!1),h=f([]),w=f(""),m=f("all"),y=f("all"),a=f(null);M(v,d=>{h.value=d?b.value:[]});const z=_(()=>v.value?h.value:b.value),$=_(()=>v.value?Math.max(0,b.value.length-h.value.length):0),I=_(()=>{const d=w.value.trim().toLowerCase();return z.value.filter(o=>{if(m.value!=="all"){if(m.value==="log"||m.value==="error"){if(o.kind!==m.value)return!1}else if(o.kind!=="action"||o.action!==m.value)return!1}return y.value!=="all"&&o.proto!==y.value?!1:d?o.srcIP.toLowerCase().includes(d)||o.dstIP.toLowerCase().includes(d)||(o.host??"").toLowerCase().includes(d)||(o.rule??"").toLowerCase().includes(d):!0})}),j=_(()=>[{value:"all",label:t("common.all")},{value:"block",label:t("action.block")},{value:"drop",label:t("action.drop")},{value:"allow",label:t("action.allow")},{value:"modify",label:t("action.modify")},{value:"log",label:t("action.log")},{value:"error",label:t("action.error")}]),q=_(()=>[{value:"all",label:t("common.all")},{value:"tcp",label:"TCP"},{value:"udp",label:"UDP"}]),L=_(()=>{var d;return Object.entries(((d=a.value)==null?void 0:d.props)??{})});async function B(){if(a.value)try{await navigator.clipboard.writeText(JSON.stringify(a.value,null,2)),T.success(t("common.copied"))}catch{T.error(t("common.error"))}}function E(){K(),h.value=[]}return(d,o)=>(n(),i("div",null,[r(J,{title:e(t)("events.title"),description:e(t)("events.subtitle")},{actions:c(()=>[r(e(g),{variant:"outline",size:"sm",onClick:o[0]||(o[0]=u=>v.value=!v.value)},{default:c(()=>[v.value?(n(),P(e(te),{key:0,class:"size-3.5"})):(n(),P(e(ee),{key:1,class:"size-3.5"})),l("span",se,s(v.value?e(t)("events.resume"):e(t)("events.pause")),1)]),_:1}),r(e(g),{variant:"outline",size:"sm",onClick:E},{default:c(()=>[r(e(X),{class:"size-3.5"}),l("span",le,s(e(t)("events.clear")),1)]),_:1})]),_:1},8,["title","description"]),l("div",ae,[l("div",oe,[r(e(R),{class:"text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2"}),r(e(G),{modelValue:w.value,"onUpdate:modelValue":o[1]||(o[1]=u=>w.value=u),placeholder:e(t)("events.searchPlaceholder"),class:"pl-9",type:"search"},null,8,["modelValue","placeholder"])]),l("div",ne,[r(e(O),{modelValue:m.value,"onUpdate:modelValue":o[2]||(o[2]=u=>m.value=u),options:j.value,"aria-label":e(t)("events.filterAction"),class:"sm:w-32"},null,8,["modelValue","options","aria-label"]),r(e(O),{modelValue:y.value,"onUpdate:modelValue":o[3]||(o[3]=u=>y.value=u),options:q.value,"aria-label":e(t)("events.filterProto"),class:"sm:w-28"},null,8,["modelValue","options","aria-label"])])]),v.value?(n(),i("div",re,[r(e(N),{variant:"drop"},{default:c(()=>[k(s(e(t)("events.paused")),1)]),_:1}),$.value>0?(n(),i("span",ue,s(e(t)("events.buffered",{n:$.value})),1)):p("",!0)])):p("",!0),r(e(H),{class:"px-1.5 py-1.5 sm:px-2.5"},{default:c(()=>[I.value.length?(n(),i("div",ie,[(n(!0),i(x,null,S(I.value,u=>(n(),P(D,{key:u.seq,event:u,onSelect:o[4]||(o[4]=C=>a.value=C)},null,8,["event"]))),128))])):(n(),i("p",de,s(z.value.length?e(t)("events.emptyFiltered"):e(t)("events.empty")),1))]),_:1}),r(e(W),{open:a.value!==null,title:e(t)("events.detail"),"onUpdate:open":o[6]||(o[6]=u=>!u&&(a.value=null))},{footer:c(()=>[r(e(g),{variant:"outline",onClick:B},{default:c(()=>[r(e(Z),{class:"size-4"}),k(" "+s(e(t)("events.copyJson")),1)]),_:1}),r(e(g),{onClick:o[5]||(o[5]=u=>a.value=null)},{default:c(()=>[k(s(e(t)("common.close")),1)]),_:1})]),default:c(()=>[a.value?(n(),i("div",ce,[l("div",ve,[r(F,{event:a.value},null,8,["event"]),r(e(N),{variant:a.value.proto==="udp"?"udp":"tcp",class:"uppercase"},{default:c(()=>[k(s(a.value.proto),1)]),_:1},8,["variant"]),l("span",me,s(e(Y)(a.value.time)),1)]),l("dl",pe,[l("dt",fe,s(e(t)("events.stream")),1),l("dd",_e,s(a.value.id),1),l("dt",xe,s(e(t)("events.source")),1),l("dd",he,s(e(U)(a.value.srcIP,a.value.srcPort)),1),l("dt",ye,s(e(t)("events.destination")),1),l("dd",ge,s(e(U)(a.value.dstIP,a.value.dstPort)),1),a.value.host?(n(),i(x,{key:0},[l("dt",ke,s(e(t)("events.host")),1),l("dd",be,s(a.value.host),1)],64)):p("",!0),a.value.rule?(n(),i(x,{key:1},[l("dt",we,s(e(t)("events.rule")),1),l("dd",Ce,s(a.value.rule),1)],64)):p("",!0),a.value.message?(n(),i(x,{key:2},[l("dt",Pe,s(e(t)("common.error")),1),l("dd",Ve,s(a.value.message),1)],64)):p("",!0)]),l("div",null,[l("p",ze,s(e(t)("events.props")),1),L.value.length?(n(),i("div",$e,[(n(!0),i(x,null,S(L.value,([u,C])=>(n(),i("div",{key:u,class:"rounded-lg border"},[l("div",Ie,s(u),1),l("pre",Le,s(JSON.stringify(C,null,2)),1)]))),128))])):(n(),i("p",Ne,s(e(t)("events.noProps")),1))])])):p("",!0)]),_:1},8,["open","title"])]))}});export{Fe as default}; diff --git a/web/dist/assets/EventsView-DvVZcEec.js b/web/dist/assets/EventsView-DvVZcEec.js deleted file mode 100644 index 05cd279..0000000 --- a/web/dist/assets/EventsView-DvVZcEec.js +++ /dev/null @@ -1,21 +0,0 @@ -import{_ as D,a as F}from"./EventItem.vue_vue_type_script_setup_true_lang-DS497KtL.js";import{_ as J}from"./PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js";import{_ as q}from"./Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js";import{c as b,d as A,x as M,a as i,p as r,w as d,u as e,l as t,b as l,y as G,t as s,j as p,_ as H,m as f,g as _,o as n,s as g,h as V,k,F as x,r as N,z as S,A as K,q as Q}from"./index-D3ZCYstt.js";import{_ as R,T as W}from"./Modal.vue_vue_type_script_setup_true_lang-gNNtNPLv.js";import{_ as T}from"./Select.vue_vue_type_script_setup_true_lang-C15l-n0X.js";import{a as X,e as j}from"./format-B6sc_rZ4.js";import"./Collection-D-pf6tmY.js";/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Y=b("CopyIcon",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Z=b("PauseIcon",[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1",key:"zuxfzm"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1",key:"1okwgv"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const ee=b("PlayIcon",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const te=b("SearchIcon",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]),se={class:"hidden sm:inline"},le={class:"hidden sm:inline"},ae={class:"mb-3 flex flex-col gap-2 sm:flex-row"},oe={class:"relative flex-1"},ne={class:"grid grid-cols-2 gap-2 sm:flex"},re={key:0,class:"text-muted-foreground mb-2 flex items-center justify-between gap-2 text-xs"},ue={key:0},ie={key:0,class:"flex flex-col"},ce={key:1,class:"text-muted-foreground py-12 text-center text-sm"},de={key:0,class:"flex flex-col gap-3 text-sm"},ve={class:"flex flex-wrap items-center gap-2"},me={class:"text-muted-foreground text-xs"},pe={class:"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-xs sm:text-sm"},fe={class:"text-muted-foreground"},_e={class:"font-mono break-all"},xe={class:"text-muted-foreground"},he={class:"font-mono break-all"},ye={class:"text-muted-foreground"},ge={class:"font-mono break-all"},ke={class:"text-muted-foreground"},be={class:"font-mono break-all"},we={class:"text-muted-foreground"},Ce={class:"break-all"},Pe={class:"text-muted-foreground"},Ve={class:"text-destructive break-all"},ze={class:"text-muted-foreground mb-1.5 text-xs font-medium"},$e={key:0,class:"flex flex-col gap-2"},Ie={class:"border-b px-2.5 py-1.5 text-xs font-medium"},Le={class:"overflow-x-auto px-2.5 py-2 font-mono text-[11px] leading-relaxed"},qe={key:1,class:"text-muted-foreground text-xs"},Fe=A({__name:"EventsView",setup(Ne){const{events:w}=Q(),v=f(!1),h=f([]),C=f(""),m=f("all"),y=f("all"),a=f(null);M(v,c=>{h.value=c?w.value:[]});const z=_(()=>v.value?h.value:w.value),$=_(()=>v.value?Math.max(0,w.value.length-h.value.length):0),I=_(()=>{const c=C.value.trim().toLowerCase();return z.value.filter(o=>{if(m.value!=="all"){if(m.value==="log"||m.value==="error"){if(o.kind!==m.value)return!1}else if(o.kind!=="action"||o.action!==m.value)return!1}return y.value!=="all"&&o.proto!==y.value?!1:c?o.srcIP.toLowerCase().includes(c)||o.dstIP.toLowerCase().includes(c)||(o.host??"").toLowerCase().includes(c)||(o.rule??"").toLowerCase().includes(c):!0})}),O=_(()=>[{value:"all",label:t("common.all")},{value:"block",label:t("action.block")},{value:"drop",label:t("action.drop")},{value:"allow",label:t("action.allow")},{value:"modify",label:t("action.modify")},{value:"log",label:t("action.log")},{value:"error",label:t("action.error")}]),U=_(()=>[{value:"all",label:t("common.all")},{value:"tcp",label:"TCP"},{value:"udp",label:"UDP"}]),L=_(()=>{var c;return Object.entries(((c=a.value)==null?void 0:c.props)??{})});async function B(){if(a.value)try{await navigator.clipboard.writeText(JSON.stringify(a.value,null,2)),S.success(t("common.copied"))}catch{S.error(t("common.error"))}}function E(){K(),h.value=[]}return(c,o)=>(n(),i("div",null,[r(J,{title:e(t)("events.title"),description:e(t)("events.subtitle")},{actions:d(()=>[r(e(g),{variant:"outline",size:"sm",onClick:o[0]||(o[0]=u=>v.value=!v.value)},{default:d(()=>[v.value?(n(),V(e(ee),{key:0,class:"size-3.5"})):(n(),V(e(Z),{key:1,class:"size-3.5"})),l("span",se,s(v.value?e(t)("events.resume"):e(t)("events.pause")),1)]),_:1}),r(e(g),{variant:"outline",size:"sm",onClick:E},{default:d(()=>[r(e(W),{class:"size-3.5"}),l("span",le,s(e(t)("events.clear")),1)]),_:1})]),_:1},8,["title","description"]),l("div",ae,[l("div",oe,[r(e(te),{class:"text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2"}),r(e(G),{modelValue:C.value,"onUpdate:modelValue":o[1]||(o[1]=u=>C.value=u),placeholder:e(t)("events.searchPlaceholder"),class:"pl-9",type:"search"},null,8,["modelValue","placeholder"])]),l("div",ne,[r(e(T),{modelValue:m.value,"onUpdate:modelValue":o[2]||(o[2]=u=>m.value=u),options:O.value,"aria-label":e(t)("events.filterAction"),class:"sm:w-32"},null,8,["modelValue","options","aria-label"]),r(e(T),{modelValue:y.value,"onUpdate:modelValue":o[3]||(o[3]=u=>y.value=u),options:U.value,"aria-label":e(t)("events.filterProto"),class:"sm:w-28"},null,8,["modelValue","options","aria-label"])])]),v.value?(n(),i("div",re,[r(e(q),{variant:"drop"},{default:d(()=>[k(s(e(t)("events.paused")),1)]),_:1}),$.value>0?(n(),i("span",ue,s(e(t)("events.buffered",{n:$.value})),1)):p("",!0)])):p("",!0),r(e(H),{class:"px-1.5 py-1.5 sm:px-2.5"},{default:d(()=>[I.value.length?(n(),i("div",ie,[(n(!0),i(x,null,N(I.value,u=>(n(),V(D,{key:u.seq,event:u,onSelect:o[4]||(o[4]=P=>a.value=P)},null,8,["event"]))),128))])):(n(),i("p",ce,s(z.value.length?e(t)("events.emptyFiltered"):e(t)("events.empty")),1))]),_:1}),r(e(R),{open:a.value!==null,title:e(t)("events.detail"),"onUpdate:open":o[6]||(o[6]=u=>!u&&(a.value=null))},{footer:d(()=>[r(e(g),{variant:"outline",onClick:B},{default:d(()=>[r(e(Y),{class:"size-4"}),k(" "+s(e(t)("events.copyJson")),1)]),_:1}),r(e(g),{onClick:o[5]||(o[5]=u=>a.value=null)},{default:d(()=>[k(s(e(t)("common.close")),1)]),_:1})]),default:d(()=>[a.value?(n(),i("div",de,[l("div",ve,[r(F,{event:a.value},null,8,["event"]),r(e(q),{variant:a.value.proto==="udp"?"udp":"tcp",class:"uppercase"},{default:d(()=>[k(s(a.value.proto),1)]),_:1},8,["variant"]),l("span",me,s(e(X)(a.value.time)),1)]),l("dl",pe,[l("dt",fe,s(e(t)("events.stream")),1),l("dd",_e,s(a.value.id),1),l("dt",xe,s(e(t)("events.source")),1),l("dd",he,s(e(j)(a.value.srcIP,a.value.srcPort)),1),l("dt",ye,s(e(t)("events.destination")),1),l("dd",ge,s(e(j)(a.value.dstIP,a.value.dstPort)),1),a.value.host?(n(),i(x,{key:0},[l("dt",ke,s(e(t)("events.host")),1),l("dd",be,s(a.value.host),1)],64)):p("",!0),a.value.rule?(n(),i(x,{key:1},[l("dt",we,s(e(t)("events.rule")),1),l("dd",Ce,s(a.value.rule),1)],64)):p("",!0),a.value.message?(n(),i(x,{key:2},[l("dt",Pe,s(e(t)("common.error")),1),l("dd",Ve,s(a.value.message),1)],64)):p("",!0)]),l("div",null,[l("p",ze,s(e(t)("events.props")),1),L.value.length?(n(),i("div",$e,[(n(!0),i(x,null,N(L.value,([u,P])=>(n(),i("div",{key:u,class:"rounded-lg border"},[l("div",Ie,s(u),1),l("pre",Le,s(JSON.stringify(P,null,2)),1)]))),128))])):(n(),i("p",qe,s(e(t)("events.noProps")),1))])])):p("",!0)]),_:1},8,["open","title"])]))}});export{Fe as default}; diff --git a/web/dist/assets/Modal.vue_vue_type_script_setup_true_lang-gNNtNPLv.js b/web/dist/assets/Modal.vue_vue_type_script_setup_true_lang-Bd1uxkqS.js similarity index 73% rename from web/dist/assets/Modal.vue_vue_type_script_setup_true_lang-gNNtNPLv.js rename to web/dist/assets/Modal.vue_vue_type_script_setup_true_lang-Bd1uxkqS.js index 2c5688f..392f46f 100644 --- a/web/dist/assets/Modal.vue_vue_type_script_setup_true_lang-gNNtNPLv.js +++ b/web/dist/assets/Modal.vue_vue_type_script_setup_true_lang-Bd1uxkqS.js @@ -1,6 +1,11 @@ -import{c as V,d as y,E as N,D as S,H as g,u as e,m as w,G as O,o as m,h as _,w as p,C as D,P,K as j,p as C,x as I,g as E,W as k,X as x,J as z,j as M,Y as L,Z as U,e as X,f as G,b as h,k as $,t as A,$ as J,a as W}from"./index-D3ZCYstt.js";import{c as Y,d as R,g as H}from"./Collection-D-pf6tmY.js";import{D as Z,g as Q,F as ee,a as F,b as te,P as T,c as oe,T as se}from"./Select.vue_vue_type_script_setup_true_lang-C15l-n0X.js";/** +import{c as T,d as y,G as K,E as N,H as g,u as e,m as w,R as O,o as m,h as _,w as p,D,P as k,O as j,p as C,x as I,g as E,a6 as P,a7 as x,M as z,j as M,V as L,W as U,e as G,f as W,b as B,k as $,t as A,Z as X,a as Z}from"./index-BKPz7Obh.js";import{c as J,d as R,g as H}from"./Collection-BaXBMWO5.js";import{D as Q,m as Y,F as ee,n as F,e as te,k as S,c as oe,T as se}from"./Select.vue_vue_type_script_setup_true_lang-CONzBLld.js";/** * @license lucide-vue-next v0.469.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const $e=V("Trash2Icon",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]),[b,ae]=Y("DialogRoot");var re=y({inheritAttrs:!1,__name:"DialogRoot",props:{open:{type:Boolean,required:!1,default:void 0},defaultOpen:{type:Boolean,required:!1,default:!1},modal:{type:Boolean,required:!1,default:!0},unmountOnHide:{type:Boolean,required:!1,default:!0}},emits:["update:open"],setup(u,{emit:r}){const o=u,t=N(o,"open",r,{defaultValue:o.defaultOpen,passive:o.open===void 0}),n=w(),f=w(),{modal:i,unmountOnHide:d}=S(o);return ae({open:t,modal:i,unmountOnHide:d,openModal:()=>{t.value=!0},onOpenChange:a=>{t.value=a},onOpenToggle:()=>{t.value=!t.value},contentId:"",titleId:"",descriptionId:"",triggerElement:n,contentElement:f}),(a,c)=>g(a.$slots,"default",{open:e(t),close:()=>t.value=!1})}}),ne=re,le=y({__name:"DialogClose",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(u){const r=u;O();const o=b();return(s,t)=>(m(),_(e(P),D(r,{type:s.as==="button"?"button":void 0,onClick:t[0]||(t[0]=n=>e(o).onOpenChange(!1))}),{default:p(()=>[g(s.$slots,"default")]),_:3},16,["type"]))}}),ue=le,ie=y({__name:"DialogContentImpl",props:{forceMount:{type:Boolean,required:!1},trapFocus:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!1}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,s=r,t=b(),{forwardRef:n,currentElement:f}=O();return t.titleId||(t.titleId=R(void 0,"reka-dialog-title")),t.descriptionId||(t.descriptionId=R(void 0,"reka-dialog-description")),j(()=>{t.contentElement=f,H()!==document.body&&(t.triggerElement.value=H())}),(i,d)=>(m(),_(e(ee),{"as-child":"",loop:"",trapped:o.trapFocus,present:o.present,onMountAutoFocus:d[5]||(d[5]=a=>s("openAutoFocus",a)),onUnmountAutoFocus:d[6]||(d[6]=a=>s("closeAutoFocus",a))},{default:p(()=>[C(e(Z),D({id:e(t).contentId,ref:e(n),as:i.as,"as-child":i.asChild,present:o.present,"disable-outside-pointer-events":i.disableOutsidePointerEvents,role:"dialog","aria-describedby":e(t).descriptionId,"aria-labelledby":e(t).titleId,"data-state":e(Q)(e(t).open.value)},i.$attrs,{onDismiss:d[0]||(d[0]=a=>e(t).onOpenChange(!1)),onEscapeKeyDown:d[1]||(d[1]=a=>s("escapeKeyDown",a)),onFocusOutside:d[2]||(d[2]=a=>s("focusOutside",a)),onInteractOutside:d[3]||(d[3]=a=>s("interactOutside",a)),onPointerDownOutside:d[4]||(d[4]=a=>s("pointerDownOutside",a))}),{default:p(()=>[g(i.$slots,"default")]),_:3},16,["id","as","as-child","present","disable-outside-pointer-events","aria-describedby","aria-labelledby","data-state"])]),_:3},8,["trapped","present"]))}}),K=ie,de=y({__name:"DialogContentModal",props:{forceMount:{type:Boolean,required:!1},trapFocus:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!0}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,s=r,t=b(),n=F(s),{forwardRef:f,currentElement:i}=O(),d=E(()=>o.present?i.value:void 0);te(d);const a=E(()=>{const{present:c,...l}=o;return l});return I(()=>o.present,(c,l)=>{var v;!c&&l&&((v=t.triggerElement.value)==null||v.focus())}),(c,l)=>(m(),_(K,D({...a.value,...e(n)},{ref:e(f),present:c.present,"trap-focus":e(t).open.value,"disable-outside-pointer-events":o.disableOutsidePointerEvents,onCloseAutoFocus:l[0]||(l[0]=v=>{var q;v.defaultPrevented||(v.preventDefault(),(q=e(t).triggerElement.value)==null||q.focus())}),onPointerDownOutside:l[1]||(l[1]=v=>{const q=v.detail.originalEvent,B=q.button===0&&q.ctrlKey===!0;(q.button===2||B)&&v.preventDefault()}),onFocusOutside:l[2]||(l[2]=v=>{v.preventDefault()})}),{default:p(()=>[g(c.$slots,"default")]),_:3},16,["present","trap-focus","disable-outside-pointer-events"]))}}),pe=de,fe=y({__name:"DialogContentNonModal",props:{forceMount:{type:Boolean,required:!1},trapFocus:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!0}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,t=F(r);O();const n=b(),f=w(!1),i=w(!1),d=E(()=>{const{present:a,...c}=o;return c});return I(()=>o.present,(a,c)=>{var l;!a&&c&&(f.value||(l=n.triggerElement.value)==null||l.focus(),f.value=!1,i.value=!1)}),(a,c)=>(m(),_(K,D({...d.value,...e(t)},{present:a.present,"trap-focus":!1,"disable-outside-pointer-events":!1,onCloseAutoFocus:c[0]||(c[0]=l=>{var v;l.defaultPrevented||(f.value||(v=e(n).triggerElement.value)==null||v.focus(),l.preventDefault()),f.value=!1,i.value=!1}),onInteractOutside:c[1]||(c[1]=l=>{var B;l.defaultPrevented||(f.value=!0,l.detail.originalEvent.type==="pointerdown"&&(i.value=!0));const v=l.target;((B=e(n).triggerElement.value)==null?void 0:B.contains(v))&&l.preventDefault(),l.detail.originalEvent.type==="focusin"&&i.value&&l.preventDefault()})}),{default:p(()=>[g(a.$slots,"default")]),_:3},16,["present"]))}}),ce=fe,ve=y({__name:"DialogContent",props:{forceMount:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1,default:void 0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,s=r,t=b(),n=F(s),{forwardRef:f}=O();return(i,d)=>(m(),_(e(T),{present:i.forceMount||e(t).open.value,"force-mount":i.forceMount||!e(t).unmountOnHide.value},{default:p(({present:a})=>[e(t).modal.value?k((m(),_(pe,D({key:0,ref:e(f),present:e(t).unmountOnHide.value||a},{...o,...e(n),...i.$attrs}),{default:p(()=>[g(i.$slots,"default")]),_:2},1040,["present"])),[[x,e(t).unmountOnHide.value||a]]):k((m(),_(ce,D({key:1,ref:e(f),present:e(t).unmountOnHide.value||a},{...o,...e(n),...i.$attrs}),{default:p(()=>[g(i.$slots,"default")]),_:2},1040,["present"])),[[x,e(t).unmountOnHide.value||a]])]),_:3},8,["present","force-mount"]))}}),me=ve,_e=y({__name:"DialogDescription",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"p"}},setup(u){const r=u;O();const o=b();return(s,t)=>(m(),_(e(P),D(r,{id:e(o).descriptionId}),{default:p(()=>[g(s.$slots,"default")]),_:3},16,["id"]))}}),ge=_e,ye=y({__name:"DialogOverlayImpl",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!1,default:!0}},setup(u){const r=u,o=b(),s=oe(r.present);return I(()=>r.present,t=>s.value=t),O(),(t,n)=>(m(),_(e(P),{as:t.as,"as-child":t.asChild,"data-state":e(o).open.value?"open":"closed",style:{"pointer-events":"auto"},onPointerdown:n[0]||(n[0]=z(()=>{},["left","self","prevent"]))},{default:p(()=>[g(t.$slots,"default")]),_:3},8,["as","as-child","data-state"]))}}),De=ye,Oe=y({__name:"DialogOverlay",props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(u){const r=b(),{forwardRef:o}=O();return(s,t)=>{var n;return(n=e(r))!=null&&n.modal.value?(m(),_(e(T),{key:0,present:s.forceMount||e(r).open.value,"force-mount":s.forceMount||!e(r).unmountOnHide.value},{default:p(({present:f})=>[k(C(De,D(s.$attrs,{ref:e(o),as:s.as,"as-child":s.asChild,present:e(r).unmountOnHide.value||f}),{default:p(()=>[g(s.$slots,"default")]),_:2},1040,["as","as-child","present"]),[[x,e(r).unmountOnHide.value||f]])]),_:3},8,["present","force-mount"])):M("v-if",!0)}}}),be=Oe,Ce=y({__name:"DialogPortal",props:{to:{type:null,required:!1},disabled:{type:Boolean,required:!1},defer:{type:Boolean,required:!1},forceMount:{type:Boolean,required:!1}},setup(u){const r=u;return(o,s)=>(m(),_(e(se),L(U(r)),{default:p(()=>[g(o.$slots,"default")]),_:3},16))}}),qe=Ce,Be=y({__name:"DialogTitle",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"h2"}},setup(u){const r=u,o=b();return O(),(s,t)=>(m(),_(e(P),D(r,{id:e(o).titleId}),{default:p(()=>[g(s.$slots,"default")]),_:3},16,["id"]))}}),he=Be;const we={class:"flex items-start justify-between gap-4"},Pe={class:"flex flex-col gap-1"},Ee={class:"min-h-0 flex-1 overflow-y-auto"},ke={key:0,class:"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"},Ae=y({__name:"Modal",props:{open:{type:Boolean},title:{},description:{},class:{}},emits:["update:open"],setup(u,{emit:r}){const o=u,s=r;return(t,n)=>(m(),_(e(ne),{open:o.open,"onUpdate:open":n[0]||(n[0]=f=>s("update:open",f))},{default:p(()=>[C(e(qe),null,{default:p(()=>[C(e(be),{class:"animate-fade-in fixed inset-0 z-50 bg-black/60 backdrop-blur-[2px]"}),C(e(me),{class:X(e(G)("bg-background fixed z-50 flex flex-col gap-4 border shadow-lg outline-none","animate-slide-up inset-x-0 bottom-0 max-h-[92vh] rounded-t-2xl border-b-0 p-4 pb-[max(1rem,env(safe-area-inset-bottom))]","sm:top-1/2 sm:bottom-auto sm:left-1/2 sm:max-h-[85vh] sm:w-full sm:max-w-lg sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-xl sm:border-b sm:p-6",o.class))},{default:p(()=>[n[1]||(n[1]=h("div",{class:"bg-muted-foreground/25 mx-auto -mt-1 mb-1 h-1 w-10 shrink-0 rounded-full sm:hidden"},null,-1)),h("div",we,[h("div",Pe,[C(e(he),{class:"text-base font-semibold"},{default:p(()=>[$(A(o.title),1)]),_:1}),o.description?(m(),_(e(ge),{key:0,class:"text-muted-foreground text-sm"},{default:p(()=>[$(A(o.description),1)]),_:1})):M("",!0)]),C(e(ue),{class:"text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring/40 -mt-1 -mr-1 rounded-md p-1.5 transition-colors outline-none focus-visible:ring-[3px]"},{default:p(()=>[C(e(J),{class:"size-4"})]),_:1})]),h("div",Ee,[g(t.$slots,"default")]),t.$slots.footer?(m(),W("div",ke,[g(t.$slots,"footer")])):M("",!0)]),_:3},8,["class"])]),_:3})]),_:3},8,["open"]))}});export{$e as T,Ae as _}; + */const $e=T("SearchIcon",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ae=T("Trash2Icon",[["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6",key:"4alrt4"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2",key:"v07s0e"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17",key:"1uufr5"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17",key:"xtxkd"}]]),[b,ae]=J("DialogRoot");var re=y({inheritAttrs:!1,__name:"DialogRoot",props:{open:{type:Boolean,required:!1,default:void 0},defaultOpen:{type:Boolean,required:!1,default:!1},modal:{type:Boolean,required:!1,default:!0},unmountOnHide:{type:Boolean,required:!1,default:!0}},emits:["update:open"],setup(u,{emit:r}){const o=u,t=K(o,"open",r,{defaultValue:o.defaultOpen,passive:o.open===void 0}),n=w(),f=w(),{modal:i,unmountOnHide:d}=N(o);return ae({open:t,modal:i,unmountOnHide:d,openModal:()=>{t.value=!0},onOpenChange:a=>{t.value=a},onOpenToggle:()=>{t.value=!t.value},contentId:"",titleId:"",descriptionId:"",triggerElement:n,contentElement:f}),(a,c)=>g(a.$slots,"default",{open:e(t),close:()=>t.value=!1})}}),ne=re,le=y({__name:"DialogClose",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(u){const r=u;O();const o=b();return(s,t)=>(m(),_(e(k),D(r,{type:s.as==="button"?"button":void 0,onClick:t[0]||(t[0]=n=>e(o).onOpenChange(!1))}),{default:p(()=>[g(s.$slots,"default")]),_:3},16,["type"]))}}),ue=le,ie=y({__name:"DialogContentImpl",props:{forceMount:{type:Boolean,required:!1},trapFocus:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!1}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,s=r,t=b(),{forwardRef:n,currentElement:f}=O();return t.titleId||(t.titleId=R(void 0,"reka-dialog-title")),t.descriptionId||(t.descriptionId=R(void 0,"reka-dialog-description")),j(()=>{t.contentElement=f,H()!==document.body&&(t.triggerElement.value=H())}),(i,d)=>(m(),_(e(ee),{"as-child":"",loop:"",trapped:o.trapFocus,present:o.present,onMountAutoFocus:d[5]||(d[5]=a=>s("openAutoFocus",a)),onUnmountAutoFocus:d[6]||(d[6]=a=>s("closeAutoFocus",a))},{default:p(()=>[C(e(Q),D({id:e(t).contentId,ref:e(n),as:i.as,"as-child":i.asChild,present:o.present,"disable-outside-pointer-events":i.disableOutsidePointerEvents,role:"dialog","aria-describedby":e(t).descriptionId,"aria-labelledby":e(t).titleId,"data-state":e(Y)(e(t).open.value)},i.$attrs,{onDismiss:d[0]||(d[0]=a=>e(t).onOpenChange(!1)),onEscapeKeyDown:d[1]||(d[1]=a=>s("escapeKeyDown",a)),onFocusOutside:d[2]||(d[2]=a=>s("focusOutside",a)),onInteractOutside:d[3]||(d[3]=a=>s("interactOutside",a)),onPointerDownOutside:d[4]||(d[4]=a=>s("pointerDownOutside",a))}),{default:p(()=>[g(i.$slots,"default")]),_:3},16,["id","as","as-child","present","disable-outside-pointer-events","aria-describedby","aria-labelledby","data-state"])]),_:3},8,["trapped","present"]))}}),V=ie,de=y({__name:"DialogContentModal",props:{forceMount:{type:Boolean,required:!1},trapFocus:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!0}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,s=r,t=b(),n=F(s),{forwardRef:f,currentElement:i}=O(),d=E(()=>o.present?i.value:void 0);te(d);const a=E(()=>{const{present:c,...l}=o;return l});return I(()=>o.present,(c,l)=>{var v;!c&&l&&((v=t.triggerElement.value)==null||v.focus())}),(c,l)=>(m(),_(V,D({...a.value,...e(n)},{ref:e(f),present:c.present,"trap-focus":e(t).open.value,"disable-outside-pointer-events":o.disableOutsidePointerEvents,onCloseAutoFocus:l[0]||(l[0]=v=>{var q;v.defaultPrevented||(v.preventDefault(),(q=e(t).triggerElement.value)==null||q.focus())}),onPointerDownOutside:l[1]||(l[1]=v=>{const q=v.detail.originalEvent,h=q.button===0&&q.ctrlKey===!0;(q.button===2||h)&&v.preventDefault()}),onFocusOutside:l[2]||(l[2]=v=>{v.preventDefault()})}),{default:p(()=>[g(c.$slots,"default")]),_:3},16,["present","trap-focus","disable-outside-pointer-events"]))}}),pe=de,fe=y({__name:"DialogContentNonModal",props:{forceMount:{type:Boolean,required:!1},trapFocus:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!0}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,t=F(r);O();const n=b(),f=w(!1),i=w(!1),d=E(()=>{const{present:a,...c}=o;return c});return I(()=>o.present,(a,c)=>{var l;!a&&c&&(f.value||(l=n.triggerElement.value)==null||l.focus(),f.value=!1,i.value=!1)}),(a,c)=>(m(),_(V,D({...d.value,...e(t)},{present:a.present,"trap-focus":!1,"disable-outside-pointer-events":!1,onCloseAutoFocus:c[0]||(c[0]=l=>{var v;l.defaultPrevented||(f.value||(v=e(n).triggerElement.value)==null||v.focus(),l.preventDefault()),f.value=!1,i.value=!1}),onInteractOutside:c[1]||(c[1]=l=>{var h;l.defaultPrevented||(f.value=!0,l.detail.originalEvent.type==="pointerdown"&&(i.value=!0));const v=l.target;((h=e(n).triggerElement.value)==null?void 0:h.contains(v))&&l.preventDefault(),l.detail.originalEvent.type==="focusin"&&i.value&&l.preventDefault()})}),{default:p(()=>[g(a.$slots,"default")]),_:3},16,["present"]))}}),ce=fe,ve=y({__name:"DialogContent",props:{forceMount:{type:Boolean,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1,default:void 0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside","openAutoFocus","closeAutoFocus"],setup(u,{emit:r}){const o=u,s=r,t=b(),n=F(s),{forwardRef:f}=O();return(i,d)=>(m(),_(e(S),{present:i.forceMount||e(t).open.value,"force-mount":i.forceMount||!e(t).unmountOnHide.value},{default:p(({present:a})=>[e(t).modal.value?P((m(),_(pe,D({key:0,ref:e(f),present:e(t).unmountOnHide.value||a},{...o,...e(n),...i.$attrs}),{default:p(()=>[g(i.$slots,"default")]),_:2},1040,["present"])),[[x,e(t).unmountOnHide.value||a]]):P((m(),_(ce,D({key:1,ref:e(f),present:e(t).unmountOnHide.value||a},{...o,...e(n),...i.$attrs}),{default:p(()=>[g(i.$slots,"default")]),_:2},1040,["present"])),[[x,e(t).unmountOnHide.value||a]])]),_:3},8,["present","force-mount"]))}}),me=ve,_e=y({__name:"DialogDescription",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"p"}},setup(u){const r=u;O();const o=b();return(s,t)=>(m(),_(e(k),D(r,{id:e(o).descriptionId}),{default:p(()=>[g(s.$slots,"default")]),_:3},16,["id"]))}}),ge=_e,ye=y({__name:"DialogOverlayImpl",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1},present:{type:Boolean,required:!1,default:!0}},setup(u){const r=u,o=b(),s=oe(r.present);return I(()=>r.present,t=>s.value=t),O(),(t,n)=>(m(),_(e(k),{as:t.as,"as-child":t.asChild,"data-state":e(o).open.value?"open":"closed",style:{"pointer-events":"auto"},onPointerdown:n[0]||(n[0]=z(()=>{},["left","self","prevent"]))},{default:p(()=>[g(t.$slots,"default")]),_:3},8,["as","as-child","data-state"]))}}),De=ye,Oe=y({__name:"DialogOverlay",props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(u){const r=b(),{forwardRef:o}=O();return(s,t)=>{var n;return(n=e(r))!=null&&n.modal.value?(m(),_(e(S),{key:0,present:s.forceMount||e(r).open.value,"force-mount":s.forceMount||!e(r).unmountOnHide.value},{default:p(({present:f})=>[P(C(De,D(s.$attrs,{ref:e(o),as:s.as,"as-child":s.asChild,present:e(r).unmountOnHide.value||f}),{default:p(()=>[g(s.$slots,"default")]),_:2},1040,["as","as-child","present"]),[[x,e(r).unmountOnHide.value||f]])]),_:3},8,["present","force-mount"])):M("v-if",!0)}}}),be=Oe,Ce=y({__name:"DialogPortal",props:{to:{type:null,required:!1},disabled:{type:Boolean,required:!1},defer:{type:Boolean,required:!1},forceMount:{type:Boolean,required:!1}},setup(u){const r=u;return(o,s)=>(m(),_(e(se),L(U(r)),{default:p(()=>[g(o.$slots,"default")]),_:3},16))}}),qe=Ce,he=y({__name:"DialogTitle",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"h2"}},setup(u){const r=u,o=b();return O(),(s,t)=>(m(),_(e(k),D(r,{id:e(o).titleId}),{default:p(()=>[g(s.$slots,"default")]),_:3},16,["id"]))}}),Be=he;const we={class:"flex items-start justify-between gap-4"},ke={class:"flex flex-col gap-1"},Ee={class:"min-h-0 flex-1 overflow-y-auto"},Pe={key:0,class:"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"},Re=y({__name:"Modal",props:{open:{type:Boolean},title:{},description:{},class:{}},emits:["update:open"],setup(u,{emit:r}){const o=u,s=r;return(t,n)=>(m(),_(e(ne),{open:o.open,"onUpdate:open":n[0]||(n[0]=f=>s("update:open",f))},{default:p(()=>[C(e(qe),null,{default:p(()=>[C(e(be),{class:"animate-fade-in fixed inset-0 z-50 bg-black/60 backdrop-blur-[2px]"}),C(e(me),{class:G(e(W)("bg-background fixed z-50 flex flex-col gap-4 border shadow-lg outline-none","animate-slide-up inset-x-0 bottom-0 max-h-[92vh] rounded-t-2xl border-b-0 p-4 pb-[max(1rem,env(safe-area-inset-bottom))]","sm:top-1/2 sm:bottom-auto sm:left-1/2 sm:max-h-[85vh] sm:w-full sm:max-w-lg sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-xl sm:border-b sm:p-6",o.class))},{default:p(()=>[n[1]||(n[1]=B("div",{class:"bg-muted-foreground/25 mx-auto -mt-1 mb-1 h-1 w-10 shrink-0 rounded-full sm:hidden"},null,-1)),B("div",we,[B("div",ke,[C(e(Be),{class:"text-base font-semibold"},{default:p(()=>[$(A(o.title),1)]),_:1}),o.description?(m(),_(e(ge),{key:0,class:"text-muted-foreground text-sm"},{default:p(()=>[$(A(o.description),1)]),_:1})):M("",!0)]),C(e(ue),{class:"text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring/40 -mt-1 -mr-1 rounded-md p-1.5 transition-colors outline-none focus-visible:ring-[3px]"},{default:p(()=>[C(e(X),{class:"size-4"})]),_:1})]),B("div",Ee,[g(t.$slots,"default")]),t.$slots.footer?(m(),Z("div",Pe,[g(t.$slots,"footer")])):M("",!0)]),_:3},8,["class"])]),_:3})]),_:3},8,["open"]))}});export{$e as S,Ae as T,Re as _}; diff --git a/web/dist/assets/PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js b/web/dist/assets/PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js similarity index 90% rename from web/dist/assets/PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js rename to web/dist/assets/PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js index aef7ab2..a0cc132 100644 --- a/web/dist/assets/PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js +++ b/web/dist/assets/PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js @@ -1 +1 @@ -import{d as c,a as t,b as n,t as i,j as a,H as d,o as s}from"./index-D3ZCYstt.js";const l={class:"mb-4 flex flex-wrap items-end justify-between gap-3 sm:mb-6"},m={class:"min-w-0"},p={class:"text-lg font-semibold tracking-tight sm:text-2xl"},_={key:0,class:"text-muted-foreground mt-0.5 text-xs sm:text-sm"},x={key:0,class:"flex shrink-0 items-center gap-2"},g=c({__name:"PageHeader",props:{title:{},description:{}},setup(r){const e=r;return(o,f)=>(s(),t("div",l,[n("div",m,[n("h1",p,i(e.title),1),e.description?(s(),t("p",_,i(e.description),1)):a("",!0)]),o.$slots.actions?(s(),t("div",x,[d(o.$slots,"actions")])):a("",!0)]))}});export{g as _}; +import{d as c,a as t,b as n,t as i,j as a,H as d,o as s}from"./index-BKPz7Obh.js";const l={class:"mb-4 flex flex-wrap items-end justify-between gap-3 sm:mb-6"},m={class:"min-w-0"},p={class:"text-lg font-semibold tracking-tight sm:text-2xl"},_={key:0,class:"text-muted-foreground mt-0.5 text-xs sm:text-sm"},x={key:0,class:"flex shrink-0 items-center gap-2"},g=c({__name:"PageHeader",props:{title:{},description:{}},setup(r){const e=r;return(o,f)=>(s(),t("div",l,[n("div",m,[n("h1",p,i(e.title),1),e.description?(s(),t("p",_,i(e.description),1)):a("",!0)]),o.$slots.actions?(s(),t("div",x,[d(o.$slots,"actions")])):a("",!0)]))}});export{g as _}; diff --git a/web/dist/assets/RulesView-SxOStRNP.js b/web/dist/assets/RulesView-SxOStRNP.js deleted file mode 100644 index fac631a..0000000 --- a/web/dist/assets/RulesView-SxOStRNP.js +++ /dev/null @@ -1,36 +0,0 @@ -import{c as E,B as ge,d as M,x as be,o as c,h as C,C as F,g as B,a as q,j as $,F as N,r as ie,D as ke,E as xe,G as Q,p as u,w as o,H as L,u as e,I as we,J as de,P as W,m as V,K as ce,L as Ve,n as Ce,e as X,f as Y,M as T,N as j,l as n,b as g,t as r,s as I,O as qe,Q as $e,k as b,_ as Se,R as P,y as Ie,z as K}from"./index-D3ZCYstt.js";import{_ as ze}from"./PageHeader.vue_vue_type_script_setup_true_lang-CDyKzgiP.js";import{_ as O}from"./Badge.vue_vue_type_script_setup_true_lang--8bF8KCa.js";import{_ as te,T as Ae}from"./Modal.vue_vue_type_script_setup_true_lang-gNNtNPLv.js";import{V as Be,u as Me,P as Re,_ as se}from"./Select.vue_vue_type_script_setup_true_lang-C15l-n0X.js";import{u as Ee,c as Te}from"./Collection-D-pf6tmY.js";import{i as Pe,m as Ue,c as He,_ as ue,a as je,b as ne}from"./TabsTrigger.vue_vue_type_script_setup_true_lang-DTNukDpV.js";/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Oe=E("ArrowDownIcon",[["path",{d:"M12 5v14",key:"s699le"}],["path",{d:"m19 12-7 7-7-7",key:"1idqje"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Fe=E("ArrowUpIcon",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Ne=E("FileCode2Icon",[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4",key:"1pf5j1"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"m5 12-3 3 3 3",key:"oke12k"}],["path",{d:"m9 18 3-3-3-3",key:"112psh"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Le=E("PencilIcon",[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const De=E("PlusIcon",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Je=E("RotateCcwIcon",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** - * @license lucide-vue-next v0.469.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Ke=E("SaveIcon",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]);function Ge(){var l,t;const k=(t=(l=ge())==null?void 0:l.vnode)==null?void 0:t.scopeId;return k?{[k]:""}:{}}var Qe=M({inheritAttrs:!1,__name:"VisuallyHiddenInputBubble",props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:"fully-hidden"}},setup(k){const l=k,{primitiveElement:t,currentElement:i}=Ee(),m=B(()=>l.checked??l.value);return be(m,(f,p)=>{if(!i.value)return;const _=i.value,w=window.HTMLInputElement.prototype,v=Object.getOwnPropertyDescriptor(w,"value").set;if(v&&f!==p){const A=new Event("input",{bubbles:!0}),S=new Event("change",{bubbles:!0});v.call(_,f),_.dispatchEvent(A),_.dispatchEvent(S)}}),(f,p)=>(c(),C(Be,F({ref_key:"primitiveElement",ref:t},{...l,...f.$attrs},{as:"input"}),null,16))}}),oe=Qe,We=M({inheritAttrs:!1,__name:"VisuallyHiddenInput",props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:"fully-hidden"}},setup(k){const l=k,t=B(()=>typeof l.value=="object"&&Array.isArray(l.value)&&l.value.length===0&&l.required),i=B(()=>typeof l.value=="string"||typeof l.value=="number"||typeof l.value=="boolean"||l.value===null||l.value===void 0?[{name:l.name,value:l.value}]:typeof l.value=="object"&&Array.isArray(l.value)?l.value.flatMap((m,f)=>typeof m=="object"?Object.entries(m).map(([p,_])=>({name:`${l.name}[${f}][${p}]`,value:_})):{name:`${l.name}[${f}]`,value:m}):l.value!==null&&typeof l.value=="object"&&!Array.isArray(l.value)?Object.entries(l.value).map(([m,f])=>({name:`${l.name}[${m}]`,value:f})):[]);return(m,f)=>(c(),q(N,null,[$(" We render single input if it's required "),t.value?(c(),C(oe,F({key:m.name},{...l,...m.$attrs},{name:m.name,value:m.value}),null,16,["name","value"])):(c(!0),q(N,{key:1},ie(i.value,p=>(c(),C(oe,F({key:p.name},{ref_for:!0},{...l,...m.$attrs},{name:p.name,value:p.value}),null,16,["name","value"]))),128))],2112))}}),Xe=We;const[Ye,Ze]=Te("SwitchRoot");var ea=M({inheritAttrs:!1,__name:"SwitchRoot",props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},id:{type:String,required:!1},value:{type:String,required:!1,default:"on"},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:modelValue"],setup(k,{emit:l}){const t=k,i=l,{disabled:m}=ke(t),f=xe(t,"modelValue",i,{defaultValue:t.defaultValue??t.falseValue,passive:t.modelValue===void 0}),p=B(()=>f.value===t.trueValue);function _(){m.value||(f.value=p.value?t.falseValue:t.trueValue)}const{forwardRef:w,currentElement:h}=Q(),v=Me(h),A=Ge(),S=B(()=>{var x;return t.id&&h.value?(x=document.querySelector(`[for="${t.id}"]`))==null?void 0:x.innerText:void 0});return Ze({checked:p,toggleCheck:_,disabled:m}),(x,D)=>(c(),q(N,null,[u(e(W),F({id:x.id,ref:e(w),role:"switch",type:x.as==="button"?"button":void 0,value:x.value,"aria-label":x.$attrs["aria-label"]||S.value,"aria-checked":p.value,"aria-required":x.required,"data-state":p.value?"checked":"unchecked","data-disabled":e(m)?"":void 0,"as-child":x.asChild,as:x.as,disabled:e(m)},{...e(A),...x.$attrs},{onClick:_,onKeydown:we(de(_,["prevent"]),["enter"])}),{default:o(()=>[L(x.$slots,"default",{modelValue:e(f),checked:p.value})]),_:3},16,["id","type","value","aria-label","aria-checked","aria-required","data-state","data-disabled","as-child","as","disabled","onKeydown"]),e(v)&&x.name?(c(),C(e(Xe),F({key:0,type:"checkbox",name:x.name,disabled:e(m),required:x.required,value:x.value,checked:p.value},e(A)),null,16,["name","disabled","required","value","checked"])):$("v-if",!0)],64))}}),aa=ea,la=M({__name:"SwitchThumb",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"span"}},setup(k){const l=Ye();return Q(),(t,i)=>(c(),C(e(W),{"data-state":e(l).checked.value?"checked":"unchecked","data-disabled":e(l).disabled.value?"":void 0,"as-child":t.asChild,as:t.as},{default:o(()=>[L(t.$slots,"default")]),_:3},8,["data-state","data-disabled","as-child","as"]))}}),ta=la,sa=M({__name:"TabsContent",props:{value:{type:[String,Number],required:!0},forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(k){const l=k,{forwardRef:t}=Q(),i=Pe(),m=B(()=>Ue(i.baseId,l.value)),f=B(()=>He(i.baseId,l.value)),p=B(()=>l.value===i.modelValue.value),_=V(p.value);return ce(()=>{i.registerContent(l.value),requestAnimationFrame(()=>{_.value=!1})}),Ve(()=>{i.unregisterContent(l.value)}),(w,h)=>(c(),C(e(Re),{present:w.forceMount||p.value,"force-mount":""},{default:o(({present:v})=>[u(e(W),{id:f.value,ref:e(t),"as-child":w.asChild,as:w.as,role:"tabpanel","data-state":p.value?"active":"inactive","data-orientation":e(i).orientation.value,"aria-labelledby":m.value,hidden:!v,tabindex:"0",style:Ce({animationDuration:_.value?"0s":void 0})},{default:o(()=>[!e(i).unmountOnHide.value||v?L(w.$slots,"default",{key:0}):$("v-if",!0)]),_:2},1032,["id","as-child","as","data-state","data-orientation","aria-labelledby","hidden","style"])]),_:3},8,["present"]))}}),ua=sa;const na=M({__name:"Switch",props:{class:{},modelValue:{type:Boolean},id:{}},emits:["update:modelValue"],setup(k,{emit:l}){const t=k,i=l;return(m,f)=>(c(),C(e(aa),{id:t.id,"model-value":t.modelValue,class:X(e(Y)("peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50",t.class)),"onUpdate:modelValue":f[0]||(f[0]=p=>i("update:modelValue",p))},{default:o(()=>[u(e(ta),{class:"bg-background pointer-events-none block size-4 rounded-full shadow-sm ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0.5"})]),_:1},8,["id","model-value","class"]))}}),re=M({__name:"TabsContent",props:{class:{},value:{}},setup(k){const l=k;return(t,i)=>(c(),C(e(ua),{value:l.value,class:X(e(Y)("outline-none",l.class))},{default:o(()=>[L(t.$slots,"default")]),_:3},8,["value","class"]))}}),oa=["value"],G=M({__name:"Textarea",props:{class:{},modelValue:{}},emits:["update:modelValue"],setup(k,{emit:l}){const t=k,i=l;return(m,f)=>(c(),q("textarea",{value:t.modelValue,class:X(e(Y)("border-input bg-background flex min-h-20 w-full rounded-md border px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none sm:text-sm","placeholder:text-muted-foreground field-sizing-content","focus-visible:border-ring focus-visible:ring-ring/40 focus-visible:ring-[3px]","disabled:cursor-not-allowed disabled:opacity-50",t.class)),onInput:f[0]||(f[0]=p=>i("update:modelValue",p.target.value))},null,42,oa))}}),ra={class:"hidden sm:inline"},ia={class:"hidden sm:inline"},da={class:"mb-3 flex flex-wrap items-center gap-2"},ca={key:1,class:"text-muted-foreground ml-auto hidden truncate font-mono text-[11px] sm:inline"},va={key:0,class:"border-destructive/40 bg-destructive/10 text-destructive mb-3 rounded-lg border px-3 py-2 font-mono text-xs break-words whitespace-pre-wrap"},ma={key:0,class:"text-muted-foreground py-12 text-center text-sm"},fa={key:1,class:"flex flex-col gap-2"},pa={class:"flex items-start justify-between gap-3"},_a={class:"flex min-w-0 flex-col gap-1.5"},ya={class:"flex flex-wrap items-center gap-1.5"},ha={class:"text-muted-foreground font-mono text-[11px] tabular-nums"},ga={class:"truncate text-sm font-medium"},ba={class:"text-muted-foreground bg-muted/60 rounded-md px-2 py-1.5 font-mono text-[11px] leading-relaxed break-all sm:text-xs"},ka={class:"flex shrink-0 flex-col gap-1 sm:flex-row"},xa={key:0,class:"text-muted-foreground py-10 text-center text-sm"},wa={class:"text-muted-foreground mt-2 text-xs"},Va={class:"flex flex-col gap-2"},Ca={class:"grid gap-4 sm:grid-cols-2"},qa={class:"flex flex-col gap-2"},$a={class:"flex flex-col justify-end gap-2"},Sa={class:"flex h-9 items-center"},Ia={key:0,class:"flex flex-col gap-4"},za={class:"flex flex-col gap-2"},Aa={class:"flex flex-col gap-2"},Ba={class:"flex flex-col gap-2"},Ma={key:1,class:"text-destructive text-sm"},Oa=M({__name:"RulesView",setup(k){const l=V("visual"),t=V([]),i=V(""),m=V(""),f=V(null),p=V(!0),_=V(!1),w=V(!1),h=V(""),v=V(null),A=V(-1),S=V(-1),x=B(()=>{var a;return[{value:"",label:n("rules.actionNone")},...(((a=f.value)==null?void 0:a.actions)??[]).map(s=>({value:s,label:n(`action.${s}`)}))]}),D=B(()=>{var a;return(((a=f.value)==null?void 0:a.modifiers)??[]).map(s=>({value:s,label:s}))}),ve=a=>{switch(a){case"allow":return"allow";case"block":return"block";case"drop":return"drop";case"modify":return"modify";default:return"muted"}};ce(async()=>{try{const[a,s]=await Promise.all([T.rules(),T.meta()]);t.value=a.rules??[],i.value=a.raw,m.value=a.path,f.value=s}catch(a){h.value=a instanceof j?a.message:String(a)}finally{p.value=!1}});async function Z(a){if(!(a===l.value||_.value)){_.value=!0,h.value="";try{const s=await T.validateRules(a==="yaml"?{rules:t.value}:{raw:i.value});if(a==="yaml")i.value=s.raw;else{if(!s.valid){h.value=s.error??n("rules.invalid");return}t.value=s.rules??[]}l.value=a}catch(s){h.value=s instanceof j?s.message:String(s)}finally{_.value=!1}}}function ee(){return l.value==="yaml"?{raw:i.value}:{rules:t.value}}async function me(){_.value=!0,h.value="";try{const a=await T.validateRules(ee());a.valid?K.success(n("rules.valid")):h.value=a.error??n("rules.invalid")}catch(a){h.value=a instanceof j?a.message:String(a)}finally{_.value=!1}}async function fe(){_.value=!0,h.value="";try{const a=await T.saveRules(ee());t.value=a.rules??[],i.value=a.raw,w.value=!1,K.success(n("rules.saved"),n("rules.count",{n:t.value.length}))}catch(a){h.value=a instanceof j?a.message:String(a),K.error(n("rules.invalid"),h.value)}finally{_.value=!1}}async function pe(){_.value=!0,h.value="";try{const a=await T.rules();t.value=a.rules??[],i.value=a.raw,w.value=!1}catch(a){h.value=a instanceof j?a.message:String(a)}finally{_.value=!1}}function ae(a,s){const z=a+s;if(z<0||z>=t.value.length)return;const d=[...t.value],[y]=d.splice(a,1);d.splice(z,0,y),t.value=d,w.value=!0}function _e(){A.value=-1,v.value={name:"",action:"block",log:!1,expr:""},U.value="{}"}function ye(a){var s;A.value=a,v.value={...t.value[a]},U.value=JSON.stringify(((s=t.value[a].modifier)==null?void 0:s.args)??{},null,2)}const U=V("{}"),R=V("");function le(){var z,d;const a=v.value;if(!a)return;if(!a.name.trim()){R.value=n("rules.nameRequired");return}if(!a.expr.trim()){R.value=n("rules.exprRequired");return}if(a.action==="modify")try{const y=JSON.parse(U.value||"{}");a.modifier={name:((z=a.modifier)==null?void 0:z.name)??((d=D.value[0])==null?void 0:d.value)??"",args:y}}catch{R.value="JSON";return}else a.modifier=null;const s=[...t.value];A.value>=0?s[A.value]=a:s.push(a),t.value=s,w.value=!0,v.value=null,R.value=""}function he(a){t.value=t.value.filter((s,z)=>z!==a),w.value=!0,S.value=-1}return(a,s)=>{var z;return c(),q("div",null,[u(ze,{title:e(n)("rules.title"),description:e(n)("rules.subtitle")},{actions:o(()=>[u(e(I),{variant:"ghost",size:"sm",disabled:_.value,onClick:pe},{default:o(()=>[u(e(Je),{class:"size-3.5"}),g("span",ra,r(e(n)("common.refresh")),1)]),_:1},8,["disabled"]),u(e(I),{variant:"outline",size:"sm",disabled:_.value,onClick:me},{default:o(()=>[u(e(qe),{class:"size-3.5"}),g("span",ia,r(e(n)("rules.validate")),1)]),_:1},8,["disabled"]),u(e(I),{size:"sm",disabled:_.value,onClick:fe},{default:o(()=>[_.value?(c(),C(e($e),{key:0,class:"size-3.5 animate-spin"})):(c(),C(e(Ke),{key:1,class:"size-3.5"})),b(" "+r(e(n)("rules.save")),1)]),_:1},8,["disabled"])]),_:1},8,["title","description"]),g("div",da,[u(e(ue),{"model-value":l.value,"onUpdate:modelValue":Z},{default:o(()=>[u(e(je),null,{default:o(()=>[u(e(ne),{value:"visual"},{default:o(()=>[b(r(e(n)("rules.visual")),1)]),_:1}),u(e(ne),{value:"yaml"},{default:o(()=>[u(e(Ne)),b(" "+r(e(n)("rules.yaml")),1)]),_:1})]),_:1})]),_:1},8,["model-value"]),u(e(O),{variant:"secondary"},{default:o(()=>[b(r(e(n)("rules.count",{n:t.value.length})),1)]),_:1}),w.value?(c(),C(e(O),{key:0,variant:"drop"},{default:o(()=>[b(r(e(n)("rules.unsaved")),1)]),_:1})):$("",!0),m.value?(c(),q("span",ca,r(m.value),1)):$("",!0)]),h.value?(c(),q("p",va,r(h.value),1)):$("",!0),u(e(ue),{"model-value":l.value,"onUpdate:modelValue":Z},{default:o(()=>[u(e(re),{value:"visual"},{default:o(()=>[p.value?(c(),q("div",ma,r(e(n)("common.loading")),1)):(c(),q("div",fa,[(c(!0),q(N,null,ie(t.value,(d,y)=>(c(),C(e(Se),{key:`${d.name}-${y}`,class:"p-3 sm:p-4"},{default:o(()=>{var H;return[g("div",pa,[g("div",_a,[g("div",ya,[g("span",ha,"#"+r(y+1),1),g("span",ga,r(d.name),1),d.action?(c(),C(e(O),{key:0,variant:ve(d.action),class:"uppercase"},{default:o(()=>[b(r(e(n)(`action.${d.action}`)),1)]),_:2},1032,["variant"])):$("",!0),d.log?(c(),C(e(O),{key:1,variant:"log"},{default:o(()=>[b(r(e(n)("action.log")),1)]),_:1})):$("",!0),(H=d.modifier)!=null&&H.name?(c(),C(e(O),{key:2,variant:"outline"},{default:o(()=>[b(r(d.modifier.name),1)]),_:2},1024)):$("",!0)]),g("code",ba,r(d.expr),1)]),g("div",ka,[u(e(I),{variant:"ghost",size:"icon-sm","aria-label":e(n)("rules.moveUp"),disabled:y===0,onClick:J=>ae(y,-1)},{default:o(()=>[u(e(Fe),{class:"size-3.5"})]),_:1},8,["aria-label","disabled","onClick"]),u(e(I),{variant:"ghost",size:"icon-sm","aria-label":e(n)("rules.moveDown"),disabled:y===t.value.length-1,onClick:J=>ae(y,1)},{default:o(()=>[u(e(Oe),{class:"size-3.5"})]),_:1},8,["aria-label","disabled","onClick"]),u(e(I),{variant:"ghost",size:"icon-sm","aria-label":e(n)("common.edit"),onClick:J=>ye(y)},{default:o(()=>[u(e(Le),{class:"size-3.5"})]),_:1},8,["aria-label","onClick"]),u(e(I),{variant:"ghost",size:"icon-sm",class:"text-destructive","aria-label":e(n)("common.delete"),onClick:J=>S.value=y},{default:o(()=>[u(e(Ae),{class:"size-3.5"})]),_:1},8,["aria-label","onClick"])])])]}),_:2},1024))),128)),t.value.length?$("",!0):(c(),q("p",xa,r(e(n)("rules.empty")),1)),u(e(I),{variant:"outline",class:"mt-1 w-full",onClick:_e},{default:o(()=>[u(e(De),{class:"size-4"}),b(" "+r(e(n)("rules.add")),1)]),_:1})]))]),_:1}),u(e(re),{value:"yaml"},{default:o(()=>[u(e(G),{modelValue:i.value,"onUpdate:modelValue":[s[0]||(s[0]=d=>i.value=d),s[1]||(s[1]=d=>w.value=!0)],spellcheck:"false",class:"h-[60vh] resize-y font-mono text-xs leading-relaxed"},null,8,["modelValue"]),g("p",wa,r(e(n)("rules.hint")),1)]),_:1})]),_:1},8,["model-value"]),u(e(te),{open:v.value!==null,title:A.value>=0?e(n)("rules.editTitle"):e(n)("rules.addTitle"),"onUpdate:open":s[9]||(s[9]=d=>!d&&(v.value=null,R.value=""))},{footer:o(()=>[u(e(I),{variant:"outline",onClick:s[8]||(s[8]=d=>(v.value=null,R.value=""))},{default:o(()=>[b(r(e(n)("common.cancel")),1)]),_:1}),u(e(I),{onClick:le},{default:o(()=>[b(r(e(n)("common.save")),1)]),_:1})]),default:o(()=>{var d;return[v.value?(c(),q("form",{key:0,class:"flex flex-col gap-4",onSubmit:de(le,["prevent"])},[g("div",Va,[u(e(P),{for:"rule-name"},{default:o(()=>[b(r(e(n)("rules.name")),1)]),_:1}),u(e(Ie),{id:"rule-name",modelValue:v.value.name,"onUpdate:modelValue":s[2]||(s[2]=y=>v.value.name=y),placeholder:e(n)("rules.namePlaceholder")},null,8,["modelValue","placeholder"])]),g("div",Ca,[g("div",qa,[u(e(P),null,{default:o(()=>[b(r(e(n)("rules.action")),1)]),_:1}),u(e(se),{"model-value":v.value.action??"",options:x.value,"onUpdate:modelValue":s[3]||(s[3]=y=>v.value.action=y)},null,8,["model-value","options"])]),g("div",$a,[u(e(P),{for:"rule-log"},{default:o(()=>[b(r(e(n)("rules.log")),1)]),_:1}),g("div",Sa,[u(e(na),{id:"rule-log",modelValue:v.value.log,"onUpdate:modelValue":s[4]||(s[4]=y=>v.value.log=y)},null,8,["modelValue"])])])]),v.value.action==="modify"?(c(),q("div",Ia,[g("div",za,[u(e(P),null,{default:o(()=>[b(r(e(n)("rules.modifier")),1)]),_:1}),u(e(se),{"model-value":((d=v.value.modifier)==null?void 0:d.name)??"",options:D.value,"onUpdate:modelValue":s[5]||(s[5]=y=>{var H;return v.value.modifier={name:y,args:(H=v.value.modifier)==null?void 0:H.args}})},null,8,["model-value","options"])]),g("div",Aa,[u(e(P),{for:"rule-args"},{default:o(()=>[b(r(e(n)("rules.modifierArgs")),1)]),_:1}),u(e(G),{id:"rule-args",modelValue:U.value,"onUpdate:modelValue":s[6]||(s[6]=y=>U.value=y),class:"font-mono text-xs",rows:"4"},null,8,["modelValue"])])])):$("",!0),g("div",Ba,[u(e(P),{for:"rule-expr"},{default:o(()=>[b(r(e(n)("rules.expr")),1)]),_:1}),u(e(G),{id:"rule-expr",modelValue:v.value.expr,"onUpdate:modelValue":s[7]||(s[7]=y=>v.value.expr=y),spellcheck:"false",placeholder:e(n)("rules.exprPlaceholder"),class:"min-h-28 font-mono text-xs leading-relaxed"},null,8,["modelValue","placeholder"])]),R.value?(c(),q("p",Ma,r(R.value),1)):$("",!0)],32)):$("",!0)]}),_:1},8,["open","title"]),u(e(te),{open:S.value>=0,title:e(n)("common.delete"),description:S.value>=0?e(n)("rules.deleteConfirm",{name:((z=t.value[S.value])==null?void 0:z.name)??""}):"","onUpdate:open":s[12]||(s[12]=d=>!d&&(S.value=-1))},{footer:o(()=>[u(e(I),{variant:"outline",onClick:s[10]||(s[10]=d=>S.value=-1)},{default:o(()=>[b(r(e(n)("common.cancel")),1)]),_:1}),u(e(I),{variant:"destructive",onClick:s[11]||(s[11]=d=>he(S.value))},{default:o(()=>[b(r(e(n)("common.delete")),1)]),_:1})]),_:1},8,["open","title","description"])])}}});export{Oa as default}; diff --git a/web/dist/assets/RulesView-f8xcsZeo.js b/web/dist/assets/RulesView-f8xcsZeo.js new file mode 100644 index 0000000..27846bd --- /dev/null +++ b/web/dist/assets/RulesView-f8xcsZeo.js @@ -0,0 +1,46 @@ +import{c as he,B as pe,m as A,g as F,u as t,C as It,d as U,x as Ke,o as m,h as B,D as ae,a as S,j as G,F as ee,r as de,E as we,G as _e,w as h,H as J,P as te,I as Me,J as jt,K as Gt,p as v,L as me,M as Ae,N as Xt,O as ge,Q as rt,R as re,S as St,U as Et,i as Jt,k as H,V as Bt,t as $,W as Yt,X as Qt,n as Zt,Y as ea,e as fe,f as ve,Z as At,$ as ye,b as O,l as x,a0 as ta,s as oe,y as tt,a1 as Ee,a2 as aa,a3 as mt,_ as la,a4 as Be,z as Je}from"./index-BKPz7Obh.js";import{_ as na}from"./PageHeader.vue_vue_type_script_setup_true_lang-CPDhGTO6.js";import{u as Fe,a as De,b as st,c as be,d as Ge,g as oa}from"./Collection-BaXBMWO5.js";import{i as He,V as ra,u as sa,a as it,h as ia,P as ua,b as da,c as ca,d as pa,e as fa,f as va,F as ma,D as ha,g as ga,j as ya,k as Ft,T as ba,l as xa,C as _a,_ as je}from"./Select.vue_vue_type_script_setup_true_lang-CONzBLld.js";import{g as Ca,i as ka,m as wa,c as qa,_ as Ye,a as ht,b as Ue}from"./TabsTrigger.vue_vue_type_script_setup_true_lang-_qQ6JBVg.js";import{S as Va,T as Ot,_ as gt}from"./Modal.vue_vue_type_script_setup_true_lang-Bd1uxkqS.js";import{_ as Te}from"./Badge.vue_vue_type_script_setup_true_lang-i2F91fYk.js";/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const $a=he("ArrowDownIcon",[["path",{d:"M12 5v14",key:"s699le"}],["path",{d:"m19 12-7 7-7-7",key:"1idqje"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ia=he("ArrowUpIcon",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Sa=he("ChevronsUpDownIcon",[["path",{d:"m7 15 5 5 5-5",key:"1hf1tw"}],["path",{d:"m7 9 5-5 5 5",key:"sgt6xg"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const yt=he("FileCode2Icon",[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4",key:"1pf5j1"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"m5 12-3 3 3 3",key:"oke12k"}],["path",{d:"m9 18 3-3-3-3",key:"112psh"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ea=he("PencilIcon",[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Tt=he("PlusIcon",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ba=he("RotateCcwIcon",[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Aa=he("SaveIcon",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]);/** + * @license lucide-vue-next v0.469.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Fa=he("WandSparklesIcon",[["path",{d:"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72",key:"ul74o6"}],["path",{d:"m14 7 3 3",key:"1r5n42"}],["path",{d:"M5 6v4",key:"ilb8ba"}],["path",{d:"M19 14v4",key:"blhpug"}],["path",{d:"M10 2v2",key:"7u0qdc"}],["path",{d:"M7 8H3",key:"zfb6yr"}],["path",{d:"M21 16h-4",key:"1cnmox"}],["path",{d:"M11 3H9",key:"1obp7u"}]]);function Oa(l,a,e){const o=l.findIndex(s=>He(s,a)),n=l.findIndex(s=>He(s,e));if(o===-1||n===-1)return[];const[r,i]=[o,n].sort((s,u)=>s-u);return l.slice(r,i+1)}const Ta=["INPUT","TEXTAREA"];function Ra(l,a,e,o={}){if(!a||o.enableIgnoredElement&&Ta.includes(a.nodeName))return null;const{arrowKeyOptions:n="both",attributeName:r="[data-reka-collection-item]",itemsArray:i=[],loop:s=!0,dir:u="ltr",preventScroll:_=!0,focus:d=!1}=o,[C,I,k,y,f,g]=[l.key==="ArrowRight",l.key==="ArrowLeft",l.key==="ArrowUp",l.key==="ArrowDown",l.key==="Home",l.key==="End"],p=k||y,q=C||I;if(!f&&!g&&(!p&&!q||n==="vertical"&&q||n==="horizontal"&&p))return null;const E=i;if(!E.length)return null;_&&l.preventDefault();let V=null;return q||p?V=Rt(E,a,{goForward:p?y:u==="ltr"?C:I,loop:s}):f?V=E.at(0)||null:g&&(V=E.at(-1)||null),d&&(V==null||V.focus()),V}function Rt(l,a,e,o=l.includes(a)?l.length:l.length+1){if(--o===0)return null;const n=l.indexOf(a);let r;if(n===-1?r=e.goForward?0:l.length-1:r=e.goForward?n+1:n-1,!e.loop&&(r<0||r>=l.length))return null;const i=(r+l.length)%l.length,s=l[i];return s?s.hasAttribute("disabled")&&s.getAttribute("disabled")!=="false"?Rt(l,s,e,o):s:null}function ut(l){const a=A(!1);function e(){a.value=!0}function o(n){pe(()=>{a.value=!1,l==null||l(n)})}return{isComposing:a,handleCompositionStart:e,handleCompositionEnd:o}}function za(l){const a=F(()=>t(l)),e=F(()=>new Intl.Collator("en",{usage:"search",...a.value}));return{startsWith:(i,s)=>s.length===0?!0:(i=i.normalize("NFC"),s=s.normalize("NFC"),e.value.compare(i.slice(0,s.length),s)===0),endsWith:(i,s)=>s.length===0?!0:(i=i.normalize("NFC"),s=s.normalize("NFC"),e.value.compare(i.slice(-s.length),s)===0),contains:(i,s)=>{if(s.length===0)return!0;i=i.normalize("NFC"),s=s.normalize("NFC");let u=0;const _=s.length;for(;u+_<=i.length;u++){const d=i.slice(u,u+_);if(e.value.compare(s,d)===0)return!0}return!1}}}function Pa(){var a,e;const l=(e=(a=It())==null?void 0:a.vnode)==null?void 0:e.scopeId;return l?{[l]:""}:{}}function Da(){return{ALT:"Alt",ARROW_DOWN:"ArrowDown",ARROW_LEFT:"ArrowLeft",ARROW_RIGHT:"ArrowRight",ARROW_UP:"ArrowUp",BACKSPACE:"Backspace",CAPS_LOCK:"CapsLock",CONTROL:"Control",DELETE:"Delete",END:"End",ENTER:"Enter",ESCAPE:"Escape",F1:"F1",F10:"F10",F11:"F11",F12:"F12",F2:"F2",F3:"F3",F4:"F4",F5:"F5",F6:"F6",F7:"F7",F8:"F8",F9:"F9",HOME:"Home",META:"Meta",PAGE_DOWN:"PageDown",PAGE_UP:"PageUp",SHIFT:"Shift",SPACE:" ",TAB:"Tab",CTRL:"Control",ASTERISK:"*",SPACE_CODE:"Space"}}var La=U({inheritAttrs:!1,__name:"VisuallyHiddenInputBubble",props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:"fully-hidden"}},setup(l){const a=l,{primitiveElement:e,currentElement:o}=Fe(),n=F(()=>a.checked??a.value);return Ke(n,(r,i)=>{if(!o.value)return;const s=o.value,u=window.HTMLInputElement.prototype,d=Object.getOwnPropertyDescriptor(u,"value").set;if(d&&r!==i){const C=new Event("input",{bubbles:!0}),I=new Event("change",{bubbles:!0});d.call(s,r),s.dispatchEvent(C),s.dispatchEvent(I)}}),(r,i)=>(m(),B(ra,ae({ref_key:"primitiveElement",ref:e},{...a,...r.$attrs},{as:"input"}),null,16))}}),bt=La,Na=U({inheritAttrs:!1,__name:"VisuallyHiddenInput",props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:"fully-hidden"}},setup(l){const a=l,e=F(()=>typeof a.value=="object"&&Array.isArray(a.value)&&a.value.length===0&&a.required),o=F(()=>typeof a.value=="string"||typeof a.value=="number"||typeof a.value=="boolean"||a.value===null||a.value===void 0?[{name:a.name,value:a.value}]:typeof a.value=="object"&&Array.isArray(a.value)?a.value.flatMap((n,r)=>typeof n=="object"?Object.entries(n).map(([i,s])=>({name:`${a.name}[${r}][${i}]`,value:s})):{name:`${a.name}[${r}]`,value:n}):a.value!==null&&typeof a.value=="object"&&!Array.isArray(a.value)?Object.entries(a.value).map(([n,r])=>({name:`${a.name}[${n}]`,value:r})):[]);return(n,r)=>(m(),S(ee,null,[G(" We render single input if it's required "),e.value?(m(),B(bt,ae({key:n.name},{...a,...n.$attrs},{name:n.name,value:n.value}),null,16,["name","value"])):(m(!0),S(ee,{key:1},de(o.value,i=>(m(),B(bt,ae({key:i.name},{ref_for:!0},{...a,...n.$attrs},{name:i.name,value:i.value}),null,16,["name","value"]))),128))],2112))}}),dt=Na;function Ua(l,a,e){return l===void 0?!1:Array.isArray(l)?l.some(o=>ze(o,a,e)):ze(l,a,e)}function ze(l,a,e){return l===void 0||a===void 0?!1:typeof l=="string"?l===a:typeof e=="function"?e(l,a):typeof e=="string"?(l==null?void 0:l[e])===(a==null?void 0:a[e]):He(l,a)}const[Xe,Ma]=be("ListboxRoot");var Wa=U({__name:"ListboxRoot",props:{modelValue:{type:null,required:!1},defaultValue:{type:null,required:!1},multiple:{type:Boolean,required:!1},orientation:{type:String,required:!1,default:"vertical"},dir:{type:String,required:!1},disabled:{type:Boolean,required:!1},selectionBehavior:{type:String,required:!1,default:"toggle"},highlightOnHover:{type:Boolean,required:!1},by:{type:[String,Function],required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:modelValue","highlight","entryFocus","leave"],setup(l,{expose:a,emit:e}){const o=l,n=e,{multiple:r,highlightOnHover:i,orientation:s,disabled:u,selectionBehavior:_,dir:d}=we(o),{getItems:C}=De({isProvider:!0}),{handleTypeaheadSearch:I}=sa(),{primitiveElement:k,currentElement:y}=Fe(),f=Da(),g=st(d),p=it(y),q=A(),E=A(!1),V=A(!0),P=_e(o,"modelValue",n,{defaultValue:o.defaultValue??(r.value?[]:void 0),passive:o.modelValue===void 0,deep:!0});function ue(w){if(E.value=!0,o.multiple){const z=Array.isArray(P.value)?[...P.value]:[],D=z.findIndex(Z=>ze(Z,w,o.by));o.selectionBehavior==="toggle"?(D===-1?z.push(w):z.splice(D,1),P.value=z):(P.value=[w],q.value=w)}else o.selectionBehavior==="toggle"&&ze(P.value,w,o.by)?P.value=void 0:P.value=w;setTimeout(()=>{E.value=!1},1)}const j=A(null),T=A(null),M=A(!1),X=A(!1),Y=Me(),W=Me(),ne=Me();function le(){return C().map(w=>w.ref).filter(w=>w.dataset.disabled!=="")}function K(w,z=!0,D){if(!w)return;j.value=w,(D??V.value)&&j.value.focus(),z&&j.value.scrollIntoView({block:"nearest"});const Z=C().find(ie=>ie.ref===w);n("highlight",Z)}function Ve(w){if(M.value)ne.trigger(w);else{const z=C().find(D=>ze(D.value,w,o.by));z&&(j.value=z.ref,K(z.ref))}}function $e(w){if(j.value&&j.value.isConnected){if(w.ctrlKey||w.metaKey||w.altKey)return;w.preventDefault(),w.stopPropagation(),X.value||j.value.click()}}function Ie(w){if(V.value){if(E.value=!0,M.value)W.trigger(w);else{const z=w.altKey||w.ctrlKey||w.metaKey;if(z&&w.key==="a"&&r.value){const D=C(),Z=D.map(Se=>Se.value);P.value=[...Z],w.preventDefault();const ie=D.at(-1);ie&&K(ie.ref)}else if(!z){const D=I(w.key,C());D&&K(D)}}setTimeout(()=>{E.value=!1},1)}}function c(){X.value=!0}function b(){pe(()=>{X.value=!1})}function L(){pe(()=>{const w=new KeyboardEvent("keydown",{key:"PageUp"});Q(w)})}function R(w){const z=j.value;z!=null&&z.isConnected&&(T.value=z),j.value=null,n("leave",w)}function N(w){var D,Z;const z=new CustomEvent("listbox.entryFocus",{bubbles:!1,cancelable:!0});if((D=w.currentTarget)==null||D.dispatchEvent(z),n("entryFocus",z),!z.defaultPrevented)if(T.value)K(T.value);else{const ie=(Z=le())==null?void 0:Z[0];K(ie)}}function Q(w){const z=Ca(w,s.value,g.value);if(!z)return;let D=le();if(j.value){if(z==="last")D.reverse();else if(z==="prev"||z==="next"){z==="prev"&&D.reverse();const Z=D.indexOf(j.value);D=D.slice(Z+1)}ce(w,D[0])}if(D.length){const Z=!j.value&&z==="prev"?D.length-1:0;K(D[Z])}if(M.value)return W.trigger(w)}function ce(w,z){var Z,ie,Se;if(!(M.value||o.selectionBehavior!=="replace"||!r.value||!Array.isArray(P.value)||(w.altKey||w.ctrlKey||w.metaKey)&&!w.shiftKey)&&w.shiftKey){const Le=C().filter(Oe=>Oe.ref.dataset.disabled!=="");let Ne=(Z=Le.find(Oe=>Oe.ref===z))==null?void 0:Z.value;if(w.key===f.END?Ne=(ie=Le.at(-1))==null?void 0:ie.value:w.key===f.HOME&&(Ne=(Se=Le[0])==null?void 0:Se.value),!Ne||!q.value)return;const Ht=Oa(Le.map(Oe=>Oe.value),q.value,Ne);P.value=Ht}}async function ft(w,z=!0){if(jt)if(await pe(),M.value)Y.trigger({event:w,scroll:z});else{const D=le(),Z=D.find(Se=>Se.dataset.state==="checked"),ie=z?void 0:!1;Z?K(Z,z,ie):D.length&&K(D[0],z,ie)}}let vt=!1;return Ke(P,()=>{if(!E.value){const w=vt;vt=!0,pe(()=>{ft(void 0,w)})}},{immediate:!0,deep:!0}),a({highlightedElement:j,highlightItem:Ve,highlightFirstItem:L,highlightSelected:ft,getItems:C}),Ma({modelValue:P,onValueChange:ue,multiple:r,orientation:s,dir:g,disabled:u,highlightOnHover:i,highlightedElement:j,isVirtual:M,virtualFocusHook:Y,virtualKeydownHook:W,virtualHighlightHook:ne,by:o.by,firstValue:q,selectionBehavior:_,focusable:V,onLeave:R,onEnter:N,changeHighlight:K,onKeydownEnter:$e,onKeydownNavigation:Q,onKeydownTypeAhead:Ie,onCompositionStart:c,onCompositionEnd:b,highlightFirstItem:L}),(w,z)=>(m(),B(t(te),{ref_key:"primitiveElement",ref:k,as:w.as,"as-child":w.asChild,dir:t(g),"data-disabled":t(u)?"":void 0,onPointerleave:R,onFocusout:z[0]||(z[0]=async D=>{const Z=D.relatedTarget||D.target;await pe(),j.value&&t(y)&&!t(y).contains(Z)&&R(D)})},{default:h(()=>[J(w.$slots,"default",{modelValue:t(P)}),t(p)&&w.name?(m(),B(t(dt),{key:0,name:w.name,value:t(P),disabled:t(u),required:w.required},null,8,["name","value","disabled","required"])):G("v-if",!0)]),_:3},8,["as","as-child","dir","data-disabled"]))}}),Ka=Wa,Ha=U({__name:"ListboxContent",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(l){const{CollectionSlot:a}=De(),e=Xe(),o=Gt(!1,10);return(n,r)=>(m(),B(t(a),null,{default:h(()=>[v(t(te),{role:"listbox",as:n.as,"as-child":n.asChild,tabindex:t(e).focusable.value?t(e).highlightedElement.value?"-1":"0":"-1","aria-orientation":t(e).orientation.value,"aria-multiselectable":!!t(e).multiple.value,"data-orientation":t(e).orientation.value,onMousedown:r[0]||(r[0]=Ae(i=>o.value=!0,["left"])),onFocus:r[1]||(r[1]=i=>{t(o)||t(e).onEnter(i)}),onKeydown:[r[2]||(r[2]=me(i=>{t(e).orientation.value==="vertical"&&(i.key==="ArrowLeft"||i.key==="ArrowRight")||t(e).orientation.value==="horizontal"&&(i.key==="ArrowUp"||i.key==="ArrowDown")||(i.preventDefault(),t(e).focusable.value&&t(e).onKeydownNavigation(i))},["down","up","left","right","home","end"])),me(t(e).onKeydownEnter,["enter"]),t(e).onKeydownTypeAhead]},{default:h(()=>[J(n.$slots,"default")]),_:3},8,["as","as-child","tabindex","aria-orientation","aria-multiselectable","data-orientation","onKeydown"])]),_:3}))}}),ja=Ha,Ga=U({__name:"ListboxFilter",props:{modelValue:{type:String,required:!1},autoFocus:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"input"}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,n=_e(e,"modelValue",a,{defaultValue:"",passive:e.modelValue===void 0}),r=Xe(),{primitiveElement:i,currentElement:s}=Fe(),u=F(()=>e.disabled||r.disabled.value||!1),_=A();Xt(()=>{var p;return _.value=(p=r.highlightedElement.value)==null?void 0:p.id}),ge(()=>{r.focusable.value=!1,setTimeout(()=>{var p;e.autoFocus&&((p=s.value)==null||p.focus())},1)}),rt(()=>{r.focusable.value=!0});const{isComposing:d,handleCompositionStart:C,handleCompositionEnd:I}=ut(p=>{n.value=p.target.value,r.onCompositionEnd(),r.highlightFirstItem()});function k(){r.onCompositionStart(),C()}function y(p){d.value||(n.value=p.target.value,r.highlightFirstItem())}function f(p){d.value||(p.preventDefault(),r.onKeydownNavigation(p))}function g(p){d.value||r.onKeydownEnter(p)}return(p,q)=>(m(),B(t(te),{ref_key:"primitiveElement",ref:i,as:p.as,"as-child":p.asChild,value:t(n),disabled:u.value?"":void 0,"data-disabled":u.value?"":void 0,"aria-disabled":u.value??void 0,"aria-activedescendant":_.value,type:"text",onKeydown:[me(f,["down","up","home","end"]),me(g,["enter"])],onInput:y,onCompositionstart:k,onCompositionend:t(I)},{default:h(()=>[J(p.$slots,"default",{modelValue:t(n)})]),_:3},8,["as","as-child","value","disabled","data-disabled","aria-disabled","aria-activedescendant","onCompositionend"]))}}),Xa=Ga;const Ja="listbox.select",[Io,Ya]=be("ListboxItem");var Qa=U({__name:"ListboxItem",props:{value:{type:null,required:!0},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"div"}},emits:["select"],setup(l,{emit:a}){const e=l,o=a,n=Ge(void 0,"reka-listbox-item"),{CollectionItem:r}=De(),{forwardRef:i,currentElement:s}=re(),u=Xe(),_=F(()=>s.value!=null&&s.value===u.highlightedElement.value),d=F(()=>Ua(u.modelValue.value,e.value,u.by)),C=F(()=>u.disabled.value||e.disabled);async function I(y){o("select",y),!(y!=null&&y.defaultPrevented)&&!C.value&&y&&(u.onValueChange(e.value),u.changeHighlight(s.value))}function k(y){const f={originalEvent:y,value:e.value};ia(Ja,I,f)}return Ya({isSelected:d}),(y,f)=>(m(),B(t(r),{value:y.value},{default:h(()=>[St([_.value,d.value,C.value,t(u).focusable.value],()=>v(t(te),ae({id:t(n)},y.$attrs,{ref:t(i),role:"option",tabindex:t(u).focusable.value?_.value?"0":"-1":-1,"aria-selected":d.value,as:y.as,"as-child":y.asChild,disabled:C.value?"":void 0,"data-disabled":C.value?"":void 0,"data-highlighted":_.value?"":void 0,"data-state":d.value?"checked":"unchecked",onClick:k,onKeydown:me(Ae(k,["prevent"]),["space"]),onPointermove:f[0]||(f[0]=()=>{t(u).highlightedElement.value!==t(s)&&t(u).highlightOnHover.value&&t(u).changeHighlight(t(s),!1,!1)})}),{default:h(()=>[J(y.$slots,"default")]),_:3},16,["id","tabindex","aria-selected","as","as-child","disabled","data-disabled","data-highlighted","data-state","onKeydown"]),f,1)]),_:3},8,["value"]))}}),Za=Qa;const[qe,el]=be("ComboboxRoot");var tl=U({__name:"ComboboxRoot",props:{open:{type:Boolean,required:!1,default:void 0},defaultOpen:{type:Boolean,required:!1},resetSearchTermOnBlur:{type:Boolean,required:!1,default:!0},resetSearchTermOnSelect:{type:Boolean,required:!1,default:!0},openOnFocus:{type:Boolean,required:!1,default:!1},openOnClick:{type:Boolean,required:!1,default:!1},ignoreFilter:{type:Boolean,required:!1},resetModelValueOnClear:{type:Boolean,required:!1,default:!1},modelValue:{type:null,required:!1},defaultValue:{type:null,required:!1},multiple:{type:Boolean,required:!1},dir:{type:String,required:!1},disabled:{type:Boolean,required:!1},highlightOnHover:{type:Boolean,required:!1,default:!0},by:{type:[String,Function],required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:modelValue","highlight","update:open"],setup(l,{expose:a,emit:e}){var Ve,$e,Ie;const o=l,n=e,{primitiveElement:r,currentElement:i}=Fe(),{multiple:s,disabled:u,ignoreFilter:_,resetSearchTermOnSelect:d,openOnFocus:C,openOnClick:I,dir:k,resetModelValueOnClear:y,highlightOnHover:f}=we(o),g=st(k),p=_e(o,"modelValue",n,{defaultValue:o.defaultValue??(s.value?[]:void 0),passive:o.modelValue===void 0,deep:!0}),q=_e(o,"open",n,{defaultValue:o.defaultOpen,passive:o.open===void 0});async function E(c){var b,L;q.value=c,ne.value="",c?(await pe(),(b=r.value)==null||b.highlightSelected(),P.value=!0,(L=j.value)==null||L.focus()):(P.value=!1,setTimeout(()=>{!c&&o.resetSearchTermOnBlur&&V.trigger()},1))}const V=Me(),P=A(!1),ue=A(!1),j=A(),T=A(),M=F(()=>{var c;return((c=r.value)==null?void 0:c.highlightedElement)??void 0}),X=A(new Map),Y=A(new Map),{contains:W}=za({sensitivity:"base"}),ne=A(""),le=F(c=>{if(!ne.value||o.ignoreFilter||ue.value)return{count:X.value.size,items:(c==null?void 0:c.items)??new Map,groups:(c==null?void 0:c.groups)??new Set(Y.value.keys())};let b=0;const L=new Map,R=new Set;for(const[N,Q]of X.value){const ce=W(Q,ne.value);L.set(N,ce?1:0),ce&&b++}for(const[N,Q]of Y.value)for(const ce of Q)if(L.get(ce)>0){R.add(N);break}return{count:b,items:L,groups:R}}),K=It();return ge(()=>{var c,b,L;K!=null&&K.exposed&&(K.exposed.highlightItem=(c=r.value)==null?void 0:c.highlightItem,K.exposed.highlightFirstItem=(b=r.value)==null?void 0:b.highlightFirstItem,K.exposed.highlightSelected=(L=r.value)==null?void 0:L.highlightSelected)}),a({filtered:le,highlightedElement:M,highlightItem:(Ve=r.value)==null?void 0:Ve.highlightItem,highlightFirstItem:($e=r.value)==null?void 0:$e.highlightFirstItem,highlightSelected:(Ie=r.value)==null?void 0:Ie.highlightSelected}),el({modelValue:p,multiple:s,disabled:u,open:q,onOpenChange:E,contentId:"",isUserInputted:P,isVirtual:ue,inputElement:j,highlightedElement:M,onInputElementChange:c=>j.value=c,triggerElement:T,onTriggerElementChange:c=>T.value=c,parentElement:i,resetSearchTermOnSelect:d,onResetSearchTerm:V.on,allItems:X,allGroups:Y,filterSearch:ne,filterState:le,ignoreFilter:_,openOnFocus:C,openOnClick:I,resetModelValueOnClear:y}),(c,b)=>(m(),B(t(ua),null,{default:h(()=>[v(t(Ka),ae({ref_key:"primitiveElement",ref:r},c.$attrs,{modelValue:t(p),"onUpdate:modelValue":b[0]||(b[0]=L=>Et(p)?p.value=L:null),style:{pointerEvents:t(q)?"auto":void 0},as:c.as,"as-child":c.asChild,dir:t(g),multiple:t(s),name:c.name,required:c.required,disabled:t(u),"highlight-on-hover":t(f),by:o.by,onHighlight:b[1]||(b[1]=L=>n("highlight",L))}),{default:h(()=>[J(c.$slots,"default",{open:t(q),modelValue:t(p)})]),_:3},16,["modelValue","style","as","as-child","dir","multiple","name","required","disabled","highlight-on-hover","by"])]),_:3}))}}),al=tl,ll=U({__name:"ComboboxAnchor",props:{reference:{type:null,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(l){const{forwardRef:a}=re();return(e,o)=>(m(),B(t(da),{"as-child":"",reference:e.reference},{default:h(()=>[v(t(te),ae({ref:t(a),"as-child":e.asChild,as:e.as},e.$attrs),{default:h(()=>[J(e.$slots,"default")]),_:3},16,["as-child","as"])]),_:3},8,["reference"]))}}),nl=ll;const[So,ol]=be("ComboboxContent");var rl=U({__name:"ComboboxContentImpl",props:{position:{type:String,required:!1,default:"inline"},bodyLock:{type:Boolean,required:!1},hideWhenEmpty:{type:Boolean,required:!1},memoDependencies:{type:Array,required:!1},side:{type:null,required:!1},sideOffset:{type:Number,required:!1},sideFlip:{type:Boolean,required:!1},align:{type:null,required:!1},alignOffset:{type:Number,required:!1},alignFlip:{type:Boolean,required:!1},avoidCollisions:{type:Boolean,required:!1},collisionBoundary:{type:null,required:!1},collisionPadding:{type:[Number,Object],required:!1},arrowPadding:{type:Number,required:!1},hideShiftedArrow:{type:Boolean,required:!1},sticky:{type:String,required:!1},hideWhenDetached:{type:Boolean,required:!1},positionStrategy:{type:String,required:!1},updatePositionStrategy:{type:String,required:!1},disableUpdateOnLayoutShift:{type:Boolean,required:!1},prioritizePosition:{type:Boolean,required:!1},reference:{type:null,required:!1},dir:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside"],setup(l,{emit:a}){const e=l,o=a,{position:n}=we(e),r=qe(),i=F(()=>r.ignoreFilter.value?r.allItems.value.size===0:r.filterState.value.count===0),{forwardRef:s,currentElement:u}=re();ca(e.bodyLock),pa(),fa(r.parentElement);const _=F(()=>e.position==="popper"?e:{}),d=va(_.value),C={boxSizing:"border-box","--reka-combobox-content-transform-origin":"var(--reka-popper-transform-origin)","--reka-combobox-content-available-width":"var(--reka-popper-available-width)","--reka-combobox-content-available-height":"var(--reka-popper-available-height)","--reka-combobox-trigger-width":"var(--reka-popper-anchor-width)","--reka-combobox-trigger-height":"var(--reka-popper-anchor-height)"};ol({position:n});const I=A(!1);ge(()=>{r.inputElement.value&&(I.value=u.value.contains(r.inputElement.value),I.value&&r.inputElement.value.focus())}),rt(()=>{var f;const y=oa();I.value&&(!y||y===document.body)&&((f=r.triggerElement.value)==null||f.focus())});function k(y){var p,q;if((p=r.parentElement.value)!=null&&p.contains(y))return!0;const f=y instanceof Element?y.closest("label"):null,g=f==null?void 0:f.control;return!!g&&!!((q=r.parentElement.value)!=null&&q.contains(g))}return(y,f)=>(m(),B(t(ja),{"as-child":""},{default:h(()=>[v(t(ma),{"as-child":"",onMountAutoFocus:f[5]||(f[5]=Ae(()=>{},["prevent"])),onUnmountAutoFocus:f[6]||(f[6]=Ae(()=>{},["prevent"]))},{default:h(()=>[v(t(ha),{"as-child":"","disable-outside-pointer-events":y.disableOutsidePointerEvents,onDismiss:f[0]||(f[0]=g=>t(r).onOpenChange(!1)),onFocusOutside:f[1]||(f[1]=g=>{k(g.target)&&g.preventDefault(),o("focusOutside",g)}),onInteractOutside:f[2]||(f[2]=g=>o("interactOutside",g)),onEscapeKeyDown:f[3]||(f[3]=g=>o("escapeKeyDown",g)),onPointerDownOutside:f[4]||(f[4]=g=>{k(g.target)&&g.preventDefault(),o("pointerDownOutside",g)})},{default:h(()=>[(m(),B(Jt(t(n)==="popper"?t(ga):t(te)),ae({...y.$attrs,...t(d)},{id:t(r).contentId,ref:t(s),"memo-dependencies":t(n)==="popper"?[t(r).filterSearch.value,t(r).filterState.value]:void 0,"data-state":t(r).open.value?"open":"closed","data-empty":i.value?"":void 0,style:{display:e.hideWhenEmpty&&i.value?"none":"flex",flexDirection:"column",outline:"none",...t(n)==="popper"?C:{}}}),{default:h(()=>[J(y.$slots,"default")]),_:3},16,["id","memo-dependencies","data-state","data-empty","style"]))]),_:3},8,["disable-outside-pointer-events"])]),_:3})]),_:3}))}}),sl=rl,il=U({__name:"ComboboxContent",props:{forceMount:{type:Boolean,required:!1},position:{type:String,required:!1},bodyLock:{type:Boolean,required:!1},hideWhenEmpty:{type:Boolean,required:!1},memoDependencies:{type:Array,required:!1},side:{type:null,required:!1},sideOffset:{type:Number,required:!1},sideFlip:{type:Boolean,required:!1},align:{type:null,required:!1},alignOffset:{type:Number,required:!1},alignFlip:{type:Boolean,required:!1},avoidCollisions:{type:Boolean,required:!1},collisionBoundary:{type:null,required:!1},collisionPadding:{type:[Number,Object],required:!1},arrowPadding:{type:Number,required:!1},hideShiftedArrow:{type:Boolean,required:!1},sticky:{type:String,required:!1},hideWhenDetached:{type:Boolean,required:!1},positionStrategy:{type:String,required:!1},updatePositionStrategy:{type:String,required:!1},disableUpdateOnLayoutShift:{type:Boolean,required:!1},prioritizePosition:{type:Boolean,required:!1},reference:{type:null,required:!1},dir:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},disableOutsidePointerEvents:{type:Boolean,required:!1}},emits:["escapeKeyDown","pointerDownOutside","focusOutside","interactOutside"],setup(l,{emit:a}){const n=ya(l,a),{forwardRef:r}=re(),i=qe();return i.contentId||(i.contentId=Ge(void 0,"reka-combobox-content")),(s,u)=>(m(),B(t(Ft),{present:s.forceMount||t(i).open.value},{default:h(()=>[v(sl,ae({...t(n),...s.$attrs},{ref:t(r)}),{default:h(()=>[J(s.$slots,"default")]),_:3},16)]),_:3},8,["present"]))}}),ul=il,dl=U({__name:"ComboboxEmpty",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(l){const a=l,e=qe(),o=F(()=>e.ignoreFilter.value?e.allItems.value.size===0:e.filterState.value.count===0);return(n,r)=>o.value?(m(),B(t(te),Bt(ae({key:0},a)),{default:h(()=>[J(n.$slots,"default",{},()=>[r[0]||(r[0]=H("No options"))])]),_:3},16)):G("v-if",!0)}}),cl=dl;const[pl]=be("ComboboxGroup");var fl=U({__name:"ComboboxInput",props:{displayValue:{type:Function,required:!1},modelValue:{type:String,required:!1},autoFocus:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"input"}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a,n=qe(),r=Xe(),{primitiveElement:i,currentElement:s}=Fe(),u=_e(e,"modelValue",o,{passive:e.modelValue===void 0});ge(()=>{s.value&&n.onInputElementChange(s.value)});const{isComposing:_,handleCompositionStart:d,handleCompositionEnd:C}=ut(E=>{const V=E.target;V&&k(V.value)});function I(E){_.value||(E.preventDefault(),n.open.value||n.onOpenChange(!0))}function k(E){n.open.value?n.filterSearch.value=E:(n.onOpenChange(!0),pe(()=>{E&&(n.filterSearch.value=E,r.highlightFirstItem())}))}function y(E){_.value||k(E.target.value)}function f(){n.openOnFocus.value&&!n.open.value&&n.onOpenChange(!0)}function g(E){var j,T;if(!n.open.value)return;const V=E.relatedTarget;if(!V)return;const P=(j=n.parentElement.value)==null?void 0:j.contains(V),ue=(T=document.getElementById(n.contentId))==null?void 0:T.contains(V);!P&&!ue&&requestAnimationFrame(()=>{var Y,W;if(!n.open.value)return;const M=document.activeElement;!((Y=n.parentElement.value)!=null&&Y.contains(M))&&!((W=document.getElementById(n.contentId))!=null&&W.contains(M))&&n.onOpenChange(!1)})}function p(){n.openOnClick.value&&!n.open.value&&n.onOpenChange(!0)}function q(){const E=n.modelValue.value;e.displayValue?u.value=e.displayValue(E):!n.multiple.value&&E&&!Array.isArray(E)&&typeof E!="object"?u.value=E.toString():u.value="",pe(()=>{u.value=u.value})}return n.onResetSearchTerm(()=>{q()}),Ke(n.modelValue,async()=>{!n.isUserInputted.value&&n.resetSearchTermOnSelect.value&&q()},{immediate:!0,deep:!0}),Ke(n.filterState,(E,V)=>{!n.isVirtual.value&&V.count===0&&r.highlightFirstItem()}),(E,V)=>(m(),B(t(Xa),{ref_key:"primitiveElement",ref:i,modelValue:t(u),"onUpdate:modelValue":V[0]||(V[0]=P=>Et(u)?u.value=P:null),as:E.as,"as-child":E.asChild,"auto-focus":E.autoFocus,disabled:E.disabled,"aria-expanded":t(n).open.value,"aria-controls":t(n).contentId,"aria-autocomplete":"list",role:"combobox",autocomplete:"off",onClick:p,onInput:y,onKeydown:me(I,["down","up"]),onFocus:f,onBlur:g,onCompositionstart:t(d),onCompositionend:t(C)},{default:h(()=>[J(E.$slots,"default")]),_:3},8,["modelValue","as","as-child","auto-focus","disabled","aria-expanded","aria-controls","onCompositionstart","onCompositionend"]))}}),vl=fl,ml=U({__name:"ComboboxItem",props:{textValue:{type:String,required:!1},value:{type:null,required:!0},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:["select"],setup(l,{emit:a}){const e=l,o=a,n=Ge(void 0,"reka-combobox-item"),r=qe(),i=pl(null),{primitiveElement:s,currentElement:u}=Fe();if(e.value==="")throw new Error("A must have a value prop that is not an empty string. This is because the Combobox value can be set to an empty string to clear the selection and show the placeholder.");const _=F(()=>{if(r.isVirtual.value||r.ignoreFilter.value||!r.filterSearch.value)return!0;{const d=r.filterState.value.items.get(n);return d===void 0?!0:d>0}});return ge(()=>{var C;r.allItems.value.set(n,e.textValue||u.value.textContent||u.value.innerText);const d=i==null?void 0:i.id;d&&(r.allGroups.value.has(d)?(C=r.allGroups.value.get(d))==null||C.add(n):r.allGroups.value.set(d,new Set([n])))}),rt(()=>{r.allItems.value.delete(n)}),(d,C)=>_.value?St([_.value,t(r).filterSearch.value,t(r).disabled.value,d.disabled,e.value,e.as,e.asChild,...Object.values(d.$attrs)],()=>(m(),B(t(Za),ae({key:0},e,{id:t(n),ref_key:"primitiveElement",ref:s,disabled:t(r).disabled.value||d.disabled,onSelect:C[0]||(C[0]=I=>{var k;o("select",I),!I.defaultPrevented&&(!t(r).multiple.value&&!d.disabled&&!t(r).disabled.value?(I.preventDefault(),t(r).onOpenChange(!1),t(r).modelValue.value=e.value):t(r).multiple.value&&((k=t(r).inputElement.value)==null||k.focus()))})}),{default:h(()=>[J(d.$slots,"default",{},()=>[H($(d.value),1)])]),_:3},16,["id","disabled"])),C,1):G("v-if",!0)}}),hl=ml,gl=U({__name:"ComboboxPortal",props:{to:{type:null,required:!1},disabled:{type:Boolean,required:!1},defer:{type:Boolean,required:!1},forceMount:{type:Boolean,required:!1}},setup(l){const a=l;return(e,o)=>(m(),B(t(ba),Bt(Yt(a)),{default:h(()=>[J(e.$slots,"default")]),_:3},16))}}),yl=gl,bl=U({__name:"ComboboxTrigger",props:{disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(l){const a=l,{forwardRef:e,currentElement:o}=re(),n=qe(),r=F(()=>a.disabled||n.disabled.value||!1);return ge(()=>{o.value&&n.onTriggerElementChange(o.value)}),(i,s)=>(m(),B(t(te),ae(a,{ref:t(e),type:i.as==="button"?"button":void 0,tabindex:"-1","aria-label":"Show popup","aria-haspopup":"listbox","aria-expanded":t(n).open.value,"aria-controls":t(n).contentId,"data-state":t(n).open.value?"open":"closed",disabled:r.value,"data-disabled":r.value?"":void 0,"aria-disabled":r.value??void 0,onClick:s[0]||(s[0]=u=>t(n).onOpenChange(!t(n).open.value))}),{default:h(()=>[J(i.$slots,"default")]),_:3},16,["type","aria-expanded","aria-controls","data-state","disabled","data-disabled","aria-disabled"]))}}),xl=bl,_l=U({__name:"ComboboxViewport",props:{nonce:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(l){const a=l,{forwardRef:e}=re(),{nonce:o}=we(a),n=xa(o),r=qe();return(i,s)=>(m(),S(ee,null,[v(t(te),ae({...i.$attrs,...a},{ref:t(e),"data-reka-combobox-viewport":"",role:"presentation",style:{position:"relative",flex:t(r).isVirtual.value?void 0:1,overflow:"auto"}}),{default:h(()=>[J(i.$slots,"default")]),_:3},16,["style"]),v(t(te),{as:"style",nonce:t(n)},{default:h(()=>s[0]||(s[0]=[H(" /* Hide scrollbars cross-browser and enable momentum scroll for touch devices */ [data-reka-combobox-viewport] { scrollbar-width:none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } [data-reka-combobox-viewport]::-webkit-scrollbar { display: none; } ")])),_:1,__:[0]},8,["nonce"])],64))}}),Cl=_l;const[kl,wl]=be("SwitchRoot");var ql=U({inheritAttrs:!1,__name:"SwitchRoot",props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},id:{type:String,required:!1},value:{type:String,required:!1,default:"on"},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a,{disabled:n}=we(e),r=_e(e,"modelValue",o,{defaultValue:e.defaultValue??e.falseValue,passive:e.modelValue===void 0}),i=F(()=>r.value===e.trueValue);function s(){n.value||(r.value=i.value?e.falseValue:e.trueValue)}const{forwardRef:u,currentElement:_}=re(),d=it(_),C=Pa(),I=F(()=>{var k;return e.id&&_.value?(k=document.querySelector(`[for="${e.id}"]`))==null?void 0:k.innerText:void 0});return wl({checked:i,toggleCheck:s,disabled:n}),(k,y)=>(m(),S(ee,null,[v(t(te),ae({id:k.id,ref:t(u),role:"switch",type:k.as==="button"?"button":void 0,value:k.value,"aria-label":k.$attrs["aria-label"]||I.value,"aria-checked":i.value,"aria-required":k.required,"data-state":i.value?"checked":"unchecked","data-disabled":t(n)?"":void 0,"as-child":k.asChild,as:k.as,disabled:t(n)},{...t(C),...k.$attrs},{onClick:s,onKeydown:me(Ae(s,["prevent"]),["enter"])}),{default:h(()=>[J(k.$slots,"default",{modelValue:t(r),checked:i.value})]),_:3},16,["id","type","value","aria-label","aria-checked","aria-required","data-state","data-disabled","as-child","as","disabled","onKeydown"]),t(d)&&k.name?(m(),B(t(dt),ae({key:0,type:"checkbox",name:k.name,disabled:t(n),required:k.required,value:k.value,checked:i.value},t(C)),null,16,["name","disabled","required","value","checked"])):G("v-if",!0)],64))}}),Vl=ql,$l=U({__name:"SwitchThumb",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"span"}},setup(l){const a=kl();return re(),(e,o)=>(m(),B(t(te),{"data-state":t(a).checked.value?"checked":"unchecked","data-disabled":t(a).disabled.value?"":void 0,"as-child":e.asChild,as:e.as},{default:h(()=>[J(e.$slots,"default")]),_:3},8,["data-state","data-disabled","as-child","as"]))}}),Il=$l,Sl=U({__name:"TabsContent",props:{value:{type:[String,Number],required:!0},forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(l){const a=l,{forwardRef:e}=re(),o=ka(),n=F(()=>wa(o.baseId,a.value)),r=F(()=>qa(o.baseId,a.value)),i=F(()=>a.value===o.modelValue.value),s=A(i.value);return ge(()=>{o.registerContent(a.value),requestAnimationFrame(()=>{s.value=!1})}),Qt(()=>{o.unregisterContent(a.value)}),(u,_)=>(m(),B(t(Ft),{present:u.forceMount||i.value,"force-mount":""},{default:h(({present:d})=>[v(t(te),{id:r.value,ref:t(e),"as-child":u.asChild,as:u.as,role:"tabpanel","data-state":i.value?"active":"inactive","data-orientation":t(o).orientation.value,"aria-labelledby":n.value,hidden:!d,tabindex:"0",style:Zt({animationDuration:s.value?"0s":void 0})},{default:h(()=>[!t(o).unmountOnHide.value||d?J(u.$slots,"default",{key:0}):G("v-if",!0)]),_:2},1032,["id","as-child","as","data-state","data-orientation","aria-labelledby","hidden","style"])]),_:3},8,["present"]))}}),El=Sl;const[ct,Bl]=be("TagsInputRoot");var Al=U({__name:"TagsInputRoot",props:{modelValue:{type:[Array,null],required:!1},defaultValue:{type:Array,required:!1,default:()=>[]},addOnPaste:{type:Boolean,required:!1},addOnTab:{type:Boolean,required:!1},addOnBlur:{type:Boolean,required:!1},duplicate:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},delimiter:{type:null,required:!1,default:","},dir:{type:String,required:!1},max:{type:Number,required:!1,default:0},id:{type:String,required:!1},convertValue:{type:Function,required:!1},displayValue:{type:Function,required:!1,default:l=>l.toString()},asChild:{type:Boolean,required:!1},as:{type:null,required:!1},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:["update:modelValue","invalid","addTag","removeTag"],setup(l,{emit:a}){const e=l,o=a,{addOnPaste:n,disabled:r,delimiter:i,max:s,id:u,dir:_,addOnBlur:d,addOnTab:C}=we(e),I=st(_),k=_e(e,"modelValue",o,{defaultValue:e.defaultValue,passive:!0,deep:!0}),{forwardRef:y,currentElement:f}=re(),{focused:g}=ea(f),p=it(f),{getItems:q,CollectionSlot:E}=De({isProvider:!0}),V=A(),P=A(!1),ue=F(()=>Array.isArray(k.value)?[...k.value]:[]);function j(T){if(T!==-1){const M=q().filter(X=>X.ref.dataset.disabled!=="");k.value=k.value.filter((X,Y)=>Y!==T),o("removeTag",M[T].value)}}return Bl({modelValue:k,onAddValue:T=>{const M=[...ue.value],X=M.length>0&&typeof M[0]=="object",Y=M.length>0&&typeof e.defaultValue[0]=="object";if((X||Y)&&typeof e.convertValue!="function")throw new Error("You must provide a `convertValue` function when using objects as values.");const W=e.convertValue?e.convertValue(T):T;if(M.length>=s.value&&s.value)return o("invalid",W),!1;if(e.duplicate)return k.value=[...M,W],o("addTag",W),!0;if(M.includes(W))P.value=!0;else return k.value=[...M,W],o("addTag",W),!0;return o("invalid",W),!1},onRemoveValue:j,onInputKeydown:T=>{if(T.isComposing)return;const M=T.target,X=q().map(W=>W.ref).filter(W=>W.dataset.disabled!=="");if(!X.length)return;const Y=X.at(-1);switch(T.key){case"Delete":case"Backspace":{if(M.selectionStart!==0||M.selectionEnd!==0)break;if(V.value){const W=X.findIndex(ne=>ne===V.value);j(W),V.value=V.value===Y?X.at(W-1):X.at(W+1),T.preventDefault()}else T.key==="Backspace"&&(V.value=Y,T.preventDefault());break}case"Home":case"End":case"ArrowRight":case"ArrowLeft":{const W=T.key==="ArrowRight"&&I.value==="ltr"||T.key==="ArrowLeft"&&I.value==="rtl",ne=!W;if(M.selectionStart!==0||M.selectionEnd!==0)break;if(ne&&!V.value)V.value=Y,T.preventDefault();else if(W&&Y&&V.value===Y)V.value=void 0,T.preventDefault();else if(V.value){const le=Ra(T,V.value,void 0,{itemsArray:X,loop:!1,dir:I.value});le&&(V.value=le),T.preventDefault()}break}case"ArrowUp":case"ArrowDown":{V.value&&T.preventDefault();break}default:V.value=void 0}},selectedElement:V,isInvalidInput:P,addOnPaste:n,addOnBlur:d,addOnTab:C,dir:I,disabled:r,delimiter:i,max:s,id:u,displayValue:e.displayValue}),(T,M)=>(m(),B(t(E),null,{default:h(()=>[v(t(te),{ref:t(y),dir:t(I),as:T.as,"as-child":T.asChild,"data-invalid":P.value?"":void 0,"data-disabled":t(r)?"":void 0,"data-focused":t(g)?"":void 0},{default:h(()=>[J(T.$slots,"default",{modelValue:t(k)}),t(p)&&T.name?(m(),B(t(dt),{key:0,name:T.name,value:t(k),required:T.required,disabled:t(r)},null,8,["name","value","required","disabled"])):G("v-if",!0)]),_:3},8,["dir","as","as-child","data-invalid","data-disabled","data-focused"])]),_:3}))}}),Fl=Al,Ol=U({__name:"TagsInputInput",props:{placeholder:{type:String,required:!1},autoFocus:{type:Boolean,required:!1},maxLength:{type:Number,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"input"}},setup(l){const a=l,e=ct(),{forwardRef:o,currentElement:n}=re();function r(y){if(e.selectedElement.value=void 0,!e.addOnBlur.value)return;const f=y.target,g=y.relatedTarget,p=f.getAttribute("aria-controls");if(p&&(g!=null&&g.closest(`#${CSS.escape(p)}`))||!f.value)return;e.onAddValue(f.value)&&(f.value="")}function i(y){e.addOnTab.value&&d(y)}const{isComposing:s,handleCompositionStart:u,handleCompositionEnd:_}=ut();async function d(y){if(s.value||(await pe(),y.defaultPrevented))return;const f=y.target;if(!f.value)return;e.onAddValue(f.value)&&(f.value=""),y.preventDefault()}function C(y){if(s.value||(e.isInvalidInput.value=!1,y.data===null))return;const f=e.delimiter.value;if(f===y.data||f instanceof RegExp&&f.test(y.data)){const p=y.target;if(p.value=p.value.replace(f,""),p.value.trim()===""){p.value="";return}e.onAddValue(p.value)&&(p.value="")}}function I(y){s.value||e.onInputKeydown(y)}function k(y){if(e.addOnPaste.value){y.preventDefault();const f=y.clipboardData;if(!f)return;const g=f.getData("text");e.delimiter.value?g.split(e.delimiter.value).forEach(q=>{e.onAddValue(q)}):e.onAddValue(g)}}return ge(()=>{const y=n.value.nodeName==="INPUT"?n.value:n.value.querySelector("input");y&&setTimeout(()=>{a.autoFocus&&(y==null||y.focus())},1)}),(y,f)=>{var g;return m(),B(t(te),{id:(g=t(e).id)==null?void 0:g.value,ref:t(o),type:"text",autocomplete:"off",autocorrect:"off",autocapitalize:"off",as:y.as,"as-child":y.asChild,maxlength:y.maxLength,placeholder:y.placeholder,disabled:t(e).disabled.value,"data-invalid":t(e).isInvalidInput.value?"":void 0,onInput:C,onKeydown:[me(d,["enter"]),me(i,["tab"]),I],onBlur:r,onCompositionstart:t(u),onCompositionend:t(_),onPaste:k},{default:h(()=>[J(y.$slots,"default")]),_:3},8,["id","as","as-child","maxlength","placeholder","disabled","data-invalid","onCompositionstart","onCompositionend"])}}}),Tl=Ol;const[zt,Rl]=be("TagsInputItem");var zl=U({__name:"TagsInputItem",props:{value:{type:null,required:!0},disabled:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(l){const a=l,{value:e}=we(a),o=ct(),{forwardRef:n,currentElement:r}=re(),{CollectionItem:i}=De(),s=F(()=>o.selectedElement.value===r.value),u=F(()=>a.disabled||o.disabled.value),_=Rl({value:e,isSelected:s,disabled:u,textId:"",displayValue:F(()=>o.displayValue(e.value))});return(d,C)=>(m(),B(t(i),{value:t(e)},{default:h(()=>[v(t(te),{ref:t(n),as:d.as,"as-child":d.asChild,"aria-labelledby":t(_).textId,"aria-current":s.value,"data-disabled":u.value?"":void 0,"data-state":s.value?"active":"inactive"},{default:h(()=>[J(d.$slots,"default")]),_:3},8,["as","as-child","aria-labelledby","aria-current","data-disabled","data-state"])]),_:3},8,["value"]))}}),Pl=zl,Dl=U({__name:"TagsInputItemDelete",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(l){const a=l;re();const e=ct(),o=zt(),n=F(()=>{var i;return((i=o.disabled)==null?void 0:i.value)||e.disabled.value});function r(){if(n.value)return;const i=e.modelValue.value.findIndex(s=>He(s,o.value.value));e.onRemoveValue(i)}return(i,s)=>(m(),B(t(te),ae({tabindex:"-1"},a,{"aria-labelledby":t(o).textId,"aria-current":t(o).isSelected.value,"data-state":t(o).isSelected.value?"active":"inactive","data-disabled":n.value?"":void 0,type:i.as==="button"?"button":void 0,onClick:r}),{default:h(()=>[J(i.$slots,"default")]),_:3},16,["aria-labelledby","aria-current","data-state","data-disabled","type"]))}}),Ll=Dl,Nl=U({__name:"TagsInputItemText",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"span"}},setup(l){const a=l,e=zt();return re(),e.textId||(e.textId=Ge(void 0,"reka-tags-input-item-text")),(o,n)=>(m(),B(t(te),ae(a,{id:t(e).textId}),{default:h(()=>[J(o.$slots,"default",{},()=>[H($(t(e).displayValue.value),1)])]),_:3},16,["id"]))}}),Ul=Nl;const Ml=U({__name:"Switch",props:{class:{},modelValue:{type:Boolean},id:{}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a;return(n,r)=>(m(),B(t(Vl),{id:e.id,"model-value":e.modelValue,class:fe(t(ve)("peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50",e.class)),"onUpdate:modelValue":r[0]||(r[0]=i=>o("update:modelValue",i))},{default:h(()=>[v(t(Il),{class:"bg-background pointer-events-none block size-4 rounded-full shadow-sm ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0.5"})]),_:1},8,["id","model-value","class"]))}}),Wl={class:"flex flex-col gap-1.5"},Pt=U({__name:"TagsInput",props:{modelValue:{},placeholder:{},validate:{type:Function},class:{}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a,n=F(()=>e.validate?new Set(e.modelValue.filter(i=>{var s;return(s=e.validate)==null?void 0:s.call(e,i)})):new Set),r=F(()=>{if(!e.validate)return[];const i=new Set;for(const s of e.modelValue){const u=e.validate(s);u&&i.add(u)}return[...i]});return(i,s)=>(m(),S("div",Wl,[v(t(Fl),{"model-value":e.modelValue,delimiter:",","add-on-paste":!0,class:fe(t(ve)("border-input bg-background focus-within:border-ring focus-within:ring-ring/40 flex min-h-9 w-full flex-wrap items-center gap-1.5 rounded-md border px-2 py-1.5 shadow-xs transition-[color,box-shadow] focus-within:ring-[3px]",e.class)),"onUpdate:modelValue":s[0]||(s[0]=u=>o("update:modelValue",u))},{default:h(()=>[(m(!0),S(ee,null,de(e.modelValue,u=>(m(),B(t(Pl),{key:u,value:u,class:fe(t(ve)("flex items-center gap-1 rounded-md border px-1.5 py-0.5 font-mono text-xs",n.value.has(u)?"border-destructive/50 bg-destructive/10 text-destructive":"bg-secondary text-secondary-foreground border-transparent"))},{default:h(()=>[v(t(Ul)),v(t(Ll),{class:"hover:text-foreground opacity-60 transition-opacity hover:opacity-100"},{default:h(()=>[v(t(At),{class:"size-3"})]),_:1})]),_:1},8,["value","class"]))),128)),v(t(Tl),{placeholder:e.modelValue.length?"":e.placeholder,class:"placeholder:text-muted-foreground min-w-24 flex-1 bg-transparent px-1 text-sm outline-none"},null,8,["placeholder"])]),_:1},8,["model-value","class"]),(m(!0),S(ee,null,de(r.value,u=>(m(),S("p",{key:u,class:"text-destructive text-xs"},$(u),1))),128))]))}}),xt=U({__name:"TabsContent",props:{class:{},value:{}},setup(l){const a=l;return(e,o)=>(m(),B(t(El),{value:a.value,class:fe(t(ve)("outline-none",a.class))},{default:h(()=>[J(e.$slots,"default")]),_:3},8,["value","class"]))}}),Kl=["value"],Qe=U({__name:"Textarea",props:{class:{},modelValue:{}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a;return(n,r)=>(m(),S("textarea",{value:e.modelValue,class:fe(t(ve)("border-input bg-background flex min-h-20 w-full rounded-md border px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none sm:text-sm","placeholder:text-muted-foreground field-sizing-content","focus-visible:border-ring focus-visible:ring-ring/40 focus-visible:ring-[3px]","disabled:cursor-not-allowed disabled:opacity-50",e.class)),onInput:r[0]||(r[0]=i=>o("update:modelValue",i.target.value))},null,42,Kl))}}),We=A(null),at=A({ip:"",site:""}),lt=A(!1);let Re=null;async function Hl(l=!1){if(!(We.value&&!l))return Re||(lt.value=!0,Re=(async()=>{try{const a=await ye.geo(l);We.value=a,at.value={ip:a.ipError??"",site:a.siteError??""}}catch(a){const e=a instanceof Error?a.message:String(a);at.value={ip:e,site:e},We.value={ip:[],site:[]}}finally{lt.value=!1,Re=null}})(),Re)}function jl(){return{geo:We,error:at,loading:lt,load:Hl}}const Ze=new Map;function Gl(l){const a=l==="zh"?"zh-CN":"en";if(!Ze.has(a))try{Ze.set(a,new Intl.DisplayNames([a],{type:"region"}))}catch{return null}return Ze.get(a)??null}function Xl(l,a){var o;if(!/^[a-z]{2}$/i.test(l))return null;const e=l.toUpperCase();try{const n=(o=Gl(a))==null?void 0:o.of(e);return n&&n!==e?n:null}catch{return null}}function Jl(l){if(!/^[a-z]{2}$/i.test(l))return"";const a=127462,e=l.toUpperCase();return String.fromCodePoint(a+e.charCodeAt(0)-65,a+e.charCodeAt(1)-65)}const Yl={class:"flex flex-col gap-1.5"},Ql={class:"text-muted-foreground text-xs"},Zl={key:0,class:"font-mono"},en={key:0,class:"flex flex-wrap gap-1.5"},tn=["aria-label","onClick"],an={key:1,class:"text-muted-foreground text-xs"},ln={key:0,class:"shrink-0"},nn={class:"truncate"},on={class:"text-muted-foreground ml-auto shrink-0 text-[11px] tabular-nums"},rn=U({__name:"GeoPicker",props:{modelValue:{},kind:{}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a,{lang:n}=ta(),{geo:r,error:i,loading:s,load:u}=jl(),_=A(""),d=F(()=>{var q,E;const g=(e.kind==="geoip"?(q=r.value)==null?void 0:q.ip:(E=r.value)==null?void 0:E.site)??[],p=[];for(const V of g)if(e.kind==="geoip"){const P=Xl(V.code,n.value);p.push({value:V.code,label:P??V.code,hint:`${V.code.toUpperCase()} · ${V.count}`,flag:Jl(V.code)})}else{p.push({value:V.code,label:V.code,hint:String(V.count),flag:""});for(const P of V.attributes??[])p.push({value:`${V.code}@${P}`,label:`${V.code}@${P}`,hint:x("rules.geo.attribute"),flag:""})}return p}),C=F(()=>{const g=_.value.trim().toLowerCase();return(g?d.value.filter(q=>q.value.includes(g)||q.label.toLowerCase().includes(g)):d.value).slice(0,300)}),I=F(()=>!s.value&&d.value.length===0),k=F(()=>e.kind==="geoip"?i.value.ip:i.value.site);function y(g){o("update:modelValue",e.modelValue.filter(p=>p!==g))}function f(g){const p=d.value.find(q=>q.value===g);return p?`${p.flag} ${p.label}`.trim():g}return u(),(g,p)=>(m(),S("div",Yl,[I.value?(m(),S(ee,{key:0},[v(t(Pt),{"model-value":e.modelValue,placeholder:e.kind==="geoip"?"cn, us, private":"category-ads-all","onUpdate:modelValue":p[0]||(p[0]=q=>o("update:modelValue",q))},null,8,["model-value","placeholder"]),O("p",Ql,[H($(t(x)("rules.geo.unavailable"))+" ",1),k.value?(m(),S("span",Zl,"("+$(k.value)+")",1)):G("",!0)])],64)):(m(),S(ee,{key:1},[e.modelValue.length?(m(),S("div",en,[(m(!0),S(ee,null,de(e.modelValue,q=>(m(),S("span",{key:q,class:"bg-secondary text-secondary-foreground inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-xs"},[H($(f(q))+" ",1),O("button",{type:"button",class:"opacity-60 transition-opacity hover:opacity-100","aria-label":t(x)("common.delete"),onClick:E=>y(q)},[v(t(At),{class:"size-3"})],8,tn)]))),128))])):G("",!0),t(s)?(m(),S("p",an,$(t(x)("rules.geo.loading")),1)):G("",!0),v(t(al),{"model-value":e.modelValue,multiple:"","ignore-filter":"","reset-search-term-on-blur":!1,"onUpdate:modelValue":p[2]||(p[2]=q=>o("update:modelValue",q??[]))},{default:h(()=>[v(t(nl),{class:"border-input bg-background focus-within:border-ring focus-within:ring-ring/40 flex h-9 w-full items-center gap-2 rounded-md border px-3 shadow-xs transition-[color,box-shadow] focus-within:ring-[3px]"},{default:h(()=>[v(t(Va),{class:"text-muted-foreground size-4 shrink-0"}),v(t(vl),{modelValue:_.value,"onUpdate:modelValue":p[1]||(p[1]=q=>_.value=q),placeholder:e.kind==="geoip"?t(x)("rules.geo.searchCountry"):t(x)("rules.geo.searchSite"),class:"placeholder:text-muted-foreground w-full bg-transparent text-sm outline-none"},null,8,["modelValue","placeholder"]),v(t(xl),{class:"text-muted-foreground shrink-0"},{default:h(()=>[v(t(Sa),{class:"size-4"})]),_:1})]),_:1}),v(t(yl),null,{default:h(()=>[v(t(ul),{position:"popper","side-offset":4,class:"bg-popover text-popover-foreground animate-fade-in z-50 max-h-72 w-[var(--reka-combobox-trigger-width)] overflow-hidden rounded-md border shadow-md"},{default:h(()=>[v(t(Cl),{class:"max-h-72 overflow-y-auto p-1"},{default:h(()=>[v(t(cl),{class:"text-muted-foreground px-2 py-4 text-center text-xs"},{default:h(()=>[H($(t(x)("common.empty")),1)]),_:1}),(m(!0),S(ee,null,de(C.value,q=>(m(),B(t(hl),{key:q.value,value:q.value,class:fe(t(ve)("data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-none select-none"))},{default:h(()=>[q.flag?(m(),S("span",ln,$(q.flag),1)):G("",!0),O("span",nn,$(q.label),1),O("span",on,$(q.hint),1),e.modelValue.includes(q.value)?(m(),B(t(_a),{key:1,class:"absolute right-2 size-4"})):G("",!0)]),_:2},1032,["value","class"]))),128))]),_:1})]),_:1})]),_:1})]),_:1},8,["model-value"])],64))]))}}),Ce=[{key:"proto",group:"basic",type:"proto",expr:"proto"},{key:"ip.dst",group:"basic",type:"ip",expr:"ip.dst"},{key:"ip.src",group:"basic",type:"ip",expr:"ip.src"},{key:"port.dst",group:"basic",type:"port",expr:"port.dst"},{key:"port.src",group:"basic",type:"port",expr:"port.src"},{key:"tls.sni",group:"domain",type:"domain",expr:"string(tls?.req?.sni)",analyzer:"tls"},{key:"quic.sni",group:"domain",type:"domain",expr:"string(quic?.req?.sni)",analyzer:"quic"},{key:"dns.name",group:"domain",type:"domain",analyzer:"dns",iter:"dns?.questions ?? []",item:"string(.name)"},{key:"http.host",group:"http",type:"domain",expr:"string(http?.req?.headers?.host)",analyzer:"http"},{key:"http.path",group:"http",type:"text",expr:"string(http?.req?.path)",analyzer:"http"},{key:"http.method",group:"http",type:"text",expr:"string(http?.req?.method)",analyzer:"http"},{key:"http.ua",group:"http",type:"text",expr:'string(get(http?.req?.headers, "user-agent"))',analyzer:"http"},{key:"analyzer",group:"protocol",type:"analyzer"}],nt=Object.fromEntries(Ce.map(l=>[l.key,l])),Dt={proto:["is"],ip:["cidr","geoip","is"],port:["is","range"],domain:["subdomain","wildcard","is","contains","endsWith","startsWith","regex","geosite"],text:["contains","is","startsWith","endsWith","regex"],analyzer:["detected"]},sn=["tcp","udp"];function un(l){return Dt[l][0]}function _t(l){return Dt[l.type]}function se(l){return`"${l.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}const dn=/[.+?^${}()|[\]\\]/g;function Ct(l){return`^${l.replace(dn,"\\$&").replace(/\*/g,".*")}$`}function Lt(l){const a=l.trim();if(a==="*")return{kind:"any",value:""};if(!a.includes("*"))return{kind:"exact",value:a};const e=a.startsWith("*"),o=a.endsWith("*"),n=a.replace(/^\*/,"").replace(/\*$/,"");return n.includes("*")?{kind:"regex",value:Ct(a)}:e&&o?{kind:"contains",value:n}:e?{kind:"suffix",value:n}:o?{kind:"prefix",value:n}:{kind:"regex",value:Ct(a)}}function cn(l,a){const e=Lt(a);switch(e.kind){case"any":return`${l} != ""`;case"exact":return`${l} == ${se(e.value)}`;case"suffix":return`${l} endsWith ${se(e.value)}`;case"prefix":return`${l} startsWith ${se(e.value)}`;case"contains":return`${l} contains ${se(e.value)}`;case"regex":return`${l} matches ${se(e.value)}`}}function pn(l,a,e,o){const n=o.trim();switch(a){case"is":return l.type==="port"?`${e} == ${n}`:`${e} == ${se(n)}`;case"subdomain":return`(${e} == ${se(n)} || ${e} endsWith ${se("."+n)})`;case"wildcard":return cn(e,n);case"contains":case"startsWith":case"endsWith":return`${e} ${a} ${se(n)}`;case"regex":return`${e} matches ${se(n)}`;case"geosite":return`geosite(${e}, ${se(n.toLowerCase())})`;case"cidr":return`cidr(${e}, ${se(n)})`;case"geoip":return`geoip(${e}, ${se(n.toLowerCase())})`;case"detected":return`${n} != nil`;case"range":return""}}function fn(l){const a=nt[l.field];if(!a)return"";const e=l.values.map(n=>n.trim()).filter(Boolean);let o;if(l.op==="range"){const[n,r]=l.values;if(!(n!=null&&n.trim())||!(r!=null&&r.trim()))return"";o=`(${a.expr} >= ${n.trim()} && ${a.expr} <= ${r.trim()})`}else{if(e.length===0)return"";const n=a.iter?a.item:a.expr,r=e.map(s=>pn(a,l.op,n,s)),i=r.length>1?`(${r.join(" || ")})`:r[0];o=a.iter?`any(${a.iter}, {${i}})`:i}return l.negate?o.startsWith("(")&&o.endsWith(")")?`!${o}`:`!(${o})`:o}function ot(l){const a=l.conditions.map(fn).filter(Boolean);return a.length===0?"":a.length===1?a[0]:a.join(l.mode==="and"?" && ":" || ")}const vn=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;function Nt(l){const a=vn.exec(l);return a?a.slice(1).every(e=>Number(e)<=255&&String(Number(e))===e):!1}function Ut(l){return!l.includes(":")||!/^[0-9a-fA-F:.]+$/.test(l)?!1:(l.match(/::/g)??[]).length<=1&&l.split(":").length<=9}function mn(l){return Nt(l)||Ut(l)}function hn(l){const a=l.lastIndexOf("/");if(a<0)return!1;const e=l.slice(0,a),o=l.slice(a+1);if(!/^\d{1,3}$/.test(o))return!1;const n=Number(o);return Nt(e)?n<=32:Ut(e)?n<=128:!1}function gn(l){return/^\d{1,5}$/.test(l)&&Number(l)<=65535}function yn(l,a,e){const o=e.trim();if(!o)return"";switch(a){case"cidr":return hn(o)?"":x("rules.invalidCidr");case"regex":try{return new RegExp(o),""}catch{return x("rules.invalidRegex")}case"geoip":case"geosite":return/^[a-z0-9-]+(@[a-z0-9-]+)*$/i.test(o)?"":x("rules.invalidGeo");case"wildcard":return/^[a-z0-9.*_-]+$/i.test(o)?"":x("rules.invalidDomain")}if((l==="domain"||l==="text")&&o.includes("*"))return x("rules.starHint");switch(l){case"ip":return mn(o)?"":x("rules.invalidIp");case"port":return gn(o)?"":x("rules.invalidPort");case"domain":return/^[a-z0-9.*_-]+$/i.test(o)?"":x("rules.invalidDomain");default:return""}}const bn={class:"bg-muted/40 flex flex-col gap-2 rounded-lg border p-2.5"},xn={class:"flex flex-wrap items-center gap-2"},_n=["aria-pressed"],Cn={key:0,class:"flex flex-wrap gap-1.5"},kn=["onClick"],wn={key:1,class:"flex flex-wrap gap-1.5"},qn=["onClick"],Vn={key:2,class:"flex items-center gap-2"},$n=U({__name:"ConditionRow",props:{condition:{},analyzers:{},removable:{type:Boolean}},emits:["update","remove"],setup(l,{emit:a}){const e=l,o=a,n=F(()=>nt[e.condition.field]??Ce[0]),r=f=>`rules.field.${f.replace(/\./g,"_")}`,i=F(()=>Ce.map(f=>({value:f.key,label:`${x(`rules.group.${f.group}`)} · ${x(r(f.key))}`}))),s=F(()=>_t(n.value).map(f=>({value:f,label:x(`rules.op.${f}`)})));function u(f){o("update",{...e.condition,...f})}function _(f){const g=nt[f];if(!g)return;const p=_t(g).includes(e.condition.op);u({field:f,op:p?e.condition.op:un(g.type),values:p&&g.type===n.value.type?e.condition.values:[]})}function d(f){u({op:f,values:[]})}function C(f){const g=e.condition.values.includes(f)?e.condition.values.filter(p=>p!==f):[...e.condition.values,f];u({values:g})}const I=f=>yn(n.value.type,e.condition.op,f),k=F(()=>{switch(e.condition.op){case"cidr":return"10.0.0.0/8, 2001:db8::/32";case"wildcard":return"*.example.com";case"regex":return"^/api/v\\d+/"}switch(n.value.type){case"ip":return"1.2.3.4";case"port":return"443";case"domain":return"example.com";default:return x("rules.valuePlaceholder")}}),y=F(()=>e.condition.op!=="wildcard"?[]:e.condition.values.filter(Boolean).slice(0,4).map(f=>{const g=Lt(f);return`${f} → ${x(`rules.wildcard.${g.kind}`,{value:g.value})}`}));return(f,g)=>(m(),S("div",bn,[O("div",xn,[v(t(je),{"model-value":l.condition.field,options:i.value,"aria-label":t(x)("rules.builder.field"),class:"h-8 min-w-0 flex-1 basis-45 text-xs sm:basis-56","onUpdate:modelValue":_},null,8,["model-value","options","aria-label"]),v(t(je),{"model-value":l.condition.op,options:s.value,"aria-label":t(x)("rules.builder.operator"),class:"h-8 min-w-0 flex-1 basis-32 text-xs sm:basis-40 sm:flex-none","onUpdate:modelValue":d},null,8,["model-value","options","aria-label"]),O("button",{type:"button",class:fe(t(ve)("h-8 shrink-0 rounded-md border px-2 text-xs font-medium transition-colors",l.condition.negate?"border-block/40 bg-block/10 text-block":"text-muted-foreground hover:bg-accent")),"aria-pressed":l.condition.negate,onClick:g[0]||(g[0]=p=>u({negate:!l.condition.negate}))},$(t(x)("rules.builder.not")),11,_n),l.removable?(m(),B(t(oe),{key:0,variant:"ghost",size:"icon-sm",class:"text-muted-foreground hover:text-destructive shrink-0","aria-label":t(x)("common.delete"),onClick:g[1]||(g[1]=p=>o("remove"))},{default:h(()=>[v(t(Ot),{class:"size-3.5"})]),_:1},8,["aria-label"])):G("",!0)]),n.value.type==="proto"?(m(),S("div",Cn,[(m(!0),S(ee,null,de(t(sn),p=>(m(),S("button",{key:p,type:"button",class:fe(t(ve)("rounded-md border px-2.5 py-1 font-mono text-xs uppercase transition-colors",l.condition.values.includes(p)?"border-primary/40 bg-primary/10 text-foreground":"text-muted-foreground hover:bg-accent")),onClick:q=>C(p)},$(p),11,kn))),128))])):n.value.type==="analyzer"?(m(),S("div",wn,[(m(!0),S(ee,null,de(l.analyzers,p=>(m(),S("button",{key:p,type:"button",class:fe(t(ve)("rounded-md border px-2.5 py-1 font-mono text-xs transition-colors",l.condition.values.includes(p)?"border-primary/40 bg-primary/10 text-foreground":"text-muted-foreground hover:bg-accent")),onClick:q=>C(p)},$(p),11,qn))),128))])):l.condition.op==="range"?(m(),S("div",Vn,[v(t(tt),{"model-value":l.condition.values[0]??"",inputmode:"numeric",placeholder:"1024",class:"h-8 w-28 text-xs","onUpdate:modelValue":g[2]||(g[2]=p=>u({values:[p,l.condition.values[1]??""]}))},null,8,["model-value"]),g[6]||(g[6]=O("span",{class:"text-muted-foreground text-xs"},"–",-1)),v(t(tt),{"model-value":l.condition.values[1]??"",inputmode:"numeric",placeholder:"65535",class:"h-8 w-28 text-xs","onUpdate:modelValue":g[3]||(g[3]=p=>u({values:[l.condition.values[0]??"",p]}))},null,8,["model-value"])])):l.condition.op==="geoip"||l.condition.op==="geosite"?(m(),B(rn,{key:3,"model-value":l.condition.values,kind:l.condition.op,"onUpdate:modelValue":g[4]||(g[4]=p=>u({values:p}))},null,8,["model-value","kind"])):(m(),S(ee,{key:4},[v(t(Pt),{"model-value":l.condition.values,placeholder:k.value,validate:I,"onUpdate:modelValue":g[5]||(g[5]=p=>u({values:p}))},null,8,["model-value","placeholder"]),(m(!0),S(ee,null,de(y.value,p=>(m(),S("p",{key:p,class:"text-muted-foreground font-mono text-[11px]"},$(p),1))),128))],64))]))}});let kt=0;function xe(l={}){return kt+=1,{id:`c${kt}`,field:"tls.sni",op:"subdomain",negate:!1,values:[],...l}}function et(){return{mode:"and",conditions:[xe()]}}const In={class:"flex flex-col gap-3"},Sn={class:"flex flex-wrap items-center gap-2 text-sm"},En={class:"text-muted-foreground"},Bn={class:"bg-muted inline-flex rounded-md p-0.5"},An=["onClick"],Fn={class:"text-muted-foreground"},On={class:"flex flex-col gap-2"},Tn={key:0,class:"flex items-center gap-2"},Rn={class:"text-muted-foreground text-[11px] font-medium uppercase"},zn={class:"flex flex-col gap-1"},Pn={class:"text-muted-foreground text-xs font-medium"},Dn={class:"bg-muted/60 text-muted-foreground block rounded-md px-2.5 py-2 font-mono text-[11px] leading-relaxed break-all"},Ln=U({__name:"RuleBuilder",props:{modelValue:{},analyzers:{}},emits:["update:modelValue"],setup(l,{emit:a}){const e=l,o=a,n=F(()=>ot(e.modelValue));function r(_){o("update:modelValue",{...e.modelValue,..._})}function i(_,d){const C=[...e.modelValue.conditions];C[_]=d,r({conditions:C})}function s(_){r({conditions:e.modelValue.conditions.filter((d,C)=>C!==_)})}function u(){r({conditions:[...e.modelValue.conditions,xe()]})}return(_,d)=>(m(),S("div",In,[O("div",Sn,[O("span",En,$(t(x)("rules.builder.match")),1),O("div",Bn,[(m(),S(ee,null,de(["and","or"],C=>O("button",{key:C,type:"button",class:fe(t(ve)("rounded-[5px] px-2.5 py-1 text-xs font-medium transition-colors",e.modelValue.mode===C?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground")),onClick:I=>r({mode:C})},$(t(x)(`rules.builder.${C}`)),11,An)),64))]),O("span",Fn,$(t(x)("rules.builder.matchSuffix")),1)]),O("div",On,[(m(!0),S(ee,null,de(e.modelValue.conditions,(C,I)=>(m(),S(ee,{key:C.id},[I>0?(m(),S("div",Tn,[d[0]||(d[0]=O("span",{class:"bg-border h-px flex-1"},null,-1)),O("span",Rn,$(t(x)(`rules.builder.${e.modelValue.mode}`)),1),d[1]||(d[1]=O("span",{class:"bg-border h-px flex-1"},null,-1))])):G("",!0),v($n,{condition:C,analyzers:e.analyzers,removable:e.modelValue.conditions.length>1,onUpdate:k=>i(I,k),onRemove:k=>s(I)},null,8,["condition","analyzers","removable","onUpdate","onRemove"])],64))),128))]),v(t(oe),{variant:"outline",size:"sm",class:"w-full",onClick:u},{default:h(()=>[v(t(Tt),{class:"size-3.5"}),H(" "+$(t(x)("rules.builder.addCondition")),1)]),_:1}),O("div",zn,[O("span",Pn,$(t(x)("rules.builder.preview")),1),O("code",Dn,$(n.value||t(x)("rules.builder.empty")),1)])]))}});function wt(l){const a=l.trim();if(!a)return null;let e="and",o=ke(a,"&&");if(o.length===1){const r=ke(a,"||");r.length>1&&(e="or",o=r)}const n=[];for(const r of o){const i=Nn(r);if(!i)return null;n.push(i)}return{mode:e,conditions:n}}function Nn(l){let a=l.trim(),e=!1;a.startsWith("!")&&(e=!0,a=a.slice(1).trim());const o=Pe(a);if(o)return xe({field:o.field.key,op:o.op,negate:e,values:[o.value]});const n=pt(a),r=Mt(n,"any");if(r!==null){const[s,u]=ke(r,",").map(d=>d.trim());if(!(u!=null&&u.startsWith("{"))||!u.endsWith("}"))return null;const _=Ce.find(d=>d.iter===s);return _?qt(_,u.slice(1,-1).trim(),e,_.item):null}const i=ke(n,"&&");if(i.length===2){const s=/^(\S+)\s*>=\s*(\d+)$/.exec(i[0].trim()),u=/^(\S+)\s*<=\s*(\d+)$/.exec(i[1].trim());if(s&&u&&s[1]===u[1]){const _=Ce.find(d=>d.expr===s[1]&&d.type==="port");return _?xe({field:_.key,op:"range",negate:e,values:[s[2],u[2]]}):null}return null}return i.length>1?null:qt(null,n,e)}function qt(l,a,e,o){const n=Pe(a.trim(),o);if(n&&(!l||n.field.key===l.key))return xe({field:n.field.key,op:n.op,negate:e,values:[n.value]});const r=ke(pt(a),"||");if(r.length<2)return null;const i=[];let s=l;for(const d of r){const C=Pe(d.trim(),o);if(!C||(s||(s=C.field),C.field.key!==s.key))return null;i.push(C)}if(!s)return null;if(new Set(i.map(d=>d.op)).size===1)return xe({field:s.key,op:i[0].op,negate:e,values:i.map(d=>d.value)});const _=i.map(d=>Un(d.op,d.value));return _.some(d=>d===null)?null:xe({field:s.key,op:"wildcard",negate:e,values:_})}function Un(l,a){switch(l){case"wildcard":return a;case"is":return a.includes("*")?null:a;case"endsWith":return`*${a}`;case"startsWith":return`${a}*`;case"contains":return`*${a}*`;default:return null}}const Mn={geoip:"geoip",geosite:"geosite",cidr:"cidr"},Wn={"==":"is",contains:"contains",startsWith:"startsWith",endsWith:"endsWith",matches:"regex"};function Vt(l){const a=[];for(const e of Ce)e.item&&a.push({subject:e.item,field:e}),e.expr&&a.push({subject:e.expr,field:e});return a.sort((e,o)=>+(o.subject===l)-+(e.subject===l)||o.subject.length-e.subject.length)}function Pe(l,a){const e=l.trim(),o=/^([a-z][\w]*)\s*!=\s*nil$/.exec(e);if(o){const n=Ce.find(r=>r.type==="analyzer");if(n)return{field:n,subject:"",op:"detected",value:o[1]}}if(e.startsWith("(")&&Kt(e)){const n=ke(pt(e),"||");if(n.length===2){const r=Pe(n[0].trim(),a),i=Pe(n[1].trim(),a);if(r&&i&&r.op==="is"&&i.op==="endsWith"&&r.field.key===i.field.key&&i.value===`.${r.value}`)return{...r,op:"subdomain"}}return null}for(const[n,r]of Object.entries(Mn)){const i=Mt(e,n);if(i===null)continue;const s=ke(i,",").map(d=>d.trim());if(s.length!==2)return null;const u=Vt(a).find(d=>d.subject===s[0]),_=$t(s[1]);return!u||_===null?null:{field:u.field,subject:u.subject,op:r,value:_}}for(const{subject:n,field:r}of Vt(a)){if(!e.startsWith(n))continue;const i=e.slice(n.length).trim();if(i==='!= ""')return{field:r,subject:n,op:"wildcard",value:"*"};for(const[s,u]of Object.entries(Wn)){if(!i.startsWith(s))continue;const _=i.slice(s.length).trim();if(r.type==="port"&&/^\d+$/.test(_)&&u==="is")return{field:r,subject:n,op:u,value:_};const d=$t(_);if(d!==null)return{field:r,subject:n,op:u,value:d}}return null}return null}function Mt(l,a){const e=`${a}(`;if(!l.startsWith(e)||!l.endsWith(")"))return null;const o=l.slice(e.length,-1);return Wt(o)?o:null}function $t(l){if(l.length<2||l[0]!=='"'||l[l.length-1]!=='"')return null;const a=l.slice(1,-1);let e="";for(let o=0;oi.trim()).filter(i=>i.length>0)}function Wt(l){let a=0,e=!1;for(let o=0;o