@pie-lib/config-ui 12.0.0-beta.5 → 12.0.0-next.0

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 (116) hide show
  1. package/CHANGELOG.json +8 -1653
  2. package/CHANGELOG.md +345 -4
  3. package/LICENSE.md +5 -0
  4. package/NEXT.CHANGELOG.json +1 -0
  5. package/lib/alert-dialog.js +40 -10
  6. package/lib/alert-dialog.js.map +1 -1
  7. package/lib/checkbox.js +58 -48
  8. package/lib/checkbox.js.map +1 -1
  9. package/lib/choice-configuration/feedback-menu.js +24 -26
  10. package/lib/choice-configuration/feedback-menu.js.map +1 -1
  11. package/lib/choice-configuration/index.js +182 -185
  12. package/lib/choice-configuration/index.js.map +1 -1
  13. package/lib/choice-utils.js +5 -7
  14. package/lib/choice-utils.js.map +1 -1
  15. package/lib/feedback-config/feedback-selector.js +69 -73
  16. package/lib/feedback-config/feedback-selector.js.map +1 -1
  17. package/lib/feedback-config/group.js +22 -25
  18. package/lib/feedback-config/group.js.map +1 -1
  19. package/lib/feedback-config/index.js +41 -44
  20. package/lib/feedback-config/index.js.map +1 -1
  21. package/lib/form-section.js +31 -25
  22. package/lib/form-section.js.map +1 -1
  23. package/lib/help.js +37 -47
  24. package/lib/help.js.map +1 -1
  25. package/lib/index.js +1 -2
  26. package/lib/index.js.map +1 -1
  27. package/lib/input.js +12 -17
  28. package/lib/input.js.map +1 -1
  29. package/lib/inputs.js +58 -67
  30. package/lib/inputs.js.map +1 -1
  31. package/lib/langs.js +56 -70
  32. package/lib/langs.js.map +1 -1
  33. package/lib/layout/config-layout.js +78 -47
  34. package/lib/layout/config-layout.js.map +1 -1
  35. package/lib/layout/index.js.map +1 -1
  36. package/lib/layout/layout-contents.js +58 -60
  37. package/lib/layout/layout-contents.js.map +1 -1
  38. package/lib/layout/settings-box.js +25 -33
  39. package/lib/layout/settings-box.js.map +1 -1
  40. package/lib/mui-box/index.js +41 -50
  41. package/lib/mui-box/index.js.map +1 -1
  42. package/lib/number-text-field-custom.js +151 -89
  43. package/lib/number-text-field-custom.js.map +1 -1
  44. package/lib/number-text-field.js +74 -63
  45. package/lib/number-text-field.js.map +1 -1
  46. package/lib/radio-with-label.js +30 -16
  47. package/lib/radio-with-label.js.map +1 -1
  48. package/lib/settings/display-size.js +16 -20
  49. package/lib/settings/display-size.js.map +1 -1
  50. package/lib/settings/index.js +13 -19
  51. package/lib/settings/index.js.map +1 -1
  52. package/lib/settings/panel.js +140 -141
  53. package/lib/settings/panel.js.map +1 -1
  54. package/lib/settings/settings-radio-label.js +29 -16
  55. package/lib/settings/settings-radio-label.js.map +1 -1
  56. package/lib/settings/toggle.js +39 -25
  57. package/lib/settings/toggle.js.map +1 -1
  58. package/lib/tabs/index.js +18 -30
  59. package/lib/tabs/index.js.map +1 -1
  60. package/lib/tags-input/index.js +49 -61
  61. package/lib/tags-input/index.js.map +1 -1
  62. package/lib/two-choice.js +33 -43
  63. package/lib/two-choice.js.map +1 -1
  64. package/lib/with-stateful-model.js +8 -12
  65. package/lib/with-stateful-model.js.map +1 -1
  66. package/package.json +22 -11
  67. package/src/__tests__/alert-dialog.test.jsx +283 -0
  68. package/src/__tests__/checkbox.test.jsx +249 -0
  69. package/src/__tests__/choice-utils.test.js +12 -0
  70. package/src/__tests__/form-section.test.jsx +334 -0
  71. package/src/__tests__/help.test.jsx +184 -0
  72. package/src/__tests__/input.test.jsx +192 -0
  73. package/src/__tests__/langs.test.jsx +457 -0
  74. package/src/__tests__/number-text-field-custom.test.jsx +438 -0
  75. package/src/__tests__/number-text-field.test.jsx +341 -0
  76. package/src/__tests__/radio-with-label.test.jsx +259 -0
  77. package/src/__tests__/settings-panel.test.js +187 -0
  78. package/src/__tests__/settings.test.jsx +515 -0
  79. package/src/__tests__/tabs.test.jsx +193 -0
  80. package/src/__tests__/two-choice.test.js +110 -0
  81. package/src/__tests__/with-stateful-model.test.jsx +145 -0
  82. package/src/alert-dialog.jsx +30 -8
  83. package/src/checkbox.jsx +43 -37
  84. package/src/choice-configuration/__tests__/feedback-menu.test.jsx +163 -0
  85. package/src/choice-configuration/__tests__/index.test.jsx +234 -0
  86. package/src/choice-configuration/feedback-menu.jsx +6 -6
  87. package/src/choice-configuration/index.jsx +208 -192
  88. package/src/feedback-config/__tests__/feedback-config.test.jsx +141 -0
  89. package/src/feedback-config/__tests__/feedback-selector.test.jsx +107 -0
  90. package/src/feedback-config/feedback-selector.jsx +52 -53
  91. package/src/feedback-config/group.jsx +21 -22
  92. package/src/feedback-config/index.jsx +27 -29
  93. package/src/form-section.jsx +26 -18
  94. package/src/help.jsx +20 -28
  95. package/src/input.jsx +1 -1
  96. package/src/inputs.jsx +35 -44
  97. package/src/langs.jsx +41 -46
  98. package/src/layout/__tests__/config.layout.test.jsx +59 -0
  99. package/src/layout/__tests__/layout-content.test.jsx +3 -0
  100. package/src/layout/config-layout.jsx +53 -23
  101. package/src/layout/layout-contents.jsx +38 -40
  102. package/src/layout/settings-box.jsx +16 -19
  103. package/src/mui-box/index.jsx +35 -43
  104. package/src/number-text-field-custom.jsx +117 -65
  105. package/src/number-text-field.jsx +51 -34
  106. package/src/radio-with-label.jsx +26 -10
  107. package/src/settings/display-size.jsx +12 -11
  108. package/src/settings/index.js +2 -1
  109. package/src/settings/panel.jsx +101 -92
  110. package/src/settings/settings-radio-label.jsx +26 -10
  111. package/src/settings/toggle.jsx +37 -18
  112. package/src/tabs/index.jsx +8 -8
  113. package/src/tags-input/__tests__/index.test.jsx +113 -0
  114. package/src/tags-input/index.jsx +35 -38
  115. package/src/two-choice.jsx +15 -19
  116. package/README.md +0 -12
@@ -0,0 +1,438 @@
1
+ import React from 'react';
2
+ import { render, screen, waitFor, fireEvent } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { NumberTextFieldCustom } from '../number-text-field-custom';
5
+
6
+ describe('NumberTextFieldCustom', () => {
7
+ const defaultProps = {
8
+ value: 1,
9
+ onChange: jest.fn(),
10
+ };
11
+
12
+ beforeEach(() => {
13
+ jest.clearAllMocks();
14
+ });
15
+
16
+ describe('rendering', () => {
17
+ it('renders input field', () => {
18
+ render(<NumberTextFieldCustom {...defaultProps} />);
19
+ const input = screen.getByRole('spinbutton');
20
+ expect(input).toBeInTheDocument();
21
+ });
22
+
23
+ it('renders with custom label', () => {
24
+ render(
25
+ <NumberTextFieldCustom
26
+ {...defaultProps}
27
+ label="Custom Label"
28
+ />,
29
+ );
30
+ expect(screen.getByLabelText('Custom Label')).toBeInTheDocument();
31
+ });
32
+
33
+ it('renders add and remove buttons', () => {
34
+ render(<NumberTextFieldCustom {...defaultProps} />);
35
+ const buttons = screen.getAllByRole('button');
36
+ expect(buttons.length).toBeGreaterThanOrEqual(2);
37
+ });
38
+
39
+ it('renders with custom className', () => {
40
+ const { container } = render(
41
+ <NumberTextFieldCustom
42
+ {...defaultProps}
43
+ className="custom-class"
44
+ />,
45
+ );
46
+ expect(container.querySelector('.custom-class')).toBeInTheDocument();
47
+ });
48
+
49
+ it('renders with custom inputClassName', () => {
50
+ const { container } = render(
51
+ <NumberTextFieldCustom
52
+ {...defaultProps}
53
+ inputClassName="input-class"
54
+ />,
55
+ );
56
+ expect(container.querySelector('.input-class')).toBeInTheDocument();
57
+ });
58
+
59
+ it('renders as disabled when disabled prop is true', () => {
60
+ render(
61
+ <NumberTextFieldCustom
62
+ {...defaultProps}
63
+ disabled={true}
64
+ />,
65
+ );
66
+ const input = screen.getByRole('spinbutton');
67
+ expect(input).toBeDisabled();
68
+ });
69
+
70
+ it('renders with error styling when error is true', () => {
71
+ render(
72
+ <NumberTextFieldCustom
73
+ {...defaultProps}
74
+ error={true}
75
+ />,
76
+ );
77
+ const input = screen.getByRole('spinbutton');
78
+ expect(input).toHaveAttribute('aria-invalid', 'true');
79
+ });
80
+
81
+ it('renders helper text when provided', () => {
82
+ render(
83
+ <NumberTextFieldCustom
84
+ {...defaultProps}
85
+ helperText="This is a helper text"
86
+ />,
87
+ );
88
+ expect(screen.getByText('This is a helper text')).toBeInTheDocument();
89
+ });
90
+
91
+ it('renders with different variant', () => {
92
+ render(
93
+ <NumberTextFieldCustom
94
+ {...defaultProps}
95
+ variant="outlined"
96
+ />,
97
+ );
98
+ const input = screen.getByRole('spinbutton');
99
+ expect(input).toBeInTheDocument();
100
+ });
101
+
102
+ it('renders with text alignment', () => {
103
+ const { container } = render(
104
+ <NumberTextFieldCustom
105
+ {...defaultProps}
106
+ textAlign="left"
107
+ />,
108
+ );
109
+ expect(container.querySelector('input')).toBeInTheDocument();
110
+ });
111
+ });
112
+
113
+ describe('custom values', () => {
114
+ it('accepts custom values array', () => {
115
+ render(
116
+ <NumberTextFieldCustom
117
+ {...defaultProps}
118
+ customValues={['small', 'medium', 'large']}
119
+ value="medium"
120
+ />,
121
+ );
122
+ const input = screen.getByRole('spinbutton');
123
+ expect(input).toBeInTheDocument();
124
+ });
125
+
126
+ it('handles empty custom values array', () => {
127
+ render(
128
+ <NumberTextFieldCustom
129
+ {...defaultProps}
130
+ customValues={[]}
131
+ value={5}
132
+ />,
133
+ );
134
+ const input = screen.getByRole('spinbutton');
135
+ expect(input).toHaveValue(5);
136
+ });
137
+
138
+ it('displays custom value when selected', () => {
139
+ render(
140
+ <NumberTextFieldCustom
141
+ {...defaultProps}
142
+ customValues={['auto', 'fixed', 'dynamic']}
143
+ value="fixed"
144
+ />,
145
+ );
146
+ const input = screen.getByRole('spinbutton');
147
+ expect(input).toBeInTheDocument();
148
+ });
149
+ });
150
+
151
+ describe('step functionality', () => {
152
+ it('uses default step of 1', () => {
153
+ const onChange = jest.fn();
154
+ render(
155
+ <NumberTextFieldCustom
156
+ {...defaultProps}
157
+ value={5}
158
+ onChange={onChange}
159
+ />,
160
+ );
161
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
162
+ });
163
+
164
+ it('uses custom step value', () => {
165
+ const onChange = jest.fn();
166
+ render(
167
+ <NumberTextFieldCustom
168
+ {...defaultProps}
169
+ value={5}
170
+ step={0.5}
171
+ onChange={onChange}
172
+ />,
173
+ );
174
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
175
+ });
176
+
177
+ it('increments value by step with add button', async () => {
178
+ const user = userEvent.setup();
179
+ const onChange = jest.fn();
180
+ render(
181
+ <NumberTextFieldCustom
182
+ {...defaultProps}
183
+ value={5}
184
+ step={2}
185
+ onChange={onChange}
186
+ />,
187
+ );
188
+
189
+ const buttons = screen.getAllByRole('button');
190
+ const addButton = buttons.find((btn) => btn.querySelector('[data-testid], svg'));
191
+
192
+ if (addButton) {
193
+ await user.click(addButton);
194
+ }
195
+ });
196
+
197
+ it('decrements value by step with remove button', async () => {
198
+ const user = userEvent.setup();
199
+ const onChange = jest.fn();
200
+ render(
201
+ <NumberTextFieldCustom
202
+ {...defaultProps}
203
+ value={5}
204
+ step={1}
205
+ onChange={onChange}
206
+ />,
207
+ );
208
+
209
+ const buttons = screen.getAllByRole('button');
210
+ const removeButton = buttons[0];
211
+
212
+ if (removeButton) {
213
+ await user.click(removeButton);
214
+ }
215
+ });
216
+ });
217
+
218
+ describe('min/max constraints', () => {
219
+ it('clamps value to min', async () => {
220
+ const user = userEvent.setup();
221
+ render(
222
+ <NumberTextFieldCustom
223
+ {...defaultProps}
224
+ value={0}
225
+ min={1}
226
+ max={10}
227
+ />,
228
+ );
229
+
230
+ const input = screen.getByRole('spinbutton');
231
+ fireEvent.blur(input);
232
+
233
+ await waitFor(() => {
234
+ expect(input).toHaveValue(1);
235
+ });
236
+ });
237
+
238
+ it('clamps value to max', async () => {
239
+ const user = userEvent.setup();
240
+ render(
241
+ <NumberTextFieldCustom
242
+ {...defaultProps}
243
+ value={15}
244
+ min={1}
245
+ max={10}
246
+ />,
247
+ );
248
+
249
+ const input = screen.getByRole('spinbutton');
250
+ fireEvent.blur(input);
251
+
252
+ await waitFor(() => {
253
+ expect(input).toHaveValue(10);
254
+ });
255
+ });
256
+
257
+ it('handles only min constraint', () => {
258
+ render(
259
+ <NumberTextFieldCustom
260
+ {...defaultProps}
261
+ value={5}
262
+ min={3}
263
+ />,
264
+ );
265
+ expect(screen.getByRole('spinbutton')).toHaveValue(5);
266
+ });
267
+
268
+ it('handles only max constraint', () => {
269
+ render(
270
+ <NumberTextFieldCustom
271
+ {...defaultProps}
272
+ value={5}
273
+ max={10}
274
+ />,
275
+ );
276
+ expect(screen.getByRole('spinbutton')).toHaveValue(5);
277
+ });
278
+ });
279
+
280
+ describe('props updates', () => {
281
+ it('updates value when prop changes', () => {
282
+ const { rerender } = render(
283
+ <NumberTextFieldCustom
284
+ {...defaultProps}
285
+ value={5}
286
+ />,
287
+ );
288
+
289
+ let input = screen.getByRole('spinbutton');
290
+ expect(input).toHaveValue(5);
291
+
292
+ rerender(
293
+ <NumberTextFieldCustom
294
+ {...defaultProps}
295
+ value={8}
296
+ />,
297
+ );
298
+
299
+ input = screen.getByRole('spinbutton');
300
+ expect(input).toHaveValue(8);
301
+ });
302
+
303
+ it('updates when label changes', () => {
304
+ const { rerender } = render(
305
+ <NumberTextFieldCustom
306
+ {...defaultProps}
307
+ label="Old Label"
308
+ />,
309
+ );
310
+
311
+ expect(screen.getByLabelText('Old Label')).toBeInTheDocument();
312
+
313
+ rerender(
314
+ <NumberTextFieldCustom
315
+ {...defaultProps}
316
+ label="New Label"
317
+ />,
318
+ );
319
+
320
+ expect(screen.getByLabelText('New Label')).toBeInTheDocument();
321
+ });
322
+
323
+ it('updates constraints when min/max props change', () => {
324
+ const { rerender } = render(
325
+ <NumberTextFieldCustom
326
+ {...defaultProps}
327
+ value={5}
328
+ min={1}
329
+ max={10}
330
+ />,
331
+ );
332
+
333
+ rerender(
334
+ <NumberTextFieldCustom
335
+ {...defaultProps}
336
+ value={5}
337
+ min={1}
338
+ max={8}
339
+ />,
340
+ );
341
+
342
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
343
+ });
344
+ });
345
+
346
+ describe('text alignment', () => {
347
+ it('renders with center alignment (default)', () => {
348
+ render(
349
+ <NumberTextFieldCustom
350
+ {...defaultProps}
351
+ value={5}
352
+ />,
353
+ );
354
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
355
+ });
356
+
357
+ it('renders with custom left alignment', () => {
358
+ render(
359
+ <NumberTextFieldCustom
360
+ {...defaultProps}
361
+ value={5}
362
+ textAlign="left"
363
+ />,
364
+ );
365
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
366
+ });
367
+
368
+ it('renders with right alignment', () => {
369
+ render(
370
+ <NumberTextFieldCustom
371
+ {...defaultProps}
372
+ value={5}
373
+ textAlign="right"
374
+ />,
375
+ );
376
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
377
+ });
378
+ });
379
+
380
+ describe('type property', () => {
381
+ it('renders as number type by default', () => {
382
+ const { container } = render(
383
+ <NumberTextFieldCustom
384
+ {...defaultProps}
385
+ value={5}
386
+ />,
387
+ );
388
+ const input = container.querySelector('input[type="number"]');
389
+ expect(input).toBeInTheDocument();
390
+ });
391
+
392
+ it('can render with custom type', () => {
393
+ const { container } = render(
394
+ <NumberTextFieldCustom
395
+ {...defaultProps}
396
+ value={5}
397
+ type="text"
398
+ />,
399
+ );
400
+ const input = container.querySelector('input');
401
+ expect(input).toBeInTheDocument();
402
+ });
403
+ });
404
+
405
+ describe('accessibility', () => {
406
+ it('renders as a spinbutton', () => {
407
+ render(<NumberTextFieldCustom {...defaultProps} />);
408
+ expect(screen.getByRole('spinbutton')).toBeInTheDocument();
409
+ });
410
+
411
+ it('has proper label association', () => {
412
+ render(
413
+ <NumberTextFieldCustom
414
+ {...defaultProps}
415
+ label="Price"
416
+ />,
417
+ );
418
+ expect(screen.getByLabelText('Price')).toBeInTheDocument();
419
+ });
420
+
421
+ it('supports keyboard navigation', async () => {
422
+ const user = userEvent.setup();
423
+ render(
424
+ <NumberTextFieldCustom
425
+ {...defaultProps}
426
+ value={5}
427
+ />,
428
+ );
429
+
430
+ const input = screen.getByRole('spinbutton');
431
+ input.focus();
432
+ expect(input).toHaveFocus();
433
+
434
+ await user.keyboard('{ArrowUp}');
435
+ expect(input).toHaveFocus();
436
+ });
437
+ });
438
+ });