@pnp/spfx-controls-react 3.17.0-beta.7003036 → 3.17.0-beta.7072507

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 (55) hide show
  1. package/lib/common/SPEntities.d.ts +5 -0
  2. package/lib/common/SPEntities.d.ts.map +1 -1
  3. package/lib/common/telemetry/version.js +1 -1
  4. package/lib/common/utilities/CustomFormatting.d.ts +31 -0
  5. package/lib/common/utilities/CustomFormatting.d.ts.map +1 -0
  6. package/lib/common/utilities/CustomFormatting.js +160 -0
  7. package/lib/common/utilities/CustomFormatting.js.map +1 -0
  8. package/lib/common/utilities/FormulaEvaluation.d.ts +21 -0
  9. package/lib/common/utilities/FormulaEvaluation.d.ts.map +1 -0
  10. package/lib/common/utilities/FormulaEvaluation.js +612 -0
  11. package/lib/common/utilities/FormulaEvaluation.js.map +1 -0
  12. package/lib/common/utilities/FormulaEvaluation.types.d.ts +23 -0
  13. package/lib/common/utilities/FormulaEvaluation.types.d.ts.map +1 -0
  14. package/lib/common/utilities/FormulaEvaluation.types.js +80 -0
  15. package/lib/common/utilities/FormulaEvaluation.types.js.map +1 -0
  16. package/lib/common/utilities/ICustomFormatting.d.ts +27 -0
  17. package/lib/common/utilities/ICustomFormatting.d.ts.map +1 -0
  18. package/lib/common/utilities/ICustomFormatting.js +2 -0
  19. package/lib/common/utilities/ICustomFormatting.js.map +1 -0
  20. package/lib/controls/dynamicForm/DynamicForm.d.ts +53 -5
  21. package/lib/controls/dynamicForm/DynamicForm.d.ts.map +1 -1
  22. package/lib/controls/dynamicForm/DynamicForm.js +828 -536
  23. package/lib/controls/dynamicForm/DynamicForm.js.map +1 -1
  24. package/lib/controls/dynamicForm/DynamicForm.module.css +2 -2
  25. package/lib/controls/dynamicForm/DynamicForm.module.scss.d.ts +4 -0
  26. package/lib/controls/dynamicForm/DynamicForm.module.scss.d.ts.map +1 -1
  27. package/lib/controls/dynamicForm/DynamicForm.module.scss.js +25 -21
  28. package/lib/controls/dynamicForm/DynamicForm.module.scss.js.map +1 -1
  29. package/lib/controls/dynamicForm/IDynamicFormProps.d.ts +12 -0
  30. package/lib/controls/dynamicForm/IDynamicFormProps.d.ts.map +1 -1
  31. package/lib/controls/dynamicForm/IDynamicFormState.d.ts +25 -0
  32. package/lib/controls/dynamicForm/IDynamicFormState.d.ts.map +1 -1
  33. package/lib/controls/dynamicForm/dynamicField/DynamicField.d.ts.map +1 -1
  34. package/lib/controls/dynamicForm/dynamicField/DynamicField.js +57 -42
  35. package/lib/controls/dynamicForm/dynamicField/DynamicField.js.map +1 -1
  36. package/lib/controls/dynamicForm/dynamicField/IDynamicFieldProps.d.ts +32 -11
  37. package/lib/controls/dynamicForm/dynamicField/IDynamicFieldProps.d.ts.map +1 -1
  38. package/lib/controls/fieldCollectionData/collectionDataItem/CollectionDataItem.js.map +1 -1
  39. package/lib/controls/webPartTitle/WebPartTitle.js +1 -1
  40. package/lib/controls/webPartTitle/WebPartTitle.js.map +1 -1
  41. package/lib/services/ISPService.d.ts +194 -0
  42. package/lib/services/ISPService.d.ts.map +1 -1
  43. package/lib/services/ISPService.js +13 -0
  44. package/lib/services/ISPService.js.map +1 -1
  45. package/lib/services/SPService.d.ts +10 -1
  46. package/lib/services/SPService.d.ts.map +1 -1
  47. package/lib/services/SPService.js +69 -0
  48. package/lib/services/SPService.js.map +1 -1
  49. package/lib/services/SPServiceMock.d.ts +3 -1
  50. package/lib/services/SPServiceMock.d.ts.map +1 -1
  51. package/lib/services/SPServiceMock.js +6 -0
  52. package/lib/services/SPServiceMock.js.map +1 -1
  53. package/package.json +1 -1
  54. package/release/manifests/45165954-80f9-44c1-9967-cd38ae92a33b.manifest.json +58 -3
  55. package/tests/utils/formulaevaluation.test.ts +248 -0
@@ -17,14 +17,69 @@
17
17
  "default": "Under Development"
18
18
  },
19
19
  "title": {
20
- "default": "ControlsTest"
20
+ "default": "Controls Test"
21
21
  },
22
22
  "description": {
23
- "default": "ControlsTest description"
23
+ "default": "Web Part to test controls"
24
24
  },
25
25
  "officeFabricIconFontName": "Share",
26
26
  "properties": {
27
- "description": "ControlsTest"
27
+ "description": "Controls Test",
28
+ "dynamicFormCustomFormattingEnabled": true,
29
+ "dynamicFormClientSideValidationEnabled": true,
30
+ "dynamicFormFieldValidationEnabled": true,
31
+ "dynamicFormFileSelectionEnabled": false,
32
+ "controlVisibility": {
33
+ "all": false,
34
+ "accessibleAccordion": false,
35
+ "adaptiveCardDesignerHost": false,
36
+ "adaptiveCardHost": false,
37
+ "animatedDialog": false,
38
+ "Carousel": false,
39
+ "ChartControl": false,
40
+ "ComboBoxListItemPicker": false,
41
+ "Dashboard": false,
42
+ "DateTimePicker": false,
43
+ "DragDropFiles": false,
44
+ "DynamicForm": false,
45
+ "EnhancedThemeProvider": false,
46
+ "FieldCollectionData": false,
47
+ "FieldPicker": false,
48
+ "FilePicker": false,
49
+ "FileTypeIcon": false,
50
+ "FolderExplorer": false,
51
+ "FolderPicker": false,
52
+ "GridLayout": false,
53
+ "IconPicker": false,
54
+ "IFrameDialog": false,
55
+ "IFramePanel": false,
56
+ "ListItemComments": false,
57
+ "ListItemPicker": false,
58
+ "ListPicker": false,
59
+ "ListView": false,
60
+ "LocationPicker": false,
61
+ "Map": false,
62
+ "ModernAudio": false,
63
+ "ModernTaxonomyPicker": false,
64
+ "Pagination": false,
65
+ "PeoplePicker": false,
66
+ "Placeholder": false,
67
+ "Progress": false,
68
+ "RichText": false,
69
+ "SecurityTrimmedControl": false,
70
+ "SiteBreadcrumb": false,
71
+ "SitePicker": false,
72
+ "TaxonomyPicker": false,
73
+ "TaxonomyTree": false,
74
+ "Teams": false,
75
+ "TestControl": false,
76
+ "Toolbar": false,
77
+ "TreeView": false,
78
+ "UploadFiles": false,
79
+ "VariantThemeProvider": false,
80
+ "ViewPicker": false,
81
+ "WebPartTitle": false
82
+ }
28
83
  }
29
84
  }
30
85
  ],
@@ -0,0 +1,248 @@
1
+ ///<reference types="jest" />
2
+
3
+ import { assert } from "chai";
4
+ import { FormulaEvaluation } from "../../src/common/utilities/FormulaEvaluation";
5
+ import { ASTNode, Token } from "../../src/common/utilities/FormulaEvaluation.types";
6
+
7
+ const formulaEvaluation = new FormulaEvaluation();
8
+ const validate = formulaEvaluation.validate.bind(formulaEvaluation);
9
+ const tokenize = formulaEvaluation.tokenize.bind(formulaEvaluation);
10
+ const shuntingYard = formulaEvaluation.shuntingYard.bind(formulaEvaluation);
11
+ const buildAST = formulaEvaluation.buildAST.bind(formulaEvaluation);
12
+ const evaluateAST = formulaEvaluation.evaluateASTNode.bind(formulaEvaluation);
13
+ const evaluate = formulaEvaluation.evaluate.bind(formulaEvaluation);
14
+
15
+ describe('SharePoint Functionality', () => {
16
+ it('Should get a user image URL from an email address', () => {
17
+ const result = evaluate(`getUserImage('user@contoso.com')`);
18
+ assert.equal(result, `/_layouts/15/userphoto.aspx?size=L&accountname=user@contoso.com`);
19
+ });
20
+ it('Should get a thumbnail image URL from an image file URL', () => {
21
+ const result = evaluate(`getThumbnailImage('https://merseycarenhsuk.sharepoint.com/sites/IM/SiteAssets/CyberAwareness.png')`);
22
+ assert.equal(result, `https://merseycarenhsuk.sharepoint.com/sites/IM/SiteAssets/_t/CyberAwareness_png.jpg`);
23
+ });
24
+ });
25
+
26
+ describe('Validation', () => {
27
+ it('should validate possible expressions', () => {
28
+ assert.isTrue(validate("1 + 2"));
29
+ assert.isTrue(validate("1 + 2 > 3"));
30
+ assert.isTrue(validate("1 + 2 > 3 ? true : false"));
31
+ assert.isTrue(validate("if(1 + 2 > 3, true, false)"));
32
+ assert.isTrue(validate("toDateString(toDate('2023-09-01'))"));
33
+ assert.isFalse(validate("test(abcdef"));
34
+ });
35
+ });
36
+
37
+ describe('Algorithms', () => {
38
+
39
+ describe('Tokenization', () => {
40
+ it('should tokenize basic expressions', () => {
41
+ const result = tokenize("1 + 2");
42
+ assert.deepEqual(result, [
43
+ new Token("NUMBER", "1"),
44
+ new Token("OPERATOR", "+"),
45
+ new Token("NUMBER", "2")
46
+ ]);
47
+ });
48
+ });
49
+
50
+ describe('Shunting Yard', () => {
51
+ it('should convert basic expressions to postfix', () => {
52
+ const result = shuntingYard(tokenize("1 + 2 > 3"));
53
+ assert.deepEqual(result, [
54
+ new Token("NUMBER", "1"),
55
+ new Token("NUMBER", "2"),
56
+ new Token("OPERATOR", "+"),
57
+ new Token("NUMBER", "3"),
58
+ new Token("OPERATOR", ">"),
59
+ ]);
60
+ });
61
+ });
62
+
63
+ describe('AST Generation', () => {
64
+ it('should generate AST for basic expressions', () => {
65
+ const tokens = [
66
+ new Token("NUMBER", "1"),
67
+ new Token("NUMBER", "2"),
68
+ new Token("OPERATOR", "+")
69
+ ];
70
+ const ast = buildAST(tokens);
71
+ assert.deepEqual(ast, {
72
+ type: "OPERATOR",
73
+ value: "+",
74
+ operands: [
75
+ new Token("NUMBER", "1"),
76
+ new Token("NUMBER", "2")
77
+ ]
78
+ } as ASTNode);
79
+ });
80
+ });
81
+
82
+ describe('Evaluation', () => {
83
+ it('should evaluate basic expressions', () => {
84
+ const context = {};
85
+ const ast: ASTNode = {
86
+ type: "OPERATOR",
87
+ value: "+",
88
+ operands: [
89
+ new Token("NUMBER", "1"),
90
+ new Token("NUMBER", "2")
91
+ ]
92
+ };
93
+ const result = evaluateAST(ast, context);
94
+ assert.equal(result, 3);
95
+ });
96
+ });
97
+ });
98
+
99
+ describe('Basic Expression Evaluation', () => {
100
+ it('should evaluate a basic expression correctly obeying BODMAS/PEMDAS', () => {
101
+ const result = evaluate("1 + 2 * 3");
102
+ assert.equal(result, 7);
103
+ });
104
+ });
105
+
106
+ describe('Advanced Expression Evaluation', () => {
107
+ it('should evaluate an if expression with basic arithmetic', () => {
108
+ const result = evaluate("if(1 + 2 > 3, true, false)");
109
+ assert.equal(result, false);
110
+ });
111
+ it('should evaluate an if expression with basic arithmetic and variables', () => {
112
+ const context = { x: 2, y: 2, z: 3 };
113
+ const result = evaluate("if([x] + [y] > [z], true, false)", context);
114
+ assert.equal(result, true);
115
+ });
116
+ it('should evaluate a ternary expression with basic arithmetic', () => {
117
+ const result = evaluate("1 + 2 > 3 ? true : false");
118
+ assert.equal(result, false);
119
+ });
120
+ it('should evaluate a complex nested expression (1)', () => {
121
+ const result = evaluate('((1 + 2 * 3) + 3 > 8 ? 5 : 0) == 5 ? 1 : 0');
122
+ assert.equal(result, 1);
123
+ });
124
+ it('should evaluate a complex nested expression (2)', () => {
125
+ const result = evaluate('(cos(1 + 2 * 3) + 3 > 0.5 ? sin(5) : 0) < 0 ? 1 : 0');
126
+ assert.equal(result, 1);
127
+ });
128
+ });
129
+
130
+ describe('Math Expression Evaluation', () => {
131
+ it('Should floor a number', () => {
132
+ const result = evaluate("floor(1.5)");
133
+ assert.equal(result, 1);
134
+ });
135
+ it('Should ceil a number', () => {
136
+ const result = evaluate("ceiling(1.5)");
137
+ assert.equal(result, 2);
138
+ });
139
+ it('Should raise a number to the power of another', () => {
140
+ const result = evaluate("pow(2, 3)");
141
+ assert.equal(result, 8);
142
+ });
143
+ it('Should return the cosine of a number', () => {
144
+ const result = evaluate("cos(0.5)");
145
+ assert.approximately(result, 0.87758, 0.00001);
146
+ });
147
+ it('Should return the sine of a number', () => {
148
+ const result = evaluate("sin(0.5)");
149
+ assert.approximately(result, 0.47942, 0.00001);
150
+ });
151
+ });
152
+
153
+ describe('String Expression Evaluation', () => {
154
+ it('Should return the index of a substring', () => {
155
+ const result = evaluate("indexOf('Hello World', 'World')");
156
+ assert.equal(result, 6);
157
+ });
158
+ it('Should return the last index of a substring', () => {
159
+ const result = evaluate("lastIndexOf('Hello World', 'l')");
160
+ assert.equal(result, 9);
161
+ });
162
+ it('Should join an array of strings', () => {
163
+ const result = evaluate("join(['Hello', 'World'], ', ')");
164
+ assert.equal(result, 'Hello, World');
165
+ });
166
+ it('Should return a substring', () => {
167
+ const result = evaluate("substring('Hello World', 6, 5)");
168
+ assert.equal(result, 'World');
169
+ });
170
+ it('Should return a string in uppercase', () => {
171
+ const result = evaluate("toUpperCase('Hello World')");
172
+ assert.equal(result, 'HELLO WORLD');
173
+ });
174
+ it('Should return a string in lowercase', () => {
175
+ const result = evaluate("toLowerCase('Hello World')");
176
+ assert.equal(result, 'hello world');
177
+ });
178
+ it('Should determine if a string starts with a substring', () => {
179
+ const result = evaluate("startsWith('Hello World', 'Hello')");
180
+ assert.isTrue(result);
181
+ });
182
+ it('Should determine if a string ends with a substring', () => {
183
+ const result = evaluate("endsWith('Hello World', 'World')");
184
+ assert.isTrue(result);
185
+ });
186
+ it('Should replace a substring', () => {
187
+ const result = evaluate("replace('Hello World', 'World', 'Earth')");
188
+ assert.equal(result, 'Hello Earth');
189
+ });
190
+ it('Should replace all instances of a substring', () => {
191
+ const result = evaluate("replaceAll('Hello World', 'l', 'L')");
192
+ assert.equal(result, 'HeLLo WorLd');
193
+ });
194
+ it('Should pad the start of a string with a substring', () => {
195
+ const result = evaluate("padStart('Hello World', 15, 'x')");
196
+ assert.equal(result, 'xxxxHello World');
197
+ });
198
+ it('Should pad the end of a string with a substring', () => {
199
+ const result = evaluate("padEnd('Hello World', 15, 'x')");
200
+ assert.equal(result, 'Hello Worldxxxx');
201
+ });
202
+ it('Should split a string and return an array', () => {
203
+ const result = evaluate("split('Hello World', ' ')");
204
+ assert.deepEqual(result, ['Hello', 'World']);
205
+ });
206
+ });
207
+
208
+ describe('Date Expression Evaluation', () => {
209
+ it('Should convert a string to a date', () => {
210
+ const result = evaluate("toDate('2023-09-01')");
211
+ assert.equal(result.toISOString(), '2023-09-01T00:00:00.000Z');
212
+ });
213
+ it('Should convert a date to a date string', () => {
214
+ const result = evaluate("toDateString(toDate('2023-09-01'))");
215
+ assert.equal(result, 'Fri Sep 01 2023');
216
+ });
217
+ it('Should get the date component of a date', () => {
218
+ const result = evaluate("getDate(toDate('2023-09-01'))");
219
+ assert.equal(result, 1);
220
+ });
221
+ it('Should get the month component of a date', () => {
222
+ const result = evaluate("getMonth(toDate('2023-09-01'))");
223
+ assert.equal(result, 8);
224
+ });
225
+ it('Should get the year component of a date', () => {
226
+ const result = evaluate("getYear(toDate('2023-09-01'))");
227
+ assert.equal(result, 2023);
228
+ });
229
+ it('Should add days to a date', () => {
230
+ const result = evaluate("addDays(toDate('2023-09-01'), 1)");
231
+ assert.equal(result.toISOString(), '2023-09-02T00:00:00.000Z');
232
+ });
233
+ it('Should add minutes to a date', () => {
234
+ const result = evaluate("addMinutes(toDate('2023-09-01'), 1)");
235
+ assert.equal(result.toISOString(), '2023-09-01T00:01:00.000Z');
236
+ });
237
+ });
238
+
239
+ describe('Array Expression Evaluation', () => {
240
+ it('Should append an item to an array', () => {
241
+ const result = evaluate("appendTo(['Hello', 'World'], 'Earth')");
242
+ assert.deepEqual(result, ['Hello', 'World', 'Earth']);
243
+ });
244
+ it('Should remove an item from an array', () => {
245
+ const result = evaluate("removeFrom(['Hello', 'World'], 'World')");
246
+ assert.deepEqual(result, ['Hello']);
247
+ });
248
+ });