From 551c4d571e9546740c8fbd76419a53df2a0c4c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rge=20N=C3=A6ss?= Date: Fri, 16 Dec 2022 14:08:36 +0100 Subject: [PATCH] chore(form): replace react-sortable-hoc with dndkit (#3961) * chore(form): replace react-sortable-hoc with dndkit * fix(form): set sorting strategy for list axis * fix(form): change easing function for sortable lists --- packages/sanity/package.json | 5 +- .../Grid/GridArrayInput.tsx | 11 +- .../List/ListArrayInput.tsx | 17 +- .../ArrayOfPrimitivesInput.tsx | 20 +- .../form/inputs/arrays/common/DragHandle.tsx | 16 +- .../restrictToParentElementWithMargins.ts | 45 +++++ .../core/form/inputs/arrays/common/list.tsx | 185 ++++++++++++++---- .../form/inputs/arrays/common/sortable.tsx | 86 -------- .../form/inputs/arrays/layouts/CellLayout.tsx | 7 + .../form/inputs/arrays/layouts/RowLayout.tsx | 20 +- yarn.lock | 54 +++-- 11 files changed, 296 insertions(+), 170 deletions(-) create mode 100644 packages/sanity/src/core/form/inputs/arrays/common/dndkit-modifier/restrictToParentElementWithMargins.ts delete mode 100644 packages/sanity/src/core/form/inputs/arrays/common/sortable.tsx diff --git a/packages/sanity/package.json b/packages/sanity/package.json index c8b8769e1bb..4e2991ac11a 100644 --- a/packages/sanity/package.json +++ b/packages/sanity/package.json @@ -96,11 +96,14 @@ "write:version": "node -r esbuild-register scripts/writeVersion.ts" }, "dependencies": { + "@dnd-kit/core": "^6.0.5", + "@dnd-kit/modifiers": "^6.0.0", + "@dnd-kit/sortable": "^7.0.1", + "@dnd-kit/utilities": "^3.2.0", "@juggle/resize-observer": "^3.3.1", "@portabletext/react": "^1.0.6", "@portabletext/types": "^1.0.3", "@rexxars/react-json-inspector": "^8.0.1", - "@rexxars/react-sortable-hoc": "^2.0.0", "@sanity/asset-utils": "^1.2.5", "@sanity/bifur-client": "^0.3.0", "@sanity/block-tools": "3.0.6", diff --git a/packages/sanity/src/core/form/inputs/arrays/ArrayOfObjectsInput/Grid/GridArrayInput.tsx b/packages/sanity/src/core/form/inputs/arrays/ArrayOfObjectsInput/Grid/GridArrayInput.tsx index 6bd54c329a2..bb2d0997fd9 100644 --- a/packages/sanity/src/core/form/inputs/arrays/ArrayOfObjectsInput/Grid/GridArrayInput.tsx +++ b/packages/sanity/src/core/form/inputs/arrays/ArrayOfObjectsInput/Grid/GridArrayInput.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/jsx-handler-names */ import {Card, Stack, Text} from '@sanity/ui' -import React, {useCallback} from 'react' +import React, {useCallback, useMemo} from 'react' import {Item, List} from '../../common/list' import {ArrayOfObjectsInputProps, ObjectItem, ObjectItemProps} from '../../../../types' import {ArrayOfObjectsItem} from '../../../../members' @@ -51,6 +51,8 @@ export function GridArrayInput(props: ArrayOfObjectsInp return }, []) + const memberKeys = useMemo(() => members.map((member) => member.key), [members]) + return ( (props: ArrayOfObjectsInp {members?.length > 0 && ( - {members.map((member, index) => ( - + {members.map((member) => ( + {member.kind === 'item' && ( (props: ArrayOfObjectsInp ) const sortable = schemaType.options?.sortable !== false - + const memberKeys = useMemo(() => members.map((member) => member.key), [members]) return ( (props: ArrayOfObjectsInp ) : ( - - {members.map((member, index) => ( - + + {members.map((member) => ( + {member.kind === 'item' && ( ({ + id: `${member.key}-${member.kind === 'item' ? member.item.value : 'error'}`, + member: member, + })) + return ( - {members.length === 0 ? ( + {membersWithSortIds.length === 0 ? ( {schemaType.placeholder || <>No items} @@ -145,10 +152,15 @@ export class ArrayOfPrimitivesInput extends React.PureComponent ) : ( - - {members.map((member, index) => { + m.id)} + sortable={isSortable} + gap={1} + > + {membersWithSortIds.map(({member, id}, index) => { return ( - + {member.kind === 'item' && ( ` cursor: ${(props) => (props.grid ? 'move' : 'ns-resize')}; ` -const DRAG_HANDLE_PROPS = {[DRAG_HANDLE_ATTRIBUTE]: true} +export const SortableItemIdContext = React.createContext(null) -export const DragHandle = sortableHandle(function DragHandle( +export const DragHandle = function DragHandle( props: { grid?: boolean } & ButtonProps ) { + const id = useContext(SortableItemIdContext)! + const {listeners, attributes} = useSortable({id}) + return ( ) -}) +} diff --git a/packages/sanity/src/core/form/inputs/arrays/common/dndkit-modifier/restrictToParentElementWithMargins.ts b/packages/sanity/src/core/form/inputs/arrays/common/dndkit-modifier/restrictToParentElementWithMargins.ts new file mode 100644 index 00000000000..bc283954246 --- /dev/null +++ b/packages/sanity/src/core/form/inputs/arrays/common/dndkit-modifier/restrictToParentElementWithMargins.ts @@ -0,0 +1,45 @@ +import type {ClientRect, Modifier} from '@dnd-kit/core' +import type {Transform} from '@dnd-kit/utilities' + +function restrictToBoundingRect( + transform: Transform, + rect: ClientRect, + boundingRect: ClientRect, + margins: Margins +): Transform { + const value = { + ...transform, + } + + const marginY = margins.y || 0 + const marginX = margins.x || 0 + + if (rect.top + value.y <= boundingRect.top + marginY) { + value.y = boundingRect.top - rect.top + marginY + } else if (rect.bottom + value.y >= boundingRect.top + boundingRect.height - marginY) { + value.y = boundingRect.top + boundingRect.height - rect.bottom - marginY + } + + if (rect.left + value.x <= boundingRect.left - marginX) { + value.x = boundingRect.left - rect.left + marginX + } else if (rect.right + value.x >= boundingRect.left + boundingRect.width + marginX) { + value.x = boundingRect.left + boundingRect.width - rect.right + marginX + } + + return value +} + +interface Margins { + x?: number + y?: number +} + +export const restrictToParentElementWithMargins: (margins: Margins) => Modifier = + (margins: Margins) => + ({containerNodeRect, draggingNodeRect, transform}) => { + if (!draggingNodeRect || !containerNodeRect) { + return transform + } + + return restrictToBoundingRect(transform, draggingNodeRect, containerNodeRect, margins) + } diff --git a/packages/sanity/src/core/form/inputs/arrays/common/list.tsx b/packages/sanity/src/core/form/inputs/arrays/common/list.tsx index d460557f510..548b4d3da12 100644 --- a/packages/sanity/src/core/form/inputs/arrays/common/list.tsx +++ b/packages/sanity/src/core/form/inputs/arrays/common/list.tsx @@ -1,42 +1,139 @@ -import {Card, Grid, Theme} from '@sanity/ui' -import React, {ComponentProps, useCallback} from 'react' -import styled from 'styled-components' -import {MOVING_ITEM_CLASS_NAME, sortableItem, sortableList} from './sortable' - -const ListItem = styled(Card)` - &.${MOVING_ITEM_CLASS_NAME} { - z-index: 10000; - border-radius: ${({theme}) => theme.sanity.radius[2]}px; - box-shadow: 0 0 0 0, 0 8px 17px 2px var(--card-shadow-umbra-color), - 0 3px 14px 2px var(--card-shadow-penumbra-color), - 0 5px 5px -3px var(--card-shadow-ambient-color); - - // Used inside CellItem - [data-ui='DragHandleCard'] { - opacity: 1; - } - - [data-ui='DragHandleButton'] { - background-color: ${({theme}: {theme: Theme}) => - theme.sanity.color.button.bleed.primary.pressed.bg}; - color: ${({theme}: {theme: Theme}) => theme.sanity.color.button.bleed.primary.pressed.fg}; - [data-ui='Text'] { - color: inherit; - } - } - } +import {Box, Card, Grid} from '@sanity/ui' +import React, {ComponentProps, useCallback, useMemo} from 'react' +import styled, {css} from 'styled-components' +import { + AutoScrollOptions, + closestCenter, + DndContext, + DragEndEvent, + KeyboardSensor, + PointerSensor, + SensorOptions, + useSensor, + useSensors, +} from '@dnd-kit/core' +import { + horizontalListSortingStrategy, + SortableContext, + sortableKeyboardCoordinates, + useSortable, + verticalListSortingStrategy, +} from '@dnd-kit/sortable' +import {CSS, Transition} from '@dnd-kit/utilities' +import {restrictToHorizontalAxis, restrictToVerticalAxis} from '@dnd-kit/modifiers' +import {SortableItemIdContext} from './DragHandle' +import {restrictToParentElementWithMargins} from './dndkit-modifier/restrictToParentElementWithMargins' + +export const MOVING_ITEM_CLASS_NAME = 'moving' + +const ListItem = styled(Box) & {$moving?: boolean}>` + ${(props) => + props.$moving && + css` + z-index: 10000; + /* prevents hover-effects etc on the dragged element */ + pointer-events: none; + `} ` -const SortableList = sortableList(Grid) -const SortableListItem = sortableItem(ListItem) +const AUTO_SCROLL_OPTIONS: AutoScrollOptions = { + threshold: { + x: 0, + y: 0.02, + }, +} +const SENSOR_OPTIONS: SensorOptions = { + coordinateGetter: sortableKeyboardCoordinates, +} + +const TRANSITION = { + duration: 200, + easing: 'ease', +} + +type Axis = 'x' | 'y' + +function restrictToAxis(axis: Axis) { + return axis === 'x' ? restrictToHorizontalAxis : restrictToVerticalAxis +} +function sortingStrategy(axis: Axis) { + return axis === 'x' ? horizontalListSortingStrategy : verticalListSortingStrategy +} + +function SortableList(props: ListProps) { + const {items, axis, onItemMove, children, ...rest} = props + + const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, SENSOR_OPTIONS)) + + const handleDragEnd = useCallback( + (event: DragEndEvent) => { + const {active, over} = event + + if (active.id !== over?.id) { + onItemMove?.({ + fromIndex: items.indexOf(active.id as string), + toIndex: items.indexOf(over?.id as string), + }) + } + }, + [items, onItemMove] + ) + const modifiers = useMemo( + () => [restrictToParentElementWithMargins({y: 4}), ...(axis ? [restrictToAxis(axis)] : [])], + [axis] + ) + + return ( + + + {children} + + + ) +} + +function SortableListItem(props: ItemProps) { + const {id, children, disableTransition} = props + const {setNodeRef, transform, transition, active} = useSortable({ + id, + transition: disableTransition ? null : TRANSITION, + }) + + const isActive = id === active?.id + + const style = useMemo( + () => + ({ + transform: CSS.Translate.toString(transform), + transition, + pointerEvents: active ? 'none' : undefined, + } as const), + [transform, transition, active] + ) + return ( + + {children} + + ) +} interface ListProps extends ComponentProps { sortable?: boolean - lockAxis?: 'x' | 'y' | 'xy' - axis?: 'x' | 'y' | 'xy' + axis?: Axis + items: string[] onItemMove?: (event: {fromIndex: number; toIndex: number}) => void children?: React.ReactNode - tabIndex?: number } export function List(props: ListProps) { @@ -44,20 +141,28 @@ export function List(props: ListProps) { // Note: this is here to make SortableList API compatible with onItemMove const handleSortEnd = useCallback( - (event: {newIndex: number; oldIndex: number}) => - onItemMove?.({ - fromIndex: event.oldIndex, - toIndex: event.newIndex, - }), + (event: {fromIndex: number; toIndex: number}) => onItemMove?.(event), [onItemMove] ) - return sortable ? : + return sortable ? : } -type ItemProps = {sortable?: boolean; children?: React.ReactNode; index: number} +interface ItemProps { + id: string + + // false positive: + // eslint-disable-next-line react/no-unused-prop-types + sortable?: boolean + disableTransition?: boolean + children?: React.ReactNode +} export function Item(props: ItemProps & ComponentProps) { const {sortable, ...rest} = props - return sortable ? : + return ( + + {sortable ? : } + + ) } diff --git a/packages/sanity/src/core/form/inputs/arrays/common/sortable.tsx b/packages/sanity/src/core/form/inputs/arrays/common/sortable.tsx deleted file mode 100644 index 1088c2cb166..00000000000 --- a/packages/sanity/src/core/form/inputs/arrays/common/sortable.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import React, {ComponentType} from 'react' -import type {SortableContainerProps} from '@rexxars/react-sortable-hoc' -import {SortableContainer, SortableElement, SortableHandle} from '@rexxars/react-sortable-hoc' -import {FIXME} from '../../../../FIXME' - -export const MOVING_ITEM_CLASS_NAME = 'moving' -export const DRAG_HANDLE_ATTRIBUTE = 'data-drag-handle' - -// higher order components to make a sortable list/item components -type ExposedSortableProps = { - onSortStart?: () => void - onSortEnd?: (event: {newIndex: number; oldIndex: number}) => void -} - -export function sortableHandle( - Component: React.ComponentType -): React.ComponentType { - return SortableHandle(Component) -} - -// Wrapper to avoid accidental leaking of react-sortable-hoc props -export function sortableItem( - Component: React.ComponentType -): React.ComponentType { - return SortableElement(Component) -} - -// Wrapper to avoid accidental leaking of react-sortable-hoc props -function sortableContainer( - Component: React.ComponentType, - options: SortableContainerProps -) { - const Container = SortableContainer( - React.forwardRef(function Sortable( - props: Props & ExposedSortableProps, - forwardedRef: React.ForwardedRef> - ) { - return - }) - ) as FIXME as React.ComponentType // there are some wonky typings from react-sortable-hoc - - return React.forwardRef(function SortableList( - props: Props & ExposedSortableProps, - ref: React.ForwardedRef> - ) { - return - }) -} - -const KeyCode = { - Space: 32, - Enter: 13, - Esc: 27, - Up: 38, - Left: 37, - Right: 39, - Down: 40, -} - -const KEYCODES = { - lift: [KeyCode.Space, KeyCode.Enter], - drop: [KeyCode.Space, KeyCode.Enter], - cancel: [KeyCode.Esc], - up: [KeyCode.Left, KeyCode.Up], - down: [KeyCode.Right, KeyCode.Down], -} - -export function sortableList(Component: React.ComponentType) { - return sortableContainer(Component, { - helperClass: MOVING_ITEM_CLASS_NAME, - keyCodes: KEYCODES, - axis: 'y', - lockAxis: 'y', - useDragHandle: true, - shouldCancelStart, - }) as any as ComponentType -} - -// Cancel sorting if the event target is not drag handle -function shouldCancelStart(event: React.UIEvent) { - return !isDragHandle(event.target as HTMLElement) -} - -function isDragHandle(element: HTMLElement) { - return element.matches(`[${DRAG_HANDLE_ATTRIBUTE}="true"],[${DRAG_HANDLE_ATTRIBUTE}="true"] *`) -} diff --git a/packages/sanity/src/core/form/inputs/arrays/layouts/CellLayout.tsx b/packages/sanity/src/core/form/inputs/arrays/layouts/CellLayout.tsx index e3f5596bcdb..7de7119808c 100644 --- a/packages/sanity/src/core/form/inputs/arrays/layouts/CellLayout.tsx +++ b/packages/sanity/src/core/form/inputs/arrays/layouts/CellLayout.tsx @@ -2,6 +2,7 @@ import {Box, Card, CardTone, Flex} from '@sanity/ui' import React, {ComponentProps, ReactNode} from 'react' import styled from 'styled-components' import {DragHandle} from '../common/DragHandle' +import {MOVING_ITEM_CLASS_NAME} from '../common/list' interface RowLayoutProps { tone?: CardTone @@ -48,6 +49,12 @@ const Root = styled(Card)` } } + .${MOVING_ITEM_CLASS_NAME} & { + box-shadow: 0 0 0 0, 0 8px 17px 2px var(--card-shadow-umbra-color), + 0 3px 14px 2px var(--card-shadow-penumbra-color), + 0 5px 5px -3px var(--card-shadow-ambient-color); + } + &[aria-selected='true'] { box-shadow: 0 0 0 2px var(--card-focus-ring-color); } diff --git a/packages/sanity/src/core/form/inputs/arrays/layouts/RowLayout.tsx b/packages/sanity/src/core/form/inputs/arrays/layouts/RowLayout.tsx index f2657ccdce4..f35bae50c11 100644 --- a/packages/sanity/src/core/form/inputs/arrays/layouts/RowLayout.tsx +++ b/packages/sanity/src/core/form/inputs/arrays/layouts/RowLayout.tsx @@ -3,7 +3,7 @@ import React, {ReactNode, useRef} from 'react' import styled from 'styled-components' import {useDidUpdate} from '../../../hooks/useDidUpdate' import {DragHandle} from '../common/DragHandle' -import {MOVING_ITEM_CLASS_NAME} from '../common/sortable' +import {MOVING_ITEM_CLASS_NAME} from '../common/list' interface RowLayoutProps { tone?: CardTone @@ -21,23 +21,21 @@ const Root = styled(Card)` position: relative; border: 1px solid transparent; transition: border-color 250ms; - .dragHandle { - color: var(--card-shadow-umbra-color); + + .${MOVING_ITEM_CLASS_NAME} & { + border-color: var(--card-shadow-umbra-color); + box-shadow: 0 0 0 0, 0 8px 17px 2px var(--card-shadow-umbra-color), + 0 3px 14px 2px var(--card-shadow-penumbra-color), + 0 5px 5px -3px var(--card-shadow-ambient-color); } + &:hover { border-color: var(--card-shadow-umbra-color); - .dragHandle { - color: inherit; - } } + &[aria-selected='true'] { border-color: var(--card-focus-ring-color); } - .${MOVING_ITEM_CLASS_NAME} & { - box-shadow: 0 0 0 0, 0 8px 17px 2px var(--card-shadow-umbra-color), - 0 3px 14px 2px var(--card-shadow-penumbra-color), - 0 5px 5px -3px var(--card-shadow-ambient-color); - } ` export function RowLayout(props: RowLayoutProps) { diff --git a/yarn.lock b/yarn.lock index 189e00f47cc..30e3061bb0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1132,7 +1132,7 @@ core-js-pure "^3.25.1" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6", "@babel/runtime@^7.18.9", "@babel/runtime@^7.2.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.6", "@babel/runtime@^7.18.9", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.19.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78" integrity sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA== @@ -1472,6 +1472,45 @@ debug "^3.1.0" lodash.once "^4.1.1" +"@dnd-kit/accessibility@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.0.1.tgz#3ccbefdfca595b0a23a5dc57d3de96bc6935641c" + integrity sha512-HXRrwS9YUYQO9lFRc/49uO/VICbM+O+ZRpFDe9Pd1rwVv2PCNkRiTZRdxrDgng/UkvdC3Re9r2vwPpXXrWeFzg== + dependencies: + tslib "^2.0.0" + +"@dnd-kit/core@^6.0.5": + version "6.0.5" + resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.0.5.tgz#5670ad0dcc83cd51dbf2fa8c6a5c8af4ac0c1989" + integrity sha512-3nL+Zy5cT+1XwsWdlXIvGIFvbuocMyB4NBxTN74DeBaBqeWdH9JsnKwQv7buZQgAHmAH+eIENfS1ginkvW6bCw== + dependencies: + "@dnd-kit/accessibility" "^3.0.0" + "@dnd-kit/utilities" "^3.2.0" + tslib "^2.0.0" + +"@dnd-kit/modifiers@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@dnd-kit/modifiers/-/modifiers-6.0.0.tgz#61d8834132f791a68e9e93be5426becbcd45c078" + integrity sha512-V3+JSo6/BTcgPRHiNUTSKgqVv/doKXg+T4Z0QvKiiXp+uIyJTUtPkQOBRQApUWi3ApBhnoWljyt/3xxY4fTd0Q== + dependencies: + "@dnd-kit/utilities" "^3.2.0" + tslib "^2.0.0" + +"@dnd-kit/sortable@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-7.0.1.tgz#99c6012bbab4d8bb726c0eef7b921a338c404fdb" + integrity sha512-n77qAzJQtMMywu25sJzhz3gsHnDOUlEjTtnRl8A87rWIhnu32zuP+7zmFjwGgvqfXmRufqiHOSlH7JPC/tnJ8Q== + dependencies: + "@dnd-kit/utilities" "^3.2.0" + tslib "^2.0.0" + +"@dnd-kit/utilities@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.0.tgz#b3e956ea63a1347c9d0e1316b037ddcc6140acda" + integrity sha512-h65/pn2IPCCIWwdlR2BMLqRkDxpTEONA+HQW3n765HBijLYGyrnTCLa2YQt8VVjjSQD6EfFlTE6aS2Q/b6nb2g== + dependencies: + tslib "^2.0.0" + "@emotion/is-prop-valid@^0.8.2": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" @@ -3422,15 +3461,6 @@ debounce "1.0.0" md5-o-matic "^0.1.1" -"@rexxars/react-sortable-hoc@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@rexxars/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz#3698164385152ba9c3d1b8afa1bab8bcb83b6c5f" - integrity sha512-wAbfK73pvmUG+wZ+oRhx86tjENzWCcZ3BOlcy0OZpV9tx+py2EmRI7fRtFAe6OjF7fTXqQZ259yPxkDguun0xg== - dependencies: - "@babel/runtime" "^7.2.0" - invariant "^2.2.4" - prop-types "^15.5.7" - "@rollup/plugin-alias@^3.1.9": version "3.1.9" resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.9.tgz#a5d267548fe48441f34be8323fb64d1d4a1b3fdf" @@ -11054,7 +11084,7 @@ into-stream@^3.1.0: from2 "^2.1.1" p-is-promise "^1.1.0" -invariant@2.2.4, invariant@^2.2.4: +invariant@2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -15528,7 +15558,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.4, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==