llm-simple-router 0.9.32 → 0.9.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/config/model-context.js +21 -9
  2. package/dist/db/index.js +1 -0
  3. package/dist/db/mappings.js +6 -15
  4. package/dist/db/providers.d.ts +1 -0
  5. package/dist/db/providers.js +11 -26
  6. package/dist/db/router-keys.js +4 -5
  7. package/dist/proxy/handler/openai.js +5 -4
  8. package/dist/proxy/routing/mapping-resolver.js +7 -16
  9. package/frontend-dist/assets/{CardContent-D3x1v1V9.js → CardContent-CPeHI_vO.js} +1 -1
  10. package/frontend-dist/assets/{CardTitle-DIgY93n2.js → CardTitle-DiF3FpGs.js} +1 -1
  11. package/frontend-dist/assets/{Checkbox-BBj7YMSz.js → Checkbox-BpQYgA_C.js} +1 -1
  12. package/frontend-dist/assets/{CollapsibleContent-Cy8Zj7F7.js → CollapsibleContent-CUb_IZ--.js} +1 -1
  13. package/frontend-dist/assets/{CollapsibleTrigger-Vdxg8CPQ.js → CollapsibleTrigger-DSh5Vnmj.js} +1 -1
  14. package/frontend-dist/assets/{Dashboard-BvUBgYaB.js → Dashboard-DMaq-T6I.js} +1 -1
  15. package/frontend-dist/assets/{Input-yOkodP1n.js → Input-C9E7es5X.js} +1 -1
  16. package/frontend-dist/assets/{Label-XqpkYcVi.js → Label-kvNNc1bh.js} +1 -1
  17. package/frontend-dist/assets/{Login-BGagonui.js → Login-CC1aMDOU.js} +1 -1
  18. package/frontend-dist/assets/{Logs-bfeOLJad.js → Logs-zr32VuD0.js} +1 -1
  19. package/frontend-dist/assets/{MappingEntryEditor-CMTbBK_d.js → MappingEntryEditor-D6ABslWN.js} +1 -1
  20. package/frontend-dist/assets/{ModelCard-C81l2a_5.js → ModelCard-Dn_8Lnr-.js} +1 -1
  21. package/frontend-dist/assets/{ModelMappings-CvDWSsDP.js → ModelMappings-BD7Xd9u_.js} +1 -1
  22. package/frontend-dist/assets/{Monitor-BGH6sjdr.js → Monitor-CnQrBEqa.js} +1 -1
  23. package/frontend-dist/assets/{Providers-UK6LN6DF.js → Providers-CK4mOZS5.js} +1 -1
  24. package/frontend-dist/assets/{ProxyEnhancement-MX0PRADd.js → ProxyEnhancement-DQIrpH8f.js} +1 -1
  25. package/frontend-dist/assets/{QuickSetup-CajStS5C.js → QuickSetup-Cp1nlz0G.js} +1 -1
  26. package/frontend-dist/assets/{RetryRules-gpvpTTSc.js → RetryRules-Botm2DuB.js} +1 -1
  27. package/frontend-dist/assets/{RouterKeys-Dc8D6cEV.js → RouterKeys-C9ZluPMi.js} +1 -1
  28. package/frontend-dist/assets/{RovingFocusItem-B3BLvyzD.js → RovingFocusItem-B4cr2rFZ.js} +1 -1
  29. package/frontend-dist/assets/{Schedules-Criu9-NO.js → Schedules-C3JE7gox.js} +1 -1
  30. package/frontend-dist/assets/{Settings-BiYdwrHf.js → Settings-Dd9LXNyo.js} +1 -1
  31. package/frontend-dist/assets/{Setup-BVqlQCjs.js → Setup-DXTFJRxq.js} +1 -1
  32. package/frontend-dist/assets/{Switch-B7QaMMlY.js → Switch-CkJ3KppU.js} +1 -1
  33. package/frontend-dist/assets/{TooltipTrigger-Bz3pu02g.js → TooltipTrigger-DtY0_zHb.js} +1 -1
  34. package/frontend-dist/assets/{TransformRulesForm-DXB1ChZ2.js → TransformRulesForm-DpFk5xx0.js} +1 -1
  35. package/frontend-dist/assets/{UnifiedRequestDialog-BbGcsFXP.js → UnifiedRequestDialog-Cpn9RNu1.js} +1 -1
  36. package/frontend-dist/assets/{VisuallyHiddenInput-MTmHNjqA.js → VisuallyHiddenInput-DvHAsFOO.js} +1 -1
  37. package/frontend-dist/assets/{button-lv9v_6nd.js → button-CjKaq4D4.js} +2 -2
  38. package/frontend-dist/assets/{copy-Dwbg7SpV.js → copy-BYleSlPg.js} +1 -1
  39. package/frontend-dist/assets/{dialog-ZNKLyaHg.js → dialog-DlHPBQX7.js} +1 -1
  40. package/frontend-dist/assets/{index-CDEwS862.js → index-C19mbJF3.js} +2 -2
  41. package/frontend-dist/assets/{trash-2-UQ53WECI.js → trash-2-C6EEjS9z.js} +1 -1
  42. package/frontend-dist/assets/{useClipboard-CmrKRWL_.js → useClipboard-C_hBlc9t.js} +1 -1
  43. package/frontend-dist/assets/{useLogRetention-C59RXKSz.js → useLogRetention-DZGdtwFB.js} +1 -1
  44. package/frontend-dist/index.html +2 -2
  45. package/package.json +1 -1
@@ -88,6 +88,22 @@ export function lookupContextWindow(modelName) {
88
88
  export function normalizePatchName(name) {
89
89
  return name.replace(/-/g, "_");
90
90
  }
91
+ /**
92
+ * 解析 providers.models 的 JSON 文本。
93
+ *
94
+ * 这是解析 providers.models 字段的唯一合法入口。
95
+ * 禁止直接 JSON.parse(provider.models) —— 数据格式已从 string[] 演进为 ModelEntry[],
96
+ * 直接 JSON.parse 会得到对象数组而非字符串数组,导致运行时错误。
97
+ *
98
+ * ESLint 规则 taste/no-raw-json-parse-models 会强制执行此约束。
99
+ */
100
+ /** 旧 patch ID 到新 patch ID 的迁移映射 */
101
+ const PATCH_ID_MIGRATION = {
102
+ thinking_param: "thinking_consistency",
103
+ thinking_blocks: "thinking_consistency",
104
+ non_ds_tools: "thinking_consistency",
105
+ cache_control: "thinking_consistency",
106
+ };
91
107
  export function parseModels(raw) {
92
108
  if (!raw)
93
109
  return [];
@@ -100,20 +116,16 @@ export function parseModels(raw) {
100
116
  return item ? { name: item, patches: [] } : null;
101
117
  }
102
118
  const obj = item;
103
- if (!obj || !obj.name)
119
+ if (!obj)
120
+ return null;
121
+ const modelName = obj.name ?? obj.id;
122
+ if (!modelName)
104
123
  return null;
105
- /** 旧 patch ID 到新 patch ID 的运行时迁移映射 */
106
- const PATCH_ID_MIGRATION = {
107
- thinking_param: "thinking_consistency",
108
- thinking_blocks: "thinking_consistency",
109
- non_ds_tools: "thinking_consistency",
110
- cache_control: "thinking_consistency",
111
- };
112
124
  const rawPatches = (obj.patches ?? []).map(normalizePatchName);
113
125
  const migrated = rawPatches.map(p => PATCH_ID_MIGRATION[p] ?? p);
114
126
  const patches = [...new Set(migrated)];
115
127
  const result = {
116
- name: obj.name,
128
+ name: modelName,
117
129
  patches,
118
130
  };
119
131
  if (obj.stream_timeout_ms != null)
package/dist/db/index.js CHANGED
@@ -105,6 +105,7 @@ function runApplicationMigrations(db) {
105
105
  db.transaction(() => {
106
106
  for (const p of providers) {
107
107
  try {
108
+ // eslint-disable-next-line taste/no-raw-json-parse-models -- 迁移代码需要操作原始 JSON 结构,parseModels() 会过滤非标准字段
108
109
  const raw = JSON.parse(p.models);
109
110
  if (!Array.isArray(raw) || raw.length === 0)
110
111
  continue;
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { buildUpdateQuery, deleteById } from "./helpers.js";
3
+ import { parseModels } from "../config/model-context.js";
3
4
  const GROUP_FIELDS = new Set(["client_model", "strategy", "rule", "is_active"]);
4
5
  // --- MappingGroups CRUD ---
5
6
  export function getMappingGroup(db, clientModel) {
@@ -35,14 +36,9 @@ export function getActiveProviderModels(db) {
35
36
  const providers = db.prepare("SELECT name, models, is_active FROM providers WHERE is_active = 1").all();
36
37
  const results = [];
37
38
  for (const p of providers) {
38
- try {
39
- const models = JSON.parse(p.models);
40
- for (const m of models) {
41
- results.push({ provider_name: p.name, backend_model: m });
42
- }
43
- }
44
- catch {
45
- continue;
39
+ const modelEntries = parseModels(p.models);
40
+ for (const m of modelEntries) {
41
+ results.push({ provider_name: p.name, backend_model: m.name });
46
42
  }
47
43
  }
48
44
  return results;
@@ -83,14 +79,9 @@ export function resolveByProviderModel(db, providerName, backendModel) {
83
79
  const providerRow = db.prepare("SELECT id, models FROM providers WHERE name = ? AND is_active = 1").get(providerName);
84
80
  if (!providerRow)
85
81
  return null;
86
- try {
87
- const models = JSON.parse(providerRow.models);
88
- if (!models.includes(backendModel))
89
- return null;
90
- }
91
- catch {
82
+ const modelEntries = parseModels(providerRow.models);
83
+ if (!modelEntries.some(m => m.name === backendModel))
92
84
  return null;
93
- }
94
85
  // 尝试从 mapping_groups 找到包含此 provider+backend_model 的 client_model
95
86
  const groups = db.prepare("SELECT client_model, rule FROM mapping_groups").all();
96
87
  for (const g of groups) {
@@ -7,6 +7,7 @@ export interface Provider {
7
7
  upstream_path: string | null;
8
8
  api_key: string;
9
9
  api_key_preview?: string;
10
+ /** @internal 原始 JSON 文本,业务层请使用 parseModels() 解析,禁止直接 JSON.parse */
10
11
  models: string;
11
12
  is_active: number;
12
13
  max_concurrency: number;
@@ -1,35 +1,20 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { buildUpdateQuery, deleteById } from "./helpers.js";
3
+ import { parseModels } from "../config/model-context.js";
3
4
  /** 默认流式超时 10 分钟 */
4
5
  export const DEFAULT_STREAM_TIMEOUT_MS = 600_000;
5
6
  /** 从 provider 的 models JSON 中查找指定模型的超时值 */
6
7
  export function getModelStreamTimeout(provider, backendModel) {
7
- try {
8
- const raw = JSON.parse(provider.models);
9
- if (!Array.isArray(raw))
10
- return DEFAULT_STREAM_TIMEOUT_MS;
11
- for (const m of raw) {
12
- if (typeof m === "string") {
13
- if (m === backendModel)
14
- return DEFAULT_STREAM_TIMEOUT_MS;
15
- continue;
16
- }
17
- const obj = m;
18
- if (!obj || typeof obj !== "object")
19
- continue;
20
- const modelId = (obj.name ?? obj.id);
21
- if (modelId === backendModel) {
22
- const timeout = obj.stream_timeout_ms;
23
- // stream_timeout_ms: 0 表示禁用超时,返回 Infinity;
24
- // undefined/null/未设置 表示使用默认值
25
- if (timeout === 0)
26
- return Number.POSITIVE_INFINITY;
27
- return timeout ?? DEFAULT_STREAM_TIMEOUT_MS;
28
- }
29
- }
30
- }
31
- catch { /* ignore parse errors — models field may be empty or invalid */ } // eslint-disable-line taste/no-silent-catch
32
- return DEFAULT_STREAM_TIMEOUT_MS;
8
+ const entries = parseModels(provider.models);
9
+ const entry = entries.find(m => m.name === backendModel);
10
+ if (!entry)
11
+ return DEFAULT_STREAM_TIMEOUT_MS;
12
+ const timeout = entry.stream_timeout_ms;
13
+ // stream_timeout_ms: 0 表示禁用超时,返回 Infinity;
14
+ // undefined/null/未设置 表示使用默认值
15
+ if (timeout === 0)
16
+ return Number.POSITIVE_INFINITY;
17
+ return timeout ?? DEFAULT_STREAM_TIMEOUT_MS;
33
18
  }
34
19
  export const PROVIDER_CONCURRENCY_DEFAULTS = {
35
20
  max_concurrency: 0,
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { buildUpdateQuery, deleteById } from "./helpers.js";
3
+ import { parseModels } from "../config/model-context.js";
3
4
  export function getRouterKeyByHash(db, hash) {
4
5
  return db.prepare("SELECT id, name, allowed_models FROM router_keys WHERE key_hash = ? AND is_active = 1").get(hash);
5
6
  }
@@ -27,11 +28,9 @@ export function getAvailableModels(db) {
27
28
  const rows = db.prepare("SELECT models FROM providers WHERE is_active = 1").all();
28
29
  const set = new Set();
29
30
  for (const r of rows) {
30
- try {
31
- JSON.parse(r.models || "[]").forEach((m) => set.add(m));
32
- }
33
- catch {
34
- continue;
31
+ const entries = parseModels(r.models);
32
+ for (const m of entries) {
33
+ set.add(m.name);
35
34
  }
36
35
  }
37
36
  return [...set].sort();
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import fp from "fastify-plugin";
3
3
  import { getAllProviders, insertRequestLog } from "../../db/index.js";
4
+ import { parseModels } from "../../config/model-context.js";
4
5
  import { createErrorFormatter } from "../proxy-core.js";
5
6
  import { handleProxyRequest } from "./proxy-handler.js";
6
7
  import { createOrchestrator } from "../orchestration/orchestrator.js";
@@ -61,10 +62,10 @@ const openaiProxyRaw = (app, opts, done) => {
61
62
  const modelMeta = new Map();
62
63
  for (const p of allProviders) {
63
64
  try {
64
- const models = JSON.parse(p.models || '[]');
65
- for (const m of models) {
66
- if (!modelMeta.has(m))
67
- modelMeta.set(m, { providerName: p.name, createdAt: p.created_at });
65
+ const modelEntries = parseModels(p.models || '[]');
66
+ for (const m of modelEntries) {
67
+ if (!modelMeta.has(m.name))
68
+ modelMeta.set(m.name, { providerName: p.name, createdAt: p.created_at });
68
69
  }
69
70
  }
70
71
  catch {
@@ -1,4 +1,5 @@
1
1
  import { getMappingGroup, getActiveProviderByName, getActiveProvidersWithModels, getActiveSchedulesForGroup } from "../../db/index.js";
2
+ import { parseModels } from "../../config/model-context.js";
2
3
  // ---------- Type guards ----------
3
4
  function isTarget(value) {
4
5
  return (typeof value === "object" &&
@@ -114,14 +115,9 @@ export function resolveMapping(db, clientModel, context) {
114
115
  const backendModel = slashMatch[2];
115
116
  const provider = getActiveProviderByName(db, providerName);
116
117
  if (provider) {
117
- try {
118
- const models = JSON.parse(provider.models);
119
- if (models.includes(backendModel)) {
120
- return { target: { backend_model: backendModel, provider_id: provider.id }, targetCount: 1 };
121
- }
122
- }
123
- catch {
124
- return null;
118
+ const modelEntries = parseModels(provider.models);
119
+ if (modelEntries.some(m => m.name === backendModel)) {
120
+ return { target: { backend_model: backendModel, provider_id: provider.id }, targetCount: 1 };
125
121
  }
126
122
  }
127
123
  return null;
@@ -132,14 +128,9 @@ export function resolveMapping(db, clientModel, context) {
132
128
  // fallback: 直接查 provider 的 models 字段
133
129
  const providers = getActiveProvidersWithModels(db);
134
130
  for (const p of providers) {
135
- try {
136
- const models = JSON.parse(p.models);
137
- if (models.includes(clientModel)) {
138
- return { target: { backend_model: clientModel, provider_id: p.id }, targetCount: 1 };
139
- }
140
- }
141
- catch {
142
- continue;
131
+ const modelEntries = parseModels(p.models);
132
+ if (modelEntries.some(m => m.name === clientModel)) {
133
+ return { target: { backend_model: clientModel, provider_id: p.id }, targetCount: 1 };
143
134
  }
144
135
  }
145
136
  return null;
@@ -1 +1 @@
1
- import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-lv9v_6nd.js";var s=[`data-size`],c=e({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(e){let c=e;return(l,u)=>(r(),n(`div`,{"data-slot":`card`,"data-size":e.size,class:t(o(a)(`ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col`,c.class))},[i(l.$slots,`default`)],10,s))}}),l=e({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-content`,class:t(o(a)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[i(e.$slots,`default`)],2))}});export{c as n,l as t};
1
+ import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-CjKaq4D4.js";var s=[`data-size`],c=e({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(e){let c=e;return(l,u)=>(r(),n(`div`,{"data-slot":`card`,"data-size":e.size,class:t(o(a)(`ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col`,c.class))},[i(l.$slots,`default`)],10,s))}}),l=e({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-content`,class:t(o(a)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[i(e.$slots,`default`)],2))}});export{c as n,l as t};
@@ -1 +1 @@
1
- import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-lv9v_6nd.js";var s=e({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-header`,class:t(o(a)(`gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]`,s.class))},[i(e.$slots,`default`)],2))}}),c=e({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-title`,class:t(o(a)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[i(e.$slots,`default`)],2))}});export{s as n,c as t};
1
+ import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-CjKaq4D4.js";var s=e({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-header`,class:t(o(a)(`gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]`,s.class))},[i(e.$slots,`default`)],2))}}),c=e({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-title`,class:t(o(a)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[i(e.$slots,`default`)],2))}});export{s as n,c as t};
@@ -1 +1 @@
1
- import{$ as e,H as t,Ht as n,J as r,K as i,Q as a,U as o,Y as s,dt as c,gt as l,i as u,m as d,mt as f,o as p,ot as m,r as h,tt as g,wt as _,x as v,zt as y}from"./button-lv9v_6nd.js";import{t as b}from"./VisuallyHiddenInput-MTmHNjqA.js";import{t as x}from"./RovingFocusItem-B3BLvyzD.js";import{B as S,G as C,H as w,L as T,Y as E,nt as D,q as O}from"./index-CDEwS862.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>E(e,t)):E(e,t)}var[A,j]=O(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=O(`CheckboxRoot`),I=e({inheritAttrs:!1,__name:`CheckboxRoot`,props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},value:{type:null,required:!1,default:`on`},id:{type:String,required:!1},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(e,{emit:n}){let a=e,h=n,{forwardRef:g,currentElement:v}=p(),S=A(null),T=d(a,`modelValue`,h,{defaultValue:a.defaultValue??a.falseValue,passive:a.modelValue===void 0}),D=i(()=>S?.disabled.value||a.disabled),O=i(()=>E(T.value,a.trueValue)),j=i(()=>C(S?.modelValue.value)?T.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,a.value));function P(){if(C(S?.modelValue.value))T.value===`indeterminate`?T.value=a.trueValue:T.value=O.value?a.falseValue:a.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,a.value)){let t=e.findIndex(e=>E(e,a.value));e.splice(t,1)}else e.push(a.value);S.modelValue.value=e}}let I=w(v),L=i(()=>a.id&&v.value?document.querySelector(`[for="${a.id}"]`)?.innerText:void 0);return F({disabled:D,state:j}),(e,n)=>(c(),r(l(y(S)?.rovingFocus.value?y(x):y(u)),m(e.$attrs,{id:e.id,ref:y(g),role:`checkbox`,"as-child":e.asChild,as:e.as,type:e.as===`button`?`button`:void 0,"aria-checked":y(M)(j.value)?`mixed`:j.value,"aria-required":e.required,"aria-label":e.$attrs[`aria-label`]||L.value,"data-state":y(N)(j.value),"data-disabled":D.value?``:void 0,disabled:D.value,focusable:y(S)?.rovingFocus.value?!D.value:void 0,onKeydown:t(o(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:_(()=>[f(e.$slots,`default`,{modelValue:y(T),state:j.value}),y(I)&&e.name&&!y(S)?(c(),r(y(b),{key:0,type:`checkbox`,checked:!!j.value,name:e.name,value:e.value,disabled:D.value,required:e.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):s(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=e({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){let{forwardRef:t}=p(),n=P();return(e,i)=>(c(),r(y(T),{present:e.forceMount||y(M)(y(n).state.value)||y(n).state.value===!0},{default:_(()=>[a(y(u),m({ref:y(t),"data-state":y(N)(y(n).state.value),"data-disabled":y(n).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":e.asChild,as:e.as},e.$attrs),{default:_(()=>[f(e.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=e({__name:`Checkbox`,props:{defaultValue:{},modelValue:{},disabled:{type:Boolean},value:{},id:{},trueValue:{},falseValue:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(e,{emit:t}){let i=e,o=t,s=S(v(i,`class`),o);return(e,t)=>(c(),r(y(I),m({"data-slot":`checkbox`},y(s),{class:y(h)(`border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-md border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50`,i.class)}),{default:_(t=>[a(y(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:_(()=>[f(e.$slots,`default`,n(g(t)),()=>[a(y(D))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
1
+ import{$ as e,H as t,Ht as n,J as r,K as i,Q as a,U as o,Y as s,dt as c,gt as l,i as u,m as d,mt as f,o as p,ot as m,r as h,tt as g,wt as _,x as v,zt as y}from"./button-CjKaq4D4.js";import{t as b}from"./VisuallyHiddenInput-DvHAsFOO.js";import{t as x}from"./RovingFocusItem-B4cr2rFZ.js";import{B as S,G as C,H as w,L as T,Y as E,nt as D,q as O}from"./index-C19mbJF3.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>E(e,t)):E(e,t)}var[A,j]=O(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=O(`CheckboxRoot`),I=e({inheritAttrs:!1,__name:`CheckboxRoot`,props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},value:{type:null,required:!1,default:`on`},id:{type:String,required:!1},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(e,{emit:n}){let a=e,h=n,{forwardRef:g,currentElement:v}=p(),S=A(null),T=d(a,`modelValue`,h,{defaultValue:a.defaultValue??a.falseValue,passive:a.modelValue===void 0}),D=i(()=>S?.disabled.value||a.disabled),O=i(()=>E(T.value,a.trueValue)),j=i(()=>C(S?.modelValue.value)?T.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,a.value));function P(){if(C(S?.modelValue.value))T.value===`indeterminate`?T.value=a.trueValue:T.value=O.value?a.falseValue:a.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,a.value)){let t=e.findIndex(e=>E(e,a.value));e.splice(t,1)}else e.push(a.value);S.modelValue.value=e}}let I=w(v),L=i(()=>a.id&&v.value?document.querySelector(`[for="${a.id}"]`)?.innerText:void 0);return F({disabled:D,state:j}),(e,n)=>(c(),r(l(y(S)?.rovingFocus.value?y(x):y(u)),m(e.$attrs,{id:e.id,ref:y(g),role:`checkbox`,"as-child":e.asChild,as:e.as,type:e.as===`button`?`button`:void 0,"aria-checked":y(M)(j.value)?`mixed`:j.value,"aria-required":e.required,"aria-label":e.$attrs[`aria-label`]||L.value,"data-state":y(N)(j.value),"data-disabled":D.value?``:void 0,disabled:D.value,focusable:y(S)?.rovingFocus.value?!D.value:void 0,onKeydown:t(o(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:_(()=>[f(e.$slots,`default`,{modelValue:y(T),state:j.value}),y(I)&&e.name&&!y(S)?(c(),r(y(b),{key:0,type:`checkbox`,checked:!!j.value,name:e.name,value:e.value,disabled:D.value,required:e.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):s(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=e({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){let{forwardRef:t}=p(),n=P();return(e,i)=>(c(),r(y(T),{present:e.forceMount||y(M)(y(n).state.value)||y(n).state.value===!0},{default:_(()=>[a(y(u),m({ref:y(t),"data-state":y(N)(y(n).state.value),"data-disabled":y(n).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":e.asChild,as:e.as},e.$attrs),{default:_(()=>[f(e.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=e({__name:`Checkbox`,props:{defaultValue:{},modelValue:{},disabled:{type:Boolean},value:{},id:{},trueValue:{},falseValue:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(e,{emit:t}){let i=e,o=t,s=S(v(i,`class`),o);return(e,t)=>(c(),r(y(I),m({"data-slot":`checkbox`},y(s),{class:y(h)(`border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-md border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50`,i.class)}),{default:_(t=>[a(y(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:_(()=>[f(e.$slots,`default`,n(g(t)),()=>[a(y(D))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
@@ -1 +1 @@
1
- import{$ as e,Ht as t,J as n,K as r,Lt as i,Mt as a,Q as o,Y as s,d as c,dt as l,i as u,lt as d,m as f,mt as p,o as m,ot as h,st as g,tt as _,wt as v,xt as y,zt as b}from"./button-lv9v_6nd.js";import{B as x,L as S,q as C,z as w}from"./index-CDEwS862.js";var[T,E]=C(`CollapsibleRoot`),D=e({__name:`CollapsibleRoot`,props:{defaultOpen:{type:Boolean,required:!1,default:!1},open:{type:Boolean,required:!1,default:void 0},disabled:{type:Boolean,required:!1},unmountOnHide:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:open`],setup(e,{expose:t,emit:r}){let a=e,o=f(a,`open`,r,{defaultValue:a.defaultOpen,passive:a.open===void 0}),{disabled:s,unmountOnHide:c}=i(a);return E({contentId:``,disabled:s,open:o,unmountOnHide:c,onOpenToggle:()=>{s.value||(o.value=!o.value)}}),t({open:o}),m(),(e,t)=>(l(),n(b(u),{as:e.as,"as-child":a.asChild,"data-state":b(o)?`open`:`closed`,"data-disabled":b(s)?``:void 0},{default:v(()=>[p(e.$slots,`default`,{open:b(o)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=e({inheritAttrs:!1,__name:`CollapsibleContent`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`contentFound`],setup(e,{emit:t}){let i=e,f=t,_=T();_.contentId||=w(void 0,`reka-collapsible-content`);let x=a(),{forwardRef:C,currentElement:E}=m(),D=a(0),O=a(0),k=r(()=>_.open.value),A=a(k.value),j=a();y(()=>[k.value,x.value?.present],async()=>{await g();let e=E.value;if(!e)return;j.value=j.value||{transitionDuration:e.style.transitionDuration,animationName:e.style.animationName},e.style.transitionDuration=`0s`,e.style.animationName=`none`;let t=e.getBoundingClientRect();O.value=t.height,D.value=t.width,A.value||(e.style.transitionDuration=j.value.transitionDuration,e.style.animationName=j.value.animationName)},{immediate:!0});let M=r(()=>A.value&&_.open.value);return d(()=>{requestAnimationFrame(()=>{A.value=!1})}),c(E,`beforematch`,e=>{requestAnimationFrame(()=>{_.onOpenToggle(),f(`contentFound`)})}),(e,t)=>(l(),n(b(S),{ref_key:`presentRef`,ref:x,present:e.forceMount||b(_).open.value,"force-mount":!0},{default:v(({present:t})=>[o(b(u),h(e.$attrs,{id:b(_).contentId,ref:b(C),"as-child":i.asChild,as:e.as,hidden:t?void 0:b(_).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:b(_).open.value?`open`:`closed`,"data-disabled":b(_).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:v(()=>[!b(_).unmountOnHide.value||t?p(e.$slots,`default`,{key:0}):s(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=e({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(e,{emit:r}){let i=x(e,r);return(e,r)=>(l(),n(b(D),h({"data-slot":`collapsible`},b(i)),{default:v(n=>[p(e.$slots,`default`,t(_(n)))]),_:3},16))}}),A=e({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(e){let t=e;return(e,r)=>(l(),n(b(O),h({"data-slot":`collapsible-content`},t),{default:v(()=>[p(e.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
1
+ import{$ as e,Ht as t,J as n,K as r,Lt as i,Mt as a,Q as o,Y as s,d as c,dt as l,i as u,lt as d,m as f,mt as p,o as m,ot as h,st as g,tt as _,wt as v,xt as y,zt as b}from"./button-CjKaq4D4.js";import{B as x,L as S,q as C,z as w}from"./index-C19mbJF3.js";var[T,E]=C(`CollapsibleRoot`),D=e({__name:`CollapsibleRoot`,props:{defaultOpen:{type:Boolean,required:!1,default:!1},open:{type:Boolean,required:!1,default:void 0},disabled:{type:Boolean,required:!1},unmountOnHide:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:open`],setup(e,{expose:t,emit:r}){let a=e,o=f(a,`open`,r,{defaultValue:a.defaultOpen,passive:a.open===void 0}),{disabled:s,unmountOnHide:c}=i(a);return E({contentId:``,disabled:s,open:o,unmountOnHide:c,onOpenToggle:()=>{s.value||(o.value=!o.value)}}),t({open:o}),m(),(e,t)=>(l(),n(b(u),{as:e.as,"as-child":a.asChild,"data-state":b(o)?`open`:`closed`,"data-disabled":b(s)?``:void 0},{default:v(()=>[p(e.$slots,`default`,{open:b(o)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=e({inheritAttrs:!1,__name:`CollapsibleContent`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`contentFound`],setup(e,{emit:t}){let i=e,f=t,_=T();_.contentId||=w(void 0,`reka-collapsible-content`);let x=a(),{forwardRef:C,currentElement:E}=m(),D=a(0),O=a(0),k=r(()=>_.open.value),A=a(k.value),j=a();y(()=>[k.value,x.value?.present],async()=>{await g();let e=E.value;if(!e)return;j.value=j.value||{transitionDuration:e.style.transitionDuration,animationName:e.style.animationName},e.style.transitionDuration=`0s`,e.style.animationName=`none`;let t=e.getBoundingClientRect();O.value=t.height,D.value=t.width,A.value||(e.style.transitionDuration=j.value.transitionDuration,e.style.animationName=j.value.animationName)},{immediate:!0});let M=r(()=>A.value&&_.open.value);return d(()=>{requestAnimationFrame(()=>{A.value=!1})}),c(E,`beforematch`,e=>{requestAnimationFrame(()=>{_.onOpenToggle(),f(`contentFound`)})}),(e,t)=>(l(),n(b(S),{ref_key:`presentRef`,ref:x,present:e.forceMount||b(_).open.value,"force-mount":!0},{default:v(({present:t})=>[o(b(u),h(e.$attrs,{id:b(_).contentId,ref:b(C),"as-child":i.asChild,as:e.as,hidden:t?void 0:b(_).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:b(_).open.value?`open`:`closed`,"data-disabled":b(_).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:v(()=>[!b(_).unmountOnHide.value||t?p(e.$slots,`default`,{key:0}):s(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=e({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(e,{emit:r}){let i=x(e,r);return(e,r)=>(l(),n(b(D),h({"data-slot":`collapsible`},b(i)),{default:v(n=>[p(e.$slots,`default`,t(_(n)))]),_:3},16))}}),A=e({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(e){let t=e;return(e,r)=>(l(),n(b(O),h({"data-slot":`collapsible-content`},t),{default:v(()=>[p(e.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
@@ -1 +1 @@
1
- import{$ as e,J as t,dt as n,i as r,mt as i,o as a,ot as o,wt as s,zt as c}from"./button-lv9v_6nd.js";import{r as l}from"./CollapsibleContent-Cy8Zj7F7.js";var u=e({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(e){let o=e;a();let u=l();return(e,a)=>(n(),t(c(r),{type:e.as===`button`?`button`:void 0,as:e.as,"as-child":o.asChild,"aria-controls":c(u).contentId,"aria-expanded":c(u).open.value,"data-state":c(u).open.value?`open`:`closed`,"data-disabled":c(u).disabled?.value?``:void 0,disabled:c(u).disabled?.value,onClick:c(u).onOpenToggle},{default:s(()=>[i(e.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),d=e({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(e){let r=e;return(e,a)=>(n(),t(c(u),o({"data-slot":`collapsible-trigger`},r),{default:s(()=>[i(e.$slots,`default`)]),_:3},16))}});export{d as t};
1
+ import{$ as e,J as t,dt as n,i as r,mt as i,o as a,ot as o,wt as s,zt as c}from"./button-CjKaq4D4.js";import{r as l}from"./CollapsibleContent-CUb_IZ--.js";var u=e({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(e){let o=e;a();let u=l();return(e,a)=>(n(),t(c(r),{type:e.as===`button`?`button`:void 0,as:e.as,"as-child":o.asChild,"aria-controls":c(u).contentId,"aria-expanded":c(u).open.value,"data-state":c(u).open.value?`open`:`closed`,"data-disabled":c(u).disabled?.value?``:void 0,disabled:c(u).disabled?.value,onClick:c(u).onOpenToggle},{default:s(()=>[i(e.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),d=e({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(e){let r=e;return(e,a)=>(n(),t(c(u),o({"data-slot":`collapsible-trigger`},r),{default:s(()=>[i(e.$slots,`default`)]),_:3},16))}});export{d as t};