Samples for use-styling, use-slots, and enable enzyme testing in the repo (#456)

* use-slots sample

* add samples for use-styling package

* update jest versions to avoid typing issues

* light up snapshot tests for styling samples

* add some more samples to use-styles

* get enzyme working for RN testing

* update slots examples

* add HOC example for use slots

* Add samples and some README text to use-slots and use-styling packages

* Change files
This commit is contained in:
Jason Morse 2020-09-11 13:15:01 -07:00 коммит произвёл GitHub
Родитель ad04f1655c
Коммит 2566347850
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
50 изменённых файлов: 1679 добавлений и 86 удалений

Просмотреть файл

@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@fluentui-react-native/checkbox": "0.5.3",
"@types/jest": "^24.0.0",
"@types/jest": "^25.1.4",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui/react-native",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:30:08.789Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/adapters",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:30:10.739Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/button",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:20.337Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/component-cache",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:40.272Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/composition",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:31.047Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/framework",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:33.208Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/immutable-merge",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:52.512Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/memo-cache",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:54.702Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/merge-props",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:56.555Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/persona",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:24.087Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/persona-coin",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:26.834Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/shimmer",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:29.007Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/tester",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:12.687Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/tester-win32",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:17.217Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/use-slots",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:35.457Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@fluentui-react-native/use-styling",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:37.902Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/foundation-composable",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:42.415Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/foundation-settings",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:45.479Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/foundation-tokens",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:50.548Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/theme-registry",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:29:59.093Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/themed-settings",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:30:00.703Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/theming-ramp",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:30:02.530Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "none",
"comment": "Add samples and some README text to use-slots and use-styling packages",
"packageName": "@uifabricshared/theming-react-native",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "none",
"date": "2020-09-11T19:30:04.422Z"
}

Просмотреть файл

@ -1 +1,60 @@
# @fluentui-react-native/use-slots
A pattern and framework for building layering components together in an efficient, pluggable, and customizable manner.
When building libraries of components, larger and more complex components are often built out of smaller and more focused components. This is great conceptually because it allows good separation of concerns and enables better and more modular designs. The boundaries in this layering are not only defined by the definition of your component, whether it be a function or a class based component, but by `React.createElement`. The `createElement` calls are what JSX is syntactic sugar for, and provides the layering for things like hooks.
The issue is that this layering adds overhead as well. When building HOCs the number of elements in the JSX tree, can be far greater than the actual number of primitives rendered in the DOM. While it is possible to render a function component by calling it directly, this has to be done with caution if that component contains hooks. The storage for hooks is effectively an array indexed from the last `createElement` call. If a `useState` call were to happen on one render pass, but be skipped in the next, all subsequent hook calls would be misaligned.
## Staged Components
To solve this reliably for function components it is necessary to separate the hook calls from element tree generation. The pattern in this package is to write render functions that return a continuation function that will return the JSX tree. This pattern is as follows:
```tsx
const twoPartRender = (props: MyProps) => {
// do the hook calls in this section */
const theme = React.useContext(ThemeContext);
const [state, setState] = React.useState(() => doSomeStateSetup()));
// now return a (props) or (props, children) or (props, ...children) function that finishes the render
return (additional: MyProps, ...children: React.ReactNode[]) => {
const merged = { ...props, ...additional };
return (<View {...merged}>{children}</View>)
}
}
```
### `stagedComponent`
This type of function is not recognizable on its own as a component. This package exports a helper function `stagedComponent` that both:
- Turns a two part render function into a component that react can recognize
- Adds the means for the framework to access the initial two part function if it knows how to handle it
The helper will return a `React.FunctionComponent` that will forward props (without children) to the first call, then pass children to the continuation function.
## Consuming staged components
Staged components could be consumed by hand. This might look something like:
```ts
// create the BaseComponent as a staged component, this can still be rendered via <BaseComponent />
const BaseComponent = stagedComponent(/* some implementation */);
// create a wrapper component
const WrapperComponent = stagedComponent((props) => {
// grab the children, do some prop transformations, etc.
const { children, ...rest } = props;
const propsForBase = doSomethingWithProps(rest);
// call the first part of the function
const continuation = BaseComponent._staged(propsForBase);
// now render that component just by calling the function
return continuation({}, children)
}
```
Note that in this example the `WrapperComponent` is leveraging the code of the `BaseComponent` but will not create a dedicated tree entry. Also the `WrapperComponent` itself could be implemented as a staged component.
### Consuming staged components via a `useSlots` hook
TBD

Просмотреть файл

@ -35,7 +35,6 @@
"@fluentui-react-native/merge-props": ">=0.1.1 <1.0.0"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@uifabricshared/build-native": "^0.1.1",
"react": "16.11.0",
"react-native": "^0.62.2"

Просмотреть файл

@ -0,0 +1,395 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`useSlots sample code test suite renders sample 1 - the two types of basic bold text components 1`] = `
<div>
<BoldTextStaged
style={
Object {
"color": "black",
}
}
>
<span
style={
Object {
"color": "black",
"fontWeight": 900,
}
}
>
Staged component at one level
</span>
</BoldTextStaged>
<BoldTextStandard
style={
Object {
"color": "black",
}
}
>
<span
style={
Object {
"color": "black",
"fontWeight": 900,
}
}
>
Standard component of a single level
</span>
</BoldTextStandard>
</div>
`;
exports[`useSlots sample code test suite renders sample 2 = the two types of two level header components 1`] = `
<div>
<HeaderStaged
style={
Object {
"color": "black",
}
}
>
<span
style={
Object {
"color": "black",
"fontSize": 20,
"fontWeight": 900,
}
}
>
Staged component with two levels
</span>
</HeaderStaged>
<HeaderStandard
style={
Object {
"color": "black",
}
}
>
<BoldTextStandard
style={
Object {
"color": "black",
"fontSize": 20,
}
}
>
<span
style={
Object {
"color": "black",
"fontSize": 20,
"fontWeight": 900,
}
}
>
Standard component with two levels
</span>
</BoldTextStandard>
</HeaderStandard>
</div>
`;
exports[`useSlots sample code test suite renders sample 3 - the two types of higher order header components 1`] = `
<div>
<span>
--- SIMPLE USAGE COMPARISON ---
</span>
<CaptionedHeaderStandard';
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
}
}
>
<div
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
"display": "flex",
"flexDirection": "column",
}
}
>
<HeaderStandard>
<BoldTextStandard
style={
Object {
"fontSize": 20,
}
}
>
<span
style={
Object {
"fontSize": 20,
"fontWeight": 900,
}
}
>
Standard HOC
</span>
</BoldTextStandard>
</HeaderStandard>
</div>
</CaptionedHeaderStandard';>
<CaptionedHeaderStaged
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
}
}
>
<div
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
"display": "flex",
"flexDirection": "column",
}
}
>
<span
style={
Object {
"fontSize": 20,
"fontWeight": 900,
}
}
>
Staged HOC
</span>
</div>
</CaptionedHeaderStaged>
<span>
--- COMPARISON WITH CAPTIONS ---
</span>
<CaptionedHeaderStandard';
captionText="Caption text"
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
}
}
>
<div
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
"display": "flex",
"flexDirection": "column",
}
}
>
<HeaderStandard>
<BoldTextStandard
style={
Object {
"fontSize": 20,
}
}
>
<span
style={
Object {
"fontSize": 20,
"fontWeight": 900,
}
}
>
Standard HOC with Caption
</span>
</BoldTextStandard>
</HeaderStandard>
<BoldTextStandard>
<span
style={
Object {
"fontWeight": 900,
}
}
>
Caption text
</span>
</BoldTextStandard>
</div>
</CaptionedHeaderStandard';>
<CaptionedHeaderStaged
captionText="Caption text"
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
}
}
>
<div
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
"display": "flex",
"flexDirection": "column",
}
}
>
<span
style={
Object {
"fontSize": 20,
"fontWeight": 900,
}
}
>
Staged HOC with Caption
</span>
<span
style={
Object {
"fontWeight": 900,
}
}
>
Caption text
</span>
</div>
</CaptionedHeaderStaged>
<span>
--- COMPARISON WITH CAPTIONS AND CUSTOMIZATIONS ---
</span>
<CaptionedHeaderStandard';
captionColor="yellow"
captionText="Caption text"
headerColor="red"
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
}
}
>
<div
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
"display": "flex",
"flexDirection": "column",
}
}
>
<HeaderStandard
style={
Object {
"color": "red",
}
}
>
<BoldTextStandard
style={
Object {
"color": "red",
"fontSize": 20,
}
}
>
<span
style={
Object {
"color": "red",
"fontSize": 20,
"fontWeight": 900,
}
}
>
Standard HOC with caption and customizations
</span>
</BoldTextStandard>
</HeaderStandard>
<BoldTextStandard
style={
Object {
"color": "yellow",
}
}
>
<span
style={
Object {
"color": "yellow",
"fontWeight": 900,
}
}
>
Caption text
</span>
</BoldTextStandard>
</div>
</CaptionedHeaderStandard';>
<CaptionedHeaderStaged
captionColor="yellow"
captionText="Caption text"
headerColor="red"
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
}
}
>
<div
style={
Object {
"backgroundColor": "gray",
"borderColor": "purple",
"borderWidth": 1,
"display": "flex",
"flexDirection": "column",
}
}
>
<span
style={
Object {
"color": "red",
"fontSize": 20,
"fontWeight": 900,
}
}
>
Staged HOC with caption and customizations
</span>
<span
style={
Object {
"color": "yellow",
"fontWeight": 900,
}
}
>
Caption text
</span>
</div>
</CaptionedHeaderStaged>
</div>
`;

Просмотреть файл

@ -0,0 +1,284 @@
/** @jsx withSlots */
import { withSlots } from './withSlots';
import { stagedComponent } from './stagedComponent';
import { mergeProps } from '@fluentui-react-native/merge-props';
import { buildUseSlots } from './buildUseSlots';
import toJson from 'enzyme-to-json';
import { mount } from 'enzyme';
import { CSSProperties } from 'react';
// types for web
type TextProps = { style?: CSSProperties };
type ViewProps = { style?: CSSProperties };
type ViewStyle = CSSProperties;
type TextStyle = CSSProperties;
/**
* This file contains samples and description to help explain what the useSlots hook does and why it is useful
* for building components.
*/
describe('useSlots sample code test suite', () => {
/**
* The first mechanism to understand is the stagedComponent mechanic. This allows a component to be written, separating
* hook calls and component rendering. This allows it to be safely called as a function by a higher order component, even conditionally.
*/
/**
* Example #1: Single level simple component ----------------------------------------
*
* First we are going to create a wrapped text component that bolds all text. One component will be authored as a staged
* component and one as a regular component.
*/
const boldBaseProps: TextProps = { style: { fontWeight: 900 } };
/**
* First create the bold text in the standard way. This is just a function component.
*/
const BoldTextStandard: React.FunctionComponent<TextProps> = (props: React.PropsWithChildren<TextProps>) => {
/**
* Pick out the children to pass them on to the child Text element
*/
const { children, ...rest } = props;
/**
* Now render the text, merging the baseProps with the style updates with the rest param. Note that this leverages the fact
* that mergeProps will reliably produce style objects with the same reference, given the same inputs.
*/
return <span {...mergeProps(boldBaseProps, rest)}>{children}</span>;
};
BoldTextStandard.displayName = 'BoldTextStandard';
/**
* To write the same component using the staged pattern is only slightly more complex. The pattern involves splitting the component rendering into
* two parts and executing any hooks in the first part.
*
* The stagedComponent function takes an input function of this form and wraps it in a function component that react knows how to render
*/
const BoldTextStaged = stagedComponent((props: TextProps) => {
/**
* This section would be where hook/styling code would go, props here would include everything coming in from the base react tree with the
* exception of children, which will be passed in stage 2.
*/
return (extra: TextProps, children: React.ReactNode) => {
/**
* extra are additional props that may be filled in by a higher order component. They should not include styling and are only props the
* enclosing component are passing to the JSX elements
*/
return <span {...mergeProps(boldBaseProps, props, extra)}>{children}</span>;
};
});
BoldTextStaged.displayName = 'BoldTextStaged';
/**
* The demos of the code use enzyme with JSDom to show the full tree. This has the side effect of doubling up primitive elements in the output
* JSON. This is an issue with rendering react-native with enzyme but in real usage the nodes only render once.
*/
it('renders sample 1 - the two types of basic bold text components', () => {
const styleToMerge: TextStyle = { color: 'black' };
/**
* First render the staged component. This invokes the wrapper that was built by the stagedComponent function
*/
const wrapper = mount(
<div>
<BoldTextStaged style={styleToMerge}>Staged component at one level</BoldTextStaged>
<BoldTextStandard style={styleToMerge}>Standard component of a single level</BoldTextStandard>
</div>,
);
expect(toJson(wrapper)).toMatchSnapshot();
});
/**
* Example #2 - Simple component containing another simple component -------------------------------------
*
* Next we will build a layer on top of the previously authored components to turn the bold text components into header components. This is
* to illustrate the way in which components can be commonly built on top of other simpler components.
*/
const headerBaseProps: TextProps = { style: { fontSize: 20 } };
/**
* The standard way of doing things is a repeat of what happens above. Grab the children, pass them on, merge the rest of the props with
* base props.
*
* This again leverages style merging via mergeProps to avoid changing the references of the style objects on every render
*/
const HeaderStandard: React.FunctionComponent<TextProps> = (props) => {
const { children, ...rest } = props;
return <BoldTextStandard {...mergeProps(headerBaseProps, rest)}>{children}</BoldTextStandard>;
};
HeaderStandard.displayName = 'HeaderStandard';
/**
* To consume the staged component we'll use the use slots hook builder. This allows easy consumption of staged components (or standard components)
* This will be described in more detail further on but in this case the component has a single child component, so it only has one slot that we
* will call 'text'
*
* This should be built once, and consumed by the component, not built on the fly inside
*/
const useHeaderSlots = buildUseSlots({ slots: { text: BoldTextStaged } });
/**
* Now author the staged component using the slot hook
*/
const HeaderStaged = stagedComponent((props: TextProps) => {
/**
* Call the slots hook (or any hook) outside of the inner closure. The useSlots hook will return an object with each slot as a renderable
* function. The hooks for sub-components will be called as part of this call. Props passed in at this point will be the props that appear
* in outer part of the staged component. (For this example `props`)
*
* Note that while we are passing in props, in the simple usage case it isn't used and could be omitted if desired
* */
const BoldText = useHeaderSlots(props).text;
/** Now the inner closure, pretty much the same as before */
return (extra: TextProps, children: React.ReactNode) => {
/**
* Instead of rendering the <BoldTextStageed> component directly we render using the slot. If this is a staged component it will call the
* inner closure directly, without going through createElement. Entries passed into the JSX, including children, are what appear in the
* props of the inner closure. (In this example `extra`)
*
* NOTE: this requires using the withSlots helper via the jsx directive. This knows how to pick apart the entries and just call the second
* part of the function
*/
return <BoldText {...mergeProps(headerBaseProps, props, extra)}>{children}</BoldText>;
};
});
HeaderStaged.displayName = 'HeaderStaged';
/**
* Look at the snapshots to compare the rendered output. The staged component will skip the intermediate levels of the react hieararchy while
* still rendering to the correct primitives.
*/
it('renders sample 2 = the two types of two level header components', () => {
const styleToMerge: TextStyle = { color: 'black' };
/**
* First render the staged component. This invokes the wrapper that was built by the stagedComponent function
*/
const wrapper = mount(
<div>
<HeaderStaged style={styleToMerge}>Staged component with two levels</HeaderStaged>
<HeaderStandard style={styleToMerge}>Standard component with two levels</HeaderStandard>
</div>,
);
expect(toJson(wrapper)).toMatchSnapshot();
});
/**
* Example #3: Complex components built using useSlots --------------------------------------------------------------------
*
* We'll build a component that shows two labels, a header and a caption, embedded inside a view
*/
type HeaderWithCaptionProps = ViewProps & { headerColor?: string; captionColor?: string; captionText?: string };
/** standard props for the container */
const containerProps: ViewProps = { style: { display: 'flex', flexDirection: 'column' } };
/**
* add a quick cache to ensure that we don't thrash the styles. This is a danger any time a value from a style is added as
* a prop on a component
*/
const colorProps = {};
const getColorProps = (value?: string) => {
if (value !== undefined) {
colorProps[value] = colorProps[value] || { style: { color: value } };
return colorProps[value];
}
return {};
};
/**
* now just create the component like a standard react functional component
*/
const CaptionedHeaderStandard: React.FunctionComponent<HeaderWithCaptionProps> = (props) => {
const { headerColor, captionColor, captionText, children, ...rest } = props;
const headerColorProps = getColorProps(headerColor);
const captionColorProps = getColorProps(captionColor);
return (
<div {...mergeProps(containerProps, rest)}>
<HeaderStandard {...headerColorProps}>{children}</HeaderStandard>
{captionText && <BoldTextStandard {...captionColorProps}>{captionText}</BoldTextStandard>}
</div>
);
};
CaptionedHeaderStandard.displayName = `CaptionedHeaderStandard';`;
/**
* now build the same component using slots hook. This will also add use of the style injection pattern
*/
const useCaptionedHeaderSlots = buildUseSlots({
/** Slots are just like above, this component will have three sub-components */
slots: {
container: 'div',
header: HeaderStaged,
caption: BoldTextStaged,
},
/** useStyling is an optional function that turns props into props for the sub-components */
useStyling: (props: HeaderWithCaptionProps) => ({
container: containerProps,
header: getColorProps(props.headerColor),
caption: getColorProps(props.captionColor),
}),
});
/** a mask to clear props that we don't want to pass to the inner view */
const clearCustomProps = { headerColor: undefined, captionColor: undefined };
/**
* now use the hook to implement it as a staged component
*/
const CaptionedHeaderStaged = stagedComponent<HeaderWithCaptionProps>((props) => {
// At the point where this is called the slots are initialized with the initial prop values from useStyling above
const Slots = useCaptionedHeaderSlots(props);
return (extra: HeaderWithCaptionProps, children: React.ReactNode) => {
// merge the props together, picking out the caption text and clearing any custom values we don't want forwarded to the view
const { captionText, ...rest } = mergeProps(props, extra, clearCustomProps);
// now render using the slots. Any values passed in via JSX will be merged with values from the slot hook above
return (
<Slots.container {...rest}>
<Slots.header>{children}</Slots.header>
{captionText && <Slots.caption>{captionText}</Slots.caption>}
</Slots.container>
);
};
});
CaptionedHeaderStaged.displayName = 'CaptionedHeaderStaged';
/**
* Render to enzyme snapshots
*/
it('renders sample 3 - the two types of higher order header components', () => {
const styleToMerge: ViewStyle = { backgroundColor: 'gray', borderColor: 'purple', borderWidth: 1 };
/**
* Render the two sets of components. Note in the snapshots how the render tree layers for the standard approach are starting
* to add up.
*/
const wrapper = mount(
<div>
<span>--- SIMPLE USAGE COMPARISON ---</span>
<CaptionedHeaderStandard style={styleToMerge}>Standard HOC</CaptionedHeaderStandard>
<CaptionedHeaderStaged style={styleToMerge}>Staged HOC</CaptionedHeaderStaged>
<span>--- COMPARISON WITH CAPTIONS ---</span>
<CaptionedHeaderStandard style={styleToMerge} captionText="Caption text">
Standard HOC with Caption
</CaptionedHeaderStandard>
<CaptionedHeaderStaged style={styleToMerge} captionText="Caption text">
Staged HOC with Caption
</CaptionedHeaderStaged>
<span>--- COMPARISON WITH CAPTIONS AND CUSTOMIZATIONS ---</span>
<CaptionedHeaderStandard style={styleToMerge} captionText="Caption text" captionColor="yellow" headerColor="red">
Standard HOC with caption and customizations
</CaptionedHeaderStandard>
<CaptionedHeaderStaged style={styleToMerge} captionText="Caption text" captionColor="yellow" headerColor="red">
Staged HOC with caption and customizations
</CaptionedHeaderStaged>
</div>,
);
expect(toJson(wrapper)).toMatchSnapshot();
});
});

Просмотреть файл

@ -1,2 +1,2 @@
const { configureJest } = require('@uifabricshared/build-native');
module.exports = configureJest();
const { configureReactNativeJest } = require('@uifabricshared/build-native');
module.exports = configureReactNativeJest('android');

Просмотреть файл

@ -36,7 +36,9 @@
"@fluentui-react-native/memo-cache": "^1.0.2"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@uifabricshared/build-native": "^0.1.1"
"@types/jest": "^25.1.4",
"@uifabricshared/build-native": "^0.1.1",
"react": "16.11.0",
"react-native": "^0.62.2"
}
}

Просмотреть файл

@ -0,0 +1,163 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`useStyling samples Sample1Text rendering with no overrides 1`] = `
<Sample1Text>
<Text
style={
Object {
"color": "black",
"fontFamily": "Arial",
"fontSize": 12,
}
}
>
<Text
style={
Object {
"color": "black",
"fontFamily": "Arial",
"fontSize": 12,
}
}
>
Sample1a
</Text>
</Text>
</Sample1Text>
`;
exports[`useStyling samples Sample1Text rendering with some custom settings in the theme 1`] = `
<Sample1Text>
<Text
style={
Object {
"color": "pink",
"fontFamily": "Arial",
"fontSize": 24,
}
}
>
<Text
style={
Object {
"color": "pink",
"fontFamily": "Arial",
"fontSize": 24,
}
}
>
Sample1b
</Text>
</Text>
</Sample1Text>
`;
exports[`useStyling samples Sample2Text rendering with defaults and a color override 1`] = `
<View>
<View>
<Sample2Text>
<Text
style={
Object {
"color": "black",
"fontFamily": "Arial",
"fontSize": 12,
}
}
>
<Text
style={
Object {
"color": "black",
"fontFamily": "Arial",
"fontSize": 12,
}
}
>
Sample2 with defaults
</Text>
</Text>
</Sample2Text>
<Sample2Text
color="green"
>
<Text
style={
Object {
"color": "green",
"fontFamily": "Arial",
"fontSize": 12,
}
}
>
<Text
style={
Object {
"color": "green",
"fontFamily": "Arial",
"fontSize": 12,
}
}
>
Sample2 with color override via prop
</Text>
</Text>
</Sample2Text>
</View>
</View>
`;
exports[`useStyling samples Sample2Text rendering with some custom settings in the theme 1`] = `
<View>
<View>
<Sample2Text>
<Text
style={
Object {
"color": "pink",
"fontFamily": "Helvetica",
"fontSize": 18,
}
}
>
<Text
style={
Object {
"color": "pink",
"fontFamily": "Helvetica",
"fontSize": 18,
}
}
>
Sample2 with theme overrides set
</Text>
</Text>
</Sample2Text>
<Sample2Text
color="purple"
>
<Text
style={
Object {
"color": "purple",
"fontFamily": "Helvetica",
"fontSize": 18,
}
}
>
<Text
style={
Object {
"color": "purple",
"fontFamily": "Helvetica",
"fontSize": 18,
}
}
>
Sample2 with theme and color prop override
</Text>
</Text>
</Sample2Text>
</View>
</View>
`;

Просмотреть файл

@ -0,0 +1,248 @@
import { ThemeHelper, buildUseStyling, UseStylingOptions } from './buildUseStyling';
import { TextProps, Text, View } from 'react-native';
import { buildProps } from './buildProps';
import toJson from 'enzyme-to-json';
import * as React from 'react';
import { mount } from 'enzyme';
/**
* Sample super simple theming implementation, shared by all the samples. This is intended to be illustrative,
* not to be production ready theming code
*/
/**
* The theme just contains global values and options for looking up component overrides
*/
type Theme = {
globals: {
backgroundColor: string;
color: string;
borderColor: string;
fontFamily: string;
fontSize: number;
};
components: {
[key: string]: any;
};
};
/**
* The default/base theme just contains base values
*/
const baseTheme: Theme = {
globals: {
backgroundColor: 'white',
color: 'black',
borderColor: 'blue',
fontFamily: 'Arial',
fontSize: 12,
},
components: {},
};
const current = { theme: baseTheme };
/**
* this wrapper solves the (so-far) inexplicable type errors from the matchers in typescript
*/
function snapshotTestTree(tree: any) {
(expect(toJson(tree)) as any).toMatchSnapshot();
}
/**
* Because the buildUseStyling utility is not opinionated about theming, the theming is injected via
* a theme helper implementation. This allows for a framework to build an opinionated version with
* whatever system they desire
*/
const themeHelper: ThemeHelper<Theme> & { setActive: (theme?: Partial<Theme>) => void } = {
useTheme: () => current.theme,
getComponentInfo: (theme: Theme, name: string) => theme.components[name],
setActive: (theme?: Partial<Theme>) => {
current.theme = theme ? { ...baseTheme, ...theme } : baseTheme;
},
};
describe('useStyling samples', () => {
/**
* Sample #1 - Themeable text element
*
* This adds some default opinions for how a text element should be styled but only allows for customization
* via theming
*/
// the component itself is just text props with no style allowed
type Sample1Props = Omit<TextProps, 'style'>;
// internally the component just wraps a Text element
type Sample1SlotProps = { content: TextProps };
// the tokens for customization are just the color and font props from the theme
type Sample1Tokens = {
color?: string;
fontFamily?: string;
fontSize?: number;
};
// now create the styling hook, first the options so they can be reused later
const sample1StylingOptions: UseStylingOptions<Sample1Props, Sample1SlotProps, Sample1Tokens, Theme> = {
/**
* tell the styling hook how to build up the tokens
*/
tokens: [
/** first the default values should come from the global theme section */
(t: Theme) => ({
color: t.globals.color,
fontFamily: t.globals.fontFamily,
fontSize: t.globals.fontSize,
}),
/** next we should look for a component reference to overlay */
'Sample1',
],
/**
* Now provide the recipe for how to build props for the sub-components given the tokens
*/
slotProps: {
/** only one sub-component, a Text element called content, as a result this needs to build up TextProps */
content: buildProps(
/**
* first input for buildProps is a function which takes tokens and a theme and returns props
*/
(tokens: Sample1Tokens /*, theme: Theme */) => {
return {
style: { ...tokens },
};
},
/**
* The second input are the tokens used as inputs for the above function. This is similar to the way the useEffect hook
* works in react.
*/
['color', 'fontFamily', 'fontSize'],
),
},
};
// now build the actual hook from the options and theme helper
const useStylingSample1 = buildUseStyling(sample1StylingOptions, themeHelper);
// now the sample 1 component becomes simple to build, just merge the styled props with the input props
const Sample1Text: React.FunctionComponent<Sample1Props> = (props) => {
const styledProps = useStylingSample1(props).content;
const merged = { ...props, ...styledProps };
return <Text {...merged}>{props.children}</Text>;
};
/** first render the component with no updates */
it('Sample1Text rendering with no overrides', () => {
const tree = mount(<Sample1Text>Sample1a</Sample1Text>);
snapshotTestTree(tree);
});
/** now re-theme the component via the components in the theme */
it('Sample1Text rendering with some custom settings in the theme', () => {
themeHelper.setActive({
components: {
Sample1: {
color: 'pink',
fontSize: 24,
},
},
});
const tree = mount(<Sample1Text>Sample1b</Sample1Text>);
snapshotTestTree(tree);
});
/**
* Sample 2 - take the styled text component from the first example and allow color to be set in props as well. This is
* effectively saying that all other styles come from the theme except that color can be overriden via props.
*
* This will start with the definition from sample 1 and then extend it.
*/
/** use the props from the first sample and just add a color setting */
type Sample2Props = Sample1Props & { color?: string };
/**
* Build the styling hook for sample2. Because this isn't being recombined this is being specified inline rather
* than using a separate options object. Both are fine.
*/
const useStylingSample2 = buildUseStyling<Sample2Props, Sample1SlotProps, Sample1Tokens, Theme>(
{
/**
* This just starts with the baseline styling from sample1, in particular we are using the recipes of how to turn
* token values into the props for the internal sub-components. While this example is not super complex, for real-world
* components, re-using these can be extremely valuable.
*
* With that in mind, this copies over the recipes for how to turn tokens into props, the customizations that
* will be made are about how to ensure the tokens are set up correctly.
*/
...sample1StylingOptions,
/**
* In sample1 tokens are set to defaults from the global theme section, then patched with any values looked up with
* the string 'Sample1'
*
* We want to maintain the logic of setting up the globals, but add an additional lookup for 'Sample2'. This might correspond
* to saying that if we were making a variant of a 'Text' component called 'HeaderText', we might want to look up
* customizations from 'Text' first, then override those customizations with those from 'HeaderText'
*
* If we didn't want to add the extra 'Sample2' lookup this line would be omitted. If we didn't want to look up 'Sample1' first
* that could be filtered out of the array that is being copied
*/
tokens: [...sample1StylingOptions.tokens, 'Sample2'],
/**
* This is the final bit of magic. The tokens will already have values set from the global theme, they will then be patched with
* any customizations set into Sample1 and/or Sample2.
*
* If this value was omitted then the tokens would be passed to the slotProps recipies as is. To have those values patched from
* the component props we add a list of the props which need to be passed into tokens. If all props should be spread into the
* tokens then this value can be set to 'all'. If none should be passed it can be omitted or set to 'none'
*/
tokensThatAreAlsoProps: ['color'],
},
themeHelper,
);
// the Sample2Text component is built the same way as sample1, just using the new hook that has been created
const Sample2Text: React.FunctionComponent<Sample2Props> = (props) => {
const styledProps = useStylingSample2(props).content;
const merged = { ...props, ...styledProps };
// delete the color key to not pass it through to the text props, could be done via destructuring, filtering, or any number of ways
delete merged.color;
// render the text
return <Text {...merged}>{props.children}</Text>;
};
/** rendering the Sample2 component with the base theme */
it('Sample2Text rendering with defaults and a color override', () => {
themeHelper.setActive();
const tree = mount(
<View>
<Sample2Text>Sample2 with defaults</Sample2Text>
<Sample2Text color="green">Sample2 with color override via prop</Sample2Text>
</View>,
);
snapshotTestTree(tree);
});
/** now re-theme the component via the components in the theme */
it('Sample2Text rendering with some custom settings in the theme', () => {
themeHelper.setActive({
components: {
Sample1: {
color: 'pink',
fontSize: 24,
},
Sample2: {
fontSize: 18,
fontFamily: 'Helvetica',
},
},
});
const tree = mount(
<View>
<Sample2Text>Sample2 with theme overrides set</Sample2Text>
<Sample2Text color="purple">Sample2 with theme and color prop override</Sample2Text>
</View>,
);
snapshotTestTree(tree);
});
});

Просмотреть файл

@ -32,7 +32,7 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/node": "^10.3.5",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1",

Просмотреть файл

@ -36,7 +36,7 @@
"@uifabricshared/foundation-settings": ">=0.7.0 <1.0.0"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/react": "^16.9.34",
"react": "16.11.0",
"@uifabricshared/build-native": "^0.1.1",

Просмотреть файл

@ -36,7 +36,7 @@
"@fluentui-react-native/merge-props": ">=0.1.1 <1.0.0"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1"
}

Просмотреть файл

@ -36,7 +36,7 @@
"@uifabricshared/foundation-settings": ">=0.7.0 <1.0.0"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@uifabricshared/build-native": "^0.1.1",
"@fluentui-react-native/memo-cache": "^1.0.2"
}

Просмотреть файл

@ -32,7 +32,7 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/node": "^10.3.5",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1"

Просмотреть файл

@ -32,7 +32,7 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/node": "^10.3.5",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1"

Просмотреть файл

@ -36,7 +36,7 @@
"@fluentui-react-native/memo-cache": "^1.0.2"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1"
}

Просмотреть файл

@ -34,7 +34,7 @@
"dependencies": {},
"devDependencies": {
"@fluentui-react-native/immutable-merge": "^1.0.1",
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1"
}

Просмотреть файл

@ -35,7 +35,7 @@
"@uifabricshared/foundation-settings": ">=0.7.0 <1.0.0"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/node": "^10.3.5",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1",

Просмотреть файл

@ -36,7 +36,7 @@
"@fluentui-react-native/immutable-merge": "^1.0.1"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/react": "^16.9.34",
"react": "16.11.0",
"@uifabricshared/build-native": "^0.1.1",

Просмотреть файл

@ -32,7 +32,7 @@
"@uifabricshared/theming-ramp": ">=0.10.5 <1.0.0"
},
"devDependencies": {
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/react": "^16.9.34",
"react": "16.11.0",
"react-native": "^0.62.2",

Просмотреть файл

@ -23,7 +23,7 @@
"dependencies": {},
"devDependencies": {
"@office-iss/react-native-win32": "0.62.0-preview.3",
"@types/jest": "^19.2.2",
"@types/jest": "^25.1.4",
"@types/react-native": "^0.62.0",
"@uifabricshared/build-native": "^0.1.1",
"@uifabricshared/eslint-config-rules": "^0.1.1",

Просмотреть файл

@ -41,8 +41,8 @@
"babel-plugin-module-resolver": "^4.0.0",
"depcheck": "^1.0.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.4",
"enzyme-adapter-react-16": "^1.15.4",
"enzyme-to-json": "^3.5.0",
"eslint": "^6.3.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.18.2",
@ -53,6 +53,8 @@
"jest": "^24.9.0",
"jest-cli": "^24.9.0",
"jest-environment-jsdom": "^24.9.0",
"jest-enzyme": "^7.1.2",
"jsdom": "^16.4.0",
"just-repo-utils": "^0.2.0",
"just-scripts": "^0.38.0",
"just-task": "^0.14.3",

Просмотреть файл

@ -38,9 +38,6 @@ export function configureJest(customConfig?: object): object {
testURL: 'http://localhost',
verbose: false,
// some options which have been removed (but saved here for posterity/easy re-adding)
// setupFiles: [path.resolve(__dirname, 'jest-setup.js')],
},
customConfig,
);
@ -74,6 +71,7 @@ export function configureReactNativeJest(platform?: PlatformValue, customConfig?
},
transformIgnorePatterns: ['node_modules/(?!(react-native)/)'],
verbose: false,
setupFilesAfterEnv: [path.join(__dirname, './jest/setupEnzyme.js')],
},
customConfig,
);

Просмотреть файл

@ -1,4 +0,0 @@
import enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
enzyme.configure({ adapter: new Adapter() });

Просмотреть файл

@ -1,13 +0,0 @@
// Fail on warnings.
const consoleError = console.error;
console.error = console.warn = message => {
consoleError(message);
if (typeof message === 'object' && message.stack) {
// If the "message" was an exception, re-throw it to get the full stack trace
throw message;
} else {
throw new Error('Caught: ' + message);
}
};

Просмотреть файл

@ -0,0 +1,46 @@
// setup-tests.js
import 'react-native';
import 'jest-enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Enzyme from 'enzyme';
/**
* Set up DOM in node.js environment for Enzyme to mount to
*/
const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;
function copyProps(src, target) {
Object.defineProperties(target, {
...Object.getOwnPropertyDescriptors(src),
...Object.getOwnPropertyDescriptors(target),
});
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: 'node.js',
};
copyProps(window, global);
/**
* Hook console warnings because enzyme with react-native will generate some bogus warnings such as:
* Warning: <View /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
* Warning: The tag <View> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter
*/
const consoleErrorHandler = console.error;
console.error = (message, ...args) => {
const blockExpr = /.*(react-dom.development.js|Use PascalCase for React|is unrecognized in this browser)/i;
if (!blockExpr.test(message)) {
consoleErrorHandler(message, ...args);
}
};
/**
* Set up Enzyme to mount to DOM, simulate events,
* and inspect the DOM in tests.
*/
Enzyme.configure({ adapter: new Adapter() });

322
yarn.lock
Просмотреть файл

@ -1151,20 +1151,6 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
"@fluentui-react-native/tester@^0.3.6":
version "0.3.7"
resolved "https://registry.yarnpkg.com/@fluentui-react-native/tester/-/tester-0.3.7.tgz#8e8b890435da1ed7c3a0a2fbe1e53330754d0f56"
integrity sha512-fQVHSyfPfQY11dbrZ+C5eSXXHi04ANKxmD1jcUMByuGbgkoKuCjI+0Y6/B1D5ipXlB0OhaJjloJvZv0T1hSaWg==
dependencies:
"@fluentui-react-native/interactive-hooks" ">=0.5.1 <1.0.0"
"@fluentui-react-native/stack" ">=0.2.8 <1.0.0"
"@fluentui/react-native" ">=0.15.87 <1.0.0"
"@uifabricshared/theme-registry" ">=0.3.69 <1.0.0"
"@uifabricshared/themed-stylesheet" ">=0.3.68 <1.0.0"
"@uifabricshared/theming-ramp" ">=0.10.5 <1.0.0"
"@uifabricshared/theming-react-native" ">=0.7.76 <1.0.0"
react-native-svg "^11.0.0"
"@hapi/address@2.x.x":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
@ -2544,18 +2530,6 @@
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.10.tgz#a1a41012012b5da9d4b205ba9eba58f6cce2ab7b"
integrity sha512-3F8qpwBAiVc5+HPJeXJpbrl+XjawGmciN5LgiO7Gv1pl1RHtjoMNqZpqEksaPJW05ViKe8snYInRs6xB25Xdew==
"@types/jest@^19.2.2":
version "19.2.4"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-19.2.4.tgz#543651712535962b7dc615e18e4a381fc2687442"
integrity sha512-w9nmNHHkl9lNeOorjz1a7BLUd6zTa3pakNx2qkKCVtYS44L7taPcJB8l1kQWVOIa7kN08qwlyS11A1nz2yUvWQ==
"@types/jest@^24.0.0":
version "24.9.1"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.9.1.tgz#02baf9573c78f1b9974a5f36778b366aa77bd534"
integrity sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==
dependencies:
jest-diff "^24.3.0"
"@types/jest@^25.1.4":
version "25.2.2"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.2.tgz#6a752e7a00f69c3e790ea00c345029d5cefa92bf"
@ -2850,14 +2824,6 @@
resolved "https://registry.yarnpkg.com/@uifabric/prettier-rules/-/prettier-rules-7.0.4.tgz#03082a6cc4b586104738a24892c56e0f1d3df1b6"
integrity sha512-PK60wLAjPrG2l93r1l/VY2BmnC1la0oxIXYBuln5DOAFJcSXMea9RxoNjuqhhqZGZo6aLjO7lW070MeVOvkABQ==
"@uifabricshared/theming-react-native@0.7.75":
version "0.7.75"
resolved "https://registry.yarnpkg.com/@uifabricshared/theming-react-native/-/theming-react-native-0.7.75.tgz#68f6ff2a7c4ea04ed8e9f1e4bd6f04e763462754"
integrity sha512-wB6gW6/Gs0hsZb4rnlRLhquUvijhGc5CJM/ee/AqJmFV74qTWRUCpBEjzb/Ye9qKI4JAJZka3QASqWIMEgr/vw==
dependencies:
"@uifabricshared/theme-registry" ">=0.3.69 <1.0.0"
"@uifabricshared/theming-ramp" ">=0.10.4 <1.0.0"
"@wdio/allure-reporter@5.22.4":
version "5.22.4"
resolved "https://registry.yarnpkg.com/@wdio/allure-reporter/-/allure-reporter-5.22.4.tgz#3d0e3a5d28db5ea37fb1f1c356ed76b130d9aac3"
@ -3231,6 +3197,11 @@ abab@^2.0.0:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
abab@^2.0.3:
version "2.0.4"
resolved "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c"
integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
@ -3259,6 +3230,14 @@ acorn-globals@^4.1.0:
acorn "^6.0.1"
acorn-walk "^6.0.1"
acorn-globals@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==
dependencies:
acorn "^7.1.1"
acorn-walk "^7.1.1"
acorn-jsx@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
@ -5511,6 +5490,11 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
inherits "^2.0.1"
safe-buffer "^5.0.1"
circular-json-es6@^2.0.1:
version "2.0.2"
resolved "https://registry.npmjs.org/circular-json-es6/-/circular-json-es6-2.0.2.tgz#e4f4a093e49fb4b6aba1157365746112a78bd344"
integrity sha512-ODYONMMNb3p658Zv+Pp+/XPa5s6q7afhz3Tzyvo+VRh9WIrJ64J76ZC4GQxnlye/NesTn09jvOiuE8+xxfpwhQ==
circular-json@^0.5.9:
version "0.5.9"
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d"
@ -6224,11 +6208,16 @@ csso@^4.0.2:
dependencies:
css-tree "1.0.0-alpha.39"
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@~0.3.6:
version "0.3.8"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
cssom@^0.4.4:
version "0.4.4"
resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
cssstyle@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
@ -6236,6 +6225,13 @@ cssstyle@^1.0.0:
dependencies:
cssom "0.3.x"
cssstyle@^2.2.0:
version "2.3.0"
resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
dependencies:
cssom "~0.3.6"
csstype@^2.2.0:
version "2.6.10"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
@ -6270,6 +6266,15 @@ data-urls@^1.0.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
data-urls@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==
dependencies:
abab "^2.0.3"
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
dateformat@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
@ -6340,6 +6345,11 @@ decamelize@^2.0.0:
dependencies:
xregexp "4.0.0"
decimal.js@^10.2.0:
version "10.2.0"
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231"
integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@ -6366,6 +6376,13 @@ deep-eql@^0.1.3:
dependencies:
type-detect "0.1.1"
deep-equal-ident@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz#06f4b89e53710cd6cea4a7781c7a956642de8dc9"
integrity sha1-BvS4nlNxDNbOpKd4HHqVZkLejck=
dependencies:
lodash.isequal "^3.0"
deep-equal@^1.0.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
@ -6753,6 +6770,13 @@ domexception@^1.0.1:
dependencies:
webidl-conversions "^4.0.2"
domexception@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==
dependencies:
webidl-conversions "^5.0.0"
domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
@ -6964,9 +6988,9 @@ envinfo@^7.5.0, envinfo@^7.7.2:
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc"
integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==
enzyme-adapter-react-16@^1.15.2:
enzyme-adapter-react-16@^1.15.4:
version "1.15.4"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.4.tgz#328a782365a363ecb424f99283c4833dd92c0f21"
resolved "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.4.tgz#328a782365a363ecb424f99283c4833dd92c0f21"
integrity sha512-wPzxs+JaGDK2TPYzl5a9YWGce6i2SQ3Cg51ScLeyj2WotUZ8Obcq1ke/U1Y2VGpYlb9rrX2yCjzSMgtKCeAt5w==
dependencies:
enzyme-adapter-utils "^1.13.1"
@ -6991,6 +7015,14 @@ enzyme-adapter-utils@^1.13.1:
prop-types "^15.7.2"
semver "^5.7.1"
enzyme-matchers@^7.1.2:
version "7.1.2"
resolved "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-7.1.2.tgz#d80530a61f22d28bb993dd7588abba38bd4de282"
integrity sha512-03WqAg2XDl7id9rARIO97HQ1JIw9F2heJ3R4meGu/13hx0ULTDEgl0E67MGl2Uq1jq1DyRnJfto1/VSzskdV5A==
dependencies:
circular-json-es6 "^2.0.1"
deep-equal-ident "^1.1.1"
enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz#b9256cb25a5f430f9bfe073a84808c1d74fced2e"
@ -6999,9 +7031,9 @@ enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.4:
has "^1.0.3"
object-is "^1.1.2"
enzyme-to-json@^3.4.4:
enzyme-to-json@^3.3.0, enzyme-to-json@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.5.0.tgz#3d536f1e8fb50d972360014fe2bd64e6a672f7dd"
resolved "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.5.0.tgz#3d536f1e8fb50d972360014fe2bd64e6a672f7dd"
integrity sha512-clusXRsiaQhG7+wtyc4t7MU8N3zCOgf4eY9+CeSenYzKlFST4lxerfOvnWd4SNaToKhkuba+w6m242YpQOS7eA==
dependencies:
lodash "^4.17.15"
@ -7168,6 +7200,18 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
escodegen@^1.14.1:
version "1.14.3"
resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
dependencies:
esprima "^4.0.1"
estraverse "^4.2.0"
esutils "^2.0.2"
optionator "^0.8.1"
optionalDependencies:
source-map "~0.6.1"
escodegen@^1.9.1:
version "1.14.1"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457"
@ -8940,6 +8984,13 @@ html-encoding-sniffer@^1.0.2:
dependencies:
whatwg-encoding "^1.0.1"
html-encoding-sniffer@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==
dependencies:
whatwg-encoding "^1.0.5"
html-entities@^1.2.0, html-entities@^1.2.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44"
@ -9659,6 +9710,11 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
dependencies:
isobject "^3.0.1"
is-potential-custom-element-name@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
is-regex@^1.0.4, is-regex@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
@ -9924,7 +9980,7 @@ jest-config@^24.9.0:
pretty-format "^24.9.0"
realpath-native "^1.1.0"
jest-diff@^24.3.0, jest-diff@^24.9.0:
jest-diff@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==
@ -9962,7 +10018,14 @@ jest-each@^24.9.0:
jest-util "^24.9.0"
pretty-format "^24.9.0"
jest-environment-jsdom@^24.9.0:
jest-environment-enzyme@^7.1.2:
version "7.1.2"
resolved "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-7.1.2.tgz#4561f26a719e8e87ce8c9a6d3f540a92663ba8d5"
integrity sha512-3tfaYAzO7qZSRrv+srQnfK16Vu5XwH/pHi8FpoqSHjKKngbHzXf7aBCBuWh8y3w0OtknHRfDMFrC60Khj+g1hA==
dependencies:
jest-environment-jsdom "^24.0.0"
jest-environment-jsdom@^24.0.0, jest-environment-jsdom@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b"
integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==
@ -9985,6 +10048,15 @@ jest-environment-node@^24.9.0:
jest-mock "^24.9.0"
jest-util "^24.9.0"
jest-enzyme@^7.1.2:
version "7.1.2"
resolved "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-7.1.2.tgz#91a10b2d3be1b56c0d65b34286e5bdc41ab4ba3d"
integrity sha512-j+jkph3t5hGBS12eOldpfsnERYRCHi4c/0KWPMnqRPoJJXvCpLIc5th1MHl0xDznQDXVU0AHUXg3rqMrf8vGpA==
dependencies:
enzyme-matchers "^7.1.2"
enzyme-to-json "^3.3.0"
jest-environment-enzyme "^7.1.2"
jest-get-type@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
@ -10347,6 +10419,38 @@ jsdom@^11.5.1:
ws "^5.2.0"
xml-name-validator "^3.0.0"
jsdom@^16.4.0:
version "16.4.0"
resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb"
integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==
dependencies:
abab "^2.0.3"
acorn "^7.1.1"
acorn-globals "^6.0.0"
cssom "^0.4.4"
cssstyle "^2.2.0"
data-urls "^2.0.0"
decimal.js "^10.2.0"
domexception "^2.0.1"
escodegen "^1.14.1"
html-encoding-sniffer "^2.0.1"
is-potential-custom-element-name "^1.0.0"
nwsapi "^2.2.0"
parse5 "5.1.1"
request "^2.88.2"
request-promise-native "^1.0.8"
saxes "^5.0.0"
symbol-tree "^3.2.4"
tough-cookie "^3.0.1"
w3c-hr-time "^1.0.2"
w3c-xmlserializer "^2.0.0"
webidl-conversions "^6.1.0"
whatwg-encoding "^1.0.5"
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
ws "^7.2.3"
xml-name-validator "^3.0.0"
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@ -10897,6 +11001,25 @@ lockfile@^1.0.4:
dependencies:
signal-exit "^3.0.2"
lodash._baseisequal@^3.0.0:
version "3.0.7"
resolved "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz#d8025f76339d29342767dcc887ce5cb95a5b51f1"
integrity sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=
dependencies:
lodash.isarray "^3.0.0"
lodash.istypedarray "^3.0.0"
lodash.keys "^3.0.0"
lodash._bindcallback@^3.0.0:
version "3.0.1"
resolved "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
@ -10937,6 +11060,24 @@ lodash.get@^4.0.0, lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.isarguments@^3.0.0:
version "3.1.0"
resolved "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
lodash.isarray@^3.0.0:
version "3.0.4"
resolved "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=
lodash.isequal@^3.0:
version "3.0.4"
resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz#1c35eb3b6ef0cd1ff51743e3ea3cf7fdffdacb64"
integrity sha1-HDXrO27wzR/1F0Pj6jz3/f/ay2Q=
dependencies:
lodash._baseisequal "^3.0.0"
lodash._bindcallback "^3.0.0"
lodash.isequal@^4.0.0, lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
@ -10957,6 +11098,20 @@ lodash.isplainobject@^4.0.6:
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
lodash.istypedarray@^3.0.0:
version "3.0.6"
resolved "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62"
integrity sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=
lodash.keys@^3.0.0:
version "3.1.2"
resolved "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=
dependencies:
lodash._getnative "^3.0.0"
lodash.isarguments "^3.0.0"
lodash.isarray "^3.0.0"
lodash.merge@^4.6.1:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@ -12202,7 +12357,7 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
nwsapi@^2.0.7:
nwsapi@^2.0.7, nwsapi@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
@ -12754,6 +12909,11 @@ parse5@4.0.0:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
parse5@5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
parse5@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
@ -13953,6 +14113,13 @@ request-promise-core@1.1.3:
dependencies:
lodash "^4.17.15"
request-promise-core@1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
dependencies:
lodash "^4.17.19"
request-promise-native@^1.0.5:
version "1.0.8"
resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36"
@ -13962,6 +14129,15 @@ request-promise-native@^1.0.5:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
request-promise-native@^1.0.8:
version "1.0.9"
resolved "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
dependencies:
request-promise-core "1.1.4"
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
request-promise@4.x, request-promise@^4.1.1, request-promise@^4.2.2, request-promise@^4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.5.tgz#186222c59ae512f3497dfe4d75a9c8461bd0053c"
@ -14325,6 +14501,13 @@ sax@>=0.6.0, sax@^1.2.1, sax@^1.2.4, sax@~1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
saxes@^5.0.0:
version "5.0.1"
resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
dependencies:
xmlchars "^2.2.0"
scheduler@0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.14.0.tgz#b392c23c9c14bfa2933d4740ad5603cc0d59ea5b"
@ -15291,7 +15474,7 @@ symbol-observable@1.0.1:
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=
symbol-tree@^3.2.2:
symbol-tree@^3.2.2, symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
@ -15592,6 +15775,15 @@ tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.5.0:
psl "^1.1.28"
punycode "^2.1.1"
tough-cookie@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2"
integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==
dependencies:
ip-regex "^2.1.0"
psl "^1.1.28"
punycode "^2.1.1"
tough-cookie@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
@ -15608,6 +15800,13 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"
tr46@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479"
integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==
dependencies:
punycode "^2.1.1"
trim-repeated@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21"
@ -16168,13 +16367,20 @@ vue-template-compiler@^2.6.11:
de-indent "^1.0.2"
he "^1.1.0"
w3c-hr-time@^1.0.1:
w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
dependencies:
browser-process-hrtime "^1.0.0"
w3c-xmlserializer@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==
dependencies:
xml-name-validator "^3.0.0"
walker@^1.0.7, walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
@ -16321,6 +16527,16 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
webidl-conversions@^5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
webidl-conversions@^6.1.0:
version "6.1.0"
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-bundle-analyzer@^3.0.4:
version "3.8.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.8.0.tgz#ce6b3f908daf069fd1f7266f692cbb3bded9ba16"
@ -16545,7 +16761,7 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
@ -16557,7 +16773,7 @@ whatwg-fetch@>=0.10.0, whatwg-fetch@^3.0.0:
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
@ -16580,6 +16796,15 @@ whatwg-url@^7.0.0:
tr46 "^1.0.1"
webidl-conversions "^4.0.2"
whatwg-url@^8.0.0:
version "8.2.2"
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.2.tgz#85e7f9795108b53d554cec640b2e8aee2a0d4bfd"
integrity sha512-PcVnO6NiewhkmzV0qn7A+UZ9Xx4maNTI+O+TShmfE4pqjoCMwUMjkvoNhNHPTvgR7QH9Xt3R13iHuWy2sToFxQ==
dependencies:
lodash.sortby "^4.7.0"
tr46 "^2.0.2"
webidl-conversions "^6.1.0"
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
@ -16826,6 +17051,11 @@ xmlbuilder@~11.0.0:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
xmlchars@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xmlcreate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-1.0.2.tgz#fa6bf762a60a413fb3dd8f4b03c5b269238d308f"