floor-editor-ts 1.3.7 → 1.3.8

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.
@@ -7091,6 +7091,108 @@ var localStore = {
7091
7091
  }
7092
7092
  };
7093
7093
  //#endregion
7094
+ //#region src/lib/utils/heatmapColorScale.ts
7095
+ function normalizeHeatmapColorScale(value) {
7096
+ if (!value || typeof value !== "object") return void 0;
7097
+ const raw = value;
7098
+ const mode = raw.mode === "levels" ? "levels" : raw.mode === "gradient" ? "gradient" : void 0;
7099
+ if (!mode) return void 0;
7100
+ const hideBelow = typeof raw.hideBelow === "number" && Number.isFinite(raw.hideBelow) ? raw.hideBelow : 0;
7101
+ const levelsIn = Array.isArray(raw.levels) ? raw.levels : [];
7102
+ const levels = [];
7103
+ for (const item of levelsIn) {
7104
+ if (!item || typeof item !== "object") continue;
7105
+ const row = item;
7106
+ const min = typeof row.min === "number" && Number.isFinite(row.min) ? row.min : NaN;
7107
+ const color = typeof row.color === "string" && row.color.trim() ? row.color.trim() : "";
7108
+ if (!Number.isFinite(min) || !color) continue;
7109
+ const level = {
7110
+ min,
7111
+ color
7112
+ };
7113
+ if (typeof row.max === "number" && Number.isFinite(row.max)) level.max = row.max;
7114
+ if (typeof row.label === "string" && row.label.trim()) level.label = row.label.trim();
7115
+ levels.push(level);
7116
+ }
7117
+ levels.sort((a, b) => a.min - b.min);
7118
+ if (mode === "levels" && levels.length === 0) return {
7119
+ mode: "gradient",
7120
+ hideBelow
7121
+ };
7122
+ return {
7123
+ mode,
7124
+ hideBelow,
7125
+ ...levels.length ? { levels } : {}
7126
+ };
7127
+ }
7128
+ /** Fingerprint for heatmap offscreen cache invalidation. */
7129
+ function getHeatmapColorScaleKey(scale) {
7130
+ var _scale$hideBelow, _scale$levels;
7131
+ if (!scale) return "gradient";
7132
+ const hide = (_scale$hideBelow = scale.hideBelow) !== null && _scale$hideBelow !== void 0 ? _scale$hideBelow : 0;
7133
+ if (scale.mode !== "levels" || !((_scale$levels = scale.levels) === null || _scale$levels === void 0 ? void 0 : _scale$levels.length)) return `gradient:${hide}`;
7134
+ return `levels:${hide}:${scale.levels.map((l) => {
7135
+ var _l$max, _l$label;
7136
+ return `${l.min}:${(_l$max = l.max) !== null && _l$max !== void 0 ? _l$max : ""}:${l.color}:${(_l$label = l.label) !== null && _l$label !== void 0 ? _l$label : ""}`;
7137
+ }).join("|")}`;
7138
+ }
7139
+ function colorWithAlpha(color, alpha) {
7140
+ const a = Math.max(0, Math.min(1, alpha));
7141
+ const c = color.trim();
7142
+ const rgbaMatch = c.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*[\d.]+\s*)?\)$/i);
7143
+ if (rgbaMatch) return `rgba(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]}, ${a})`;
7144
+ let hex = c;
7145
+ const short = hex.match(/^#([0-9a-f]{3})$/i);
7146
+ if (short) {
7147
+ const h = short[1];
7148
+ hex = `#${h[0]}${h[0]}${h[1]}${h[1]}${h[2]}${h[2]}`;
7149
+ }
7150
+ const long = hex.match(/^#([0-9a-f]{6})$/i);
7151
+ if (long) {
7152
+ const n = parseInt(long[1], 16);
7153
+ return `rgba(${n >> 16 & 255}, ${n >> 8 & 255}, ${n & 255}, ${a})`;
7154
+ }
7155
+ const longA = hex.match(/^#([0-9a-f]{8})$/i);
7156
+ if (longA) {
7157
+ const n = parseInt(longA[1], 16);
7158
+ return `rgba(${n >> 24 & 255}, ${n >> 16 & 255}, ${n >> 8 & 255}, ${a})`;
7159
+ }
7160
+ return c;
7161
+ }
7162
+ /**
7163
+ * Resolve discrete band color for a cell value.
7164
+ * @returns null → do not draw
7165
+ */
7166
+ function resolveHeatmapLevelColor(value, scale) {
7167
+ var _scale$hideBelow2, _scale$levels2;
7168
+ if (!(value > ((_scale$hideBelow2 = scale.hideBelow) !== null && _scale$hideBelow2 !== void 0 ? _scale$hideBelow2 : 0))) return null;
7169
+ const levels = (_scale$levels2 = scale.levels) !== null && _scale$levels2 !== void 0 ? _scale$levels2 : [];
7170
+ if (!levels.length) return null;
7171
+ const sorted = [...levels].sort((a, b) => a.min - b.min);
7172
+ const levelCount = sorted.length;
7173
+ if (sorted.every((l) => typeof l.max === "number" && Number.isFinite(l.max))) {
7174
+ const idx = sorted.findIndex((l) => value >= l.min && value <= l.max);
7175
+ if (idx < 0) return null;
7176
+ return {
7177
+ color: sorted[idx].color,
7178
+ levelIndex: idx,
7179
+ levelCount
7180
+ };
7181
+ }
7182
+ for (let i = 0; i < sorted.length; i++) {
7183
+ const upper = i + 1 < sorted.length ? sorted[i + 1].min : Infinity;
7184
+ if (value >= sorted[i].min && value < upper) return {
7185
+ color: sorted[i].color,
7186
+ levelIndex: i,
7187
+ levelCount
7188
+ };
7189
+ }
7190
+ return null;
7191
+ }
7192
+ function isLevelsColorScale(scale) {
7193
+ return !!scale && scale.mode === "levels" && Array.isArray(scale.levels) && scale.levels.length > 0;
7194
+ }
7195
+ //#endregion
7094
7196
  //#region src/lib/packageDefaults.ts
7095
7197
  /** Flatten host camera object into string props for furniture + UI. */
7096
7198
  function assignedCameraToProps(cam) {
@@ -7110,6 +7212,7 @@ var DEFAULT_CONFIG = {
7110
7212
  floorMaxHeight: 400,
7111
7213
  heatmapEnabled: false,
7112
7214
  heatmapMatrix: [],
7215
+ heatmapColorScale: void 0,
7113
7216
  projectName: void 0,
7114
7217
  selectedCameraSerial: null,
7115
7218
  showCameraCones: false,
@@ -7140,6 +7243,7 @@ function normalizeConfig(value) {
7140
7243
  const canvasBackground = normalizeColor$1(value.canvasBackground, DEFAULT_CONFIG.canvasBackground);
7141
7244
  const floorPlateBackground = normalizeColor$1(value.floorPlateBackground, DEFAULT_CONFIG.floorPlateBackground);
7142
7245
  const headerToolsMode = value.headerToolsMode === "compact" || value.headerToolsMode === "auto" || value.headerToolsMode === "full" ? value.headerToolsMode : DEFAULT_CONFIG.headerToolsMode;
7246
+ const heatmapColorScale = normalizeHeatmapColorScale(value.heatmapColorScale);
7143
7247
  return {
7144
7248
  ...DEFAULT_CONFIG,
7145
7249
  ...value,
@@ -7149,7 +7253,8 @@ function normalizeConfig(value) {
7149
7253
  cameraThumbnailOpacity: opacity,
7150
7254
  canvasBackground,
7151
7255
  floorPlateBackground,
7152
- headerToolsMode
7256
+ headerToolsMode,
7257
+ heatmapColorScale
7153
7258
  };
7154
7259
  }
7155
7260
  function normalizeColor$1(value, fallback) {
@@ -64745,14 +64850,39 @@ function getMatrixKey(matrix) {
64745
64850
  const step = Math.max(1, Math.floor(flat.length / 20));
64746
64851
  return flat.filter((_, i) => i % step === 0).join(",");
64747
64852
  }
64748
- function drawFloorHeatmap(cs, floor, heatmapMatrix, detectedRooms) {
64853
+ function paintHeatmapBlob(blobCtx, px, py, radius, centerColor, midColor, edgeColor, fadeColor) {
64854
+ const gradient = blobCtx.createRadialGradient(px, py, 0, px, py, radius);
64855
+ gradient.addColorStop(0, centerColor);
64856
+ gradient.addColorStop(.2, midColor);
64857
+ gradient.addColorStop(.5, edgeColor);
64858
+ gradient.addColorStop(1, fadeColor);
64859
+ blobCtx.fillStyle = gradient;
64860
+ blobCtx.beginPath();
64861
+ blobCtx.arc(px, py, radius, 0, Math.PI * 2);
64862
+ blobCtx.fill();
64863
+ }
64864
+ function drawFloorHeatmap(cs, floor, heatmapMatrix, detectedRooms, colorScale) {
64749
64865
  var _heatmapMatrix$;
64750
64866
  const { ctx } = cs;
64751
64867
  const rows = heatmapMatrix.length;
64752
64868
  const cols = ((_heatmapMatrix$ = heatmapMatrix[0]) === null || _heatmapMatrix$ === void 0 ? void 0 : _heatmapMatrix$.length) || 0;
64753
64869
  if (rows === 0 || cols === 0) return;
64870
+ const useLevels = isLevelsColorScale(colorScale);
64754
64871
  const maxValue = heatmapMatrix.reduce((max, row) => row.reduce((m, v) => v > m ? v : m, max), 0);
64755
- if (maxValue <= 0) return;
64872
+ if (!useLevels && maxValue <= 0) return;
64873
+ if (useLevels) {
64874
+ var _colorScale$hideBelow;
64875
+ const hide = (_colorScale$hideBelow = colorScale.hideBelow) !== null && _colorScale$hideBelow !== void 0 ? _colorScale$hideBelow : 0;
64876
+ let anyVisible = false;
64877
+ outer: for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) {
64878
+ const v = heatmapMatrix[y][x];
64879
+ if (v > hide && resolveHeatmapLevelColor(v, colorScale)) {
64880
+ anyVisible = true;
64881
+ break outer;
64882
+ }
64883
+ }
64884
+ if (!anyVisible) return;
64885
+ }
64756
64886
  const bounds = getFloorBounds(floor);
64757
64887
  if (!bounds) return;
64758
64888
  const { minX, minY, maxX, maxY } = bounds;
@@ -64760,8 +64890,9 @@ function drawFloorHeatmap(cs, floor, heatmapMatrix, detectedRooms) {
64760
64890
  const boxH = bounds.height;
64761
64891
  if (boxW <= 0 || boxH <= 0) return;
64762
64892
  const matrixKey = getMatrixKey(heatmapMatrix);
64893
+ const scaleKey = getHeatmapColorScaleKey(colorScale);
64763
64894
  const floorId = floor.id;
64764
- const needsRedraw = !heatmapCache || heatmapCache.matrixKey !== matrixKey || heatmapCache.floorId !== floorId;
64895
+ const needsRedraw = !heatmapCache || heatmapCache.matrixKey !== matrixKey || heatmapCache.scaleKey !== scaleKey || heatmapCache.floorId !== floorId;
64765
64896
  const OFFSCREEN_W = 512;
64766
64897
  const OFFSCREEN_H = 512;
64767
64898
  if (needsRedraw) {
@@ -64776,19 +64907,18 @@ function drawFloorHeatmap(cs, floor, heatmapMatrix, detectedRooms) {
64776
64907
  for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) {
64777
64908
  const value = heatmapMatrix[y][x];
64778
64909
  if (!value || value <= 0) continue;
64779
- const intensity = Math.min(value / maxValue, 1);
64780
64910
  const px = (x + .5) * offCellW;
64781
64911
  const py = (y + .5) * offCellH;
64782
- const alpha = .5 + intensity * .45;
64783
- const gradient = blobCtx.createRadialGradient(px, py, 0, px, py, radius);
64784
- gradient.addColorStop(0, getHeatmapColor(intensity, alpha));
64785
- gradient.addColorStop(.2, getHeatmapColor(intensity, alpha * .75));
64786
- gradient.addColorStop(.5, getHeatmapColor(intensity, alpha * .25));
64787
- gradient.addColorStop(1, getHeatmapColor(intensity, 0));
64788
- blobCtx.fillStyle = gradient;
64789
- blobCtx.beginPath();
64790
- blobCtx.arc(px, py, radius, 0, Math.PI * 2);
64791
- blobCtx.fill();
64912
+ if (useLevels) {
64913
+ const hit = resolveHeatmapLevelColor(value, colorScale);
64914
+ if (!hit) continue;
64915
+ const alpha = .55 + (hit.levelCount <= 1 ? 1 : hit.levelIndex / (hit.levelCount - 1)) * .4;
64916
+ paintHeatmapBlob(blobCtx, px, py, radius, colorWithAlpha(hit.color, alpha), colorWithAlpha(hit.color, alpha * .75), colorWithAlpha(hit.color, alpha * .25), colorWithAlpha(hit.color, 0));
64917
+ } else {
64918
+ const intensity = Math.min(value / maxValue, 1);
64919
+ const alpha = .5 + intensity * .45;
64920
+ paintHeatmapBlob(blobCtx, px, py, radius, getHeatmapColor(intensity, alpha), getHeatmapColor(intensity, alpha * .75), getHeatmapColor(intensity, alpha * .25), getHeatmapColor(intensity, 0));
64921
+ }
64792
64922
  }
64793
64923
  const finalCanvas = document.createElement("canvas");
64794
64924
  finalCanvas.width = OFFSCREEN_W;
@@ -64813,6 +64943,7 @@ function drawFloorHeatmap(cs, floor, heatmapMatrix, detectedRooms) {
64813
64943
  heatmapCache = {
64814
64944
  canvas: finalCanvas,
64815
64945
  matrixKey,
64946
+ scaleKey,
64816
64947
  floorId
64817
64948
  };
64818
64949
  }
@@ -65118,7 +65249,7 @@ function FloorPlanCanvas($$anchor, $$props) {
65118
65249
  const $panMode = () => store_get(panMode, "$panMode", $$stores);
65119
65250
  const $projectSettings = () => store_get(projectSettings, "$projectSettings", $$stores);
65120
65251
  const [$$stores, $$cleanup] = setup_stores();
65121
- let selectedCameraSerial = prop($$props, "selectedCameraSerial", 3, null), showCameraCones = prop($$props, "showCameraCones", 3, false), showCameraLabels = prop($$props, "showCameraLabels", 3, true), cameraHeatmapMatrix = prop($$props, "cameraHeatmapMatrix", 19, () => []), cameraThumbnail = prop($$props, "cameraThumbnail", 3, ""), canvasBackground = prop($$props, "canvasBackground", 3, "#2E353F"), floorPlateBackground = prop($$props, "floorPlateBackground", 3, "#ffffff");
65252
+ let heatmapColorScale = prop($$props, "heatmapColorScale", 3, void 0), selectedCameraSerial = prop($$props, "selectedCameraSerial", 3, null), showCameraCones = prop($$props, "showCameraCones", 3, false), showCameraLabels = prop($$props, "showCameraLabels", 3, true), cameraHeatmapMatrix = prop($$props, "cameraHeatmapMatrix", 19, () => []), cameraThumbnail = prop($$props, "cameraThumbnail", 3, ""), canvasBackground = prop($$props, "canvasBackground", 3, "#2E353F"), floorPlateBackground = prop($$props, "floorPlateBackground", 3, "#ffffff");
65122
65253
  let canvas;
65123
65254
  let ctx;
65124
65255
  let width = /* @__PURE__ */ state(800);
@@ -65223,6 +65354,7 @@ function FloorPlanCanvas($$anchor, $$props) {
65223
65354
  $$props.projectName;
65224
65355
  $$props.heatmapEnabled;
65225
65356
  $$props.heatmapMatrix;
65357
+ heatmapColorScale();
65226
65358
  markDirty();
65227
65359
  });
65228
65360
  let layerVis = /* @__PURE__ */ state(proxy({
@@ -66109,7 +66241,7 @@ function FloorPlanCanvas($$anchor, $$props) {
66109
66241
  var _$$props$heatmapMatri, _$$props$heatmapMatri2;
66110
66242
  const floor = get(currentFloor);
66111
66243
  if (!floor || !$$props.heatmapEnabled || !((_$$props$heatmapMatri = $$props.heatmapMatrix) === null || _$$props$heatmapMatri === void 0 ? void 0 : _$$props$heatmapMatri.length)) return;
66112
- drawFloorHeatmap(getCS(), floor, (_$$props$heatmapMatri2 = $$props.heatmapMatrix) !== null && _$$props$heatmapMatri2 !== void 0 ? _$$props$heatmapMatri2 : [], get(detectedRooms));
66244
+ drawFloorHeatmap(getCS(), floor, (_$$props$heatmapMatri2 = $$props.heatmapMatrix) !== null && _$$props$heatmapMatri2 !== void 0 ? _$$props$heatmapMatri2 : [], get(detectedRooms), heatmapColorScale());
66113
66245
  }
66114
66246
  function getFloorWallBounds(floor = get(currentFloor)) {
66115
66247
  var _floor$walls;
@@ -70439,35 +70571,39 @@ function App($$anchor, $$props) {
70439
70571
  });
70440
70572
  let $5 = /* @__PURE__ */ user_derived(() => {
70441
70573
  var _$$get7;
70442
- return (_$$get7 = get(config)) === null || _$$get7 === void 0 ? void 0 : _$$get7.projectName;
70574
+ return (_$$get7 = get(config)) === null || _$$get7 === void 0 ? void 0 : _$$get7.heatmapColorScale;
70443
70575
  });
70444
70576
  let $6 = /* @__PURE__ */ user_derived(() => {
70445
70577
  var _$$get8;
70446
- return (_$$get8 = get(config)) === null || _$$get8 === void 0 ? void 0 : _$$get8.selectedCameraSerial;
70578
+ return (_$$get8 = get(config)) === null || _$$get8 === void 0 ? void 0 : _$$get8.projectName;
70447
70579
  });
70448
70580
  let $7 = /* @__PURE__ */ user_derived(() => {
70449
70581
  var _$$get9;
70450
- return (_$$get9 = get(config)) === null || _$$get9 === void 0 ? void 0 : _$$get9.showCameraCones;
70582
+ return (_$$get9 = get(config)) === null || _$$get9 === void 0 ? void 0 : _$$get9.selectedCameraSerial;
70451
70583
  });
70452
70584
  let $8 = /* @__PURE__ */ user_derived(() => {
70453
70585
  var _$$get10;
70454
- return (_$$get10 = get(config)) === null || _$$get10 === void 0 ? void 0 : _$$get10.showCameraLabels;
70586
+ return (_$$get10 = get(config)) === null || _$$get10 === void 0 ? void 0 : _$$get10.showCameraCones;
70455
70587
  });
70456
70588
  let $9 = /* @__PURE__ */ user_derived(() => {
70457
70589
  var _$$get11;
70458
- return (_$$get11 = get(config)) === null || _$$get11 === void 0 ? void 0 : _$$get11.cameraHeatmapMatrix;
70590
+ return (_$$get11 = get(config)) === null || _$$get11 === void 0 ? void 0 : _$$get11.showCameraLabels;
70459
70591
  });
70460
70592
  let $10 = /* @__PURE__ */ user_derived(() => {
70461
70593
  var _$$get12;
70462
- return ((_$$get12 = get(config)) === null || _$$get12 === void 0 ? void 0 : _$$get12.cameraThumbnail) || "";
70594
+ return (_$$get12 = get(config)) === null || _$$get12 === void 0 ? void 0 : _$$get12.cameraHeatmapMatrix;
70463
70595
  });
70464
70596
  let $11 = /* @__PURE__ */ user_derived(() => {
70465
70597
  var _$$get13;
70466
- return (_$$get13 = get(config)) === null || _$$get13 === void 0 ? void 0 : _$$get13.canvasBackground;
70598
+ return ((_$$get13 = get(config)) === null || _$$get13 === void 0 ? void 0 : _$$get13.cameraThumbnail) || "";
70467
70599
  });
70468
70600
  let $12 = /* @__PURE__ */ user_derived(() => {
70469
70601
  var _$$get14;
70470
- return (_$$get14 = get(config)) === null || _$$get14 === void 0 ? void 0 : _$$get14.floorPlateBackground;
70602
+ return (_$$get14 = get(config)) === null || _$$get14 === void 0 ? void 0 : _$$get14.canvasBackground;
70603
+ });
70604
+ let $13 = /* @__PURE__ */ user_derived(() => {
70605
+ var _$$get15;
70606
+ return (_$$get15 = get(config)) === null || _$$get15 === void 0 ? void 0 : _$$get15.floorPlateBackground;
70471
70607
  });
70472
70608
  FloorPlanCanvas(node_4, {
70473
70609
  get viewOnly() {
@@ -70485,29 +70621,32 @@ function App($$anchor, $$props) {
70485
70621
  get heatmapEnabled() {
70486
70622
  return get($4);
70487
70623
  },
70488
- get projectName() {
70624
+ get heatmapColorScale() {
70489
70625
  return get($5);
70490
70626
  },
70491
- get selectedCameraSerial() {
70627
+ get projectName() {
70492
70628
  return get($6);
70493
70629
  },
70494
- get showCameraCones() {
70630
+ get selectedCameraSerial() {
70495
70631
  return get($7);
70496
70632
  },
70497
- get showCameraLabels() {
70633
+ get showCameraCones() {
70498
70634
  return get($8);
70499
70635
  },
70500
- get cameraHeatmapMatrix() {
70636
+ get showCameraLabels() {
70501
70637
  return get($9);
70502
70638
  },
70503
- get cameraThumbnail() {
70639
+ get cameraHeatmapMatrix() {
70504
70640
  return get($10);
70505
70641
  },
70506
- get canvasBackground() {
70642
+ get cameraThumbnail() {
70507
70643
  return get($11);
70508
70644
  },
70509
- get floorPlateBackground() {
70645
+ get canvasBackground() {
70510
70646
  return get($12);
70647
+ },
70648
+ get floorPlateBackground() {
70649
+ return get($13);
70511
70650
  }
70512
70651
  });
70513
70652
  }
@@ -70536,12 +70675,12 @@ function App($$anchor, $$props) {
70536
70675
  {
70537
70676
  let $0 = /* @__PURE__ */ user_derived(() => get(mode) === "3d");
70538
70677
  let $1 = /* @__PURE__ */ user_derived(() => {
70539
- var _$$get$siteCameras, _$$get15;
70540
- return (_$$get$siteCameras = (_$$get15 = get(config)) === null || _$$get15 === void 0 ? void 0 : _$$get15.siteCameras) !== null && _$$get$siteCameras !== void 0 ? _$$get$siteCameras : [];
70678
+ var _$$get$siteCameras, _$$get16;
70679
+ return (_$$get$siteCameras = (_$$get16 = get(config)) === null || _$$get16 === void 0 ? void 0 : _$$get16.siteCameras) !== null && _$$get$siteCameras !== void 0 ? _$$get$siteCameras : [];
70541
70680
  });
70542
70681
  let $2 = /* @__PURE__ */ user_derived(() => {
70543
- var _$$get$cameraThumbnai, _$$get16;
70544
- return (_$$get$cameraThumbnai = (_$$get16 = get(config)) === null || _$$get16 === void 0 ? void 0 : _$$get16.cameraThumbnail) !== null && _$$get$cameraThumbnai !== void 0 ? _$$get$cameraThumbnai : "";
70682
+ var _$$get$cameraThumbnai, _$$get17;
70683
+ return (_$$get$cameraThumbnai = (_$$get17 = get(config)) === null || _$$get17 === void 0 ? void 0 : _$$get17.cameraThumbnail) !== null && _$$get$cameraThumbnai !== void 0 ? _$$get$cameraThumbnai : "";
70545
70684
  });
70546
70685
  PropertiesPanel($$anchor, {
70547
70686
  get is3D() {