powerpagestoolkit 2.7.1420 → 2.7.1433

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/dist/README.md DELETED
@@ -1,508 +0,0 @@
1
- # PowerPages Tool Kit
2
-
3
- A TypeScript/JavaScript utility package for seamless DOM manipulation and DataVerse API interactions in PowerPages applications. This toolkit provides robust DOM element management and standardized DataVerse CRUD operations with full TypeScript support.
4
-
5
- ## Features
6
-
7
- - Powerful DOM element manipulation and reference management
8
- - Type-safe DataVerse API operations
9
- - Automatic value synchronization for form elements
10
- - Advanced conditional rendering and validation
11
- - Radio button and checkbox handling
12
- - Event management with proper TypeScript typing
13
- - Mutation observer integration for dynamic content
14
- - Tooltip and label management utilities
15
-
16
- ## Installation
17
-
18
- ```bash
19
- npm install powerpagestoolkit
20
- ```
21
-
22
- # Core Modules
23
-
24
- ### DOMNodeReference
25
-
26
- A powerful class for managing DOM elements with automatic value synchronization and event handling.
27
-
28
- #### Basic Usage
29
-
30
- DOMNodeReferences are instantiated with the help of the following factory function: `createRef`
31
-
32
- ```typescript
33
- createRef(
34
- target: HTMLElement | string,
35
- options: {
36
- multiple: (() => boolean) | boolean = false,
37
- root: HTMLElement,
38
- timeoutMs:number
39
- }
40
- ): Promise<DOMNodeReference | DOMNodeReference[]>;
41
- ```
42
-
43
- createRef takes two main arguments:
44
-
45
- <table style="width: 100%; border-collapse: collapse;">
46
- <thead>
47
- <tr>
48
- <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Property</th>
49
- <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Type</th>
50
- <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Details</th>
51
- </tr>
52
- </thead>
53
- <tbody>
54
- <tr>
55
- <td style="border: 1px solid #ddd; padding: 8px;">target</td>
56
- <td style="border: 1px solid #ddd; padding: 8px;">
57
- <pre><code class="language-javascript">string | HTMLElement</code></pre>
58
- </td>
59
- <td style="border: 1px solid #ddd; padding: 8px;">
60
- Use standard <code>querySelector</code> syntax to target an element, or elements in the DOM, or pass in an instance of the element itself to create a reference.
61
- </td>
62
- </tr>
63
- <tr>
64
- <td style="border: 1px solid #ddd; padding: 8px;">options</td>
65
- <td style="border: 1px solid #ddd; padding: 8px;">
66
- <pre><code class="language-javascript">{
67
- multiple: () => boolean | boolean,
68
- root: HTMLElement,
69
- timeoutMs:number
70
- }</code></pre>
71
- </td>
72
- <td style="border: 1px solid #ddd; padding: 8px;">
73
- Provides advanced configurations for niche scenarios, such as async DOM element loading, returning arrays of elements, or specifying the parent to search within for the target node.
74
- </td>
75
- </tr>
76
- </tbody>
77
- </table>
78
-
79
- Import the utility function for creating DOMNodeReference(s)
80
-
81
- ```typescript
82
- import { createRef } from "powerpagestoolkit";
83
- ```
84
-
85
- Instantiate one, or multiple instances of a DOMNodeReference, and optionally configure advanced options
86
-
87
- ```javascript
88
- // Create a single reference (i.e. 'querySelector')
89
- const node = await createRef("#myElement");
90
-
91
- // Create multiple references (i.e. 'querySelectorAll')
92
- const nodes = await createRef(".my-class", { multiple: true });
93
-
94
- /******************/
95
- // ADVANCED OPTIONS
96
- // in the event that you need to be more granular with how you are targeting
97
- // and retrieving elements, there are additional options
98
-
99
- // If the node you are targeting is not available at the initial execution
100
- // of the script, set a timeout for 2 seconds
101
- const node2 = await createRef("#target", { timeoutMs:2000 });
102
-
103
- // need to target a node within a specific node? use that node as the root
104
- const otherElement = document.getElementById("id");
105
- const node3 = await createRef("#target", { root: otherElement });
106
-
107
- // implement all options:
108
- const nodes2 = await createRef("#target", {
109
- multiple: true,
110
- timeoutMs:4000,
111
- root: otherElement,
112
- });
113
- ```
114
-
115
- #### Properties
116
-
117
- | Property | Type | Description |
118
- | -------- | ------------------------ | --------------------------------------------- |
119
- | element | HTMLElement | The referenced DOM element |
120
- | value | any | Current synchronized value of the element |
121
- | isLoaded | boolean | Element load status |
122
- | target | HTMLElement \| string | Original target selector or element |
123
- | yesRadio | DOMNodeReference \| null | Reference to 'yes' radio (for boolean fields) |
124
- | noRadio | DOMNodeReference \| null | Reference to 'no' radio (for boolean fields) |
125
- | checked | boolean | Checkbox/radio checked state |
126
-
127
- #### Key Methods
128
-
129
- ##### Event Handling
130
-
131
- ```typescript
132
- // Add event listener with proper 'this' context
133
- // uses standard eventListener API, and so supports all DOM events
134
- node.on("change", function (e) {
135
- console.log("Current value:", this.value);
136
- });
137
-
138
- node.on("click", function (e) {
139
- console.log(this, " has been clicked");
140
- });
141
-
142
- ...
143
- ```
144
-
145
- ##### Business Rule Application
146
-
147
- This utility provides a flexible way to dynamically control field visibility, requirement status, values, and enabled states based on dependencies within PowerPages forms.
148
-
149
- _Method Signature:_
150
-
151
- ```typescript
152
- applyBusinessRule(
153
- rule: BusinessRule,
154
- dependencies: DOMNodeReference[]
155
- ): DOMNodeReference; /* Instance of this is returned for optional
156
- method chaining */
157
- ```
158
-
159
- **BusinessRule Definition**
160
-
161
- ```typescript
162
- interface BusinessRule {
163
- setVisibility?: [
164
- condition: () => boolean,
165
- clearValuesOnHide?: boolean = true
166
- ];
167
- setRequired?: [
168
- isRequired: () => boolean,
169
- isValid: () => boolean
170
- ];
171
- setValue?: [
172
- condition: () => boolean,
173
- value: () => any | any
174
- ];
175
- setDisabled?: () => boolean;
176
- }
177
- ```
178
-
179
- ##### Visibility Control
180
-
181
- ```typescript
182
- // Show the 'taxIdField' only when
183
- // 'businessTypeField' is set to 'Corporation' or 'LLC'
184
- taxIdField.applyBusinessRule(
185
- {
186
- setVisibility: [
187
- () =>
188
- businessTypeField.value === "Corporation" ||
189
- businessTypeField.value === "LLC",
190
- ],
191
- },
192
- [businessTypeField] // Re-evaluate when businessTypeField changes
193
- );
194
-
195
- // Optionally disable 'clearValuesOnHide':
196
- taxIdField.applyBusinessRule(
197
- {
198
- setVisibility: [
199
- () =>
200
- businessTypeField.value === "Corporation" ||
201
- businessTypeField.value === "LLC",
202
- false, // defaults to true. False will prevent the fields from losing it's value if it is hidden
203
- ],
204
- },
205
- [businessTypeField] // Re-evaluate when businessTypeField changes
206
- );
207
- ```
208
-
209
- ##### Validation and Requirements
210
-
211
- ```typescript
212
- // Require 'taxIdField' when 'businessTypeField' is 'Corporation' or 'LLC'
213
- taxIdField.applyBusinessRule(
214
- {
215
- setRequired: [
216
- function () {
217
- return (
218
- businessTypeField.value === "Corporation" ||
219
- businessTypeField.value === "LLC"
220
- );
221
- },
222
- function () {
223
- return this.value != null && this.value !== "";
224
- },
225
- ],
226
- },
227
- [businessTypeField] // Revalidate when businessTypeField changes
228
- );
229
- ```
230
-
231
- ##### Setting Field Values Conditionally
232
-
233
- ```typescript
234
- // Set default industry value when 'businessTypeField' is 'Corporation'
235
- industryField.applyBusinessRule(
236
- {
237
- setValue: [
238
- () => businessTypeField.value === "Corporation",
239
- "Corporate"
240
- ],
241
- },
242
- [businessTypeField] // Apply value when businessTypeField changes
243
- );
244
- ```
245
-
246
- ##### Enabling and Disabling Fields
247
-
248
- ```typescript
249
- // Disable 'taxIdField' when 'businessTypeField' is 'Individual'
250
- taxIdField.applyBusinessRule(
251
- {
252
- setDisabled: () => businessTypeField.value === "Individual",
253
- },
254
- [businessTypeField] // Enable/disable when businessTypeField changes
255
- );
256
- ```
257
-
258
- ##### Element Manipulation
259
-
260
- _Value management_
261
-
262
- ```typescript
263
- // set a static value
264
- node.setValue("new value");
265
-
266
- // or set a value by using some sort of logic
267
- node.setValue(() => {
268
- if (true) {
269
- return "value";
270
- } else return "default";
271
- });
272
-
273
- // Sync with DOM
274
- node.updateValue();
275
-
276
- // Clear the value for both the instance and the target element
277
- node.clearValue();
278
- ```
279
-
280
- _Content manipulation_
281
-
282
- ```typescript
283
- node.setInnerHTML("<span>New content</span>");
284
- node.append(childElement);
285
- node.prepend(headerElement);
286
- node.after(siblingElement);
287
- node.before(labelElement);
288
- ```
289
-
290
- _Styling_
291
-
292
- ```typescript
293
- node.setStyle({
294
- display: "block",
295
- color: "red",
296
- });
297
- ```
298
-
299
- _Enabling/Disabling inputs_
300
-
301
- ```typescript
302
- node.disable();
303
- node.enable();
304
- ```
305
-
306
- ##### Label and Tooltip Management
307
-
308
- ```typescript
309
- // LABEL AND INFO OPERATIONS
310
- const label = node.getLabel();
311
- // appends a tooltip to the label associated with the element targeted by 'this'
312
- node.addLabelTooltip(
313
- "Helper text",
314
- /* Optionally pass in css styles to customize the tooltip icon*/
315
- { color: "orange", fontSize: "30px" }
316
- );
317
- // appends a tooltip directly to the element targeted by 'this'
318
- node.addTooltip(
319
- "Inline helper",
320
- /* Optionally pass in css styles to customize the tooltip icon*/
321
- { color: "orange", fontSize: "30px" }
322
- );
323
- ```
324
-
325
- _Example:_
326
-
327
- ```typescript
328
- import { createRef } from "powerpagestoolkit";
329
-
330
- const title = await createRef("#myTitle");
331
-
332
- title.addTooltip("This is an Example of a tooltip!", { color: "red" });
333
- ```
334
-
335
- ![Example](./assets//infoIconExample.gif)
336
-
337
- Here's an improved markdown documentation with more comprehensive details:
338
-
339
- ### BindForm Method
340
-
341
- The `bindForm` method simplifies form element management in DataVerse by providing a semantic and efficient way to access form controls, sections, and tabs.
342
-
343
- ##### Key Features
344
-
345
- - Retrieves form definition directly from DataVerse
346
- - Automatically generates references for:
347
- - Controls
348
- - Sections
349
- - Tabs
350
-
351
- ##### Element Types
352
-
353
- | Element Type | Description | Accessibility |
354
- | ------------ | ------------------------------------------- | ------------------------- |
355
- | `control` | Includes all form fields and sub-grids | Accessed via logical name |
356
- | `section` | Standard PowerApps form sections | Accessed via logical name |
357
- | `tab` | Form tabs corresponding to PowerApps layout | Accessed via logical name |
358
-
359
- ##### Usage Example
360
-
361
- ```javascript
362
- import { bindForm } from "powerpagestoolkit";
363
-
364
- // Basic form binding
365
- bindForm("form-guid").then((form) => {
366
- // Access elements by their logical name
367
- const nameField = form["name"];
368
-
369
- // execute custom methods
370
- nameField.applyBusinessRule(
371
- {
372
- setVisibility: [() => someNode.value === "desired value"],
373
- },
374
- [someNode]
375
- );
376
-
377
- // Or executes methods immediately upon accessing
378
- form["phonenumber"].addTooltip("Example tooltip text");
379
- });
380
- ```
381
-
382
- ##### Method Signature
383
-
384
- ```typescript
385
- /**
386
- * Binds a form by its GUID and returns a collection of form elements
387
- * @param formGuid Unique identifier for the form
388
- * @returns Promise resolving to form element references
389
- */
390
- function bindForm(formGuid: string): Promise<DOMNodeReferenceArray & Record<string: DOMNodeReference>>;
391
- ```
392
-
393
- ##### Benefits
394
-
395
- - Reduces code complexity
396
- - Improves readability
397
- - Provides type-safe access to form elements
398
- - Supports flexible form interactions
399
-
400
- ##### Best Practices
401
-
402
- - Use logical names consistently
403
- - Handle async nature of form binding
404
- - Leverage TypeScript for enhanced type checking
405
-
406
- ##### Error Handling
407
-
408
- Ensure proper error handling for form binding:
409
-
410
- ```javascript
411
- bindForm("form-guid")
412
- .then((form) => {
413
- // Form processing
414
- })
415
- .catch((error) => {
416
- console.error("Form binding failed", error);
417
- });
418
- ```
419
-
420
- ### DataVerse API
421
-
422
- Perform secure API calls to DataVerse from your PowerPages site. This method implements the shell deferred token to send requests with `__RequestVerificationToken`
423
-
424
- #### Create Records
425
-
426
- ```typescript
427
- await API.createRecord("accounts", {
428
- name: "Gypsum LLC",
429
- type: "Vendor",
430
- })
431
- .then((recordId) => {
432
- console.log("Created record:", recordId);
433
- })
434
- .catch((error) => {
435
- console.error("Creation failed:", error);
436
- });
437
- ```
438
-
439
- #### Get Records
440
-
441
- ```typescript
442
- // Single record
443
- const record = await API.getRecord(
444
- "accounts",
445
- "record-guid",
446
- "select=name,accountnumber"
447
- );
448
-
449
- // Multiple records
450
- const records = await API.getMultiple(
451
- "contacts",
452
- '$filter=firstname eq "Jane"&$select=firstname,lastname'
453
- );
454
- ```
455
-
456
- #### Update Record
457
-
458
- ```typescript
459
- await API.updateRecord("contacts", "record-guid", {
460
- name: "Jane Smith",
461
- email: "jane@example.com",
462
- });
463
- ```
464
-
465
- ## Best Practices
466
-
467
- 1. Always await DOMNodeReference creation:
468
-
469
- ```typescript
470
- const node = await createRef("#element");
471
- ```
472
-
473
- 2. Include all referenced nodes in dependency arrays:
474
-
475
- ```typescript
476
- node.configureConditionalRendering(
477
- () => dependentNode.value === "test",
478
- [dependentNode] // Required!
479
- );
480
- ```
481
-
482
- 3. Use TypeScript for better type safety and IntelliSense support.
483
-
484
- 4. Use proper error handling with API operations:
485
-
486
- ```typescript
487
- /* optionally await */ API.createRecord(/*...*/)
488
- .then((recordId) => {})
489
- .catch((error) => {
490
- // handle your errors appropriately
491
- });
492
- ```
493
-
494
- ## TypeScript Support
495
-
496
- The package includes full TypeScript definitions and type safety. Use TypeScript for the best development experience and catch potential errors at compile time.
497
-
498
- ## Contributing
499
-
500
- Contributions are welcome, feel free to create a pull request with enhancements. Please include an explanation of the changes made. All pull requests will be reviewed by the project owner.
501
-
502
- ## License
503
-
504
- This project is licensed under the AGPL-3.0 License - see the [LICENSE](LICENSE) file for details.
505
-
506
- ## Funding
507
-
508
- If you like this project, found it useful, or would like to help support the long-term support of this package, please feel free to contribute via GitHub Sponsors: [Keaton-Brewster](https://github.com/sponsors/Keaton-Brewster)