@meshmakers/octo-meshboard 3.4.530 → 3.4.550

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.
package/README.md CHANGED
@@ -72,6 +72,36 @@ To set a Well-Known Name for a MeshBoard:
72
72
 
73
73
  The Well-Known Name should be lowercase with hyphens, similar to URL slugs.
74
74
 
75
+ ### URL Sync on Board Switch (`meshBoardSyncUrl`)
76
+
77
+ After a post-init board switch (e.g. via the manager dialog), the view syncs the
78
+ loaded board's rtId into the URL:
79
+
80
+ - If the active route has an `:rtId` param, the last URL segment is replaced —
81
+ always enabled, no configuration needed.
82
+ - If the route has **no** `:rtId` param, appending the rtId is **opt-in** via
83
+ the `meshBoardSyncUrl: true` route data flag. Only set it when a matching
84
+ `<path>/:rtId` sibling route exists:
85
+
86
+ ```typescript
87
+ {
88
+ path: "meshboards",
89
+ loadComponent: () =>
90
+ import('@meshmakers/octo-meshboard').then(m => m.MeshBoardViewComponent),
91
+ data: { meshBoardSyncUrl: true }
92
+ },
93
+ {
94
+ path: "meshboards/:rtId",
95
+ loadComponent: () =>
96
+ import('@meshmakers/octo-meshboard').then(m => m.MeshBoardViewComponent)
97
+ }
98
+ ```
99
+
100
+ Without the flag, embedded boards (e.g. readonly `meshBoardWellKnownName`
101
+ routes) never rewrite the URL. Appending an rtId to a route without an
102
+ `:rtId` variant would fall through to the app's `'**'` wildcard route (bouncing
103
+ the user back to home) or fail with a `NavigationError` (AB#4457).
104
+
75
105
  ## Architecture
76
106
 
77
107
  ```
@@ -30766,6 +30766,31 @@ function placeWidgetsForTier(widgets, tier, configuredColumns) {
30766
30766
  }));
30767
30767
  }
30768
30768
 
30769
+ /**
30770
+ * Returns the URL to navigate to after a board load/switch, or `null` when the
30771
+ * URL must not be rewritten.
30772
+ *
30773
+ * - Route has an `:rtId` param → the last path segment is replaced.
30774
+ * - `meshBoardSyncUrl: true` route data → the rtId is appended (the host app
30775
+ * guarantees a matching `<path>/:rtId` sibling route).
30776
+ * - Otherwise → `null` (embedded boards never rewrite the URL).
30777
+ *
30778
+ * Query parameters are preserved in all cases.
30779
+ */
30780
+ function buildUrlWithRtId(input) {
30781
+ const { currentUrl, rtId, hasRtIdParam, syncUrlOptIn } = input;
30782
+ const [pathPart, queryPart] = currentUrl.split('?');
30783
+ const querySuffix = queryPart ? '?' + queryPart : '';
30784
+ if (hasRtIdParam) {
30785
+ const lastSlashIndex = pathPart.lastIndexOf('/');
30786
+ return pathPart.substring(0, lastSlashIndex + 1) + rtId + querySuffix;
30787
+ }
30788
+ if (syncUrlOptIn) {
30789
+ return `${pathPart}/${rtId}${querySuffix}`;
30790
+ }
30791
+ return null;
30792
+ }
30793
+
30769
30794
  /**
30770
30795
  * Component for editing MeshBoard variables.
30771
30796
  * Allows adding, editing, and removing static variables with type-specific input controls.
@@ -32149,24 +32174,23 @@ class MeshBoardViewComponent {
32149
32174
  }
32150
32175
  }
32151
32176
  /**
32152
- * Updates the URL to include the current MeshBoard rtId.
32153
- * Preserves existing query parameters.
32177
+ * Updates the URL to include the current MeshBoard rtId, preserving query
32178
+ * parameters. Only rewrites the URL when the route can represent the rtId:
32179
+ * the route has an `:rtId` param, or the host app opted in with the
32180
+ * `meshBoardSyncUrl: true` route data flag (which requires a matching
32181
+ * `<path>/:rtId` sibling route). Embedded boards without either stay on
32182
+ * their URL — appending would fall through to the app's `'**'` wildcard or
32183
+ * fail with a NavigationError (AB#4457).
32154
32184
  */
32155
32185
  updateUrlWithRtId(rtId) {
32156
- const currentUrl = this.router.url;
32157
- const hasRtIdParam = this.route.snapshot.paramMap.has('rtId');
32158
- // Split off query string to preserve it
32159
- const [pathPart, queryPart] = currentUrl.split('?');
32160
- const querySuffix = queryPart ? '?' + queryPart : '';
32161
- if (hasRtIdParam) {
32162
- // Replace the last URL segment (the old rtId) with the new one
32163
- const lastSlashIndex = pathPart.lastIndexOf('/');
32164
- const newPath = pathPart.substring(0, lastSlashIndex + 1) + rtId;
32165
- this.router.navigateByUrl(newPath + querySuffix, { replaceUrl: true });
32166
- }
32167
- else {
32168
- // Append the rtId to the current URL
32169
- this.router.navigateByUrl(`${pathPart}/${rtId}${querySuffix}`, { replaceUrl: true });
32186
+ const targetUrl = buildUrlWithRtId({
32187
+ currentUrl: this.router.url,
32188
+ rtId,
32189
+ hasRtIdParam: this.route.snapshot.paramMap.has('rtId'),
32190
+ syncUrlOptIn: this.route.snapshot.data['meshBoardSyncUrl'] === true
32191
+ });
32192
+ if (targetUrl !== null) {
32193
+ this.router.navigateByUrl(targetUrl, { replaceUrl: true });
32170
32194
  }
32171
32195
  }
32172
32196
  async ngOnInit() {