diff --git a/api/openapi.yaml b/api/openapi.yaml index 44b765d..97a277a 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -372,6 +372,7 @@ components: dial_timeout_ms: {type: integer, minimum: 100, maximum: 2147483647, default: 10000} max_samples: {type: integer, minimum: 1, maximum: 2147483647, nullable: true} max_duration_seconds: {type: integer, minimum: 1, maximum: 2147483647, nullable: true} + target_country: {type: string, pattern: '^([A-Za-z]{2})?$', nullable: true} Session: type: object required: [id, name, proxy_display, mode, status, cadence_seconds, probes_per_sample, @@ -382,6 +383,7 @@ components: name: {type: string} proxy_display: {type: string} proxy_username: {type: string, nullable: true} + target_country: {type: string, nullable: true} mode: {type: string, enum: [sticky, pool]} status: {type: string, enum: [running, stopped, finished]} cadence_seconds: {type: integer, minimum: 1, maximum: 2147483647} @@ -604,6 +606,7 @@ components: dial_timeout_ms: {type: integer, minimum: 100, maximum: 2147483647, default: 10000} max_samples: {type: integer, minimum: 1, maximum: 2147483647, nullable: true} max_duration_seconds: {type: integer, minimum: 1, maximum: 2147483647, nullable: true} + target_country: {type: string, pattern: '^([A-Za-z]{2})?$', nullable: true} RunConfig: type: object required: [max_variants_per_run] @@ -630,6 +633,7 @@ components: params: type: object additionalProperties: {type: string} + target_country: {type: string, nullable: true} status: {type: string, enum: [running, stopped, finished]} samples_taken: {type: integer, minimum: 0} distinct_ips: {type: integer, minimum: 0} @@ -646,6 +650,7 @@ components: required: [cell_key, params, variant_count, distinct_ips, composition] properties: cell_key: {type: string} + target_country: {type: string, nullable: true} params: type: object additionalProperties: {type: string} diff --git a/internal/api/openapi/openapi.gen.go b/internal/api/openapi/openapi.gen.go index bf505ac..ccdbdc7 100644 --- a/internal/api/openapi/openapi.gen.go +++ b/internal/api/openapi/openapi.gen.go @@ -192,12 +192,13 @@ type AxisSpecKind string // CellReport defines model for CellReport. type CellReport struct { - CellKey string `json:"cell_key"` - Composition PoolComposition `json:"composition"` - DistinctIps int `json:"distinct_ips"` - HonorRate *float64 `json:"honor_rate,omitempty"` - Params map[string]string `json:"params"` - VariantCount int `json:"variant_count"` + CellKey string `json:"cell_key"` + Composition PoolComposition `json:"composition"` + DistinctIps int `json:"distinct_ips"` + HonorRate *float64 `json:"honor_rate,omitempty"` + Params map[string]string `json:"params"` + TargetCountry *string `json:"target_country,omitempty"` + VariantCount int `json:"variant_count"` } // CreateRunRequest defines model for CreateRunRequest. @@ -211,6 +212,7 @@ type CreateRunRequest struct { Name string `json:"name"` ProbeTarget *string `json:"probe_target,omitempty"` ProbesPerSample *int `json:"probes_per_sample,omitempty"` + TargetCountry *string `json:"target_country,omitempty"` Template *string `json:"template,omitempty"` } @@ -228,6 +230,7 @@ type CreateSessionRequest struct { ProbeTarget *string `json:"probe_target,omitempty"` ProbesPerSample *int `json:"probes_per_sample,omitempty"` Proxy *string `json:"proxy,omitempty"` + TargetCountry *string `json:"target_country,omitempty"` } // CreateSessionRequestMode defines model for CreateSessionRequest.Mode. @@ -431,6 +434,7 @@ type Session struct { Status SessionStatus `json:"status"` StoppedAt *time.Time `json:"stopped_at,omitempty"` SuccessRate float64 `json:"success_rate"` + TargetCountry *string `json:"target_country,omitempty"` } // SessionMode defines model for Session.Mode. @@ -460,13 +464,14 @@ type Stickiness struct { // VariantSummary defines model for VariantSummary. type VariantSummary struct { - CellKey string `json:"cell_key"` - DistinctIps int `json:"distinct_ips"` - Name string `json:"name"` - Params map[string]string `json:"params"` - SamplesTaken int `json:"samples_taken"` - SessionId openapi_types.UUID `json:"session_id"` - Status VariantSummaryStatus `json:"status"` + CellKey string `json:"cell_key"` + DistinctIps int `json:"distinct_ips"` + Name string `json:"name"` + Params map[string]string `json:"params"` + SamplesTaken int `json:"samples_taken"` + SessionId openapi_types.UUID `json:"session_id"` + Status VariantSummaryStatus `json:"status"` + TargetCountry *string `json:"target_country,omitempty"` } // VariantSummaryStatus defines model for VariantSummary.Status. @@ -3465,57 +3470,58 @@ func (sh *strictHandler) Readyz(w http.ResponseWriter, r *http.Request) { // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "7Bzbcts29lc42H2kbaVx2q33KbHbrWc6XY+d7Uumw4HIIwk1CTAAKFvN+N93cOEdEEnrkjRxX1KLwDkH", - "534h+AnFLMsZBSoFuviEcsxxBhK4/utnzjL1L6HoAn0sgG9QiCjOAF2ghXoWIhGvIMNq0YLxDEt0gRIs", - "4USSDFCI5CZXi4XkhC7R01OIbgt6fVUBzbFc1TBJgkLE4WNBOCToQvICnBiKQq/sA78DIQg7IIL3zMcP", - "yaZz40kRI3JGBWh+v8PJLXwsQEj1V8yoBKr/F+d5SmIsCaNnfwpG1W81rn9yWKAL9I+zWpZn5qk4+4lz", - "xg2qBETMSa6AoAt0Tdc4JUnALcKnEF0yukhJfATktyBYwWMIhMQSgrhE/BSiK8iBJkDjzf8oXmOS4nkK", - "h6fobVCqRZBUFAREBEWDiqcQXVMJnOLUADqClAy6QABfAw/ALAzRb0z+zAqaHFFWlMlgoXGqRXafAvv2", - "kYi7HGJNQJIQtRGnN5zlwCVRqr3AqYAQ5Y2fFNmFITojlGRFhi5eVSZCqIQl6JMurBPqP7kn5vxA1eYP", - "KCVCKvvGdAnm34Rl6I+e3YUoBbqUq2Hckrkxr3FamEMQCZloLKpx2B8w53iDjKmXfueDIb2mjM3/BKP+", - "l5Cmt5AzrjnTYRikaXQPGyc6LVJBjNC2i/qGsfSysVyJnAhJaCwjkosWW2YutqwYZTziWELb1bFCWUmI", - "MvxYMbUJiRapNWfjeS1kWmRzA1iHH+HXIz+baw6uMSeYyqivXo6zdMRScbgipQuvw6o2350C5YAl3Ba0", - "4dknGAl+hK382Cbnyi5dbIqxcnEQCYgZTYzQS7F99+r8h/N/vf7+/IdwwEASgtNIRTdWyMhILoEFLlKJ", - "Ll7NZrNZOAR15tSwDD9GScG1I5tEokfFOqAFzvIU9gaRJdD0Q0KS+F7rEGOp0/+YnEEj/9W6Is2IjNDq", - "b8e2nLM5RBLzJch2vsIJ8q0XUQ7cnrh94DdvhsQrIctTa+bbaAvRAycS/kvTjWFT17D0gRvwQqPYlnd9", - "bfRbkk3xnmdNL0r/ovSDSp9z9rjZl8YbYJP0vEotJ+VSRho9bmQgBF66nnVDnyGwXO8i7BfAqcma2shV", - "El+IpjKwe4cGdBDaXU5ELE36aFymUSkDofL7cxQOJC4qr08iLMdWaCEiuZOtDVuaSIKQmMtJRHT4RnLU", - "gtI4VU1X2OeWi9HXN7fsoc9pLKg7x8QSloz7EtCCSs+zhIp5Gq2InJQzl/tUXg9JY8OcsRSwTlwXhAsZ", - "CQA6XqZLDhvKiIAoTrFwU7IijQxyoog9OkOE+/cUTz4BJ+I+EjHjbedWutOhhNuX/mrVqoRci9TQHmq9", - "aCHv87Ijs5boW9JqnrvJbpeadguWvmvAEsegauXh4iVjc5LC8DoOgiRAJcHp8OKC3lP2QCeWG5aUNq6w", - "eZoaso8v/+HsQa5uGKGOinGKp+uWgJOUvnMw3CuUXOTfAk4IBWOBnXiWkvh+xQoBbrPPmZBL3ioJq6cd", - "WqqlYROqm568kNpp3hVZho0v6yhaqc3jCuVFipdLSKYtzoHH0HE8jtK6a+u9YloyidMxqDsMq/e1D9Cn", - "MOzww8lUIu7fFfE9uBoaY0p05SjmkLqzG/y43QE6zJ/QaVs63DHEGDiGAOsn3adnRqF2M80FZ1nky0SI", - "yidzDmvCCrFDbiSZG4XLtEuCyl1eMpw8KRzsiHVxNy03m9a0IsmIFn9dpfQZ3ctyeUGpqQWEZHmuw92C", - "UCJWkDgroLL8jRIi8hS7c6Vd+lf6SJ1au0JWHWG4p1ULwyPAS0YXZNkXo6ozLXBTgvGCDrVZu0HRBcJD", - "xhVITNI+GRbrtuaY0sKa2+28dNu+382GMkIMNXoVJQ0snnNs6/iOJ63RO3bk0sdsEE8MkyAkybTG5Yyl", - "kSB/wRceWw/WAbenGSVvU705RF1xMUrZA/BoXk6K+omUTuZXREi25DgbjboR1R34BXAC489xp5ebFNYB", - "TfKCqqIkMY225mzq/QoCYSwxICJQsAsJSaDiU4CDGCuvHJiiOGCLQK4gyJiQAQelBgGbC+BrHaHFv4Om", - "jgeYJoFDLwPMIdBcDTRXxWkdRHwZaMe7urTdJ7Pm6dsm3BPd1GStElNo3YxRPpeHutMM/GkNrhqj6xkc", - "5q3SbxFtaxBA2fNyNGCieIXp0tcAoPDgx5xzonQj2tq4KBeZ7Mdjof3liv0+rGwOUdeSBwH3rFiDYfeu", - "lkmDAe5tXEphe9Pdvc2cz7VXRFiq5KHdc+meT1jKHIWzlJEK4j6k+jkk258T6n1uzDkS8NGZ5fo27NBy", - "a2BsQXMwrMmdXl7V0OVacVsHbnGnxUqHMnd0sal4XTVoaFNpbH5Dv7EN47adV2o0zqc3XIZL0SyKgU48", - "XkI/G/BM6qXp0+zStjAns9Q10ZfwnTxrRK/dGjCtJtbE6q3StPbcw5GZbEtrKgV9TgGpig0ab6L8zcza", - "7kTsFYAf3zwPQN3am0h6p9c3taVfxLEKcNPTwd4JGn3EnftvLbJ64umx261DLZ0Id+5Y2umto9LZy2T2", - "eV2E3jT3WdPb4TxoZAdC98WrhGgwbdDLXYnOtJ0jsx+9R4elbUlNyysIaZVpm1gGEX8jw/F9jb9NcjYi", - "OXKOy73L/GHWM0ff2uoyKwoBvDz+oBpYOUUS3wP15IfDE9ZhNLs3++yy3cjYV2TZ0idsi6l6U6HqFXY9", - "s0tlOmrad6pdwbXT5JZy9QLXtOZk9X6Qu6O2v/7Kbv00DWKpZ3ej6emO+xyU8WqEFYl6hrW1k9Mbev09", - "ukLapVbTw62A6pW9wq7sgDSgtWXjELaTy452jLeb0qK8Uy+sgauqY8XSxDnLGZcIq+3jOa1ft3GwOIOE", - "YLorLdyOwMbTUw3Nhprr5phNFKGbg+6zuITTae9Pewd7WpPcH/L38BZ0L04OlDDGa0YjU9Sdw2PPDiv0", - "VVxyvYtdBaVuNBl410DhI3Rh3uYnUkVcdKPiXmD6FDx4e3ONQrQGbsoT9Op0djpTR2U5UJwTdIFen85O", - "X2tq5Eqf/Qzn5CyuJmE2QVNy0tp4naCLxqysc9fnu9lsb3c3aiSu+xsFPeGgir0kiFMCVAaGZptMq0O+", - "McS4cFREn7WvvjxpVJoFvDDG7WTAr0TI20Kb5k7nH+c5CpfTcLFEPPfYatfr4V3ua0yalpwJB5+qewL2", - "hhoI+Y4lm73pSO8ewlPbCPU7rD0ZvdqnjnpEEdiMTo9cbPKu+Hw+RjqNK3OfSaBNKzj7RJInM6ZKwaTs", - "bSlf6d9LKbdYfd4fbynmGEjPZci5Abt9S3WX7LOZhM91vttcXx3YcdpXCDyqmdinXzPzm3d+P7jh1EvO", - "zP3dpz96an8Gj6rkOo3F2hsMftJLVLi6+31YrhIe5ZkF57hZOyfUZN6Oa7VtSV5BUuSQBCqVD65vAoN9", - "BTixF50vDdKTKyKaNV2NtIfi2xMvB6DlXdznwfSFvlsL2ekWZ8eIQBxODAlftZ91ybTskvg8sO2jHFYs", - "5UtLfeHcKIvl1TtN35jJqVJq/+Z2J1n++UytLA+/ATuzVe322uiuXHSM+qgcv42okSq6vsg6qTzIIWul", - "zk3TI9dLlai8ovlK6qbSSkbWTk3JD9VPJaOOXEOdz34c3nDZ+ObJF1R0WZYduvAaod0vpVc3sNdfN6qT", - "hZb1jC/BLKjjlmGXK84oS9mSxDgNcuAnevCnyrHAUL6XquxFWTrKEg4u1h/6GrHuPfOq3vPLw6ZaD5WI", - "Xu9/VNdUl4s69pazj5fwMhDdh+rN9uz+8DL2151mWg9JICqR1zXoi4P5HA6m8YbWNuW5q76AcDjtqd+S", - "dqjOb/AAQp7oq+5Bjpf64smSs6K+iiJe9OgIehS6P9RoX+6uRV1/u2f766VexXxWl2ZM1LuTLH9OvXPk", - "HsvfJiCt9Ads/vK6kF/s8wP6DvsNHVerk7MYhAiICHBK1rDbXJ4DTjb+k96ax4dsAVYfd3AOZKyUCAh9", - "o06Tu7NqHJ7wtzJIAQsZMArbPhSq//t/AAAA//8=", + "7Bxpc9y29a9w0HxoZyhpHctJs/3QsaWk0Uwm1UhpPtTjcrDk211EJEAD4Eprj/57Bwdv8NIedmzli6Ml", + "8N7Duw+CH1HIkpRRoFKg+UeUYo4TkMD1Xz9xlqh/CUVz9D4DvkU+ojgBNEdL9cxHIlxDgtWiJeMJlmiO", + "IizhRJIEkI/kNlWLheSErtDjo49uMnp1WQBNsVyXMEmEfMThfUY4RGgueQZODFmmV7aB34IQhB0QwW+s", + "ix+STefGoyJGpIwK0Px+g6MbeJ+BkOqvkFEJVP8vTtOYhFgSRs/+EIyq30pc33BYojn6y1kpyzPzVJz9", + "yDnjBlUEIuQkVUDQHF3RDY5J5HGL8NFHF4wuYxIeAfkNCJbxEDwhsQQvzBE/+ugSUqAR0HD7H4o3mMR4", + "EcPhKXrt5WrhRQUFHhFeVqHi0UdXVAKnODaAjiAlg84TwDfAPTALffQrkz+xjEZHlBVl0ltqnGqR3afA", + "vn4g4jaFUBMQRURtxPE1ZylwSZRqL3EswEdp5SdFdmaITgglSZag+YvCRAiVsAJ90qV1Qu0nd8ScH6ja", + "/BbFREhl35iuwPwbsQS9a9mdj2KgK7kexi2ZG/MGx5k5BJGQiMqiEof9AXOOt8iYeu533hrSS8rY4g8w", + "6n8BcXwDKeOaMw2GQRwHd7B1otMiFcQIrV/U14zFF5XlSuRESEJDGZBU1Ngyc7FlzSjjAccS6q6OZcpK", + "fJTgh4KpVUg0i605G89rIdMsWRjAOvyIbj3qZnPJQYn5CmSgtYtrXnWgLWFsMCeY2j1Dx29IshBKQX0T", + "XoO7dVE5dYADlnCT0UowmGBX+AF6WdinGoUpuzgbYuUVIRAQMhoZPckl/e2L8+/P//7yu/Pv/QGbigiO", + "AxUQWSYDI+wIljiLJZq/mM1mM38I6syplAl+CKKMa983icQO9WiAFjhJY9gbRBZB1XUJScI7rUOMxU6X", + "ZdIMjfwX6700IxJCi78d21LOFhAYm6inOJygrvUiSIHbE9cP/OrVkHiHzS/FUgU1NEf/++vb1yf/xScf", + "3n389vFv//zGRZCEJI2tp+k7q4/uOZHwbxpvDaKmoWoGVuD5xlCsLNra3W2ZNst8mnU+G9GzEQ0aUcrZ", + "w3a6xu/b+twWZIibZDdFtjwpPTTSbXE3ASHwyvWsGZoNgfl6F2E/A45NIlhHruqSTFSVi905NKqB0O5y", + "ImJx1EbjMrVCuQiV350jfyAXU6VKFGA5tuj0EUmdbK3Y5kQShMRcTiKiwTeSohqUyqlKuvw2t1yMvrq+", + "YfdtTmNB3WkzlrBivCunLsyo9SyiYhEHayInlQH5PlWqQFTZsGAsBqxz8SXhQgYCgI6X6YrDljIiIAhj", + "LNyUrEklw50o4g6dIcL9e4wnn4ATcReIkPG6s8zd81AN0ZWea9UqhFyK1NDua72oIW/zsiGzmuhr0qqe", + "u8pul5o2a7C2a8ASh6DK/+F6LGELEsPwOg6CREAlwfHw4ozeUXZPJ5ZDlpQ6Lr96mhJyF1/+xdm9XF8z", + "Qh1F8BRP16xqJyl942C4Vci5yL8BHBEKxgIb8Swm4d2aZQLcZp8yIVe8VuUWTxu0FEv9KlQ3PWkmtdO8", + "zZIEG1/WULRcm8fV/ssYr1YQTVucAg+h4Xgc3YKmrbf6A5JJHI9B3WBYua9+gDaFfoMfTqYScfcmC+/A", + "1aMZ00JQjmIBsTu7wQ/9DtBh/oRO29LgjiHGwDEEWD/pPj0zCrWbaS45S4KuTISofDLlsCEsEzvkRpK5", + "UbhMOyco39VJhpMnmYMdoS4Wp+Vm0/pwJBoxtSirnjajW1kuzyg1tYWQLE11uFsSSsQaImdFlZfTQURE", + "GmN3rrRLf00fqVG7F8iKIwz33EphdAjwgtElWbXFqOpWC9yUdDyjQ53jZlB0gegg4xIkJnGbDIu1r3mn", + "tLDkdj0v7dv3u9mQR4ih3rWipIKl4xx9TezxpFXa4Y5c+pg974lhEoQkida4lLE4EOQDfOax9WBNfXua", + "UfI21ZtD1AUXg5jdAw8W+fCrnUjpZH5NhGQrjpPRqCtR3YFfACcw/hy3erlJYR3QJM+oKkoi07irjtt+", + "W4MnjCV6RHgKdiYh8lR88rAXYuWVPVMUe2zpyTV4CRPS46DUwGMLAXyjI7T4h1fVcQ/TyHPopYc5eJqr", + "nuaqOC2DSFcG2vCuLm3vkln19HUTboluarJWiMm3bsYon8tD3WoG/rgBV43R9AwO81bptwj6GgSQ97wc", + "DZggXGO66moAULjvxpxyonQj6G1c5ItM9jM4/8qXK/Z3YWULCJqWPAi4ZcUaDLtztUwqDHBv41IK2+tu", + "7q3mfK69IsBSJQ/1nkvzfMJS5iicpQxUEO9Cqp9D1P+c0M7nxpwDAe+dWW7Xhh1abhWMNWgOhlW508qr", + "KrpcKm7twDXu1FjpUOaGLlYVr6kGFW3Kja3b0K9tw7hu54UajfPpFZfhUjSLYqCzj1fQzgY6Xj6Qpk+z", + "S9vCnMxSV0Wfw3fyrBK9dmvA1JpYE6u3QtPqcxRHZtKX1hQK+pQCUhUbNNwG6auZtd2J2AsAP7x6GoCy", + "tTeR9Eavb2pLPwtDFeCmp4OtE1T6iDv332pktcTTYrdbh2o64e/csbTTYEels5dJ79O6CK3p8JOmwcN5", + "0MgOhO6LFwnRYNqgl7sSnWk7R2Y/eo8OS31JTc0rCGmVqU8sg4i/kmH7vsbpJjkbkRw5x++dy7rDbMdc", + "vrfVZVZkAnh+/EE1sHIKJL4D2pEfDk9Yh9Hs3uyzy3YjY3+RZfKbfj2txbpki5cbivZi05m7tKyh2W0/", + "3JR1PbOu6WMr1k3rZxavKLmbcPtryezWgtMgVnrcN5qe5oTQQRkvpl6BKMdevc2f1pzsz9FI0l64GDj2", + "AipXtmrBvGlSgVaXjUPYTi47OjidDZga5Y0SYwNcFSprFkfO8c+43FltH89p/YaOg8UJRATTXWnhdmo2", + "np5izjbUjzfHrKLw3Rx0n8UlnMZEYNqb6NP66t1Zwh7eBW+F1oGqx3jNYGRWu4/x2Y4hrEJxEcpcb6QX", + "cawZgAbeaFD4CF2aaxBEKrLQtQqVnumGcO/19RXy0Qa4KYLQi9PZ6UwdjaVAcUrQHL08nZ2+1NTItWbX", + "GU7JWVjM22waqESrFfgqQvPKRK5xSerb2Wxvl15KJK6LLxk94aBKysgLYwJUeoZmm7KrQ74yxLhwFESf", + "1e8MPWpUmgU8M/7AyYBfiJA3mbbmnc4/ztlkLj/jYol46rHVrpfDu9z3vzQtKRMOPhW3JezVPhDyDYu2", + "e9OR1m2Mx7oR2jdvGzJ6sU8d7RCFZ5NAPdixJYLi8/kY6VTuGn4igVat4OwjiR7NMCwGUxjUpXypf8+l", + "XGP1eXuIpphjID2VIecGbP+W4hLeJzOJLtf5Znt1eWDHaV9U6FDNyD79kplfvSz91g2nXHJmLj4/vmup", + "/Rk8qCrtNBSbzmDwo16iwtXt78NylfAgzyw4x5XkBaEmWXfcR65L8hKiLIXIU9m/d3XtGexrwJG9IX5h", + "kJ5cElEtA0ukLRRfn3g5AM0vMT8NZlfou7GQnW5xdowIxOHEkPBF+1mXTPPGSpcHtq2Xw4olfzWqLZxr", + "ZbG8eHPqKzM5VX3t39xuJUs/nanlFeVXYGe2qu2vjW7zRceoj/Ih34gaqaDrs6yT8oMcslZq3I89cr1U", + "iKpTNF9I3ZRbycjaqSr5ofopZ9SRa6jz2Q/DGy4qH4v5jIouy7JDF14jtPu59GoG9vKzUGWyULOe8SWY", + "BXXcMuxizRllMVuREMdeCvxEzwpVOeYZyvdSlT0rS0NZ/MHF+gtpI9b9xjpV7+nlYVWth0rETu9/VNdU", + "los69ubjkufwMhDdh+rN+rj/8DLurjvNgB8iTxQiL2vQZwfzKRxM5T2wPuW5Lb6zcDjtKd/FdqjOr3AP", + "Qp7oC/Veilf6esuKs6y88CKe9egIeuS7v3BpXyEvRV1+caj/JdZOxXxSl2ZM1LuVLH1KvXPkHsufJiCt", + "9WdyPnS6kJ/t8wP6DvulHlerk7MQhPCI8HBMNrDbXJ4DjrbdJ70xjw/ZAiw+IeEcyFgpERD63p4md2fV", + "ODzhr6UXAxbSYxT6vrCq//t/AAAA//8=", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/api/run_report.go b/internal/api/run_report.go index f0471e1..f5efa22 100644 --- a/internal/api/run_report.go +++ b/internal/api/run_report.go @@ -103,8 +103,8 @@ func mapCells(cells []variation.CellReport) []openapi.CellReport { params := map[string]string{} _ = json.Unmarshal(cell.Params, ¶ms) result = append(result, openapi.CellReport{ - CellKey: cell.CellKey, Params: params, VariantCount: cell.VariantCount, - DistinctIps: cell.DistinctIPs, HonorRate: cell.HonorRate, + CellKey: cell.CellKey, Params: params, TargetCountry: optionalString(cell.TargetCountry), + VariantCount: cell.VariantCount, DistinctIps: cell.DistinctIPs, HonorRate: cell.HonorRate, Composition: openapi.PoolComposition{ Mobile: cell.Composition.Mobile, Residential: cell.Composition.Residential, Datacenter: cell.Composition.Datacenter, Unknown: cell.Composition.Unknown, diff --git a/internal/api/runs.go b/internal/api/runs.go index d7c6d7b..5eacbb0 100644 --- a/internal/api/runs.go +++ b/internal/api/runs.go @@ -74,6 +74,10 @@ func (s *Server) CreateRun(ctx context.Context, request openapi.CreateRunRequest !validOptionalPersistedInteger(body.MaxSamples) || !validOptionalPersistedInteger(body.MaxDurationSeconds) { return nil, invalidRequest() } + targetCountry, ok := normalizedTargetCountry(body.TargetCountry) + if !ok { + return nil, invalidRequest() + } if s.runStore == nil || s.cipher == nil || s.store == nil || s.control == nil { return nil, internalError() @@ -142,7 +146,7 @@ func (s *Server) CreateRun(ctx context.Context, request openapi.CreateRunRequest Cadence: time.Duration(body.CadenceSeconds) * time.Second, ProbesPerSample: probes, ProbeTarget: probeTarget, DialTimeout: dialTimeout, MaxSamples: cloneInt(body.MaxSamples), MaxDuration: secondsPointer(body.MaxDurationSeconds), Status: session.StatusRunning, - CreatedAt: now, StartedAt: timePointer(now), + TargetCountry: targetCountry, CreatedAt: now, StartedAt: timePointer(now), } children = append(children, variation.ChildSession{Session: child, Params: paramsJSON, CellKey: variant.CellKey}) } @@ -547,7 +551,8 @@ func mapVariant(v variation.VariantSession) openapi.VariantSummary { _ = json.Unmarshal(v.Params, ¶ms) return openapi.VariantSummary{ SessionId: v.SessionID, Name: v.Name, CellKey: v.CellKey, Params: params, - Status: openapi.VariantSummaryStatus(v.Status), SamplesTaken: v.Snapshot.SamplesTaken, + TargetCountry: optionalString(v.TargetCountry), + Status: openapi.VariantSummaryStatus(v.Status), SamplesTaken: v.Snapshot.SamplesTaken, DistinctIps: v.Snapshot.DistinctIPs, } } diff --git a/internal/api/runs_test.go b/internal/api/runs_test.go index 41f1bac..0b25f29 100644 --- a/internal/api/runs_test.go +++ b/internal/api/runs_test.go @@ -63,6 +63,42 @@ func TestCreateRunExpandsVariants(t *testing.T) { } } +func TestCreateRunPropagatesTargetCountryToChildren(t *testing.T) { + store := newMemoryStore() + runStore := newMemoryRunStore() + handler := testRunHandler(t, store, runStore, &fakeControl{}) + + body := `{"name":"geo","template":"socks5h://u-sid-{session}:pw@gate.example:1080","axes":{"session":{"kind":"random","count":2,"length":8}},"mode":"sticky","cadence_seconds":30,"target_country":"us"}` + resp := request(t, handler, http.MethodPost, "/api/runs", body) + if resp.Code != http.StatusCreated { + t.Fatalf("status = %d body=%s", resp.Code, resp.Body.String()) + } + children := runStore.children[runStore.runs[0].ID] + if len(children) != 2 { + t.Fatalf("children = %d, want 2", len(children)) + } + for _, child := range children { + if child.Session.TargetCountry != "US" { + t.Errorf("child target country = %q, want US (normalized uppercase)", child.Session.TargetCountry) + } + } +} + +func TestCreateRunRejectsInvalidTargetCountry(t *testing.T) { + store := newMemoryStore() + runStore := newMemoryRunStore() + handler := testRunHandler(t, store, runStore, &fakeControl{}) + + body := `{"name":"geo","template":"socks5h://u:pw@gate.example:1080","axes":{},"mode":"sticky","cadence_seconds":30,"target_country":"usa"}` + resp := request(t, handler, http.MethodPost, "/api/runs", body) + if resp.Code != http.StatusBadRequest { + t.Fatalf("status = %d, want 400; body=%s", resp.Code, resp.Body.String()) + } + if len(runStore.runs) != 0 { + t.Fatal("run persisted despite invalid target country") + } +} + func TestCreateRunRejectsCapExceeded(t *testing.T) { store := newMemoryStore() runStore := newMemoryRunStore() diff --git a/internal/api/server.go b/internal/api/server.go index 52f5cfc..cfb76b8 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -9,6 +9,7 @@ import ( "io" "net/http" "net/url" + "regexp" "strings" "time" "unicode/utf8" @@ -181,7 +182,7 @@ func validateCreateSessionJSON(raw []byte) error { } for name, value := range fields { switch name { - case "name", "proxy", "mode", "cadence_seconds", "max_samples", "max_duration_seconds": + case "name", "proxy", "mode", "cadence_seconds", "max_samples", "max_duration_seconds", "target_country": case "probes_per_sample", "probe_target", "dial_timeout_ms": if bytes.Equal(bytes.TrimSpace(value), []byte("null")) { return invalidRequest() @@ -209,7 +210,7 @@ func validateCreateRunJSON(raw []byte) error { } for name, value := range fields { switch name { - case "name", "template", "mode", "cadence_seconds", "max_samples", "max_duration_seconds": + case "name", "template", "mode", "cadence_seconds", "max_samples", "max_duration_seconds", "target_country": case "probes_per_sample", "probe_target", "dial_timeout_ms": if bytes.Equal(bytes.TrimSpace(value), []byte("null")) { return invalidRequest() @@ -290,6 +291,10 @@ func (s *Server) CreateSession(ctx context.Context, request openapi.CreateSessio !validOptionalPersistedInteger(body.MaxSamples) || !validOptionalPersistedInteger(body.MaxDurationSeconds) { return nil, invalidRequest() } + targetCountry, ok := normalizedTargetCountry(body.TargetCountry) + if !ok { + return nil, invalidRequest() + } proxyDisplay, err := proxydial.Display(*body.Proxy) if err != nil { @@ -309,7 +314,7 @@ func (s *Server) CreateSession(ctx context.Context, request openapi.CreateSessio Cadence: time.Duration(body.CadenceSeconds) * time.Second, ProbesPerSample: probes, ProbeTarget: probeTarget, DialTimeout: dialTimeout, MaxSamples: cloneInt(body.MaxSamples), MaxDuration: secondsPointer(body.MaxDurationSeconds), Status: session.StatusRunning, - CreatedAt: now, StartedAt: timePointer(now), + TargetCountry: targetCountry, CreatedAt: now, StartedAt: timePointer(now), } created, err := s.store.Create(ctx, value) if err != nil { @@ -482,15 +487,38 @@ func mapSession(value session.Session) openapi.Session { lastPrimaryIP := value.Snapshot.LastPrimaryIP.String() result.LastPrimaryIp = &lastPrimaryIP } - if value.Snapshot.LastCategory != "" { - lastCategory := value.Snapshot.LastCategory - result.LastPrimaryCategory = &lastCategory + result.LastPrimaryCategory = optionalString(value.Snapshot.LastCategory) + result.LastError = optionalString(value.Snapshot.LastError) + result.TargetCountry = optionalString(value.TargetCountry) + return result +} + +// optionalString maps an empty-means-unset string to the pointer shape of the +// generated response types: nil when empty, otherwise a pointer to a copy. +func optionalString(value string) *string { + if value == "" { + return nil } - if value.Snapshot.LastError != "" { - lastError := value.Snapshot.LastError - result.LastError = &lastError + return &value +} + +// targetCountryPattern mirrors the target_country schema in api/openapi.yaml +// (sans the optional-empty alternative, which normalizedTargetCountry treats +// as unset before matching). +var targetCountryPattern = regexp.MustCompile(`^[A-Za-z]{2}$`) + +// normalizedTargetCountry validates an optional manual target country: unset +// (nil or empty) is fine, otherwise it must be a 2-letter ISO 3166-1 alpha-2 +// code, normalized to uppercase for storage so comparisons and display are +// uniform regardless of how the operator typed it. +func normalizedTargetCountry(value *string) (string, bool) { + if value == nil || *value == "" { + return "", true } - return result + if !targetCountryPattern.MatchString(*value) { + return "", false + } + return strings.ToUpper(*value), true } func durationSeconds(value *time.Duration) *int { diff --git a/internal/api/server_test.go b/internal/api/server_test.go index fb7cd17..864b6f5 100644 --- a/internal/api/server_test.go +++ b/internal/api/server_test.go @@ -103,6 +103,53 @@ func TestCreateSessionUsesExplicitTargetTimeoutAndCaps(t *testing.T) { } } +func TestCreateSessionPersistsTargetCountry(t *testing.T) { + store := newMemoryStore() + handler := testHandler(t, store, &fakeControl{}) + body := `{"name":"Geo","proxy":"` + testProxy + `","mode":"sticky","cadence_seconds":30,"target_country":"de"}` + + response := request(t, handler, http.MethodPost, "/api/sessions", body) + if response.Code != http.StatusCreated { + t.Fatalf("status = %d, want 201; body=%s", response.Code, response.Body.String()) + } + if store.sessions[0].TargetCountry != "DE" { + t.Errorf("target country = %q, want DE (normalized uppercase)", store.sessions[0].TargetCountry) + } + if !strings.Contains(response.Body.String(), `"target_country":"DE"`) { + t.Errorf("response missing target_country: %s", response.Body.String()) + } +} + +func TestCreateSessionRejectsInvalidTargetCountry(t *testing.T) { + for _, value := range []string{"deu", "d", "d1", "**"} { + store := newMemoryStore() + handler := testHandler(t, store, &fakeControl{}) + body := `{"name":"Geo","proxy":"` + testProxy + `","mode":"sticky","cadence_seconds":30,"target_country":"` + value + `"}` + response := request(t, handler, http.MethodPost, "/api/sessions", body) + if response.Code != http.StatusBadRequest { + t.Errorf("target_country %q: status = %d, want 400", value, response.Code) + } + if len(store.sessions) != 0 { + t.Errorf("target_country %q: session persisted despite invalid value", value) + } + } +} + +func TestSessionByIDOmitsUnsetTargetCountry(t *testing.T) { + store := newMemoryStore() + handler := testHandler(t, store, &fakeControl{}) + seeded := sampleSession() + store.sessions = append(store.sessions, seeded) + + response := request(t, handler, http.MethodGet, "/api/sessions/"+seeded.ID.String(), "") + if response.Code != http.StatusOK { + t.Fatalf("status = %d, want 200", response.Code) + } + if strings.Contains(response.Body.String(), "target_country") { + t.Errorf("unset target_country should be omitted: %s", response.Body.String()) + } +} + func TestCreateSessionRejectsMalformedProxyBeforeEncryption(t *testing.T) { store := newMemoryStore() server := NewServer(store, &fakeControl{}, nil, Defaults{ProbeTarget: testProbeTarget, DialTimeout: 10 * time.Second}, nil, 128) diff --git a/internal/db/models.go b/internal/db/models.go index f97a36a..245fa56 100644 --- a/internal/db/models.go +++ b/internal/db/models.go @@ -66,6 +66,7 @@ type SamplingSession struct { RunID pgtype.UUID `json:"run_id"` VariantParams []byte `json:"variant_params"` CellKey *string `json:"cell_key"` + TargetCountry string `json:"target_country"` } type SessionIp struct { diff --git a/internal/db/query/runs.sql b/internal/db/query/runs.sql index 6374e9f..7fbc86b 100644 --- a/internal/db/query/runs.sql +++ b/internal/db/query/runs.sql @@ -10,7 +10,7 @@ INSERT INTO sampling_sessions ( max_samples, max_duration_seconds, status, samples_taken, probes_ok, probes_total, distinct_ips, last_sample_at, last_primary_ip, last_rtt_ms, last_error, created_at, started_at, stopped_at, sequence_offset, - run_id, variant_params, cell_key + target_country, run_id, variant_params, cell_key ) VALUES ( sqlc.arg(id), sqlc.arg(name), sqlc.arg(proxy_ciphertext), sqlc.arg(proxy_nonce), sqlc.arg(proxy_display), sqlc.arg(mode), sqlc.arg(cadence_seconds), @@ -21,7 +21,7 @@ INSERT INTO sampling_sessions ( NULLIF(sqlc.arg(last_primary_ip)::text, '')::inet, sqlc.narg(last_rtt_ms), NULLIF(sqlc.arg(last_error)::text, ''), sqlc.arg(created_at), sqlc.narg(started_at), sqlc.narg(stopped_at), sqlc.arg(sequence_offset), - sqlc.arg(run_id), sqlc.arg(variant_params), sqlc.arg(cell_key) + sqlc.arg(target_country), sqlc.arg(run_id), sqlc.arg(variant_params), sqlc.arg(cell_key) ); -- name: Runs :many @@ -57,7 +57,7 @@ GROUP BY run.id; -- name: RunSessions :many SELECT s.id, s.name, COALESCE(s.variant_params, '{}'::jsonb) AS variant_params, - COALESCE(s.cell_key, '') AS cell_key, s.status, + COALESCE(s.cell_key, '') AS cell_key, s.target_country, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips FROM sampling_sessions AS s WHERE s.run_id = sqlc.arg(run_id) diff --git a/internal/db/query/sessions.sql b/internal/db/query/sessions.sql index 449482e..8ff58e2 100644 --- a/internal/db/query/sessions.sql +++ b/internal/db/query/sessions.sql @@ -4,7 +4,8 @@ INSERT INTO sampling_sessions ( cadence_seconds, probes_per_sample, probe_target, dial_timeout_ms, max_samples, max_duration_seconds, status, samples_taken, probes_ok, probes_total, distinct_ips, last_sample_at, last_primary_ip, last_rtt_ms, - last_error, created_at, started_at, stopped_at, sequence_offset + last_error, created_at, started_at, stopped_at, sequence_offset, + target_country ) VALUES ( sqlc.arg(id), sqlc.arg(name), sqlc.arg(proxy_ciphertext), sqlc.arg(proxy_nonce), sqlc.arg(proxy_display), sqlc.arg(mode), sqlc.arg(cadence_seconds), @@ -14,7 +15,8 @@ INSERT INTO sampling_sessions ( sqlc.arg(distinct_ips), sqlc.narg(last_sample_at), NULLIF(sqlc.arg(last_primary_ip)::text, '')::inet, sqlc.narg(last_rtt_ms), NULLIF(sqlc.arg(last_error)::text, ''), sqlc.arg(created_at), - sqlc.narg(started_at), sqlc.narg(stopped_at), sqlc.arg(sequence_offset) + sqlc.narg(started_at), sqlc.narg(stopped_at), sqlc.arg(sequence_offset), + sqlc.arg(target_country) ); -- name: Sessions :many @@ -24,7 +26,7 @@ SELECT s.max_samples, s.max_duration_seconds, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips, s.last_sample_at, CAST(COALESCE(s.last_primary_ip::text, '') AS text) AS last_primary_ip, COALESCE(r.category, '') AS last_category, s.last_rtt_ms, s.last_error, - s.created_at, s.started_at, s.stopped_at, s.sequence_offset + s.created_at, s.started_at, s.stopped_at, s.sequence_offset, s.target_country FROM sampling_sessions AS s LEFT JOIN ip_reputation_cache AS r ON r.ip = s.last_primary_ip WHERE s.run_id IS NULL @@ -37,7 +39,7 @@ SELECT s.max_samples, s.max_duration_seconds, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips, s.last_sample_at, CAST(COALESCE(s.last_primary_ip::text, '') AS text) AS last_primary_ip, COALESCE(r.category, '') AS last_category, s.last_rtt_ms, s.last_error, - s.created_at, s.started_at, s.stopped_at, s.sequence_offset + s.created_at, s.started_at, s.stopped_at, s.sequence_offset, s.target_country FROM sampling_sessions AS s LEFT JOIN ip_reputation_cache AS r ON r.ip = s.last_primary_ip WHERE s.id = sqlc.arg(id); @@ -49,7 +51,7 @@ SELECT s.max_samples, s.max_duration_seconds, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips, s.last_sample_at, CAST(COALESCE(s.last_primary_ip::text, '') AS text) AS last_primary_ip, COALESCE(r.category, '') AS last_category, s.last_rtt_ms, s.last_error, - s.created_at, s.started_at, s.stopped_at, s.sequence_offset + s.created_at, s.started_at, s.stopped_at, s.sequence_offset, s.target_country FROM sampling_sessions AS s LEFT JOIN ip_reputation_cache AS r ON r.ip = s.last_primary_ip WHERE s.status = 'running' diff --git a/internal/db/runs.go b/internal/db/runs.go index 1c2e3f9..1b8454e 100644 --- a/internal/db/runs.go +++ b/internal/db/runs.go @@ -49,7 +49,7 @@ func (s *Store) CreateRun(ctx context.Context, run variation.Run, children []var LastSampleAt: base.LastSampleAt, LastPrimaryIp: base.LastPrimaryIp, LastRttMs: base.LastRttMs, LastError: base.LastError, CreatedAt: base.CreatedAt, StartedAt: base.StartedAt, StoppedAt: base.StoppedAt, SequenceOffset: base.SequenceOffset, - RunID: pgUUID(run.ID), VariantParams: child.Params, CellKey: &cellKey, + TargetCountry: base.TargetCountry, RunID: pgUUID(run.ID), VariantParams: child.Params, CellKey: &cellKey, }); err != nil { return fmt.Errorf("insert run session: %w", err) } @@ -108,7 +108,7 @@ func (s *Store) RunSessions(ctx context.Context, id uuid.UUID) ([]variation.Vari for _, row := range rows { result = append(result, variation.VariantSession{ SessionID: row.ID, Name: row.Name, Params: row.VariantParams, CellKey: row.CellKey, - Status: session.Status(row.Status), + TargetCountry: row.TargetCountry, Status: session.Status(row.Status), Snapshot: session.Snapshot{ SamplesTaken: int(row.SamplesTaken), ProbesOK: row.ProbesOk, ProbesTotal: row.ProbesTotal, DistinctIPs: int(row.DistinctIps), diff --git a/internal/db/runs.sql.go b/internal/db/runs.sql.go index 2b1ba8a..77212b1 100644 --- a/internal/db/runs.sql.go +++ b/internal/db/runs.sql.go @@ -57,7 +57,7 @@ INSERT INTO sampling_sessions ( max_samples, max_duration_seconds, status, samples_taken, probes_ok, probes_total, distinct_ips, last_sample_at, last_primary_ip, last_rtt_ms, last_error, created_at, started_at, stopped_at, sequence_offset, - run_id, variant_params, cell_key + target_country, run_id, variant_params, cell_key ) VALUES ( $1, $2, $3, $4, $5, $6, $7, @@ -68,7 +68,7 @@ INSERT INTO sampling_sessions ( NULLIF($19::text, '')::inet, $20, NULLIF($21::text, ''), $22, $23, $24, $25, - $26, $27, $28 + $26, $27, $28, $29 ) ` @@ -98,6 +98,7 @@ type InsertRunSessionParams struct { StartedAt pgtype.Timestamptz `json:"started_at"` StoppedAt pgtype.Timestamptz `json:"stopped_at"` SequenceOffset int32 `json:"sequence_offset"` + TargetCountry string `json:"target_country"` RunID pgtype.UUID `json:"run_id"` VariantParams []byte `json:"variant_params"` CellKey *string `json:"cell_key"` @@ -130,6 +131,7 @@ func (q *Queries) InsertRunSession(ctx context.Context, arg InsertRunSessionPara arg.StartedAt, arg.StoppedAt, arg.SequenceOffset, + arg.TargetCountry, arg.RunID, arg.VariantParams, arg.CellKey, @@ -286,7 +288,7 @@ func (q *Queries) RunIPObservations(ctx context.Context, arg RunIPObservationsPa const runSessions = `-- name: RunSessions :many SELECT s.id, s.name, COALESCE(s.variant_params, '{}'::jsonb) AS variant_params, - COALESCE(s.cell_key, '') AS cell_key, s.status, + COALESCE(s.cell_key, '') AS cell_key, s.target_country, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips FROM sampling_sessions AS s WHERE s.run_id = $1 @@ -298,6 +300,7 @@ type RunSessionsRow struct { Name string `json:"name"` VariantParams []byte `json:"variant_params"` CellKey string `json:"cell_key"` + TargetCountry string `json:"target_country"` Status string `json:"status"` SamplesTaken int32 `json:"samples_taken"` ProbesOk int64 `json:"probes_ok"` @@ -319,6 +322,7 @@ func (q *Queries) RunSessions(ctx context.Context, runID pgtype.UUID) ([]RunSess &i.Name, &i.VariantParams, &i.CellKey, + &i.TargetCountry, &i.Status, &i.SamplesTaken, &i.ProbesOk, diff --git a/internal/db/runs_integration_test.go b/internal/db/runs_integration_test.go index 86b7f4d..c9aec8c 100644 --- a/internal/db/runs_integration_test.go +++ b/internal/db/runs_integration_test.go @@ -53,6 +53,9 @@ func TestCreateRunPersistsChildren(t *testing.T) { if len(sessions) != 1 || sessions[0].CellKey != `{"country":"de"}` { t.Fatalf("run sessions = %#v", sessions) } + if sessions[0].TargetCountry != "DE" { + t.Fatalf("run session target country = %q, want DE (from child session row)", sessions[0].TargetCountry) + } // Child is excluded from the standalone session list. standalone, err := sessionStore.Sessions(ctx) diff --git a/internal/db/sessions.sql.go b/internal/db/sessions.sql.go index ccf1773..59b6f35 100644 --- a/internal/db/sessions.sql.go +++ b/internal/db/sessions.sql.go @@ -46,7 +46,8 @@ INSERT INTO sampling_sessions ( cadence_seconds, probes_per_sample, probe_target, dial_timeout_ms, max_samples, max_duration_seconds, status, samples_taken, probes_ok, probes_total, distinct_ips, last_sample_at, last_primary_ip, last_rtt_ms, - last_error, created_at, started_at, stopped_at, sequence_offset + last_error, created_at, started_at, stopped_at, sequence_offset, + target_country ) VALUES ( $1, $2, $3, $4, $5, $6, $7, @@ -56,7 +57,8 @@ INSERT INTO sampling_sessions ( $17, $18, NULLIF($19::text, '')::inet, $20, NULLIF($21::text, ''), $22, - $23, $24, $25 + $23, $24, $25, + $26 ) ` @@ -86,6 +88,7 @@ type InsertSessionParams struct { StartedAt pgtype.Timestamptz `json:"started_at"` StoppedAt pgtype.Timestamptz `json:"stopped_at"` SequenceOffset int32 `json:"sequence_offset"` + TargetCountry string `json:"target_country"` } func (q *Queries) InsertSession(ctx context.Context, arg InsertSessionParams) error { @@ -115,6 +118,7 @@ func (q *Queries) InsertSession(ctx context.Context, arg InsertSessionParams) er arg.StartedAt, arg.StoppedAt, arg.SequenceOffset, + arg.TargetCountry, ) return err } @@ -155,7 +159,7 @@ SELECT s.max_samples, s.max_duration_seconds, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips, s.last_sample_at, CAST(COALESCE(s.last_primary_ip::text, '') AS text) AS last_primary_ip, COALESCE(r.category, '') AS last_category, s.last_rtt_ms, s.last_error, - s.created_at, s.started_at, s.stopped_at, s.sequence_offset + s.created_at, s.started_at, s.stopped_at, s.sequence_offset, s.target_country FROM sampling_sessions AS s LEFT JOIN ip_reputation_cache AS r ON r.ip = s.last_primary_ip WHERE s.status = 'running' @@ -189,6 +193,7 @@ type RunningSessionsRow struct { StartedAt pgtype.Timestamptz `json:"started_at"` StoppedAt pgtype.Timestamptz `json:"stopped_at"` SequenceOffset int32 `json:"sequence_offset"` + TargetCountry string `json:"target_country"` } func (q *Queries) RunningSessions(ctx context.Context) ([]RunningSessionsRow, error) { @@ -227,6 +232,7 @@ func (q *Queries) RunningSessions(ctx context.Context) ([]RunningSessionsRow, er &i.StartedAt, &i.StoppedAt, &i.SequenceOffset, + &i.TargetCountry, ); err != nil { return nil, err } @@ -245,7 +251,7 @@ SELECT s.max_samples, s.max_duration_seconds, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips, s.last_sample_at, CAST(COALESCE(s.last_primary_ip::text, '') AS text) AS last_primary_ip, COALESCE(r.category, '') AS last_category, s.last_rtt_ms, s.last_error, - s.created_at, s.started_at, s.stopped_at, s.sequence_offset + s.created_at, s.started_at, s.stopped_at, s.sequence_offset, s.target_country FROM sampling_sessions AS s LEFT JOIN ip_reputation_cache AS r ON r.ip = s.last_primary_ip WHERE s.id = $1 @@ -278,6 +284,7 @@ type SessionByIDRow struct { StartedAt pgtype.Timestamptz `json:"started_at"` StoppedAt pgtype.Timestamptz `json:"stopped_at"` SequenceOffset int32 `json:"sequence_offset"` + TargetCountry string `json:"target_country"` } func (q *Queries) SessionByID(ctx context.Context, id uuid.UUID) (SessionByIDRow, error) { @@ -310,6 +317,7 @@ func (q *Queries) SessionByID(ctx context.Context, id uuid.UUID) (SessionByIDRow &i.StartedAt, &i.StoppedAt, &i.SequenceOffset, + &i.TargetCountry, ) return i, err } @@ -409,7 +417,7 @@ SELECT s.max_samples, s.max_duration_seconds, s.status, s.samples_taken, s.probes_ok, s.probes_total, s.distinct_ips, s.last_sample_at, CAST(COALESCE(s.last_primary_ip::text, '') AS text) AS last_primary_ip, COALESCE(r.category, '') AS last_category, s.last_rtt_ms, s.last_error, - s.created_at, s.started_at, s.stopped_at, s.sequence_offset + s.created_at, s.started_at, s.stopped_at, s.sequence_offset, s.target_country FROM sampling_sessions AS s LEFT JOIN ip_reputation_cache AS r ON r.ip = s.last_primary_ip WHERE s.run_id IS NULL @@ -443,6 +451,7 @@ type SessionsRow struct { StartedAt pgtype.Timestamptz `json:"started_at"` StoppedAt pgtype.Timestamptz `json:"stopped_at"` SequenceOffset int32 `json:"sequence_offset"` + TargetCountry string `json:"target_country"` } func (q *Queries) Sessions(ctx context.Context) ([]SessionsRow, error) { @@ -481,6 +490,7 @@ func (q *Queries) Sessions(ctx context.Context) ([]SessionsRow, error) { &i.StartedAt, &i.StoppedAt, &i.SequenceOffset, + &i.TargetCountry, ); err != nil { return nil, err } diff --git a/internal/db/store.go b/internal/db/store.go index 35ad9f4..d7b726f 100644 --- a/internal/db/store.go +++ b/internal/db/store.go @@ -257,6 +257,7 @@ type sessionRow struct { StartedAt pgtype.Timestamptz StoppedAt pgtype.Timestamptz SequenceOffset int32 + TargetCountry string } func mapSession(row sessionRow) (session.Session, error) { @@ -273,7 +274,7 @@ func mapSession(row sessionRow) (session.Session, error) { MaxSamples: intPtr(row.MaxSamples), MaxDuration: secondsDurationPtr(row.MaxDurationSeconds), Status: session.Status(row.Status), CreatedAt: row.CreatedAt.Time, StartedAt: timePtr(row.StartedAt), StoppedAt: timePtr(row.StoppedAt), - SequenceOffset: int(row.SequenceOffset), + SequenceOffset: int(row.SequenceOffset), TargetCountry: row.TargetCountry, Snapshot: session.Snapshot{ SamplesTaken: int(row.SamplesTaken), ProbesOK: row.ProbesOK, ProbesTotal: row.ProbesTotal, DistinctIPs: int(row.DistinctIPs), LastSampleAt: timePtr(row.LastSampleAt), @@ -293,7 +294,7 @@ func mapSessionByIDRow(row SessionByIDRow) (session.Session, error) { DistinctIPs: row.DistinctIps, LastSampleAt: row.LastSampleAt, LastPrimaryIP: row.LastPrimaryIp, LastCategory: row.LastCategory, LastRTTMs: row.LastRttMs, LastError: row.LastError, CreatedAt: row.CreatedAt, StartedAt: row.StartedAt, StoppedAt: row.StoppedAt, - SequenceOffset: row.SequenceOffset, + SequenceOffset: row.SequenceOffset, TargetCountry: row.TargetCountry, }) } @@ -307,7 +308,7 @@ func mapSessionsRow(row SessionsRow) (session.Session, error) { DistinctIPs: row.DistinctIps, LastSampleAt: row.LastSampleAt, LastPrimaryIP: row.LastPrimaryIp, LastCategory: row.LastCategory, LastRTTMs: row.LastRttMs, LastError: row.LastError, CreatedAt: row.CreatedAt, StartedAt: row.StartedAt, StoppedAt: row.StoppedAt, - SequenceOffset: row.SequenceOffset, + SequenceOffset: row.SequenceOffset, TargetCountry: row.TargetCountry, }) } @@ -321,7 +322,7 @@ func mapRunningSessionsRow(row RunningSessionsRow) (session.Session, error) { DistinctIPs: row.DistinctIps, LastSampleAt: row.LastSampleAt, LastPrimaryIP: row.LastPrimaryIp, LastCategory: row.LastCategory, LastRTTMs: row.LastRttMs, LastError: row.LastError, CreatedAt: row.CreatedAt, StartedAt: row.StartedAt, StoppedAt: row.StoppedAt, - SequenceOffset: row.SequenceOffset, + SequenceOffset: row.SequenceOffset, TargetCountry: row.TargetCountry, }) } @@ -338,7 +339,7 @@ func insertSessionParams(value session.Session) InsertSessionParams { LastPrimaryIp: addrString(value.Snapshot.LastPrimaryIP), LastRttMs: durationMillisPtr(value.Snapshot.LastRTT), LastError: value.Snapshot.LastError, CreatedAt: timestamp(value.CreatedAt), StartedAt: timestampPtr(value.StartedAt), StoppedAt: timestampPtr(value.StoppedAt), - SequenceOffset: int32(value.SequenceOffset), + SequenceOffset: int32(value.SequenceOffset), TargetCountry: value.TargetCountry, } } diff --git a/internal/db/store_integration_test.go b/internal/db/store_integration_test.go index 9d21875..9615a63 100644 --- a/internal/db/store_integration_test.go +++ b/internal/db/store_integration_test.go @@ -359,7 +359,7 @@ func testSession() session.Session { Mode: session.ModeSticky, Cadence: 30 * time.Second, ProbesPerSample: 3, ProbeTarget: "https://example.com/trace", DialTimeout: 5 * time.Second, MaxSamples: &maxSamples, MaxDuration: &maxDuration, Status: session.StatusRunning, - CreatedAt: now, StartedAt: &started, + TargetCountry: "DE", CreatedAt: now, StartedAt: &started, } } @@ -370,6 +370,7 @@ func assertSession(t *testing.T, got, want session.Session) { got.Cadence != want.Cadence || got.ProbesPerSample != want.ProbesPerSample || got.ProbeTarget != want.ProbeTarget || got.DialTimeout != want.DialTimeout || !reflect.DeepEqual(got.MaxSamples, want.MaxSamples) || !reflect.DeepEqual(got.MaxDuration, want.MaxDuration) || got.Status != want.Status || + got.TargetCountry != want.TargetCountry || !got.CreatedAt.Equal(want.CreatedAt) || !timePtrEqual(got.StartedAt, want.StartedAt) || !timePtrEqual(got.StoppedAt, want.StoppedAt) { t.Fatalf("session mismatch\n got: %#v\nwant: %#v", got, want) diff --git a/internal/session/session.go b/internal/session/session.go index 8a32883..354c7e4 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -38,11 +38,16 @@ type Session struct { MaxSamples *int MaxDuration *time.Duration Status Status - SequenceOffset int - Snapshot Snapshot - CreatedAt time.Time - StartedAt *time.Time - StoppedAt *time.Time + // TargetCountry is a manually declared target country (ISO 3166-1 alpha-2, + // uppercase; empty = unset). It records intent the proxy config itself does + // not encode, and overrides any country parsed from the proxy username or a + // run's country axis when comparing requested vs observed egress. + TargetCountry string + SequenceOffset int + Snapshot Snapshot + CreatedAt time.Time + StartedAt *time.Time + StoppedAt *time.Time } type Snapshot struct { diff --git a/internal/variation/report.go b/internal/variation/report.go index 360063d..8b574e8 100644 --- a/internal/variation/report.go +++ b/internal/variation/report.go @@ -47,12 +47,17 @@ type IPRow struct { // CellReport summarizes one parameter cell (params minus random axes). type CellReport struct { - CellKey string - Params json.RawMessage - VariantCount int - DistinctIPs int - HonorRate *float64 - Composition Composition + CellKey string + Params json.RawMessage + // TargetCountry is the manual target the cell's honor rate was measured + // against, when one was set on the run. Params may still name a country + // axis value the override ignored, so reports must not present the honor + // rate as measuring the params country when this is set. + TargetCountry string + VariantCount int + DistinctIPs int + HonorRate *float64 + Composition Composition } // PoolReport is the aggregated, IP-deduped view over a whole run. @@ -164,13 +169,14 @@ func boolValue(value *bool) bool { return value != nil && *value } func buildHonorAndCells(variants []VariantSession, sessionObs map[uuid.UUID][]IPObservation) (*float64, []CellReport) { type cellAccum struct { - key string - params json.RawMessage - variantCount int - honored int - sampled int - ips map[netip.Addr]struct{} - composition Composition + key string + params json.RawMessage + targetCountry string + variantCount int + honored int + sampled int + ips map[netip.Addr]struct{} + composition Composition } order := []string{} cells := map[string]*cellAccum{} @@ -188,6 +194,11 @@ func buildHonorAndCells(variants []VariantSession, sessionObs map[uuid.UUID][]IP order = append(order, v.CellKey) } accum.variantCount++ + // All of a run's children share one manual target, so the first + // non-empty value is the cell's effective override. + if accum.targetCountry == "" { + accum.targetCountry = v.TargetCountry + } obs := sessionObs[v.SessionID] for _, o := range obs { if _, seen := accum.ips[o.IP]; !seen { @@ -202,7 +213,7 @@ func buildHonorAndCells(variants []VariantSession, sessionObs map[uuid.UUID][]IP // un-reputed variant as a mismatch. Observation presence — not the // per-run SamplesTaken counter, which a re-enable resets — drives this, // so already-observed variants survive a re-enable. - switch variantHonor(v.Params, obs) { + switch variantHonor(v.Params, v.TargetCountry, obs) { case honorMatch: accum.sampled++ accum.honored++ @@ -218,8 +229,8 @@ func buildHonorAndCells(variants []VariantSession, sessionObs map[uuid.UUID][]IP for _, key := range order { accum := cells[key] cell := CellReport{ - CellKey: accum.key, Params: accum.params, VariantCount: accum.variantCount, - DistinctIPs: len(accum.ips), Composition: accum.composition, + CellKey: accum.key, Params: accum.params, TargetCountry: accum.targetCountry, + VariantCount: accum.variantCount, DistinctIPs: len(accum.ips), Composition: accum.composition, } if accum.sampled > 0 { rate := float64(accum.honored) / float64(accum.sampled) @@ -249,11 +260,16 @@ const ( // observed values across the variant's IPs. It returns honorUnknown when there // is nothing to compare — no target, or no known observed value for the target // — so such variants can be excluded from the honor-rate denominator rather -// than silently counted as honored (100%) or as a mismatch. -func variantHonor(params json.RawMessage, obs []IPObservation) honorOutcome { +// than silently counted as honored (100%) or as a mismatch. A non-empty +// targetCountry (the manually declared target) overrides any country axis +// param. +func variantHonor(params json.RawMessage, targetCountry string, obs []IPObservation) honorOutcome { requested := map[string]string{} _ = json.Unmarshal(params, &requested) country := firstParam(requested, "country", "cc") + if targetCountry != "" { + country = targetCountry + } isp := firstParam(requested, "isp") if country == "" && isp == "" { return honorUnknown diff --git a/internal/variation/report_test.go b/internal/variation/report_test.go index 73a9944..7c9f167 100644 --- a/internal/variation/report_test.go +++ b/internal/variation/report_test.go @@ -143,6 +143,63 @@ func TestBuildPoolReportHonorISPTolerantMatch(t *testing.T) { } } +func TestBuildPoolReportHonorUsesTargetCountryWithoutAxis(t *testing.T) { + s1 := uuid.New() + // A run without a country axis can carry a manual target country; it drives + // the honor outcome exactly like a country axis param would. + variants := []VariantSession{ + {SessionID: s1, CellKey: `{}`, Params: json.RawMessage(`{"session":"abc"}`), TargetCountry: "de", Snapshot: session.Snapshot{SamplesTaken: 3}}, + } + obs := []IPObservation{{SessionID: s1, IP: netip.MustParseAddr("9.9.9.2"), HitCount: 3, Reputation: rep("DE", "", "residential")}} + report := BuildPoolReport(variants, obs) + if report.HonorRate == nil || *report.HonorRate != 1 { + t.Fatalf("honor rate = %v, want 1 (manual target de, observed DE)", report.HonorRate) + } +} + +func TestBuildPoolReportHonorTargetCountryMismatch(t *testing.T) { + s1 := uuid.New() + variants := []VariantSession{ + {SessionID: s1, CellKey: `{}`, Params: json.RawMessage(`{}`), TargetCountry: "jp", Snapshot: session.Snapshot{SamplesTaken: 2}}, + } + obs := []IPObservation{{SessionID: s1, IP: netip.MustParseAddr("9.9.9.3"), HitCount: 5, Reputation: rep("US", "", "datacenter")}} + report := BuildPoolReport(variants, obs) + if report.HonorRate == nil || *report.HonorRate != 0 { + t.Fatalf("honor rate = %v, want 0 (manual target jp, observed US)", report.HonorRate) + } +} + +func TestBuildPoolReportHonorTargetCountryOverridesAxis(t *testing.T) { + s1 := uuid.New() + // When both a country axis param and a manual target exist, the manual + // target wins (chosen semantics: manual overrides). + variants := []VariantSession{ + {SessionID: s1, CellKey: `{"country":"de"}`, Params: json.RawMessage(`{"country":"de"}`), TargetCountry: "us", Snapshot: session.Snapshot{SamplesTaken: 2}}, + } + obs := []IPObservation{{SessionID: s1, IP: netip.MustParseAddr("9.9.9.4"), HitCount: 4, Reputation: rep("DE", "", "residential")}} + report := BuildPoolReport(variants, obs) + if report.HonorRate == nil || *report.HonorRate != 0 { + t.Fatalf("honor rate = %v, want 0 (manual target us overrides axis de; observed DE)", report.HonorRate) + } + // The cell must disclose the target its honor rate was measured against — + // its params still say country=de, which the override just ignored. + if len(report.Cells) != 1 || report.Cells[0].TargetCountry != "us" { + t.Fatalf("cells = %+v, want one cell carrying target country us", report.Cells) + } +} + +func TestBuildPoolReportCellsCarryTargetCountryWithoutAxis(t *testing.T) { + s1 := uuid.New() + variants := []VariantSession{ + {SessionID: s1, CellKey: `{}`, Params: json.RawMessage(`{"session":"abc"}`), TargetCountry: "de", Snapshot: session.Snapshot{SamplesTaken: 1}}, + } + obs := []IPObservation{{SessionID: s1, IP: netip.MustParseAddr("9.9.9.5"), HitCount: 1, Reputation: rep("DE", "", "residential")}} + report := BuildPoolReport(variants, obs) + if len(report.Cells) != 1 || report.Cells[0].TargetCountry != "de" { + t.Fatalf("cells = %+v, want one cell carrying target country de", report.Cells) + } +} + func TestBuildPoolReportHonorUnknownWhenNoTarget(t *testing.T) { s1 := uuid.New() // A random/port-only variant targets no country or ISP, so its honor diff --git a/internal/variation/run.go b/internal/variation/run.go index 3782266..7ebfb57 100644 --- a/internal/variation/run.go +++ b/internal/variation/run.go @@ -56,8 +56,13 @@ type VariantSession struct { Name string Params json.RawMessage CellKey string - Status session.Status - Snapshot session.Snapshot + // TargetCountry is the manually declared target country (ISO 3166-1 + // alpha-2). When set it overrides any country axis param for honor + // evaluation; runs whose template encodes no country axis have no other + // requested-country signal. + TargetCountry string + Status session.Status + Snapshot session.Snapshot } // IPObservation is one child session observing one exit IP, with reputation. diff --git a/migrations/postgres/20260823090000_session_target_country.sql b/migrations/postgres/20260823090000_session_target_country.sql new file mode 100644 index 0000000..5c4878b --- /dev/null +++ b/migrations/postgres/20260823090000_session_target_country.sql @@ -0,0 +1,5 @@ +-- +goose Up +ALTER TABLE sampling_sessions ADD COLUMN target_country text NOT NULL DEFAULT ''; + +-- +goose Down +ALTER TABLE sampling_sessions DROP COLUMN target_country; diff --git a/web/dist/assets/index-NIa5ODC0.js b/web/dist/assets/index-D1U5YqHo.js similarity index 94% rename from web/dist/assets/index-NIa5ODC0.js rename to web/dist/assets/index-D1U5YqHo.js index 4944781..6fb913a 100644 --- a/web/dist/assets/index-NIa5ODC0.js +++ b/web/dist/assets/index-D1U5YqHo.js @@ -1,4 +1,4 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/session-page-BHtrUHcT.js","assets/risk-histogram-Bw31Zp4T.js","assets/run-page-SJdc0Mk9.js"])))=>i.map(i=>d[i]); +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/session-page-DwoLWZj3.js","assets/risk-histogram-dP0_I5OY.js","assets/run-page-CsK2gHGg.js"])))=>i.map(i=>d[i]); var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var u=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var ee=Array.isArray;function S(){}var C={H:null,A:null,T:null,S:null},w=Object.prototype.hasOwnProperty;function te(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function ne(e,t){return te(e.type,t,e.props)}function T(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function re(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ie=/\/+/g;function ae(e,t){return typeof e==`object`&&e&&e.key!=null?re(``+e.key):t.toString(36)}function oe(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(S,S):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function se(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,se(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+ae(e,0):a,ee(o)?(i=``,c!=null&&(i=c.replace(ie,`$&/`)+`/`),se(o,r,i,``,function(e){return e})):o!=null&&(T(o)&&(o=ne(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ie,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ee(e))for(var u=0;u{t.exports=u()})),f=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,ee||(ee=!0,T());else{var t=n(l);t!==null&&ae(x,t.startTime-e)}}var ee=!1,S=-1,C=5,w=-1;function te(){return g?!0:!(e.unstable_now()-wt&&te());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&ae(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?T():ee=!1}}}var T;if(typeof y==`function`)T=function(){y(ne)};else if(typeof MessageChannel<`u`){var re=new MessageChannel,ie=re.port2;re.port1.onmessage=ne,T=function(){ie.postMessage(null)}}else T=function(){_(ne,0)};function ae(t,n){S=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(S),S=-1):h=!0,ae(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,T()))),r},e.unstable_shouldYield=te,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),p=o(((e,t)=>{t.exports=f()})),m=o((e=>{var t=d();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=m()})),g=o((e=>{var t=p(),n=d(),r=h();function i(e){var t=`https://react.dev/errors/`+e;if(1fe||(e.current=de[fe],de[fe]=null,fe--)}function A(e,t){fe++,de[fe]=e.current,e.current=t}var pe=O(null),me=O(null),he=O(null),ge=O(null);function _e(e,t){switch(A(he,t),A(me,e),A(pe,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}k(pe),A(pe,e)}function ve(){k(pe),k(me),k(he)}function ye(e){e.memoizedState!==null&&A(ge,e);var t=pe.current,n=Hd(t,e.type);t!==n&&(A(me,e),A(pe,n))}function be(e){me.current===e&&(k(pe),k(me)),ge.current===e&&(k(ge),Qf._currentValue=ue)}var xe,Se;function Ce(e){if(xe===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);xe=t&&t[1]||``,Se=-1)`:-1i[2])return!0}r=r.parentNode}while(r&&r!==n.body);return!1},z_=function(e){return[e.scrollTop,e.scrollHeight,e.clientHeight]},B_=function(e){return[e.scrollLeft,e.scrollWidth,e.clientWidth]},V_=function(e,t){return e===`v`?I_(t):L_(t)},H_=function(e,t){return e===`v`?z_(t):B_(t)},U_=function(e,t){return e===`h`&&t===`rtl`?-1:1},W_=function(e,t,n,r,i){var a=U_(e,window.getComputedStyle(t).direction),o=a*r,s=n.target,c=t.contains(s),l=!1,u=o>0,d=0,f=0;do{if(!s)break;var p=H_(e,s),m=p[0],h=p[1]-p[2]-a*m;(m||h)&&V_(e,s)&&(d+=h,f+=m);var g=s.parentNode;s=g&&g.nodeType===Node.DOCUMENT_FRAGMENT_NODE?g.host:g}while(!c&&s!==document.body||c&&(t.contains(s)||t===s));return(u&&(i&&Math.abs(d)<1||!i&&o>d)||!u&&(i&&Math.abs(f)<1||!i&&-o>f))&&(l=!0),l},G_=function(e){return`changedTouches`in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]},K_=function(e){return[e.deltaX,e.deltaY]},q_=function(e){return e&&`current`in e?e.current:e},J_=function(e,t){return e[0]===t[0]&&e[1]===t[1]},Y_=function(e){return` .block-interactivity-${e} {pointer-events: none;} .allow-interactivity-${e} {pointer-events: all;} -`},X_=0,Z_=[];function Q_(e){var t=j.useRef([]),n=j.useRef([0,0]),r=j.useRef(),i=j.useState(X_++)[0],a=j.useState(b_)[0],o=j.useRef(e);j.useEffect(function(){o.current=e},[e]),j.useEffect(function(){if(e.inert){document.body.classList.add(`block-interactivity-${i}`);var t=Yg([e.lockRef.current],(e.shards||[]).map(q_),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add(`allow-interactivity-${i}`)}),function(){document.body.classList.remove(`block-interactivity-${i}`),t.forEach(function(e){return e.classList.remove(`allow-interactivity-${i}`)})}}},[e.inert,e.lockRef.current,e.shards]);var s=j.useCallback(function(e,t){if(`touches`in e&&e.touches.length===2||e.type===`wheel`&&e.ctrlKey)return!o.current.allowPinchZoom;var i=G_(e),a=n.current,s=`deltaX`in e?e.deltaX:a[0]-i[0],c=`deltaY`in e?e.deltaY:a[1]-i[1],l,u=e.target,d=Math.abs(s)>Math.abs(c)?`h`:`v`;if(`touches`in e&&d===`h`&&u.type===`range`)return!1;var f=window.getSelection(),p=f&&f.anchorNode;if(p&&(p===u||p.contains(u)))return!1;var m=R_(d,u);if(!m)return!0;if(m?l=d:(l=d===`v`?`h`:`v`,m=R_(d,u)),!m)return!1;if(!r.current&&`changedTouches`in e&&(s||c)&&(r.current=l),!l)return!0;var h=r.current||l;return W_(h,t,e,h===`h`?s:c,!0)},[]),c=j.useCallback(function(e){var n=e;if(!(!Z_.length||Z_[Z_.length-1]!==a)){var r=`deltaY`in n?K_(n):G_(n),i=t.current.filter(function(e){return e.name===n.type&&(e.target===n.target||n.target===e.shadowParent)&&J_(e.delta,r)})[0];if(i&&i.should){n.cancelable&&n.preventDefault();return}if(!i){var c=(o.current.shards||[]).map(q_).filter(Boolean).filter(function(e){return e.contains(n.target)});(c.length>0?s(n,c[0]):!o.current.noIsolation)&&n.cancelable&&n.preventDefault()}}},[]),l=j.useCallback(function(e,n,r,i){var a={name:e,delta:n,target:r,should:i,shadowParent:$_(r)};t.current.push(a),setTimeout(function(){t.current=t.current.filter(function(e){return e!==a})},1)},[]),u=j.useCallback(function(e){n.current=G_(e),r.current=void 0},[]),d=j.useCallback(function(t){l(t.type,K_(t),t.target,s(t,e.lockRef.current))},[]),f=j.useCallback(function(t){l(t.type,G_(t),t.target,s(t,e.lockRef.current))},[]);j.useEffect(function(){return Z_.push(a),e.setCallbacks({onScrollCapture:d,onWheelCapture:d,onTouchMoveCapture:f}),document.addEventListener(`wheel`,c,N_),document.addEventListener(`touchmove`,c,N_),document.addEventListener(`touchstart`,u,N_),function(){Z_=Z_.filter(function(e){return e!==a}),document.removeEventListener(`wheel`,c,N_),document.removeEventListener(`touchmove`,c,N_),document.removeEventListener(`touchstart`,u,N_)}},[]);var p=e.removeScrollBar,m=e.inert;return j.createElement(j.Fragment,null,m?j.createElement(a,{styles:Y_(i)}):null,p?j.createElement(A_,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function $_(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}var ev=l_(u_,Q_),tv=j.forwardRef(function(e,t){return j.createElement(f_,qg({},e,{ref:t,sideCar:ev}))});tv.classNames=f_.classNames;var nv=function(e){return typeof document>`u`?null:(Array.isArray(e)?e[0]:e).ownerDocument.body},rv=new WeakMap,iv=new WeakMap,av={},ov=0,sv=function(e){return e&&(e.host||sv(e.parentNode))},cv=function(e,t){return t.map(function(t){if(e.contains(t))return t;var n=sv(t);return n&&e.contains(n)?n:(console.error(`aria-hidden`,t,`in not contained inside`,e,`. Doing nothing`),null)}).filter(function(e){return!!e})},lv=function(e,t,n,r){var i=cv(t,Array.isArray(e)?e:[e]);av[n]||(av[n]=new WeakMap);var a=av[n],o=[],s=new Set,c=new Set(i),l=function(e){!e||s.has(e)||(s.add(e),l(e.parentNode))};i.forEach(l);var u=function(e){!e||c.has(e)||Array.prototype.forEach.call(e.children,function(e){if(s.has(e))u(e);else try{var t=e.getAttribute(r),i=t!==null&&t!==`false`,c=(rv.get(e)||0)+1,l=(a.get(e)||0)+1;rv.set(e,c),a.set(e,l),o.push(e),c===1&&i&&iv.set(e,!0),l===1&&e.setAttribute(n,`true`),i||e.setAttribute(r,`true`)}catch(t){console.error(`aria-hidden: cannot operate on `,e,t)}})};return u(t),s.clear(),ov++,function(){o.forEach(function(e){var t=rv.get(e)-1,i=a.get(e)-1;rv.set(e,t),a.set(e,i),t||(iv.has(e)||e.removeAttribute(r),iv.delete(e)),i||e.removeAttribute(n)}),ov--,ov||(rv=new WeakMap,rv=new WeakMap,iv=new WeakMap,av={})}},uv=function(e,t,n){n===void 0&&(n=`data-aria-hidden`);var r=Array.from(Array.isArray(e)?e:[e]),i=t||nv(e);return i?(r.push.apply(r,Array.from(i.querySelectorAll(`[aria-live], script`))),lv(r,i,n,`aria-hidden`)):function(){return null}},dv=Object.defineProperty,fv=(e,t)=>dv(e,`name`,{value:t,configurable:!0}),pv=`Dialog`,[mv,hv]=$m(pv),[gv,_v]=mv(pv),vv=fv(e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!0}=e,s=j.useRef(null),c=j.useRef(null),[l,u]=ch({prop:r,defaultProp:i??!1,onChange:a,caller:pv}),[d,f]=j.useState(0),[p,m]=j.useState(0);return(0,M.jsx)(gv,{scope:t,triggerRef:s,contentRef:c,contentId:Hh(),titleId:Hh(),descriptionId:Hh(),titlePresent:d>0,descriptionPresent:p>0,setTitleCount:f,setDescriptionCount:m,open:l,onOpenChange:u,onOpenToggle:j.useCallback(()=>u(e=>!e),[u]),modal:o,children:n})},`Dialog`),yv=`DialogPortal`,[bv,xv]=mv(yv,{forceMount:void 0}),Sv=fv(e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=_v(yv,t);return(0,M.jsx)(bv,{scope:t,forceMount:n,children:j.Children.map(r,e=>(0,M.jsx)(Ph,{present:n||a.open,children:(0,M.jsx)(Hg,{asChild:!0,container:i,children:e})}))})},`DialogPortal`),Cv=`DialogOverlay`,wv=j.forwardRef(fv(function(e,t){let n=xv(Cv,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=_v(Cv,e.__scopeDialog);return a.modal?(0,M.jsx)(Ph,{present:r||a.open,children:(0,M.jsx)(Ev,{...i,ref:t})}):null},`DialogOverlay`)),Tv=gh(`DialogOverlay.RemoveScroll`),Ev=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Cv,n),a=hh(t,vg());return(0,M.jsx)(tv,{as:Tv,allowPinchZoom:!0,shards:[i.contentRef],children:(0,M.jsx)(kh.div,{"data-state":Rv(i.open),...r,ref:a,style:{pointerEvents:`auto`,...r.style}})})},`DialogOverlayImpl`)),Dv=`DialogContent`,Ov=j.forwardRef(fv(function(e,t){let n=xv(Dv,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=_v(Dv,e.__scopeDialog);return(0,M.jsx)(Ph,{present:r||a.open,children:a.modal?(0,M.jsx)(kv,{...i,ref:t}):(0,M.jsx)(Av,{...i,ref:t})})},`DialogContent`)),kv=j.forwardRef(fv(function(e,t){let n=_v(Dv,e.__scopeDialog),r=j.useRef(null),i=hh(t,n.contentRef,r);return j.useEffect(()=>{let e=r.current;if(e)return uv(e)},[]),(0,M.jsx)(jv,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:n.open,onCloseAutoFocus:Jm(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:Jm(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:Jm(e.onFocusOutside,e=>e.preventDefault())})},`DialogContentModal`)),Av=j.forwardRef(fv(function(e,t){let n=_v(Dv,e.__scopeDialog),r=j.useRef(!1),i=j.useRef(!1);return(0,M.jsx)(jv,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})},`DialogContentNonModal`)),jv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,...o}=e,s=_v(Dv,n);return Gg(),(0,M.jsx)(M.Fragment,{children:(0,M.jsx)(kg,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,M.jsx)(_g,{role:`dialog`,id:s.contentId,"aria-describedby":s.descriptionPresent?s.descriptionId:void 0,"aria-labelledby":s.titlePresent?s.titleId:void 0,"data-state":Rv(s.open),...o,ref:t,deferPointerDownOutside:!0,onDismiss:()=>s.onOpenChange(!1)})})})},`DialogContentImpl`)),Mv=`DialogTitle`,Nv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Mv,n),{setTitleCount:a}=i;return th(()=>(a(e=>e+1),()=>a(e=>e-1)),[a]),(0,M.jsx)(kh.h2,{id:i.titleId,...r,ref:t})},`DialogTitle`)),Pv=`DialogDescription`,Fv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Pv,n),{setDescriptionCount:a}=i;return th(()=>(a(e=>e+1),()=>a(e=>e-1)),[a]),(0,M.jsx)(kh.p,{id:i.descriptionId,...r,ref:t})},`DialogDescription`)),Iv=`DialogClose`,Lv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Iv,n);return(0,M.jsx)(kh.button,{type:`button`,...r,ref:t,onClick:Jm(e.onClick,()=>i.onOpenChange(!1))})},`DialogClose`));function Rv(e){return e?`open`:`closed`}fv(Rv,`getState`);var zv=vv,Bv=Nv,Vv=Fv,Hv=(0,j.forwardRef)(({className:e,children:t,closeDisabled:n,...r},i)=>(0,M.jsxs)(Sv,{children:[(0,M.jsx)(wv,{className:`dialog-overlay`}),(0,M.jsxs)(Ov,{ref:i,className:Go(`dialog-content`,e),...r,children:[t,(0,M.jsx)(Lv,{className:`dialog-x`,"aria-label":`Close dialog`,disabled:n,children:(0,M.jsx)(Ji,{"aria-hidden":`true`,size:18})})]})]}));Hv.displayName=`DialogContent`;var Uv=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`input`,{ref:n,className:Go(`input`,e),...t}));Uv.displayName=`Input`;var Wv=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`label`,{ref:n,className:Go(`label`,e),...t}));Wv.displayName=`Label`;var Gv=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`select`,{ref:n,className:Go(`select`,e),...t}));Gv.displayName=`Select`;var Kv=/^[1-9]\d*$/,qv=/^\d+$/,Jv=fm({name:Rp().trim().min(1,`Axis name is required`),kind:vm([`list`,`range`,`random`]),values:Rp(),from:Rp(),to:Rp(),count:Rp(),length:Rp()}).superRefine((e,t)=>{e.kind===`list`?ty(e.values).length<1&&t.addIssue({code:`custom`,path:[`values`],message:`Add at least one value`}):e.kind===`range`?(qv.test(e.from)||t.addIssue({code:`custom`,path:[`from`],message:`Enter a whole number`}),qv.test(e.to)||t.addIssue({code:`custom`,path:[`to`],message:`Enter a whole number`}),qv.test(e.from)&&qv.test(e.to)&&Number(e.to)e===`sticky`||e===`pool`,`Choose a sampling mode`),cadence:Rp().regex(Kv,`Cadence must be a positive integer`),axes:um(Jv).min(1,`Add at least one axis`).superRefine((e,t)=>{let n=new Set;e.forEach((e,r)=>{let i=e.name.trim();i!==``&&(n.has(i)?t.addIssue({code:`custom`,message:`Axis names must be unique`,path:[r,`name`]}):n.add(i))})}),probes:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`).refine(e=>e===``||Number(e)<=255,`Probes cannot exceed 255`),probeTarget:Rp().refine(e=>e===``||ry(e),`Enter an HTTP or HTTPS URL`),dialTimeout:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`).refine(e=>e===``||Number(e)>=100,`Timeout must be at least 100 ms`),maxSamples:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`),maxDuration:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`)}),Xv={name:``,kind:`list`,values:``,from:``,to:``,count:``,length:``},Zv={name:``,template:``,mode:``,cadence:`30`,axes:[],probes:``,probeTarget:``,dialTimeout:``,maxSamples:``,maxDuration:``};function Qv({open:e,onClose:t}){let n=da(),r=sa().data?.max_variants_per_run??128,[i,a]=(0,j.useState)(!1),[o,s]=(0,j.useState)(null),c=zc({resolver:dp(Yv),defaultValues:Zv}),l=cc({control:c.control,name:`axes`}),u=Ts({control:c.control,name:`axes`})??[],d=Hm(ny(u)),f=d>r,p=e=>{n.isPending||e||(c.reset(Zv),a(!1),s(null),n.reset(),t())},m=c.handleSubmit(async e=>{if(f)return;s(null);let t={name:e.name.trim(),template:e.template,axes:ny(e.axes),mode:e.mode,cadence_seconds:Number(e.cadence),...e.probes?{probes_per_sample:Number(e.probes)}:{},...e.probeTarget?{probe_target:e.probeTarget}:{},...e.dialTimeout?{dial_timeout_ms:Number(e.dialTimeout)}:{},...e.maxSamples?{max_samples:Number(e.maxSamples)}:{},...e.maxDuration?{max_duration_seconds:Number(e.maxDuration)}:{}};try{await n.mutateAsync(t),p(!1)}catch(e){s(e instanceof Yi?e.message:`The run could not be started. Try again.`)}finally{n.reset()}});return(0,M.jsx)(zv,{open:e,onOpenChange:p,children:(0,M.jsxs)(Hv,{"aria-describedby":`new-run-description`,closeDisabled:n.isPending,onEscapeKeyDown:e=>{n.isPending&&e.preventDefault()},onPointerDownOutside:e=>{n.isPending&&e.preventDefault()},children:[(0,M.jsxs)(`div`,{className:`dialog-heading`,children:[(0,M.jsx)(Bv,{children:`New parameter-variation run`}),(0,M.jsx)(Vv,{id:`new-run-description`,children:`Expand a proxy template across one or more axes and sample every resulting variant.`})]}),(0,M.jsxs)(`form`,{onSubmit:m,noValidate:!0,children:[o&&(0,M.jsx)(Wm,{className:`form-alert`,children:o}),(0,M.jsxs)(`fieldset`,{disabled:n.isPending,className:`form-fields`,children:[(0,M.jsx)(ey,{label:`Run name`,error:c.formState.errors.name?.message,children:(0,M.jsx)(Uv,{autoFocus:!0,id:`run-name`,placeholder:`Experiment name`,...c.register(`name`)})}),(0,M.jsx)(ey,{label:`Proxy template`,error:c.formState.errors.template?.message,hint:`Use {axis_name} placeholders, e.g. socks5h://u-cc-{country}:pw@gate:1080`,children:(0,M.jsx)(Uv,{id:`proxy-template`,spellCheck:!1,placeholder:`socks5h://u-cc-{country}:pw@gate:1080`,...c.register(`template`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(Ds,{control:c.control,name:`mode`,render:({field:e,fieldState:t})=>(0,M.jsx)(ey,{label:`Sampling mode`,error:t.error?.message,children:(0,M.jsxs)(Gv,{id:`sampling-mode`,...e,children:[(0,M.jsx)(`option`,{value:``,children:`Select mode`}),(0,M.jsx)(`option`,{value:`sticky`,children:`Sticky`}),(0,M.jsx)(`option`,{value:`pool`,children:`Pool`})]})})}),(0,M.jsx)(ey,{label:`Cadence (seconds)`,error:c.formState.errors.cadence?.message,children:(0,M.jsx)(Uv,{id:`cadence`,type:`number`,min:`1`,inputMode:`numeric`,...c.register(`cadence`)})})]}),(0,M.jsxs)(`div`,{className:`axes-builder`,children:[(0,M.jsxs)(`div`,{className:`axes-builder-heading`,children:[(0,M.jsx)(`span`,{className:`label`,children:`Axes`}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,size:`small`,onClick:()=>l.append({...Xv}),children:[(0,M.jsx)(Ui,{"aria-hidden":`true`,size:14}),` Add axis`]})]}),c.formState.errors.axes?.root?.message&&(0,M.jsx)(`p`,{className:`field-error`,role:`alert`,children:c.formState.errors.axes.root.message}),l.fields.length===0&&(0,M.jsx)(`p`,{className:`field-hint`,children:`No axes yet. Add at least one to expand this run into variants.`}),l.fields.map((e,t)=>(0,M.jsx)($v,{index:t,form:c,kind:u[t]?.kind??`list`,onRemove:()=>l.remove(t)},e.id)),(0,M.jsxs)(`p`,{className:f?`field-error`:`field-hint`,role:f?`alert`:void 0,children:[d,` variants`,f?` — exceeds the maximum of ${r}. Remove or narrow an axis.`:``]})]}),(0,M.jsxs)(og,{open:i,onOpenChange:a,className:`advanced-settings`,children:[(0,M.jsx)(sg,{asChild:!0,children:(0,M.jsxs)(qo,{type:`button`,variant:`quiet`,className:`advanced-trigger`,"aria-expanded":i,children:[`Advanced settings `,(0,M.jsx)(Vi,{"aria-hidden":`true`,className:i?`rotate`:void 0,size:16})]})}),(0,M.jsxs)(cg,{className:`advanced-content`,children:[(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Probes per sample (optional)`,error:c.formState.errors.probes?.message,children:(0,M.jsx)(Uv,{id:`probes`,type:`number`,min:`1`,max:`255`,inputMode:`numeric`,...c.register(`probes`)})}),(0,M.jsx)(ey,{label:`Dial timeout (milliseconds, optional)`,error:c.formState.errors.dialTimeout?.message,children:(0,M.jsx)(Uv,{id:`dial-timeout`,type:`number`,min:`100`,inputMode:`numeric`,...c.register(`dialTimeout`)})})]}),(0,M.jsx)(ey,{label:`Probe target URL (optional)`,error:c.formState.errors.probeTarget?.message,children:(0,M.jsx)(Uv,{id:`probe-target`,type:`url`,spellCheck:!1,...c.register(`probeTarget`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Maximum samples (optional)`,error:c.formState.errors.maxSamples?.message,children:(0,M.jsx)(Uv,{id:`max-samples`,type:`number`,min:`1`,inputMode:`numeric`,...c.register(`maxSamples`)})}),(0,M.jsx)(ey,{label:`Maximum duration (seconds, optional)`,error:c.formState.errors.maxDuration?.message,children:(0,M.jsx)(Uv,{id:`max-duration`,type:`number`,min:`1`,inputMode:`numeric`,...c.register(`maxDuration`)})})]})]})]})]}),(0,M.jsxs)(`div`,{className:`dialog-actions`,children:[(0,M.jsx)(qo,{type:`button`,variant:`quiet`,disabled:n.isPending,onClick:()=>p(!1),children:`Cancel`}),(0,M.jsx)(qo,{type:`submit`,variant:`primary`,disabled:n.isPending||f,children:n.isPending?(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(Hi,{className:`spin`,"aria-hidden":`true`,size:16}),` Starting run…`]}):`Start run`})]})]})]})})}function $v({index:e,form:t,kind:n,onRemove:r}){let i=e+1,a=t.formState.errors.axes?.[e];return(0,M.jsxs)(`div`,{className:`axis-row`,children:[(0,M.jsxs)(`div`,{className:`axis-row-fields`,children:[(0,M.jsx)(ey,{label:`Axis ${i} name`,error:a?.name?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-name`,placeholder:`country`,...t.register(`axes.${e}.name`)})}),(0,M.jsx)(ey,{label:`Axis ${i} kind`,children:(0,M.jsxs)(Gv,{id:`axis-${i}-kind`,...t.register(`axes.${e}.kind`),children:[(0,M.jsx)(`option`,{value:`list`,children:`List`}),(0,M.jsx)(`option`,{value:`range`,children:`Range`}),(0,M.jsx)(`option`,{value:`random`,children:`Random`})]})}),n===`list`&&(0,M.jsx)(ey,{label:`Axis ${i} values`,error:a?.values?.message,hint:`Comma-separated`,children:(0,M.jsx)(Uv,{id:`axis-${i}-values`,placeholder:`de, us, fr, jp`,...t.register(`axes.${e}.values`)})}),n===`range`&&(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Axis ${i} from`,error:a?.from?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-from`,type:`number`,inputMode:`numeric`,...t.register(`axes.${e}.from`)})}),(0,M.jsx)(ey,{label:`Axis ${i} to`,error:a?.to?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-to`,type:`number`,inputMode:`numeric`,...t.register(`axes.${e}.to`)})})]}),n===`random`&&(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Axis ${i} count`,error:a?.count?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-count`,type:`number`,min:`1`,inputMode:`numeric`,...t.register(`axes.${e}.count`)})}),(0,M.jsx)(ey,{label:`Axis ${i} length (optional)`,error:a?.length?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-length`,type:`number`,min:`1`,inputMode:`numeric`,...t.register(`axes.${e}.length`)})})]})]}),(0,M.jsxs)(qo,{type:`button`,variant:`quiet`,size:`small`,onClick:r,children:[(0,M.jsx)(Ki,{"aria-hidden":`true`,size:14}),` Remove axis`]})]})}function ey({label:e,error:t,hint:n,children:r}){let i=r.props.id,a=n&&i?`${i}-hint`:void 0,o=t&&i?`${i}-error`:void 0,s=(0,j.cloneElement)(r,{"aria-invalid":t?!0:void 0,"aria-describedby":[a,o].filter(Boolean).join(` `)||void 0});return(0,M.jsxs)(`div`,{className:`field`,children:[(0,M.jsx)(Wv,{htmlFor:i,children:e}),s,n&&(0,M.jsx)(`p`,{className:`field-hint`,id:a,children:n}),t&&(0,M.jsx)(`p`,{className:`field-error`,id:o,role:`alert`,children:t})]})}function ty(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function ny(e){let t={};for(let n of e){let e=n?.name?.trim();if(e)if(n?.kind===`range`){let r=Number(n.from),i=Number(n.to);if(n.from===``||n.to===``||Number.isNaN(r)||Number.isNaN(i))continue;t[e]={kind:`range`,from:r,to:i}}else if(n?.kind===`random`){let r=Number(n.count);if(n.count===``||Number.isNaN(r))continue;let i=n.length?Number(n.length):void 0;t[e]={kind:`random`,count:r,...i!==void 0&&!Number.isNaN(i)?{length:i}:{}}}else t[e]={kind:`list`,values:ty(n?.values??``)}}return t}function ry(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}var iy=/^[1-9]\d*$/,ay=fm({name:Rp().trim().min(1,`Name is required`).max(100,`Name must be 100 characters or fewer`),proxy:Rp().min(1,`Proxy connection string is required`),mode:Rp().refine(e=>e===`sticky`||e===`pool`,`Choose a sampling mode`),cadence:Rp().regex(iy,`Cadence must be a positive integer`),probes:Rp().regex(iy,`Probes must be a positive integer`).refine(e=>Number(e)<=255,`Probes cannot exceed 255`),probeTarget:Rp().refine(e=>e===``||ly(e),`Enter an HTTP or HTTPS URL`),dialTimeout:Rp().regex(iy,`Timeout must be a positive integer`).refine(e=>Number(e)>=100,`Timeout must be at least 100 ms`),maxSamples:Rp().refine(e=>e===``||iy.test(e),`Enter a positive integer or leave blank`),maxDuration:Rp().refine(e=>e===``||iy.test(e),`Enter a positive integer or leave blank`)}),oy={name:``,proxy:``,mode:``,cadence:`30`,probes:``,probeTarget:`https://speed.cloudflare.com/cdn-cgi/trace`,dialTimeout:`10000`,maxSamples:``,maxDuration:``};function sy({open:e,onOpenChange:t}){let n=qn(),r=ia(),i=(0,j.useRef)(!1),[a,o]=(0,j.useState)(!1),[s,c]=(0,j.useState)(null),l=zc({resolver:dp(ay),defaultValues:oy}),u=e=>{r.isPending||(e||(l.reset(oy),i.current=!1,o(!1),c(null),r.reset()),t(e))},d=l.handleSubmit(async e=>{c(null);let t={name:e.name.trim(),proxy:e.proxy,mode:e.mode,cadence_seconds:Number(e.cadence),probes_per_sample:Number(e.probes),...e.probeTarget?{probe_target:e.probeTarget}:{},...e.dialTimeout?{dial_timeout_ms:Number(e.dialTimeout)}:{},...e.maxSamples?{max_samples:Number(e.maxSamples)}:{},...e.maxDuration?{max_duration_seconds:Number(e.maxDuration)}:{}};l.resetField(`proxy`,{defaultValue:``});try{let e=await r.mutateAsync(t);u(!1),n(`/sessions/${e.id}`)}catch(e){c(e instanceof Yi?e.message:`The session could not be started. Try again.`)}finally{r.reset()}});return(0,M.jsx)(zv,{open:e,onOpenChange:u,children:(0,M.jsxs)(Hv,{"aria-describedby":`new-session-description`,closeDisabled:r.isPending,onEscapeKeyDown:e=>{r.isPending&&e.preventDefault()},onPointerDownOutside:e=>{r.isPending&&e.preventDefault()},children:[(0,M.jsxs)(`div`,{className:`dialog-heading`,children:[(0,M.jsx)(Bv,{children:`New sampling session`}),(0,M.jsx)(Vv,{id:`new-session-description`,children:`Start a durable measurement run against one proxy endpoint.`})]}),(0,M.jsxs)(`form`,{onSubmit:d,noValidate:!0,children:[s&&(0,M.jsx)(Wm,{className:`form-alert`,children:s}),(0,M.jsxs)(`fieldset`,{disabled:r.isPending,className:`form-fields`,children:[(0,M.jsx)(cy,{label:`Session name`,error:l.formState.errors.name?.message,children:(0,M.jsx)(Uv,{autoFocus:!0,id:`session-name`,placeholder:`Provider or endpoint name`,...l.register(`name`)})}),(0,M.jsx)(cy,{label:`Proxy connection string`,error:l.formState.errors.proxy?.message,hint:`Supports socks5h:// and http:// connection strings.`,children:(0,M.jsx)(Uv,{id:`proxy-connection-string`,type:`password`,autoComplete:`off`,spellCheck:!1,placeholder:`socks5h://user:password@host:port`,...l.register(`proxy`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(Ds,{control:l.control,name:`mode`,render:({field:e,fieldState:t})=>(0,M.jsx)(cy,{label:`Sampling mode`,error:t.error?.message,children:(0,M.jsxs)(Gv,{id:`sampling-mode`,...e,onChange:t=>{e.onChange(t),i.current||l.setValue(`probes`,t.target.value===`pool`?`8`:t.target.value===`sticky`?`3`:``,{shouldValidate:!0})},children:[(0,M.jsx)(`option`,{value:``,children:`Select mode`}),(0,M.jsx)(`option`,{value:`sticky`,children:`Sticky`}),(0,M.jsx)(`option`,{value:`pool`,children:`Pool`})]})})}),(0,M.jsx)(cy,{label:`Cadence (seconds)`,error:l.formState.errors.cadence?.message,children:(0,M.jsx)(Uv,{id:`cadence`,type:`number`,min:`1`,inputMode:`numeric`,...l.register(`cadence`)})}),(0,M.jsx)(cy,{label:`Probes per sample`,error:l.formState.errors.probes?.message,children:(0,M.jsx)(Uv,{id:`probes`,type:`number`,min:`1`,max:`255`,inputMode:`numeric`,...l.register(`probes`,{onChange:()=>{i.current=!0}})})})]}),(0,M.jsxs)(og,{open:a,onOpenChange:o,className:`advanced-settings`,children:[(0,M.jsx)(sg,{asChild:!0,children:(0,M.jsxs)(qo,{type:`button`,variant:`quiet`,className:`advanced-trigger`,"aria-expanded":a,children:[`Advanced settings `,(0,M.jsx)(Vi,{"aria-hidden":`true`,className:a?`rotate`:void 0,size:16})]})}),(0,M.jsxs)(cg,{className:`advanced-content`,children:[(0,M.jsx)(cy,{label:`Probe target URL`,error:l.formState.errors.probeTarget?.message,children:(0,M.jsx)(Uv,{id:`probe-target`,type:`url`,spellCheck:!1,...l.register(`probeTarget`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(cy,{label:`Dial timeout (milliseconds)`,error:l.formState.errors.dialTimeout?.message,children:(0,M.jsx)(Uv,{id:`dial-timeout`,type:`number`,min:`100`,inputMode:`numeric`,...l.register(`dialTimeout`)})}),(0,M.jsx)(cy,{label:`Maximum samples (optional)`,error:l.formState.errors.maxSamples?.message,children:(0,M.jsx)(Uv,{id:`max-samples`,type:`number`,min:`1`,inputMode:`numeric`,...l.register(`maxSamples`)})}),(0,M.jsx)(cy,{label:`Maximum duration (seconds, optional)`,error:l.formState.errors.maxDuration?.message,children:(0,M.jsx)(Uv,{id:`max-duration`,type:`number`,min:`1`,inputMode:`numeric`,...l.register(`maxDuration`)})})]})]})]})]}),(0,M.jsxs)(`div`,{className:`dialog-actions`,children:[(0,M.jsx)(qo,{type:`button`,variant:`quiet`,disabled:r.isPending,onClick:()=>u(!1),children:`Cancel`}),(0,M.jsx)(qo,{type:`submit`,variant:`primary`,disabled:r.isPending,children:r.isPending?(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(Hi,{className:`spin`,"aria-hidden":`true`,size:16}),` Starting session…`]}):`Start session`})]})]})]})})}function cy({label:e,error:t,hint:n,children:r}){let i=r.props.id,a=n&&i?`${i}-hint`:void 0,o=t&&i?`${i}-error`:void 0,s=(0,j.cloneElement)(r,{"aria-invalid":t?!0:void 0,"aria-describedby":[a,o].filter(Boolean).join(` `)||void 0});return(0,M.jsxs)(`div`,{className:`field`,children:[(0,M.jsx)(Wv,{htmlFor:i,children:e}),s,n&&(0,M.jsx)(`p`,{className:`field-hint`,id:a,children:n}),t&&(0,M.jsx)(`p`,{className:`field-error`,id:o,role:`alert`,children:t})]})}function ly(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function uy(e){return new Intl.NumberFormat(void 0,{style:`percent`,maximumFractionDigits:1}).format(e)}function dy(e){return e==null||!Number.isFinite(e)?`—`:`${new Intl.NumberFormat().format(e)} ms`}function fy(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`}).format(t)}function py(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:new Intl.DateTimeFormat(void 0,{year:`numeric`,month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`}).format(t)}function my(e){if(!Number.isFinite(e)||e<0)return`—`;if(e<60)return`${Math.round(e)}s`;let t=Math.floor(e/60),n=Math.round(e%60);return n?`${t}m ${n}s`:`${t}m`}function hy(e,t){return e?t?`${e} · ${t}`:e:`—`}function gy({className:e,...t}){return(0,M.jsx)(`span`,{className:Go(`badge`,e),...t})}function _y({status:e}){return(0,M.jsx)(gy,{className:`status-badge status-${e}`,children:e===`running`?`Running`:e===`stopped`?`Stopped`:`Finished`})}var vy=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`table`,{ref:n,className:Go(`table`,e),...t}));vy.displayName=`Table`;var yy=e=>(0,M.jsx)(`thead`,{...e}),by=e=>(0,M.jsx)(`tbody`,{...e}),xy=(0,j.forwardRef)((e,t)=>(0,M.jsx)(`tr`,{ref:t,...e}));xy.displayName=`TableRow`;var Sy=e=>(0,M.jsx)(`th`,{scope:`col`,...e}),Cy=e=>(0,M.jsx)(`td`,{...e}),wy=[`Name`,`Proxy`,`Mode`,`Status`,`Success rate`,`Median RTT`,`Distinct IPs`,`Last IP / category`,`Last sample`];function Ty({id:e,title:t,emptyMessage:n,sessions:r,stoppingID:i,onStop:a}){let o=qn(),s=e=>o(`/sessions/${e.id}`),c=(e,t)=>{e.stopPropagation(),a(t)};return(0,M.jsxs)(`section`,{className:`session-section`,"aria-labelledby":e,children:[(0,M.jsxs)(`div`,{className:`section-heading`,children:[(0,M.jsx)(`h2`,{id:e,children:t}),(0,M.jsx)(`span`,{className:`section-count`,"aria-label":`${r.length} sessions`,children:r.length})]}),r.length===0?(0,M.jsx)(`p`,{className:`section-empty`,children:n}):(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(`div`,{className:`session-table-wrap`,children:(0,M.jsxs)(vy,{children:[(0,M.jsx)(yy,{children:(0,M.jsxs)(xy,{children:[wy.map(e=>(0,M.jsx)(Sy,{children:e},e)),(0,M.jsx)(Sy,{children:(0,M.jsx)(`span`,{className:`sr-only`,children:`Actions`})})]})}),(0,M.jsx)(by,{children:r.map(e=>(0,M.jsxs)(xy,{className:`session-row`,onClick:()=>s(e),children:[(0,M.jsx)(Cy,{children:(0,M.jsx)(fi,{className:`session-link`,to:`/sessions/${e.id}`,onClick:e=>e.stopPropagation(),children:(0,M.jsx)(`strong`,{children:e.name})})}),(0,M.jsx)(Cy,{className:`mono`,children:e.proxy_display}),(0,M.jsx)(Cy,{className:`capitalize`,children:e.mode}),(0,M.jsx)(Cy,{children:(0,M.jsx)(_y,{status:e.status})}),(0,M.jsx)(Cy,{className:`numeric`,children:uy(e.success_rate)}),(0,M.jsx)(Cy,{className:`numeric`,children:dy(e.last_rtt_ms)}),(0,M.jsx)(Cy,{className:`numeric`,children:e.distinct_ips}),(0,M.jsx)(Cy,{className:`mono compact-cell`,children:hy(e.last_primary_ip,e.last_primary_category)}),(0,M.jsx)(Cy,{children:fy(e.last_sample_at)}),(0,M.jsx)(Cy,{className:`row-action`,children:e.status===`running`&&(0,M.jsx)(qo,{type:`button`,variant:`quiet`,size:`icon`,"aria-label":`Stop ${e.name}`,disabled:i===e.id,onClick:t=>c(t,e),children:(0,M.jsx)(Gi,{"aria-hidden":`true`,size:15})})})]},e.id))})]})}),(0,M.jsx)(`div`,{className:`session-records`,children:r.map(e=>(0,M.jsxs)(`article`,{className:`session-record`,children:[(0,M.jsxs)(`div`,{className:`record-heading`,children:[(0,M.jsx)(fi,{className:`record-title`,to:`/sessions/${e.id}`,children:e.name}),(0,M.jsx)(_y,{status:e.status})]}),(0,M.jsxs)(`dl`,{children:[(0,M.jsx)(Ey,{label:`Proxy`,value:e.proxy_display,mono:!0}),(0,M.jsx)(Ey,{label:`Mode`,value:e.mode}),(0,M.jsx)(Ey,{label:`Status`,value:e.status}),(0,M.jsx)(Ey,{label:`Success rate`,value:uy(e.success_rate)}),(0,M.jsx)(Ey,{label:`Median RTT`,value:dy(e.last_rtt_ms)}),(0,M.jsx)(Ey,{label:`Distinct IPs`,value:String(e.distinct_ips)}),(0,M.jsx)(Ey,{label:`Last IP / category`,value:hy(e.last_primary_ip,e.last_primary_category),mono:!0}),(0,M.jsx)(Ey,{label:`Last sample`,value:fy(e.last_sample_at)})]}),e.status===`running`&&(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,disabled:i===e.id,onClick:t=>c(t,e),children:[(0,M.jsx)(Gi,{"aria-hidden":`true`,size:15}),` Stop session`]})]},e.id))})]})]})}function Ey({label:e,value:t,mono:n=!1}){return(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`dt`,{children:e}),(0,M.jsx)(`dd`,{className:n?`mono`:void 0,children:t})]})}function Dy({className:e,...t}){return(0,M.jsx)(`div`,{"aria-hidden":`true`,className:Go(`skeleton`,e),...t})}function Oy({onNewSession:e,onNewRun:t}){let n=Qi(),r=$i();return(0,M.jsxs)(`main`,{className:`home-page`,children:[(0,M.jsx)(Ay,{runs:ca(),onNewRun:t}),(0,M.jsx)(ky,{sessions:n,stop:r,onNewSession:e})]})}function ky({sessions:e,stop:t,onNewSession:n}){if(e.isPending)return(0,M.jsx)(jy,{});if(e.isError)return(0,M.jsxs)(Wm,{className:`error-state`,children:[(0,M.jsx)(qi,{"aria-hidden":`true`,size:18}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Sessions are unavailable`}),(0,M.jsx)(`p`,{children:e.error.message})]}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,onClick:()=>e.refetch(),children:[(0,M.jsx)(Wi,{"aria-hidden":`true`,size:15}),` Retry`]})]});let r=e.data.filter(e=>e.status===`running`),i=e.data.filter(e=>e.status!==`running`),a=t.isPending?t.variables:void 0;return(0,M.jsxs)(M.Fragment,{children:[t.isError&&(0,M.jsxs)(Wm,{className:`inline-alert`,children:[(0,M.jsx)(qi,{"aria-hidden":`true`,size:18}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Session could not be stopped`}),(0,M.jsx)(`p`,{children:t.error.message})]})]}),e.data.length===0?(0,M.jsxs)(`section`,{className:`empty-state`,"aria-labelledby":`empty-heading`,children:[(0,M.jsx)(`h1`,{id:`empty-heading`,children:`Start your first sampling session`}),(0,M.jsx)(`p`,{children:`Sticky sessions measure how long one egress IP is held. Pool sessions measure per-request rotation and how the available pool grows.`}),(0,M.jsxs)(qo,{type:`button`,variant:`primary`,onClick:n,children:[(0,M.jsx)(Ui,{"aria-hidden":`true`,size:16}),` New session`]})]}):(0,M.jsxs)(`div`,{className:`session-sections`,children:[(0,M.jsx)(`h1`,{className:`sr-only`,children:`Sampling sessions`}),(0,M.jsx)(Ty,{id:`active-sessions`,title:`Active sessions`,emptyMessage:`No sessions are currently running.`,sessions:r,stoppingID:a,onStop:e=>t.mutate(e.id)}),(0,M.jsx)(Ty,{id:`inactive-sessions`,title:`Stopped / Finished sessions`,emptyMessage:`Stopped and finished sessions will appear here.`,sessions:i,stoppingID:a,onStop:e=>t.mutate(e.id)})]})]})}function Ay({runs:e,onNewRun:t}){let n=qn();return(0,M.jsxs)(`section`,{className:`runs-section`,"aria-labelledby":`runs-heading`,children:[(0,M.jsxs)(`div`,{className:`section-heading`,children:[(0,M.jsx)(`h2`,{id:`runs-heading`,children:`Parameter-variation runs`}),(0,M.jsx)(`span`,{className:`section-count`,"aria-label":`${e.data?.length??0} runs`,children:e.data?.length??0}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,size:`small`,className:`section-action`,onClick:t,children:[(0,M.jsx)(Ui,{"aria-hidden":`true`,size:15}),` New run`]})]}),e.isPending?(0,M.jsx)(`div`,{className:`skeleton-list`,children:(0,M.jsxs)(`div`,{className:`skeleton-row`,"aria-label":`Loading runs`,children:[(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{})]})}):e.isError?(0,M.jsxs)(Wm,{className:`inline-alert`,children:[(0,M.jsx)(qi,{"aria-hidden":`true`,size:18}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Runs are unavailable`}),(0,M.jsx)(`p`,{children:e.error.message})]}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,onClick:()=>e.refetch(),children:[(0,M.jsx)(Wi,{"aria-hidden":`true`,size:15}),` Retry`]})]}):e.data.length===0?(0,M.jsx)(`p`,{className:`section-empty`,children:`No parameter-variation runs yet. A run expands one template across several proxy configurations.`}):(0,M.jsx)(`div`,{className:`data-table-wrap`,children:(0,M.jsxs)(vy,{children:[(0,M.jsx)(yy,{children:(0,M.jsxs)(xy,{children:[(0,M.jsx)(Sy,{children:`Name`}),(0,M.jsx)(Sy,{children:`Variants`}),(0,M.jsx)(Sy,{children:`Status`}),(0,M.jsx)(Sy,{children:`Distinct IPs`}),(0,M.jsx)(Sy,{children:`Created`})]})}),(0,M.jsx)(by,{children:e.data.map(e=>(0,M.jsxs)(xy,{className:`session-row`,onClick:()=>n(`/runs/${e.id}`),children:[(0,M.jsx)(Cy,{children:(0,M.jsx)(fi,{className:`session-link`,to:`/runs/${e.id}`,onClick:e=>e.stopPropagation(),children:(0,M.jsx)(`strong`,{children:e.name})})}),(0,M.jsx)(Cy,{className:`numeric`,children:e.variant_count}),(0,M.jsx)(Cy,{children:(0,M.jsx)(_y,{status:e.status})}),(0,M.jsx)(Cy,{className:`numeric`,children:e.distinct_ips}),(0,M.jsx)(Cy,{children:fy(e.created_at)})]},e.id))})]})})]})}function jy(){return(0,M.jsxs)(`div`,{role:`status`,"aria-label":`Loading sessions`,children:[(0,M.jsx)(`span`,{className:`sr-only`,children:`Loading sessions`}),(0,M.jsxs)(`div`,{className:`skeleton-heading`,children:[(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{})]}),(0,M.jsx)(`div`,{className:`skeleton-list`,children:Array.from({length:4},(e,t)=>(0,M.jsxs)(`div`,{className:`skeleton-row`,"aria-label":`Loading session`,children:[(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{})]},t))})]})}var My=(0,j.lazy)(()=>xt(()=>import(`./session-page-BHtrUHcT.js`).then(e=>({default:e.SessionPage})),__vite__mapDeps([0,1]))),Ny=(0,j.lazy)(()=>xt(()=>import(`./run-page-SJdc0Mk9.js`).then(e=>({default:e.RunPage})),__vite__mapDeps([2,1])));function Py(){let[e,t]=(0,j.useState)(!1),[n,r]=(0,j.useState)(!1);return(0,M.jsxs)(Jo,{onNewSession:()=>t(!0),children:[(0,M.jsxs)(xr,{children:[(0,M.jsx)(yr,{path:`/`,element:(0,M.jsx)(Oy,{onNewSession:()=>t(!0),onNewRun:()=>r(!0)})}),(0,M.jsx)(yr,{path:`/sessions/:id`,element:(0,M.jsx)(j.Suspense,{fallback:(0,M.jsx)(`main`,{className:`route-placeholder`,"aria-label":`Session report loading boundary`}),children:(0,M.jsx)(My,{})})}),(0,M.jsx)(yr,{path:`/runs/:id`,element:(0,M.jsx)(j.Suspense,{fallback:(0,M.jsx)(`main`,{className:`route-placeholder`,"aria-label":`Run report loading boundary`}),children:(0,M.jsx)(Ny,{})})})]}),(0,M.jsx)(sy,{open:e,onOpenChange:t}),(0,M.jsx)(Qv,{open:n,onClose:()=>r(!1)})]})}var Fy=new Ye({defaultOptions:{queries:{retry:1,staleTime:1e3},mutations:{retry:!1}}});(0,_t.createRoot)(document.getElementById(`root`)).render((0,M.jsx)(j.StrictMode,{children:(0,M.jsx)(et,{client:Fy,children:(0,M.jsx)(ui,{children:(0,M.jsx)(Py,{})})})}));export{o as $,Yi as A,$i as B,ch as C,Wm as D,Jm as E,ua as F,P as G,Ki as H,ta as I,Yn as J,fi as K,na as L,pa as M,ea as N,qo as O,la as P,d as Q,ra as R,hh as S,$m as T,Gi as U,qi as V,Vi as W,Ze as X,bi as Y,h as Z,Hh as _,Sy as a,gh as b,_y as c,dy as d,s as et,uy as f,lg as g,_g as h,Cy as i,ma as j,ga as k,my as l,Hg as m,vy as n,yy as o,py as p,qn as q,by as r,xy as s,Dy as t,l as tt,hy as u,Ph as v,th as w,vh as x,kh as y,fa as z}; \ No newline at end of file +`},X_=0,Z_=[];function Q_(e){var t=j.useRef([]),n=j.useRef([0,0]),r=j.useRef(),i=j.useState(X_++)[0],a=j.useState(b_)[0],o=j.useRef(e);j.useEffect(function(){o.current=e},[e]),j.useEffect(function(){if(e.inert){document.body.classList.add(`block-interactivity-${i}`);var t=Yg([e.lockRef.current],(e.shards||[]).map(q_),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add(`allow-interactivity-${i}`)}),function(){document.body.classList.remove(`block-interactivity-${i}`),t.forEach(function(e){return e.classList.remove(`allow-interactivity-${i}`)})}}},[e.inert,e.lockRef.current,e.shards]);var s=j.useCallback(function(e,t){if(`touches`in e&&e.touches.length===2||e.type===`wheel`&&e.ctrlKey)return!o.current.allowPinchZoom;var i=G_(e),a=n.current,s=`deltaX`in e?e.deltaX:a[0]-i[0],c=`deltaY`in e?e.deltaY:a[1]-i[1],l,u=e.target,d=Math.abs(s)>Math.abs(c)?`h`:`v`;if(`touches`in e&&d===`h`&&u.type===`range`)return!1;var f=window.getSelection(),p=f&&f.anchorNode;if(p&&(p===u||p.contains(u)))return!1;var m=R_(d,u);if(!m)return!0;if(m?l=d:(l=d===`v`?`h`:`v`,m=R_(d,u)),!m)return!1;if(!r.current&&`changedTouches`in e&&(s||c)&&(r.current=l),!l)return!0;var h=r.current||l;return W_(h,t,e,h===`h`?s:c,!0)},[]),c=j.useCallback(function(e){var n=e;if(!(!Z_.length||Z_[Z_.length-1]!==a)){var r=`deltaY`in n?K_(n):G_(n),i=t.current.filter(function(e){return e.name===n.type&&(e.target===n.target||n.target===e.shadowParent)&&J_(e.delta,r)})[0];if(i&&i.should){n.cancelable&&n.preventDefault();return}if(!i){var c=(o.current.shards||[]).map(q_).filter(Boolean).filter(function(e){return e.contains(n.target)});(c.length>0?s(n,c[0]):!o.current.noIsolation)&&n.cancelable&&n.preventDefault()}}},[]),l=j.useCallback(function(e,n,r,i){var a={name:e,delta:n,target:r,should:i,shadowParent:$_(r)};t.current.push(a),setTimeout(function(){t.current=t.current.filter(function(e){return e!==a})},1)},[]),u=j.useCallback(function(e){n.current=G_(e),r.current=void 0},[]),d=j.useCallback(function(t){l(t.type,K_(t),t.target,s(t,e.lockRef.current))},[]),f=j.useCallback(function(t){l(t.type,G_(t),t.target,s(t,e.lockRef.current))},[]);j.useEffect(function(){return Z_.push(a),e.setCallbacks({onScrollCapture:d,onWheelCapture:d,onTouchMoveCapture:f}),document.addEventListener(`wheel`,c,N_),document.addEventListener(`touchmove`,c,N_),document.addEventListener(`touchstart`,u,N_),function(){Z_=Z_.filter(function(e){return e!==a}),document.removeEventListener(`wheel`,c,N_),document.removeEventListener(`touchmove`,c,N_),document.removeEventListener(`touchstart`,u,N_)}},[]);var p=e.removeScrollBar,m=e.inert;return j.createElement(j.Fragment,null,m?j.createElement(a,{styles:Y_(i)}):null,p?j.createElement(A_,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function $_(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}var ev=l_(u_,Q_),tv=j.forwardRef(function(e,t){return j.createElement(f_,qg({},e,{ref:t,sideCar:ev}))});tv.classNames=f_.classNames;var nv=function(e){return typeof document>`u`?null:(Array.isArray(e)?e[0]:e).ownerDocument.body},rv=new WeakMap,iv=new WeakMap,av={},ov=0,sv=function(e){return e&&(e.host||sv(e.parentNode))},cv=function(e,t){return t.map(function(t){if(e.contains(t))return t;var n=sv(t);return n&&e.contains(n)?n:(console.error(`aria-hidden`,t,`in not contained inside`,e,`. Doing nothing`),null)}).filter(function(e){return!!e})},lv=function(e,t,n,r){var i=cv(t,Array.isArray(e)?e:[e]);av[n]||(av[n]=new WeakMap);var a=av[n],o=[],s=new Set,c=new Set(i),l=function(e){!e||s.has(e)||(s.add(e),l(e.parentNode))};i.forEach(l);var u=function(e){!e||c.has(e)||Array.prototype.forEach.call(e.children,function(e){if(s.has(e))u(e);else try{var t=e.getAttribute(r),i=t!==null&&t!==`false`,c=(rv.get(e)||0)+1,l=(a.get(e)||0)+1;rv.set(e,c),a.set(e,l),o.push(e),c===1&&i&&iv.set(e,!0),l===1&&e.setAttribute(n,`true`),i||e.setAttribute(r,`true`)}catch(t){console.error(`aria-hidden: cannot operate on `,e,t)}})};return u(t),s.clear(),ov++,function(){o.forEach(function(e){var t=rv.get(e)-1,i=a.get(e)-1;rv.set(e,t),a.set(e,i),t||(iv.has(e)||e.removeAttribute(r),iv.delete(e)),i||e.removeAttribute(n)}),ov--,ov||(rv=new WeakMap,rv=new WeakMap,iv=new WeakMap,av={})}},uv=function(e,t,n){n===void 0&&(n=`data-aria-hidden`);var r=Array.from(Array.isArray(e)?e:[e]),i=t||nv(e);return i?(r.push.apply(r,Array.from(i.querySelectorAll(`[aria-live], script`))),lv(r,i,n,`aria-hidden`)):function(){return null}},dv=Object.defineProperty,fv=(e,t)=>dv(e,`name`,{value:t,configurable:!0}),pv=`Dialog`,[mv,hv]=$m(pv),[gv,_v]=mv(pv),vv=fv(e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!0}=e,s=j.useRef(null),c=j.useRef(null),[l,u]=ch({prop:r,defaultProp:i??!1,onChange:a,caller:pv}),[d,f]=j.useState(0),[p,m]=j.useState(0);return(0,M.jsx)(gv,{scope:t,triggerRef:s,contentRef:c,contentId:Hh(),titleId:Hh(),descriptionId:Hh(),titlePresent:d>0,descriptionPresent:p>0,setTitleCount:f,setDescriptionCount:m,open:l,onOpenChange:u,onOpenToggle:j.useCallback(()=>u(e=>!e),[u]),modal:o,children:n})},`Dialog`),yv=`DialogPortal`,[bv,xv]=mv(yv,{forceMount:void 0}),Sv=fv(e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=_v(yv,t);return(0,M.jsx)(bv,{scope:t,forceMount:n,children:j.Children.map(r,e=>(0,M.jsx)(Ph,{present:n||a.open,children:(0,M.jsx)(Hg,{asChild:!0,container:i,children:e})}))})},`DialogPortal`),Cv=`DialogOverlay`,wv=j.forwardRef(fv(function(e,t){let n=xv(Cv,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=_v(Cv,e.__scopeDialog);return a.modal?(0,M.jsx)(Ph,{present:r||a.open,children:(0,M.jsx)(Ev,{...i,ref:t})}):null},`DialogOverlay`)),Tv=gh(`DialogOverlay.RemoveScroll`),Ev=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Cv,n),a=hh(t,vg());return(0,M.jsx)(tv,{as:Tv,allowPinchZoom:!0,shards:[i.contentRef],children:(0,M.jsx)(kh.div,{"data-state":Rv(i.open),...r,ref:a,style:{pointerEvents:`auto`,...r.style}})})},`DialogOverlayImpl`)),Dv=`DialogContent`,Ov=j.forwardRef(fv(function(e,t){let n=xv(Dv,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=_v(Dv,e.__scopeDialog);return(0,M.jsx)(Ph,{present:r||a.open,children:a.modal?(0,M.jsx)(kv,{...i,ref:t}):(0,M.jsx)(Av,{...i,ref:t})})},`DialogContent`)),kv=j.forwardRef(fv(function(e,t){let n=_v(Dv,e.__scopeDialog),r=j.useRef(null),i=hh(t,n.contentRef,r);return j.useEffect(()=>{let e=r.current;if(e)return uv(e)},[]),(0,M.jsx)(jv,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:n.open,onCloseAutoFocus:Jm(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:Jm(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:Jm(e.onFocusOutside,e=>e.preventDefault())})},`DialogContentModal`)),Av=j.forwardRef(fv(function(e,t){let n=_v(Dv,e.__scopeDialog),r=j.useRef(!1),i=j.useRef(!1);return(0,M.jsx)(jv,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})},`DialogContentNonModal`)),jv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,...o}=e,s=_v(Dv,n);return Gg(),(0,M.jsx)(M.Fragment,{children:(0,M.jsx)(kg,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,M.jsx)(_g,{role:`dialog`,id:s.contentId,"aria-describedby":s.descriptionPresent?s.descriptionId:void 0,"aria-labelledby":s.titlePresent?s.titleId:void 0,"data-state":Rv(s.open),...o,ref:t,deferPointerDownOutside:!0,onDismiss:()=>s.onOpenChange(!1)})})})},`DialogContentImpl`)),Mv=`DialogTitle`,Nv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Mv,n),{setTitleCount:a}=i;return th(()=>(a(e=>e+1),()=>a(e=>e-1)),[a]),(0,M.jsx)(kh.h2,{id:i.titleId,...r,ref:t})},`DialogTitle`)),Pv=`DialogDescription`,Fv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Pv,n),{setDescriptionCount:a}=i;return th(()=>(a(e=>e+1),()=>a(e=>e-1)),[a]),(0,M.jsx)(kh.p,{id:i.descriptionId,...r,ref:t})},`DialogDescription`)),Iv=`DialogClose`,Lv=j.forwardRef(fv(function(e,t){let{__scopeDialog:n,...r}=e,i=_v(Iv,n);return(0,M.jsx)(kh.button,{type:`button`,...r,ref:t,onClick:Jm(e.onClick,()=>i.onOpenChange(!1))})},`DialogClose`));function Rv(e){return e?`open`:`closed`}fv(Rv,`getState`);var zv=vv,Bv=Nv,Vv=Fv,Hv=(0,j.forwardRef)(({className:e,children:t,closeDisabled:n,...r},i)=>(0,M.jsxs)(Sv,{children:[(0,M.jsx)(wv,{className:`dialog-overlay`}),(0,M.jsxs)(Ov,{ref:i,className:Go(`dialog-content`,e),...r,children:[t,(0,M.jsx)(Lv,{className:`dialog-x`,"aria-label":`Close dialog`,disabled:n,children:(0,M.jsx)(Ji,{"aria-hidden":`true`,size:18})})]})]}));Hv.displayName=`DialogContent`;var Uv=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`input`,{ref:n,className:Go(`input`,e),...t}));Uv.displayName=`Input`;var Wv=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`label`,{ref:n,className:Go(`label`,e),...t}));Wv.displayName=`Label`;var Gv=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`select`,{ref:n,className:Go(`select`,e),...t}));Gv.displayName=`Select`;var Kv=/^[1-9]\d*$/,qv=/^\d+$/,Jv=fm({name:Rp().trim().min(1,`Axis name is required`),kind:vm([`list`,`range`,`random`]),values:Rp(),from:Rp(),to:Rp(),count:Rp(),length:Rp()}).superRefine((e,t)=>{e.kind===`list`?ty(e.values).length<1&&t.addIssue({code:`custom`,path:[`values`],message:`Add at least one value`}):e.kind===`range`?(qv.test(e.from)||t.addIssue({code:`custom`,path:[`from`],message:`Enter a whole number`}),qv.test(e.to)||t.addIssue({code:`custom`,path:[`to`],message:`Enter a whole number`}),qv.test(e.from)&&qv.test(e.to)&&Number(e.to)e===`sticky`||e===`pool`,`Choose a sampling mode`),cadence:Rp().regex(Kv,`Cadence must be a positive integer`),axes:um(Jv).min(1,`Add at least one axis`).superRefine((e,t)=>{let n=new Set;e.forEach((e,r)=>{let i=e.name.trim();i!==``&&(n.has(i)?t.addIssue({code:`custom`,message:`Axis names must be unique`,path:[r,`name`]}):n.add(i))})}),probes:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`).refine(e=>e===``||Number(e)<=255,`Probes cannot exceed 255`),probeTarget:Rp().refine(e=>e===``||ry(e),`Enter an HTTP or HTTPS URL`),dialTimeout:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`).refine(e=>e===``||Number(e)>=100,`Timeout must be at least 100 ms`),maxSamples:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`),maxDuration:Rp().refine(e=>e===``||Kv.test(e),`Enter a positive integer or leave blank`),targetCountry:Rp().trim().refine(e=>e===``||/^[A-Za-z]{2}$/.test(e),`Enter a 2-letter country code or leave blank`)}),Xv={name:``,kind:`list`,values:``,from:``,to:``,count:``,length:``},Zv={name:``,template:``,mode:``,cadence:`30`,axes:[],probes:``,probeTarget:``,dialTimeout:``,maxSamples:``,maxDuration:``,targetCountry:``};function Qv({open:e,onClose:t}){let n=da(),r=sa().data?.max_variants_per_run??128,[i,a]=(0,j.useState)(!1),[o,s]=(0,j.useState)(null),c=zc({resolver:dp(Yv),defaultValues:Zv}),l=cc({control:c.control,name:`axes`}),u=Ts({control:c.control,name:`axes`})??[],d=Hm(ny(u)),f=d>r,p=e=>{n.isPending||e||(c.reset(Zv),a(!1),s(null),n.reset(),t())},m=c.handleSubmit(async e=>{if(f)return;s(null);let t={name:e.name.trim(),template:e.template,axes:ny(e.axes),mode:e.mode,cadence_seconds:Number(e.cadence),...e.probes?{probes_per_sample:Number(e.probes)}:{},...e.probeTarget?{probe_target:e.probeTarget}:{},...e.dialTimeout?{dial_timeout_ms:Number(e.dialTimeout)}:{},...e.maxSamples?{max_samples:Number(e.maxSamples)}:{},...e.maxDuration?{max_duration_seconds:Number(e.maxDuration)}:{},...e.targetCountry?{target_country:e.targetCountry}:{}};try{await n.mutateAsync(t),p(!1)}catch(e){s(e instanceof Yi?e.message:`The run could not be started. Try again.`)}finally{n.reset()}});return(0,M.jsx)(zv,{open:e,onOpenChange:p,children:(0,M.jsxs)(Hv,{"aria-describedby":`new-run-description`,closeDisabled:n.isPending,onEscapeKeyDown:e=>{n.isPending&&e.preventDefault()},onPointerDownOutside:e=>{n.isPending&&e.preventDefault()},children:[(0,M.jsxs)(`div`,{className:`dialog-heading`,children:[(0,M.jsx)(Bv,{children:`New parameter-variation run`}),(0,M.jsx)(Vv,{id:`new-run-description`,children:`Expand a proxy template across one or more axes and sample every resulting variant.`})]}),(0,M.jsxs)(`form`,{onSubmit:m,noValidate:!0,children:[o&&(0,M.jsx)(Wm,{className:`form-alert`,children:o}),(0,M.jsxs)(`fieldset`,{disabled:n.isPending,className:`form-fields`,children:[(0,M.jsx)(ey,{label:`Run name`,error:c.formState.errors.name?.message,children:(0,M.jsx)(Uv,{autoFocus:!0,id:`run-name`,placeholder:`Experiment name`,...c.register(`name`)})}),(0,M.jsx)(ey,{label:`Proxy template`,error:c.formState.errors.template?.message,hint:`Use {axis_name} placeholders, e.g. socks5h://u-cc-{country}:pw@gate:1080`,children:(0,M.jsx)(Uv,{id:`proxy-template`,spellCheck:!1,placeholder:`socks5h://u-cc-{country}:pw@gate:1080`,...c.register(`template`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(Ds,{control:c.control,name:`mode`,render:({field:e,fieldState:t})=>(0,M.jsx)(ey,{label:`Sampling mode`,error:t.error?.message,children:(0,M.jsxs)(Gv,{id:`sampling-mode`,...e,children:[(0,M.jsx)(`option`,{value:``,children:`Select mode`}),(0,M.jsx)(`option`,{value:`sticky`,children:`Sticky`}),(0,M.jsx)(`option`,{value:`pool`,children:`Pool`})]})})}),(0,M.jsx)(ey,{label:`Cadence (seconds)`,error:c.formState.errors.cadence?.message,children:(0,M.jsx)(Uv,{id:`cadence`,type:`number`,min:`1`,inputMode:`numeric`,...c.register(`cadence`)})})]}),(0,M.jsxs)(`div`,{className:`axes-builder`,children:[(0,M.jsxs)(`div`,{className:`axes-builder-heading`,children:[(0,M.jsx)(`span`,{className:`label`,children:`Axes`}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,size:`small`,onClick:()=>l.append({...Xv}),children:[(0,M.jsx)(Ui,{"aria-hidden":`true`,size:14}),` Add axis`]})]}),c.formState.errors.axes?.root?.message&&(0,M.jsx)(`p`,{className:`field-error`,role:`alert`,children:c.formState.errors.axes.root.message}),l.fields.length===0&&(0,M.jsx)(`p`,{className:`field-hint`,children:`No axes yet. Add at least one to expand this run into variants.`}),l.fields.map((e,t)=>(0,M.jsx)($v,{index:t,form:c,kind:u[t]?.kind??`list`,onRemove:()=>l.remove(t)},e.id)),(0,M.jsxs)(`p`,{className:f?`field-error`:`field-hint`,role:f?`alert`:void 0,children:[d,` variants`,f?` — exceeds the maximum of ${r}. Remove or narrow an axis.`:``]})]}),(0,M.jsxs)(og,{open:i,onOpenChange:a,className:`advanced-settings`,children:[(0,M.jsx)(sg,{asChild:!0,children:(0,M.jsxs)(qo,{type:`button`,variant:`quiet`,className:`advanced-trigger`,"aria-expanded":i,children:[`Advanced settings `,(0,M.jsx)(Vi,{"aria-hidden":`true`,className:i?`rotate`:void 0,size:16})]})}),(0,M.jsxs)(cg,{className:`advanced-content`,children:[(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Probes per sample (optional)`,error:c.formState.errors.probes?.message,children:(0,M.jsx)(Uv,{id:`probes`,type:`number`,min:`1`,max:`255`,inputMode:`numeric`,...c.register(`probes`)})}),(0,M.jsx)(ey,{label:`Dial timeout (milliseconds, optional)`,error:c.formState.errors.dialTimeout?.message,children:(0,M.jsx)(Uv,{id:`dial-timeout`,type:`number`,min:`100`,inputMode:`numeric`,...c.register(`dialTimeout`)})})]}),(0,M.jsx)(ey,{label:`Probe target URL (optional)`,error:c.formState.errors.probeTarget?.message,children:(0,M.jsx)(Uv,{id:`probe-target`,type:`url`,spellCheck:!1,...c.register(`probeTarget`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Maximum samples (optional)`,error:c.formState.errors.maxSamples?.message,children:(0,M.jsx)(Uv,{id:`max-samples`,type:`number`,min:`1`,inputMode:`numeric`,...c.register(`maxSamples`)})}),(0,M.jsx)(ey,{label:`Maximum duration (seconds, optional)`,error:c.formState.errors.maxDuration?.message,children:(0,M.jsx)(Uv,{id:`max-duration`,type:`number`,min:`1`,inputMode:`numeric`,...c.register(`maxDuration`)})})]}),(0,M.jsx)(ey,{label:`Target country (optional)`,error:c.formState.errors.targetCountry?.message,hint:`2-letter code, e.g. DE. Declares the intended egress country when no country axis exists; overrides a country axis in the honor rate.`,children:(0,M.jsx)(Uv,{id:`target-country`,spellCheck:!1,placeholder:`DE`,...c.register(`targetCountry`)})})]})]})]}),(0,M.jsxs)(`div`,{className:`dialog-actions`,children:[(0,M.jsx)(qo,{type:`button`,variant:`quiet`,disabled:n.isPending,onClick:()=>p(!1),children:`Cancel`}),(0,M.jsx)(qo,{type:`submit`,variant:`primary`,disabled:n.isPending||f,children:n.isPending?(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(Hi,{className:`spin`,"aria-hidden":`true`,size:16}),` Starting run…`]}):`Start run`})]})]})]})})}function $v({index:e,form:t,kind:n,onRemove:r}){let i=e+1,a=t.formState.errors.axes?.[e];return(0,M.jsxs)(`div`,{className:`axis-row`,children:[(0,M.jsxs)(`div`,{className:`axis-row-fields`,children:[(0,M.jsx)(ey,{label:`Axis ${i} name`,error:a?.name?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-name`,placeholder:`country`,...t.register(`axes.${e}.name`)})}),(0,M.jsx)(ey,{label:`Axis ${i} kind`,children:(0,M.jsxs)(Gv,{id:`axis-${i}-kind`,...t.register(`axes.${e}.kind`),children:[(0,M.jsx)(`option`,{value:`list`,children:`List`}),(0,M.jsx)(`option`,{value:`range`,children:`Range`}),(0,M.jsx)(`option`,{value:`random`,children:`Random`})]})}),n===`list`&&(0,M.jsx)(ey,{label:`Axis ${i} values`,error:a?.values?.message,hint:`Comma-separated`,children:(0,M.jsx)(Uv,{id:`axis-${i}-values`,placeholder:`de, us, fr, jp`,...t.register(`axes.${e}.values`)})}),n===`range`&&(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Axis ${i} from`,error:a?.from?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-from`,type:`number`,inputMode:`numeric`,...t.register(`axes.${e}.from`)})}),(0,M.jsx)(ey,{label:`Axis ${i} to`,error:a?.to?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-to`,type:`number`,inputMode:`numeric`,...t.register(`axes.${e}.to`)})})]}),n===`random`&&(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(ey,{label:`Axis ${i} count`,error:a?.count?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-count`,type:`number`,min:`1`,inputMode:`numeric`,...t.register(`axes.${e}.count`)})}),(0,M.jsx)(ey,{label:`Axis ${i} length (optional)`,error:a?.length?.message,children:(0,M.jsx)(Uv,{id:`axis-${i}-length`,type:`number`,min:`1`,inputMode:`numeric`,...t.register(`axes.${e}.length`)})})]})]}),(0,M.jsxs)(qo,{type:`button`,variant:`quiet`,size:`small`,onClick:r,children:[(0,M.jsx)(Ki,{"aria-hidden":`true`,size:14}),` Remove axis`]})]})}function ey({label:e,error:t,hint:n,children:r}){let i=r.props.id,a=n&&i?`${i}-hint`:void 0,o=t&&i?`${i}-error`:void 0,s=(0,j.cloneElement)(r,{"aria-invalid":t?!0:void 0,"aria-describedby":[a,o].filter(Boolean).join(` `)||void 0});return(0,M.jsxs)(`div`,{className:`field`,children:[(0,M.jsx)(Wv,{htmlFor:i,children:e}),s,n&&(0,M.jsx)(`p`,{className:`field-hint`,id:a,children:n}),t&&(0,M.jsx)(`p`,{className:`field-error`,id:o,role:`alert`,children:t})]})}function ty(e){return e.split(`,`).map(e=>e.trim()).filter(Boolean)}function ny(e){let t={};for(let n of e){let e=n?.name?.trim();if(e)if(n?.kind===`range`){let r=Number(n.from),i=Number(n.to);if(n.from===``||n.to===``||Number.isNaN(r)||Number.isNaN(i))continue;t[e]={kind:`range`,from:r,to:i}}else if(n?.kind===`random`){let r=Number(n.count);if(n.count===``||Number.isNaN(r))continue;let i=n.length?Number(n.length):void 0;t[e]={kind:`random`,count:r,...i!==void 0&&!Number.isNaN(i)?{length:i}:{}}}else t[e]={kind:`list`,values:ty(n?.values??``)}}return t}function ry(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}var iy=/^[1-9]\d*$/,ay=fm({name:Rp().trim().min(1,`Name is required`).max(100,`Name must be 100 characters or fewer`),proxy:Rp().min(1,`Proxy connection string is required`),mode:Rp().refine(e=>e===`sticky`||e===`pool`,`Choose a sampling mode`),cadence:Rp().regex(iy,`Cadence must be a positive integer`),probes:Rp().regex(iy,`Probes must be a positive integer`).refine(e=>Number(e)<=255,`Probes cannot exceed 255`),probeTarget:Rp().refine(e=>e===``||ly(e),`Enter an HTTP or HTTPS URL`),dialTimeout:Rp().regex(iy,`Timeout must be a positive integer`).refine(e=>Number(e)>=100,`Timeout must be at least 100 ms`),maxSamples:Rp().refine(e=>e===``||iy.test(e),`Enter a positive integer or leave blank`),maxDuration:Rp().refine(e=>e===``||iy.test(e),`Enter a positive integer or leave blank`),targetCountry:Rp().trim().refine(e=>e===``||/^[A-Za-z]{2}$/.test(e),`Enter a 2-letter country code or leave blank`)}),oy={name:``,proxy:``,mode:``,cadence:`30`,probes:``,probeTarget:`https://speed.cloudflare.com/cdn-cgi/trace`,dialTimeout:`10000`,maxSamples:``,maxDuration:``,targetCountry:``};function sy({open:e,onOpenChange:t}){let n=qn(),r=ia(),i=(0,j.useRef)(!1),[a,o]=(0,j.useState)(!1),[s,c]=(0,j.useState)(null),l=zc({resolver:dp(ay),defaultValues:oy}),u=e=>{r.isPending||(e||(l.reset(oy),i.current=!1,o(!1),c(null),r.reset()),t(e))},d=l.handleSubmit(async e=>{c(null);let t={name:e.name.trim(),proxy:e.proxy,mode:e.mode,cadence_seconds:Number(e.cadence),probes_per_sample:Number(e.probes),...e.probeTarget?{probe_target:e.probeTarget}:{},...e.dialTimeout?{dial_timeout_ms:Number(e.dialTimeout)}:{},...e.maxSamples?{max_samples:Number(e.maxSamples)}:{},...e.maxDuration?{max_duration_seconds:Number(e.maxDuration)}:{},...e.targetCountry?{target_country:e.targetCountry}:{}};l.resetField(`proxy`,{defaultValue:``});try{let e=await r.mutateAsync(t);u(!1),n(`/sessions/${e.id}`)}catch(e){c(e instanceof Yi?e.message:`The session could not be started. Try again.`)}finally{r.reset()}});return(0,M.jsx)(zv,{open:e,onOpenChange:u,children:(0,M.jsxs)(Hv,{"aria-describedby":`new-session-description`,closeDisabled:r.isPending,onEscapeKeyDown:e=>{r.isPending&&e.preventDefault()},onPointerDownOutside:e=>{r.isPending&&e.preventDefault()},children:[(0,M.jsxs)(`div`,{className:`dialog-heading`,children:[(0,M.jsx)(Bv,{children:`New sampling session`}),(0,M.jsx)(Vv,{id:`new-session-description`,children:`Start a durable measurement run against one proxy endpoint.`})]}),(0,M.jsxs)(`form`,{onSubmit:d,noValidate:!0,children:[s&&(0,M.jsx)(Wm,{className:`form-alert`,children:s}),(0,M.jsxs)(`fieldset`,{disabled:r.isPending,className:`form-fields`,children:[(0,M.jsx)(cy,{label:`Session name`,error:l.formState.errors.name?.message,children:(0,M.jsx)(Uv,{autoFocus:!0,id:`session-name`,placeholder:`Provider or endpoint name`,...l.register(`name`)})}),(0,M.jsx)(cy,{label:`Proxy connection string`,error:l.formState.errors.proxy?.message,hint:`Supports socks5h:// and http:// connection strings.`,children:(0,M.jsx)(Uv,{id:`proxy-connection-string`,type:`password`,autoComplete:`off`,spellCheck:!1,placeholder:`socks5h://user:password@host:port`,...l.register(`proxy`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(Ds,{control:l.control,name:`mode`,render:({field:e,fieldState:t})=>(0,M.jsx)(cy,{label:`Sampling mode`,error:t.error?.message,children:(0,M.jsxs)(Gv,{id:`sampling-mode`,...e,onChange:t=>{e.onChange(t),i.current||l.setValue(`probes`,t.target.value===`pool`?`8`:t.target.value===`sticky`?`3`:``,{shouldValidate:!0})},children:[(0,M.jsx)(`option`,{value:``,children:`Select mode`}),(0,M.jsx)(`option`,{value:`sticky`,children:`Sticky`}),(0,M.jsx)(`option`,{value:`pool`,children:`Pool`})]})})}),(0,M.jsx)(cy,{label:`Cadence (seconds)`,error:l.formState.errors.cadence?.message,children:(0,M.jsx)(Uv,{id:`cadence`,type:`number`,min:`1`,inputMode:`numeric`,...l.register(`cadence`)})}),(0,M.jsx)(cy,{label:`Probes per sample`,error:l.formState.errors.probes?.message,children:(0,M.jsx)(Uv,{id:`probes`,type:`number`,min:`1`,max:`255`,inputMode:`numeric`,...l.register(`probes`,{onChange:()=>{i.current=!0}})})})]}),(0,M.jsxs)(og,{open:a,onOpenChange:o,className:`advanced-settings`,children:[(0,M.jsx)(sg,{asChild:!0,children:(0,M.jsxs)(qo,{type:`button`,variant:`quiet`,className:`advanced-trigger`,"aria-expanded":a,children:[`Advanced settings `,(0,M.jsx)(Vi,{"aria-hidden":`true`,className:a?`rotate`:void 0,size:16})]})}),(0,M.jsxs)(cg,{className:`advanced-content`,children:[(0,M.jsx)(cy,{label:`Probe target URL`,error:l.formState.errors.probeTarget?.message,children:(0,M.jsx)(Uv,{id:`probe-target`,type:`url`,spellCheck:!1,...l.register(`probeTarget`)})}),(0,M.jsxs)(`div`,{className:`form-grid`,children:[(0,M.jsx)(cy,{label:`Dial timeout (milliseconds)`,error:l.formState.errors.dialTimeout?.message,children:(0,M.jsx)(Uv,{id:`dial-timeout`,type:`number`,min:`100`,inputMode:`numeric`,...l.register(`dialTimeout`)})}),(0,M.jsx)(cy,{label:`Maximum samples (optional)`,error:l.formState.errors.maxSamples?.message,children:(0,M.jsx)(Uv,{id:`max-samples`,type:`number`,min:`1`,inputMode:`numeric`,...l.register(`maxSamples`)})}),(0,M.jsx)(cy,{label:`Maximum duration (seconds, optional)`,error:l.formState.errors.maxDuration?.message,children:(0,M.jsx)(Uv,{id:`max-duration`,type:`number`,min:`1`,inputMode:`numeric`,...l.register(`maxDuration`)})})]}),(0,M.jsx)(cy,{label:`Target country (optional)`,error:l.formState.errors.targetCountry?.message,hint:`2-letter code, e.g. DE. Declares the intended egress country when the proxy config does not encode one; overrides a country parsed from the username.`,children:(0,M.jsx)(Uv,{id:`target-country`,spellCheck:!1,placeholder:`DE`,...l.register(`targetCountry`)})})]})]})]}),(0,M.jsxs)(`div`,{className:`dialog-actions`,children:[(0,M.jsx)(qo,{type:`button`,variant:`quiet`,disabled:r.isPending,onClick:()=>u(!1),children:`Cancel`}),(0,M.jsx)(qo,{type:`submit`,variant:`primary`,disabled:r.isPending,children:r.isPending?(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(Hi,{className:`spin`,"aria-hidden":`true`,size:16}),` Starting session…`]}):`Start session`})]})]})]})})}function cy({label:e,error:t,hint:n,children:r}){let i=r.props.id,a=n&&i?`${i}-hint`:void 0,o=t&&i?`${i}-error`:void 0,s=(0,j.cloneElement)(r,{"aria-invalid":t?!0:void 0,"aria-describedby":[a,o].filter(Boolean).join(` `)||void 0});return(0,M.jsxs)(`div`,{className:`field`,children:[(0,M.jsx)(Wv,{htmlFor:i,children:e}),s,n&&(0,M.jsx)(`p`,{className:`field-hint`,id:a,children:n}),t&&(0,M.jsx)(`p`,{className:`field-error`,id:o,role:`alert`,children:t})]})}function ly(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function uy(e){return new Intl.NumberFormat(void 0,{style:`percent`,maximumFractionDigits:1}).format(e)}function dy(e){return e==null||!Number.isFinite(e)?`—`:`${new Intl.NumberFormat().format(e)} ms`}function fy(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`}).format(t)}function py(e){if(!e)return`—`;let t=new Date(e);return Number.isNaN(t.getTime())?`—`:new Intl.DateTimeFormat(void 0,{year:`numeric`,month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`}).format(t)}function my(e){if(!Number.isFinite(e)||e<0)return`—`;if(e<60)return`${Math.round(e)}s`;let t=Math.floor(e/60),n=Math.round(e%60);return n?`${t}m ${n}s`:`${t}m`}function hy(e,t){return e?t?`${e} · ${t}`:e:`—`}function gy({className:e,...t}){return(0,M.jsx)(`span`,{className:Go(`badge`,e),...t})}function _y({status:e}){return(0,M.jsx)(gy,{className:`status-badge status-${e}`,children:e===`running`?`Running`:e===`stopped`?`Stopped`:`Finished`})}var vy=(0,j.forwardRef)(({className:e,...t},n)=>(0,M.jsx)(`table`,{ref:n,className:Go(`table`,e),...t}));vy.displayName=`Table`;var yy=e=>(0,M.jsx)(`thead`,{...e}),by=e=>(0,M.jsx)(`tbody`,{...e}),xy=(0,j.forwardRef)((e,t)=>(0,M.jsx)(`tr`,{ref:t,...e}));xy.displayName=`TableRow`;var Sy=e=>(0,M.jsx)(`th`,{scope:`col`,...e}),Cy=e=>(0,M.jsx)(`td`,{...e}),wy=[`Name`,`Proxy`,`Mode`,`Status`,`Success rate`,`Median RTT`,`Distinct IPs`,`Last IP / category`,`Last sample`];function Ty({id:e,title:t,emptyMessage:n,sessions:r,stoppingID:i,onStop:a}){let o=qn(),s=e=>o(`/sessions/${e.id}`),c=(e,t)=>{e.stopPropagation(),a(t)};return(0,M.jsxs)(`section`,{className:`session-section`,"aria-labelledby":e,children:[(0,M.jsxs)(`div`,{className:`section-heading`,children:[(0,M.jsx)(`h2`,{id:e,children:t}),(0,M.jsx)(`span`,{className:`section-count`,"aria-label":`${r.length} sessions`,children:r.length})]}),r.length===0?(0,M.jsx)(`p`,{className:`section-empty`,children:n}):(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(`div`,{className:`session-table-wrap`,children:(0,M.jsxs)(vy,{children:[(0,M.jsx)(yy,{children:(0,M.jsxs)(xy,{children:[wy.map(e=>(0,M.jsx)(Sy,{children:e},e)),(0,M.jsx)(Sy,{children:(0,M.jsx)(`span`,{className:`sr-only`,children:`Actions`})})]})}),(0,M.jsx)(by,{children:r.map(e=>(0,M.jsxs)(xy,{className:`session-row`,onClick:()=>s(e),children:[(0,M.jsx)(Cy,{children:(0,M.jsx)(fi,{className:`session-link`,to:`/sessions/${e.id}`,onClick:e=>e.stopPropagation(),children:(0,M.jsx)(`strong`,{children:e.name})})}),(0,M.jsx)(Cy,{className:`mono`,children:e.proxy_display}),(0,M.jsx)(Cy,{className:`capitalize`,children:e.mode}),(0,M.jsx)(Cy,{children:(0,M.jsx)(_y,{status:e.status})}),(0,M.jsx)(Cy,{className:`numeric`,children:uy(e.success_rate)}),(0,M.jsx)(Cy,{className:`numeric`,children:dy(e.last_rtt_ms)}),(0,M.jsx)(Cy,{className:`numeric`,children:e.distinct_ips}),(0,M.jsx)(Cy,{className:`mono compact-cell`,children:hy(e.last_primary_ip,e.last_primary_category)}),(0,M.jsx)(Cy,{children:fy(e.last_sample_at)}),(0,M.jsx)(Cy,{className:`row-action`,children:e.status===`running`&&(0,M.jsx)(qo,{type:`button`,variant:`quiet`,size:`icon`,"aria-label":`Stop ${e.name}`,disabled:i===e.id,onClick:t=>c(t,e),children:(0,M.jsx)(Gi,{"aria-hidden":`true`,size:15})})})]},e.id))})]})}),(0,M.jsx)(`div`,{className:`session-records`,children:r.map(e=>(0,M.jsxs)(`article`,{className:`session-record`,children:[(0,M.jsxs)(`div`,{className:`record-heading`,children:[(0,M.jsx)(fi,{className:`record-title`,to:`/sessions/${e.id}`,children:e.name}),(0,M.jsx)(_y,{status:e.status})]}),(0,M.jsxs)(`dl`,{children:[(0,M.jsx)(Ey,{label:`Proxy`,value:e.proxy_display,mono:!0}),(0,M.jsx)(Ey,{label:`Mode`,value:e.mode}),(0,M.jsx)(Ey,{label:`Status`,value:e.status}),(0,M.jsx)(Ey,{label:`Success rate`,value:uy(e.success_rate)}),(0,M.jsx)(Ey,{label:`Median RTT`,value:dy(e.last_rtt_ms)}),(0,M.jsx)(Ey,{label:`Distinct IPs`,value:String(e.distinct_ips)}),(0,M.jsx)(Ey,{label:`Last IP / category`,value:hy(e.last_primary_ip,e.last_primary_category),mono:!0}),(0,M.jsx)(Ey,{label:`Last sample`,value:fy(e.last_sample_at)})]}),e.status===`running`&&(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,disabled:i===e.id,onClick:t=>c(t,e),children:[(0,M.jsx)(Gi,{"aria-hidden":`true`,size:15}),` Stop session`]})]},e.id))})]})]})}function Ey({label:e,value:t,mono:n=!1}){return(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`dt`,{children:e}),(0,M.jsx)(`dd`,{className:n?`mono`:void 0,children:t})]})}function Dy({className:e,...t}){return(0,M.jsx)(`div`,{"aria-hidden":`true`,className:Go(`skeleton`,e),...t})}function Oy({onNewSession:e,onNewRun:t}){let n=Qi(),r=$i();return(0,M.jsxs)(`main`,{className:`home-page`,children:[(0,M.jsx)(Ay,{runs:ca(),onNewRun:t}),(0,M.jsx)(ky,{sessions:n,stop:r,onNewSession:e})]})}function ky({sessions:e,stop:t,onNewSession:n}){if(e.isPending)return(0,M.jsx)(jy,{});if(e.isError)return(0,M.jsxs)(Wm,{className:`error-state`,children:[(0,M.jsx)(qi,{"aria-hidden":`true`,size:18}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Sessions are unavailable`}),(0,M.jsx)(`p`,{children:e.error.message})]}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,onClick:()=>e.refetch(),children:[(0,M.jsx)(Wi,{"aria-hidden":`true`,size:15}),` Retry`]})]});let r=e.data.filter(e=>e.status===`running`),i=e.data.filter(e=>e.status!==`running`),a=t.isPending?t.variables:void 0;return(0,M.jsxs)(M.Fragment,{children:[t.isError&&(0,M.jsxs)(Wm,{className:`inline-alert`,children:[(0,M.jsx)(qi,{"aria-hidden":`true`,size:18}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Session could not be stopped`}),(0,M.jsx)(`p`,{children:t.error.message})]})]}),e.data.length===0?(0,M.jsxs)(`section`,{className:`empty-state`,"aria-labelledby":`empty-heading`,children:[(0,M.jsx)(`h1`,{id:`empty-heading`,children:`Start your first sampling session`}),(0,M.jsx)(`p`,{children:`Sticky sessions measure how long one egress IP is held. Pool sessions measure per-request rotation and how the available pool grows.`}),(0,M.jsxs)(qo,{type:`button`,variant:`primary`,onClick:n,children:[(0,M.jsx)(Ui,{"aria-hidden":`true`,size:16}),` New session`]})]}):(0,M.jsxs)(`div`,{className:`session-sections`,children:[(0,M.jsx)(`h1`,{className:`sr-only`,children:`Sampling sessions`}),(0,M.jsx)(Ty,{id:`active-sessions`,title:`Active sessions`,emptyMessage:`No sessions are currently running.`,sessions:r,stoppingID:a,onStop:e=>t.mutate(e.id)}),(0,M.jsx)(Ty,{id:`inactive-sessions`,title:`Stopped / Finished sessions`,emptyMessage:`Stopped and finished sessions will appear here.`,sessions:i,stoppingID:a,onStop:e=>t.mutate(e.id)})]})]})}function Ay({runs:e,onNewRun:t}){let n=qn();return(0,M.jsxs)(`section`,{className:`runs-section`,"aria-labelledby":`runs-heading`,children:[(0,M.jsxs)(`div`,{className:`section-heading`,children:[(0,M.jsx)(`h2`,{id:`runs-heading`,children:`Parameter-variation runs`}),(0,M.jsx)(`span`,{className:`section-count`,"aria-label":`${e.data?.length??0} runs`,children:e.data?.length??0}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,size:`small`,className:`section-action`,onClick:t,children:[(0,M.jsx)(Ui,{"aria-hidden":`true`,size:15}),` New run`]})]}),e.isPending?(0,M.jsx)(`div`,{className:`skeleton-list`,children:(0,M.jsxs)(`div`,{className:`skeleton-row`,"aria-label":`Loading runs`,children:[(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{})]})}):e.isError?(0,M.jsxs)(Wm,{className:`inline-alert`,children:[(0,M.jsx)(qi,{"aria-hidden":`true`,size:18}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Runs are unavailable`}),(0,M.jsx)(`p`,{children:e.error.message})]}),(0,M.jsxs)(qo,{type:`button`,variant:`secondary`,onClick:()=>e.refetch(),children:[(0,M.jsx)(Wi,{"aria-hidden":`true`,size:15}),` Retry`]})]}):e.data.length===0?(0,M.jsx)(`p`,{className:`section-empty`,children:`No parameter-variation runs yet. A run expands one template across several proxy configurations.`}):(0,M.jsx)(`div`,{className:`data-table-wrap`,children:(0,M.jsxs)(vy,{children:[(0,M.jsx)(yy,{children:(0,M.jsxs)(xy,{children:[(0,M.jsx)(Sy,{children:`Name`}),(0,M.jsx)(Sy,{children:`Variants`}),(0,M.jsx)(Sy,{children:`Status`}),(0,M.jsx)(Sy,{children:`Distinct IPs`}),(0,M.jsx)(Sy,{children:`Created`})]})}),(0,M.jsx)(by,{children:e.data.map(e=>(0,M.jsxs)(xy,{className:`session-row`,onClick:()=>n(`/runs/${e.id}`),children:[(0,M.jsx)(Cy,{children:(0,M.jsx)(fi,{className:`session-link`,to:`/runs/${e.id}`,onClick:e=>e.stopPropagation(),children:(0,M.jsx)(`strong`,{children:e.name})})}),(0,M.jsx)(Cy,{className:`numeric`,children:e.variant_count}),(0,M.jsx)(Cy,{children:(0,M.jsx)(_y,{status:e.status})}),(0,M.jsx)(Cy,{className:`numeric`,children:e.distinct_ips}),(0,M.jsx)(Cy,{children:fy(e.created_at)})]},e.id))})]})})]})}function jy(){return(0,M.jsxs)(`div`,{role:`status`,"aria-label":`Loading sessions`,children:[(0,M.jsx)(`span`,{className:`sr-only`,children:`Loading sessions`}),(0,M.jsxs)(`div`,{className:`skeleton-heading`,children:[(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{})]}),(0,M.jsx)(`div`,{className:`skeleton-list`,children:Array.from({length:4},(e,t)=>(0,M.jsxs)(`div`,{className:`skeleton-row`,"aria-label":`Loading session`,children:[(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{}),(0,M.jsx)(Dy,{})]},t))})]})}var My=(0,j.lazy)(()=>xt(()=>import(`./session-page-DwoLWZj3.js`).then(e=>({default:e.SessionPage})),__vite__mapDeps([0,1]))),Ny=(0,j.lazy)(()=>xt(()=>import(`./run-page-CsK2gHGg.js`).then(e=>({default:e.RunPage})),__vite__mapDeps([2,1])));function Py(){let[e,t]=(0,j.useState)(!1),[n,r]=(0,j.useState)(!1);return(0,M.jsxs)(Jo,{onNewSession:()=>t(!0),children:[(0,M.jsxs)(xr,{children:[(0,M.jsx)(yr,{path:`/`,element:(0,M.jsx)(Oy,{onNewSession:()=>t(!0),onNewRun:()=>r(!0)})}),(0,M.jsx)(yr,{path:`/sessions/:id`,element:(0,M.jsx)(j.Suspense,{fallback:(0,M.jsx)(`main`,{className:`route-placeholder`,"aria-label":`Session report loading boundary`}),children:(0,M.jsx)(My,{})})}),(0,M.jsx)(yr,{path:`/runs/:id`,element:(0,M.jsx)(j.Suspense,{fallback:(0,M.jsx)(`main`,{className:`route-placeholder`,"aria-label":`Run report loading boundary`}),children:(0,M.jsx)(Ny,{})})})]}),(0,M.jsx)(sy,{open:e,onOpenChange:t}),(0,M.jsx)(Qv,{open:n,onClose:()=>r(!1)})]})}var Fy=new Ye({defaultOptions:{queries:{retry:1,staleTime:1e3},mutations:{retry:!1}}});(0,_t.createRoot)(document.getElementById(`root`)).render((0,M.jsx)(j.StrictMode,{children:(0,M.jsx)(et,{client:Fy,children:(0,M.jsx)(ui,{children:(0,M.jsx)(Py,{})})})}));export{o as $,Yi as A,$i as B,ch as C,Wm as D,Jm as E,ua as F,P as G,Ki as H,ta as I,Yn as J,fi as K,na as L,pa as M,ea as N,qo as O,la as P,d as Q,ra as R,hh as S,$m as T,Gi as U,qi as V,Vi as W,Ze as X,bi as Y,h as Z,Hh as _,Sy as a,gh as b,_y as c,dy as d,s as et,uy as f,lg as g,_g as h,Cy as i,ma as j,ga as k,my as l,Hg as m,vy as n,yy as o,py as p,qn as q,by as r,xy as s,Dy as t,l as tt,hy as u,Ph as v,th as w,vh as x,kh as y,fa as z}; \ No newline at end of file diff --git a/web/dist/assets/risk-histogram-Bw31Zp4T.js b/web/dist/assets/risk-histogram-dP0_I5OY.js similarity index 99% rename from web/dist/assets/risk-histogram-Bw31Zp4T.js rename to web/dist/assets/risk-histogram-dP0_I5OY.js index 1d4c0b5..3ca7f28 100644 --- a/web/dist/assets/risk-histogram-Bw31Zp4T.js +++ b/web/dist/assets/risk-histogram-dP0_I5OY.js @@ -1,4 +1,4 @@ -import{$ as e,C as t,E as n,G as r,Q as i,S as a,T as o,W as s,X as c,Z as l,_ as u,d,et as f,f as p,g as m,h,k as g,m as _,p as v,tt as y,v as b,w as x,x as S,y as C}from"./index-NIa5ODC0.js";var w=r(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]),T=r(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),E=r(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),D=r(`rotate-ccw`,[[`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`}]]),O=y(i(),1),k=[`top`,`right`,`bottom`,`left`],A=Math.min,j=Math.max,M=Math.round,N=Math.floor,P=e=>({x:e,y:e}),ee={left:`right`,right:`left`,bottom:`top`,top:`bottom`};function te(e,t,n){return j(e,A(t,n))}function ne(e,t){return typeof e==`function`?e(t):e}function re(e){return e.split(`-`)[0]}function ie(e){return e.split(`-`)[1]}function ae(e){return e===`x`?`y`:`x`}function oe(e){return e===`y`?`height`:`width`}function se(e){let t=e[0];return t===`t`||t===`b`?`y`:`x`}function ce(e){return ae(se(e))}function le(e,t,n){n===void 0&&(n=!1);let r=ie(e),i=ce(e),a=oe(i),o=i===`x`?r===(n?`end`:`start`)?`right`:`left`:r===`start`?`bottom`:`top`;return t.reference[a]>t.floating[a]&&(o=ve(o)),[o,ve(o)]}function ue(e){let t=ve(e);return[de(e),t,de(t)]}function de(e){return e.includes(`start`)?e.replace(`start`,`end`):e.replace(`end`,`start`)}var fe=[`left`,`right`],pe=[`right`,`left`],me=[`top`,`bottom`],he=[`bottom`,`top`];function ge(e,t,n){switch(e){case`top`:case`bottom`:return n?t?pe:fe:t?fe:pe;case`left`:case`right`:return t?me:he;default:return[]}}function _e(e,t,n,r){let i=ie(e),a=ge(re(e),n===`start`,r);return i&&(a=a.map(e=>e+`-`+i),t&&(a=a.concat(a.map(de)))),a}function ve(e){let t=re(e);return ee[t]+e.slice(t.length)}function ye(e){return{top:e.top??0,right:e.right??0,bottom:e.bottom??0,left:e.left??0}}function be(e){return typeof e==`number`?{top:e,right:e,bottom:e,left:e}:ye(e)}function xe(e){let{x:t,y:n,width:r,height:i}=e;return{width:r,height:i,top:n,left:t,right:t+r,bottom:n+i,x:t,y:n}}function Se(e,t,n){let{reference:r,floating:i}=e,a=se(t),o=ce(t),s=oe(o),c=re(t),l=a===`y`,u=r.x+r.width/2-i.width/2,d=r.y+r.height/2-i.height/2,f=r[s]/2-i[s]/2,p;switch(c){case`top`:p={x:u,y:r.y-i.height};break;case`bottom`:p={x:u,y:r.y+r.height};break;case`right`:p={x:r.x+r.width,y:d};break;case`left`:p={x:r.x-i.width,y:d};break;default:p={x:r.x,y:r.y}}let m=ie(t);return m&&(p[o]+=f*(m===`end`?1:-1)*(n&&l?-1:1)),p}async function Ce(e,t){t===void 0&&(t={});let{x:n,y:r,platform:i,rects:a,elements:o,strategy:s}=e,{boundary:c=`clippingAncestors`,rootBoundary:l=`viewport`,elementContext:u=`floating`,altBoundary:d=!1,padding:f=0}=ne(t,e),p=be(f),m=o[d?u===`floating`?`reference`:`floating`:u],h=xe(await i.getClippingRect({element:await(i.isElement==null?void 0:i.isElement(m))??!0?m:m.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(o.floating)),boundary:c,rootBoundary:l,strategy:s})),g=u===`floating`?{x:n,y:r,width:a.floating.width,height:a.floating.height}:a.reference,_=await(i.getOffsetParent==null?void 0:i.getOffsetParent(o.floating)),v=await(i.isElement==null?void 0:i.isElement(_))&&await(i.getScale==null?void 0:i.getScale(_))||{x:1,y:1},y=xe(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:o,rect:g,offsetParent:_,strategy:s}):g);return{top:(h.top-y.top+p.top)/v.y,bottom:(y.bottom-h.bottom+p.bottom)/v.y,left:(h.left-y.left+p.left)/v.x,right:(y.right-h.right+p.right)/v.x}}var we=50,Te=async(e,t,n)=>{let{placement:r=`bottom`,strategy:i=`absolute`,middleware:a=[],platform:o}=n,s=o.detectOverflow?o:{...o,detectOverflow:Ce},c=await(o.isRTL==null?void 0:o.isRTL(t)),l=await o.getElementRects({reference:e,floating:t,strategy:i}),{x:u,y:d}=Se(l,r,c),f=r,p=0,m={};for(let n=0;n({name:`arrow`,options:e,async fn(t){let{x:n,y:r,placement:i,rects:a,platform:o,elements:s,middlewareData:c}=t,{element:l,padding:u=0}=ne(e,t)||{};if(l==null)return{};let d=be(u),f={x:n,y:r},p=ce(i),m=oe(p),h=await o.getDimensions(l),g=p===`y`,_=g?`top`:`left`,v=g?`bottom`:`right`,y=g?`clientHeight`:`clientWidth`,b=a.reference[m]+a.reference[p]-f[p]-a.floating[m],x=f[p]-a.reference[p],S=await(o.getOffsetParent==null?void 0:o.getOffsetParent(l)),C=S?S[y]:0;(!C||!await(o.isElement==null?void 0:o.isElement(S)))&&(C=s.floating[y]||a.floating[m]);let w=b/2-x/2,T=C/2-h[m]/2-1,E=A(d[_],T),D=A(d[v],T),O=C-h[m]-D,k=C/2-h[m]/2+w,j=te(E,k,O),M=!c.arrow&&ie(i)!=null&&k!==j&&a.reference[m]/2-(ke<=0)){let e=(i.flip?.index||0)+1,t=S[e];if(t&&(!(u===`alignment`&&_!==se(t))||T.every(e=>se(e.placement)!==_||e.overflows[0]>0)))return{data:{index:e,overflows:T},reset:{placement:t}};let n=T.filter(e=>e.overflows[0]<=0).sort((e,t)=>e.overflows[1]-t.overflows[1])[0]?.placement;if(!n)switch(f){case`bestFit`:{let e=T.filter(e=>{if(x){let t=se(e.placement);return t===_||t===`y`}return!0}).map(e=>[e.placement,e.overflows.filter(e=>e>0).reduce((e,t)=>e+t,0)]).sort((e,t)=>e[1]-t[1])[0]?.[0];e&&(n=e);break}case`initialPlacement`:n=o;break}if(r!==n)return{reset:{placement:n}}}return{}}}};function Oe(e,t){return{top:e.top-t.height,right:e.right-t.width,bottom:e.bottom-t.height,left:e.left-t.width}}function ke(e){return k.some(t=>e[t]>=0)}var Ae=function(e){return e===void 0&&(e={}),{name:`hide`,options:e,async fn(t){let{rects:n,platform:r}=t,{strategy:i=`referenceHidden`,...a}=ne(e,t);switch(i){case`referenceHidden`:{let e=Oe(await r.detectOverflow(t,{...a,elementContext:`reference`}),n.reference);return{data:{referenceHiddenOffsets:e,referenceHidden:ke(e)}}}case`escaped`:{let e=Oe(await r.detectOverflow(t,{...a,altBoundary:!0}),n.floating);return{data:{escapedOffsets:e,escaped:ke(e)}}}default:return{}}}}},je=new Set([`left`,`top`]);async function Me(e,t){let{placement:n,platform:r,elements:i}=e,a=await(r.isRTL==null?void 0:r.isRTL(i.floating)),o=re(n),s=ie(n),c=se(n)===`y`,l=je.has(o)?-1:1,u=a&&c?-1:1,d=ne(t,e),{mainAxis:f,crossAxis:p,alignmentAxis:m}=typeof d==`number`?{mainAxis:d,crossAxis:0,alignmentAxis:null}:{mainAxis:d.mainAxis||0,crossAxis:d.crossAxis||0,alignmentAxis:d.alignmentAxis};return s&&typeof m==`number`&&(p=s===`end`?m*-1:m),c?{x:p*u,y:f*l}:{x:f*l,y:p*u}}var Ne=function(e){return e===void 0&&(e=0),{name:`offset`,options:e,async fn(t){var n;let{x:r,y:i,placement:a,middlewareData:o}=t,s=await Me(t,e);return a===o.offset?.placement&&(n=o.arrow)!=null&&n.alignmentOffset?{}:{x:r+s.x,y:i+s.y,data:{...s,placement:a}}}}},Pe=function(e){return e===void 0&&(e={}),{name:`shift`,options:e,async fn(t){let{x:n,y:r,placement:i,platform:a}=t,{mainAxis:o=!0,crossAxis:s=!1,limiter:c={fn:e=>{let{x:t,y:n}=e;return{x:t,y:n}}},...l}=ne(e,t),u={x:n,y:r},d=await a.detectOverflow(t,l),f=se(i),p=ae(f),m=u[p],h=u[f],g=(e,t)=>te(t+d[e===`y`?`top`:`left`],t,t-d[e===`y`?`bottom`:`right`]);o&&(m=g(p,m)),s&&(h=g(f,h));let _=c.fn({...t,[p]:m,[f]:h});return{..._,data:{x:_.x-n,y:_.y-r,enabled:{[p]:o,[f]:s}}}}}},Fe=function(e){return e===void 0&&(e={}),{options:e,fn(t){let{x:n,y:r,placement:i,rects:a,middlewareData:o}=t,{offset:s=0,mainAxis:c=!0,crossAxis:l=!0}=ne(e,t),u={x:n,y:r},d=se(i),f=ae(d),p=u[f],m=u[d],h=ne(s,t),g=typeof h==`number`?{mainAxis:h,crossAxis:0}:{mainAxis:h.mainAxis??0,crossAxis:h.crossAxis??0};if(c){let e=f===`y`?`height`:`width`,t=a.reference[f]-a.floating[e]+g.mainAxis,n=a.reference[f]+a.reference[e]-g.mainAxis;pn&&(p=n)}if(l){let e=f===`y`?`width`:`height`,t=je.has(re(i)),n=a.reference[d]-a.floating[e]+(t&&o.offset?.[d]||0)+(t?0:g.crossAxis),r=a.reference[d]+a.reference[e]+(t?0:o.offset?.[d]||0)-(t?g.crossAxis:0);mr&&(m=r)}return{[f]:p,[d]:m}}}},Ie=function(e){return e===void 0&&(e={}),{name:`size`,options:e,async fn(t){let{placement:n,rects:r,platform:i,elements:a}=t,{apply:o=()=>{},...s}=ne(e,t),c=await i.detectOverflow(t,s),l=re(n),u=ie(n),d=se(n)===`y`,{width:f,height:p}=r.floating,m,h;l===`top`||l===`bottom`?(m=l,h=u===(await(i.isRTL==null?void 0:i.isRTL(a.floating))?`start`:`end`)?`left`:`right`):(h=l,m=u===`end`?`top`:`bottom`);let g=p-c.top-c.bottom,_=f-c.left-c.right,v=A(p-c[m],g),y=A(f-c[h],_),b=t.middlewareData.shift,x=!b,S=v,C=y;b!=null&&b.enabled.x&&(C=_),b!=null&&b.enabled.y&&(S=g),x&&!u&&(d?C=f-2*j(c.left,c.right):S=p-2*j(c.top,c.bottom)),await o({...t,availableWidth:C,availableHeight:S});let w=await i.getDimensions(a.floating);return f!==w.width||p!==w.height?{reset:{rects:!0}}:{}}}};function Le(){return typeof window<`u`}function Re(e){return Ve(e)?(e.nodeName||``).toLowerCase():`#document`}function ze(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function Be(e){return((Ve(e)?e.ownerDocument:e.document)||window.document)?.documentElement}function Ve(e){return Le()?e instanceof Node||e instanceof ze(e).Node:!1}function He(e){return Le()?e instanceof Element||e instanceof ze(e).Element:!1}function Ue(e){return Le()?e instanceof HTMLElement||e instanceof ze(e).HTMLElement:!1}function We(e){return!Le()||typeof ShadowRoot>`u`?!1:e instanceof ShadowRoot||e instanceof ze(e).ShadowRoot}function Ge(e){let{overflow:t,overflowX:n,overflowY:r,display:i}=nt(e);return/auto|scroll|overlay|hidden|clip/.test(t+r+n)&&i!==`inline`&&i!==`contents`}function Ke(e){return/^(table|td|th)$/.test(Re(e))}function qe(e){try{if(e.matches(`:popover-open`))return!0}catch{}try{return e.matches(`:modal`)}catch{return!1}}var Je=/transform|translate|scale|rotate|perspective|filter/,Ye=/paint|layout|strict|content/,Xe=e=>!!e&&e!==`none`,Ze;function Qe(e){let t=He(e)?nt(e):e;return Xe(t.transform)||Xe(t.translate)||Xe(t.scale)||Xe(t.rotate)||Xe(t.perspective)||!et()&&(Xe(t.backdropFilter)||Xe(t.filter))||Je.test(t.willChange||``)||Ye.test(t.contain||``)}function $e(e){let t=it(e);for(;Ue(t)&&!tt(t);){if(Qe(t))return t;if(qe(t))return null;t=it(t)}return null}function et(){return Ze??=typeof CSS<`u`&&CSS.supports&&CSS.supports(`-webkit-backdrop-filter`,`none`),Ze}function tt(e){return/^(html|body|#document)$/.test(Re(e))}function nt(e){return ze(e).getComputedStyle(e)}function rt(e){return He(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function it(e){if(Re(e)===`html`)return e;let t=e.assignedSlot||e.parentNode||We(e)&&e.host||Be(e);return We(t)?t.host:t}function at(e){let t=it(e);return tt(t)?(e.ownerDocument||e).body:Ue(t)&&Ge(t)?t:at(t)}function ot(e,t,n){t===void 0&&(t=[]),n===void 0&&(n=!0);let r=at(e),i=r===e.ownerDocument?.body,a=ze(r);if(i){let e=st(a);return t.concat(a,a.visualViewport||[],Ge(r)?r:[],e&&n?ot(e):[])}else return t.concat(r,ot(r,[],n))}function st(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}function ct(e){let t=nt(e),n=parseFloat(t.width)||0,r=parseFloat(t.height)||0,i=Ue(e),a=i?e.offsetWidth:n,o=i?e.offsetHeight:r,s=M(n)!==a||M(r)!==o;return s&&(n=a,r=o),{width:n,height:r,$:s}}function lt(e){return He(e)?e:e.contextElement}function ut(e){let t=lt(e);if(!Ue(t))return P(1);let n=t.getBoundingClientRect(),{width:r,height:i,$:a}=ct(t),o=(a?M(n.width):n.width)/r,s=(a?M(n.height):n.height)/i;return(!o||!Number.isFinite(o))&&(o=1),(!s||!Number.isFinite(s))&&(s=1),{x:o,y:s}}var dt=P(0);function ft(e){let t=ze(e);return!et()||!t.visualViewport?dt:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function pt(e,t,n){return t===void 0&&(t=!1),!!n&&t&&n===ze(e)}function mt(e,t,n,r){t===void 0&&(t=!1),n===void 0&&(n=!1);let i=e.getBoundingClientRect(),a=lt(e),o=P(1);t&&(r?He(r)&&(o=ut(r)):o=ut(e));let s=pt(a,n,r)?ft(a):P(0),c=(i.left+s.x)/o.x,l=(i.top+s.y)/o.y,u=i.width/o.x,d=i.height/o.y;if(a&&r){let e=ze(a),t=He(r)?ze(r):r,n=e,i=st(n);for(;i&&t!==n;){let e=ut(i),t=i.getBoundingClientRect(),r=nt(i),a=t.left+(i.clientLeft+parseFloat(r.paddingLeft))*e.x,o=t.top+(i.clientTop+parseFloat(r.paddingTop))*e.y;c*=e.x,l*=e.y,u*=e.x,d*=e.y,c+=a,l+=o,n=ze(i),i=st(n)}}return xe({width:u,height:d,x:c,y:l})}function ht(e,t){let n=rt(e).scrollLeft;return t?t.left+n:mt(Be(e)).left+n}function gt(e,t){let n=e.getBoundingClientRect();return{x:n.left+t.scrollLeft-ht(e,n),y:n.top+t.scrollTop}}function _t(e){let{elements:t,rect:n,offsetParent:r,strategy:i}=e,a=i===`fixed`,o=Be(r),s=t?qe(t.floating):!1;if(r===o||s&&a)return n;let c={scrollLeft:0,scrollTop:0},l=P(1),u=P(0),d=Ue(r);if((d||!a)&&((Re(r)!==`body`||Ge(o))&&(c=rt(r)),d)){let e=mt(r);l=ut(r),u.x=e.x+r.clientLeft,u.y=e.y+r.clientTop}let f=o&&!d&&!a?gt(o,c):P(0);return{width:n.width*l.x,height:n.height*l.y,x:n.x*l.x-c.scrollLeft*l.x+u.x+f.x,y:n.y*l.y-c.scrollTop*l.y+u.y+f.y}}function vt(e){return e.getClientRects?Array.from(e.getClientRects()):[]}function yt(e){let t=rt(e),n=e.ownerDocument.body,r=j(e.scrollWidth,e.clientWidth,n.scrollWidth,n.clientWidth),i=j(e.scrollHeight,e.clientHeight,n.scrollHeight,n.clientHeight),a=-t.scrollLeft+ht(e),o=-t.scrollTop;return nt(n).direction===`rtl`&&(a+=j(e.clientWidth,n.clientWidth)-r),{width:r,height:i,x:a,y:o}}var bt=25;function xt(e,t,n){n===void 0&&(n=`viewport`);let r=n===`layoutViewport`,i=ze(e),a=Be(e),o=i.visualViewport,s=a.clientWidth,c=a.clientHeight,l=0,u=0;if(o){let e=!et()||t===`fixed`;r?e||(l=-o.offsetLeft,u=-o.offsetTop):(s=o.width,c=o.height,e&&(l=o.offsetLeft,u=o.offsetTop))}if(ht(a)<=0){let e=a.ownerDocument,t=e.body,n=getComputedStyle(t),r=e.compatMode===`CSS1Compat`&&parseFloat(n.marginLeft)+parseFloat(n.marginRight)||0,i=Math.abs(a.clientWidth-t.clientWidth-r),o=getComputedStyle(a).scrollbarGutter===`stable both-edges`?i/2:i;o<=bt&&(s-=o)}return{width:s,height:c,x:l,y:u}}function St(e,t){let n=mt(e,!0,t===`fixed`),r=n.top+e.clientTop,i=n.left+e.clientLeft,a=ut(e);return{width:e.clientWidth*a.x,height:e.clientHeight*a.y,x:i*a.x,y:r*a.y}}function Ct(e,t,n){let r;if(t===`viewport`||t===`layoutViewport`)r=xt(e,n,t);else if(t===`document`)r=yt(Be(e));else if(He(t))r=St(t,n);else{let n=ft(e);r={x:t.x-n.x,y:t.y-n.y,width:t.width,height:t.height}}return xe(r)}function wt(e,t){let n=t.get(e);if(n)return n;let r=ot(e,[],!1).filter(e=>He(e)&&Re(e)!==`body`),i=null,a=nt(e).position===`fixed`,o=a?it(e):e;for(;He(o)&&!tt(o);){let e=nt(o),t=Qe(o),n=i?i.position:a?`fixed`:``;!t&&(n===`fixed`||n===`absolute`&&e.position===`static`)?r=r.filter(e=>e!==o):i=e,o=it(o)}return t.set(e,r),r}function Tt(e){let{element:t,boundary:n,rootBoundary:r,strategy:i}=e,a=[...n===`clippingAncestors`?qe(t)?[]:wt(t,this._c):[].concat(n),r],o=Ct(t,a[0],i),s=o.top,c=o.right,l=o.bottom,u=o.left;for(let e=1;e{s(!1,1e-7)},1e3)}y=!1}try{r=new IntersectionObserver(b,{...v,root:a.ownerDocument})}catch{r=new IntersectionObserver(b,v)}r.observe(e)}let c=ze(e),l=()=>s(n);return c.addEventListener(`resize`,l),s(!0),()=>{c.removeEventListener(`resize`,l),o()}}function It(e,t,n,r){r===void 0&&(r={});let{ancestorScroll:i=!0,ancestorResize:a=!0,elementResize:o=typeof ResizeObserver==`function`,layoutShift:s=typeof IntersectionObserver==`function`,animationFrame:c=!1}=r,l=lt(e),u=i||a?[...l?ot(l):[],...t?ot(t):[]]:[];u.forEach(e=>{i&&e.addEventListener(`scroll`,n),a&&e.addEventListener(`resize`,n)});let d=l&&s?Ft(l,n,a):null,f=-1,p=null;o&&(p=new ResizeObserver(e=>{let[r]=e;r&&r.target===l&&p&&t&&(p.unobserve(t),cancelAnimationFrame(f),f=requestAnimationFrame(()=>{var e;(e=p)==null||e.observe(t)})),n()}),l&&!c&&p.observe(l),t&&p.observe(t));let m,h=c?mt(e):null;c&&g();function g(){let t=mt(e);h&&!Pt(h,t)&&n(),h=t,m=requestAnimationFrame(g)}return n(),()=>{var e;u.forEach(e=>{i&&e.removeEventListener(`scroll`,n),a&&e.removeEventListener(`resize`,n)}),d?.(),(e=p)==null||e.disconnect(),p=null,c&&cancelAnimationFrame(m)}}var Lt=Ne,Rt=Pe,zt=De,Bt=Ie,Vt=Ae,Ht=Ee,Ut=Fe,Wt=(e,t,n)=>{let r=new Map,i=n??{},a={...Nt,...i.platform,_c:r};return Te(e,t,{...i,platform:a})},Gt=y(l(),1),Kt=typeof document<`u`?O.useLayoutEffect:function(){};function qt(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typeof e==`function`&&e.toString()===t.toString())return!0;let n,r,i;if(e&&t&&typeof e==`object`){if(Array.isArray(e)){if(n=e.length,n!==t.length)return!1;for(r=n;r--!==0;)if(!qt(e[r],t[r]))return!1;return!0}if(i=Object.keys(e),n=i.length,n!==Object.keys(t).length)return!1;for(r=n;r--!==0;)if(!{}.hasOwnProperty.call(t,i[r]))return!1;for(r=n;r--!==0;){let n=i[r];if(!(n===`_owner`&&e.$$typeof)&&!qt(e[n],t[n]))return!1}return!0}return e!==e&&t!==t}function Jt(e){return typeof window>`u`?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function Yt(e,t){let n=Jt(e);return Math.round(t*n)/n}function Xt(e){let t=O.useRef(e);return Kt(()=>{t.current=e}),t}function Zt(e){e===void 0&&(e={});let{placement:t=`bottom`,strategy:n=`absolute`,middleware:r=[],platform:i,elements:{reference:a,floating:o}={},transform:s=!0,whileElementsMounted:c,open:l}=e,[u,d]=O.useState({x:0,y:0,strategy:n,placement:t,middlewareData:{},isPositioned:!1}),[f,p]=O.useState(r);qt(f,r)||p(r);let[m,h]=O.useState(null),[g,_]=O.useState(null),v=O.useCallback(e=>{e!==S.current&&(S.current=e,h(e))},[]),y=O.useCallback(e=>{e!==C.current&&(C.current=e,_(e))},[]),b=a||m,x=o||g,S=O.useRef(null),C=O.useRef(null),w=O.useRef(u),T=c!=null,E=Xt(c),D=Xt(i),k=Xt(l),A=O.useCallback(()=>{if(!S.current||!C.current)return;let e={placement:t,strategy:n,middleware:f};D.current&&(e.platform=D.current),Wt(S.current,C.current,e).then(e=>{let t={...e,isPositioned:k.current!==!1};j.current&&!qt(w.current,t)&&(w.current=t,Gt.flushSync(()=>{d(t)}))})},[f,t,n,D,k]);Kt(()=>{l===!1&&w.current.isPositioned&&(w.current.isPositioned=!1,d(e=>({...e,isPositioned:!1})))},[l]);let j=O.useRef(!1);Kt(()=>(j.current=!0,()=>{j.current=!1}),[]),Kt(()=>{if(b&&(S.current=b),x&&(C.current=x),b&&x){if(E.current)return E.current(b,x,A);A()}},[b,x,A,E,T]);let M=O.useMemo(()=>({reference:S,floating:C,setReference:v,setFloating:y}),[v,y]),N=O.useMemo(()=>({reference:b,floating:x}),[b,x]),P=O.useMemo(()=>{let e={position:n,left:0,top:0};if(!N.floating)return e;let t=Yt(N.floating,u.x),r=Yt(N.floating,u.y);return s?{...e,transform:`translate(`+t+`px, `+r+`px)`,...Jt(N.floating)>=1.5&&{willChange:`transform`}}:{position:n,left:t,top:r}},[n,s,N.floating,u.x,u.y]);return O.useMemo(()=>({...u,update:A,refs:M,elements:N,floatingStyles:P}),[u,A,M,N,P])}var Qt=e=>{function t(e){return{}.hasOwnProperty.call(e,`current`)}return{name:`arrow`,options:e,fn(n){let{element:r,padding:i}=typeof e==`function`?e(n):e;return r&&t(r)?r.current==null?{}:Ht({element:r.current,padding:i}).fn(n):r?Ht({element:r,padding:i}).fn(n):{}}}},$t=(e,t)=>{let n=Lt(e);return{name:n.name,fn:n.fn,options:[e,t]}},en=(e,t)=>{let n=Rt(e);return{name:n.name,fn:n.fn,options:[e,t]}},tn=(e,t)=>({fn:Ut(e).fn,options:[e,t]}),nn=(e,t)=>{let n=zt(e);return{name:n.name,fn:n.fn,options:[e,t]}},rn=(e,t)=>{let n=Bt(e);return{name:n.name,fn:n.fn,options:[e,t]}},an=(e,t)=>{let n=Vt(e);return{name:n.name,fn:n.fn,options:[e,t]}},on=(e,t)=>{let n=Qt(e);return{name:n.name,fn:n.fn,options:[e,t]}};function sn(e){let[t,n]=O.useState(void 0);return x(()=>{if(e){n({width:e.offsetWidth,height:e.offsetHeight});let t=new ResizeObserver(t=>{if(!Array.isArray(t)||!t.length)return;let r=t[0],i,a;if(`borderBoxSize`in r){let e=r.borderBoxSize,t=Array.isArray(e)?e[0]:e;i=t.inlineSize,a=t.blockSize}else i=e.offsetWidth,a=e.offsetHeight;n({width:i,height:a})});return t.observe(e,{box:`border-box`}),()=>t.unobserve(e)}else n(void 0)},[e]),t}var F=c(),cn=Object.defineProperty,ln=(e,t)=>cn(e,`name`,{value:t,configurable:!0}),un=`Popper`,[dn,fn]=o(un),[pn,mn]=dn(un),hn=ln(e=>{let{__scopePopper:t,children:n}=e,[r,i]=O.useState(null),[a,o]=O.useState(void 0);return(0,F.jsx)(pn,{scope:t,anchor:r,onAnchorChange:i,placementState:a,setPlacementState:o,children:n})},`Popper`),gn=`PopperAnchor`,_n=O.forwardRef(ln(function(e,t){let{__scopePopper:n,virtualRef:r,...i}=e,o=mn(gn,n),s=O.useRef(null),c=o.onAnchorChange,l=a(t,O.useCallback(e=>{s.current=e,e&&c(e)},[c])),u=O.useRef(null);O.useEffect(()=>{if(!r)return;let e=u.current;u.current=r.current,e!==u.current&&c(u.current)});let d=o.placementState&&wn(o.placementState),f=d?.[0],p=d?.[1];return r?null:(0,F.jsx)(C.div,{"data-radix-popper-side":f,"data-radix-popper-align":p,...i,ref:l})},`PopperAnchor`)),vn=`PopperContent`,[yn,bn]=dn(vn),xn=O.forwardRef(ln(function(e,t){let{__scopePopper:n,side:r=`bottom`,sideOffset:i=0,align:o=`center`,alignOffset:s=0,arrowPadding:c=0,avoidCollisions:l=!0,collisionBoundary:u=[],collisionPadding:d=0,sticky:f=`partial`,hideWhenDetached:p=!1,updatePositionStrategy:h=`optimized`,onPlaced:g,..._}=e,v=mn(vn,n),[y,b]=O.useState(null),S=a(t,b),[w,T]=O.useState(null),E=sn(w),D=E?.width??0,k=E?.height??0,A=r+(o===`center`?``:`-`+o),j=typeof d==`number`?d:{top:0,right:0,bottom:0,left:0,...d},M=Array.isArray(u)?u:[u],N=M.length>0,P={padding:j,boundary:M.filter(Sn),altBoundary:N},{refs:ee,floatingStyles:te,placement:ne,isPositioned:re,middlewareData:ie}=Zt({strategy:`fixed`,placement:A,whileElementsMounted:ln((...e)=>It(...e,{animationFrame:h===`always`}),`whileElementsMounted`),elements:{reference:v.anchor},middleware:[$t({mainAxis:i+k,alignmentAxis:s}),l&&en({mainAxis:!0,crossAxis:!1,limiter:f===`partial`?tn():void 0,...P}),l&&nn({...P}),rn({...P,apply:ln(({elements:e,rects:t,availableWidth:n,availableHeight:r})=>{let{width:i,height:a}=t.reference,o=e.floating.style;o.setProperty(`--radix-popper-available-width`,`${n}px`),o.setProperty(`--radix-popper-available-height`,`${r}px`),o.setProperty(`--radix-popper-anchor-width`,`${i}px`),o.setProperty(`--radix-popper-anchor-height`,`${a}px`)},`apply`)}),w&&on({element:w,padding:c}),Cn({arrowWidth:D,arrowHeight:k}),p&&an({strategy:`referenceHidden`,...P,boundary:N?P.boundary:void 0})]}),ae=v.setPlacementState;x(()=>(ae(ne),()=>{ae(void 0)}),[ne,ae]);let[oe,se]=wn(ne),ce=m(g);x(()=>{re&&ce?.()},[re,ce]);let le=ie.arrow?.x,ue=ie.arrow?.y,de=ie.arrow?.centerOffset!==0,[fe,pe]=O.useState();return x(()=>{y&&pe(window.getComputedStyle(y).zIndex)},[y]),(0,F.jsx)(`div`,{ref:ee.setFloating,"data-radix-popper-content-wrapper":``,style:{...te,transform:re?te.transform:`translate(0, -200%)`,minWidth:`max-content`,zIndex:fe,"--radix-popper-transform-origin":[ie.transformOrigin?.x,ie.transformOrigin?.y].join(` `),...ie.hide?.referenceHidden&&{visibility:`hidden`,pointerEvents:`none`}},dir:e.dir,children:(0,F.jsx)(yn,{scope:n,placedSide:oe,placedAlign:se,onArrowChange:T,arrowX:le,arrowY:ue,shouldHideArrow:de,children:(0,F.jsx)(C.div,{"data-side":oe,"data-align":se,..._,ref:S,style:{..._.style,animation:re?_.style?.animation:`none`}})})})},`PopperContent`));function Sn(e){return e!==null}ln(Sn,`isNotNull`);var Cn=ln(e=>({name:`transformOrigin`,options:e,fn(t){let{placement:n,rects:r,middlewareData:i}=t,a=i.arrow?.centerOffset!==0,o=a?0:e.arrowWidth,s=a?0:e.arrowHeight,[c,l]=wn(n),u={start:`0%`,center:`50%`,end:`100%`}[l],d=(i.arrow?.x??0)+o/2,f=(i.arrow?.y??0)+s/2,p=``,m=``;return c===`bottom`?(p=a?u:`${d}px`,m=`${-s}px`):c===`top`?(p=a?u:`${d}px`,m=`${r.floating.height+s}px`):c===`right`?(p=`${-s}px`,m=a?u:`${f}px`):c===`left`&&(p=`${r.floating.width+s}px`,m=a?u:`${f}px`),{data:{x:p,y:m}}}}),`transformOrigin`);function wn(e){let[t,n=`center`]=e.split(`-`);return[t,n]}ln(wn,`getSideAndAlignFromPlacement`);var Tn=hn,En=_n,Dn=xn,On=Object.defineProperty,kn=(e,t)=>On(e,`name`,{value:t,configurable:!0}),An=Object.freeze({position:`absolute`,border:0,width:1,height:1,padding:0,margin:-1,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,whiteSpace:`nowrap`,wordWrap:`normal`}),jn=O.forwardRef(kn(function(e,t){return(0,F.jsx)(C.span,{...e,ref:t,style:{...An,...e.style}})},`VisuallyHidden`)),Mn=Object.defineProperty,Nn=(e,t)=>Mn(e,`name`,{value:t,configurable:!0}),[Pn,Fn]=o(`Tooltip`,[fn]),In=fn(),Ln=`TooltipProvider`,Rn=700,zn=`tooltip.open`,[Bn,Vn]=Pn(Ln),Hn=Nn(e=>{let{__scopeTooltip:t,delayDuration:n=Rn,skipDelayDuration:r=300,disableHoverableContent:i=!1,children:a}=e,o=O.useRef(!0),s=O.useRef(!1),c=O.useRef(0);return O.useEffect(()=>{let e=c.current;return()=>window.clearTimeout(e)},[]),(0,F.jsx)(Bn,{scope:t,isOpenDelayedRef:o,delayDuration:n,onOpen:O.useCallback(()=>{r<=0||(window.clearTimeout(c.current),o.current=!1)},[r]),onClose:O.useCallback(()=>{r<=0||(window.clearTimeout(c.current),c.current=window.setTimeout(()=>o.current=!0,r))},[r]),isPointerInTransitRef:s,onPointerInTransitChange:O.useCallback(e=>{s.current=e},[]),disableHoverableContent:i,children:a})},`TooltipProvider`),Un=`Tooltip`,[Wn,Gn]=Pn(Un),Kn=Nn(e=>{let{__scopeTooltip:n,children:r,open:i,defaultOpen:a,onOpenChange:o,disableHoverableContent:s,delayDuration:c}=e,l=Vn(Un,e.__scopeTooltip),d=In(n),[f,p]=O.useState(null),[m,h]=O.useState(void 0),g=u(),_=O.useRef(0),v=s??l.disableHoverableContent,y=c??l.delayDuration,b=O.useRef(!1),[x,S]=t({prop:i,defaultProp:a??!1,onChange:Nn(e=>{e?(l.onOpen(),document.dispatchEvent(new CustomEvent(zn))):l.onClose(),o?.(e)},`onChange`),caller:Un}),C=O.useMemo(()=>x?b.current?`delayed-open`:`instant-open`:`closed`,[x]),w=O.useCallback(()=>{window.clearTimeout(_.current),_.current=0,b.current=!1,S(!0)},[S]),T=O.useCallback(()=>{window.clearTimeout(_.current),_.current=0,S(!1)},[S]),E=O.useCallback(()=>{window.clearTimeout(_.current),_.current=window.setTimeout(()=>{b.current=!0,S(!0),_.current=0},y)},[y,S]);O.useEffect(()=>()=>{_.current&&=(window.clearTimeout(_.current),0)},[]);let D=m??g;return(0,F.jsx)(Tn,{...d,children:(0,F.jsx)(Wn,{scope:n,contentId:D,setContentId:h,open:x,stateAttribute:C,trigger:f,onTriggerChange:p,onTriggerEnter:O.useCallback(()=>{l.isOpenDelayedRef.current?E():w()},[l.isOpenDelayedRef,E,w]),onTriggerLeave:O.useCallback(()=>{v?T():(window.clearTimeout(_.current),_.current=0)},[T,v]),onOpen:w,onClose:T,disableHoverableContent:v,children:r})})},`Tooltip`),qn=`TooltipTrigger`,Jn=O.forwardRef(Nn(function(e,t){let{__scopeTooltip:r,...i}=e,o=Gn(qn,r),s=Vn(qn,r),c=In(r),l=a(t,O.useRef(null),o.onTriggerChange),u=O.useRef(!1),d=O.useRef(!1),f=O.useCallback(()=>u.current=!1,[]);return O.useEffect(()=>()=>document.removeEventListener(`pointerup`,f),[f]),(0,F.jsx)(En,{asChild:!0,...c,children:(0,F.jsx)(C.button,{"aria-describedby":o.open?o.contentId:void 0,"data-state":o.stateAttribute,...i,ref:l,onPointerMove:n(e.onPointerMove,e=>{e.pointerType!==`touch`&&!d.current&&!s.isPointerInTransitRef.current&&(o.onTriggerEnter(),d.current=!0)}),onPointerLeave:n(e.onPointerLeave,()=>{o.onTriggerLeave(),d.current=!1}),onPointerDown:n(e.onPointerDown,()=>{o.open&&o.onClose(),u.current=!0,document.addEventListener(`pointerup`,f,{once:!0})}),onFocus:n(e.onFocus,()=>{u.current||o.onOpen()}),onBlur:n(e.onBlur,o.onClose),onClick:n(e.onClick,o.onClose)})})},`TooltipTrigger`)),Yn=`TooltipPortal`,[Xn,Zn]=Pn(Yn,{forceMount:void 0}),Qn=Nn(e=>{let{__scopeTooltip:t,forceMount:n,children:r,container:i}=e,a=Gn(Yn,t);return(0,F.jsx)(Xn,{scope:t,forceMount:n,children:(0,F.jsx)(b,{present:n||a.open,children:(0,F.jsx)(_,{asChild:!0,container:i,children:r})})})},`TooltipPortal`),$n=`TooltipContent`,er=O.forwardRef(Nn(function(e,t){let n=Zn($n,e.__scopeTooltip),{forceMount:r=n.forceMount,side:i=`top`,...a}=e,o=Gn($n,e.__scopeTooltip);return(0,F.jsx)(b,{present:r||o.open,children:o.disableHoverableContent?(0,F.jsx)(rr,{side:i,...a,ref:t}):(0,F.jsx)(tr,{side:i,...a,ref:t})})},`TooltipContent`)),tr=O.forwardRef(Nn(function(e,t){let n=Gn($n,e.__scopeTooltip),r=Vn($n,e.__scopeTooltip),i=O.useRef(null),o=a(t,i),[s,c]=O.useState(null),{trigger:l,onClose:u}=n,d=i.current,{onPointerInTransitChange:f}=r,p=O.useCallback(()=>{c(null),f(!1)},[f]),m=O.useCallback((e,t)=>{let n=e.currentTarget,r={x:e.clientX,y:e.clientY},i=ar(r,ir(r,n.getBoundingClientRect())),a=or(t.getBoundingClientRect()),o=cr([...i,...a]);c(o),f(!0)},[f]);return O.useEffect(()=>()=>p(),[p]),O.useEffect(()=>{if(l&&d){let e=Nn(e=>m(e,d),`handleTriggerLeave`),t=Nn(e=>m(e,l),`handleContentLeave`);return l.addEventListener(`pointerleave`,e),d.addEventListener(`pointerleave`,t),()=>{l.removeEventListener(`pointerleave`,e),d.removeEventListener(`pointerleave`,t)}}},[l,d,m,p]),O.useEffect(()=>{if(s){let e=Nn(e=>{let t=e.target,n={x:e.clientX,y:e.clientY},r=l?.contains(t)||d?.contains(t),i=!sr(n,s);r?p():i&&(p(),u())},`handleTrackPointerGrace`);return document.addEventListener(`pointermove`,e),()=>document.removeEventListener(`pointermove`,e)}},[l,d,s,u,p]),(0,F.jsx)(rr,{...e,ref:o})},`TooltipContentHoverable`)),nr=S(`TooltipContent`),rr=O.forwardRef(Nn(function(e,t){let{__scopeTooltip:n,children:r,"aria-label":i,id:a,onEscapeKeyDown:o,onPointerDownOutside:s,...c}=e,l=Gn($n,n),u=In(n),{onClose:d}=l;O.useEffect(()=>(document.addEventListener(zn,d),()=>document.removeEventListener(zn,d)),[d]),O.useEffect(()=>{if(l.trigger){let e=Nn(e=>{e.target instanceof Node&&e.target.contains(l.trigger)&&d()},`handleScroll`);return window.addEventListener(`scroll`,e,{capture:!0}),()=>window.removeEventListener(`scroll`,e,{capture:!0})}},[l.trigger,d]);let{setContentId:f}=l;return x(()=>(f(a),()=>{f(void 0)}),[a,f]),(0,F.jsx)(h,{asChild:!0,disableOutsidePointerEvents:!1,onEscapeKeyDown:o,onPointerDownOutside:s,onFocusOutside:e=>e.preventDefault(),onDismiss:d,children:(0,F.jsxs)(Dn,{"data-state":l.stateAttribute,role:i?void 0:`tooltip`,id:i?void 0:l.contentId,...u,...c,ref:t,style:{...c.style,"--radix-tooltip-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-tooltip-content-available-width":`var(--radix-popper-available-width)`,"--radix-tooltip-content-available-height":`var(--radix-popper-available-height)`,"--radix-tooltip-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-tooltip-trigger-height":`var(--radix-popper-anchor-height)`},children:[(0,F.jsx)(nr,{children:r}),i?(0,F.jsx)(jn,{id:l.contentId,role:`tooltip`,children:i}):null]})})},`TooltipContentImpl`));function ir(e,t){let n=Math.abs(t.top-e.y),r=Math.abs(t.bottom-e.y),i=Math.abs(t.right-e.x),a=Math.abs(t.left-e.x);switch(Math.min(n,r,i,a)){case a:return`left`;case i:return`right`;case n:return`top`;case r:return`bottom`;default:throw Error(`unreachable`)}}Nn(ir,`getExitSideFromRect`);function ar(e,t,n=5){let r=[];switch(t){case`top`:r.push({x:e.x-n,y:e.y+n},{x:e.x+n,y:e.y+n});break;case`bottom`:r.push({x:e.x-n,y:e.y-n},{x:e.x+n,y:e.y-n});break;case`left`:r.push({x:e.x+n,y:e.y-n},{x:e.x+n,y:e.y+n});break;case`right`:r.push({x:e.x-n,y:e.y-n},{x:e.x-n,y:e.y+n});break}return r}Nn(ar,`getPaddedExitPoints`);function or(e){let{top:t,right:n,bottom:r,left:i}=e;return[{x:i,y:t},{x:n,y:t},{x:n,y:r},{x:i,y:r}]}Nn(or,`getPointsFromRect`);function sr(e,t){let{x:n,y:r}=e,i=!1;for(let e=0,a=t.length-1;er!=d>r&&n<(u-c)*(r-l)/(d-l)+c&&(i=!i)}return i}Nn(sr,`isPointInPolygon`);function cr(e){let t=e.slice();return t.sort((e,t)=>e.xt.x?1:e.yt.y)),lr(t)}Nn(cr,`getHull`);function lr(e){if(e.length<=1)return e.slice();let t=[];for(let n=0;n=2;){let e=t[t.length-1],n=t[t.length-2];if((e.x-n.x)*(r.y-n.y)>=(e.y-n.y)*(r.x-n.x))t.pop();else break}t.push(r)}t.pop();let n=[];for(let t=e.length-1;t>=0;t--){let r=e[t];for(;n.length>=2;){let e=n[n.length-1],t=n[n.length-2];if((e.x-t.x)*(r.y-t.y)>=(e.y-t.y)*(r.x-t.x))n.pop();else break}n.push(r)}return n.pop(),t.length===1&&n.length===1&&t[0].x===n[0].x&&t[0].y===n[0].y?t:t.concat(n)}Nn(lr,`getHullPresorted`);var ur=Hn,dr=Kn,fr=Jn,pr=Qn,mr=er,hr=ur,gr=dr,_r=fr,vr=(0,O.forwardRef)(({className:e,sideOffset:t=6,...n},r)=>(0,F.jsx)(pr,{children:(0,F.jsx)(mr,{ref:r,sideOffset:t,className:[`tooltip-content`,e].filter(Boolean).join(` `),...n})}));vr.displayName=`TooltipContent`;function yr({rows:e}){let[t,n]=(0,O.useState)(()=>new Set),r=[...e].sort((e,t)=>t.hit_count-e.hit_count||e.ip.localeCompare(t.ip));if(r.length===0)return(0,F.jsx)(`p`,{className:`section-empty`,children:`IP reputation rows appear after an egress IP is observed.`});let i=e=>n(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n});return(0,F.jsxs)(hr,{delayDuration:250,children:[(0,F.jsx)(`div`,{className:`ip-table-wrap`,children:(0,F.jsxs)(`table`,{className:`table ip-table`,children:[(0,F.jsx)(`thead`,{children:(0,F.jsxs)(`tr`,{children:[(0,F.jsx)(`th`,{scope:`col`,children:`IP`}),(0,F.jsx)(`th`,{scope:`col`,children:`Category`}),(0,F.jsx)(`th`,{scope:`col`,children:`Country`}),(0,F.jsx)(`th`,{scope:`col`,children:`ISP`}),(0,F.jsx)(`th`,{scope:`col`,children:`ASN`}),(0,F.jsx)(`th`,{scope:`col`,children:`Risk`}),(0,F.jsx)(`th`,{scope:`col`,children:`GreyNoise`}),(0,F.jsx)(`th`,{scope:`col`,children:`DNSBL`}),(0,F.jsx)(`th`,{scope:`col`,children:`First seen`}),(0,F.jsx)(`th`,{scope:`col`,children:`Last seen`}),(0,F.jsx)(`th`,{scope:`col`,children:`Hits`})]})}),(0,F.jsx)(`tbody`,{children:r.map(e=>(0,F.jsxs)(`tr`,{children:[(0,F.jsx)(`th`,{scope:`row`,className:`mono`,children:e.ip}),(0,F.jsx)(`td`,{children:(0,F.jsx)(xr,{category:e.category})}),(0,F.jsx)(`td`,{children:e.country||`—`}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`Full ISP for ${e.ip}`,value:e.isp||`—`})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`Full ASN for ${e.ip}`,value:e.asn||`—`})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(Sr,{score:e.risk_score})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`Full GreyNoise classification for ${e.ip}`,value:e.greynoise_class||`—`})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`DNSBL details for ${e.ip}`,value:e.dnsbl_listed?`Listed: ${e.dnsbl_hits.join(`, `)||`unspecified list`}`:`Not listed`})}),(0,F.jsx)(`td`,{children:v(e.first_seen)}),(0,F.jsx)(`td`,{children:v(e.last_seen)}),(0,F.jsx)(`td`,{className:`numeric`,children:e.hit_count})]},e.ip))})]})}),(0,F.jsx)(`div`,{className:`ip-records`,children:r.map(e=>{let n=t.has(e.ip);return(0,F.jsxs)(`article`,{className:`ip-record`,children:[(0,F.jsxs)(`div`,{className:`ip-record-summary`,children:[(0,F.jsx)(`strong`,{className:`mono`,children:e.ip}),(0,F.jsx)(xr,{category:e.category}),(0,F.jsx)(Sr,{score:e.risk_score})]}),(0,F.jsxs)(`button`,{type:`button`,className:`ip-details-trigger`,"aria-expanded":n,"aria-controls":`ip-${wr(e.ip)}-details`,onClick:()=>i(e.ip),children:[n?(0,F.jsx)(s,{size:16,"aria-hidden":`true`}):(0,F.jsx)(w,{size:16,"aria-hidden":`true`}),` `,n?`Hide`:`Show`,` details for `,e.ip]}),n&&(0,F.jsxs)(`dl`,{id:`ip-${wr(e.ip)}-details`,className:`ip-details`,children:[(0,F.jsx)(Cr,{label:`Country`,value:e.country||`—`}),(0,F.jsx)(Cr,{label:`ISP`,value:e.isp||`—`}),(0,F.jsx)(Cr,{label:`ASN`,value:e.asn||`—`}),(0,F.jsx)(Cr,{label:`GreyNoise`,value:e.greynoise_class||`—`}),(0,F.jsx)(Cr,{label:`DNSBL`,value:e.dnsbl_listed?`Listed: ${e.dnsbl_hits.join(`, `)||`unspecified list`}`:`Not listed`}),(0,F.jsx)(Cr,{label:`First seen`,value:v(e.first_seen)}),(0,F.jsx)(Cr,{label:`Last seen`,value:v(e.last_seen)}),(0,F.jsx)(Cr,{label:`Hits`,value:String(e.hit_count)})]})]},e.ip)})})]})}function br({value:e,label:t}){return(0,F.jsxs)(gr,{children:[(0,F.jsx)(_r,{asChild:!0,children:(0,F.jsxs)(`button`,{type:`button`,className:`clipped-value`,"aria-label":t,children:[e,(0,F.jsx)(E,{size:13,"aria-hidden":`true`})]})}),(0,F.jsx)(vr,{side:`top`,children:e})]})}function xr({category:e}){return(0,F.jsxs)(`span`,{className:`category-label category-${[`mobile`,`residential`,`datacenter`].includes(e)?e:`unknown`}`,children:[(0,F.jsx)(`span`,{className:`category-dot`,"aria-hidden":`true`}),e||`unknown`]})}function Sr({score:e}){if(e==null)return(0,F.jsx)(`span`,{className:`risk-label risk-unknown`,children:`Unknown`});let t=e>=70?`High`:e>=40?`Elevated`:`Low`;return(0,F.jsxs)(`span`,{className:`risk-label risk-${t.toLowerCase()}`,children:[t,` `,e]})}function Cr({label:e,value:t}){return(0,F.jsxs)(`div`,{children:[(0,F.jsx)(`dt`,{children:e}),(0,F.jsx)(`dd`,{children:t})]})}function wr(e){return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}var Tr=`dangerouslySetInnerHTML.onCopy.onCopyCapture.onCut.onCutCapture.onPaste.onPasteCapture.onCompositionEnd.onCompositionEndCapture.onCompositionStart.onCompositionStartCapture.onCompositionUpdate.onCompositionUpdateCapture.onFocus.onFocusCapture.onBlur.onBlurCapture.onChange.onChangeCapture.onBeforeInput.onBeforeInputCapture.onInput.onInputCapture.onReset.onResetCapture.onSubmit.onSubmitCapture.onInvalid.onInvalidCapture.onLoad.onLoadCapture.onError.onErrorCapture.onKeyDown.onKeyDownCapture.onKeyPress.onKeyPressCapture.onKeyUp.onKeyUpCapture.onAbort.onAbortCapture.onCanPlay.onCanPlayCapture.onCanPlayThrough.onCanPlayThroughCapture.onDurationChange.onDurationChangeCapture.onEmptied.onEmptiedCapture.onEncrypted.onEncryptedCapture.onEnded.onEndedCapture.onLoadedData.onLoadedDataCapture.onLoadedMetadata.onLoadedMetadataCapture.onLoadStart.onLoadStartCapture.onPause.onPauseCapture.onPlay.onPlayCapture.onPlaying.onPlayingCapture.onProgress.onProgressCapture.onRateChange.onRateChangeCapture.onSeeked.onSeekedCapture.onSeeking.onSeekingCapture.onStalled.onStalledCapture.onSuspend.onSuspendCapture.onTimeUpdate.onTimeUpdateCapture.onVolumeChange.onVolumeChangeCapture.onWaiting.onWaitingCapture.onAuxClick.onAuxClickCapture.onClick.onClickCapture.onContextMenu.onContextMenuCapture.onDoubleClick.onDoubleClickCapture.onDrag.onDragCapture.onDragEnd.onDragEndCapture.onDragEnter.onDragEnterCapture.onDragExit.onDragExitCapture.onDragLeave.onDragLeaveCapture.onDragOver.onDragOverCapture.onDragStart.onDragStartCapture.onDrop.onDropCapture.onMouseDown.onMouseDownCapture.onMouseEnter.onMouseLeave.onMouseMove.onMouseMoveCapture.onMouseOut.onMouseOutCapture.onMouseOver.onMouseOverCapture.onMouseUp.onMouseUpCapture.onSelect.onSelectCapture.onTouchCancel.onTouchCancelCapture.onTouchEnd.onTouchEndCapture.onTouchMove.onTouchMoveCapture.onTouchStart.onTouchStartCapture.onPointerDown.onPointerDownCapture.onPointerMove.onPointerMoveCapture.onPointerUp.onPointerUpCapture.onPointerCancel.onPointerCancelCapture.onPointerEnter.onPointerEnterCapture.onPointerLeave.onPointerLeaveCapture.onPointerOver.onPointerOverCapture.onPointerOut.onPointerOutCapture.onGotPointerCapture.onGotPointerCaptureCapture.onLostPointerCapture.onLostPointerCaptureCapture.onScroll.onScrollCapture.onWheel.onWheelCapture.onAnimationStart.onAnimationStartCapture.onAnimationEnd.onAnimationEndCapture.onAnimationIteration.onAnimationIterationCapture.onTransitionEnd.onTransitionEndCapture`.split(`.`);function Er(e){return typeof e==`string`&&Tr.includes(e)}var Dr=new Set(`aria-activedescendant.aria-atomic.aria-autocomplete.aria-busy.aria-checked.aria-colcount.aria-colindex.aria-colspan.aria-controls.aria-current.aria-describedby.aria-details.aria-disabled.aria-errormessage.aria-expanded.aria-flowto.aria-haspopup.aria-hidden.aria-invalid.aria-keyshortcuts.aria-label.aria-labelledby.aria-level.aria-live.aria-modal.aria-multiline.aria-multiselectable.aria-orientation.aria-owns.aria-placeholder.aria-posinset.aria-pressed.aria-readonly.aria-relevant.aria-required.aria-roledescription.aria-rowcount.aria-rowindex.aria-rowspan.aria-selected.aria-setsize.aria-sort.aria-valuemax.aria-valuemin.aria-valuenow.aria-valuetext.className.color.height.id.lang.max.media.method.min.name.style.target.width.role.tabIndex.accentHeight.accumulate.additive.alignmentBaseline.allowReorder.alphabetic.amplitude.arabicForm.ascent.attributeName.attributeType.autoReverse.azimuth.baseFrequency.baselineShift.baseProfile.bbox.begin.bias.by.calcMode.capHeight.clip.clipPath.clipPathUnits.clipRule.colorInterpolation.colorInterpolationFilters.colorProfile.colorRendering.contentScriptType.contentStyleType.cursor.cx.cy.d.decelerate.descent.diffuseConstant.direction.display.divisor.dominantBaseline.dur.dx.dy.edgeMode.elevation.enableBackground.end.exponent.externalResourcesRequired.fill.fillOpacity.fillRule.filter.filterRes.filterUnits.floodColor.floodOpacity.focusable.fontFamily.fontSize.fontSizeAdjust.fontStretch.fontStyle.fontVariant.fontWeight.format.from.fx.fy.g1.g2.glyphName.glyphOrientationHorizontal.glyphOrientationVertical.glyphRef.gradientTransform.gradientUnits.hanging.horizAdvX.horizOriginX.href.ideographic.imageRendering.in2.in.intercept.k1.k2.k3.k4.k.kernelMatrix.kernelUnitLength.kerning.keyPoints.keySplines.keyTimes.lengthAdjust.letterSpacing.lightingColor.limitingConeAngle.local.markerEnd.markerHeight.markerMid.markerStart.markerUnits.markerWidth.mask.maskContentUnits.maskUnits.mathematical.mode.numOctaves.offset.opacity.operator.order.orient.orientation.origin.overflow.overlinePosition.overlineThickness.paintOrder.panose1.pathLength.patternContentUnits.patternTransform.patternUnits.pointerEvents.pointsAtX.pointsAtY.pointsAtZ.preserveAlpha.preserveAspectRatio.primitiveUnits.r.radius.refX.refY.renderingIntent.repeatCount.repeatDur.requiredExtensions.requiredFeatures.restart.result.rotate.rx.ry.seed.shapeRendering.slope.spacing.specularConstant.specularExponent.speed.spreadMethod.startOffset.stdDeviation.stemh.stemv.stitchTiles.stopColor.stopOpacity.strikethroughPosition.strikethroughThickness.string.stroke.strokeDasharray.strokeDashoffset.strokeLinecap.strokeLinejoin.strokeMiterlimit.strokeOpacity.strokeWidth.surfaceScale.systemLanguage.tableValues.targetX.targetY.textAnchor.textDecoration.textLength.textRendering.to.transform.u1.u2.underlinePosition.underlineThickness.unicode.unicodeBidi.unicodeRange.unitsPerEm.vAlphabetic.values.vectorEffect.version.vertAdvY.vertOriginX.vertOriginY.vHanging.vIdeographic.viewTarget.visibility.vMathematical.widths.wordSpacing.writingMode.x1.x2.x.xChannelSelector.xHeight.xlinkActuate.xlinkArcrole.xlinkHref.xlinkRole.xlinkShow.xlinkTitle.xlinkType.xmlBase.xmlLang.xmlns.xmlnsXlink.xmlSpace.y1.y2.y.yChannelSelector.z.zoomAndPan.ref.key.angle`.split(`.`));function Or(e){return typeof e==`string`&&Dr.has(e)}function kr(e){return typeof e==`string`&&e.startsWith(`data-`)}function Ar(e){if(typeof e!=`object`||!e)return{};var t={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(Or(n)||kr(n))&&(t[n]=e[n]);return t}function jr(e){if(e==null)return null;if((0,O.isValidElement)(e)&&typeof e.props==`object`&&e.props!==null){var t=e.props;return Ar(t)}return typeof e==`object`&&!Array.isArray(e)?Ar(e):null}function Mr(e){var t={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(Or(n)||kr(n)||Er(n))&&(t[n]=e[n]);return t}function Nr(e){return e==null?null:(0,O.isValidElement)(e)?Mr(e.props):typeof e==`object`&&!Array.isArray(e)?Mr(e):null}var Pr=[`children`,`width`,`height`,`viewBox`,`className`,`style`,`title`,`desc`];function Fr(){return Fr=Object.assign?Object.assign.bind():function(e){for(var t=1;t{var n=e.children,r=e.width,i=e.height,a=e.viewBox,o=e.className,s=e.style,c=e.title,l=e.desc,u=Ir(e,Pr),d=a||{width:r,height:i,x:0,y:0},f=g(`recharts-surface`,o);return O.createElement(`svg`,Fr({},Mr(u),{className:f,width:r,height:i,style:s,viewBox:`${d.x} ${d.y} ${d.width} ${d.height}`,ref:t}),O.createElement(`title`,null,c),O.createElement(`desc`,null,l),n)}),zr=[`children`,`className`];function Br(){return Br=Object.assign?Object.assign.bind():function(e){for(var t=1;t{var n=e.children,r=e.className,i=Vr(e,zr),a=g(`recharts-layer`,r);return O.createElement(`g`,Br({className:a},Mr(i),{ref:t}),n)});function Ur(e){return e===`__proto__`}function Wr(e){switch(typeof e){case`number`:case`symbol`:return!1;case`string`:return e.includes(`.`)||e.includes(`[`)||e.includes(`]`)}}function Gr(e){return typeof e==`string`||typeof e==`symbol`?e:Object.is(e?.valueOf?.(),-0)?`-0`:String(e)}function Kr(e){if(e==null)return``;if(typeof e==`string`)return e;if(Array.isArray(e))return e.map(Kr).join(`,`);let t=String(e);return t===`0`&&Object.is(Number(e),-0)?`-0`:t}function qr(e){if(Array.isArray(e))return e.map(Gr);if(typeof e==`symbol`)return[e];e=Kr(e);let t=[],n=e.length;if(n===0)return t;let r=0,i=``,a=``,o=!1;for(e.charCodeAt(0)===46&&t.push(``);r1&&arguments[1]!==void 0?arguments[1]:Xr),n=Math.round(e*t)/t;return Object.is(n,-0)?0:n}function Qr(e){var t=[...arguments].slice(1);return e.reduce((e,n,r)=>{var i=t[r-1];return typeof i==`string`?e+i+n:i===void 0?e+n:e+Zr(i)+n},``)}var $r=e=>e===0?0:e>0?1:-1,ei=e=>typeof e==`number`&&e!=+e,ti=e=>typeof e==`string`&&e.length>1&&e.indexOf(`%`)===e.length-1,L=e=>(typeof e==`number`||e instanceof Number)&&!ei(e),ni=e=>L(e)||typeof e==`string`,ri=0,ii=e=>{var t=++ri;return`${e||``}${t}`},ai=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,r=arguments.length>3&&arguments[3]!==void 0&&arguments[3];if(!L(e)&&typeof e!=`string`)return n;var i;if(ti(e)){if(t==null)return n;var a=e.indexOf(`%`);i=t*parseFloat(e.slice(0,a))/100}else i=+e;return ei(i)&&(i=n),r&&t!=null&&i>t&&(i=t),i},oi=e=>{if(!Array.isArray(e))return!1;for(var t=e.length,n={},r=0;re&&(typeof t==`function`?t(e):Jr(e,t))===n)}var z=e=>e==null,ci=e=>z(e)?e:`${e.charAt(0).toUpperCase()}${e.slice(1)}`;function li(e){return e!=null}function ui(){}function di(e){if(e)return{x:e.x,y:e.y,upperWidth:`upperWidth`in e?e.upperWidth:e.width,lowerWidth:`lowerWidth`in e?e.lowerWidth:e.width,width:e.width,height:e.height}}function fi(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function pi(e){for(var t=1;t{var t=e.viewBox,n=e.position,r=e.offset,i=r===void 0?0:r,a=e.parentViewBox,o=e.clamp,s=di(t),c=s.x,l=s.y,u=s.height,d=s.upperWidth,f=s.lowerWidth,p=c,m=c+(d-f)/2,h=(p+m)/2,g=(d+f)/2,_=p+d/2,v=u>=0?1:-1,y=v*i,b=v>0?`end`:`start`,x=v>0?`start`:`end`,S=d>=0?1:-1,C=S*i,w=S>0?`end`:`start`,T=S>0?`start`:`end`,E=a;if(n===`top`){var D={x:p+d/2,y:l-y,horizontalAnchor:`middle`,verticalAnchor:b};return o&&E&&(D.height=Math.max(l-E.y,0),D.width=d),D}if(n===`bottom`){var O={x:m+f/2,y:l+u+y,horizontalAnchor:`middle`,verticalAnchor:x};return o&&E&&(O.height=Math.max(E.y+E.height-(l+u),0),O.width=f),O}if(n===`left`){var k={x:h-C,y:l+u/2,horizontalAnchor:w,verticalAnchor:`middle`};return o&&E&&(k.width=Math.max(k.x-E.x,0),k.height=u),k}if(n===`right`){var A={x:h+g+C,y:l+u/2,horizontalAnchor:T,verticalAnchor:`middle`};return o&&E&&(A.width=Math.max(E.x+E.width-A.x,0),A.height=u),A}var j=o&&E?{width:g,height:u}:{};return n===`insideLeft`?pi({x:h+C,y:l+u/2,horizontalAnchor:T,verticalAnchor:`middle`},j):n===`insideRight`?pi({x:h+g-C,y:l+u/2,horizontalAnchor:w,verticalAnchor:`middle`},j):n===`insideTop`?pi({x:p+d/2,y:l+y,horizontalAnchor:`middle`,verticalAnchor:x},j):n===`insideBottom`?pi({x:m+f/2,y:l+u-y,horizontalAnchor:`middle`,verticalAnchor:b},j):n===`insideTopLeft`?pi({x:p+C,y:l+y,horizontalAnchor:T,verticalAnchor:x},j):n===`insideTopRight`?pi({x:p+d-C,y:l+y,horizontalAnchor:w,verticalAnchor:x},j):n===`insideBottomLeft`?pi({x:m+C,y:l+u-y,horizontalAnchor:T,verticalAnchor:b},j):n===`insideBottomRight`?pi({x:m+f-C,y:l+u-y,horizontalAnchor:w,verticalAnchor:b},j):n&&typeof n==`object`&&(L(n.x)||ti(n.x))&&(L(n.y)||ti(n.y))?pi({x:c+ai(n.x,g),y:l+ai(n.y,u),horizontalAnchor:`end`,verticalAnchor:`end`},j):pi({x:_,y:l+u/2,horizontalAnchor:`middle`,verticalAnchor:`middle`},j)},vi=[`top`,`left`,`right`,`bottom`];function yi(e){return e==null?!1:typeof e==`object`||vi.includes(e)}var bi=(0,O.createContext)(null);function xi(e){return function(){return e}}var Si=Math.PI,Ci=2*Si,wi=1e-6,Ti=Ci-wi;function Ei(e){this._+=e[0];for(let t=1,n=e.length;t=0))throw Error(`invalid digits: ${e}`);if(t>15)return Ei;let n=10**t;return function(e){this._+=e[0];for(let t=1,r=e.length;twi)if(!(Math.abs(u*s-c*l)>wi)||!i)this._append`L${this._x1=e},${this._y1=t}`;else{let f=n-a,p=r-o,m=s*s+c*c,h=f*f+p*p,g=Math.sqrt(m),_=Math.sqrt(d),v=i*Math.tan((Si-Math.acos((m+d-h)/(2*g*_)))/2),y=v/_,b=v/g;Math.abs(y-1)>wi&&this._append`L${e+y*l},${t+y*u}`,this._append`A${i},${i},0,0,${+(u*f>l*p)},${this._x1=e+b*s},${this._y1=t+b*c}`}}arc(e,t,n,r,i,a){if(e=+e,t=+t,n=+n,a=!!a,n<0)throw Error(`negative radius: ${n}`);let o=n*Math.cos(r),s=n*Math.sin(r),c=e+o,l=t+s,u=1^a,d=a?r-i:i-r;this._x1===null?this._append`M${c},${l}`:(Math.abs(this._x1-c)>wi||Math.abs(this._y1-l)>wi)&&this._append`L${c},${l}`,n&&(d<0&&(d=d%Ci+Ci),d>Ti?this._append`A${n},${n},0,1,${u},${e-o},${t-s}A${n},${n},0,1,${u},${this._x1=c},${this._y1=l}`:d>wi&&this._append`A${n},${n},0,${+(d>=Si)},${u},${this._x1=e+n*Math.cos(i)},${this._y1=t+n*Math.sin(i)}`)}rect(e,t,n,r){this._append`M${this._x0=this._x1=+e},${this._y0=this._y1=+t}h${n=+n}v${+r}h${-n}Z`}toString(){return this._}};function ki(){return new Oi}ki.prototype=Oi.prototype;function Ai(e){let t=3;return e.digits=function(n){if(!arguments.length)return t;if(n==null)t=null;else{let e=Math.floor(n);if(!(e>=0))throw RangeError(`invalid digits: ${n}`);t=e}return e},()=>new Oi(t)}Array.prototype.slice;function ji(e){return typeof e==`object`&&`length`in e?e:Array.from(e)}function Mi(e){this._context=e}Mi.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:this._context.lineTo(e,t);break}}};function Ni(e){return new Mi(e)}function Pi(e){return e[0]}function Fi(e){return e[1]}function Ii(e,t){var n=xi(!0),r=null,i=Ni,a=null,o=Ai(s);e=typeof e==`function`?e:e===void 0?Pi:xi(e),t=typeof t==`function`?t:t===void 0?Fi:xi(t);function s(s){var c,l=(s=ji(s)).length,u,d=!1,f;for(r??(a=i(f=o())),c=0;c<=l;++c)!(c=d;--f)s.point(_[f],v[f]);s.lineEnd(),s.areaEnd()}h&&(_[u]=+e(m,u,l),v[u]=+t(m,u,l),s.point(r?+r(m,u,l):_[u],n?+n(m,u,l):v[u]))}if(g)return s=null,g+``||null}function u(){return Ii().defined(i).curve(o).context(a)}return l.x=function(t){return arguments.length?(e=typeof t==`function`?t:xi(+t),r=null,l):e},l.x0=function(t){return arguments.length?(e=typeof t==`function`?t:xi(+t),l):e},l.x1=function(e){return arguments.length?(r=e==null?null:typeof e==`function`?e:xi(+e),l):r},l.y=function(e){return arguments.length?(t=typeof e==`function`?e:xi(+e),n=null,l):t},l.y0=function(e){return arguments.length?(t=typeof e==`function`?e:xi(+e),l):t},l.y1=function(e){return arguments.length?(n=e==null?null:typeof e==`function`?e:xi(+e),l):n},l.lineX0=l.lineY0=function(){return u().x(e).y(t)},l.lineY1=function(){return u().x(e).y(n)},l.lineX1=function(){return u().x(r).y(t)},l.defined=function(e){return arguments.length?(i=typeof e==`function`?e:xi(!!e),l):i},l.curve=function(e){return arguments.length?(o=e,a!=null&&(s=o(a)),l):o},l.context=function(e){return arguments.length?(e==null?a=s=null:s=o(a=e),l):a},l}var Ri=class{constructor(e,t){this._context=e,this._x=t}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line}point(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+e)/2,this._y0,this._x0,t,e,t):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+t)/2,e,this._y0,e,t);break}this._x0=e,this._y0=t}};function zi(e){return new Ri(e,!0)}function Bi(e){return new Ri(e,!1)}function Vi(){}function Hi(e,t,n){e._context.bezierCurveTo((2*e._x0+e._x1)/3,(2*e._y0+e._y1)/3,(e._x0+2*e._x1)/3,(e._y0+2*e._y1)/3,(e._x0+4*e._x1+t)/6,(e._y0+4*e._y1+n)/6)}function Ui(e){this._context=e}Ui.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Hi(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Hi(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function Wi(e){return new Ui(e)}function Gi(e){this._context=e}Gi.prototype={areaStart:Vi,areaEnd:Vi,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4);break}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x2=e,this._y2=t;break;case 1:this._point=2,this._x3=e,this._y3=t;break;case 2:this._point=3,this._x4=e,this._y4=t,this._context.moveTo((this._x0+4*this._x1+e)/6,(this._y0+4*this._y1+t)/6);break;default:Hi(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function Ki(e){return new Gi(e)}function qi(e){this._context=e}qi.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+e)/6,r=(this._y0+4*this._y1+t)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:Hi(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function Ji(e){return new qi(e)}function Yi(e){this._context=e}Yi.prototype={areaStart:Vi,areaEnd:Vi,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(e,t){e=+e,t=+t,this._point?this._context.lineTo(e,t):(this._point=1,this._context.moveTo(e,t))}};function Xi(e){return new Yi(e)}function Zi(e){return e<0?-1:1}function Qi(e,t,n){var r=e._x1-e._x0,i=t-e._x1,a=(e._y1-e._y0)/(r||i<0&&-0),o=(n-e._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(Zi(a)+Zi(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function $i(e,t){var n=e._x1-e._x0;return n?(3*(e._y1-e._y0)/n-t)/2:t}function ea(e,t,n){var r=e._x0,i=e._y0,a=e._x1,o=e._y1,s=(a-r)/3;e._context.bezierCurveTo(r+s,i+s*t,a-s,o-s*n,a,o)}function ta(e){this._context=e}ta.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:ea(this,this._t0,$i(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){var n=NaN;if(e=+e,t=+t,!(e===this._x1&&t===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,ea(this,$i(this,n=Qi(this,e,t)),n);break;default:ea(this,this._t0,n=Qi(this,e,t));break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t,this._t0=n}}};function na(e){this._context=new ra(e)}(na.prototype=Object.create(ta.prototype)).point=function(e,t){ta.prototype.point.call(this,t,e)};function ra(e){this._context=e}ra.prototype={moveTo:function(e,t){this._context.moveTo(t,e)},closePath:function(){this._context.closePath()},lineTo:function(e,t){this._context.lineTo(t,e)},bezierCurveTo:function(e,t,n,r,i,a){this._context.bezierCurveTo(t,e,r,n,a,i)}};function ia(e){return new ta(e)}function aa(e){return new na(e)}function oa(e){this._context=e}oa.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var e=this._x,t=this._y,n=e.length;if(n)if(this._line?this._context.lineTo(e[0],t[0]):this._context.moveTo(e[0],t[0]),n===2)this._context.lineTo(e[1],t[1]);else for(var r=sa(e),i=sa(t),a=0,o=1;o=0;--t)i[t]=(o[t]-i[t+1])/a[t];for(a[n-1]=(e[n]+i[n-1])/2,t=0;t=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,t),this._context.lineTo(e,t);else{var n=this._x*(1-this._t)+e*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,t)}break}this._x=e,this._y=t}};function ua(e){return new la(e,.5)}function da(e){return new la(e,0)}function fa(e){return new la(e,1)}function pa(e,t){if((o=e.length)>1)for(var n=1,r,i,a=e[t[0]],o,s=a.length;n=0;)n[t]=t;return n}function ha(e,t){return e[t]}function ga(e){let t=[];return t.key=e,t}function _a(){var e=xi([]),t=ma,n=pa,r=ha;function i(i){var a=Array.from(e.apply(this,arguments),ga),o,s=a.length,c=-1,l;for(let e of i)for(o=0,++c;o0){for(var n,r,i=0,a=e[0].length,o;i0){for(var n=0,r=e[t[0]],i,a=r.length;n0)||!((a=(i=e[t[0]]).length)>0))){for(var n=0,r=1,i,a,o;r`radius`in e&&`startAngle`in e&&`endAngle`in e,Sa=(e,t)=>{if(!e||typeof e==`function`||typeof e==`boolean`)return null;var n=e;if((0,O.isValidElement)(e)&&(n=e.props),typeof n!=`object`&&typeof n!=`function`)return null;var r={};return Object.keys(n).forEach(e=>{Er(e)&&typeof n[e]==`function`&&(r[e]=t||(t=>n[e](n,t)))}),r},Ca=(e,t,n)=>r=>(e(t,n,r),null),wa=(e,t,n)=>{if(e===null||typeof e!=`object`&&typeof e!=`function`)return null;var r=null;return Object.keys(e).forEach(i=>{var a=e[i];Er(i)&&typeof a==`function`&&(r||={},r[i]=Ca(a,t,n))}),r};function Ta(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Ea(e){for(var t=1;t(e[t]===void 0&&r[t]!==void 0&&(e[t]=r[t]),e),n)}function ja(e,t){let n=new Map;for(let r=0;rObject.prototype.propertyIsEnumerable.call(e,t))}function Ra(e){return e==null?e===void 0?`[object Undefined]`:`[object Null]`:Object.prototype.toString.call(e)}var za=`[object RegExp]`,Ba=`[object String]`,Va=`[object Number]`,Ha=`[object Boolean]`,Ua=`[object Arguments]`,Wa=`[object Symbol]`,Ga=`[object Date]`,Ka=`[object Map]`,qa=`[object Set]`,Ja=`[object Array]`,Ya=`[object Function]`,Xa=`[object ArrayBuffer]`,Za=`[object Object]`,Qa=`[object Error]`,$a=`[object DataView]`,eo=`[object Uint8Array]`,to=`[object Uint8ClampedArray]`,no=`[object Uint16Array]`,ro=`[object Uint32Array]`,io=`[object BigUint64Array]`,ao=`[object Int8Array]`,oo=`[object Int16Array]`,so=`[object Int32Array]`,co=`[object BigInt64Array]`,lo=`[object Float32Array]`,uo=`[object Float64Array]`,fo=typeof globalThis==`object`&&globalThis||typeof window==`object`&&window||typeof self==`object`&&self||typeof global==`object`&&global||(function(){return this})();function po(e){return fo.Buffer!==void 0&&fo.Buffer.isBuffer(e)}function mo(e,t){return ho(e,void 0,e,new Map,t)}function ho(e,t,n,r=new Map,i=void 0){let a=i?.(e,t,n,r);if(a!==void 0)return a;if(Fa(e))return e;if(r.has(e))return r.get(e);if(Array.isArray(e)){let t=Array(e.length);r.set(e,t);for(let a=0;avoid 0)}function So(e,t,n,r,i=!1){if(t===e)return!0;switch(typeof t){case`object`:return Co(e,t,n,r);case`function`:return Object.keys(t).length>0?So(e,{...t},n,r,i):yo(e,t);default:return bo(e)&&i?typeof t!=`string`||t===``:yo(e,t)}}function Co(e,t,n,r){if(t==null)return!0;if(Array.isArray(t))return To(e,t,n,r);if(t instanceof Map)return wo(e,t,n,r);if(t instanceof Set)return Eo(e,t,n,r);let i=Object.keys(t);if(e==null||Fa(e))return i.length===0;if(i.length===0)return!0;if(r?.has(t))return r.get(t)===e;r?.set(t,e);try{for(let a=0;avoid 0)}function Oo(e){return e=vo(e),t=>Do(t,e)}function ko(e,t){return mo(e,(n,r,i,a)=>{let o=t?.(n,r,i,a);if(o!==void 0)return o;if(typeof e==`object`){if(Ra(e)===`[object Object]`&&typeof e.constructor!=`function`){let t={};return a.set(e,t),go(t,e,i,a),t}switch(Object.prototype.toString.call(e)){case Va:case Ba:case Ha:{let t=new e.constructor(e?.valueOf());return go(t,e),t}case Ua:{let t={};return go(t,e),t.length=e.length,t[Symbol.iterator]=e[Symbol.iterator],t}default:return}}})}function Ao(e){return ko(e)}var jo=/^(?:0|[1-9]\d*)$/;function Mo(e,t=2**53-1){switch(typeof e){case`number`:return Number.isInteger(e)&&e>=0&&e=0}function Ro(e){return e!=null&&typeof e!=`function`&&Lo(e.length)}function zo(e){return typeof e==`object`&&!!e}function Bo(e){return zo(e)&&Ro(e)}function Vo(e,t=Na){return Bo(e)?ja(Array.from(e),Ma(Io(t),1)):[]}function Ho(e,t,n){return t===!0?Vo(e,n):typeof t==`function`?Vo(e,t):e}var Uo=e((e=>{var t=i();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,a=t.useState,o=t.useEffect,s=t.useLayoutEffect,c=t.useDebugValue;function l(e,t){var n=t(),r=a({inst:{value:n,getSnapshot:t}}),i=r[0].inst,l=r[1];return s(function(){i.value=n,i.getSnapshot=t,u(i)&&l({inst:i})},[e,n,t]),o(function(){return u(i)&&l({inst:i}),e(function(){u(i)&&l({inst:i})})},[e]),c(n),n}function u(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function d(e,t){return t()}var f=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?d:l;e.useSyncExternalStore=t.useSyncExternalStore===void 0?f:t.useSyncExternalStore})),Wo=e(((e,t)=>{t.exports=Uo()})),Go=e((e=>{var t=i(),n=Wo();function r(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var a=typeof Object.is==`function`?Object.is:r,o=n.useSyncExternalStore,s=t.useRef,c=t.useEffect,l=t.useMemo,u=t.useDebugValue;e.useSyncExternalStoreWithSelector=function(e,t,n,r,i){var d=s(null);if(d.current===null){var f={hasValue:!1,value:null};d.current=f}else f=d.current;d=l(function(){function e(e){if(!o){if(o=!0,s=e,e=r(e),i!==void 0&&f.hasValue){var t=f.value;if(i(t,e))return c=t}return c=e}if(t=c,a(s,e))return t;var n=r(e);return i!==void 0&&i(t,n)?(s=e,t):(s=e,c=n)}var o=!1,s,c,l=n===void 0?null:n;return[function(){return e(t())},l===null?void 0:function(){return e(l())}]},[t,n,r,i]);var p=o(e,d[0],d[1]);return c(function(){f.hasValue=!0,f.value=p},[p]),u(p),p}})),Ko=e(((e,t)=>{t.exports=Go()}))(),qo=(0,O.createContext)(null),Jo=e=>e,B=()=>{var e=(0,O.useContext)(qo);return e?e.store.dispatch:Jo},Yo=()=>{},Xo=()=>Yo,Zo=(e,t)=>e===t;function V(e){var t=(0,O.useContext)(qo),n=(0,O.useMemo)(()=>t?t=>{if(t!=null)return e(t)}:Yo,[t,e]);return(0,Ko.useSyncExternalStoreWithSelector)(t?t.subscription.addNestedSub:Xo,t?t.store.getState:Yo,t?t.store.getState:Yo,n,Zo)}function Qo(e,t=`expected a function, instead received ${typeof e}`){if(typeof e!=`function`)throw TypeError(t)}function $o(e,t=`expected all items to be functions, instead received the following types: `){if(!e.every(e=>typeof e==`function`)){let n=e.map(e=>typeof e==`function`?`function ${e.name||`unnamed`}()`:typeof e).join(`, `);throw TypeError(`${t}[${n}]`)}}var es=e=>Array.isArray(e)?e:[e];function ts(e){let t=Array.isArray(e[0])?e[0]:e;return $o(t,`createSelector expects all input-selectors to be functions, but received the following types: `),t}function ns(e,t){let n=[],{length:r}=e;for(let i=0;i`u`?rs:WeakRef,as=0,os=1;function ss(){return{s:as,v:void 0,o:null,p:null}}function cs(e){return e instanceof is?e.deref():e}function ls(e,t={}){let n=ss(),{resultEqualityCheck:r}=t,i,a=0;function o(){let t=n,{length:o}=arguments;for(let e=0,n=o;e{n=ss(),o.resetResultsCount()},o.resultsCount=()=>a,o.resetResultsCount=()=>{a=0},o}function us(e,...t){let n=typeof e==`function`?{memoize:e,memoizeOptions:t}:e,r=(...e)=>{let t=0,r=0,i,a={},o=e.pop();typeof o==`object`&&(a=o,o=e.pop()),Qo(o,`createSelector expects an output function after the inputs, but received: [${typeof o}]`);let{memoize:s,memoizeOptions:c=[],argsMemoize:l=ls,argsMemoizeOptions:u=[]}={...n,...a},d=es(c),f=es(u),p=ts(e),m=s(function(){return t++,o.apply(null,arguments)},...d),h=l(function(){r++;let e=ns(p,arguments);return i=m.apply(null,e),i},...f);return Object.assign(h,{resultFunc:o,memoizedResultFunc:m,dependencies:p,dependencyRecomputations:()=>r,resetDependencyRecomputations:()=>{r=0},lastResult:()=>i,recomputations:()=>t,resetRecomputations:()=>{t=0},memoize:s,argsMemoize:l})};return Object.assign(r,{withTypes:()=>r}),r}var H=us(ls);function ds(e,t=1){let n=[],r=Math.floor(t),i=(e,t)=>{for(let a=0;a{if(e!==t){let r=ps(e),i=ps(t);if(r===i&&r===0){if(et)return n===`desc`?-1:1}return n===`desc`?i-r:r-i}return 0};function hs(e){return typeof e==`symbol`||e instanceof Symbol}var gs=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,_s=/^\w*$/;function vs(e,t){return Array.isArray(e)?!1:typeof e==`number`||typeof e==`boolean`||e==null||hs(e)?!0:typeof e==`string`&&(_s.test(e)||!gs.test(e))||t!=null&&Object.hasOwn(t,e)}function ys(e,t,n,r){if(e==null)return[];n=r?void 0:n,Array.isArray(e)||(e=Object.values(e)),Array.isArray(t)||(t=t==null?[null]:[t]),t.length===0&&(t=[null]),Array.isArray(n)||(n=n==null?[]:[n]),n=n.map(e=>String(e));let i=(e,t)=>{let n=e;for(let e=0;et==null||e==null?t:typeof e==`object`&&`key`in e?Object.hasOwn(t,e.key)?t[e.key]:i(t,e.path):typeof e==`function`?e(t):Array.isArray(e)?i(t,e):typeof t==`object`?t[e]:t,o=t.map(e=>(Array.isArray(e)&&e.length===1&&(e=e[0]),e==null||typeof e==`function`||Array.isArray(e)||vs(e)?e:{key:e,path:qr(e)}));return e.map(e=>({original:e,criteria:o.map(t=>a(t,e))})).slice().sort((e,t)=>{for(let r=0;re.original)}function bs(e,...t){let n=t.length;return n>1&&fs(e,t[0],t[1])?t=[]:n>2&&fs(t[0],t[1],t[2])&&(t=[t[0]]),ys(e,ds(t),[`asc`])}var xs=e=>e.legend.settings,Ss=e=>e.legend.size;H([e=>e.legend.payload,xs],(e,t)=>{var n=t.itemSorter,r=e.flat(1);return n?bs(r,n):r});function Cs(e,t){return Os(e)||Ds(e,t)||Ts(e,t)||ws()}function ws(){throw TypeError(`Invalid attempt to destructure non-iterable instance. +import{$ as e,C as t,E as n,G as r,Q as i,S as a,T as o,W as s,X as c,Z as l,_ as u,d,et as f,f as p,g as m,h,k as g,m as _,p as v,tt as y,v as b,w as x,x as S,y as C}from"./index-D1U5YqHo.js";var w=r(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]),T=r(`download`,[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]),E=r(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),D=r(`rotate-ccw`,[[`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`}]]),O=y(i(),1),k=[`top`,`right`,`bottom`,`left`],A=Math.min,j=Math.max,M=Math.round,N=Math.floor,P=e=>({x:e,y:e}),ee={left:`right`,right:`left`,bottom:`top`,top:`bottom`};function te(e,t,n){return j(e,A(t,n))}function ne(e,t){return typeof e==`function`?e(t):e}function re(e){return e.split(`-`)[0]}function ie(e){return e.split(`-`)[1]}function ae(e){return e===`x`?`y`:`x`}function oe(e){return e===`y`?`height`:`width`}function se(e){let t=e[0];return t===`t`||t===`b`?`y`:`x`}function ce(e){return ae(se(e))}function le(e,t,n){n===void 0&&(n=!1);let r=ie(e),i=ce(e),a=oe(i),o=i===`x`?r===(n?`end`:`start`)?`right`:`left`:r===`start`?`bottom`:`top`;return t.reference[a]>t.floating[a]&&(o=ve(o)),[o,ve(o)]}function ue(e){let t=ve(e);return[de(e),t,de(t)]}function de(e){return e.includes(`start`)?e.replace(`start`,`end`):e.replace(`end`,`start`)}var fe=[`left`,`right`],pe=[`right`,`left`],me=[`top`,`bottom`],he=[`bottom`,`top`];function ge(e,t,n){switch(e){case`top`:case`bottom`:return n?t?pe:fe:t?fe:pe;case`left`:case`right`:return t?me:he;default:return[]}}function _e(e,t,n,r){let i=ie(e),a=ge(re(e),n===`start`,r);return i&&(a=a.map(e=>e+`-`+i),t&&(a=a.concat(a.map(de)))),a}function ve(e){let t=re(e);return ee[t]+e.slice(t.length)}function ye(e){return{top:e.top??0,right:e.right??0,bottom:e.bottom??0,left:e.left??0}}function be(e){return typeof e==`number`?{top:e,right:e,bottom:e,left:e}:ye(e)}function xe(e){let{x:t,y:n,width:r,height:i}=e;return{width:r,height:i,top:n,left:t,right:t+r,bottom:n+i,x:t,y:n}}function Se(e,t,n){let{reference:r,floating:i}=e,a=se(t),o=ce(t),s=oe(o),c=re(t),l=a===`y`,u=r.x+r.width/2-i.width/2,d=r.y+r.height/2-i.height/2,f=r[s]/2-i[s]/2,p;switch(c){case`top`:p={x:u,y:r.y-i.height};break;case`bottom`:p={x:u,y:r.y+r.height};break;case`right`:p={x:r.x+r.width,y:d};break;case`left`:p={x:r.x-i.width,y:d};break;default:p={x:r.x,y:r.y}}let m=ie(t);return m&&(p[o]+=f*(m===`end`?1:-1)*(n&&l?-1:1)),p}async function Ce(e,t){t===void 0&&(t={});let{x:n,y:r,platform:i,rects:a,elements:o,strategy:s}=e,{boundary:c=`clippingAncestors`,rootBoundary:l=`viewport`,elementContext:u=`floating`,altBoundary:d=!1,padding:f=0}=ne(t,e),p=be(f),m=o[d?u===`floating`?`reference`:`floating`:u],h=xe(await i.getClippingRect({element:await(i.isElement==null?void 0:i.isElement(m))??!0?m:m.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(o.floating)),boundary:c,rootBoundary:l,strategy:s})),g=u===`floating`?{x:n,y:r,width:a.floating.width,height:a.floating.height}:a.reference,_=await(i.getOffsetParent==null?void 0:i.getOffsetParent(o.floating)),v=await(i.isElement==null?void 0:i.isElement(_))&&await(i.getScale==null?void 0:i.getScale(_))||{x:1,y:1},y=xe(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:o,rect:g,offsetParent:_,strategy:s}):g);return{top:(h.top-y.top+p.top)/v.y,bottom:(y.bottom-h.bottom+p.bottom)/v.y,left:(h.left-y.left+p.left)/v.x,right:(y.right-h.right+p.right)/v.x}}var we=50,Te=async(e,t,n)=>{let{placement:r=`bottom`,strategy:i=`absolute`,middleware:a=[],platform:o}=n,s=o.detectOverflow?o:{...o,detectOverflow:Ce},c=await(o.isRTL==null?void 0:o.isRTL(t)),l=await o.getElementRects({reference:e,floating:t,strategy:i}),{x:u,y:d}=Se(l,r,c),f=r,p=0,m={};for(let n=0;n({name:`arrow`,options:e,async fn(t){let{x:n,y:r,placement:i,rects:a,platform:o,elements:s,middlewareData:c}=t,{element:l,padding:u=0}=ne(e,t)||{};if(l==null)return{};let d=be(u),f={x:n,y:r},p=ce(i),m=oe(p),h=await o.getDimensions(l),g=p===`y`,_=g?`top`:`left`,v=g?`bottom`:`right`,y=g?`clientHeight`:`clientWidth`,b=a.reference[m]+a.reference[p]-f[p]-a.floating[m],x=f[p]-a.reference[p],S=await(o.getOffsetParent==null?void 0:o.getOffsetParent(l)),C=S?S[y]:0;(!C||!await(o.isElement==null?void 0:o.isElement(S)))&&(C=s.floating[y]||a.floating[m]);let w=b/2-x/2,T=C/2-h[m]/2-1,E=A(d[_],T),D=A(d[v],T),O=C-h[m]-D,k=C/2-h[m]/2+w,j=te(E,k,O),M=!c.arrow&&ie(i)!=null&&k!==j&&a.reference[m]/2-(ke<=0)){let e=(i.flip?.index||0)+1,t=S[e];if(t&&(!(u===`alignment`&&_!==se(t))||T.every(e=>se(e.placement)!==_||e.overflows[0]>0)))return{data:{index:e,overflows:T},reset:{placement:t}};let n=T.filter(e=>e.overflows[0]<=0).sort((e,t)=>e.overflows[1]-t.overflows[1])[0]?.placement;if(!n)switch(f){case`bestFit`:{let e=T.filter(e=>{if(x){let t=se(e.placement);return t===_||t===`y`}return!0}).map(e=>[e.placement,e.overflows.filter(e=>e>0).reduce((e,t)=>e+t,0)]).sort((e,t)=>e[1]-t[1])[0]?.[0];e&&(n=e);break}case`initialPlacement`:n=o;break}if(r!==n)return{reset:{placement:n}}}return{}}}};function Oe(e,t){return{top:e.top-t.height,right:e.right-t.width,bottom:e.bottom-t.height,left:e.left-t.width}}function ke(e){return k.some(t=>e[t]>=0)}var Ae=function(e){return e===void 0&&(e={}),{name:`hide`,options:e,async fn(t){let{rects:n,platform:r}=t,{strategy:i=`referenceHidden`,...a}=ne(e,t);switch(i){case`referenceHidden`:{let e=Oe(await r.detectOverflow(t,{...a,elementContext:`reference`}),n.reference);return{data:{referenceHiddenOffsets:e,referenceHidden:ke(e)}}}case`escaped`:{let e=Oe(await r.detectOverflow(t,{...a,altBoundary:!0}),n.floating);return{data:{escapedOffsets:e,escaped:ke(e)}}}default:return{}}}}},je=new Set([`left`,`top`]);async function Me(e,t){let{placement:n,platform:r,elements:i}=e,a=await(r.isRTL==null?void 0:r.isRTL(i.floating)),o=re(n),s=ie(n),c=se(n)===`y`,l=je.has(o)?-1:1,u=a&&c?-1:1,d=ne(t,e),{mainAxis:f,crossAxis:p,alignmentAxis:m}=typeof d==`number`?{mainAxis:d,crossAxis:0,alignmentAxis:null}:{mainAxis:d.mainAxis||0,crossAxis:d.crossAxis||0,alignmentAxis:d.alignmentAxis};return s&&typeof m==`number`&&(p=s===`end`?m*-1:m),c?{x:p*u,y:f*l}:{x:f*l,y:p*u}}var Ne=function(e){return e===void 0&&(e=0),{name:`offset`,options:e,async fn(t){var n;let{x:r,y:i,placement:a,middlewareData:o}=t,s=await Me(t,e);return a===o.offset?.placement&&(n=o.arrow)!=null&&n.alignmentOffset?{}:{x:r+s.x,y:i+s.y,data:{...s,placement:a}}}}},Pe=function(e){return e===void 0&&(e={}),{name:`shift`,options:e,async fn(t){let{x:n,y:r,placement:i,platform:a}=t,{mainAxis:o=!0,crossAxis:s=!1,limiter:c={fn:e=>{let{x:t,y:n}=e;return{x:t,y:n}}},...l}=ne(e,t),u={x:n,y:r},d=await a.detectOverflow(t,l),f=se(i),p=ae(f),m=u[p],h=u[f],g=(e,t)=>te(t+d[e===`y`?`top`:`left`],t,t-d[e===`y`?`bottom`:`right`]);o&&(m=g(p,m)),s&&(h=g(f,h));let _=c.fn({...t,[p]:m,[f]:h});return{..._,data:{x:_.x-n,y:_.y-r,enabled:{[p]:o,[f]:s}}}}}},Fe=function(e){return e===void 0&&(e={}),{options:e,fn(t){let{x:n,y:r,placement:i,rects:a,middlewareData:o}=t,{offset:s=0,mainAxis:c=!0,crossAxis:l=!0}=ne(e,t),u={x:n,y:r},d=se(i),f=ae(d),p=u[f],m=u[d],h=ne(s,t),g=typeof h==`number`?{mainAxis:h,crossAxis:0}:{mainAxis:h.mainAxis??0,crossAxis:h.crossAxis??0};if(c){let e=f===`y`?`height`:`width`,t=a.reference[f]-a.floating[e]+g.mainAxis,n=a.reference[f]+a.reference[e]-g.mainAxis;pn&&(p=n)}if(l){let e=f===`y`?`width`:`height`,t=je.has(re(i)),n=a.reference[d]-a.floating[e]+(t&&o.offset?.[d]||0)+(t?0:g.crossAxis),r=a.reference[d]+a.reference[e]+(t?0:o.offset?.[d]||0)-(t?g.crossAxis:0);mr&&(m=r)}return{[f]:p,[d]:m}}}},Ie=function(e){return e===void 0&&(e={}),{name:`size`,options:e,async fn(t){let{placement:n,rects:r,platform:i,elements:a}=t,{apply:o=()=>{},...s}=ne(e,t),c=await i.detectOverflow(t,s),l=re(n),u=ie(n),d=se(n)===`y`,{width:f,height:p}=r.floating,m,h;l===`top`||l===`bottom`?(m=l,h=u===(await(i.isRTL==null?void 0:i.isRTL(a.floating))?`start`:`end`)?`left`:`right`):(h=l,m=u===`end`?`top`:`bottom`);let g=p-c.top-c.bottom,_=f-c.left-c.right,v=A(p-c[m],g),y=A(f-c[h],_),b=t.middlewareData.shift,x=!b,S=v,C=y;b!=null&&b.enabled.x&&(C=_),b!=null&&b.enabled.y&&(S=g),x&&!u&&(d?C=f-2*j(c.left,c.right):S=p-2*j(c.top,c.bottom)),await o({...t,availableWidth:C,availableHeight:S});let w=await i.getDimensions(a.floating);return f!==w.width||p!==w.height?{reset:{rects:!0}}:{}}}};function Le(){return typeof window<`u`}function Re(e){return Ve(e)?(e.nodeName||``).toLowerCase():`#document`}function ze(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function Be(e){return((Ve(e)?e.ownerDocument:e.document)||window.document)?.documentElement}function Ve(e){return Le()?e instanceof Node||e instanceof ze(e).Node:!1}function He(e){return Le()?e instanceof Element||e instanceof ze(e).Element:!1}function Ue(e){return Le()?e instanceof HTMLElement||e instanceof ze(e).HTMLElement:!1}function We(e){return!Le()||typeof ShadowRoot>`u`?!1:e instanceof ShadowRoot||e instanceof ze(e).ShadowRoot}function Ge(e){let{overflow:t,overflowX:n,overflowY:r,display:i}=nt(e);return/auto|scroll|overlay|hidden|clip/.test(t+r+n)&&i!==`inline`&&i!==`contents`}function Ke(e){return/^(table|td|th)$/.test(Re(e))}function qe(e){try{if(e.matches(`:popover-open`))return!0}catch{}try{return e.matches(`:modal`)}catch{return!1}}var Je=/transform|translate|scale|rotate|perspective|filter/,Ye=/paint|layout|strict|content/,Xe=e=>!!e&&e!==`none`,Ze;function Qe(e){let t=He(e)?nt(e):e;return Xe(t.transform)||Xe(t.translate)||Xe(t.scale)||Xe(t.rotate)||Xe(t.perspective)||!et()&&(Xe(t.backdropFilter)||Xe(t.filter))||Je.test(t.willChange||``)||Ye.test(t.contain||``)}function $e(e){let t=it(e);for(;Ue(t)&&!tt(t);){if(Qe(t))return t;if(qe(t))return null;t=it(t)}return null}function et(){return Ze??=typeof CSS<`u`&&CSS.supports&&CSS.supports(`-webkit-backdrop-filter`,`none`),Ze}function tt(e){return/^(html|body|#document)$/.test(Re(e))}function nt(e){return ze(e).getComputedStyle(e)}function rt(e){return He(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function it(e){if(Re(e)===`html`)return e;let t=e.assignedSlot||e.parentNode||We(e)&&e.host||Be(e);return We(t)?t.host:t}function at(e){let t=it(e);return tt(t)?(e.ownerDocument||e).body:Ue(t)&&Ge(t)?t:at(t)}function ot(e,t,n){t===void 0&&(t=[]),n===void 0&&(n=!0);let r=at(e),i=r===e.ownerDocument?.body,a=ze(r);if(i){let e=st(a);return t.concat(a,a.visualViewport||[],Ge(r)?r:[],e&&n?ot(e):[])}else return t.concat(r,ot(r,[],n))}function st(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}function ct(e){let t=nt(e),n=parseFloat(t.width)||0,r=parseFloat(t.height)||0,i=Ue(e),a=i?e.offsetWidth:n,o=i?e.offsetHeight:r,s=M(n)!==a||M(r)!==o;return s&&(n=a,r=o),{width:n,height:r,$:s}}function lt(e){return He(e)?e:e.contextElement}function ut(e){let t=lt(e);if(!Ue(t))return P(1);let n=t.getBoundingClientRect(),{width:r,height:i,$:a}=ct(t),o=(a?M(n.width):n.width)/r,s=(a?M(n.height):n.height)/i;return(!o||!Number.isFinite(o))&&(o=1),(!s||!Number.isFinite(s))&&(s=1),{x:o,y:s}}var dt=P(0);function ft(e){let t=ze(e);return!et()||!t.visualViewport?dt:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function pt(e,t,n){return t===void 0&&(t=!1),!!n&&t&&n===ze(e)}function mt(e,t,n,r){t===void 0&&(t=!1),n===void 0&&(n=!1);let i=e.getBoundingClientRect(),a=lt(e),o=P(1);t&&(r?He(r)&&(o=ut(r)):o=ut(e));let s=pt(a,n,r)?ft(a):P(0),c=(i.left+s.x)/o.x,l=(i.top+s.y)/o.y,u=i.width/o.x,d=i.height/o.y;if(a&&r){let e=ze(a),t=He(r)?ze(r):r,n=e,i=st(n);for(;i&&t!==n;){let e=ut(i),t=i.getBoundingClientRect(),r=nt(i),a=t.left+(i.clientLeft+parseFloat(r.paddingLeft))*e.x,o=t.top+(i.clientTop+parseFloat(r.paddingTop))*e.y;c*=e.x,l*=e.y,u*=e.x,d*=e.y,c+=a,l+=o,n=ze(i),i=st(n)}}return xe({width:u,height:d,x:c,y:l})}function ht(e,t){let n=rt(e).scrollLeft;return t?t.left+n:mt(Be(e)).left+n}function gt(e,t){let n=e.getBoundingClientRect();return{x:n.left+t.scrollLeft-ht(e,n),y:n.top+t.scrollTop}}function _t(e){let{elements:t,rect:n,offsetParent:r,strategy:i}=e,a=i===`fixed`,o=Be(r),s=t?qe(t.floating):!1;if(r===o||s&&a)return n;let c={scrollLeft:0,scrollTop:0},l=P(1),u=P(0),d=Ue(r);if((d||!a)&&((Re(r)!==`body`||Ge(o))&&(c=rt(r)),d)){let e=mt(r);l=ut(r),u.x=e.x+r.clientLeft,u.y=e.y+r.clientTop}let f=o&&!d&&!a?gt(o,c):P(0);return{width:n.width*l.x,height:n.height*l.y,x:n.x*l.x-c.scrollLeft*l.x+u.x+f.x,y:n.y*l.y-c.scrollTop*l.y+u.y+f.y}}function vt(e){return e.getClientRects?Array.from(e.getClientRects()):[]}function yt(e){let t=rt(e),n=e.ownerDocument.body,r=j(e.scrollWidth,e.clientWidth,n.scrollWidth,n.clientWidth),i=j(e.scrollHeight,e.clientHeight,n.scrollHeight,n.clientHeight),a=-t.scrollLeft+ht(e),o=-t.scrollTop;return nt(n).direction===`rtl`&&(a+=j(e.clientWidth,n.clientWidth)-r),{width:r,height:i,x:a,y:o}}var bt=25;function xt(e,t,n){n===void 0&&(n=`viewport`);let r=n===`layoutViewport`,i=ze(e),a=Be(e),o=i.visualViewport,s=a.clientWidth,c=a.clientHeight,l=0,u=0;if(o){let e=!et()||t===`fixed`;r?e||(l=-o.offsetLeft,u=-o.offsetTop):(s=o.width,c=o.height,e&&(l=o.offsetLeft,u=o.offsetTop))}if(ht(a)<=0){let e=a.ownerDocument,t=e.body,n=getComputedStyle(t),r=e.compatMode===`CSS1Compat`&&parseFloat(n.marginLeft)+parseFloat(n.marginRight)||0,i=Math.abs(a.clientWidth-t.clientWidth-r),o=getComputedStyle(a).scrollbarGutter===`stable both-edges`?i/2:i;o<=bt&&(s-=o)}return{width:s,height:c,x:l,y:u}}function St(e,t){let n=mt(e,!0,t===`fixed`),r=n.top+e.clientTop,i=n.left+e.clientLeft,a=ut(e);return{width:e.clientWidth*a.x,height:e.clientHeight*a.y,x:i*a.x,y:r*a.y}}function Ct(e,t,n){let r;if(t===`viewport`||t===`layoutViewport`)r=xt(e,n,t);else if(t===`document`)r=yt(Be(e));else if(He(t))r=St(t,n);else{let n=ft(e);r={x:t.x-n.x,y:t.y-n.y,width:t.width,height:t.height}}return xe(r)}function wt(e,t){let n=t.get(e);if(n)return n;let r=ot(e,[],!1).filter(e=>He(e)&&Re(e)!==`body`),i=null,a=nt(e).position===`fixed`,o=a?it(e):e;for(;He(o)&&!tt(o);){let e=nt(o),t=Qe(o),n=i?i.position:a?`fixed`:``;!t&&(n===`fixed`||n===`absolute`&&e.position===`static`)?r=r.filter(e=>e!==o):i=e,o=it(o)}return t.set(e,r),r}function Tt(e){let{element:t,boundary:n,rootBoundary:r,strategy:i}=e,a=[...n===`clippingAncestors`?qe(t)?[]:wt(t,this._c):[].concat(n),r],o=Ct(t,a[0],i),s=o.top,c=o.right,l=o.bottom,u=o.left;for(let e=1;e{s(!1,1e-7)},1e3)}y=!1}try{r=new IntersectionObserver(b,{...v,root:a.ownerDocument})}catch{r=new IntersectionObserver(b,v)}r.observe(e)}let c=ze(e),l=()=>s(n);return c.addEventListener(`resize`,l),s(!0),()=>{c.removeEventListener(`resize`,l),o()}}function It(e,t,n,r){r===void 0&&(r={});let{ancestorScroll:i=!0,ancestorResize:a=!0,elementResize:o=typeof ResizeObserver==`function`,layoutShift:s=typeof IntersectionObserver==`function`,animationFrame:c=!1}=r,l=lt(e),u=i||a?[...l?ot(l):[],...t?ot(t):[]]:[];u.forEach(e=>{i&&e.addEventListener(`scroll`,n),a&&e.addEventListener(`resize`,n)});let d=l&&s?Ft(l,n,a):null,f=-1,p=null;o&&(p=new ResizeObserver(e=>{let[r]=e;r&&r.target===l&&p&&t&&(p.unobserve(t),cancelAnimationFrame(f),f=requestAnimationFrame(()=>{var e;(e=p)==null||e.observe(t)})),n()}),l&&!c&&p.observe(l),t&&p.observe(t));let m,h=c?mt(e):null;c&&g();function g(){let t=mt(e);h&&!Pt(h,t)&&n(),h=t,m=requestAnimationFrame(g)}return n(),()=>{var e;u.forEach(e=>{i&&e.removeEventListener(`scroll`,n),a&&e.removeEventListener(`resize`,n)}),d?.(),(e=p)==null||e.disconnect(),p=null,c&&cancelAnimationFrame(m)}}var Lt=Ne,Rt=Pe,zt=De,Bt=Ie,Vt=Ae,Ht=Ee,Ut=Fe,Wt=(e,t,n)=>{let r=new Map,i=n??{},a={...Nt,...i.platform,_c:r};return Te(e,t,{...i,platform:a})},Gt=y(l(),1),Kt=typeof document<`u`?O.useLayoutEffect:function(){};function qt(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typeof e==`function`&&e.toString()===t.toString())return!0;let n,r,i;if(e&&t&&typeof e==`object`){if(Array.isArray(e)){if(n=e.length,n!==t.length)return!1;for(r=n;r--!==0;)if(!qt(e[r],t[r]))return!1;return!0}if(i=Object.keys(e),n=i.length,n!==Object.keys(t).length)return!1;for(r=n;r--!==0;)if(!{}.hasOwnProperty.call(t,i[r]))return!1;for(r=n;r--!==0;){let n=i[r];if(!(n===`_owner`&&e.$$typeof)&&!qt(e[n],t[n]))return!1}return!0}return e!==e&&t!==t}function Jt(e){return typeof window>`u`?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function Yt(e,t){let n=Jt(e);return Math.round(t*n)/n}function Xt(e){let t=O.useRef(e);return Kt(()=>{t.current=e}),t}function Zt(e){e===void 0&&(e={});let{placement:t=`bottom`,strategy:n=`absolute`,middleware:r=[],platform:i,elements:{reference:a,floating:o}={},transform:s=!0,whileElementsMounted:c,open:l}=e,[u,d]=O.useState({x:0,y:0,strategy:n,placement:t,middlewareData:{},isPositioned:!1}),[f,p]=O.useState(r);qt(f,r)||p(r);let[m,h]=O.useState(null),[g,_]=O.useState(null),v=O.useCallback(e=>{e!==S.current&&(S.current=e,h(e))},[]),y=O.useCallback(e=>{e!==C.current&&(C.current=e,_(e))},[]),b=a||m,x=o||g,S=O.useRef(null),C=O.useRef(null),w=O.useRef(u),T=c!=null,E=Xt(c),D=Xt(i),k=Xt(l),A=O.useCallback(()=>{if(!S.current||!C.current)return;let e={placement:t,strategy:n,middleware:f};D.current&&(e.platform=D.current),Wt(S.current,C.current,e).then(e=>{let t={...e,isPositioned:k.current!==!1};j.current&&!qt(w.current,t)&&(w.current=t,Gt.flushSync(()=>{d(t)}))})},[f,t,n,D,k]);Kt(()=>{l===!1&&w.current.isPositioned&&(w.current.isPositioned=!1,d(e=>({...e,isPositioned:!1})))},[l]);let j=O.useRef(!1);Kt(()=>(j.current=!0,()=>{j.current=!1}),[]),Kt(()=>{if(b&&(S.current=b),x&&(C.current=x),b&&x){if(E.current)return E.current(b,x,A);A()}},[b,x,A,E,T]);let M=O.useMemo(()=>({reference:S,floating:C,setReference:v,setFloating:y}),[v,y]),N=O.useMemo(()=>({reference:b,floating:x}),[b,x]),P=O.useMemo(()=>{let e={position:n,left:0,top:0};if(!N.floating)return e;let t=Yt(N.floating,u.x),r=Yt(N.floating,u.y);return s?{...e,transform:`translate(`+t+`px, `+r+`px)`,...Jt(N.floating)>=1.5&&{willChange:`transform`}}:{position:n,left:t,top:r}},[n,s,N.floating,u.x,u.y]);return O.useMemo(()=>({...u,update:A,refs:M,elements:N,floatingStyles:P}),[u,A,M,N,P])}var Qt=e=>{function t(e){return{}.hasOwnProperty.call(e,`current`)}return{name:`arrow`,options:e,fn(n){let{element:r,padding:i}=typeof e==`function`?e(n):e;return r&&t(r)?r.current==null?{}:Ht({element:r.current,padding:i}).fn(n):r?Ht({element:r,padding:i}).fn(n):{}}}},$t=(e,t)=>{let n=Lt(e);return{name:n.name,fn:n.fn,options:[e,t]}},en=(e,t)=>{let n=Rt(e);return{name:n.name,fn:n.fn,options:[e,t]}},tn=(e,t)=>({fn:Ut(e).fn,options:[e,t]}),nn=(e,t)=>{let n=zt(e);return{name:n.name,fn:n.fn,options:[e,t]}},rn=(e,t)=>{let n=Bt(e);return{name:n.name,fn:n.fn,options:[e,t]}},an=(e,t)=>{let n=Vt(e);return{name:n.name,fn:n.fn,options:[e,t]}},on=(e,t)=>{let n=Qt(e);return{name:n.name,fn:n.fn,options:[e,t]}};function sn(e){let[t,n]=O.useState(void 0);return x(()=>{if(e){n({width:e.offsetWidth,height:e.offsetHeight});let t=new ResizeObserver(t=>{if(!Array.isArray(t)||!t.length)return;let r=t[0],i,a;if(`borderBoxSize`in r){let e=r.borderBoxSize,t=Array.isArray(e)?e[0]:e;i=t.inlineSize,a=t.blockSize}else i=e.offsetWidth,a=e.offsetHeight;n({width:i,height:a})});return t.observe(e,{box:`border-box`}),()=>t.unobserve(e)}else n(void 0)},[e]),t}var F=c(),cn=Object.defineProperty,ln=(e,t)=>cn(e,`name`,{value:t,configurable:!0}),un=`Popper`,[dn,fn]=o(un),[pn,mn]=dn(un),hn=ln(e=>{let{__scopePopper:t,children:n}=e,[r,i]=O.useState(null),[a,o]=O.useState(void 0);return(0,F.jsx)(pn,{scope:t,anchor:r,onAnchorChange:i,placementState:a,setPlacementState:o,children:n})},`Popper`),gn=`PopperAnchor`,_n=O.forwardRef(ln(function(e,t){let{__scopePopper:n,virtualRef:r,...i}=e,o=mn(gn,n),s=O.useRef(null),c=o.onAnchorChange,l=a(t,O.useCallback(e=>{s.current=e,e&&c(e)},[c])),u=O.useRef(null);O.useEffect(()=>{if(!r)return;let e=u.current;u.current=r.current,e!==u.current&&c(u.current)});let d=o.placementState&&wn(o.placementState),f=d?.[0],p=d?.[1];return r?null:(0,F.jsx)(C.div,{"data-radix-popper-side":f,"data-radix-popper-align":p,...i,ref:l})},`PopperAnchor`)),vn=`PopperContent`,[yn,bn]=dn(vn),xn=O.forwardRef(ln(function(e,t){let{__scopePopper:n,side:r=`bottom`,sideOffset:i=0,align:o=`center`,alignOffset:s=0,arrowPadding:c=0,avoidCollisions:l=!0,collisionBoundary:u=[],collisionPadding:d=0,sticky:f=`partial`,hideWhenDetached:p=!1,updatePositionStrategy:h=`optimized`,onPlaced:g,..._}=e,v=mn(vn,n),[y,b]=O.useState(null),S=a(t,b),[w,T]=O.useState(null),E=sn(w),D=E?.width??0,k=E?.height??0,A=r+(o===`center`?``:`-`+o),j=typeof d==`number`?d:{top:0,right:0,bottom:0,left:0,...d},M=Array.isArray(u)?u:[u],N=M.length>0,P={padding:j,boundary:M.filter(Sn),altBoundary:N},{refs:ee,floatingStyles:te,placement:ne,isPositioned:re,middlewareData:ie}=Zt({strategy:`fixed`,placement:A,whileElementsMounted:ln((...e)=>It(...e,{animationFrame:h===`always`}),`whileElementsMounted`),elements:{reference:v.anchor},middleware:[$t({mainAxis:i+k,alignmentAxis:s}),l&&en({mainAxis:!0,crossAxis:!1,limiter:f===`partial`?tn():void 0,...P}),l&&nn({...P}),rn({...P,apply:ln(({elements:e,rects:t,availableWidth:n,availableHeight:r})=>{let{width:i,height:a}=t.reference,o=e.floating.style;o.setProperty(`--radix-popper-available-width`,`${n}px`),o.setProperty(`--radix-popper-available-height`,`${r}px`),o.setProperty(`--radix-popper-anchor-width`,`${i}px`),o.setProperty(`--radix-popper-anchor-height`,`${a}px`)},`apply`)}),w&&on({element:w,padding:c}),Cn({arrowWidth:D,arrowHeight:k}),p&&an({strategy:`referenceHidden`,...P,boundary:N?P.boundary:void 0})]}),ae=v.setPlacementState;x(()=>(ae(ne),()=>{ae(void 0)}),[ne,ae]);let[oe,se]=wn(ne),ce=m(g);x(()=>{re&&ce?.()},[re,ce]);let le=ie.arrow?.x,ue=ie.arrow?.y,de=ie.arrow?.centerOffset!==0,[fe,pe]=O.useState();return x(()=>{y&&pe(window.getComputedStyle(y).zIndex)},[y]),(0,F.jsx)(`div`,{ref:ee.setFloating,"data-radix-popper-content-wrapper":``,style:{...te,transform:re?te.transform:`translate(0, -200%)`,minWidth:`max-content`,zIndex:fe,"--radix-popper-transform-origin":[ie.transformOrigin?.x,ie.transformOrigin?.y].join(` `),...ie.hide?.referenceHidden&&{visibility:`hidden`,pointerEvents:`none`}},dir:e.dir,children:(0,F.jsx)(yn,{scope:n,placedSide:oe,placedAlign:se,onArrowChange:T,arrowX:le,arrowY:ue,shouldHideArrow:de,children:(0,F.jsx)(C.div,{"data-side":oe,"data-align":se,..._,ref:S,style:{..._.style,animation:re?_.style?.animation:`none`}})})})},`PopperContent`));function Sn(e){return e!==null}ln(Sn,`isNotNull`);var Cn=ln(e=>({name:`transformOrigin`,options:e,fn(t){let{placement:n,rects:r,middlewareData:i}=t,a=i.arrow?.centerOffset!==0,o=a?0:e.arrowWidth,s=a?0:e.arrowHeight,[c,l]=wn(n),u={start:`0%`,center:`50%`,end:`100%`}[l],d=(i.arrow?.x??0)+o/2,f=(i.arrow?.y??0)+s/2,p=``,m=``;return c===`bottom`?(p=a?u:`${d}px`,m=`${-s}px`):c===`top`?(p=a?u:`${d}px`,m=`${r.floating.height+s}px`):c===`right`?(p=`${-s}px`,m=a?u:`${f}px`):c===`left`&&(p=`${r.floating.width+s}px`,m=a?u:`${f}px`),{data:{x:p,y:m}}}}),`transformOrigin`);function wn(e){let[t,n=`center`]=e.split(`-`);return[t,n]}ln(wn,`getSideAndAlignFromPlacement`);var Tn=hn,En=_n,Dn=xn,On=Object.defineProperty,kn=(e,t)=>On(e,`name`,{value:t,configurable:!0}),An=Object.freeze({position:`absolute`,border:0,width:1,height:1,padding:0,margin:-1,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,whiteSpace:`nowrap`,wordWrap:`normal`}),jn=O.forwardRef(kn(function(e,t){return(0,F.jsx)(C.span,{...e,ref:t,style:{...An,...e.style}})},`VisuallyHidden`)),Mn=Object.defineProperty,Nn=(e,t)=>Mn(e,`name`,{value:t,configurable:!0}),[Pn,Fn]=o(`Tooltip`,[fn]),In=fn(),Ln=`TooltipProvider`,Rn=700,zn=`tooltip.open`,[Bn,Vn]=Pn(Ln),Hn=Nn(e=>{let{__scopeTooltip:t,delayDuration:n=Rn,skipDelayDuration:r=300,disableHoverableContent:i=!1,children:a}=e,o=O.useRef(!0),s=O.useRef(!1),c=O.useRef(0);return O.useEffect(()=>{let e=c.current;return()=>window.clearTimeout(e)},[]),(0,F.jsx)(Bn,{scope:t,isOpenDelayedRef:o,delayDuration:n,onOpen:O.useCallback(()=>{r<=0||(window.clearTimeout(c.current),o.current=!1)},[r]),onClose:O.useCallback(()=>{r<=0||(window.clearTimeout(c.current),c.current=window.setTimeout(()=>o.current=!0,r))},[r]),isPointerInTransitRef:s,onPointerInTransitChange:O.useCallback(e=>{s.current=e},[]),disableHoverableContent:i,children:a})},`TooltipProvider`),Un=`Tooltip`,[Wn,Gn]=Pn(Un),Kn=Nn(e=>{let{__scopeTooltip:n,children:r,open:i,defaultOpen:a,onOpenChange:o,disableHoverableContent:s,delayDuration:c}=e,l=Vn(Un,e.__scopeTooltip),d=In(n),[f,p]=O.useState(null),[m,h]=O.useState(void 0),g=u(),_=O.useRef(0),v=s??l.disableHoverableContent,y=c??l.delayDuration,b=O.useRef(!1),[x,S]=t({prop:i,defaultProp:a??!1,onChange:Nn(e=>{e?(l.onOpen(),document.dispatchEvent(new CustomEvent(zn))):l.onClose(),o?.(e)},`onChange`),caller:Un}),C=O.useMemo(()=>x?b.current?`delayed-open`:`instant-open`:`closed`,[x]),w=O.useCallback(()=>{window.clearTimeout(_.current),_.current=0,b.current=!1,S(!0)},[S]),T=O.useCallback(()=>{window.clearTimeout(_.current),_.current=0,S(!1)},[S]),E=O.useCallback(()=>{window.clearTimeout(_.current),_.current=window.setTimeout(()=>{b.current=!0,S(!0),_.current=0},y)},[y,S]);O.useEffect(()=>()=>{_.current&&=(window.clearTimeout(_.current),0)},[]);let D=m??g;return(0,F.jsx)(Tn,{...d,children:(0,F.jsx)(Wn,{scope:n,contentId:D,setContentId:h,open:x,stateAttribute:C,trigger:f,onTriggerChange:p,onTriggerEnter:O.useCallback(()=>{l.isOpenDelayedRef.current?E():w()},[l.isOpenDelayedRef,E,w]),onTriggerLeave:O.useCallback(()=>{v?T():(window.clearTimeout(_.current),_.current=0)},[T,v]),onOpen:w,onClose:T,disableHoverableContent:v,children:r})})},`Tooltip`),qn=`TooltipTrigger`,Jn=O.forwardRef(Nn(function(e,t){let{__scopeTooltip:r,...i}=e,o=Gn(qn,r),s=Vn(qn,r),c=In(r),l=a(t,O.useRef(null),o.onTriggerChange),u=O.useRef(!1),d=O.useRef(!1),f=O.useCallback(()=>u.current=!1,[]);return O.useEffect(()=>()=>document.removeEventListener(`pointerup`,f),[f]),(0,F.jsx)(En,{asChild:!0,...c,children:(0,F.jsx)(C.button,{"aria-describedby":o.open?o.contentId:void 0,"data-state":o.stateAttribute,...i,ref:l,onPointerMove:n(e.onPointerMove,e=>{e.pointerType!==`touch`&&!d.current&&!s.isPointerInTransitRef.current&&(o.onTriggerEnter(),d.current=!0)}),onPointerLeave:n(e.onPointerLeave,()=>{o.onTriggerLeave(),d.current=!1}),onPointerDown:n(e.onPointerDown,()=>{o.open&&o.onClose(),u.current=!0,document.addEventListener(`pointerup`,f,{once:!0})}),onFocus:n(e.onFocus,()=>{u.current||o.onOpen()}),onBlur:n(e.onBlur,o.onClose),onClick:n(e.onClick,o.onClose)})})},`TooltipTrigger`)),Yn=`TooltipPortal`,[Xn,Zn]=Pn(Yn,{forceMount:void 0}),Qn=Nn(e=>{let{__scopeTooltip:t,forceMount:n,children:r,container:i}=e,a=Gn(Yn,t);return(0,F.jsx)(Xn,{scope:t,forceMount:n,children:(0,F.jsx)(b,{present:n||a.open,children:(0,F.jsx)(_,{asChild:!0,container:i,children:r})})})},`TooltipPortal`),$n=`TooltipContent`,er=O.forwardRef(Nn(function(e,t){let n=Zn($n,e.__scopeTooltip),{forceMount:r=n.forceMount,side:i=`top`,...a}=e,o=Gn($n,e.__scopeTooltip);return(0,F.jsx)(b,{present:r||o.open,children:o.disableHoverableContent?(0,F.jsx)(rr,{side:i,...a,ref:t}):(0,F.jsx)(tr,{side:i,...a,ref:t})})},`TooltipContent`)),tr=O.forwardRef(Nn(function(e,t){let n=Gn($n,e.__scopeTooltip),r=Vn($n,e.__scopeTooltip),i=O.useRef(null),o=a(t,i),[s,c]=O.useState(null),{trigger:l,onClose:u}=n,d=i.current,{onPointerInTransitChange:f}=r,p=O.useCallback(()=>{c(null),f(!1)},[f]),m=O.useCallback((e,t)=>{let n=e.currentTarget,r={x:e.clientX,y:e.clientY},i=ar(r,ir(r,n.getBoundingClientRect())),a=or(t.getBoundingClientRect()),o=cr([...i,...a]);c(o),f(!0)},[f]);return O.useEffect(()=>()=>p(),[p]),O.useEffect(()=>{if(l&&d){let e=Nn(e=>m(e,d),`handleTriggerLeave`),t=Nn(e=>m(e,l),`handleContentLeave`);return l.addEventListener(`pointerleave`,e),d.addEventListener(`pointerleave`,t),()=>{l.removeEventListener(`pointerleave`,e),d.removeEventListener(`pointerleave`,t)}}},[l,d,m,p]),O.useEffect(()=>{if(s){let e=Nn(e=>{let t=e.target,n={x:e.clientX,y:e.clientY},r=l?.contains(t)||d?.contains(t),i=!sr(n,s);r?p():i&&(p(),u())},`handleTrackPointerGrace`);return document.addEventListener(`pointermove`,e),()=>document.removeEventListener(`pointermove`,e)}},[l,d,s,u,p]),(0,F.jsx)(rr,{...e,ref:o})},`TooltipContentHoverable`)),nr=S(`TooltipContent`),rr=O.forwardRef(Nn(function(e,t){let{__scopeTooltip:n,children:r,"aria-label":i,id:a,onEscapeKeyDown:o,onPointerDownOutside:s,...c}=e,l=Gn($n,n),u=In(n),{onClose:d}=l;O.useEffect(()=>(document.addEventListener(zn,d),()=>document.removeEventListener(zn,d)),[d]),O.useEffect(()=>{if(l.trigger){let e=Nn(e=>{e.target instanceof Node&&e.target.contains(l.trigger)&&d()},`handleScroll`);return window.addEventListener(`scroll`,e,{capture:!0}),()=>window.removeEventListener(`scroll`,e,{capture:!0})}},[l.trigger,d]);let{setContentId:f}=l;return x(()=>(f(a),()=>{f(void 0)}),[a,f]),(0,F.jsx)(h,{asChild:!0,disableOutsidePointerEvents:!1,onEscapeKeyDown:o,onPointerDownOutside:s,onFocusOutside:e=>e.preventDefault(),onDismiss:d,children:(0,F.jsxs)(Dn,{"data-state":l.stateAttribute,role:i?void 0:`tooltip`,id:i?void 0:l.contentId,...u,...c,ref:t,style:{...c.style,"--radix-tooltip-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-tooltip-content-available-width":`var(--radix-popper-available-width)`,"--radix-tooltip-content-available-height":`var(--radix-popper-available-height)`,"--radix-tooltip-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-tooltip-trigger-height":`var(--radix-popper-anchor-height)`},children:[(0,F.jsx)(nr,{children:r}),i?(0,F.jsx)(jn,{id:l.contentId,role:`tooltip`,children:i}):null]})})},`TooltipContentImpl`));function ir(e,t){let n=Math.abs(t.top-e.y),r=Math.abs(t.bottom-e.y),i=Math.abs(t.right-e.x),a=Math.abs(t.left-e.x);switch(Math.min(n,r,i,a)){case a:return`left`;case i:return`right`;case n:return`top`;case r:return`bottom`;default:throw Error(`unreachable`)}}Nn(ir,`getExitSideFromRect`);function ar(e,t,n=5){let r=[];switch(t){case`top`:r.push({x:e.x-n,y:e.y+n},{x:e.x+n,y:e.y+n});break;case`bottom`:r.push({x:e.x-n,y:e.y-n},{x:e.x+n,y:e.y-n});break;case`left`:r.push({x:e.x+n,y:e.y-n},{x:e.x+n,y:e.y+n});break;case`right`:r.push({x:e.x-n,y:e.y-n},{x:e.x-n,y:e.y+n});break}return r}Nn(ar,`getPaddedExitPoints`);function or(e){let{top:t,right:n,bottom:r,left:i}=e;return[{x:i,y:t},{x:n,y:t},{x:n,y:r},{x:i,y:r}]}Nn(or,`getPointsFromRect`);function sr(e,t){let{x:n,y:r}=e,i=!1;for(let e=0,a=t.length-1;er!=d>r&&n<(u-c)*(r-l)/(d-l)+c&&(i=!i)}return i}Nn(sr,`isPointInPolygon`);function cr(e){let t=e.slice();return t.sort((e,t)=>e.xt.x?1:e.yt.y)),lr(t)}Nn(cr,`getHull`);function lr(e){if(e.length<=1)return e.slice();let t=[];for(let n=0;n=2;){let e=t[t.length-1],n=t[t.length-2];if((e.x-n.x)*(r.y-n.y)>=(e.y-n.y)*(r.x-n.x))t.pop();else break}t.push(r)}t.pop();let n=[];for(let t=e.length-1;t>=0;t--){let r=e[t];for(;n.length>=2;){let e=n[n.length-1],t=n[n.length-2];if((e.x-t.x)*(r.y-t.y)>=(e.y-t.y)*(r.x-t.x))n.pop();else break}n.push(r)}return n.pop(),t.length===1&&n.length===1&&t[0].x===n[0].x&&t[0].y===n[0].y?t:t.concat(n)}Nn(lr,`getHullPresorted`);var ur=Hn,dr=Kn,fr=Jn,pr=Qn,mr=er,hr=ur,gr=dr,_r=fr,vr=(0,O.forwardRef)(({className:e,sideOffset:t=6,...n},r)=>(0,F.jsx)(pr,{children:(0,F.jsx)(mr,{ref:r,sideOffset:t,className:[`tooltip-content`,e].filter(Boolean).join(` `),...n})}));vr.displayName=`TooltipContent`;function yr({rows:e}){let[t,n]=(0,O.useState)(()=>new Set),r=[...e].sort((e,t)=>t.hit_count-e.hit_count||e.ip.localeCompare(t.ip));if(r.length===0)return(0,F.jsx)(`p`,{className:`section-empty`,children:`IP reputation rows appear after an egress IP is observed.`});let i=e=>n(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n});return(0,F.jsxs)(hr,{delayDuration:250,children:[(0,F.jsx)(`div`,{className:`ip-table-wrap`,children:(0,F.jsxs)(`table`,{className:`table ip-table`,children:[(0,F.jsx)(`thead`,{children:(0,F.jsxs)(`tr`,{children:[(0,F.jsx)(`th`,{scope:`col`,children:`IP`}),(0,F.jsx)(`th`,{scope:`col`,children:`Category`}),(0,F.jsx)(`th`,{scope:`col`,children:`Country`}),(0,F.jsx)(`th`,{scope:`col`,children:`ISP`}),(0,F.jsx)(`th`,{scope:`col`,children:`ASN`}),(0,F.jsx)(`th`,{scope:`col`,children:`Risk`}),(0,F.jsx)(`th`,{scope:`col`,children:`GreyNoise`}),(0,F.jsx)(`th`,{scope:`col`,children:`DNSBL`}),(0,F.jsx)(`th`,{scope:`col`,children:`First seen`}),(0,F.jsx)(`th`,{scope:`col`,children:`Last seen`}),(0,F.jsx)(`th`,{scope:`col`,children:`Hits`})]})}),(0,F.jsx)(`tbody`,{children:r.map(e=>(0,F.jsxs)(`tr`,{children:[(0,F.jsx)(`th`,{scope:`row`,className:`mono`,children:e.ip}),(0,F.jsx)(`td`,{children:(0,F.jsx)(xr,{category:e.category})}),(0,F.jsx)(`td`,{children:e.country||`—`}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`Full ISP for ${e.ip}`,value:e.isp||`—`})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`Full ASN for ${e.ip}`,value:e.asn||`—`})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(Sr,{score:e.risk_score})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`Full GreyNoise classification for ${e.ip}`,value:e.greynoise_class||`—`})}),(0,F.jsx)(`td`,{children:(0,F.jsx)(br,{label:`DNSBL details for ${e.ip}`,value:e.dnsbl_listed?`Listed: ${e.dnsbl_hits.join(`, `)||`unspecified list`}`:`Not listed`})}),(0,F.jsx)(`td`,{children:v(e.first_seen)}),(0,F.jsx)(`td`,{children:v(e.last_seen)}),(0,F.jsx)(`td`,{className:`numeric`,children:e.hit_count})]},e.ip))})]})}),(0,F.jsx)(`div`,{className:`ip-records`,children:r.map(e=>{let n=t.has(e.ip);return(0,F.jsxs)(`article`,{className:`ip-record`,children:[(0,F.jsxs)(`div`,{className:`ip-record-summary`,children:[(0,F.jsx)(`strong`,{className:`mono`,children:e.ip}),(0,F.jsx)(xr,{category:e.category}),(0,F.jsx)(Sr,{score:e.risk_score})]}),(0,F.jsxs)(`button`,{type:`button`,className:`ip-details-trigger`,"aria-expanded":n,"aria-controls":`ip-${wr(e.ip)}-details`,onClick:()=>i(e.ip),children:[n?(0,F.jsx)(s,{size:16,"aria-hidden":`true`}):(0,F.jsx)(w,{size:16,"aria-hidden":`true`}),` `,n?`Hide`:`Show`,` details for `,e.ip]}),n&&(0,F.jsxs)(`dl`,{id:`ip-${wr(e.ip)}-details`,className:`ip-details`,children:[(0,F.jsx)(Cr,{label:`Country`,value:e.country||`—`}),(0,F.jsx)(Cr,{label:`ISP`,value:e.isp||`—`}),(0,F.jsx)(Cr,{label:`ASN`,value:e.asn||`—`}),(0,F.jsx)(Cr,{label:`GreyNoise`,value:e.greynoise_class||`—`}),(0,F.jsx)(Cr,{label:`DNSBL`,value:e.dnsbl_listed?`Listed: ${e.dnsbl_hits.join(`, `)||`unspecified list`}`:`Not listed`}),(0,F.jsx)(Cr,{label:`First seen`,value:v(e.first_seen)}),(0,F.jsx)(Cr,{label:`Last seen`,value:v(e.last_seen)}),(0,F.jsx)(Cr,{label:`Hits`,value:String(e.hit_count)})]})]},e.ip)})})]})}function br({value:e,label:t}){return(0,F.jsxs)(gr,{children:[(0,F.jsx)(_r,{asChild:!0,children:(0,F.jsxs)(`button`,{type:`button`,className:`clipped-value`,"aria-label":t,children:[e,(0,F.jsx)(E,{size:13,"aria-hidden":`true`})]})}),(0,F.jsx)(vr,{side:`top`,children:e})]})}function xr({category:e}){return(0,F.jsxs)(`span`,{className:`category-label category-${[`mobile`,`residential`,`datacenter`].includes(e)?e:`unknown`}`,children:[(0,F.jsx)(`span`,{className:`category-dot`,"aria-hidden":`true`}),e||`unknown`]})}function Sr({score:e}){if(e==null)return(0,F.jsx)(`span`,{className:`risk-label risk-unknown`,children:`Unknown`});let t=e>=70?`High`:e>=40?`Elevated`:`Low`;return(0,F.jsxs)(`span`,{className:`risk-label risk-${t.toLowerCase()}`,children:[t,` `,e]})}function Cr({label:e,value:t}){return(0,F.jsxs)(`div`,{children:[(0,F.jsx)(`dt`,{children:e}),(0,F.jsx)(`dd`,{children:t})]})}function wr(e){return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}var Tr=`dangerouslySetInnerHTML.onCopy.onCopyCapture.onCut.onCutCapture.onPaste.onPasteCapture.onCompositionEnd.onCompositionEndCapture.onCompositionStart.onCompositionStartCapture.onCompositionUpdate.onCompositionUpdateCapture.onFocus.onFocusCapture.onBlur.onBlurCapture.onChange.onChangeCapture.onBeforeInput.onBeforeInputCapture.onInput.onInputCapture.onReset.onResetCapture.onSubmit.onSubmitCapture.onInvalid.onInvalidCapture.onLoad.onLoadCapture.onError.onErrorCapture.onKeyDown.onKeyDownCapture.onKeyPress.onKeyPressCapture.onKeyUp.onKeyUpCapture.onAbort.onAbortCapture.onCanPlay.onCanPlayCapture.onCanPlayThrough.onCanPlayThroughCapture.onDurationChange.onDurationChangeCapture.onEmptied.onEmptiedCapture.onEncrypted.onEncryptedCapture.onEnded.onEndedCapture.onLoadedData.onLoadedDataCapture.onLoadedMetadata.onLoadedMetadataCapture.onLoadStart.onLoadStartCapture.onPause.onPauseCapture.onPlay.onPlayCapture.onPlaying.onPlayingCapture.onProgress.onProgressCapture.onRateChange.onRateChangeCapture.onSeeked.onSeekedCapture.onSeeking.onSeekingCapture.onStalled.onStalledCapture.onSuspend.onSuspendCapture.onTimeUpdate.onTimeUpdateCapture.onVolumeChange.onVolumeChangeCapture.onWaiting.onWaitingCapture.onAuxClick.onAuxClickCapture.onClick.onClickCapture.onContextMenu.onContextMenuCapture.onDoubleClick.onDoubleClickCapture.onDrag.onDragCapture.onDragEnd.onDragEndCapture.onDragEnter.onDragEnterCapture.onDragExit.onDragExitCapture.onDragLeave.onDragLeaveCapture.onDragOver.onDragOverCapture.onDragStart.onDragStartCapture.onDrop.onDropCapture.onMouseDown.onMouseDownCapture.onMouseEnter.onMouseLeave.onMouseMove.onMouseMoveCapture.onMouseOut.onMouseOutCapture.onMouseOver.onMouseOverCapture.onMouseUp.onMouseUpCapture.onSelect.onSelectCapture.onTouchCancel.onTouchCancelCapture.onTouchEnd.onTouchEndCapture.onTouchMove.onTouchMoveCapture.onTouchStart.onTouchStartCapture.onPointerDown.onPointerDownCapture.onPointerMove.onPointerMoveCapture.onPointerUp.onPointerUpCapture.onPointerCancel.onPointerCancelCapture.onPointerEnter.onPointerEnterCapture.onPointerLeave.onPointerLeaveCapture.onPointerOver.onPointerOverCapture.onPointerOut.onPointerOutCapture.onGotPointerCapture.onGotPointerCaptureCapture.onLostPointerCapture.onLostPointerCaptureCapture.onScroll.onScrollCapture.onWheel.onWheelCapture.onAnimationStart.onAnimationStartCapture.onAnimationEnd.onAnimationEndCapture.onAnimationIteration.onAnimationIterationCapture.onTransitionEnd.onTransitionEndCapture`.split(`.`);function Er(e){return typeof e==`string`&&Tr.includes(e)}var Dr=new Set(`aria-activedescendant.aria-atomic.aria-autocomplete.aria-busy.aria-checked.aria-colcount.aria-colindex.aria-colspan.aria-controls.aria-current.aria-describedby.aria-details.aria-disabled.aria-errormessage.aria-expanded.aria-flowto.aria-haspopup.aria-hidden.aria-invalid.aria-keyshortcuts.aria-label.aria-labelledby.aria-level.aria-live.aria-modal.aria-multiline.aria-multiselectable.aria-orientation.aria-owns.aria-placeholder.aria-posinset.aria-pressed.aria-readonly.aria-relevant.aria-required.aria-roledescription.aria-rowcount.aria-rowindex.aria-rowspan.aria-selected.aria-setsize.aria-sort.aria-valuemax.aria-valuemin.aria-valuenow.aria-valuetext.className.color.height.id.lang.max.media.method.min.name.style.target.width.role.tabIndex.accentHeight.accumulate.additive.alignmentBaseline.allowReorder.alphabetic.amplitude.arabicForm.ascent.attributeName.attributeType.autoReverse.azimuth.baseFrequency.baselineShift.baseProfile.bbox.begin.bias.by.calcMode.capHeight.clip.clipPath.clipPathUnits.clipRule.colorInterpolation.colorInterpolationFilters.colorProfile.colorRendering.contentScriptType.contentStyleType.cursor.cx.cy.d.decelerate.descent.diffuseConstant.direction.display.divisor.dominantBaseline.dur.dx.dy.edgeMode.elevation.enableBackground.end.exponent.externalResourcesRequired.fill.fillOpacity.fillRule.filter.filterRes.filterUnits.floodColor.floodOpacity.focusable.fontFamily.fontSize.fontSizeAdjust.fontStretch.fontStyle.fontVariant.fontWeight.format.from.fx.fy.g1.g2.glyphName.glyphOrientationHorizontal.glyphOrientationVertical.glyphRef.gradientTransform.gradientUnits.hanging.horizAdvX.horizOriginX.href.ideographic.imageRendering.in2.in.intercept.k1.k2.k3.k4.k.kernelMatrix.kernelUnitLength.kerning.keyPoints.keySplines.keyTimes.lengthAdjust.letterSpacing.lightingColor.limitingConeAngle.local.markerEnd.markerHeight.markerMid.markerStart.markerUnits.markerWidth.mask.maskContentUnits.maskUnits.mathematical.mode.numOctaves.offset.opacity.operator.order.orient.orientation.origin.overflow.overlinePosition.overlineThickness.paintOrder.panose1.pathLength.patternContentUnits.patternTransform.patternUnits.pointerEvents.pointsAtX.pointsAtY.pointsAtZ.preserveAlpha.preserveAspectRatio.primitiveUnits.r.radius.refX.refY.renderingIntent.repeatCount.repeatDur.requiredExtensions.requiredFeatures.restart.result.rotate.rx.ry.seed.shapeRendering.slope.spacing.specularConstant.specularExponent.speed.spreadMethod.startOffset.stdDeviation.stemh.stemv.stitchTiles.stopColor.stopOpacity.strikethroughPosition.strikethroughThickness.string.stroke.strokeDasharray.strokeDashoffset.strokeLinecap.strokeLinejoin.strokeMiterlimit.strokeOpacity.strokeWidth.surfaceScale.systemLanguage.tableValues.targetX.targetY.textAnchor.textDecoration.textLength.textRendering.to.transform.u1.u2.underlinePosition.underlineThickness.unicode.unicodeBidi.unicodeRange.unitsPerEm.vAlphabetic.values.vectorEffect.version.vertAdvY.vertOriginX.vertOriginY.vHanging.vIdeographic.viewTarget.visibility.vMathematical.widths.wordSpacing.writingMode.x1.x2.x.xChannelSelector.xHeight.xlinkActuate.xlinkArcrole.xlinkHref.xlinkRole.xlinkShow.xlinkTitle.xlinkType.xmlBase.xmlLang.xmlns.xmlnsXlink.xmlSpace.y1.y2.y.yChannelSelector.z.zoomAndPan.ref.key.angle`.split(`.`));function Or(e){return typeof e==`string`&&Dr.has(e)}function kr(e){return typeof e==`string`&&e.startsWith(`data-`)}function Ar(e){if(typeof e!=`object`||!e)return{};var t={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(Or(n)||kr(n))&&(t[n]=e[n]);return t}function jr(e){if(e==null)return null;if((0,O.isValidElement)(e)&&typeof e.props==`object`&&e.props!==null){var t=e.props;return Ar(t)}return typeof e==`object`&&!Array.isArray(e)?Ar(e):null}function Mr(e){var t={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(Or(n)||kr(n)||Er(n))&&(t[n]=e[n]);return t}function Nr(e){return e==null?null:(0,O.isValidElement)(e)?Mr(e.props):typeof e==`object`&&!Array.isArray(e)?Mr(e):null}var Pr=[`children`,`width`,`height`,`viewBox`,`className`,`style`,`title`,`desc`];function Fr(){return Fr=Object.assign?Object.assign.bind():function(e){for(var t=1;t{var n=e.children,r=e.width,i=e.height,a=e.viewBox,o=e.className,s=e.style,c=e.title,l=e.desc,u=Ir(e,Pr),d=a||{width:r,height:i,x:0,y:0},f=g(`recharts-surface`,o);return O.createElement(`svg`,Fr({},Mr(u),{className:f,width:r,height:i,style:s,viewBox:`${d.x} ${d.y} ${d.width} ${d.height}`,ref:t}),O.createElement(`title`,null,c),O.createElement(`desc`,null,l),n)}),zr=[`children`,`className`];function Br(){return Br=Object.assign?Object.assign.bind():function(e){for(var t=1;t{var n=e.children,r=e.className,i=Vr(e,zr),a=g(`recharts-layer`,r);return O.createElement(`g`,Br({className:a},Mr(i),{ref:t}),n)});function Ur(e){return e===`__proto__`}function Wr(e){switch(typeof e){case`number`:case`symbol`:return!1;case`string`:return e.includes(`.`)||e.includes(`[`)||e.includes(`]`)}}function Gr(e){return typeof e==`string`||typeof e==`symbol`?e:Object.is(e?.valueOf?.(),-0)?`-0`:String(e)}function Kr(e){if(e==null)return``;if(typeof e==`string`)return e;if(Array.isArray(e))return e.map(Kr).join(`,`);let t=String(e);return t===`0`&&Object.is(Number(e),-0)?`-0`:t}function qr(e){if(Array.isArray(e))return e.map(Gr);if(typeof e==`symbol`)return[e];e=Kr(e);let t=[],n=e.length;if(n===0)return t;let r=0,i=``,a=``,o=!1;for(e.charCodeAt(0)===46&&t.push(``);r1&&arguments[1]!==void 0?arguments[1]:Xr),n=Math.round(e*t)/t;return Object.is(n,-0)?0:n}function Qr(e){var t=[...arguments].slice(1);return e.reduce((e,n,r)=>{var i=t[r-1];return typeof i==`string`?e+i+n:i===void 0?e+n:e+Zr(i)+n},``)}var $r=e=>e===0?0:e>0?1:-1,ei=e=>typeof e==`number`&&e!=+e,ti=e=>typeof e==`string`&&e.length>1&&e.indexOf(`%`)===e.length-1,L=e=>(typeof e==`number`||e instanceof Number)&&!ei(e),ni=e=>L(e)||typeof e==`string`,ri=0,ii=e=>{var t=++ri;return`${e||``}${t}`},ai=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,r=arguments.length>3&&arguments[3]!==void 0&&arguments[3];if(!L(e)&&typeof e!=`string`)return n;var i;if(ti(e)){if(t==null)return n;var a=e.indexOf(`%`);i=t*parseFloat(e.slice(0,a))/100}else i=+e;return ei(i)&&(i=n),r&&t!=null&&i>t&&(i=t),i},oi=e=>{if(!Array.isArray(e))return!1;for(var t=e.length,n={},r=0;re&&(typeof t==`function`?t(e):Jr(e,t))===n)}var z=e=>e==null,ci=e=>z(e)?e:`${e.charAt(0).toUpperCase()}${e.slice(1)}`;function li(e){return e!=null}function ui(){}function di(e){if(e)return{x:e.x,y:e.y,upperWidth:`upperWidth`in e?e.upperWidth:e.width,lowerWidth:`lowerWidth`in e?e.lowerWidth:e.width,width:e.width,height:e.height}}function fi(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function pi(e){for(var t=1;t{var t=e.viewBox,n=e.position,r=e.offset,i=r===void 0?0:r,a=e.parentViewBox,o=e.clamp,s=di(t),c=s.x,l=s.y,u=s.height,d=s.upperWidth,f=s.lowerWidth,p=c,m=c+(d-f)/2,h=(p+m)/2,g=(d+f)/2,_=p+d/2,v=u>=0?1:-1,y=v*i,b=v>0?`end`:`start`,x=v>0?`start`:`end`,S=d>=0?1:-1,C=S*i,w=S>0?`end`:`start`,T=S>0?`start`:`end`,E=a;if(n===`top`){var D={x:p+d/2,y:l-y,horizontalAnchor:`middle`,verticalAnchor:b};return o&&E&&(D.height=Math.max(l-E.y,0),D.width=d),D}if(n===`bottom`){var O={x:m+f/2,y:l+u+y,horizontalAnchor:`middle`,verticalAnchor:x};return o&&E&&(O.height=Math.max(E.y+E.height-(l+u),0),O.width=f),O}if(n===`left`){var k={x:h-C,y:l+u/2,horizontalAnchor:w,verticalAnchor:`middle`};return o&&E&&(k.width=Math.max(k.x-E.x,0),k.height=u),k}if(n===`right`){var A={x:h+g+C,y:l+u/2,horizontalAnchor:T,verticalAnchor:`middle`};return o&&E&&(A.width=Math.max(E.x+E.width-A.x,0),A.height=u),A}var j=o&&E?{width:g,height:u}:{};return n===`insideLeft`?pi({x:h+C,y:l+u/2,horizontalAnchor:T,verticalAnchor:`middle`},j):n===`insideRight`?pi({x:h+g-C,y:l+u/2,horizontalAnchor:w,verticalAnchor:`middle`},j):n===`insideTop`?pi({x:p+d/2,y:l+y,horizontalAnchor:`middle`,verticalAnchor:x},j):n===`insideBottom`?pi({x:m+f/2,y:l+u-y,horizontalAnchor:`middle`,verticalAnchor:b},j):n===`insideTopLeft`?pi({x:p+C,y:l+y,horizontalAnchor:T,verticalAnchor:x},j):n===`insideTopRight`?pi({x:p+d-C,y:l+y,horizontalAnchor:w,verticalAnchor:x},j):n===`insideBottomLeft`?pi({x:m+C,y:l+u-y,horizontalAnchor:T,verticalAnchor:b},j):n===`insideBottomRight`?pi({x:m+f-C,y:l+u-y,horizontalAnchor:w,verticalAnchor:b},j):n&&typeof n==`object`&&(L(n.x)||ti(n.x))&&(L(n.y)||ti(n.y))?pi({x:c+ai(n.x,g),y:l+ai(n.y,u),horizontalAnchor:`end`,verticalAnchor:`end`},j):pi({x:_,y:l+u/2,horizontalAnchor:`middle`,verticalAnchor:`middle`},j)},vi=[`top`,`left`,`right`,`bottom`];function yi(e){return e==null?!1:typeof e==`object`||vi.includes(e)}var bi=(0,O.createContext)(null);function xi(e){return function(){return e}}var Si=Math.PI,Ci=2*Si,wi=1e-6,Ti=Ci-wi;function Ei(e){this._+=e[0];for(let t=1,n=e.length;t=0))throw Error(`invalid digits: ${e}`);if(t>15)return Ei;let n=10**t;return function(e){this._+=e[0];for(let t=1,r=e.length;twi)if(!(Math.abs(u*s-c*l)>wi)||!i)this._append`L${this._x1=e},${this._y1=t}`;else{let f=n-a,p=r-o,m=s*s+c*c,h=f*f+p*p,g=Math.sqrt(m),_=Math.sqrt(d),v=i*Math.tan((Si-Math.acos((m+d-h)/(2*g*_)))/2),y=v/_,b=v/g;Math.abs(y-1)>wi&&this._append`L${e+y*l},${t+y*u}`,this._append`A${i},${i},0,0,${+(u*f>l*p)},${this._x1=e+b*s},${this._y1=t+b*c}`}}arc(e,t,n,r,i,a){if(e=+e,t=+t,n=+n,a=!!a,n<0)throw Error(`negative radius: ${n}`);let o=n*Math.cos(r),s=n*Math.sin(r),c=e+o,l=t+s,u=1^a,d=a?r-i:i-r;this._x1===null?this._append`M${c},${l}`:(Math.abs(this._x1-c)>wi||Math.abs(this._y1-l)>wi)&&this._append`L${c},${l}`,n&&(d<0&&(d=d%Ci+Ci),d>Ti?this._append`A${n},${n},0,1,${u},${e-o},${t-s}A${n},${n},0,1,${u},${this._x1=c},${this._y1=l}`:d>wi&&this._append`A${n},${n},0,${+(d>=Si)},${u},${this._x1=e+n*Math.cos(i)},${this._y1=t+n*Math.sin(i)}`)}rect(e,t,n,r){this._append`M${this._x0=this._x1=+e},${this._y0=this._y1=+t}h${n=+n}v${+r}h${-n}Z`}toString(){return this._}};function ki(){return new Oi}ki.prototype=Oi.prototype;function Ai(e){let t=3;return e.digits=function(n){if(!arguments.length)return t;if(n==null)t=null;else{let e=Math.floor(n);if(!(e>=0))throw RangeError(`invalid digits: ${n}`);t=e}return e},()=>new Oi(t)}Array.prototype.slice;function ji(e){return typeof e==`object`&&`length`in e?e:Array.from(e)}function Mi(e){this._context=e}Mi.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:this._context.lineTo(e,t);break}}};function Ni(e){return new Mi(e)}function Pi(e){return e[0]}function Fi(e){return e[1]}function Ii(e,t){var n=xi(!0),r=null,i=Ni,a=null,o=Ai(s);e=typeof e==`function`?e:e===void 0?Pi:xi(e),t=typeof t==`function`?t:t===void 0?Fi:xi(t);function s(s){var c,l=(s=ji(s)).length,u,d=!1,f;for(r??(a=i(f=o())),c=0;c<=l;++c)!(c=d;--f)s.point(_[f],v[f]);s.lineEnd(),s.areaEnd()}h&&(_[u]=+e(m,u,l),v[u]=+t(m,u,l),s.point(r?+r(m,u,l):_[u],n?+n(m,u,l):v[u]))}if(g)return s=null,g+``||null}function u(){return Ii().defined(i).curve(o).context(a)}return l.x=function(t){return arguments.length?(e=typeof t==`function`?t:xi(+t),r=null,l):e},l.x0=function(t){return arguments.length?(e=typeof t==`function`?t:xi(+t),l):e},l.x1=function(e){return arguments.length?(r=e==null?null:typeof e==`function`?e:xi(+e),l):r},l.y=function(e){return arguments.length?(t=typeof e==`function`?e:xi(+e),n=null,l):t},l.y0=function(e){return arguments.length?(t=typeof e==`function`?e:xi(+e),l):t},l.y1=function(e){return arguments.length?(n=e==null?null:typeof e==`function`?e:xi(+e),l):n},l.lineX0=l.lineY0=function(){return u().x(e).y(t)},l.lineY1=function(){return u().x(e).y(n)},l.lineX1=function(){return u().x(r).y(t)},l.defined=function(e){return arguments.length?(i=typeof e==`function`?e:xi(!!e),l):i},l.curve=function(e){return arguments.length?(o=e,a!=null&&(s=o(a)),l):o},l.context=function(e){return arguments.length?(e==null?a=s=null:s=o(a=e),l):a},l}var Ri=class{constructor(e,t){this._context=e,this._x=t}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line}point(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:this._x?this._context.bezierCurveTo(this._x0=(this._x0+e)/2,this._y0,this._x0,t,e,t):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+t)/2,e,this._y0,e,t);break}this._x0=e,this._y0=t}};function zi(e){return new Ri(e,!0)}function Bi(e){return new Ri(e,!1)}function Vi(){}function Hi(e,t,n){e._context.bezierCurveTo((2*e._x0+e._x1)/3,(2*e._y0+e._y1)/3,(e._x0+2*e._x1)/3,(e._y0+2*e._y1)/3,(e._x0+4*e._x1+t)/6,(e._y0+4*e._y1+n)/6)}function Ui(e){this._context=e}Ui.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Hi(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Hi(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function Wi(e){return new Ui(e)}function Gi(e){this._context=e}Gi.prototype={areaStart:Vi,areaEnd:Vi,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4);break}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x2=e,this._y2=t;break;case 1:this._point=2,this._x3=e,this._y3=t;break;case 2:this._point=3,this._x4=e,this._y4=t,this._context.moveTo((this._x0+4*this._x1+e)/6,(this._y0+4*this._y1+t)/6);break;default:Hi(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function Ki(e){return new Gi(e)}function qi(e){this._context=e}qi.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+e)/6,r=(this._y0+4*this._y1+t)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:Hi(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function Ji(e){return new qi(e)}function Yi(e){this._context=e}Yi.prototype={areaStart:Vi,areaEnd:Vi,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(e,t){e=+e,t=+t,this._point?this._context.lineTo(e,t):(this._point=1,this._context.moveTo(e,t))}};function Xi(e){return new Yi(e)}function Zi(e){return e<0?-1:1}function Qi(e,t,n){var r=e._x1-e._x0,i=t-e._x1,a=(e._y1-e._y0)/(r||i<0&&-0),o=(n-e._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(Zi(a)+Zi(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function $i(e,t){var n=e._x1-e._x0;return n?(3*(e._y1-e._y0)/n-t)/2:t}function ea(e,t,n){var r=e._x0,i=e._y0,a=e._x1,o=e._y1,s=(a-r)/3;e._context.bezierCurveTo(r+s,i+s*t,a-s,o-s*n,a,o)}function ta(e){this._context=e}ta.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:ea(this,this._t0,$i(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){var n=NaN;if(e=+e,t=+t,!(e===this._x1&&t===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,ea(this,$i(this,n=Qi(this,e,t)),n);break;default:ea(this,this._t0,n=Qi(this,e,t));break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t,this._t0=n}}};function na(e){this._context=new ra(e)}(na.prototype=Object.create(ta.prototype)).point=function(e,t){ta.prototype.point.call(this,t,e)};function ra(e){this._context=e}ra.prototype={moveTo:function(e,t){this._context.moveTo(t,e)},closePath:function(){this._context.closePath()},lineTo:function(e,t){this._context.lineTo(t,e)},bezierCurveTo:function(e,t,n,r,i,a){this._context.bezierCurveTo(t,e,r,n,a,i)}};function ia(e){return new ta(e)}function aa(e){return new na(e)}function oa(e){this._context=e}oa.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var e=this._x,t=this._y,n=e.length;if(n)if(this._line?this._context.lineTo(e[0],t[0]):this._context.moveTo(e[0],t[0]),n===2)this._context.lineTo(e[1],t[1]);else for(var r=sa(e),i=sa(t),a=0,o=1;o=0;--t)i[t]=(o[t]-i[t+1])/a[t];for(a[n-1]=(e[n]+i[n-1])/2,t=0;t=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,t),this._context.lineTo(e,t);else{var n=this._x*(1-this._t)+e*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,t)}break}this._x=e,this._y=t}};function ua(e){return new la(e,.5)}function da(e){return new la(e,0)}function fa(e){return new la(e,1)}function pa(e,t){if((o=e.length)>1)for(var n=1,r,i,a=e[t[0]],o,s=a.length;n=0;)n[t]=t;return n}function ha(e,t){return e[t]}function ga(e){let t=[];return t.key=e,t}function _a(){var e=xi([]),t=ma,n=pa,r=ha;function i(i){var a=Array.from(e.apply(this,arguments),ga),o,s=a.length,c=-1,l;for(let e of i)for(o=0,++c;o0){for(var n,r,i=0,a=e[0].length,o;i0){for(var n=0,r=e[t[0]],i,a=r.length;n0)||!((a=(i=e[t[0]]).length)>0))){for(var n=0,r=1,i,a,o;r`radius`in e&&`startAngle`in e&&`endAngle`in e,Sa=(e,t)=>{if(!e||typeof e==`function`||typeof e==`boolean`)return null;var n=e;if((0,O.isValidElement)(e)&&(n=e.props),typeof n!=`object`&&typeof n!=`function`)return null;var r={};return Object.keys(n).forEach(e=>{Er(e)&&typeof n[e]==`function`&&(r[e]=t||(t=>n[e](n,t)))}),r},Ca=(e,t,n)=>r=>(e(t,n,r),null),wa=(e,t,n)=>{if(e===null||typeof e!=`object`&&typeof e!=`function`)return null;var r=null;return Object.keys(e).forEach(i=>{var a=e[i];Er(i)&&typeof a==`function`&&(r||={},r[i]=Ca(a,t,n))}),r};function Ta(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Ea(e){for(var t=1;t(e[t]===void 0&&r[t]!==void 0&&(e[t]=r[t]),e),n)}function ja(e,t){let n=new Map;for(let r=0;rObject.prototype.propertyIsEnumerable.call(e,t))}function Ra(e){return e==null?e===void 0?`[object Undefined]`:`[object Null]`:Object.prototype.toString.call(e)}var za=`[object RegExp]`,Ba=`[object String]`,Va=`[object Number]`,Ha=`[object Boolean]`,Ua=`[object Arguments]`,Wa=`[object Symbol]`,Ga=`[object Date]`,Ka=`[object Map]`,qa=`[object Set]`,Ja=`[object Array]`,Ya=`[object Function]`,Xa=`[object ArrayBuffer]`,Za=`[object Object]`,Qa=`[object Error]`,$a=`[object DataView]`,eo=`[object Uint8Array]`,to=`[object Uint8ClampedArray]`,no=`[object Uint16Array]`,ro=`[object Uint32Array]`,io=`[object BigUint64Array]`,ao=`[object Int8Array]`,oo=`[object Int16Array]`,so=`[object Int32Array]`,co=`[object BigInt64Array]`,lo=`[object Float32Array]`,uo=`[object Float64Array]`,fo=typeof globalThis==`object`&&globalThis||typeof window==`object`&&window||typeof self==`object`&&self||typeof global==`object`&&global||(function(){return this})();function po(e){return fo.Buffer!==void 0&&fo.Buffer.isBuffer(e)}function mo(e,t){return ho(e,void 0,e,new Map,t)}function ho(e,t,n,r=new Map,i=void 0){let a=i?.(e,t,n,r);if(a!==void 0)return a;if(Fa(e))return e;if(r.has(e))return r.get(e);if(Array.isArray(e)){let t=Array(e.length);r.set(e,t);for(let a=0;avoid 0)}function So(e,t,n,r,i=!1){if(t===e)return!0;switch(typeof t){case`object`:return Co(e,t,n,r);case`function`:return Object.keys(t).length>0?So(e,{...t},n,r,i):yo(e,t);default:return bo(e)&&i?typeof t!=`string`||t===``:yo(e,t)}}function Co(e,t,n,r){if(t==null)return!0;if(Array.isArray(t))return To(e,t,n,r);if(t instanceof Map)return wo(e,t,n,r);if(t instanceof Set)return Eo(e,t,n,r);let i=Object.keys(t);if(e==null||Fa(e))return i.length===0;if(i.length===0)return!0;if(r?.has(t))return r.get(t)===e;r?.set(t,e);try{for(let a=0;avoid 0)}function Oo(e){return e=vo(e),t=>Do(t,e)}function ko(e,t){return mo(e,(n,r,i,a)=>{let o=t?.(n,r,i,a);if(o!==void 0)return o;if(typeof e==`object`){if(Ra(e)===`[object Object]`&&typeof e.constructor!=`function`){let t={};return a.set(e,t),go(t,e,i,a),t}switch(Object.prototype.toString.call(e)){case Va:case Ba:case Ha:{let t=new e.constructor(e?.valueOf());return go(t,e),t}case Ua:{let t={};return go(t,e),t.length=e.length,t[Symbol.iterator]=e[Symbol.iterator],t}default:return}}})}function Ao(e){return ko(e)}var jo=/^(?:0|[1-9]\d*)$/;function Mo(e,t=2**53-1){switch(typeof e){case`number`:return Number.isInteger(e)&&e>=0&&e=0}function Ro(e){return e!=null&&typeof e!=`function`&&Lo(e.length)}function zo(e){return typeof e==`object`&&!!e}function Bo(e){return zo(e)&&Ro(e)}function Vo(e,t=Na){return Bo(e)?ja(Array.from(e),Ma(Io(t),1)):[]}function Ho(e,t,n){return t===!0?Vo(e,n):typeof t==`function`?Vo(e,t):e}var Uo=e((e=>{var t=i();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,a=t.useState,o=t.useEffect,s=t.useLayoutEffect,c=t.useDebugValue;function l(e,t){var n=t(),r=a({inst:{value:n,getSnapshot:t}}),i=r[0].inst,l=r[1];return s(function(){i.value=n,i.getSnapshot=t,u(i)&&l({inst:i})},[e,n,t]),o(function(){return u(i)&&l({inst:i}),e(function(){u(i)&&l({inst:i})})},[e]),c(n),n}function u(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function d(e,t){return t()}var f=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?d:l;e.useSyncExternalStore=t.useSyncExternalStore===void 0?f:t.useSyncExternalStore})),Wo=e(((e,t)=>{t.exports=Uo()})),Go=e((e=>{var t=i(),n=Wo();function r(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var a=typeof Object.is==`function`?Object.is:r,o=n.useSyncExternalStore,s=t.useRef,c=t.useEffect,l=t.useMemo,u=t.useDebugValue;e.useSyncExternalStoreWithSelector=function(e,t,n,r,i){var d=s(null);if(d.current===null){var f={hasValue:!1,value:null};d.current=f}else f=d.current;d=l(function(){function e(e){if(!o){if(o=!0,s=e,e=r(e),i!==void 0&&f.hasValue){var t=f.value;if(i(t,e))return c=t}return c=e}if(t=c,a(s,e))return t;var n=r(e);return i!==void 0&&i(t,n)?(s=e,t):(s=e,c=n)}var o=!1,s,c,l=n===void 0?null:n;return[function(){return e(t())},l===null?void 0:function(){return e(l())}]},[t,n,r,i]);var p=o(e,d[0],d[1]);return c(function(){f.hasValue=!0,f.value=p},[p]),u(p),p}})),Ko=e(((e,t)=>{t.exports=Go()}))(),qo=(0,O.createContext)(null),Jo=e=>e,B=()=>{var e=(0,O.useContext)(qo);return e?e.store.dispatch:Jo},Yo=()=>{},Xo=()=>Yo,Zo=(e,t)=>e===t;function V(e){var t=(0,O.useContext)(qo),n=(0,O.useMemo)(()=>t?t=>{if(t!=null)return e(t)}:Yo,[t,e]);return(0,Ko.useSyncExternalStoreWithSelector)(t?t.subscription.addNestedSub:Xo,t?t.store.getState:Yo,t?t.store.getState:Yo,n,Zo)}function Qo(e,t=`expected a function, instead received ${typeof e}`){if(typeof e!=`function`)throw TypeError(t)}function $o(e,t=`expected all items to be functions, instead received the following types: `){if(!e.every(e=>typeof e==`function`)){let n=e.map(e=>typeof e==`function`?`function ${e.name||`unnamed`}()`:typeof e).join(`, `);throw TypeError(`${t}[${n}]`)}}var es=e=>Array.isArray(e)?e:[e];function ts(e){let t=Array.isArray(e[0])?e[0]:e;return $o(t,`createSelector expects all input-selectors to be functions, but received the following types: `),t}function ns(e,t){let n=[],{length:r}=e;for(let i=0;i`u`?rs:WeakRef,as=0,os=1;function ss(){return{s:as,v:void 0,o:null,p:null}}function cs(e){return e instanceof is?e.deref():e}function ls(e,t={}){let n=ss(),{resultEqualityCheck:r}=t,i,a=0;function o(){let t=n,{length:o}=arguments;for(let e=0,n=o;e{n=ss(),o.resetResultsCount()},o.resultsCount=()=>a,o.resetResultsCount=()=>{a=0},o}function us(e,...t){let n=typeof e==`function`?{memoize:e,memoizeOptions:t}:e,r=(...e)=>{let t=0,r=0,i,a={},o=e.pop();typeof o==`object`&&(a=o,o=e.pop()),Qo(o,`createSelector expects an output function after the inputs, but received: [${typeof o}]`);let{memoize:s,memoizeOptions:c=[],argsMemoize:l=ls,argsMemoizeOptions:u=[]}={...n,...a},d=es(c),f=es(u),p=ts(e),m=s(function(){return t++,o.apply(null,arguments)},...d),h=l(function(){r++;let e=ns(p,arguments);return i=m.apply(null,e),i},...f);return Object.assign(h,{resultFunc:o,memoizedResultFunc:m,dependencies:p,dependencyRecomputations:()=>r,resetDependencyRecomputations:()=>{r=0},lastResult:()=>i,recomputations:()=>t,resetRecomputations:()=>{t=0},memoize:s,argsMemoize:l})};return Object.assign(r,{withTypes:()=>r}),r}var H=us(ls);function ds(e,t=1){let n=[],r=Math.floor(t),i=(e,t)=>{for(let a=0;a{if(e!==t){let r=ps(e),i=ps(t);if(r===i&&r===0){if(et)return n===`desc`?-1:1}return n===`desc`?i-r:r-i}return 0};function hs(e){return typeof e==`symbol`||e instanceof Symbol}var gs=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,_s=/^\w*$/;function vs(e,t){return Array.isArray(e)?!1:typeof e==`number`||typeof e==`boolean`||e==null||hs(e)?!0:typeof e==`string`&&(_s.test(e)||!gs.test(e))||t!=null&&Object.hasOwn(t,e)}function ys(e,t,n,r){if(e==null)return[];n=r?void 0:n,Array.isArray(e)||(e=Object.values(e)),Array.isArray(t)||(t=t==null?[null]:[t]),t.length===0&&(t=[null]),Array.isArray(n)||(n=n==null?[]:[n]),n=n.map(e=>String(e));let i=(e,t)=>{let n=e;for(let e=0;et==null||e==null?t:typeof e==`object`&&`key`in e?Object.hasOwn(t,e.key)?t[e.key]:i(t,e.path):typeof e==`function`?e(t):Array.isArray(e)?i(t,e):typeof t==`object`?t[e]:t,o=t.map(e=>(Array.isArray(e)&&e.length===1&&(e=e[0]),e==null||typeof e==`function`||Array.isArray(e)||vs(e)?e:{key:e,path:qr(e)}));return e.map(e=>({original:e,criteria:o.map(t=>a(t,e))})).slice().sort((e,t)=>{for(let r=0;re.original)}function bs(e,...t){let n=t.length;return n>1&&fs(e,t[0],t[1])?t=[]:n>2&&fs(t[0],t[1],t[2])&&(t=[t[0]]),ys(e,ds(t),[`asc`])}var xs=e=>e.legend.settings,Ss=e=>e.legend.size;H([e=>e.legend.payload,xs],(e,t)=>{var n=t.itemSorter,r=e.flat(1);return n?bs(r,n):r});function Cs(e,t){return Os(e)||Ds(e,t)||Ts(e,t)||ws()}function ws(){throw TypeError(`Invalid attempt to destructure non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Ts(e,t){if(e){if(typeof e==`string`)return Es(e,t);var n={}.toString.call(e).slice(8,-1);return n===`Object`&&e.constructor&&(n=e.constructor.name),n===`Map`||n===`Set`?Array.from(e):n===`Arguments`||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Es(e,t):void 0}}function Es(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nks||Math.abs(e.left-t.left)>ks||Math.abs(e.top-t.top)>ks||Math.abs(e.width-t.width)>ks}function js(e){var t=e.getBoundingClientRect();return{height:t.height,left:t.left,top:t.top,width:t.width}}function Ms(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[],t=Cs((0,O.useState)({height:0,left:0,top:0,width:0}),2),n=t[0],r=t[1],i=(0,O.useRef)(null),a=(0,O.useRef)(n);a.current=n;var o=(0,O.useCallback)(e=>{if(i.current!=null&&(i.current.disconnect(),i.current=null),e!=null){var t=js(e);if(As(t,a.current)&&r(t),typeof ResizeObserver<`u`){var n=new ResizeObserver(()=>{var t=js(e);As(t,a.current)&&r(t)});n.observe(e),i.current=n}}},[...e]);return(0,O.useEffect)(()=>()=>{var e;(e=i.current)==null||e.disconnect()},[]),[n,o]}function Ns(e){return`Minified Redux error #${e}; visit https://redux.js.org/Errors?code=${e} for the full message or use the non-minified dev environment for full errors. `}var Ps=typeof Symbol==`function`&&Symbol.observable||`@@observable`,Fs=()=>Math.random().toString(36).substring(7).split(``).join(`.`),Is={INIT:`@@redux/INIT${Fs()}`,REPLACE:`@@redux/REPLACE${Fs()}`,PROBE_UNKNOWN_ACTION:()=>`@@redux/PROBE_UNKNOWN_ACTION${Fs()}`};function Ls(e){if(typeof e!=`object`||!e)return!1;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t||Object.getPrototypeOf(e)===null}function Rs(e,t,n){if(typeof e!=`function`)throw Error(Ns(2));if(typeof t==`function`&&typeof n==`function`||typeof n==`function`&&typeof arguments[3]==`function`)throw Error(Ns(0));if(typeof t==`function`&&n===void 0&&(n=t,t=void 0),n!==void 0){if(typeof n!=`function`)throw Error(Ns(1));return n(Rs)(e,t)}let r=e,i=t,a=new Map,o=a,s=0,c=!1;function l(){o===a&&(o=new Map,a.forEach((e,t)=>{o.set(t,e)}))}function u(){if(c)throw Error(Ns(3));return i}function d(e){if(typeof e!=`function`)throw Error(Ns(4));if(c)throw Error(Ns(5));let t=!0;l();let n=s++;return o.set(n,e),function(){if(t){if(c)throw Error(Ns(6));t=!1,l(),o.delete(n),a=null}}}function f(e){if(!Ls(e))throw Error(Ns(7));if(e.type===void 0)throw Error(Ns(8));if(typeof e.type!=`string`)throw Error(Ns(17));if(c)throw Error(Ns(9));try{c=!0,i=r(i,e)}finally{c=!1}return(a=o).forEach(e=>{e()}),e}function p(e){if(typeof e!=`function`)throw Error(Ns(10));r=e,f({type:Is.REPLACE})}function m(){let e=d;return{subscribe(t){if(typeof t!=`object`||!t)throw Error(Ns(11));function n(){let e=t;e.next&&e.next(u())}return n(),{unsubscribe:e(n)}},[Ps](){return this}}}return f({type:Is.INIT}),{dispatch:f,subscribe:d,getState:u,replaceReducer:p,[Ps]:m}}function zs(e){Object.keys(e).forEach(t=>{let n=e[t];if(n(void 0,{type:Is.INIT})===void 0)throw Error(Ns(12));if(n(void 0,{type:Is.PROBE_UNKNOWN_ACTION()})===void 0)throw Error(Ns(13))})}function Bs(e){let t=Object.keys(e),n={};for(let r=0;re:e.length===1?e[0]:e.reduce((e,t)=>(...n)=>e(t(...n)))}function Hs(...e){return t=>(n,r)=>{let i=t(n,r),a=()=>{throw Error(Ns(15))},o={getState:i.getState,dispatch:(e,...t)=>a(e,...t)};return a=Vs(...e.map(e=>e(o)))(i.dispatch),{...i,dispatch:a}}}function Us(e){return Ls(e)&&`type`in e&&typeof e.type==`string`}var Ws=Symbol.for(`immer-nothing`),Gs=Symbol.for(`immer-draftable`),Ks=Symbol.for(`immer-state`);function qs(e,...t){throw Error(`[Immer] minified error nr: ${e}. Full error at: https://bit.ly/3cXEKWf`)}var Js=Object,Ys=Js.getPrototypeOf,Xs=`constructor`,Zs=`prototype`,Qs=`configurable`,$s=`enumerable`,ec=`writable`,tc=`value`,nc=e=>!!e&&!!e[Ks];function rc(e){return e?oc(e)||pc(e)||!!e[Gs]||!!e[Xs]?.[Gs]||mc(e)||hc(e):!1}var ic=Js[Zs][Xs].toString(),ac=new WeakMap;function oc(e){if(!e||!gc(e))return!1;let t=Ys(e);if(t===null||t===Js[Zs])return!0;let n=Js.hasOwnProperty.call(t,Xs)&&t[Xs];if(n===Object)return!0;if(!_c(n))return!1;let r=ac.get(n);return r===void 0&&(r=Function.toString.call(n),ac.set(n,r)),r===ic}function sc(e,t,n=!0){cc(e)===0?(n?Reflect.ownKeys(e):Js.keys(e)).forEach(n=>{t(n,e[n],e)}):e.forEach((n,r)=>t(r,n,e))}function cc(e){let t=e[Ks];return t?t.type_:pc(e)?1:mc(e)?2:hc(e)?3:0}var lc=(e,t,n=cc(e))=>n===2?e.has(t):Js[Zs].hasOwnProperty.call(e,t),uc=(e,t,n=cc(e))=>n===2?e.get(t):e[t],dc=(e,t,n,r=cc(e))=>{r===2?e.set(t,n):r===3?e.add(n):e[t]=n};function fc(e,t){return e===t?e!==0||1/e==1/t:e!==e&&t!==t}var pc=Array.isArray,mc=e=>e instanceof Map,hc=e=>e instanceof Set,gc=e=>typeof e==`object`,_c=e=>typeof e==`function`,vc=e=>typeof e==`boolean`;function yc(e){let t=+e;return Number.isInteger(t)&&String(t)===e}var bc=e=>e.copy_||e.base_,xc=e=>e.modified_?e.copy_:e.base_;function Sc(e,t){if(mc(e))return new Map(e);if(hc(e))return new Set(e);if(pc(e))return Array[Zs].slice.call(e);let n=oc(e);if(t===!0||t===`class_only`&&!n){let t=Js.getOwnPropertyDescriptors(e);delete t[Ks];let n=Reflect.ownKeys(t);for(let r=0;r1&&Js.defineProperties(e,{set:Tc,add:Tc,clear:Tc,delete:Tc}),Js.freeze(e),t&&sc(e,(e,t)=>{Cc(t,!0)},!1),e)}function wc(){qs(2)}var Tc={[tc]:wc};function Ec(e){return e===null||!gc(e)||Js.isFrozen(e)}var Dc=`MapSet`,Oc=`Patches`,kc=`ArrayMethods`,Ac={};function jc(e){let t=Ac[e];return t||qs(0,e),t}var Mc=e=>!!Ac[e],Nc,Pc=()=>Nc,Fc=(e,t)=>({drafts_:[],parent_:e,immer_:t,canAutoFreeze_:!0,unfinalizedDrafts_:0,handledSet_:new Set,processedForPatches_:new Set,mapSetPlugin_:Mc(Dc)?jc(Dc):void 0,arrayMethodsPlugin_:Mc(kc)?jc(kc):void 0});function Ic(e,t){t&&(e.patchPlugin_=jc(Oc),e.patches_=[],e.inversePatches_=[],e.patchListener_=t)}function Lc(e){Rc(e),e.drafts_.forEach(Bc),e.drafts_=null}function Rc(e){e===Nc&&(Nc=e.parent_)}var zc=e=>Nc=Fc(Nc,e);function Bc(e){let t=e[Ks];t.type_===0||t.type_===1?t.revoke_():t.revoked_=!0}function Vc(e,t){t.unfinalizedDrafts_=t.drafts_.length;let n=t.drafts_[0];if(e!==void 0&&e!==n){n[Ks].modified_&&(Lc(t),qs(4)),rc(e)&&(e=Hc(t,e));let{patchPlugin_:r}=t;r&&r.generateReplacementPatches_(n[Ks].base_,e,t)}else e=Hc(t,n);return Uc(t,e,!0),Lc(t),t.patches_&&t.patchListener_(t.patches_,t.inversePatches_),e===Ws?void 0:e}function Hc(e,t){if(Ec(t))return t;let n=t[Ks];if(!n)return Zc(t,e.handledSet_,e);if(!Gc(n,e))return t;if(!n.modified_)return n.base_;if(!n.finalized_){let{callbacks_:t}=n;if(t)for(;t.length>0;)t.pop()(e);Yc(n,e)}return n.copy_}function Uc(e,t,n=!1){!e.parent_&&e.immer_.autoFreeze_&&e.canAutoFreeze_&&Cc(t,n)}function Wc(e){e.finalized_=!0,e.scope_.unfinalizedDrafts_--}var Gc=(e,t)=>e.scope_===t,Kc=[];function qc(e,t,n,r){let i=bc(e),a=e.type_;if(r!==void 0&&uc(i,r,a)===t){dc(i,r,n,a);return}if(!e.draftLocations_){let t=e.draftLocations_=new Map;sc(i,(e,n)=>{if(nc(n)){let r=t.get(n)||[];r.push(e),t.set(n,r)}})}let o=e.draftLocations_.get(t)??Kc;for(let e of o)dc(i,e,n,a)}function Jc(e,t,n){e.callbacks_.push(function(r){let i=t;if(!i||!Gc(i,r))return;r.mapSetPlugin_?.fixSetContents(i);let a=xc(i);qc(e,i.draft_??i,a,n),Yc(i,r)})}function Yc(e,t){if(e.modified_&&!e.finalized_&&(e.type_===3||e.type_===1&&e.allIndicesReassigned_||(e.assigned_?.size??0)>0)){let{patchPlugin_:n}=t;if(n){let r=n.getPath(e);r&&n.generatePatches_(e,r,t)}Wc(e)}}function Xc(e,t,n){let{scope_:r}=e;if(nc(n)){let i=n[Ks];Gc(i,r)&&i.callbacks_.push(function(){ol(e),qc(e,n,xc(i),t)})}else rc(n)&&e.callbacks_.push(function(){let i=bc(e);e.type_===3?i.has(n)&&Zc(n,r.handledSet_,r):uc(i,t,e.type_)===n&&r.drafts_.length>1&&(e.assigned_.get(t)??!1)===!0&&e.copy_&&Zc(uc(e.copy_,t,e.type_),r.handledSet_,r)})}function Zc(e,t,n){return!n.immer_.autoFreeze_&&n.unfinalizedDrafts_<1||nc(e)||t.has(e)||!rc(e)||Ec(e)?e:(t.add(e),sc(e,(r,i)=>{if(nc(i)){let t=i[Ks];Gc(t,n)&&(dc(e,r,xc(t),e.type_),Wc(t))}else rc(i)&&Zc(i,t,n)}),e)}function Qc(e,t){let n=pc(e),r={type_:+!!n,scope_:t?t.scope_:Pc(),modified_:!1,finalized_:!1,assigned_:void 0,parent_:t,base_:e,draft_:null,copy_:null,revoke_:null,isManual_:!1,callbacks_:void 0},i=r,a=$c;n&&(i=[r],a=el);let{revoke:o,proxy:s}=Proxy.revocable(i,a);return r.draft_=s,r.revoke_=o,[s,r]}var $c={get(e,t){if(t===Ks)return e;let n=e.scope_.arrayMethodsPlugin_,r=e.type_===1&&typeof t==`string`;if(r&&n?.isArrayOperationMethod(t))return n.createMethodInterceptor(e,t);let i=bc(e);if(!lc(i,t,e.type_))return rl(e,i,t);let a=i[t];if(e.finalized_||!rc(a)||r&&e.operationMethod&&n?.isMutatingArrayMethod(e.operationMethod)&&yc(t))return a;if(a===tl(e.base_,t)||nl(e,t,a)){ol(e);let n=e.type_===1?+t:t,r=cl(e.scope_,a,e,n);return e.copy_[n]=r}return a},has(e,t){return t in bc(e)},ownKeys(e){return Reflect.ownKeys(bc(e))},set(e,t,n){let r=il(bc(e),t);if(r?.set)return r.set.call(e.draft_,n),!0;if(!e.modified_){let r=tl(bc(e),t),i=r?.[Ks];if(i&&i.base_===n)return e.copy_[t]=n,e.assigned_.set(t,!1),!0;if(fc(n,r)&&(n!==void 0||lc(e.base_,t,e.type_)))return!0;ol(e),al(e)}return e.copy_[t]===n&&(n!==void 0||lc(e.copy_,t,e.type_))||Number.isNaN(n)&&Number.isNaN(e.copy_[t])?!0:(e.copy_[t]=n,e.assigned_.set(t,!0),Xc(e,t,n),!0)},deleteProperty(e,t){return ol(e),tl(e.base_,t)!==void 0||t in e.base_?(e.assigned_.set(t,!1),al(e)):e.assigned_.delete(t),e.copy_&&delete e.copy_[t],!0},getOwnPropertyDescriptor(e,t){let n=bc(e),r=Reflect.getOwnPropertyDescriptor(n,t);return r&&{[ec]:!0,[Qs]:e.type_!==1||t!==`length`,[$s]:r[$s],[tc]:n[t]}},defineProperty(){qs(11)},getPrototypeOf(e){return Ys(e.base_)},setPrototypeOf(){qs(12)}},el={};for(let e in $c){let t=$c[e];el[e]=function(){let e=arguments;return e[0]=e[0][0],t.apply(this,e)}}el.deleteProperty=function(e,t){return el.set.call(this,e,t,void 0)},el.set=function(e,t,n){return $c.set.call(this,e[0],t,n,e[0])};function tl(e,t){let n=e[Ks];return(n?bc(n):e)[t]}function nl(e,t,n){return e.type_!==1||!e.allIndicesReassigned_||e.assigned_?.get(t)||!rc(n)||n[Ks]?!1:e.baseRefs_.has(n)}function rl(e,t,n){let r=il(t,n);return r?tc in r?r[tc]:r.get?.call(e.draft_):void 0}function il(e,t){if(!(t in e))return;let n=Ys(e);for(;n;){let e=Object.getOwnPropertyDescriptor(n,t);if(e)return e;n=Ys(n)}}function al(e){e.modified_||(e.modified_=!0,e.parent_&&al(e.parent_))}function ol(e){e.copy_||=(e.assigned_=new Map,Sc(e.base_,e.scope_.immer_.useStrictShallowCopy_))}var sl=class{constructor(e){this.autoFreeze_=!0,this.useStrictShallowCopy_=!1,this.useStrictIteration_=!1,this.produce=(e,t,n)=>{if(_c(e)&&!_c(t)){let n=t;t=e;let r=this;return function(e=n,...i){return r.produce(e,e=>t.call(this,e,...i))}}_c(t)||qs(6),n!==void 0&&!_c(n)&&qs(7);let r;if(rc(e)){let i=zc(this),a=cl(i,e,void 0),o=!0;try{r=t(a),o=!1}finally{o?Lc(i):Rc(i)}return Ic(i,n),Vc(r,i)}else if(!e||!gc(e)){if(r=t(e),r===void 0&&(r=e),r===Ws&&(r=void 0),this.autoFreeze_&&Cc(r,!0),n){let t=[],i=[];jc(Oc).generateReplacementPatches_(e,r,{patches_:t,inversePatches_:i}),n(t,i)}return r}else qs(1,e)},this.produceWithPatches=(e,t)=>{if(_c(e))return(t,...n)=>this.produceWithPatches(t,t=>e(t,...n));let n,r;return[this.produce(e,t,(e,t)=>{n=e,r=t}),n,r]},vc(e?.autoFreeze)&&this.setAutoFreeze(e.autoFreeze),vc(e?.useStrictShallowCopy)&&this.setUseStrictShallowCopy(e.useStrictShallowCopy),vc(e?.useStrictIteration)&&this.setUseStrictIteration(e.useStrictIteration)}createDraft(e){rc(e)||qs(8),nc(e)&&(e=ll(e));let t=zc(this),n=cl(t,e,void 0);return n[Ks].isManual_=!0,Rc(t),n}finishDraft(e,t){let n=e&&e[Ks];(!n||!n.isManual_)&&qs(9);let{scope_:r}=n;return Ic(r,t),Vc(void 0,r)}setAutoFreeze(e){this.autoFreeze_=e}setUseStrictShallowCopy(e){this.useStrictShallowCopy_=e}setUseStrictIteration(e){this.useStrictIteration_=e}shouldUseStrictIteration(){return this.useStrictIteration_}applyPatches(e,t){let n;for(n=t.length-1;n>=0;n--){let r=t[n];if(r.path.length===0&&r.op===`replace`){e=r.value;break}}n>-1&&(t=t.slice(n+1));let r=jc(Oc).applyPatches_;return nc(e)?r(e,t):this.produce(e,e=>r(e,t))}};function cl(e,t,n,r){let[i,a]=mc(t)?jc(Dc).proxyMap_(t,n):hc(t)?jc(Dc).proxySet_(t,n):Qc(t,n);return(n?.scope_??Pc()).drafts_.push(i),a.callbacks_=n?.callbacks_??[],a.key_=r,n&&r!==void 0?Jc(n,a,r):a.callbacks_.push(function(e){e.mapSetPlugin_?.fixSetContents(a);let{patchPlugin_:t}=e;a.modified_&&t&&t.generatePatches_(a,[],e)}),i}function ll(e){return nc(e)||qs(10,e),ul(e)}function ul(e){if(!rc(e)||Ec(e))return e;let t=e[Ks],n,r=!0;if(t){if(!t.modified_)return t.base_;t.finalized_=!0,n=Sc(e,t.scope_.immer_.useStrictShallowCopy_),r=t.scope_.immer_.shouldUseStrictIteration()}else n=Sc(e,!0);return sc(n,(e,t)=>{dc(n,e,ul(t))},r),t&&(t.finalized_=!1),n}var dl=new sl().produce,U=e=>e;function fl(e){return({dispatch:t,getState:n})=>r=>i=>typeof i==`function`?i(t,n,e):r(i)}var pl=fl(),ml=fl,hl=typeof window<`u`&&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__:function(){if(arguments.length!==0)return typeof arguments[0]==`object`?Vs:Vs.apply(null,arguments)};typeof window<`u`&&window.__REDUX_DEVTOOLS_EXTENSION__&&window.__REDUX_DEVTOOLS_EXTENSION__;function gl(e,t){function n(...n){if(t){let r=t(...n);if(!r)throw Error(wu(0));return{type:e,payload:r.payload,...`meta`in r&&{meta:r.meta},...`error`in r&&{error:r.error}}}return{type:e,payload:n[0]}}return n.toString=()=>`${e}`,n.type=e,n.match=t=>Us(t)&&t.type===e,n}var _l=class e extends Array{constructor(...t){super(...t),Object.setPrototypeOf(this,e.prototype)}static get[Symbol.species](){return e}concat(...e){return super.concat.apply(this,e)}prepend(...t){return t.length===1&&Array.isArray(t[0])?new e(...t[0].concat(this)):new e(...t.concat(this))}};function vl(e){return rc(e)?dl(e,()=>{}):e}function yl(e,t,n){return e.has(t)?e.get(t):e.set(t,n(t)).get(t)}function bl(e){return typeof e==`boolean`}var xl=()=>function(e){let{thunk:t=!0,immutableCheck:n=!0,serializableCheck:r=!0,actionCreatorCheck:i=!0}=e??{},a=new _l;return t&&(bl(t)?a.push(pl):a.push(ml(t.extraArgument))),a},Sl=`RTK_autoBatch`,W=()=>e=>({payload:e,meta:{[Sl]:!0}}),Cl=e=>t=>{setTimeout(t,e)},wl=(e,t)=>n=>{let r=!1,i=()=>{r||(r=!0,cancelAnimationFrame(a),clearTimeout(o),n())},a=e(i),o=setTimeout(i,t)},Tl=(e={type:`raf`})=>t=>(...n)=>{let r=t(...n),i=!0,a=!1,o=!1,s=new Set,c=e.type===`tick`?queueMicrotask:e.type===`raf`?typeof window<`u`&&window.requestAnimationFrame?wl(window.requestAnimationFrame,100):Cl(10):e.type===`callback`?e.queueNotification:Cl(e.timeout),l=()=>{o=!1,a&&(a=!1,s.forEach(e=>e()))};return Object.assign({},r,{subscribe(e){let t=r.subscribe(()=>i&&e());return s.add(e),()=>{t(),s.delete(e)}},dispatch(e){try{return i=!e?.meta?.[Sl],a=!i,a&&(o||(o=!0,c(l))),r.dispatch(e)}finally{i=!0}}})},El=e=>function(t){let{autoBatch:n=!0}=t??{},r=new _l(e);return n&&r.push(Tl(typeof n==`object`?n:void 0)),r};function Dl(e){let t=xl(),{reducer:n=void 0,middleware:r,devTools:i=!0,duplicateMiddlewareCheck:a=!0,preloadedState:o=void 0,enhancers:s=void 0}=e||{},c;if(typeof n==`function`)c=n;else if(Ls(n))c=Bs(n);else throw Error(wu(1));let l;l=typeof r==`function`?r(t):t();let u=Vs;i&&(u=hl({trace:!1,...typeof i==`object`&&i}));let d=El(Hs(...l)),f=typeof s==`function`?s(d):d(),p=u(...f);return Rs(c,o,p)}function Ol(e){let t={},n=[],r,i={addCase(e,n){let r=typeof e==`string`?e:e.type;if(!r)throw Error(wu(28));if(r in t)throw Error(wu(29));return t[r]=n,i},addAsyncThunk(e,r){return r.pending&&(t[e.pending.type]=r.pending),r.rejected&&(t[e.rejected.type]=r.rejected),r.fulfilled&&(t[e.fulfilled.type]=r.fulfilled),r.settled&&n.push({matcher:e.settled,reducer:r.settled}),i},addMatcher(e,t){return n.push({matcher:e,reducer:t}),i},addDefaultCase(e){return r=e,i}};return e(i),[t,n,r]}function kl(e){return typeof e==`function`}function Al(e,t){let[n,r,i]=Ol(t),a;if(kl(e))a=()=>vl(e());else{let t=vl(e);a=()=>t}function o(e=a(),t){let o=[n[t.type],...r.filter(({matcher:e})=>e(t)).map(({reducer:e})=>e)];return o.filter(e=>!!e).length===0&&(o=[i]),o.reduce((e,n)=>{if(n)if(nc(e)){let r=n(e,t);return r===void 0?e:r}else if(rc(e))return dl(e,e=>n(e,t));else{let r=n(e,t);if(r===void 0){if(e===null)return e;throw Error(`A case reducer on a non-draftable value must not return undefined`)}return r}return e},e)}return o.getInitialState=a,o}var jl=`ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW`,Ml=(e=21)=>{let t=``,n=e;for(;n--;)t+=jl[Math.random()*64|0];return t},Nl=Symbol.for(`rtk-slice-createasyncthunk`);function Pl(e,t){return`${e}/${t}`}function Fl({creators:e}={}){let t=e?.asyncThunk?.[Nl];return function(e){let{name:n,reducerPath:r=n}=e;if(!n)throw Error(wu(11));let i=(typeof e.reducers==`function`?e.reducers(Rl()):e.reducers)||{},a=Object.keys(i),o={sliceCaseReducersByName:{},sliceCaseReducersByType:{},actionCreators:{},sliceMatchers:[]},s={addCase(e,t){let n=typeof e==`string`?e:e.type;if(!n)throw Error(wu(12));if(n in o.sliceCaseReducersByType)throw Error(wu(13));return o.sliceCaseReducersByType[n]=t,s},addMatcher(e,t){return o.sliceMatchers.push({matcher:e,reducer:t}),s},exposeAction(e,t){return o.actionCreators[e]=t,s},exposeCaseReducer(e,t){return o.sliceCaseReducersByName[e]=t,s}};a.forEach(r=>{let a=i[r],o={reducerName:r,type:Pl(n,r),createNotation:typeof e.reducers==`function`};Bl(a)?Hl(o,a,s,t):zl(o,a,s)});function c(){let[t={},n=[],r=void 0]=typeof e.extraReducers==`function`?Ol(e.extraReducers):[e.extraReducers],i={...t,...o.sliceCaseReducersByType};return Al(e.initialState,e=>{for(let t in i)e.addCase(t,i[t]);for(let t of o.sliceMatchers)e.addMatcher(t.matcher,t.reducer);for(let t of n)e.addMatcher(t.matcher,t.reducer);r&&e.addDefaultCase(r)})}let l=e=>e,u=new Map,d=new WeakMap,f;function p(e,t){return f||=c(),f(e,t)}function m(){return f||=c(),f.getInitialState()}function h(t,n=!1){function r(e){let i=e[t];return i===void 0&&n&&(i=yl(d,r,m)),i}function i(t=l){return yl(yl(u,n,()=>new WeakMap),t,()=>{let r={};for(let[i,a]of Object.entries(e.selectors??{}))r[i]=Il(a,t,()=>yl(d,t,m),n);return r})}return{reducerPath:t,getSelectors:i,get selectors(){return i(r)},selectSlice:r}}let g={name:n,reducer:p,actions:o.actionCreators,caseReducers:o.sliceCaseReducersByName,getInitialState:m,...h(r),injectInto(e,{reducerPath:t,...n}={}){let i=t??r;return e.inject({reducerPath:i,reducer:p},n),{...g,...h(i,!0)}}};return g}}function Il(e,t,n,r){function i(i,...a){let o=t(i);return o===void 0&&r&&(o=n()),e(o,...a)}return i.unwrapped=e,i}var Ll=Fl();function Rl(){function e(e,t){return{_reducerDefinitionType:`asyncThunk`,payloadCreator:e,...t}}return e.withTypes=()=>e,{reducer(e){return Object.assign({[e.name](...t){return e(...t)}}[e.name],{_reducerDefinitionType:`reducer`})},preparedReducer(e,t){return{_reducerDefinitionType:`reducerWithPrepare`,prepare:e,reducer:t}},asyncThunk:e}}function zl({type:e,reducerName:t,createNotation:n},r,i){let a,o;if(`reducer`in r){if(n&&!Vl(r))throw Error(wu(17));a=r.reducer,o=r.prepare}else a=r;i.addCase(e,a).exposeCaseReducer(t,a).exposeAction(t,o?gl(e,o):gl(e))}function Bl(e){return e._reducerDefinitionType===`asyncThunk`}function Vl(e){return e._reducerDefinitionType===`reducerWithPrepare`}function Hl({type:e,reducerName:t},n,r,i){if(!i)throw Error(wu(18));let{payloadCreator:a,fulfilled:o,pending:s,rejected:c,settled:l,options:u}=n,d=i(e,a,u);r.exposeAction(t,d),o&&r.addCase(d.fulfilled,o),s&&r.addCase(d.pending,s),c&&r.addCase(d.rejected,c),l&&r.addMatcher(d.settled,l),r.exposeCaseReducer(t,{fulfilled:o||Ul,pending:s||Ul,rejected:c||Ul,settled:l||Ul})}function Ul(){}var Wl=`task`,Gl=`listener`,Kl=`completed`,ql=`cancelled`,Jl=`task-${ql}`,Yl=`task-${Kl}`,Xl=`${Gl}-${ql}`,Zl=`${Gl}-${Kl}`,Ql=class{constructor(e){this.code=e,this.message=`${Wl} ${ql} (reason: ${e})`}code;name=`TaskAbortError`;message},$l=(e,t)=>{if(typeof e!=`function`)throw TypeError(wu(32))},eu=()=>{},tu=(e,t=eu)=>(e.catch(t),e),nu=(e,t)=>(e.addEventListener(`abort`,t,{once:!0}),()=>e.removeEventListener(`abort`,t)),ru=e=>{if(e.aborted)throw new Ql(e.reason)};function iu(e,t){let n=eu;return new Promise((r,i)=>{let a=()=>i(new Ql(e.reason));if(e.aborted){a();return}n=nu(e,a),t.finally(()=>n()).then(r,i)}).finally(()=>{n=eu})}var au=async(e,t)=>{try{return await Promise.resolve(),{status:`ok`,value:await e()}}catch(e){return{status:e instanceof Ql?`cancelled`:`rejected`,error:e}}finally{t?.()}},ou=e=>t=>tu(iu(e,t).then(t=>(ru(e),t))),su=e=>{let t=ou(e);return e=>t(new Promise(t=>setTimeout(t,e)))},{assign:cu}=Object,lu={},uu=`listenerMiddleware`,du=(e,t)=>{let n=t=>nu(e,()=>t.abort(e.reason));return(r,i)=>{$l(r,`taskExecutor`);let a=new AbortController;n(a);let o=au(async()=>{ru(e),ru(a.signal);let t=await r({pause:ou(a.signal),delay:su(a.signal),signal:a.signal});return ru(a.signal),t},()=>a.abort(Yl));return i?.autoJoin&&t.push(o.catch(eu)),{result:ou(e)(o),cancel(){a.abort(Jl)}}}},fu=(e,t)=>{let n=async(n,r)=>{ru(t);let i=()=>{},a=[new Promise((t,r)=>{let a=e({predicate:n,effect:(e,n)=>{n.unsubscribe(),t([e,n.getState(),n.getOriginalState()])}});i=()=>{a(),r()}})];r!=null&&a.push(new Promise(e=>setTimeout(e,r,null)));try{let e=await iu(t,Promise.race(a));return ru(t),e}finally{i()}};return((e,t)=>tu(n(e,t)))},pu=e=>{let{type:t,actionCreator:n,matcher:r,predicate:i,effect:a}=e;if(t)i=gl(t).match;else if(n)t=n.type,i=n.match;else if(r)i=r;else if(!i)throw Error(wu(21));return $l(a,`options.listener`),{predicate:i,type:t,effect:a}},mu=cu(e=>{let{type:t,predicate:n,effect:r}=pu(e);return{id:Ml(),effect:r,type:t,predicate:n,pending:new Set,unsubscribe:()=>{throw Error(wu(22))}}},{withTypes:()=>mu}),hu=(e,t)=>{let{type:n,effect:r,predicate:i}=pu(t);return Array.from(e.values()).find(e=>(typeof n==`string`?e.type===n:e.predicate===i)&&e.effect===r)},gu=e=>{e.pending.forEach(e=>{e.abort(Xl)})},_u=(e,t)=>()=>{for(let e of t.keys())gu(e);e.clear()},vu=(e,t,n)=>{try{e(t,n)}catch(e){setTimeout(()=>{throw e},0)}},yu=cu(gl(`${uu}/add`),{withTypes:()=>yu}),bu=gl(`${uu}/removeAll`),xu=cu(gl(`${uu}/remove`),{withTypes:()=>xu}),Su=(...e)=>{console.error(`${uu}/error`,...e)},Cu=(e={})=>{let t=new Map,n=new Map,r=e=>{let t=n.get(e)??0;n.set(e,t+1)},i=e=>{let t=n.get(e)??1;t===1?n.delete(e):n.set(e,t-1)},{extra:a,onError:o=Su}=e;$l(o,`onError`);let s=e=>(e.unsubscribe=()=>t.delete(e.id),t.set(e.id,e),t=>{e.unsubscribe(),t?.cancelActive&&gu(e)}),c=(e=>{let n=hu(t,e)??mu(e);return s(n)});cu(c,{withTypes:()=>c});let l=e=>{let n=hu(t,e);return n&&(n.unsubscribe(),e.cancelActive&&gu(n)),!!n};cu(l,{withTypes:()=>l});let u=async(e,n,s,l)=>{let u=new AbortController,d=fu(c,u.signal),f=[];try{e.pending.add(u),r(e),await Promise.resolve(e.effect(n,cu({},s,{getOriginalState:l,condition:(e,t)=>d(e,t).then(Boolean),take:d,delay:su(u.signal),pause:ou(u.signal),extra:a,signal:u.signal,fork:du(u.signal,f),unsubscribe:e.unsubscribe,subscribe:()=>{t.set(e.id,e)},cancelActiveListeners:()=>{e.pending.forEach((e,t,n)=>{e!==u&&(e.abort(Xl),n.delete(e))})},cancel:()=>{u.abort(Xl),e.pending.delete(u)},throwIfCancelled:()=>{ru(u.signal)}})))}catch(e){e instanceof Ql||vu(o,e,{raisedBy:`effect`})}finally{await Promise.all(f),u.abort(Zl),i(e),e.pending.delete(u)}},d=_u(t,n);return{middleware:e=>n=>r=>{if(!Us(r))return n(r);if(yu.match(r))return c(r.payload);if(bu.match(r)){d();return}if(xu.match(r))return l(r.payload);let i=e.getState(),a=()=>{if(i===lu)throw Error(wu(23));return i},s;try{if(s=n(r),t.size>0){let n=e.getState(),s=Array.from(t.values());for(let t of s){let s=!1;try{s=t.predicate(r,n,i)}catch(e){s=!1,vu(o,e,{raisedBy:`predicate`})}s&&u(t,r,e,a)}}}finally{i=lu}return s},startListening:c,stopListening:l,clearListeners:d}};function wu(e){return`Minified Redux Toolkit error #${e}; visit https://redux-toolkit.js.org/Errors?code=${e} for the full message or use the non-minified dev environment for full errors. `}var Tu=Ll({name:`chartLayout`,initialState:{layoutType:`horizontal`,width:0,height:0,margin:{top:5,right:5,bottom:5,left:5},scale:1},reducers:{setLayout(e,t){e.layoutType=t.payload},setChartSize(e,t){e.width=t.payload.width,e.height=t.payload.height},setMargin(e,t){e.margin.top=t.payload.top??0,e.margin.right=t.payload.right??0,e.margin.bottom=t.payload.bottom??0,e.margin.left=t.payload.left??0},setScale(e,t){e.scale=t.payload}}}),Eu=Tu.actions,Du=Eu.setMargin,Ou=Eu.setLayout,ku=Eu.setChartSize,Au=Eu.setScale,ju=Tu.reducer;function Mu(e,t,n){return Array.isArray(e)&&e&&t+n!==0?e.slice(t,n+1):e}function G(e){return Number.isFinite(e)}function Nu(e){return typeof e==`number`&&e>0&&Number.isFinite(e)}function Pu(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function Fu(e){for(var t=1;t{if(t&&n){var r=n.width,i=n.height,a=t.align,o=t.verticalAlign,s=t.layout,c=t.position,l=t.offset,u=l===void 0?0:l;if(c!=null){if(yi(c)){if(c===`top`&&L(e.top))return Fu(Fu({},e),{},{top:e.top+(i||0)+u});if(c===`bottom`&&L(e.bottom))return Fu(Fu({},e),{},{bottom:e.bottom+(i||0)+u});if(c===`left`&&L(e.left))return Fu(Fu({},e),{},{left:e.left+(r||0)+u});if(c===`right`&&L(e.right))return Fu(Fu({},e),{},{right:e.right+(r||0)+u})}return e}if((s===`vertical`||s===`horizontal`&&o===`middle`)&&a!==`center`&&L(e[a]))return Fu(Fu({},e),{},{[a]:e[a]+(r||0)});if((s===`horizontal`||s===`vertical`&&a===`center`)&&o!==`middle`&&L(e[o]))return Fu(Fu({},e),{},{[o]:e[o]+(i||0)})}return e},Bu=(e,t)=>e===`horizontal`&&t===`xAxis`||e===`vertical`&&t===`yAxis`||e===`centric`&&t===`angleAxis`||e===`radial`&&t===`radiusAxis`,Vu=(e,t,n,r)=>{if(r)return e.map(e=>e.coordinate);var i,a,o=e.map(e=>(e.coordinate===t&&(i=!0),e.coordinate===n&&(a=!0),e.coordinate));return i||o.push(t),a||o.push(n),o},Hu=(e,t,n)=>{if(!e)return null;var r=e.duplicateDomain,i=e.type,a=e.range,o=e.scale,s=e.realScaleType,c=e.isCategorical,l=e.categoricalDomain,u=e.tickCount,d=e.ticks,f=e.niceTicks,p=e.axisType;if(!o)return null;var m=s===`scaleBand`&&o.bandwidth?o.bandwidth()/2:2,h=(t||n)&&i===`category`&&o.bandwidth?o.bandwidth()/m:0;return h=p===`angleAxis`&&a&&a.length>=2?$r(a[0]-a[1])*2*h:h,t&&(d||f)?(d||f||[]).map((e,t)=>{var n=r?r.indexOf(e):e,i=o.map(n);return G(i)?{coordinate:i+h,value:e,offset:h,index:t}:null}).filter(li):c&&l?l.map((e,t)=>{var n=o.map(e);return G(n)?{coordinate:n+h,value:e,index:t,offset:h}:null}).filter(li):o.ticks&&!n&&u!=null?o.ticks(u).map((e,t)=>{var n=o.map(e);return G(n)?{coordinate:n+h,value:e,index:t,offset:h}:null}).filter(li):o.domain().map((e,t)=>{var n=o.map(e);return G(n)?{coordinate:n+h,value:r?r[e]:e,index:t,offset:h}:null}).filter(li)},Uu=(e,t)=>{if(!t||t.length!==2||!L(t[0])||!L(t[1]))return e;var n=Math.min(t[0],t[1]),r=Math.max(t[0],t[1]),i=[e[0],e[1]];return(!L(e[0])||e[0]r)&&(i[1]=r),i[0]>r&&(i[0]=r),i[1]{var t=e.length;if(!(t<=0)){var n=e[0]?.length;if(!(n==null||n<=0))for(var r=0;r=0?(s[0]=i,i+=u,s[1]=i):(s[0]=a,a+=u,s[1]=a)}}}},expand:va,none:pa,silhouette:ya,wiggle:ba,positive:e=>{var t=e.length;if(!(t<=0)){var n=e[0]?.length;if(!(n==null||n<=0))for(var r=0;r=0?(o[0]=i,i+=s,o[1]=i):(o[0]=0,o[1]=0)}}}}},Gu=(e,t,n)=>{var r=Wu[n]??pa,i=_a().keys(t).value((e,t)=>Number(K(e,t,0))).order(ma).offset(r)(e);return i.forEach((n,r)=>{n.forEach((n,i)=>{var a=K(e[i],t[r],0);Array.isArray(a)&&a.length===2&&L(a[0])&&L(a[1])&&(n[0]=a[0],n[1]=a[1])})}),i};function Ku(e){return e==null?void 0:String(e)}function qu(e){var t=e.axis,n=e.ticks,r=e.bandSize,i=e.entry,a=e.index,o=e.dataKey;if(t.type===`category`){if(!t.allowDuplicatedCategory&&t.dataKey&&!z(i[t.dataKey])){var s=si(n,`value`,i[t.dataKey]);if(s)return s.coordinate+r/2}return n!=null&&n[a]?n[a].coordinate+r/2:null}var c=K(i,z(o)?t.dataKey:o),l=t.scale.map(c);return L(l)?l:null}var Ju=e=>{var t=e.axis,n=e.ticks,r=e.offset,i=e.bandSize,a=e.entry,o=e.index;if(t.type===`category`)return n[o]?n[o].coordinate+r:null;var s=K(a,t.dataKey,t.scale.domain()[o]);if(z(s))return null;var c=t.scale.map(s);return L(c)?c-i/2+r:null},Yu=e=>{var t=e.numericAxis,n=t.scale.domain();if(t.type===`number`){var r=Math.min(n[0],n[1]),i=Math.max(n[0],n[1]);return r<=0&&i>=0?0:i<0?i:r}return n[0]},Xu=e=>{var t=e.flat(2).filter(L);return[Math.min(...t),Math.max(...t)]},Zu=e=>[e[0]===1/0?0:e[0],e[1]===-1/0?0:e[1]],Qu=(e,t,n)=>{if(!(e==null||Object.keys(e).length===0))return Zu(Object.keys(e).reduce((r,i)=>{var a=e[i];if(!a)return r;var o=a.stackedData.reduce((e,r)=>{var i=Xu(Mu(r,t,n));return!G(i[0])||!G(i[1])?e:[Math.min(e[0],i[0]),Math.max(e[1],i[1])]},[1/0,-1/0]);return[Math.min(o[0],r[0]),Math.max(o[1],r[1])]},[1/0,-1/0]))},$u=/^dataMin[\s]*-[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/,ed=/^dataMax[\s]*\+[\s]*([0-9]+([.]{1}[0-9]+){0,1})$/,td=(e,t,n)=>{if(e&&e.scale&&e.scale.bandwidth){var r=e.scale.bandwidth();if(!n||r>0)return r}if(e&&t&&t.length>=2){for(var i=bs(t,e=>e.coordinate),a=[],o=0,s=1,c=i.length;su&&(d=Math.min(f,d));return d===1/0?0:d}return n?void 0:0};function nd(e){var t=e.tooltipEntrySettings,n=e.dataKey,r=e.payload,i=e.value,a=e.name;return Fu(Fu({},t),{},{dataKey:n,payload:r,value:i,name:a})}function rd(e,t){if(e!=null)return String(e);if(typeof t==`string`)return t}var id=(e,t)=>{if(t===`horizontal`)return e.relativeX;if(t===`vertical`)return e.relativeY},ad=(e,t)=>t===`centric`?e.angle:e.radius,od=e=>e.layout.width,sd=e=>e.layout.height,cd=e=>e.layout.scale,ld=e=>e.layout.margin,ud=H(e=>e.cartesianAxis.xAxis,e=>Object.values(e)),dd=H(e=>e.cartesianAxis.yAxis,e=>Object.values(e)),fd=`data-recharts-item-index`,pd=`data-recharts-item-id`;function md(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function hd(e){for(var t=1;te.brush.height;function bd(e){return dd(e).reduce((e,t)=>t.orientation===`left`&&!t.mirror&&!t.hide?e+(typeof t.width==`number`?t.width:60):e,0)}function xd(e){return dd(e).reduce((e,t)=>t.orientation===`right`&&!t.mirror&&!t.hide?e+(typeof t.width==`number`?t.width:60):e,0)}function Sd(e){return ud(e).reduce((e,t)=>t.orientation===`top`&&!t.mirror&&!t.hide?e+(typeof t.height==`number`?t.height:30):e,0)}function Cd(e){return ud(e).reduce((e,t)=>t.orientation===`bottom`&&!t.mirror&&!t.hide?e+(typeof t.height==`number`?t.height:30):e,0)}var wd=H([od,sd,ld,yd,bd,xd,Sd,Cd,xs,Ss],(e,t,n,r,i,a,o,s,c,l)=>{var u={left:(n.left||0)+i,right:(n.right||0)+a},d=hd(hd({},{top:(n.top||0)+o,bottom:(n.bottom||0)+s}),u),f=d.bottom;d.bottom+=r,d=zu(d,c,l);var p=e-d.left-d.right,m=t-d.top-d.bottom;return hd(hd({brushBottom:f},d),{},{width:Math.max(p,0),height:Math.max(m,0)})}),Td=H(wd,e=>({x:e.left,y:e.top,width:e.width,height:e.height})),Ed=H(od,sd,(e,t)=>({x:0,y:0,width:e,height:t})),Dd=(0,O.createContext)(null),Od=()=>(0,O.useContext)(Dd)!=null,kd=e=>e.brush,Ad=H([kd,wd,ld],(e,t,n)=>({height:e.height,x:L(e.x)?e.x:t.left,y:L(e.y)?e.y:t.top+t.height+t.brushBottom-(n?.bottom||0),width:L(e.width)?e.width:t.width}));function jd(e,t,{signal:n,edges:r}={}){let i,a=null,o=r!=null&&r.includes(`leading`),s=r==null||r.includes(`trailing`),c=()=>{a!==null&&(e.apply(i,a),i=void 0,a=null)},l=()=>{s&&c(),p()},u=null,d=()=>{u!=null&&clearTimeout(u),u=setTimeout(()=>{u=null,l()},t)},f=()=>{u!==null&&(clearTimeout(u),u=null)},p=()=>{f(),i=void 0,a=null},m=()=>{c()},h=function(...e){if(n?.aborted)return;i=this,a=e;let t=u==null;d(),o&&t&&c()};return h.schedule=d,h.cancel=p,h.flush=m,n?.addEventListener(`abort`,p,{once:!0}),h}function Md(e,t=0,n={}){typeof n!=`object`&&(n={});let{leading:r=!1,trailing:i=!0,maxWait:a}=n,o=[,,];r&&(o[0]=`leading`),i&&(o[1]=`trailing`);let s,c=null,l=jd(function(...t){s=e.apply(this,t),c=null},t,{edges:o}),u=function(...t){return a!=null&&(c===null&&(c=Date.now()),Date.now()-c>=a)?(s=e.apply(this,t),c=Date.now(),l.cancel(),l.schedule(),s):(l.apply(this,t),s)};return u.cancel=l.cancel,u.flush=()=>(l.flush(),s),u}function Nd(e,t=0,n={}){let{leading:r=!0,trailing:i=!0}=n;return Md(e,t,{leading:r,maxWait:t,trailing:i})}var Pd=function(e,t){var n=[...arguments].slice(2);if(typeof console<`u`&&console.warn&&(t===void 0&&console.warn(`LogUtils requires an error message argument`),!e))if(t===void 0)console.warn(`Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.`);else{var r=0;console.warn(t.replace(/%s/g,()=>n[r++]))}},Fd={width:`100%`,height:`100%`,debounce:0,minWidth:0,initialDimension:{width:-1,height:-1}},Id=(e,t,n)=>{var r=n.width,i=r===void 0?Fd.width:r,a=n.height,o=a===void 0?Fd.height:a,s=n.aspect,c=n.maxHeight,l=ti(i)?e:Number(i),u=ti(o)?t:Number(o);return s&&s>0&&(l?u=l/s:u&&(l=u*s),c&&u!=null&&u>c&&(u=c)),{calculatedWidth:l,calculatedHeight:u}},Ld={width:0,height:0,overflow:`visible`},Rd={width:0,overflowX:`visible`},zd={height:0,overflowY:`visible`},Bd={},Vd=e=>{var t=e.width,n=e.height,r=ti(t),i=ti(n);return r&&i?Ld:r?Rd:i?zd:Bd};function Hd(e){var t=e.width,n=e.height,r=e.aspect,i=t,a=n;return i===void 0&&a===void 0?(i=Fd.width,a=Fd.height):i===void 0?i=r&&r>0?void 0:Fd.width:a===void 0&&(a=r&&r>0?void 0:Fd.height),{width:i,height:a}}var Ud=[`aspect`,`initialDimension`,`width`,`height`,`minWidth`,`minHeight`,`maxHeight`,`children`,`debounce`,`id`,`className`,`onResize`,`style`];function Wd(){return Wd=Object.assign?Object.assign.bind():function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n({width:n,height:r}),[n,r]);return of(i)?O.createElement(af.Provider,{value:i},t):null}var cf=()=>(0,O.useContext)(af),lf=(0,O.forwardRef)((e,t)=>{var n=e.aspect,r=e.initialDimension,i=r===void 0?Fd.initialDimension:r,a=e.width,o=e.height,s=e.minWidth,c=s===void 0?Fd.minWidth:s,l=e.minHeight,u=e.maxHeight,d=e.children,f=e.debounce,p=f===void 0?Fd.debounce:f,m=e.id,h=e.className,_=e.onResize,v=e.style,y=v===void 0?{}:v,b=nf(e,Ud),x=(0,O.useRef)(null),S=(0,O.useRef)();S.current=_,(0,O.useImperativeHandle)(t,()=>x.current);var C=Xd((0,O.useState)({containerWidth:i.width,containerHeight:i.height}),2),w=C[0],T=C[1],E=(0,O.useCallback)((e,t)=>{T(n=>{var r=Math.round(e),i=Math.round(t);return n.containerWidth===r&&n.containerHeight===i?n:{containerWidth:r,containerHeight:i}})},[]);(0,O.useEffect)(()=>{if(x.current==null||typeof ResizeObserver>`u`)return ui;var e=e=>{var t,n=e[0];if(n!=null){var r=n.contentRect,i=r.width,a=r.height;E(i,a),(t=S.current)==null||t.call(S,i,a)}};p>0&&(e=Nd(e,p,{trailing:!0,leading:!1}));var t=new ResizeObserver(e),n=x.current.getBoundingClientRect(),r=n.width,i=n.height;return E(r,i),t.observe(x.current),()=>{t.disconnect()}},[E,p]);var D=w.containerWidth,k=w.containerHeight;Pd(!n||n>0,`The aspect(%s) must be greater than zero.`,n);var A=Id(D,k,{width:a,height:o,aspect:n,maxHeight:u}),j=A.calculatedWidth,M=A.calculatedHeight;return Pd(D<0||k<0||j!=null&&j>0||M!=null&&M>0,`The width(%s) and height(%s) of chart should be greater than 0, please check the style of container, or the props width(%s) and height(%s), diff --git a/web/dist/assets/run-page-CsK2gHGg.js b/web/dist/assets/run-page-CsK2gHGg.js new file mode 100644 index 0000000..6ec077e --- /dev/null +++ b/web/dist/assets/run-page-CsK2gHGg.js @@ -0,0 +1 @@ +import{c as e,d as t,l as n,o as r,r as i,t as a,u as o}from"./risk-histogram-dP0_I5OY.js";import{A as s,D as c,F as l,H as u,J as d,K as f,M as p,O as m,P as h,U as g,V as _,X as v,a as y,c as b,f as x,i as S,j as C,n as w,o as T,p as E,q as D,r as O,s as k,t as A,z as j}from"./index-D1U5YqHo.js";var M=v();function N(){let{id:v=``}=d(),y=D(),x=h(v),S=l(v,x.data?.run.status===`running`),w=j(),T=p(),O=C();if(x.isPending)return(0,M.jsx)(B,{});if(x.error instanceof s&&x.error.status===404)return(0,M.jsx)(H,{});if(x.isError||!x.data)return(0,M.jsxs)(`main`,{className:`session-page`,children:[(0,M.jsxs)(c,{className:`error-state`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not load run`}),(0,M.jsx)(`p`,{children:U(x.error)})]}),(0,M.jsx)(m,{type:`button`,onClick:()=>x.refetch(),children:`Retry`})]}),(0,M.jsx)(f,{to:`/`,className:`back-link`,children:`Back to runs`})]});let{run:k,variants:A}=x.data,N=A.find(e=>e.target_country)?.target_country;return(0,M.jsxs)(`main`,{className:`session-page`,children:[(0,M.jsx)(f,{to:`/`,className:`breadcrumb`,children:`Runs`}),(0,M.jsxs)(`header`,{className:`session-header`,children:[(0,M.jsxs)(`div`,{className:`session-title`,children:[(0,M.jsxs)(`div`,{className:`session-title-line`,children:[(0,M.jsx)(`h1`,{children:k.name}),(0,M.jsx)(b,{status:k.status})]}),(0,M.jsxs)(`p`,{children:[(0,M.jsx)(`span`,{className:`mono`,children:k.template_display}),(0,M.jsx)(`span`,{"aria-hidden":`true`,children:` · `}),(0,M.jsxs)(`span`,{children:[k.variant_count,` variant`,k.variant_count===1?``:`s`]}),N&&(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(`span`,{"aria-hidden":`true`,children:` · `}),(0,M.jsxs)(`span`,{children:[`Target country `,(0,M.jsx)(`span`,{className:`mono`,children:N}),` (manual)`]})]})]})]}),(0,M.jsxs)(`div`,{className:`session-actions`,children:[k.status===`running`&&(0,M.jsxs)(m,{type:`button`,variant:`danger`,onClick:()=>{window.confirm(`Stop “${k.name}”? You can re-enable it later.`)&&w.mutate(v)},disabled:w.isPending,children:[(0,M.jsx)(g,{size:14,fill:`currentColor`,"aria-hidden":`true`}),w.isPending?`Stopping…`:`Stop run`]}),k.status!==`running`&&(0,M.jsxs)(m,{type:`button`,onClick:()=>{window.confirm(`Re-enable “${k.name}”? Sampling resumes across all variants; progress counters reset while prior samples are kept.`)&&T.mutate(v)},disabled:T.isPending,children:[(0,M.jsx)(o,{size:14,"aria-hidden":`true`}),T.isPending?`Re-enabling…`:`Re-enable`]}),(0,M.jsxs)(m,{type:`button`,variant:`secondary`,onClick:()=>{window.confirm(`Delete “${k.name}”? This removes the run and all its variant sessions. This cannot be undone.`)&&O.mutate(v,{onSuccess:()=>y(`/`)})},disabled:O.isPending,children:[(0,M.jsx)(u,{size:14,"aria-hidden":`true`}),O.isPending?`Deleting…`:`Delete`]}),(0,M.jsxs)(`a`,{className:`button button-secondary`,href:`/api/runs/${v}/export.csv`,download:!0,children:[(0,M.jsx)(t,{size:16,"aria-hidden":`true`}),`Export pool CSV`]})]})]}),w.isError&&(0,M.jsxs)(c,{className:`inline-alert`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not stop run`}),(0,M.jsx)(`p`,{children:U(w.error)})]})]}),T.isError&&(0,M.jsxs)(c,{className:`inline-alert`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not re-enable run`}),(0,M.jsx)(`p`,{children:U(T.error)})]})]}),O.isError&&(0,M.jsxs)(c,{className:`inline-alert`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not delete run`}),(0,M.jsx)(`p`,{children:U(O.error)})]})]}),(0,M.jsx)(z,{report:S,children:S.data&&(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(P,{run:k,report:S.data}),(0,M.jsx)(`div`,{className:`report-meta`,"aria-live":`polite`,children:S.dataUpdatedAt>0?`Last updated ${E(new Date(S.dataUpdatedAt).toISOString())}`:`Waiting for report update`}),(0,M.jsxs)(`div`,{className:`report-grid`,children:[(0,M.jsx)(e,{data:S.data.series}),(0,M.jsx)(r,{data:S.data.series}),(0,M.jsx)(i,{data:S.data.composition}),(0,M.jsx)(a,{data:S.data.risk_histogram})]}),(0,M.jsxs)(`section`,{className:`report-section`,children:[(0,M.jsx)(`h2`,{children:`Per-cell breakdown`}),(0,M.jsx)(F,{cells:S.data.cells})]}),(0,M.jsxs)(`section`,{className:`report-section`,children:[(0,M.jsx)(`h2`,{children:`IP reputation`}),(0,M.jsx)(n,{rows:S.data.ips})]})]})}),(0,M.jsxs)(`section`,{className:`report-section`,children:[(0,M.jsx)(`h2`,{children:`Variants`}),(0,M.jsx)(I,{variants:A})]})]})}function P({run:e,report:t}){let n=new Intl.NumberFormat().format(t.estimated_pool_size);return(0,M.jsx)(`dl`,{className:`summary-strip`,role:`region`,"aria-label":`Run summary`,children:[[`Variants`,new Intl.NumberFormat().format(e.variant_count)],[`Distinct IPs`,new Intl.NumberFormat().format(t.distinct_ips)],[`Estimated pool size`,t.pool_size_lower_bound?(0,M.jsx)(`abbr`,{title:`Lower-bound estimate: sampling may not have covered the full pool yet.`,children:`≥ ${n}`}):n],[`Honor rate`,t.honor_rate==null?`—`:x(t.honor_rate)],[`Flagged`,x(t.flagged_percent/100)],[`DNSBL hits`,new Intl.NumberFormat().format(t.dnsbl_hit_ips)]].map(([e,t])=>(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`dt`,{children:e}),(0,M.jsx)(`dd`,{className:`numeric`,children:t})]},e))})}function F({cells:e}){if(e.length===0)return(0,M.jsx)(`p`,{className:`section-empty`,children:`Per-cell data appears once a variant reports samples.`});let t=[...e].sort((e,t)=>t.variant_count-e.variant_count||e.cell_key.localeCompare(t.cell_key));return(0,M.jsx)(`div`,{className:`data-table-wrap`,children:(0,M.jsxs)(w,{children:[(0,M.jsx)(T,{children:(0,M.jsxs)(k,{children:[(0,M.jsx)(y,{children:`Cell`}),(0,M.jsx)(y,{children:`Variants`}),(0,M.jsx)(y,{children:`Distinct IPs`}),(0,M.jsx)(y,{children:`Honor rate`}),(0,M.jsx)(y,{children:`Composition`})]})}),(0,M.jsx)(O,{children:t.map(e=>(0,M.jsxs)(k,{children:[(0,M.jsxs)(S,{className:`mono compact-cell`,children:[L(e.params),e.target_country&&(0,M.jsxs)(`span`,{className:`muted`,children:[` · target `,e.target_country,` (manual)`]})]}),(0,M.jsx)(S,{className:`numeric`,children:e.variant_count}),(0,M.jsx)(S,{className:`numeric`,children:e.distinct_ips}),(0,M.jsx)(S,{className:`numeric`,children:e.honor_rate==null?`—`:x(e.honor_rate)}),(0,M.jsx)(S,{children:R(e.composition)})]},e.cell_key))})]})})}function I({variants:e}){let t=D();return e.length===0?(0,M.jsx)(`p`,{className:`section-empty`,children:`Variants will appear once the run expands into sessions.`}):(0,M.jsx)(`div`,{className:`data-table-wrap`,children:(0,M.jsxs)(w,{children:[(0,M.jsx)(T,{children:(0,M.jsxs)(k,{children:[(0,M.jsx)(y,{children:`Name`}),(0,M.jsx)(y,{children:`Cell`}),(0,M.jsx)(y,{children:`Status`}),(0,M.jsx)(y,{children:`Samples`}),(0,M.jsx)(y,{children:`Distinct IPs`})]})}),(0,M.jsx)(O,{children:e.map(e=>(0,M.jsxs)(k,{className:`session-row`,onClick:()=>t(`/sessions/${e.session_id}`),children:[(0,M.jsx)(S,{children:(0,M.jsx)(f,{className:`session-link`,to:`/sessions/${e.session_id}`,onClick:e=>e.stopPropagation(),children:(0,M.jsx)(`strong`,{children:e.name})})}),(0,M.jsx)(S,{className:`mono compact-cell`,children:L(e.params)}),(0,M.jsx)(S,{children:(0,M.jsx)(b,{status:e.status})}),(0,M.jsx)(S,{className:`numeric`,children:e.samples_taken}),(0,M.jsx)(S,{className:`numeric`,children:e.distinct_ips})]},e.session_id))})]})})}function L(e){let t=Object.entries(e);return t.length===0?`—`:t.map(([e,t])=>`${e}=${t}`).join(`, `)}function R(e){let t=[];return e.mobile&&t.push(`${e.mobile} mobile`),e.residential&&t.push(`${e.residential} residential`),e.datacenter&&t.push(`${e.datacenter} datacenter`),e.unknown&&t.push(`${e.unknown} unknown`),t.length===0?`—`:t.join(` · `)}function z({report:e,children:t}){return e.isPending?(0,M.jsx)(V,{}):e.isError?(0,M.jsxs)(c,{children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not load report`}),(0,M.jsx)(`p`,{children:U(e.error)})]}),(0,M.jsx)(m,{type:`button`,onClick:()=>e.refetch(),children:`Retry report`})]}):t}function B(){return(0,M.jsxs)(`main`,{className:`session-page session-loading`,children:[(0,M.jsxs)(`div`,{role:`status`,"aria-label":`Loading run detail`,children:[(0,M.jsx)(`span`,{className:`sr-only`,children:`Loading run detail`}),(0,M.jsx)(A,{className:`session-heading-skeleton`}),(0,M.jsx)(A,{className:`session-subheading-skeleton`})]}),(0,M.jsx)(V,{})]})}function V(){return(0,M.jsxs)(`div`,{className:`report-loading`,"aria-label":`Loading report`,children:[(0,M.jsx)(A,{className:`summary-skeleton`}),Array.from({length:4},(e,t)=>(0,M.jsx)(A,{className:`chart-skeleton`},t))]})}function H(){return(0,M.jsxs)(`main`,{className:`empty-state`,children:[(0,M.jsx)(`h1`,{children:`Run not found`}),(0,M.jsx)(`p`,{children:`This run may have been removed, or the link may be incomplete.`}),(0,M.jsx)(f,{to:`/`,className:`button button-primary`,children:`Back to runs`})]})}function U(e){return e instanceof Error?e.message:`The request could not be completed.`}export{N as RunPage}; \ No newline at end of file diff --git a/web/dist/assets/run-page-SJdc0Mk9.js b/web/dist/assets/run-page-SJdc0Mk9.js deleted file mode 100644 index 1fb22a5..0000000 --- a/web/dist/assets/run-page-SJdc0Mk9.js +++ /dev/null @@ -1 +0,0 @@ -import{c as e,d as t,l as n,o as r,r as i,t as a,u as o}from"./risk-histogram-Bw31Zp4T.js";import{A as s,D as c,F as l,H as u,J as d,K as f,M as p,O as m,P as h,U as g,V as _,X as v,a as y,c as b,f as x,i as S,j as C,n as w,o as T,p as E,q as D,r as O,s as k,t as A,z as j}from"./index-NIa5ODC0.js";var M=v();function N(){let{id:v=``}=d(),y=D(),x=h(v),S=l(v,x.data?.run.status===`running`),w=j(),T=p(),O=C();if(x.isPending)return(0,M.jsx)(B,{});if(x.error instanceof s&&x.error.status===404)return(0,M.jsx)(H,{});if(x.isError||!x.data)return(0,M.jsxs)(`main`,{className:`session-page`,children:[(0,M.jsxs)(c,{className:`error-state`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not load run`}),(0,M.jsx)(`p`,{children:U(x.error)})]}),(0,M.jsx)(m,{type:`button`,onClick:()=>x.refetch(),children:`Retry`})]}),(0,M.jsx)(f,{to:`/`,className:`back-link`,children:`Back to runs`})]});let{run:k,variants:A}=x.data;return(0,M.jsxs)(`main`,{className:`session-page`,children:[(0,M.jsx)(f,{to:`/`,className:`breadcrumb`,children:`Runs`}),(0,M.jsxs)(`header`,{className:`session-header`,children:[(0,M.jsxs)(`div`,{className:`session-title`,children:[(0,M.jsxs)(`div`,{className:`session-title-line`,children:[(0,M.jsx)(`h1`,{children:k.name}),(0,M.jsx)(b,{status:k.status})]}),(0,M.jsxs)(`p`,{children:[(0,M.jsx)(`span`,{className:`mono`,children:k.template_display}),(0,M.jsx)(`span`,{"aria-hidden":`true`,children:` · `}),(0,M.jsxs)(`span`,{children:[k.variant_count,` variant`,k.variant_count===1?``:`s`]})]})]}),(0,M.jsxs)(`div`,{className:`session-actions`,children:[k.status===`running`&&(0,M.jsxs)(m,{type:`button`,variant:`danger`,onClick:()=>{window.confirm(`Stop “${k.name}”? You can re-enable it later.`)&&w.mutate(v)},disabled:w.isPending,children:[(0,M.jsx)(g,{size:14,fill:`currentColor`,"aria-hidden":`true`}),w.isPending?`Stopping…`:`Stop run`]}),k.status!==`running`&&(0,M.jsxs)(m,{type:`button`,onClick:()=>{window.confirm(`Re-enable “${k.name}”? Sampling resumes across all variants; progress counters reset while prior samples are kept.`)&&T.mutate(v)},disabled:T.isPending,children:[(0,M.jsx)(o,{size:14,"aria-hidden":`true`}),T.isPending?`Re-enabling…`:`Re-enable`]}),(0,M.jsxs)(m,{type:`button`,variant:`secondary`,onClick:()=>{window.confirm(`Delete “${k.name}”? This removes the run and all its variant sessions. This cannot be undone.`)&&O.mutate(v,{onSuccess:()=>y(`/`)})},disabled:O.isPending,children:[(0,M.jsx)(u,{size:14,"aria-hidden":`true`}),O.isPending?`Deleting…`:`Delete`]}),(0,M.jsxs)(`a`,{className:`button button-secondary`,href:`/api/runs/${v}/export.csv`,download:!0,children:[(0,M.jsx)(t,{size:16,"aria-hidden":`true`}),`Export pool CSV`]})]})]}),w.isError&&(0,M.jsxs)(c,{className:`inline-alert`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not stop run`}),(0,M.jsx)(`p`,{children:U(w.error)})]})]}),T.isError&&(0,M.jsxs)(c,{className:`inline-alert`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not re-enable run`}),(0,M.jsx)(`p`,{children:U(T.error)})]})]}),O.isError&&(0,M.jsxs)(c,{className:`inline-alert`,children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not delete run`}),(0,M.jsx)(`p`,{children:U(O.error)})]})]}),(0,M.jsx)(z,{report:S,children:S.data&&(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(P,{run:k,report:S.data}),(0,M.jsx)(`div`,{className:`report-meta`,"aria-live":`polite`,children:S.dataUpdatedAt>0?`Last updated ${E(new Date(S.dataUpdatedAt).toISOString())}`:`Waiting for report update`}),(0,M.jsxs)(`div`,{className:`report-grid`,children:[(0,M.jsx)(e,{data:S.data.series}),(0,M.jsx)(r,{data:S.data.series}),(0,M.jsx)(i,{data:S.data.composition}),(0,M.jsx)(a,{data:S.data.risk_histogram})]}),(0,M.jsxs)(`section`,{className:`report-section`,children:[(0,M.jsx)(`h2`,{children:`Per-cell breakdown`}),(0,M.jsx)(F,{cells:S.data.cells})]}),(0,M.jsxs)(`section`,{className:`report-section`,children:[(0,M.jsx)(`h2`,{children:`IP reputation`}),(0,M.jsx)(n,{rows:S.data.ips})]})]})}),(0,M.jsxs)(`section`,{className:`report-section`,children:[(0,M.jsx)(`h2`,{children:`Variants`}),(0,M.jsx)(I,{variants:A})]})]})}function P({run:e,report:t}){let n=new Intl.NumberFormat().format(t.estimated_pool_size);return(0,M.jsx)(`dl`,{className:`summary-strip`,role:`region`,"aria-label":`Run summary`,children:[[`Variants`,new Intl.NumberFormat().format(e.variant_count)],[`Distinct IPs`,new Intl.NumberFormat().format(t.distinct_ips)],[`Estimated pool size`,t.pool_size_lower_bound?(0,M.jsx)(`abbr`,{title:`Lower-bound estimate: sampling may not have covered the full pool yet.`,children:`≥ ${n}`}):n],[`Honor rate`,t.honor_rate==null?`—`:x(t.honor_rate)],[`Flagged`,x(t.flagged_percent/100)],[`DNSBL hits`,new Intl.NumberFormat().format(t.dnsbl_hit_ips)]].map(([e,t])=>(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`dt`,{children:e}),(0,M.jsx)(`dd`,{className:`numeric`,children:t})]},e))})}function F({cells:e}){if(e.length===0)return(0,M.jsx)(`p`,{className:`section-empty`,children:`Per-cell data appears once a variant reports samples.`});let t=[...e].sort((e,t)=>t.variant_count-e.variant_count||e.cell_key.localeCompare(t.cell_key));return(0,M.jsx)(`div`,{className:`data-table-wrap`,children:(0,M.jsxs)(w,{children:[(0,M.jsx)(T,{children:(0,M.jsxs)(k,{children:[(0,M.jsx)(y,{children:`Cell`}),(0,M.jsx)(y,{children:`Variants`}),(0,M.jsx)(y,{children:`Distinct IPs`}),(0,M.jsx)(y,{children:`Honor rate`}),(0,M.jsx)(y,{children:`Composition`})]})}),(0,M.jsx)(O,{children:t.map(e=>(0,M.jsxs)(k,{children:[(0,M.jsx)(S,{className:`mono compact-cell`,children:L(e.params)}),(0,M.jsx)(S,{className:`numeric`,children:e.variant_count}),(0,M.jsx)(S,{className:`numeric`,children:e.distinct_ips}),(0,M.jsx)(S,{className:`numeric`,children:e.honor_rate==null?`—`:x(e.honor_rate)}),(0,M.jsx)(S,{children:R(e.composition)})]},e.cell_key))})]})})}function I({variants:e}){let t=D();return e.length===0?(0,M.jsx)(`p`,{className:`section-empty`,children:`Variants will appear once the run expands into sessions.`}):(0,M.jsx)(`div`,{className:`data-table-wrap`,children:(0,M.jsxs)(w,{children:[(0,M.jsx)(T,{children:(0,M.jsxs)(k,{children:[(0,M.jsx)(y,{children:`Name`}),(0,M.jsx)(y,{children:`Cell`}),(0,M.jsx)(y,{children:`Status`}),(0,M.jsx)(y,{children:`Samples`}),(0,M.jsx)(y,{children:`Distinct IPs`})]})}),(0,M.jsx)(O,{children:e.map(e=>(0,M.jsxs)(k,{className:`session-row`,onClick:()=>t(`/sessions/${e.session_id}`),children:[(0,M.jsx)(S,{children:(0,M.jsx)(f,{className:`session-link`,to:`/sessions/${e.session_id}`,onClick:e=>e.stopPropagation(),children:(0,M.jsx)(`strong`,{children:e.name})})}),(0,M.jsx)(S,{className:`mono compact-cell`,children:L(e.params)}),(0,M.jsx)(S,{children:(0,M.jsx)(b,{status:e.status})}),(0,M.jsx)(S,{className:`numeric`,children:e.samples_taken}),(0,M.jsx)(S,{className:`numeric`,children:e.distinct_ips})]},e.session_id))})]})})}function L(e){let t=Object.entries(e);return t.length===0?`—`:t.map(([e,t])=>`${e}=${t}`).join(`, `)}function R(e){let t=[];return e.mobile&&t.push(`${e.mobile} mobile`),e.residential&&t.push(`${e.residential} residential`),e.datacenter&&t.push(`${e.datacenter} datacenter`),e.unknown&&t.push(`${e.unknown} unknown`),t.length===0?`—`:t.join(` · `)}function z({report:e,children:t}){return e.isPending?(0,M.jsx)(V,{}):e.isError?(0,M.jsxs)(c,{children:[(0,M.jsx)(_,{"aria-hidden":`true`}),(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`strong`,{children:`Could not load report`}),(0,M.jsx)(`p`,{children:U(e.error)})]}),(0,M.jsx)(m,{type:`button`,onClick:()=>e.refetch(),children:`Retry report`})]}):t}function B(){return(0,M.jsxs)(`main`,{className:`session-page session-loading`,children:[(0,M.jsxs)(`div`,{role:`status`,"aria-label":`Loading run detail`,children:[(0,M.jsx)(`span`,{className:`sr-only`,children:`Loading run detail`}),(0,M.jsx)(A,{className:`session-heading-skeleton`}),(0,M.jsx)(A,{className:`session-subheading-skeleton`})]}),(0,M.jsx)(V,{})]})}function V(){return(0,M.jsxs)(`div`,{className:`report-loading`,"aria-label":`Loading report`,children:[(0,M.jsx)(A,{className:`summary-skeleton`}),Array.from({length:4},(e,t)=>(0,M.jsx)(A,{className:`chart-skeleton`},t))]})}function H(){return(0,M.jsxs)(`main`,{className:`empty-state`,children:[(0,M.jsx)(`h1`,{children:`Run not found`}),(0,M.jsx)(`p`,{children:`This run may have been removed, or the link may be incomplete.`}),(0,M.jsx)(f,{to:`/`,className:`button button-primary`,children:`Back to runs`})]})}function U(e){return e instanceof Error?e.message:`The request could not be completed.`}export{N as RunPage}; \ No newline at end of file diff --git a/web/dist/assets/session-page-BHtrUHcT.js b/web/dist/assets/session-page-BHtrUHcT.js deleted file mode 100644 index 37c3637..0000000 --- a/web/dist/assets/session-page-BHtrUHcT.js +++ /dev/null @@ -1 +0,0 @@ -import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"./risk-histogram-Bw31Zp4T.js";import{A as f,B as p,C as m,D as h,E as g,I as _,J as v,K as y,L as b,N as x,O as S,Q as C,R as ee,S as w,T,U as te,V as E,W as D,X as O,Y as ne,_ as k,b as A,c as re,d as j,f as ie,g as ae,l as M,p as N,t as P,tt as oe,u as se,v as ce,w as le,y as F}from"./index-NIa5ODC0.js";var I=oe(C(),1),L=O();function ue({page:e}){let[t,n]=(0,I.useState)(()=>new Set),[r,i]=ne(),a=pe(r.get(`page`),e.page),o=[...e.items].sort((e,t)=>Date.parse(t.sampled_at)-Date.parse(e.sampled_at)||t.sample_seq-e.sample_seq),s=Math.max(1,Math.ceil(e.total/e.page_size)),c=e=>{let t=new URLSearchParams(r);t.set(`tab`,`samples`),t.set(`page`,String(e)),i(t)};if(o.length===0&&e.total===0)return(0,L.jsx)(`p`,{className:`section-empty`,children:`Samples will appear after the first sampling interval completes.`});if(o.length===0)return(0,L.jsxs)(`div`,{className:`sample-empty-recovery`,children:[(0,L.jsxs)(`p`,{className:`section-empty`,children:[`Page `,e.page,` has no samples.`]}),(0,L.jsx)(`nav`,{className:`pagination`,"aria-label":`Sample pages`,children:(0,L.jsx)(S,{type:`button`,variant:`secondary`,size:`small`,onClick:()=>c(s),children:`Go to last page`})})]});let l=e=>{n(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})};return(0,L.jsxs)(`div`,{className:`sample-table-section`,children:[(0,L.jsx)(`div`,{className:`sample-table-wrap`,children:(0,L.jsxs)(`table`,{className:`table sample-table`,children:[(0,L.jsx)(`thead`,{children:(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`th`,{scope:`col`,children:`Sample`}),(0,L.jsx)(`th`,{scope:`col`,children:`Sampled at`}),(0,L.jsx)(`th`,{scope:`col`,children:`Probes`}),(0,L.jsx)(`th`,{scope:`col`,children:`Primary IP`}),(0,L.jsx)(`th`,{scope:`col`,children:`Distinct IPs`}),(0,L.jsx)(`th`,{scope:`col`,children:`Changed`}),(0,L.jsx)(`th`,{scope:`col`,children:`New IPs`}),(0,L.jsx)(`th`,{scope:`col`,children:`RTT min / med / max`}),(0,L.jsx)(`th`,{scope:`col`,children:`Category`}),(0,L.jsx)(`th`,{scope:`col`,children:`Risk`}),(0,L.jsx)(`th`,{scope:`col`,children:`Error`})]})}),o.map(e=>(0,L.jsx)(de,{sample:e,open:t.has(e.sample_seq),onToggle:()=>l(e.sample_seq)},e.sample_seq))]})}),(0,L.jsxs)(`nav`,{className:`pagination`,"aria-label":`Sample pages`,children:[(0,L.jsx)(S,{type:`button`,variant:`secondary`,size:`small`,disabled:a<=1,"aria-label":`Previous page`,onClick:()=>c(a-1),children:`Previous`}),(0,L.jsxs)(`span`,{className:`numeric`,children:[`Page `,e.page,` of `,s]}),(0,L.jsx)(S,{type:`button`,variant:`secondary`,size:`small`,disabled:a>=s,"aria-label":`Next page`,onClick:()=>c(a+1),children:`Next`})]})]})}function de({sample:e,open:t,onToggle:n}){return(0,L.jsx)(I.Fragment,{children:(0,L.jsxs)(`tbody`,{className:`sample-group`,children:[(0,L.jsxs)(`tr`,{className:`sample-parent-row`,children:[(0,L.jsx)(`th`,{scope:`row`,children:(0,L.jsxs)(`button`,{type:`button`,className:`sample-disclosure`,"aria-label":`Sample ${e.sample_seq} details`,"aria-expanded":t,"aria-controls":`sample-${e.sample_seq}-probes`,onClick:n,children:[t?(0,L.jsx)(D,{size:16,"aria-hidden":`true`}):(0,L.jsx)(r,{size:16,"aria-hidden":`true`}),(0,L.jsxs)(`span`,{children:[`Sample `,e.sample_seq]})]})}),(0,L.jsx)(`td`,{title:N(e.sampled_at),children:N(e.sampled_at)}),(0,L.jsxs)(`td`,{className:`numeric`,children:[e.probes_ok,` / `,e.probes_attempted]}),(0,L.jsx)(`td`,{className:`mono`,children:e.primary_ip??`—`}),(0,L.jsx)(`td`,{className:`numeric`,children:e.distinct_ips}),(0,L.jsx)(`td`,{children:(0,L.jsx)(`span`,{className:`badge ${e.ip_changed?`sample-change`:`sample-stable`}`,children:e.ip_changed?`Changed`:`Stable`})}),(0,L.jsx)(`td`,{className:`numeric`,children:e.new_ips}),(0,L.jsxs)(`td`,{className:`numeric`,children:[j(e.rtt_min_ms),` / `,j(e.rtt_med_ms),` / `,j(e.rtt_max_ms)]}),(0,L.jsx)(`td`,{className:`capitalize`,children:e.primary_category||`unknown`}),(0,L.jsx)(`td`,{className:`numeric`,children:e.primary_risk}),(0,L.jsx)(`td`,{className:`compact-cell`,title:e.error||void 0,children:e.error||`—`})]}),t&&Array.from({length:Math.max(0,e.probes_attempted)},(t,n)=>(0,L.jsx)(fe,{sample:e,index:n},n))]})})}function fe({sample:e,index:t}){let n=e.probe_ok[t]??!1,r=e.probe_ips[t]??`—`,i=e.probe_rtts_ms[t];return(0,L.jsxs)(`tr`,{id:t===0?`sample-${e.sample_seq}-probes`:void 0,className:`probe-row`,"aria-label":`Probe ${t} for sample ${e.sample_seq}`,children:[(0,L.jsxs)(`th`,{scope:`row`,children:[`Probe `,t]}),(0,L.jsx)(`td`,{children:n?`Succeeded`:`Failed`}),(0,L.jsx)(`td`,{className:`mono`,children:r}),(0,L.jsx)(`td`,{className:`numeric`,children:j(n&&Number.isFinite(i)?i:null)}),(0,L.jsx)(`td`,{colSpan:7,children:n?`—`:e.error||`Probe did not complete.`})]})}function pe(e,t){let n=Number(e);return Number.isSafeInteger(n)&&n>0?n:t}function me({data:t}){if(t.holds.length===0)return(0,L.jsx)(i,{title:`Stickiness`,children:(0,L.jsx)(e,{children:`Stickiness segments appear after an IP has been observed.`})});let n=t.holds.map(e=>Date.parse(e.started_at)).filter(Number.isFinite),r=t.holds.map(e=>Date.parse(e.ended_at)).filter(Number.isFinite),a=Math.min(...n),o=Math.max(...r),s=Math.max(1,o-a);return(0,L.jsxs)(i,{title:`Stickiness`,children:[(0,L.jsxs)(`p`,{className:`chart-summary`,children:[`Hold segments show `,t.holds.length,` observed IP runs; the median hold was `,M(t.median_hold_seconds),` and the average was `,M(t.average_hold_seconds),`.`]}),(0,L.jsx)(`div`,{className:`stickiness-track`,role:`img`,"aria-label":`${t.holds.length} separate IP hold segments, not a continuous measurement line`,children:t.holds.map((e,t)=>{let n=Date.parse(e.started_at),r=Date.parse(e.ended_at),i=Number.isFinite(n)?(n-a)/s*100:0,o=Number.isFinite(r)&&Number.isFinite(n)?Math.max(1.5,(r-n)/s*100):1.5;return(0,L.jsx)(`span`,{className:`hold-segment`,tabIndex:0,style:{left:`${Math.max(0,i)}%`,width:`${Math.min(100-Math.max(0,i),o)}%`},"aria-label":`${e.ip}, ${e.samples} samples, held ${M(e.duration_seconds)}, from ${N(e.started_at)} to ${N(e.ended_at)}`},`${e.ip}-${e.started_at}-${t}`)})}),(0,L.jsxs)(`div`,{className:`stickiness-scale`,"aria-hidden":`true`,children:[(0,L.jsx)(`span`,{children:N(t.holds[0]?.started_at)}),(0,L.jsx)(`span`,{children:N(t.holds.at(-1)?.ended_at)})]}),(0,L.jsxs)(`details`,{className:`chart-data`,children:[(0,L.jsx)(`summary`,{children:`View stickiness data`}),(0,L.jsx)(`div`,{className:`chart-data-scroll`,children:(0,L.jsxs)(`table`,{children:[(0,L.jsx)(`caption`,{className:`sr-only`,children:`IP hold segments`}),(0,L.jsx)(`thead`,{children:(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`th`,{scope:`col`,children:`IP`}),(0,L.jsx)(`th`,{scope:`col`,children:`Started`}),(0,L.jsx)(`th`,{scope:`col`,children:`Ended`}),(0,L.jsx)(`th`,{scope:`col`,children:`Samples`}),(0,L.jsx)(`th`,{scope:`col`,children:`Duration`})]})}),(0,L.jsx)(`tbody`,{children:t.holds.map((e,t)=>(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{className:`mono`,children:e.ip}),(0,L.jsx)(`td`,{children:N(e.started_at)}),(0,L.jsx)(`td`,{children:N(e.ended_at)}),(0,L.jsx)(`td`,{children:e.samples}),(0,L.jsx)(`td`,{children:M(e.duration_seconds)})]},`${e.ip}-${t}`))})]})})]})]})}function he({session:e}){return(0,L.jsx)(`dl`,{className:`summary-strip`,role:`region`,"aria-label":`Session summary`,children:[[`Success rate`,ie(e.success_rate)],[`Median RTT`,j(e.last_rtt_ms)],[`Distinct IPs`,new Intl.NumberFormat().format(e.distinct_ips)],[`Samples`,new Intl.NumberFormat().format(e.samples_taken)],[`Last IP`,se(e.last_primary_ip,e.last_primary_category)],[`Last sample`,N(e.last_sample_at)]].map(([e,t])=>(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`dt`,{children:e}),(0,L.jsx)(`dd`,{className:e===`Last IP`?`mono`:`numeric`,children:t})]},e))})}function R(e,t){return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0}var ge={country:{label:`Country`,category:`geo`},cc:{label:`Country`,category:`geo`},region:{label:`Region`,category:`geo`},state:{label:`State`,category:`geo`},st:{label:`State`,category:`geo`},city:{label:`City`,category:`geo`},session:{label:`Session`,category:`session`},sess:{label:`Session`,category:`session`},sid:{label:`Session`,category:`session`},sticky:{label:`Sticky`,category:`session`},rotate:{label:`Rotation`,category:`session`},rotating:{label:`Rotation`,category:`session`},ttl:{label:`Session TTL`,category:`session`},sesstime:{label:`Session TTL`,category:`session`},zone:{label:`Network type`,category:`network`},type:{label:`Network type`,category:`network`},isp:{label:`ISP`,category:`network`},asn:{label:`ASN`,category:`network`}},_e={cc:`country`,st:`state`,sess:`session`,sid:`session`,rotating:`rotate`,sesstime:`ttl`,zone:`type`};function ve(e){if(!e)return{attributes:[],raw:[]};let t=e.split(/[-_:]+/).filter(e=>e.length>0),n=[],r=[];for(let e=0;ee.key===t)}function ye(e){if(e.length===0)return;let t=new Map,n=0;for(let r of e){if(!r.country)continue;let e=r.hit_count>0?r.hit_count:1;t.set(r.country,(t.get(r.country)??0)+e),n+=e}if(n===0)return;let[r,i]=[...t.entries()].sort((e,t)=>t[1]-e[1])[0];return{code:r,share:i/n}}function be(e){if(e.length===0)return;let t=new Map;for(let n of e){if(!n.isp)continue;let e=n.hit_count>0?n.hit_count:1;t.set(n.isp,(t.get(n.isp)??0)+e)}if(t.size!==0)return[...t.entries()].sort((e,t)=>t[1]-e[1])[0][0]}function xe(e){let t=e.pool_composition,n=[[`mobile`,t.mobile],[`residential`,t.residential],[`datacenter`,t.datacenter],[`unknown`,t.unknown]],r=n.reduce((e,[,t])=>e+t,0);if(r===0)return;let[i,a]=n.sort((e,t)=>t[1]-e[1])[0];return{type:i,share:a/r}}var Se={resi:`residential`,residential:`residential`,res:`residential`,mob:`mobile`,mobile:`mobile`,dc:`datacenter`,datacenter:`datacenter`,dch:`datacenter`};function Ce(e){return`${Math.round(e*100)}%`}function we(e,t){let n=[],r=z(e,`country`);if(r){let e=r.value.toUpperCase(),i=t?ye(t.ips):void 0;n.push(i?{label:`Country`,requested:e,observed:`${i.code} (${Ce(i.share)})`,verdict:i.code.toUpperCase()===e?i.share>=.9?`match`:`partial`:`mismatch`}:{label:`Country`,requested:e,observed:`—`,verdict:`unknown`})}let i=z(e,`type`);if(i){let e=R(Se,i.value.toLowerCase())??i.value.toLowerCase(),r=t?xe(t):void 0;n.push(r?{label:`Network type`,requested:e,observed:`${r.type} (${Ce(r.share)})`,verdict:r.type===e?r.share>=.6?`match`:`partial`:`mismatch`}:{label:`Network type`,requested:e,observed:`—`,verdict:`unknown`})}for(let t of[`region`,`state`,`city`]){let r=z(e,t);r&&n.push({label:r.label,requested:r.value,observed:`—`,verdict:`unknown`})}let a=z(e,`isp`);if(a){let e=t?be(t.ips)??``:``;n.push({label:`ISP`,requested:a.value,observed:e||`—`,verdict:e&&e.toLowerCase().includes(a.value.toLowerCase())?`match`:e?`mismatch`:`unknown`})}return n}function Te({session:e,report:t}){let n=ve(e.proxy_username);if(n.attributes.length===0&&n.raw.length===0)return(0,L.jsxs)(`section`,{className:`report-section targeting-panel`,children:[(0,L.jsx)(`h2`,{children:`Targeting`}),(0,L.jsx)(`p`,{className:`muted`,children:`No username on this proxy, so no targeting attributes are available.`})]});let r=we(n,t);return(0,L.jsxs)(`section`,{className:`report-section targeting-panel`,children:[(0,L.jsx)(`h2`,{children:`Targeting`}),(0,L.jsxs)(`div`,{className:`targeting-chips`,children:[[[`geo`,`Geo`],[`session`,`Session`],[`network`,`Network`],[`other`,`Other`]].map(([e,t])=>{let r=n.attributes.filter(t=>t.category===e);return r.length===0?null:(0,L.jsxs)(`div`,{className:`targeting-group`,children:[(0,L.jsx)(`span`,{className:`targeting-group-label`,children:t}),r.map(e=>(0,L.jsxs)(`span`,{className:`chip`,children:[(0,L.jsx)(`strong`,{children:e.label}),` `,e.value]},`${e.key}-${e.value}`))]},e)}),n.raw.length>0&&(0,L.jsxs)(`div`,{className:`targeting-group`,children:[(0,L.jsx)(`span`,{className:`targeting-group-label`,children:`Unparsed`}),n.raw.map((e,t)=>(0,L.jsx)(`span`,{className:`chip mono`,children:e},`${e}-${t}`))]})]}),r.length>0&&(0,L.jsxs)(`table`,{className:`targeting-comparison`,children:[(0,L.jsx)(`thead`,{children:(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`th`,{children:`Attribute`}),(0,L.jsx)(`th`,{children:`Requested`}),(0,L.jsx)(`th`,{children:`Observed`}),(0,L.jsx)(`th`,{children:`Result`})]})}),(0,L.jsx)(`tbody`,{children:r.map(e=>(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{children:e.label}),(0,L.jsx)(`td`,{className:`mono`,children:e.requested}),(0,L.jsx)(`td`,{className:`mono`,children:e.observed}),(0,L.jsx)(`td`,{children:(0,L.jsx)(`span`,{className:`verdict verdict-${e.verdict}`,children:e.verdict})})]},e.label))})]})]})}function Ee(e){let t=e+`CollectionProvider`,[n,r]=T(t),[i,a]=n(t,{collectionRef:{current:null},itemMap:new Map}),o=e=>{let{scope:t,children:n}=e,r=I.useRef(null),a=I.useRef(new Map).current;return(0,L.jsx)(i,{scope:t,itemMap:a,collectionRef:r,children:n})};o.displayName=t;let s=e+`CollectionSlot`,c=A(s),l=I.forwardRef((e,t)=>{let{scope:n,children:r}=e,i=w(t,a(s,n).collectionRef);return(0,L.jsx)(c,{ref:i,children:r})});l.displayName=s;let u=e+`CollectionItemSlot`,d=`data-radix-collection-item`,f=A(u),p=I.forwardRef((e,t)=>{let{scope:n,children:r,...i}=e,o=I.useRef(null),s=w(t,o),c=a(u,n);return I.useEffect(()=>(c.itemMap.set(o,{ref:o,...i}),()=>void c.itemMap.delete(o))),(0,L.jsx)(f,{[d]:``,ref:s,children:r})});p.displayName=u;function m(t){let n=a(e+`CollectionConsumer`,t);return I.useCallback(()=>{let e=n.collectionRef.current;if(!e)return[];let t=Array.from(e.querySelectorAll(`[${d}]`));return Array.from(n.itemMap.values()).sort((e,n)=>t.indexOf(e.ref.current)-t.indexOf(n.ref.current))},[n.collectionRef,n.itemMap])}return[{Provider:o,Slot:l,ItemSlot:p},m,r]}var De=I.createContext(void 0);function Oe(e){let t=I.useContext(De);return e||t||`ltr`}var B=!1;function ke(){let[e,t]=I.useState(B);return I.useEffect(()=>{B||(B=!0,t(!0))},[]),e}var Ae=I.useSyncExternalStore;function je(){return()=>{}}function Me(){return Ae(je,()=>!0,()=>!1)}var Ne=typeof Ae==`function`?Me:ke,Pe=Object.defineProperty,V=(e,t)=>Pe(e,`name`,{value:t,configurable:!0}),H=`rovingFocusGroup.onEntryFocus`,Fe={bubbles:!1,cancelable:!0},U=`RovingFocusGroup`,[W,Ie,Le]=Ee(U),[Re,ze]=T(U,[Le]),[Be,Ve]=Re(U),He=I.forwardRef(V(function(e,t){return(0,L.jsx)(W.Provider,{scope:e.__scopeRovingFocusGroup,children:(0,L.jsx)(W.Slot,{scope:e.__scopeRovingFocusGroup,children:(0,L.jsx)(Ue,{...e,ref:t})})})},`RovingFocusGroup`)),Ue=I.forwardRef(V(function(e,t){let{__scopeRovingFocusGroup:n,orientation:r,loop:i=!1,dir:a,currentTabStopId:o,defaultCurrentTabStopId:s,onCurrentTabStopIdChange:c,onEntryFocus:l,preventScrollOnEntryFocus:u=!1,...d}=e,f=I.useRef(null),p=w(t,f),h=Oe(a),[_,v]=m({prop:o,defaultProp:s??null,onChange:c,caller:U}),[y,b]=I.useState(!1),x=ae(l),S=Ie(n),C=I.useRef(!1),[ee,T]=I.useState(0);return I.useEffect(()=>{let e=f.current;if(e)return e.addEventListener(H,x),()=>e.removeEventListener(H,x)},[x]),(0,L.jsx)(Be,{scope:n,orientation:r,dir:h,loop:i,currentTabStopId:_,onItemFocus:I.useCallback(e=>v(e),[v]),onItemShiftTab:I.useCallback(()=>b(!0),[]),onFocusableItemAdd:I.useCallback(()=>T(e=>e+1),[]),onFocusableItemRemove:I.useCallback(()=>T(e=>e-1),[]),children:(0,L.jsx)(F.div,{tabIndex:y||ee===0?-1:0,"data-orientation":r,...d,ref:p,style:{outline:`none`,...e.style},onMouseDown:g(e.onMouseDown,()=>{C.current=!0}),onFocus:g(e.onFocus,e=>{let t=!C.current;if(e.target===e.currentTarget&&t&&!y){let t=new CustomEvent(H,Fe);if(e.currentTarget.dispatchEvent(t),!t.defaultPrevented){let e=S().filter(e=>e.focusable);G([e.find(e=>e.active),e.find(e=>e.id===_),...e].filter(Boolean).map(e=>e.ref.current),u)}}C.current=!1}),onBlur:g(e.onBlur,()=>b(!1))})})},`RovingFocusGroupImpl`)),We=`RovingFocusGroupItem`,Ge=I.forwardRef(V(function(e,t){let{__scopeRovingFocusGroup:n,focusable:r=!0,active:i=!1,tabStopId:a,children:o,...s}=e,c=k(),l=a||c,u=Ve(We,n),d=u.currentTabStopId===l,f=Ie(n),{onFocusableItemAdd:p,onFocusableItemRemove:m,currentTabStopId:h}=u,_=Ne();return le(()=>{if(!(!_||!r))return p(),()=>m()},[_,r,p,m]),I.useEffect(()=>{if(!(_||!r))return p(),()=>m()},[_,r,p,m]),(0,L.jsx)(W.ItemSlot,{scope:n,id:l,focusable:r,active:i,children:(0,L.jsx)(F.span,{tabIndex:d?0:-1,"data-orientation":u.orientation,...s,ref:t,onMouseDown:g(e.onMouseDown,e=>{r?u.onItemFocus(l):e.preventDefault()}),onFocus:g(e.onFocus,()=>u.onItemFocus(l)),onKeyDown:g(e.onKeyDown,e=>{if(e.key===`Tab`&&e.shiftKey){u.onItemShiftTab();return}if(e.target!==e.currentTarget)return;let t=Je(e,u.orientation,u.dir);if(t!==void 0){if(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)return;e.preventDefault();let n=f().filter(e=>e.focusable).map(e=>e.ref.current);if(t===`last`)n.reverse();else if(t===`prev`||t===`next`){t===`prev`&&n.reverse();let r=n.indexOf(e.currentTarget);n=u.loop?Ye(n,r+1):n.slice(r+1)}setTimeout(()=>G(n))}}),children:typeof o==`function`?o({isCurrentTabStop:d,hasTabStop:h!=null}):o})})},`RovingFocusGroupItem`)),Ke={ArrowLeft:`prev`,ArrowUp:`prev`,ArrowRight:`next`,ArrowDown:`next`,PageUp:`first`,Home:`first`,PageDown:`last`,End:`last`};function qe(e,t){return t===`rtl`?e===`ArrowLeft`?`ArrowRight`:e===`ArrowRight`?`ArrowLeft`:e:e}V(qe,`getDirectionAwareKey`);function Je(e,t,n){let r=qe(e.key,n);if(!(t===`vertical`&&[`ArrowLeft`,`ArrowRight`].includes(r))&&!(t===`horizontal`&&[`ArrowUp`,`ArrowDown`].includes(r)))return Ke[r]}V(Je,`getFocusIntent`);function G(e,t=!1){let n=document.activeElement;for(let r of e)if(r===n||(r.focus({preventScroll:t}),document.activeElement!==n))return}V(G,`focusFirst`);function Ye(e,t){return e.map((n,r)=>e[(t+r)%e.length])}V(Ye,`wrapArray`);var Xe=He,Ze=Ge,Qe=Object.defineProperty,K=(e,t)=>Qe(e,`name`,{value:t,configurable:!0}),q=`Tabs`,[$e,et]=T(q,[ze]),tt=ze(),[nt,J]=$e(q),rt=I.forwardRef(K(function(e,t){let{__scopeTabs:n,value:r,onValueChange:i,defaultValue:a,orientation:o=`horizontal`,dir:s,activationMode:c=`automatic`,...l}=e,u=Oe(s),[d,f]=m({prop:r,onChange:i,defaultProp:a??``,caller:q});return(0,L.jsx)(nt,{scope:n,baseId:k(),value:d,onValueChange:f,orientation:o,dir:u,activationMode:c,children:(0,L.jsx)(F.div,{dir:u,"data-orientation":o,...l,ref:t})})},`Tabs`)),it=`TabsList`,at=I.forwardRef(K(function(e,t){let{__scopeTabs:n,loop:r=!0,...i}=e,a=J(it,n),o=tt(n);return(0,L.jsx)(Xe,{asChild:!0,...o,orientation:a.orientation,dir:a.dir,loop:r,children:(0,L.jsx)(F.div,{role:`tablist`,"aria-orientation":a.orientation,...i,ref:t})})},`TabsList`)),ot=`TabsTrigger`,st=I.forwardRef(K(function(e,t){let{__scopeTabs:n,value:r,disabled:i=!1,...a}=e,o=J(ot,n),s=tt(n),c=Y(o.baseId,r),l=X(o.baseId,r),u=r===o.value;return(0,L.jsx)(Ze,{asChild:!0,...s,focusable:!i,active:u,children:(0,L.jsx)(F.button,{type:`button`,role:`tab`,"aria-selected":u,"aria-controls":l,"data-state":u?`active`:`inactive`,"data-disabled":i?``:void 0,disabled:i,id:c,...a,ref:t,onMouseDown:g(e.onMouseDown,e=>{!i&&e.button===0&&e.ctrlKey===!1?o.onValueChange(r):e.preventDefault()}),onKeyDown:g(e.onKeyDown,e=>{i||e.target!==e.currentTarget||[` `,`Enter`].includes(e.key)&&o.onValueChange(r)}),onFocus:g(e.onFocus,()=>{let e=o.activationMode!==`manual`;!u&&!i&&e&&o.onValueChange(r)})})})},`TabsTrigger`)),ct=`TabsContent`,lt=I.forwardRef(K(function(e,t){let{__scopeTabs:n,value:r,forceMount:i,children:a,...o}=e,s=J(ct,n),c=Y(s.baseId,r),l=X(s.baseId,r),u=r===s.value,d=I.useRef(u);return I.useEffect(()=>{let e=requestAnimationFrame(()=>d.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,L.jsx)(ce,{present:i||u,children:({present:n})=>(0,L.jsx)(F.div,{"data-state":u?`active`:`inactive`,"data-orientation":s.orientation,role:`tabpanel`,"aria-labelledby":c,hidden:!n,id:l,tabIndex:0,...o,ref:t,style:{...e.style,animationDuration:d.current?`0s`:void 0},children:n&&a})})},`TabsContent`));function Y(e,t){return`${e}-trigger-${t}`}K(Y,`makeTriggerId`);function X(e,t){return`${e}-content-${t}`}K(X,`makeContentId`);var ut=rt,dt=at,ft=st,pt=lt,mt=ut,ht=dt,Z=ft,Q=pt;function gt(){let{id:e=``}=v(),[r,i]=ne(),m=r.get(`tab`),g=m===`reputation`||m===`samples`?m:`overview`,C=St(r.get(`page`)),w=_(e),T=w.data?.status===`running`,D=b(e,T),O=ee(e,C,g===`samples`,T),k=p(),A=x();return w.isPending?(0,L.jsx)(vt,{includeSamples:g===`samples`}):w.error instanceof f&&w.error.status===404?(0,L.jsx)(xt,{}):w.isError||!w.data?(0,L.jsxs)(`div`,{className:`session-page`,children:[(0,L.jsxs)(h,{className:`error-state`,children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not load session`}),(0,L.jsx)(`p`,{children:$(w.error)})]}),(0,L.jsx)(S,{type:`button`,onClick:()=>w.refetch(),children:`Retry`})]}),(0,L.jsx)(y,{to:`/`,className:`back-link`,children:`Back to sessions`})]}):(0,L.jsxs)(`main`,{className:`session-page`,children:[(0,L.jsx)(y,{to:`/`,className:`breadcrumb`,children:`Sessions`}),(0,L.jsxs)(`header`,{className:`session-header`,children:[(0,L.jsxs)(`div`,{className:`session-title`,children:[(0,L.jsxs)(`div`,{className:`session-title-line`,children:[(0,L.jsx)(`h1`,{children:w.data.name}),(0,L.jsx)(re,{status:w.data.status})]}),(0,L.jsxs)(`p`,{children:[(0,L.jsx)(`span`,{className:`mono`,children:w.data.proxy_display}),(0,L.jsx)(`span`,{"aria-hidden":`true`,children:` · `}),(0,L.jsx)(`span`,{children:w.data.mode===`sticky`?`Sticky`:`Pool`})]})]}),(0,L.jsxs)(`div`,{className:`session-actions`,children:[w.data.status===`running`&&(0,L.jsxs)(S,{type:`button`,variant:`danger`,onClick:()=>{window.confirm(`Stop “${w.data.name}”? You can re-enable it later.`)&&k.mutate(e)},disabled:k.isPending,children:[(0,L.jsx)(te,{size:14,fill:`currentColor`,"aria-hidden":`true`}),k.isPending?`Stopping…`:`Stop session`]}),w.data.status!==`running`&&(0,L.jsxs)(S,{type:`button`,onClick:()=>{window.confirm(`Re-enable “${w.data.name}”? Sampling resumes; progress counters reset while prior samples are kept.`)&&A.mutate(e)},disabled:A.isPending,children:[(0,L.jsx)(d,{size:14,"aria-hidden":`true`}),A.isPending?`Re-enabling…`:`Re-enable`]}),(0,L.jsxs)(`a`,{className:`button button-secondary`,href:`/api/sessions/${e}/export.csv`,download:!0,children:[(0,L.jsx)(n,{size:16,"aria-hidden":`true`}),`Export CSV`]})]})]}),k.isError&&(0,L.jsxs)(h,{className:`inline-alert`,children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not stop session`}),(0,L.jsx)(`p`,{children:$(k.error)})]})]}),A.isError&&(0,L.jsxs)(h,{className:`inline-alert`,children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not re-enable session`}),(0,L.jsx)(`p`,{children:$(A.error)})]})]}),(0,L.jsx)(he,{session:w.data}),(0,L.jsx)(`div`,{className:`report-meta`,"aria-live":`polite`,children:D.dataUpdatedAt>0?`Last updated ${N(new Date(D.dataUpdatedAt).toISOString())}`:`Waiting for report update`}),(0,L.jsxs)(mt,{className:`report-tabs`,value:g,onValueChange:e=>{if(e!==`overview`&&e!==`reputation`&&e!==`samples`)return;let t=new URLSearchParams(r);t.set(`tab`,e),e===`samples`?t.has(`page`)||t.set(`page`,`1`):t.delete(`page`),i(t)},children:[(0,L.jsxs)(ht,{className:`tabs-list`,"aria-label":`Session report views`,children:[(0,L.jsx)(Z,{className:`tab-trigger`,value:`overview`,children:`Overview`}),(0,L.jsx)(Z,{className:`tab-trigger`,value:`reputation`,children:`Reputation`}),(0,L.jsx)(Z,{className:`tab-trigger`,value:`samples`,children:`Samples`})]}),(0,L.jsxs)(Q,{className:`tab-content`,value:`overview`,children:[(0,L.jsx)(Te,{session:w.data,report:D.data}),(0,L.jsx)(_t,{report:D,children:D.data&&(0,L.jsxs)(`div`,{className:`report-grid`,children:[(0,L.jsx)(t,{data:D.data.series}),(0,L.jsx)(s,{data:D.data.series}),(0,L.jsx)(o,{data:D.data.series}),(0,L.jsx)(c,{data:D.data.pool_composition}),(0,L.jsx)(me,{data:D.data.stickiness}),(0,L.jsx)(l,{data:D.data.pool_growth})]})})]}),(0,L.jsx)(Q,{className:`tab-content`,value:`reputation`,children:(0,L.jsx)(_t,{report:D,children:D.data&&(0,L.jsxs)(L.Fragment,{children:[(0,L.jsxs)(`div`,{className:`reputation-summary`,"aria-label":`Reputation summary`,children:[(0,L.jsxs)(`span`,{children:[(0,L.jsx)(`strong`,{children:D.data.reputation_summary.total_ips}),` observed IPs`]}),(0,L.jsxs)(`span`,{children:[(0,L.jsx)(`strong`,{children:D.data.reputation_summary.flagged_ips}),` flagged (`,ie(D.data.reputation_summary.flagged_percent/100),`)`]}),(0,L.jsxs)(`span`,{children:[(0,L.jsx)(`strong`,{children:D.data.reputation_summary.dnsbl_hit_ips}),` DNSBL hits`]})]}),(0,L.jsx)(u,{data:D.data.risk_histogram}),(0,L.jsxs)(`section`,{className:`report-section`,children:[(0,L.jsx)(`h2`,{children:`IP reputation`}),(0,L.jsx)(a,{rows:D.data.ips})]})]})})}),(0,L.jsx)(Q,{className:`tab-content`,value:`samples`,children:(0,L.jsxs)(`section`,{className:`report-section`,children:[(0,L.jsx)(`h2`,{children:`Sample history`}),O.isPending?(0,L.jsx)(bt,{}):O.isError?(0,L.jsxs)(h,{children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not load samples`}),(0,L.jsx)(`p`,{children:$(O.error)})]}),(0,L.jsx)(S,{type:`button`,onClick:()=>O.refetch(),children:`Retry samples`})]}):O.data&&(0,L.jsx)(ue,{page:O.data})]})})]})]})}function _t({report:e,children:t}){return e.isPending?(0,L.jsx)(yt,{}):e.isError?(0,L.jsxs)(h,{children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not load report`}),(0,L.jsx)(`p`,{children:$(e.error)})]}),(0,L.jsx)(S,{type:`button`,onClick:()=>e.refetch(),children:`Retry report`})]}):t}function vt({includeSamples:e}){return(0,L.jsxs)(`main`,{className:`session-page session-loading`,children:[(0,L.jsxs)(`div`,{role:`status`,"aria-label":`Loading session detail`,children:[(0,L.jsx)(`span`,{className:`sr-only`,children:`Loading session detail`}),(0,L.jsx)(P,{className:`session-heading-skeleton`}),(0,L.jsx)(P,{className:`session-subheading-skeleton`})]}),(0,L.jsx)(yt,{}),e&&(0,L.jsx)(bt,{})]})}function yt(){return(0,L.jsxs)(`div`,{className:`report-loading`,"aria-label":`Loading report`,children:[(0,L.jsx)(P,{className:`summary-skeleton`}),Array.from({length:4},(e,t)=>(0,L.jsx)(P,{className:`chart-skeleton`},t))]})}function bt(){return(0,L.jsxs)(`div`,{className:`sample-loading`,"aria-label":`Loading samples`,children:[(0,L.jsx)(P,{className:`sample-heading-skeleton`}),Array.from({length:4},(e,t)=>(0,L.jsx)(P,{className:`sample-row-skeleton`},t))]})}function xt(){return(0,L.jsxs)(`main`,{className:`empty-state`,children:[(0,L.jsx)(`h1`,{children:`Session not found`}),(0,L.jsx)(`p`,{children:`This session may have been removed, or the link may be incomplete.`}),(0,L.jsx)(y,{to:`/`,className:`button button-primary`,children:`Back to sessions`})]})}function St(e){let t=Number(e);return Number.isSafeInteger(t)&&t>0?t:1}function $(e){return e instanceof Error?e.message:`The request could not be completed.`}export{gt as SessionPage}; \ No newline at end of file diff --git a/web/dist/assets/session-page-DwoLWZj3.js b/web/dist/assets/session-page-DwoLWZj3.js new file mode 100644 index 0000000..12af090 --- /dev/null +++ b/web/dist/assets/session-page-DwoLWZj3.js @@ -0,0 +1 @@ +import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"./risk-histogram-dP0_I5OY.js";import{A as f,B as p,C as m,D as h,E as g,I as _,J as v,K as y,L as b,N as x,O as S,Q as C,R as ee,S as w,T,U as te,V as E,W as D,X as O,Y as ne,_ as k,b as A,c as re,d as j,f as ie,g as ae,l as M,p as N,t as P,tt as oe,u as se,v as ce,w as le,y as F}from"./index-D1U5YqHo.js";var I=oe(C(),1),L=O();function ue({page:e}){let[t,n]=(0,I.useState)(()=>new Set),[r,i]=ne(),a=pe(r.get(`page`),e.page),o=[...e.items].sort((e,t)=>Date.parse(t.sampled_at)-Date.parse(e.sampled_at)||t.sample_seq-e.sample_seq),s=Math.max(1,Math.ceil(e.total/e.page_size)),c=e=>{let t=new URLSearchParams(r);t.set(`tab`,`samples`),t.set(`page`,String(e)),i(t)};if(o.length===0&&e.total===0)return(0,L.jsx)(`p`,{className:`section-empty`,children:`Samples will appear after the first sampling interval completes.`});if(o.length===0)return(0,L.jsxs)(`div`,{className:`sample-empty-recovery`,children:[(0,L.jsxs)(`p`,{className:`section-empty`,children:[`Page `,e.page,` has no samples.`]}),(0,L.jsx)(`nav`,{className:`pagination`,"aria-label":`Sample pages`,children:(0,L.jsx)(S,{type:`button`,variant:`secondary`,size:`small`,onClick:()=>c(s),children:`Go to last page`})})]});let l=e=>{n(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})};return(0,L.jsxs)(`div`,{className:`sample-table-section`,children:[(0,L.jsx)(`div`,{className:`sample-table-wrap`,children:(0,L.jsxs)(`table`,{className:`table sample-table`,children:[(0,L.jsx)(`thead`,{children:(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`th`,{scope:`col`,children:`Sample`}),(0,L.jsx)(`th`,{scope:`col`,children:`Sampled at`}),(0,L.jsx)(`th`,{scope:`col`,children:`Probes`}),(0,L.jsx)(`th`,{scope:`col`,children:`Primary IP`}),(0,L.jsx)(`th`,{scope:`col`,children:`Distinct IPs`}),(0,L.jsx)(`th`,{scope:`col`,children:`Changed`}),(0,L.jsx)(`th`,{scope:`col`,children:`New IPs`}),(0,L.jsx)(`th`,{scope:`col`,children:`RTT min / med / max`}),(0,L.jsx)(`th`,{scope:`col`,children:`Category`}),(0,L.jsx)(`th`,{scope:`col`,children:`Risk`}),(0,L.jsx)(`th`,{scope:`col`,children:`Error`})]})}),o.map(e=>(0,L.jsx)(de,{sample:e,open:t.has(e.sample_seq),onToggle:()=>l(e.sample_seq)},e.sample_seq))]})}),(0,L.jsxs)(`nav`,{className:`pagination`,"aria-label":`Sample pages`,children:[(0,L.jsx)(S,{type:`button`,variant:`secondary`,size:`small`,disabled:a<=1,"aria-label":`Previous page`,onClick:()=>c(a-1),children:`Previous`}),(0,L.jsxs)(`span`,{className:`numeric`,children:[`Page `,e.page,` of `,s]}),(0,L.jsx)(S,{type:`button`,variant:`secondary`,size:`small`,disabled:a>=s,"aria-label":`Next page`,onClick:()=>c(a+1),children:`Next`})]})]})}function de({sample:e,open:t,onToggle:n}){return(0,L.jsx)(I.Fragment,{children:(0,L.jsxs)(`tbody`,{className:`sample-group`,children:[(0,L.jsxs)(`tr`,{className:`sample-parent-row`,children:[(0,L.jsx)(`th`,{scope:`row`,children:(0,L.jsxs)(`button`,{type:`button`,className:`sample-disclosure`,"aria-label":`Sample ${e.sample_seq} details`,"aria-expanded":t,"aria-controls":`sample-${e.sample_seq}-probes`,onClick:n,children:[t?(0,L.jsx)(D,{size:16,"aria-hidden":`true`}):(0,L.jsx)(r,{size:16,"aria-hidden":`true`}),(0,L.jsxs)(`span`,{children:[`Sample `,e.sample_seq]})]})}),(0,L.jsx)(`td`,{title:N(e.sampled_at),children:N(e.sampled_at)}),(0,L.jsxs)(`td`,{className:`numeric`,children:[e.probes_ok,` / `,e.probes_attempted]}),(0,L.jsx)(`td`,{className:`mono`,children:e.primary_ip??`—`}),(0,L.jsx)(`td`,{className:`numeric`,children:e.distinct_ips}),(0,L.jsx)(`td`,{children:(0,L.jsx)(`span`,{className:`badge ${e.ip_changed?`sample-change`:`sample-stable`}`,children:e.ip_changed?`Changed`:`Stable`})}),(0,L.jsx)(`td`,{className:`numeric`,children:e.new_ips}),(0,L.jsxs)(`td`,{className:`numeric`,children:[j(e.rtt_min_ms),` / `,j(e.rtt_med_ms),` / `,j(e.rtt_max_ms)]}),(0,L.jsx)(`td`,{className:`capitalize`,children:e.primary_category||`unknown`}),(0,L.jsx)(`td`,{className:`numeric`,children:e.primary_risk}),(0,L.jsx)(`td`,{className:`compact-cell`,title:e.error||void 0,children:e.error||`—`})]}),t&&Array.from({length:Math.max(0,e.probes_attempted)},(t,n)=>(0,L.jsx)(fe,{sample:e,index:n},n))]})})}function fe({sample:e,index:t}){let n=e.probe_ok[t]??!1,r=e.probe_ips[t]??`—`,i=e.probe_rtts_ms[t];return(0,L.jsxs)(`tr`,{id:t===0?`sample-${e.sample_seq}-probes`:void 0,className:`probe-row`,"aria-label":`Probe ${t} for sample ${e.sample_seq}`,children:[(0,L.jsxs)(`th`,{scope:`row`,children:[`Probe `,t]}),(0,L.jsx)(`td`,{children:n?`Succeeded`:`Failed`}),(0,L.jsx)(`td`,{className:`mono`,children:r}),(0,L.jsx)(`td`,{className:`numeric`,children:j(n&&Number.isFinite(i)?i:null)}),(0,L.jsx)(`td`,{colSpan:7,children:n?`—`:e.error||`Probe did not complete.`})]})}function pe(e,t){let n=Number(e);return Number.isSafeInteger(n)&&n>0?n:t}function me({data:t}){if(t.holds.length===0)return(0,L.jsx)(i,{title:`Stickiness`,children:(0,L.jsx)(e,{children:`Stickiness segments appear after an IP has been observed.`})});let n=t.holds.map(e=>Date.parse(e.started_at)).filter(Number.isFinite),r=t.holds.map(e=>Date.parse(e.ended_at)).filter(Number.isFinite),a=Math.min(...n),o=Math.max(...r),s=Math.max(1,o-a);return(0,L.jsxs)(i,{title:`Stickiness`,children:[(0,L.jsxs)(`p`,{className:`chart-summary`,children:[`Hold segments show `,t.holds.length,` observed IP runs; the median hold was `,M(t.median_hold_seconds),` and the average was `,M(t.average_hold_seconds),`.`]}),(0,L.jsx)(`div`,{className:`stickiness-track`,role:`img`,"aria-label":`${t.holds.length} separate IP hold segments, not a continuous measurement line`,children:t.holds.map((e,t)=>{let n=Date.parse(e.started_at),r=Date.parse(e.ended_at),i=Number.isFinite(n)?(n-a)/s*100:0,o=Number.isFinite(r)&&Number.isFinite(n)?Math.max(1.5,(r-n)/s*100):1.5;return(0,L.jsx)(`span`,{className:`hold-segment`,tabIndex:0,style:{left:`${Math.max(0,i)}%`,width:`${Math.min(100-Math.max(0,i),o)}%`},"aria-label":`${e.ip}, ${e.samples} samples, held ${M(e.duration_seconds)}, from ${N(e.started_at)} to ${N(e.ended_at)}`},`${e.ip}-${e.started_at}-${t}`)})}),(0,L.jsxs)(`div`,{className:`stickiness-scale`,"aria-hidden":`true`,children:[(0,L.jsx)(`span`,{children:N(t.holds[0]?.started_at)}),(0,L.jsx)(`span`,{children:N(t.holds.at(-1)?.ended_at)})]}),(0,L.jsxs)(`details`,{className:`chart-data`,children:[(0,L.jsx)(`summary`,{children:`View stickiness data`}),(0,L.jsx)(`div`,{className:`chart-data-scroll`,children:(0,L.jsxs)(`table`,{children:[(0,L.jsx)(`caption`,{className:`sr-only`,children:`IP hold segments`}),(0,L.jsx)(`thead`,{children:(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`th`,{scope:`col`,children:`IP`}),(0,L.jsx)(`th`,{scope:`col`,children:`Started`}),(0,L.jsx)(`th`,{scope:`col`,children:`Ended`}),(0,L.jsx)(`th`,{scope:`col`,children:`Samples`}),(0,L.jsx)(`th`,{scope:`col`,children:`Duration`})]})}),(0,L.jsx)(`tbody`,{children:t.holds.map((e,t)=>(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{className:`mono`,children:e.ip}),(0,L.jsx)(`td`,{children:N(e.started_at)}),(0,L.jsx)(`td`,{children:N(e.ended_at)}),(0,L.jsx)(`td`,{children:e.samples}),(0,L.jsx)(`td`,{children:M(e.duration_seconds)})]},`${e.ip}-${t}`))})]})})]})]})}function he({session:e}){return(0,L.jsx)(`dl`,{className:`summary-strip`,role:`region`,"aria-label":`Session summary`,children:[[`Success rate`,ie(e.success_rate)],[`Median RTT`,j(e.last_rtt_ms)],[`Distinct IPs`,new Intl.NumberFormat().format(e.distinct_ips)],[`Samples`,new Intl.NumberFormat().format(e.samples_taken)],[`Last IP`,se(e.last_primary_ip,e.last_primary_category)],[`Last sample`,N(e.last_sample_at)]].map(([e,t])=>(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`dt`,{children:e}),(0,L.jsx)(`dd`,{className:e===`Last IP`?`mono`:`numeric`,children:t})]},e))})}function R(e,t){return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0}var ge={country:{label:`Country`,category:`geo`},cc:{label:`Country`,category:`geo`},region:{label:`Region`,category:`geo`},state:{label:`State`,category:`geo`},st:{label:`State`,category:`geo`},city:{label:`City`,category:`geo`},session:{label:`Session`,category:`session`},sess:{label:`Session`,category:`session`},sid:{label:`Session`,category:`session`},sticky:{label:`Sticky`,category:`session`},rotate:{label:`Rotation`,category:`session`},rotating:{label:`Rotation`,category:`session`},ttl:{label:`Session TTL`,category:`session`},sesstime:{label:`Session TTL`,category:`session`},zone:{label:`Network type`,category:`network`},type:{label:`Network type`,category:`network`},isp:{label:`ISP`,category:`network`},asn:{label:`ASN`,category:`network`}},_e={cc:`country`,st:`state`,sess:`session`,sid:`session`,rotating:`rotate`,sesstime:`ttl`,zone:`type`};function ve(e){if(!e)return{attributes:[],raw:[]};let t=e.split(/[-_:]+/).filter(e=>e.length>0),n=[],r=[];for(let e=0;ee.key===t)}function ye(e){if(e.length===0)return;let t=new Map,n=0;for(let r of e){if(!r.country)continue;let e=r.country.toUpperCase(),i=r.hit_count>0?r.hit_count:1;t.set(e,(t.get(e)??0)+i),n+=i}if(n===0)return;let[r,i]=[...t.entries()].sort((e,t)=>t[1]-e[1])[0];return{code:r,share:i/n}}function be(e){if(e.length===0)return;let t=new Map;for(let n of e){if(!n.isp)continue;let e=n.hit_count>0?n.hit_count:1;t.set(n.isp,(t.get(n.isp)??0)+e)}if(t.size!==0)return[...t.entries()].sort((e,t)=>t[1]-e[1])[0][0]}function xe(e){let t=e.pool_composition,n=[[`mobile`,t.mobile],[`residential`,t.residential],[`datacenter`,t.datacenter],[`unknown`,t.unknown]],r=n.reduce((e,[,t])=>e+t,0);if(r===0)return;let[i,a]=n.sort((e,t)=>t[1]-e[1])[0];return{type:i,share:a/r}}var Se={resi:`residential`,residential:`residential`,res:`residential`,mob:`mobile`,mobile:`mobile`,dc:`datacenter`,datacenter:`datacenter`,dch:`datacenter`};function Ce(e){return`${Math.round(e*100)}%`}function we(e,t,n){let r=[],i=z(e,`country`),a=n?.trim().toUpperCase()||``;if(i||a){let e=i?i.value.toUpperCase():``,n=a||e,o=a?e&&e!==a?`${a} (manual, overrides ${e})`:`${a} (manual)`:e,s=t?ye(t.ips):void 0;r.push(s?{label:`Country`,requested:o,observed:`${s.code} (${Ce(s.share)})`,verdict:s.code.toUpperCase()===n?s.share>=.9?`match`:`partial`:`mismatch`}:{label:`Country`,requested:o,observed:`—`,verdict:`unknown`})}let o=z(e,`type`);if(o){let e=R(Se,o.value.toLowerCase())??o.value.toLowerCase(),n=t?xe(t):void 0;r.push(n?{label:`Network type`,requested:e,observed:`${n.type} (${Ce(n.share)})`,verdict:n.type===e?n.share>=.6?`match`:`partial`:`mismatch`}:{label:`Network type`,requested:e,observed:`—`,verdict:`unknown`})}for(let t of[`region`,`state`,`city`]){let n=z(e,t);n&&r.push({label:n.label,requested:n.value,observed:`—`,verdict:`unknown`})}let s=z(e,`isp`);if(s){let e=t?be(t.ips)??``:``;r.push({label:`ISP`,requested:s.value,observed:e||`—`,verdict:e&&e.toLowerCase().includes(s.value.toLowerCase())?`match`:e?`mismatch`:`unknown`})}return r}function Te({session:e,report:t}){let n=ve(e.proxy_username);if(n.attributes.length===0&&n.raw.length===0&&!e.target_country)return(0,L.jsxs)(`section`,{className:`report-section targeting-panel`,children:[(0,L.jsx)(`h2`,{children:`Targeting`}),(0,L.jsx)(`p`,{className:`muted`,children:`No username on this proxy, so no targeting attributes are available.`})]});let r=we(n,t,e.target_country);return(0,L.jsxs)(`section`,{className:`report-section targeting-panel`,children:[(0,L.jsx)(`h2`,{children:`Targeting`}),(0,L.jsxs)(`div`,{className:`targeting-chips`,children:[[[`geo`,`Geo`],[`session`,`Session`],[`network`,`Network`],[`other`,`Other`]].map(([e,t])=>{let r=n.attributes.filter(t=>t.category===e);return r.length===0?null:(0,L.jsxs)(`div`,{className:`targeting-group`,children:[(0,L.jsx)(`span`,{className:`targeting-group-label`,children:t}),r.map(e=>(0,L.jsxs)(`span`,{className:`chip`,children:[(0,L.jsx)(`strong`,{children:e.label}),` `,e.value]},`${e.key}-${e.value}`))]},e)}),n.raw.length>0&&(0,L.jsxs)(`div`,{className:`targeting-group`,children:[(0,L.jsx)(`span`,{className:`targeting-group-label`,children:`Unparsed`}),n.raw.map((e,t)=>(0,L.jsx)(`span`,{className:`chip mono`,children:e},`${e}-${t}`))]})]}),r.length>0&&(0,L.jsxs)(`table`,{className:`targeting-comparison`,children:[(0,L.jsx)(`thead`,{children:(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`th`,{children:`Attribute`}),(0,L.jsx)(`th`,{children:`Requested`}),(0,L.jsx)(`th`,{children:`Observed`}),(0,L.jsx)(`th`,{children:`Result`})]})}),(0,L.jsx)(`tbody`,{children:r.map(e=>(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{children:e.label}),(0,L.jsx)(`td`,{className:`mono`,children:e.requested}),(0,L.jsx)(`td`,{className:`mono`,children:e.observed}),(0,L.jsx)(`td`,{children:(0,L.jsx)(`span`,{className:`verdict verdict-${e.verdict}`,children:e.verdict})})]},e.label))})]})]})}function Ee(e){let t=e+`CollectionProvider`,[n,r]=T(t),[i,a]=n(t,{collectionRef:{current:null},itemMap:new Map}),o=e=>{let{scope:t,children:n}=e,r=I.useRef(null),a=I.useRef(new Map).current;return(0,L.jsx)(i,{scope:t,itemMap:a,collectionRef:r,children:n})};o.displayName=t;let s=e+`CollectionSlot`,c=A(s),l=I.forwardRef((e,t)=>{let{scope:n,children:r}=e,i=w(t,a(s,n).collectionRef);return(0,L.jsx)(c,{ref:i,children:r})});l.displayName=s;let u=e+`CollectionItemSlot`,d=`data-radix-collection-item`,f=A(u),p=I.forwardRef((e,t)=>{let{scope:n,children:r,...i}=e,o=I.useRef(null),s=w(t,o),c=a(u,n);return I.useEffect(()=>(c.itemMap.set(o,{ref:o,...i}),()=>void c.itemMap.delete(o))),(0,L.jsx)(f,{[d]:``,ref:s,children:r})});p.displayName=u;function m(t){let n=a(e+`CollectionConsumer`,t);return I.useCallback(()=>{let e=n.collectionRef.current;if(!e)return[];let t=Array.from(e.querySelectorAll(`[${d}]`));return Array.from(n.itemMap.values()).sort((e,n)=>t.indexOf(e.ref.current)-t.indexOf(n.ref.current))},[n.collectionRef,n.itemMap])}return[{Provider:o,Slot:l,ItemSlot:p},m,r]}var De=I.createContext(void 0);function Oe(e){let t=I.useContext(De);return e||t||`ltr`}var B=!1;function ke(){let[e,t]=I.useState(B);return I.useEffect(()=>{B||(B=!0,t(!0))},[]),e}var Ae=I.useSyncExternalStore;function je(){return()=>{}}function Me(){return Ae(je,()=>!0,()=>!1)}var Ne=typeof Ae==`function`?Me:ke,Pe=Object.defineProperty,V=(e,t)=>Pe(e,`name`,{value:t,configurable:!0}),H=`rovingFocusGroup.onEntryFocus`,Fe={bubbles:!1,cancelable:!0},U=`RovingFocusGroup`,[W,Ie,Le]=Ee(U),[Re,ze]=T(U,[Le]),[Be,Ve]=Re(U),He=I.forwardRef(V(function(e,t){return(0,L.jsx)(W.Provider,{scope:e.__scopeRovingFocusGroup,children:(0,L.jsx)(W.Slot,{scope:e.__scopeRovingFocusGroup,children:(0,L.jsx)(Ue,{...e,ref:t})})})},`RovingFocusGroup`)),Ue=I.forwardRef(V(function(e,t){let{__scopeRovingFocusGroup:n,orientation:r,loop:i=!1,dir:a,currentTabStopId:o,defaultCurrentTabStopId:s,onCurrentTabStopIdChange:c,onEntryFocus:l,preventScrollOnEntryFocus:u=!1,...d}=e,f=I.useRef(null),p=w(t,f),h=Oe(a),[_,v]=m({prop:o,defaultProp:s??null,onChange:c,caller:U}),[y,b]=I.useState(!1),x=ae(l),S=Ie(n),C=I.useRef(!1),[ee,T]=I.useState(0);return I.useEffect(()=>{let e=f.current;if(e)return e.addEventListener(H,x),()=>e.removeEventListener(H,x)},[x]),(0,L.jsx)(Be,{scope:n,orientation:r,dir:h,loop:i,currentTabStopId:_,onItemFocus:I.useCallback(e=>v(e),[v]),onItemShiftTab:I.useCallback(()=>b(!0),[]),onFocusableItemAdd:I.useCallback(()=>T(e=>e+1),[]),onFocusableItemRemove:I.useCallback(()=>T(e=>e-1),[]),children:(0,L.jsx)(F.div,{tabIndex:y||ee===0?-1:0,"data-orientation":r,...d,ref:p,style:{outline:`none`,...e.style},onMouseDown:g(e.onMouseDown,()=>{C.current=!0}),onFocus:g(e.onFocus,e=>{let t=!C.current;if(e.target===e.currentTarget&&t&&!y){let t=new CustomEvent(H,Fe);if(e.currentTarget.dispatchEvent(t),!t.defaultPrevented){let e=S().filter(e=>e.focusable);G([e.find(e=>e.active),e.find(e=>e.id===_),...e].filter(Boolean).map(e=>e.ref.current),u)}}C.current=!1}),onBlur:g(e.onBlur,()=>b(!1))})})},`RovingFocusGroupImpl`)),We=`RovingFocusGroupItem`,Ge=I.forwardRef(V(function(e,t){let{__scopeRovingFocusGroup:n,focusable:r=!0,active:i=!1,tabStopId:a,children:o,...s}=e,c=k(),l=a||c,u=Ve(We,n),d=u.currentTabStopId===l,f=Ie(n),{onFocusableItemAdd:p,onFocusableItemRemove:m,currentTabStopId:h}=u,_=Ne();return le(()=>{if(!(!_||!r))return p(),()=>m()},[_,r,p,m]),I.useEffect(()=>{if(!(_||!r))return p(),()=>m()},[_,r,p,m]),(0,L.jsx)(W.ItemSlot,{scope:n,id:l,focusable:r,active:i,children:(0,L.jsx)(F.span,{tabIndex:d?0:-1,"data-orientation":u.orientation,...s,ref:t,onMouseDown:g(e.onMouseDown,e=>{r?u.onItemFocus(l):e.preventDefault()}),onFocus:g(e.onFocus,()=>u.onItemFocus(l)),onKeyDown:g(e.onKeyDown,e=>{if(e.key===`Tab`&&e.shiftKey){u.onItemShiftTab();return}if(e.target!==e.currentTarget)return;let t=Je(e,u.orientation,u.dir);if(t!==void 0){if(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)return;e.preventDefault();let n=f().filter(e=>e.focusable).map(e=>e.ref.current);if(t===`last`)n.reverse();else if(t===`prev`||t===`next`){t===`prev`&&n.reverse();let r=n.indexOf(e.currentTarget);n=u.loop?Ye(n,r+1):n.slice(r+1)}setTimeout(()=>G(n))}}),children:typeof o==`function`?o({isCurrentTabStop:d,hasTabStop:h!=null}):o})})},`RovingFocusGroupItem`)),Ke={ArrowLeft:`prev`,ArrowUp:`prev`,ArrowRight:`next`,ArrowDown:`next`,PageUp:`first`,Home:`first`,PageDown:`last`,End:`last`};function qe(e,t){return t===`rtl`?e===`ArrowLeft`?`ArrowRight`:e===`ArrowRight`?`ArrowLeft`:e:e}V(qe,`getDirectionAwareKey`);function Je(e,t,n){let r=qe(e.key,n);if(!(t===`vertical`&&[`ArrowLeft`,`ArrowRight`].includes(r))&&!(t===`horizontal`&&[`ArrowUp`,`ArrowDown`].includes(r)))return Ke[r]}V(Je,`getFocusIntent`);function G(e,t=!1){let n=document.activeElement;for(let r of e)if(r===n||(r.focus({preventScroll:t}),document.activeElement!==n))return}V(G,`focusFirst`);function Ye(e,t){return e.map((n,r)=>e[(t+r)%e.length])}V(Ye,`wrapArray`);var Xe=He,Ze=Ge,Qe=Object.defineProperty,K=(e,t)=>Qe(e,`name`,{value:t,configurable:!0}),q=`Tabs`,[$e,et]=T(q,[ze]),tt=ze(),[nt,J]=$e(q),rt=I.forwardRef(K(function(e,t){let{__scopeTabs:n,value:r,onValueChange:i,defaultValue:a,orientation:o=`horizontal`,dir:s,activationMode:c=`automatic`,...l}=e,u=Oe(s),[d,f]=m({prop:r,onChange:i,defaultProp:a??``,caller:q});return(0,L.jsx)(nt,{scope:n,baseId:k(),value:d,onValueChange:f,orientation:o,dir:u,activationMode:c,children:(0,L.jsx)(F.div,{dir:u,"data-orientation":o,...l,ref:t})})},`Tabs`)),it=`TabsList`,at=I.forwardRef(K(function(e,t){let{__scopeTabs:n,loop:r=!0,...i}=e,a=J(it,n),o=tt(n);return(0,L.jsx)(Xe,{asChild:!0,...o,orientation:a.orientation,dir:a.dir,loop:r,children:(0,L.jsx)(F.div,{role:`tablist`,"aria-orientation":a.orientation,...i,ref:t})})},`TabsList`)),ot=`TabsTrigger`,st=I.forwardRef(K(function(e,t){let{__scopeTabs:n,value:r,disabled:i=!1,...a}=e,o=J(ot,n),s=tt(n),c=Y(o.baseId,r),l=X(o.baseId,r),u=r===o.value;return(0,L.jsx)(Ze,{asChild:!0,...s,focusable:!i,active:u,children:(0,L.jsx)(F.button,{type:`button`,role:`tab`,"aria-selected":u,"aria-controls":l,"data-state":u?`active`:`inactive`,"data-disabled":i?``:void 0,disabled:i,id:c,...a,ref:t,onMouseDown:g(e.onMouseDown,e=>{!i&&e.button===0&&e.ctrlKey===!1?o.onValueChange(r):e.preventDefault()}),onKeyDown:g(e.onKeyDown,e=>{i||e.target!==e.currentTarget||[` `,`Enter`].includes(e.key)&&o.onValueChange(r)}),onFocus:g(e.onFocus,()=>{let e=o.activationMode!==`manual`;!u&&!i&&e&&o.onValueChange(r)})})})},`TabsTrigger`)),ct=`TabsContent`,lt=I.forwardRef(K(function(e,t){let{__scopeTabs:n,value:r,forceMount:i,children:a,...o}=e,s=J(ct,n),c=Y(s.baseId,r),l=X(s.baseId,r),u=r===s.value,d=I.useRef(u);return I.useEffect(()=>{let e=requestAnimationFrame(()=>d.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,L.jsx)(ce,{present:i||u,children:({present:n})=>(0,L.jsx)(F.div,{"data-state":u?`active`:`inactive`,"data-orientation":s.orientation,role:`tabpanel`,"aria-labelledby":c,hidden:!n,id:l,tabIndex:0,...o,ref:t,style:{...e.style,animationDuration:d.current?`0s`:void 0},children:n&&a})})},`TabsContent`));function Y(e,t){return`${e}-trigger-${t}`}K(Y,`makeTriggerId`);function X(e,t){return`${e}-content-${t}`}K(X,`makeContentId`);var ut=rt,dt=at,ft=st,pt=lt,mt=ut,ht=dt,Z=ft,Q=pt;function gt(){let{id:e=``}=v(),[r,i]=ne(),m=r.get(`tab`),g=m===`reputation`||m===`samples`?m:`overview`,C=St(r.get(`page`)),w=_(e),T=w.data?.status===`running`,D=b(e,T),O=ee(e,C,g===`samples`,T),k=p(),A=x();return w.isPending?(0,L.jsx)(vt,{includeSamples:g===`samples`}):w.error instanceof f&&w.error.status===404?(0,L.jsx)(xt,{}):w.isError||!w.data?(0,L.jsxs)(`div`,{className:`session-page`,children:[(0,L.jsxs)(h,{className:`error-state`,children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not load session`}),(0,L.jsx)(`p`,{children:$(w.error)})]}),(0,L.jsx)(S,{type:`button`,onClick:()=>w.refetch(),children:`Retry`})]}),(0,L.jsx)(y,{to:`/`,className:`back-link`,children:`Back to sessions`})]}):(0,L.jsxs)(`main`,{className:`session-page`,children:[(0,L.jsx)(y,{to:`/`,className:`breadcrumb`,children:`Sessions`}),(0,L.jsxs)(`header`,{className:`session-header`,children:[(0,L.jsxs)(`div`,{className:`session-title`,children:[(0,L.jsxs)(`div`,{className:`session-title-line`,children:[(0,L.jsx)(`h1`,{children:w.data.name}),(0,L.jsx)(re,{status:w.data.status})]}),(0,L.jsxs)(`p`,{children:[(0,L.jsx)(`span`,{className:`mono`,children:w.data.proxy_display}),(0,L.jsx)(`span`,{"aria-hidden":`true`,children:` · `}),(0,L.jsx)(`span`,{children:w.data.mode===`sticky`?`Sticky`:`Pool`})]})]}),(0,L.jsxs)(`div`,{className:`session-actions`,children:[w.data.status===`running`&&(0,L.jsxs)(S,{type:`button`,variant:`danger`,onClick:()=>{window.confirm(`Stop “${w.data.name}”? You can re-enable it later.`)&&k.mutate(e)},disabled:k.isPending,children:[(0,L.jsx)(te,{size:14,fill:`currentColor`,"aria-hidden":`true`}),k.isPending?`Stopping…`:`Stop session`]}),w.data.status!==`running`&&(0,L.jsxs)(S,{type:`button`,onClick:()=>{window.confirm(`Re-enable “${w.data.name}”? Sampling resumes; progress counters reset while prior samples are kept.`)&&A.mutate(e)},disabled:A.isPending,children:[(0,L.jsx)(d,{size:14,"aria-hidden":`true`}),A.isPending?`Re-enabling…`:`Re-enable`]}),(0,L.jsxs)(`a`,{className:`button button-secondary`,href:`/api/sessions/${e}/export.csv`,download:!0,children:[(0,L.jsx)(n,{size:16,"aria-hidden":`true`}),`Export CSV`]})]})]}),k.isError&&(0,L.jsxs)(h,{className:`inline-alert`,children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not stop session`}),(0,L.jsx)(`p`,{children:$(k.error)})]})]}),A.isError&&(0,L.jsxs)(h,{className:`inline-alert`,children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not re-enable session`}),(0,L.jsx)(`p`,{children:$(A.error)})]})]}),(0,L.jsx)(he,{session:w.data}),(0,L.jsx)(`div`,{className:`report-meta`,"aria-live":`polite`,children:D.dataUpdatedAt>0?`Last updated ${N(new Date(D.dataUpdatedAt).toISOString())}`:`Waiting for report update`}),(0,L.jsxs)(mt,{className:`report-tabs`,value:g,onValueChange:e=>{if(e!==`overview`&&e!==`reputation`&&e!==`samples`)return;let t=new URLSearchParams(r);t.set(`tab`,e),e===`samples`?t.has(`page`)||t.set(`page`,`1`):t.delete(`page`),i(t)},children:[(0,L.jsxs)(ht,{className:`tabs-list`,"aria-label":`Session report views`,children:[(0,L.jsx)(Z,{className:`tab-trigger`,value:`overview`,children:`Overview`}),(0,L.jsx)(Z,{className:`tab-trigger`,value:`reputation`,children:`Reputation`}),(0,L.jsx)(Z,{className:`tab-trigger`,value:`samples`,children:`Samples`})]}),(0,L.jsxs)(Q,{className:`tab-content`,value:`overview`,children:[(0,L.jsx)(Te,{session:w.data,report:D.data}),(0,L.jsx)(_t,{report:D,children:D.data&&(0,L.jsxs)(`div`,{className:`report-grid`,children:[(0,L.jsx)(t,{data:D.data.series}),(0,L.jsx)(s,{data:D.data.series}),(0,L.jsx)(o,{data:D.data.series}),(0,L.jsx)(c,{data:D.data.pool_composition}),(0,L.jsx)(me,{data:D.data.stickiness}),(0,L.jsx)(l,{data:D.data.pool_growth})]})})]}),(0,L.jsx)(Q,{className:`tab-content`,value:`reputation`,children:(0,L.jsx)(_t,{report:D,children:D.data&&(0,L.jsxs)(L.Fragment,{children:[(0,L.jsxs)(`div`,{className:`reputation-summary`,"aria-label":`Reputation summary`,children:[(0,L.jsxs)(`span`,{children:[(0,L.jsx)(`strong`,{children:D.data.reputation_summary.total_ips}),` observed IPs`]}),(0,L.jsxs)(`span`,{children:[(0,L.jsx)(`strong`,{children:D.data.reputation_summary.flagged_ips}),` flagged (`,ie(D.data.reputation_summary.flagged_percent/100),`)`]}),(0,L.jsxs)(`span`,{children:[(0,L.jsx)(`strong`,{children:D.data.reputation_summary.dnsbl_hit_ips}),` DNSBL hits`]})]}),(0,L.jsx)(u,{data:D.data.risk_histogram}),(0,L.jsxs)(`section`,{className:`report-section`,children:[(0,L.jsx)(`h2`,{children:`IP reputation`}),(0,L.jsx)(a,{rows:D.data.ips})]})]})})}),(0,L.jsx)(Q,{className:`tab-content`,value:`samples`,children:(0,L.jsxs)(`section`,{className:`report-section`,children:[(0,L.jsx)(`h2`,{children:`Sample history`}),O.isPending?(0,L.jsx)(bt,{}):O.isError?(0,L.jsxs)(h,{children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not load samples`}),(0,L.jsx)(`p`,{children:$(O.error)})]}),(0,L.jsx)(S,{type:`button`,onClick:()=>O.refetch(),children:`Retry samples`})]}):O.data&&(0,L.jsx)(ue,{page:O.data})]})})]})]})}function _t({report:e,children:t}){return e.isPending?(0,L.jsx)(yt,{}):e.isError?(0,L.jsxs)(h,{children:[(0,L.jsx)(E,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{children:[(0,L.jsx)(`strong`,{children:`Could not load report`}),(0,L.jsx)(`p`,{children:$(e.error)})]}),(0,L.jsx)(S,{type:`button`,onClick:()=>e.refetch(),children:`Retry report`})]}):t}function vt({includeSamples:e}){return(0,L.jsxs)(`main`,{className:`session-page session-loading`,children:[(0,L.jsxs)(`div`,{role:`status`,"aria-label":`Loading session detail`,children:[(0,L.jsx)(`span`,{className:`sr-only`,children:`Loading session detail`}),(0,L.jsx)(P,{className:`session-heading-skeleton`}),(0,L.jsx)(P,{className:`session-subheading-skeleton`})]}),(0,L.jsx)(yt,{}),e&&(0,L.jsx)(bt,{})]})}function yt(){return(0,L.jsxs)(`div`,{className:`report-loading`,"aria-label":`Loading report`,children:[(0,L.jsx)(P,{className:`summary-skeleton`}),Array.from({length:4},(e,t)=>(0,L.jsx)(P,{className:`chart-skeleton`},t))]})}function bt(){return(0,L.jsxs)(`div`,{className:`sample-loading`,"aria-label":`Loading samples`,children:[(0,L.jsx)(P,{className:`sample-heading-skeleton`}),Array.from({length:4},(e,t)=>(0,L.jsx)(P,{className:`sample-row-skeleton`},t))]})}function xt(){return(0,L.jsxs)(`main`,{className:`empty-state`,children:[(0,L.jsx)(`h1`,{children:`Session not found`}),(0,L.jsx)(`p`,{children:`This session may have been removed, or the link may be incomplete.`}),(0,L.jsx)(y,{to:`/`,className:`button button-primary`,children:`Back to sessions`})]})}function St(e){let t=Number(e);return Number.isSafeInteger(t)&&t>0?t:1}function $(e){return e instanceof Error?e.message:`The request could not be completed.`}export{gt as SessionPage}; \ No newline at end of file diff --git a/web/dist/index.html b/web/dist/index.html index d43ff65..a83fb1b 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -5,7 +5,7 @@ Proxy Sampler - + diff --git a/web/src/components/new-run-dialog.test.tsx b/web/src/components/new-run-dialog.test.tsx index 1792d66..9db08ae 100644 --- a/web/src/components/new-run-dialog.test.tsx +++ b/web/src/components/new-run-dialog.test.tsx @@ -69,6 +69,25 @@ describe('NewRunDialog', () => { expect(await screen.findByText('Axis names must be unique')).toBeInTheDocument() }) + it('submits the manual target country with the run', async () => { + const fetchMock = stubFetch() + renderDialog() + const user = userEvent.setup() + await user.type(screen.getByLabelText('Run name'), 'geo') + await user.type(screen.getByLabelText('Proxy template'), 'socks5h://u-sid-{session}:pw@gate:1080') + await user.click(screen.getByRole('button', { name: 'Add axis' })) + await user.type(screen.getByLabelText('Axis 1 name'), 'session') + await user.selectOptions(screen.getByLabelText('Axis 1 kind'), 'random') + await user.type(screen.getByLabelText('Axis 1 count'), '2') + await user.selectOptions(screen.getByLabelText('Sampling mode'), 'sticky') + await user.click(screen.getByRole('button', { name: 'Advanced settings' })) + await user.type(screen.getByLabelText('Target country (optional)'), 'us') + await user.click(screen.getByRole('button', { name: 'Start run' })) + await vi.waitFor(() => expect(callsTo(fetchMock, '/api/runs')).toHaveLength(1)) + const body = JSON.parse((callsTo(fetchMock, '/api/runs')[0][1] as RequestInit).body as string) + expect(body.target_country).toBe('us') + }) + it('caps the preview using the server-configured maximum', async () => { stubFetch(3) renderDialog() diff --git a/web/src/components/new-run-dialog.tsx b/web/src/components/new-run-dialog.tsx index 79fc80d..c4d74ae 100644 --- a/web/src/components/new-run-dialog.tsx +++ b/web/src/components/new-run-dialog.tsx @@ -75,6 +75,7 @@ const formSchema = z.object({ dialTimeout: z.string().refine((value) => value === '' || positiveInteger.test(value), 'Enter a positive integer or leave blank').refine((value) => value === '' || Number(value) >= 100, 'Timeout must be at least 100 ms'), maxSamples: z.string().refine((value) => value === '' || positiveInteger.test(value), 'Enter a positive integer or leave blank'), maxDuration: z.string().refine((value) => value === '' || positiveInteger.test(value), 'Enter a positive integer or leave blank'), + targetCountry: z.string().trim().refine((value) => value === '' || /^[A-Za-z]{2}$/.test(value), 'Enter a 2-letter country code or leave blank'), }) type FormValues = z.input @@ -94,6 +95,7 @@ const defaults: FormValues = { dialTimeout: '', maxSamples: '', maxDuration: '', + targetCountry: '', } export function NewRunDialog({ open, onClose }: { open: boolean; onClose: () => void }) { @@ -135,6 +137,7 @@ export function NewRunDialog({ open, onClose }: { open: boolean; onClose: () => ...(values.dialTimeout ? { dial_timeout_ms: Number(values.dialTimeout) } : {}), ...(values.maxSamples ? { max_samples: Number(values.maxSamples) } : {}), ...(values.maxDuration ? { max_duration_seconds: Number(values.maxDuration) } : {}), + ...(values.targetCountry ? { target_country: values.targetCountry } : {}), } try { await create.mutateAsync(request) @@ -235,6 +238,9 @@ export function NewRunDialog({ open, onClose }: { open: boolean; onClose: () => + + + diff --git a/web/src/components/new-session-dialog.test.tsx b/web/src/components/new-session-dialog.test.tsx index feb7f1e..7da378e 100644 --- a/web/src/components/new-session-dialog.test.tsx +++ b/web/src/components/new-session-dialog.test.tsx @@ -68,6 +68,38 @@ describe('NewSessionDialog', () => { expect(body.max_duration_seconds).toBe(3600) }) + it('validates and submits the manual target country', async () => { + vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(createdSession))) + renderDialog() + const user = userEvent.setup() + await fillRequired(user) + await user.click(screen.getByRole('button', { name: 'Advanced settings' })) + const target = screen.getByLabelText('Target country (optional)') + + await user.type(target, 'usa') + await user.click(screen.getByRole('button', { name: 'Start session' })) + expect(await screen.findByText('Enter a 2-letter country code or leave blank')).toBeInTheDocument() + expect(fetch).not.toHaveBeenCalled() + + await user.clear(target) + await user.type(target, 'de') + await user.click(screen.getByRole('button', { name: 'Start session' })) + await waitFor(() => expect(fetch).toHaveBeenCalledOnce()) + const body = JSON.parse((vi.mocked(fetch).mock.calls[0][1] as RequestInit).body as string) + expect(body.target_country).toBe('de') + }) + + it('omits target_country when the field is left blank', async () => { + vi.stubGlobal('fetch', vi.fn().mockResolvedValue(jsonResponse(createdSession))) + renderDialog() + const user = userEvent.setup() + await fillRequired(user) + await user.click(screen.getByRole('button', { name: 'Start session' })) + await waitFor(() => expect(fetch).toHaveBeenCalledOnce()) + const body = JSON.parse((vi.mocked(fetch).mock.calls[0][1] as RequestInit).body as string) + expect('target_country' in body).toBe(false) + }) + it('clears the secret immediately, disables controls, then closes and navigates on success', async () => { let resolveRequest!: (response: Response) => void const fetchMock = vi.fn((_input: RequestInfo | URL, _init?: RequestInit) => new Promise((resolve) => { resolveRequest = resolve })) diff --git a/web/src/components/new-session-dialog.tsx b/web/src/components/new-session-dialog.tsx index 0a16648..82a1613 100644 --- a/web/src/components/new-session-dialog.tsx +++ b/web/src/components/new-session-dialog.tsx @@ -25,6 +25,7 @@ const formSchema = z.object({ dialTimeout: z.string().regex(positiveInteger, 'Timeout must be a positive integer').refine((value) => Number(value) >= 100, 'Timeout must be at least 100 ms'), maxSamples: z.string().refine((value) => value === '' || positiveInteger.test(value), 'Enter a positive integer or leave blank'), maxDuration: z.string().refine((value) => value === '' || positiveInteger.test(value), 'Enter a positive integer or leave blank'), + targetCountry: z.string().trim().refine((value) => value === '' || /^[A-Za-z]{2}$/.test(value), 'Enter a 2-letter country code or leave blank'), }) type FormValues = z.input @@ -40,6 +41,7 @@ const defaults: FormValues = { dialTimeout: '10000', maxSamples: '', maxDuration: '', + targetCountry: '', } export function NewSessionDialog({ open, onOpenChange }: { open: boolean; onOpenChange: (open: boolean) => void }) { @@ -74,6 +76,7 @@ export function NewSessionDialog({ open, onOpenChange }: { open: boolean; onOpen ...(values.dialTimeout ? { dial_timeout_ms: Number(values.dialTimeout) } : {}), ...(values.maxSamples ? { max_samples: Number(values.maxSamples) } : {}), ...(values.maxDuration ? { max_duration_seconds: Number(values.maxDuration) } : {}), + ...(values.targetCountry ? { target_country: values.targetCountry } : {}), } form.resetField('proxy', { defaultValue: '' }) try { @@ -173,6 +176,9 @@ export function NewSessionDialog({ open, onOpenChange }: { open: boolean; onOpen + + + diff --git a/web/src/components/report/targeting-panel.test.tsx b/web/src/components/report/targeting-panel.test.tsx index 513c7ae..a93c407 100644 --- a/web/src/components/report/targeting-panel.test.tsx +++ b/web/src/components/report/targeting-panel.test.tsx @@ -26,4 +26,11 @@ describe('TargetingPanel', () => { render() expect(screen.getByText(/no username/i)).toBeInTheDocument() }) + + it('renders the comparison from the manual target country when the proxy has no username', () => { + render() + expect(screen.queryByText(/no username/i)).not.toBeInTheDocument() + expect(screen.getAllByText(/US/).length).toBeGreaterThan(0) + expect(screen.getByText('match')).toBeInTheDocument() + }) }) diff --git a/web/src/components/report/targeting-panel.tsx b/web/src/components/report/targeting-panel.tsx index 45ea593..3a08b09 100644 --- a/web/src/components/report/targeting-panel.tsx +++ b/web/src/components/report/targeting-panel.tsx @@ -3,7 +3,7 @@ import { compareAttributes, parseProxyAttributes } from '../../lib/proxy-attribu export function TargetingPanel({ session, report }: { session: Session; report: SessionReport | undefined }) { const parsed = parseProxyAttributes(session.proxy_username) - if (parsed.attributes.length === 0 && parsed.raw.length === 0) { + if (parsed.attributes.length === 0 && parsed.raw.length === 0 && !session.target_country) { return (

Targeting

@@ -11,7 +11,7 @@ export function TargetingPanel({ session, report }: { session: Session; report:
) } - const rows = compareAttributes(parsed, report) + const rows = compareAttributes(parsed, report, session.target_country) const groups: Array<['geo' | 'session' | 'network' | 'other', string]> = [ ['geo', 'Geo'], ['session', 'Session'], ['network', 'Network'], ['other', 'Other'], ] diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 4b85bdf..d5f7e26 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -9,6 +9,7 @@ export interface Session { name: string proxy_display: string proxy_username?: string | null + target_country?: string | null mode: SessionMode status: SessionStatus cadence_seconds: number @@ -42,6 +43,7 @@ export interface CreateSessionRequest { dial_timeout_ms?: number max_samples?: number | null max_duration_seconds?: number | null + target_country?: string } export interface Readiness { @@ -323,6 +325,7 @@ export interface VariantSummary { name: string cell_key: string params: Record + target_country?: string | null status: SessionStatus samples_taken: number distinct_ips: number @@ -344,11 +347,13 @@ export interface CreateRunRequest { dial_timeout_ms?: number max_samples?: number | null max_duration_seconds?: number | null + target_country?: string } export interface CellReport { cell_key: string params: Record + target_country?: string | null variant_count: number distinct_ips: number honor_rate?: number | null diff --git a/web/src/lib/proxy-attributes.test.ts b/web/src/lib/proxy-attributes.test.ts index ab2ec2f..b7d5ae7 100644 --- a/web/src/lib/proxy-attributes.test.ts +++ b/web/src/lib/proxy-attributes.test.ts @@ -87,6 +87,57 @@ describe('compareAttributes', () => { expect(isp.verdict).toBe('match') }) + it('compares against a manual target country when the username has none', () => { + const rows = compareAttributes(parseProxyAttributes('session-ab12'), report, 'US') + const country = rows.find((r) => r.label === 'Country')! + expect(country.requested).toContain('US') + expect(country.requested).toContain('manual') + expect(country.observed).toContain('US') + expect(country.verdict).toBe('match') + }) + + it('lets a manual target country override the username country', () => { + const rows = compareAttributes(parseProxyAttributes('country-us'), report, 'DE') + const country = rows.find((r) => r.label === 'Country')! + expect(country.requested).toContain('DE') + // Dominant observed is US, so the overriding manual target de mismatches. + expect(country.verdict).toBe('mismatch') + }) + + it('notes the username country that a conflicting manual target overrides', () => { + const rows = compareAttributes(parseProxyAttributes('country-us'), report, 'DE') + const country = rows.find((r) => r.label === 'Country')! + expect(country.requested).toContain('DE (manual, overrides US)') + }) + + it('does not claim an override when the manual target equals the username country', () => { + const rows = compareAttributes(parseProxyAttributes('country-de'), report, 'DE') + const country = rows.find((r) => r.label === 'Country')! + expect(country.requested).toBe('DE (manual)') + }) + + it('buckets observed country codes case-insensitively for the dominant share', () => { + const mixedCase: SessionReport = { + ...report, + ips: [ + { ip: '203.0.113.1', category: 'residential', country: 'DE', isp: '', asn: '', risk_score: null, greynoise_class: '', dnsbl_listed: false, dnsbl_hits: [], first_seen: '', last_seen: '', hit_count: 6 }, + { ip: '203.0.113.2', category: 'residential', country: 'de', isp: '', asn: '', risk_score: null, greynoise_class: '', dnsbl_listed: false, dnsbl_hits: [], first_seen: '', last_seen: '', hit_count: 5 }, + ], + } + const rows = compareAttributes(parseProxyAttributes(''), mixedCase, 'DE') + const country = rows.find((r) => r.label === 'Country')! + // All traffic is DE; a case-split vote must not downgrade the verdict. + expect(country.observed).toContain('100%') + expect(country.verdict).toBe('match') + }) + + it('reports an unknown verdict for a manual target with no observations', () => { + const rows = compareAttributes(parseProxyAttributes(''), { ...report, ips: [] }, 'DE') + const country = rows.find((r) => r.label === 'Country')! + expect(country.observed).toBe('—') + expect(country.verdict).toBe('unknown') + }) + it('marks a country request as partial when the dominant share is below the match threshold', () => { const mixedReport: SessionReport = { ...report, diff --git a/web/src/lib/proxy-attributes.ts b/web/src/lib/proxy-attributes.ts index f5eccdf..39adff2 100644 --- a/web/src/lib/proxy-attributes.ts +++ b/web/src/lib/proxy-attributes.ts @@ -88,8 +88,11 @@ function dominantCountry(ips: IPRow[]): { code: string; share: number } | undefi let sum = 0 for (const ip of ips) { if (!ip.country) continue + // Bucket case-insensitively: a mixed-case code in the reputation data must + // not split the vote and downgrade a true match to partial. + const code = ip.country.toUpperCase() const weight = ip.hit_count > 0 ? ip.hit_count : 1 - totals.set(ip.country, (totals.get(ip.country) ?? 0) + weight) + totals.set(code, (totals.get(code) ?? 0) + weight) sum += weight } if (sum === 0) return undefined @@ -129,15 +132,28 @@ function pct(share: number): string { return `${Math.round(share * 100)}%` } -export function compareAttributes(parsed: ParsedAttributes, report: SessionReport | undefined): ComparisonRow[] { +export function compareAttributes(parsed: ParsedAttributes, report: SessionReport | undefined, targetCountry?: string | null): ComparisonRow[] { const rows: ComparisonRow[] = [] + // A manually declared target country overrides any country parsed from the + // username; it is the only requested-country signal for proxies whose config + // does not encode one. const country = attribute(parsed, 'country') - if (country) { - const requested = country.value.toUpperCase() + const manual = targetCountry?.trim().toUpperCase() || '' + if (country || manual) { + const usernameCode = country ? country.value.toUpperCase() : '' + const code = manual || usernameCode + // When the manual target contradicts a username-encoded country, surface + // the overridden value too — a mismatch verdict against a hidden config + // country would send the operator debugging the wrong side. + const requested = manual + ? usernameCode && usernameCode !== manual + ? `${manual} (manual, overrides ${usernameCode})` + : `${manual} (manual)` + : usernameCode const observed = report ? dominantCountry(report.ips) : undefined rows.push(observed - ? { label: 'Country', requested, observed: `${observed.code} (${pct(observed.share)})`, verdict: observed.code.toUpperCase() === requested ? (observed.share >= 0.9 ? 'match' : 'partial') : 'mismatch' } + ? { label: 'Country', requested, observed: `${observed.code} (${pct(observed.share)})`, verdict: observed.code.toUpperCase() === code ? (observed.share >= 0.9 ? 'match' : 'partial') : 'mismatch' } : { label: 'Country', requested, observed: '—', verdict: 'unknown' }) } diff --git a/web/src/pages/run-page.test.tsx b/web/src/pages/run-page.test.tsx index d0be9f3..01e224e 100644 --- a/web/src/pages/run-page.test.tsx +++ b/web/src/pages/run-page.test.tsx @@ -29,4 +29,53 @@ describe('RunPage', () => { await waitFor(() => expect(screen.getByText('poolcheck')).toBeInTheDocument()) expect(await screen.findByText(/40/)).toBeInTheDocument() // estimated pool size }) + + it('shows the manual target country the honor rate is measured against', async () => { + const detail = { + run: { id: 'r1', name: 'geo', template_display: 'gate:1080', status: 'running', variant_count: 1, distinct_ips: 0, created_at: new Date().toISOString() }, + variants: [{ session_id: 's1', name: 'geo #1', cell_key: '{}', params: { session: 'ab12' }, target_country: 'US', status: 'running', samples_taken: 0, distinct_ips: 0 }], + } + const report = { distinct_ips: 0, estimated_pool_size: 0, pool_size_lower_bound: false, honor_rate: null, composition: { mobile: 0, residential: 0, datacenter: 0, unknown: 0 }, risk_histogram: [], flagged_ips: 0, flagged_percent: 0, dnsbl_hit_ips: 0, series: [], cells: [], ips: [] } + vi.stubGlobal('fetch', mockFetch(detail, report)) + const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + render( + + + } /> + + , + ) + await waitFor(() => expect(screen.getByText('geo')).toBeInTheDocument()) + expect(screen.getByText(/target country/i)).toBeInTheDocument() + expect(screen.getByText('US')).toBeInTheDocument() + }) + + it('labels a cell with the manual target its honor rate was measured against', async () => { + const detail = { + run: { id: 'r1', name: 'geo', template_display: 'gate:1080', status: 'running', variant_count: 1, distinct_ips: 1, created_at: new Date().toISOString() }, + variants: [{ session_id: 's1', name: 'geo #1', cell_key: '{"country":"de"}', params: { country: 'de' }, target_country: 'US', status: 'running', samples_taken: 2, distinct_ips: 1 }], + } + const report = { + distinct_ips: 1, estimated_pool_size: 1, pool_size_lower_bound: false, honor_rate: 1, + composition: { mobile: 0, residential: 1, datacenter: 0, unknown: 0 }, risk_histogram: [], + flagged_ips: 0, flagged_percent: 0, dnsbl_hit_ips: 0, series: [], + cells: [{ cell_key: '{"country":"de"}', params: { country: 'de' }, target_country: 'US', variant_count: 1, distinct_ips: 1, honor_rate: 1, composition: { mobile: 0, residential: 1, datacenter: 0, unknown: 0 } }], + ips: [], + } + vi.stubGlobal('fetch', mockFetch(detail, report)) + const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }) + render( + + + } /> + + , + ) + await waitFor(() => expect(screen.getByText('geo')).toBeInTheDocument()) + // The cell label must disclose the override: params say country=de, but the + // honor rate was measured against the manual target US. country=de appears + // in both the cell and variants tables, so assert presence, not uniqueness. + expect((await screen.findAllByText(/country=de/)).length).toBeGreaterThan(0) + expect(screen.getByText(/target US \(manual\)/)).toBeInTheDocument() + }) }) diff --git a/web/src/pages/run-page.tsx b/web/src/pages/run-page.tsx index ff7df00..7d8734c 100644 --- a/web/src/pages/run-page.tsx +++ b/web/src/pages/run-page.tsx @@ -51,6 +51,8 @@ export function RunPage() { } const { run: detail, variants } = run.data + // Every child of a run shares one manual target country, set at creation. + const targetCountry = variants.find((v) => v.target_country)?.target_country const confirmStop = () => { if (window.confirm(`Stop “${detail.name}”? You can re-enable it later.`)) stop.mutate(id) @@ -70,7 +72,7 @@ export function RunPage() {

{detail.name}

-

{detail.template_display}{detail.variant_count} variant{detail.variant_count === 1 ? '' : 's'}

+

{detail.template_display}{detail.variant_count} variant{detail.variant_count === 1 ? '' : 's'}{targetCountry && <>Target country {targetCountry} (manual)}

{detail.status === 'running' && } @@ -140,7 +142,7 @@ function CellTable({ cells }: { cells: CellReport[] }) { {sorted.map((cell) => ( - {formatParams(cell.params)} + {formatParams(cell.params)}{cell.target_country && · target {cell.target_country} (manual)} {cell.variant_count} {cell.distinct_ips} {cell.honor_rate == null ? '—' : formatPercent(cell.honor_rate)}