Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEV-13410] Fix - Coverage placeholder fixes #572

Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -89,6 +89,7 @@ export function WithFooter() {
renderSuggestions={({ activeElement, query, suggestions, children }) => (
<SearchInput.Suggestions<string>
activeElement={activeElement}
origin={null}
query={query}
suggestions={suggestions}
footer={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export function SearchInput<T = unknown>({
suggestions,
onClose: handleClose,
onSelect,
origin: rootRef.current,
children: suggestions.map((suggestion) =>
renderSuggestion({
suggestion,
Expand Down Expand Up @@ -184,6 +185,7 @@ export namespace SearchInput {
activeElement: HTMLElement | undefined;
activeSuggestion: Suggestion<T> | undefined;
loading: boolean;
origin: HTMLElement | null;
query: string;
suggestions: Suggestion<T>[];
onClose: () => void;
Expand Down Expand Up @@ -227,13 +229,15 @@ function defaultRenderSuggestions<T>({
activeElement,
query,
suggestions,
origin,
children,
}: SearchInput.Props.Suggestions<T>) {
return (
<SearchInput.Suggestions<T>
activeElement={activeElement}
query={query}
suggestions={suggestions}
origin={origin}
>
{children}
</SearchInput.Suggestions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
.Suggestions {
display: flex;
flex-direction: column;
width: 100%;
}
50 changes: 31 additions & 19 deletions packages/slate-editor/src/components/SearchInput/Suggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { FlipModifier } from '@popperjs/core/lib/modifiers/flip';
import type { PreventOverflowModifier } from '@popperjs/core/lib/modifiers/preventOverflow';
import classNames from 'classnames';
import type { HTMLAttributes, ReactNode } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { usePopper } from 'react-popper';

import { useFunction } from '#lib';

Expand All @@ -12,40 +15,54 @@ import type { Suggestion } from './types';

export interface Props<T> extends HTMLAttributes<HTMLDivElement> {
activeElement: HTMLElement | undefined;
minHeight?: number;
footer?: ReactNode;
maxHeight?: number;
minHeight?: number;
origin: HTMLElement | null;
query: string;
suggestions: Suggestion<T>[];
footer?: ReactNode;
}

export function Suggestions<T>({
activeElement,
children,
className,
footer,
minHeight = 200,
maxHeight = 500,
minHeight = 200,
origin,
query,
suggestions,
...attributes
}: Props<T>) {
const [height, setHeight] = useState<number>();
const [calculatedMaxHeight, setMaxHeight] = useState<number>();
const container = useRef<HTMLDivElement | null>(null);
const childrenContainer = useRef<HTMLDivElement | null>(null);
const [scrollarea, setScrollarea] = useState<FancyScrollbars | null>(null);

const popper = usePopper(origin, container.current, {
modifiers: [
{
name: 'flip',
enabled: true,
options: {
fallbackPlacements: ['top'],
},
} satisfies Partial<FlipModifier>,
{
name: 'preventOverflow',
enabled: true,
options: {
altAxis: true,
mainAxis: true,
},
} satisfies Partial<PreventOverflowModifier>,
],
placement: 'bottom',
});

const updatePanelSize = useFunction(() => {
setHeight(childrenContainer.current?.getBoundingClientRect().height);

if (container.current) {
const viewport = document.body.getBoundingClientRect();
const rect = container.current.getBoundingClientRect();
setMaxHeight(clamp(viewport.height - rect.top - 4, minHeight, maxHeight));
} else {
setMaxHeight(undefined);
}
});

useEffect(() => {
Expand All @@ -71,7 +88,8 @@ export function Suggestions<T>({
return (
<Panel
{...attributes}
style={{ maxHeight: calculatedMaxHeight, ...attributes.style }}
{...popper.attributes.popper}
style={{ maxHeight, ...attributes.style, ...popper.styles.popper }}
ref={container}
className={classNames(className, styles.Suggestions)}
footer={footer}
Expand All @@ -82,9 +100,3 @@ export function Suggestions<T>({
</Panel>
);
}

function clamp(num: number, min: number, max: number) {
if (num < min) return min;
if (num > max) return max;
return num;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import styles from './InputPlaceholder.module.scss';
import type { ContentRenderProps } from './Placeholder';

export interface Props extends Omit<BaseProps, 'title' | 'onSubmit'> {
children?: ReactNode;
title: ReactNode | FunctionComponent<ContentRenderProps>;
description: ReactNode | FunctionComponent<ContentRenderProps>;
// Input properties
Expand All @@ -28,6 +29,7 @@ export interface Props extends Omit<BaseProps, 'title' | 'onSubmit'> {
const isEsc = isHotkey('esc');

export function InputPlaceholder({
children,
className,
action,
title,
Expand Down Expand Up @@ -135,6 +137,7 @@ export function InputPlaceholder({
value={value}
/>
</form>
{children}
</Frame>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export function ContactPlaceholderElement({
query={props.query}
suggestions={props.suggestions}
footer={renderSuggestionsFooter?.(props)}
origin={props.origin}
>
{props.children}
</SearchInput.Suggestions>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import "styles/variables";

.Action {
kudlajz marked this conversation as resolved.
Show resolved Hide resolved
margin: $spacing-2 0 0;
}

.Button {
text-decoration: none;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import React, { type DragEvent, useEffect, useState } from 'react';
import { Transforms } from 'slate';
import { useSelected, useSlateStatic } from 'slate-react';

import { SearchInput } from '#components';
import { PlaceholderCoverage } from '#icons';
import { Button, SearchInput } from '#components';
import { PlaceholderCoverage, Upload } from '#icons';
import { URL_WITH_OPTIONAL_PROTOCOL_REGEXP, useFunction } from '#lib';

import { createCoverage } from '#extensions/coverage';
import { EventsEditor } from '#modules/events';
import { UploadcareEditor } from '#modules/uploadcare';

import { InputPlaceholder } from '../components/InputPlaceholder';
import { withLoadingDots } from '../components/LoadingDots';
Expand All @@ -24,6 +25,8 @@ import { replacePlaceholder } from '../lib';
import type { PlaceholderNode } from '../PlaceholderNode';
import { PlaceholdersManager, usePlaceholderManagement } from '../PlaceholdersManager';

import styles from './CoveragePlaceholderElement.module.scss';

type Url = string;
type CoverageRef = Pick<CoverageNode, 'coverage'>;
type Mode = 'search' | 'create';
Expand All @@ -49,6 +52,22 @@ export function CoveragePlaceholderElement({
PlaceholdersManager.activate(element);
});

const handleUpload = useFunction(async () => {
const files = await UploadcareEditor.upload(editor, { multiple: false });
if (!files) {
return;
}

setMode('search');
const uploading = toProgressPromise(files[0]).then(async (fileInfo: PrezlyFileInfo) => {
const file = UploadcareFile.createFromUploadcareWidgetPayload(fileInfo);
const ref = await onCreateCoverage(file);

return { coverage: { id: ref.coverage.id } };
});
PlaceholdersManager.register(element.type, element.uuid, uploading);
});

const handleDrop = useFunction((event: DragEvent) => {
event.preventDefault();
event.stopPropagation();
Expand Down Expand Up @@ -126,17 +145,19 @@ export function CoveragePlaceholderElement({
query={props.query}
suggestions={props.suggestions}
footer={renderSuggestionsFooter?.({ ...props, onMode })}
origin={props.origin}
>
{props.children}
</SearchInput.Suggestions>
)}
renderFrame={() =>
mode === 'create' ? (
<InputPlaceholder
autoFocus
format="card"
selected={isSelected}
title="Coverage"
description="Type the URL of the new Coverage you want to add"
title="Log new coverage"
description="Paste a coverage URL or upload a coverage file (you can also drop it here)."
placeholder="www.website.com/article"
pattern={URL_WITH_OPTIONAL_PROTOCOL_REGEXP.source}
action="Add coverage"
Expand All @@ -145,7 +166,18 @@ export function CoveragePlaceholderElement({
onEsc={() => PlaceholdersManager.deactivate(element)}
onRemove={handleRemove}
onSubmit={handleSubmitUrl}
/>
>
<div className={styles.Action}>
<Button
className={styles.Button}
icon={Upload}
onClick={handleUpload}
variant="underlined"
>
Upload a coverage file
</Button>
</div>
</InputPlaceholder>
) : undefined
}
inputTitle="Coverage"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export function GalleryBookmarkPlaceholderElement({
query={props.query}
suggestions={props.suggestions}
footer={renderSuggestionsFooter?.(props)}
origin={props.origin}
>
{props.children}
</SearchInput.Suggestions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export function InlineContactPlaceholderElement({
query={props.query}
suggestions={props.suggestions}
footer={renderSuggestionsFooter?.(props)}
origin={props.origin}
>
{props.children}
</SearchInput.Suggestions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function StoryBookmarkPlaceholderElement({
query={props.query}
suggestions={props.suggestions}
footer={renderSuggestionsFooter?.(props)}
origin={props.origin}
>
{props.children}
</SearchInput.Suggestions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function StoryEmbedPlaceholderElement({
query={props.query}
suggestions={props.suggestions}
footer={renderSuggestionsFooter?.(props)}
origin={props.origin}
>
{props.children}
</SearchInput.Suggestions>
Expand Down
3 changes: 3 additions & 0 deletions packages/slate-editor/src/icons/Upload.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/slate-editor/src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export { default as Resize } from './Resize.svg';
export { default as Search } from './Search.svg';
export { default as SocialFacebook } from './Social-Facebook.svg';
export { default as SocialTwitter } from './Social-Twitter.svg';
export { default as Upload } from './Upload.svg';
export { default as User } from './User.svg';
export { default as Video } from './Video.svg';
export { default as WarningCircle } from './Warning-Circle.svg';
Expand Down
Loading