@camstack/addon-model-studio 1.1.323 → 1.1.325

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.
Files changed (19) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{MotionZonesSettings-CBVJdmZ_.mjs → MotionZonesSettings-BFSzpDlc.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-CFuZa1xW.mjs → PrivacyMaskSettings-bzbS1q77.mjs} +4 -4
  4. package/dist/{SceneMonitorEditor-DHYl0WUF.mjs → SceneMonitorEditor-5jtlWR_n.mjs} +3 -3
  5. package/dist/_stub.js +11 -11
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DiTB72W6.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-Cw6pUSlz.mjs} +3 -3
  7. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D8h8qfbd.mjs +26 -0
  8. package/dist/{hostInit-BL6ZxXXr.mjs → hostInit-BCmIggoT.mjs} +2 -2
  9. package/dist/model-studio.addon.js +322 -3
  10. package/dist/model-studio.addon.mjs +322 -3
  11. package/dist/{player-overlays-CDEmtjZg.mjs → player-overlays-DwnklNvS.mjs} +1 -1
  12. package/dist/remoteEntry.js +1 -1
  13. package/dist/{responsive-B_pKmFhb.mjs → responsive-DFhiWOST.mjs} +1 -1
  14. package/dist/{scene-monitor-copy-KV9Ti6_0.mjs → scene-monitor-copy-DVaiZyk_.mjs} +1 -1
  15. package/dist/{square-ByW1TPIi.mjs → square-CL1GZCDy.mjs} +1 -1
  16. package/dist/{trash-2-9gFkA-Zu.mjs → trash-2-Bs4Zqar1.mjs} +1 -1
  17. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-B880BvK0.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-BX2O_m8t.mjs} +1 -1
  18. package/package.json +1 -1
  19. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B3TmOWWR.mjs +0 -26
@@ -5850,7 +5850,7 @@ var ZodIssueCode = {
5850
5850
  var ZodFirstPartyTypeKind;
5851
5851
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5852
5852
  //#endregion
5853
- //#region ../types/dist/sleep-6eG9C8Xl.mjs
5853
+ //#region ../types/dist/sleep-63gM_1JR.mjs
5854
5854
  /**
5855
5855
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5856
5856
  * window to float samples (D455).
@@ -9211,6 +9211,7 @@ var CAP_NAMES = Object.freeze([
9211
9211
  "recording-signal",
9212
9212
  "records",
9213
9213
  "remote",
9214
+ "remote-layout-components",
9214
9215
  "running-state",
9215
9216
  "scene-monitor",
9216
9217
  "script-runner",
@@ -58816,6 +58817,30 @@ object({
58816
58817
  at: number()
58817
58818
  }).nullable()
58818
58819
  });
58820
+ var RemoteButtonShapeSchema = _enum([
58821
+ "rect",
58822
+ "rounded",
58823
+ "round",
58824
+ "pill"
58825
+ ]);
58826
+ var RemoteButtonToneSchema = _enum([
58827
+ "neutral",
58828
+ "accent",
58829
+ "danger",
58830
+ "red",
58831
+ "green",
58832
+ "yellow",
58833
+ "blue"
58834
+ ]);
58835
+ var RemoteGroupFrameSchema = _enum([
58836
+ "none",
58837
+ "panel",
58838
+ "divider",
58839
+ "dpad",
58840
+ "rocker-v",
58841
+ "rocker-h",
58842
+ "keypad"
58843
+ ]);
58819
58844
  var RemoteLayoutButtonSchema = object({
58820
58845
  id: string().min(1).max(40),
58821
58846
  /** 0-based grid position. */
@@ -58825,12 +58850,94 @@ var RemoteLayoutButtonSchema = object({
58825
58850
  colSpan: number().int().min(1).max(24),
58826
58851
  icon: string().min(1).max(60).optional(),
58827
58852
  label: string().min(1).max(40).optional(),
58828
- role: RemoteRoleSchema
58853
+ role: RemoteRoleSchema,
58854
+ /** Absent = the plain rendering every layout had before shapes existed. */
58855
+ shape: RemoteButtonShapeSchema.optional(),
58856
+ tone: RemoteButtonToneSchema.optional(),
58857
+ /** The group this button belongs to; it must lie inside that group's rectangle. */
58858
+ groupId: string().min(1).max(40).optional()
58859
+ });
58860
+ /**
58861
+ * A rectangle of the grid that moves as ONE thing and is drawn with a frame: a
58862
+ * titled panel, a section divider, a D-pad ring. `componentId` names the palette
58863
+ * entry it came from (informational: the layout is self-contained).
58864
+ */
58865
+ var RemoteLayoutGroupSchema = object({
58866
+ id: string().min(1).max(40),
58867
+ componentId: string().min(1).max(80),
58868
+ frame: RemoteGroupFrameSchema,
58869
+ row: number().int().min(0).max(24),
58870
+ col: number().int().min(0).max(24),
58871
+ rowSpan: number().int().min(1).max(24),
58872
+ colSpan: number().int().min(1).max(24),
58873
+ title: string().min(1).max(40).optional()
58829
58874
  });
58875
+ function rectsOverlap(a, b) {
58876
+ return a.row < b.row + b.rowSpan && b.row < a.row + a.rowSpan && a.col < b.col + b.colSpan && b.col < a.col + a.colSpan;
58877
+ }
58878
+ function rectContains(outer, inner) {
58879
+ return inner.row >= outer.row && inner.col >= outer.col && inner.row + inner.rowSpan <= outer.row + outer.rowSpan && inner.col + inner.colSpan <= outer.col + outer.colSpan;
58880
+ }
58881
+ /**
58882
+ * The group rules of a layout: inside the grid, no two groups overlap, a
58883
+ * member lies inside its group, a divider holds nothing, and a button that is
58884
+ * not a member never sits inside someone else's rectangle (a group moves as
58885
+ * one thing, so a stray key under it would be left behind).
58886
+ */
58887
+ function refineGroups(grid, ctx) {
58888
+ const groups = grid.groups ?? [];
58889
+ const byId = /* @__PURE__ */ new Map();
58890
+ const fail = (message, path) => {
58891
+ ctx.addIssue({
58892
+ code: "custom",
58893
+ message,
58894
+ path
58895
+ });
58896
+ };
58897
+ groups.forEach((group, index) => {
58898
+ if (byId.has(group.id)) fail(`group id "${group.id}" is used twice`, [
58899
+ "groups",
58900
+ index,
58901
+ "id"
58902
+ ]);
58903
+ byId.set(group.id, group);
58904
+ if (group.row + group.rowSpan > grid.rows || group.col + group.colSpan > grid.columns) fail(`group "${group.id}" leaves the grid`, ["groups", index]);
58905
+ for (let other = 0; other < index; other += 1) {
58906
+ const earlier = groups[other];
58907
+ if (earlier !== void 0 && rectsOverlap(earlier, group)) {
58908
+ fail(`groups "${earlier.id}" and "${group.id}" overlap`, ["groups", index]);
58909
+ return;
58910
+ }
58911
+ }
58912
+ });
58913
+ grid.buttons.forEach((button, index) => {
58914
+ if (button.groupId !== void 0) {
58915
+ const group = byId.get(button.groupId);
58916
+ if (group === void 0) {
58917
+ fail(`button "${button.id}" names the unknown group "${button.groupId}"`, [
58918
+ "buttons",
58919
+ index,
58920
+ "groupId"
58921
+ ]);
58922
+ return;
58923
+ }
58924
+ if (group.frame === "divider") fail(`a divider group ("${group.id}") holds no buttons`, [
58925
+ "buttons",
58926
+ index,
58927
+ "groupId"
58928
+ ]);
58929
+ if (!rectContains(group, button)) fail(`button "${button.id}" lies outside its group "${group.id}"`, ["buttons", index]);
58930
+ return;
58931
+ }
58932
+ const foreign = groups.find((group) => rectsOverlap(group, button));
58933
+ if (foreign !== void 0) fail(`button "${button.id}" lies inside group "${foreign.id}" but is not a member`, ["buttons", index]);
58934
+ });
58935
+ }
58830
58936
  object({
58831
58937
  columns: number().int().min(1).max(24),
58832
58938
  rows: number().int().min(1).max(24),
58833
- buttons: array(RemoteLayoutButtonSchema).max(200)
58939
+ buttons: array(RemoteLayoutButtonSchema).max(200),
58940
+ groups: array(RemoteLayoutGroupSchema).max(50).optional()
58834
58941
  }).superRefine((grid, ctx) => {
58835
58942
  const ids = /* @__PURE__ */ new Set();
58836
58943
  const taken = /* @__PURE__ */ new Map();
@@ -58867,6 +58974,7 @@ object({
58867
58974
  taken.set(cell, button.id);
58868
58975
  }
58869
58976
  });
58977
+ refineGroups(grid, ctx);
58870
58978
  });
58871
58979
  var RemoteBoundCommandSchema = object({
58872
58980
  role: RemoteRoleSchema,
@@ -58998,6 +59106,91 @@ method(object({ kind: TemplateKindSchema.optional() }), array(TemplateRecordSche
58998
59106
  kind: "mutation",
58999
59107
  auth: "admin"
59000
59108
  });
59109
+ var RemoteComponentCategorySchema = _enum([
59110
+ "power",
59111
+ "navigation",
59112
+ "volume",
59113
+ "numbers",
59114
+ "media",
59115
+ "colour",
59116
+ "apps",
59117
+ "layout"
59118
+ ]);
59119
+ /** `<namespace>:<name>`, both lowercase slugs — `core:dpad`, `<addonId>:<name>`. */
59120
+ var COMPONENT_ID_RE = /^[a-z0-9][a-z0-9_.-]*:[a-z0-9][a-z0-9_-]*$/;
59121
+ var RemoteComponentButtonSchema = object({
59122
+ /** Joined to the instance id when the component is inserted. */
59123
+ idSuffix: string().regex(/^[a-z0-9][a-z0-9_-]{0,19}$/, { message: "a short lowercase slug" }),
59124
+ row: number().int().min(0).max(24),
59125
+ col: number().int().min(0).max(24),
59126
+ rowSpan: number().int().min(1).max(24),
59127
+ colSpan: number().int().min(1).max(24),
59128
+ role: RemoteRoleSchema,
59129
+ icon: string().min(1).max(60).optional(),
59130
+ label: string().min(1).max(40).optional(),
59131
+ shape: RemoteButtonShapeSchema.optional(),
59132
+ tone: RemoteButtonToneSchema.optional()
59133
+ });
59134
+ var RemoteLayoutComponentSchema = object({
59135
+ id: string().max(80).regex(COMPONENT_ID_RE, { message: "<namespace>:<name>, lowercase" }),
59136
+ name: string().min(1).max(60),
59137
+ nameI18n: object({
59138
+ en: string().min(1).max(60),
59139
+ it: string().min(1).max(60)
59140
+ }).optional(),
59141
+ /** A display icon key, resolved by the UI like a button icon. */
59142
+ icon: string().min(1).max(60),
59143
+ category: RemoteComponentCategorySchema,
59144
+ size: object({
59145
+ rows: number().int().min(1).max(24),
59146
+ cols: number().int().min(1).max(24)
59147
+ }),
59148
+ /** The frame drawn around the whole component, or null for loose buttons. */
59149
+ group: object({
59150
+ frame: RemoteGroupFrameSchema,
59151
+ title: string().min(1).max(40).optional()
59152
+ }).nullable(),
59153
+ buttons: array(RemoteComponentButtonSchema).max(40)
59154
+ }).superRefine((component, ctx) => {
59155
+ const suffixes = /* @__PURE__ */ new Set();
59156
+ component.buttons.forEach((button, index) => {
59157
+ if (suffixes.has(button.idSuffix)) ctx.addIssue({
59158
+ code: "custom",
59159
+ message: `button "${button.idSuffix}" is listed twice`,
59160
+ path: [
59161
+ "buttons",
59162
+ index,
59163
+ "idSuffix"
59164
+ ]
59165
+ });
59166
+ suffixes.add(button.idSuffix);
59167
+ if (button.row + button.rowSpan > component.size.rows || button.col + button.colSpan > component.size.cols) {
59168
+ ctx.addIssue({
59169
+ code: "custom",
59170
+ message: `button "${button.idSuffix}" leaves the component`,
59171
+ path: ["buttons", index]
59172
+ });
59173
+ return;
59174
+ }
59175
+ for (let other = 0; other < index; other += 1) {
59176
+ const earlier = component.buttons[other];
59177
+ if (earlier !== void 0 && rectsOverlap(earlier, button)) {
59178
+ ctx.addIssue({
59179
+ code: "custom",
59180
+ message: `buttons "${earlier.idSuffix}" and "${button.idSuffix}" overlap`,
59181
+ path: ["buttons", index]
59182
+ });
59183
+ return;
59184
+ }
59185
+ }
59186
+ });
59187
+ if (component.group?.frame === "divider" && component.buttons.length > 0) ctx.addIssue({
59188
+ code: "custom",
59189
+ message: "a divider component holds no buttons",
59190
+ path: ["buttons"]
59191
+ });
59192
+ });
59193
+ method(object({}), array(RemoteLayoutComponentSchema), { auth: "protected" });
59001
59194
  DeviceType.Button, method(object({ deviceId: number().int().nonnegative() }), _void(), {
59002
59195
  kind: "mutation",
59003
59196
  auth: "protected"
@@ -67933,6 +68126,124 @@ method(object({}), array(TrainingBaseModelSchema).readonly(), { auth: "admin" })
67933
68126
  kind: "mutation",
67934
68127
  auth: "admin"
67935
68128
  });
68129
+ var btn = (idSuffix, row, col, init) => ({
68130
+ idSuffix,
68131
+ row,
68132
+ col,
68133
+ rowSpan: 1,
68134
+ colSpan: 1,
68135
+ ...init
68136
+ });
68137
+ function rocker(id, name, it, frame, title, buttons, size) {
68138
+ return {
68139
+ id,
68140
+ name,
68141
+ nameI18n: {
68142
+ en: name,
68143
+ it
68144
+ },
68145
+ icon: frame === "rocker-v" ? "chevrons-up-down" : "chevrons-left-right",
68146
+ category: id.includes("channel") || id.includes("volume") ? "volume" : "navigation",
68147
+ size,
68148
+ group: title === null ? { frame } : {
68149
+ frame,
68150
+ title
68151
+ },
68152
+ buttons
68153
+ };
68154
+ }
68155
+ btn("power", 0, 0, {
68156
+ role: "power",
68157
+ shape: "round",
68158
+ tone: "danger"
68159
+ }), btn("up", 0, 1, {
68160
+ role: "up",
68161
+ icon: "chevron-up"
68162
+ }), btn("left", 1, 0, {
68163
+ role: "left",
68164
+ icon: "chevron-left"
68165
+ }), btn("ok", 1, 1, {
68166
+ role: "ok",
68167
+ shape: "round",
68168
+ tone: "accent"
68169
+ }), btn("right", 1, 2, {
68170
+ role: "right",
68171
+ icon: "chevron-right"
68172
+ }), btn("down", 2, 1, {
68173
+ role: "down",
68174
+ icon: "chevron-down"
68175
+ }), rocker("core:rocker-volume-v", "Volume rocker", "Bilanciere volume", "rocker-v", "VOL", [btn("up", 0, 0, {
68176
+ role: "volume_up",
68177
+ icon: "plus",
68178
+ shape: "pill"
68179
+ }), btn("down", 1, 0, {
68180
+ role: "volume_down",
68181
+ icon: "minus",
68182
+ shape: "pill"
68183
+ })], {
68184
+ rows: 2,
68185
+ cols: 1
68186
+ }), rocker("core:rocker-channel-v", "Channel rocker", "Bilanciere canali", "rocker-v", "CH", [btn("up", 0, 0, {
68187
+ role: "channel_up",
68188
+ icon: "chevron-up",
68189
+ shape: "pill"
68190
+ }), btn("down", 1, 0, {
68191
+ role: "channel_down",
68192
+ icon: "chevron-down",
68193
+ shape: "pill"
68194
+ })], {
68195
+ rows: 2,
68196
+ cols: 1
68197
+ }), rocker("core:rocker-h", "Minus / plus rocker", "Bilanciere meno / più", "rocker-h", null, [btn("minus", 0, 0, {
68198
+ role: "custom:minus",
68199
+ label: "Minus",
68200
+ icon: "minus",
68201
+ shape: "pill"
68202
+ }), btn("plus", 0, 1, {
68203
+ role: "custom:plus",
68204
+ label: "Plus",
68205
+ icon: "plus",
68206
+ shape: "pill"
68207
+ })], {
68208
+ rows: 1,
68209
+ cols: 2
68210
+ }), [...Array.from({ length: 9 }, (_, i) => btn(`d${i + 1}`, Math.floor(i / 3), i % 3, { role: `digit_${i + 1}` })), btn("d0", 3, 1, { role: "digit_0" })], btn("red", 0, 0, {
68211
+ role: "custom:color_red",
68212
+ label: "Red",
68213
+ tone: "red"
68214
+ }), btn("green", 0, 1, {
68215
+ role: "custom:color_green",
68216
+ label: "Green",
68217
+ tone: "green"
68218
+ }), btn("yellow", 0, 2, {
68219
+ role: "custom:color_yellow",
68220
+ label: "Yellow",
68221
+ tone: "yellow"
68222
+ }), btn("blue", 0, 3, {
68223
+ role: "custom:color_blue",
68224
+ label: "Blue",
68225
+ tone: "blue"
68226
+ }), btn("rewind", 0, 0, {
68227
+ role: "rewind",
68228
+ icon: "rewind"
68229
+ }), btn("play", 0, 1, {
68230
+ role: "play",
68231
+ icon: "play"
68232
+ }), btn("pause", 0, 2, {
68233
+ role: "pause",
68234
+ icon: "pause"
68235
+ }), btn("forward", 0, 3, {
68236
+ role: "fast_forward",
68237
+ icon: "fast-forward"
68238
+ }), btn("stop", 0, 4, {
68239
+ role: "stop",
68240
+ icon: "square"
68241
+ }), [
68242
+ 1,
68243
+ 2,
68244
+ 3,
68245
+ 4
68246
+ ].map((n) => btn(`app${n}`, 0, n - 1, { role: `custom:app_slot_${n}` })), btn("back", 0, 0, { role: "back" }), btn("home", 0, 1, { role: "home" }), btn("menu", 0, 2, { role: "menu" });
67936
68247
  discriminatedUnion("kind", [object({
67937
68248
  kind: literal("raw"),
67938
68249
  timings: array(number().int()),
@@ -75895,6 +76206,13 @@ Object.freeze({
75895
76206
  access: "create",
75896
76207
  role: "admin"
75897
76208
  },
76209
+ "remoteLayoutComponents.listComponents": {
76210
+ capName: "remote-layout-components",
76211
+ capScope: "system",
76212
+ addonId: null,
76213
+ access: "view",
76214
+ role: "admin"
76215
+ },
75898
76216
  "runningState.getStatus": {
75899
76217
  capName: "running-state",
75900
76218
  capScope: "device",
@@ -82071,6 +82389,7 @@ var SYSTEM_CAP_VOCABULARY = {
82071
82389
  "recording-export": system("recording exports — requested from the timeline, not an automation step"),
82072
82390
  records: system(INTERNAL),
82073
82391
  remote: system("the per-device remote setup — authored in the Customize remote editor, sent through the remote UI"),
82392
+ "remote-layout-components": system("the palette of the remote template editor — read-only data, never actuated"),
82074
82393
  "server-management": system(CLUSTER),
82075
82394
  "settings-store": system(INTERNAL),
82076
82395
  "smtp-provider": system(INTERNAL),