powerpagestoolkit 2.5.404 → 2.5.409

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
@@ -28,18 +28,15 @@ A powerful class for managing DOM elements with automatic value synchronization
28
28
  #### Basic Usage
29
29
 
30
30
  ```typescript
31
- import {
32
- createDOMNodeReference,
33
- createMultipleDOMNodeReferences,
34
- } from "powerpagestoolkit";
31
+ import { createRef } from "powerpagestoolkit";
35
32
 
36
33
  // Both methods support standard querySelector syntax:
37
34
 
38
35
  // Create a single reference
39
- const node = await createDOMNodeReference("#myElement");
36
+ const node = await createRef("#myElement");
40
37
 
41
38
  // Create multiple references
42
- const nodes = await createMultipleDOMNodeReferences(".my-class");
39
+ const nodes = await createRef(".my-class", true);
43
40
  ```
44
41
 
45
42
  #### Properties
@@ -204,7 +201,7 @@ await API.updateRecord("contacts", "record-guid", {
204
201
  1. Always await DOMNodeReference creation:
205
202
 
206
203
  ```typescript
207
- const node = await createDOMNodeReference("#element");
204
+ const node = await createRef("#element");
208
205
  ```
209
206
 
210
207
  2. Include all referenced nodes in dependency arrays:
@@ -15,7 +15,7 @@ export default class DOMNodeReference {
15
15
  * or access properties not available through this class.
16
16
  * @property {HTMLElement | null}
17
17
  */
18
- element: HTMLElement;
18
+ element: Element;
19
19
  private visibilityController;
20
20
  checked: boolean;
21
21
  /**
@@ -44,6 +44,7 @@ export default class DOMNodeReference {
44
44
  * @private
45
45
  */
46
46
  private _initValueSync;
47
+ private _initDateSync;
47
48
  /**
48
49
  * Updates the value and checked state based on element type
49
50
  * @public
@@ -54,12 +55,12 @@ export default class DOMNodeReference {
54
55
  * @private
55
56
  * @returns {ElementValue} Object containing value and optional checked state
56
57
  */
57
- private getElementValue;
58
+ private _getElementValue;
58
59
  /**
59
60
  * Updates related radio buttons if this is part of a radio group
60
61
  * @private
61
62
  */
62
- private updateRadioGroup;
63
+ private _updateRadioGroup;
63
64
  private _attachVisibilityController;
64
65
  private _attachRadioButtons;
65
66
  /**
@@ -192,7 +193,7 @@ export default class DOMNodeReference {
192
193
  * @throws {ConditionalRenderingError} When there's an error in setting up conditional rendering
193
194
  * @returns {DOMNodeReference} - Instance of this [provides option to method chain]
194
195
  */
195
- configureConditionalRendering(condition: () => boolean, dependencies?: Array<DOMNodeReference>): DOMNodeReference;
196
+ configureConditionalRendering(condition: () => boolean, dependencies?: Array<DOMNodeReference>, clearValuesOnHide?: boolean): DOMNodeReference;
196
197
  /**
197
198
  * Sets up validation and requirement rules for the field with enhanced error handling and dynamic updates.
198
199
  *
package/dist/List.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * so far this whole thing is a moot point
3
+ * Microsoft provides no way to get important specific information
4
+ * about the records represented by each 'row' in a list
5
+ * rendering this effort particularly useless
6
+ *
7
+ * Saving for in case things change in the future and this
8
+ * could be re-factored/extended to provide some usable value
9
+ */
10
+ export declare const _init: symbol;
11
+ /**
12
+ * Provides information about how to target elements in
13
+ * the construction of the list
14
+ */
15
+ interface ListOptions {
16
+ containerSelector: string;
17
+ rowSelector: string;
18
+ cellSelector: string;
19
+ }
20
+ interface ListItem extends Array<Element> {
21
+ }
22
+ export default class List {
23
+ items: ListItem[];
24
+ private options;
25
+ private container;
26
+ constructor(options?: Partial<ListOptions>);
27
+ }
28
+ export {};
package/dist/bundle.js CHANGED
@@ -103,10 +103,10 @@ var API = {
103
103
  var API_default = API;
104
104
 
105
105
  // src/waitFor.ts
106
- function waitFor(target) {
106
+ function waitFor(target, root = document) {
107
107
  return new Promise((resolve, reject) => {
108
108
  const observer = new MutationObserver(() => {
109
- const observedElement = document.querySelector(target);
109
+ const observedElement = root.querySelector(target);
110
110
  if (observedElement) {
111
111
  clearTimeout(timeout);
112
112
  observer.disconnect();
@@ -121,7 +121,7 @@ function waitFor(target) {
121
121
  clearTimeout(timeout);
122
122
  return resolve(target);
123
123
  }
124
- const element = document.querySelector(target);
124
+ const element = root.querySelector(target);
125
125
  if (element) {
126
126
  clearTimeout(timeout);
127
127
  return resolve(element);
@@ -251,6 +251,7 @@ var DOMNodeReference = class _DOMNodeReference {
251
251
  this.isLoaded = false;
252
252
  this.defaultDisplay = "";
253
253
  this.value = null;
254
+ this.updateValue = this.updateValue.bind(this);
254
255
  }
255
256
  async [_init]() {
256
257
  try {
@@ -275,38 +276,64 @@ var DOMNodeReference = class _DOMNodeReference {
275
276
  * based on element type.
276
277
  * @private
277
278
  */
278
- _initValueSync() {
279
- this.updateValue();
280
- const input = this.element;
281
- const eventMapping = {
282
- checkbox: "click",
283
- radio: "click",
284
- "select-one": "change",
285
- select: "change",
286
- "select-multiple": "change"
287
- };
288
- const boundUpdateValue = this.updateValue.bind(this);
289
- const eventType = eventMapping[input.type] || "input";
290
- this.element.addEventListener(eventType, boundUpdateValue);
279
+ async _initValueSync() {
280
+ try {
281
+ this.updateValue();
282
+ if (!(this.element instanceof HTMLElement)) {
283
+ throw new Error("Element is not a valid HTML element");
284
+ }
285
+ const eventMapping = {
286
+ checkbox: "click",
287
+ radio: "click",
288
+ select: "change",
289
+ "select-multiple": "change"
290
+ // Add other input types as needed
291
+ };
292
+ let eventType;
293
+ if (this.element instanceof HTMLSelectElement) {
294
+ eventType = "change";
295
+ } else if (this.element instanceof HTMLInputElement) {
296
+ eventType = eventMapping[this.element.type] || "input";
297
+ } else {
298
+ eventType = "input";
299
+ }
300
+ this.element.addEventListener(eventType, this.updateValue);
301
+ if (this.element instanceof HTMLInputElement && this.element.dataset.type === "date") {
302
+ await this._initDateSync(this.element);
303
+ }
304
+ } catch (error) {
305
+ throw new DOMNodeInitializationError(
306
+ this,
307
+ `Failed to initialize value sync: ${error}`
308
+ );
309
+ }
310
+ }
311
+ async _initDateSync(element) {
312
+ const parentElement = element.parentElement;
313
+ if (!parentElement) {
314
+ throw new Error("Date input must have a parent element");
315
+ }
316
+ const dateNode = await waitFor("[data-date-format]", parentElement);
317
+ dateNode.addEventListener("select", this.updateValue);
291
318
  }
292
319
  /**
293
320
  * Updates the value and checked state based on element type
294
321
  * @public
295
322
  */
296
323
  updateValue() {
297
- const elementValue = this.getElementValue();
324
+ const elementValue = this._getElementValue();
298
325
  this.value = elementValue.value;
299
326
  if (elementValue.checked !== void 0) {
300
327
  this.checked = elementValue.checked;
301
328
  }
302
- this.updateRadioGroup();
329
+ this._updateRadioGroup();
303
330
  }
304
331
  /**
305
332
  * Gets the current value of the element based on its type
306
333
  * @private
307
334
  * @returns {ElementValue} Object containing value and optional checked state
308
335
  */
309
- getElementValue() {
336
+ _getElementValue() {
310
337
  const input = this.element;
311
338
  const select = this.element;
312
339
  switch (input.type) {
@@ -332,7 +359,7 @@ var DOMNodeReference = class _DOMNodeReference {
332
359
  };
333
360
  default:
334
361
  return {
335
- value: this.element.classList.contains("decimal") ? parseFloat(input.value) : input.value
362
+ value: this.element.classList.contains("decimal") || this.element.classList.contains("money") ? parseFloat(input.value) : input.value
336
363
  };
337
364
  }
338
365
  }
@@ -340,7 +367,7 @@ var DOMNodeReference = class _DOMNodeReference {
340
367
  * Updates related radio buttons if this is part of a radio group
341
368
  * @private
342
369
  */
343
- updateRadioGroup() {
370
+ _updateRadioGroup() {
344
371
  if (this.yesRadio instanceof _DOMNodeReference && this.noRadio instanceof _DOMNodeReference) {
345
372
  this.yesRadio.updateValue();
346
373
  this.noRadio?.updateValue();
@@ -507,7 +534,7 @@ var DOMNodeReference = class _DOMNodeReference {
507
534
  );
508
535
  if (childInputs.length > 0) {
509
536
  const clearPromises = childInputs.map(async (input) => {
510
- const inputRef = await createDOMNodeReference(input);
537
+ const inputRef = await createDOMNodeReference(input, false);
511
538
  return inputRef.clearValues();
512
539
  });
513
540
  await Promise.all(clearPromises);
@@ -669,7 +696,7 @@ var DOMNodeReference = class _DOMNodeReference {
669
696
  * @throws {ConditionalRenderingError} When there's an error in setting up conditional rendering
670
697
  * @returns {DOMNodeReference} - Instance of this [provides option to method chain]
671
698
  */
672
- configureConditionalRendering(condition, dependencies) {
699
+ configureConditionalRendering(condition, dependencies, clearValuesOnHide = true) {
673
700
  try {
674
701
  if (typeof condition !== "function") {
675
702
  throw new TypeError("Condition must be a function");
@@ -692,7 +719,7 @@ var DOMNodeReference = class _DOMNodeReference {
692
719
  const handleChange = () => {
693
720
  try {
694
721
  this.toggleVisibility(condition());
695
- if (condition() === false) {
722
+ if (condition() === false && clearValuesOnHide) {
696
723
  this.clearValues();
697
724
  }
698
725
  } catch (error) {
@@ -854,50 +881,59 @@ var DOMNodeReference = class _DOMNodeReference {
854
881
  };
855
882
 
856
883
  // src/createDOMNodeReferences.ts
857
- async function createDOMNodeReference(target) {
884
+ async function createDOMNodeReference(target, multiple = false) {
858
885
  try {
886
+ const isMultiple = typeof multiple === "function" ? multiple() : multiple;
887
+ if (isMultiple) {
888
+ if (typeof target !== "string") {
889
+ throw new Error(
890
+ `'target' must be of type 'string' if 'multiple' is set to 'true'. Received type: '${typeof target}'`
891
+ );
892
+ }
893
+ const elements = Array.from(
894
+ document.querySelectorAll(target)
895
+ );
896
+ const initializedElements = await Promise.all(
897
+ elements.map(async (element) => {
898
+ const instance2 = new DOMNodeReference(element);
899
+ await instance2[_init]();
900
+ return new Proxy(instance2, createProxyHandler());
901
+ })
902
+ );
903
+ return enhanceArray(initializedElements);
904
+ }
859
905
  const instance = new DOMNodeReference(target);
860
906
  await instance[_init]();
861
- return new Proxy(instance, {
862
- get: (target2, prop) => {
863
- if (prop.toString().startsWith("_")) return void 0;
864
- const value = target2[prop];
865
- if (typeof value === "function" && prop !== "onceLoaded") {
866
- return (...args) => {
867
- target2.onceLoaded(() => value.apply(target2, args));
868
- return target2;
869
- };
870
- }
871
- return value;
872
- }
873
- });
907
+ return new Proxy(instance, createProxyHandler());
874
908
  } catch (e) {
875
909
  throw new Error(e);
876
910
  }
877
911
  }
878
- async function createMultipleDOMNodeReferences(querySelector) {
879
- try {
880
- const elements = Array.from(
881
- document.querySelectorAll(querySelector)
882
- );
883
- const initializedElements = await Promise.all(
884
- elements.map((element) => createDOMNodeReference(element))
885
- );
886
- const domNodeArray = initializedElements;
887
- domNodeArray.hideAll = () => domNodeArray.forEach((instance) => instance.hide());
888
- domNodeArray.showAll = () => domNodeArray.forEach((instance) => instance.show());
889
- return domNodeArray;
890
- } catch (e) {
891
- console.error(
892
- `There was an error creating multiple DOMNodeReferences: ${e}`
893
- );
894
- throw new Error(e);
895
- }
912
+ function createProxyHandler() {
913
+ return {
914
+ get: (target, prop) => {
915
+ if (prop.toString().startsWith("_")) return void 0;
916
+ const value = target[prop];
917
+ if (typeof value === "function" && prop !== "onceLoaded") {
918
+ return (...args) => {
919
+ target.onceLoaded(() => value.apply(target, args));
920
+ return target;
921
+ };
922
+ }
923
+ return value;
924
+ }
925
+ };
926
+ }
927
+ function enhanceArray(array) {
928
+ const enhanced = array;
929
+ enhanced.hideAll = () => enhanced.forEach((instance) => instance.hide());
930
+ enhanced.showAll = () => enhanced.forEach((instance) => instance.show());
931
+ return enhanced;
896
932
  }
897
933
  export {
898
934
  API_default as API,
899
- createDOMNodeReference,
900
- createMultipleDOMNodeReferences
935
+ createDOMNodeReference as createRef,
936
+ waitFor
901
937
  };
902
938
 
903
939
 
@@ -2,14 +2,8 @@ import DOMNodeReference from "./DOMNodeReference.js";
2
2
  /**
3
3
  * Creates and initializes a DOMNodeReference instance.
4
4
  * @async
5
- * @param {string | HTMLElement} target - The CSS selector for the desired DOM element, or, optionally, the element itself for which to create a DOMNodeReference.
6
- * @returns {Promise<DOMNodeReference>} A promise that resolves to a Proxy of the initialized DOMNodeReference instance.
5
+ * @param target - The CSS selector for the desired DOM element, or, optionally, the element itself for which to create a DOMNodeReference.
6
+ * @param multiple Should this call return an array of instantiated references, or just a single? Defaults to false, returning a single instance
7
+ * @returns A promise that resolves to a Proxy of the initialized DOMNodeReference instance.
7
8
  */
8
- export declare function createDOMNodeReference(target: HTMLElement | string): Promise<DOMNodeReference>;
9
- /**
10
- * Creates and initializes multiple DOMNodeReference instances.
11
- * @async
12
- * @param {string} querySelector - The CSS selector for the desired DOM elements.
13
- * @returns {Promise<DOMNodeReference[]>} A promise that resolves to an array of Proxies of initialized DOMNodeReference instances.
14
- */
15
- export declare function createMultipleDOMNodeReferences(querySelector: string): Promise<DOMNodeReference[]>;
9
+ export default function createDOMNodeReference(target: HTMLElement | string, multiple?: (() => boolean) | boolean): Promise<DOMNodeReference | DOMNodeReferenceArray>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import './style.css';
1
+ import "./style.css";
2
2
  import API from "./API.js";
3
- import { createDOMNodeReference, createMultipleDOMNodeReferences } from "./createDOMNodeReferences.js";
4
- export { API, createDOMNodeReference, createMultipleDOMNodeReferences };
3
+ import createRef from "./createDOMNodeReferences.js";
4
+ import waitFor from "./waitFor.js";
5
+ export { API, createRef, waitFor };
package/dist/waitFor.d.ts CHANGED
@@ -1 +1,7 @@
1
- export default function waitFor(target: HTMLElement | string): Promise<HTMLElement>;
1
+ /**
2
+ *
3
+ * @param target basic querySelector syntax to select an element
4
+ * @param root optional parameter to replace document as the root from which to perform the node search
5
+ * @returns
6
+ */
7
+ export default function waitFor(target: HTMLElement | string, root?: Element | Document): Promise<Element>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powerpagestoolkit",
3
- "version": "2.5.404",
3
+ "version": "2.5.409",
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",