@smarterplan/ngx-smarterplan-core 1.4.12 → 1.4.13

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.
@@ -426,6 +426,14 @@ var SpModule;
426
426
  SpModule["HOTEL"] = "HOTEL";
427
427
  SpModule["IMMO"] = "IMMO";
428
428
  })(SpModule || (SpModule = {}));
429
+ var MatterportViewType;
430
+ (function (MatterportViewType) {
431
+ MatterportViewType["BASE"] = "viewtype.base";
432
+ MatterportViewType["DEFURNISH"] = "viewtype.defurnish";
433
+ MatterportViewType["LAYERED_BASE"] = "viewtype.layeredbase";
434
+ MatterportViewType["OTHER"] = "viewtype.other";
435
+ MatterportViewType["USER"] = "viewtype.user";
436
+ })(MatterportViewType || (MatterportViewType = {}));
429
437
 
430
438
  /**
431
439
  * The base of all `SceneComponent` created with the sdk.
@@ -3407,6 +3415,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
3407
3415
 
3408
3416
  class MatterportTagService {
3409
3417
  navigationService;
3418
+ /** Name of the common layer every Smarterplan tag is created in. */
3419
+ static SHARED_TAG_LAYER_NAME = 'smarterplan-shared-tags';
3410
3420
  dictionnaryTags = new Map();
3411
3421
  tagAddQueue = Promise.resolve();
3412
3422
  mattertagToFollow = null;
@@ -3417,6 +3427,22 @@ class MatterportTagService {
3417
3427
  tagService = null;
3418
3428
  tagsCurrentOpacity = new Map();
3419
3429
  tagsCurrentEnabled = new Map();
3430
+ /**
3431
+ * Single layer holding every Smarterplan tag, added to every view of the space so a
3432
+ * tag stays in place — same sid, same content — when the user switches between the
3433
+ * furnished and the Defurnished view. Tags added to the global sdk.Tag (or to a
3434
+ * view's own layer) belong to that view only, which is what made them pop in and out
3435
+ * on every view change.
3436
+ *
3437
+ * Deliberately NOT created with `{ common: true }`: in SDK 26.7.5 a common layer is
3438
+ * pushed into `getOrderedModelViews()` at creation time, and that call defaults to
3439
+ * `includeDefurnish: false`, so the Defurnished view never receives it — while
3440
+ * `View.addLayer()` refuses to repair it ("Layer is common. No need to add."). A
3441
+ * plain layer we attach to each view ourselves reaches every view, Defurnished
3442
+ * included. See attachSharedTagLayerToViews().
3443
+ */
3444
+ sharedTagLayer = null;
3445
+ sharedTagLayerPromise = null;
3420
3446
  constructor(navigationService) {
3421
3447
  this.navigationService = navigationService;
3422
3448
  }
@@ -3429,6 +3455,7 @@ class MatterportTagService {
3429
3455
  return;
3430
3456
  try {
3431
3457
  this.onGoToTag.next(sid);
3458
+ // `open` only exists on the global Tag module, never on a layer-scoped one.
3432
3459
  await sdk.Tag.open(sid);
3433
3460
  }
3434
3461
  catch (e) {
@@ -3436,6 +3463,102 @@ class MatterportTagService {
3436
3463
  console.warn('Cannot open tag', sid, e);
3437
3464
  }
3438
3465
  }
3466
+ /**
3467
+ * Returns the SDK Tag module to use for an operation addressing an existing tag by ID
3468
+ * (icon, opacity, position, attachments, removal...): always the global sdk.Tag.
3469
+ *
3470
+ * A layer-scoped Tag module only exposes the *replayable* mutations, meant to build
3471
+ * the layer's own content; applying them to an already-created tag silently does
3472
+ * nothing — which is what left every pin white instead of carrying its icon. Only
3473
+ * `add` has to go through the layer, see getTagCreationModule().
3474
+ */
3475
+ getTagModule(sdk, tagId) {
3476
+ return sdk?.Tag;
3477
+ }
3478
+ /**
3479
+ * Returns the Tag module every new tag must be created through: the shared layer
3480
+ * when the View API is available, the global sdk.Tag otherwise.
3481
+ */
3482
+ async getTagCreationModule(sdk) {
3483
+ const layer = await this.ensureSharedTagLayer(sdk);
3484
+ return layer?.Tag || sdk?.Tag;
3485
+ }
3486
+ /**
3487
+ * Creates (once per SDK session) and returns the shared tag layer.
3488
+ * Resolves to null when the View API is unavailable, so callers transparently fall
3489
+ * back to the global sdk.Tag.
3490
+ */
3491
+ async ensureSharedTagLayer(sdk) {
3492
+ if (this.sharedTagLayer)
3493
+ return this.sharedTagLayer;
3494
+ if (!sdk?.View?.createLayer)
3495
+ return null;
3496
+ if (!this.sharedTagLayerPromise) {
3497
+ this.sharedTagLayerPromise = Promise.resolve(sdk.View.createLayer(MatterportTagService.SHARED_TAG_LAYER_NAME))
3498
+ .then(async (layer) => {
3499
+ this.sharedTagLayer = layer;
3500
+ // A freshly created layer can come back toggled off, which hides its tags.
3501
+ if (layer && layer.toggled === false) {
3502
+ await layer.toggle(true).catch(() => { });
3503
+ }
3504
+ return layer;
3505
+ })
3506
+ .catch((e) => {
3507
+ // Allow a later retry (e.g. the SDK was not fully ready yet).
3508
+ this.sharedTagLayerPromise = null;
3509
+ if (isDevMode())
3510
+ console.warn('[MatterportTagService] Could not create the shared tag layer', e);
3511
+ return null;
3512
+ });
3513
+ }
3514
+ return this.sharedTagLayerPromise;
3515
+ }
3516
+ /**
3517
+ * Makes sure the shared layer is part of every view of the space, Defurnished
3518
+ * included. This is what actually shares the tags across views, and the reason the
3519
+ * layer must not be a common one: the SDK only performs the attachment for
3520
+ * non-common layers. Idempotent, so it can run on every view collection update.
3521
+ */
3522
+ async attachSharedTagLayerToViews(sdk, views) {
3523
+ const layer = await this.ensureSharedTagLayer(sdk);
3524
+ if (!layer)
3525
+ return;
3526
+ for (const view of views) {
3527
+ if (!view?.addLayer || view.hasLayer?.(layer))
3528
+ continue;
3529
+ try {
3530
+ await view.addLayer(layer);
3531
+ }
3532
+ catch (e) {
3533
+ if (isDevMode())
3534
+ console.warn('[MatterportTagService] Cannot add the shared tag layer to view', view?.id, e);
3535
+ }
3536
+ }
3537
+ }
3538
+ /**
3539
+ * Adds a tag through the shared layer so it exists in every view. Falls back
3540
+ * to the global sdk.Tag when the View API is unavailable; that call is raced against
3541
+ * a timeout as a safety net, since it never resolves while a Defurnished view is
3542
+ * active.
3543
+ */
3544
+ async addTagToSdk(sdk, descriptor) {
3545
+ const sharedTagModule = await this.getTagCreationModule(sdk);
3546
+ try {
3547
+ const sidList = (await Promise.race([
3548
+ sharedTagModule.add(descriptor),
3549
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Tag.add timed out')), 4000)),
3550
+ ]));
3551
+ if (sidList?.length)
3552
+ return sidList[0];
3553
+ }
3554
+ catch (error) {
3555
+ if (error?.message?.includes('already in use'))
3556
+ throw error;
3557
+ if (isDevMode())
3558
+ console.warn('[MatterportTagService] Tag.add failed/timed out', error?.message);
3559
+ }
3560
+ return null;
3561
+ }
3439
3562
  /** Opens the most recently created tag in the viewer. */
3440
3563
  async goToLastTag(sdk) {
3441
3564
  if (!sdk || this.mattertagIDs.length === 0)
@@ -3450,36 +3573,40 @@ class MatterportTagService {
3450
3573
  async addMattertagToViewer(sdk, mattertagData) {
3451
3574
  if (!sdk)
3452
3575
  return null;
3453
- console.log('---------------');
3454
- console.log('element id ' + mattertagData.elementID);
3455
- console.log('position: ', mattertagData.getPosition());
3456
- console.log('rotation: ', mattertagData.getRotation());
3457
- console.log('sweep id: ', mattertagData.getSweepID());
3458
- console.log('---------------');
3459
- this.tagAddQueue = this.tagAddQueue.then(async () => {
3460
- const data = mattertagData.getData();
3461
- const existingId = data?.id || null;
3576
+ this.tagAddQueue = this.tagAddQueue
3577
+ .then(async () => {
3578
+ const descriptor = mattertagData.getMattertagDescriptor()[0];
3579
+ const existingId = descriptor?.id || null;
3462
3580
  try {
3463
- const sidList = await sdk.Tag.add(data);
3464
- if (sidList && sidList.length > 0) {
3465
- const mattertagID = sidList[0];
3466
- this.mattertagIDs.push(mattertagID);
3467
- this.dictionnaryTags.set(mattertagID, mattertagData);
3468
- return mattertagID;
3581
+ const sid = await this.addTagToSdk(sdk, descriptor);
3582
+ if (sid) {
3583
+ mattertagData.setMatterportSid(sid);
3584
+ if (!this.mattertagIDs.includes(sid)) {
3585
+ this.mattertagIDs.push(sid);
3586
+ }
3587
+ this.dictionnaryTags.set(sid, mattertagData);
3588
+ return sid;
3469
3589
  }
3590
+ if (isDevMode())
3591
+ console.warn('[MatterportTagService] Tag.add returned no sid', descriptor);
3470
3592
  }
3471
3593
  catch (error) {
3472
3594
  if (error?.message?.includes('already in use') && existingId) {
3473
3595
  if (!this.dictionnaryTags.has(existingId)) {
3474
3596
  this.mattertagIDs.push(existingId);
3475
- this.dictionnaryTags.set(existingId, mattertagData);
3476
3597
  }
3598
+ this.dictionnaryTags.set(existingId, mattertagData);
3477
3599
  return existingId;
3478
3600
  }
3479
3601
  if (isDevMode())
3480
- console.warn('Failed to add tag to viewer', error);
3602
+ console.warn('[MatterportTagService] addMattertagToViewer failed', error);
3481
3603
  }
3482
3604
  return null;
3605
+ })
3606
+ .catch((e) => {
3607
+ if (isDevMode())
3608
+ console.warn('[MatterportTagService] tagAddQueue rejected', e);
3609
+ return null;
3483
3610
  });
3484
3611
  return this.tagAddQueue;
3485
3612
  }
@@ -3498,7 +3625,8 @@ class MatterportTagService {
3498
3625
  }
3499
3626
  this.tagAddQueue = this.tagAddQueue.then(async () => {
3500
3627
  try {
3501
- const [createdSid] = await sdk.Tag.add(...descriptor);
3628
+ const tagModule = await this.getTagCreationModule(sdk);
3629
+ const [createdSid] = await tagModule.add(...descriptor);
3502
3630
  this.mattertagIDs.push(createdSid);
3503
3631
  this.dictionnaryTags.set(createdSid, mattertagData);
3504
3632
  await wait(100);
@@ -3545,36 +3673,6 @@ class MatterportTagService {
3545
3673
  tagPos.z >= min.z - margin && tagPos.z <= max.z + margin);
3546
3674
  });
3547
3675
  }
3548
- /**
3549
- * Computes the final context-aware opacity for a single tag.
3550
- * @param currentFloorSequence Authoritative current floor sequence from sdk.Floor.current
3551
- * (null = single-floor model or unknown).
3552
- * @param currentRooms Array of active rooms the camera is in.
3553
- */
3554
- /*computeSingleTagContextOpacity(
3555
- mattertagData: MattertagData,
3556
- poseCamera: any,
3557
- sweepCollection: any,
3558
- currentFloorSequence: number | null,
3559
- currentRooms: any[]
3560
- ): number {
3561
- const mode = this.navigationService.currentCameraMode;
3562
-
3563
- // 1. Check Floor
3564
- const tagFloorId = this.getFloorIdForTag(mattertagData, sweepCollection);
3565
- const currentFloorId = currentFloorSequence?.toString();
3566
- if (tagFloorId && currentFloorId && tagFloorId !== currentFloorId) {
3567
- return 0;
3568
- }
3569
-
3570
- // 2. Si Dollhouse -> Pleine opacité
3571
- //if (mode !== CameraMode.INSIDE) return 1;
3572
-
3573
- // 3. Si Inside -> Check pièce + Distance progressive
3574
- //if (!this.isTagInRooms(mattertagData, currentRooms)) return 0;
3575
-
3576
- return 1;
3577
- }*/
3578
3676
  /** Returns the ID of the most recently added tag. */
3579
3677
  getLastTag() {
3580
3678
  if (this.mattertagIDs.length === 0)
@@ -3624,10 +3722,11 @@ class MatterportTagService {
3624
3722
  }
3625
3723
  // Apply changes
3626
3724
  // Tooltip and click management
3725
+ const tagModule = this.getTagModule(sdk, tagId);
3627
3726
  const lastEnabled = this.tagsCurrentEnabled.get(tagId);
3628
3727
  if (lastEnabled !== shouldBeEnabled) {
3629
3728
  this.tagsCurrentEnabled.set(tagId, shouldBeEnabled);
3630
- promises.push(sdk.Tag.allowAction(tagId, {
3729
+ promises.push(tagModule.allowAction(tagId, {
3631
3730
  opening: shouldBeEnabled,
3632
3731
  navigating: shouldBeEnabled,
3633
3732
  docking: false
@@ -3637,16 +3736,26 @@ class MatterportTagService {
3637
3736
  const lastOpacity = this.tagsCurrentOpacity.get(tagId) ?? -1;
3638
3737
  if (Math.abs(lastOpacity - targetOpacity) > 0.05) {
3639
3738
  this.tagsCurrentOpacity.set(tagId, targetOpacity);
3640
- promises.push(sdk.Tag.editOpacity(tagId, targetOpacity).catch(() => { }));
3739
+ promises.push(tagModule.editOpacity(tagId, targetOpacity).catch(() => { }));
3641
3740
  }
3642
3741
  }
3643
3742
  await Promise.all(promises);
3644
3743
  }
3744
+ /**
3745
+ * Drops the memoized opacity/enabled state so the next visibility pass re-applies it
3746
+ * to every tag. Needed after a view switch (furnished <-> defurnished): the SDK
3747
+ * re-renders the shared layer's tags and the cached values would otherwise make
3748
+ * updateTagsVisibilityForContext() skip them, leaving tags stuck invisible.
3749
+ */
3750
+ resetVisibilityCache() {
3751
+ this.tagsCurrentOpacity.clear();
3752
+ this.tagsCurrentEnabled.clear();
3753
+ }
3645
3754
  /** Removes a specific tag from the viewer and local dictionaries. */
3646
3755
  async deleteMattertagFromId(sdk, mattertagID) {
3647
3756
  try {
3648
3757
  if (sdk)
3649
- await sdk.Tag.remove(mattertagID);
3758
+ await this.getTagModule(sdk, mattertagID).remove(mattertagID);
3650
3759
  this.dictionnaryTags.delete(mattertagID);
3651
3760
  const index = this.mattertagIDs.indexOf(mattertagID);
3652
3761
  if (index > -1)
@@ -3669,7 +3778,7 @@ class MatterportTagService {
3669
3778
  const sidsToRemove = [...this.mattertagIDs];
3670
3779
  for (const sid of sidsToRemove) {
3671
3780
  try {
3672
- await sdk.Tag.remove(sid);
3781
+ await this.getTagModule(sdk, sid).remove(sid);
3673
3782
  }
3674
3783
  catch (e) { }
3675
3784
  }
@@ -3680,7 +3789,7 @@ class MatterportTagService {
3680
3789
  * Creates and configures a Mattertag from a POI, handling coordinates, normals, and sweep ID.
3681
3790
  * Skips creation if a tag for the object already exists.
3682
3791
  */
3683
- async createMattertagFromPOI(sdk, tagType, object, poi, poseCamera, getTagFromElementId, setTagIconAndOpacity, injectHtmlInTag) {
3792
+ async createMattertagFromPOI(sdk, tagType, object, poi, getTagFromElementId, setTagIconAndOpacity, injectHtmlInTag) {
3684
3793
  const { tag } = getTagFromElementId(object.id);
3685
3794
  if (tag)
3686
3795
  return;
@@ -3742,10 +3851,11 @@ class MatterportTagService {
3742
3851
  return;
3743
3852
  try {
3744
3853
  const iconName = `custom-icon-${mattertagID}`;
3854
+ const tagModule = this.getTagModule(sdk, mattertagID);
3745
3855
  await sdk.Asset.registerTexture(iconName, iconPath);
3746
- await sdk.Tag.editIcon(mattertagID, iconName);
3856
+ await tagModule.editIcon(mattertagID, iconName);
3747
3857
  if (applyOpacity) {
3748
- await sdk.Tag.editOpacity(mattertagID, opacity);
3858
+ await tagModule.editOpacity(mattertagID, opacity);
3749
3859
  }
3750
3860
  }
3751
3861
  catch (error) {
@@ -3809,16 +3919,17 @@ class MatterportTagService {
3809
3919
  if (html && html.trim().length > 0 && sdk) {
3810
3920
  const scriptTag = this.tagService.getScriptForTag(object, tagType);
3811
3921
  html += `${scriptTag}`;
3922
+ const tagModule = this.getTagModule(sdk, tagID);
3812
3923
  const [sandboxId, messenger] = await sdk.Tag.registerSandbox(html);
3813
3924
  const attachmentID = this.tagsAttachments[tagID];
3814
3925
  if (attachmentID) {
3815
3926
  try {
3816
- await sdk.Tag.detach(tagID, attachmentID);
3927
+ await tagModule.detach(tagID, attachmentID);
3817
3928
  }
3818
3929
  catch (e) { }
3819
3930
  }
3820
3931
  this.tagsAttachments[tagID] = sandboxId;
3821
- await sdk.Tag.attach(tagID, sandboxId);
3932
+ await tagModule.attach(tagID, sandboxId);
3822
3933
  // Attach the "View informations" handler in tooltip
3823
3934
  messenger.on(TagAction.DETAIL_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
3824
3935
  messenger.on(TagAction.TICKET_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
@@ -3831,11 +3942,12 @@ class MatterportTagService {
3831
3942
  else if (sdk) {
3832
3943
  const { comment, tagDescription } = this.tagService.getBillboardMediaToEmbed(object);
3833
3944
  if (comment) {
3945
+ const tagModule = this.getTagModule(sdk, tagID);
3834
3946
  // 1) Register the media attachment by passing the URL string(s).
3835
3947
  // registerAttachment returns an array of attachment IDs.
3836
3948
  const [attachmentID] = await sdk.Tag.registerAttachment(comment.externalLink);
3837
3949
  // 2) Attach the registered media to the tag.
3838
- await sdk.Tag.attach(tagID, attachmentID);
3950
+ await tagModule.attach(tagID, attachmentID);
3839
3951
  // 3) Determine media type for the billboard (PHOTO or VIDEO).
3840
3952
  // Use a simple heuristic: YouTube/Vimeo -> VIDEO, otherwise PHOTO.
3841
3953
  // The SDK exposes MediaType on the Tag namespace.
@@ -3843,7 +3955,7 @@ class MatterportTagService {
3843
3955
  const mediaType = isVideo ? sdk.Mattertag.MediaType.VIDEO : sdk.Mattertag.MediaType.PHOTO;
3844
3956
  // 4) Update the billboard text and media using editBillboard.
3845
3957
  // editBillboard accepts Partial<Tag.EditableProperties> such as label, description, media.
3846
- await sdk.Tag.editBillboard(tagID, {
3958
+ await tagModule.editBillboard(tagID, {
3847
3959
  label: object.title || 'Media',
3848
3960
  description: tagDescription || '',
3849
3961
  media: {
@@ -3869,9 +3981,14 @@ class MatterportTagService {
3869
3981
  /** Clears all local tag data and resets the addition queue. */
3870
3982
  clear() {
3871
3983
  this.dictionnaryTags.clear();
3984
+ this.tagsCurrentOpacity.clear();
3985
+ this.tagsCurrentEnabled.clear();
3872
3986
  this.tagAddQueue = Promise.resolve();
3873
3987
  this.mattertagToFollow = null;
3874
3988
  this.mattertagIDs = [];
3989
+ // A new space means a new SDK session, hence a new shared layer to create.
3990
+ this.sharedTagLayer = null;
3991
+ this.sharedTagLayerPromise = null;
3875
3992
  }
3876
3993
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, deps: [{ token: MatterportNavigationService }], target: i0.ɵɵFactoryTarget.Injectable });
3877
3994
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, providedIn: 'root' });
@@ -3987,6 +4104,15 @@ class MatterportService {
3987
4104
  this.navigationService.forbiddenSweeps = value;
3988
4105
  }
3989
4106
  tagAction = new Subject();
4107
+ /** Views (furnished, defurnished...) exposed by the SDK for the current space. */
4108
+ viewsByType = new Map();
4109
+ currentView = null;
4110
+ viewSubscriptions = [];
4111
+ /** Emits the active view every time the user switches between furnished/defurnished. */
4112
+ onViewChanged = new Subject();
4113
+ /** Delay left to the SDK to rebuild the layer's tags after a view switch. */
4114
+ static VIEW_SWITCH_REFRESH_DELAY_MS = 800;
4115
+ viewSwitchRestoreTimer = null;
3990
4116
  get mattertagToFollow() {
3991
4117
  return this.matterportTagService.mattertagToFollow;
3992
4118
  }
@@ -4142,7 +4268,9 @@ class MatterportService {
4142
4268
  default:
4143
4269
  break;
4144
4270
  }
4145
- this.sdk.Asset.registerTexture('icon-position', this.config.my_config.icon_position);
4271
+ this.sdk.Asset.registerTexture('icon-position', this.config.my_config.icon_position)
4272
+ .catch((e) => { if (isDevMode())
4273
+ console.warn('icon-position texture registration failed', e); });
4146
4274
  // Current Room (used for getting bounding box and eventually lazy load mattertag or object3D inside current Room)
4147
4275
  this.sdk.Room.current.subscribe((currentRoom) => {
4148
4276
  const rooms = Array.isArray(currentRoom) ? currentRoom : (currentRoom ? [currentRoom] : []);
@@ -4240,8 +4368,9 @@ class MatterportService {
4240
4368
  if (!this.sdk || sid === this.mattertagToFollow)
4241
4369
  return; // ignore when we are in positioning mode
4242
4370
  try {
4243
- if (this.sdk.Tag?.allowAction) {
4244
- this.sdk.Tag.allowAction(sid, { opening: true, navigating: true, docking: false });
4371
+ const tagModule = this.matterportTagService.getTagModule(this.sdk, sid);
4372
+ if (tagModule?.allowAction) {
4373
+ tagModule.allowAction(sid, { opening: true, navigating: true, docking: false });
4245
4374
  }
4246
4375
  }
4247
4376
  catch (e) {
@@ -4253,7 +4382,11 @@ class MatterportService {
4253
4382
  };
4254
4383
  // Wait for the application to reach PLAYING phase
4255
4384
  if (this.sdk.App && this.sdk.App.state) {
4256
- this.sdk.App.state.waitUntil((s) => s.phase === this.sdk.App.Phase.PLAYING).then(() => {
4385
+ this.sdk.App.state.waitUntil((s) => s.phase === this.sdk.App.Phase.PLAYING).then(async () => {
4386
+ // Create the common layer holding every tag before any tag is added, so that
4387
+ // tags are shared between the furnished and the defurnished views.
4388
+ await this.matterportTagService.ensureSharedTagLayer(this.sdk);
4389
+ this.initViews();
4257
4390
  this.sdk.Camera.pose.subscribe((pose) => {
4258
4391
  this.poseCamera = pose;
4259
4392
  this.matterportTagService.updateTagsVisibilityForContext(this.sdk, this.sweepCollection, this.navigationService.currentCameraMode, this.mattertagToFollow, this.navigationService.currentFloorSequence, this.navigationService.currentRooms);
@@ -4393,7 +4526,7 @@ class MatterportService {
4393
4526
  */
4394
4527
  enable_following_tag(mattertag) {
4395
4528
  const OFFSET = 0.0001; // quasi-invisible mais suffit à éviter l'interception
4396
- this.sdk.Tag.editPosition(mattertag, {
4529
+ this.matterportTagService.getTagModule(this.sdk, mattertag).editPosition(mattertag, {
4397
4530
  anchorPosition: {
4398
4531
  x: this.poseMatterport.position.x + OFFSET,
4399
4532
  y: this.poseMatterport.position.y,
@@ -4420,28 +4553,42 @@ class MatterportService {
4420
4553
  //
4421
4554
  /** Creates a temporary Mattertag that follows the user's cursor for positioning. */
4422
4555
  async addCursorMattertag(mattertagData) {
4556
+ if (!this.poseMatterport && this.poseCamera) {
4557
+ this.poseMatterport = {
4558
+ position: { ...this.poseCamera.position },
4559
+ normal: { x: 0, y: -0.15, z: 0 },
4560
+ time: new Date().getTime()
4561
+ };
4562
+ }
4423
4563
  if (!this.poseMatterport)
4424
4564
  return;
4425
4565
  this.mattertagToFollow = await this.addMattertagToViewer(mattertagData);
4566
+ if (!this.mattertagToFollow) {
4567
+ if (isDevMode())
4568
+ console.warn('addCursorMattertag: tag creation failed, mattertagToFollow is null');
4569
+ return;
4570
+ }
4426
4571
  await wait(50);
4427
- this.sdk.Tag.editIcon(this.mattertagToFollow, 'icon-position');
4428
- this.sdk.Tag.editOpacity(this.mattertagToFollow, 1);
4429
- this.sdk.Tag.editPosition(this.mattertagToFollow, {
4430
- anchorPosition: { ...this.poseMatterport.position },
4431
- stemVector: {
4432
- x: this.poseMatterport.normal.x * 0.3,
4433
- y: this.poseMatterport.normal.y * 0.3,
4434
- z: this.poseMatterport.normal.z * 0.3,
4435
- }
4436
- });
4572
+ const tagModule = this.matterportTagService.getTagModule(this.sdk, this.mattertagToFollow);
4437
4573
  try {
4438
- await this.sdk.Tag.allowAction(this.mattertagToFollow, {
4439
- opening: true,
4440
- navigating: false,
4441
- docking: false
4574
+ await tagModule.editIcon(this.mattertagToFollow, 'icon-position');
4575
+ await tagModule.editOpacity(this.mattertagToFollow, 1);
4576
+ await tagModule.editPosition(this.mattertagToFollow, {
4577
+ anchorPosition: { ...this.poseMatterport.position },
4578
+ stemVector: {
4579
+ x: (this.poseMatterport.normal?.x ?? 0) * 0.3,
4580
+ y: (this.poseMatterport.normal?.y ?? -0.15) * 0.3,
4581
+ z: (this.poseMatterport.normal?.z ?? 0) * 0.3,
4582
+ }
4442
4583
  });
4584
+ await tagModule.allowAction(this.mattertagToFollow, {
4585
+ opening: true, navigating: false, docking: false
4586
+ });
4587
+ }
4588
+ catch (e) {
4589
+ if (isDevMode())
4590
+ console.warn('addCursorMattertag: error configuring cursor tag', e);
4443
4591
  }
4444
- catch (e) { }
4445
4592
  }
4446
4593
  get tagAddQueue() {
4447
4594
  return this.matterportTagService.tagAddQueue;
@@ -4470,7 +4617,7 @@ class MatterportService {
4470
4617
  /** Applies a pre-registered icon to a Mattertag. */
4471
4618
  async setRegistredIconForTag(mattertagID, iconName) {
4472
4619
  try {
4473
- this.sdk.Tag.editIcon(mattertagID, iconName);
4620
+ this.matterportTagService.getTagModule(this.sdk, mattertagID).editIcon(mattertagID, iconName);
4474
4621
  }
4475
4622
  catch (e) {
4476
4623
  if (isDevMode())
@@ -4488,7 +4635,7 @@ class MatterportService {
4488
4635
  else {
4489
4636
  iconName = `${iconName}_unavailable`;
4490
4637
  }
4491
- this.sdk.Tag.editIcon(mattertagID, iconName);
4638
+ await this.editTagIcon(mattertagID, iconName);
4492
4639
  return;
4493
4640
  }
4494
4641
  const stringTagType = poiTypeToString(mattertagData.getType());
@@ -4520,11 +4667,19 @@ class MatterportService {
4520
4667
  opacity = tagIcon.opacity;
4521
4668
  }
4522
4669
  }
4670
+ await this.editTagIcon(mattertagID, iconName);
4671
+ }
4672
+ /**
4673
+ * Applies an icon to a tag. The call is awaited and its rejection reported: a
4674
+ * silently dropped promise here leaves the pin with its default white look.
4675
+ */
4676
+ async editTagIcon(mattertagID, iconName) {
4523
4677
  try {
4524
- this.sdk.Tag.editIcon(mattertagID, iconName);
4678
+ await this.matterportTagService.getTagModule(this.sdk, mattertagID).editIcon(mattertagID, iconName);
4525
4679
  }
4526
4680
  catch (error) {
4527
- console.log('Error editIcon or opacity', error);
4681
+ if (isDevMode())
4682
+ console.warn('[MatterportService] editIcon failed for', mattertagID, iconName, error);
4528
4683
  }
4529
4684
  }
4530
4685
  /** Navigates the camera to the most recently created tag. */
@@ -4545,12 +4700,9 @@ class MatterportService {
4545
4700
  await this.sdk.Camera.lookAt(position, {
4546
4701
  transition: this.sdk.Camera.TransitionType.FLY
4547
4702
  });
4548
- await this.sdk.Tag.open(mattertagID);
4549
- }
4550
- else {
4551
- // Fallback for cases where we don't have local data yet
4552
- await this.sdk.Tag.open(mattertagID);
4553
4703
  }
4704
+ // `open` only exists on the global Tag module, never on a layer-scoped one.
4705
+ await this.sdk.Tag.open(mattertagID);
4554
4706
  }
4555
4707
  catch (error) {
4556
4708
  if (isDevMode())
@@ -4634,6 +4786,9 @@ class MatterportService {
4634
4786
  .logo-link,
4635
4787
  .footer-logo,
4636
4788
  .bottom-ui,
4789
+ img.logo-image,
4790
+ img[class^="logo-image"],
4791
+ img[class*=" logo-image"],
4637
4792
  [data-testid="showcase-footer"] {
4638
4793
  opacity: 0 !important;
4639
4794
  visibility: hidden !important;
@@ -4660,7 +4815,7 @@ class MatterportService {
4660
4815
  */
4661
4816
  async updateMatterTagContentForTagID(mattertagID, object = null, tagType = null) {
4662
4817
  if (this.sdk) {
4663
- await this.sdk.Tag.editBillboard(mattertagID, this.dictionnaryTags.get(mattertagID).getData());
4818
+ await this.matterportTagService.getTagModule(this.sdk, mattertagID).editBillboard(mattertagID, this.dictionnaryTags.get(mattertagID).getData());
4664
4819
  }
4665
4820
  // Mise à jour de l'icône immédiate
4666
4821
  await this.matterportTagService.updateMatterTagContentForTagID(this.sdk, mattertagID, object, tagType, this.setTagIconAndOpacity.bind(this),
@@ -4703,7 +4858,7 @@ class MatterportService {
4703
4858
  * @returns
4704
4859
  */
4705
4860
  async createMattertagFromPOI(tagType, object, poi) {
4706
- return this.matterportTagService.createMattertagFromPOI(this.sdk, tagType, object, poi, this.poseCamera, this.getTagFromElementId.bind(this), this.setTagIconAndOpacity.bind(this), this.injectHtmlInTag.bind(this));
4861
+ return this.matterportTagService.createMattertagFromPOI(this.sdk, tagType, object, poi, this.getTagFromElementId.bind(this), this.setTagIconAndOpacity.bind(this), this.injectHtmlInTag.bind(this));
4707
4862
  }
4708
4863
  /**
4709
4864
  * Inject custom HTML as Mattertag content
@@ -4768,6 +4923,10 @@ class MatterportService {
4768
4923
  const mattertagData = new MattertagData(poiType);
4769
4924
  mattertagData.setSweepID(this.navigationService.resolveSweepUuid(this.poseCamera.sweep));
4770
4925
  mattertagData.setRotation(this.poseCamera.rotation);
4926
+ const initialPosition = this.poseMatterport?.position ?? this.poseCamera.position;
4927
+ const initialNormal = this.poseMatterport?.normal ?? { x: 0, y: -0.15, z: 0 };
4928
+ mattertagData.setPosition({ ...initialPosition });
4929
+ mattertagData.setNormal({ ...initialNormal });
4771
4930
  this.setInteractionMode(ViewerInteractions.ADDING);
4772
4931
  await this.addCursorMattertag(mattertagData);
4773
4932
  }
@@ -4885,8 +5044,14 @@ class MatterportService {
4885
5044
  }
4886
5045
  }
4887
5046
  async updateMatterTagPosInSdkViewer(mattertagID, object, poiType, poi = null) {
4888
- const IndexToUpdate = object.pois.items.findIndex((u) => u.id === poi.id);
4889
- object.pois.items[IndexToUpdate] = poi;
5047
+ if (!poi || !poi.coordinate) {
5048
+ console.warn('updateMatterTagPosInSdkViewer: poi or poi.coordinate is missing', poi);
5049
+ return;
5050
+ }
5051
+ const IndexToUpdate = object.pois?.items ? object.pois.items.findIndex((u) => u?.id === poi.id) : -1;
5052
+ if (IndexToUpdate !== -1 && object.pois?.items) {
5053
+ object.pois.items[IndexToUpdate] = poi;
5054
+ }
4890
5055
  const { x, y, z } = JSON.parse(poi.coordinate);
4891
5056
  const newPosition = {
4892
5057
  anchorPosition: {
@@ -4901,8 +5066,7 @@ class MatterportService {
4901
5066
  z: 0,
4902
5067
  },
4903
5068
  };
4904
- //this.sdk.Mattertag.editPosition(mattertagID, newPosition);
4905
- this.sdk.Tag.editPosition(mattertagID, newPosition);
5069
+ this.matterportTagService.getTagModule(this.sdk, mattertagID).editPosition(mattertagID, newPosition);
4906
5070
  this.dictionnaryTags
4907
5071
  .get(mattertagID)
4908
5072
  .setPosition(newPosition.anchorPosition);
@@ -4912,8 +5076,7 @@ class MatterportService {
4912
5076
  continue;
4913
5077
  }
4914
5078
  if (currentTag.elementID === object.id && tagId !== mattertagID) {
4915
- this.dictionnaryTags.delete(tagId);
4916
- this.sdk.Tag.remove(tagId);
5079
+ await this.matterportTagService.deleteMattertagFromId(this.sdk, tagId);
4917
5080
  break;
4918
5081
  }
4919
5082
  }
@@ -4955,6 +5118,140 @@ class MatterportService {
4955
5118
  return null;
4956
5119
  }
4957
5120
  //
5121
+ // ---------- Views (furnished / defurnished) ----------
5122
+ //
5123
+ /**
5124
+ * Subscribes to the SDK View API to keep track of the views available for the space
5125
+ * and of the active one. Tags live in a shared common layer, so a view change only
5126
+ * requires re-applying their visibility, never re-creating them.
5127
+ */
5128
+ initViews() {
5129
+ this.clearViewSubscriptions();
5130
+ this.viewsByType.clear();
5131
+ this.currentView = null;
5132
+ if (!this.sdk?.View?.views) {
5133
+ if (isDevMode())
5134
+ console.warn('[MatterportService] View API unavailable on this SDK version');
5135
+ return;
5136
+ }
5137
+ this.viewSubscriptions.push(this.sdk.View.views.subscribe({
5138
+ onCollectionUpdated: (collection) => {
5139
+ // SDK callbacks run outside Angular: re-enter the zone so the views made
5140
+ // available here (defurnish button...) are picked up by change detection.
5141
+ this.ngZone.run(() => {
5142
+ this.viewsByType.clear();
5143
+ for (const view of Object.values(collection)) {
5144
+ this.viewsByType.set(view.type, view);
5145
+ }
5146
+ });
5147
+ // Views are discovered progressively: make sure each one carries the shared
5148
+ // tag layer, otherwise its tags would not exist in that view.
5149
+ this.matterportTagService.attachSharedTagLayerToViews(this.sdk, Object.values(collection));
5150
+ },
5151
+ }));
5152
+ this.viewSubscriptions.push(this.sdk.View.current.subscribe((view) => {
5153
+ const changed = this.currentView?.id !== view?.id;
5154
+ this.currentView = view;
5155
+ if (!changed)
5156
+ return;
5157
+ this.restoreTagsForActiveView(view);
5158
+ this.ngZone.run(() => this.onViewChanged.next(view));
5159
+ }));
5160
+ }
5161
+ /**
5162
+ * Forces the opacity/enabled state to be pushed again to every tag. The SDK
5163
+ * re-renders the shared layer's tags on a view swap, and the memoized values would
5164
+ * otherwise make updateTagsVisibilityForContext() skip them, leaving tags invisible.
5165
+ */
5166
+ reapplyTagsVisibility() {
5167
+ this.matterportTagService.resetVisibilityCache();
5168
+ this.refreshTagsVisibility();
5169
+ }
5170
+ /**
5171
+ * Puts the tags back in shape in the view that just became active.
5172
+ *
5173
+ * Activating a view re-materializes the shared layer's tags from the descriptors
5174
+ * recorded when they were added, so everything applied to a tag *afterwards* through
5175
+ * the global Tag module is dropped along the way: the custom icon (the pin falls back
5176
+ * to the descriptor's white) and the sandbox carrying the hover content. They have to
5177
+ * be applied again on the freshly rebuilt tags.
5178
+ *
5179
+ * Visibility is refreshed straight away so the tags show up without waiting, then
5180
+ * content is re-applied once the transition is over — re-applying it too early would
5181
+ * target tags the SDK has not rebuilt yet.
5182
+ */
5183
+ restoreTagsForActiveView(view) {
5184
+ // A view only materializes its layers once activated: (re)attach the shared one.
5185
+ this.matterportTagService.attachSharedTagLayerToViews(this.sdk, [view])
5186
+ .then(() => this.reapplyTagsVisibility());
5187
+ this.reapplyTagsVisibility();
5188
+ clearTimeout(this.viewSwitchRestoreTimer);
5189
+ this.viewSwitchRestoreTimer = setTimeout(() => {
5190
+ this.refreshTagsContent()
5191
+ .catch((e) => {
5192
+ if (isDevMode())
5193
+ console.warn('[MatterportService] Cannot restore tags for view', view?.id, e);
5194
+ })
5195
+ .then(() => this.reapplyTagsVisibility());
5196
+ }, MatterportService.VIEW_SWITCH_REFRESH_DELAY_MS);
5197
+ }
5198
+ /**
5199
+ * Re-applies the icon and the injected HTML of every tag we own. Used after a view
5200
+ * switch, see restoreTagsForActiveView().
5201
+ */
5202
+ async refreshTagsContent() {
5203
+ if (!this.sdk)
5204
+ return;
5205
+ // Snapshot: the dictionary can be mutated while the awaits below are pending.
5206
+ for (const [sid, mattertagData] of [...this.dictionnaryTags]) {
5207
+ if (sid === this.mattertagToFollow)
5208
+ continue;
5209
+ await this.setTagIconAndOpacity(sid, mattertagData);
5210
+ this.injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), sid)
5211
+ .catch((err) => {
5212
+ if (isDevMode())
5213
+ console.warn('[MatterportService] HTML re-injection failed for', sid, err);
5214
+ });
5215
+ }
5216
+ }
5217
+ clearViewSubscriptions() {
5218
+ clearTimeout(this.viewSwitchRestoreTimer);
5219
+ this.viewSwitchRestoreTimer = null;
5220
+ for (const subscription of this.viewSubscriptions) {
5221
+ try {
5222
+ subscription.cancel();
5223
+ }
5224
+ catch (e) {
5225
+ if (isDevMode())
5226
+ console.warn('[MatterportService] Cannot cancel view subscription', e);
5227
+ }
5228
+ }
5229
+ this.viewSubscriptions = [];
5230
+ }
5231
+ /** True when the space provides a defurnished view. */
5232
+ get hasDefurnishView() {
5233
+ return this.viewsByType.has(MatterportViewType.DEFURNISH);
5234
+ }
5235
+ /** True when the defurnished view is the active one. */
5236
+ get isDefurnishedView() {
5237
+ return this.currentView?.type === MatterportViewType.DEFURNISH;
5238
+ }
5239
+ /**
5240
+ * Switches between the defurnished view and the furnished one.
5241
+ * @param returnToStart Move the camera back to the view's start location.
5242
+ */
5243
+ async toggleDefurnishView(returnToStart = false) {
5244
+ const target = this.isDefurnishedView
5245
+ ? this.viewsByType.get(MatterportViewType.LAYERED_BASE) ?? this.viewsByType.get(MatterportViewType.BASE)
5246
+ : this.viewsByType.get(MatterportViewType.DEFURNISH);
5247
+ if (!target) {
5248
+ if (isDevMode())
5249
+ console.warn('[MatterportService] No target view to switch to');
5250
+ return;
5251
+ }
5252
+ await target.setActive(returnToStart);
5253
+ }
5254
+ //
4958
5255
  // ---------- Viewer related (switch views, go to) ----------
4959
5256
  //
4960
5257
  async action_toolbox_floorplan() {
@@ -5006,6 +5303,9 @@ class MatterportService {
5006
5303
  */
5007
5304
  async clearAll() {
5008
5305
  console.log('removing viewer');
5306
+ this.clearViewSubscriptions();
5307
+ this.viewsByType.clear();
5308
+ this.currentView = null;
5009
5309
  await this.action_delete_all_mattertags();
5010
5310
  this.floors = null;
5011
5311
  this.sweeps = null;
@@ -5253,6 +5553,13 @@ class ViewerService {
5253
5553
  await this.actionAddObjectFromPOI(object, poi);
5254
5554
  }
5255
5555
  }));
5556
+ // Newly created tags have no opacity/allowAction applied yet (only set by
5557
+ // updateTagsVisibilityForContext, which runs on Mode/Sweep/Floor/Room/Camera
5558
+ // events). If this batch loaded after those fired, the tags stay in whatever
5559
+ // default state the SDK gave them until something else nudges a refresh.
5560
+ if (this.checkMode('Matterport')) {
5561
+ this.matterportService.refreshTagsVisibility();
5562
+ }
5256
5563
  }
5257
5564
  async actionAddObjectFromPOI(object, poi) {
5258
5565
  if (this.checkMode('Matterport')) {
@@ -14840,5 +15147,5 @@ function floatValidator() {
14840
15147
  * Generated bundle index. Do not edit.
14841
15148
  */
14842
15149
 
14843
- export { AffectationService, AvatarComponent, BaseLateralTabService, BaseTagService, BaseUserService, BaseVisibilityService, CameraMode, CaptureService, CaptureViewer, CommentService, CommentType, Config, ContentService, CsvExportComponent, DomainService, DomainType, DurationToStringPipe, EmailStatus, EquipmentService, EventService, EventStatus, EventType, FeatureService, FeatureType, FilterService, HashtagFromIdPipe, HashtagService, InterventionService, InventoryStatus, LayerService, LevelStatus, LoaderComponent, Locale, LocaleService, MATTERPORT_SDK_KEY, MatterportImportService, MatterportService, MatterportTagCopyService, MattertagActionMode, MattertagData, MeasurementService, MenuBarComponent, MissionService, NavigationService, NavigatorService, NgxSmarterplanCoreModule, NgxSmarterplanCoreService, NodeService, Object3DService, OperationService, OrganisationService, PaymentStatus, PlanService, PoiService, PoiType, ProfileEntity, ProfileService, ProfileStatus, PropertyService, PropertyType, RoleStatus, SafeUrlPipe, SearchBarComponent, SearchObjectType, SearchService, SpModule, SpaceService, SpaceStatus, StatusEquipment, SupportModalComponent, SupportService, TagAction, TemplateService, TicketPriority, TicketStatus, TicketType, TicketsService, TimeDateToLocalStringPipe, TypeNote, UsernameFromIdPipe, ValidatorsService, ViewerInteractions, ViewerService, VisitService, ZoneChangeService, ZoneService, applyRigidTransformToPoint, applyRigidTransformToYRotationDeg, arraysContainSameElements, checkElementById, computeRigidTransform, convertTimestampToLocalZone, copyFileInS3, dateHasExpired, dateTimeToLocalString, deleteFromS3, distance, downloadBlob, downloadEquipmentDocument, downloadFile, downloadFileAsObject, durationToString, emailValidator, enumToArray, filterUniqueArrayByID, floatValidator, getBufferForFileFromS3, getCoefficientsForImage, getCurrentLang, getDistanceBetweenTwoPoints, getHighestLevelForMissions, getHighestRoleForMissions, getLevelsBelow, getLocaleLong, getLocaleShort, getMetaForImage, getRolesBelowForManager, getSignedFile, getSignedImageUrlForEquipment, getSignedImageUrlForProfile, getSignedImageUrlForSpace, getSpaceIDFromUrl, getVisitUrl, isEmptyObject, listFilesInFolder, mean, noEmptyValidator, numberToDateString, openDocument, openModalForVisitSwitch, poiTypeToString, pointToString, removeAllFilesFromFolderS3, removeNullKeysFromObject, showScanPointsOnPlanInDiv, shuffleArray, sortAlphabeticallyOnName, stringLocaleToEnum, stringToLowercaseNoSpaces, styleButton, textValidator, translateDatePeriod, uploadBase64Image, uploadBase64ImageWithRetry, uploadFileToS3, uploadJsonToS3, validEmail, wait, waitUntil };
15150
+ export { AffectationService, AvatarComponent, BaseLateralTabService, BaseTagService, BaseUserService, BaseVisibilityService, CameraMode, CaptureService, CaptureViewer, CommentService, CommentType, Config, ContentService, CsvExportComponent, DomainService, DomainType, DurationToStringPipe, EmailStatus, EquipmentService, EventService, EventStatus, EventType, FeatureService, FeatureType, FilterService, HashtagFromIdPipe, HashtagService, InterventionService, InventoryStatus, LayerService, LevelStatus, LoaderComponent, Locale, LocaleService, MATTERPORT_SDK_KEY, MatterportImportService, MatterportService, MatterportTagCopyService, MatterportViewType, MattertagActionMode, MattertagData, MeasurementService, MenuBarComponent, MissionService, NavigationService, NavigatorService, NgxSmarterplanCoreModule, NgxSmarterplanCoreService, NodeService, Object3DService, OperationService, OrganisationService, PaymentStatus, PlanService, PoiService, PoiType, ProfileEntity, ProfileService, ProfileStatus, PropertyService, PropertyType, RoleStatus, SafeUrlPipe, SearchBarComponent, SearchObjectType, SearchService, SpModule, SpaceService, SpaceStatus, StatusEquipment, SupportModalComponent, SupportService, TagAction, TemplateService, TicketPriority, TicketStatus, TicketType, TicketsService, TimeDateToLocalStringPipe, TypeNote, UsernameFromIdPipe, ValidatorsService, ViewerInteractions, ViewerService, VisitService, ZoneChangeService, ZoneService, applyRigidTransformToPoint, applyRigidTransformToYRotationDeg, arraysContainSameElements, checkElementById, computeRigidTransform, convertTimestampToLocalZone, copyFileInS3, dateHasExpired, dateTimeToLocalString, deleteFromS3, distance, downloadBlob, downloadEquipmentDocument, downloadFile, downloadFileAsObject, durationToString, emailValidator, enumToArray, filterUniqueArrayByID, floatValidator, getBufferForFileFromS3, getCoefficientsForImage, getCurrentLang, getDistanceBetweenTwoPoints, getHighestLevelForMissions, getHighestRoleForMissions, getLevelsBelow, getLocaleLong, getLocaleShort, getMetaForImage, getRolesBelowForManager, getSignedFile, getSignedImageUrlForEquipment, getSignedImageUrlForProfile, getSignedImageUrlForSpace, getSpaceIDFromUrl, getVisitUrl, isEmptyObject, listFilesInFolder, mean, noEmptyValidator, numberToDateString, openDocument, openModalForVisitSwitch, poiTypeToString, pointToString, removeAllFilesFromFolderS3, removeNullKeysFromObject, showScanPointsOnPlanInDiv, shuffleArray, sortAlphabeticallyOnName, stringLocaleToEnum, stringToLowercaseNoSpaces, styleButton, textValidator, translateDatePeriod, uploadBase64Image, uploadBase64ImageWithRetry, uploadFileToS3, uploadJsonToS3, validEmail, wait, waitUntil };
14844
15151
  //# sourceMappingURL=smarterplan-ngx-smarterplan-core.mjs.map