@camstack/ui-library 1.1.27 → 1.1.28
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.
- package/dist/composites/grouped-model-selector.d.ts +8 -0
- package/dist/composites/index.d.ts +2 -0
- package/dist/composites/pipeline-builder.d.ts +8 -1
- package/dist/composites/pipeline-step.d.ts +15 -5
- package/dist/composites/pipeline-tree-matrix.d.ts +2 -0
- package/dist/generated/system-hooks.d.ts +6 -4
- package/dist/hooks/use-ptz.d.ts +6 -0
- package/dist/index.cjs +361 -121
- package/dist/index.js +359 -121
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3748,37 +3748,41 @@ function mirror(input) {
|
|
|
3748
3748
|
});
|
|
3749
3749
|
continue;
|
|
3750
3750
|
}
|
|
3751
|
-
const srcModel = findModel(targetAddon, srcCfg.modelId);
|
|
3752
|
-
const canUseSource = srcModel !== null && Boolean(srcModel.formats[target.engine.format]);
|
|
3753
3751
|
let chosenModelId;
|
|
3754
3752
|
let outcome;
|
|
3755
|
-
if (
|
|
3756
|
-
chosenModelId =
|
|
3753
|
+
if (srcCfg.modelId === void 0) {
|
|
3754
|
+
chosenModelId = void 0;
|
|
3757
3755
|
outcome = "exact";
|
|
3758
3756
|
} else {
|
|
3759
|
-
const
|
|
3760
|
-
if (
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3757
|
+
const srcModel = findModel(targetAddon, srcCfg.modelId);
|
|
3758
|
+
if (srcModel !== null && Boolean(srcModel.formats[target.engine.format])) {
|
|
3759
|
+
chosenModelId = srcCfg.modelId;
|
|
3760
|
+
outcome = "exact";
|
|
3761
|
+
} else {
|
|
3762
|
+
const fallback = firstModelFor(targetAddon, target.engine.format);
|
|
3763
|
+
if (!fallback) {
|
|
3764
|
+
out.push({
|
|
3765
|
+
addonId,
|
|
3766
|
+
outcome: "skip",
|
|
3767
|
+
modelId: null,
|
|
3768
|
+
reason: "no compatible model for target format",
|
|
3769
|
+
patch: null
|
|
3770
|
+
});
|
|
3771
|
+
continue;
|
|
3772
|
+
}
|
|
3773
|
+
chosenModelId = fallback.id;
|
|
3774
|
+
outcome = "mapped";
|
|
3769
3775
|
}
|
|
3770
|
-
chosenModelId = fallback.id;
|
|
3771
|
-
outcome = "mapped";
|
|
3772
3776
|
}
|
|
3773
3777
|
const patch = {
|
|
3774
3778
|
enabled: srcCfg.enabled,
|
|
3775
|
-
modelId: chosenModelId,
|
|
3779
|
+
...chosenModelId ? { modelId: chosenModelId } : {},
|
|
3776
3780
|
settings: dropModelSpecific(srcCfg.settings, targetAddon)
|
|
3777
3781
|
};
|
|
3778
3782
|
out.push({
|
|
3779
3783
|
addonId,
|
|
3780
3784
|
outcome,
|
|
3781
|
-
modelId: chosenModelId,
|
|
3785
|
+
modelId: chosenModelId ?? null,
|
|
3782
3786
|
patch
|
|
3783
3787
|
});
|
|
3784
3788
|
}
|
|
@@ -13268,10 +13272,11 @@ function modelsForStep(schema) {
|
|
|
13268
13272
|
name: m.name
|
|
13269
13273
|
}));
|
|
13270
13274
|
}
|
|
13271
|
-
function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0, onChange, onDelete: _onDelete, readOnly = false, toggleMode = "simple", overrideState = null, onOverrideChange, inheritedEnabled, hideModelAndSettings = false }) {
|
|
13275
|
+
function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0, onChange, onDelete: _onDelete, readOnly = false, toggleMode = "simple", overrideState = null, onOverrideChange, inheritedEnabled, hideModelAndSettings = false, allowAutoModel = false }) {
|
|
13272
13276
|
const [expanded, setExpanded] = (0, react$1.useState)(false);
|
|
13273
13277
|
const models = modelsForStep(schema);
|
|
13274
|
-
|
|
13278
|
+
const isAutoSentinel = allowAutoModel && step.modelId === "";
|
|
13279
|
+
if (models.length > 0 && !isAutoSentinel && !models.some((m) => m.id === step.modelId) && !readOnly) {
|
|
13275
13280
|
const fallback = (schema?.defaultModelId ? models.find((m) => m.id === schema.defaultModelId) : null) ?? models[0];
|
|
13276
13281
|
if (fallback && fallback.id !== step.modelId) queueMicrotask(() => onChange({
|
|
13277
13282
|
...step,
|
|
@@ -13356,59 +13361,28 @@ function PipelineStep({ step, schema, allSchemas: _allSchemas, depth: _depth = 0
|
|
|
13356
13361
|
children: "Model and detection settings are managed per agent — open the Pipeline page for this camera's agent to edit them."
|
|
13357
13362
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13358
13363
|
className: "space-y-3",
|
|
13359
|
-
children: [
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
},
|
|
13382
|
-
{
|
|
13383
|
-
value: "node/coreml",
|
|
13384
|
-
label: "Node.js — Apple SoundAnalysis (macOS)"
|
|
13385
|
-
},
|
|
13386
|
-
{
|
|
13387
|
-
value: "python/cpu",
|
|
13388
|
-
label: "Python — ONNX CPU"
|
|
13389
|
-
}
|
|
13390
|
-
],
|
|
13391
|
-
onChange: (v) => {
|
|
13392
|
-
const [runtime, backend] = v.split("/");
|
|
13393
|
-
const format = backend === "coreml" ? "coreml" : "onnx";
|
|
13394
|
-
onChange({
|
|
13395
|
-
...step,
|
|
13396
|
-
engine: {
|
|
13397
|
-
runtime,
|
|
13398
|
-
backend,
|
|
13399
|
-
format
|
|
13400
|
-
}
|
|
13401
|
-
});
|
|
13402
|
-
}
|
|
13403
|
-
}),
|
|
13404
|
-
schema?.configSchema?.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSchemaField, {
|
|
13405
|
-
field,
|
|
13406
|
-
allFields: schema.configSchema ?? [],
|
|
13407
|
-
step,
|
|
13408
|
-
disabled: readOnly,
|
|
13409
|
-
onChange
|
|
13410
|
-
}, field.key))
|
|
13411
|
-
]
|
|
13364
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSelect, {
|
|
13365
|
+
label: "Model",
|
|
13366
|
+
value: step.modelId,
|
|
13367
|
+
disabled: readOnly,
|
|
13368
|
+
options: [...allowAutoModel ? [{
|
|
13369
|
+
value: "",
|
|
13370
|
+
label: "Auto (node default)"
|
|
13371
|
+
}] : [], ...models.map((m) => ({
|
|
13372
|
+
value: m.id,
|
|
13373
|
+
label: m.name
|
|
13374
|
+
}))],
|
|
13375
|
+
onChange: (v) => onChange({
|
|
13376
|
+
...step,
|
|
13377
|
+
modelId: v
|
|
13378
|
+
})
|
|
13379
|
+
}), schema?.configSchema?.map((field) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConfigSchemaField, {
|
|
13380
|
+
field,
|
|
13381
|
+
allFields: schema.configSchema ?? [],
|
|
13382
|
+
step,
|
|
13383
|
+
disabled: readOnly,
|
|
13384
|
+
onChange
|
|
13385
|
+
}, field.key))]
|
|
13412
13386
|
})
|
|
13413
13387
|
});
|
|
13414
13388
|
}
|
|
@@ -13607,7 +13581,181 @@ function ThreeStateButton({ label, active, variant, subtext, onClick }) {
|
|
|
13607
13581
|
});
|
|
13608
13582
|
}
|
|
13609
13583
|
//#endregion
|
|
13584
|
+
//#region src/composites/grouped-model-selector.tsx
|
|
13585
|
+
/**
|
|
13586
|
+
* GroupedModelSelector — the shared Family → Tier → Variant model picker.
|
|
13587
|
+
*
|
|
13588
|
+
* The catalog is a FLAT list of models (ids like `yolo26s`, `yolo26s-int8`);
|
|
13589
|
+
* this folds it into a `family → tier → variant` tree (see
|
|
13590
|
+
* `buildModelVariantGroups` in `@camstack/types`) so the operator picks
|
|
13591
|
+
* "YOLO26 → Small → Int8" instead of scanning a flat dropdown of every
|
|
13592
|
+
* size×quantization. The selected value stays the flat model id.
|
|
13593
|
+
*
|
|
13594
|
+
* Parameterised on the minimal `ModelVariantSource` shape so BOTH the config-UI
|
|
13595
|
+
* catalog (`ModelCatalogEntry`) and the pipeline/device steppers
|
|
13596
|
+
* (`PipelineModelOption`) drive the same component. Legacy / ungrouped models
|
|
13597
|
+
* never appear here (the grouping helpers skip them).
|
|
13598
|
+
*/
|
|
13599
|
+
function Chip({ active, onClick, disabled, children, title }) {
|
|
13600
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
13601
|
+
type: "button",
|
|
13602
|
+
onClick,
|
|
13603
|
+
disabled,
|
|
13604
|
+
title,
|
|
13605
|
+
className: cn("rounded-full px-3 py-1 text-[11px] font-medium border transition-colors", active ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-foreground-subtle hover:text-foreground hover:border-foreground-subtle/40", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
|
|
13606
|
+
children
|
|
13607
|
+
});
|
|
13608
|
+
}
|
|
13609
|
+
function GroupedModelSelector({ catalog, value, onChange, disabled }) {
|
|
13610
|
+
const families = (0, _camstack_types.buildModelVariantGroups)(catalog);
|
|
13611
|
+
const current = (0, _camstack_types.describeModelVariant)(catalog, value);
|
|
13612
|
+
const activeFamily = families.find((f) => f.family === current?.family)?.family ?? families[0]?.family ?? "";
|
|
13613
|
+
const family = families.find((f) => f.family === activeFamily) ?? families[0];
|
|
13614
|
+
if (!family) return null;
|
|
13615
|
+
const activeTier = family.tiers.find((t) => t.tier === current?.tier)?.tier ?? family.tiers[0]?.tier ?? "";
|
|
13616
|
+
const tier = family.tiers.find((t) => t.tier === activeTier) ?? family.tiers[0];
|
|
13617
|
+
if (!tier) return null;
|
|
13618
|
+
const selectTier = (tierId) => {
|
|
13619
|
+
const t = family.tiers.find((x) => x.tier === tierId);
|
|
13620
|
+
if (!t) return;
|
|
13621
|
+
const want = {
|
|
13622
|
+
precision: current?.precision,
|
|
13623
|
+
optimization: current?.optimization
|
|
13624
|
+
};
|
|
13625
|
+
onChange((t.options.find((o) => o.precision === (want.precision ?? "fp32") && o.optimization === (want.optimization ?? "standard")) ?? t.options[0]).modelId);
|
|
13626
|
+
};
|
|
13627
|
+
const selectVariant = (opt) => {
|
|
13628
|
+
const id = (0, _camstack_types.resolveVariantModelId)(catalog, {
|
|
13629
|
+
family: family.family,
|
|
13630
|
+
tier: tier.tier,
|
|
13631
|
+
precision: opt.precision,
|
|
13632
|
+
optimization: opt.optimization
|
|
13633
|
+
});
|
|
13634
|
+
if (id) onChange(id);
|
|
13635
|
+
};
|
|
13636
|
+
const selectedOption = tier.options.find((o) => o.modelId === value) ?? null;
|
|
13637
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13638
|
+
className: "space-y-3",
|
|
13639
|
+
children: [
|
|
13640
|
+
families.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
13641
|
+
className: "text-[10px] uppercase tracking-wide text-foreground-subtle mb-1.5",
|
|
13642
|
+
children: "Family"
|
|
13643
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13644
|
+
className: "flex flex-wrap gap-1.5",
|
|
13645
|
+
children: families.map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chip, {
|
|
13646
|
+
active: f.family === family.family,
|
|
13647
|
+
disabled,
|
|
13648
|
+
onClick: () => onChange(f.tiers[0]?.baseModelId ?? ""),
|
|
13649
|
+
children: f.label
|
|
13650
|
+
}, f.family))
|
|
13651
|
+
})] }),
|
|
13652
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
13653
|
+
className: "text-[10px] uppercase tracking-wide text-foreground-subtle mb-1.5",
|
|
13654
|
+
children: [family.label, " — size"]
|
|
13655
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13656
|
+
className: "grid grid-cols-2 gap-1.5 sm:grid-cols-4",
|
|
13657
|
+
children: family.tiers.map((t) => {
|
|
13658
|
+
const active = t.tier === tier.tier;
|
|
13659
|
+
const base = t.options.find((o) => o.modelId === t.baseModelId) ?? t.options[0];
|
|
13660
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
13661
|
+
type: "button",
|
|
13662
|
+
disabled,
|
|
13663
|
+
onClick: () => selectTier(t.tier),
|
|
13664
|
+
className: cn("rounded-lg border px-2 py-2 text-left transition-all", active ? "border-primary bg-primary/5 ring-1 ring-primary/30" : "border-border bg-background hover:border-foreground-subtle/40", disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"),
|
|
13665
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13666
|
+
className: "flex items-center gap-1",
|
|
13667
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
13668
|
+
className: "text-xs font-semibold text-foreground",
|
|
13669
|
+
children: t.label
|
|
13670
|
+
}), active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Check, { className: "h-3 w-3 text-primary" })]
|
|
13671
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
13672
|
+
className: "text-[10px] text-foreground-subtle",
|
|
13673
|
+
children: [
|
|
13674
|
+
"~",
|
|
13675
|
+
base?.sizeMB ?? 0,
|
|
13676
|
+
" MB"
|
|
13677
|
+
]
|
|
13678
|
+
})]
|
|
13679
|
+
}, t.tier);
|
|
13680
|
+
})
|
|
13681
|
+
})] }),
|
|
13682
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
13683
|
+
className: "text-[10px] uppercase tracking-wide text-foreground-subtle mb-1.5",
|
|
13684
|
+
children: "Variant"
|
|
13685
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13686
|
+
className: "flex flex-wrap gap-1.5",
|
|
13687
|
+
children: tier.options.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chip, {
|
|
13688
|
+
active: opt.modelId === value,
|
|
13689
|
+
disabled,
|
|
13690
|
+
title: `${opt.formats.join(", ")} · ~${opt.sizeMB} MB`,
|
|
13691
|
+
onClick: () => selectVariant(opt),
|
|
13692
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
13693
|
+
className: "inline-flex items-center gap-1",
|
|
13694
|
+
children: [opt.optimization === "fast" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Zap, { className: "h-3 w-3" }), opt.label]
|
|
13695
|
+
})
|
|
13696
|
+
}, opt.modelId))
|
|
13697
|
+
})] }),
|
|
13698
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13699
|
+
className: "flex items-center gap-2 text-[10px] text-foreground-subtle pt-0.5",
|
|
13700
|
+
children: [
|
|
13701
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Cpu, { className: "h-3 w-3" }),
|
|
13702
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
13703
|
+
className: "font-mono",
|
|
13704
|
+
children: value || "—"
|
|
13705
|
+
}),
|
|
13706
|
+
selectedOption && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
13707
|
+
"· ",
|
|
13708
|
+
selectedOption.formats.join(", "),
|
|
13709
|
+
" · ~",
|
|
13710
|
+
selectedOption.sizeMB,
|
|
13711
|
+
" MB"
|
|
13712
|
+
] })
|
|
13713
|
+
]
|
|
13714
|
+
})
|
|
13715
|
+
]
|
|
13716
|
+
});
|
|
13717
|
+
}
|
|
13718
|
+
//#endregion
|
|
13610
13719
|
//#region src/composites/agent-step-editor.tsx
|
|
13720
|
+
/**
|
|
13721
|
+
* Shared model picker for the step editor — renders the grouped
|
|
13722
|
+
* Family→Tier→Variant selector when the step's models declare variant groups
|
|
13723
|
+
* (yolo26 …), else a flat `<select>` (face / plate / classifier catalogs and
|
|
13724
|
+
* custom models). Same component both the agent-default and per-device-override
|
|
13725
|
+
* modes use, so the picker looks identical across the pipeline stepper, the
|
|
13726
|
+
* device stepper and the cluster matrix.
|
|
13727
|
+
*/
|
|
13728
|
+
function ModelPicker({ models, value, onChange, disabled }) {
|
|
13729
|
+
const hasGroups = (0, react$1.useMemo)(() => (0, _camstack_types.buildModelVariantGroups)(models).length > 0, [models]);
|
|
13730
|
+
const ungrouped = (0, react$1.useMemo)(() => models.filter((m) => m.group === void 0), [models]);
|
|
13731
|
+
const flatSelect = (opts, selectPlaceholder) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
13732
|
+
disabled,
|
|
13733
|
+
className: "w-full bg-surface border border-border rounded px-2 py-1 text-xs disabled:opacity-50",
|
|
13734
|
+
value: opts.some((m) => m.id === value) ? value : "",
|
|
13735
|
+
onChange: (e) => onChange(e.target.value),
|
|
13736
|
+
children: [selectPlaceholder !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
13737
|
+
value: "",
|
|
13738
|
+
disabled: true,
|
|
13739
|
+
children: selectPlaceholder
|
|
13740
|
+
}), opts.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
13741
|
+
value: m.id,
|
|
13742
|
+
children: m.name
|
|
13743
|
+
}, m.id))]
|
|
13744
|
+
});
|
|
13745
|
+
if (!hasGroups) return flatSelect(models);
|
|
13746
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13747
|
+
className: "space-y-3",
|
|
13748
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupedModelSelector, {
|
|
13749
|
+
catalog: models,
|
|
13750
|
+
value,
|
|
13751
|
+
onChange,
|
|
13752
|
+
disabled
|
|
13753
|
+
}), ungrouped.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13754
|
+
className: "text-[10px] uppercase tracking-widest text-foreground-subtle mb-1",
|
|
13755
|
+
children: "Other models"
|
|
13756
|
+
}), flatSelect(ungrouped, "— custom / ungrouped model —")] })]
|
|
13757
|
+
});
|
|
13758
|
+
}
|
|
13611
13759
|
function buildDisplayStep(addon, cfg) {
|
|
13612
13760
|
return {
|
|
13613
13761
|
addonId: addon.id,
|
|
@@ -13616,7 +13764,7 @@ function buildDisplayStep(addon, cfg) {
|
|
|
13616
13764
|
inputClasses: [...addon.inputClasses],
|
|
13617
13765
|
outputClasses: [...addon.outputClasses],
|
|
13618
13766
|
enabled: cfg.enabled,
|
|
13619
|
-
modelId: cfg.modelId,
|
|
13767
|
+
modelId: cfg.modelId ?? addon.defaultModelId,
|
|
13620
13768
|
children: [],
|
|
13621
13769
|
settings: { ...cfg.settings }
|
|
13622
13770
|
};
|
|
@@ -13654,14 +13802,10 @@ function AgentModeEditor({ addon, agentDefault, modelsForFormat, onChangeAgentCo
|
|
|
13654
13802
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13655
13803
|
className: "text-[10px] uppercase tracking-widest text-foreground-subtle mb-1",
|
|
13656
13804
|
children: "Model"
|
|
13657
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
13658
|
-
|
|
13659
|
-
value: agentDefault.modelId,
|
|
13660
|
-
onChange: (
|
|
13661
|
-
children: modelsForFormat.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
13662
|
-
value: m.id,
|
|
13663
|
-
children: m.name
|
|
13664
|
-
}, m.id))
|
|
13805
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPicker, {
|
|
13806
|
+
models: modelsForFormat,
|
|
13807
|
+
value: agentDefault.modelId ?? "",
|
|
13808
|
+
onChange: (modelId) => update({ modelId })
|
|
13665
13809
|
})] }),
|
|
13666
13810
|
(addon.configSchema?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13667
13811
|
className: "pt-2 border-t border-border/50 space-y-3",
|
|
@@ -13752,15 +13896,11 @@ function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, mode
|
|
|
13752
13896
|
children: "Override"
|
|
13753
13897
|
})]
|
|
13754
13898
|
}),
|
|
13755
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
13899
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPicker, {
|
|
13900
|
+
models: modelsForFormat,
|
|
13756
13901
|
disabled: !modelOverridden,
|
|
13757
|
-
|
|
13758
|
-
|
|
13759
|
-
onChange: (e) => setModel(e.target.value),
|
|
13760
|
-
children: modelsForFormat.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
13761
|
-
value: m.id,
|
|
13762
|
-
children: m.name
|
|
13763
|
-
}, m.id))
|
|
13902
|
+
value: (modelOverridden ? currentPatch?.modelId ?? agentDefault.modelId : agentDefault.modelId) ?? "",
|
|
13903
|
+
onChange: (modelId) => setModel(modelId)
|
|
13764
13904
|
}),
|
|
13765
13905
|
!modelOverridden && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
13766
13906
|
className: "text-[10px] text-foreground-subtle mt-1",
|
|
@@ -13940,17 +14080,33 @@ function QuickToggle({ enabled, onChange, disabled }) {
|
|
|
13940
14080
|
function renderCellContent(state) {
|
|
13941
14081
|
if (state.kind === "enabled") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
13942
14082
|
className: "flex min-w-0 items-center gap-1",
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
14083
|
+
title: state.overridden ? "override" : void 0,
|
|
14084
|
+
children: [
|
|
14085
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 rounded-full shrink-0", state.overridden ? "bg-amber-500" : "bg-emerald-500") }),
|
|
14086
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14087
|
+
className: "font-mono text-foreground truncate",
|
|
14088
|
+
children: state.modelId
|
|
14089
|
+
}),
|
|
14090
|
+
state.overridden && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14091
|
+
className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-amber-500",
|
|
14092
|
+
children: "ovr"
|
|
14093
|
+
})
|
|
14094
|
+
]
|
|
13947
14095
|
});
|
|
13948
14096
|
if (state.kind === "disabled") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
13949
14097
|
className: "flex min-w-0 items-center gap-1 text-foreground-subtle",
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
14098
|
+
title: state.overridden ? "override" : void 0,
|
|
14099
|
+
children: [
|
|
14100
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cn("h-1.5 w-1.5 rounded-full shrink-0", state.overridden ? "bg-amber-500" : "border border-foreground-subtle/60") }),
|
|
14101
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14102
|
+
className: "truncate",
|
|
14103
|
+
children: "off"
|
|
14104
|
+
}),
|
|
14105
|
+
state.overridden && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14106
|
+
className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-amber-500",
|
|
14107
|
+
children: "ovr"
|
|
14108
|
+
})
|
|
14109
|
+
]
|
|
13954
14110
|
});
|
|
13955
14111
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
13956
14112
|
className: "flex min-w-0 items-center gap-1 text-foreground-subtle/70",
|
|
@@ -15597,6 +15753,22 @@ function usePTZ(trpc, deviceId, hookOptions) {
|
|
|
15597
15753
|
refreshPresets,
|
|
15598
15754
|
wrap
|
|
15599
15755
|
]),
|
|
15756
|
+
updatePreset: (0, react$1.useCallback)(async (presetId) => {
|
|
15757
|
+
if (!ptz) return;
|
|
15758
|
+
await wrap(async () => {
|
|
15759
|
+
const existing = presets.find((p) => p.id === presetId);
|
|
15760
|
+
await ptz.savePreset({
|
|
15761
|
+
presetId,
|
|
15762
|
+
name: existing?.name ?? ""
|
|
15763
|
+
});
|
|
15764
|
+
await refreshPresets();
|
|
15765
|
+
});
|
|
15766
|
+
}, [
|
|
15767
|
+
ptz,
|
|
15768
|
+
presets,
|
|
15769
|
+
refreshPresets,
|
|
15770
|
+
wrap
|
|
15771
|
+
]),
|
|
15600
15772
|
deletePreset: (0, react$1.useCallback)(async (presetId) => {
|
|
15601
15773
|
if (!ptz) return;
|
|
15602
15774
|
await wrap(async () => {
|
|
@@ -15691,10 +15863,13 @@ function DPadButton({ direction, icon: Icon, disabled, className, variant, onMov
|
|
|
15691
15863
|
});
|
|
15692
15864
|
}
|
|
15693
15865
|
function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true, showHome = true, className }) {
|
|
15694
|
-
const { move, startContinuous, stopContinuous, zoom, goHome, goToPreset, savePreset, deletePreset, presets, options, busy, error } = controls;
|
|
15866
|
+
const { move, startContinuous, stopContinuous, zoom, goHome, goToPreset, savePreset, updatePreset, deletePreset, presets, options, busy, error } = controls;
|
|
15695
15867
|
const confirm = useConfirm();
|
|
15696
15868
|
const [presetsOpen, setPresetsOpen] = (0, react$1.useState)(false);
|
|
15697
15869
|
const [presetName, setPresetName] = (0, react$1.useState)("");
|
|
15870
|
+
const presetTriggerRef = (0, react$1.useRef)(null);
|
|
15871
|
+
const presetMenuRef = (0, react$1.useRef)(null);
|
|
15872
|
+
const [menuPos, setMenuPos] = (0, react$1.useState)(null);
|
|
15698
15873
|
const isPanel = mode === "panel";
|
|
15699
15874
|
const zoomVisible = showZoom && (options?.hasZoom ?? true);
|
|
15700
15875
|
const supportsPresets = options?.supportsPresets ?? presets.length > 0;
|
|
@@ -15720,6 +15895,51 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
|
|
|
15720
15895
|
})) return;
|
|
15721
15896
|
await deletePreset(presetId);
|
|
15722
15897
|
}, [confirm, deletePreset]);
|
|
15898
|
+
const handleUpdatePreset = (0, react$1.useCallback)(async (presetId, label) => {
|
|
15899
|
+
if (!await confirm({
|
|
15900
|
+
title: "Update preset",
|
|
15901
|
+
message: `Overwrite preset "${label}" with the camera's current position?`,
|
|
15902
|
+
confirmLabel: "Update"
|
|
15903
|
+
})) return;
|
|
15904
|
+
await updatePreset(presetId);
|
|
15905
|
+
}, [confirm, updatePreset]);
|
|
15906
|
+
(0, react$1.useLayoutEffect)(() => {
|
|
15907
|
+
if (!presetsOpen) {
|
|
15908
|
+
setMenuPos(null);
|
|
15909
|
+
return;
|
|
15910
|
+
}
|
|
15911
|
+
const reposition = () => {
|
|
15912
|
+
const rect = presetTriggerRef.current?.getBoundingClientRect();
|
|
15913
|
+
if (rect) setMenuPos({
|
|
15914
|
+
top: rect.bottom + 4,
|
|
15915
|
+
right: window.innerWidth - rect.right
|
|
15916
|
+
});
|
|
15917
|
+
};
|
|
15918
|
+
reposition();
|
|
15919
|
+
window.addEventListener("resize", reposition);
|
|
15920
|
+
window.addEventListener("scroll", reposition, true);
|
|
15921
|
+
return () => {
|
|
15922
|
+
window.removeEventListener("resize", reposition);
|
|
15923
|
+
window.removeEventListener("scroll", reposition, true);
|
|
15924
|
+
};
|
|
15925
|
+
}, [presetsOpen]);
|
|
15926
|
+
(0, react$1.useEffect)(() => {
|
|
15927
|
+
if (!presetsOpen) return;
|
|
15928
|
+
const onPointerDown = (e) => {
|
|
15929
|
+
const target = e.target;
|
|
15930
|
+
if (presetMenuRef.current?.contains(target) || presetTriggerRef.current?.contains(target)) return;
|
|
15931
|
+
setPresetsOpen(false);
|
|
15932
|
+
};
|
|
15933
|
+
const onKey = (e) => {
|
|
15934
|
+
if (e.key === "Escape") setPresetsOpen(false);
|
|
15935
|
+
};
|
|
15936
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
15937
|
+
document.addEventListener("keydown", onKey);
|
|
15938
|
+
return () => {
|
|
15939
|
+
document.removeEventListener("mousedown", onPointerDown);
|
|
15940
|
+
document.removeEventListener("keydown", onKey);
|
|
15941
|
+
};
|
|
15942
|
+
}, [presetsOpen]);
|
|
15723
15943
|
const containerClass = isPanel ? "flex flex-col items-stretch gap-2 w-full h-full p-3" : "pointer-events-auto absolute top-3 right-3 z-10 flex flex-col items-end gap-2";
|
|
15724
15944
|
const rowClass = isPanel ? cn("flex items-center gap-3 rounded-lg p-2", busy && "ring-1 ring-primary/40") : cn("flex items-center gap-2 rounded-lg border border-white/30 bg-zinc-900/90 backdrop-blur-md p-2 shadow-lg shadow-black/40", busy && "ring-1 ring-primary/40");
|
|
15725
15945
|
const sideButtonSize = isPanel ? "h-9 w-9" : "h-7 w-7";
|
|
@@ -15820,14 +16040,22 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
|
|
|
15820
16040
|
presetsVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
15821
16041
|
className: "relative",
|
|
15822
16042
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
16043
|
+
ref: presetTriggerRef,
|
|
15823
16044
|
type: "button",
|
|
15824
16045
|
onClick: () => setPresetsOpen((v) => !v),
|
|
15825
16046
|
disabled: busy,
|
|
15826
16047
|
className: cn("flex items-center gap-1 rounded px-2 text-[10px] disabled:opacity-40", isPanel ? "h-9 text-foreground hover:bg-surface-hover" : "h-7 text-white hover:bg-white/15"),
|
|
15827
16048
|
title: "Presets",
|
|
15828
16049
|
children: ["Presets", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, { className: cn("h-3 w-3 transition-transform", presetsOpen && "rotate-180") })]
|
|
15829
|
-
}), presetsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
15830
|
-
|
|
16050
|
+
}), presetsOpen && menuPos && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16051
|
+
ref: presetMenuRef,
|
|
16052
|
+
style: {
|
|
16053
|
+
position: "fixed",
|
|
16054
|
+
top: menuPos.top,
|
|
16055
|
+
right: menuPos.right,
|
|
16056
|
+
zIndex: 60
|
|
16057
|
+
},
|
|
16058
|
+
className: cn("rounded-lg shadow-xl py-1", presetManagementVisible ? "min-w-[220px]" : "min-w-[140px]", isPanel ? "bg-surface border border-border" : "border border-white/30 bg-zinc-900/95 backdrop-blur-md"),
|
|
15831
16059
|
children: [
|
|
15832
16060
|
presets.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
15833
16061
|
className: cn("px-3 py-1.5 text-[10px]", isPanel ? "text-foreground-subtle" : "text-white/60"),
|
|
@@ -15844,14 +16072,21 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
|
|
|
15844
16072
|
disabled: busy,
|
|
15845
16073
|
className: cn("flex-1 px-3 py-1.5 text-left text-[10px] disabled:opacity-40", isPanel ? "text-foreground" : "text-white"),
|
|
15846
16074
|
children: p.name || p.id
|
|
15847
|
-
}), presetManagementVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16075
|
+
}), presetManagementVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
16076
|
+
type: "button",
|
|
16077
|
+
onClick: () => void handleUpdatePreset(p.id, p.name || p.id),
|
|
16078
|
+
disabled: busy,
|
|
16079
|
+
title: `Overwrite "${p.name || p.id}" with current position`,
|
|
16080
|
+
className: cn("flex h-5 w-5 shrink-0 items-center justify-center rounded", "text-foreground-subtle hover:bg-primary/15 hover:text-primary disabled:opacity-40"),
|
|
16081
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Crosshair, { className: "h-3 w-3" })
|
|
16082
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
15848
16083
|
type: "button",
|
|
15849
16084
|
onClick: () => void handleDeletePreset(p.id, p.name || p.id),
|
|
15850
16085
|
disabled: busy,
|
|
15851
16086
|
title: `Delete preset ${p.name || p.id}`,
|
|
15852
16087
|
className: cn("mr-1 flex h-5 w-5 shrink-0 items-center justify-center rounded", "text-foreground-subtle hover:bg-danger/15 hover:text-danger disabled:opacity-40"),
|
|
15853
16088
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(X, { className: "h-3 w-3" })
|
|
15854
|
-
})]
|
|
16089
|
+
})] })]
|
|
15855
16090
|
}, p.id)),
|
|
15856
16091
|
presetManagementVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
15857
16092
|
presets.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: cn("my-1 h-px", isPanel ? "bg-border" : "bg-white/15") }),
|
|
@@ -15887,7 +16122,7 @@ function PTZOverlay({ controls, mode = "overlay", showPresets, showZoom = true,
|
|
|
15887
16122
|
})
|
|
15888
16123
|
] })
|
|
15889
16124
|
]
|
|
15890
|
-
})]
|
|
16125
|
+
}), document.body)]
|
|
15891
16126
|
})
|
|
15892
16127
|
]
|
|
15893
16128
|
})]
|
|
@@ -17712,6 +17947,8 @@ var usePipelineExecutorGetGlobalSteps = trpc.pipelineExecutor.getGlobalSteps.use
|
|
|
17712
17947
|
var usePipelineExecutorGetGlobalPipelineConfig = trpc.pipelineExecutor.getGlobalPipelineConfig.useQuery;
|
|
17713
17948
|
/** Generated alias around `trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery`. */
|
|
17714
17949
|
var usePipelineExecutorGetOrchestratorConfigSchema = trpc.pipelineExecutor.getOrchestratorConfigSchema.useQuery;
|
|
17950
|
+
/** Generated alias around `trpc.pipelineExecutor.validatePipeline.useQuery`. */
|
|
17951
|
+
var usePipelineExecutorValidatePipeline = trpc.pipelineExecutor.validatePipeline.useQuery;
|
|
17715
17952
|
/** Generated alias around `trpc.pipelineExecutor.listTemplates.useQuery`. */
|
|
17716
17953
|
var usePipelineExecutorListTemplates = trpc.pipelineExecutor.listTemplates.useQuery;
|
|
17717
17954
|
/** Generated alias around `trpc.pipelineExecutor.saveTemplate.useMutation`. */
|
|
@@ -17782,6 +18019,8 @@ var usePipelineOrchestratorGetCameraMetrics = trpc.pipelineOrchestrator.getCamer
|
|
|
17782
18019
|
var usePipelineOrchestratorGetCapabilityBindings = trpc.pipelineOrchestrator.getCapabilityBindings.useQuery;
|
|
17783
18020
|
/** Generated alias around `trpc.pipelineOrchestrator.setCapabilityBinding.useMutation`. */
|
|
17784
18021
|
var usePipelineOrchestratorSetCapabilityBinding = trpc.pipelineOrchestrator.setCapabilityBinding.useMutation;
|
|
18022
|
+
/** Generated alias around `trpc.pipelineOrchestrator.getIngestOwner.useQuery`. */
|
|
18023
|
+
var usePipelineOrchestratorGetIngestOwner = trpc.pipelineOrchestrator.getIngestOwner.useQuery;
|
|
17785
18024
|
/** Generated alias around `trpc.pipelineOrchestrator.assignDecoder.useMutation`. */
|
|
17786
18025
|
var usePipelineOrchestratorAssignDecoder = trpc.pipelineOrchestrator.assignDecoder.useMutation;
|
|
17787
18026
|
/** Generated alias around `trpc.pipelineOrchestrator.unassignDecoder.useMutation`. */
|
|
@@ -17814,6 +18053,8 @@ var usePipelineOrchestratorSetAgentMaxCameras = trpc.pipelineOrchestrator.setAge
|
|
|
17814
18053
|
var usePipelineOrchestratorSetAgentDetectWeight = trpc.pipelineOrchestrator.setAgentDetectWeight.useMutation;
|
|
17815
18054
|
/** Generated alias around `trpc.pipelineOrchestrator.setAgentCapabilities.useMutation`. */
|
|
17816
18055
|
var usePipelineOrchestratorSetAgentCapabilities = trpc.pipelineOrchestrator.setAgentCapabilities.useMutation;
|
|
18056
|
+
/** Generated alias around `trpc.pipelineOrchestrator.setAgentReachableHost.useMutation`. */
|
|
18057
|
+
var usePipelineOrchestratorSetAgentReachableHost = trpc.pipelineOrchestrator.setAgentReachableHost.useMutation;
|
|
17817
18058
|
/** Generated alias around `trpc.pipelineOrchestrator.getCameraSettings.useQuery`. */
|
|
17818
18059
|
var usePipelineOrchestratorGetCameraSettings = trpc.pipelineOrchestrator.getCameraSettings.useQuery;
|
|
17819
18060
|
/** Generated alias around `trpc.pipelineOrchestrator.setCameraStepToggle.useMutation`. */
|
|
@@ -17988,10 +18229,6 @@ var useSnapshotGetDeviceSettingsContribution = trpc.snapshot.getDeviceSettingsCo
|
|
|
17988
18229
|
var useSnapshotGetDeviceLiveContribution = trpc.snapshot.getDeviceLiveContribution.useQuery;
|
|
17989
18230
|
/** Generated alias around `trpc.snapshot.applyDeviceSettingsPatch.useMutation`. */
|
|
17990
18231
|
var useSnapshotApplyDeviceSettingsPatch = trpc.snapshot.applyDeviceSettingsPatch.useMutation;
|
|
17991
|
-
/** Generated alias around `trpc.snapshotProvider.supportsDevice.useQuery`. */
|
|
17992
|
-
var useSnapshotProviderSupportsDevice = trpc.snapshotProvider.supportsDevice.useQuery;
|
|
17993
|
-
/** Generated alias around `trpc.snapshotProvider.getSnapshot.useQuery`. */
|
|
17994
|
-
var useSnapshotProviderGetSnapshot = trpc.snapshotProvider.getSnapshot.useQuery;
|
|
17995
18232
|
/** Generated alias around `trpc.storage.resolve.useQuery`. */
|
|
17996
18233
|
var useStorageResolve = trpc.storage.resolve.useQuery;
|
|
17997
18234
|
/** Generated alias around `trpc.storage.write.useMutation`. */
|
|
@@ -30042,10 +30279,11 @@ function PlaceholderStep({ addon, onClick }) {
|
|
|
30042
30279
|
})
|
|
30043
30280
|
});
|
|
30044
30281
|
}
|
|
30045
|
-
function PipelineBuilder({ schema, steps, onChange, templates, selectedTemplateId, onSelectTemplate, onSaveTemplate, onUpdateTemplate, onDeleteTemplate, readOnly = false, excludeAddons = [], hideTemplates = false, showOnlyEnabled = false, showSlotLabels = false, toggleMode = "simple", overrides = {}, onOverrideChange, inheritedEnabledByAddon = {}, hideModelAndSettings = false }) {
|
|
30282
|
+
function PipelineBuilder({ schema, steps, onChange, templates, selectedTemplateId, onSelectTemplate, onSaveTemplate, onUpdateTemplate, onDeleteTemplate, readOnly = false, excludeAddons = [], hideTemplates = false, showOnlyEnabled = false, showSlotLabels = false, toggleMode = "simple", overrides = {}, onOverrideChange, inheritedEnabledByAddon = {}, hideModelAndSettings = false, allowAutoModel = false }) {
|
|
30046
30283
|
const stepExtraProps = (addonId) => ({
|
|
30047
30284
|
toggleMode,
|
|
30048
30285
|
hideModelAndSettings,
|
|
30286
|
+
allowAutoModel,
|
|
30049
30287
|
...toggleMode === "threeState" ? {
|
|
30050
30288
|
overrideState: overrides[addonId] !== void 0 ? overrides[addonId] : null,
|
|
30051
30289
|
onOverrideChange: onOverrideChange ? (next) => onOverrideChange(addonId, next) : void 0,
|
|
@@ -33278,7 +33516,7 @@ function ScheduleBandsEditor({ schedules, onChange }) {
|
|
|
33278
33516
|
className: "space-y-2",
|
|
33279
33517
|
children: [schedules.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
33280
33518
|
className: "text-[11px] text-foreground-subtle",
|
|
33281
|
-
children: "
|
|
33519
|
+
children: "Always (24/7) — add a band to restrict hours."
|
|
33282
33520
|
}) : schedules.map((band, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BandRow, {
|
|
33283
33521
|
band,
|
|
33284
33522
|
onChange: (b) => replaceAt(i, b),
|
|
@@ -33287,7 +33525,7 @@ function ScheduleBandsEditor({ schedules, onChange }) {
|
|
|
33287
33525
|
type: "button",
|
|
33288
33526
|
onClick: addBand,
|
|
33289
33527
|
className: "flex items-center gap-1 rounded-md bg-surface-hover px-2 py-1 text-[11px] text-foreground-subtle hover:text-foreground",
|
|
33290
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plus, { className: "h-3 w-3" }), "
|
|
33528
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Plus, { className: "h-3 w-3" }), " Add band"]
|
|
33291
33529
|
})]
|
|
33292
33530
|
});
|
|
33293
33531
|
}
|
|
@@ -33297,18 +33535,18 @@ function BandRow({ band, onChange, onRemove }) {
|
|
|
33297
33535
|
children: [
|
|
33298
33536
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
33299
33537
|
className: "flex-1",
|
|
33300
|
-
children: "
|
|
33538
|
+
children: "Always"
|
|
33301
33539
|
}),
|
|
33302
33540
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
33303
33541
|
type: "button",
|
|
33304
33542
|
onClick: () => onChange(newBand()),
|
|
33305
33543
|
className: "text-foreground-subtle hover:text-foreground underline",
|
|
33306
|
-
children: "
|
|
33544
|
+
children: "Set band"
|
|
33307
33545
|
}),
|
|
33308
33546
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
33309
33547
|
type: "button",
|
|
33310
33548
|
onClick: onRemove,
|
|
33311
|
-
"aria-label": "
|
|
33549
|
+
"aria-label": "Remove band",
|
|
33312
33550
|
className: "text-foreground-subtle hover:text-red-500",
|
|
33313
33551
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Trash2, { className: "h-3.5 w-3.5" })
|
|
33314
33552
|
})
|
|
@@ -33353,7 +33591,7 @@ function BandRow({ band, onChange, onRemove }) {
|
|
|
33353
33591
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
33354
33592
|
type: "button",
|
|
33355
33593
|
onClick: onRemove,
|
|
33356
|
-
"aria-label": "
|
|
33594
|
+
"aria-label": "Remove band",
|
|
33357
33595
|
className: "text-foreground-subtle hover:text-red-500",
|
|
33358
33596
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Trash2, { className: "h-3.5 w-3.5" })
|
|
33359
33597
|
})
|
|
@@ -33369,7 +33607,7 @@ function BandRow({ band, onChange, onRemove }) {
|
|
|
33369
33607
|
}, d.value);
|
|
33370
33608
|
}), days.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
33371
33609
|
className: "self-center text-[10px] text-foreground-subtle",
|
|
33372
|
-
children: "
|
|
33610
|
+
children: "every day"
|
|
33373
33611
|
}) : null]
|
|
33374
33612
|
})]
|
|
33375
33613
|
});
|
|
@@ -33415,7 +33653,7 @@ function RecordingSettings({ initial, saving, onSave }) {
|
|
|
33415
33653
|
});
|
|
33416
33654
|
const numOrUndef = (v) => v === "" ? void 0 : Number(v);
|
|
33417
33655
|
const toggleProfile = (p) => {
|
|
33418
|
-
const cur = common.profiles ?? [];
|
|
33656
|
+
const cur = common.profiles ?? [...PROFILES];
|
|
33419
33657
|
const next = cur.includes(p) ? cur.filter((x) => x !== p) : [...cur, p];
|
|
33420
33658
|
setCommon({
|
|
33421
33659
|
...common,
|
|
@@ -33593,7 +33831,7 @@ function RecordingSettings({ initial, saving, onSave }) {
|
|
|
33593
33831
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
33594
33832
|
type: "button",
|
|
33595
33833
|
onClick: () => toggleProfile(p),
|
|
33596
|
-
className: `rounded px-2 py-1 ${
|
|
33834
|
+
className: `rounded px-2 py-1 ${common.profiles == null || common.profiles.includes(p) ? "bg-primary text-primary-foreground" : "bg-surface-hover text-foreground-subtle"}`,
|
|
33597
33835
|
children: p
|
|
33598
33836
|
}, p);
|
|
33599
33837
|
})]
|
|
@@ -34136,7 +34374,7 @@ function CoverageTrack({ windowFrom, windowTo, spans, playheadMs, onSeek, onScru
|
|
|
34136
34374
|
const left = pctForMs(s.startMs, windowFrom, windowTo);
|
|
34137
34375
|
const right = pctForMs(s.endMs, windowFrom, windowTo);
|
|
34138
34376
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
34139
|
-
"data-testid": "coverage-
|
|
34377
|
+
"data-testid": "coverage-band",
|
|
34140
34378
|
className: "absolute inset-y-0 bg-gradient-to-b from-primary to-primary/80",
|
|
34141
34379
|
style: {
|
|
34142
34380
|
left: `${left}%`,
|
|
@@ -45158,6 +45396,7 @@ exports.GRID_GAP = GRID_GAP;
|
|
|
45158
45396
|
exports.GRID_PAIRED = GRID_PAIRED;
|
|
45159
45397
|
exports.GRID_QUICK_STATS = GRID_QUICK_STATS;
|
|
45160
45398
|
exports.GripTrack = GripTrack;
|
|
45399
|
+
exports.GroupedModelSelector = GroupedModelSelector;
|
|
45161
45400
|
exports.HOST_WIDGETS = HOST_WIDGETS;
|
|
45162
45401
|
exports.HlsVideo = HlsVideo;
|
|
45163
45402
|
exports.HoverZoomImage = HoverZoomImage;
|
|
@@ -45894,6 +46133,7 @@ exports.usePipelineExecutorSetVideoPipelineSteps = usePipelineExecutorSetVideoPi
|
|
|
45894
46133
|
exports.usePipelineExecutorSpinEngine = usePipelineExecutorSpinEngine;
|
|
45895
46134
|
exports.usePipelineExecutorUncacheFrame = usePipelineExecutorUncacheFrame;
|
|
45896
46135
|
exports.usePipelineExecutorUpdateTemplate = usePipelineExecutorUpdateTemplate;
|
|
46136
|
+
exports.usePipelineExecutorValidatePipeline = usePipelineExecutorValidatePipeline;
|
|
45897
46137
|
exports.usePipelineOrchestratorApplyDeviceSettingsPatch = usePipelineOrchestratorApplyDeviceSettingsPatch;
|
|
45898
46138
|
exports.usePipelineOrchestratorAssignAudio = usePipelineOrchestratorAssignAudio;
|
|
45899
46139
|
exports.usePipelineOrchestratorAssignDecoder = usePipelineOrchestratorAssignDecoder;
|
|
@@ -45915,6 +46155,7 @@ exports.usePipelineOrchestratorGetDecoderAssignments = usePipelineOrchestratorGe
|
|
|
45915
46155
|
exports.usePipelineOrchestratorGetDeviceLiveContribution = usePipelineOrchestratorGetDeviceLiveContribution;
|
|
45916
46156
|
exports.usePipelineOrchestratorGetDeviceSettingsContribution = usePipelineOrchestratorGetDeviceSettingsContribution;
|
|
45917
46157
|
exports.usePipelineOrchestratorGetGlobalMetrics = usePipelineOrchestratorGetGlobalMetrics;
|
|
46158
|
+
exports.usePipelineOrchestratorGetIngestOwner = usePipelineOrchestratorGetIngestOwner;
|
|
45918
46159
|
exports.usePipelineOrchestratorGetPipelineAssignment = usePipelineOrchestratorGetPipelineAssignment;
|
|
45919
46160
|
exports.usePipelineOrchestratorGetPipelineAssignments = usePipelineOrchestratorGetPipelineAssignments;
|
|
45920
46161
|
exports.usePipelineOrchestratorListAgentSettings = usePipelineOrchestratorListAgentSettings;
|
|
@@ -45927,6 +46168,7 @@ exports.usePipelineOrchestratorSetAgentAddonDefaults = usePipelineOrchestratorSe
|
|
|
45927
46168
|
exports.usePipelineOrchestratorSetAgentCapabilities = usePipelineOrchestratorSetAgentCapabilities;
|
|
45928
46169
|
exports.usePipelineOrchestratorSetAgentDetectWeight = usePipelineOrchestratorSetAgentDetectWeight;
|
|
45929
46170
|
exports.usePipelineOrchestratorSetAgentMaxCameras = usePipelineOrchestratorSetAgentMaxCameras;
|
|
46171
|
+
exports.usePipelineOrchestratorSetAgentReachableHost = usePipelineOrchestratorSetAgentReachableHost;
|
|
45930
46172
|
exports.usePipelineOrchestratorSetCameraPipelineForAgent = usePipelineOrchestratorSetCameraPipelineForAgent;
|
|
45931
46173
|
exports.usePipelineOrchestratorSetCameraStepOverride = usePipelineOrchestratorSetCameraStepOverride;
|
|
45932
46174
|
exports.usePipelineOrchestratorSetCameraStepToggle = usePipelineOrchestratorSetCameraStepToggle;
|
|
@@ -46014,8 +46256,6 @@ exports.useSnapshotGetDeviceSettingsContribution = useSnapshotGetDeviceSettingsC
|
|
|
46014
46256
|
exports.useSnapshotGetSnapshot = useSnapshotGetSnapshot;
|
|
46015
46257
|
exports.useSnapshotGetStatus = useSnapshotGetStatus;
|
|
46016
46258
|
exports.useSnapshotInvalidateCache = useSnapshotInvalidateCache;
|
|
46017
|
-
exports.useSnapshotProviderGetSnapshot = useSnapshotProviderGetSnapshot;
|
|
46018
|
-
exports.useSnapshotProviderSupportsDevice = useSnapshotProviderSupportsDevice;
|
|
46019
46259
|
exports.useStorageAbortUpload = useStorageAbortUpload;
|
|
46020
46260
|
exports.useStorageBeginDownload = useStorageBeginDownload;
|
|
46021
46261
|
exports.useStorageBeginUpload = useStorageBeginUpload;
|