@camstack/ui-library 1.2.323 → 1.2.324
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/clips/ClipsSection.d.ts +3 -3
- package/dist/composites/device-item/header.d.ts +1 -1
- package/dist/composites/device-list/columns.d.ts +1 -1
- package/dist/composites/device-list/fuzzy-match.d.ts +8 -8
- package/dist/composites/model-picker.d.ts +1 -1
- package/dist/hooks/use-stationary-overlay.d.ts +1 -1
- package/dist/index.cjs +16 -16
- package/dist/index.js +16 -16
- package/package.json +1 -1
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
* - **Four states are tellable apart**: loading, empty-with-a-cause,
|
|
32
32
|
* degraded-per-source, and each silent source in its own words. Every one
|
|
33
33
|
* of them used to render as "no clips", which is the defect this whole line
|
|
34
|
-
* of work is about — a camera with no SD card (
|
|
35
|
-
* camera whose own index disagrees with its own calendar (
|
|
34
|
+
* of work is about — a camera with no SD card (106) is not quiet, and a
|
|
35
|
+
* camera whose own index disagrees with its own calendar (108, 6–20
|
|
36
36
|
* September) is not quiet either.
|
|
37
37
|
*
|
|
38
38
|
* ## The period comes from the recording section's timebar, not a day picker
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
* There is no "default" option and no empty value. This section used to send
|
|
86
86
|
* no `provider` at all until the operator chose, because the cap documented
|
|
87
87
|
* absence as "the device's bound provider, which is CamStack on every camera".
|
|
88
|
-
* No code implemented that: measured on device
|
|
88
|
+
* No code implemented that: measured on device 107 (2026-09-20, bound to
|
|
89
89
|
* `recorder` AND `provider-reolink`) a bare `listClips` with `limit: 3`
|
|
90
90
|
* answered SIX rows — three per source, merged — while the default option read
|
|
91
91
|
* "CamStack recordings". The label named one thing and the query asked two.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* narrow. Used by table view + minimal in-panel lists.
|
|
10
10
|
* - `stacked=true`: name is the visual anchor of a vertical card. No
|
|
11
11
|
* truncation, two-line clamp so longer names wrap instead of
|
|
12
|
-
* collapsing into "
|
|
12
|
+
* collapsing into "Camera vera…". Typography is larger /
|
|
13
13
|
* heavier so the name dominates the secondary metadata that sits
|
|
14
14
|
* below it.
|
|
15
15
|
*
|
|
@@ -89,7 +89,7 @@ export declare const NAME_COLUMN_PIN_CLASS: "md:sticky md:left-0 md:z-[1]";
|
|
|
89
89
|
* ── The NAME never truncates below the pin breakpoint ─────────────────────
|
|
90
90
|
*
|
|
91
91
|
* Fitting NAME + Preview inside a phone viewport was the wrong trade: every
|
|
92
|
-
* camera collapsed to "
|
|
92
|
+
* camera collapsed to "Camera ve…" / "Camera co…", which is not a
|
|
93
93
|
* shortened name, it is NO name — the rows became indistinguishable and the
|
|
94
94
|
* one thing the operator opened the page to read was the part that got cut.
|
|
95
95
|
*
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
* fuzzy-match — case and separator-insensitive text search helper.
|
|
3
3
|
*
|
|
4
4
|
* Normalization rule: lowercase + strip all runs of hyphens, underscores and
|
|
5
|
-
* whitespace entirely. This makes `Tapparella
|
|
6
|
-
* both normalize to `
|
|
5
|
+
* whitespace entirely. This makes `Tapparella kitchen` and `tapparella-kitchen`
|
|
6
|
+
* both normalize to `tapparellakitchen`, so a substring match succeeds in
|
|
7
7
|
* either direction.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Strips hyphens, underscores and whitespace runs from `s` and lowercases it.
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
|
-
* normalizeForSearch('Tapparella
|
|
14
|
-
* normalizeForSearch('tapparella-
|
|
15
|
-
* normalizeForSearch('
|
|
13
|
+
* normalizeForSearch('Tapparella kitchen') // 'tapparellakitchen'
|
|
14
|
+
* normalizeForSearch('tapparella-kitchen') // 'tapparellakitchen'
|
|
15
|
+
* normalizeForSearch('tapparella_kitchen') // 'tapparellakitchen'
|
|
16
16
|
*/
|
|
17
17
|
export declare function normalizeForSearch(s: string): string;
|
|
18
18
|
/**
|
|
@@ -20,8 +20,8 @@ export declare function normalizeForSearch(s: string): string;
|
|
|
20
20
|
* form of `query`. An empty query always matches.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
|
-
* fuzzyMatch('Tapparella
|
|
24
|
-
* fuzzyMatch('tapparella
|
|
25
|
-
* fuzzyMatch('xyz', 'tapparella-
|
|
23
|
+
* fuzzyMatch('Tapparella kitchen', 'tapparella-kitchen') // true
|
|
24
|
+
* fuzzyMatch('tapparella kitchen', 'Tapparella-Kitchen') // true
|
|
25
|
+
* fuzzyMatch('xyz', 'tapparella-kitchen') // false
|
|
26
26
|
*/
|
|
27
27
|
export declare function fuzzyMatch(query: string, target: string): boolean;
|
|
@@ -4,7 +4,7 @@ export type ModelOption = PipelineAddonSchema["models"][number];
|
|
|
4
4
|
/**
|
|
5
5
|
* Shared model picker — the ONE model-selection control across the app.
|
|
6
6
|
*
|
|
7
|
-
* Provider first (CamStack /
|
|
7
|
+
* Provider first (CamStack / plus catalog / plugin catalog / Custom), then inside that
|
|
8
8
|
* catalog the grouped Family→Tier→Variant selector when entries declare
|
|
9
9
|
* `group`, else a flat `<select>`. The persisted value stays the flat model
|
|
10
10
|
* id. `value === ''` renders nothing selected (callers that support an
|
|
@@ -3,7 +3,7 @@ import type { StationaryOverlayBox } from "@camstack/types";
|
|
|
3
3
|
* The ONE route this hook needs.
|
|
4
4
|
*
|
|
5
5
|
* Deliberately NOT the device proxy. The proxy exposes only the caps BOUND to
|
|
6
|
-
* a device, and `zone-analytics` is not one of them — on device
|
|
6
|
+
* a device, and `zone-analytics` is not one of them — on device 102 the
|
|
7
7
|
* bindings are `pipeline-analytics` and `motion-zones`. Reading the census
|
|
8
8
|
* through `dev?.zoneAnalytics?.…` therefore resolved to `undefined`, the hook
|
|
9
9
|
* returned an empty census, and the overlay drew nothing while reporting
|
package/dist/index.cjs
CHANGED
|
@@ -13076,7 +13076,7 @@ var FACET_TRIGGER = "inline-flex max-w-full items-center gap-1 rounded-md border
|
|
|
13076
13076
|
var FACET_ITEM = "flex h-7 w-full items-center gap-2 px-2 text-left text-xs text-foreground hover:bg-surface-hover";
|
|
13077
13077
|
/**
|
|
13078
13078
|
* One facet as a compact MULTI-select dropdown: closed it is one line
|
|
13079
|
-
* ("Location ·
|
|
13079
|
+
* ("Location · Kitchen, Hall"), open it lists every value with a check.
|
|
13080
13080
|
* The operator asked for dropdowns over rows of chips (2026-09-05): with
|
|
13081
13081
|
* sixteen rooms and a dozen types the chips ate the panel.
|
|
13082
13082
|
*/
|
|
@@ -20436,7 +20436,7 @@ function CameraGridLayoutEditor({ deviceId }) {
|
|
|
20436
20436
|
* The honest report. A grid's `high` composes its sources' `high` and its `low`
|
|
20437
20437
|
* their `low`, so a profile is on offer only when EVERY source can serve it —
|
|
20438
20438
|
* and the refusal names the source, because "this grid has no low" is not
|
|
20439
|
-
* something an operator can act on and "
|
|
20439
|
+
* something an operator can act on and "101 has no low" is.
|
|
20440
20440
|
*
|
|
20441
20441
|
* Read-only on purpose: what is on offer is decided by the source cameras'
|
|
20442
20442
|
* assignments, and a control here would be a switch that writes nothing (D62).
|
|
@@ -23914,8 +23914,8 @@ function resolveClipsView(input, t = defaultUiText) {
|
|
|
23914
23914
|
* - **Four states are tellable apart**: loading, empty-with-a-cause,
|
|
23915
23915
|
* degraded-per-source, and each silent source in its own words. Every one
|
|
23916
23916
|
* of them used to render as "no clips", which is the defect this whole line
|
|
23917
|
-
* of work is about — a camera with no SD card (
|
|
23918
|
-
* camera whose own index disagrees with its own calendar (
|
|
23917
|
+
* of work is about — a camera with no SD card (106) is not quiet, and a
|
|
23918
|
+
* camera whose own index disagrees with its own calendar (108, 6–20
|
|
23919
23919
|
* September) is not quiet either.
|
|
23920
23920
|
*
|
|
23921
23921
|
* ## The period comes from the recording section's timebar, not a day picker
|
|
@@ -23968,7 +23968,7 @@ function resolveClipsView(input, t = defaultUiText) {
|
|
|
23968
23968
|
* There is no "default" option and no empty value. This section used to send
|
|
23969
23969
|
* no `provider` at all until the operator chose, because the cap documented
|
|
23970
23970
|
* absence as "the device's bound provider, which is CamStack on every camera".
|
|
23971
|
-
* No code implemented that: measured on device
|
|
23971
|
+
* No code implemented that: measured on device 107 (2026-09-20, bound to
|
|
23972
23972
|
* `recorder` AND `provider-reolink`) a bare `listClips` with `limit: 3`
|
|
23973
23973
|
* answered SIX rows — three per source, merged — while the default option read
|
|
23974
23974
|
* "CamStack recordings". The label named one thing and the query asked two.
|
|
@@ -31960,8 +31960,8 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
|
|
|
31960
31960
|
//#region src/composites/model-picker.tsx
|
|
31961
31961
|
var PROVIDER_LABEL = {
|
|
31962
31962
|
camstack: "CamStack",
|
|
31963
|
-
frigate: "
|
|
31964
|
-
scrypted: "
|
|
31963
|
+
frigate: "plus catalog",
|
|
31964
|
+
scrypted: "plugin catalog",
|
|
31965
31965
|
custom: "Custom"
|
|
31966
31966
|
};
|
|
31967
31967
|
function providerOf(model) {
|
|
@@ -31970,7 +31970,7 @@ function providerOf(model) {
|
|
|
31970
31970
|
/**
|
|
31971
31971
|
* Shared model picker — the ONE model-selection control across the app.
|
|
31972
31972
|
*
|
|
31973
|
-
* Provider first (CamStack /
|
|
31973
|
+
* Provider first (CamStack / plus catalog / plugin catalog / Custom), then inside that
|
|
31974
31974
|
* catalog the grouped Family→Tier→Variant selector when entries declare
|
|
31975
31975
|
* `group`, else a flat `<select>`. The persisted value stays the flat model
|
|
31976
31976
|
* id. `value === ''` renders nothing selected (callers that support an
|
|
@@ -39749,17 +39749,17 @@ function CopyButton({ value, label, srLabel, className, disabled }) {
|
|
|
39749
39749
|
* fuzzy-match — case and separator-insensitive text search helper.
|
|
39750
39750
|
*
|
|
39751
39751
|
* Normalization rule: lowercase + strip all runs of hyphens, underscores and
|
|
39752
|
-
* whitespace entirely. This makes `Tapparella
|
|
39753
|
-
* both normalize to `
|
|
39752
|
+
* whitespace entirely. This makes `Tapparella kitchen` and `tapparella-kitchen`
|
|
39753
|
+
* both normalize to `tapparellakitchen`, so a substring match succeeds in
|
|
39754
39754
|
* either direction.
|
|
39755
39755
|
*/
|
|
39756
39756
|
/**
|
|
39757
39757
|
* Strips hyphens, underscores and whitespace runs from `s` and lowercases it.
|
|
39758
39758
|
*
|
|
39759
39759
|
* @example
|
|
39760
|
-
* normalizeForSearch('Tapparella
|
|
39761
|
-
* normalizeForSearch('tapparella-
|
|
39762
|
-
* normalizeForSearch('
|
|
39760
|
+
* normalizeForSearch('Tapparella kitchen') // 'tapparellakitchen'
|
|
39761
|
+
* normalizeForSearch('tapparella-kitchen') // 'tapparellakitchen'
|
|
39762
|
+
* normalizeForSearch('tapparella_kitchen') // 'tapparellakitchen'
|
|
39763
39763
|
*/
|
|
39764
39764
|
function normalizeForSearch(s) {
|
|
39765
39765
|
return s.toLowerCase().replace(/[-_\s]+/g, "");
|
|
@@ -39769,9 +39769,9 @@ function normalizeForSearch(s) {
|
|
|
39769
39769
|
* form of `query`. An empty query always matches.
|
|
39770
39770
|
*
|
|
39771
39771
|
* @example
|
|
39772
|
-
* fuzzyMatch('Tapparella
|
|
39773
|
-
* fuzzyMatch('tapparella
|
|
39774
|
-
* fuzzyMatch('xyz', 'tapparella-
|
|
39772
|
+
* fuzzyMatch('Tapparella kitchen', 'tapparella-kitchen') // true
|
|
39773
|
+
* fuzzyMatch('tapparella kitchen', 'Tapparella-Kitchen') // true
|
|
39774
|
+
* fuzzyMatch('xyz', 'tapparella-kitchen') // false
|
|
39775
39775
|
*/
|
|
39776
39776
|
function fuzzyMatch(query, target) {
|
|
39777
39777
|
const nq = normalizeForSearch(query);
|
package/dist/index.js
CHANGED
|
@@ -13052,7 +13052,7 @@ var FACET_TRIGGER = "inline-flex max-w-full items-center gap-1 rounded-md border
|
|
|
13052
13052
|
var FACET_ITEM = "flex h-7 w-full items-center gap-2 px-2 text-left text-xs text-foreground hover:bg-surface-hover";
|
|
13053
13053
|
/**
|
|
13054
13054
|
* One facet as a compact MULTI-select dropdown: closed it is one line
|
|
13055
|
-
* ("Location ·
|
|
13055
|
+
* ("Location · Kitchen, Hall"), open it lists every value with a check.
|
|
13056
13056
|
* The operator asked for dropdowns over rows of chips (2026-09-05): with
|
|
13057
13057
|
* sixteen rooms and a dozen types the chips ate the panel.
|
|
13058
13058
|
*/
|
|
@@ -20412,7 +20412,7 @@ function CameraGridLayoutEditor({ deviceId }) {
|
|
|
20412
20412
|
* The honest report. A grid's `high` composes its sources' `high` and its `low`
|
|
20413
20413
|
* their `low`, so a profile is on offer only when EVERY source can serve it —
|
|
20414
20414
|
* and the refusal names the source, because "this grid has no low" is not
|
|
20415
|
-
* something an operator can act on and "
|
|
20415
|
+
* something an operator can act on and "101 has no low" is.
|
|
20416
20416
|
*
|
|
20417
20417
|
* Read-only on purpose: what is on offer is decided by the source cameras'
|
|
20418
20418
|
* assignments, and a control here would be a switch that writes nothing (D62).
|
|
@@ -23890,8 +23890,8 @@ function resolveClipsView(input, t = defaultUiText) {
|
|
|
23890
23890
|
* - **Four states are tellable apart**: loading, empty-with-a-cause,
|
|
23891
23891
|
* degraded-per-source, and each silent source in its own words. Every one
|
|
23892
23892
|
* of them used to render as "no clips", which is the defect this whole line
|
|
23893
|
-
* of work is about — a camera with no SD card (
|
|
23894
|
-
* camera whose own index disagrees with its own calendar (
|
|
23893
|
+
* of work is about — a camera with no SD card (106) is not quiet, and a
|
|
23894
|
+
* camera whose own index disagrees with its own calendar (108, 6–20
|
|
23895
23895
|
* September) is not quiet either.
|
|
23896
23896
|
*
|
|
23897
23897
|
* ## The period comes from the recording section's timebar, not a day picker
|
|
@@ -23944,7 +23944,7 @@ function resolveClipsView(input, t = defaultUiText) {
|
|
|
23944
23944
|
* There is no "default" option and no empty value. This section used to send
|
|
23945
23945
|
* no `provider` at all until the operator chose, because the cap documented
|
|
23946
23946
|
* absence as "the device's bound provider, which is CamStack on every camera".
|
|
23947
|
-
* No code implemented that: measured on device
|
|
23947
|
+
* No code implemented that: measured on device 107 (2026-09-20, bound to
|
|
23948
23948
|
* `recorder` AND `provider-reolink`) a bare `listClips` with `limit: 3`
|
|
23949
23949
|
* answered SIX rows — three per source, merged — while the default option read
|
|
23950
23950
|
* "CamStack recordings". The label named one thing and the query asked two.
|
|
@@ -31936,8 +31936,8 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
|
|
|
31936
31936
|
//#region src/composites/model-picker.tsx
|
|
31937
31937
|
var PROVIDER_LABEL = {
|
|
31938
31938
|
camstack: "CamStack",
|
|
31939
|
-
frigate: "
|
|
31940
|
-
scrypted: "
|
|
31939
|
+
frigate: "plus catalog",
|
|
31940
|
+
scrypted: "plugin catalog",
|
|
31941
31941
|
custom: "Custom"
|
|
31942
31942
|
};
|
|
31943
31943
|
function providerOf(model) {
|
|
@@ -31946,7 +31946,7 @@ function providerOf(model) {
|
|
|
31946
31946
|
/**
|
|
31947
31947
|
* Shared model picker — the ONE model-selection control across the app.
|
|
31948
31948
|
*
|
|
31949
|
-
* Provider first (CamStack /
|
|
31949
|
+
* Provider first (CamStack / plus catalog / plugin catalog / Custom), then inside that
|
|
31950
31950
|
* catalog the grouped Family→Tier→Variant selector when entries declare
|
|
31951
31951
|
* `group`, else a flat `<select>`. The persisted value stays the flat model
|
|
31952
31952
|
* id. `value === ''` renders nothing selected (callers that support an
|
|
@@ -39725,17 +39725,17 @@ function CopyButton({ value, label, srLabel, className, disabled }) {
|
|
|
39725
39725
|
* fuzzy-match — case and separator-insensitive text search helper.
|
|
39726
39726
|
*
|
|
39727
39727
|
* Normalization rule: lowercase + strip all runs of hyphens, underscores and
|
|
39728
|
-
* whitespace entirely. This makes `Tapparella
|
|
39729
|
-
* both normalize to `
|
|
39728
|
+
* whitespace entirely. This makes `Tapparella kitchen` and `tapparella-kitchen`
|
|
39729
|
+
* both normalize to `tapparellakitchen`, so a substring match succeeds in
|
|
39730
39730
|
* either direction.
|
|
39731
39731
|
*/
|
|
39732
39732
|
/**
|
|
39733
39733
|
* Strips hyphens, underscores and whitespace runs from `s` and lowercases it.
|
|
39734
39734
|
*
|
|
39735
39735
|
* @example
|
|
39736
|
-
* normalizeForSearch('Tapparella
|
|
39737
|
-
* normalizeForSearch('tapparella-
|
|
39738
|
-
* normalizeForSearch('
|
|
39736
|
+
* normalizeForSearch('Tapparella kitchen') // 'tapparellakitchen'
|
|
39737
|
+
* normalizeForSearch('tapparella-kitchen') // 'tapparellakitchen'
|
|
39738
|
+
* normalizeForSearch('tapparella_kitchen') // 'tapparellakitchen'
|
|
39739
39739
|
*/
|
|
39740
39740
|
function normalizeForSearch(s) {
|
|
39741
39741
|
return s.toLowerCase().replace(/[-_\s]+/g, "");
|
|
@@ -39745,9 +39745,9 @@ function normalizeForSearch(s) {
|
|
|
39745
39745
|
* form of `query`. An empty query always matches.
|
|
39746
39746
|
*
|
|
39747
39747
|
* @example
|
|
39748
|
-
* fuzzyMatch('Tapparella
|
|
39749
|
-
* fuzzyMatch('tapparella
|
|
39750
|
-
* fuzzyMatch('xyz', 'tapparella-
|
|
39748
|
+
* fuzzyMatch('Tapparella kitchen', 'tapparella-kitchen') // true
|
|
39749
|
+
* fuzzyMatch('tapparella kitchen', 'Tapparella-Kitchen') // true
|
|
39750
|
+
* fuzzyMatch('xyz', 'tapparella-kitchen') // false
|
|
39751
39751
|
*/
|
|
39752
39752
|
function fuzzyMatch(query, target) {
|
|
39753
39753
|
const nq = normalizeForSearch(query);
|