@camstack/ui-library 1.2.319 → 1.2.321
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/account-sign-in-field.d.ts +17 -0
- package/dist/composites/device-controls/dishwasher-control.d.ts +7 -0
- package/dist/composites/device-item/header.d.ts +3 -1
- package/dist/composites/index.d.ts +4 -0
- package/dist/composites/running-badge.d.ts +20 -0
- package/dist/composites/running-status.d.ts +20 -0
- package/dist/composites/scope-picker.d.ts +2 -3
- package/dist/composites/step-inspector/index.d.ts +1 -1
- package/dist/composites/step-inspector/layered-settings-form.d.ts +1 -1
- package/dist/composites/step-inspector/setting-values.d.ts +9 -1
- package/dist/generated/system-hooks.d.ts +2 -0
- package/dist/index.cjs +477 -54
- package/dist/index.js +472 -56
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -12229,6 +12229,8 @@ var useRecordingOnboardSetSettings = trpc.recordingOnboard.setSettings.useMutati
|
|
|
12229
12229
|
var useRecordingOnboardGetStatus = trpc.recordingOnboard.getStatus.useQuery;
|
|
12230
12230
|
/** Generated alias around `trpc.recordingSignal.getStatus.useQuery`. */
|
|
12231
12231
|
var useRecordingSignalGetStatus = trpc.recordingSignal.getStatus.useQuery;
|
|
12232
|
+
/** Generated alias around `trpc.runningState.getStatus.useQuery`. */
|
|
12233
|
+
var useRunningStateGetStatus = trpc.runningState.getStatus.useQuery;
|
|
12232
12234
|
/** Generated alias around `trpc.sceneMonitor.listScenes.useQuery`. */
|
|
12233
12235
|
var useSceneMonitorListScenes = trpc.sceneMonitor.listScenes.useQuery;
|
|
12234
12236
|
/** Generated alias around `trpc.sceneMonitor.listScenesBatch.useQuery`. */
|
|
@@ -13026,7 +13028,7 @@ function selectedDeviceOptions(options, selected) {
|
|
|
13026
13028
|
* select. Both are inline in ui-library (like `node-select`) so any host that
|
|
13027
13029
|
* renders the shared form field gets them without extra registration.
|
|
13028
13030
|
*/
|
|
13029
|
-
var INPUT_CLASS$
|
|
13031
|
+
var INPUT_CLASS$2 = "w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none disabled:opacity-50 disabled:cursor-not-allowed";
|
|
13030
13032
|
var INPUT_SHELL$1 = "flex items-center gap-1.5 rounded-md border border-border bg-background px-2 py-1.5 focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/30";
|
|
13031
13033
|
var LABEL_CLASS$3 = "block text-[11px] font-medium text-foreground mb-1 break-words";
|
|
13032
13034
|
var DESC_CLASS$2 = "text-[10px] text-foreground-subtle mt-0.5 break-words";
|
|
@@ -13156,7 +13158,7 @@ function DeviceSelectField({ field, value, onChange, disabled, translationFn })
|
|
|
13156
13158
|
required: field.required,
|
|
13157
13159
|
translationFn,
|
|
13158
13160
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
13159
|
-
className: INPUT_CLASS$
|
|
13161
|
+
className: INPUT_CLASS$2,
|
|
13160
13162
|
value: current,
|
|
13161
13163
|
disabled: disabled || field.disabled,
|
|
13162
13164
|
onChange: (e) => onChange(e.target.value),
|
|
@@ -14382,6 +14384,282 @@ function useCustomFieldRenderer(type) {
|
|
|
14382
14384
|
return (0, react$1.useContext)(CustomFieldRenderersContext)[type] ?? null;
|
|
14383
14385
|
}
|
|
14384
14386
|
//#endregion
|
|
14387
|
+
//#region src/primitives/button.tsx
|
|
14388
|
+
var buttonVariants = cva("inline-flex items-center justify-center rounded-md font-medium transition-colors cursor-pointer disabled:opacity-50 disabled:pointer-events-none", {
|
|
14389
|
+
variants: {
|
|
14390
|
+
variant: {
|
|
14391
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
14392
|
+
secondary: "bg-surface text-foreground hover:bg-surface-hover",
|
|
14393
|
+
ghost: "hover:bg-surface-hover text-foreground-muted",
|
|
14394
|
+
danger: "bg-danger text-white hover:bg-danger/90",
|
|
14395
|
+
outline: "border border-border bg-transparent text-foreground hover:bg-surface-hover"
|
|
14396
|
+
},
|
|
14397
|
+
size: {
|
|
14398
|
+
sm: "h-7 px-2.5 text-xs gap-1.5",
|
|
14399
|
+
md: "h-8 px-3 text-sm gap-2",
|
|
14400
|
+
lg: "h-9 px-4 text-sm gap-2"
|
|
14401
|
+
}
|
|
14402
|
+
},
|
|
14403
|
+
defaultVariants: {
|
|
14404
|
+
variant: "primary",
|
|
14405
|
+
size: "sm"
|
|
14406
|
+
}
|
|
14407
|
+
});
|
|
14408
|
+
var Button = (0, react$1.forwardRef)(({ className, variant, size, ...props }, ref) => {
|
|
14409
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
14410
|
+
ref,
|
|
14411
|
+
className: cn(buttonVariants({
|
|
14412
|
+
variant,
|
|
14413
|
+
size
|
|
14414
|
+
}), className),
|
|
14415
|
+
...props
|
|
14416
|
+
});
|
|
14417
|
+
});
|
|
14418
|
+
Button.displayName = "Button";
|
|
14419
|
+
//#endregion
|
|
14420
|
+
//#region src/composites/account-sign-in-field.tsx
|
|
14421
|
+
var INPUT_CLASS$1 = "w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-xs text-foreground focus:border-primary focus:ring-1 focus:ring-primary/30 outline-none disabled:opacity-50 disabled:cursor-not-allowed";
|
|
14422
|
+
var BARE_CODE = /^[A-Za-z0-9._~-]{8,}$/;
|
|
14423
|
+
function isRecord$3(value) {
|
|
14424
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14425
|
+
}
|
|
14426
|
+
function isPresent(value) {
|
|
14427
|
+
if (typeof value === "string") return value.trim().length > 0;
|
|
14428
|
+
if ((0, _camstack_types.isSecretFieldView)(value) || (0, _camstack_types.isSecretMarker)(value)) return true;
|
|
14429
|
+
return false;
|
|
14430
|
+
}
|
|
14431
|
+
function accountText(value) {
|
|
14432
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : "";
|
|
14433
|
+
}
|
|
14434
|
+
function countFromValue(value) {
|
|
14435
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
14436
|
+
if (Array.isArray(value)) return value.length;
|
|
14437
|
+
if (typeof value === "string" && value.trim().startsWith("[")) try {
|
|
14438
|
+
const parsed = JSON.parse(value);
|
|
14439
|
+
if (Array.isArray(parsed)) return parsed.length;
|
|
14440
|
+
} catch {
|
|
14441
|
+
return null;
|
|
14442
|
+
}
|
|
14443
|
+
return null;
|
|
14444
|
+
}
|
|
14445
|
+
function nounFor(count, noun) {
|
|
14446
|
+
return count === 1 ? noun : `${noun}s`;
|
|
14447
|
+
}
|
|
14448
|
+
function choicesOf(value) {
|
|
14449
|
+
if (!Array.isArray(value)) return [];
|
|
14450
|
+
const out = [];
|
|
14451
|
+
for (const row of value) {
|
|
14452
|
+
if (!isRecord$3(row) || typeof row["value"] !== "string" || typeof row["label"] !== "string") continue;
|
|
14453
|
+
out.push({
|
|
14454
|
+
value: row["value"],
|
|
14455
|
+
label: row["label"],
|
|
14456
|
+
...typeof row["brand"] === "string" ? { brand: row["brand"] } : {},
|
|
14457
|
+
...typeof row["region"] === "string" ? { region: row["region"] } : {}
|
|
14458
|
+
});
|
|
14459
|
+
}
|
|
14460
|
+
return out;
|
|
14461
|
+
}
|
|
14462
|
+
function selectedChoice(value) {
|
|
14463
|
+
return typeof value === "string" ? value : "";
|
|
14464
|
+
}
|
|
14465
|
+
function shouldComplete(text) {
|
|
14466
|
+
const trimmed = text.trim();
|
|
14467
|
+
if (trimmed.length === 0) return false;
|
|
14468
|
+
if (trimmed.includes("code=") || trimmed.includes("://") || trimmed.includes("error=")) return true;
|
|
14469
|
+
return BARE_CODE.test(trimmed);
|
|
14470
|
+
}
|
|
14471
|
+
function AccountSignInField({ field, values, disabled, onAction, onChangeMany }) {
|
|
14472
|
+
const t = useUiText();
|
|
14473
|
+
const [phase, setPhase] = (0, react$1.useState)("idle");
|
|
14474
|
+
const [attemptId, setAttemptId] = (0, react$1.useState)(null);
|
|
14475
|
+
const [authorizeUrl, setAuthorizeUrl] = (0, react$1.useState)(null);
|
|
14476
|
+
const [paste, setPaste] = (0, react$1.useState)("");
|
|
14477
|
+
const [error, setError] = (0, react$1.useState)(null);
|
|
14478
|
+
const [working, setWorking] = (0, react$1.useState)(false);
|
|
14479
|
+
const [choices, setChoices] = (0, react$1.useState)([]);
|
|
14480
|
+
const inFlight = (0, react$1.useRef)(false);
|
|
14481
|
+
const account = accountText(values[field.accountKey]);
|
|
14482
|
+
const tokenPresent = field.secretKeys.some((key) => isPresent(values[key]));
|
|
14483
|
+
const signedIn = account.length > 0 || tokenPresent;
|
|
14484
|
+
const count = (field.countKey !== void 0 ? countFromValue(values[field.countKey]) : null) ?? (field.countFromKey !== void 0 ? countFromValue(values[field.countFromKey]) : null);
|
|
14485
|
+
const showPaste = phase === "pasting" || !signedIn && attemptId !== null;
|
|
14486
|
+
const applyResult = (result) => {
|
|
14487
|
+
const patch = {};
|
|
14488
|
+
for (const [formKey, resultKey] of Object.entries(field.assignResult ?? {})) {
|
|
14489
|
+
const assigned = result[resultKey];
|
|
14490
|
+
if (typeof assigned === "string" || typeof assigned === "number") patch[formKey] = assigned;
|
|
14491
|
+
}
|
|
14492
|
+
if (Object.keys(patch).length > 0) onChangeMany?.(patch);
|
|
14493
|
+
const nextChoices = choicesOf(result["choices"]);
|
|
14494
|
+
setChoices(nextChoices.length > 1 ? nextChoices : []);
|
|
14495
|
+
setPhase("idle");
|
|
14496
|
+
setPaste("");
|
|
14497
|
+
setAttemptId(null);
|
|
14498
|
+
setAuthorizeUrl(null);
|
|
14499
|
+
};
|
|
14500
|
+
const begin = async () => {
|
|
14501
|
+
if (!onAction || working) return;
|
|
14502
|
+
setWorking(true);
|
|
14503
|
+
setError(null);
|
|
14504
|
+
try {
|
|
14505
|
+
const result = await onAction(field.beginAction, field.key, {});
|
|
14506
|
+
if (!isRecord$3(result) || typeof result["authorizeUrl"] !== "string" || typeof result["attemptId"] !== "string") {
|
|
14507
|
+
setError(t("uiLibrary.accountSignIn.noLink", "The sign-in page could not be opened. Try again."));
|
|
14508
|
+
return;
|
|
14509
|
+
}
|
|
14510
|
+
if ("verifier" in result || "state" in result) {
|
|
14511
|
+
setError(t("uiLibrary.accountSignIn.noLink", "The sign-in page could not be opened. Try again."));
|
|
14512
|
+
return;
|
|
14513
|
+
}
|
|
14514
|
+
setAttemptId(result["attemptId"]);
|
|
14515
|
+
setAuthorizeUrl(result["authorizeUrl"]);
|
|
14516
|
+
setPhase("pasting");
|
|
14517
|
+
window.open(result["authorizeUrl"], "_blank", "noopener,noreferrer");
|
|
14518
|
+
} catch (err) {
|
|
14519
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
14520
|
+
} finally {
|
|
14521
|
+
setWorking(false);
|
|
14522
|
+
}
|
|
14523
|
+
};
|
|
14524
|
+
const complete = async (callback) => {
|
|
14525
|
+
if (!onAction || attemptId === null || inFlight.current) return;
|
|
14526
|
+
inFlight.current = true;
|
|
14527
|
+
setWorking(true);
|
|
14528
|
+
setError(null);
|
|
14529
|
+
try {
|
|
14530
|
+
const result = await onAction(field.completeAction, field.key, {
|
|
14531
|
+
attemptId,
|
|
14532
|
+
callback
|
|
14533
|
+
});
|
|
14534
|
+
if (!isRecord$3(result)) {
|
|
14535
|
+
setError(t("uiLibrary.accountSignIn.rejected", "The sign-in was not accepted. Start again."));
|
|
14536
|
+
return;
|
|
14537
|
+
}
|
|
14538
|
+
applyResult(result);
|
|
14539
|
+
} catch (err) {
|
|
14540
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
14541
|
+
} finally {
|
|
14542
|
+
inFlight.current = false;
|
|
14543
|
+
setWorking(false);
|
|
14544
|
+
}
|
|
14545
|
+
};
|
|
14546
|
+
const signOut = async () => {
|
|
14547
|
+
if (!onAction || working) return;
|
|
14548
|
+
setWorking(true);
|
|
14549
|
+
setError(null);
|
|
14550
|
+
try {
|
|
14551
|
+
await onAction(field.signOutAction, field.key, {});
|
|
14552
|
+
const patch = { [field.accountKey]: "" };
|
|
14553
|
+
if (field.countKey !== void 0) patch[field.countKey] = 0;
|
|
14554
|
+
if (field.choiceKey !== void 0) patch[field.choiceKey] = "";
|
|
14555
|
+
if (field.countFromKey !== void 0) patch[field.countFromKey] = [];
|
|
14556
|
+
for (const key of field.secretKeys) patch[key] = _camstack_types.SECRET_CLEAR;
|
|
14557
|
+
onChangeMany?.(patch);
|
|
14558
|
+
setChoices([]);
|
|
14559
|
+
setPhase("idle");
|
|
14560
|
+
setAttemptId(null);
|
|
14561
|
+
setPaste("");
|
|
14562
|
+
} catch (err) {
|
|
14563
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
14564
|
+
} finally {
|
|
14565
|
+
setWorking(false);
|
|
14566
|
+
}
|
|
14567
|
+
};
|
|
14568
|
+
const pick = (value) => {
|
|
14569
|
+
const chosen = choices.find((row) => row.value === value);
|
|
14570
|
+
if (chosen === void 0 || field.choiceKey === void 0) return;
|
|
14571
|
+
const patch = { [field.choiceKey]: chosen.value };
|
|
14572
|
+
if (chosen.brand !== void 0) patch["brand"] = chosen.brand;
|
|
14573
|
+
if (chosen.region !== void 0) patch["region"] = chosen.region;
|
|
14574
|
+
onChangeMany?.(patch);
|
|
14575
|
+
};
|
|
14576
|
+
const statusAccount = account.length > 0 ? account : t("uiLibrary.accountSignIn.yourAccount", "your account");
|
|
14577
|
+
const status = count === null ? t("uiLibrary.accountSignIn.signedIn", "Signed in as {{account}}", { account: statusAccount }) : t("uiLibrary.accountSignIn.signedInCount", "Signed in as {{account}} · {{detail}}", {
|
|
14578
|
+
account: statusAccount,
|
|
14579
|
+
detail: field.countNoun !== void 0 ? `${count} ${nounFor(count, field.countNoun)}` : String(count)
|
|
14580
|
+
});
|
|
14581
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14582
|
+
className: "col-span-1 flex min-w-0 flex-col gap-2",
|
|
14583
|
+
children: [
|
|
14584
|
+
signedIn && phase === "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14585
|
+
className: "flex flex-col gap-2",
|
|
14586
|
+
children: [
|
|
14587
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14588
|
+
className: "text-xs text-foreground",
|
|
14589
|
+
children: status
|
|
14590
|
+
}),
|
|
14591
|
+
choices.length > 1 && field.choiceKey !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Select, {
|
|
14592
|
+
"aria-label": field.choiceLabel ?? t("uiLibrary.accountSignIn.choose", "Choose"),
|
|
14593
|
+
options: choices.map((row) => ({
|
|
14594
|
+
value: row.value,
|
|
14595
|
+
label: row.label
|
|
14596
|
+
})),
|
|
14597
|
+
value: selectedChoice(values[field.choiceKey]),
|
|
14598
|
+
onChange: (event) => pick(event.target.value),
|
|
14599
|
+
disabled: disabled || working
|
|
14600
|
+
}),
|
|
14601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14602
|
+
className: "flex flex-wrap gap-2",
|
|
14603
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
14604
|
+
type: "button",
|
|
14605
|
+
variant: "outline",
|
|
14606
|
+
size: "sm",
|
|
14607
|
+
disabled: disabled || working,
|
|
14608
|
+
onClick: () => void begin(),
|
|
14609
|
+
children: t("uiLibrary.accountSignIn.again", "Sign in again")
|
|
14610
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
14611
|
+
type: "button",
|
|
14612
|
+
variant: "ghost",
|
|
14613
|
+
size: "sm",
|
|
14614
|
+
disabled: disabled || working,
|
|
14615
|
+
onClick: () => void signOut(),
|
|
14616
|
+
children: t("uiLibrary.accountSignIn.signOut", "Sign out")
|
|
14617
|
+
})]
|
|
14618
|
+
})
|
|
14619
|
+
]
|
|
14620
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
14621
|
+
type: "button",
|
|
14622
|
+
variant: "primary",
|
|
14623
|
+
size: "sm",
|
|
14624
|
+
disabled: disabled || working,
|
|
14625
|
+
onClick: () => void begin(),
|
|
14626
|
+
children: working && phase !== "pasting" ? t("uiLibrary.accountSignIn.working", "Working…") : t("uiLibrary.accountSignIn.signInWith", "Sign in with {{provider}}", { provider: field.providerLabel })
|
|
14627
|
+
}),
|
|
14628
|
+
showPaste && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14629
|
+
className: "flex flex-col gap-1.5",
|
|
14630
|
+
children: [authorizeUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
14631
|
+
className: "text-[11px] text-primary break-all",
|
|
14632
|
+
href: authorizeUrl,
|
|
14633
|
+
target: "_blank",
|
|
14634
|
+
rel: "noopener noreferrer",
|
|
14635
|
+
children: t("uiLibrary.accountSignIn.open", "Open the sign-in page")
|
|
14636
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
14637
|
+
className: `${INPUT_CLASS$1} min-h-[60px] resize-y`,
|
|
14638
|
+
"aria-label": t("uiLibrary.accountSignIn.paste", "Redirect address or code"),
|
|
14639
|
+
placeholder: field.pastePlaceholder,
|
|
14640
|
+
value: paste,
|
|
14641
|
+
disabled: disabled || working,
|
|
14642
|
+
onChange: (event) => {
|
|
14643
|
+
const next = event.target.value;
|
|
14644
|
+
setPaste(next);
|
|
14645
|
+
if (shouldComplete(next)) complete(next);
|
|
14646
|
+
}
|
|
14647
|
+
})]
|
|
14648
|
+
}),
|
|
14649
|
+
error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14650
|
+
className: "text-[11px] text-danger",
|
|
14651
|
+
children: error
|
|
14652
|
+
})
|
|
14653
|
+
]
|
|
14654
|
+
});
|
|
14655
|
+
}
|
|
14656
|
+
function SecretPresenceField({ field, values }) {
|
|
14657
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14658
|
+
className: "col-span-1 text-xs text-foreground",
|
|
14659
|
+
children: isPresent(values[field.sourceKey]) ? field.yesLabel : field.noLabel
|
|
14660
|
+
});
|
|
14661
|
+
}
|
|
14662
|
+
//#endregion
|
|
14385
14663
|
//#region src/composites/confirm-dialog.tsx
|
|
14386
14664
|
/**
|
|
14387
14665
|
* The ONE modal dialog of the product — confirm, alert and prompt.
|
|
@@ -20685,39 +20963,6 @@ var Skeleton = (0, react$1.forwardRef)(({ className, ...props }, ref) => {
|
|
|
20685
20963
|
});
|
|
20686
20964
|
Skeleton.displayName = "Skeleton";
|
|
20687
20965
|
//#endregion
|
|
20688
|
-
//#region src/primitives/button.tsx
|
|
20689
|
-
var buttonVariants = cva("inline-flex items-center justify-center rounded-md font-medium transition-colors cursor-pointer disabled:opacity-50 disabled:pointer-events-none", {
|
|
20690
|
-
variants: {
|
|
20691
|
-
variant: {
|
|
20692
|
-
primary: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
20693
|
-
secondary: "bg-surface text-foreground hover:bg-surface-hover",
|
|
20694
|
-
ghost: "hover:bg-surface-hover text-foreground-muted",
|
|
20695
|
-
danger: "bg-danger text-white hover:bg-danger/90",
|
|
20696
|
-
outline: "border border-border bg-transparent text-foreground hover:bg-surface-hover"
|
|
20697
|
-
},
|
|
20698
|
-
size: {
|
|
20699
|
-
sm: "h-7 px-2.5 text-xs gap-1.5",
|
|
20700
|
-
md: "h-8 px-3 text-sm gap-2",
|
|
20701
|
-
lg: "h-9 px-4 text-sm gap-2"
|
|
20702
|
-
}
|
|
20703
|
-
},
|
|
20704
|
-
defaultVariants: {
|
|
20705
|
-
variant: "primary",
|
|
20706
|
-
size: "sm"
|
|
20707
|
-
}
|
|
20708
|
-
});
|
|
20709
|
-
var Button = (0, react$1.forwardRef)(({ className, variant, size, ...props }, ref) => {
|
|
20710
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
20711
|
-
ref,
|
|
20712
|
-
className: cn(buttonVariants({
|
|
20713
|
-
variant,
|
|
20714
|
-
size
|
|
20715
|
-
}), className),
|
|
20716
|
-
...props
|
|
20717
|
-
});
|
|
20718
|
-
});
|
|
20719
|
-
Button.displayName = "Button";
|
|
20720
|
-
//#endregion
|
|
20721
20966
|
//#region src/composites/cap-settings/consumable-rows.tsx
|
|
20722
20967
|
/** `value` null = unknown (D393) — renders an em-dash, never a fake `0`. */
|
|
20723
20968
|
function formatRemaining(t, r) {
|
|
@@ -29962,7 +30207,7 @@ function ProbeField({ field, value, onChange, disabled, translationFn, onTestFie
|
|
|
29962
30207
|
]
|
|
29963
30208
|
});
|
|
29964
30209
|
}
|
|
29965
|
-
function GroupField({ field, values, onChange, disabled, translationFn, onTestField }) {
|
|
30210
|
+
function GroupField({ field, values, onChange, onChangeMany, disabled, translationFn, onTestField, onAction }) {
|
|
29966
30211
|
const [collapsed, setCollapsed] = (0, react$1.useState)(field.defaultCollapsed ?? false);
|
|
29967
30212
|
const isAccordion = field.style === "accordion";
|
|
29968
30213
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -29986,9 +30231,11 @@ function GroupField({ field, values, onChange, disabled, translationFn, onTestFi
|
|
|
29986
30231
|
field: subField,
|
|
29987
30232
|
values,
|
|
29988
30233
|
onChange,
|
|
30234
|
+
onChangeMany,
|
|
29989
30235
|
disabled,
|
|
29990
30236
|
translationFn,
|
|
29991
|
-
onTestField
|
|
30237
|
+
onTestField,
|
|
30238
|
+
onAction
|
|
29992
30239
|
}, subField.key))
|
|
29993
30240
|
})]
|
|
29994
30241
|
})
|
|
@@ -30404,6 +30651,10 @@ function AddonActionSelectField({ field, value, values, onChange, disabled, onAc
|
|
|
30404
30651
|
}
|
|
30405
30652
|
}
|
|
30406
30653
|
setOptions(list);
|
|
30654
|
+
if (field.hideWhenFewerThan !== void 0 && list.length === 1 && (typeof value !== "string" || value.length === 0)) {
|
|
30655
|
+
const only = list[0]?.[valueKey];
|
|
30656
|
+
if (typeof only === "string" && only.length > 0) onChange(only);
|
|
30657
|
+
}
|
|
30407
30658
|
}).catch((err) => {
|
|
30408
30659
|
if (cancelled) return;
|
|
30409
30660
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -30423,6 +30674,8 @@ function AddonActionSelectField({ field, value, values, onChange, disabled, onAc
|
|
|
30423
30674
|
const valueKey = field.mapOption.value;
|
|
30424
30675
|
const labelKey = field.mapOption.label;
|
|
30425
30676
|
const descKey = field.mapOption.description;
|
|
30677
|
+
if (!onAction && field.hideWhenFewerThan !== void 0) return null;
|
|
30678
|
+
if (field.hideWhenFewerThan !== void 0 && options !== null && options.length < field.hideWhenFewerThan) return null;
|
|
30426
30679
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FieldWrapper, {
|
|
30427
30680
|
label: field.label,
|
|
30428
30681
|
description: field.description,
|
|
@@ -31055,9 +31308,11 @@ function FormField({ field, values, onChange, onChangeMany, disabled, translatio
|
|
|
31055
31308
|
field,
|
|
31056
31309
|
values,
|
|
31057
31310
|
onChange,
|
|
31311
|
+
onChangeMany,
|
|
31058
31312
|
disabled,
|
|
31059
31313
|
translationFn,
|
|
31060
|
-
onTestField
|
|
31314
|
+
onTestField,
|
|
31315
|
+
onAction
|
|
31061
31316
|
});
|
|
31062
31317
|
case "sub-tabs": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SubTabsField, {
|
|
31063
31318
|
field,
|
|
@@ -31086,22 +31341,36 @@ function FormField({ field, values, onChange, onChangeMany, disabled, translatio
|
|
|
31086
31341
|
disabled,
|
|
31087
31342
|
onAction
|
|
31088
31343
|
});
|
|
31089
|
-
case "addon-action-select":
|
|
31344
|
+
case "addon-action-select": {
|
|
31345
|
+
const storedKey = field.writesKey ?? field.key;
|
|
31346
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddonActionSelectField, {
|
|
31347
|
+
field,
|
|
31348
|
+
value: values[storedKey],
|
|
31349
|
+
values,
|
|
31350
|
+
onChange: (next) => onChange(storedKey, next),
|
|
31351
|
+
disabled,
|
|
31352
|
+
onAction
|
|
31353
|
+
});
|
|
31354
|
+
}
|
|
31355
|
+
case "addon-action-button": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddonActionButtonField, {
|
|
31090
31356
|
field,
|
|
31091
|
-
value,
|
|
31092
31357
|
values,
|
|
31093
|
-
onChange: handleChange,
|
|
31094
31358
|
disabled,
|
|
31095
|
-
onAction
|
|
31359
|
+
onAction,
|
|
31360
|
+
onChange,
|
|
31361
|
+
onChangeMany
|
|
31096
31362
|
});
|
|
31097
|
-
case "
|
|
31363
|
+
case "account-sign-in": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountSignInField, {
|
|
31098
31364
|
field,
|
|
31099
31365
|
values,
|
|
31100
31366
|
disabled,
|
|
31101
31367
|
onAction,
|
|
31102
|
-
onChange,
|
|
31103
31368
|
onChangeMany
|
|
31104
31369
|
});
|
|
31370
|
+
case "secret-presence": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SecretPresenceField, {
|
|
31371
|
+
field,
|
|
31372
|
+
values
|
|
31373
|
+
});
|
|
31105
31374
|
case "device-action-button": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceActionButtonField, {
|
|
31106
31375
|
field,
|
|
31107
31376
|
values,
|
|
@@ -32467,9 +32736,36 @@ function ConfigSchemaFieldControl({ field, allFields, step, disabled, modelScope
|
|
|
32467
32736
|
}
|
|
32468
32737
|
//#endregion
|
|
32469
32738
|
//#region src/composites/step-inspector/setting-values.ts
|
|
32739
|
+
/**
|
|
32740
|
+
* How the step inspector names a stored setting value, and what a field falls
|
|
32741
|
+
* back to when no layer stores it. Pure, so the provenance line and its tests
|
|
32742
|
+
* agree on one spelling.
|
|
32743
|
+
*/
|
|
32470
32744
|
function isValueField(field) {
|
|
32471
32745
|
return field.type !== "separator" && field.type !== "info" && field.type !== "group";
|
|
32472
32746
|
}
|
|
32747
|
+
/**
|
|
32748
|
+
* A field only the accelerator that runs the model may set (D927): a model id,
|
|
32749
|
+
* a `<key>ModelId` binding, a `minConfidence*` floor, or any field the schema
|
|
32750
|
+
* marks as bound to its model. A camera never renders one as an input.
|
|
32751
|
+
*/
|
|
32752
|
+
function isModelScopedField(field) {
|
|
32753
|
+
if ("bindsToModel" in field && field.bindsToModel === true) return true;
|
|
32754
|
+
return "key" in field && (0, _camstack_types.isModelScopedStepSettingKey)(field.key);
|
|
32755
|
+
}
|
|
32756
|
+
/** The fields a CAMERA may edit: every model-scoped field removed, groups recursed. */
|
|
32757
|
+
function withoutModelScopedFields(fields) {
|
|
32758
|
+
return fields.flatMap((field) => {
|
|
32759
|
+
if (field.type === "group") {
|
|
32760
|
+
const inner = withoutModelScopedFields(field.fields);
|
|
32761
|
+
return inner.length > 0 ? [{
|
|
32762
|
+
...field,
|
|
32763
|
+
fields: [...inner]
|
|
32764
|
+
}] : [];
|
|
32765
|
+
}
|
|
32766
|
+
return isModelScopedField(field) ? [] : [field];
|
|
32767
|
+
});
|
|
32768
|
+
}
|
|
32473
32769
|
/** True for a D738 field whose value is stored with the model it was made for. */
|
|
32474
32770
|
function bindsToModel(field) {
|
|
32475
32771
|
return (field.type === "slider" || field.type === "number") && field.bindsToModel === true;
|
|
@@ -32586,7 +32882,7 @@ function SettingProvenance({ field, layers, target, labels, boundKeys, modelId,
|
|
|
32586
32882
|
children: withDefault.join(" · ")
|
|
32587
32883
|
}),
|
|
32588
32884
|
pinned && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
32589
|
-
className: "rounded border border-
|
|
32885
|
+
className: "rounded border border-warning/40 px-1.5 py-px text-warning",
|
|
32590
32886
|
title: t("uiLibrary.layeredSettings.pinnedHint", "Stored by an older editor as a copy of the value below. It changes nothing today, but it stops later changes below from reaching this camera."),
|
|
32591
32887
|
children: t("uiLibrary.layeredSettings.pinned", "pinned at the {{source}} value", { source: pinnedAt.toLowerCase() })
|
|
32592
32888
|
}),
|
|
@@ -32603,8 +32899,9 @@ function SettingProvenance({ field, layers, target, labels, boundKeys, modelId,
|
|
|
32603
32899
|
]
|
|
32604
32900
|
});
|
|
32605
32901
|
}
|
|
32606
|
-
function LayeredSettingsForm({ addon, fields, layers, target, labels, modelId, onChangeLayer, rootModel, pinnedKeys = [], fieldActions, headerActions, highlightKey = null, disabled = false }) {
|
|
32902
|
+
function LayeredSettingsForm({ addon, fields: givenFields, layers, target, labels, modelId, onChangeLayer, rootModel, pinnedKeys = [], fieldActions, headerActions, highlightKey = null, disabled = false }) {
|
|
32607
32903
|
const t = useUiText();
|
|
32904
|
+
const fields = target === "camera" ? withoutModelScopedFields(givenFields) : givenFields;
|
|
32608
32905
|
const boundKeys = (0, _camstack_types.collectModelBoundKeys)(fields);
|
|
32609
32906
|
const effective = (0, _camstack_types.effectiveStepSettings)(layers);
|
|
32610
32907
|
const targetLayer = layers[target];
|
|
@@ -33616,6 +33913,99 @@ function BatteryBadge({ status, variant = "compact", className }) {
|
|
|
33616
33913
|
});
|
|
33617
33914
|
}
|
|
33618
33915
|
//#endregion
|
|
33916
|
+
//#region src/composites/running-status.ts
|
|
33917
|
+
function trimmedPhase(phase) {
|
|
33918
|
+
if (phase === null) return void 0;
|
|
33919
|
+
const trimmed = phase.trim();
|
|
33920
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
33921
|
+
}
|
|
33922
|
+
/** Minutes elapsed since `since`, at least 1; null when `since` is not usable. */
|
|
33923
|
+
function runningDurationSince(since, now) {
|
|
33924
|
+
if (since === null || !Number.isFinite(since) || since <= 0) return null;
|
|
33925
|
+
const ms = now - since;
|
|
33926
|
+
if (ms <= 0) return null;
|
|
33927
|
+
const totalMinutes = Math.floor(ms / 6e4);
|
|
33928
|
+
if (totalMinutes < 60) return { minutes: Math.max(1, totalMinutes) };
|
|
33929
|
+
return { hours: Math.floor(totalMinutes / 60) };
|
|
33930
|
+
}
|
|
33931
|
+
function runningStatusParts(running, since, phase, now) {
|
|
33932
|
+
const phaseLabel = trimmedPhase(phase);
|
|
33933
|
+
if (running === null) return { key: "unknown" };
|
|
33934
|
+
if (running === false) return phaseLabel === void 0 ? { key: "idle" } : {
|
|
33935
|
+
key: "idle",
|
|
33936
|
+
phase: phaseLabel
|
|
33937
|
+
};
|
|
33938
|
+
const duration = runningDurationSince(since, now);
|
|
33939
|
+
if (duration === null) return phaseLabel === void 0 ? { key: "running" } : {
|
|
33940
|
+
key: "running",
|
|
33941
|
+
phase: phaseLabel
|
|
33942
|
+
};
|
|
33943
|
+
return {
|
|
33944
|
+
key: "running",
|
|
33945
|
+
duration,
|
|
33946
|
+
...phaseLabel === void 0 ? {} : { phase: phaseLabel }
|
|
33947
|
+
};
|
|
33948
|
+
}
|
|
33949
|
+
//#endregion
|
|
33950
|
+
//#region src/composites/running-badge.tsx
|
|
33951
|
+
function RunningBadge({ running, children, className }) {
|
|
33952
|
+
const t = useUiText();
|
|
33953
|
+
if (running === null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
33954
|
+
"data-running": "unknown",
|
|
33955
|
+
className: cn("inline-flex shrink-0", className),
|
|
33956
|
+
children
|
|
33957
|
+
});
|
|
33958
|
+
if (running === true) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
33959
|
+
"data-running": "running",
|
|
33960
|
+
className: cn("relative inline-flex shrink-0 rounded-full p-0.5", className),
|
|
33961
|
+
"aria-label": t("uiLibrary.runningBadge.running", "Running"),
|
|
33962
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
33963
|
+
className: "pointer-events-none absolute inset-0 rounded-full border border-primary animate-pulse",
|
|
33964
|
+
"aria-hidden": true
|
|
33965
|
+
}), children]
|
|
33966
|
+
});
|
|
33967
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
33968
|
+
"data-running": "idle",
|
|
33969
|
+
className: cn("relative inline-flex shrink-0", className),
|
|
33970
|
+
"aria-label": t("uiLibrary.runningBadge.idle", "Idle"),
|
|
33971
|
+
children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
33972
|
+
className: "pointer-events-none absolute -bottom-px -right-px h-1.5 w-1.5 rounded-full bg-foreground-subtle",
|
|
33973
|
+
"aria-hidden": true
|
|
33974
|
+
})]
|
|
33975
|
+
});
|
|
33976
|
+
}
|
|
33977
|
+
function RunningStatusLine({ running, since, phase, className, now = Date.now() }) {
|
|
33978
|
+
const t = useUiText();
|
|
33979
|
+
const parts = runningStatusParts(running, since, phase, now);
|
|
33980
|
+
if (parts.key === "unknown") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
33981
|
+
className: cn("text-[11px] text-foreground-subtle", className),
|
|
33982
|
+
children: t("uiLibrary.runningStatus.unknown", "Unknown")
|
|
33983
|
+
});
|
|
33984
|
+
if (parts.key === "idle") {
|
|
33985
|
+
const base = t("uiLibrary.runningStatus.idle", "Idle");
|
|
33986
|
+
const text = parts.phase === void 0 ? base : t("uiLibrary.runningStatus.withPhase", "{{state}} · {{phase}}", {
|
|
33987
|
+
state: base,
|
|
33988
|
+
phase: parts.phase
|
|
33989
|
+
});
|
|
33990
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
33991
|
+
className: cn("text-[11px] text-foreground-muted", className),
|
|
33992
|
+
children: text
|
|
33993
|
+
});
|
|
33994
|
+
}
|
|
33995
|
+
let base;
|
|
33996
|
+
if (parts.duration === void 0) base = t("uiLibrary.runningStatus.running", "Running");
|
|
33997
|
+
else if ("minutes" in parts.duration) base = t("uiLibrary.runningStatus.runningForMinutes", "Running for {{count}} min", { count: parts.duration.minutes });
|
|
33998
|
+
else base = t("uiLibrary.runningStatus.runningForHours", "Running for {{count}} h", { count: parts.duration.hours });
|
|
33999
|
+
const text = parts.phase === void 0 ? base : t("uiLibrary.runningStatus.withPhase", "{{state}} · {{phase}}", {
|
|
34000
|
+
state: base,
|
|
34001
|
+
phase: parts.phase
|
|
34002
|
+
});
|
|
34003
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
34004
|
+
className: cn("text-[11px] text-foreground-muted", className),
|
|
34005
|
+
children: text
|
|
34006
|
+
});
|
|
34007
|
+
}
|
|
34008
|
+
//#endregion
|
|
33619
34009
|
//#region src/composites/network-link-badge.tsx
|
|
33620
34010
|
/**
|
|
33621
34011
|
* NetworkLinkBadge — compact link indicator for device rows and headers.
|
|
@@ -50556,6 +50946,18 @@ function dishwasherHeadline(status, t = defaultUiText) {
|
|
|
50556
50946
|
function featureLabel(key) {
|
|
50557
50947
|
return (key.split(".").pop() ?? key).replace(/([a-z0-9])([A-Z])/g, "$1 $2");
|
|
50558
50948
|
}
|
|
50949
|
+
/**
|
|
50950
|
+
* Salt and rinse aid are consumable items (D915). Their events must not
|
|
50951
|
+
* reappear on the hero — the Consumables section is the only surface.
|
|
50952
|
+
*/
|
|
50953
|
+
function isConsumableDishwasherEvent(event) {
|
|
50954
|
+
const short = (event.split(".").pop() ?? event).toLowerCase();
|
|
50955
|
+
return short.includes("salt") || short.includes("rinse");
|
|
50956
|
+
}
|
|
50957
|
+
/** Raised events the hero may name. Consumable events are dropped. */
|
|
50958
|
+
function visibleDishwasherEvents(events) {
|
|
50959
|
+
return events.filter((event) => !isConsumableDishwasherEvent(event));
|
|
50960
|
+
}
|
|
50559
50961
|
/** Whole seconds as a short duration: `1 h 24 min`, `42 min`, `30 s`. */
|
|
50560
50962
|
function formatDuration(seconds, t = defaultUiText) {
|
|
50561
50963
|
if (seconds < 60) return t("uiLibrary.dishwasher.durationSeconds", "{{n}} s", { n: seconds });
|
|
@@ -50712,7 +51114,7 @@ function DishwasherPanel({ trpc, deviceId, layout }) {
|
|
|
50712
51114
|
children: [display.doorOpen === true && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
50713
51115
|
className: "inline-flex items-center gap-1 text-xs text-warning",
|
|
50714
51116
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DoorOpen, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.doorOpen", "Door open")]
|
|
50715
|
-
}), display.activeEvents.map((event) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
51117
|
+
}), visibleDishwasherEvents(display.activeEvents).map((event) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
50716
51118
|
className: "text-xs text-warning",
|
|
50717
51119
|
title: event,
|
|
50718
51120
|
children: featureLabel(event)
|
|
@@ -55202,6 +55604,8 @@ function ChildRow$1({ trpc, child, onNavigate, parentName }) {
|
|
|
55202
55604
|
const showMotionTrigger = enabled && hasMotionTriggerFeature(child);
|
|
55203
55605
|
const roleDefaults = useRoleDisplayDefaults();
|
|
55204
55606
|
useIconGlyphsVersion();
|
|
55607
|
+
const ChildIcon = deviceLeadIcon(child, roleDefaults);
|
|
55608
|
+
const runningSlice = useDeviceState(trpc, child.id, (s) => s.runningState);
|
|
55205
55609
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
55206
55610
|
onClick: (e) => {
|
|
55207
55611
|
e.stopPropagation();
|
|
@@ -55209,7 +55613,10 @@ function ChildRow$1({ trpc, child, onNavigate, parentName }) {
|
|
|
55209
55613
|
},
|
|
55210
55614
|
className: "w-full flex items-center gap-2 px-3 py-1.5 text-left hover:bg-surface-hover transition-colors cursor-pointer",
|
|
55211
55615
|
children: [
|
|
55212
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
55616
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RunningBadge, {
|
|
55617
|
+
running: runningSlice === void 0 || runningSlice.running === null ? null : runningSlice.running,
|
|
55618
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChildIcon, { className: "h-3 w-3 text-foreground-subtle flex-shrink-0" })
|
|
55619
|
+
}),
|
|
55213
55620
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
55214
55621
|
className: "text-[10.5px] text-foreground flex-1 truncate",
|
|
55215
55622
|
children: childListName(child, parentName)
|
|
@@ -55603,13 +56010,16 @@ var CHEVRON_SLOT_CLASS = {
|
|
|
55603
56010
|
horizontal: "h-3.5 w-3.5",
|
|
55604
56011
|
stacked: "h-4 w-4 mt-0.5"
|
|
55605
56012
|
};
|
|
55606
|
-
function DeviceItemHeader({ device, variant, flags, parent, integrationIcon, hasChildren, expanded, onToggleExpand, onNavigateToParent, stacked = false, nameOverflow = "truncate" }) {
|
|
56013
|
+
function DeviceItemHeader({ trpc, device, variant, flags, parent, integrationIcon, hasChildren, expanded, onToggleExpand, onNavigateToParent, stacked = false, nameOverflow = "truncate" }) {
|
|
55607
56014
|
const t = useUiText();
|
|
55608
56015
|
const containerChildren = useContainerChildren(device.id);
|
|
55609
56016
|
const roleDefaults = useRoleDisplayDefaults();
|
|
55610
56017
|
useIconGlyphsVersion();
|
|
55611
56018
|
const Icon = deviceLeadIcon(effectiveIconDevice(device, containerChildren), roleDefaults);
|
|
56019
|
+
const runningSlice = useDeviceState(trpc, device.id, (s) => s.runningState);
|
|
56020
|
+
const runningBadge = runningSlice === void 0 || runningSlice.running === null ? null : runningSlice.running;
|
|
55612
56021
|
const slotClass = stacked ? CHEVRON_SLOT_CLASS.stacked : CHEVRON_SLOT_CLASS.horizontal;
|
|
56022
|
+
const iconClass = cn("text-foreground-subtle flex-shrink-0", stacked ? "h-4 w-4 mt-0.5" : variant === "minimal" ? "h-3 w-3" : "h-3.5 w-3.5");
|
|
55613
56023
|
const lineClass = nameOverflow === "scroll" ? NAME_TEXT_CLASS : "truncate";
|
|
55614
56024
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
55615
56025
|
className: cn(stacked ? "flex items-start gap-2 w-full min-w-0" : "flex items-center gap-2 flex-1 min-w-0"),
|
|
@@ -55629,7 +56039,10 @@ function DeviceItemHeader({ device, variant, flags, parent, integrationIcon, has
|
|
|
55629
56039
|
"data-testid": "chevron-slot",
|
|
55630
56040
|
className: cn("flex-shrink-0", slotClass)
|
|
55631
56041
|
}) : null,
|
|
55632
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
56042
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RunningBadge, {
|
|
56043
|
+
running: runningBadge,
|
|
56044
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: iconClass })
|
|
56045
|
+
}),
|
|
55633
56046
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
55634
56047
|
className: "flex-1 min-w-0",
|
|
55635
56048
|
children: [
|
|
@@ -56123,6 +56536,7 @@ function DeviceItem(props) {
|
|
|
56123
56536
|
className: "flex-shrink-0"
|
|
56124
56537
|
}),
|
|
56125
56538
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItemHeader, {
|
|
56539
|
+
trpc,
|
|
56126
56540
|
device,
|
|
56127
56541
|
variant,
|
|
56128
56542
|
flags,
|
|
@@ -56199,6 +56613,7 @@ function DeviceItem(props) {
|
|
|
56199
56613
|
className: "flex-shrink-0 mt-0.5"
|
|
56200
56614
|
}),
|
|
56201
56615
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItemHeader, {
|
|
56616
|
+
trpc,
|
|
56202
56617
|
device,
|
|
56203
56618
|
variant,
|
|
56204
56619
|
flags,
|
|
@@ -56290,6 +56705,7 @@ function DeviceItemTableRow(props) {
|
|
|
56290
56705
|
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name: device.name }),
|
|
56291
56706
|
className: "flex-shrink-0"
|
|
56292
56707
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItemHeader, {
|
|
56708
|
+
trpc,
|
|
56293
56709
|
device,
|
|
56294
56710
|
variant,
|
|
56295
56711
|
flags,
|
|
@@ -61234,6 +61650,7 @@ function RecordEntrySecretField({ name, label, required, value, disabled, onPatc
|
|
|
61234
61650
|
function SchemaField(props) {
|
|
61235
61651
|
const { path, name, node, value, secretPaths, required, disabled, onPatch } = props;
|
|
61236
61652
|
const label = labelFor(name, node);
|
|
61653
|
+
const uiText = useUiText();
|
|
61237
61654
|
if (isSecretField(path, secretPaths, node)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RecordEntrySecretField, {
|
|
61238
61655
|
name,
|
|
61239
61656
|
label,
|
|
@@ -61305,7 +61722,7 @@ function SchemaField(props) {
|
|
|
61305
61722
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormField$1, {
|
|
61306
61723
|
label,
|
|
61307
61724
|
required,
|
|
61308
|
-
description: "JSON object",
|
|
61725
|
+
description: uiText("uiLibrary.recordEntries.jsonObject", "JSON object"),
|
|
61309
61726
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
61310
61727
|
className: cn("min-h-[8rem] w-full resize-y rounded-md border border-border bg-surface px-2.5 py-2 font-mono text-xs text-foreground", "placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-inset focus:ring-primary", "disabled:cursor-not-allowed disabled:opacity-50"),
|
|
61311
61728
|
rows: 6,
|
|
@@ -62062,9 +62479,8 @@ function ResponseLog({ data, label = "Response", className = "" }) {
|
|
|
62062
62479
|
* `clampToParent` narrows the target dropdown + access checkboxes to
|
|
62063
62480
|
* what the CALLER possesses. Admins pass `null` to allow everything.
|
|
62064
62481
|
*
|
|
62065
|
-
* This is the RAW editor.
|
|
62066
|
-
*
|
|
62067
|
-
* one is what an operator drops into when a grant set is not a plain role.
|
|
62482
|
+
* This is the RAW editor, for TOKENS. People are not edited here: a person
|
|
62483
|
+
* is an Admin or a Viewer (D921), set from `/system/identity?tab=users`.
|
|
62068
62484
|
*/
|
|
62069
62485
|
/** `<select>` value → the tri-state `includeLinked` it means. */
|
|
62070
62486
|
var INCLUDE_LINKED_VALUES = {
|
|
@@ -68460,6 +68876,8 @@ exports.RotateCcw = RotateCcw;
|
|
|
68460
68876
|
exports.RotateCw = RotateCw;
|
|
68461
68877
|
exports.Route = Route;
|
|
68462
68878
|
exports.RunReport = RunReport;
|
|
68879
|
+
exports.RunningBadge = RunningBadge;
|
|
68880
|
+
exports.RunningStatusLine = RunningStatusLine;
|
|
68463
68881
|
exports.SCENE_CAPTURE_VARIANTS = SCENE_CAPTURE_VARIANTS;
|
|
68464
68882
|
exports.SCENE_CAPTURE_VARIANTS$1 = SCENE_CAPTURE_VARIANTS;
|
|
68465
68883
|
exports.SECRET_MASK_PLACEHOLDER = SECRET_MASK_PLACEHOLDER;
|
|
@@ -68800,6 +69218,7 @@ exports.isFieldVisible = isFieldVisible;
|
|
|
68800
69218
|
exports.isGroupExpanded = isGroupExpanded;
|
|
68801
69219
|
exports.isHistoryWindowId = isHistoryWindowId;
|
|
68802
69220
|
exports.isKeychainFieldValue = isKeychainFieldValue;
|
|
69221
|
+
exports.isModelScopedField = isModelScopedField;
|
|
68803
69222
|
exports.isRedactedSecret = isRedactedSecret;
|
|
68804
69223
|
exports.isRefusal = isRefusal;
|
|
68805
69224
|
exports.isSecretField = isSecretField;
|
|
@@ -68900,6 +69319,8 @@ exports.roiTooLarge = roiTooLarge;
|
|
|
68900
69319
|
exports.roiTooLarge$1 = roiTooLarge;
|
|
68901
69320
|
exports.rootSourceState = rootSourceState;
|
|
68902
69321
|
exports.routerBasename = routerBasename;
|
|
69322
|
+
exports.runningDurationSince = runningDurationSince;
|
|
69323
|
+
exports.runningStatusParts = runningStatusParts;
|
|
68903
69324
|
exports.sameLocationSuggestions = sameLocationSuggestions;
|
|
68904
69325
|
exports.scrubReducer = scrubReducer;
|
|
68905
69326
|
exports.searchSteps = searchSteps;
|
|
@@ -69994,6 +70415,7 @@ exports.useRecordingOnboardSetSettings = useRecordingOnboardSetSettings;
|
|
|
69994
70415
|
exports.useRecordingSignalGetStatus = useRecordingSignalGetStatus;
|
|
69995
70416
|
exports.useRemoteComponent = useRemoteComponent;
|
|
69996
70417
|
exports.useRoleDisplayDefaults = useRoleDisplayDefaults;
|
|
70418
|
+
exports.useRunningStateGetStatus = useRunningStateGetStatus;
|
|
69997
70419
|
exports.useSceneMonitorCaptureReference = useSceneMonitorCaptureReference;
|
|
69998
70420
|
exports.useSceneMonitorCreateScene = useSceneMonitorCreateScene;
|
|
69999
70421
|
exports.useSceneMonitorDeleteReference = useSceneMonitorDeleteReference;
|
|
@@ -70264,5 +70686,6 @@ exports.withHiddenChart = withHiddenChart;
|
|
|
70264
70686
|
exports.withPanel = withPanel;
|
|
70265
70687
|
exports.withResolvedParentDetail = withResolvedParentDetail;
|
|
70266
70688
|
exports.withUseRootModel = withUseRootModel;
|
|
70689
|
+
exports.withoutModelScopedFields = withoutModelScopedFields;
|
|
70267
70690
|
exports.withoutPanel = withoutPanel;
|
|
70268
70691
|
exports.writeStoredGroupBy = writeStoredGroupBy;
|