mui-org / material-ui
Showing 8 of 26 files from the diff.

@@ -0,0 +1,23 @@
Loading
1 +
import isHostComponent from './isHostComponent';
2 +
3 +
/**
4 +
 * Appends the styleProps object to the props, merging with the existing one if necessary.
5 +
 *
6 +
 * @param elementType Type of the element that owns the `existingProps`. If the element is a DOM node, `styleProps` are not applied.
7 +
 * @param existingProps Props of the element.
8 +
 * @param styleProps
9 +
 */
10 +
export default function appendStyleProps(
11 +
  elementType: React.ElementType,
12 +
  existingProps: Record<string, any>,
13 +
  styleProps: object,
14 +
) {
15 +
  if (isHostComponent(elementType)) {
16 +
    return existingProps;
17 +
  }
18 +
19 +
  return {
20 +
    ...existingProps,
21 +
    styleProps: { ...existingProps.styleProps, ...styleProps },
22 +
  };
23 +
}

@@ -0,0 +1,26 @@
Loading
1 +
import * as React from 'react';
2 +
import FormControlUnstyledProps from './FormControlUnstyledProps';
3 +
4 +
type ContextFromPropsKey = 'disabled' | 'error' | 'onChange' | 'required' | 'value';
5 +
6 +
export interface FormControlUnstyledState
7 +
  extends Pick<FormControlUnstyledProps, ContextFromPropsKey> {
8 +
  filled: boolean;
9 +
  focused: boolean;
10 +
  onBlur: () => void;
11 +
  onFocus: () => void;
12 +
  registerEffect: () => void;
13 +
}
14 +
15 +
/**
16 +
 * @ignore - internal component.
17 +
 */
18 +
const FormControlUnstyledContext = React.createContext<FormControlUnstyledState | undefined>(
19 +
  undefined,
20 +
);
21 +
22 +
if (process.env.NODE_ENV !== 'production') {
23 +
  FormControlUnstyledContext.displayName = 'FormControlUnstyledContext';
24 +
}
25 +
26 +
export default FormControlUnstyledContext;

@@ -0,0 +1,259 @@
Loading
1 +
import * as React from 'react';
2 +
import { expect } from 'chai';
3 +
import { spy } from 'sinon';
4 +
import {
5 +
  createMount,
6 +
  createClientRender,
7 +
  describeConformanceUnstyled,
8 +
  fireEvent,
9 +
} from 'test/utils';
10 +
import FormControlUnstyled, {
11 +
  formControlUnstyledClasses,
12 +
  useFormControlUnstyled,
13 +
} from '@material-ui/unstyled/FormControlUnstyled';
14 +
15 +
describe('<FormControlUnstyled />', () => {
16 +
  const mount = createMount();
17 +
  const render = createClientRender();
18 +
19 +
  describeConformanceUnstyled(<FormControlUnstyled />, () => ({
20 +
    inheritComponent: 'div',
21 +
    render,
22 +
    mount,
23 +
    refInstanceof: window.HTMLDivElement,
24 +
    testComponentPropWith: 'div',
25 +
    muiName: 'MuiFormControl',
26 +
    slots: {
27 +
      root: {
28 +
        expectedClassName: formControlUnstyledClasses.root,
29 +
      },
30 +
    },
31 +
  }));
32 +
33 +
  describe('initial state', () => {
34 +
    it('has undefined value', () => {
35 +
      function TestComponent() {
36 +
        const context = useFormControlUnstyled();
37 +
        return <input value={context!.value as string} onChange={context!.onChange} />;
38 +
      }
39 +
40 +
      const { getByRole } = render(
41 +
        <FormControlUnstyled>
42 +
          <TestComponent />
43 +
        </FormControlUnstyled>,
44 +
      );
45 +
46 +
      expect(getByRole('textbox')).to.have.property('value', '');
47 +
    });
48 +
49 +
    it('has disabled, filled, focused, and required set to false', () => {
50 +
      function TestComponent() {
51 +
        const context = useFormControlUnstyled();
52 +
53 +
        return (
54 +
          <input
55 +
            data-filled={context!.filled}
56 +
            data-focused={context!.focused}
57 +
            disabled={context!.disabled}
58 +
            required={context!.required}
59 +
          />
60 +
        );
61 +
      }
62 +
63 +
      const { getByRole } = render(
64 +
        <FormControlUnstyled>
65 +
          <TestComponent />
66 +
        </FormControlUnstyled>,
67 +
      );
68 +
69 +
      expect(getByRole('textbox')).to.include({
70 +
        disabled: false,
71 +
        required: false,
72 +
      });
73 +
74 +
      expect(getByRole('textbox').dataset).to.include({
75 +
        filled: 'false',
76 +
        focused: 'false',
77 +
      });
78 +
    });
79 +
  });
80 +
81 +
  describe('prop: value', () => {
82 +
    it('propagates the value via the context', () => {
83 +
      function TestComponent() {
84 +
        const context = useFormControlUnstyled();
85 +
        return <input value={context!.value as string} onChange={context!.onChange} />;
86 +
      }
87 +
88 +
      const { getByRole } = render(
89 +
        <FormControlUnstyled value="42">
90 +
          <TestComponent />
91 +
        </FormControlUnstyled>,
92 +
      );
93 +
94 +
      expect(getByRole('textbox')).to.have.property('value', '42');
95 +
    });
96 +
  });
97 +
98 +
  describe('prop: disabled', () => {
99 +
    it('propagates the value via the context', () => {
100 +
      function TestComponent() {
101 +
        const context = useFormControlUnstyled();
102 +
        return <input disabled={context?.disabled} />;
103 +
      }
104 +
105 +
      const { getByRole } = render(
106 +
        <FormControlUnstyled disabled>
107 +
          <TestComponent />
108 +
        </FormControlUnstyled>,
109 +
      );
110 +
111 +
      expect(getByRole('textbox')).to.have.property('disabled', true);
112 +
    });
113 +
  });
114 +
115 +
  describe('prop: defaultValue', () => {
116 +
    it('propagates the value via the context', () => {
117 +
      function TestComponent() {
118 +
        const context = useFormControlUnstyled();
119 +
        return <input value={context!.value as string} onChange={context!.onChange} />;
120 +
      }
121 +
122 +
      const { getByRole } = render(
123 +
        <FormControlUnstyled defaultValue="foo">
124 +
          <TestComponent />
125 +
        </FormControlUnstyled>,
126 +
      );
127 +
128 +
      expect(getByRole('textbox')).to.have.property('value', 'foo');
129 +
    });
130 +
  });
131 +
132 +
  describe('prop: focused', () => {
133 +
    it('propagates the value via the context', () => {
134 +
      function TestComponent() {
135 +
        const context = useFormControlUnstyled();
136 +
        return <input data-focused={context!.focused} />;
137 +
      }
138 +
139 +
      const { getByRole } = render(
140 +
        <FormControlUnstyled focused>
141 +
          <TestComponent />
142 +
        </FormControlUnstyled>,
143 +
      );
144 +
145 +
      expect(getByRole('textbox').dataset).to.have.property('focused', 'true');
146 +
    });
147 +
148 +
    it('ignores focused when disabled', () => {
149 +
      function TestComponent() {
150 +
        const context = useFormControlUnstyled();
151 +
        return <input data-focused={context!.focused} disabled={context?.disabled} />;
152 +
      }
153 +
154 +
      const { getByRole } = render(
155 +
        <FormControlUnstyled focused disabled>
156 +
          <TestComponent />
157 +
        </FormControlUnstyled>,
158 +
      );
159 +
      expect(getByRole('textbox')).to.have.property('disabled', true);
160 +
      expect(getByRole('textbox').dataset).to.have.property('focused', 'false');
161 +
    });
162 +
  });
163 +
164 +
  describe('prop: required', () => {
165 +
    it('propagates the value via the context', () => {
166 +
      function TestComponent() {
167 +
        const context = useFormControlUnstyled();
168 +
        return <input required={context!.required} />;
169 +
      }
170 +
171 +
      const { getByRole } = render(
172 +
        <FormControlUnstyled required>
173 +
          <TestComponent />
174 +
        </FormControlUnstyled>,
175 +
      );
176 +
177 +
      expect(getByRole('textbox')).to.have.property('required', true);
178 +
    });
179 +
  });
180 +
181 +
  describe('prop: filled', () => {
182 +
    it('should be set if value is provided', () => {
183 +
      function TestComponent() {
184 +
        const context = useFormControlUnstyled();
185 +
        return <input data-filled={context!.filled} />;
186 +
      }
187 +
188 +
      const { getByRole } = render(
189 +
        <FormControlUnstyled value="foo">
190 +
          <TestComponent />
191 +
        </FormControlUnstyled>,
192 +
      );
193 +
194 +
      expect(getByRole('textbox').dataset).to.have.property('filled', 'true');
195 +
    });
196 +
197 +
    it('should be set if defaultValue is provided', () => {
198 +
      function TestComponent() {
199 +
        const context = useFormControlUnstyled();
200 +
        return <input data-filled={context!.filled} />;
201 +
      }
202 +
203 +
      const { getByRole } = render(
204 +
        <FormControlUnstyled defaultValue="foo">
205 +
          <TestComponent />
206 +
        </FormControlUnstyled>,
207 +
      );
208 +
209 +
      expect(getByRole('textbox').dataset).to.have.property('filled', 'true');
210 +
    });
211 +
212 +
    it('should be set if a controlled inner input sets its value', () => {
213 +
      function TestComponent() {
214 +
        const context = useFormControlUnstyled();
215 +
        return (
216 +
          <input
217 +
            data-filled={context!.filled}
218 +
            value={context!.value as string}
219 +
            onChange={context!.onChange}
220 +
          />
221 +
        );
222 +
      }
223 +
224 +
      const { getByRole } = render(
225 +
        <FormControlUnstyled>
226 +
          <TestComponent />
227 +
        </FormControlUnstyled>,
228 +
      );
229 +
230 +
      const input = getByRole('textbox');
231 +
      fireEvent.change(input, { target: { value: 'a' } });
232 +
233 +
      expect(input.dataset).to.have.property('filled', 'true');
234 +
    });
235 +
  });
236 +
237 +
  describe('prop: onChange', () => {
238 +
    it("propagates the inner input's onChange to FormControlUnstyled's onChange", () => {
239 +
      function TestComponent() {
240 +
        const context = useFormControlUnstyled();
241 +
        return <input value={context!.value as string} onChange={context!.onChange} />;
242 +
      }
243 +
244 +
      const handleChange = spy();
245 +
      const { getByRole } = render(
246 +
        <FormControlUnstyled onChange={handleChange}>
247 +
          <TestComponent />
248 +
        </FormControlUnstyled>,
249 +
      );
250 +
251 +
      const input = getByRole('textbox');
252 +
      fireEvent.change(input, { target: { value: 'test' } });
253 +
254 +
      expect(handleChange.callCount).to.equal(1);
255 +
      expect(handleChange.args[0][0]).to.have.property('target');
256 +
      expect(handleChange.args[0][0].target).to.have.property('value', 'test');
257 +
    });
258 +
  });
259 +
});

@@ -3,7 +3,7 @@
Loading
3 3
import clsx from 'clsx';
4 4
import useSwitch, { SwitchState, UseSwitchProps } from './useSwitch';
5 5
import classes from './switchUnstyledClasses';
6 -
import { isHostComponent } from '../utils';
6 +
import appendStyleProps from '../utils/appendStyleProps';
7 7
8 8
export interface SwitchUnstyledProps extends UseSwitchProps {
9 9
  /**
@@ -38,16 +38,6 @@
Loading
38 38
  };
39 39
}
40 40
41 -
const appendStyleProps = (
42 -
  component: React.ElementType,
43 -
  componentsProps: Record<string, any>,
44 -
  state: SwitchState,
45 -
) => {
46 -
  if (!isHostComponent(component)) {
47 -
    componentsProps.styleProps = { ...componentsProps.styleProps, ...state };
48 -
  }
49 -
};
50 -
51 41
/**
52 42
 * The foundation for building custom-styled switches.
53 43
 *
@@ -80,15 +70,6 @@
Loading
80 70
    ...otherProps
81 71
  } = props;
82 72
83 -
  const Root: React.ElementType = component ?? components.Root ?? 'span';
84 -
  const rootProps: any = { ...otherProps, ...componentsProps.root };
85 -
86 -
  const Thumb: React.ElementType = components.Thumb ?? 'span';
87 -
  const thumbProps: any = componentsProps.thumb ?? {};
88 -
89 -
  const Input: React.ElementType = components.Input ?? 'input';
90 -
  const inputProps: any = componentsProps.input ?? {};
91 -
92 73
  const useSwitchProps = {
93 74
    checked: checkedProp,
94 75
    defaultChecked,
@@ -110,9 +91,14 @@
Loading
110 91
    readOnly,
111 92
  };
112 93
113 -
  appendStyleProps(Root, rootProps, styleProps);
114 -
  appendStyleProps(Input, inputProps, styleProps);
115 -
  appendStyleProps(Thumb, thumbProps, styleProps);
94 +
  const Root: React.ElementType = component ?? components.Root ?? 'span';
95 +
  const rootProps = appendStyleProps(Root, { ...otherProps, ...componentsProps.root }, styleProps);
96 +
97 +
  const Thumb: React.ElementType = components.Thumb ?? 'span';
98 +
  const thumbProps = appendStyleProps(Thumb, componentsProps.thumb ?? {}, styleProps);
99 +
100 +
  const Input: React.ElementType = components.Input ?? 'input';
101 +
  const inputProps = appendStyleProps(Input, componentsProps.input ?? {}, styleProps);
116 102
117 103
  const stateClasses = {
118 104
    [classes.checked]: checked,

@@ -0,0 +1,22 @@
Loading
1 +
import generateUtilityClass from '../generateUtilityClass';
2 +
import generateUtilityClasses from '../generateUtilityClasses';
3 +
4 +
export interface FormControlUnstyledClasses {
5 +
  /** Class applied to the root element. */
6 +
  root: string;
7 +
  /** Class applied to the root element if `disabled={true}`. */
8 +
  disabled: string;
9 +
}
10 +
11 +
export type FormControlUnstyledClassKey = keyof FormControlUnstyledClasses;
12 +
13 +
export function getFormControlUnstyledUtilityClasses(slot: string): string {
14 +
  return generateUtilityClass('MuiFormControl', slot);
15 +
}
16 +
17 +
const formControlUnstyledClasses: FormControlUnstyledClasses = generateUtilityClasses(
18 +
  'MuiFormControl',
19 +
  ['root', 'disabled'],
20 +
);
21 +
22 +
export default formControlUnstyledClasses;

@@ -0,0 +1,56 @@
Loading
1 +
import { expect } from 'chai';
2 +
import appendStyleProps from './appendStyleProps';
3 +
4 +
const styleProps = {
5 +
  className: 'bar',
6 +
  checked: true,
7 +
};
8 +
9 +
const CustomComponent = () => null;
10 +
11 +
describe('appendStyleProps', () => {
12 +
  describe('when a DOM element is provided as elementType', () => {
13 +
    it('returns the provided existingProps without modification ', () => {
14 +
      const existingProps = { className: 'foo' };
15 +
      const actual = appendStyleProps('div', existingProps, styleProps);
16 +
17 +
      expect(actual).to.equal(existingProps);
18 +
    });
19 +
  });
20 +
21 +
  describe('when a React component is provided as elementType', () => {
22 +
    it('returns the provided existingProps with added styleProps', () => {
23 +
      const existingProps = { className: 'foo' };
24 +
      const actual = appendStyleProps(CustomComponent, existingProps, styleProps);
25 +
26 +
      expect(actual).to.deep.equal({
27 +
        className: 'foo',
28 +
        styleProps: {
29 +
          className: 'bar',
30 +
          checked: true,
31 +
        },
32 +
      });
33 +
    });
34 +
35 +
    it('merges the provided styleProps with existing ones', () => {
36 +
      const existingProps = {
37 +
        styleProps: {
38 +
          className: 'foo',
39 +
          id: 'foo',
40 +
        },
41 +
        className: 'foo',
42 +
      };
43 +
44 +
      const actual = appendStyleProps(CustomComponent, existingProps, styleProps);
45 +
46 +
      expect(actual).to.deep.equal({
47 +
        className: 'foo',
48 +
        styleProps: {
49 +
          className: 'bar',
50 +
          id: 'foo',
51 +
          checked: true,
52 +
        },
53 +
      });
54 +
    });
55 +
  });
56 +
});

@@ -0,0 +1,233 @@
Loading
1 +
import * as React from 'react';
2 +
import PropTypes from 'prop-types';
3 +
import clsx from 'clsx';
4 +
import { OverridableComponent } from '@material-ui/types';
5 +
import { unstable_useControlled as useControlled } from '@material-ui/utils';
6 +
import FormControlUnstyledContext, { FormControlUnstyledState } from './FormControlContext';
7 +
import appendStyleProps from '../utils/appendStyleProps';
8 +
import classes from './formControlUnstyledClasses';
9 +
import FormControlUnstyledProps, {
10 +
  NativeFormControlElement,
11 +
  FormControlUnstyledOwnProps,
12 +
  FormControlUnstyledTypeMap,
13 +
} from './FormControlUnstyledProps';
14 +
15 +
function hasValue(value: unknown) {
16 +
  return value != null && !(Array.isArray(value) && value.length === 0) && value !== '';
17 +
}
18 +
19 +
type NonOptionalStyleProps = 'disabled' | 'error' | 'focused' | 'required';
20 +
21 +
export type FormControlUnstyledStyleProps = Omit<
22 +
  FormControlUnstyledOwnProps,
23 +
  NonOptionalStyleProps
24 +
> &
25 +
  Required<Pick<FormControlUnstyledProps, NonOptionalStyleProps>> & {
26 +
    filled: boolean;
27 +
  };
28 +
29 +
/**
30 +
 * Provides context such as filled/focused/error/required for form inputs.
31 +
 * Relying on the context provides high flexibility and ensures that the state always stays
32 +
 * consistent across the children of the `FormControl`.
33 +
 * This context is used by the following components:
34 +
 *
35 +
 * *   FormLabel
36 +
 * *   FormHelperText
37 +
 * *   Input
38 +
 * *   InputLabel
39 +
 *
40 +
 * You can find one composition example below and more going to [the demos](https://material-ui.com/components/text-fields/#components).
41 +
 *
42 +
 * ```jsx
43 +
 * <FormControl>
44 +
 *   <InputLabel htmlFor="my-input">Email address</InputLabel>
45 +
 *   <Input id="my-input" aria-describedby="my-helper-text" />
46 +
 *   <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
47 +
 * </FormControl>
48 +
 * ```
49 +
 *
50 +
 * ⚠️ Only one `Input` can be used within a FormControl because it create visual inconsistencies.
51 +
 * For instance, only one input can be focused at the same time, the state shouldn't be shared.
52 +
 *
53 +
 * Demos:
54 +
 *
55 +
 * - [Text Fields](https://material-ui.com/components/text-fields/)
56 +
 *
57 +
 * API:
58 +
 *
59 +
 * - [FormControlUnstyled API](https://material-ui.com/api/form-control-unstyled/)
60 +
 */
61 +
const FormControlUnstyled = React.forwardRef(function FormControlUnstyled<
62 +
  D extends React.ElementType = FormControlUnstyledTypeMap['defaultComponent'],
63 +
>(props: FormControlUnstyledProps<D>, ref: React.ForwardedRef<any>) {
64 +
  const {
65 +
    defaultValue,
66 +
    children,
67 +
    className,
68 +
    component,
69 +
    components = {},
70 +
    componentsProps = {},
71 +
    disabled = false,
72 +
    error = false,
73 +
    focused: visuallyFocused = false,
74 +
    onChange,
75 +
    required = false,
76 +
    value: incomingValue,
77 +
    ...other
78 +
  } = props;
79 +
80 +
  const [value, setValue] = useControlled({
81 +
    controlled: incomingValue,
82 +
    default: defaultValue,
83 +
    name: 'FormControl',
84 +
    state: 'value',
85 +
  });
86 +
87 +
  const filled = hasValue(value);
88 +
89 +
  const [focusedState, setFocused] = React.useState(false);
90 +
  if (disabled && focusedState) {
91 +
    setFocused(false);
92 +
  }
93 +
94 +
  const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState;
95 +
96 +
  const styleProps: FormControlUnstyledStyleProps = {
97 +
    ...props,
98 +
    disabled,
99 +
    error,
100 +
    filled,
101 +
    focused,
102 +
    required,
103 +
  };
104 +
105 +
  let registerEffect = () => {};
106 +
  if (process.env.NODE_ENV !== 'production') {
107 +
    // eslint-disable-next-line react-hooks/rules-of-hooks
108 +
    const registeredInput = React.useRef(false);
109 +
    registerEffect = () => {
110 +
      if (registeredInput.current) {
111 +
        console.error(
112 +
          [
113 +
            'Material-UI: There are multiple `Input` components inside a FormControl.',
114 +
            'This creates visual inconsistencies, only use one `Input`.',
115 +
          ].join('\n'),
116 +
        );
117 +
      }
118 +
119 +
      registeredInput.current = true;
120 +
      return () => {
121 +
        registeredInput.current = false;
122 +
      };
123 +
    };
124 +
  }
125 +
126 +
  const handleChange = (event: React.ChangeEvent<NativeFormControlElement>) => {
127 +
    setValue(event.target.value);
128 +
    onChange?.(event);
129 +
  };
130 +
131 +
  const childContext: FormControlUnstyledState = {
132 +
    disabled,
133 +
    error,
134 +
    filled,
135 +
    focused,
136 +
    onBlur: () => {
137 +
      setFocused(false);
138 +
    },
139 +
    onChange: handleChange,
140 +
    onFocus: () => {
141 +
      setFocused(true);
142 +
    },
143 +
    registerEffect,
144 +
    required,
145 +
    value: value ?? '',
146 +
  };
147 +
148 +
  const Root = component ?? components.Root ?? 'div';
149 +
  const rootProps = appendStyleProps(Root, { ...other, ...componentsProps.root }, styleProps);
150 +
151 +
  return (
152 +
    <FormControlUnstyledContext.Provider value={childContext}>
153 +
      <Root
154 +
        ref={ref}
155 +
        {...rootProps}
156 +
        className={clsx(
157 +
          classes.root,
158 +
          className,
159 +
          rootProps?.className,
160 +
          disabled && classes.disabled,
161 +
        )}
162 +
      >
163 +
        {children}
164 +
      </Root>
165 +
    </FormControlUnstyledContext.Provider>
166 +
  );
167 +
}) as OverridableComponent<FormControlUnstyledTypeMap>;
168 +
169 +
FormControlUnstyled.propTypes /* remove-proptypes */ = {
170 +
  // ----------------------------- Warning --------------------------------
171 +
  // | These PropTypes are generated from the TypeScript type definitions |
172 +
  // |     To update them edit TypeScript types and run "yarn proptypes"  |
173 +
  // ----------------------------------------------------------------------
174 +
  /**
175 +
   * The content of the component.
176 +
   */
177 +
  children: PropTypes.node,
178 +
  /**
179 +
   * Class name applied to the root element.
180 +
   */
181 +
  className: PropTypes.string,
182 +
  /**
183 +
   * The component used for the root node.
184 +
   * Either a string to use a HTML element or a component.
185 +
   */
186 +
  component: PropTypes.elementType,
187 +
  /**
188 +
   * The components used for each slot inside the FormControl.
189 +
   * Either a string to use a HTML element or a component.
190 +
   * @default {}
191 +
   */
192 +
  components: PropTypes.shape({
193 +
    Root: PropTypes.elementType,
194 +
  }),
195 +
  /**
196 +
   * @ignore
197 +
   */
198 +
  componentsProps: PropTypes.object,
199 +
  /**
200 +
   * @ignore
201 +
   */
202 +
  defaultValue: PropTypes.any,
203 +
  /**
204 +
   * If `true`, the label, input and helper text should be displayed in a disabled state.
205 +
   * @default false
206 +
   */
207 +
  disabled: PropTypes.bool,
208 +
  /**
209 +
   * If `true`, the label is displayed in an error state.
210 +
   * @default false
211 +
   */
212 +
  error: PropTypes.bool,
213 +
  /**
214 +
   * If `true`, the component is displayed in focused state.
215 +
   * @default false
216 +
   */
217 +
  focused: PropTypes.bool,
218 +
  /**
219 +
   * @ignore
220 +
   */
221 +
  onChange: PropTypes.func,
222 +
  /**
223 +
   * If `true`, the label will indicate that the `input` is required.
224 +
   * @default false
225 +
   */
226 +
  required: PropTypes.bool,
227 +
  /**
228 +
   * @ignore
229 +
   */
230 +
  value: PropTypes.any,
231 +
} as any;
232 +
233 +
export default FormControlUnstyled;

@@ -0,0 +1,6 @@
Loading
1 +
import * as React from 'react';
2 +
import FormControlUnstyledContext from './FormControlContext';
3 +
4 +
export default function useFormControlUnstyled() {
5 +
  return React.useContext(FormControlUnstyledContext);
6 +
}
Files Coverage
packages 96.03%
test 72.69%
Project Totals (833 files) 95.44%
278667
stable-browser
278668
stable-jsdom

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading