@camstack/ui-library 1.2.300 → 1.2.302
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/data-records/data-records-hub.d.ts +9 -0
- package/dist/composites/data-records/data-records-model.d.ts +26 -0
- package/dist/composites/data-records/index.d.ts +2 -0
- package/dist/composites/data-table-filter-bar.d.ts +6 -0
- package/dist/composites/data-table.d.ts +11 -2
- package/dist/composites/device-controls/dishwasher-control.d.ts +14 -2
- package/dist/composites/index.d.ts +1 -0
- package/dist/composites/record-entries/index.d.ts +0 -1
- package/dist/composites/record-entries/record-entries-panel.d.ts +15 -3
- package/dist/composites/storage-records/index.d.ts +0 -1
- package/dist/generated/system-hooks.d.ts +14 -0
- package/dist/index.cjs +615 -385
- package/dist/index.js +600 -380
- package/package.json +1 -1
- package/dist/composites/record-entries/record-entries-hub.d.ts +0 -9
- package/dist/composites/storage-records/storage-records-hub.d.ts +0 -4
package/dist/index.cjs
CHANGED
|
@@ -11016,6 +11016,8 @@ var useDeviceStatusGetStatus = trpc.deviceStatus.getStatus.useQuery;
|
|
|
11016
11016
|
var useDishwasherStart = trpc.dishwasher.start.useMutation;
|
|
11017
11017
|
/** Generated alias around `trpc.dishwasher.pause.useMutation`. */
|
|
11018
11018
|
var useDishwasherPause = trpc.dishwasher.pause.useMutation;
|
|
11019
|
+
/** Generated alias around `trpc.dishwasher.resume.useMutation`. */
|
|
11020
|
+
var useDishwasherResume = trpc.dishwasher.resume.useMutation;
|
|
11019
11021
|
/** Generated alias around `trpc.dishwasher.stop.useMutation`. */
|
|
11020
11022
|
var useDishwasherStop = trpc.dishwasher.stop.useMutation;
|
|
11021
11023
|
/** Generated alias around `trpc.dishwasher.setProgram.useMutation`. */
|
|
@@ -11026,8 +11028,18 @@ var useDishwasherSetPower = trpc.dishwasher.setPower.useMutation;
|
|
|
11026
11028
|
var useDishwasherSetHalfLoad = trpc.dishwasher.setHalfLoad.useMutation;
|
|
11027
11029
|
/** Generated alias around `trpc.dishwasher.setHygienePlus.useMutation`. */
|
|
11028
11030
|
var useDishwasherSetHygienePlus = trpc.dishwasher.setHygienePlus.useMutation;
|
|
11031
|
+
/** Generated alias around `trpc.dishwasher.setExtraDry.useMutation`. */
|
|
11032
|
+
var useDishwasherSetExtraDry = trpc.dishwasher.setExtraDry.useMutation;
|
|
11033
|
+
/** Generated alias around `trpc.dishwasher.setIntensiveZone.useMutation`. */
|
|
11034
|
+
var useDishwasherSetIntensiveZone = trpc.dishwasher.setIntensiveZone.useMutation;
|
|
11035
|
+
/** Generated alias around `trpc.dishwasher.setVarioSpeedPlus.useMutation`. */
|
|
11036
|
+
var useDishwasherSetVarioSpeedPlus = trpc.dishwasher.setVarioSpeedPlus.useMutation;
|
|
11037
|
+
/** Generated alias around `trpc.dishwasher.setChildLock.useMutation`. */
|
|
11038
|
+
var useDishwasherSetChildLock = trpc.dishwasher.setChildLock.useMutation;
|
|
11029
11039
|
/** Generated alias around `trpc.dishwasher.setOption.useMutation`. */
|
|
11030
11040
|
var useDishwasherSetOption = trpc.dishwasher.setOption.useMutation;
|
|
11041
|
+
/** Generated alias around `trpc.dishwasher.getOptions.useQuery`. */
|
|
11042
|
+
var useDishwasherGetOptions = trpc.dishwasher.getOptions.useQuery;
|
|
11031
11043
|
/** Generated alias around `trpc.dishwasher.getStatus.useQuery`. */
|
|
11032
11044
|
var useDishwasherGetStatus = trpc.dishwasher.getStatus.useQuery;
|
|
11033
11045
|
/** Generated alias around `trpc.doorbell.getStatus.useQuery`. */
|
|
@@ -12354,6 +12366,8 @@ var useStorageMigrationStatus = trpc.storageMigration.status.useQuery;
|
|
|
12354
12366
|
var useStorageMigrationCancel = trpc.storageMigration.cancel.useMutation;
|
|
12355
12367
|
/** Generated alias around `trpc.storageMigration.movers.useQuery`. */
|
|
12356
12368
|
var useStorageMigrationMovers = trpc.storageMigration.movers.useQuery;
|
|
12369
|
+
/** Generated alias around `trpc.storageMigration.moverClearance.useQuery`. */
|
|
12370
|
+
var useStorageMigrationMoverClearance = trpc.storageMigration.moverClearance.useQuery;
|
|
12357
12371
|
/** Generated alias around `trpc.storageMigration.residue.useQuery`. */
|
|
12358
12372
|
var useStorageMigrationResidue = trpc.storageMigration.residue.useQuery;
|
|
12359
12373
|
/** Generated alias around `trpc.storageMigration.drain.useMutation`. */
|
|
@@ -28580,7 +28594,7 @@ var STATUS_DOT_STYLES = {
|
|
|
28580
28594
|
idle: "bg-foreground-subtle/40",
|
|
28581
28595
|
unknown: "bg-foreground-subtle/40"
|
|
28582
28596
|
};
|
|
28583
|
-
function formatDuration(ms) {
|
|
28597
|
+
function formatDuration$1(ms) {
|
|
28584
28598
|
if (!Number.isFinite(ms) || ms < 0) return "—";
|
|
28585
28599
|
if (ms < 1e3) return `${ms}ms`;
|
|
28586
28600
|
const totalSec = Math.round(ms / 1e3);
|
|
@@ -28608,7 +28622,7 @@ function ObjectArrayCell({ kind, value }) {
|
|
|
28608
28622
|
});
|
|
28609
28623
|
if (kind === "duration" && typeof value === "number") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
28610
28624
|
className: "font-mono text-[11px]",
|
|
28611
|
-
children: formatDuration(value)
|
|
28625
|
+
children: formatDuration$1(value)
|
|
28612
28626
|
});
|
|
28613
28627
|
if (kind === "timestamp" && typeof value === "number") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
28614
28628
|
className: "font-mono text-[11px]",
|
|
@@ -35108,7 +35122,7 @@ var ALIGN_CLASS = {
|
|
|
35108
35122
|
right: "text-right",
|
|
35109
35123
|
center: "text-center"
|
|
35110
35124
|
};
|
|
35111
|
-
function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyMessage, className, bordered = true, rowClassName, maxBodyHeight, fill = false, defaultSort, sort: sortProp, onSortChange, pageSize, page: pageProp, onPageChange, paginationLabels = DEFAULT_PAGINATION_LABELS, selection }) {
|
|
35125
|
+
function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyMessage, className, bordered = true, rowClassName, maxBodyHeight, fill = false, defaultSort, sort: sortProp, onSortChange, pageSize, page: pageProp, onPageChange, paginationLabels = DEFAULT_PAGINATION_LABELS, selection, renderExpanded, isExpanded }) {
|
|
35112
35126
|
const [innerSort, setInnerSort] = (0, react$1.useState)(defaultSort ?? null);
|
|
35113
35127
|
const [innerPage, setInnerPage] = (0, react$1.useState)(0);
|
|
35114
35128
|
const sort = sortProp !== void 0 ? sortProp : innerSort;
|
|
@@ -35185,7 +35199,8 @@ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyM
|
|
|
35185
35199
|
const key = rowKey ? rowKey(row, rowIndex) : rowIndex;
|
|
35186
35200
|
const extra = rowClassName?.(row, rowIndex) ?? "";
|
|
35187
35201
|
const interactive = onRowClick !== void 0;
|
|
35188
|
-
|
|
35202
|
+
const detail = renderExpanded !== void 0 && isExpanded?.(row) === true ? renderExpanded(row, rowIndex) : null;
|
|
35203
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react$1.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
|
|
35189
35204
|
onClick: interactive ? () => onRowClick(row, rowIndex) : void 0,
|
|
35190
35205
|
className: [interactive ? "cursor-pointer hover:bg-primary/5" : "hover:bg-primary/5", extra].filter(Boolean).join(" "),
|
|
35191
35206
|
children: shownColumns.map((col) => {
|
|
@@ -35201,7 +35216,15 @@ function DataTable({ columns, rows, rowKey, onRowClick, minWidthPx = 480, emptyM
|
|
|
35201
35216
|
children: col.render(row, rowIndex)
|
|
35202
35217
|
}, col.key);
|
|
35203
35218
|
})
|
|
35204
|
-
},
|
|
35219
|
+
}), detail !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
|
|
35220
|
+
"data-expanded-row": "",
|
|
35221
|
+
className: "bg-surface",
|
|
35222
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
35223
|
+
colSpan: shownColumns.length,
|
|
35224
|
+
className: "border-b border-border px-3 py-2",
|
|
35225
|
+
children: detail
|
|
35226
|
+
})
|
|
35227
|
+
})] }, key);
|
|
35205
35228
|
}) })]
|
|
35206
35229
|
})
|
|
35207
35230
|
});
|
|
@@ -37765,6 +37788,88 @@ function filterDataTableRows(rows, state, config) {
|
|
|
37765
37788
|
});
|
|
37766
37789
|
}
|
|
37767
37790
|
//#endregion
|
|
37791
|
+
//#region src/composites/device-list/multi-select.tsx
|
|
37792
|
+
/**
|
|
37793
|
+
* Compact multi-select dropdown — a single chip-sized trigger ("Label · N")
|
|
37794
|
+
* that opens a checklist. Self-contained (outside-click / Escape dismiss), so
|
|
37795
|
+
* it stays compressed regardless of how many options exist or how little
|
|
37796
|
+
* horizontal room the container has. Shared by the device list's generic-mode
|
|
37797
|
+
* type filter and any other multi-select needs.
|
|
37798
|
+
*/
|
|
37799
|
+
function MultiSelectDropdown({ label, options, selected, onChange }) {
|
|
37800
|
+
const t = useUiText();
|
|
37801
|
+
const [open, setOpen] = (0, react$1.useState)(false);
|
|
37802
|
+
const rootRef = (0, react$1.useRef)(null);
|
|
37803
|
+
(0, react$1.useEffect)(() => {
|
|
37804
|
+
if (!open) return;
|
|
37805
|
+
const onOutside = (e) => {
|
|
37806
|
+
const target = e.target instanceof Node ? e.target : null;
|
|
37807
|
+
if (target && rootRef.current && !rootRef.current.contains(target)) setOpen(false);
|
|
37808
|
+
};
|
|
37809
|
+
const onKey = (e) => {
|
|
37810
|
+
if (e.key === "Escape") setOpen(false);
|
|
37811
|
+
};
|
|
37812
|
+
document.addEventListener("mousedown", onOutside);
|
|
37813
|
+
document.addEventListener("touchstart", onOutside);
|
|
37814
|
+
document.addEventListener("keydown", onKey);
|
|
37815
|
+
return () => {
|
|
37816
|
+
document.removeEventListener("mousedown", onOutside);
|
|
37817
|
+
document.removeEventListener("touchstart", onOutside);
|
|
37818
|
+
document.removeEventListener("keydown", onKey);
|
|
37819
|
+
};
|
|
37820
|
+
}, [open]);
|
|
37821
|
+
const selectedSet = new Set(selected);
|
|
37822
|
+
const count = selected.length;
|
|
37823
|
+
const toggle = (id) => {
|
|
37824
|
+
const next = new Set(selectedSet);
|
|
37825
|
+
if (next.has(id)) next.delete(id);
|
|
37826
|
+
else next.add(id);
|
|
37827
|
+
onChange(options.filter((o) => next.has(o.id)).map((o) => o.id));
|
|
37828
|
+
};
|
|
37829
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37830
|
+
ref: rootRef,
|
|
37831
|
+
className: "relative",
|
|
37832
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
37833
|
+
type: "button",
|
|
37834
|
+
onClick: () => setOpen((v) => !v),
|
|
37835
|
+
"aria-haspopup": "listbox",
|
|
37836
|
+
"aria-expanded": open,
|
|
37837
|
+
className: `inline-flex items-center gap-1.5 h-7 px-2.5 rounded-full border text-[10.5px] font-medium transition-colors ${count > 0 ? "border-primary/40 bg-primary/15 text-primary" : "border-border bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover"}`,
|
|
37838
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [label, count > 0 ? ` · ${String(count)}` : ""] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, { className: `h-3 w-3 transition-transform ${open ? "rotate-180" : ""}` })]
|
|
37839
|
+
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37840
|
+
role: "listbox",
|
|
37841
|
+
className: "absolute left-0 top-full mt-1 z-30 min-w-[180px] max-h-72 overflow-y-auto rounded-lg border border-border bg-surface shadow-xl py-1",
|
|
37842
|
+
children: [count > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37843
|
+
type: "button",
|
|
37844
|
+
onClick: () => onChange([]),
|
|
37845
|
+
className: "flex w-full items-center px-3 py-1.5 text-left text-[10.5px] text-foreground-subtle hover:bg-surface-hover hover:text-foreground",
|
|
37846
|
+
children: t("uiLibrary.multiSelect.clear", "Clear selection")
|
|
37847
|
+
}), options.map((o) => {
|
|
37848
|
+
const active = selectedSet.has(o.id);
|
|
37849
|
+
const Icon = o.icon;
|
|
37850
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
37851
|
+
type: "button",
|
|
37852
|
+
role: "option",
|
|
37853
|
+
"aria-selected": active,
|
|
37854
|
+
onClick: () => toggle(o.id),
|
|
37855
|
+
className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-[10.5px] text-foreground hover:bg-surface-hover",
|
|
37856
|
+
children: [
|
|
37857
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37858
|
+
className: `flex h-3.5 w-3.5 items-center justify-center rounded border shrink-0 ${active ? "border-primary bg-primary" : "border-border"}`,
|
|
37859
|
+
children: active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Check, { className: "h-2.5 w-2.5 text-primary-foreground" })
|
|
37860
|
+
}),
|
|
37861
|
+
Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0 text-foreground-subtle" }),
|
|
37862
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37863
|
+
className: "truncate",
|
|
37864
|
+
children: o.label
|
|
37865
|
+
})
|
|
37866
|
+
]
|
|
37867
|
+
}, o.id);
|
|
37868
|
+
})]
|
|
37869
|
+
})]
|
|
37870
|
+
});
|
|
37871
|
+
}
|
|
37872
|
+
//#endregion
|
|
37768
37873
|
//#region src/composites/data-table-filter-bar.tsx
|
|
37769
37874
|
/**
|
|
37770
37875
|
* The controls of one table's filter: a search box and the facet chips.
|
|
@@ -37817,7 +37922,18 @@ function DataTableFilterBar({ state, facets, labels, onSearch, onToggleFacet, on
|
|
|
37817
37922
|
}, facet.value);
|
|
37818
37923
|
})
|
|
37819
37924
|
}),
|
|
37820
|
-
groups.filter((group) => group.facets.length > 1).map((group) => /* @__PURE__ */ (0, react_jsx_runtime.
|
|
37925
|
+
groups.filter((group) => group.facets.length > 1).map((group) => group.display === "menu" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiSelectDropdown, {
|
|
37926
|
+
label: group.label,
|
|
37927
|
+
options: group.facets.map((facet) => ({
|
|
37928
|
+
id: facet.value,
|
|
37929
|
+
label: `${group.facetLabel ? group.facetLabel(facet.value) : facet.value} (${String(facet.count)})`
|
|
37930
|
+
})),
|
|
37931
|
+
selected: group.selected,
|
|
37932
|
+
onChange: (next) => {
|
|
37933
|
+
const chosen = new Set(next);
|
|
37934
|
+
for (const facet of group.facets) if (chosen.has(facet.value) !== group.selected.includes(facet.value)) onToggleGroupFacet?.(group.id, facet.value);
|
|
37935
|
+
}
|
|
37936
|
+
}, group.id) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37821
37937
|
role: "group",
|
|
37822
37938
|
"aria-label": group.label,
|
|
37823
37939
|
className: "flex flex-wrap items-center gap-1",
|
|
@@ -48681,47 +48797,95 @@ function PetFeederHeroCard({ trpc, deviceId, features, optimistic }) {
|
|
|
48681
48797
|
*
|
|
48682
48798
|
* Reads the `dishwasher` cap status slice and renders inline + hero surfaces
|
|
48683
48799
|
* mirroring vacuum-control / pet-feeder patterns.
|
|
48800
|
+
*
|
|
48801
|
+
* UNKNOWN IS NOT OFF. The slice carries `null` for everything the appliance has not
|
|
48802
|
+
* reported, and this view renders that as "—" / a disabled control, never as an unchecked
|
|
48803
|
+
* box or a zero. It also does not echo a command before the appliance confirms it: the
|
|
48804
|
+
* slice moves when the appliance says so.
|
|
48684
48805
|
*/
|
|
48685
|
-
|
|
48686
|
-
|
|
48687
|
-
|
|
48688
|
-
|
|
48806
|
+
/** What the operation state is called to a person, and how it is toned. */
|
|
48807
|
+
function dishwasherOperationMeta(operationState, t = defaultUiText) {
|
|
48808
|
+
switch (operationState) {
|
|
48809
|
+
case "Run": return {
|
|
48810
|
+
label: t("uiLibrary.dishwasher.op.run", "Running"),
|
|
48689
48811
|
tone: "text-primary"
|
|
48690
48812
|
};
|
|
48691
|
-
case "
|
|
48692
|
-
label: t("uiLibrary.dishwasher.
|
|
48813
|
+
case "Pause": return {
|
|
48814
|
+
label: t("uiLibrary.dishwasher.op.pause", "Paused"),
|
|
48693
48815
|
tone: "text-warning"
|
|
48694
48816
|
};
|
|
48695
|
-
case "
|
|
48696
|
-
label: t("uiLibrary.dishwasher.finished", "Finished"),
|
|
48817
|
+
case "Finished": return {
|
|
48818
|
+
label: t("uiLibrary.dishwasher.op.finished", "Finished"),
|
|
48697
48819
|
tone: "text-success"
|
|
48698
48820
|
};
|
|
48699
|
-
case "
|
|
48700
|
-
label: t("uiLibrary.dishwasher.error", "Error"),
|
|
48701
|
-
tone: "text-
|
|
48821
|
+
case "Error": return {
|
|
48822
|
+
label: t("uiLibrary.dishwasher.op.error", "Error"),
|
|
48823
|
+
tone: "text-danger"
|
|
48702
48824
|
};
|
|
48703
|
-
case "
|
|
48704
|
-
label: t("uiLibrary.dishwasher.
|
|
48705
|
-
tone: "text-
|
|
48825
|
+
case "Aborting": return {
|
|
48826
|
+
label: t("uiLibrary.dishwasher.op.aborting", "Stopping"),
|
|
48827
|
+
tone: "text-warning"
|
|
48706
48828
|
};
|
|
48707
|
-
case "
|
|
48708
|
-
label: t("uiLibrary.dishwasher.
|
|
48829
|
+
case "ActionRequired": return {
|
|
48830
|
+
label: t("uiLibrary.dishwasher.op.actionRequired", "Action required"),
|
|
48831
|
+
tone: "text-warning"
|
|
48832
|
+
};
|
|
48833
|
+
case "DelayedStart": return {
|
|
48834
|
+
label: t("uiLibrary.dishwasher.op.delayedStart", "Delayed start"),
|
|
48835
|
+
tone: "text-primary"
|
|
48836
|
+
};
|
|
48837
|
+
case "Ready": return {
|
|
48838
|
+
label: t("uiLibrary.dishwasher.op.ready", "Ready"),
|
|
48839
|
+
tone: "text-foreground"
|
|
48840
|
+
};
|
|
48841
|
+
case "Inactive": return {
|
|
48842
|
+
label: t("uiLibrary.dishwasher.op.inactive", "Inactive"),
|
|
48709
48843
|
tone: "text-foreground-subtle"
|
|
48710
48844
|
};
|
|
48711
|
-
case
|
|
48845
|
+
case null: return {
|
|
48712
48846
|
label: t("uiLibrary.dishwasher.unknown", "Unknown"),
|
|
48713
48847
|
tone: "text-foreground-subtle"
|
|
48714
48848
|
};
|
|
48715
48849
|
}
|
|
48716
48850
|
}
|
|
48851
|
+
/** The headline for the whole slice: the appliance's state, or why there is none. */
|
|
48852
|
+
function dishwasherHeadline(status, t = defaultUiText) {
|
|
48853
|
+
switch (status.availability) {
|
|
48854
|
+
case "offline": return {
|
|
48855
|
+
label: t("uiLibrary.dishwasher.offline", "Offline"),
|
|
48856
|
+
tone: "text-foreground-subtle"
|
|
48857
|
+
};
|
|
48858
|
+
case "description-missing": return {
|
|
48859
|
+
label: t("uiLibrary.dishwasher.descriptionMissing", "Waiting for the appliance profile"),
|
|
48860
|
+
tone: "text-warning"
|
|
48861
|
+
};
|
|
48862
|
+
case "available": return dishwasherOperationMeta(status.operationState, t);
|
|
48863
|
+
}
|
|
48864
|
+
}
|
|
48717
48865
|
function consumableTone(level) {
|
|
48718
48866
|
switch (level) {
|
|
48719
48867
|
case "ok": return "text-success";
|
|
48720
48868
|
case "low": return "text-warning";
|
|
48721
|
-
case "empty": return "text-
|
|
48869
|
+
case "empty": return "text-danger";
|
|
48722
48870
|
case null: return "text-foreground-subtle";
|
|
48723
48871
|
}
|
|
48724
48872
|
}
|
|
48873
|
+
/** Last segment of a feature key, spaced out: `Dishcare.Dishwasher.Program.Eco50` -> `Eco50`. */
|
|
48874
|
+
function featureLabel(key) {
|
|
48875
|
+
return (key.split(".").pop() ?? key).replace(/([a-z0-9])([A-Z])/g, "$1 $2");
|
|
48876
|
+
}
|
|
48877
|
+
/** Whole seconds as a short duration: `1 h 24 min`, `42 min`, `30 s`. */
|
|
48878
|
+
function formatDuration(seconds, t = defaultUiText) {
|
|
48879
|
+
if (seconds < 60) return t("uiLibrary.dishwasher.durationSeconds", "{{n}} s", { n: seconds });
|
|
48880
|
+
const minutes = Math.round(seconds / 60);
|
|
48881
|
+
if (minutes < 60) return t("uiLibrary.dishwasher.durationMinutes", "{{n}} min", { n: minutes });
|
|
48882
|
+
const hours = Math.floor(minutes / 60);
|
|
48883
|
+
const rest = minutes % 60;
|
|
48884
|
+
return rest === 0 ? t("uiLibrary.dishwasher.durationHours", "{{n}} h", { n: hours }) : t("uiLibrary.dishwasher.durationHoursMinutes", "{{h}} h {{m}} min", {
|
|
48885
|
+
h: hours,
|
|
48886
|
+
m: rest
|
|
48887
|
+
});
|
|
48888
|
+
}
|
|
48725
48889
|
function useDishwasher(trpc, deviceId) {
|
|
48726
48890
|
return useDeviceCapability({
|
|
48727
48891
|
trpc,
|
|
@@ -48755,13 +48919,11 @@ function ConsumableBadge({ label, level }) {
|
|
|
48755
48919
|
]
|
|
48756
48920
|
});
|
|
48757
48921
|
}
|
|
48758
|
-
function DishwasherGraphic({
|
|
48759
|
-
const running = state === "running";
|
|
48922
|
+
function DishwasherGraphic({ running, progressPercent }) {
|
|
48760
48923
|
const pct = progressPercent != null ? Math.max(0, Math.min(100, progressPercent)) : running ? 40 : 0;
|
|
48761
48924
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48762
48925
|
"aria-hidden": "true",
|
|
48763
48926
|
className: "relative w-28 h-36 rounded border-2 border-border bg-gradient-to-b from-surface-hover to-surface overflow-hidden flex-shrink-0",
|
|
48764
|
-
style: { boxShadow: "inset 0 0 0 2px rgba(255,255,255,.06)" },
|
|
48765
48927
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48766
48928
|
className: cn("absolute inset-x-0 bottom-0 bg-primary/25 transition-[height] duration-500", running && "animate-pulse"),
|
|
48767
48929
|
style: { height: `${pct}%` }
|
|
@@ -48771,61 +48933,73 @@ function DishwasherGraphic({ state, progressPercent }) {
|
|
|
48771
48933
|
})]
|
|
48772
48934
|
});
|
|
48773
48935
|
}
|
|
48774
|
-
function DishwasherPanel({ trpc, deviceId, layout
|
|
48936
|
+
function DishwasherPanel({ trpc, deviceId, layout }) {
|
|
48775
48937
|
const t = useUiText();
|
|
48776
48938
|
const { cap, slice, available } = useDishwasher(trpc, deviceId);
|
|
48777
|
-
const { display, applyOptimistic } = useOptimisticSlice(slice, { enabled: optimistic ?? true });
|
|
48778
48939
|
if (cap === void 0) return null;
|
|
48779
|
-
if (
|
|
48780
|
-
const
|
|
48781
|
-
const
|
|
48782
|
-
const
|
|
48783
|
-
const
|
|
48784
|
-
const
|
|
48940
|
+
if (slice === void 0) return null;
|
|
48941
|
+
const display = slice;
|
|
48942
|
+
const link = display.availability === "available";
|
|
48943
|
+
const busy = !available || !link;
|
|
48944
|
+
const optionTogglesLocked = display.childLock === true;
|
|
48945
|
+
const meta = dishwasherHeadline(display, t);
|
|
48946
|
+
const running = display.operationState === "Run";
|
|
48947
|
+
const paused = display.operationState === "Pause";
|
|
48948
|
+
const startable = display.remoteStartAllowed === true && display.selectedProgram !== null;
|
|
48949
|
+
const press = (fn) => {
|
|
48785
48950
|
if (busy) return;
|
|
48786
|
-
applyOptimistic(patch);
|
|
48787
48951
|
fn();
|
|
48788
48952
|
};
|
|
48789
|
-
if (layout === "compact")
|
|
48790
|
-
|
|
48791
|
-
|
|
48792
|
-
|
|
48793
|
-
|
|
48794
|
-
|
|
48795
|
-
|
|
48796
|
-
|
|
48797
|
-
|
|
48798
|
-
|
|
48799
|
-
|
|
48800
|
-
children: meta.label
|
|
48801
|
-
}),
|
|
48802
|
-
display.remainingMinutes != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48803
|
-
className: "inline-flex items-center gap-0.5 text-xs text-foreground-subtle tabular-nums",
|
|
48804
|
-
children: [
|
|
48805
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Timer, { className: "h-3 w-3" }),
|
|
48806
|
-
display.remainingMinutes,
|
|
48807
|
-
"m"
|
|
48808
|
-
]
|
|
48809
|
-
}),
|
|
48810
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48811
|
-
label: t("uiLibrary.dishwasher.start", "Start"),
|
|
48812
|
-
busy: busy || !display.remoteStartAllowed,
|
|
48813
|
-
active: running,
|
|
48814
|
-
onClick: () => press(() => cap.start({}), {
|
|
48815
|
-
state: "running",
|
|
48816
|
-
remoteStartAllowed: false
|
|
48953
|
+
if (layout === "compact") {
|
|
48954
|
+
const saltWarn = display.saltLevel === "low" || display.saltLevel === "empty";
|
|
48955
|
+
const rinseWarn = display.rinseAidLevel === "low" || display.rinseAidLevel === "empty";
|
|
48956
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48957
|
+
className: "inline-flex items-center gap-1.5 max-w-full",
|
|
48958
|
+
children: [
|
|
48959
|
+
display.doorOpen === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48960
|
+
className: "inline-flex text-warning shrink-0",
|
|
48961
|
+
title: t("uiLibrary.dishwasher.doorOpen", "Door open"),
|
|
48962
|
+
"aria-label": t("uiLibrary.dishwasher.doorOpen", "Door open"),
|
|
48963
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DoorOpen, { className: "h-3.5 w-3.5" })
|
|
48817
48964
|
}),
|
|
48818
|
-
|
|
48819
|
-
|
|
48820
|
-
|
|
48821
|
-
|
|
48822
|
-
|
|
48823
|
-
|
|
48824
|
-
|
|
48825
|
-
|
|
48826
|
-
|
|
48827
|
-
|
|
48828
|
-
|
|
48965
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48966
|
+
className: cn("text-xs font-medium tabular-nums shrink-0", meta.tone),
|
|
48967
|
+
children: meta.label
|
|
48968
|
+
}),
|
|
48969
|
+
display.program != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48970
|
+
className: "text-xs text-foreground-subtle truncate max-w-[7rem]",
|
|
48971
|
+
title: display.program,
|
|
48972
|
+
children: featureLabel(display.program)
|
|
48973
|
+
}),
|
|
48974
|
+
display.remainingSeconds != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48975
|
+
className: "inline-flex items-center gap-0.5 text-xs text-foreground-subtle tabular-nums shrink-0",
|
|
48976
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Timer, { className: "h-3 w-3" }), formatDuration(display.remainingSeconds, t)]
|
|
48977
|
+
}),
|
|
48978
|
+
saltWarn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48979
|
+
className: cn("text-[10px] font-medium shrink-0", consumableTone(display.saltLevel)),
|
|
48980
|
+
children: t("uiLibrary.dishwasher.salt", "Salt")
|
|
48981
|
+
}),
|
|
48982
|
+
rinseWarn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48983
|
+
className: cn("text-[10px] font-medium shrink-0", consumableTone(display.rinseAidLevel)),
|
|
48984
|
+
children: t("uiLibrary.dishwasher.rinseAid", "Rinse")
|
|
48985
|
+
}),
|
|
48986
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48987
|
+
label: t("uiLibrary.dishwasher.start", "Start"),
|
|
48988
|
+
busy: busy || !startable,
|
|
48989
|
+
active: running,
|
|
48990
|
+
onClick: () => press(() => cap.start({})),
|
|
48991
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Play, { className: "h-3 w-3" })
|
|
48992
|
+
}),
|
|
48993
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48994
|
+
label: paused ? t("uiLibrary.dishwasher.resume", "Resume") : t("uiLibrary.dishwasher.pause", "Pause"),
|
|
48995
|
+
busy: busy || !(running || paused),
|
|
48996
|
+
active: paused,
|
|
48997
|
+
onClick: () => press(() => paused ? cap.resume({}) : cap.pause({})),
|
|
48998
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pause, { className: "h-3 w-3" })
|
|
48999
|
+
})
|
|
49000
|
+
]
|
|
49001
|
+
});
|
|
49002
|
+
}
|
|
48829
49003
|
const programs = display.availablePrograms;
|
|
48830
49004
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48831
49005
|
className: "flex flex-col gap-3 rounded-lg border border-border bg-surface p-4",
|
|
@@ -48833,7 +49007,7 @@ function DishwasherPanel({ trpc, deviceId, layout, optimistic }) {
|
|
|
48833
49007
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48834
49008
|
className: "flex items-start gap-4",
|
|
48835
49009
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherGraphic, {
|
|
48836
|
-
|
|
49010
|
+
running,
|
|
48837
49011
|
progressPercent: display.progressPercent
|
|
48838
49012
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48839
49013
|
className: "flex min-w-0 flex-1 flex-col gap-2",
|
|
@@ -48843,14 +49017,23 @@ function DishwasherPanel({ trpc, deviceId, layout, optimistic }) {
|
|
|
48843
49017
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48844
49018
|
className: cn("text-3xl font-semibold", meta.tone),
|
|
48845
49019
|
children: meta.label
|
|
48846
|
-
}),
|
|
49020
|
+
}), display.powerOn === false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48847
49021
|
className: "text-xs font-medium text-foreground-subtle",
|
|
48848
49022
|
children: t("uiLibrary.dishwasher.powerOff", "Power off")
|
|
48849
49023
|
})]
|
|
48850
49024
|
}),
|
|
48851
49025
|
display.program != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48852
49026
|
className: "text-sm text-foreground-subtle",
|
|
48853
|
-
|
|
49027
|
+
title: display.program,
|
|
49028
|
+
children: featureLabel(display.program)
|
|
49029
|
+
}),
|
|
49030
|
+
display.remainingSeconds != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
49031
|
+
className: "inline-flex items-center gap-1 text-sm text-foreground-subtle tabular-nums",
|
|
49032
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Timer, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.remaining", "{{time}} left", { time: formatDuration(display.remainingSeconds, t) })]
|
|
49033
|
+
}),
|
|
49034
|
+
display.delayedStartSeconds != null && display.delayedStartSeconds > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
49035
|
+
className: "text-xs text-foreground-subtle tabular-nums",
|
|
49036
|
+
children: t("uiLibrary.dishwasher.startsIn", "Starts in {{time}}", { time: formatDuration(display.delayedStartSeconds, t) })
|
|
48854
49037
|
}),
|
|
48855
49038
|
display.progressPercent != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48856
49039
|
className: "flex items-center gap-2",
|
|
@@ -48876,53 +49059,52 @@ function DishwasherPanel({ trpc, deviceId, layout, optimistic }) {
|
|
|
48876
49059
|
label: t("uiLibrary.dishwasher.rinseAid", "Rinse aid"),
|
|
48877
49060
|
level: display.rinseAidLevel
|
|
48878
49061
|
}),
|
|
48879
|
-
display.doorOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
49062
|
+
display.doorOpen === true && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48880
49063
|
className: "inline-flex items-center gap-1 text-xs text-warning",
|
|
48881
49064
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DoorOpen, { className: "h-3.5 w-3.5" }), t("uiLibrary.dishwasher.doorOpen", "Door open")]
|
|
48882
|
-
})
|
|
49065
|
+
}),
|
|
49066
|
+
display.activeEvents.map((event) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
49067
|
+
className: "text-xs text-warning",
|
|
49068
|
+
title: event,
|
|
49069
|
+
children: featureLabel(event)
|
|
49070
|
+
}, event))
|
|
48883
49071
|
]
|
|
48884
49072
|
}),
|
|
48885
|
-
display.
|
|
48886
|
-
className: "inline-flex items-center gap-1 text-xs text-
|
|
48887
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TriangleAlert, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: display.errorLabel
|
|
49073
|
+
display.operationState === "Error" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
49074
|
+
className: "inline-flex items-center gap-1 text-xs text-danger",
|
|
49075
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TriangleAlert, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: display.errorLabel != null ? featureLabel(display.errorLabel) : display.errorCode != null ? t("uiLibrary.dishwasher.errorCode", "Error {{code}}", { code: display.errorCode }) : t("uiLibrary.dishwasher.op.error", "Error") })]
|
|
48888
49076
|
}),
|
|
48889
49077
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48890
49078
|
className: "flex flex-wrap items-center gap-2",
|
|
48891
49079
|
children: [
|
|
48892
49080
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48893
49081
|
label: t("uiLibrary.dishwasher.start", "Start"),
|
|
48894
|
-
busy: busy || !
|
|
49082
|
+
busy: busy || !startable,
|
|
48895
49083
|
active: running,
|
|
48896
|
-
onClick: () => press(() => cap.start({}),
|
|
48897
|
-
state: "running",
|
|
48898
|
-
remoteStartAllowed: false
|
|
48899
|
-
}),
|
|
49084
|
+
onClick: () => press(() => cap.start({})),
|
|
48900
49085
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Play, { className: "h-4 w-4" })
|
|
48901
49086
|
}),
|
|
48902
49087
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48903
|
-
label: t("uiLibrary.dishwasher.pause", "Pause"),
|
|
48904
|
-
busy: busy || !running,
|
|
49088
|
+
label: paused ? t("uiLibrary.dishwasher.resume", "Resume") : t("uiLibrary.dishwasher.pause", "Pause"),
|
|
49089
|
+
busy: busy || !(running || paused),
|
|
48905
49090
|
active: paused,
|
|
48906
|
-
onClick: () => press(() => cap.
|
|
49091
|
+
onClick: () => press(() => paused ? cap.resume({}) : cap.pause({})),
|
|
48907
49092
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pause, { className: "h-4 w-4" })
|
|
48908
49093
|
}),
|
|
48909
49094
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48910
49095
|
label: t("uiLibrary.dishwasher.stop", "Stop"),
|
|
48911
|
-
busy,
|
|
49096
|
+
busy: busy || !(running || paused),
|
|
48912
49097
|
active: false,
|
|
48913
|
-
onClick: () => press(() => cap.stop({}),
|
|
48914
|
-
state: "idle",
|
|
48915
|
-
remainingMinutes: null
|
|
48916
|
-
}),
|
|
49098
|
+
onClick: () => press(() => cap.stop({})),
|
|
48917
49099
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Square, { className: "h-3.5 w-3.5" })
|
|
48918
49100
|
}),
|
|
48919
49101
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DishwasherIconButton, {
|
|
48920
49102
|
label: t("uiLibrary.dishwasher.power", "Power"),
|
|
48921
|
-
busy,
|
|
48922
|
-
active: display.powerOn,
|
|
49103
|
+
busy: busy || display.powerOn === null,
|
|
49104
|
+
active: display.powerOn === true,
|
|
48923
49105
|
onClick: () => {
|
|
48924
|
-
const next =
|
|
48925
|
-
press(() => cap.setPower({ on: next })
|
|
49106
|
+
const next = display.powerOn !== true;
|
|
49107
|
+
press(() => cap.setPower({ on: next }));
|
|
48926
49108
|
},
|
|
48927
49109
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Power, { className: "h-4 w-4" })
|
|
48928
49110
|
})
|
|
@@ -48938,65 +49120,106 @@ function DishwasherPanel({ trpc, deviceId, layout, optimistic }) {
|
|
|
48938
49120
|
children: t("uiLibrary.dishwasher.program", "Program")
|
|
48939
49121
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
48940
49122
|
"aria-label": t("uiLibrary.dishwasher.program", "Program"),
|
|
48941
|
-
value: display.
|
|
49123
|
+
value: display.selectedProgram ?? "",
|
|
48942
49124
|
disabled: busy,
|
|
48943
49125
|
onChange: (e) => {
|
|
48944
49126
|
const program = e.target.value;
|
|
48945
49127
|
if (!program) return;
|
|
48946
|
-
applyOptimistic({ program });
|
|
48947
49128
|
cap.setProgram({ program });
|
|
48948
49129
|
},
|
|
48949
49130
|
onClick: (e) => {
|
|
48950
49131
|
e.stopPropagation();
|
|
48951
49132
|
},
|
|
48952
49133
|
className: "flex-1 rounded border border-border bg-surface px-2 py-1 text-foreground disabled:opacity-50",
|
|
48953
|
-
children: [display.
|
|
49134
|
+
children: [display.selectedProgram == null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
48954
49135
|
value: "",
|
|
48955
49136
|
children: "—"
|
|
48956
49137
|
}), programs.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
48957
49138
|
value: p,
|
|
48958
|
-
children: p
|
|
49139
|
+
children: featureLabel(p)
|
|
48959
49140
|
}, p))]
|
|
48960
49141
|
})]
|
|
48961
49142
|
}),
|
|
48962
49143
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48963
49144
|
className: "flex flex-wrap gap-4 text-xs",
|
|
48964
|
-
children: [
|
|
48965
|
-
|
|
48966
|
-
|
|
48967
|
-
|
|
48968
|
-
|
|
48969
|
-
|
|
48970
|
-
cap.setHalfLoad({ on })
|
|
48971
|
-
}
|
|
48972
|
-
|
|
48973
|
-
|
|
48974
|
-
|
|
48975
|
-
|
|
48976
|
-
|
|
48977
|
-
|
|
48978
|
-
|
|
48979
|
-
|
|
48980
|
-
|
|
49145
|
+
children: [
|
|
49146
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
49147
|
+
label: t("uiLibrary.dishwasher.halfLoad", "Half load"),
|
|
49148
|
+
checked: display.halfLoad,
|
|
49149
|
+
shown: link,
|
|
49150
|
+
busy: busy || optionTogglesLocked,
|
|
49151
|
+
onChange: (on) => void cap.setHalfLoad({ on })
|
|
49152
|
+
}),
|
|
49153
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
49154
|
+
label: t("uiLibrary.dishwasher.hygienePlus", "Hygiene plus"),
|
|
49155
|
+
checked: display.hygienePlus,
|
|
49156
|
+
shown: link,
|
|
49157
|
+
busy: busy || optionTogglesLocked,
|
|
49158
|
+
onChange: (on) => void cap.setHygienePlus({ on })
|
|
49159
|
+
}),
|
|
49160
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
49161
|
+
label: t("uiLibrary.dishwasher.extraDry", "Extra dry"),
|
|
49162
|
+
checked: display.extraDry,
|
|
49163
|
+
shown: link,
|
|
49164
|
+
busy: busy || optionTogglesLocked,
|
|
49165
|
+
onChange: (on) => void cap.setExtraDry({ on })
|
|
49166
|
+
}),
|
|
49167
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
49168
|
+
label: t("uiLibrary.dishwasher.intensiveZone", "Intensive zone"),
|
|
49169
|
+
checked: display.intensiveZone,
|
|
49170
|
+
shown: link,
|
|
49171
|
+
busy: busy || optionTogglesLocked,
|
|
49172
|
+
onChange: (on) => void cap.setIntensiveZone({ on })
|
|
49173
|
+
}),
|
|
49174
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
49175
|
+
label: t("uiLibrary.dishwasher.varioSpeedPlus", "VarioSpeed+"),
|
|
49176
|
+
checked: display.varioSpeedPlus,
|
|
49177
|
+
shown: link,
|
|
49178
|
+
busy: busy || optionTogglesLocked,
|
|
49179
|
+
onChange: (on) => void cap.setVarioSpeedPlus({ on })
|
|
49180
|
+
}),
|
|
49181
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleRow, {
|
|
49182
|
+
label: t("uiLibrary.dishwasher.childLock", "Child lock"),
|
|
49183
|
+
checked: display.childLock,
|
|
49184
|
+
shown: link,
|
|
49185
|
+
busy,
|
|
49186
|
+
onChange: (on) => void cap.setChildLock({ on })
|
|
49187
|
+
})
|
|
49188
|
+
]
|
|
48981
49189
|
})
|
|
48982
49190
|
]
|
|
48983
49191
|
});
|
|
48984
49192
|
}
|
|
48985
|
-
|
|
49193
|
+
/**
|
|
49194
|
+
* One boolean setting. `checked === null` is "the appliance has not said": on a reachable
|
|
49195
|
+
* appliance that means it does not offer the setting (hidden); on an unreachable one the
|
|
49196
|
+
* setting is shown but disabled and marked unknown — never as an unchecked box.
|
|
49197
|
+
*/
|
|
49198
|
+
function ToggleRow({ label, checked, shown, busy, onChange }) {
|
|
49199
|
+
const t = useUiText();
|
|
49200
|
+
if (checked === null && shown) return null;
|
|
48986
49201
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
48987
49202
|
className: "inline-flex items-center gap-2 cursor-pointer",
|
|
48988
|
-
children: [
|
|
48989
|
-
|
|
48990
|
-
|
|
48991
|
-
|
|
48992
|
-
|
|
48993
|
-
|
|
48994
|
-
|
|
48995
|
-
|
|
48996
|
-
|
|
48997
|
-
|
|
48998
|
-
|
|
48999
|
-
|
|
49203
|
+
children: [
|
|
49204
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
49205
|
+
type: "checkbox",
|
|
49206
|
+
checked: checked === true,
|
|
49207
|
+
"aria-checked": checked === null ? "mixed" : checked,
|
|
49208
|
+
disabled: busy || checked === null,
|
|
49209
|
+
onChange: (e) => {
|
|
49210
|
+
onChange(e.target.checked);
|
|
49211
|
+
},
|
|
49212
|
+
onClick: (e) => {
|
|
49213
|
+
e.stopPropagation();
|
|
49214
|
+
},
|
|
49215
|
+
className: "rounded border-border"
|
|
49216
|
+
}),
|
|
49217
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }),
|
|
49218
|
+
checked === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
49219
|
+
className: "text-foreground-subtle",
|
|
49220
|
+
children: t("uiLibrary.dishwasher.unknownValue", "—")
|
|
49221
|
+
})
|
|
49222
|
+
]
|
|
49000
49223
|
});
|
|
49001
49224
|
}
|
|
49002
49225
|
function DishwasherInlineControl(props) {
|
|
@@ -54628,88 +54851,6 @@ function PageSizeSelect({ value, options, onChange, ariaLabel }) {
|
|
|
54628
54851
|
});
|
|
54629
54852
|
}
|
|
54630
54853
|
//#endregion
|
|
54631
|
-
//#region src/composites/device-list/multi-select.tsx
|
|
54632
|
-
/**
|
|
54633
|
-
* Compact multi-select dropdown — a single chip-sized trigger ("Label · N")
|
|
54634
|
-
* that opens a checklist. Self-contained (outside-click / Escape dismiss), so
|
|
54635
|
-
* it stays compressed regardless of how many options exist or how little
|
|
54636
|
-
* horizontal room the container has. Shared by the device list's generic-mode
|
|
54637
|
-
* type filter and any other multi-select needs.
|
|
54638
|
-
*/
|
|
54639
|
-
function MultiSelectDropdown({ label, options, selected, onChange }) {
|
|
54640
|
-
const t = useUiText();
|
|
54641
|
-
const [open, setOpen] = (0, react$1.useState)(false);
|
|
54642
|
-
const rootRef = (0, react$1.useRef)(null);
|
|
54643
|
-
(0, react$1.useEffect)(() => {
|
|
54644
|
-
if (!open) return;
|
|
54645
|
-
const onOutside = (e) => {
|
|
54646
|
-
const target = e.target instanceof Node ? e.target : null;
|
|
54647
|
-
if (target && rootRef.current && !rootRef.current.contains(target)) setOpen(false);
|
|
54648
|
-
};
|
|
54649
|
-
const onKey = (e) => {
|
|
54650
|
-
if (e.key === "Escape") setOpen(false);
|
|
54651
|
-
};
|
|
54652
|
-
document.addEventListener("mousedown", onOutside);
|
|
54653
|
-
document.addEventListener("touchstart", onOutside);
|
|
54654
|
-
document.addEventListener("keydown", onKey);
|
|
54655
|
-
return () => {
|
|
54656
|
-
document.removeEventListener("mousedown", onOutside);
|
|
54657
|
-
document.removeEventListener("touchstart", onOutside);
|
|
54658
|
-
document.removeEventListener("keydown", onKey);
|
|
54659
|
-
};
|
|
54660
|
-
}, [open]);
|
|
54661
|
-
const selectedSet = new Set(selected);
|
|
54662
|
-
const count = selected.length;
|
|
54663
|
-
const toggle = (id) => {
|
|
54664
|
-
const next = new Set(selectedSet);
|
|
54665
|
-
if (next.has(id)) next.delete(id);
|
|
54666
|
-
else next.add(id);
|
|
54667
|
-
onChange(options.filter((o) => next.has(o.id)).map((o) => o.id));
|
|
54668
|
-
};
|
|
54669
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
54670
|
-
ref: rootRef,
|
|
54671
|
-
className: "relative",
|
|
54672
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
54673
|
-
type: "button",
|
|
54674
|
-
onClick: () => setOpen((v) => !v),
|
|
54675
|
-
"aria-haspopup": "listbox",
|
|
54676
|
-
"aria-expanded": open,
|
|
54677
|
-
className: `inline-flex items-center gap-1.5 h-7 px-2.5 rounded-full border text-[10.5px] font-medium transition-colors ${count > 0 ? "border-primary/40 bg-primary/15 text-primary" : "border-border bg-surface text-foreground-subtle hover:text-foreground hover:bg-surface-hover"}`,
|
|
54678
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [label, count > 0 ? ` · ${String(count)}` : ""] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, { className: `h-3 w-3 transition-transform ${open ? "rotate-180" : ""}` })]
|
|
54679
|
-
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
54680
|
-
role: "listbox",
|
|
54681
|
-
className: "absolute left-0 top-full mt-1 z-30 min-w-[180px] max-h-72 overflow-y-auto rounded-lg border border-border bg-surface shadow-xl py-1",
|
|
54682
|
-
children: [count > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
54683
|
-
type: "button",
|
|
54684
|
-
onClick: () => onChange([]),
|
|
54685
|
-
className: "flex w-full items-center px-3 py-1.5 text-left text-[10.5px] text-foreground-subtle hover:bg-surface-hover hover:text-foreground",
|
|
54686
|
-
children: t("uiLibrary.multiSelect.clear", "Clear selection")
|
|
54687
|
-
}), options.map((o) => {
|
|
54688
|
-
const active = selectedSet.has(o.id);
|
|
54689
|
-
const Icon = o.icon;
|
|
54690
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
54691
|
-
type: "button",
|
|
54692
|
-
role: "option",
|
|
54693
|
-
"aria-selected": active,
|
|
54694
|
-
onClick: () => toggle(o.id),
|
|
54695
|
-
className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-[10.5px] text-foreground hover:bg-surface-hover",
|
|
54696
|
-
children: [
|
|
54697
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
54698
|
-
className: `flex h-3.5 w-3.5 items-center justify-center rounded border shrink-0 ${active ? "border-primary bg-primary" : "border-border"}`,
|
|
54699
|
-
children: active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Check, { className: "h-2.5 w-2.5 text-primary-foreground" })
|
|
54700
|
-
}),
|
|
54701
|
-
Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0 text-foreground-subtle" }),
|
|
54702
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
54703
|
-
className: "truncate",
|
|
54704
|
-
children: o.label
|
|
54705
|
-
})
|
|
54706
|
-
]
|
|
54707
|
-
}, o.id);
|
|
54708
|
-
})]
|
|
54709
|
-
})]
|
|
54710
|
-
});
|
|
54711
|
-
}
|
|
54712
|
-
//#endregion
|
|
54713
54854
|
//#region src/composites/device-list/type-filter.tsx
|
|
54714
54855
|
/**
|
|
54715
54856
|
* Shared, multi-select type filter that adapts to its OWN available width
|
|
@@ -59402,19 +59543,35 @@ function objectFromJson(text) {
|
|
|
59402
59543
|
return null;
|
|
59403
59544
|
}
|
|
59404
59545
|
}
|
|
59405
|
-
|
|
59406
|
-
|
|
59407
|
-
|
|
59546
|
+
/**
|
|
59547
|
+
* What the secret control is hydrated with. A read hands a stored secret as a
|
|
59548
|
+
* VIEW (`{ $secret: <row ref>, set: true }`) the control reveals by ref through
|
|
59549
|
+
* the host's audited reveal; the legacy redaction token is "set, no ref" (it
|
|
59550
|
+
* can be replaced but not revealed); anything else is "nothing stored".
|
|
59551
|
+
*/
|
|
59552
|
+
function hydratedSecret(value) {
|
|
59553
|
+
if ((0, _camstack_types.isSecretFieldView)(value) || (0, _camstack_types.isSecretClear)(value)) return value;
|
|
59554
|
+
if (isRedactedSecret(value)) return {
|
|
59555
|
+
$secret: null,
|
|
59556
|
+
v: 1,
|
|
59557
|
+
set: true
|
|
59558
|
+
};
|
|
59559
|
+
return null;
|
|
59560
|
+
}
|
|
59561
|
+
function RecordEntrySecretField({ name, label, required, value, disabled, onPatch }) {
|
|
59408
59562
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormField$1, {
|
|
59409
59563
|
label,
|
|
59410
59564
|
required,
|
|
59411
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
59412
|
-
|
|
59413
|
-
|
|
59414
|
-
|
|
59415
|
-
|
|
59416
|
-
|
|
59417
|
-
|
|
59565
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SecretFieldControl, {
|
|
59566
|
+
field: {
|
|
59567
|
+
type: "password",
|
|
59568
|
+
key: name,
|
|
59569
|
+
label,
|
|
59570
|
+
required
|
|
59571
|
+
},
|
|
59572
|
+
value: hydratedSecret(value),
|
|
59573
|
+
onChange: onPatch,
|
|
59574
|
+
disabled
|
|
59418
59575
|
})
|
|
59419
59576
|
});
|
|
59420
59577
|
}
|
|
@@ -59422,6 +59579,7 @@ function SchemaField(props) {
|
|
|
59422
59579
|
const { path, name, node, value, secretPaths, required, disabled, onPatch } = props;
|
|
59423
59580
|
const label = labelFor(name, node);
|
|
59424
59581
|
if (isSecretField(path, secretPaths, node)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RecordEntrySecretField, {
|
|
59582
|
+
name,
|
|
59425
59583
|
label,
|
|
59426
59584
|
required,
|
|
59427
59585
|
value,
|
|
@@ -59571,7 +59729,7 @@ function defaultBody(schema) {
|
|
|
59571
59729
|
}
|
|
59572
59730
|
return out;
|
|
59573
59731
|
}
|
|
59574
|
-
function RecordEntriesPanel({ kind }) {
|
|
59732
|
+
function RecordEntriesPanel({ kind, rowActions, extraColumns = [], showUpdated = true, minWidthPx }) {
|
|
59575
59733
|
const t = useUiText();
|
|
59576
59734
|
const queryClient = (0, _tanstack_react_query.useQueryClient)();
|
|
59577
59735
|
const confirm = useConfirm();
|
|
@@ -59644,41 +59802,51 @@ function RecordEntriesPanel({ kind }) {
|
|
|
59644
59802
|
})
|
|
59645
59803
|
})
|
|
59646
59804
|
},
|
|
59647
|
-
{
|
|
59805
|
+
...showUpdated ? [{
|
|
59648
59806
|
key: "updated",
|
|
59649
59807
|
header: t("uiLibrary.recordEntries.colUpdated", "Updated"),
|
|
59650
59808
|
nowrap: true,
|
|
59651
59809
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
59652
59810
|
className: "text-[11px] text-foreground-subtle",
|
|
59653
|
-
|
|
59811
|
+
title: new Date(row.updatedAt).toLocaleString(),
|
|
59812
|
+
children: new Date(row.updatedAt).toLocaleDateString()
|
|
59654
59813
|
})
|
|
59655
|
-
},
|
|
59814
|
+
}] : [],
|
|
59815
|
+
...extraColumns,
|
|
59656
59816
|
{
|
|
59657
59817
|
key: "actions",
|
|
59658
59818
|
header: "",
|
|
59659
59819
|
align: "right",
|
|
59660
59820
|
nowrap: true,
|
|
59821
|
+
width: "w-px",
|
|
59661
59822
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
59662
59823
|
className: "flex justify-end gap-1",
|
|
59663
|
-
children: [
|
|
59664
|
-
|
|
59665
|
-
|
|
59666
|
-
|
|
59667
|
-
|
|
59668
|
-
|
|
59669
|
-
|
|
59670
|
-
|
|
59671
|
-
|
|
59672
|
-
|
|
59673
|
-
|
|
59674
|
-
|
|
59675
|
-
|
|
59824
|
+
children: [
|
|
59825
|
+
rowActions?.(row),
|
|
59826
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
59827
|
+
size: "sm",
|
|
59828
|
+
variant: "ghost",
|
|
59829
|
+
type: "button",
|
|
59830
|
+
onClick: () => openEdit(row),
|
|
59831
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Pencil, { className: "h-3.5 w-3.5" })
|
|
59832
|
+
}),
|
|
59833
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
59834
|
+
size: "sm",
|
|
59835
|
+
variant: "ghost",
|
|
59836
|
+
type: "button",
|
|
59837
|
+
onClick: () => void onDelete(row),
|
|
59838
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Trash2, { className: "h-3.5 w-3.5 text-danger" })
|
|
59839
|
+
})
|
|
59840
|
+
]
|
|
59676
59841
|
})
|
|
59677
59842
|
}
|
|
59678
59843
|
];
|
|
59679
59844
|
}, [
|
|
59845
|
+
extraColumns,
|
|
59680
59846
|
onDelete,
|
|
59681
59847
|
openEdit,
|
|
59848
|
+
rowActions,
|
|
59849
|
+
showUpdated,
|
|
59682
59850
|
t
|
|
59683
59851
|
]);
|
|
59684
59852
|
const dialogOpen = formUrl.state.mode !== "closed";
|
|
@@ -59726,6 +59894,7 @@ function RecordEntriesPanel({ kind }) {
|
|
|
59726
59894
|
title: t("uiLibrary.recordEntries.emptyTitle", "No entries yet"),
|
|
59727
59895
|
description: t("uiLibrary.recordEntries.emptyDescription", "Add the first row for this kind.")
|
|
59728
59896
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
|
|
59897
|
+
...minWidthPx !== void 0 ? { minWidthPx } : {},
|
|
59729
59898
|
columns,
|
|
59730
59899
|
rows: entries,
|
|
59731
59900
|
rowKey: (r) => r.id,
|
|
@@ -59756,73 +59925,6 @@ function RecordEntriesPanel({ kind }) {
|
|
|
59756
59925
|
});
|
|
59757
59926
|
}
|
|
59758
59927
|
//#endregion
|
|
59759
|
-
//#region src/composites/record-entries/record-entries-hub.tsx
|
|
59760
|
-
var RECORD_ENTRY_OWNER_PARAM = "entryOwner";
|
|
59761
|
-
var RECORD_ENTRY_KIND_PARAM = "entryKind";
|
|
59762
|
-
function kindKey$1(k) {
|
|
59763
|
-
return `${k.owner}/${k.kind}`;
|
|
59764
|
-
}
|
|
59765
|
-
function RecordEntriesHub({ filter }) {
|
|
59766
|
-
const t = useUiText();
|
|
59767
|
-
const kindsQuery = useRecordEntriesListEntryKinds({}, { staleTime: 3e4 });
|
|
59768
|
-
const [ownerParam, setOwner] = useUrlQueryParam(RECORD_ENTRY_OWNER_PARAM);
|
|
59769
|
-
const [kindParam, setKind] = useUrlQueryParam(RECORD_ENTRY_KIND_PARAM);
|
|
59770
|
-
const kinds = (0, react$1.useMemo)(() => {
|
|
59771
|
-
return (kindsQuery.data?.kinds ?? []).filter((k) => {
|
|
59772
|
-
if (filter?.owner !== void 0 && k.owner !== filter.owner) return false;
|
|
59773
|
-
if (filter?.kind !== void 0 && k.kind !== filter.kind) return false;
|
|
59774
|
-
return true;
|
|
59775
|
-
});
|
|
59776
|
-
}, [
|
|
59777
|
-
filter?.kind,
|
|
59778
|
-
filter?.owner,
|
|
59779
|
-
kindsQuery.data?.kinds
|
|
59780
|
-
]);
|
|
59781
|
-
const active = (0, react$1.useMemo)(() => {
|
|
59782
|
-
if (kinds.length === 0) return null;
|
|
59783
|
-
return kinds.find((k) => k.owner === ownerParam && k.kind === kindParam) ?? kinds[0] ?? null;
|
|
59784
|
-
}, [
|
|
59785
|
-
kindParam,
|
|
59786
|
-
kinds,
|
|
59787
|
-
ownerParam
|
|
59788
|
-
]);
|
|
59789
|
-
const selectKind = (k) => {
|
|
59790
|
-
setOwner(k.owner);
|
|
59791
|
-
setKind(k.kind);
|
|
59792
|
-
};
|
|
59793
|
-
if (kindsQuery.isError) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, { message: kindsQuery.error instanceof Error ? kindsQuery.error.message : t("uiLibrary.recordEntries.kindsFailed", "Could not load entry kinds") });
|
|
59794
|
-
if (kindsQuery.isPending) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
59795
|
-
className: "flex justify-center py-10 text-foreground-subtle",
|
|
59796
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderCircle, { className: "h-5 w-5 animate-spin" })
|
|
59797
|
-
});
|
|
59798
|
-
if (kinds.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmptyState, {
|
|
59799
|
-
title: t("uiLibrary.recordEntries.noKindsTitle", "No entry kinds"),
|
|
59800
|
-
description: t("uiLibrary.recordEntries.noKindsDescription", "No addon has declared an entry record kind yet.")
|
|
59801
|
-
});
|
|
59802
|
-
const activeKey = active === null ? "" : kindKey$1(active);
|
|
59803
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
59804
|
-
className: "space-y-4",
|
|
59805
|
-
children: [kinds.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tabs, {
|
|
59806
|
-
appearance: "pills",
|
|
59807
|
-
value: activeKey,
|
|
59808
|
-
onValueChange: (key) => {
|
|
59809
|
-
const found = kinds.find((k) => kindKey$1(k) === key);
|
|
59810
|
-
if (found !== void 0) selectKind(found);
|
|
59811
|
-
},
|
|
59812
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabsList, {
|
|
59813
|
-
className: "flex flex-wrap gap-1",
|
|
59814
|
-
children: kinds.map((k) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TabsTrigger, {
|
|
59815
|
-
value: kindKey$1(k),
|
|
59816
|
-
children: [k.title, k.rows > 0 ? ` (${k.rows})` : ""]
|
|
59817
|
-
}, kindKey$1(k)))
|
|
59818
|
-
})
|
|
59819
|
-
}), active !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [kinds.length === 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
59820
|
-
className: "mb-2 text-sm font-semibold text-foreground",
|
|
59821
|
-
children: active.title
|
|
59822
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RecordEntriesPanel, { kind: active })] })]
|
|
59823
|
-
});
|
|
59824
|
-
}
|
|
59825
|
-
//#endregion
|
|
59826
59928
|
//#region src/composites/storage-records/storage-records-panel.tsx
|
|
59827
59929
|
function StorageRecordsPanel({ kind }) {
|
|
59828
59930
|
const t = useUiText();
|
|
@@ -59946,47 +60048,143 @@ function StorageRecordsPanel({ kind }) {
|
|
|
59946
60048
|
});
|
|
59947
60049
|
}
|
|
59948
60050
|
//#endregion
|
|
59949
|
-
//#region src/composites/
|
|
59950
|
-
|
|
59951
|
-
|
|
59952
|
-
|
|
59953
|
-
|
|
60051
|
+
//#region src/composites/data-records/data-records-model.ts
|
|
60052
|
+
function dataRecordKey(kind) {
|
|
60053
|
+
return `${kind.owner}/${kind.kind}`;
|
|
60054
|
+
}
|
|
60055
|
+
function dataRecordType(kind) {
|
|
60056
|
+
return kind.entry ? "entry" : "record";
|
|
59954
60057
|
}
|
|
60058
|
+
/** `unknown` is a kind whose count was not asked for or could not be read — never "empty". */
|
|
60059
|
+
function dataRecordContents(kind) {
|
|
60060
|
+
if (kind.rows === null) return "unknown";
|
|
60061
|
+
return kind.rows > 0 ? "has-rows" : "empty";
|
|
60062
|
+
}
|
|
60063
|
+
/**
|
|
60064
|
+
* Join the declared kinds with the entry catalog. A pending/failed catalog
|
|
60065
|
+
* (`undefined`) leaves titles `null`; it never changes which kinds are listed.
|
|
60066
|
+
*/
|
|
60067
|
+
function buildDataRecordRows(kinds, entryKinds) {
|
|
60068
|
+
const titles = /* @__PURE__ */ new Map();
|
|
60069
|
+
for (const entry of entryKinds ?? []) titles.set(dataRecordKey(entry), entry.title);
|
|
60070
|
+
return kinds.map((kind) => ({
|
|
60071
|
+
kind,
|
|
60072
|
+
entryTitle: kind.entry ? titles.get(dataRecordKey(kind)) ?? null : null
|
|
60073
|
+
}));
|
|
60074
|
+
}
|
|
60075
|
+
var DATA_RECORD_FACET_GROUPS = [
|
|
60076
|
+
{
|
|
60077
|
+
id: "kind",
|
|
60078
|
+
value: (row) => dataRecordKey(row.kind)
|
|
60079
|
+
},
|
|
60080
|
+
{
|
|
60081
|
+
id: "owner",
|
|
60082
|
+
value: (row) => row.kind.owner
|
|
60083
|
+
},
|
|
60084
|
+
{
|
|
60085
|
+
id: "type",
|
|
60086
|
+
value: (row) => dataRecordType(row.kind)
|
|
60087
|
+
},
|
|
60088
|
+
{
|
|
60089
|
+
id: "database",
|
|
60090
|
+
value: (row) => row.kind.database
|
|
60091
|
+
},
|
|
60092
|
+
{
|
|
60093
|
+
id: "class",
|
|
60094
|
+
value: (row) => row.kind.class
|
|
60095
|
+
},
|
|
60096
|
+
{
|
|
60097
|
+
id: "state",
|
|
60098
|
+
value: (row) => row.kind.state
|
|
60099
|
+
},
|
|
60100
|
+
{
|
|
60101
|
+
id: "contents",
|
|
60102
|
+
value: (row) => dataRecordContents(row.kind)
|
|
60103
|
+
}
|
|
60104
|
+
];
|
|
60105
|
+
function dataRecordSearchText(row) {
|
|
60106
|
+
const { kind } = row;
|
|
60107
|
+
return [
|
|
60108
|
+
kind.owner,
|
|
60109
|
+
kind.kind,
|
|
60110
|
+
kind.class,
|
|
60111
|
+
kind.database,
|
|
60112
|
+
kind.state,
|
|
60113
|
+
row.entryTitle ?? ""
|
|
60114
|
+
];
|
|
60115
|
+
}
|
|
60116
|
+
//#endregion
|
|
60117
|
+
//#region src/composites/data-records/data-records-hub.tsx
|
|
60118
|
+
var DATA_RECORDS_OWNER_PARAM = "recordsOwner";
|
|
60119
|
+
var DATA_RECORDS_KIND_PARAM = "recordsKind";
|
|
59955
60120
|
function formatBytes(n) {
|
|
59956
60121
|
if (n === null) return "—";
|
|
59957
60122
|
if (n < 1024) return `${n} B`;
|
|
59958
60123
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KiB`;
|
|
59959
60124
|
return `${(n / (1024 * 1024)).toFixed(1)} MiB`;
|
|
59960
60125
|
}
|
|
59961
|
-
function
|
|
60126
|
+
function groupLabel(id, t) {
|
|
60127
|
+
switch (id) {
|
|
60128
|
+
case "kind": return t("uiLibrary.dataRecords.facetKind", "Kind");
|
|
60129
|
+
case "owner": return t("uiLibrary.dataRecords.facetOwner", "Owner");
|
|
60130
|
+
case "type": return t("uiLibrary.dataRecords.facetType", "Type");
|
|
60131
|
+
case "database": return t("uiLibrary.dataRecords.facetDatabase", "Database");
|
|
60132
|
+
case "class": return t("uiLibrary.dataRecords.facetClass", "Class");
|
|
60133
|
+
case "state": return t("uiLibrary.dataRecords.facetState", "State");
|
|
60134
|
+
default: return t("uiLibrary.dataRecords.facetContents", "Contents");
|
|
60135
|
+
}
|
|
60136
|
+
}
|
|
60137
|
+
function facetCaption(groupId, value, t) {
|
|
60138
|
+
if (groupId === "type") return value === "entry" ? t("uiLibrary.dataRecords.typeEntry", "Entries (editable)") : t("uiLibrary.dataRecords.typeRecord", "Records (read-only)");
|
|
60139
|
+
if (groupId === "contents") {
|
|
60140
|
+
if (value === "has-rows") return t("uiLibrary.dataRecords.contentsHasRows", "Has rows");
|
|
60141
|
+
if (value === "empty") return t("uiLibrary.dataRecords.contentsEmpty", "Empty");
|
|
60142
|
+
return t("uiLibrary.dataRecords.contentsUnknown", "Count unknown");
|
|
60143
|
+
}
|
|
60144
|
+
return value;
|
|
60145
|
+
}
|
|
60146
|
+
/** Entry kinds open the editable list; every other kind opens the read-only preview. */
|
|
60147
|
+
function KindDetail({ kind, entryKinds, entryKindsPending, entryKindsError }) {
|
|
60148
|
+
const t = useUiText();
|
|
60149
|
+
if (!kind.entry) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StorageRecordsPanel, { kind });
|
|
60150
|
+
if (entryKindsPending) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
60151
|
+
className: "flex justify-center py-8 text-foreground-subtle",
|
|
60152
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderCircle, { className: "h-5 w-5 animate-spin" })
|
|
60153
|
+
});
|
|
60154
|
+
if (entryKindsError !== null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, { message: entryKindsError });
|
|
60155
|
+
const info = entryKinds?.find((e) => dataRecordKey(e) === dataRecordKey(kind));
|
|
60156
|
+
if (info === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, { message: t("uiLibrary.dataRecords.entryKindMissing", "This entry kind is not served by the entries service.") });
|
|
60157
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
60158
|
+
className: "space-y-2",
|
|
60159
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
60160
|
+
className: "text-sm font-semibold text-foreground",
|
|
60161
|
+
children: info.title
|
|
60162
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RecordEntriesPanel, { kind: info })]
|
|
60163
|
+
});
|
|
60164
|
+
}
|
|
60165
|
+
/**
|
|
60166
|
+
* System → Data → Records: every declared record kind in ONE table with
|
|
60167
|
+
* compact filters; an entry kind opens its editable list, any other kind its
|
|
60168
|
+
* read-only row preview. Selection is in `?recordsOwner=&recordsKind=`.
|
|
60169
|
+
*/
|
|
60170
|
+
function DataRecordsHub() {
|
|
59962
60171
|
const t = useUiText();
|
|
59963
60172
|
const kindsQuery = trpc.storageAdmin.listKinds.useQuery({}, { staleTime: 3e4 });
|
|
59964
|
-
const
|
|
59965
|
-
const [
|
|
59966
|
-
const
|
|
59967
|
-
const
|
|
59968
|
-
|
|
59969
|
-
|
|
59970
|
-
|
|
59971
|
-
|
|
59972
|
-
row.database,
|
|
59973
|
-
row.state
|
|
59974
|
-
],
|
|
59975
|
-
facetGroups: [{
|
|
59976
|
-
id: "owner",
|
|
59977
|
-
value: (row) => row.owner
|
|
59978
|
-
}, {
|
|
59979
|
-
id: "database",
|
|
59980
|
-
value: (row) => row.database
|
|
59981
|
-
}]
|
|
60173
|
+
const entryKindsQuery = useRecordEntriesListEntryKinds({}, { staleTime: 3e4 });
|
|
60174
|
+
const [ownerParam, setOwner] = useUrlQueryParam(DATA_RECORDS_OWNER_PARAM);
|
|
60175
|
+
const [kindParam, setKind] = useUrlQueryParam(DATA_RECORDS_KIND_PARAM);
|
|
60176
|
+
const entryKinds = entryKindsQuery.data?.kinds;
|
|
60177
|
+
const rows = (0, react$1.useMemo)(() => buildDataRecordRows(kindsQuery.data?.kinds ?? [], entryKinds), [entryKinds, kindsQuery.data?.kinds]);
|
|
60178
|
+
const filter = useDataTableFilter(rows, {
|
|
60179
|
+
searchText: dataRecordSearchText,
|
|
60180
|
+
facetGroups: DATA_RECORD_FACET_GROUPS
|
|
59982
60181
|
});
|
|
59983
60182
|
const active = (0, react$1.useMemo)(() => {
|
|
59984
|
-
|
|
59985
|
-
return kinds.find((k) => k.owner === ownerParam && k.kind === kindParam) ?? null;
|
|
60183
|
+
return rows.find((r) => r.kind.owner === ownerParam && r.kind.kind === kindParam)?.kind ?? null;
|
|
59986
60184
|
}, [
|
|
59987
60185
|
kindParam,
|
|
59988
|
-
|
|
59989
|
-
|
|
60186
|
+
ownerParam,
|
|
60187
|
+
rows
|
|
59990
60188
|
]);
|
|
59991
60189
|
const selectKind = (0, react$1.useCallback)((k) => {
|
|
59992
60190
|
setOwner(k.owner);
|
|
@@ -59996,72 +60194,87 @@ function StorageRecordsHub() {
|
|
|
59996
60194
|
return [
|
|
59997
60195
|
{
|
|
59998
60196
|
key: "kind",
|
|
59999
|
-
header: t("uiLibrary.
|
|
60197
|
+
header: t("uiLibrary.dataRecords.colKind", "Kind"),
|
|
60000
60198
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
60001
|
-
className: "
|
|
60002
|
-
children: [
|
|
60003
|
-
|
|
60004
|
-
|
|
60005
|
-
|
|
60006
|
-
|
|
60199
|
+
className: "flex flex-col",
|
|
60200
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
60201
|
+
className: "font-mono text-xs",
|
|
60202
|
+
children: dataRecordKey(row.kind)
|
|
60203
|
+
}), row.entryTitle !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
60204
|
+
className: "text-[11px] text-foreground-subtle",
|
|
60205
|
+
children: row.entryTitle
|
|
60206
|
+
}) : null]
|
|
60207
|
+
}),
|
|
60208
|
+
sortValue: (row) => dataRecordKey(row.kind)
|
|
60209
|
+
},
|
|
60210
|
+
{
|
|
60211
|
+
key: "type",
|
|
60212
|
+
header: t("uiLibrary.dataRecords.colType", "Type"),
|
|
60213
|
+
nowrap: true,
|
|
60214
|
+
render: (row) => row.kind.entry ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
60215
|
+
variant: "info",
|
|
60216
|
+
children: t("uiLibrary.dataRecords.badgeEntry", "Entry")
|
|
60217
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
60218
|
+
variant: "neutral",
|
|
60219
|
+
children: t("uiLibrary.dataRecords.badgeRecord", "Record")
|
|
60007
60220
|
}),
|
|
60008
|
-
sortValue: (row) =>
|
|
60221
|
+
sortValue: (row) => row.kind.entry ? "entry" : "record"
|
|
60009
60222
|
},
|
|
60010
60223
|
{
|
|
60011
60224
|
key: "database",
|
|
60012
|
-
header: t("uiLibrary.
|
|
60225
|
+
header: t("uiLibrary.dataRecords.colDatabase", "DB"),
|
|
60013
60226
|
nowrap: true,
|
|
60014
60227
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
60015
60228
|
variant: "neutral",
|
|
60016
60229
|
style: "outline",
|
|
60017
|
-
children: row.database
|
|
60230
|
+
children: row.kind.database
|
|
60018
60231
|
}),
|
|
60019
|
-
sortValue: (row) => row.database
|
|
60232
|
+
sortValue: (row) => row.kind.database
|
|
60020
60233
|
},
|
|
60021
60234
|
{
|
|
60022
60235
|
key: "class",
|
|
60023
|
-
header: t("uiLibrary.
|
|
60236
|
+
header: t("uiLibrary.dataRecords.colClass", "Class"),
|
|
60024
60237
|
nowrap: true,
|
|
60025
60238
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
60026
60239
|
className: "text-xs text-foreground-muted",
|
|
60027
|
-
children: row.class
|
|
60240
|
+
children: row.kind.class
|
|
60028
60241
|
}),
|
|
60029
|
-
sortValue: (row) => row.class
|
|
60242
|
+
sortValue: (row) => row.kind.class
|
|
60030
60243
|
},
|
|
60031
60244
|
{
|
|
60032
60245
|
key: "state",
|
|
60033
|
-
header: t("uiLibrary.
|
|
60246
|
+
header: t("uiLibrary.dataRecords.colState", "State"),
|
|
60034
60247
|
nowrap: true,
|
|
60035
60248
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
60036
|
-
variant: row.state === "declared" ? "default" : "neutral",
|
|
60037
|
-
children: row.state
|
|
60249
|
+
variant: row.kind.state === "declared" ? "default" : "neutral",
|
|
60250
|
+
children: row.kind.state
|
|
60038
60251
|
}),
|
|
60039
|
-
sortValue: (row) => row.state
|
|
60252
|
+
sortValue: (row) => row.kind.state
|
|
60040
60253
|
},
|
|
60041
60254
|
{
|
|
60042
60255
|
key: "rows",
|
|
60043
|
-
header: t("uiLibrary.
|
|
60256
|
+
header: t("uiLibrary.dataRecords.colRows", "Rows"),
|
|
60044
60257
|
align: "right",
|
|
60045
60258
|
nowrap: true,
|
|
60046
60259
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
60047
60260
|
className: "font-mono text-xs tabular-nums",
|
|
60048
|
-
children: row.rows === null ? "—" : row.rows
|
|
60261
|
+
children: row.kind.rows === null ? "—" : row.kind.rows
|
|
60049
60262
|
}),
|
|
60050
|
-
sortValue: (row) => row.rows ?? -1
|
|
60263
|
+
sortValue: (row) => row.kind.rows ?? -1
|
|
60051
60264
|
},
|
|
60052
60265
|
{
|
|
60053
60266
|
key: "bytes",
|
|
60054
|
-
header: t("uiLibrary.
|
|
60267
|
+
header: t("uiLibrary.dataRecords.colSize", "Est. size"),
|
|
60055
60268
|
align: "right",
|
|
60056
60269
|
nowrap: true,
|
|
60057
60270
|
render: (row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
60058
60271
|
className: "text-xs text-foreground-subtle",
|
|
60059
|
-
children: formatBytes(row.bytesEstimate)
|
|
60272
|
+
children: formatBytes(row.kind.bytesEstimate)
|
|
60060
60273
|
}),
|
|
60061
|
-
sortValue: (row) => row.bytesEstimate ?? -1
|
|
60274
|
+
sortValue: (row) => row.kind.bytesEstimate ?? -1
|
|
60062
60275
|
},
|
|
60063
60276
|
{
|
|
60064
|
-
key: "
|
|
60277
|
+
key: "open",
|
|
60065
60278
|
header: "",
|
|
60066
60279
|
align: "right",
|
|
60067
60280
|
nowrap: true,
|
|
@@ -60069,12 +60282,12 @@ function StorageRecordsHub() {
|
|
|
60069
60282
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
60070
60283
|
type: "button",
|
|
60071
60284
|
size: "sm",
|
|
60072
|
-
variant: active !== null &&
|
|
60073
|
-
onClick: () => selectKind(row),
|
|
60074
|
-
children: t("uiLibrary.
|
|
60285
|
+
variant: active !== null && dataRecordKey(active) === dataRecordKey(row.kind) ? "primary" : "outline",
|
|
60286
|
+
onClick: () => selectKind(row.kind),
|
|
60287
|
+
children: row.kind.entry ? t("uiLibrary.dataRecords.manage", "Manage") : t("uiLibrary.dataRecords.viewRows", "View rows")
|
|
60075
60288
|
});
|
|
60076
60289
|
},
|
|
60077
|
-
notSortableReason: t("uiLibrary.
|
|
60290
|
+
notSortableReason: t("uiLibrary.dataRecords.actionColumn", "Actions")
|
|
60078
60291
|
}
|
|
60079
60292
|
];
|
|
60080
60293
|
}, [
|
|
@@ -60082,14 +60295,14 @@ function StorageRecordsHub() {
|
|
|
60082
60295
|
selectKind,
|
|
60083
60296
|
t
|
|
60084
60297
|
]);
|
|
60085
|
-
if (kindsQuery.isError) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, { message: kindsQuery.error instanceof Error ? kindsQuery.error.message : t("uiLibrary.
|
|
60298
|
+
if (kindsQuery.isError) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBox, { message: kindsQuery.error instanceof Error ? kindsQuery.error.message : t("uiLibrary.dataRecords.kindsFailed", "Could not load record kinds") });
|
|
60086
60299
|
if (kindsQuery.isPending) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
60087
60300
|
className: "flex justify-center py-10 text-foreground-subtle",
|
|
60088
60301
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderCircle, { className: "h-5 w-5 animate-spin" })
|
|
60089
60302
|
});
|
|
60090
|
-
if (
|
|
60091
|
-
title: t("uiLibrary.
|
|
60092
|
-
description: t("uiLibrary.
|
|
60303
|
+
if (rows.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmptyState, {
|
|
60304
|
+
title: t("uiLibrary.dataRecords.noKindsTitle", "No record kinds"),
|
|
60305
|
+
description: t("uiLibrary.dataRecords.noKindsDescription", "No addon has declared a record kind on this hub yet.")
|
|
60093
60306
|
});
|
|
60094
60307
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
60095
60308
|
className: "space-y-4",
|
|
@@ -60099,13 +60312,15 @@ function StorageRecordsHub() {
|
|
|
60099
60312
|
facets: filter.facets,
|
|
60100
60313
|
groups: filter.groups.map((g) => ({
|
|
60101
60314
|
...g,
|
|
60102
|
-
label: g.id
|
|
60315
|
+
label: groupLabel(g.id, t),
|
|
60316
|
+
display: "menu",
|
|
60317
|
+
facetLabel: (value) => facetCaption(g.id, value, t)
|
|
60103
60318
|
})),
|
|
60104
60319
|
labels: {
|
|
60105
|
-
searchPlaceholder: t("uiLibrary.
|
|
60106
|
-
searchLabel: t("uiLibrary.
|
|
60107
|
-
facetsLabel: t("uiLibrary.
|
|
60108
|
-
clearLabel: t("uiLibrary.
|
|
60320
|
+
searchPlaceholder: t("uiLibrary.dataRecords.search", "Search kinds…"),
|
|
60321
|
+
searchLabel: t("uiLibrary.dataRecords.searchLabel", "Search record kinds"),
|
|
60322
|
+
facetsLabel: t("uiLibrary.dataRecords.facetsLabel", "Filter record kinds"),
|
|
60323
|
+
clearLabel: t("uiLibrary.dataRecords.clearFilters", "Clear filters")
|
|
60109
60324
|
},
|
|
60110
60325
|
onSearch: filter.setSearch,
|
|
60111
60326
|
onToggleFacet: filter.toggleFacet,
|
|
@@ -60115,15 +60330,20 @@ function StorageRecordsHub() {
|
|
|
60115
60330
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
|
|
60116
60331
|
columns,
|
|
60117
60332
|
rows: filter.rows,
|
|
60118
|
-
rowKey: (
|
|
60333
|
+
rowKey: (r) => dataRecordKey(r.kind),
|
|
60119
60334
|
maxBodyHeight: TABLE_SCROLL_MAX_H,
|
|
60120
60335
|
defaultSort: {
|
|
60121
60336
|
columnKey: "kind",
|
|
60122
60337
|
dir: "asc"
|
|
60123
60338
|
},
|
|
60124
|
-
emptyMessage: t("uiLibrary.
|
|
60339
|
+
emptyMessage: t("uiLibrary.dataRecords.noMatch", "No kinds match the filter")
|
|
60125
60340
|
}),
|
|
60126
|
-
active !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
60341
|
+
active !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KindDetail, {
|
|
60342
|
+
kind: active,
|
|
60343
|
+
entryKinds,
|
|
60344
|
+
entryKindsPending: entryKindsQuery.isPending,
|
|
60345
|
+
entryKindsError: entryKindsQuery.isError ? entryKindsQuery.error instanceof Error ? entryKindsQuery.error.message : t("uiLibrary.dataRecords.entryKindsFailed", "Could not load entry kinds") : null
|
|
60346
|
+
}) : null
|
|
60127
60347
|
]
|
|
60128
60348
|
});
|
|
60129
60349
|
}
|
|
@@ -64532,6 +64752,9 @@ exports.CoverPanel = CoverPanel;
|
|
|
64532
64752
|
exports.Cpu = Cpu;
|
|
64533
64753
|
exports.Crosshair = Crosshair;
|
|
64534
64754
|
exports.CustomFieldRenderersProvider = CustomFieldRenderersProvider;
|
|
64755
|
+
exports.DATA_RECORDS_KIND_PARAM = DATA_RECORDS_KIND_PARAM;
|
|
64756
|
+
exports.DATA_RECORDS_OWNER_PARAM = DATA_RECORDS_OWNER_PARAM;
|
|
64757
|
+
exports.DATA_RECORD_FACET_GROUPS = DATA_RECORD_FACET_GROUPS;
|
|
64535
64758
|
exports.DEFAULT_COLOR = DEFAULT_COLOR;
|
|
64536
64759
|
exports.DEFAULT_PAGINATION_LABELS = DEFAULT_PAGINATION_LABELS;
|
|
64537
64760
|
exports.DEVICE_COLUMNS = DEVICE_COLUMNS;
|
|
@@ -64542,6 +64765,7 @@ exports.DEVICE_PICKER_GROUP_STORAGE_KEY = DEVICE_PICKER_GROUP_STORAGE_KEY;
|
|
|
64542
64765
|
exports.DEVICE_ROLE_META = DEVICE_ROLE_META;
|
|
64543
64766
|
exports.DEVICE_TYPE_CONTROL = DEVICE_TYPE_CONTROL;
|
|
64544
64767
|
exports.DEVICE_TYPE_META = DEVICE_TYPE_META;
|
|
64768
|
+
exports.DataRecordsHub = DataRecordsHub;
|
|
64545
64769
|
exports.DataTable = DataTable;
|
|
64546
64770
|
exports.DataTableFilterBar = DataTableFilterBar;
|
|
64547
64771
|
exports.DataTablePager = DataTablePager;
|
|
@@ -64786,8 +65010,6 @@ exports.QrCode = QrCode;
|
|
|
64786
65010
|
exports.QrCode$1 = QrCode$1;
|
|
64787
65011
|
exports.RECONNECT_POLICY = RECONNECT_POLICY;
|
|
64788
65012
|
exports.RECORDED_PLAYBACK_MODES = RECORDED_PLAYBACK_MODES;
|
|
64789
|
-
exports.RECORD_ENTRY_KIND_PARAM = RECORD_ENTRY_KIND_PARAM;
|
|
64790
|
-
exports.RECORD_ENTRY_OWNER_PARAM = RECORD_ENTRY_OWNER_PARAM;
|
|
64791
65013
|
exports.RIGHT = RIGHT;
|
|
64792
65014
|
exports.ROI_AREA_WARN_FRACTION = ROI_AREA_WARN_FRACTION;
|
|
64793
65015
|
exports.ROLE_DESCRIPTOR = ROLE_DESCRIPTOR;
|
|
@@ -64796,7 +65018,6 @@ exports.Radar = Radar;
|
|
|
64796
65018
|
exports.RadialGauge = RadialGauge;
|
|
64797
65019
|
exports.Radio = Radio;
|
|
64798
65020
|
exports.RadioTower = RadioTower;
|
|
64799
|
-
exports.RecordEntriesHub = RecordEntriesHub;
|
|
64800
65021
|
exports.RecordEntriesPanel = RecordEntriesPanel;
|
|
64801
65022
|
exports.RecordedPlaybackProvider = RecordedPlaybackProvider;
|
|
64802
65023
|
exports.RecordingPanel = RecordingPanel;
|
|
@@ -64830,8 +65051,6 @@ exports.SPLIT_PANEL_SIDE = SPLIT_PANEL_SIDE;
|
|
|
64830
65051
|
exports.STACK_GAP = STACK_GAP;
|
|
64831
65052
|
exports.STATE_COLOR = STATE_COLOR;
|
|
64832
65053
|
exports.STEP_DOCK_WIDTH_PX = STEP_DOCK_WIDTH_PX;
|
|
64833
|
-
exports.STORAGE_RECORDS_KIND_PARAM = STORAGE_RECORDS_KIND_PARAM;
|
|
64834
|
-
exports.STORAGE_RECORDS_OWNER_PARAM = STORAGE_RECORDS_OWNER_PARAM;
|
|
64835
65054
|
exports.Sailboat = Sailboat;
|
|
64836
65055
|
exports.Save = Save;
|
|
64837
65056
|
exports.Scan = Scan;
|
|
@@ -64890,7 +65109,6 @@ exports.StepInspectorPanel = StepInspectorPanel;
|
|
|
64890
65109
|
exports.StepModelRow = StepModelRow;
|
|
64891
65110
|
exports.StepTimings = StepTimings;
|
|
64892
65111
|
exports.Stepper = Stepper;
|
|
64893
|
-
exports.StorageRecordsHub = StorageRecordsHub;
|
|
64894
65112
|
exports.StorageRecordsPanel = StorageRecordsPanel;
|
|
64895
65113
|
exports.StreamBrokerSelector = StreamBrokerSelector;
|
|
64896
65114
|
exports.StreamDebugOverlay = StreamDebugOverlay;
|
|
@@ -64992,6 +65210,7 @@ exports.badgeFor = badgeFor;
|
|
|
64992
65210
|
exports.badgeFor$1 = badgeFor;
|
|
64993
65211
|
exports.bindsToModel = bindsToModel;
|
|
64994
65212
|
exports.buildColorByNodeId = buildColorByNodeId;
|
|
65213
|
+
exports.buildDataRecordRows = buildDataRecordRows;
|
|
64995
65214
|
exports.buildPeerConnectionConfig = buildPeerConnectionConfig;
|
|
64996
65215
|
exports.buildStepTreeFromSchema = buildStepTreeFromSchema;
|
|
64997
65216
|
exports.catalogHasDraft = catalogHasDraft;
|
|
@@ -65019,6 +65238,10 @@ exports.createTheme = require_theme_index.createTheme$1;
|
|
|
65019
65238
|
exports.currentAddonLanguage = currentAddonLanguage;
|
|
65020
65239
|
exports.cursorFractionFor = cursorFractionFor;
|
|
65021
65240
|
exports.darkColors = require_theme_to_root_css.darkColors;
|
|
65241
|
+
exports.dataRecordContents = dataRecordContents;
|
|
65242
|
+
exports.dataRecordKey = dataRecordKey;
|
|
65243
|
+
exports.dataRecordSearchText = dataRecordSearchText;
|
|
65244
|
+
exports.dataRecordType = dataRecordType;
|
|
65022
65245
|
exports.dataTableFacetGroups = dataTableFacetGroups;
|
|
65023
65246
|
exports.dataTableFacets = dataTableFacets;
|
|
65024
65247
|
exports.defaultOfField = defaultOfField;
|
|
@@ -65602,13 +65825,19 @@ exports.useDeviceStateSlice$1 = useDeviceStateSlice;
|
|
|
65602
65825
|
exports.useDeviceStatusGetStatus = useDeviceStatusGetStatus;
|
|
65603
65826
|
exports.useDeviceWebrtc = useDeviceWebrtc;
|
|
65604
65827
|
exports.useDevices = useDevices;
|
|
65828
|
+
exports.useDishwasherGetOptions = useDishwasherGetOptions;
|
|
65605
65829
|
exports.useDishwasherGetStatus = useDishwasherGetStatus;
|
|
65606
65830
|
exports.useDishwasherPause = useDishwasherPause;
|
|
65831
|
+
exports.useDishwasherResume = useDishwasherResume;
|
|
65832
|
+
exports.useDishwasherSetChildLock = useDishwasherSetChildLock;
|
|
65833
|
+
exports.useDishwasherSetExtraDry = useDishwasherSetExtraDry;
|
|
65607
65834
|
exports.useDishwasherSetHalfLoad = useDishwasherSetHalfLoad;
|
|
65608
65835
|
exports.useDishwasherSetHygienePlus = useDishwasherSetHygienePlus;
|
|
65836
|
+
exports.useDishwasherSetIntensiveZone = useDishwasherSetIntensiveZone;
|
|
65609
65837
|
exports.useDishwasherSetOption = useDishwasherSetOption;
|
|
65610
65838
|
exports.useDishwasherSetPower = useDishwasherSetPower;
|
|
65611
65839
|
exports.useDishwasherSetProgram = useDishwasherSetProgram;
|
|
65840
|
+
exports.useDishwasherSetVarioSpeedPlus = useDishwasherSetVarioSpeedPlus;
|
|
65612
65841
|
exports.useDishwasherStart = useDishwasherStart;
|
|
65613
65842
|
exports.useDishwasherStop = useDishwasherStop;
|
|
65614
65843
|
exports.useDisplayIconResolver = useDisplayIconResolver;
|
|
@@ -66294,6 +66523,7 @@ exports.useStorageMigrationCleanupStart = useStorageMigrationCleanupStart;
|
|
|
66294
66523
|
exports.useStorageMigrationCleanupStatus = useStorageMigrationCleanupStatus;
|
|
66295
66524
|
exports.useStorageMigrationDrain = useStorageMigrationDrain;
|
|
66296
66525
|
exports.useStorageMigrationHistory = useStorageMigrationHistory;
|
|
66526
|
+
exports.useStorageMigrationMoverClearance = useStorageMigrationMoverClearance;
|
|
66297
66527
|
exports.useStorageMigrationMovers = useStorageMigrationMovers;
|
|
66298
66528
|
exports.useStorageMigrationPlan = useStorageMigrationPlan;
|
|
66299
66529
|
exports.useStorageMigrationResidue = useStorageMigrationResidue;
|