@scenid/react-formulator 0.5.2 → 0.5.4

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 (64) hide show
  1. package/dist/index.cjs.js +34 -19
  2. package/dist/index.esm.js +34 -19
  3. package/package.json +4 -1
  4. package/.babelrc +0 -30
  5. package/.eslintignore +0 -22
  6. package/.eslintrc +0 -70
  7. package/.firebaserc +0 -5
  8. package/.storybook/main.js +0 -12
  9. package/.storybook/preview.js +0 -9
  10. package/firebase.json +0 -22
  11. package/functions/.eslintignore +0 -1
  12. package/functions/.eslintrc.js +0 -29
  13. package/functions/index.js +0 -32
  14. package/functions/package-lock.json +0 -6810
  15. package/functions/package.json +0 -29
  16. package/rollup.config.js +0 -40
  17. package/src/Components/HiddenData.jsx +0 -24
  18. package/src/Components/SelectOrCreate.jsx +0 -156
  19. package/src/Editable/FormAutocomplete/FormAutocomplete.jsx +0 -164
  20. package/src/Editable/FormAutocomplete/useFetchOptions.js +0 -83
  21. package/src/Editable/FormBoolean.jsx +0 -46
  22. package/src/Editable/FormCatalogType.jsx +0 -29
  23. package/src/Editable/FormField.jsx +0 -231
  24. package/src/Editable/FormNumber.jsx +0 -36
  25. package/src/Editable/FormRepeater.jsx +0 -218
  26. package/src/Editable/FormSelect.jsx +0 -52
  27. package/src/Editable/FormText.jsx +0 -20
  28. package/src/FormGroupHeader.jsx +0 -85
  29. package/src/FormHelpers.js +0 -191
  30. package/src/FormSectionBlock.jsx +0 -71
  31. package/src/FormSectionCard.jsx +0 -62
  32. package/src/FormulatorForm.jsx +0 -539
  33. package/src/FormulatorFormSection.jsx +0 -457
  34. package/src/ReadOnly/FormReadOnlyBoolean.jsx +0 -36
  35. package/src/ReadOnly/FormReadOnlyField.jsx +0 -126
  36. package/src/ReadOnly/FormReadOnlyMarkdown.jsx +0 -20
  37. package/src/ReadOnly/FormReadOnlyNumber.jsx +0 -17
  38. package/src/ReadOnly/FormReadOnlyRepeater.jsx +0 -36
  39. package/src/ReadOnly/FormReadOnlySelect.jsx +0 -18
  40. package/src/ReadOnly/FormReadOnlyText.jsx +0 -41
  41. package/src/helpers.js +0 -13
  42. package/src/index.js +0 -20
  43. package/stories/CustomRenderField.jsx +0 -46
  44. package/stories/Forms.stories.jsx +0 -267
  45. package/stories/Introduction.stories.mdx +0 -206
  46. package/stories/StoryBase.jsx +0 -35
  47. package/stories/assets/code-brackets.svg +0 -1
  48. package/stories/assets/colors.svg +0 -1
  49. package/stories/assets/comments.svg +0 -1
  50. package/stories/assets/direction.svg +0 -1
  51. package/stories/assets/flow.svg +0 -1
  52. package/stories/assets/plugin.svg +0 -1
  53. package/stories/assets/repo.svg +0 -1
  54. package/stories/assets/stackalt.svg +0 -1
  55. package/stories/forms/login.render.schema.json +0 -23
  56. package/stories/forms/login.validation.schema.json +0 -29
  57. package/stories/forms/markdown.render.schema.json +0 -30
  58. package/stories/forms/markdown.validation.schema.json +0 -18
  59. package/stories/forms/register.render.schema.json +0 -32
  60. package/stories/forms/register.validation.schema.json +0 -34
  61. package/stories/forms/rlp.render.schema.json +0 -153
  62. package/stories/forms/rlp.translations.json +0 -883
  63. package/stories/forms/rlp.validation.schema.json +0 -1631
  64. package/stories/forms/types.schemas.js +0 -319
@@ -1,539 +0,0 @@
1
- import React from 'react'
2
- import PropTypes from 'prop-types'
3
-
4
- import EventEmitter from 'eventemitter3'
5
- import { validate as validator } from '@scenid/formulator'
6
- import isEqual from 'fast-deep-equal'
7
-
8
- import { render as mm } from 'micromustache'
9
-
10
- import FormulatorFormSection from './FormulatorFormSection'
11
- import HiddenData from './Components/HiddenData'
12
-
13
- import 'highlight.js/styles/shades-of-purple.css'
14
-
15
- const asyncValidatorEnvelope = async (path, func) => {
16
- const r = await func()
17
-
18
- if (r !== true) {
19
- return ({
20
- path,
21
- validator: 'Async',
22
- message: r
23
- })
24
- }
25
-
26
- return true
27
- }
28
-
29
- const validate = async (ee, schema, data, oldAsyncErrors, fieldStates, asyncValidators) => {
30
- const { errors, results, ...rest } = validator(schema, data)
31
-
32
- let asyncResults = []
33
- let asyncErrors = oldAsyncErrors
34
-
35
- if (asyncValidators) {
36
- const activeValidators = (
37
- Object
38
- .entries(asyncValidators)
39
- .map(e => ({ path: e[0], func: e[1] }))
40
- .filter(({ path }) => results[path].sanitizedData !== undefined)
41
- )
42
-
43
- if (activeValidators.length > 0) {
44
- const newFieldStates = JSON.parse(JSON.stringify(fieldStates))
45
- activeValidators.forEach(({ path }) => { newFieldStates[path].validating = true })
46
- ee.emit('fieldStates', newFieldStates)
47
-
48
- asyncResults = await Promise.all(
49
- activeValidators
50
- .map(({ path, func }) => {
51
- if (data[path]) {
52
- return asyncValidatorEnvelope(
53
- path,
54
- () => func(path, data[path])
55
- )
56
- }
57
- return Promise.resolve(true)
58
- })
59
- )
60
-
61
- asyncErrors = asyncResults.filter(m => m !== true)
62
- }
63
- }
64
-
65
- const mergedErrors = [...errors, ...asyncErrors]
66
-
67
- const mergedResults = { ...results }
68
- asyncErrors.forEach(e => {
69
- const fr = mergedResults[e.path]
70
- fr.errors = [...fr.errors, e]
71
- fr.hasErrors = true
72
- fr.sanitizedData = undefined
73
- })
74
-
75
- ee.emit(
76
- 'validation',
77
- {
78
- ...rest,
79
- hasErrors: Object.keys(mergedErrors).length > 0,
80
- errors: mergedErrors,
81
- asyncErrors,
82
- results: mergedResults,
83
- fieldStates
84
- }
85
- )
86
- }
87
-
88
- const validateSync = (schema, data) => validator(schema, data)
89
-
90
- const getInitialData = (schema, iniData, transientData, iniFieldStates) => {
91
- const { hasErrors, errors, results, data, sanitizedData } = validateSync(schema, { ...iniData, ...transientData })
92
-
93
- const fieldStates = iniFieldStates || (
94
- Object
95
- .keys(results)
96
- .map(path => ({
97
- [path]: {
98
- validating: false,
99
- active: false,
100
- touched: false,
101
- dirty: false,
102
- inactive: true,
103
- pristine: true,
104
- clean: true
105
- }
106
- }))
107
- .reduce((l, r) => ({ ...l, ...r }), {})
108
- )
109
-
110
- const finalData = (
111
- Object
112
- .entries(data)
113
- .map(e => {
114
- let value = e[1]
115
- if (value === undefined && sanitizedData[e[0]] !== undefined) value = sanitizedData[e[0]]
116
- return { [e[0]]: value }
117
- })
118
- .reduce((l, r) => ({ ...l, ...r }), {})
119
- )
120
-
121
- return ({
122
- preSubmitValidation: false,
123
- hasErrors,
124
- isDirty: Object.values(fieldStates).reduce((l, r) => l || r.dirty, false),
125
- errors,
126
- results,
127
- data: finalData,
128
- asyncErrors: [],
129
- fieldStates
130
- })
131
- }
132
-
133
- class FormulatorForm extends React.Component {
134
- constructor(props) {
135
- super(props)
136
-
137
- const { schema, data, transientData, fieldStates, onStateChange } = props
138
-
139
- this.state = getInitialData(schema, data, transientData, fieldStates)
140
-
141
- this.handleFieldChange = this.handleFieldChange.bind(this)
142
- this.handleFocus = this.handleFocus.bind(this)
143
- this.handleBlur = this.handleBlur.bind(this)
144
-
145
- this.ee = new EventEmitter()
146
-
147
- this.ee.addListener('validation', this.handleValidation.bind(this))
148
- if (onStateChange) this.ee.addListener('validation', onStateChange)
149
-
150
- this.ee.addListener('fieldStates', this.handleFieldStates.bind(this))
151
- }
152
-
153
- componentDidMount() {
154
- this.reportStatus()
155
- }
156
-
157
- componentDidUpdate(prevProps) {
158
- const { data, transientData } = this.props
159
-
160
- if (!isEqual(prevProps.data, data)) {
161
- this.reinitialize()
162
- }
163
-
164
- if (transientData && !isEqual(transientData, prevProps.transientData)) {
165
- this.forceFieldChanges(
166
- Object
167
- .entries(transientData)
168
- .filter(e => e[1] !== prevProps.data[e[0]])
169
- .map(e => ({ name: e[0], value: e[1] }))
170
- )
171
- }
172
- }
173
-
174
- componentWillUnmount() {
175
- const { hasErrors, isDirty, data, fieldStates } = this.state
176
- const { onUnmount } = this.props
177
-
178
- if (onUnmount) onUnmount({ hasErrors, isDirty, data, fieldStates })
179
- this.ee.removeAllListeners()
180
- }
181
-
182
- reinitialize() {
183
- const { schema, data, transientData } = this.props
184
-
185
- this.setState(getInitialData(schema, data, transientData))
186
- }
187
-
188
- forceFieldChanges(transientData) {
189
- const { schema, data: initData, disabled, asyncValidators } = this.props
190
- const { preSubmitValidation, data: oldData, asyncErrors, fieldStates } = this.state
191
-
192
- if (preSubmitValidation || disabled) return
193
-
194
- const newData = { ...oldData }
195
- let newAsyncErrors = []
196
- const newFieldStates = { ...fieldStates }
197
-
198
- transientData.forEach(({ name, value }) => {
199
- let finalValue = value
200
- if (schema.properties[name].type === 'boolean') finalValue = oldData[name] !== true
201
-
202
- const isDirty = initData[name] !== value
203
-
204
- newAsyncErrors = asyncErrors.filter(({ path }) => path !== name).concat(newAsyncErrors)
205
-
206
- newFieldStates[name] = {
207
- ...fieldStates[name],
208
- dirty: isDirty,
209
- clean: !isDirty
210
- }
211
-
212
- newData[name] = finalValue
213
- })
214
-
215
- validate(
216
- this.ee,
217
- schema,
218
- newData,
219
- newAsyncErrors,
220
- newFieldStates,
221
- asyncValidators
222
- )
223
- }
224
-
225
- handleFieldChange(e) {
226
- const { name, value } = e.target
227
-
228
- const { schema, data: initData, disabled, asyncValidators } = this.props
229
- const { preSubmitValidation, data: oldData, asyncErrors, fieldStates } = this.state
230
-
231
- if (preSubmitValidation || disabled) return
232
-
233
- const isDirty = initData[name] !== value
234
-
235
- const newAsyncErrors = asyncErrors.filter(({ path }) => path !== name)
236
-
237
- validate(
238
- this.ee,
239
- schema,
240
- { ...oldData, [name]: value },
241
- newAsyncErrors,
242
- {
243
- ...fieldStates,
244
- [name]: {
245
- ...fieldStates[name],
246
- dirty: isDirty,
247
- clean: !isDirty
248
- }
249
- },
250
- asyncValidators
251
- )
252
- }
253
-
254
- handleValidation({ hasErrors, fieldStates, errors, ...result }) {
255
- const { onSubmit, onStatusUpdate } = this.props
256
- const { preSubmitValidation } = this.state
257
-
258
- const statusFields = {
259
- preSubmitValidation: false,
260
- hasErrors,
261
- errors,
262
- isDirty: Object.values(fieldStates).reduce((l, r) => l || r.dirty, false)
263
- }
264
-
265
- this.setState(
266
- { ...statusFields, fieldStates, errors, ...result },
267
- () => {
268
- if (onStatusUpdate) onStatusUpdate(statusFields)
269
-
270
- if (preSubmitValidation && !hasErrors && onSubmit) onSubmit(result.sanitizedData)
271
- }
272
- )
273
- }
274
-
275
- reportStatus() {
276
- const { onStatusUpdate } = this.props
277
- const { hasErrors, fieldStates } = this.state
278
-
279
- const statusFields = {
280
- preSubmitValidation: false,
281
- hasErrors,
282
- isDirty: Object.values(fieldStates).reduce((l, r) => l || r.dirty, false)
283
- }
284
-
285
- if (onStatusUpdate) onStatusUpdate(statusFields)
286
- }
287
-
288
- handleFieldStates(fieldStates) {
289
- this.setState({ fieldStates })
290
- }
291
-
292
- handleSubmit() {
293
- const { schema, asyncValidators, onStatusUpdate } = this.props
294
- const { errors, hasErrors, data, asyncErrors, fieldStates } = this.state
295
-
296
- this.setState(
297
- { preSubmitValidation: true },
298
- () => {
299
- const statusFields = {
300
- preSubmitValidation: true,
301
- hasErrors,
302
- errors,
303
- isDirty: Object.values(fieldStates).reduce((l, r) => l || r.dirty, false)
304
- }
305
-
306
- if (onStatusUpdate) onStatusUpdate(statusFields)
307
-
308
- validate(this.ee, schema, data, asyncErrors, fieldStates, asyncValidators)
309
- }
310
- )
311
- }
312
-
313
- setFieldState(path, flags) {
314
- const { fieldStates } = this.state
315
-
316
- this.setState({
317
- fieldStates: {
318
- ...fieldStates,
319
- [path]: {
320
- ...fieldStates[path],
321
- ...flags
322
- }
323
- }
324
- })
325
- }
326
-
327
- handleFocus(e) {
328
- const path = e.target.name
329
-
330
- this.setFieldState(
331
- path,
332
- {
333
- active: true,
334
- inactive: false
335
- }
336
- )
337
- }
338
-
339
- handleBlur(e) {
340
- const path = e.target.name
341
-
342
- this.setFieldState(
343
- path,
344
- {
345
- active: false,
346
- inactive: true,
347
- touched: true,
348
- pristine: false
349
- }
350
- )
351
- }
352
-
353
- render() {
354
- const {
355
- id,
356
- variant,
357
- inputVariant,
358
- groupLabelVariant,
359
- groupDescVariant,
360
- textAlign,
361
- readOnly,
362
- listErrors,
363
- schema,
364
- renderSchema,
365
- disabled: propDisabled,
366
- translations,
367
- componentMap,
368
- renderComponentMap,
369
- obscuredFields,
370
- obscuredGroups,
371
- errorMessages,
372
- onReset
373
- } = this.props
374
-
375
- const {
376
- hasErrors,
377
- errors,
378
- results,
379
- data,
380
- fieldStates,
381
- preSubmitValidation
382
- } = this.state
383
-
384
- const disabled = preSubmitValidation || propDisabled
385
-
386
- return (
387
- <form
388
- id={id}
389
- className="formulator-form"
390
- disabled={disabled}
391
- onSubmit={e => {
392
- e.preventDefault()
393
- if (!disabled) this.handleSubmit()
394
- }}
395
- onReset={e => {
396
- e.preventDefault()
397
- this.reinitialize()
398
- if (onReset) onReset()
399
- }}
400
- >
401
- {
402
- renderSchema.title
403
- && <h5>{renderSchema.title}</h5>
404
- }
405
- {
406
- renderSchema.description
407
- && <h5>{renderSchema.description}</h5>
408
- }
409
- {
410
- renderSchema.groups
411
- .map(({ id: sectionId, label, description, fields }) => {
412
- if (readOnly && Array.isArray(obscuredGroups) && obscuredGroups.includes(sectionId)) {
413
- return <HiddenData key={`hidden-field-${sectionId}`} subject="Der Bereich" label={label} />
414
- }
415
-
416
- return (
417
- <FormulatorFormSection
418
- key={`form-section-${sectionId}`}
419
- id={id}
420
- sectionId={sectionId}
421
- variant={variant}
422
- inputVariant={inputVariant}
423
- labelVariant={groupLabelVariant}
424
- descVariant={groupDescVariant}
425
- textAlign={textAlign}
426
- readOnly={readOnly}
427
- disabled={disabled}
428
- schema={schema}
429
- label={label}
430
- desc={description}
431
- fields={fields}
432
- results={results}
433
- data={data}
434
- fieldStates={fieldStates}
435
- obscuredFields={obscuredFields}
436
- translations={translations}
437
- errorMessages={errorMessages}
438
- componentMap={componentMap}
439
- renderComponentMap={renderComponentMap}
440
- onChange={this.handleFieldChange}
441
- />
442
- )
443
- })
444
- }
445
- {
446
- (listErrors && hasErrors)
447
- && (
448
- <div className="errors">
449
- {
450
- errors.map(({ path, message, options, validator: eVal }) => {
451
- let finalMessage = message
452
-
453
- if (options && options.human) finalMessage = options.human
454
- else if (errorMessages[eVal]) finalMessage = mm(errorMessages[eVal], options)
455
-
456
- return (
457
- <div
458
- key={`form-error-${path}-${validator}`}
459
- className="error"
460
- >
461
- <div className="field">{translations.labels[path] || path}</div>
462
- <div className="message">
463
- {finalMessage}
464
- </div>
465
- </div>
466
- )
467
- })
468
- }
469
- </div>
470
- )
471
- }
472
- </form>
473
- )
474
- }
475
- }
476
-
477
- FormulatorForm.propTypes = {
478
- id: PropTypes.string.isRequired,
479
- variant: PropTypes.oneOf(['card', 'block']),
480
- inputVariant: PropTypes.oneOf(['standard', 'filled', 'outlined']),
481
- textAlign: PropTypes.oneOf(['left', 'center', 'right']),
482
- groupLabelVariant: PropTypes.oneOf([
483
- 'h1',
484
- 'h2',
485
- 'h3',
486
- 'h4',
487
- 'h5',
488
- 'h6',
489
- 'subtitle1',
490
- 'subtitle2',
491
- 'body1',
492
- 'body2',
493
- 'button',
494
- 'caption',
495
- 'overline'
496
- ]),
497
- groupDescVariant: PropTypes.oneOf([
498
- 'h1',
499
- 'h2',
500
- 'h3',
501
- 'h4',
502
- 'h5',
503
- 'h6',
504
- 'subtitle1',
505
- 'subtitle2',
506
- 'body1',
507
- 'body2',
508
- 'button',
509
- 'caption',
510
- 'overline'
511
- ]),
512
- disabled: PropTypes.bool,
513
- readOnly: PropTypes.bool,
514
- listErrors: PropTypes.bool,
515
- schema: PropTypes.object.isRequired,
516
- data: PropTypes.object.isRequired,
517
- transientData: PropTypes.object,
518
- fieldStates: PropTypes.object,
519
- renderSchema: PropTypes.object.isRequired,
520
- translations: PropTypes.object.isRequired,
521
- asyncValidators: PropTypes.object,
522
- errorMessages: PropTypes.object,
523
- componentMap: PropTypes.object,
524
- renderComponentMap: PropTypes.object,
525
- obscuredFields: PropTypes.array,
526
- obscuredGroups: PropTypes.array,
527
- onSubmit: PropTypes.func,
528
- onReset: PropTypes.func,
529
- onStatusUpdate: PropTypes.func,
530
- onStateChange: PropTypes.func,
531
- onUnmount: PropTypes.func
532
- }
533
-
534
- FormulatorForm.defaultProps = {
535
- variant: 'card',
536
- errorMessages: {}
537
- }
538
-
539
- export default FormulatorForm