@configura/web-api 1.3.0-alpha.2 → 1.3.0-alpha.7

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.
Files changed (31) hide show
  1. package/dist/CatalogueAPI.d.ts +55 -1
  2. package/dist/CfgMeasure.d.ts +33 -0
  3. package/dist/CfgMeasure.js +30 -0
  4. package/dist/CfgProduct.d.ts +106 -5
  5. package/dist/CfgProduct.js +117 -71
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/material/CfgMaterialMapping.js +11 -6
  9. package/dist/material/CfgMtrlApplication.js +4 -4
  10. package/dist/productConfiguration/CfgFeature.d.ts +30 -4
  11. package/dist/productConfiguration/CfgFeature.js +162 -52
  12. package/dist/productConfiguration/CfgOption.d.ts +21 -5
  13. package/dist/productConfiguration/CfgOption.js +125 -24
  14. package/dist/productConfiguration/CfgProductConfiguration.d.ts +74 -4
  15. package/dist/productConfiguration/CfgProductConfiguration.js +158 -49
  16. package/dist/productConfiguration/utilitiesProductConfiguration.d.ts +9 -1
  17. package/dist/productConfiguration/utilitiesProductConfiguration.js +32 -13
  18. package/dist/productLoader.d.ts +22 -0
  19. package/dist/productLoader.js +22 -14
  20. package/dist/tests/testData/dummyProductForTest.js +1 -0
  21. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +13 -0
  22. package/dist/tests/testData/testDataCachedGetProduct.js +6 -0
  23. package/dist/tests/testData/testDataCachedPostValidate.js +6 -0
  24. package/dist/tests/testData/testDataNoAdditionalProductNoPropagateForTest.js +2 -0
  25. package/dist/tests/testData/testDataProductAggregatedPrice.js +6 -1
  26. package/dist/tests/testData/testDataUpcharge.js +4 -0
  27. package/dist/utilitiesCatalogueData.d.ts +5 -1
  28. package/dist/utilitiesCatalogueData.js +9 -1
  29. package/dist/utilitiesNumericValues.d.ts +25 -0
  30. package/dist/utilitiesNumericValues.js +109 -0
  31. package/package.json +3 -3
@@ -7,7 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { AggregatedLoadingObservable, compareArrays, count, Observable, } from "@configura/web-utilities";
10
+ import { AggregatedLoadingObservable, compareArrays, count, Observable, toLengthUnit, } from "@configura/web-utilities";
11
+ import { CfgMeasureDefinition } from "./CfgMeasure.js";
11
12
  import { ProductConfigurationBubbleMode } from "./productConfiguration/CfgOption.js";
12
13
  import { CfgProductConfiguration } from "./productConfiguration/CfgProductConfiguration.js";
13
14
  import { collectAdditionalProductRefs } from "./productConfiguration/utilitiesProductConfiguration.js";
@@ -20,21 +21,22 @@ function completeSettings(uncompleteSettings) {
20
21
  strictSetApiSelectionMatch: (_b = uncompleteSettings === null || uncompleteSettings === void 0 ? void 0 : uncompleteSettings.strictSetApiSelectionMatch) !== null && _b !== void 0 ? _b : false,
21
22
  };
22
23
  }
24
+ /**
25
+ * This enum is used internally in the SDK and is not expected by be used directly by integrators.
26
+ */
23
27
  export var CfgProductBubbleMode;
24
28
  (function (CfgProductBubbleMode) {
25
- /// Stop bubbling
26
- /// This mode is support for internal functionality is not expected to be used by integrators
29
+ /** Stop bubbling. */
27
30
  CfgProductBubbleMode["Stop"] = "Stop";
28
- /// Bubble to the parent CfgProduct up the tree. This makes the CfgProduct we
29
- /// we call from notify that it has changed, and the CfgProduct above switch out the reference
30
- /// to this.
31
- /// This mode is support for internal functionality is not expected to be used by integrators
31
+ /**
32
+ * Bubble to the parent CfgProduct up the tree.
33
+ * This makes the CfgProduct we we call from notify that it has changed, and the CfgProduct
34
+ * above switch out the reference to this.
35
+ */
32
36
  CfgProductBubbleMode["OneLevel"] = "OneLevel";
33
- /// Bubble to the root CfgProduct
34
- /// This mode is support for internal functionality is not expected to be used by integrators
37
+ /** Bubble to the root CfgProduct. */
35
38
  CfgProductBubbleMode["ToRoot"] = "ToRoot";
36
- /// Bubble to the root CfgProduct and turn on all optional CfgProducts on the way up
37
- /// This mode is support for internal functionality is not expected to be used by integrators
39
+ /** Bubble to the root CfgProduct and turn on all optional CfgProducts on the way up. */
38
40
  CfgProductBubbleMode["ToRootAndBubbleSelected"] = "ToRootAndBubbleSelected";
39
41
  })(CfgProductBubbleMode || (CfgProductBubbleMode = {}));
40
42
  function isDescriptionMatch(l, r) {
@@ -42,24 +44,27 @@ function isDescriptionMatch(l, r) {
42
44
  const rd = r.description;
43
45
  return ld !== undefined && rd !== undefined && ld.toLowerCase() === rd.toLowerCase();
44
46
  }
45
- /// This class is meant to only be used through CfgProduct. It should never
46
- /// be instantiated on its own. Normally the internal state of this class
47
- /// should never be directly modified. CfgProduct is the class that should
48
- /// be used and interacted with.
47
+ /**
48
+ * This class is meant to only be used through CfgProduct. It should never be instantiated on its
49
+ * own. Normally the internal state of this class should never be directly modified. CfgProduct is
50
+ * the class that should be used and interacted with.
51
+ */
49
52
  export class _CfgProductInternal {
50
- constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawProductData, apiSelection, loadingObservable, refKey, refDescription, parent, root, transform) {
53
+ constructor(initSuccess, initFail, _productLoaderRaw, lang, catId, partNumber, settings, optional, selected, rootFeatureRefs, allRawFeatures, uuid, _rawUnit, _rawProductData, apiSelection, loadingObservable, refKey, refDescription, parent, root, transform, anchor) {
51
54
  this._productLoaderRaw = _productLoaderRaw;
52
55
  this.lang = lang;
53
56
  this.catId = catId;
54
57
  this.partNumber = partNumber;
55
58
  this.settings = settings;
56
59
  this.uuid = uuid;
60
+ this._rawUnit = _rawUnit;
57
61
  this._rawProductData = _rawProductData;
58
62
  this.loadingObservable = loadingObservable;
59
63
  this.refKey = refKey;
60
64
  this.refDescription = refDescription;
61
65
  this.parent = parent;
62
66
  this.transform = transform;
67
+ this.anchor = anchor;
63
68
  this._destroyed = false;
64
69
  this.additionalProducts = [];
65
70
  this.changeObservable = new Observable();
@@ -84,7 +89,7 @@ export class _CfgProductInternal {
84
89
  : bubbleMode);
85
90
  }
86
91
  });
87
- /// Called when a child (additional product or the configuration) has changed
92
+ /** Called when a child (additional product or the configuration) has changed. */
88
93
  this._childHasChanged = (bubbleMode) => __awaiter(this, void 0, void 0, function* () {
89
94
  if (bubbleMode === CfgProductBubbleMode.ToRootAndBubbleSelected &&
90
95
  this.optional &&
@@ -94,7 +99,7 @@ export class _CfgProductInternal {
94
99
  }
95
100
  yield this._notifyAllOfChange(bubbleMode);
96
101
  });
97
- /// Called by child to tell its parent that it has changed.
102
+ /** Called by child to tell its parent that it has changed. */
98
103
  this._additionalProductHasChanged = (freshRef, bubbleMode) => __awaiter(this, void 0, void 0, function* () {
99
104
  const i = this.additionalProducts.findIndex((a) => a.isBackedBySame(freshRef));
100
105
  if (i !== -1) {
@@ -107,7 +112,7 @@ export class _CfgProductInternal {
107
112
  }
108
113
  yield this._childHasChanged(bubbleMode);
109
114
  });
110
- /// Called by the configuration to tell its parent that it has changed.
115
+ /** Called by the configuration to tell its parent that it has changed. */
111
116
  this._configurationHasChanged = (freshRef, bubbleMode) => __awaiter(this, void 0, void 0, function* () {
112
117
  this._configuration = freshRef;
113
118
  switch (bubbleMode) {
@@ -246,17 +251,18 @@ export class _CfgProductInternal {
246
251
  }
247
252
  return change;
248
253
  });
249
- /// Only features in selected options and selected additional products
254
+ /** Only features in selected options and selected additional products. */
250
255
  this._getDescendantFeaturesWithCode = (code) => this.additionalProducts.reduce((agg, additionalProduct) => {
251
256
  if (additionalProduct.selected) {
252
257
  agg.push(...additionalProduct._internal._getDescendantFeaturesWithCode(code));
253
258
  }
254
259
  return agg;
255
260
  }, this._configuration._internal._getFeaturesWithCode(code));
256
- /// Do a validate call for this product. It does not validate additional products, only
257
- /// this product in isolation. The validation result is applied on the configuration.
258
- /// Then additional products are synced (unloaded, loaded etc.) Finally the changes
259
- /// bubble up the tree.
261
+ /**
262
+ * Do a validate call for this product. It does not validate additional products, only this
263
+ * product in isolation. The validation result is applied on the configuration. Then additional
264
+ * products are synced (unloaded, loaded etc.) Finally the changes bubble up the tree.
265
+ */
260
266
  this._revalidate = (bubbleMode, productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
261
267
  const { _configuration: configuration } = this;
262
268
  const token = this.loadingObservable.startChildLoading();
@@ -306,8 +312,10 @@ export class _CfgProductInternal {
306
312
  this.loadingObservable.stopChildLoading(token);
307
313
  }
308
314
  });
309
- /// Based on this configuration find what additional products should be shown and not,
310
- /// unload (destroy) those that should no longer be shown, load the new ones.
315
+ /**
316
+ * Based on this configuration find what additional products should be shown and not, unload
317
+ * (i.e. destroy) those that should no longer be shown, load the new ones.
318
+ */
311
319
  this._syncAndLoadAdditionalProducts = (productLoaderForGroupedLoad) => __awaiter(this, void 0, void 0, function* () {
312
320
  const { lang, _productLoaderRaw: productLoaderRaw, rawProductData: productData, configuration, additionalProducts: currentAdditionalProducts, } = this;
313
321
  const additionalProductRefs = [
@@ -341,7 +349,7 @@ export class _CfgProductInternal {
341
349
  const additionalProductRef = p.prodRef;
342
350
  return {
343
351
  originalIndex: p.originalIndex,
344
- product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable, additionalProductRef.refKey, additionalProductRef.refDescription, this, this.root, additionalProductRef.transform)),
352
+ product: CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoaderRaw, productLoaderForGroupedLoad, lang, additionalProductRef.catId, additionalProductRef.partNumber, this.settings, additionalProductRef.optional === true, this.loadingObservable, additionalProductRef.refKey, additionalProductRef.refDescription, this, this.root, additionalProductRef.transform, additionalProductRef.anchor)),
345
353
  };
346
354
  }))()));
347
355
  if (this._destroyed) {
@@ -373,7 +381,7 @@ export class _CfgProductInternal {
373
381
  const product = yield new Promise((initSuccess, initFail) => {
374
382
  const p = new _CfgProductInternal(() => {
375
383
  initSuccess(p);
376
- }, initFail, this._productLoaderRaw, this.lang, this.catId, this.partNumber, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawProductData, this.configuration.getApiSelection(), new AggregatedLoadingObservable(), this.refKey, this.refDescription, parent, root, this.transform);
384
+ }, initFail, this._productLoaderRaw, this.lang, this.catId, this.partNumber, this.settings, this.optional, this.selected, this._configuration.rootFeatureRefs, this._configuration.allRawFeatures, this.uuid, this._rawUnit, this._rawProductData, this.configuration.getApiSelection(), new AggregatedLoadingObservable(), this.refKey, this.refDescription, parent, root, this.transform, this.anchor);
377
385
  });
378
386
  for (const additionalProduct of this.additionalProducts) {
379
387
  product.additionalProducts.push(CfgProduct._makeNewRefFrom(yield additionalProduct._internal.clone(product, root || product)));
@@ -399,6 +407,22 @@ export class _CfgProductInternal {
399
407
  get prices() {
400
408
  return this._rawProductData.partsData.prices;
401
409
  }
410
+ get measureDefinitions() {
411
+ var _a;
412
+ if (this._measureDefinitions === undefined) {
413
+ this._measureDefinitions = ((_a = this._rawProductData.measurements) !== null && _a !== void 0 ? _a : [])
414
+ .map((m) => CfgMeasureDefinition.make(m))
415
+ .filter((m) => m !== undefined);
416
+ }
417
+ return this._measureDefinitions;
418
+ }
419
+ /** @throws an error if the actual unit sent by the server was not a LengthUnit */
420
+ get unit() {
421
+ if (this._unit === undefined) {
422
+ this._unit = toLengthUnit(this._rawUnit);
423
+ }
424
+ return this._unit;
425
+ }
402
426
  get aggregatedPrice() {
403
427
  const { currency, fractionDigits, rawProductData } = this;
404
428
  const { partsData } = rawProductData;
@@ -448,20 +472,20 @@ export class _CfgProductInternal {
448
472
  }
449
473
  }
450
474
  _CfgProductInternal.make = (productLoaderRaw, productLoaderForGroupedLoad, // Used when instantiating the current product
451
- lang, catId, partNumber, settings, optional, loadingObservable, refKey, refDescription, parent, root, transform) => __awaiter(void 0, void 0, void 0, function* () {
475
+ lang, catId, partNumber, settings, optional, loadingObservable, refKey, refDescription, parent, root, transform, anchor) => __awaiter(void 0, void 0, void 0, function* () {
452
476
  // wrap with cache will make getProduct for this function call use the same server call
453
477
  // for the same product with the same params
454
478
  productLoaderForGroupedLoad =
455
479
  productLoaderForGroupedLoad || wrapWithCache(productLoaderRaw);
456
480
  const productResponse = yield productLoaderForGroupedLoad.getProduct(Object.assign(Object.assign({ lang }, correctDefaultsOnCatalogueParams(catId)), { partNumber }));
457
- const { productData, rootFeatureRefs, features: allRawFeatures, uuid } = productResponse;
481
+ const { productData, rootFeatureRefs, features: allRawFeatures, uuid, unit, } = productResponse;
458
482
  const product = yield new Promise((initSuccess, initFail) => {
459
483
  const p = new _CfgProductInternal(() => {
460
484
  // We absolutely do not want anyone to assign to this._configuration. So we want that field private.
461
485
  // But we can not set the api selection synchronously. And the product configuration needs "this". So we use this callback.
462
486
  // Feel free to find a nicer more readable solution :)
463
487
  initSuccess(p);
464
- }, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, productData, productData.partsData.selOptions || [], loadingObservable, refKey, refDescription, parent, root, transform);
488
+ }, initFail, productLoaderRaw, lang, catId, partNumber, settings, optional, !optional, rootFeatureRefs, allRawFeatures, uuid, unit, productData, productData.partsData.selOptions || [], loadingObservable, refKey, refDescription, parent, root, transform, anchor);
465
489
  });
466
490
  yield product._syncAndLoadAdditionalProducts(productLoaderForGroupedLoad);
467
491
  return product;
@@ -470,35 +494,40 @@ export class CfgProduct {
470
494
  constructor(_internal) {
471
495
  this._internal = _internal;
472
496
  this.isBackedBySame = (other) => this._internal === other._internal;
473
- /// Recursively marks this and descendants as destroyed so that late events
474
- /// are ignored correctly.
475
- /// If you destroy one shallow copy of this you destroy all.
497
+ /**
498
+ * Recursively marks this and descendants as destroyed so that late events are ignored
499
+ * correctly. If you destroy one shallow copy of this you destroy all.
500
+ */
476
501
  this.destroy = () => this._internal.destroy();
477
- /// Makes a clone of this. It is disconnected from the original.
502
+ /** Makes a clone of this. It is disconnected from the original. */
478
503
  this.clone = () => __awaiter(this, void 0, void 0, function* () { return CfgProduct._makeNewRefFrom(yield this._internal.clone()); });
479
- /// Only applicable when this product is optional.
480
- /// Setting this does not cause a validation call as toggling an optional additional
481
- /// product is assumed to always be legal.
504
+ /**
505
+ * Only applicable when this product is optional.
506
+ * Setting this does not cause a validation call as toggling an optional additional product is
507
+ * assumed to always be legal.
508
+ */
482
509
  this.setSelected = (v) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setSelected(v, CfgProductBubbleMode.ToRootAndBubbleSelected); });
483
- /// Experimental. Additional products lacks descriptions or keys that are suitably for structure
484
- /// compare, so we use strict-order when trying to match the additional products. This makes
485
- /// this method work nicely for different products having pretty much the same child products.
510
+ /**
511
+ * Experimental. Additional products lacks descriptions or keys that are suitably for structure
512
+ * compare, so we use strict-order when trying to match the additional products. This makes
513
+ * this method work nicely for different products having pretty much the same child products.
514
+ */
486
515
  this.structureCompare = (other, strictOrder = true, descriptionMatch = false) => this._internal.structureCompare(other._internal, strictOrder, descriptionMatch);
487
- /// Experimental. Additional products lacks descriptions or keys that are suitably for try
488
- /// match, so we use strict-order when trying to match the additional products. This makes
489
- /// this method work nicely for different products having pretty much the same child products.
490
- /// This method does not propagate its selections.
491
- /// This method will cause validation calls if something change.
516
+ /**
517
+ * Experimental. Additional products lacks descriptions or keys that are suitably for try
518
+ * match, so we use strict-order when trying to match the additional products. This makes
519
+ * this method work nicely for different products having pretty much the same child products.
520
+ * This method does not propagate its selections.
521
+ * This method will cause validation calls if something change.
522
+ */
492
523
  this.tryMatchSelection = (other, descriptionMatch = false // Match on case insensitive description, not code
493
524
  ) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.tryMatchSelection(other._internal, descriptionMatch); });
494
- /// Gets what selections has been made on the product, recursively including product configuration,
495
- /// optional products and additional products. Used when a full view of all selections on a product
496
- /// is needed, such as when doing Render or Export.
525
+ /**
526
+ * Gets what selections has been made on the product, recursively including product
527
+ * configuration, optional products and additional products. Used when a full view of all
528
+ * selections on a product is needed, such as when doing Render or Export.
529
+ */
497
530
  this.getApiSelection = () => this._internal.getApiSelection();
498
- /// Experimental. The API currently never sends ApiSelections for products with additional products
499
- /// downstream, so this is only provided as a convenience function if someone would for instance want
500
- /// to store previous selection states of a product by doing getApiSelection.
501
- /// This method does not propagate its selections.
502
531
  this.setApiSelection = (s, doValidate = false) => __awaiter(this, void 0, void 0, function* () { return yield this._internal.setApiSelection(s, doValidate); });
503
532
  this.listenForChange = (l) => this._internal.changeObservable.listen(l);
504
533
  this.stopListenForChange = (l) => this._internal.changeObservable.stopListen(l);
@@ -507,14 +536,31 @@ export class CfgProduct {
507
536
  this.stopListenForLoading = (l) => this._internal.loadingObservable.stopListen(l);
508
537
  this.stopAllListenForLoading = () => this._internal.loadingObservable.stopAllListen();
509
538
  }
510
- /// A client side only key that should uniquely identify this product amongst
511
- /// other additional products.
539
+ static make(productLoader, lang, catId, partNumber, settings) {
540
+ return __awaiter(this, void 0, void 0, function* () {
541
+ return this._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined, undefined, undefined, undefined));
542
+ });
543
+ }
544
+ /**
545
+ * Makes an object wrapping the passed object. This is not a clone method, it is a method to
546
+ * make a new outer reference. Like a shallow copy./ We use this to help frameworks that are
547
+ * build around using equals to detect change.
548
+ */
549
+ static _makeNewRefFrom(source) {
550
+ return new this(source);
551
+ }
552
+ /**
553
+ * A client side only key that should uniquely identify this product amongst other additional
554
+ * products.
555
+ */
512
556
  get key() {
513
557
  return this._internal.key;
514
558
  }
515
- /// Only used when this product is in additional product. As a product can
516
- /// have multiple instances of the same additional product this key exists.
517
- /// It will be unique amongst child products, but not globally unique.
559
+ /**
560
+ * Only used when this product is in additional product.
561
+ * As a product can have multiple instances of the same additional product this key exists.
562
+ * It will be unique amongst child products, but not globally unique.
563
+ */
518
564
  get refKey() {
519
565
  return this._internal.refKey;
520
566
  }
@@ -530,12 +576,14 @@ export class CfgProduct {
530
576
  get isAdditionalProduct() {
531
577
  return this._internal.isAdditionalProduct;
532
578
  }
533
- /// Only used when this product is an additional product. Root products are never optional.
579
+ /** Only used when this product is an additional product. Root products are never optional. */
534
580
  get optional() {
535
581
  return this._internal.optional;
536
582
  }
537
- /// Only applicable when this product is optional. If this product is not
538
- /// optional this is always true.
583
+ /**
584
+ * Only applicable when this product is optional. If this product is not optional this is
585
+ * always true.
586
+ */
539
587
  get selected() {
540
588
  return this._internal.selected;
541
589
  }
@@ -545,13 +593,16 @@ export class CfgProduct {
545
593
  get uuid() {
546
594
  return this._internal.uuid;
547
595
  }
596
+ get unit() {
597
+ return this._internal.unit;
598
+ }
548
599
  get sku() {
549
600
  return this._internal.rawProductData.sku;
550
601
  }
551
602
  get styleNr() {
552
603
  return this._internal.rawProductData.partsData.styleNr;
553
604
  }
554
- /// An URL
605
+ /** An URL. */
555
606
  get preview() {
556
607
  return this._internal.rawProductData.navImage;
557
608
  }
@@ -570,8 +621,10 @@ export class CfgProduct {
570
621
  get currency() {
571
622
  return this._internal.currency;
572
623
  }
573
- /// If positive the number of fraction digits, if negative
574
- /// rounding (essentially the number of zeros to the right)
624
+ /**
625
+ * If positive the number of fraction digits.
626
+ * If negative rounding (essentially the number of zeros to the right)
627
+ */
575
628
  get fractionDigits() {
576
629
  return this._internal.fractionDigits;
577
630
  }
@@ -579,10 +632,3 @@ export class CfgProduct {
579
632
  return this._internal.aggregatedPrice;
580
633
  }
581
634
  }
582
- CfgProduct.make = (productLoader, lang, catId, partNumber, settings) => __awaiter(void 0, void 0, void 0, function* () {
583
- return CfgProduct._makeNewRefFrom(yield _CfgProductInternal.make(productLoader, undefined, lang, catId, partNumber, completeSettings(settings), false, new AggregatedLoadingObservable(), undefined, undefined, undefined, undefined, undefined));
584
- });
585
- /// Makes an object wrapping the passed object. This is not a clone method,
586
- /// it is a method to make a new outer reference. Like a shallow copy.
587
- /// We use this to help frameworks that are build around using equals to detect change.
588
- CfgProduct._makeNewRefFrom = (source) => new CfgProduct(source);
package/dist/index.d.ts CHANGED
@@ -13,4 +13,5 @@ export * from "./productConfiguration/productParamsGenerator.js";
13
13
  export * from "./productLoader.js";
14
14
  export * from "./utilitiesCatalogueData.js";
15
15
  export * from "./utilitiesCataloguePermission.js";
16
+ export * from "./utilitiesNumericValues.js";
16
17
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -13,3 +13,4 @@ export * from "./productConfiguration/productParamsGenerator.js";
13
13
  export * from "./productLoader.js";
14
14
  export * from "./utilitiesCatalogueData.js";
15
15
  export * from "./utilitiesCataloguePermission.js";
16
+ export * from "./utilitiesNumericValues.js";
@@ -2,15 +2,19 @@ import { CfgMtrlSourceBuffer, CfgMtrlSourceUrl } from "./CfgMtrlSource.js";
2
2
  // In this file an "application" is a combination of 0..1 Material (Mtrl) and 0..m AreaTags.
3
3
  // These can exist on Catalogue-level (Application Areas), Product-level, in the Feature-Options
4
4
  // tree (Configuration) and for the sake of debugging, locally as debug overrides.
5
+ //
5
6
  // What this file is about is reducing/aggregating/compiling this to a simple map which says that
6
7
  // Area1 should have material Jeans etc. The code is written to match the behavior in CET.
8
+ //
7
9
  // Side note: There is no connection in material application between products
8
10
  // in a product with additional products. So there exists no methods for
9
11
  // aggregating over multiple products at all.
10
- /// When there are multiple applications on the same node we need to reduce these to what is
11
- /// actually applied. The cases where there multiple applications on the same node affecting
12
- /// the same thing are probably user errors i Catalogue Creator. However, Catalogue Creator
13
- /// allows the user to let them slip through, so we need to handle them the same way CET does.
12
+ /**
13
+ * When there are multiple applications on the same node we need to reduce these to what is
14
+ * actually applied. The cases where there multiple applications on the same node affecting the
15
+ * same thing are probably user errors i Catalogue Creator. However, Catalogue Creator allows the
16
+ * user to let them slip through, so we need to handle them the same way CET does.
17
+ */
14
18
  const reduceApplications = (applications, skipNoMtrl = false) => applications.reduce((acc, application) => {
15
19
  const { areaTags, mtrl } = application;
16
20
  // Applications which have a Mtrl but no AreaTags only have meaning on Option nodes. That
@@ -80,8 +84,9 @@ export function aggregateAllMaterialApplications(applicationAreas, productMtrlAp
80
84
  }
81
85
  return areasToMaterials;
82
86
  }
83
- /// For this Feature and it's descendants, compile the Applications
84
- /// into the passed areasToMaterials.
87
+ /**
88
+ * For this Feature and it's descendants, compile the Applications into the passed areasToMaterials.
89
+ */
85
90
  function aggregateForFeature(feature, areasToMaterials, areasOpenForOverrideInOption = new Set()) {
86
91
  const featureMtrlApplications = feature._internal.mtrlApplications;
87
92
  for (const [areaTag, mtrlSource] of reduceApplications(featureMtrlApplications)) {
@@ -8,17 +8,17 @@ export class CfgMtrlApplication {
8
8
  this._previewUrl = _previewUrl;
9
9
  }
10
10
  static fromUrlForDebug(areaTags, url) {
11
- return CfgMtrlApplication.fromMtrlSourceForDebug(areaTags, new CfgMtrlSourceUrl(url, "debug"));
11
+ return this.fromMtrlSourceForDebug(areaTags, new CfgMtrlSourceUrl(url, "debug"));
12
12
  }
13
13
  static fromBufferForDebug(areaTags, fileName, buffer) {
14
- return CfgMtrlApplication.fromMtrlSourceForDebug(areaTags, new CfgMtrlSourceBuffer(fileName, buffer));
14
+ return this.fromMtrlSourceForDebug(areaTags, new CfgMtrlSourceBuffer(fileName, buffer));
15
15
  }
16
16
  static fromMtrlSourceForDebug(areaTags, mtrlSource) {
17
17
  const ts = areaTags.filter((t) => t.trim() !== "");
18
18
  if (ts.length === 0) {
19
19
  throw Error("No tags");
20
20
  }
21
- return new CfgMtrlApplication(CfgMtrlApplicationSource.Debug, areaTags, mtrlSource, undefined);
21
+ return new this(CfgMtrlApplicationSource.Debug, areaTags, mtrlSource, undefined);
22
22
  }
23
23
  static fromMtrlLikeApplication(source, application) {
24
24
  const materialUrl = application.material;
@@ -26,7 +26,7 @@ export class CfgMtrlApplication {
26
26
  const url = materialUrl || previewUrl;
27
27
  const urlIsFromProperty = materialUrl ? "material" : "preview";
28
28
  const mtrl = url ? new CfgMtrlSourceUrl(url, urlIsFromProperty) : undefined;
29
- return new CfgMtrlApplication(source, application.areas, mtrl, previewUrl);
29
+ return new this(source, application.areas, mtrl, previewUrl);
30
30
  }
31
31
  get source() {
32
32
  return this._source;
@@ -1,4 +1,4 @@
1
- import { Observable, SingleArgCallback } from "@configura/web-utilities";
1
+ import { LengthUnit, Observable, SingleArgCallback } from "@configura/web-utilities";
2
2
  import { Feature, SelectedOption } from "../CatalogueAPI.js";
3
3
  import { CfgProduct, _CfgProductInternal } from "../CfgProduct.js";
4
4
  import { CfgMtrlApplication } from "../material/CfgMtrlApplication.js";
@@ -33,10 +33,11 @@ export declare class _CfgFeatureInternal {
33
33
  private readonly allRawFeatures;
34
34
  readonly key: string;
35
35
  readonly parent: _CfgProductConfigurationInternal | _CfgOptionInternal;
36
+ readonly parentConfiguration: _CfgProductConfigurationInternal;
36
37
  readonly parentProduct: _CfgProductInternal;
37
38
  readonly rootProduct: _CfgProductInternal;
38
39
  constructor(rawFeature: Feature, allRawFeatures: Feature[], key: string, // Unique amongst siblings
39
- parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
40
+ parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal);
40
41
  readonly selectionType: SelectionType;
41
42
  private _options;
42
43
  private readonly _selectedOptions;
@@ -45,7 +46,17 @@ export declare class _CfgFeatureInternal {
45
46
  readonly changeObservable: Observable<FeatureChangeNotification>;
46
47
  get code(): string;
47
48
  get groupCode(): string | undefined;
49
+ get isUseNumericValue(): boolean;
50
+ get numericValue(): number | undefined;
51
+ setNumericValue: (val: number) => Promise<boolean>;
48
52
  get description(): string;
53
+ /**
54
+ * The MeasureParam class is re-used for different purposes. In Features it is used
55
+ * to indicate which stretch measures inside Models shall be affected by this state
56
+ * of this Feature. Hence only the code property is used.
57
+ */
58
+ get measureParamCodes(): string[] | undefined;
59
+ get unit(): LengthUnit;
49
60
  get mtrlApplications(): CfgMtrlApplication[];
50
61
  get selectedOptions(): CfgOption[];
51
62
  get ancestorsSelected(): boolean;
@@ -72,6 +83,8 @@ export declare class _CfgFeatureInternal {
72
83
  setApiSelection: (apiOptionSelectionMap: {
73
84
  [index: string]: SelectedOption;
74
85
  } | undefined) => Promise<boolean>;
86
+ /** Pushes to refresh stretch. Does not cause validation. */
87
+ pushStretch: () => Promise<boolean>;
75
88
  structureCompare: (other: _CfgFeatureInternal, strictOrder?: boolean, descriptionMatch?: boolean) => boolean;
76
89
  tryMatchSelection: (other: _CfgFeatureInternal, descriptionMatch?: boolean) => Promise<boolean>;
77
90
  /**
@@ -94,13 +107,13 @@ export declare class _CfgFeatureInternal {
94
107
  }
95
108
  export declare class CfgFeature {
96
109
  readonly _internal: _CfgFeatureInternal;
97
- static make: (rawFeature: Feature, allRawFeatures: Feature[], key: string, parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal) => CfgFeature;
110
+ static make(rawFeature: Feature, allRawFeatures: Feature[], key: string, parent: _CfgProductConfigurationInternal | _CfgOptionInternal, parentConfiguration: _CfgProductConfigurationInternal, parentProduct: _CfgProductInternal, rootProduct: _CfgProductInternal): CfgFeature;
98
111
  /**
99
112
  * Makes an object wrapping the passed object. This is not a clone method,
100
113
  * it is a method to make a new outer reference. Like a shallow copy.
101
114
  * We use this to help frameworks that are built around using equals to detect change.
102
115
  */
103
- static _makeNewRefFrom: (internal: _CfgFeatureInternal) => CfgFeature;
116
+ static _makeNewRefFrom(internal: _CfgFeatureInternal): CfgFeature;
104
117
  /**
105
118
  * Private constructor and make-method because make new ref requires the constructor to
106
119
  * take an internal and we don't want those who instantiate CfgFeature to have to be aware
@@ -114,6 +127,19 @@ export declare class CfgFeature {
114
127
  get key(): string;
115
128
  get code(): string;
116
129
  get groupCode(): string | undefined;
130
+ /**
131
+ * If true the options in the feature is selected by both sending its code and numeric value
132
+ * when selecting.
133
+ */
134
+ get isUseNumericValue(): boolean;
135
+ /** This will read the numeric value of the selected option. */
136
+ get numericValue(): number | undefined;
137
+ /**
138
+ * This will find the first option allowing the value, set the value on it and select it.
139
+ * This is an implicit option-select.
140
+ */
141
+ setNumericValue: (val: number) => Promise<boolean>;
142
+ get unit(): LengthUnit;
117
143
  get description(): string;
118
144
  get hasUpcharge(): boolean | undefined;
119
145
  get selectedOptions(): CfgOption[];