Chore(front): Add more typeguards (#2136)
* Chore(front): Add more typeguards Co-authored-by: Benjamin Mayanja V <vibenjamin6@gmail.com> Co-authored-by: KlingerMatheus <klinger.matheus@gitstart.dev> * Remove source map generation to avoid warnings --------- Co-authored-by: Benjamin Mayanja V <vibenjamin6@gmail.com> Co-authored-by: KlingerMatheus <klinger.matheus@gitstart.dev> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
REACT_APP_SERVER_BASE_URL=http://localhost:3000
|
||||
GENERATE_SOURCEMAP=false
|
||||
|
||||
# ———————— Optional ————————
|
||||
# REACT_APP_SERVER_AUTH_URL=http://localhost:3000/auth
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
"@floating-ui/react": "^0.24.3",
|
||||
"@hello-pangea/dnd": "^16.2.0",
|
||||
"@hookform/resolvers": "^3.1.1",
|
||||
"@sniptt/guards": "^0.2.0",
|
||||
"@tabler/icons-react": "^2.30.0",
|
||||
"@tanstack/react-virtual": "^3.0.0-alpha.0",
|
||||
"@types/node": "^16.18.4",
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import React, { Ref, RefCallback } from 'react';
|
||||
import { isFunction } from '@sniptt/guards';
|
||||
|
||||
export const useCombinedRefs =
|
||||
<T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> =>
|
||||
(node: T) => {
|
||||
for (const ref of refs) {
|
||||
if (typeof ref === 'function') {
|
||||
if (isFunction(ref)) {
|
||||
ref(node);
|
||||
} else if (ref !== null && ref !== undefined) {
|
||||
(ref as React.MutableRefObject<T | null>).current = node;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
@ -10,7 +11,6 @@ import {
|
||||
} from '@/ui/input/components/AutosizeTextInput';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { Activity, useCreateCommentMutation } from '~/generated/graphql';
|
||||
import { isNonEmptyString } from '~/utils/isNonEmptyString';
|
||||
|
||||
import { Comment } from '../comment/Comment';
|
||||
import { GET_ACTIVITY } from '../graphql/queries/getActivity';
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isBoolean } from '@sniptt/guards';
|
||||
|
||||
import { FieldBooleanValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldBooleanValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldBooleanValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'boolean';
|
||||
): fieldValue is FieldBooleanValue => isBoolean(fieldValue);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldChipValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldChipValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldChipValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'string';
|
||||
): fieldValue is FieldChipValue => isString(fieldValue);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { isNull, isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldDateValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldDateValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldDateValue =>
|
||||
fieldValue === null ||
|
||||
(fieldValue !== undefined && typeof fieldValue === 'string');
|
||||
): fieldValue is FieldDateValue => isNull(fieldValue) || isString(fieldValue);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldEmailValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldEmailValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldEmailValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'string';
|
||||
): fieldValue is FieldEmailValue => isString(fieldValue);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { isNull, isNumber } from '@sniptt/guards';
|
||||
|
||||
import { FieldMoneyValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldMoneyValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldMoneyValue =>
|
||||
fieldValue === null ||
|
||||
(fieldValue !== undefined && typeof fieldValue === 'number');
|
||||
): fieldValue is FieldMoneyValue => isNull(fieldValue) || isNumber(fieldValue);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { isNull, isNumber } from '@sniptt/guards';
|
||||
|
||||
import { FieldNumberValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldNumberValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldNumberValue =>
|
||||
fieldValue === null ||
|
||||
(fieldValue !== undefined && typeof fieldValue === 'number');
|
||||
): fieldValue is FieldNumberValue => isNull(fieldValue) || isNumber(fieldValue);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldPhoneValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldPhoneValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldPhoneValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'string';
|
||||
): fieldValue is FieldPhoneValue => isString(fieldValue);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isNumber } from '@sniptt/guards';
|
||||
|
||||
import { FieldProbabilityValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldProbabilityValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldProbabilityValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'number';
|
||||
): fieldValue is FieldProbabilityValue => isNumber(fieldValue);
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { isObject, isUndefined } from '@sniptt/guards';
|
||||
|
||||
import { FieldRelationValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldRelationValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldRelationValue =>
|
||||
fieldValue !== undefined && typeof fieldValue === 'object';
|
||||
!isUndefined(fieldValue) && isObject(fieldValue);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldTextValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldTextValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldTextValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'string';
|
||||
): fieldValue is FieldTextValue => isString(fieldValue);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { FieldURLValue } from '../FieldMetadata';
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldURLValue = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldURLValue =>
|
||||
fieldValue !== null &&
|
||||
fieldValue !== undefined &&
|
||||
typeof fieldValue === 'string';
|
||||
): fieldValue is FieldURLValue => isString(fieldValue);
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
import { Avatar, AvatarType } from '@/users/components/Avatar';
|
||||
import { isNonEmptyString } from '~/utils/isNonEmptyString';
|
||||
|
||||
import { Chip, ChipVariant } from './Chip';
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useRef } from 'react';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
@ -9,7 +10,6 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { MenuItemMultiSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemMultiSelectAvatar';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { Avatar } from '@/users/components/Avatar';
|
||||
import { isNonEmptyString } from '~/utils/isNonEmptyString';
|
||||
|
||||
import { EntityForSelect } from '../types/EntityForSelect';
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useRef } from 'react';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { IconPlus } from '@/ui/display/icon';
|
||||
@ -11,7 +12,6 @@ import { MenuItemSelectAvatar } from '@/ui/navigation/menu-item/components/MenuI
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { Avatar } from '@/users/components/Avatar';
|
||||
import { assertNotNull } from '~/utils/assert';
|
||||
import { isNonEmptyString } from '~/utils/isNonEmptyString';
|
||||
|
||||
import { CreateButtonId, EmptyButtonId } from '../constants';
|
||||
import { useEntitySelectScroll } from '../hooks/useEntitySelectScroll';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { isNonEmptyString } from '~/utils/isNonEmptyString';
|
||||
import { stringToHslColor } from '~/utils/string-to-hsl';
|
||||
|
||||
import { getImageAbsoluteURIOrBase64 } from '../utils/getProfilePictureAbsoluteURI';
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
||||
|
||||
import { AppPath } from '../../modules/types/AppPath';
|
||||
import { isNonEmptyString } from '../../utils/isNonEmptyString';
|
||||
|
||||
export const VerifyEffect = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
||||
@ -8,7 +9,6 @@ import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
import { useImpersonateMutation } from '~/generated/graphql';
|
||||
|
||||
import { AppPath } from '../../modules/types/AppPath';
|
||||
import { isNonEmptyString } from '../../utils/isNonEmptyString';
|
||||
|
||||
export const ImpersonateEffect = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { isString } from '@sniptt/guards';
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/testing-library';
|
||||
@ -116,7 +117,7 @@ const editRelationMocks = (
|
||||
) => [
|
||||
...graphqlMocks.filter((graphqlMock) => {
|
||||
if (
|
||||
typeof graphqlMock.info.operationName === 'string' &&
|
||||
isString(graphqlMock.info.operationName) &&
|
||||
[
|
||||
getOperationName(UPDATE_ONE_PERSON),
|
||||
getOperationName(SEARCH_COMPANY_QUERY),
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { ComponentProps, JSX } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isNumber, isString } from '@sniptt/guards';
|
||||
import { Decorator } from '@storybook/react';
|
||||
|
||||
const StyledColumnTitle = styled.h1`
|
||||
@ -75,6 +76,9 @@ const emptyDimension = {
|
||||
props: () => ({}),
|
||||
} as CatalogDimension;
|
||||
|
||||
const isStringOrNumber = (term: unknown): term is string | number =>
|
||||
isString(term) || isNumber(term);
|
||||
|
||||
export type CatalogDimension<
|
||||
ComponentType extends React.ElementType = () => JSX.Element,
|
||||
> = {
|
||||
@ -108,30 +112,26 @@ export const CatalogDecorator: Decorator = (Story, context) => {
|
||||
<StyledColumnContainer key={value4}>
|
||||
<StyledColumnTitle>
|
||||
{dimension4.labels?.(value4) ??
|
||||
(['string', 'number'].includes(typeof value4) ? value4 : '')}
|
||||
(isStringOrNumber(value4) ? value4 : '')}
|
||||
</StyledColumnTitle>
|
||||
{dimension3.values.map((value3: any) => (
|
||||
<StyledRowsContainer key={value3}>
|
||||
<StyledRowsTitle>
|
||||
{dimension3.labels?.(value3) ??
|
||||
(['string', 'number'].includes(typeof value3) ? value3 : '')}
|
||||
(isStringOrNumber(value3) ? value3 : '')}
|
||||
</StyledRowsTitle>
|
||||
{dimension2.values.map((value2: any) => (
|
||||
<StyledRowContainer key={value2}>
|
||||
<StyledRowTitle>
|
||||
{dimension2.labels?.(value2) ??
|
||||
(['string', 'number'].includes(typeof value2)
|
||||
? value2
|
||||
: '')}
|
||||
(isStringOrNumber(value2) ? value2 : '')}
|
||||
</StyledRowTitle>
|
||||
{dimension1.values.map((value1: any) => {
|
||||
return (
|
||||
<StyledCellContainer key={value1} id={value1}>
|
||||
<StyledElementTitle>
|
||||
{dimension1.labels?.(value1) ??
|
||||
(['string', 'number'].includes(typeof value1)
|
||||
? value1
|
||||
: '')}
|
||||
(isStringOrNumber(value1) ? value1 : '')}
|
||||
</StyledElementTitle>
|
||||
<StyledElementContainer
|
||||
width={options?.elementContainer?.width}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { isObject, isString } from '@sniptt/guards';
|
||||
import { GraphQLVariables } from 'msw';
|
||||
|
||||
import {
|
||||
@ -27,7 +28,7 @@ const filterData = <DataT>(
|
||||
const nestedKey = Object.keys(filterElement.is)[0] as string;
|
||||
if (
|
||||
item[key as keyof typeof item] &&
|
||||
typeof item[key as keyof typeof item] === 'object'
|
||||
isObject(item[key as keyof typeof item])
|
||||
) {
|
||||
const nestedItem = item[key as keyof typeof item];
|
||||
return (
|
||||
@ -116,7 +117,7 @@ export const filterAndSortData = <DataT>(
|
||||
|
||||
const sortDirection =
|
||||
firstOrderBy[key as unknown as keyof typeof firstOrderBy];
|
||||
if (typeof itemAValue === 'string' && typeof itemBValue === 'string') {
|
||||
if (isString(itemAValue) && isString(itemBValue)) {
|
||||
return sortDirection === 'desc'
|
||||
? itemBValue.localeCompare(itemAValue)
|
||||
: -itemBValue.localeCompare(itemAValue);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { isNull, isNumber, isString } from '@sniptt/guards';
|
||||
|
||||
import { logError } from './logError';
|
||||
|
||||
const DEBUG_MODE = false;
|
||||
@ -11,13 +13,13 @@ export const canBeCastAsIntegerOrNull = (
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof probableNumberOrNull === 'number') {
|
||||
if (isNumber(probableNumberOrNull)) {
|
||||
if (DEBUG_MODE) logError('typeof probableNumberOrNull === "number"');
|
||||
|
||||
return Number.isInteger(probableNumberOrNull);
|
||||
}
|
||||
|
||||
if (probableNumberOrNull === null) {
|
||||
if (isNull(probableNumberOrNull)) {
|
||||
if (DEBUG_MODE) logError('probableNumberOrNull === null');
|
||||
|
||||
return true;
|
||||
@ -29,7 +31,7 @@ export const canBeCastAsIntegerOrNull = (
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof probableNumberOrNull === 'string') {
|
||||
if (isString(probableNumberOrNull)) {
|
||||
const stringAsNumber = +probableNumberOrNull;
|
||||
|
||||
if (isNaN(stringAsNumber)) {
|
||||
@ -54,7 +56,7 @@ export const castAsIntegerOrNull = (
|
||||
throw new Error('Cannot cast to number or null');
|
||||
}
|
||||
|
||||
if (probableNumberOrNull === null) {
|
||||
if (isNull(probableNumberOrNull)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -62,11 +64,11 @@ export const castAsIntegerOrNull = (
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof probableNumberOrNull === 'number') {
|
||||
if (isNumber(probableNumberOrNull)) {
|
||||
return probableNumberOrNull;
|
||||
}
|
||||
|
||||
if (typeof probableNumberOrNull === 'string') {
|
||||
if (isString(probableNumberOrNull)) {
|
||||
return +probableNumberOrNull;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { isInteger, isNull, isNumber, isString } from '@sniptt/guards';
|
||||
|
||||
export const canBeCastAsPositiveIntegerOrNull = (
|
||||
probablePositiveNumberOrNull: string | undefined | number | null,
|
||||
): probablePositiveNumberOrNull is number | null => {
|
||||
@ -5,14 +7,14 @@ export const canBeCastAsPositiveIntegerOrNull = (
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof probablePositiveNumberOrNull === 'number') {
|
||||
if (isNumber(probablePositiveNumberOrNull)) {
|
||||
return (
|
||||
Number.isInteger(probablePositiveNumberOrNull) &&
|
||||
Math.sign(probablePositiveNumberOrNull) !== -1
|
||||
);
|
||||
}
|
||||
|
||||
if (probablePositiveNumberOrNull === null) {
|
||||
if (isNull(probablePositiveNumberOrNull)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -20,14 +22,14 @@ export const canBeCastAsPositiveIntegerOrNull = (
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof probablePositiveNumberOrNull === 'string') {
|
||||
if (isString(probablePositiveNumberOrNull)) {
|
||||
const stringAsNumber = +probablePositiveNumberOrNull;
|
||||
|
||||
if (isNaN(stringAsNumber)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Number.isInteger(stringAsNumber) && Math.sign(stringAsNumber) !== -1) {
|
||||
if (isInteger(stringAsNumber) && Math.sign(stringAsNumber) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -52,11 +54,11 @@ export const castAsPositiveIntegerOrNull = (
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof probablePositiveNumberOrNull === 'number') {
|
||||
if (isNumber(probablePositiveNumberOrNull)) {
|
||||
return probablePositiveNumberOrNull;
|
||||
}
|
||||
|
||||
if (typeof probablePositiveNumberOrNull === 'string') {
|
||||
if (isString(probablePositiveNumberOrNull)) {
|
||||
return +probablePositiveNumberOrNull;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { isDate, isNumber, isString } from '@sniptt/guards';
|
||||
import { differenceInCalendarDays, formatDistanceToNow } from 'date-fns';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
@ -10,11 +11,11 @@ export const parseDate = (dateToParse: Date | string | number) => {
|
||||
|
||||
if (!dateToParse) {
|
||||
throw new Error(`Invalid date passed to formatPastDate: "${dateToParse}"`);
|
||||
} else if (typeof dateToParse === 'string') {
|
||||
} else if (isString(dateToParse)) {
|
||||
formattedDate = DateTime.fromISO(dateToParse);
|
||||
} else if (dateToParse instanceof Date) {
|
||||
} else if (isDate(dateToParse)) {
|
||||
formattedDate = DateTime.fromJSDate(dateToParse);
|
||||
} else if (typeof dateToParse === 'number') {
|
||||
} else if (isNumber(dateToParse)) {
|
||||
formattedDate = DateTime.fromMillis(dateToParse);
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { isDefined } from './isDefined';
|
||||
|
||||
export const isNonEmptyString = (
|
||||
probableNonEmptyString: string | undefined | null,
|
||||
): probableNonEmptyString is string => {
|
||||
if (
|
||||
isDefined(probableNonEmptyString) &&
|
||||
typeof probableNonEmptyString === 'string' &&
|
||||
probableNonEmptyString !== ''
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
@ -3922,6 +3922,11 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@sniptt/guards@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@sniptt/guards/-/guards-0.2.0.tgz#6b95d259bfd77c5db2945605e033cdcfcea97eba"
|
||||
integrity sha512-QNxknl5YcrxpLtP99iEvNEJRlfXtIfpkvcEWHJKD6bHUr93dsH6OZGUF6reVBddKs1ps44lndSMoDK2Dz0n6ZQ==
|
||||
|
||||
"@storybook/addon-actions@7.3.0", "@storybook/addon-actions@^7.0.22":
|
||||
version "7.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-7.3.0.tgz#fb1663a2810918a4147edebc5c7ff056d6ec7e94"
|
||||
|
||||
Reference in New Issue
Block a user