powerpagestoolkit 2.5.4111 → 2.5.4212

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
@@ -99,23 +99,25 @@ Out of the box, Microsoft does not provide PowerPages developers the ability to
99
99
  _Method signature:_
100
100
 
101
101
  ```typescript
102
- DOMNodeReference.configureConditionalRendering(
102
+ configureConditionalRendering(
103
103
  condition: () => boolean,
104
104
  dependencies?: Array<DOMNodeReference>,
105
105
  clearValuesOnHide: boolean = true
106
- ): DOMNodeReference
106
+ ): DOMNodeReference /* Instance of this returned
107
+ for optional method chaining */
107
108
  ```
108
109
 
109
110
  _Example implementation:_
110
111
 
111
112
  ```typescript
112
113
  node.configureConditionalRendering(
113
- // Function to evaluate wether this node should be visible or not
114
- function () {
114
+ function () // Function to evaluate wether this node should be visible or not
115
+ {
115
116
  return otherNode.value === "some value";
116
117
  },
117
118
  [otherNode] /* Dependency array | if the values or visibility of these
118
119
  change, the function is re-evaluated */,
120
+
119
121
  true /* should the values in the targeted elements (this.element)
120
122
  be cleared if this node is hidden? Default = true */
121
123
  );
@@ -128,12 +130,11 @@ This utility enhances PowerPages forms by adding dynamic field validation and co
128
130
  _Method signature:_
129
131
 
130
132
  ```typescript
131
- // Core method for setting up validation
132
- function configureValidationAndRequirements(
133
- isRequired: () => boolean, // Determines if field is required
134
- isValid: () => boolean, // Validates field content
135
- fieldDisplayName: string, // User-facing field name for error messages
136
- dependencies: DOMNodeReference[] // Fields that trigger validation checks
133
+ configureValidationAndRequirements(
134
+ isRequired: () => boolean,
135
+ isValid: () => boolean,
136
+ fieldDisplayName: string,
137
+ dependencies: DOMNodeReference[]
137
138
  ): DOMNodeReference; /* instance of this is returned for optional
138
139
  method chaining */
139
140
  ```
@@ -218,6 +219,20 @@ node.addTooltip(
218
219
  );
219
220
  ```
220
221
 
222
+ _Example:_
223
+
224
+ ```typescript
225
+ import { createRef } from "powerpagestoolkit";
226
+
227
+ const title = await createRef("h1");
228
+
229
+ title.setInnerHTML("Hello World");
230
+ title.addTooltip("This is an Example of a tooltip!", { color: "red" });
231
+ ```
232
+
233
+ ![Example](./assets//infoIconExample.gif)
234
+
235
+
221
236
  ### DataVerse API
222
237
 
223
238
  Perform secure API calls to DataVerse from your PowerPages site. This method implements the shell deferred token to send requests with `__RequestVerificationToken`
Binary file
@@ -3,6 +3,8 @@ export default class DOMNodeReference {
3
3
  target: HTMLElement | string;
4
4
  private isLoaded;
5
5
  private defaultDisplay;
6
+ private observers;
7
+ private boundEventListeners;
6
8
  /**
7
9
  * The value of the element that this node represents
8
10
  * stays in syncs with the live DOM elements?.,m via event handler
@@ -13,7 +15,7 @@ export default class DOMNodeReference {
13
15
  * Made available in order to perform normal DOM traversal,
14
16
  * or access properties not available through this class.
15
17
  */
16
- element: Element;
18
+ element: HTMLElement;
17
19
  private visibilityController;
18
20
  checked: boolean;
19
21
  /**
@@ -41,11 +43,6 @@ export default class DOMNodeReference {
41
43
  */
42
44
  private _initValueSync;
43
45
  private _initDateSync;
44
- /**
45
- * Updates the value and checked state based on element type
46
- * @public
47
- */
48
- updateValue(): void;
49
46
  /**
50
47
  * Gets the current value of the element based on its type
51
48
  * @private
@@ -59,6 +56,13 @@ export default class DOMNodeReference {
59
56
  private _updateRadioGroup;
60
57
  private _attachVisibilityController;
61
58
  private _attachRadioButtons;
59
+ private _bindMethods;
60
+ private _destroy;
61
+ /**
62
+ * Updates the value and checked state based on element type
63
+ * @public
64
+ */
65
+ updateValue(): void;
62
66
  /**
63
67
  * Sets up an event listener based on the specified event type, executing the specified
64
68
  * event handler
@@ -67,7 +71,7 @@ export default class DOMNodeReference {
67
71
  * specified event occurs.
68
72
  * @returns - Instance of this [provides option to method chain]
69
73
  */
70
- on(eventType: string, eventHandler: (e: Event) => void): DOMNodeReference;
74
+ on(eventType: keyof HTMLElementEventMap, eventHandler: (e: Event) => void): DOMNodeReference;
71
75
  /**
72
76
  * Hides the element by setting its display style to "none".
73
77
  * @returns - Instance of this [provides option to method chain]
@@ -100,7 +104,8 @@ export default class DOMNodeReference {
100
104
  disable(): DOMNodeReference;
101
105
  /**
102
106
  * Clears all values and states of the element.
103
- * Handles different input types appropriately.
107
+ * Handles different input types appropriately, and can be called
108
+ * on an element containing N child inputs to clear all
104
109
  *
105
110
  * @returns - Instance of this [provides option to method chain]
106
111
  * @throws If clearing values fails
@@ -180,25 +185,25 @@ export default class DOMNodeReference {
180
185
  * Configures conditional rendering for the target element based on a condition
181
186
  * and the visibility of one or more trigger elements.
182
187
  *
183
- * @param {() => boolean} condition - A function that returns a boolean to determine
188
+ * @param condition - A function that returns a boolean to determine
184
189
  * the visibility of the target element. If `condition()` returns true, the element is shown;
185
190
  * otherwise, it is hidden.
186
- * @param {Array<DOMNodeReference>} [dependencies] - An array of `DOMNodeReference` instances. Event listeners are
191
+ * @param dependencies - An array of `DOMNodeReference` instances. Event listeners are
187
192
  * registered on each to toggle the visibility of the target element based on the `condition` and the visibility of
188
193
  * the target node.
189
- * @throws {ConditionalRenderingError} When there's an error in setting up conditional rendering
190
- * @returns {DOMNodeReference} - Instance of this [provides option to method chain]
194
+ * @throws - When there's an error in setting up conditional rendering
195
+ * @returns - Instance of this [provides option to method chain]
191
196
  */
192
197
  configureConditionalRendering(condition: () => boolean, dependencies?: Array<DOMNodeReference>, clearValuesOnHide?: boolean): DOMNodeReference;
193
198
  /**
194
199
  * Sets up validation and requirement rules for the field with enhanced error handling and dynamic updates.
195
200
  *
196
- * @param {() => boolean} isRequired - Function determining if field is required
197
- * @param {() => boolean} isValid - Function validating field input
198
- * @param {string} fieldDisplayName - Display name for error messages
199
- * @param {Array<DOMNodeReference>} dependencies - Fields that trigger requirement/validation updates
200
- * @returns {DOMNodeReference} Instance of this
201
- * @throws {ValidationConfigError} If validation setup fails
201
+ * @param isRequired - Function determining if field is required
202
+ * @param isValid - Function validating field input
203
+ * @param fieldDisplayName - Display name for error messages
204
+ * @param dependencies - Fields that trigger requirement/validation updates
205
+ * @returns - Instance of this
206
+ * @throws - If validation setup fails
202
207
  */
203
208
  configureValidationAndRequirements(isRequired: () => boolean, isValid: () => boolean, fieldDisplayName: string, dependencies: Array<DOMNodeReference>): DOMNodeReference;
204
209
  /**
@@ -212,7 +217,7 @@ export default class DOMNodeReference {
212
217
  /**
213
218
  * Sets the required level for the field by adding or removing the "required-field" class on the label.
214
219
  *
215
- * @param {Function | boolean} isRequired - Determines whether the field should be marked as required.
220
+ * @param isRequired - Determines whether the field should be marked as required.
216
221
  * If true, the "required-field" class is added to the label; if false, it is removed.
217
222
  * @returns - Instance of this [provides option to method chain]
218
223
  */
@@ -221,7 +226,8 @@ export default class DOMNodeReference {
221
226
  * Executes a callback function once the element is fully loaded.
222
227
  * If the element is already loaded, the callback is called immediately.
223
228
  * Otherwise, a MutationObserver is used to detect when the element is added to the DOM.
224
- * @param {Function} callback - A callback function to execute once the element is loaded.
229
+ * @param callback - A callback function to execute once the element is loaded.
230
+ * Receives instance of 'this' as an argument
225
231
  */
226
232
  onceLoaded(callback: (instance: DOMNodeReference) => any): any;
227
233
  }
package/dist/bundle.js CHANGED
@@ -234,6 +234,8 @@ var DOMNodeReference = class _DOMNodeReference {
234
234
  target;
235
235
  isLoaded;
236
236
  defaultDisplay;
237
+ observers;
238
+ boundEventListeners;
237
239
  /**
238
240
  * The value of the element that this node represents
239
241
  * stays in syncs with the live DOM elements?.,m via event handler
@@ -250,7 +252,9 @@ var DOMNodeReference = class _DOMNodeReference {
250
252
  this.isLoaded = false;
251
253
  this.defaultDisplay = "";
252
254
  this.value = null;
253
- this.updateValue = this.updateValue.bind(this);
255
+ this.observers = [];
256
+ this.boundEventListeners = [];
257
+ this._bindMethods();
254
258
  }
255
259
  async [_init]() {
256
260
  try {
@@ -265,9 +269,23 @@ var DOMNodeReference = class _DOMNodeReference {
265
269
  this._initValueSync();
266
270
  this._attachVisibilityController();
267
271
  this.defaultDisplay = this.visibilityController.style.display;
272
+ const observer = new MutationObserver((mutations) => {
273
+ for (const mutation of mutations) {
274
+ if (Array.from(mutation.removedNodes).includes(this.element)) {
275
+ this._destroy();
276
+ observer.disconnect();
277
+ break;
278
+ }
279
+ }
280
+ });
281
+ observer.observe(document.body, {
282
+ childList: true,
283
+ subtree: true
284
+ });
268
285
  this.isLoaded = true;
269
- } catch (e) {
270
- throw new DOMNodeInitializationError(this, e);
286
+ } catch (error) {
287
+ const errorMessage = error instanceof Error ? error.message : String(error);
288
+ throw new DOMNodeInitializationError(this, errorMessage);
271
289
  }
272
290
  }
273
291
  /**
@@ -297,6 +315,13 @@ var DOMNodeReference = class _DOMNodeReference {
297
315
  eventType = "input";
298
316
  }
299
317
  this.element.addEventListener(eventType, this.updateValue);
318
+ const _element = this.element;
319
+ const _updateValue = this.updateValue;
320
+ this.boundEventListeners.push({
321
+ element: _element,
322
+ handler: _updateValue,
323
+ event: eventType
324
+ });
300
325
  if (this.element instanceof HTMLInputElement && this.element.dataset.type === "date") {
301
326
  await this._initDateSync(this.element);
302
327
  }
@@ -314,18 +339,12 @@ var DOMNodeReference = class _DOMNodeReference {
314
339
  }
315
340
  const dateNode = await waitFor("[data-date-format]", parentElement);
316
341
  dateNode.addEventListener("select", this.updateValue);
317
- }
318
- /**
319
- * Updates the value and checked state based on element type
320
- * @public
321
- */
322
- updateValue() {
323
- const elementValue = this._getElementValue();
324
- this.value = elementValue.value;
325
- if (elementValue.checked !== void 0) {
326
- this.checked = elementValue.checked;
327
- }
328
- this._updateRadioGroup();
342
+ const _handler = this.updateValue;
343
+ this.boundEventListeners.push({
344
+ element: dateNode,
345
+ handler: _handler,
346
+ event: "select"
347
+ });
329
348
  }
330
349
  /**
331
350
  * Gets the current value of the element based on its type
@@ -401,6 +420,44 @@ var DOMNodeReference = class _DOMNodeReference {
401
420
  this.yesRadio = await createDOMNodeReference(`#${this.element.id}_1`);
402
421
  this.noRadio = await createDOMNodeReference(`#${this.element.id}_0`);
403
422
  }
423
+ _bindMethods() {
424
+ for (const key of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
425
+ const value = this[key];
426
+ if (key !== "constructor" && typeof value === "function") {
427
+ this[key] = value.bind(this);
428
+ }
429
+ }
430
+ }
431
+ _destroy() {
432
+ if (this.boundEventListeners.length > 0) {
433
+ this.boundEventListeners.forEach((binding) => {
434
+ binding.element?.removeEventListener(binding.event, binding.handler);
435
+ });
436
+ }
437
+ if (this.observers.length > 0) {
438
+ this.observers.forEach((observer) => {
439
+ observer.disconnect();
440
+ });
441
+ }
442
+ this.yesRadio?._destroy();
443
+ this.noRadio?._destroy();
444
+ this.yesRadio = null;
445
+ this.noRadio = null;
446
+ this.isLoaded = false;
447
+ this.value = null;
448
+ }
449
+ /**
450
+ * Updates the value and checked state based on element type
451
+ * @public
452
+ */
453
+ updateValue() {
454
+ const elementValue = this._getElementValue();
455
+ this.value = elementValue.value;
456
+ if (elementValue.checked !== void 0) {
457
+ this.checked = elementValue.checked;
458
+ }
459
+ this._updateRadioGroup();
460
+ }
404
461
  /**
405
462
  * Sets up an event listener based on the specified event type, executing the specified
406
463
  * event handler
@@ -410,17 +467,19 @@ var DOMNodeReference = class _DOMNodeReference {
410
467
  * @returns - Instance of this [provides option to method chain]
411
468
  */
412
469
  on(eventType, eventHandler) {
413
- if (typeof eventType !== "string") {
414
- throw new Error(
415
- `Argument "eventType" must be of type "string". Received: ${typeof eventType}`
416
- );
417
- }
418
470
  if (typeof eventHandler !== "function") {
419
471
  throw new Error(
420
472
  `Argument "eventHandler" must be a Function. Received: ${typeof eventHandler}`
421
473
  );
422
474
  }
423
475
  this.element.addEventListener(eventType, eventHandler.bind(this));
476
+ const _element = this.element;
477
+ const _handler = eventHandler;
478
+ this.boundEventListeners.push({
479
+ element: _element,
480
+ handler: _handler,
481
+ event: eventType
482
+ });
424
483
  return this;
425
484
  }
426
485
  /**
@@ -479,16 +538,18 @@ var DOMNodeReference = class _DOMNodeReference {
479
538
  disable() {
480
539
  try {
481
540
  this.element.disabled = true;
482
- } catch (e) {
541
+ } catch (error) {
542
+ const errorMessage = error instanceof Error ? error.message : String(error);
483
543
  throw new Error(
484
- `There was an error trying to disable the target: ${this.target}`
544
+ `There was an error trying to disable the target: ${this.target}: "${errorMessage}"`
485
545
  );
486
546
  }
487
547
  return this;
488
548
  }
489
549
  /**
490
550
  * Clears all values and states of the element.
491
- * Handles different input types appropriately.
551
+ * Handles different input types appropriately, and can be called
552
+ * on an element containing N child inputs to clear all
492
553
  *
493
554
  * @returns - Instance of this [provides option to method chain]
494
555
  * @throws If clearing values fails
@@ -532,11 +593,11 @@ var DOMNodeReference = class _DOMNodeReference {
532
593
  this.element.querySelectorAll("input, select, textarea")
533
594
  );
534
595
  if (childInputs.length > 0) {
535
- const clearPromises = childInputs.map(async (input) => {
596
+ const promises = childInputs.map(async (input) => {
536
597
  const inputRef = await createDOMNodeReference(input, false);
537
598
  return inputRef.clearValue();
538
599
  });
539
- await Promise.all(clearPromises);
600
+ await Promise.all(promises);
540
601
  }
541
602
  }
542
603
  if (this.yesRadio instanceof _DOMNodeReference && this.noRadio instanceof _DOMNodeReference) {
@@ -686,14 +747,14 @@ var DOMNodeReference = class _DOMNodeReference {
686
747
  * Configures conditional rendering for the target element based on a condition
687
748
  * and the visibility of one or more trigger elements.
688
749
  *
689
- * @param {() => boolean} condition - A function that returns a boolean to determine
750
+ * @param condition - A function that returns a boolean to determine
690
751
  * the visibility of the target element. If `condition()` returns true, the element is shown;
691
752
  * otherwise, it is hidden.
692
- * @param {Array<DOMNodeReference>} [dependencies] - An array of `DOMNodeReference` instances. Event listeners are
753
+ * @param dependencies - An array of `DOMNodeReference` instances. Event listeners are
693
754
  * registered on each to toggle the visibility of the target element based on the `condition` and the visibility of
694
755
  * the target node.
695
- * @throws {ConditionalRenderingError} When there's an error in setting up conditional rendering
696
- * @returns {DOMNodeReference} - Instance of this [provides option to method chain]
756
+ * @throws - When there's an error in setting up conditional rendering
757
+ * @returns - Instance of this [provides option to method chain]
697
758
  */
698
759
  configureConditionalRendering(condition, dependencies, clearValuesOnHide = true) {
699
760
  try {
@@ -728,12 +789,12 @@ var DOMNodeReference = class _DOMNodeReference {
728
789
  /**
729
790
  * Sets up validation and requirement rules for the field with enhanced error handling and dynamic updates.
730
791
  *
731
- * @param {() => boolean} isRequired - Function determining if field is required
732
- * @param {() => boolean} isValid - Function validating field input
733
- * @param {string} fieldDisplayName - Display name for error messages
734
- * @param {Array<DOMNodeReference>} dependencies - Fields that trigger requirement/validation updates
735
- * @returns {DOMNodeReference} Instance of this
736
- * @throws {ValidationConfigError} If validation setup fails
792
+ * @param isRequired - Function determining if field is required
793
+ * @param isValid - Function validating field input
794
+ * @param fieldDisplayName - Display name for error messages
795
+ * @param dependencies - Fields that trigger requirement/validation updates
796
+ * @returns - Instance of this
797
+ * @throws - If validation setup fails
737
798
  */
738
799
  configureValidationAndRequirements(isRequired, isValid, fieldDisplayName, dependencies) {
739
800
  if (!fieldDisplayName?.trim()) {
@@ -834,6 +895,7 @@ var DOMNodeReference = class _DOMNodeReference {
834
895
  attributeFilter: ["style"],
835
896
  subtree: false
836
897
  });
898
+ this.observers.push(observer);
837
899
  }
838
900
  if (trackRadioButtons && (dep.yesRadio || dep.noRadio)) {
839
901
  [dep.yesRadio, dep.noRadio].forEach((radio) => {
@@ -845,7 +907,7 @@ var DOMNodeReference = class _DOMNodeReference {
845
907
  /**
846
908
  * Sets the required level for the field by adding or removing the "required-field" class on the label.
847
909
  *
848
- * @param {Function | boolean} isRequired - Determines whether the field should be marked as required.
910
+ * @param isRequired - Determines whether the field should be marked as required.
849
911
  * If true, the "required-field" class is added to the label; if false, it is removed.
850
912
  * @returns - Instance of this [provides option to method chain]
851
913
  */
@@ -862,7 +924,8 @@ var DOMNodeReference = class _DOMNodeReference {
862
924
  * Executes a callback function once the element is fully loaded.
863
925
  * If the element is already loaded, the callback is called immediately.
864
926
  * Otherwise, a MutationObserver is used to detect when the element is added to the DOM.
865
- * @param {Function} callback - A callback function to execute once the element is loaded.
927
+ * @param callback - A callback function to execute once the element is loaded.
928
+ * Receives instance of 'this' as an argument
866
929
  */
867
930
  onceLoaded(callback) {
868
931
  if (this.isLoaded) {
@@ -884,6 +947,7 @@ var DOMNodeReference = class _DOMNodeReference {
884
947
  subtree: true,
885
948
  childList: true
886
949
  });
950
+ this.observers.push(observer);
887
951
  }
888
952
  };
889
953
 
@@ -932,10 +996,21 @@ function createProxyHandler() {
932
996
  };
933
997
  }
934
998
  function enhanceArray(array) {
935
- const enhanced = array;
936
- enhanced.hideAll = () => enhanced.forEach((instance) => instance.hide());
937
- enhanced.showAll = () => enhanced.forEach((instance) => instance.show());
938
- return enhanced;
999
+ Object.defineProperties(array, {
1000
+ hideAll: {
1001
+ value: function() {
1002
+ this.forEach((instance) => instance.hide());
1003
+ return this;
1004
+ }
1005
+ },
1006
+ showAll: {
1007
+ value: function() {
1008
+ this.forEach((instance) => instance.show());
1009
+ return this;
1010
+ }
1011
+ }
1012
+ });
1013
+ return array;
939
1014
  }
940
1015
  export {
941
1016
  API_default as API,
@@ -6,4 +6,4 @@ import DOMNodeReference from "./DOMNodeReference.js";
6
6
  * @param multiple Should this call return an array of instantiated references, or just a single? Defaults to false, returning a single instance
7
7
  * @returns A promise that resolves to a Proxy of the initialized DOMNodeReference instance.
8
8
  */
9
- export default function createDOMNodeReference(target: HTMLElement | string, multiple?: (() => boolean) | boolean): Promise<DOMNodeReference | DOMNodeReferenceArray>;
9
+ export default function createDOMNodeReference(target: HTMLElement | string, multiple?: (() => boolean) | boolean): Promise<DOMNodeReference | DOMNodeReference[]>;
package/dist/waitFor.d.ts CHANGED
@@ -4,4 +4,4 @@
4
4
  * @param root optional parameter to replace document as the root from which to perform the node search
5
5
  * @returns
6
6
  */
7
- export default function waitFor(target: HTMLElement | string, root?: Element | Document): Promise<Element>;
7
+ export default function waitFor(target: HTMLElement | string, root?: HTMLElement | Document): Promise<HTMLElement>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powerpagestoolkit",
3
- "version": "2.5.4111",
3
+ "version": "2.5.4212",
4
4
  "description": "Reference, manipulate, and engage with Power Pages sites through the nodes in the DOM; use a variety of custom methods that allow customizing your power pages site quicker and easier. ",
5
5
  "main": "./dist/bundle.js",
6
6
  "types": "./dist/index.d.ts",
@@ -58,7 +58,8 @@
58
58
  "files": [
59
59
  "dist/bundle.js",
60
60
  "dist/bundle.css",
61
- "dist/**/*.d.ts"
61
+ "dist/**/*.d.ts",
62
+ "assets/**"
62
63
  ],
63
64
  "exports": {
64
65
  ".": {