Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,46 @@ describe('Hotspots', () => {

expect(scroller.scrollTo).toHaveBeenCalled();
});

it('scrolls pan zoom scroller when link button is clicked', async () => {
const seed = {
imageFileUrlTemplates: {large: ':id_partition/image.webp'},
imageFiles: [{id: 1, permaId: 100}]
};
const configuration = {
image: 100,
enablePanZoom: 'always',
areas: [
{
id: 1,
outline: [[10, 20], [10, 30], [40, 30], [40, 20]],
indicatorPosition: [20, 25],
}
],
tooltipTexts: {
1: {
title: [{type: 'heading', children: [{text: 'Some title'}]}],
link: [{type: 'heading', children: [{text: 'Some link'}]}]
}
},
tooltipLinks: {
1: {href: 'https://example.com', openInNewTab: true}
}
};

const user = userEvent.setup();
const {container, getByRole, simulateScrollPosition} = renderInContentElement(
<Hotspots configuration={configuration} />, {seed}
);
simulateScrollPosition('near viewport');

simulateIntersecting(container.querySelectorAll(`.${scrollerStyles.step}`)[1]);
const scroller = container.querySelector(`.${scrollerStyles.scroller}`);
scroller.scrollTo = jest.fn();
await user.click(getByRole('link'));

expect(scroller.scrollTo).toHaveBeenCalled();
});
});

function clickableArea(container) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,43 @@ describe('Hotspots', () => {
expect(container.querySelector(`.${tooltipStyles.box}`)).not.toBeNull();
});

it('hides tooltip when link button is clicked', async () => {
const seed = {
imageFileUrlTemplates: {large: ':id_partition/image.webp'},
imageFiles: [{id: 1, permaId: 100}]
};
const configuration = {
image: 100,
areas: [
{
id: 1,
outline: [[10, 20], [10, 30], [40, 30], [40, 20]],
indicatorPosition: [20, 25],
}
],
tooltipTexts: {
1: {
title: [{type: 'heading', children: [{text: 'Some title'}]}],
link: [{type: 'heading', children: [{text: 'Some link'}]}]
}
},
tooltipLinks: {
1: {href: 'https://example.com', openInNewTab: true}
}
};

const user = userEvent.setup();
const {container, getByRole, simulateScrollPosition} = renderInContentElement(
<Hotspots configuration={configuration} />, {seed}
);
simulateScrollPosition('near viewport');

await user.hover(clickableArea(container));
await user.click(getByRole('link'));

expect(container.querySelector(`.${tooltipStyles.box}`)).toBeNull();
});

it('hides when backdrop element is intersecting content', async () => {
const seed = {
imageFileUrlTemplates: {large: ':id_partition/image.webp'},
Expand Down
15 changes: 15 additions & 0 deletions entry_types/scrolled/package/spec/frontend/EditableLink-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import {EditableLink} from 'frontend';

import {renderInEntry} from 'support';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/extend-expect'

// Link behavior is tested in Link-spec.js.
Expand All @@ -25,4 +26,18 @@ describe('EditableLink', () => {

expect(getByRole('link')).toHaveClass('custom')
});

it('supports onClick', async () => {
const onClick = jest.fn(event =>
event.preventDefault() // Prevent jsdom warning
);
const user = userEvent.setup();
const {getByRole} = renderInEntry(
<EditableLink href="https://example.com" onClick={onClick}>Some link</EditableLink>
);

await user.click(getByRole('link'));

expect(onClick).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import '@testing-library/jest-dom/extend-expect'
jest.mock('frontend/inlineEditing/useSelectLinkDestination');

describe('EditableLink', () => {
beforeEach(() => {
const rect = {width: 100, height: 20, top: 100, left: 100, bottom: 120, right: 200, x: 100, y: 100};
Element.prototype.getClientRects = jest.fn(() => [rect]);
Element.prototype.getBoundingClientRect = jest.fn(() => rect);
});

useFakeTranslations({
'pageflow_scrolled.inline_editing.change_link_destination': 'Change link destination',
'pageflow_scrolled.inline_editing.select_link_destination': 'Select link destination',
Expand Down Expand Up @@ -145,4 +151,17 @@ describe('EditableLink', () => {

expect(onChange).toHaveBeenCalledWith(null);
});

it('triggers onClick when tooltip is clicked', async () => {
const onClick = jest.fn();
const user = userEvent.setup();
render(
<EditableLink href="https://example.com" onClick={onClick}>Some link</EditableLink>
);

await user.hover(screen.getByText('Some link'));
await user.click(screen.getByRole('link'));

expect(onClick).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ export function HotspotsImage({
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(-1)}
onClick={() => setActiveIndex(index)}
onLinkClick={event => {
activateArea(-1);
setHoveredIndex(-1);
event.stopPropagation();
}}
onDismiss={() => activateArea(-1)} />
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function Tooltip({
imageFile, containerRect, keepInViewport, floatingStrategy,
aboveNavigationWidgets,
wrapperRef,
onMouseEnter, onMouseLeave, onClick, onDismiss,
onMouseEnter, onMouseLeave, onClick, onDismiss, onLinkClick
}) {
const {t: translateWithEntryLocale} = useI18n();
const {t} = useI18n({locale: 'ui'});
Expand Down Expand Up @@ -110,7 +110,10 @@ export function Tooltip({

const dismiss = useDismiss(context, {
outsidePressEvent: 'mousedown',
outsidePress: event => !insidePagerButton(event.target)
outsidePress: event => !insidePagerButton(event.target),
capture: {
outsidePress: false
}
});

const {getReferenceProps, getFloatingProps} = useInteractions([
Expand Down Expand Up @@ -198,7 +201,7 @@ export function Tooltip({
light ? styles.light : styles.dark,
{[styles.paddingForScrollButtons]: keepInViewport,
[styles.minWidth]: presentOrEditing('link')})}
onMouseEnter={onMouseEnter}
onMouseEnter={() => storylineMode === 'active' && onMouseEnter()}
onMouseLeave={onMouseLeave}
onClick={onClick}
{...getFloatingProps()}>
Expand Down Expand Up @@ -239,7 +242,8 @@ export function Tooltip({
value={tooltipTexts[area.id]?.link}
allowRemove={true}
onTextChange={value => handleTextChange('link', value)}
onLinkChange={value => handleLinkChange(value)} />}
onLinkChange={value => handleLinkChange(value)}
onClick={onLinkClick} />}
</div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions entry_types/scrolled/package/src/frontend/EditableLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {Link} from './Link';

export const EditableLink = withInlineEditingAlternative(
'EditableLink',
function EditableLink({className, href, openInNewTab, children}) {
function EditableLink({className, href, openInNewTab, onClick, children}) {
return (
<Link href={href}
openInNewTab={openInNewTab}
attributes={{className}}
attributes={{className, onClick}}
children={children} />
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import styles from './EditableLink.module.css';
export function EditableLink({
className, href, openInNewTab, children,
onChange,
onClick,
linkPreviewDisabled,
linkPreviewPosition = 'below',
linkPreviewAlign = 'center',
Expand Down Expand Up @@ -43,6 +44,7 @@ export function EditableLink({
<LinkTooltipProvider position={linkPreviewPosition}
floatingStrategy={linkPreviewFloatingStrategy}
align={linkPreviewAlign}
onClick={onClick}
gap={5}>
<LinkPreview disabled={linkPreviewDisabled}
href={href}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function LinkTooltipProvider(props) {
}

export function LinkTooltipProviderInner({
disabled, position, floatingStrategy, children, align = 'left', gap = 10
disabled, position, floatingStrategy, onClick, children, align = 'left', gap = 10
}) {
const storylineMode = useStorylineActivity();
const [state, setState] = useState();
Expand Down Expand Up @@ -103,6 +103,7 @@ export function LinkTooltipProviderInner({
floatingStyles={floatingStyles}
floatingContext={floatingContext}
arrowRef={arrowRef}
onClick={onClick}
disabled={disabled} />
</FloatingPortal>
{children}
Expand Down Expand Up @@ -130,17 +131,25 @@ export function LinkPreview({disabled, href, openInNewTab, children, className})
);
}

export function LinkTooltip({disabled, setFloating, floatingStyles, floatingContext, arrowRef, state}) {
export function LinkTooltip({disabled, setFloating, floatingStyles, floatingContext, arrowRef, onClick, state}) {
const {keep, deactivate} = useContext(UpdateContext);

if (disabled || !state || !state.href) {
return null;
}

function handleClick(event) {
event.stopPropagation();

if (onClick) {
onClick(event);
}
}

return (
<div ref={setFloating}
className={classNames(styles.linkTooltip)}
onClick={e => e.stopPropagation()}
onClick={handleClick}
onMouseEnter={keep}
onMouseLeave={deactivate}
style={floatingStyles}>
Expand Down
Loading