floor-editor-ts 1.3.2 → 1.3.4

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.
@@ -5963,6 +5963,25 @@ if (typeof window !== "undefined") {
5963
5963
  var _window$__svelte, _window$__svelte$v, _window, _window$__svelte2;
5964
5964
  ((_window$__svelte$v = (_window$__svelte = (_window$__svelte2 = (_window = window).__svelte) !== null && _window$__svelte2 !== void 0 ? _window$__svelte2 : _window.__svelte = {}).v) !== null && _window$__svelte$v !== void 0 ? _window$__svelte$v : _window$__svelte.v = /* @__PURE__ */ new Set()).add("5");
5965
5965
  }
5966
+ /** True while host → package assignedCameras sync is mutating furniture. */
5967
+ var assignedCamerasSyncing = false;
5968
+ function setAssignedCamerasSyncing(value) {
5969
+ assignedCamerasSyncing = value;
5970
+ }
5971
+ function isAssignedCamerasSyncing() {
5972
+ return assignedCamerasSyncing;
5973
+ }
5974
+ var dispatcher = null;
5975
+ /** Wire from App so stores/utils can emit without prop drilling. */
5976
+ function setFloorCallbackDispatcher(fn) {
5977
+ dispatcher = fn;
5978
+ }
5979
+ function emitFloorCallback(type, data) {
5980
+ dispatcher === null || dispatcher === void 0 || dispatcher("floor:callbackEvent", {
5981
+ type,
5982
+ data
5983
+ });
5984
+ }
5966
5985
  //#endregion
5967
5986
  //#region src/lib/stores/onboarding.svelte.ts
5968
5987
  var onboarding_svelte_exports = /* @__PURE__ */ __exportAll({
@@ -6346,6 +6365,18 @@ function scaleFurniture(id, scale) {
6346
6365
  };
6347
6366
  });
6348
6367
  }
6368
+ function removeFurniture(id) {
6369
+ const p = get$1(currentProject);
6370
+ const floor = p === null || p === void 0 ? void 0 : p.floors.find((f) => f.id === p.activeFloorId);
6371
+ const removedCamera = floor === null || floor === void 0 ? void 0 : floor.furniture.find((fi) => fi.id === id && fi.catalogId === "camera" && fi.serial);
6372
+ mutate((f) => {
6373
+ f.furniture = f.furniture.filter((fi) => fi.id !== id);
6374
+ }, "Deleted furniture");
6375
+ if ((removedCamera === null || removedCamera === void 0 ? void 0 : removedCamera.serial) && !isAssignedCamerasSyncing()) emitFloorCallback("cameraRemoved", {
6376
+ serial: removedCamera.serial,
6377
+ name: removedCamera.name
6378
+ });
6379
+ }
6349
6380
  function addStair(position) {
6350
6381
  const id = uid$1();
6351
6382
  mutate((f) => {
@@ -6441,6 +6472,9 @@ var placingStair = writable(false);
6441
6472
  var calibrationMode = writable(false);
6442
6473
  var calibrationPoints = writable([]);
6443
6474
  function removeElement(id) {
6475
+ const p = get$1(currentProject);
6476
+ const floor = p === null || p === void 0 ? void 0 : p.floors.find((f) => f.id === p.activeFloorId);
6477
+ const removedCamera = floor === null || floor === void 0 ? void 0 : floor.furniture.find((fi) => fi.id === id && fi.catalogId === "camera" && fi.serial);
6444
6478
  mutate((f) => {
6445
6479
  const isWall = f.walls.some((w) => w.id === id);
6446
6480
  f.walls = f.walls.filter((w) => w.id !== id);
@@ -6455,6 +6489,10 @@ function removeElement(id) {
6455
6489
  if (f.columns) f.columns = f.columns.filter((c) => c.id !== id);
6456
6490
  if (f.textAnnotations) f.textAnnotations = f.textAnnotations.filter((t) => t.id !== id);
6457
6491
  }, "Deleted element");
6492
+ if ((removedCamera === null || removedCamera === void 0 ? void 0 : removedCamera.serial) && !isAssignedCamerasSyncing()) emitFloorCallback("cameraRemoved", {
6493
+ serial: removedCamera.serial,
6494
+ name: removedCamera.name
6495
+ });
6458
6496
  }
6459
6497
  /** Move a wall endpoint without creating an undo snapshot (for dragging) */
6460
6498
  function moveWallEndpoint(id, endpoint, position) {
@@ -6994,6 +7032,7 @@ var DEFAULT_CONFIG = {
6994
7032
  showCameraLabels: true,
6995
7033
  cameraHeatmapMatrix: [],
6996
7034
  siteCameras: [],
7035
+ assignedCameras: [],
6997
7036
  cameraThumbnail: "",
6998
7037
  cameraThumbnailOpacity: .65,
6999
7038
  canvasBackground: "#f8f9fa",
@@ -7002,6 +7041,7 @@ var DEFAULT_CONFIG = {
7002
7041
  function normalizeConfig(value) {
7003
7042
  if (!value || typeof value !== "object") return { ...DEFAULT_CONFIG };
7004
7043
  const siteCameras = Array.isArray(value.siteCameras) ? value.siteCameras.filter((c) => !!c && typeof c === "object" && typeof c.serial === "string" && typeof c.name === "string") : DEFAULT_CONFIG.siteCameras;
7044
+ const assignedCameras = Array.isArray(value.assignedCameras) ? value.assignedCameras.filter((c) => !!c && typeof c === "object" && typeof c.serial === "string" && c.serial.trim().length > 0 && typeof c.name === "string") : DEFAULT_CONFIG.assignedCameras;
7005
7045
  const image = typeof value.cameraThumbnail === "string" ? value.cameraThumbnail ? value.cameraThumbnail : DEFAULT_CONFIG.cameraThumbnail : DEFAULT_CONFIG.cameraThumbnail;
7006
7046
  const opacity = typeof value.cameraThumbnailOpacity === "number" && value.cameraThumbnailOpacity >= 0 && value.cameraThumbnailOpacity <= 1 ? value.cameraThumbnailOpacity : DEFAULT_CONFIG.cameraThumbnailOpacity;
7007
7047
  const canvasBackground = normalizeColor$1(value.canvasBackground, DEFAULT_CONFIG.canvasBackground);
@@ -7010,6 +7050,7 @@ function normalizeConfig(value) {
7010
7050
  ...DEFAULT_CONFIG,
7011
7051
  ...value,
7012
7052
  siteCameras,
7053
+ assignedCameras,
7013
7054
  cameraThumbnail: image,
7014
7055
  cameraThumbnailOpacity: opacity,
7015
7056
  canvasBackground,
@@ -56133,7 +56174,7 @@ var root_7$6 = /* @__PURE__ */ from_html(`<div class="flex items-center justify-
56133
56174
  before:content-[''] before:absolute before:w-4 before:h-4 before:rounded-full before:bg-white before:top-0.5 before:left-0.5 before:transition-transform checked:before:translate-x-5"/></label> <div class="flex items-center justify-between px-4 py-3.5"><span class="text-sm text-gray-700">Line Color</span> <div class="flex items-center gap-2"><button style="background-color: #ffffff" aria-label="White line color"></button> <span class="text-gray-300">|</span> <button style="background-color: #1e293b" aria-label="Dark line color"></button></div></div></div>`, 1);
56134
56175
  var root_9$2 = /* @__PURE__ */ from_html(`<button><span class="text-2xl"> </span> <span class="text-xs font-medium text-gray-700 dark:text-gray-300"> </span></button>`);
56135
56176
  var root_8$3 = /* @__PURE__ */ from_html(`<div class="space-y-4"><div><span class="text-sm font-medium text-gray-700 dark:text-gray-300 block mb-3">Theme</span> <div class="flex gap-3"></div></div></div>`);
56136
- var root_11$1 = /* @__PURE__ */ from_html(`<button class="px-4 py-2 text-sm font-medium text-red-600 dark:text-red-400 border border-red-300 dark:border-red-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors">Remove</button>`);
56177
+ var root_11$2 = /* @__PURE__ */ from_html(`<button class="px-4 py-2 text-sm font-medium text-red-600 dark:text-red-400 border border-red-300 dark:border-red-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors">Remove</button>`);
56137
56178
  var root_12$3 = /* @__PURE__ */ from_html(`<button class="px-4 py-2 text-sm font-medium text-red-600 dark:text-red-400 border border-red-300 dark:border-red-600 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors">Remove</button>`);
56138
56179
  var root_10$2 = /* @__PURE__ */ from_html(`<div class="space-y-4"><div><span class="text-sm font-medium text-gray-700 dark:text-gray-300 block mb-1">Gemini API Key</span> <p class="text-xs text-gray-500 dark:text-gray-400 mb-3">Required for AI-powered photorealistic rendering. Your key is stored locally in your browser only - never sent to our servers.</p> <div class="flex gap-2"><div class="relative flex-1"><input class="w-full px-3 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-mono focus:ring-2 focus:ring-slate-500 focus:border-slate-500 outline-none bg-white dark:bg-gray-700 dark:text-gray-100" placeholder="AIza..."/> <button class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-sm"> </button></div></div> <div class="flex gap-2 mt-3"><button class="px-4 py-2 text-sm font-medium bg-slate-700 text-white rounded-lg hover:bg-slate-600 transition-colors"> </button> <!></div></div> <div class="border-t border-gray-200 dark:border-gray-700 pt-4"><span class="text-sm font-medium text-gray-700 dark:text-gray-300 block mb-2">How to get a Gemini key</span> <ol class="text-xs text-gray-500 dark:text-gray-400 space-y-1 list-decimal list-inside"><li>Go to <a href="https://aistudio.google.com/apikey" target="_blank" rel="noopener" class="text-blue-500 hover:underline">Google AI Studio</a></li> <li>Click "Create API Key"</li> <li>Copy and paste it above</li></ol></div> <div class="border-t border-gray-200 dark:border-gray-700 pt-4"><span class="text-sm font-medium text-gray-700 dark:text-gray-300 block mb-1">OpenAI API Key</span> <p class="text-xs text-gray-500 dark:text-gray-400 mb-3">Optional — enables OpenAI image generation as an alternative to Gemini. Stored locally only.</p> <div class="flex gap-2"><div class="relative flex-1"><input class="w-full px-3 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-mono focus:ring-2 focus:ring-slate-500 focus:border-slate-500 outline-none bg-white dark:bg-gray-700 dark:text-gray-100" placeholder="sk-..."/> <button class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-sm"> </button></div></div> <div class="flex gap-2 mt-3"><button class="px-4 py-2 text-sm font-medium bg-slate-700 text-white rounded-lg hover:bg-slate-600 transition-colors"> </button> <!></div> <div class="mt-3"><span class="text-sm font-medium text-gray-700 dark:text-gray-300 block mb-2">How to get an OpenAI key</span> <ol class="text-xs text-gray-500 dark:text-gray-400 space-y-1 list-decimal list-inside"><li>Go to <a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener" class="text-blue-500 hover:underline">OpenAI Platform</a></li> <li>Click "Create new secret key"</li> <li>Copy and paste it above</li></ol></div></div></div>`);
56139
56180
  var root_1$13 = /* @__PURE__ */ from_html(`<div class="fixed inset-0 bg-black/50 z-50 flex items-center justify-center" role="dialog" tabindex="-1" aria-label="Settings"><div class="bg-white dark:bg-gray-800 rounded-xl shadow-2xl w-[420px] max-h-[80vh] flex flex-col" role="document"><div class="flex items-center justify-between px-5 pt-4 pb-2"><h2 class="text-lg font-bold text-gray-800 dark:text-gray-100">Settings</h2> <button class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-xl leading-none" aria-label="Close settings">✕</button></div> <div class="flex border-b border-gray-200 dark:border-gray-700 px-5"><button>Project <!></button> <button>Dimensions <!></button> <button>Appearance <!></button> <button>AI <!></button></div> <div class="p-5 overflow-y-auto"><!></div></div></div>`);
@@ -56425,7 +56466,7 @@ function SettingsDialog($$anchor, $$props) {
56425
56466
  reset(button_11);
56426
56467
  var node_6 = sibling(button_11, 2);
56427
56468
  var consequent_7 = ($$anchor) => {
56428
- var button_12 = root_11$1();
56469
+ var button_12 = root_11$2();
56429
56470
  delegated("click", button_12, clearGeminiKey);
56430
56471
  append($$anchor, button_12);
56431
56472
  };
@@ -56860,10 +56901,13 @@ async function autoSave(onDispatch) {
56860
56901
  saveState.set("saving");
56861
56902
  try {
56862
56903
  const thumbnail = captureThumbnail(p.id);
56863
- onDispatch("floor:autoSave", { data: {
56864
- ...exportProjectForSave(p),
56865
- thumbnail
56866
- } });
56904
+ onDispatch("floor:callbackEvent", {
56905
+ type: "autoSave",
56906
+ data: {
56907
+ ...exportProjectForSave(p),
56908
+ thumbnail
56909
+ }
56910
+ });
56867
56911
  saveState.set("saved");
56868
56912
  lastSavedAt.set(/* @__PURE__ */ new Date());
56869
56913
  } catch (e) {
@@ -57048,10 +57092,13 @@ function TopBar($$anchor, $$props) {
57048
57092
  const p = get$1(currentProject);
57049
57093
  if (!p) return;
57050
57094
  const thumbnail = captureThumbnail(p.id);
57051
- $$props.onDispatch("floor:save", { data: {
57052
- ...exportProjectForSave(p),
57053
- thumbnail
57054
- } });
57095
+ $$props.onDispatch("floor:callbackEvent", {
57096
+ type: "save",
57097
+ data: {
57098
+ ...exportProjectForSave(p),
57099
+ thumbnail
57100
+ }
57101
+ });
57055
57102
  }
57056
57103
  let lastSavedText = /* @__PURE__ */ state("");
57057
57104
  let lastSavedTime = /* @__PURE__ */ state(null);
@@ -58121,9 +58168,9 @@ var root_17$2 = /* @__PURE__ */ from_html(`<div class="text-[10px] text-gray-400
58121
58168
  var root_18$2 = /* @__PURE__ */ from_html(`<button> </button>`);
58122
58169
  var root_20$2 = /* @__PURE__ */ from_html(`<button draggable="true"><span role="button" tabindex="0"> </span> <div class="w-8 h-8 rounded-lg flex items-center justify-center"><div class="w-4 h-4 rounded-sm"></div></div> <span class="text-[10px] font-medium text-gray-600 leading-tight text-center"> </span></button>`);
58123
58170
  var root_19$2 = /* @__PURE__ */ from_html(`<div class="mt-1"><h4 class="text-[10px] font-semibold text-gray-400 uppercase mb-1.5">Recent</h4> <div class="grid grid-cols-2 gap-2"></div></div> <hr class="border-gray-100"/>`, 1);
58124
- var root_22$1 = /* @__PURE__ */ from_html(`<span class="text-xs font-medium text-gray-600"> <mark class="bg-yellow-200 text-gray-800 rounded-sm px-0.5"> </mark> </span>`);
58171
+ var root_22$2 = /* @__PURE__ */ from_html(`<span class="text-xs font-medium text-gray-600"> <mark class="bg-yellow-200 text-gray-800 rounded-sm px-0.5"> </mark> </span>`);
58125
58172
  var root_23$2 = /* @__PURE__ */ from_html(`<span class="text-xs font-medium text-gray-600"> </span>`);
58126
- var root_21$2 = /* @__PURE__ */ from_html(`<button draggable="true"><span role="button" tabindex="0"> </span> <div class="w-10 h-10 rounded-lg flex items-center justify-center"><div class="w-5 h-5 rounded-sm"></div></div> <!> <span class="text-[10px] text-gray-400"> </span></button>`);
58173
+ var root_21$1 = /* @__PURE__ */ from_html(`<button draggable="true"><span role="button" tabindex="0"> </span> <div class="w-10 h-10 rounded-lg flex items-center justify-center"><div class="w-5 h-5 rounded-sm"></div></div> <!> <span class="text-[10px] text-gray-400"> </span></button>`);
58127
58174
  var root_15$2 = /* @__PURE__ */ from_html(`<div class="space-y-2"><div class="relative"><input type="text" placeholder="Search furniture..." class="w-full px-3 py-2 pr-8 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-200 focus:border-blue-400 outline-none"/> <!></div> <!> <div class="flex flex-wrap gap-1 max-h-24 overflow-y-auto"><button>All</button> <button> </button> <!></div> <!> <div class="grid grid-cols-2 gap-2 mt-2"></div></div>`);
58128
58175
  var root_24$2 = /* @__PURE__ */ from_html(`<div class="fixed z-50 pointer-events-none"><div class="bg-white rounded-xl shadow-2xl border border-gray-200 overflow-hidden" style="width: 220px;"><div class="w-full h-[120px] bg-gray-50 flex items-center justify-center p-3"><div class="w-16 h-16 rounded-xl flex items-center justify-center"><div class="w-10 h-10 rounded-md"></div></div></div> <div class="p-3 space-y-1.5"><div class="flex items-center gap-2"><span class="text-sm font-semibold text-gray-800"> </span> <span class="px-1.5 py-0.5 rounded-full text-[9px] font-semibold text-white"> </span></div> <div class="text-xs text-gray-500"> </div></div></div></div>`);
58129
58176
  var root_25$1 = /* @__PURE__ */ from_html(`<div class="fixed inset-0 bg-black/50 z-50 flex items-center justify-center"><div class="bg-white rounded-xl shadow-2xl w-80 p-5"><h3 class="text-sm font-bold text-gray-800 mb-1">Import RoomPlan</h3> <p class="text-xs text-gray-400 mb-4"> </p> <div class="space-y-3"><label class="flex items-start gap-2.5 cursor-pointer"><input type="checkbox" class="accent-blue-500 mt-0.5"/> <div><div class="text-sm font-medium text-gray-700">Straighten walls</div> <div class="text-xs text-gray-400">Snap near-horizontal/vertical walls to axis</div></div></label> <label class="flex items-start gap-2.5 cursor-pointer"><input type="checkbox" class="accent-blue-500 mt-0.5"/> <div><div class="text-sm font-medium text-gray-700">Enforce orthogonal <span class="text-xs text-blue-400 font-mono"> </span></div> <div class="text-xs text-gray-400">Force all walls to 90°/180° angles</div></div></label> <label class="block"><div class="text-xs text-gray-500 mb-1">Corner merge distance (cm)</div> <input type="number" min="0" max="50" step="5" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label></div> <div class="flex gap-2 mt-5"><button class="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm text-gray-600 hover:bg-gray-50 transition-colors">Cancel</button> <button class="flex-1 px-3 py-2 bg-blue-500 text-white rounded-lg text-sm font-medium hover:bg-blue-600 transition-colors">Import</button></div></div></div>`);
@@ -58781,7 +58828,7 @@ function BuildPanel($$anchor, $$props) {
58781
58828
  var div_29 = sibling(node_6, 2);
58782
58829
  each(div_29, 21, () => get(filtered), index$1, ($$anchor, item) => {
58783
58830
  const s = /* @__PURE__ */ user_derived(() => get(search).toLowerCase());
58784
- var button_23 = root_21$2();
58831
+ var button_23 = root_21$1();
58785
58832
  var span_10 = child(button_23);
58786
58833
  var text_22 = child(span_10, true);
58787
58834
  reset(span_10);
@@ -58791,7 +58838,7 @@ function BuildPanel($$anchor, $$props) {
58791
58838
  var node_7 = sibling(div_30, 2);
58792
58839
  var consequent_12 = ($$anchor) => {
58793
58840
  const idx = /* @__PURE__ */ user_derived(() => get(item).name.toLowerCase().indexOf(get(s)));
58794
- var span_11 = root_22$1();
58841
+ var span_11 = root_22$2();
58795
58842
  var text_23 = child(span_11, true);
58796
58843
  var mark = sibling(text_23);
58797
58844
  var text_24 = child(mark, true);
@@ -59369,23 +59416,23 @@ var root_1$7 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-
59369
59416
  var root_8$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-amber-100 rounded flex items-center justify-center text-xs">🚪</span> Door Properties</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="1" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Type</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>Single</option><option>Double</option><option>Sliding</option><option>French</option><option>Pocket</option><option>Bifold</option></select></label> <label class="block"><span class="text-xs text-gray-500">Hinge Side</span> <div class="flex gap-2"><button>Left</button> <button>Right</button></div></label> <label class="block"><span class="text-xs text-gray-500">Opens</span> <div class="flex gap-2"><button>Inward</button> <button>Outward</button></div></label></div>`, 1);
59370
59417
  var root_9$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-cyan-100 rounded flex items-center justify-center text-xs">🪟</span> Window Properties</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Type</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>Standard</option><option>Fixed</option><option>Casement</option><option>Sliding</option><option>Bay</option></select></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="1" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label></div>`, 1);
59371
59418
  var root_13$1 = /* @__PURE__ */ from_html(`<option> </option>`);
59372
- var root_14$1 = /* @__PURE__ */ from_html(`<p class="text-xs text-gray-500">Serial: <span class="text-gray-700 font-mono"> </span></p>`);
59373
- var root_12$1 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Camera</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm bg-white"><option>Select camera...</option><!></select></label> <!>`, 1);
59374
- var root_15$1 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Camera Name</span> <input type="text" placeholder="Display name" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Camera Serial</span> <input type="text" placeholder="Device serial" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label>`, 1);
59375
- var root_16 = /* @__PURE__ */ from_html(`<button></button>`);
59419
+ var root_12$1 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Camera</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm bg-white"><option>Select camera...</option><!></select></label>`);
59420
+ var root_14$1 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Camera Serial</span> <input type="text" disabled="" readonly="" placeholder="Assigned by host" class="w-full px-2 py-1 border border-gray-200 rounded text-sm bg-gray-50 text-gray-600 font-mono"/></label>`);
59421
+ var root_11$1 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Camera Name</span> <input type="text" placeholder="Display name" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <!>`, 1);
59422
+ var root_15$1 = /* @__PURE__ */ from_html(`<button></button>`);
59376
59423
  var root_10$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-purple-100 rounded flex items-center justify-center text-xs"> </span> <button> </button></h3> <div class="space-y-3"><!> <div><div class="flex items-center gap-1 mb-2"><span class="text-xs text-gray-500">Color</span> <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-gray-400"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path></svg></div> <div class="grid grid-cols-5 gap-1.5 mb-2"></div> <div class="flex items-center gap-2"><span class="text-xs text-gray-500">Custom:</span> <input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/></div></div> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="1" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="1" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="1" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Material</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>Wood</option><option>Metal</option><option>Fabric</option><option>Leather</option><option>Glass</option><option>Plastic</option><option>Stone</option><option>Ceramic</option></select></label> <label class="block"><span class="text-xs text-gray-500">Rotation (degrees)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <div class="flex gap-1"><button class="flex-1 px-2 py-1.5 border border-gray-200 rounded text-sm hover:bg-gray-50 transition-colors" title="Rotate 90° left">↺ 90°</button> <button class="flex-1 px-2 py-1.5 border border-gray-200 rounded text-sm hover:bg-gray-50 transition-colors" title="Rotate 90° right">↻ 90°</button></div> <div class="flex gap-1"><button class="flex-1 px-2 py-1.5 border border-gray-200 rounded text-sm hover:bg-gray-50 transition-colors" title="Flip horizontally">↔ Flip H</button> <button class="flex-1 px-2 py-1.5 border border-gray-200 rounded text-sm hover:bg-gray-50 transition-colors" title="Flip vertically">↕ Flip V</button></div> <button class="w-full px-2 py-1.5 border border-gray-300 rounded text-sm text-gray-600 hover:bg-gray-50 transition-colors">Reset to defaults</button></div>`, 1);
59377
- var root_18$1 = /* @__PURE__ */ from_html(`<label class="block pb-3 border-b border-gray-200"><span class="text-xs text-gray-500"> </span> <input type="range" min="0.05" max="1" step="0.05" class="w-full"/></label>`);
59378
- var root_19$1 = /* @__PURE__ */ from_html(`<option> </option>`);
59379
- var root_20$1 = /* @__PURE__ */ from_html(`<button></button>`);
59380
- var root_23$1 = /* @__PURE__ */ from_html(`<button><div class="w-full h-12 rounded-md mb-1 overflow-hidden"></div> <div class="text-center leading-3 text-[10px] text-gray-600 truncate"> </div></button>`);
59381
- var root_21$1 = /* @__PURE__ */ from_html(`<div><span class="text-xs font-medium text-gray-600 mb-1.5 block"> </span> <div class="grid grid-cols-3 gap-1.5"></div></div>`);
59382
- var root_17$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-green-100 rounded flex items-center justify-center text-xs">⬜</span> Room Properties</h3> <div class="space-y-3"><!> <label class="block"><span class="text-xs text-gray-500">Room Type</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"></select></label> <label class="block"><span class="text-xs text-gray-500">Room Name</span> <input type="text" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Category</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>🏠 Indoor</option><option>🌳 Outdoor</option><option>🚗 Garage</option><option>🔧 Utility</option></select></label> <div><span class="text-xs text-gray-500">Area</span> <p class="text-sm text-gray-700"> </p></div> <div><span class="text-xs text-gray-500 mb-1.5 block">Room Color</span> <div class="grid grid-cols-5 gap-1.5 mb-2"></div> <div class="flex items-center gap-2"><span class="text-xs text-gray-500">Custom:</span> <input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/></div></div> <div><div class="flex items-center gap-1 mb-2"><span class="text-xs text-gray-500">Floor Material</span> <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-gray-400"><path d="M3 3h18v18H3z"></path><path d="M8 8h8v8H8z"></path></svg></div> <div class="space-y-3"></div></div></div>`, 1);
59383
- var root_24$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-xs">🪜</span> Stair Properties</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Type</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>Straight</option><option>L-Shaped</option><option>U-Shaped</option><option>Spiral</option></select></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Risers</span> <input type="number" min="3" max="30" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Direction</span> <div class="flex gap-2"><button>Up ↑</button> <button>Down ↓</button></div></label> <label class="block"><span class="text-xs text-gray-500">Rotation (degrees)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label></div>`, 1);
59384
- var root_26 = /* @__PURE__ */ from_html(`<button></button>`);
59385
- var root_27 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Rotation (degrees)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label>`);
59386
- var root_25 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-xs">🏛️</span> Column Properties</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Shape</span> <div class="flex gap-2"><button>⭕ Round</button> <button>⬜ Square</button></div></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="10" max="200" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="50" max="1000" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <div><span class="text-xs text-gray-500 mb-1.5 block">Color</span> <div class="grid grid-cols-5 gap-1.5 mb-2"></div> <div class="flex items-center gap-2"><span class="text-xs text-gray-500">Custom:</span> <input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/></div></div> <!></div>`, 1);
59387
- var root_28 = /* @__PURE__ */ from_html(`<div class="space-y-3"><h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-emerald-100 rounded flex items-center justify-center text-xs">🏷️</span> Text Annotation</h3> <label class="block"><span class="text-xs text-gray-500">Text</span> <input type="text" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Font Size</span> <input type="number" min="8" max="72" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Color</span> <div class="flex items-center gap-2"><input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/> <span class="text-xs text-gray-400"> </span></div></label> <label class="block"><span class="text-xs text-gray-500">Rotation (°)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">X</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Y</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label></div>`);
59388
- var root_29 = /* @__PURE__ */ from_html(`<div class="mt-4 pt-3 border-t border-gray-200"><h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-blue-100 rounded flex items-center justify-center text-xs">🖼️</span> Background Image</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Opacity</span> <input type="range" min="0.05" max="1" step="0.05" class="w-full"/></label> <label class="block"><span class="text-xs text-gray-500">Scale</span> <input type="range" min="0.1" max="5" step="0.05" class="w-full"/></label> <label class="block"><span class="text-xs text-gray-500">Rotation</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <div class="flex gap-2"><button> </button> <button class="flex-1 px-2 py-1.5 border rounded text-sm border-gray-200 hover:bg-gray-50">📏 Set Scale</button></div> <button class="w-full px-2 py-1.5 border border-red-300 rounded text-sm text-red-600 hover:bg-red-50">Remove Image</button></div></div>`);
59424
+ var root_17$1 = /* @__PURE__ */ from_html(`<label class="block pb-3 border-b border-gray-200"><span class="text-xs text-gray-500"> </span> <input type="range" min="0.05" max="1" step="0.05" class="w-full"/></label>`);
59425
+ var root_18$1 = /* @__PURE__ */ from_html(`<option> </option>`);
59426
+ var root_19$1 = /* @__PURE__ */ from_html(`<button></button>`);
59427
+ var root_22$1 = /* @__PURE__ */ from_html(`<button><div class="w-full h-12 rounded-md mb-1 overflow-hidden"></div> <div class="text-center leading-3 text-[10px] text-gray-600 truncate"> </div></button>`);
59428
+ var root_20$1 = /* @__PURE__ */ from_html(`<div><span class="text-xs font-medium text-gray-600 mb-1.5 block"> </span> <div class="grid grid-cols-3 gap-1.5"></div></div>`);
59429
+ var root_16 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-green-100 rounded flex items-center justify-center text-xs">⬜</span> Room Properties</h3> <div class="space-y-3"><!> <label class="block"><span class="text-xs text-gray-500">Room Type</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"></select></label> <label class="block"><span class="text-xs text-gray-500">Room Name</span> <input type="text" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Category</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>🏠 Indoor</option><option>🌳 Outdoor</option><option>🚗 Garage</option><option>🔧 Utility</option></select></label> <div><span class="text-xs text-gray-500">Area</span> <p class="text-sm text-gray-700"> </p></div> <div><span class="text-xs text-gray-500 mb-1.5 block">Room Color</span> <div class="grid grid-cols-5 gap-1.5 mb-2"></div> <div class="flex items-center gap-2"><span class="text-xs text-gray-500">Custom:</span> <input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/></div></div> <div><div class="flex items-center gap-1 mb-2"><span class="text-xs text-gray-500">Floor Material</span> <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-gray-400"><path d="M3 3h18v18H3z"></path><path d="M8 8h8v8H8z"></path></svg></div> <div class="space-y-3"></div></div></div>`, 1);
59430
+ var root_23$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-xs">🪜</span> Stair Properties</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Type</span> <select class="w-full px-2 py-1 border border-gray-200 rounded text-sm"><option>Straight</option><option>L-Shaped</option><option>U-Shaped</option><option>Spiral</option></select></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Risers</span> <input type="number" min="3" max="30" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Direction</span> <div class="flex gap-2"><button>Up ↑</button> <button>Down ↓</button></div></label> <label class="block"><span class="text-xs text-gray-500">Rotation (degrees)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label></div>`, 1);
59431
+ var root_25 = /* @__PURE__ */ from_html(`<button></button>`);
59432
+ var root_26 = /* @__PURE__ */ from_html(`<label class="block"><span class="text-xs text-gray-500">Rotation (degrees)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label>`);
59433
+ var root_24$1 = /* @__PURE__ */ from_html(`<h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-xs">🏛️</span> Column Properties</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Shape</span> <div class="flex gap-2"><button>⭕ Round</button> <button>⬜ Square</button></div></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="10" max="200" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500"> </span> <input type="number" min="50" max="1000" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <div><span class="text-xs text-gray-500 mb-1.5 block">Color</span> <div class="grid grid-cols-5 gap-1.5 mb-2"></div> <div class="flex items-center gap-2"><span class="text-xs text-gray-500">Custom:</span> <input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/></div></div> <!></div>`, 1);
59434
+ var root_27 = /* @__PURE__ */ from_html(`<div class="space-y-3"><h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-emerald-100 rounded flex items-center justify-center text-xs">🏷️</span> Text Annotation</h3> <label class="block"><span class="text-xs text-gray-500">Text</span> <input type="text" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Font Size</span> <input type="number" min="8" max="72" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Color</span> <div class="flex items-center gap-2"><input type="color" class="w-8 h-6 rounded border border-gray-200 cursor-pointer"/> <span class="text-xs text-gray-400"> </span></div></label> <label class="block"><span class="text-xs text-gray-500">Rotation (°)</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">X</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <label class="block"><span class="text-xs text-gray-500">Y</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label></div>`);
59435
+ var root_28 = /* @__PURE__ */ from_html(`<div class="mt-4 pt-3 border-t border-gray-200"><h3 class="text-sm font-semibold text-gray-700 mb-3 flex items-center gap-2"><span class="w-6 h-6 bg-blue-100 rounded flex items-center justify-center text-xs">🖼️</span> Background Image</h3> <div class="space-y-3"><label class="block"><span class="text-xs text-gray-500">Opacity</span> <input type="range" min="0.05" max="1" step="0.05" class="w-full"/></label> <label class="block"><span class="text-xs text-gray-500">Scale</span> <input type="range" min="0.1" max="5" step="0.05" class="w-full"/></label> <label class="block"><span class="text-xs text-gray-500">Rotation</span> <input type="number" class="w-full px-2 py-1 border border-gray-200 rounded text-sm"/></label> <div class="flex gap-2"><button> </button> <button class="flex-1 px-2 py-1.5 border rounded text-sm border-gray-200 hover:bg-gray-50">📏 Set Scale</button></div> <button class="w-full px-2 py-1.5 border border-red-300 rounded text-sm text-red-600 hover:bg-red-50">Remove Image</button></div></div>`);
59389
59436
  var root$3 = /* @__PURE__ */ from_html(`<div data-properties-panel="" style="top: 48px; bottom: 36px;"><!> <!></div>`);
59390
59437
  function PropertiesPanel($$anchor, $$props) {
59391
59438
  push($$props, true);
@@ -59566,10 +59613,6 @@ function PropertiesPanel($$anchor, $$props) {
59566
59613
  if (!get(selectedFurniture)) return;
59567
59614
  updateFurniture(get(selectedFurniture).id, { name: e.target.value });
59568
59615
  }
59569
- function onFurnitureSerial(e) {
59570
- if (!get(selectedFurniture)) return;
59571
- updateFurniture(get(selectedFurniture).id, { serial: e.target.value });
59572
- }
59573
59616
  const useSiteCameraSelect = /* @__PURE__ */ user_derived(() => siteCameras().length > 0);
59574
59617
  const usedCameraSerials = /* @__PURE__ */ user_derived(() => {
59575
59618
  var _$$get13;
@@ -60301,7 +60344,7 @@ function PropertiesPanel($$anchor, $$props) {
60301
60344
  delegated("input", input_13, onWindowSill);
60302
60345
  append($$anchor, fragment_2);
60303
60346
  };
60304
- var consequent_7 = ($$anchor) => {
60347
+ var consequent_6 = ($$anchor) => {
60305
60348
  var fragment_3 = root_10$1();
60306
60349
  var h3 = first_child(fragment_3);
60307
60350
  var span_14 = child(h3);
@@ -60314,13 +60357,16 @@ function PropertiesPanel($$anchor, $$props) {
60314
60357
  reset(h3);
60315
60358
  var div_15 = sibling(h3, 2);
60316
60359
  var node_4 = child(div_15);
60317
- var consequent_6 = ($$anchor) => {
60318
- var fragment_4 = comment();
60319
- var node_5 = first_child(fragment_4);
60320
- var consequent_5 = ($$anchor) => {
60321
- var fragment_5 = root_12$1();
60322
- var label_18 = first_child(fragment_5);
60323
- var select_2 = sibling(child(label_18), 2);
60360
+ var consequent_5 = ($$anchor) => {
60361
+ var fragment_4 = root_11$1();
60362
+ var label_18 = first_child(fragment_4);
60363
+ var input_14 = sibling(child(label_18), 2);
60364
+ remove_input_defaults(input_14);
60365
+ reset(label_18);
60366
+ var node_5 = sibling(label_18, 2);
60367
+ var consequent_4 = ($$anchor) => {
60368
+ var label_19 = root_12$1();
60369
+ var select_2 = sibling(child(label_19), 2);
60324
60370
  var option_11 = child(select_2);
60325
60371
  option_11.value = option_11.__value = "";
60326
60372
  each(sibling(option_11), 17, () => get(selectableSiteCameras), (cam) => cam.serial, ($$anchor, cam) => {
@@ -60339,59 +60385,35 @@ function PropertiesPanel($$anchor, $$props) {
60339
60385
  append($$anchor, option_12);
60340
60386
  });
60341
60387
  reset(select_2);
60342
- var select_2_value;
60343
- init_select(select_2);
60344
- reset(label_18);
60345
- var node_7 = sibling(label_18, 2);
60346
- var consequent_4 = ($$anchor) => {
60347
- var p = root_14$1();
60348
- var span_15 = sibling(child(p));
60349
- var text_19 = child(span_15, true);
60350
- reset(span_15);
60351
- reset(p);
60352
- template_effect(() => set_text(text_19, get(selectedFurniture).serial));
60353
- append($$anchor, p);
60354
- };
60355
- if_block(node_7, ($$render) => {
60356
- if (get(selectedFurniture).serial) $$render(consequent_4);
60357
- });
60358
- template_effect(() => {
60359
- var _$$get$serial3;
60360
- if (select_2_value !== (select_2_value = (_$$get$serial3 = get(selectedFurniture).serial) !== null && _$$get$serial3 !== void 0 ? _$$get$serial3 : "")) {
60361
- var _select_2$__value, _$$get$serial4, _$$get$serial5;
60362
- select_2.value = (_select_2$__value = select_2.__value = (_$$get$serial4 = get(selectedFurniture).serial) !== null && _$$get$serial4 !== void 0 ? _$$get$serial4 : "") !== null && _select_2$__value !== void 0 ? _select_2$__value : "", select_option(select_2, (_$$get$serial5 = get(selectedFurniture).serial) !== null && _$$get$serial5 !== void 0 ? _$$get$serial5 : "");
60363
- }
60364
- });
60388
+ select_2.value = select_2.__value = "";
60389
+ reset(label_19);
60365
60390
  delegated("change", select_2, onSiteCameraSelect);
60366
- append($$anchor, fragment_5);
60391
+ append($$anchor, label_19);
60367
60392
  };
60368
60393
  var alternate_1 = ($$anchor) => {
60369
- var fragment_6 = root_15$1();
60370
- var label_19 = first_child(fragment_6);
60371
- var input_14 = sibling(child(label_19), 2);
60372
- remove_input_defaults(input_14);
60373
- reset(label_19);
60374
- var label_20 = sibling(label_19, 2);
60394
+ var label_20 = root_14$1();
60375
60395
  var input_15 = sibling(child(label_20), 2);
60376
60396
  remove_input_defaults(input_15);
60377
60397
  reset(label_20);
60378
60398
  template_effect(() => {
60379
- var _$$get$name3, _$$get$serial6;
60380
- set_value(input_14, (_$$get$name3 = get(selectedFurniture).name) !== null && _$$get$name3 !== void 0 ? _$$get$name3 : "");
60381
- set_value(input_15, (_$$get$serial6 = get(selectedFurniture).serial) !== null && _$$get$serial6 !== void 0 ? _$$get$serial6 : "");
60399
+ var _$$get$serial3;
60400
+ return set_value(input_15, (_$$get$serial3 = get(selectedFurniture).serial) !== null && _$$get$serial3 !== void 0 ? _$$get$serial3 : "");
60382
60401
  });
60383
- delegated("input", input_14, onFurnitureName);
60384
- delegated("input", input_15, onFurnitureSerial);
60385
- append($$anchor, fragment_6);
60402
+ append($$anchor, label_20);
60386
60403
  };
60387
60404
  if_block(node_5, ($$render) => {
60388
- if (get(useSiteCameraSelect)) $$render(consequent_5);
60405
+ if (get(useSiteCameraSelect) && !get(selectedFurniture).serial) $$render(consequent_4);
60389
60406
  else $$render(alternate_1, -1);
60390
60407
  });
60408
+ template_effect(() => {
60409
+ var _$$get$name3;
60410
+ return set_value(input_14, (_$$get$name3 = get(selectedFurniture).name) !== null && _$$get$name3 !== void 0 ? _$$get$name3 : "");
60411
+ });
60412
+ delegated("input", input_14, onFurnitureName);
60391
60413
  append($$anchor, fragment_4);
60392
60414
  };
60393
60415
  if_block(node_4, ($$render) => {
60394
- if (get(selectedFurniture).catalogId === "camera") $$render(consequent_6);
60416
+ if (get(selectedFurniture).catalogId === "camera") $$render(consequent_5);
60395
60417
  });
60396
60418
  var div_16 = sibling(node_4, 2);
60397
60419
  var div_17 = sibling(child(div_16), 2);
@@ -60407,7 +60429,7 @@ function PropertiesPanel($$anchor, $$props) {
60407
60429
  "#dc143c",
60408
60430
  "#228b22"
60409
60431
  ], index$1, ($$anchor, color) => {
60410
- var button_14 = root_16();
60432
+ var button_14 = root_15$1();
60411
60433
  template_effect(($0) => {
60412
60434
  set_class(button_14, 1, `w-6 h-6 rounded border-2 hover:border-gray-300 transition-colors ${$0 !== null && $0 !== void 0 ? $0 : ""}`);
60413
60435
  set_style(button_14, `background-color: ${color !== null && color !== void 0 ? color : ""}`);
@@ -60426,24 +60448,24 @@ function PropertiesPanel($$anchor, $$props) {
60426
60448
  reset(div_18);
60427
60449
  reset(div_16);
60428
60450
  var label_21 = sibling(div_16, 2);
60429
- var span_16 = child(label_21);
60430
- var text_20 = child(span_16);
60431
- reset(span_16);
60432
- var input_17 = sibling(span_16, 2);
60451
+ var span_15 = child(label_21);
60452
+ var text_19 = child(span_15);
60453
+ reset(span_15);
60454
+ var input_17 = sibling(span_15, 2);
60433
60455
  remove_input_defaults(input_17);
60434
60456
  reset(label_21);
60435
60457
  var label_22 = sibling(label_21, 2);
60436
- var span_17 = child(label_22);
60437
- var text_21 = child(span_17);
60438
- reset(span_17);
60439
- var input_18 = sibling(span_17, 2);
60458
+ var span_16 = child(label_22);
60459
+ var text_20 = child(span_16);
60460
+ reset(span_16);
60461
+ var input_18 = sibling(span_16, 2);
60440
60462
  remove_input_defaults(input_18);
60441
60463
  reset(label_22);
60442
60464
  var label_23 = sibling(label_22, 2);
60443
- var span_18 = child(label_23);
60444
- var text_22 = child(span_18);
60445
- reset(span_18);
60446
- var input_19 = sibling(span_18, 2);
60465
+ var span_17 = child(label_23);
60466
+ var text_21 = child(span_17);
60467
+ reset(span_17);
60468
+ var input_19 = sibling(span_17, 2);
60447
60469
  remove_input_defaults(input_19);
60448
60470
  reset(label_23);
60449
60471
  var label_24 = sibling(label_23, 2);
@@ -60490,11 +60512,11 @@ function PropertiesPanel($$anchor, $$props) {
60490
60512
  set_attribute(button_13, "title", get(selectedFurniture).locked ? "Unlock (Ctrl+L)" : "Lock (Ctrl+L)");
60491
60513
  set_text(text_17, get(selectedFurniture).locked ? "🔒 Locked" : "🔓");
60492
60514
  set_value(input_16, $2);
60493
- set_text(text_20, `Width (${$3 !== null && $3 !== void 0 ? $3 : ""})`);
60515
+ set_text(text_19, `Width (${$3 !== null && $3 !== void 0 ? $3 : ""})`);
60494
60516
  set_value(input_17, $4);
60495
- set_text(text_21, `Depth (${$5 !== null && $5 !== void 0 ? $5 : ""})`);
60517
+ set_text(text_20, `Depth (${$5 !== null && $5 !== void 0 ? $5 : ""})`);
60496
60518
  set_value(input_18, $6);
60497
- set_text(text_22, `Height (${$7 !== null && $7 !== void 0 ? $7 : ""})`);
60519
+ set_text(text_21, `Height (${$7 !== null && $7 !== void 0 ? $7 : ""})`);
60498
60520
  set_value(input_19, $8);
60499
60521
  if (select_3_value !== (select_3_value = (_$$get$material = get(selectedFurniture).material) !== null && _$$get$material !== void 0 ? _$$get$material : "Wood")) {
60500
60522
  var _select_3$__value, _$$get$material2, _$$get$material3;
@@ -60569,38 +60591,38 @@ function PropertiesPanel($$anchor, $$props) {
60569
60591
  delegated("click", button_19, resetFurnitureDefaults);
60570
60592
  append($$anchor, fragment_3);
60571
60593
  };
60572
- var consequent_10 = ($$anchor) => {
60573
- var fragment_7 = root_17$1();
60574
- var div_21 = sibling(first_child(fragment_7), 2);
60575
- var node_8 = child(div_21);
60576
- var consequent_8 = ($$anchor) => {
60577
- var label_26 = root_18$1();
60578
- var span_19 = child(label_26);
60579
- var text_23 = child(span_19);
60580
- reset(span_19);
60581
- var input_21 = sibling(span_19, 2);
60594
+ var consequent_9 = ($$anchor) => {
60595
+ var fragment_5 = root_16();
60596
+ var div_21 = sibling(first_child(fragment_5), 2);
60597
+ var node_7 = child(div_21);
60598
+ var consequent_7 = ($$anchor) => {
60599
+ var label_26 = root_17$1();
60600
+ var span_18 = child(label_26);
60601
+ var text_22 = child(span_18);
60602
+ reset(span_18);
60603
+ var input_21 = sibling(span_18, 2);
60582
60604
  remove_input_defaults(input_21);
60583
60605
  reset(label_26);
60584
60606
  template_effect(($0) => {
60585
- set_text(text_23, `Camera Thumbnail Opacity (${$0 !== null && $0 !== void 0 ? $0 : ""}%)`);
60607
+ set_text(text_22, `Camera Thumbnail Opacity (${$0 !== null && $0 !== void 0 ? $0 : ""}%)`);
60586
60608
  set_value(input_21, get(thumbOpacity));
60587
60609
  }, [() => Math.round(get(thumbOpacity) * 100)]);
60588
60610
  delegated("input", input_21, (e) => updateCameraThumbnailOpacity(Number(e.target.value)));
60589
60611
  append($$anchor, label_26);
60590
60612
  };
60591
- if_block(node_8, ($$render) => {
60592
- if (get(hasCameraThumbnailOverlay)) $$render(consequent_8);
60613
+ if_block(node_7, ($$render) => {
60614
+ if (get(hasCameraThumbnailOverlay)) $$render(consequent_7);
60593
60615
  });
60594
- var label_27 = sibling(node_8, 2);
60616
+ var label_27 = sibling(node_7, 2);
60595
60617
  var select_4 = sibling(child(label_27), 2);
60596
60618
  each(select_4, 21, () => roomTypes, index$1, ($$anchor, rt) => {
60597
- var option_21 = root_19$1();
60598
- var text_24 = child(option_21);
60619
+ var option_21 = root_18$1();
60620
+ var text_23 = child(option_21);
60599
60621
  reset(option_21);
60600
60622
  var option_21_value = {};
60601
60623
  template_effect(() => {
60602
60624
  var _$$get$icon, _$$get$label;
60603
- set_text(text_24, `${(_$$get$icon = get(rt).icon) !== null && _$$get$icon !== void 0 ? _$$get$icon : ""} ${(_$$get$label = get(rt).label) !== null && _$$get$label !== void 0 ? _$$get$label : ""}`);
60625
+ set_text(text_23, `${(_$$get$icon = get(rt).icon) !== null && _$$get$icon !== void 0 ? _$$get$icon : ""} ${(_$$get$label = get(rt).label) !== null && _$$get$label !== void 0 ? _$$get$label : ""}`);
60604
60626
  if (option_21_value !== (option_21_value = get(rt).id)) {
60605
60627
  var _option_21$__value;
60606
60628
  option_21.value = (_option_21$__value = option_21.__value = get(rt).id) !== null && _option_21$__value !== void 0 ? _option_21$__value : "";
@@ -60631,14 +60653,14 @@ function PropertiesPanel($$anchor, $$props) {
60631
60653
  init_select(select_5);
60632
60654
  reset(label_29);
60633
60655
  var div_22 = sibling(label_29, 2);
60634
- var p_1 = sibling(child(div_22), 2);
60635
- var text_25 = child(p_1, true);
60636
- reset(p_1);
60656
+ var p = sibling(child(div_22), 2);
60657
+ var text_24 = child(p, true);
60658
+ reset(p);
60637
60659
  reset(div_22);
60638
60660
  var div_23 = sibling(div_22, 2);
60639
60661
  var div_24 = sibling(child(div_23), 2);
60640
60662
  each(div_24, 21, () => roomColorPresets, index$1, ($$anchor, preset) => {
60641
- var button_20 = root_20$1();
60663
+ var button_20 = root_19$1();
60642
60664
  template_effect(() => {
60643
60665
  var _$$get$color5;
60644
60666
  set_class(button_20, 1, `w-7 h-7 rounded-md border-2 hover:border-gray-300 transition-colors ${get(selectedRoom).color === get(preset).color ? "border-blue-500 ring-1 ring-blue-200" : "border-gray-200"}`);
@@ -60657,43 +60679,43 @@ function PropertiesPanel($$anchor, $$props) {
60657
60679
  var div_26 = sibling(div_23, 2);
60658
60680
  var div_27 = sibling(child(div_26), 2);
60659
60681
  each(div_27, 21, () => textureGroups, index$1, ($$anchor, group) => {
60660
- var div_28 = root_21$1();
60661
- var span_20 = child(div_28);
60662
- var text_26 = child(span_20, true);
60663
- reset(span_20);
60664
- var div_29 = sibling(span_20, 2);
60682
+ var div_28 = root_20$1();
60683
+ var span_19 = child(div_28);
60684
+ var text_25 = child(span_19, true);
60685
+ reset(span_19);
60686
+ var div_29 = sibling(span_19, 2);
60665
60687
  each(div_29, 21, () => get(group).ids, index$1, ($$anchor, matId) => {
60666
60688
  const mat = /* @__PURE__ */ user_derived(() => floorMaterials.find((m) => m.id === get(matId)));
60667
- var fragment_8 = comment();
60668
- var node_9 = first_child(fragment_8);
60669
- var consequent_9 = ($$anchor) => {
60689
+ var fragment_6 = comment();
60690
+ var node_8 = first_child(fragment_6);
60691
+ var consequent_8 = ($$anchor) => {
60670
60692
  const texPath = /* @__PURE__ */ user_derived(() => {
60671
60693
  var _floorTexPaths$$$get$;
60672
60694
  return (_floorTexPaths$$$get$ = floorTexPaths[get(mat).id]) !== null && _floorTexPaths$$$get$ !== void 0 ? _floorTexPaths$$$get$ : "";
60673
60695
  });
60674
- var button_21 = root_23$1();
60696
+ var button_21 = root_22$1();
60675
60697
  var div_30 = child(button_21);
60676
60698
  var div_31 = sibling(div_30, 2);
60677
- var text_27 = child(div_31, true);
60699
+ var text_26 = child(div_31, true);
60678
60700
  reset(div_31);
60679
60701
  reset(button_21);
60680
60702
  template_effect(() => {
60681
60703
  set_class(button_21, 1, `p-1 rounded-lg border-2 hover:border-gray-300 transition-all text-xs ${get(selectedRoom).floorTexture === get(mat).id ? "border-blue-500 ring-2 ring-blue-200 shadow-sm" : "border-gray-200"}`);
60682
60704
  set_attribute(button_21, "title", get(mat).name);
60683
60705
  set_style(div_30, get(texPath) ? `background-image: url(${get(texPath)}); background-size: cover; background-position: center;` : `background-color: ${get(mat).color}`);
60684
- set_text(text_27, get(mat).name);
60706
+ set_text(text_26, get(mat).name);
60685
60707
  });
60686
60708
  delegated("click", button_21, () => onRoomFloor(get(mat).id));
60687
60709
  append($$anchor, button_21);
60688
60710
  };
60689
- if_block(node_9, ($$render) => {
60690
- if (get(mat)) $$render(consequent_9);
60711
+ if_block(node_8, ($$render) => {
60712
+ if (get(mat)) $$render(consequent_8);
60691
60713
  });
60692
- append($$anchor, fragment_8);
60714
+ append($$anchor, fragment_6);
60693
60715
  });
60694
60716
  reset(div_29);
60695
60717
  reset(div_28);
60696
- template_effect(() => set_text(text_26, get(group).label));
60718
+ template_effect(() => set_text(text_25, get(group).label));
60697
60719
  append($$anchor, div_28);
60698
60720
  });
60699
60721
  reset(div_27);
@@ -60710,7 +60732,7 @@ function PropertiesPanel($$anchor, $$props) {
60710
60732
  var _select_5$__value, _$$get$roomType2, _$$get$roomType3;
60711
60733
  select_5.value = (_select_5$__value = select_5.__value = (_$$get$roomType2 = get(selectedRoom).roomType) !== null && _$$get$roomType2 !== void 0 ? _$$get$roomType2 : "indoor") !== null && _select_5$__value !== void 0 ? _select_5$__value : "", select_option(select_5, (_$$get$roomType3 = get(selectedRoom).roomType) !== null && _$$get$roomType3 !== void 0 ? _$$get$roomType3 : "indoor");
60712
60734
  }
60713
- set_text(text_25, $0);
60735
+ set_text(text_24, $0);
60714
60736
  set_value(input_23, (_$$get$color6 = get(selectedRoom).color) !== null && _$$get$color6 !== void 0 ? _$$get$color6 : "#ffffff");
60715
60737
  }, [() => formatArea(get(selectedRoom).area, get(settings).units)]);
60716
60738
  delegated("change", select_4, onRoomType);
@@ -60723,11 +60745,11 @@ function PropertiesPanel($$anchor, $$props) {
60723
60745
  }
60724
60746
  });
60725
60747
  delegated("input", input_23, (e) => onRoomColor(e.target.value));
60726
- append($$anchor, fragment_7);
60748
+ append($$anchor, fragment_5);
60727
60749
  };
60728
- var consequent_11 = ($$anchor) => {
60729
- var fragment_9 = root_24$1();
60730
- var div_32 = sibling(first_child(fragment_9), 2);
60750
+ var consequent_10 = ($$anchor) => {
60751
+ var fragment_7 = root_23$1();
60752
+ var div_32 = sibling(first_child(fragment_7), 2);
60731
60753
  var label_30 = child(div_32);
60732
60754
  var select_6 = sibling(child(label_30), 2);
60733
60755
  var option_26 = child(select_6);
@@ -60743,17 +60765,17 @@ function PropertiesPanel($$anchor, $$props) {
60743
60765
  init_select(select_6);
60744
60766
  reset(label_30);
60745
60767
  var label_31 = sibling(label_30, 2);
60746
- var span_21 = child(label_31);
60747
- var text_28 = child(span_21);
60748
- reset(span_21);
60749
- var input_24 = sibling(span_21, 2);
60768
+ var span_20 = child(label_31);
60769
+ var text_27 = child(span_20);
60770
+ reset(span_20);
60771
+ var input_24 = sibling(span_20, 2);
60750
60772
  remove_input_defaults(input_24);
60751
60773
  reset(label_31);
60752
60774
  var label_32 = sibling(label_31, 2);
60753
- var span_22 = child(label_32);
60754
- var text_29 = child(span_22);
60755
- reset(span_22);
60756
- var input_25 = sibling(span_22, 2);
60775
+ var span_21 = child(label_32);
60776
+ var text_28 = child(span_21);
60777
+ reset(span_21);
60778
+ var input_25 = sibling(span_21, 2);
60757
60779
  remove_input_defaults(input_25);
60758
60780
  reset(label_32);
60759
60781
  var label_33 = sibling(label_32, 2);
@@ -60776,9 +60798,9 @@ function PropertiesPanel($$anchor, $$props) {
60776
60798
  var _select_6$__value;
60777
60799
  select_6.value = (_select_6$__value = select_6.__value = get(selectedStair).stairType || "straight") !== null && _select_6$__value !== void 0 ? _select_6$__value : "", select_option(select_6, get(selectedStair).stairType || "straight");
60778
60800
  }
60779
- set_text(text_28, `Width (${$0 !== null && $0 !== void 0 ? $0 : ""})`);
60801
+ set_text(text_27, `Width (${$0 !== null && $0 !== void 0 ? $0 : ""})`);
60780
60802
  set_value(input_24, $1);
60781
- set_text(text_29, `Depth (${$2 !== null && $2 !== void 0 ? $2 : ""})`);
60803
+ set_text(text_28, `Depth (${$2 !== null && $2 !== void 0 ? $2 : ""})`);
60782
60804
  set_value(input_25, $3);
60783
60805
  set_value(input_26, get(selectedStair).riserCount);
60784
60806
  set_class(button_22, 1, `flex-1 px-2 py-1.5 border rounded text-sm transition-colors ${get(selectedStair).direction === "up" ? "bg-blue-100 border-blue-400 text-blue-700" : "border-gray-200 hover:bg-gray-50"}`);
@@ -60797,11 +60819,11 @@ function PropertiesPanel($$anchor, $$props) {
60797
60819
  delegated("click", button_22, () => updateStair(get(selectedStair).id, { direction: "up" }));
60798
60820
  delegated("click", button_23, () => updateStair(get(selectedStair).id, { direction: "down" }));
60799
60821
  delegated("input", input_27, (e) => updateStair(get(selectedStair).id, { rotation: Number(e.target.value) }));
60800
- append($$anchor, fragment_9);
60822
+ append($$anchor, fragment_7);
60801
60823
  };
60802
- var consequent_13 = ($$anchor) => {
60803
- var fragment_10 = root_25();
60804
- var div_34 = sibling(first_child(fragment_10), 2);
60824
+ var consequent_12 = ($$anchor) => {
60825
+ var fragment_8 = root_24$1();
60826
+ var div_34 = sibling(first_child(fragment_8), 2);
60805
60827
  var label_36 = child(div_34);
60806
60828
  var div_35 = sibling(child(label_36), 2);
60807
60829
  var button_24 = child(div_35);
@@ -60809,23 +60831,23 @@ function PropertiesPanel($$anchor, $$props) {
60809
60831
  reset(div_35);
60810
60832
  reset(label_36);
60811
60833
  var label_37 = sibling(label_36, 2);
60812
- var span_23 = child(label_37);
60813
- var text_30 = child(span_23);
60814
- reset(span_23);
60815
- var input_28 = sibling(span_23, 2);
60834
+ var span_22 = child(label_37);
60835
+ var text_29 = child(span_22);
60836
+ reset(span_22);
60837
+ var input_28 = sibling(span_22, 2);
60816
60838
  remove_input_defaults(input_28);
60817
60839
  reset(label_37);
60818
60840
  var label_38 = sibling(label_37, 2);
60819
- var span_24 = child(label_38);
60820
- var text_31 = child(span_24);
60821
- reset(span_24);
60822
- var input_29 = sibling(span_24, 2);
60841
+ var span_23 = child(label_38);
60842
+ var text_30 = child(span_23);
60843
+ reset(span_23);
60844
+ var input_29 = sibling(span_23, 2);
60823
60845
  remove_input_defaults(input_29);
60824
60846
  reset(label_38);
60825
60847
  var div_36 = sibling(label_38, 2);
60826
60848
  var div_37 = sibling(child(div_36), 2);
60827
60849
  each(div_37, 21, () => columnColorPresets, index$1, ($$anchor, preset) => {
60828
- var button_26 = root_26();
60850
+ var button_26 = root_25();
60829
60851
  template_effect(() => {
60830
60852
  var _$$get$color7;
60831
60853
  set_class(button_26, 1, `w-7 h-7 rounded-md border-2 hover:border-gray-300 transition-colors ${get(selectedColumn).color === get(preset).color ? "border-blue-500 ring-1 ring-blue-200" : "border-gray-200"}`);
@@ -60841,9 +60863,9 @@ function PropertiesPanel($$anchor, $$props) {
60841
60863
  remove_input_defaults(input_30);
60842
60864
  reset(div_38);
60843
60865
  reset(div_36);
60844
- var node_10 = sibling(div_36, 2);
60845
- var consequent_12 = ($$anchor) => {
60846
- var label_39 = root_27();
60866
+ var node_9 = sibling(div_36, 2);
60867
+ var consequent_11 = ($$anchor) => {
60868
+ var label_39 = root_26();
60847
60869
  var input_31 = sibling(child(label_39), 2);
60848
60870
  remove_input_defaults(input_31);
60849
60871
  reset(label_39);
@@ -60851,16 +60873,16 @@ function PropertiesPanel($$anchor, $$props) {
60851
60873
  delegated("input", input_31, (e) => updateColumn(get(selectedColumn).id, { rotation: Number(e.target.value) }));
60852
60874
  append($$anchor, label_39);
60853
60875
  };
60854
- if_block(node_10, ($$render) => {
60855
- if (get(selectedColumn).shape === "square") $$render(consequent_12);
60876
+ if_block(node_9, ($$render) => {
60877
+ if (get(selectedColumn).shape === "square") $$render(consequent_11);
60856
60878
  });
60857
60879
  reset(div_34);
60858
60880
  template_effect(($0, $1, $2, $3) => {
60859
60881
  set_class(button_24, 1, `flex-1 px-2 py-1.5 border rounded text-sm transition-colors ${get(selectedColumn).shape === "round" ? "bg-blue-100 border-blue-400 text-blue-700" : "border-gray-200 hover:bg-gray-50"}`);
60860
60882
  set_class(button_25, 1, `flex-1 px-2 py-1.5 border rounded text-sm transition-colors ${get(selectedColumn).shape === "square" ? "bg-blue-100 border-blue-400 text-blue-700" : "border-gray-200 hover:bg-gray-50"}`);
60861
- set_text(text_30, `${get(selectedColumn).shape === "round" ? "Diameter" : "Side Length"} (${$0 !== null && $0 !== void 0 ? $0 : ""})`);
60883
+ set_text(text_29, `${get(selectedColumn).shape === "round" ? "Diameter" : "Side Length"} (${$0 !== null && $0 !== void 0 ? $0 : ""})`);
60862
60884
  set_value(input_28, $1);
60863
- set_text(text_31, `Height (${$2 !== null && $2 !== void 0 ? $2 : ""})`);
60885
+ set_text(text_30, `Height (${$2 !== null && $2 !== void 0 ? $2 : ""})`);
60864
60886
  set_value(input_29, $3);
60865
60887
  set_value(input_30, get(selectedColumn).color);
60866
60888
  }, [
@@ -60874,10 +60896,10 @@ function PropertiesPanel($$anchor, $$props) {
60874
60896
  delegated("input", input_28, (e) => updateColumn(get(selectedColumn).id, { diameter: inputToCm(Number(e.target.value)) }));
60875
60897
  delegated("input", input_29, (e) => updateColumn(get(selectedColumn).id, { height: inputToCm(Number(e.target.value)) }));
60876
60898
  delegated("input", input_30, (e) => updateColumn(get(selectedColumn).id, { color: e.target.value }));
60877
- append($$anchor, fragment_10);
60899
+ append($$anchor, fragment_8);
60878
60900
  };
60879
- var consequent_14 = ($$anchor) => {
60880
- var div_39 = root_28();
60901
+ var consequent_13 = ($$anchor) => {
60902
+ var div_39 = root_27();
60881
60903
  var label_40 = sibling(child(div_39), 2);
60882
60904
  var input_32 = sibling(child(label_40), 2);
60883
60905
  remove_input_defaults(input_32);
@@ -60890,9 +60912,9 @@ function PropertiesPanel($$anchor, $$props) {
60890
60912
  var div_40 = sibling(child(label_42), 2);
60891
60913
  var input_34 = child(div_40);
60892
60914
  remove_input_defaults(input_34);
60893
- var span_25 = sibling(input_34, 2);
60894
- var text_32 = child(span_25, true);
60895
- reset(span_25);
60915
+ var span_24 = sibling(input_34, 2);
60916
+ var text_31 = child(span_24, true);
60917
+ reset(span_24);
60896
60918
  reset(div_40);
60897
60919
  reset(label_42);
60898
60920
  var label_43 = sibling(label_42, 2);
@@ -60912,7 +60934,7 @@ function PropertiesPanel($$anchor, $$props) {
60912
60934
  set_value(input_32, get(selectedTextAnnotation).text);
60913
60935
  set_value(input_33, get(selectedTextAnnotation).fontSize);
60914
60936
  set_value(input_34, get(selectedTextAnnotation).color);
60915
- set_text(text_32, get(selectedTextAnnotation).color);
60937
+ set_text(text_31, get(selectedTextAnnotation).color);
60916
60938
  set_value(input_35, get(selectedTextAnnotation).rotation);
60917
60939
  set_value(input_36, $0);
60918
60940
  set_value(input_37, $1);
@@ -60929,15 +60951,15 @@ function PropertiesPanel($$anchor, $$props) {
60929
60951
  if (get(selectedWall)) $$render(consequent_1);
60930
60952
  else if (get(selectedDoor)) $$render(consequent_2, 1);
60931
60953
  else if (get(selectedWindow)) $$render(consequent_3, 2);
60932
- else if (get(selectedFurniture)) $$render(consequent_7, 3);
60933
- else if (get(selectedRoom)) $$render(consequent_10, 4);
60934
- else if (get(selectedStair)) $$render(consequent_11, 5);
60935
- else if (get(selectedColumn)) $$render(consequent_13, 6);
60936
- else if (get(selectedTextAnnotation)) $$render(consequent_14, 7);
60954
+ else if (get(selectedFurniture)) $$render(consequent_6, 3);
60955
+ else if (get(selectedRoom)) $$render(consequent_9, 4);
60956
+ else if (get(selectedStair)) $$render(consequent_10, 5);
60957
+ else if (get(selectedColumn)) $$render(consequent_12, 6);
60958
+ else if (get(selectedTextAnnotation)) $$render(consequent_13, 7);
60937
60959
  });
60938
- var node_11 = sibling(node, 2);
60939
- var consequent_15 = ($$anchor) => {
60940
- var div_41 = root_29();
60960
+ var node_10 = sibling(node, 2);
60961
+ var consequent_14 = ($$anchor) => {
60962
+ var div_41 = root_28();
60941
60963
  var div_42 = sibling(child(div_41), 2);
60942
60964
  var label_46 = child(div_42);
60943
60965
  var input_38 = sibling(child(label_46), 2);
@@ -60953,7 +60975,7 @@ function PropertiesPanel($$anchor, $$props) {
60953
60975
  reset(label_48);
60954
60976
  var div_43 = sibling(label_48, 2);
60955
60977
  var button_27 = child(div_43);
60956
- var text_33 = child(button_27, true);
60978
+ var text_32 = child(button_27, true);
60957
60979
  reset(button_27);
60958
60980
  var button_28 = sibling(button_27, 2);
60959
60981
  reset(div_43);
@@ -60965,7 +60987,7 @@ function PropertiesPanel($$anchor, $$props) {
60965
60987
  set_value(input_39, get(floor).backgroundImage.scale);
60966
60988
  set_value(input_40, get(floor).backgroundImage.rotation);
60967
60989
  set_class(button_27, 1, `flex-1 px-2 py-1.5 border rounded text-sm ${get(floor).backgroundImage.locked ? "bg-amber-100 border-amber-400 text-amber-700" : "border-gray-200 hover:bg-gray-50"}`);
60968
- set_text(text_33, get(floor).backgroundImage.locked ? "🔒 Locked" : "🔓 Unlocked");
60990
+ set_text(text_32, get(floor).backgroundImage.locked ? "🔒 Locked" : "🔓 Unlocked");
60969
60991
  });
60970
60992
  delegated("input", input_38, (e) => updateBackgroundImage({ opacity: Number(e.target.value) }));
60971
60993
  delegated("input", input_39, (e) => updateBackgroundImage({ scale: Number(e.target.value) }));
@@ -60978,9 +61000,9 @@ function PropertiesPanel($$anchor, $$props) {
60978
61000
  delegated("click", button_29, () => setBackgroundImage(void 0));
60979
61001
  append($$anchor, div_41);
60980
61002
  };
60981
- if_block(node_11, ($$render) => {
61003
+ if_block(node_10, ($$render) => {
60982
61004
  var _$$get18;
60983
- if (get(hasBgImage) && ((_$$get18 = get(floor)) === null || _$$get18 === void 0 ? void 0 : _$$get18.backgroundImage)) $$render(consequent_15);
61005
+ if (get(hasBgImage) && ((_$$get18 = get(floor)) === null || _$$get18 === void 0 ? void 0 : _$$get18.backgroundImage)) $$render(consequent_14);
60984
61006
  });
60985
61007
  reset(div);
60986
61008
  template_effect(() => classes = set_class(div, 1, `${is3D() ? "w-80" : "w-64"} shrink-0 bg-white border-l border-gray-200 flex flex-col overflow-y-auto p-3 fixed right-0 z-40 shadow-lg`, null, classes, { hidden: !get(hasSelection) }));
@@ -69742,6 +69764,112 @@ function OnboardingTooltip($$anchor, $$props) {
69742
69764
  }
69743
69765
  delegate(["click"]);
69744
69766
  //#endregion
69767
+ //#region src/lib/stores/assignedCamerasSync.ts
69768
+ var CAMERA_SPACING = 40;
69769
+ var CAMERA_HIT = 28;
69770
+ /** Avoid spamming host with the same rejection. */
69771
+ var lastRejectedKey = "";
69772
+ function getCameraFurniture(floor) {
69773
+ return floor.furniture.filter((f) => f.catalogId === "camera");
69774
+ }
69775
+ function positionsOverlap(a, b, minDist = CAMERA_HIT) {
69776
+ return Math.hypot(a.x - b.x, a.y - b.y) < minDist;
69777
+ }
69778
+ function getFloorCenter(floor) {
69779
+ const bounds = getFloorBounds(floor, { includeWallThickness: false });
69780
+ if (!bounds) return null;
69781
+ return {
69782
+ x: (bounds.minX + bounds.maxX) / 2,
69783
+ y: (bounds.minY + bounds.maxY) / 2
69784
+ };
69785
+ }
69786
+ function findOpenCameraPosition(floor, preferred) {
69787
+ const occupied = getCameraFurniture(floor).map((c) => c.position);
69788
+ if (!occupied.some((p) => positionsOverlap(preferred, p))) return preferred;
69789
+ for (let ring = 1; ring <= 24; ring++) {
69790
+ const steps = ring * 6;
69791
+ for (let i = 0; i < steps; i++) {
69792
+ const angle = i / steps * Math.PI * 2;
69793
+ const candidate = {
69794
+ x: preferred.x + Math.cos(angle) * CAMERA_SPACING * ring,
69795
+ y: preferred.y + Math.sin(angle) * CAMERA_SPACING * ring
69796
+ };
69797
+ if (!occupied.some((p) => positionsOverlap(candidate, p))) return candidate;
69798
+ }
69799
+ }
69800
+ return {
69801
+ x: preferred.x + CAMERA_SPACING * 25,
69802
+ y: preferred.y
69803
+ };
69804
+ }
69805
+ /**
69806
+ * Sync host `assignedCameras` onto the active floor.
69807
+ * - Adds missing serials at floor center (non-overlapping)
69808
+ * - Updates names for existing serials
69809
+ * - Removes cameras whose serial is no longer assigned
69810
+ * - If floor has no walls, rejects adds and emits camerasRejected
69811
+ */
69812
+ function syncAssignedCameras(assigned) {
69813
+ var _floor$walls$length, _floor$walls;
69814
+ const floor = get$1(activeFloor);
69815
+ const project = get$1(currentProject);
69816
+ if (!floor || !project) return;
69817
+ const normalized = assigned.filter((c) => c && typeof c.serial === "string" && c.serial.trim());
69818
+ const assignedBySerial = new Map(normalized.map((c) => [c.serial.trim(), c]));
69819
+ const existing = getCameraFurniture(floor);
69820
+ const existingBySerial = /* @__PURE__ */ new Map();
69821
+ for (const item of existing) if (item.serial) existingBySerial.set(item.serial, item);
69822
+ const toAdd = normalized.filter((c) => !existingBySerial.has(c.serial.trim()));
69823
+ const hasFloorLayout = ((_floor$walls$length = (_floor$walls = floor.walls) === null || _floor$walls === void 0 ? void 0 : _floor$walls.length) !== null && _floor$walls$length !== void 0 ? _floor$walls$length : 0) > 0;
69824
+ function rejectNoFloor(cameras) {
69825
+ if (cameras.length === 0) return;
69826
+ const key = cameras.map((c) => c.serial.trim()).sort().join(",");
69827
+ if (key === lastRejectedKey) return;
69828
+ lastRejectedKey = key;
69829
+ emitFloorCallback("camerasRejected", {
69830
+ reason: "no-floor",
69831
+ cameras: cameras.map((c) => ({
69832
+ serial: c.serial,
69833
+ name: c.name
69834
+ }))
69835
+ });
69836
+ }
69837
+ if (toAdd.length > 0 && !hasFloorLayout) rejectNoFloor(toAdd);
69838
+ setAssignedCamerasSyncing(true);
69839
+ try {
69840
+ for (const item of existing) {
69841
+ if (!item.serial) continue;
69842
+ if (!assignedBySerial.has(item.serial)) removeFurniture(item.id);
69843
+ }
69844
+ const floorAfterRemove = get$1(activeFloor);
69845
+ if (!floorAfterRemove) return;
69846
+ for (const item of getCameraFurniture(floorAfterRemove)) {
69847
+ if (!item.serial) continue;
69848
+ const assignedCam = assignedBySerial.get(item.serial);
69849
+ if (assignedCam && assignedCam.name !== item.name) updateFurniture(item.id, { name: assignedCam.name });
69850
+ }
69851
+ if (!hasFloorLayout) return;
69852
+ const center = getFloorCenter(floorAfterRemove);
69853
+ if (!center) {
69854
+ rejectNoFloor(toAdd);
69855
+ return;
69856
+ }
69857
+ lastRejectedKey = "";
69858
+ let workingFloor = get$1(activeFloor);
69859
+ for (const cam of toAdd) {
69860
+ const serial = cam.serial.trim();
69861
+ if (getCameraFurniture(workingFloor).some((f) => f.serial === serial)) continue;
69862
+ updateFurniture(addFurniture("camera", findOpenCameraPosition(workingFloor, center)), {
69863
+ serial,
69864
+ name: cam.name
69865
+ });
69866
+ workingFloor = get$1(activeFloor);
69867
+ }
69868
+ } finally {
69869
+ setAssignedCamerasSyncing(false);
69870
+ }
69871
+ }
69872
+ //#endregion
69745
69873
  //#region src/App.svelte
69746
69874
  init_client();
69747
69875
  init_index_client();
@@ -69754,11 +69882,29 @@ function App($$anchor, $$props) {
69754
69882
  let showLayers = /* @__PURE__ */ state(false);
69755
69883
  let floorData = /* @__PURE__ */ state(null);
69756
69884
  let config = /* @__PURE__ */ state(proxy({ ...DEFAULT_CONFIG }));
69885
+ let activeFloorId = /* @__PURE__ */ state(null);
69886
+ let activeFloorWallCount = /* @__PURE__ */ state(0);
69757
69887
  (_$$props$stores = $$props.stores) === null || _$$props$stores === void 0 || _$$props$stores.floorData.subscribe((v) => set(floorData, v, true));
69758
69888
  (_$$props$stores2 = $$props.stores) === null || _$$props$stores2 === void 0 || _$$props$stores2.config.subscribe((v) => set(config, normalizeConfig(v), true));
69889
+ activeFloor.subscribe((f) => {
69890
+ var _f$id, _f$walls$length, _f$walls;
69891
+ set(activeFloorId, (_f$id = f === null || f === void 0 ? void 0 : f.id) !== null && _f$id !== void 0 ? _f$id : null, true);
69892
+ set(activeFloorWallCount, (_f$walls$length = f === null || f === void 0 || (_f$walls = f.walls) === null || _f$walls === void 0 ? void 0 : _f$walls.length) !== null && _f$walls$length !== void 0 ? _f$walls$length : 0, true);
69893
+ });
69894
+ user_effect(() => {
69895
+ setFloorCallbackDispatcher($$props.onDispatch ? (eventName, detail) => $$props.onDispatch(eventName, detail) : null);
69896
+ return () => setFloorCallbackDispatcher(null);
69897
+ });
69759
69898
  user_effect(() => {
69760
69899
  if (get(config).cameraThumbnailOpacity != null) cameraThumbnailOpacity.set(get(config).cameraThumbnailOpacity);
69761
69900
  });
69901
+ user_effect(() => {
69902
+ var _$$get$assignedCamera;
69903
+ const assigned = (_$$get$assignedCamera = get(config).assignedCameras) !== null && _$$get$assignedCamera !== void 0 ? _$$get$assignedCamera : [];
69904
+ get(activeFloorId);
69905
+ get(activeFloorWallCount);
69906
+ syncAssignedCameras(assigned);
69907
+ });
69762
69908
  let commandPaletteOpen = /* @__PURE__ */ state(false);
69763
69909
  let printOpen = /* @__PURE__ */ state(false);
69764
69910
  let mode = /* @__PURE__ */ state("2d");