@plattar/plattar-ar-adapter 1.155.3 → 1.155.4-b2

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.
@@ -8,6 +8,7 @@ export declare class ConfiguratorController extends PlattarController {
8
8
  private _cachedConfigState;
9
9
  getConfiguratorState(): Promise<DecodedConfiguratorState>;
10
10
  onAttributesUpdated(attributeName: string): Promise<void>;
11
+ startARQRCode(options: any): Promise<HTMLElement>;
11
12
  startViewerQRCode(options: any): Promise<HTMLElement>;
12
13
  startRenderer(): Promise<HTMLElement>;
13
14
  initAR(): Promise<LauncherAR>;
@@ -65,12 +65,58 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
65
65
  return;
66
66
  }
67
67
  }
68
+ async startARQRCode(options) {
69
+ try {
70
+ const dState = await this.getConfiguratorState();
71
+ // if this is declared, we have a furniture scene that we need to re-create the embed
72
+ // with new attributes
73
+ const product = dState.state.firstOfType("product");
74
+ if (product) {
75
+ this.parent.lockObserver();
76
+ this.parent.destroy();
77
+ this.setAttribute("product-id", product.scene_product_id);
78
+ this.parent.unlockObserver();
79
+ const controller = this.parent.create();
80
+ if (controller) {
81
+ return controller.startARQRCode(options);
82
+ }
83
+ return Promise.reject(new Error("ConfiguratorController.startARQRCode() - legacy product transition failed"));
84
+ }
85
+ }
86
+ catch (_err) {
87
+ }
88
+ return super.startARQRCode(options);
89
+ }
68
90
  async startViewerQRCode(options) {
69
91
  // remove the old renderer instance if any
70
92
  this.removeRenderer();
71
93
  const sceneID = this.getAttribute("scene-id");
72
94
  if (!sceneID) {
73
- throw new Error("ConfiguratorController.startQRCode() - minimum required attributes not set, use scene-id as a minimum");
95
+ throw new Error("ConfiguratorController.startViewerQRCode() - minimum required attributes not set, use scene-id as a minimum");
96
+ }
97
+ // optional attributes
98
+ let configState = null;
99
+ try {
100
+ const dState = await this.getConfiguratorState();
101
+ // if this is declared, we have a furniture scene that we need to re-create the embed
102
+ // with new attributes
103
+ const product = dState.state.firstOfType("product");
104
+ if (product) {
105
+ this.parent.lockObserver();
106
+ this.parent.destroy();
107
+ this.setAttribute("product-id", product.scene_product_id);
108
+ this.parent.unlockObserver();
109
+ const controller = this.parent.create();
110
+ if (controller) {
111
+ return controller.startViewerQRCode(options);
112
+ }
113
+ return Promise.reject(new Error("ConfiguratorController.startViewerQRCode() - legacy product transition failed"));
114
+ }
115
+ configState = dState.state.encode();
116
+ }
117
+ catch (_err) {
118
+ // config state is not available
119
+ configState = null;
74
120
  }
75
121
  const opt = options || this._GetDefaultQROptions();
76
122
  const viewer = document.createElement("plattar-qrcode");
@@ -91,17 +137,8 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
91
137
  }
92
138
  viewer.setAttribute("shorten", (opt.shorten && (opt.shorten === true || opt.shorten === "true")) ? "true" : "false");
93
139
  let dst = plattar_api_1.Server.location().base + "renderer/configurator.html?scene_id=" + sceneID;
94
- // optional attributes
95
- let configState = null;
96
140
  const showAR = this.getAttribute("show-ar");
97
141
  const showUI = this.getAttribute("show-ui");
98
- try {
99
- configState = (await this.getConfiguratorState()).state.encode();
100
- }
101
- catch (_err) {
102
- // config state is not available
103
- configState = null;
104
- }
105
142
  if (showUI && showUI === "true") {
106
143
  dst = plattar_api_1.Server.location().base + "configurator/dist/index.html?scene_id=" + sceneID;
107
144
  }
@@ -128,6 +165,30 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
128
165
  if (!sceneID) {
129
166
  throw new Error("ConfiguratorController.startRenderer() - minimum required attributes not set, use scene-id as a minimum");
130
167
  }
168
+ // optional attributes
169
+ let configState = null;
170
+ try {
171
+ const dState = await this.getConfiguratorState();
172
+ // if this is declared, we have a furniture scene that we need to re-create the embed
173
+ // with new attributes
174
+ const product = dState.state.firstOfType("product");
175
+ if (product) {
176
+ this.parent.lockObserver();
177
+ this.parent.destroy();
178
+ this.setAttribute("product-id", product.scene_product_id);
179
+ this.parent.unlockObserver();
180
+ const controller = this.parent.create();
181
+ if (controller) {
182
+ return controller.startRenderer();
183
+ }
184
+ return Promise.reject(new Error("ConfiguratorController.startRenderer() - legacy product transition failed"));
185
+ }
186
+ configState = dState;
187
+ }
188
+ catch (_err) {
189
+ // config state is not available
190
+ configState = null;
191
+ }
131
192
  // required attributes with defaults for plattar-configurator node
132
193
  const width = this.getAttribute("width") || "500px";
133
194
  const height = this.getAttribute("height") || "500px";
@@ -138,15 +199,6 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
138
199
  viewer.setAttribute("height", height);
139
200
  viewer.setAttribute("server", server);
140
201
  viewer.setAttribute("scene-id", sceneID);
141
- // optional attributes
142
- let configState = null;
143
- try {
144
- configState = await this.getConfiguratorState();
145
- }
146
- catch (_err) {
147
- // config state is not available
148
- configState = null;
149
- }
150
202
  const showAR = this.getAttribute("show-ar");
151
203
  const showUI = this.getAttribute("show-ui");
152
204
  if (configState) {
@@ -171,6 +223,26 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
171
223
  if (!util_1.Util.canAugment()) {
172
224
  throw new Error("ConfiguratorController.initAR() - cannot proceed as AR not available in context");
173
225
  }
226
+ try {
227
+ const dState = await this.getConfiguratorState();
228
+ // if this is declared, we have a furniture scene that we need to re-create the embed
229
+ // with new attributes
230
+ const product = dState.state.firstOfType("product");
231
+ if (product) {
232
+ this.parent.lockObserver();
233
+ this.parent.destroy();
234
+ this.setAttribute("product-id", product.scene_product_id);
235
+ this.parent.unlockObserver();
236
+ const controller = this.parent.create();
237
+ if (controller) {
238
+ return controller.initAR();
239
+ }
240
+ return Promise.reject(new Error("ConfiguratorController.initAR() - legacy product transition failed"));
241
+ }
242
+ }
243
+ catch (_err) {
244
+ // config state is not available
245
+ }
174
246
  const arMode = this.getAttribute("ar-mode") || "generated";
175
247
  switch (arMode.toLowerCase()) {
176
248
  case "inherited":
@@ -1,5 +1,6 @@
1
1
  import { LauncherAR } from "../../ar/launcher-ar";
2
2
  import { DecodedConfiguratorState } from "../../util/configurator-state";
3
+ import type PlattarEmbed from "../plattar-embed";
3
4
  export declare enum ControllerState {
4
5
  None = 0,
5
6
  Renderer = 1,
@@ -19,7 +20,7 @@ export declare abstract class PlattarController {
19
20
  protected _prevQROpt: any;
20
21
  private _selectVariationObserver;
21
22
  private _selectVariationSKUObserver;
22
- constructor(parent: HTMLElement);
23
+ constructor(parent: PlattarEmbed);
23
24
  /**
24
25
  * Generates a brand new Configurator State from the provided SceneID or inputted Configurator State
25
26
  */
@@ -82,13 +83,20 @@ export declare abstract class PlattarController {
82
83
  /**
83
84
  * Returns the Parent Instance
84
85
  */
85
- get parent(): HTMLElement;
86
+ get parent(): PlattarEmbed;
86
87
  /**
87
88
  * Returns the specified attribute from the parent
88
- * @param attribute - The name of thhe attribute
89
+ * @param attribute - The name of the attribute
89
90
  * @returns - The attribute value or null
90
91
  */
91
92
  getAttribute(attribute: string): string | null;
93
+ /**
94
+ * Sets a particular attribute into the HTML DOM
95
+ *
96
+ * @param attribute - The name of the attribute
97
+ * @param value - The value of the attribute
98
+ */
99
+ setAttribute(attribute: string, value: string): void;
92
100
  /**
93
101
  * Appends the provided element into the shadow-root of the parent element
94
102
  * @param element - The element to append
@@ -205,12 +205,23 @@ class PlattarController {
205
205
  }
206
206
  /**
207
207
  * Returns the specified attribute from the parent
208
- * @param attribute - The name of thhe attribute
208
+ * @param attribute - The name of the attribute
209
209
  * @returns - The attribute value or null
210
210
  */
211
211
  getAttribute(attribute) {
212
212
  return this.parent ? (this.parent.hasAttribute(attribute) ? this.parent.getAttribute(attribute) : null) : null;
213
213
  }
214
+ /**
215
+ * Sets a particular attribute into the HTML DOM
216
+ *
217
+ * @param attribute - The name of the attribute
218
+ * @param value - The value of the attribute
219
+ */
220
+ setAttribute(attribute, value) {
221
+ if (this.parent) {
222
+ this.parent.setAttribute(attribute, value);
223
+ }
224
+ }
214
225
  /**
215
226
  * Appends the provided element into the shadow-root of the parent element
216
227
  * @param element - The element to append
@@ -9,7 +9,6 @@ import { DecodedConfiguratorState } from "../../util/configurator-state";
9
9
  */
10
10
  export declare class ProductController extends PlattarController {
11
11
  getConfiguratorState(): Promise<DecodedConfiguratorState>;
12
- constructor(parent: HTMLElement);
13
12
  onAttributesUpdated(attributeName: string): Promise<void>;
14
13
  startViewerQRCode(options: any): Promise<HTMLElement>;
15
14
  /**
@@ -15,11 +15,6 @@ class ProductController extends plattar_controller_1.PlattarController {
15
15
  async getConfiguratorState() {
16
16
  throw new Error("ProductController.getConfiguratorState() - legacy embeds do not support configurator states");
17
17
  }
18
- constructor(parent) {
19
- // this is a hack against DecodedConfiguratorState that's now stored in PlattarController
20
- // this is not used in legacy mode
21
- super(parent);
22
- }
23
18
  async onAttributesUpdated(attributeName) {
24
19
  const state = this._state;
25
20
  // re-render the QR Code when attributes have changed
@@ -1,10 +1,12 @@
1
1
  import { LauncherAR } from "../ar/launcher-ar";
2
+ import { PlattarController } from "./controllers/plattar-controller";
2
3
  /**
3
4
  * This is the primary <plattar-embed /> node that allows easy embedding
4
5
  * of Plattar related content
5
6
  */
6
7
  export default class PlattarEmbed extends HTMLElement {
7
8
  private _currentType;
9
+ private _observerState;
8
10
  private _controller;
9
11
  private _currentSceneID;
10
12
  private _observer;
@@ -17,7 +19,15 @@ export default class PlattarEmbed extends HTMLElement {
17
19
  /**
18
20
  * creates a brand new instance of this embed
19
21
  */
20
- create(): void;
22
+ create(): PlattarController | null;
23
+ /**
24
+ * Locks the observer so attribute changes do not trigger anything
25
+ */
26
+ lockObserver(): void;
27
+ /**
28
+ * Unlocks the observer so attribute changes will start to re-trigger properly
29
+ */
30
+ unlockObserver(): void;
21
31
  /**
22
32
  * Destroys the active instance of this embed and resets internal state to default
23
33
  */
@@ -14,6 +14,14 @@ var EmbedType;
14
14
  EmbedType[EmbedType["VTO"] = 2] = "VTO";
15
15
  EmbedType[EmbedType["None"] = 3] = "None";
16
16
  })(EmbedType || (EmbedType = {}));
17
+ /**
18
+ * Controls the state of the observer
19
+ */
20
+ var ObserverState;
21
+ (function (ObserverState) {
22
+ ObserverState[ObserverState["Locked"] = 0] = "Locked";
23
+ ObserverState[ObserverState["Unlocked"] = 1] = "Unlocked";
24
+ })(ObserverState || (ObserverState = {}));
17
25
  /**
18
26
  * This is the primary <plattar-embed /> node that allows easy embedding
19
27
  * of Plattar related content
@@ -23,6 +31,7 @@ class PlattarEmbed extends HTMLElement {
23
31
  super();
24
32
  // this is the current embed type, viewer by default
25
33
  this._currentType = EmbedType.None;
34
+ this._observerState = ObserverState.Unlocked;
26
35
  this._controller = null;
27
36
  this._currentSceneID = null;
28
37
  this._observer = null;
@@ -45,17 +54,19 @@ class PlattarEmbed extends HTMLElement {
45
54
  plattar_api_1.Server.create(plattar_api_1.Server.match(server || "production"));
46
55
  if (!this._observer) {
47
56
  this._observer = new MutationObserver((mutations) => {
48
- mutations.forEach((mutation) => {
49
- if (mutation.type === "attributes") {
50
- const attributeName = mutation.attributeName ? mutation.attributeName : "none";
51
- if (this._currentType !== EmbedType.Legacy) {
52
- this._CreateEmbed(attributeName);
53
- }
54
- else {
55
- this._OnAttributesUpdated(attributeName);
57
+ if (this._observerState === ObserverState.Unlocked) {
58
+ mutations.forEach((mutation) => {
59
+ if (mutation.type === "attributes") {
60
+ const attributeName = mutation.attributeName ? mutation.attributeName : "none";
61
+ if (this._currentType !== EmbedType.Legacy) {
62
+ this._CreateEmbed(attributeName);
63
+ }
64
+ else {
65
+ this._OnAttributesUpdated(attributeName);
66
+ }
56
67
  }
57
- }
58
- });
68
+ });
69
+ }
59
70
  });
60
71
  this._observer.observe(this, {
61
72
  attributes: true
@@ -65,9 +76,22 @@ class PlattarEmbed extends HTMLElement {
65
76
  if (productID) {
66
77
  this._currentType = EmbedType.Legacy;
67
78
  this._CreateLegacyEmbed();
68
- return;
79
+ return this._controller;
69
80
  }
70
81
  this._CreateEmbed("none");
82
+ return this._controller;
83
+ }
84
+ /**
85
+ * Locks the observer so attribute changes do not trigger anything
86
+ */
87
+ lockObserver() {
88
+ this._observerState = ObserverState.Locked;
89
+ }
90
+ /**
91
+ * Unlocks the observer so attribute changes will start to re-trigger properly
92
+ */
93
+ unlockObserver() {
94
+ this._observerState = ObserverState.Unlocked;
71
95
  }
72
96
  /**
73
97
  * Destroys the active instance of this embed and resets internal state to default
@@ -1,4 +1,5 @@
1
1
  import { Scene } from "@plattar/plattar-api";
2
+ export type SceneProductDataMetaType = "sceneproduct" | "scenemodel" | "product";
2
3
  export interface SceneProductData {
3
4
  scene_product_id: string;
4
5
  product_variation_id: string;
@@ -6,7 +7,7 @@ export interface SceneProductData {
6
7
  }
7
8
  export interface SceneProductDataMeta {
8
9
  augment: boolean;
9
- type: "sceneproduct" | "scenemodel";
10
+ type: SceneProductDataMetaType;
10
11
  }
11
12
  export interface DecodedConfiguratorState {
12
13
  readonly scene: Scene;
@@ -47,6 +48,13 @@ export declare class ConfiguratorState {
47
48
  * @param metaData - Arbitrary meta-data that can be used against certain operaions
48
49
  */
49
50
  setSceneModel(SceneModelID: string, metaData?: SceneProductDataMeta | null | undefined): void;
51
+ /**
52
+ * Adds a new Product with meta-data into the Configurator State
53
+ *
54
+ * @param productID - The Product ID to add
55
+ * @param metaData - Arbitrary meta-data that can be used against certain operaions
56
+ */
57
+ setProduct(productID: string, productVariationID: string, metaData?: SceneProductDataMeta | null | undefined): void;
50
58
  /**
51
59
  * Adds a new Scene Product/Variation combo with meta-data into the Configurator State
52
60
  *
@@ -79,6 +87,10 @@ export declare class ConfiguratorState {
79
87
  * @returns Returns the first reference of data in the stack, otherwise returns null
80
88
  */
81
89
  first(): SceneProductData | null;
90
+ /**
91
+ * @returns Returns the first reference of data in the stack that matches a type, otherwise returns null
92
+ */
93
+ firstOfType(type: SceneProductDataMetaType): SceneProductData | null;
82
94
  get length(): number;
83
95
  /**
84
96
  * Decodes and returns an instance of ConfiguratorState from a previously
@@ -14,6 +14,7 @@ class ConfiguratorState {
14
14
  meta: {
15
15
  scene_product_index: 0,
16
16
  scene_model_index: 0,
17
+ product_index: 0,
17
18
  product_variation_index: 1,
18
19
  meta_index: 2,
19
20
  },
@@ -27,6 +28,7 @@ class ConfiguratorState {
27
28
  if (parsedState.meta) {
28
29
  defaultState.meta.scene_product_index = parsedState.meta.scene_product_index || 0;
29
30
  defaultState.meta.scene_model_index = parsedState.meta.scene_model_index || 0;
31
+ defaultState.meta.product_index = parsedState.meta.product_index || 0;
30
32
  defaultState.meta.product_variation_index = parsedState.meta.product_variation_index || 1;
31
33
  defaultState.meta.meta_index = parsedState.meta.meta_index || 2;
32
34
  }
@@ -103,6 +105,33 @@ class ConfiguratorState {
103
105
  newData[meta.meta_index] = metaData;
104
106
  }
105
107
  }
108
+ /**
109
+ * Adds a new Product with meta-data into the Configurator State
110
+ *
111
+ * @param productID - The Product ID to add
112
+ * @param metaData - Arbitrary meta-data that can be used against certain operaions
113
+ */
114
+ setProduct(productID, productVariationID, metaData = null) {
115
+ if (productID && productVariationID) {
116
+ metaData = metaData || { augment: true, type: "product" };
117
+ metaData.type = "product";
118
+ const states = this._state.states;
119
+ const meta = this._state.meta;
120
+ let newData = null;
121
+ const existingData = this.findSceneProductIndex(productID);
122
+ if (existingData) {
123
+ newData = existingData;
124
+ }
125
+ else {
126
+ newData = [];
127
+ // push the new data into the stack
128
+ states.push(newData);
129
+ }
130
+ newData[meta.product_index] = productID;
131
+ newData[meta.product_variation_index] = productVariationID;
132
+ newData[meta.meta_index] = metaData;
133
+ }
134
+ }
106
135
  /**
107
136
  * Adds a new Scene Product/Variation combo with meta-data into the Configurator State
108
137
  *
@@ -246,6 +275,35 @@ class ConfiguratorState {
246
275
  }
247
276
  return null;
248
277
  }
278
+ /**
279
+ * @returns Returns the first reference of data in the stack that matches a type, otherwise returns null
280
+ */
281
+ firstOfType(type) {
282
+ const states = this._state.states;
283
+ if (states.length > 0) {
284
+ const meta = this._state.meta;
285
+ const found = states.find((productState) => {
286
+ const check = productState[meta.scene_product_index];
287
+ if (check !== null && check !== undefined) {
288
+ return productState.length === 3 && productState[meta.meta_index].type === type;
289
+ }
290
+ return false;
291
+ });
292
+ if (!found) {
293
+ return null;
294
+ }
295
+ const data = {
296
+ scene_product_id: found[meta.scene_product_index],
297
+ product_variation_id: found[meta.product_variation_index],
298
+ meta_data: {
299
+ augment: found[meta.meta_index].augment || true,
300
+ type: found[meta.meta_index].type || type
301
+ }
302
+ };
303
+ return data;
304
+ }
305
+ return null;
306
+ }
249
307
  get length() {
250
308
  return this._state.states.length;
251
309
  }
@@ -271,6 +329,7 @@ class ConfiguratorState {
271
329
  const configState = new ConfiguratorState(state);
272
330
  const fscene = new plattar_api_1.Scene(sceneID);
273
331
  fscene.include(plattar_api_1.Project);
332
+ fscene.include(plattar_api_1.Product);
274
333
  fscene.include(plattar_api_1.SceneProduct);
275
334
  fscene.include(plattar_api_1.SceneModel);
276
335
  fscene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product.include(plattar_api_1.ProductVariation)));
@@ -295,18 +354,29 @@ class ConfiguratorState {
295
354
  fscene.include(plattar_api_1.Project);
296
355
  fscene.include(plattar_api_1.SceneProduct);
297
356
  fscene.include(plattar_api_1.SceneModel);
357
+ fscene.include(plattar_api_1.Product);
298
358
  fscene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product.include(plattar_api_1.ProductVariation)));
299
359
  const scene = await fscene.get();
300
360
  const sceneProducts = scene.relationships.filter(plattar_api_1.SceneProduct);
301
361
  const sceneModels = scene.relationships.filter(plattar_api_1.SceneModel);
302
- // add out scene models
362
+ const products = scene.relationships.filter(plattar_api_1.Product);
363
+ // add our scene models
303
364
  sceneModels.forEach((sceneModel) => {
304
365
  configState.setSceneModel(sceneModel.id, {
305
366
  augment: sceneModel.attributes.include_in_augment,
306
367
  type: "scenemodel"
307
368
  });
308
369
  });
309
- // add out scene products
370
+ // add our products - this is used when scene == furniture
371
+ products.forEach((product) => {
372
+ if (product.attributes.product_variation_id) {
373
+ configState.setProduct(product.id, product.attributes.product_variation_id, {
374
+ augment: true,
375
+ type: "product"
376
+ });
377
+ }
378
+ });
379
+ // add our scene products
310
380
  sceneProducts.forEach((sceneProduct) => {
311
381
  const product = sceneProduct.relationships.find(plattar_api_1.Product);
312
382
  if (product) {
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "1.155.3";
1
+ declare const _default: "1.155.4-b2";
2
2
  export default _default;
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = "1.155.3";
3
+ exports.default = "1.155.4-b2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plattar/plattar-ar-adapter",
3
- "version": "1.155.3",
3
+ "version": "1.155.4-b2",
4
4
  "description": "Plattar AR Adapter for interfacing with Google & Apple WebAR",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",