architwin 1.15.0 → 1.15.2

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.
@@ -538,7 +538,8 @@ i18n
538
538
  "PressEscCancelRelocation": "再配置をキャンセルするには、Esc キーを押します。",
539
539
  "Window": "建具",
540
540
  "CannotBackDrawingMode": "描画モードがアクティブな間は戻ることができません。",
541
- "PleaseOffDrawingMode": "操作を行う前に、描画モードをオフにしてください。"
541
+ "PleaseOffDrawingMode": "操作を行う前に、描画モードをオフにしてください。",
542
+ "Successfully Deleted Tag": "タグを削除しました"
542
543
  }
543
544
  }
544
545
  },
@@ -3,6 +3,7 @@ import { setActiveMenu, clearActiveMenu, getObjectListStatus } from "./menuBar";
3
3
  import { renderObjectCards, removeObjectCard } from "./objectListPane";
4
4
  import { getTagFormData, setTagCategoriesOption, tagFormMode, selectedTag, renderCategoryDropdownOptions, toggleDropdown } from "./tagFormPane";
5
5
  import { renderTags, renderTagRow, addClickEventToTagRow, setTagLink, getTagLink, selectedCategoryFilterId, selectedSubCategoryFilterId, filterTagList } from "./tagListPane";
6
+ import { renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal } from "./previewModal";
6
7
  import { setActiveActionBtn, clearActiveActionBtn, toggleActionBarButtons } from "./actionBar";
7
8
  import { renderLibraryCards } from "./libraryPane";
8
9
  import { setActiveThemeCard } from "./themePane";
@@ -21,4 +22,4 @@ declare let actionBar: HTMLElement;
21
22
  */
22
23
  declare function setPreferredLanguage(): void;
23
24
  declare function renderToolbarUI(payload: IToolbarData): void;
24
- export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage };
25
+ export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage, renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal };
@@ -7,6 +7,7 @@ import { renderViewingRemoteSpace } from "./viewingRemoteSpace";
7
7
  import { renderAddObjectPane } from "./addObjectPane";
8
8
  import { renderTagFormPane, getTagFormData, setTagCategoriesOption, tagFormMode, selectedTag, renderCategoryDropdownOptions, toggleDropdown } from "./tagFormPane";
9
9
  import { renderTagListPane, renderTags, renderTagRow, addClickEventToTagRow, setTagLink, getTagLink, selectedCategoryFilterId, selectedSubCategoryFilterId, filterTagList } from "./tagListPane";
10
+ import { renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal } from "./previewModal";
10
11
  import { renderAddMediascreenFormPane } from "./addMediascreenFormPane";
11
12
  import { renderActionBar, setActiveActionBtn, clearActiveActionBtn, toggleActionBarButtons } from "./actionBar";
12
13
  import { renderLibraryPane, renderLibraryCards } from "./libraryPane";
@@ -108,6 +109,7 @@ function renderToolbarUI(payload) {
108
109
  pipeListPane = pipeList.renderPane();
109
110
  pipeFormPane = pipeForm.renderPane();
110
111
  renderModal();
112
+ renderPreviewModal();
111
113
  sidebarContainer.appendChild(modelControlPane);
112
114
  sidebarContainer.appendChild(basepointCalibratePane);
113
115
  sidebarContainer.appendChild(actionBar);
@@ -165,4 +167,4 @@ function renderToolbarUI(payload) {
165
167
  themeManager(config);
166
168
  }
167
169
  }
168
- export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage };
170
+ export { actionBar, tagFormMode, selectedTag, selectedCategoryFilterId, selectedSubCategoryFilterId, renderToolbarUI, renderObjectCards, setActiveMenu, clearActiveMenu, setActiveActionBtn, renderLibraryCards, renderTags, getTagFormData, renderTagRow, addClickEventToTagRow, setTagCategoriesOption, setActiveThemeCard, setActiveCard, setActiveLibraryCard, clearActiveCard, clearActiveLibraryCard, removeObjectCard, renderRecepientOptions, renderTagMessages, createTagMessage, renderCategoryDropdownOptions, toggleDropdown, setTagLink, getTagLink, setTagMessagingDetails, clearTagFormDropdown, clearTagFilterDropdown, getObjectListStatus, toggleModal, setModalAction, toggleModelControl, toggleActionSettings, clearActiveActionBtn, toggleActionBarButtons, filterTagList, setPreferredLanguage, renderPreviewModal, togglePreviewModal, closePreviewModal, setPreviewModalAction, activePreviewModal };
@@ -0,0 +1,6 @@
1
+ import type { ModalContent } from '../../../types';
2
+ export declare let activePreviewModal: boolean;
3
+ export declare function renderPreviewModal(): void;
4
+ export declare function togglePreviewModal(visible?: boolean): void;
5
+ export declare function closePreviewModal(): void;
6
+ export declare function setPreviewModalAction(content: ModalContent, iframeSrc?: string): Promise<void>;
@@ -0,0 +1,104 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ export let activePreviewModal = false;
11
+ export function renderPreviewModal() {
12
+ const element = document.createElement('div');
13
+ element.setAttribute('id', 'at-preview-modal-overlay');
14
+ element.setAttribute('data-cy', 'at-preview-modal-overlay');
15
+ element.innerHTML = `
16
+ <div class="at_preview_modal">
17
+ <div class="at_preview_modal-header">
18
+ <h2 class="at_preview_modal-title" id="at-preview-modal-content-heading" data-cy="at-preview-modal-content-heading"></h2>
19
+ <button class="at_preview_modal-close-btn" data-cy="at-preview-modal-close-btn">&times;</button>
20
+ </div>
21
+ <div class="at_preview_modal-body">
22
+ <div class="at_preview_modal-content" id="at-preview-modal-content-subheading" data-cy="at-preview-modal-content-subheading">
23
+ </div>
24
+ </div>
25
+ </div>
26
+ `;
27
+ document.body.appendChild(element);
28
+ const modalOverlay = document.getElementById('at-preview-modal-overlay');
29
+ const modalCloseBtn = document.querySelector('.at_preview_modal-close-btn');
30
+ if (modalCloseBtn) {
31
+ modalCloseBtn.addEventListener('click', () => {
32
+ modalOverlay.classList.remove('show');
33
+ });
34
+ }
35
+ if (modalOverlay) {
36
+ modalOverlay.addEventListener('click', (event) => {
37
+ if (event.target === modalOverlay) {
38
+ modalOverlay.classList.remove('show');
39
+ }
40
+ });
41
+ }
42
+ const handleEscape = (event) => {
43
+ if (event.key === 'Escape') {
44
+ modalOverlay.classList.remove('show');
45
+ document.removeEventListener('keydown', handleEscape);
46
+ }
47
+ };
48
+ document.addEventListener('keydown', handleEscape);
49
+ }
50
+ export function togglePreviewModal(visible = true) {
51
+ const modalOverlay = document.getElementById('at-preview-modal-overlay');
52
+ if (!modalOverlay) {
53
+ console.error("Preview modal overlay is undefined");
54
+ return;
55
+ }
56
+ if (visible) {
57
+ modalOverlay.classList.add('show');
58
+ activePreviewModal = true;
59
+ return;
60
+ }
61
+ modalOverlay.classList.remove('show');
62
+ activePreviewModal = false;
63
+ return;
64
+ }
65
+ export function closePreviewModal() {
66
+ const modalOverlay = document.getElementById('at-preview-modal-overlay');
67
+ if (modalOverlay) {
68
+ modalOverlay.classList.remove('show');
69
+ activePreviewModal = false;
70
+ }
71
+ }
72
+ export function setPreviewModalAction(content, iframeSrc) {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ const modalAcceptBtn = document.querySelector('.at_modal-accept-button');
75
+ const modalTitle = document.getElementById('at-preview-modal-content-heading');
76
+ const modelDesc = document.getElementById('at-preview-modal-content-subheading');
77
+ if (content) {
78
+ if (modalTitle && content.title) {
79
+ modalTitle.textContent = content.title;
80
+ }
81
+ if (modelDesc) {
82
+ if (iframeSrc) {
83
+ // If iframeSrc is provided, create iframe instead of text
84
+ modelDesc.innerHTML = `<iframe src="${iframeSrc}" class="at_preview_modal-iframe"></iframe>`;
85
+ }
86
+ else {
87
+ modelDesc.innerHTML = `<div class="at_preview_modal-content">${content.description}</div>`;
88
+ }
89
+ }
90
+ }
91
+ // if (modalAcceptBtn) {
92
+ // if (content && content.buttonLabel) {
93
+ // modalAcceptBtn.textContent = content.buttonLabel
94
+ // }
95
+ // if (callback) {
96
+ // modalAcceptBtn.onclick = async () => {
97
+ // await callback()
98
+ // }
99
+ // }else{
100
+ // modalAcceptBtn.onclick = closePreviewModal
101
+ // }
102
+ // }
103
+ });
104
+ }
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import i18n from '../i18n';
11
11
  import { SPACE_EVENTS } from "../../../../types";
12
12
  import { batchAddEventListenerByClassName } from "../../../events";
13
- import { startDraw, cancelDraw, disposeModel, _3DXObjects, getCurrentPolygon, dispatchSpaceEvent, enableVerticeControls, setCurrentPolygon, setMeshChildrenMaterialProperty, get3DXObjects, getChildrenOfModel, clearSelectedObject, renderPolygon, addUndoDrawActions, setWallBaseHeight, clearWallBaseHeight, setDrawingConfig, resetDrawingConfig, goToPosition } from '../../../../architwin';
13
+ import { startDraw, cancelDraw, disposeModel, _3DXObjects, getCurrentPolygon, dispatchSpaceEvent, enableVerticeControls, setCurrentPolygon, setMeshChildrenMaterialProperty, get3DXObjects, getChildrenOfModel, clearSelectedObject, renderPolygon, addUndoDrawActions, setWallBaseHeight, clearWallBaseHeight, setDrawingConfig, resetDrawingConfig, goToPosition, clearFloorBaseHeight } from '../../../../architwin';
14
14
  import { generateUUID, extractUUID } from '../../../../utils';
15
15
  import { getCurrentEditRoomData } from './roomTreePane';
16
16
  import { toggleModal, setModalAction } from "../modal";
@@ -249,6 +249,7 @@ export function toggleDrawWindowButton() {
249
249
  `;
250
250
  const objectIndex = _3DXObjects.findIndex(obj => obj.object.id == currentObject.object.id);
251
251
  log.info("objectIndex", objectIndex);
252
+ clearFloorBaseHeight();
252
253
  drawingConfig = {
253
254
  lineTypeComponentConfig: {
254
255
  renderPolygonOnAdd: false,
@@ -1023,48 +1024,53 @@ function setupDeleteWindow(element, window) {
1023
1024
  if (!deleteBtn)
1024
1025
  return;
1025
1026
  deleteBtn.addEventListener("click", () => {
1026
- toggleModal();
1027
- setModalAction({
1028
- title: i18n.t("DeleteWindow"),
1029
- description: i18n.t("ConfirmDeleteWindow"),
1030
- buttonLabel: i18n.t("YesDelete"),
1031
- }, () => __awaiter(this, void 0, void 0, function* () {
1032
- element.remove();
1033
- log.info("Deleted window:", window.index);
1034
- toggleModal(false);
1035
- // Update wall windows
1036
- currentPolygonData.walls = currentPolygonData.walls.map(wall => {
1037
- if (wall.uuid !== currentWall.uuid)
1038
- return wall;
1039
- if (wall.windows.length === 1) {
1040
- const windowLists = document.getElementById(`at-window-list-${wall.uuid}`);
1041
- if (windowLists)
1042
- windowLists.style.display = "none";
1043
- }
1044
- currentWall = Object.assign(Object.assign({}, wall), { windows: wall.windows.filter((w) => w.index !== window.index) });
1045
- return currentWall;
1046
- });
1047
- const objectIndex = _3DXObjects.findIndex(obj => obj.object.object_id == currentObject.object.object_id);
1048
- if (objectIndex != null) {
1049
- log.info("objectIndex", objectIndex);
1050
- if (_3DXObjects[objectIndex].children) {
1051
- _3DXObjects[objectIndex].children.map((win) => __awaiter(this, void 0, void 0, function* () {
1052
- log.info("WIND", win);
1053
- if (win.index == window.index && win.wallUUID == currentWall.uuid) {
1054
- yield disposeModel(win);
1055
- }
1056
- }));
1027
+ if (!isDrawing) {
1028
+ toggleModal();
1029
+ setModalAction({
1030
+ title: i18n.t("DeleteWindow"),
1031
+ description: i18n.t("ConfirmDeleteWindow"),
1032
+ buttonLabel: i18n.t("YesDelete"),
1033
+ }, () => __awaiter(this, void 0, void 0, function* () {
1034
+ element.remove();
1035
+ log.info("Deleted window:", window.index);
1036
+ toggleModal(false);
1037
+ // Update wall windows
1038
+ currentPolygonData.walls = currentPolygonData.walls.map(wall => {
1039
+ if (wall.uuid !== currentWall.uuid)
1040
+ return wall;
1041
+ if (wall.windows.length === 1) {
1042
+ const windowLists = document.getElementById(`at-window-list-${wall.uuid}`);
1043
+ if (windowLists)
1044
+ windowLists.style.display = "none";
1045
+ }
1046
+ currentWall = Object.assign(Object.assign({}, wall), { windows: wall.windows.filter((w) => w.index !== window.index) });
1047
+ return currentWall;
1048
+ });
1049
+ const objectIndex = _3DXObjects.findIndex(obj => obj.object.object_id == currentObject.object.object_id);
1050
+ if (objectIndex != null) {
1051
+ log.info("objectIndex", objectIndex);
1052
+ if (_3DXObjects[objectIndex].children) {
1053
+ _3DXObjects[objectIndex].children.map((win) => __awaiter(this, void 0, void 0, function* () {
1054
+ log.info("WIND", win);
1055
+ if (win.index == window.index && win.wallUUID == currentWall.uuid) {
1056
+ yield disposeModel(win);
1057
+ }
1058
+ }));
1059
+ }
1057
1060
  }
1058
- }
1059
- // Save + rerender window
1060
- currentObject.object.object_data.json_data = currentPolygonData;
1061
- saveWallChanges();
1062
- notify.success(`${i18n.t('SuccessWindowDelete')}`);
1063
- log.info("currentPartition polygonJson", JSON.parse(currentPartitionData.polygon_json));
1064
- log.info("currentObject", currentObject);
1065
- log.info("currentWall", currentWall);
1066
- log.info("currentPolygonData", currentPolygonData);
1067
- }));
1061
+ // Save + rerender window
1062
+ currentObject.object.object_data.json_data = currentPolygonData;
1063
+ saveWallChanges();
1064
+ notify.success(`${i18n.t('SuccessWindowDelete')}`);
1065
+ log.info("currentPartition polygonJson", JSON.parse(currentPartitionData.polygon_json));
1066
+ log.info("currentObject", currentObject);
1067
+ log.info("currentWall", currentWall);
1068
+ log.info("currentPolygonData", currentPolygonData);
1069
+ }));
1070
+ }
1071
+ else {
1072
+ notify.error(i18n.t("PleaseOffDrawingMode"));
1073
+ }
1068
1074
  });
1069
1075
  }
1070
1076
  /**
@@ -81,7 +81,7 @@ export declare function highlightSelectedPartitionChild(partitionId: string, nam
81
81
  * @param name - The specific name/identifier of the child element whose container to toggle
82
82
  * @param expand - Optional boolean to explicitly set expansion state (true = show, false = hide). If undefined, toggles current state
83
83
  */
84
- export declare function toggleExpandParitionWallChild(partitionId: string, name: string, expand?: boolean): void;
84
+ export declare function toggleExpandPartitionWallChild(partitionId: string, name: string, expand?: boolean): void;
85
85
  /**
86
86
  * Highlights the selected window element by toggling CSS classes and ensures its parent partition is expanded.
87
87
  * @param wallUuid - The unique identifier of the wall containing the window elements
@@ -92,6 +92,11 @@ export declare function highlightSelectedWindow(wallUuid: string, index: number
92
92
  * Removes the highlight from all selected window items by removing the 'selected' CSS class.
93
93
  */
94
94
  export declare function toggleHighlightedWindowItem(): void;
95
+ /**
96
+ * Toggles the highlighted state of partition items by adding 'selected' class to the matching partition and removing it from others.
97
+ * @param partitionId - The partition ID to highlight (only the prefix before the first hyphen is used for matching)
98
+ */
99
+ export declare function toggleHighlightedPartitionItem(partitionId: string): void;
95
100
  /**
96
101
  * Calculates the midpoint (centroid) of multiple 3D coordinates by averaging their x, y, and z values.
97
102
  * @param coords - An array of objects containing start Vector3 coordinates
@@ -120,7 +120,7 @@ export function displayRoomPartition(partition, objectData) {
120
120
  element.innerHTML = `
121
121
  <li class="at_room_tree_parent">
122
122
  <div id="at-div-room-${partition.uuid}" class="at_flex at_space_between at_toggle">
123
- <span class="toggle selectable" id="at-room-${partition.uuid}">▶ ${partition.name}</span>
123
+ <span class="at_room_name_text toggle selectable" id="at-room-${partition.uuid}">▶ ${partition.name}</span>
124
124
  <div>
125
125
  <span id="at-room-edit-${partition.uuid}-btn" class="mdi mdi-pencil at_room_edit_btn" target-pane="at-room-form-pane"></span>
126
126
  <span id="at-room-visibility-btn-${partition.uuid}" class="mdi ${isVisible ? 'mdi-eye ' : 'mdi-eye-off'} at_room_visible_btn"></span>
@@ -182,8 +182,8 @@ export function displayChildPartitions(partitions, parentPartitionId, objectData
182
182
  return `
183
183
 
184
184
  <li class="at_room_tree_child">
185
- <div id="at-child-partition-${partition.uuid.split('-')[0]}" class="at_flex at_space_between at_toggle">
186
- <span class="toggle selectable" id="at-partition-${partition.uuid}" object-id="${objectId}" parentId="at-partition-${parentPartitionId}">▶ ${i18n.t(`${partition.name}`)}</span>
185
+ <div id="at-child-partition-${partition.uuid.split('-')[0]}" class="at_partion_row_item at_flex at_space_between at_toggle">
186
+ <span class="at_partition_name_text toggle selectable" id="at-partition-${partition.uuid}" object-id="${objectId}" parentId="at-partition-${parentPartitionId}">▶ ${i18n.t(`${partition.name}`)}</span>
187
187
  <div>
188
188
  <span id="at-partition-visibility-btn-${objectId}" parent-id="${parentPartitionId}"
189
189
  class="mdi ${isVisible ? 'mdi-eye ' : 'mdi-eye-off'} at_room_visible_btn"></span>
@@ -363,7 +363,7 @@ function toggleSelectedPartition() {
363
363
  yield new Promise(resolve => setTimeout(resolve, 0));
364
364
  yield new Promise(resolve => requestAnimationFrame(resolve));
365
365
  const wallId = target.getAttribute('polygon-item-id');
366
- const windowItems = document.querySelectorAll(`li.at_wall_window_row_item[wall-id="${wallId}"]`);
366
+ const windowItems = document.querySelectorAll(`li.at_window_row_item[wall-id="${wallId}"]`);
367
367
  if (windowItems && windowItems.length > 0) {
368
368
  windowItems.forEach((windowLi) => {
369
369
  const visibilityBtn = windowLi.querySelector('.at_child_visible_btn');
@@ -387,6 +387,7 @@ function toggleSelectedPartition() {
387
387
  yield goToPosition(wallBottomMidPoint);
388
388
  highlightSelectedPartitionChild(partitionId, objectName);
389
389
  toggleHighlightedWindowItem();
390
+ toggleHighlightedPartitionItem(partitionId);
390
391
  }
391
392
  catch (e) {
392
393
  log.info('goToPosition failed: ', e);
@@ -404,6 +405,7 @@ function toggleSelectedPartition() {
404
405
  const floorMidPoint = calculateMidPoint(floorCoords);
405
406
  yield goToPosition(floorMidPoint);
406
407
  highlightSelectedPartitionChild(partitionId, objectName);
408
+ toggleHighlightedPartitionItem(partitionId);
407
409
  }
408
410
  catch (e) {
409
411
  log.info('goToPosition failed: ', e);
@@ -441,18 +443,21 @@ function toggleSelectedPartition() {
441
443
  log.info('goToPosition failed: ', e);
442
444
  }
443
445
  }));
444
- batchAddEventListenerByClassName('at_wall_window_row_item', (event) => __awaiter(this, void 0, void 0, function* () {
446
+ batchAddEventListenerByClassName('at_window_row_item', (event) => __awaiter(this, void 0, void 0, function* () {
445
447
  event.stopPropagation();
446
448
  const targetElement = event.currentTarget;
447
449
  const wallUuid = targetElement.getAttribute('wall-id');
448
450
  const windowIndex = targetElement.getAttribute('window-index');
451
+ const partitionId = targetElement.getAttribute('partition-id');
449
452
  const windowCoordsEncoded = targetElement.getAttribute('window-coords');
450
453
  const windowCoordsJSON = atob(windowCoordsEncoded);
451
454
  const windowCoords = JSON.parse(windowCoordsJSON);
452
455
  try {
453
456
  const windowBottomMidPoint = calculateMidPoint(windowCoords);
454
457
  yield goToPosition(windowBottomMidPoint);
458
+ toggleHighlightedWindowItem();
455
459
  highlightSelectedWindow(wallUuid, windowIndex);
460
+ toggleHighlightedPartitionItem(partitionId);
456
461
  }
457
462
  catch (e) {
458
463
  log.info('goToPosition failed: ', e);
@@ -720,20 +725,15 @@ export function highlightSelectedPartitionChild(partitionId, name) {
720
725
  partitionChildren.forEach((partitionChild) => {
721
726
  const isSelected = partitionChild.id === targetId;
722
727
  const header = partitionChild.querySelector('.at_partition_child_header');
723
- if (header) {
724
- header.classList.toggle('selected', isSelected);
725
- const arrow = header.querySelector('.at_partition_child_expand_icon');
726
- if (arrow && arrow.textContent) {
727
- if (isSelected) {
728
- arrow.textContent = arrow.textContent.replace('▶', '▼');
729
- toggleExpandParitionWallChild(partitionId, name, false);
730
- }
731
- else {
732
- arrow.textContent = arrow.textContent.replace('▼', '▶');
733
- toggleExpandParitionWallChild(partitionId, name, true);
734
- }
735
- }
736
- }
728
+ const listContainer = partitionChild.querySelector('.at_wall_children_container');
729
+ const arrow = header === null || header === void 0 ? void 0 : header.querySelector('.at_partition_child_expand_icon');
730
+ header === null || header === void 0 ? void 0 : header.classList.toggle('selected', isSelected);
731
+ if (!header || !(arrow === null || arrow === void 0 ? void 0 : arrow.textContent) || !listContainer)
732
+ return;
733
+ // for selected: toggle expand/collapse, for non-selected: always collapse
734
+ const shouldExpand = isSelected && arrow.textContent.includes('▶');
735
+ arrow.textContent = arrow.textContent.replace(shouldExpand ? '▶' : '▼', shouldExpand ? '▼' : '▶');
736
+ listContainer.classList.toggle('at_hidden', !shouldExpand);
737
737
  });
738
738
  }
739
739
  /**
@@ -742,20 +742,27 @@ export function highlightSelectedPartitionChild(partitionId, name) {
742
742
  * @param name - The specific name/identifier of the child element whose container to toggle
743
743
  * @param expand - Optional boolean to explicitly set expansion state (true = show, false = hide). If undefined, toggles current state
744
744
  */
745
- export function toggleExpandParitionWallChild(partitionId, name, expand) {
745
+ export function toggleExpandPartitionWallChild(partitionId, name, expand) {
746
746
  const partitionChildren = document.querySelectorAll(`li[partition-li-id="${partitionId}"]`);
747
747
  const targetId = `partition-child-${name}`;
748
748
  partitionChildren.forEach((partitionChild) => {
749
749
  const isSelected = partitionChild.id === targetId;
750
+ const header = partitionChild.querySelector('.at_partition_child_header');
750
751
  const listContainer = partitionChild.querySelector('.at_wall_children_container');
751
- if (listContainer) {
752
- if (isSelected) {
753
- listContainer.classList.toggle('at_hidden', expand !== undefined ? !expand : undefined);
754
- }
755
- else {
756
- listContainer.classList.add('at_hidden');
757
- }
752
+ const arrow = header === null || header === void 0 ? void 0 : header.querySelector('.at_partition_child_expand_icon');
753
+ if (!header || !(arrow === null || arrow === void 0 ? void 0 : arrow.textContent) || !listContainer)
754
+ return;
755
+ // Determine if should be expanded
756
+ let shouldExpand;
757
+ if (isSelected) {
758
+ shouldExpand = expand !== undefined ? expand : !arrow.textContent.includes('▶');
759
+ }
760
+ else {
761
+ shouldExpand = false;
758
762
  }
763
+ // Update arrow and container based on shouldExpand
764
+ arrow.textContent = arrow.textContent.replace(shouldExpand ? '▶' : '▼', shouldExpand ? '▼' : '▶');
765
+ listContainer.classList.toggle('at_hidden', !shouldExpand);
759
766
  });
760
767
  }
761
768
  function displayWindows(wall, partitionId, parentId) {
@@ -767,7 +774,7 @@ function displayWindows(wall, partitionId, parentId) {
767
774
  const windowCoords = JSON.stringify(window.edges);
768
775
  const windowCoordsEncoded = btoa(windowCoords);
769
776
  itemsHTML += `
770
- <li window-coords="${windowCoordsEncoded}" id="window-${wall.uuid}-${window.index}" wall-id="${wall.uuid}" window-name="${window.name}" window-index="${window.index}" class="at_wall_window_row_item">
777
+ <li window-coords="${windowCoordsEncoded}" partition-id="${partitionId}" id="window-${wall.uuid}-${window.index}" wall-id="${wall.uuid}" window-name="${window.name}" window-index="${window.index}" class="at_window_row_item">
771
778
  <div>${window.name}</div>
772
779
  <div>
773
780
  <span window-coords="${windowCoordsEncoded}" partition-id="${partitionId}" partition-parent-uuid="${parentId}" polygon-item-id="${wall.uuid}" index="${window.index}" class="mdi mdi-pencil at_window_edit_btn"></span>
@@ -843,7 +850,7 @@ export function highlightSelectedWindow(wallUuid, index) {
843
850
  const parentWallItem = windowElement.closest('li.at_partition_wall_row_item');
844
851
  const partitionId = parentWallItem.getAttribute('partition-li-id');
845
852
  const objectName = parentWallItem.getAttribute('object-name');
846
- toggleExpandParitionWallChild(partitionId, objectName, true);
853
+ toggleExpandPartitionWallChild(partitionId, objectName, true);
847
854
  }
848
855
  windowElement.classList.toggle('selected', windowElement.id === targetId);
849
856
  });
@@ -852,11 +859,28 @@ export function highlightSelectedWindow(wallUuid, index) {
852
859
  * Removes the highlight from all selected window items by removing the 'selected' CSS class.
853
860
  */
854
861
  export function toggleHighlightedWindowItem() {
855
- const windowItems = document.querySelectorAll('li.at_wall_window_row_item.selected');
862
+ const windowItems = document.querySelectorAll('li.at_window_row_item.selected');
856
863
  windowItems.forEach(el => {
857
864
  el.classList.remove('selected');
858
865
  });
859
866
  }
867
+ /**
868
+ * Toggles the highlighted state of partition items by adding 'selected' class to the matching partition and removing it from others.
869
+ * @param partitionId - The partition ID to highlight (only the prefix before the first hyphen is used for matching)
870
+ */
871
+ export function toggleHighlightedPartitionItem(partitionId) {
872
+ const partitions = document.querySelectorAll('div.at_partion_row_item');
873
+ partitions === null || partitions === void 0 ? void 0 : partitions.forEach(partition => {
874
+ if (partition.getAttribute('id') === `at-child-partition-${partitionId.split('-')[0]}`) {
875
+ partition.classList.add('selected');
876
+ partition.querySelector('.at_partition_name_text').classList.add('selected'); // Added dot
877
+ }
878
+ else {
879
+ partition.classList.remove('selected');
880
+ partition.querySelector('.at_partition_name_text').classList.remove('selected'); // Added dot
881
+ }
882
+ });
883
+ }
860
884
  /**
861
885
  * Calculates the midpoint (centroid) of multiple 3D coordinates by averaging their x, y, and z values.
862
886
  * @param coords - An array of objects containing start Vector3 coordinates
@@ -245,7 +245,7 @@ export function renderTags(tags, showOwnTagsOnly = false) {
245
245
  const payload = { tag: targetTag };
246
246
  dispatchSpaceEvent(SPACE_EVENTS.TAG_DISPOSED, payload);
247
247
  toggleModal(false);
248
- notify.success("Successfully deleted tag");
248
+ notify.success(i18n.t('Successfully deleted tag'));
249
249
  }
250
250
  else {
251
251
  toggleModal(false);
@@ -414,7 +414,7 @@ export function addClickEventToTagRow(tag) {
414
414
  yield disposeTag({ tagId: tagId });
415
415
  const tagRow = document.getElementById(`at-tag-row-${tagId}`);
416
416
  tagRow.remove();
417
- notify.success("Successfully deleted tag");
417
+ notify.success(i18n.t('Successfully deleted tag'));
418
418
  }
419
419
  else {
420
420
  notify.error("Tag id not found!");
@@ -3776,7 +3776,15 @@ function handleClickEventInTagSortOption() {
3776
3776
  if (closestOption) {
3777
3777
  const sortOption = closestOption.dataset.sort;
3778
3778
  updateSelectedTagSortOption(sortOption);
3779
- const tags = getMpTags();
3779
+ log.info("_@ _tags: ", _tags);
3780
+ let tags;
3781
+ if (currentTagPaneMode == TAG_TYPE.MP) {
3782
+ tags = getMpTags().filter(tag => (tag.tag_type === TAG_TYPE.MP || tag.tag_type === undefined));
3783
+ }
3784
+ else {
3785
+ tags = getMpTags().filter(tag => tag.tag_type === TAG_TYPE.IOT);
3786
+ }
3787
+ // const tags = getMpTags()
3780
3788
  const filteredTags = filterTagList(tags);
3781
3789
  const sortConfig = sortTagOptions[sortOption] || { by: 'label', order: 'asc' };
3782
3790
  if (selectedCategoryFilterId || selectedSubCategoryFilterId) {
@@ -1114,12 +1114,31 @@ export class BufferGeometry {
1114
1114
  const p2 = new THREE.Vector3(path3D[2].x, path3D[2].y, path3D[2].z);
1115
1115
  const v1 = new THREE.Vector3().subVectors(p1, p0);
1116
1116
  const v2 = new THREE.Vector3().subVectors(p2, p0);
1117
- const normal = new THREE.Vector3().crossVectors(v1, v2);
1117
+ let normal = new THREE.Vector3().crossVectors(v1, v2);
1118
1118
  const normalLen = normal.length();
1119
1119
  if (normalLen === 0) {
1120
1120
  continue;
1121
1121
  }
1122
1122
  normal.divideScalar(normalLen);
1123
+ // CRITICAL FIX: Ensure normal points outward from the wall
1124
+ // Calculate the centroid of the main polygon (floor)
1125
+ const centroid = new THREE.Vector3();
1126
+ for (const point of this.inputs.path) {
1127
+ centroid.add(new THREE.Vector3(point.x, point.y, point.z));
1128
+ }
1129
+ centroid.divideScalar(this.inputs.path.length);
1130
+ // Calculate window center
1131
+ const windowCenter = new THREE.Vector3();
1132
+ for (const point of path3D) {
1133
+ windowCenter.add(new THREE.Vector3(point.x, point.y, point.z));
1134
+ }
1135
+ windowCenter.divideScalar(path3D.length);
1136
+ // Vector from centroid to window center
1137
+ const outwardVector = new THREE.Vector3().subVectors(windowCenter, centroid);
1138
+ // If normal points inward (dot product < 0), flip it
1139
+ if (normal.dot(outwardVector) < 0) {
1140
+ normal.negate();
1141
+ }
1123
1142
  const uAxis = v1.clone().normalize();
1124
1143
  const vAxis = new THREE.Vector3().crossVectors(normal, uAxis).normalize();
1125
1144
  const shapePoints2D = [];
@@ -1140,8 +1159,8 @@ export class BufferGeometry {
1140
1159
  const basisMatrix = new THREE.Matrix4().makeBasis(uAxis, vAxis, normal);
1141
1160
  const translation = new THREE.Matrix4().makeTranslation(p0.x, p0.y, p0.z);
1142
1161
  const worldMatrix = new THREE.Matrix4().multiplyMatrices(translation, basisMatrix);
1143
- // Apply a small offset along the wall normal to avoid z-fighting with coplanar planes
1144
- const offset = -0.05;
1162
+ // Apply a small offset along the wall normal to avoid z-fighting
1163
+ const offset = -0.08;
1145
1164
  const offsetMatrix = new THREE.Matrix4().makeTranslation(normal.x * offset, normal.y * offset, normal.z * offset);
1146
1165
  const finalMatrix = new THREE.Matrix4().multiplyMatrices(offsetMatrix, worldMatrix);
1147
1166
  windowGeometry.applyMatrix4(finalMatrix);
@@ -1192,7 +1211,6 @@ export class BufferGeometry {
1192
1211
  let windowLabelText = windows[i].name ? `${windows[i].name}` : windowMesh.name;
1193
1212
  windowLabelText = windows[i].material ? `${windowLabelText}_${windows[i].material}: ${windowDimension.area.toFixed(2)}m²` : `${windowLabelText}: ${windowDimension.area.toFixed(2)}m²`;
1194
1213
  log.info("windowLabelText ", windowLabelText);
1195
- //const windowLabel = windows[i].name ? `${windows[i].name}_${windows[i].material}` : `Window ${i}_${windows[i].material}`
1196
1214
  const windowCanvas = this.createLabelCanvas(windowLabelText);
1197
1215
  const windowArea = Math.abs(twiceSignedArea * 0.5);
1198
1216
  const labelWidth = Math.max(0.5, Math.min(2, Math.sqrt(Math.max(0.0001, windowArea))));
@@ -1209,11 +1227,12 @@ export class BufferGeometry {
1209
1227
  .addScaledVector(vAxis, centerV)
1210
1228
  .add(p0);
1211
1229
  const labelOffset = 0.01;
1230
+ // Position label slightly offset from window, facing inward (opposite to normal)
1212
1231
  windowCenterLabel.position.copy(center3D).addScaledVector(normal.clone().negate(), labelOffset);
1213
1232
  windowCenterLabel.name = windowMesh.name;
1214
1233
  windowCenterLabel.visible = windows[i].options ? windows[i].options.is_visible : true;
1234
+ // Make label face inward (opposite direction of the outward normal)
1215
1235
  windowCenterLabel.lookAt(windowCenterLabel.position.clone().add(normal.clone().negate()));
1216
- //windowCenterLabel.name = windows[i].uuid ? `${windows[i].uuid}_windowLabel` : `windowLabel-${i}`;
1217
1236
  this.groupedMesh.add(windowCenterLabel);
1218
1237
  }
1219
1238
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "architwin",
3
- "version": "1.15.0",
3
+ "version": "1.15.2",
4
4
  "description": "ArchiTwin Library for Matterport",
5
5
  "main": "./lib/architwin.js",
6
6
  "types": "./lib/architwin.d.ts",