@khanacademy/wonder-blocks-form 4.2.2 → 4.3.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 (33) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/checkbox-core.d.ts +13 -8
  3. package/dist/components/checkbox-core.js.flow +19 -10
  4. package/dist/components/checkbox-group.d.ts +2 -5
  5. package/dist/components/checkbox-group.js.flow +5 -6
  6. package/dist/components/checkbox.d.ts +33 -39
  7. package/dist/components/checkbox.js.flow +38 -41
  8. package/dist/components/choice-internal.d.ts +19 -31
  9. package/dist/components/choice-internal.js.flow +25 -32
  10. package/dist/components/choice.d.ts +50 -60
  11. package/dist/components/choice.js.flow +79 -84
  12. package/dist/components/radio-core.d.ts +13 -5
  13. package/dist/components/radio-core.js.flow +19 -7
  14. package/dist/components/radio-group.d.ts +2 -5
  15. package/dist/components/radio-group.js.flow +5 -6
  16. package/dist/components/radio.d.ts +18 -24
  17. package/dist/components/radio.js.flow +24 -27
  18. package/dist/es/index.js +262 -294
  19. package/dist/index.js +262 -294
  20. package/dist/util/types.d.ts +1 -1
  21. package/dist/util/types.js.flow +1 -1
  22. package/package.json +6 -6
  23. package/src/components/__tests__/{checkbox.test.js → checkbox.test.tsx} +55 -1
  24. package/src/components/checkbox-core.tsx +32 -31
  25. package/src/components/checkbox-group.tsx +33 -22
  26. package/src/components/checkbox.tsx +21 -16
  27. package/src/components/choice-internal.tsx +60 -58
  28. package/src/components/choice.tsx +39 -32
  29. package/src/components/radio-core.tsx +16 -14
  30. package/src/components/radio-group.tsx +14 -11
  31. package/src/components/radio.tsx +21 -16
  32. package/src/util/types.ts +1 -1
  33. package/tsconfig-build.tsbuildinfo +1 -1
package/dist/es/index.js CHANGED
@@ -62,61 +62,55 @@ const checkPath = {
62
62
  const indeterminatePath = {
63
63
  small: "M3 8C3 7.44772 3.44772 7 4 7H12C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9H4C3.44772 9 3 8.55228 3 8Z"
64
64
  };
65
- class CheckboxCore extends React.Component {
66
- constructor(...args) {
67
- super(...args);
68
- this.inputRef = React.createRef();
69
- this.handleChange = () => {
70
- return;
71
- };
72
- }
73
- componentDidMount() {
74
- if (this.props.checked == null && this.inputRef.current != null) {
75
- this.inputRef.current.indeterminate = true;
76
- }
77
- }
78
- componentDidUpdate(prevProps) {
79
- if (this.inputRef.current != null) {
80
- this.inputRef.current.indeterminate = this.props.checked == null;
65
+ const CheckboxCore = React.forwardRef((props, ref) => {
66
+ const {
67
+ checked,
68
+ disabled,
69
+ error,
70
+ groupName,
71
+ id,
72
+ testId
73
+ } = props,
74
+ sharedProps = _objectWithoutPropertiesLoose(props, _excluded$4);
75
+ const innerRef = React.useRef(null);
76
+ React.useEffect(() => {
77
+ if (innerRef.current != null) {
78
+ innerRef.current.indeterminate = checked == null;
81
79
  }
82
- }
83
- render() {
84
- const _this$props = this.props,
85
- {
86
- checked,
87
- disabled,
88
- error,
89
- groupName,
90
- id,
91
- testId
92
- } = _this$props,
93
- sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
94
- const stateStyles = _generateStyles$1(checked, error);
95
- const defaultStyle = [sharedStyles$1.inputReset, sharedStyles$1.default, !disabled && stateStyles.default, disabled && sharedStyles$1.disabled];
96
- const props = {
97
- "data-test-id": testId
98
- };
99
- const checkboxIcon = React.createElement(Icon, {
100
- color: disabled ? offBlack32$1 : white$1,
101
- icon: checked ? checkPath : indeterminatePath,
102
- size: "small",
103
- style: sharedStyles$1.checkboxIcon
104
- });
105
- const ariaChecked = mapCheckedToAriaChecked(checked);
106
- return React.createElement(React.Fragment, null, React.createElement(StyledInput$2, _extends({}, sharedProps, {
107
- ref: this.inputRef,
108
- type: "checkbox",
109
- "aria-checked": ariaChecked,
110
- "aria-invalid": error,
111
- checked: checked != null ? checked : undefined,
112
- disabled: disabled,
113
- id: id,
114
- name: groupName,
115
- onChange: this.handleChange,
116
- style: defaultStyle
117
- }, props)), checked || checked == null ? checkboxIcon : React.createElement(React.Fragment, null));
118
- }
119
- }
80
+ }, [checked, innerRef]);
81
+ const handleChange = () => {
82
+ return;
83
+ };
84
+ const stateStyles = _generateStyles$1(checked, error);
85
+ const defaultStyle = [sharedStyles$1.inputReset, sharedStyles$1.default, !disabled && stateStyles.default, disabled && sharedStyles$1.disabled];
86
+ const checkboxIcon = React.createElement(Icon, {
87
+ color: disabled ? offBlack32$1 : white$1,
88
+ icon: checked ? checkPath : indeterminatePath,
89
+ size: "small",
90
+ style: sharedStyles$1.checkboxIcon
91
+ });
92
+ const ariaChecked = mapCheckedToAriaChecked(checked);
93
+ return React.createElement(React.Fragment, null, React.createElement(StyledInput$2, _extends({}, sharedProps, {
94
+ ref: node => {
95
+ innerRef.current = node;
96
+ if (typeof ref === "function") {
97
+ ref(node);
98
+ } else if (ref != null) {
99
+ ref.current = node;
100
+ }
101
+ },
102
+ type: "checkbox",
103
+ "aria-checked": ariaChecked,
104
+ "aria-invalid": error,
105
+ checked: checked != null ? checked : undefined,
106
+ disabled: disabled,
107
+ id: id,
108
+ name: groupName,
109
+ onChange: handleChange,
110
+ style: defaultStyle,
111
+ "data-test-id": testId
112
+ })), checked || checked == null ? checkboxIcon : React.createElement(React.Fragment, null));
113
+ });
120
114
  const size$1 = 16;
121
115
  const sharedStyles$1 = StyleSheet.create({
122
116
  inputReset: {
@@ -226,43 +220,36 @@ const {
226
220
  offBlack50
227
221
  } = Color;
228
222
  const StyledInput$1 = addStyle("input");
229
- class RadioCore extends React.Component {
230
- constructor(...args) {
231
- super(...args);
232
- this.handleChange = () => {
233
- return;
234
- };
235
- }
236
- render() {
237
- const _this$props = this.props,
238
- {
239
- checked,
240
- disabled,
241
- error,
242
- groupName,
243
- id,
244
- testId
245
- } = _this$props,
246
- sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$3);
247
- const stateStyles = _generateStyles(checked, error);
248
- const defaultStyle = [sharedStyles.inputReset, sharedStyles.default, !disabled && stateStyles.default, disabled && sharedStyles.disabled];
249
- const props = {
250
- "data-test-id": testId
251
- };
252
- return React.createElement(React.Fragment, null, React.createElement(StyledInput$1, _extends({}, sharedProps, {
253
- type: "radio",
254
- "aria-invalid": error,
255
- checked: checked != null ? checked : undefined,
256
- disabled: disabled,
257
- id: id,
258
- name: groupName,
259
- onChange: this.handleChange,
260
- style: defaultStyle
261
- }, props)), disabled && checked && React.createElement("span", {
262
- style: disabledChecked
263
- }));
264
- }
265
- }
223
+ const RadioCore = React.forwardRef((props, ref) => {
224
+ const handleChange = () => {
225
+ return;
226
+ };
227
+ const {
228
+ checked,
229
+ disabled,
230
+ error,
231
+ groupName,
232
+ id,
233
+ testId
234
+ } = props,
235
+ sharedProps = _objectWithoutPropertiesLoose(props, _excluded$3);
236
+ const stateStyles = _generateStyles(checked, error);
237
+ const defaultStyle = [sharedStyles.inputReset, sharedStyles.default, !disabled && stateStyles.default, disabled && sharedStyles.disabled];
238
+ return React.createElement(React.Fragment, null, React.createElement(StyledInput$1, _extends({}, sharedProps, {
239
+ type: "radio",
240
+ "aria-invalid": error,
241
+ checked: checked != null ? checked : undefined,
242
+ disabled: disabled,
243
+ id: id,
244
+ name: groupName,
245
+ onChange: handleChange,
246
+ style: defaultStyle,
247
+ "data-test-id": testId,
248
+ ref: ref
249
+ })), disabled && checked && React.createElement("span", {
250
+ style: disabledChecked
251
+ }));
252
+ });
266
253
  const size = 16;
267
254
  const disabledChecked = {
268
255
  position: "absolute",
@@ -367,86 +354,70 @@ const _generateStyles = (checked, error) => {
367
354
  return styles$4[styleKey];
368
355
  };
369
356
 
370
- const _excluded$2 = ["label", "description", "id", "onChange", "style", "className", "variant"];
371
- class ChoiceInternal extends React.Component {
372
- constructor(...args) {
373
- super(...args);
374
- this.handleClick = () => {
375
- const {
376
- checked,
377
- onChange,
378
- variant
379
- } = this.props;
380
- if (variant === "radio" && checked) {
381
- return;
382
- }
383
- onChange(!checked);
384
- };
385
- }
386
- getChoiceCoreComponent() {
387
- if (this.props.variant === "radio") {
357
+ const ChoiceInternal = React.forwardRef((props, ref) => {
358
+ const {
359
+ checked,
360
+ description,
361
+ disabled = false,
362
+ error = false,
363
+ id,
364
+ label,
365
+ onChange,
366
+ style,
367
+ className,
368
+ variant
369
+ } = props;
370
+ const handleClick = () => {
371
+ if (variant === "radio" && checked) {
372
+ return;
373
+ }
374
+ onChange(!checked);
375
+ };
376
+ const getChoiceCoreComponent = () => {
377
+ if (variant === "radio") {
388
378
  return RadioCore;
389
379
  } else {
390
380
  return CheckboxCore;
391
381
  }
392
- }
393
- getLabel(id) {
394
- const {
395
- disabled,
396
- label
397
- } = this.props;
382
+ };
383
+ const getLabel = id => {
398
384
  return React.createElement(LabelMedium, {
399
385
  style: [styles$3.label, disabled && styles$3.disabledLabel]
400
386
  }, React.createElement("label", {
401
387
  htmlFor: id
402
388
  }, label));
403
- }
404
- getDescription(id) {
405
- const {
406
- description
407
- } = this.props;
389
+ };
390
+ const getDescription = id => {
408
391
  return React.createElement(LabelSmall, {
409
392
  style: styles$3.description,
410
393
  id: id
411
394
  }, description);
412
- }
413
- render() {
414
- const _this$props = this.props,
415
- {
416
- label,
417
- description,
418
- id,
419
- style,
420
- className
421
- } = _this$props,
422
- coreProps = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
423
- const ChoiceCore = this.getChoiceCoreComponent();
424
- return React.createElement(UniqueIDProvider, {
425
- mockOnFirstRender: true,
426
- scope: "choice"
427
- }, ids => {
428
- const uniqueId = id || ids.get("main");
429
- const descriptionId = description ? ids.get("description") : undefined;
430
- return React.createElement(View, {
431
- style: style,
432
- className: className
433
- }, React.createElement(View, {
434
- style: styles$3.wrapper,
435
- tabIndex: -1
436
- }, React.createElement(ChoiceCore, _extends({}, coreProps, {
437
- id: uniqueId,
438
- "aria-describedby": descriptionId,
439
- onClick: this.handleClick
440
- })), React.createElement(Strut, {
441
- size: Spacing.xSmall_8
442
- }), label && this.getLabel(uniqueId)), description && this.getDescription(descriptionId));
443
- });
444
- }
445
- }
446
- ChoiceInternal.defaultProps = {
447
- disabled: false,
448
- error: false
449
- };
395
+ };
396
+ const ChoiceCore = getChoiceCoreComponent();
397
+ return React.createElement(UniqueIDProvider, {
398
+ mockOnFirstRender: true,
399
+ scope: "choice"
400
+ }, ids => {
401
+ const uniqueId = id || ids.get("main");
402
+ const descriptionId = description ? ids.get("description") : undefined;
403
+ return React.createElement(View, {
404
+ style: style,
405
+ className: className
406
+ }, React.createElement(View, {
407
+ style: styles$3.wrapper,
408
+ tabIndex: -1
409
+ }, React.createElement(ChoiceCore, _extends({}, props, {
410
+ id: uniqueId,
411
+ "aria-describedby": descriptionId,
412
+ onClick: handleClick,
413
+ disabled: disabled,
414
+ error: error,
415
+ ref: ref
416
+ })), React.createElement(Strut, {
417
+ size: Spacing.xSmall_8
418
+ }), label && getLabel(uniqueId)), description && getDescription(descriptionId));
419
+ });
420
+ });
450
421
  const styles$3 = StyleSheet.create({
451
422
  wrapper: {
452
423
  flexDirection: "row",
@@ -466,54 +437,58 @@ const styles$3 = StyleSheet.create({
466
437
  }
467
438
  });
468
439
 
469
- class Checkbox extends React.Component {
470
- render() {
471
- return React.createElement(ChoiceInternal, _extends({
472
- variant: "checkbox"
473
- }, this.props));
474
- }
475
- }
476
- Checkbox.defaultProps = {
477
- disabled: false,
478
- error: false
479
- };
440
+ const Checkbox = React.forwardRef((props, ref) => {
441
+ const {
442
+ disabled = false,
443
+ error = false
444
+ } = props;
445
+ return React.createElement(ChoiceInternal, _extends({}, props, {
446
+ variant: "checkbox",
447
+ disabled: disabled,
448
+ error: error,
449
+ ref: ref
450
+ }));
451
+ });
480
452
 
481
- class Radio extends React.Component {
482
- render() {
483
- return React.createElement(ChoiceInternal, _extends({
484
- variant: "radio"
485
- }, this.props));
486
- }
487
- }
488
- Radio.defaultProps = {
489
- disabled: false,
490
- error: false
491
- };
453
+ const _excluded$2 = ["disabled", "error"];
454
+ const Radio = React.forwardRef((props, ref) => {
455
+ const {
456
+ disabled = false,
457
+ error = false
458
+ } = props,
459
+ otherProps = _objectWithoutPropertiesLoose(props, _excluded$2);
460
+ return React.createElement(ChoiceInternal, _extends({}, otherProps, {
461
+ variant: "radio",
462
+ disabled: disabled,
463
+ error: error,
464
+ ref: ref
465
+ }));
466
+ });
492
467
 
493
- const _excluded$1 = ["value", "variant"];
494
- class Choice extends React.Component {
495
- getChoiceComponent(variant) {
468
+ const _excluded$1 = ["checked", "disabled", "onChange", "value", "variant"];
469
+ const Choice = React.forwardRef((props, ref) => {
470
+ const {
471
+ checked = false,
472
+ disabled = false,
473
+ onChange = () => {},
474
+ variant
475
+ } = props,
476
+ remainingProps = _objectWithoutPropertiesLoose(props, _excluded$1);
477
+ const getChoiceComponent = variant => {
496
478
  if (variant === "checkbox") {
497
479
  return Checkbox;
498
480
  } else {
499
481
  return Radio;
500
482
  }
501
- }
502
- render() {
503
- const _this$props = this.props,
504
- {
505
- variant
506
- } = _this$props,
507
- remainingProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
508
- const ChoiceComponent = this.getChoiceComponent(variant);
509
- return React.createElement(ChoiceComponent, remainingProps);
510
- }
511
- }
512
- Choice.defaultProps = {
513
- checked: false,
514
- disabled: false,
515
- onChange: () => {}
516
- };
483
+ };
484
+ const ChoiceComponent = getChoiceComponent(variant);
485
+ return React.createElement(ChoiceComponent, _extends({}, remainingProps, {
486
+ checked: checked,
487
+ disabled: disabled,
488
+ onChange: onChange,
489
+ ref: ref
490
+ }));
491
+ });
517
492
 
518
493
  const styles$2 = StyleSheet.create({
519
494
  fieldset: {
@@ -539,12 +514,19 @@ const styles$2 = StyleSheet.create({
539
514
 
540
515
  const StyledFieldset$1 = addStyle("fieldset");
541
516
  const StyledLegend$1 = addStyle("legend");
542
- class CheckboxGroup extends React.Component {
543
- handleChange(changedValue, originalCheckedState) {
544
- const {
545
- onChange,
546
- selectedValues
547
- } = this.props;
517
+ const CheckboxGroup = React.forwardRef((props, ref) => {
518
+ const {
519
+ children,
520
+ label,
521
+ description,
522
+ errorMessage,
523
+ groupName,
524
+ onChange,
525
+ selectedValues,
526
+ style,
527
+ testId
528
+ } = props;
529
+ const handleChange = (changedValue, originalCheckedState) => {
548
530
  if (originalCheckedState) {
549
531
  const index = selectedValues.indexOf(changedValue);
550
532
  const updatedSelection = [...selectedValues.slice(0, index), ...selectedValues.slice(index + 1)];
@@ -552,102 +534,88 @@ class CheckboxGroup extends React.Component {
552
534
  } else {
553
535
  onChange([...selectedValues, changedValue]);
554
536
  }
555
- }
556
- render() {
537
+ };
538
+ const allChildren = React.Children.toArray(children).filter(Boolean);
539
+ return React.createElement(StyledFieldset$1, {
540
+ "data-test-id": testId,
541
+ style: styles$2.fieldset,
542
+ ref: ref
543
+ }, React.createElement(View, {
544
+ style: style
545
+ }, label && React.createElement(StyledLegend$1, {
546
+ style: styles$2.legend
547
+ }, React.createElement(LabelMedium, null, label)), description && React.createElement(LabelSmall, {
548
+ style: styles$2.description
549
+ }, description), errorMessage && React.createElement(LabelSmall, {
550
+ style: styles$2.error
551
+ }, errorMessage), (label || description || errorMessage) && React.createElement(Strut, {
552
+ size: Spacing.small_12
553
+ }), allChildren.map((child, index) => {
557
554
  const {
558
- children,
559
- label,
560
- description,
561
- errorMessage,
562
- groupName,
563
- selectedValues,
564
555
  style,
565
- testId
566
- } = this.props;
567
- const allChildren = React.Children.toArray(children).filter(Boolean);
568
- return React.createElement(StyledFieldset$1, {
569
- "data-test-id": testId,
570
- style: styles$2.fieldset
571
- }, React.createElement(View, {
572
- style: style
573
- }, label && React.createElement(StyledLegend$1, {
574
- style: styles$2.legend
575
- }, React.createElement(LabelMedium, null, label)), description && React.createElement(LabelSmall, {
576
- style: styles$2.description
577
- }, description), errorMessage && React.createElement(LabelSmall, {
578
- style: styles$2.error
579
- }, errorMessage), (label || description || errorMessage) && React.createElement(Strut, {
580
- size: Spacing.small_12
581
- }), allChildren.map((child, index) => {
582
- const {
583
- style,
584
- value
585
- } = child.props;
586
- const checked = selectedValues.includes(value);
587
- return React.cloneElement(child, {
588
- checked: checked,
589
- error: !!errorMessage,
590
- groupName: groupName,
591
- id: `${groupName}-${value}`,
592
- key: value,
593
- onChange: () => this.handleChange(value, checked),
594
- style: [index > 0 && styles$2.defaultLineGap, style],
595
- variant: "checkbox"
596
- });
597
- })));
598
- }
599
- }
556
+ value
557
+ } = child.props;
558
+ const checked = selectedValues.includes(value);
559
+ return React.cloneElement(child, {
560
+ checked: checked,
561
+ error: !!errorMessage,
562
+ groupName: groupName,
563
+ id: `${groupName}-${value}`,
564
+ key: value,
565
+ onChange: () => handleChange(value, checked),
566
+ style: [index > 0 && styles$2.defaultLineGap, style],
567
+ variant: "checkbox"
568
+ });
569
+ })));
570
+ });
600
571
 
601
572
  const StyledFieldset = addStyle("fieldset");
602
573
  const StyledLegend = addStyle("legend");
603
- class RadioGroup extends React.Component {
604
- handleChange(changedValue) {
605
- this.props.onChange(changedValue);
606
- }
607
- render() {
574
+ const RadioGroup = React.forwardRef((props, ref) => {
575
+ const {
576
+ children,
577
+ label,
578
+ description,
579
+ errorMessage,
580
+ groupName,
581
+ onChange,
582
+ selectedValue,
583
+ style,
584
+ testId
585
+ } = props;
586
+ const allChildren = React.Children.toArray(children).filter(Boolean);
587
+ return React.createElement(StyledFieldset, {
588
+ "data-test-id": testId,
589
+ style: styles$2.fieldset,
590
+ ref: ref
591
+ }, React.createElement(View, {
592
+ style: style
593
+ }, label && React.createElement(StyledLegend, {
594
+ style: styles$2.legend
595
+ }, React.createElement(LabelMedium, null, label)), description && React.createElement(LabelSmall, {
596
+ style: styles$2.description
597
+ }, description), errorMessage && React.createElement(LabelSmall, {
598
+ style: styles$2.error
599
+ }, errorMessage), (label || description || errorMessage) && React.createElement(Strut, {
600
+ size: Spacing.small_12
601
+ }), allChildren.map((child, index) => {
608
602
  const {
609
- children,
610
- label,
611
- description,
612
- errorMessage,
613
- groupName,
614
- selectedValue,
615
603
  style,
616
- testId
617
- } = this.props;
618
- const allChildren = React.Children.toArray(children).filter(Boolean);
619
- return React.createElement(StyledFieldset, {
620
- "data-test-id": testId,
621
- style: styles$2.fieldset
622
- }, React.createElement(View, {
623
- style: style
624
- }, label && React.createElement(StyledLegend, {
625
- style: styles$2.legend
626
- }, React.createElement(LabelMedium, null, label)), description && React.createElement(LabelSmall, {
627
- style: styles$2.description
628
- }, description), errorMessage && React.createElement(LabelSmall, {
629
- style: styles$2.error
630
- }, errorMessage), (label || description || errorMessage) && React.createElement(Strut, {
631
- size: Spacing.small_12
632
- }), allChildren.map((child, index) => {
633
- const {
634
- style,
635
- value
636
- } = child.props;
637
- const checked = selectedValue === value;
638
- return React.cloneElement(child, {
639
- checked: checked,
640
- error: !!errorMessage,
641
- groupName: groupName,
642
- id: `${groupName}-${value}`,
643
- key: value,
644
- onChange: () => this.handleChange(value),
645
- style: [index > 0 && styles$2.defaultLineGap, style],
646
- variant: "radio"
647
- });
648
- })));
649
- }
650
- }
604
+ value
605
+ } = child.props;
606
+ const checked = selectedValue === value;
607
+ return React.cloneElement(child, {
608
+ checked: checked,
609
+ error: !!errorMessage,
610
+ groupName: groupName,
611
+ id: `${groupName}-${value}`,
612
+ key: value,
613
+ onChange: () => onChange(value),
614
+ style: [index > 0 && styles$2.defaultLineGap, style],
615
+ variant: "radio"
616
+ });
617
+ })));
618
+ });
651
619
 
652
620
  const _excluded = ["id", "type", "value", "disabled", "onKeyDown", "placeholder", "light", "style", "testId", "readOnly", "autoFocus", "autoComplete", "forwardedRef", "onFocus", "onBlur", "onValidate", "validate", "onChange", "required"];
653
621
  const defaultErrorMessage = "This field is required.";