@camstack/ui-library 1.2.180 → 1.2.181

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.
@@ -38,6 +38,14 @@ export interface GridProfileOffer {
38
38
  * the only place the grid's actual size is ever stated.
39
39
  */
40
40
  readonly canvas: string;
41
+ /**
42
+ * Whether this profile is PUBLISHED, of the ones the grid could serve.
43
+ *
44
+ * A grid's `high` composes its sources' `high`, so on a 4K fleet it is a 4K
45
+ * canvas built from 4K decodes — an opt-in, not something a viewer's adaptive
46
+ * should be handed by climbing to the top rung it can see.
47
+ */
48
+ readonly published: boolean;
41
49
  }
42
50
  export interface GridLayoutView {
43
51
  readonly instanceId: string;
package/dist/index.cjs CHANGED
@@ -16642,7 +16642,8 @@ function readProfileOffer(value) {
16642
16642
  profile,
16643
16643
  offered,
16644
16644
  missingSources,
16645
- canvas: typeof value["canvas"] === "string" ? value["canvas"] : ""
16645
+ canvas: typeof value["canvas"] === "string" ? value["canvas"] : "",
16646
+ published: typeof value["published"] === "boolean" ? value["published"] : offered
16646
16647
  };
16647
16648
  }
16648
16649
  /**
@@ -16887,7 +16888,7 @@ function CameraGridLayoutEditor({ deviceId }) {
16887
16888
  setLoaded("unreadable");
16888
16889
  });
16889
16890
  }, [dev, reload]);
16890
- const save = (0, react$1.useCallback)(async () => {
16891
+ const save = (0, react$1.useCallback)(async (extra) => {
16891
16892
  const layout = dev?.cameraGridLayout;
16892
16893
  if (draft === null || !layout) return;
16893
16894
  setSaving(true);
@@ -16896,7 +16897,8 @@ function CameraGridLayoutEditor({ deviceId }) {
16896
16897
  const outcome = parseGridView(await layout.saveLayout({
16897
16898
  name: draft.name,
16898
16899
  fps: draft.fps,
16899
- cells: draft.cells.map((cell) => ({ ...cell }))
16900
+ cells: draft.cells.map((cell) => ({ ...cell })),
16901
+ ...extra?.publishedProfiles !== void 0 ? { publishedProfiles: [...extra.publishedProfiles] } : {}
16900
16902
  }));
16901
16903
  if (outcome !== null && outcome !== "unreadable") {
16902
16904
  setLoaded(outcome);
@@ -17084,7 +17086,12 @@ function CameraGridLayoutEditor({ deviceId }) {
17084
17086
  }),
17085
17087
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GridProfileReport, {
17086
17088
  offers: loaded.profiles,
17087
- cameras
17089
+ cameras,
17090
+ onToggle: (profile) => {
17091
+ if (draft === null) return;
17092
+ const current = loaded.profiles.filter((row) => row.published).map((row) => row.profile);
17093
+ save({ publishedProfiles: current.includes(profile) ? current.filter((entry) => entry !== profile) : [...current, profile] });
17094
+ }
17088
17095
  }),
17089
17096
  draft.cells[selected] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CellInspector, {
17090
17097
  cell: draft.cells[selected],
@@ -17114,7 +17121,7 @@ function CameraGridLayoutEditor({ deviceId }) {
17114
17121
  * Read-only on purpose: what is on offer is decided by the source cameras'
17115
17122
  * assignments, and a control here would be a switch that writes nothing (D62).
17116
17123
  */
17117
- function GridProfileReport({ offers, cameras }) {
17124
+ function GridProfileReport({ offers, cameras, onToggle }) {
17118
17125
  const nameOf = (deviceId) => cameras.find((camera) => camera.id === deviceId)?.name ?? `#${String(deviceId)}`;
17119
17126
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17120
17127
  className: "flex flex-col gap-1 rounded border border-border p-2 text-[10.5px]",
@@ -17123,20 +17130,33 @@ function GridProfileReport({ offers, cameras }) {
17123
17130
  children: "Published profiles"
17124
17131
  }), offers.map((offer) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17125
17132
  className: "flex items-baseline gap-2",
17126
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17127
- className: "w-10 uppercase",
17128
- children: offer.profile
17129
- }), offer.offered ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
17130
- className: "text-foreground-subtle",
17131
- children: [
17132
- offer.canvas,
17133
- " — composed from every source’s ",
17134
- offer.profile
17135
- ]
17136
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17137
- className: "text-danger",
17138
- children: offer.missingSources.length === 0 ? "not offered — this grid has no cells yet" : `not offered — no ${offer.profile} on ${offer.missingSources.map(nameOf).join(", ")}`
17139
- })]
17133
+ children: [
17134
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
17135
+ type: "checkbox",
17136
+ checked: offer.published,
17137
+ disabled: !offer.offered,
17138
+ "aria-label": `publish ${offer.profile}`,
17139
+ onChange: () => {
17140
+ onToggle(offer.profile);
17141
+ }
17142
+ }),
17143
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17144
+ className: "w-10 uppercase",
17145
+ children: offer.profile
17146
+ }),
17147
+ offer.offered ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
17148
+ className: "text-foreground-subtle",
17149
+ children: [
17150
+ offer.canvas,
17151
+ " —",
17152
+ " ",
17153
+ offer.published ? `composed from every source’s ${offer.profile}` : "serviceable, not published"
17154
+ ]
17155
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
17156
+ className: "text-danger",
17157
+ children: offer.missingSources.length === 0 ? "not offered — this grid has no cells yet" : `not offered — no ${offer.profile} on ${offer.missingSources.map(nameOf).join(", ")}`
17158
+ })
17159
+ ]
17140
17160
  }, offer.profile))]
17141
17161
  });
17142
17162
  }
package/dist/index.js CHANGED
@@ -16618,7 +16618,8 @@ function readProfileOffer(value) {
16618
16618
  profile,
16619
16619
  offered,
16620
16620
  missingSources,
16621
- canvas: typeof value["canvas"] === "string" ? value["canvas"] : ""
16621
+ canvas: typeof value["canvas"] === "string" ? value["canvas"] : "",
16622
+ published: typeof value["published"] === "boolean" ? value["published"] : offered
16622
16623
  };
16623
16624
  }
16624
16625
  /**
@@ -16863,7 +16864,7 @@ function CameraGridLayoutEditor({ deviceId }) {
16863
16864
  setLoaded("unreadable");
16864
16865
  });
16865
16866
  }, [dev, reload]);
16866
- const save = useCallback(async () => {
16867
+ const save = useCallback(async (extra) => {
16867
16868
  const layout = dev?.cameraGridLayout;
16868
16869
  if (draft === null || !layout) return;
16869
16870
  setSaving(true);
@@ -16872,7 +16873,8 @@ function CameraGridLayoutEditor({ deviceId }) {
16872
16873
  const outcome = parseGridView(await layout.saveLayout({
16873
16874
  name: draft.name,
16874
16875
  fps: draft.fps,
16875
- cells: draft.cells.map((cell) => ({ ...cell }))
16876
+ cells: draft.cells.map((cell) => ({ ...cell })),
16877
+ ...extra?.publishedProfiles !== void 0 ? { publishedProfiles: [...extra.publishedProfiles] } : {}
16876
16878
  }));
16877
16879
  if (outcome !== null && outcome !== "unreadable") {
16878
16880
  setLoaded(outcome);
@@ -17060,7 +17062,12 @@ function CameraGridLayoutEditor({ deviceId }) {
17060
17062
  }),
17061
17063
  /* @__PURE__ */ jsx(GridProfileReport, {
17062
17064
  offers: loaded.profiles,
17063
- cameras
17065
+ cameras,
17066
+ onToggle: (profile) => {
17067
+ if (draft === null) return;
17068
+ const current = loaded.profiles.filter((row) => row.published).map((row) => row.profile);
17069
+ save({ publishedProfiles: current.includes(profile) ? current.filter((entry) => entry !== profile) : [...current, profile] });
17070
+ }
17064
17071
  }),
17065
17072
  draft.cells[selected] !== void 0 && /* @__PURE__ */ jsx(CellInspector, {
17066
17073
  cell: draft.cells[selected],
@@ -17090,7 +17097,7 @@ function CameraGridLayoutEditor({ deviceId }) {
17090
17097
  * Read-only on purpose: what is on offer is decided by the source cameras'
17091
17098
  * assignments, and a control here would be a switch that writes nothing (D62).
17092
17099
  */
17093
- function GridProfileReport({ offers, cameras }) {
17100
+ function GridProfileReport({ offers, cameras, onToggle }) {
17094
17101
  const nameOf = (deviceId) => cameras.find((camera) => camera.id === deviceId)?.name ?? `#${String(deviceId)}`;
17095
17102
  return /* @__PURE__ */ jsxs("div", {
17096
17103
  className: "flex flex-col gap-1 rounded border border-border p-2 text-[10.5px]",
@@ -17099,20 +17106,33 @@ function GridProfileReport({ offers, cameras }) {
17099
17106
  children: "Published profiles"
17100
17107
  }), offers.map((offer) => /* @__PURE__ */ jsxs("div", {
17101
17108
  className: "flex items-baseline gap-2",
17102
- children: [/* @__PURE__ */ jsx("span", {
17103
- className: "w-10 uppercase",
17104
- children: offer.profile
17105
- }), offer.offered ? /* @__PURE__ */ jsxs("span", {
17106
- className: "text-foreground-subtle",
17107
- children: [
17108
- offer.canvas,
17109
- " — composed from every source’s ",
17110
- offer.profile
17111
- ]
17112
- }) : /* @__PURE__ */ jsx("span", {
17113
- className: "text-danger",
17114
- children: offer.missingSources.length === 0 ? "not offered — this grid has no cells yet" : `not offered — no ${offer.profile} on ${offer.missingSources.map(nameOf).join(", ")}`
17115
- })]
17109
+ children: [
17110
+ /* @__PURE__ */ jsx("input", {
17111
+ type: "checkbox",
17112
+ checked: offer.published,
17113
+ disabled: !offer.offered,
17114
+ "aria-label": `publish ${offer.profile}`,
17115
+ onChange: () => {
17116
+ onToggle(offer.profile);
17117
+ }
17118
+ }),
17119
+ /* @__PURE__ */ jsx("span", {
17120
+ className: "w-10 uppercase",
17121
+ children: offer.profile
17122
+ }),
17123
+ offer.offered ? /* @__PURE__ */ jsxs("span", {
17124
+ className: "text-foreground-subtle",
17125
+ children: [
17126
+ offer.canvas,
17127
+ " —",
17128
+ " ",
17129
+ offer.published ? `composed from every source’s ${offer.profile}` : "serviceable, not published"
17130
+ ]
17131
+ }) : /* @__PURE__ */ jsx("span", {
17132
+ className: "text-danger",
17133
+ children: offer.missingSources.length === 0 ? "not offered — this grid has no cells yet" : `not offered — no ${offer.profile} on ${offer.missingSources.map(nameOf).join(", ")}`
17134
+ })
17135
+ ]
17116
17136
  }, offer.profile))]
17117
17137
  });
17118
17138
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/ui-library",
3
- "version": "1.2.180",
3
+ "version": "1.2.181",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",