@@ -4,6 +4,8 @@ | |||
"main": "lib/index.js", | |||
"types": "lib/index.d.ts", | |||
"scripts": { | |||
"format": "prettier --write --list-different \"src/**/*.{ts,tsx}\"", | |||
"format-check": "prettier --list-different \"src/**/*.{ts,tsx}\"", | |||
"build": "yarn lint && yarn ts-check && vite build", | |||
"build:no-checks": "vite build", | |||
"build-release": "yarn install --immutable && yarn build", | |||
@@ -11,7 +13,7 @@ | |||
"lint-report-ci": "yarn install --immutable && eslint --ext js,ts,tsx -f json -o eslint-report/eslint-report.json src || yarn lint", | |||
"test": "jest", | |||
"ts-check": "tsc --noEmit", | |||
"validate-ci": "yarn install --immutable && yarn ts-check && yarn test --coverage --ci" | |||
"validate-ci": "yarn install --immutable && yarn ts-check && yarn format-check && yarn test --coverage --ci" | |||
}, | |||
"devDependencies": { | |||
"@babel/core": "7.23.2", | |||
@@ -44,6 +46,7 @@ | |||
"postcss": "8.4.31", | |||
"postcss-calc": "9.0.1", | |||
"postcss-custom-properties": "12.1.11", | |||
"prettier": "^3.1.0", | |||
"twin.macro": "3.4.0", | |||
"typescript": "5.2.2", | |||
"vite": "4.5.0", |
@@ -78,7 +78,9 @@ const accordionStyle = (props: ThemedProps) => css` | |||
border: ${themeBorder('default', 'buttonSecondaryBorder')(props)}; | |||
color: ${themeContrast('buttonSecondary')(props)}; | |||
background-color: ${themeColor('buttonSecondary')(props)}; | |||
transition: background-color 0.2s ease, outline 0.2s ease; | |||
transition: | |||
background-color 0.2s ease, | |||
outline 0.2s ease; | |||
& > button { | |||
${tw`sw-body-sm-highlight`} |
@@ -122,7 +122,7 @@ export function Breadcrumbs(props: Props) { | |||
overlay={modifiedChildren[index].props.children as React.ReactNode} | |||
> | |||
{modifiedChildren[index]} | |||
</Tooltip> | |||
</Tooltip>, | |||
); | |||
} else if ( | |||
isLastBreadcrumb || |
@@ -121,7 +121,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
k, | |||
}); | |||
}, | |||
[padding] | |||
[padding], | |||
); | |||
const boundNode = React.useCallback( | |||
@@ -130,7 +130,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
zoomRef.current = zoom().scaleExtent([1, 10]).on('zoom', zoomed); | |||
select(nodeRef.current).call(zoomRef.current); | |||
}, | |||
[zoomed] | |||
[zoomed], | |||
); | |||
const resetZoom = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => { | |||
@@ -150,7 +150,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
const dMaxX = maxX > x2 ? maxX - x2 : 0; | |||
return [dMinX, availableWidth - dMaxX]; | |||
}, | |||
[items] | |||
[items], | |||
); | |||
const getYRange = React.useCallback( | |||
@@ -162,7 +162,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
const dMaxY = maxY > y1 ? maxY - y1 : 0; | |||
return [availableHeight - dMaxY, dMinY]; | |||
}, | |||
[items] | |||
[items], | |||
); | |||
const getTicks = React.useCallback( | |||
@@ -176,7 +176,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
: TICKS_COUNT * zoomAmount; | |||
return scale.ticks(ticksCount); | |||
}, | |||
[transform] | |||
[transform], | |||
); | |||
const renderXGrid = React.useCallback( | |||
@@ -202,7 +202,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
return <g>{lines}</g>; | |||
}, | |||
[transform, displayXGrid] | |||
[transform, displayXGrid], | |||
); | |||
const renderYGrid = React.useCallback( | |||
@@ -228,7 +228,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
return <g>{lines}</g>; | |||
}, | |||
[displayYGrid, transform] | |||
[displayYGrid, transform], | |||
); | |||
const renderXTicks = React.useCallback( | |||
@@ -252,7 +252,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
return <g>{ticks}</g>; | |||
}, | |||
[displayXTicks, formatXTick, transform] | |||
[displayXTicks, formatXTick, transform], | |||
); | |||
const renderYTicks = React.useCallback( | |||
@@ -283,7 +283,7 @@ export function BubbleChart<T>(props: BubbleChartProps<T>) { | |||
return <g>{ticks}</g>; | |||
}, | |||
[displayYTicks, formatYTick, transform] | |||
[displayYTicks, formatYTick, transform], | |||
); | |||
const renderChart = (width: number) => { | |||
@@ -406,7 +406,7 @@ function Bubble<T>(props: BubbleProps<T>) { | |||
event.preventDefault(); | |||
onClick?.(data); | |||
}, | |||
[data, onClick] | |||
[data, onClick], | |||
); | |||
const circle = ( |
@@ -70,7 +70,7 @@ export function CodeSnippet(props: Props) { | |||
'code-snippet-simple-oneline': isSimpleOneLine, | |||
}, | |||
className, | |||
'fs-mask' | |||
'fs-mask', | |||
)} | |||
> | |||
{!noCopy && copyButton} |
@@ -107,7 +107,10 @@ const buttonIconStyle = (props: ThemedProps & { size: InteractiveIconSize }) => | |||
text-decoration: none; | |||
color: var(--color); | |||
background-color: var(--background); | |||
transition: background-color 0.2s ease, outline 0.2s ease, color 0.2s ease; | |||
transition: | |||
background-color 0.2s ease, | |||
outline 0.2s ease, | |||
color 0.2s ease; | |||
${tw`sw-inline-flex sw-items-center sw-justify-center`} | |||
${tw`sw-cursor-pointer`} | |||
@@ -158,11 +161,10 @@ export const InteractiveIcon: React.FC<React.PropsWithChildren<InteractiveIconPr | |||
--focus: ${themeColor('interactiveIconFocus', OPACITY_20_PERCENT)}; | |||
`; | |||
export const DiscreetInteractiveIcon: React.FC< | |||
React.PropsWithChildren<InteractiveIconProps> | |||
> = styled(InteractiveIcon)` | |||
--color: ${themeColor('discreetInteractiveIcon')}; | |||
`; | |||
export const DiscreetInteractiveIcon: React.FC<React.PropsWithChildren<InteractiveIconProps>> = | |||
styled(InteractiveIcon)` | |||
--color: ${themeColor('discreetInteractiveIcon')}; | |||
`; | |||
export const DestructiveIcon: React.FC<React.PropsWithChildren<InteractiveIconProps>> = styled( | |||
InteractiveIconBase, | |||
@@ -174,14 +176,13 @@ export const DestructiveIcon: React.FC<React.PropsWithChildren<InteractiveIconPr | |||
--focus: ${themeColor('destructiveIconFocus', OPACITY_20_PERCENT)}; | |||
`; | |||
export const DismissProductNewsIcon: React.FC< | |||
React.PropsWithChildren<InteractiveIconProps> | |||
> = styled(InteractiveIcon)` | |||
--background: ${themeColor('productNews')}; | |||
--backgroundHover: ${themeColor('productNewsHover')}; | |||
--color: ${themeContrast('productNews')}; | |||
--colorHover: ${themeContrast('productNewsHover')}; | |||
--focus: ${themeColor('interactiveIconFocus', OPACITY_20_PERCENT)}; | |||
export const DismissProductNewsIcon: React.FC<React.PropsWithChildren<InteractiveIconProps>> = | |||
styled(InteractiveIcon)` | |||
--background: ${themeColor('productNews')}; | |||
--backgroundHover: ${themeColor('productNewsHover')}; | |||
--color: ${themeContrast('productNews')}; | |||
--colorHover: ${themeContrast('productNewsHover')}; | |||
--focus: ${themeColor('interactiveIconFocus', OPACITY_20_PERCENT)}; | |||
height: 28px; | |||
`; | |||
height: 28px; | |||
`; |
@@ -34,7 +34,7 @@ interface Props { | |||
function InternalLocationMarker( | |||
{ className, onClick, text, selected }: Props, | |||
ref: LegacyRef<HTMLDivElement> | |||
ref: LegacyRef<HTMLDivElement>, | |||
) { | |||
return ( | |||
<StyledMarker |
@@ -58,7 +58,7 @@ export function NavBarTabLink(props: NavBarTabLinkProps) { | |||
classNames( | |||
'sw-flex sw-items-center', | |||
{ active: isDefined(active) ? active : isActive }, | |||
className | |||
className, | |||
) | |||
} | |||
{...linkProps} |
@@ -60,7 +60,7 @@ function NavLinkWithRef(props: NavLinkProps, ref: React.ForwardedRef<HTMLAnchorE | |||
onClick(event); | |||
} | |||
}, | |||
[onClick, blurAfterClick, preventDefault, stopPropagation, disabled] | |||
[onClick, blurAfterClick, preventDefault, stopPropagation, disabled], | |||
); | |||
return ( |
@@ -68,7 +68,7 @@ export function SelectionCard(props: SelectionCardProps) { | |||
disabled, | |||
selected, | |||
}, | |||
className | |||
className, | |||
)} | |||
onClick={isActionable && !disabled && !selected ? onClick : undefined} | |||
role={isActionable ? 'radio' : 'presentation'} |
@@ -128,7 +128,7 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
// position (which is no longer correct). | |||
this.positionTooltip(); | |||
} | |||
} | |||
}, | |||
); | |||
} | |||
} | |||
@@ -195,7 +195,7 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
adjustArrowPosition = ( | |||
placement: PopupPlacement, | |||
{ leftFix, topFix, height, width }: Measurements | |||
{ leftFix, topFix, height, width }: Measurements, | |||
) => { | |||
switch (placement) { | |||
case PopupPlacement.Left: | |||
@@ -223,7 +223,7 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
const { height, left, leftFix, top, topFix, width } = popupPositioning( | |||
toggleNode, | |||
this.tooltipNode, | |||
this.getPlacement() | |||
this.getPlacement(), | |||
); | |||
// save width and height (and later set in `render`) to avoid resizing the popup element, | |||
@@ -253,18 +253,21 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
}; | |||
handlePointerEnter = () => { | |||
this.mouseEnterTimeout = window.setTimeout(() => { | |||
// for some reason even after the `this.mouseEnterTimeout` is cleared, it still triggers | |||
// to workaround this issue, check that its value is not `undefined` | |||
// (if it's `undefined`, it means the timer has been reset) | |||
if ( | |||
this.mounted && | |||
this.props.visible === undefined && | |||
this.mouseEnterTimeout !== undefined | |||
) { | |||
this.setState({ visible: true }); | |||
} | |||
}, (this.props.mouseEnterDelay ?? 0) * MILLISECONDS_IN_A_SECOND); | |||
this.mouseEnterTimeout = window.setTimeout( | |||
() => { | |||
// for some reason even after the `this.mouseEnterTimeout` is cleared, it still triggers | |||
// to workaround this issue, check that its value is not `undefined` | |||
// (if it's `undefined`, it means the timer has been reset) | |||
if ( | |||
this.mounted && | |||
this.props.visible === undefined && | |||
this.mouseEnterTimeout !== undefined | |||
) { | |||
this.setState({ visible: true }); | |||
} | |||
}, | |||
(this.props.mouseEnterDelay ?? 0) * MILLISECONDS_IN_A_SECOND, | |||
); | |||
if (this.props.onShow) { | |||
this.props.onShow(); | |||
@@ -278,11 +281,14 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
} | |||
if (!this.mouseIn) { | |||
this.mouseLeaveTimeout = window.setTimeout(() => { | |||
if (this.mounted && this.props.visible === undefined && !this.mouseIn) { | |||
this.setState({ visible: false }); | |||
} | |||
}, (this.props.mouseLeaveDelay ?? 0) * MILLISECONDS_IN_A_SECOND); | |||
this.mouseLeaveTimeout = window.setTimeout( | |||
() => { | |||
if (this.mounted && this.props.visible === undefined && !this.mouseIn) { | |||
this.setState({ visible: false }); | |||
} | |||
}, | |||
(this.props.mouseLeaveDelay ?? 0) * MILLISECONDS_IN_A_SECOND, | |||
); | |||
if (this.props.onHide) { | |||
this.props.onHide(); |
@@ -29,13 +29,13 @@ it('should render with close button', async () => { | |||
expect( | |||
screen.getByRole('button', { | |||
name: 'dismiss', | |||
}) | |||
}), | |||
).toBeVisible(); | |||
await user.click( | |||
screen.getByRole('button', { | |||
name: 'dismiss', | |||
}) | |||
}), | |||
); | |||
expect(onDismiss).toHaveBeenCalledTimes(1); | |||
@@ -45,6 +45,6 @@ function setupWithProps(props: Partial<FCProps<typeof Banner>> = {}) { | |||
return renderWithContext( | |||
<Banner {...props} variant="warning"> | |||
<Note className="sw-body-sm">{props.children ?? 'Test Message'}</Note> | |||
</Banner> | |||
</Banner>, | |||
); | |||
} |
@@ -58,6 +58,6 @@ function renderChart(overrides: Partial<FCProps<typeof BarChart>> = {}) { | |||
onBarClick={jest.fn()} | |||
width={200} | |||
{...overrides} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -33,7 +33,7 @@ it('should display three breadcrumbs correctly', () => { | |||
<HoverLink to="/first">first</HoverLink> | |||
<HoverLink to="/second">second</HoverLink> | |||
<HoverLink to="/third">third</HoverLink> | |||
</BreadcrumbsFullWidth> | |||
</BreadcrumbsFullWidth>, | |||
); | |||
expect(screen.getAllByRole('link').length).toBe(3); |
@@ -86,6 +86,6 @@ function renderBubbleChart(props: Partial<FCProps<typeof BubbleChart>> = {}) { | |||
]} | |||
padding={[0, 0, 0, 0]} | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -35,7 +35,7 @@ it('renders card correctly with classNames', () => { | |||
render( | |||
<Card className="sw-bg-black sw-border-8" role="tabpanel"> | |||
Hello | |||
</Card> | |||
</Card>, | |||
); | |||
const cardContent = screen.getByText('Hello'); | |||
expect(cardContent).toHaveClass('sw-bg-black sw-border-8'); | |||
@@ -46,7 +46,7 @@ it('renders grey card correctly with classNames', () => { | |||
render( | |||
<GreyCard className="sw-bg-black sw-border-8" role="tabpanel"> | |||
Hello | |||
</GreyCard> | |||
</GreyCard>, | |||
); | |||
const cardContent = screen.getByText('Hello'); | |||
expect(cardContent).toHaveClass('sw-bg-black sw-border-8'); |
@@ -46,6 +46,6 @@ function setupWithProps(props: Partial<FCProps<typeof CodeSnippet>> = {}) { | |||
return renderWithContext( | |||
<HelmetProvider> | |||
<CodeSnippet snippet={'foo\nbar'} {...props} /> | |||
</HelmetProvider> | |||
</HelmetProvider>, | |||
); | |||
} |
@@ -29,7 +29,7 @@ it('renders correctly with no code', () => { | |||
<p>There's no code here.</p> | |||
`} | |||
/> | |||
/>, | |||
); | |||
// eslint-disable-next-line testing-library/no-node-access | |||
@@ -45,7 +45,7 @@ it('renders correctly with code', () => { | |||
<p>There's some <code>"code"</code> here.</p> | |||
`} | |||
language="typescript" | |||
/> | |||
/>, | |||
); | |||
// eslint-disable-next-line testing-library/no-node-access | |||
@@ -61,7 +61,7 @@ it('handles html code snippets', () => { | |||
htmlAsString={ | |||
'\u003ch4\u003eNoncompliant code example\u003c/h4\u003e\n\u003cpre data-diff-id\u003d"1" data-diff-type\u003d"noncompliant"\u003e\npublic void Method(MyObject myObject)\n{\n if (myObject is null)\n {\n new MyObject(); // Noncompliant\n }\n\n if (myObject.IsCorrupted)\n {\n new ArgumentException($"{nameof(myObject)} is corrupted"); // Noncompliant\n }\n\n // ...\n}\n\u003c/pre\u003e\n\u003ch4\u003eCompliant solution\u003c/h4\u003e\n\u003cpre data-diff-id\u003d"1" data-diff-type\u003d"compliant"\u003e\npublic void Method(MyObject myObject)\n{\n if (myObject is null)\n {\n myObject \u003d new MyObject(); // Compliant\n }\n\n if (myObject.IsCorrupted)\n {\n throw new ArgumentException($"{nameof(myObject)} is corrupted"); // Compliant\n }\n\n // ...\n}\n\u003c/pre\u003e' | |||
} | |||
/> | |||
/>, | |||
); | |||
expect(container.querySelectorAll('pre')).toHaveLength(2); |
@@ -57,7 +57,7 @@ it('menu items should work with tooltips', async () => { | |||
<ItemButton onClick={jest.fn()}>button</ItemButton> | |||
</Tooltip>, | |||
{}, | |||
{ delay: null } | |||
{ delay: null }, | |||
); | |||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); | |||
@@ -103,6 +103,6 @@ function renderDropdownMenu() { | |||
<ItemRadioButton checked={false} onCheck={noop} value="radios"> | |||
Radio item | |||
</ItemRadioButton> | |||
</DropdownMenu> | |||
</DropdownMenu>, | |||
); | |||
} |
@@ -35,7 +35,7 @@ it.each(['A', 'B', 'C', 'D', 'E', 'F'])( | |||
(variant: DuplicationLabel) => { | |||
setupWithProps({ rating: variant }); | |||
expect(screen.getByRole('img', { hidden: true })).toMatchSnapshot(); | |||
} | |||
}, | |||
); | |||
function setupWithProps(props: Partial<FCProps<typeof DuplicationsIndicator>> = {}) { |
@@ -33,11 +33,11 @@ it('should render correctly expanded', () => { | |||
function renderExecutionFlowAccordion( | |||
props: Partial<FCProps<typeof ExecutionFlowAccordion>> = {}, | |||
children?: React.ReactNode | |||
children?: React.ReactNode, | |||
) { | |||
return render( | |||
<ExecutionFlowAccordion header="header" id="id" {...props}> | |||
{children} | |||
</ExecutionFlowAccordion> | |||
</ExecutionFlowAccordion>, | |||
); | |||
} |
@@ -69,6 +69,6 @@ function renderComponent({ children, ...props }: Partial<FacetBoxProps> = {}) { | |||
return renderWithContext( | |||
<FacetBox name="Test FacetBox" {...props}> | |||
{children} | |||
</FacetBox> | |||
</FacetBox>, | |||
); | |||
} |
@@ -70,6 +70,6 @@ it('should not add an aria label if the name is not a string', () => { | |||
function renderComponent(props: Partial<FacetItemProps> = {}) { | |||
return render( | |||
<BaseFacetItem name="Test facet item" onClick={jest.fn()} value="Value" {...props} /> | |||
<BaseFacetItem name="Test facet item" onClick={jest.fn()} value="Value" {...props} />, | |||
); | |||
} |
@@ -45,6 +45,6 @@ it('should toggle favorite', async () => { | |||
function renderFavoriteButton(props: Partial<FCProps<typeof FavoriteButton>> = {}) { | |||
return render( | |||
<FavoriteButton favorite overlay="label-info" toggleFavorite={jest.fn()} {...props} /> | |||
<FavoriteButton favorite overlay="label-info" toggleFavorite={jest.fn()} {...props} />, | |||
); | |||
} |
@@ -32,7 +32,7 @@ it.each(Object.values(HotspotRatingEnum))( | |||
(rating) => { | |||
renderHotspotRating(rating, 'label'); | |||
expect(screen.getByLabelText('label')).toMatchSnapshot(); | |||
} | |||
}, | |||
); | |||
function renderHotspotRating(rating?: HotspotRatingEnum, label?: string) { |
@@ -27,7 +27,7 @@ it('should render correctly when covered', () => { | |||
it('should render correctly when uncovered', () => { | |||
expect( | |||
setupWithProps({ lineNumber: 16, coverageStatus: 'uncovered' }).container | |||
setupWithProps({ lineNumber: 16, coverageStatus: 'uncovered' }).container, | |||
).toMatchSnapshot(); | |||
}); | |||
@@ -36,7 +36,7 @@ it('should render correctly when partially covered without conditions', () => { | |||
setupWithProps({ | |||
lineNumber: 16, | |||
coverageStatus: 'partially-covered', | |||
}).container | |||
}).container, | |||
).toMatchSnapshot(); | |||
}); | |||
@@ -45,7 +45,7 @@ it('should render correctly when partially covered with 5/10 conditions', () => | |||
setupWithProps({ | |||
lineNumber: 16, | |||
coverageStatus: 'partially-covered', | |||
}).container | |||
}).container, | |||
).toMatchSnapshot(); | |||
}); | |||
@@ -41,6 +41,6 @@ it('should be clickable when onIssueSelect is provided', async () => { | |||
function setupWithProps(props?: Partial<FCProps<typeof LineFinding>>) { | |||
return render( | |||
<LineFinding issueKey="key" message="message" onIssueSelect={jest.fn()} {...props} /> | |||
<LineFinding issueKey="key" message="message" onIssueSelect={jest.fn()} {...props} />, | |||
); | |||
} |
@@ -40,6 +40,6 @@ function setupWithProps(props: Partial<FCProps<typeof LineNumber>> = {}) { | |||
lineNumber={16} | |||
popup={<div>Popup</div>} | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -34,7 +34,7 @@ it('should properly setup css grid columns', () => { | |||
}); | |||
expect( | |||
setupWithProps({ displayCoverage: false, displaySCM: false, duplicationsCount: 0 }).container | |||
.firstChild | |||
.firstChild, | |||
).toHaveStyle({ '--columns': '44px 26px 1fr' }); | |||
}); | |||
@@ -45,12 +45,6 @@ it('should set a highlighted background color in css props', () => { | |||
function setupWithProps(props: Partial<FCProps<typeof LineWrapper>> = {}) { | |||
return render( | |||
<LineWrapper | |||
displayCoverage | |||
displaySCM | |||
duplicationsCount={2} | |||
highlighted={false} | |||
{...props} | |||
/> | |||
<LineWrapper displayCoverage displaySCM duplicationsCount={2} highlighted={false} {...props} />, | |||
); | |||
} |
@@ -49,13 +49,13 @@ it('should render the logo', () => { | |||
function setupWithProps( | |||
props: FCProps<typeof MainAppBar> = { | |||
Logo: () => <img alt="logo" src="http://example.com/logo.png" />, | |||
} | |||
}, | |||
) { | |||
return render( | |||
<MemoryRouter initialEntries={['/']}> | |||
<Routes> | |||
<Route element={<MainAppBar {...props} />} path="/" /> | |||
</Routes> | |||
</MemoryRouter> | |||
</MemoryRouter>, | |||
); | |||
} |
@@ -28,7 +28,7 @@ it('should render default', () => { | |||
render( | |||
<MainMenuItem> | |||
<a>Hi</a> | |||
</MainMenuItem> | |||
</MainMenuItem>, | |||
); | |||
expect(screen.getByText('Hi')).toHaveStyle({ | |||
@@ -41,7 +41,7 @@ it('should render active link', () => { | |||
render( | |||
<MainMenuItem> | |||
<a className="active">Hi</a> | |||
</MainMenuItem> | |||
</MainMenuItem>, | |||
); | |||
expect(screen.getByText('Hi')).toHaveStyle({ | |||
@@ -54,7 +54,7 @@ it('should render hovered link', () => { | |||
render( | |||
<MainMenuItem> | |||
<a className="hover">Hi</a> | |||
</MainMenuItem> | |||
</MainMenuItem>, | |||
); | |||
expect(screen.getByText('Hi')).toHaveStyle({ |
@@ -37,7 +37,7 @@ describe('NewNavBarTabs', () => { | |||
return renderWithRouter( | |||
<NavBarTabs> | |||
<NavBarTabLink text="test" to="/summary/new_code" /> | |||
</NavBarTabs> | |||
</NavBarTabs>, | |||
); | |||
} | |||
}); |
@@ -60,7 +60,7 @@ it('should stop propagation when stopPropagation is true', async () => { | |||
const { user } = setupWithMemoryRouter( | |||
<button onClick={buttonOnClick} type="button"> | |||
<NavLink stopPropagation to="/second" /> | |||
</button> | |||
</button>, | |||
); | |||
await user.click(screen.getByRole('link')); | |||
@@ -71,7 +71,7 @@ it('should stop propagation when stopPropagation is true', async () => { | |||
it('should call onClick when one is passed', async () => { | |||
const onClick = jest.fn(); | |||
const { user } = setupWithMemoryRouter( | |||
<NavLink onClick={onClick} stopPropagation to="/second" /> | |||
<NavLink onClick={onClick} stopPropagation to="/second" />, | |||
); | |||
await user.click(screen.getByRole('link')); | |||
@@ -108,6 +108,6 @@ const setupWithMemoryRouter = (component: JSX.Element, initialEntries = ['/initi | |||
/> | |||
<Route element={<ShowPath />} path="/second" /> | |||
</Routes> | |||
</MemoryRouter> | |||
</MemoryRouter>, | |||
); | |||
}; |
@@ -44,7 +44,7 @@ it.each([ | |||
setupWithProps({ status, size }); | |||
expect(screen.getByRole('status')).toHaveAttribute('width', SIZE_VS_WIDTH[size]); | |||
} | |||
}, | |||
); | |||
it('should display tooltip', () => { |
@@ -74,6 +74,6 @@ function renderSelectionCard(props: Partial<FCProps<typeof SelectionCard>> = {}) | |||
title="Selection Card" | |||
titleInfo="info" | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -68,38 +68,38 @@ it('check that the html structure and style is correct for a regular table', () | |||
// Rows should have accessible attributes | |||
expect( | |||
screen.getByRole('row', { name: 'ContentCellHeader NumericalCellHeader CheckboxCellHeader' }) | |||
screen.getByRole('row', { name: 'ContentCellHeader NumericalCellHeader CheckboxCellHeader' }), | |||
).toBeInTheDocument(); | |||
expect( | |||
screen.getByRole('row', { | |||
name: 'ContentCell 1 NumericalCell 1 CheckboxCell 1', | |||
}) | |||
}), | |||
).toBeInTheDocument(); | |||
expect( | |||
screen.getByRole('row', { | |||
name: 'ContentCell 1 NumericalCell 1 CheckboxCell 1', | |||
}) | |||
}), | |||
).not.toHaveAttribute('aria-selected'); | |||
expect( | |||
screen.getByRole('row', { | |||
selected: true, | |||
name: 'ContentCell 2 NumericalCell 2 CheckboxCell 2', | |||
}) | |||
}), | |||
).toBeInTheDocument(); | |||
expect( | |||
screen.getByRole('row', { | |||
name: 'NumericalCell 4 CheckboxCell 4', | |||
}) | |||
}), | |||
).toBeInTheDocument(); | |||
// Cells should have accessible attributes | |||
expect(screen.getByRole('cell', { name: 'NumericalCell 4' })).toHaveAttribute( | |||
'aria-colindex', | |||
'2' | |||
'2', | |||
); | |||
expect(screen.getByRole('cell', { name: 'CheckboxCell 4' })).toHaveAttribute( | |||
'aria-colindex', | |||
'3' | |||
'3', | |||
); | |||
}); | |||
@@ -57,7 +57,7 @@ it('should work in tablist mode', () => { | |||
expect(screen.getAllByRole('tab')).toHaveLength(3); | |||
expect(screen.getByRole('tab', { name: 'second' })).toHaveAttribute( | |||
'aria-controls', | |||
getTabPanelId(2) | |||
getTabPanelId(2), | |||
); | |||
}); | |||
@@ -49,7 +49,7 @@ describe('TooltipInner', () => { | |||
const onPointerLeave = jest.fn(); | |||
const { user } = setupWithProps( | |||
{ onHide, onShow }, | |||
<div onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave} role="note" /> | |||
<div onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave} role="note" />, | |||
); | |||
await user.hover(screen.getByRole('note')); | |||
@@ -93,12 +93,12 @@ describe('TooltipInner', () => { | |||
function setupWithProps( | |||
props: Partial<TooltipInner['props']> = {}, | |||
children = <div role="note" /> | |||
children = <div role="note" />, | |||
) { | |||
return render( | |||
<TooltipInner mouseLeaveDelay={0} overlay={<span id="overlay" />} {...props}> | |||
{children} | |||
</TooltipInner> | |||
</TooltipInner>, | |||
); | |||
} | |||
}); | |||
@@ -124,12 +124,12 @@ describe('Tooltip', () => { | |||
function setupWithProps( | |||
props: Partial<FCProps<typeof Tooltip>> = {}, | |||
children = <div role="note" /> | |||
children = <div role="note" />, | |||
) { | |||
return render( | |||
<Tooltip overlay={<span id="overlay" />} {...props}> | |||
{children} | |||
</Tooltip> | |||
</Tooltip>, | |||
); | |||
} | |||
}); |
@@ -60,6 +60,6 @@ it('should render correctly and forward click event', async () => { | |||
function renderTreeMap(props: Partial<TreeMapProps<unknown>>) { | |||
return render( | |||
<TreeMap height={100} items={[]} onRectangleClick={jest.fn()} width={100} {...props} /> | |||
<TreeMap height={100} items={[]} onRectangleClick={jest.fn()} width={100} {...props} />, | |||
); | |||
} |
@@ -33,6 +33,6 @@ function renderTutorialStep() { | |||
return render( | |||
<TutorialStepList> | |||
<TutorialStep title="This is title">These are children</TutorialStep> | |||
</TutorialStepList> | |||
</TutorialStepList>, | |||
); | |||
} |
@@ -36,7 +36,7 @@ it('should be able to render with hash only', () => { | |||
setupWithProps({ hash: '7daf6c79d4802916d83f6266e24850af' }); | |||
expect(screen.getByRole('img')).toHaveAttribute( | |||
'src', | |||
'http://example.com/7daf6c79d4802916d83f6266e24850af.jpg?s=48' | |||
'http://example.com/7daf6c79d4802916d83f6266e24850af.jpg?s=48', | |||
); | |||
}); | |||
@@ -64,6 +64,6 @@ it('should display organization avatar correctly', () => { | |||
function setupWithProps(props: Partial<FCProps<typeof Avatar>> = {}) { | |||
return render( | |||
<Avatar enableGravatar gravatarServerUrl={gravatarServerUrl} name="foo" {...props} /> | |||
<Avatar enableGravatar gravatarServerUrl={gravatarServerUrl} name="foo" {...props} />, | |||
); | |||
} |
@@ -112,7 +112,9 @@ export const buttonStyle = (props: ThemedProps) => css` | |||
border: var(--border); | |||
color: var(--color); | |||
background-color: var(--background); | |||
transition: background-color 0.2s ease, outline 0.2s ease; | |||
transition: | |||
background-color 0.2s ease, | |||
outline 0.2s ease; | |||
${tw`sw-inline-flex sw-items-center`} | |||
${tw`sw-h-control`} |
@@ -33,7 +33,7 @@ interface Props { | |||
function LineFindingFunc( | |||
{ message, issueKey, selected = true, className, onIssueSelect }: Props, | |||
ref: Ref<HTMLButtonElement> | |||
ref: Ref<HTMLButtonElement>, | |||
) { | |||
return ( | |||
<LineFindingStyled |
@@ -37,7 +37,7 @@ export function LineIssuePointer({ issueFindingRef }: Props) { | |||
if (pointerRef.current && issueFindingRef?.current) { | |||
setDistance( | |||
issueFindingRef.current.getBoundingClientRect().top - | |||
pointerRef.current.getBoundingClientRect().bottom | |||
pointerRef.current.getBoundingClientRect().bottom, | |||
); | |||
} | |||
}, [pointerRef, issueFindingRef]); |
@@ -35,7 +35,7 @@ interface Props { | |||
function LineMarkerFunc( | |||
{ hideLocationIndex, index, leading, message, onLocationSelect, selected }: Props, | |||
ref: Ref<HTMLElement> | |||
ref: Ref<HTMLElement>, | |||
) { | |||
const element = useRef<HTMLDivElement | null>(null); | |||
const elementMessage = useRef<HTMLDivElement | null>(null); |
@@ -26,7 +26,7 @@ it('should render custom icon correctly', () => { | |||
render( | |||
<CustomIcon> | |||
<path d="test" /> | |||
</CustomIcon> | |||
</CustomIcon>, | |||
); | |||
expect(screen.queryByRole('img')).not.toBeInTheDocument(); | |||
@@ -37,7 +37,7 @@ it('should not be hidden when aria-label is set', () => { | |||
render( | |||
<CustomIcon aria-label="test"> | |||
<path d="test" /> | |||
</CustomIcon> | |||
</CustomIcon>, | |||
); | |||
expect(screen.getByRole('img')).toBeVisible(); |
@@ -32,14 +32,14 @@ type SearchSelectProps< | |||
V, | |||
Option extends LabelValueSelectOption<V>, | |||
IsMulti extends boolean = false, | |||
Group extends GroupBase<Option> = GroupBase<Option> | |||
Group extends GroupBase<Option> = GroupBase<Option>, | |||
> = SelectProps<V, Option, IsMulti, Group> & AsyncProps<Option, IsMulti, Group>; | |||
export function SearchSelect< | |||
V, | |||
Option extends LabelValueSelectOption<V>, | |||
IsMulti extends boolean = false, | |||
Group extends GroupBase<Option> = GroupBase<Option> | |||
Group extends GroupBase<Option> = GroupBase<Option>, | |||
>({ | |||
size = 'full', | |||
selectRef, | |||
@@ -57,7 +57,7 @@ export function SearchSelect< | |||
control: ({ isDisabled }) => | |||
classNames( | |||
'sw-border-0 sw-rounded-2 sw-outline-none sw-shadow-none', | |||
isDisabled && 'sw-pointer-events-none sw-cursor-not-allowed' | |||
isDisabled && 'sw-pointer-events-none sw-cursor-not-allowed', | |||
), | |||
indicatorsContainer: () => 'sw-hidden', | |||
input: () => `sw-flex sw-w-full sw-p-0 sw-m-0`, | |||
@@ -85,7 +85,7 @@ export function SearchSelectInput< | |||
V, | |||
Option extends LabelValueSelectOption<V>, | |||
IsMulti extends boolean = false, | |||
Group extends GroupBase<Option> = GroupBase<Option> | |||
Group extends GroupBase<Option> = GroupBase<Option>, | |||
>(props: InputProps<Option, IsMulti, Group>) { | |||
const { | |||
selectProps: { placeholder, isLoading, inputValue, minLength }, |
@@ -54,6 +54,6 @@ function setupWithProps(props: Partial<FCProps<typeof DiscreetSelect>>) { | |||
setValue={jest.fn()} | |||
value="foo" | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -36,11 +36,11 @@ it('should render with required and description', () => { | |||
function renderFormField( | |||
props: Partial<FCProps<typeof FormField>> = {}, | |||
children: any = <div>Fake input</div> | |||
children: any = <div>Fake input</div>, | |||
) { | |||
return render( | |||
<FormField htmlFor="input" label="Hello" {...props}> | |||
{children} | |||
</FormField> | |||
</FormField>, | |||
); | |||
} |
@@ -83,6 +83,6 @@ function setupWithProps(props: Partial<FCProps<typeof InputSearch>> = {}) { | |||
searchInputAriaLabel="" | |||
value="foo" | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -109,6 +109,6 @@ function renderMultiselect(props: Partial<MultiSelectMenu['props']> = {}) { | |||
searchInputAriaLabel="search" | |||
selectedElements={[]} | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -57,6 +57,6 @@ function setupWithProps(props?: Partial<FCProps<typeof RadioButton>>) { | |||
return render( | |||
<RadioButton checked={false} onCheck={jest.fn()} value="value" {...props}> | |||
foo | |||
</RadioButton> | |||
</RadioButton>, | |||
); | |||
} |
@@ -52,6 +52,6 @@ function setupWithProps(props: Partial<FCProps<typeof InputSearch>> = {}) { | |||
searchInputAriaLabel="" | |||
value="foo" | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -31,7 +31,7 @@ const defaultOptions = [ | |||
const loadOptions = ( | |||
query: string, | |||
cb: (options: Array<LabelValueSelectOption<string>>) => void | |||
cb: (options: Array<LabelValueSelectOption<string>>) => void, | |||
) => { | |||
cb(defaultOptions.filter((o) => o.label.includes(query))); | |||
}; | |||
@@ -94,6 +94,6 @@ function renderSearchSelectDropdown(props: Partial<FCProps<typeof SearchSelectDr | |||
loadOptions={loadOptions} | |||
placeholder="search for things" | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} |
@@ -27,7 +27,7 @@ it('renders correctly', () => { | |||
<NumberedList> | |||
<NumberedListItem>First item</NumberedListItem> | |||
<NumberedListItem>Second item</NumberedListItem> | |||
</NumberedList> | |||
</NumberedList>, | |||
); | |||
expect(screen.getAllByRole('listitem')).toHaveLength(2); | |||
}); |
@@ -27,7 +27,7 @@ it('renders correctly', () => { | |||
<UnorderedList> | |||
<ListItem>First item</ListItem> | |||
<ListItem>Second item</ListItem> | |||
</UnorderedList> | |||
</UnorderedList>, | |||
); | |||
expect(screen.getAllByRole('listitem')).toHaveLength(2); | |||
}); |
@@ -68,7 +68,7 @@ function setupPredefinedContent(props: Partial<PropsWithSections> = {}) { | |||
onClose={jest.fn()} | |||
secondaryButtonLabel="Close" | |||
{...props} | |||
/> | |||
/>, | |||
); | |||
} | |||
@@ -76,7 +76,7 @@ function setupLooseContent(props: Partial<PropsWithChildren> = {}, children = <d | |||
return renderWithContext( | |||
<Modal onClose={jest.fn()} {...props}> | |||
{children} | |||
</Modal> | |||
</Modal>, | |||
); | |||
} | |||
@@ -85,6 +85,6 @@ function setupLooseContentWithMultipleChildren(props: Partial<PropsWithChildren> | |||
<Modal onClose={jest.fn()} {...props}> | |||
<div>Hello there!</div> | |||
<div>How are you?</div> | |||
</Modal> | |||
</Modal>, | |||
); | |||
} |
@@ -70,6 +70,6 @@ function setupWithProps(props: Partial<FCProps<typeof SubnavigationAccordion>> = | |||
return render( | |||
<SubnavigationAccordion header="Header" id="test" {...props}> | |||
<span>Foo</span> | |||
</SubnavigationAccordion> | |||
</SubnavigationAccordion>, | |||
); | |||
} |
@@ -34,6 +34,6 @@ function setupWithProps(props: Partial<FCProps<typeof SubnavigationItem>> = {}) | |||
return render( | |||
<SubnavigationItem active={false} onClick={jest.fn()} value="foo" {...props}> | |||
<button type="button">Foo</button> | |||
</SubnavigationItem> | |||
</SubnavigationItem>, | |||
); | |||
} |
@@ -33,13 +33,13 @@ describe('getProp', () => { | |||
describe('themeColor', () => { | |||
it('should work for light theme', () => { | |||
expect(ThemeHelper.themeColor('backgroundPrimary')({ theme: lightTheme })).toEqual( | |||
'rgb(252,252,253)' | |||
'rgb(252,252,253)', | |||
); | |||
}); | |||
it('should work with a theme-defined opacity', () => { | |||
expect(ThemeHelper.themeColor('bannerIconHover')({ theme: lightTheme })).toEqual( | |||
'rgba(217,45,32,0.2)' | |||
'rgba(217,45,32,0.2)', | |||
); | |||
}); | |||
@@ -53,13 +53,13 @@ describe('themeColor', () => { | |||
ThemeHelper.themeColor(ThemeHelper.themeContrast('backgroundPrimary')({ theme: lightTheme }))( | |||
{ | |||
theme: lightTheme, | |||
} | |||
) | |||
}, | |||
), | |||
).toEqual('rgb(8,9,12)'); | |||
expect( | |||
ThemeHelper.themeColor(ThemeHelper.themeAvatarColor('luke')({ theme: lightTheme }))({ | |||
theme: lightTheme, | |||
}) | |||
}), | |||
).toEqual('rgb(209,215,254)'); | |||
}); | |||
}); | |||
@@ -67,7 +67,7 @@ describe('themeColor', () => { | |||
describe('themeContrast', () => { | |||
it('should work for light theme', () => { | |||
expect(ThemeHelper.themeContrast('backgroundPrimary')({ theme: lightTheme })).toEqual( | |||
'rgb(8,9,12)' | |||
'rgb(8,9,12)', | |||
); | |||
}); | |||
@@ -75,19 +75,19 @@ describe('themeContrast', () => { | |||
expect(ThemeHelper.themeContrast('var(--test)')({ theme: lightTheme })).toEqual('var(--test)'); | |||
expect(ThemeHelper.themeContrast('rgb(0,0,0)')({ theme: lightTheme })).toEqual('rgb(0,0,0)'); | |||
expect(ThemeHelper.themeContrast('rgba(0,0,0,1)')({ theme: lightTheme })).toEqual( | |||
'rgba(0,0,0,1)' | |||
'rgba(0,0,0,1)', | |||
); | |||
expect( | |||
ThemeHelper.themeContrast(ThemeHelper.themeColor('backgroundPrimary')({ theme: lightTheme }))( | |||
{ | |||
theme: lightTheme, | |||
} | |||
) | |||
}, | |||
), | |||
).toEqual('rgb(252,252,253)'); | |||
expect( | |||
ThemeHelper.themeContrast(ThemeHelper.themeAvatarColor('luke')({ theme: lightTheme }))({ | |||
theme: lightTheme, | |||
}) | |||
}), | |||
).toEqual('rgb(209,215,254)'); | |||
expect( | |||
ThemeHelper.themeContrast('backgroundPrimary')({ | |||
@@ -95,7 +95,7 @@ describe('themeContrast', () => { | |||
...lightTheme, | |||
contrasts: { ...lightTheme.contrasts, backgroundPrimary: 'inherit' }, | |||
}, | |||
}) | |||
}), | |||
).toEqual('inherit'); | |||
}); | |||
}); | |||
@@ -106,17 +106,17 @@ describe('themeBorder', () => { | |||
}); | |||
it('should allow to override the color of the border', () => { | |||
expect(ThemeHelper.themeBorder('focus', 'primaryLight')({ theme: lightTheme })).toEqual( | |||
'4px solid rgba(123,135,217,0.2)' | |||
'4px solid rgba(123,135,217,0.2)', | |||
); | |||
}); | |||
it('should allow to override the opacity of the border', () => { | |||
expect(ThemeHelper.themeBorder('focus', undefined, 0.5)({ theme: lightTheme })).toEqual( | |||
'4px solid rgba(197,205,223,0.5)' | |||
'4px solid rgba(197,205,223,0.5)', | |||
); | |||
}); | |||
it('should allow to pass a CSS prop as color name', () => { | |||
expect( | |||
ThemeHelper.themeBorder('focus', 'var(--outlineColor)', 0.5)({ theme: lightTheme }) | |||
ThemeHelper.themeBorder('focus', 'var(--outlineColor)', 0.5)({ theme: lightTheme }), | |||
).toEqual('4px solid var(--outlineColor)'); | |||
}); | |||
}); | |||
@@ -124,25 +124,25 @@ describe('themeBorder', () => { | |||
describe('themeShadow', () => { | |||
it('should work for light theme', () => { | |||
expect(ThemeHelper.themeShadow('xs')({ theme: lightTheme })).toEqual( | |||
'0px 1px 2px 0px rgba(29,33,47,0.05)' | |||
'0px 1px 2px 0px rgba(29,33,47,0.05)', | |||
); | |||
}); | |||
it('should allow to override the color of the shadow', () => { | |||
expect(ThemeHelper.themeShadow('xs', 'backgroundPrimary')({ theme: lightTheme })).toEqual( | |||
'0px 1px 2px 0px rgba(252,252,253,0.05)' | |||
'0px 1px 2px 0px rgba(252,252,253,0.05)', | |||
); | |||
expect(ThemeHelper.themeShadow('xs', 'transparent')({ theme: lightTheme })).toEqual( | |||
'0px 1px 2px 0px transparent' | |||
'0px 1px 2px 0px transparent', | |||
); | |||
}); | |||
it('should allow to override the opacity of the shadow', () => { | |||
expect(ThemeHelper.themeShadow('xs', 'backgroundPrimary', 0.8)({ theme: lightTheme })).toEqual( | |||
'0px 1px 2px 0px rgba(252,252,253,0.8)' | |||
'0px 1px 2px 0px rgba(252,252,253,0.8)', | |||
); | |||
}); | |||
it('should allow to pass a CSS prop as color name', () => { | |||
expect(ThemeHelper.themeShadow('xs', 'var(--shadowColor)')({ theme: lightTheme })).toEqual( | |||
'0px 1px 2px 0px var(--shadowColor)' | |||
'0px 1px 2px 0px var(--shadowColor)', | |||
); | |||
}); | |||
}); |
@@ -55,7 +55,7 @@ export function isInput(event: KeyboardEvent): boolean { | |||
} | |||
export function isTextarea( | |||
event: KeyboardEvent | |||
event: KeyboardEvent, | |||
): event is KeyboardEvent & { target: HTMLTextAreaElement } { | |||
return event.target instanceof HTMLTextAreaElement; | |||
} |
@@ -80,7 +80,7 @@ const MARGIN_TO_EDGE = 4; | |||
export function popupPositioning( | |||
toggleNode: Element, | |||
popupNode: Element, | |||
placement: PopupPlacement = PopupPlacement.Bottom | |||
placement: PopupPlacement = PopupPlacement.Bottom, | |||
) { | |||
const toggleRect = toggleNode.getBoundingClientRect(); | |||
const popupRect = popupNode.getBoundingClientRect(); | |||
@@ -136,12 +136,12 @@ export function popupPositioning( | |||
const inBoundariesLeft = Math.min( | |||
Math.max(left, getMinLeftPlacement(toggleRect)), | |||
getMaxLeftPlacement(toggleRect, popupRect) | |||
getMaxLeftPlacement(toggleRect, popupRect), | |||
); | |||
const inBoundariesTop = Math.min( | |||
Math.max(top, getMinTopPlacement(toggleRect)), | |||
getMaxTopPlacement(toggleRect, popupRect) | |||
getMaxTopPlacement(toggleRect, popupRect), | |||
); | |||
return { | |||
@@ -157,27 +157,27 @@ export function popupPositioning( | |||
function getMinLeftPlacement(toggleRect: DOMRect) { | |||
return Math.min( | |||
MARGIN_TO_EDGE, // Left edge of the sceen | |||
toggleRect.left + toggleRect.width / 2 // Left edge of the screen when scrolled | |||
toggleRect.left + toggleRect.width / 2, // Left edge of the screen when scrolled | |||
); | |||
} | |||
function getMaxLeftPlacement(toggleRect: DOMRect, popupRect: DOMRect) { | |||
return Math.max( | |||
document.documentElement.clientWidth - popupRect.width - MARGIN_TO_EDGE, // Right edge of the screen | |||
toggleRect.left + toggleRect.width / 2 - popupRect.width // Right edge of the screen when scrolled | |||
toggleRect.left + toggleRect.width / 2 - popupRect.width, // Right edge of the screen when scrolled | |||
); | |||
} | |||
function getMinTopPlacement(toggleRect: DOMRect) { | |||
return Math.min( | |||
MARGIN_TO_EDGE, // Top edge of the sceen | |||
toggleRect.top + toggleRect.height / 2 // Top edge of the screen when scrolled | |||
toggleRect.top + toggleRect.height / 2, // Top edge of the screen when scrolled | |||
); | |||
} | |||
function getMaxTopPlacement(toggleRect: DOMRect, popupRect: DOMRect) { | |||
return Math.max( | |||
document.documentElement.clientHeight - popupRect.height - MARGIN_TO_EDGE, // Bottom edge of the screen | |||
toggleRect.top + toggleRect.height / 2 - popupRect.height // Bottom edge of the screen when scrolled | |||
toggleRect.top + toggleRect.height / 2 - popupRect.height, // Bottom edge of the screen when scrolled | |||
); | |||
} |
@@ -39,7 +39,7 @@ export function themeContrast(name: ThemeColors | CSSColor) { | |||
export function themeBorder( | |||
name: keyof Theme['borders'] = 'default', | |||
color?: ThemeColors | CSSColor, | |||
opacity?: number | |||
opacity?: number, | |||
) { | |||
return function ({ theme }: ThemedProps) { | |||
const [width, style, ...rgba] = theme.borders[name]; | |||
@@ -50,7 +50,7 @@ export function themeBorder( | |||
export function themeShadow( | |||
name: keyof Theme['shadows'], | |||
color?: ThemeColors | CSSColor, | |||
opacity?: number | |||
opacity?: number, | |||
) { | |||
return function ({ theme }: ThemedProps) { | |||
const shadows = theme.shadows[name]; | |||
@@ -89,7 +89,7 @@ function getColor( | |||
theme: Theme, | |||
[r, g, b, a]: number[], | |||
colorOverride?: ThemeColors | CSSColor, | |||
opacityOverride?: number | |||
opacityOverride?: number, | |||
) { | |||
// Custom CSS property or rgb(a) color, return it directly | |||
if ( |
@@ -6940,6 +6940,7 @@ __metadata: | |||
postcss: 8.4.31 | |||
postcss-calc: 9.0.1 | |||
postcss-custom-properties: 12.1.11 | |||
prettier: ^3.1.0 | |||
react-toastify: 8.2.0 | |||
twin.macro: 3.4.0 | |||
typescript: 5.2.2 | |||
@@ -11538,6 +11539,15 @@ __metadata: | |||
languageName: node | |||
linkType: hard | |||
"prettier@npm:^3.1.0": | |||
version: 3.1.0 | |||
resolution: "prettier@npm:3.1.0" | |||
bin: | |||
prettier: bin/prettier.cjs | |||
checksum: 44b556bd56f74d7410974fbb2418bb4e53a894d3e7b42f6f87779f69f27a6c272fa7fc27cec0118cd11730ef3246478052e002cbd87e9a253f9cd04a56aa7d9b | |||
languageName: node | |||
linkType: hard | |||
"pretty-format@npm:^27.0.0, pretty-format@npm:^27.4.6": | |||
version: 27.4.6 | |||
resolution: "pretty-format@npm:27.4.6" |