diff --git a/packages/slate-editor/src/components/Button/Button.module.scss b/packages/slate-editor/src/components/Button/Button.module.scss index 64f405596..ff016c048 100644 --- a/packages/slate-editor/src/components/Button/Button.module.scss +++ b/packages/slate-editor/src/components/Button/Button.module.scss @@ -22,10 +22,20 @@ &:hover, &:focus-visible { background: rgba(255, 255, 255, 0.12); + color: inherit; + text-decoration: none; + } + + &:visited, + &:focus { + color: inherit; + text-decoration: none; } &:active { background: rgba(255, 255, 255, 0.16); + color: inherit; + text-decoration: none; } &:focus-visible { diff --git a/packages/slate-editor/src/components/Button/Button.stories.tsx b/packages/slate-editor/src/components/Button/Button.stories.tsx index 6ae2e17d2..0d5047735 100644 --- a/packages/slate-editor/src/components/Button/Button.stories.tsx +++ b/packages/slate-editor/src/components/Button/Button.stories.tsx @@ -23,15 +23,15 @@ export function WithIcon() { return (
- +
-
-
); diff --git a/packages/slate-editor/src/components/Button/Button.tsx b/packages/slate-editor/src/components/Button/Button.tsx index 9d74a74a1..b00404d4a 100644 --- a/packages/slate-editor/src/components/Button/Button.tsx +++ b/packages/slate-editor/src/components/Button/Button.tsx @@ -8,7 +8,7 @@ import styles from './Button.module.scss'; interface ButtonBaseProps { variant?: 'clear'; - Icon?: React.ComponentType>; + icon?: React.ComponentType>; iconPosition?: 'left' | 'right'; fullWidth?: boolean; round?: boolean; @@ -28,7 +28,7 @@ type ButtonProps = AsButtonProps | AsLinkProps; export function Button({ variant, - Icon, + icon: Icon, iconPosition, fullWidth, type, diff --git a/packages/slate-editor/src/components/EditorBlock/EditorBlock.module.scss b/packages/slate-editor/src/components/EditorBlock/EditorBlock.module.scss index 3264dc696..1f9958ad8 100644 --- a/packages/slate-editor/src/components/EditorBlock/EditorBlock.module.scss +++ b/packages/slate-editor/src/components/EditorBlock/EditorBlock.module.scss @@ -44,14 +44,8 @@ } .menu { - width: 280px; // FIXME - min-height: 320px; // FIXME - + width: 280px; position: absolute; - border-radius: 12px; - padding: 16px; - background-color: rgba($indigo-900, 0.96); - color: white; backdrop-filter: blur(6px); } diff --git a/packages/slate-editor/src/components/EditorBlock/EditorBlock.tsx b/packages/slate-editor/src/components/EditorBlock/EditorBlock.tsx index 1556d9908..3886fe665 100644 --- a/packages/slate-editor/src/components/EditorBlock/EditorBlock.tsx +++ b/packages/slate-editor/src/components/EditorBlock/EditorBlock.tsx @@ -1,7 +1,7 @@ import type { ElementNode } from '@prezly/slate-types'; import classNames from 'classnames'; import type { ReactNode } from 'react'; -import React, { forwardRef, useState } from 'react'; +import React, { forwardRef, useCallback, useState } from 'react'; import { useSelected } from 'slate-react'; import type { RenderElementProps } from 'slate-react'; @@ -27,7 +27,7 @@ interface Props extends Omit, SlateInternalAtt */ extendedHitArea?: boolean; renderBlock: (props: { isSelected: boolean }) => ReactNode; - renderMenu?: () => ReactNode; + renderMenu?: (props: { onClose: () => void }) => ReactNode; overlay?: OverlayMode; void?: boolean; } @@ -48,7 +48,10 @@ export const EditorBlock = forwardRef(function ( ) { const editorElement = useSlateDom(); const isSelected = useSelected(); + const [menuOpen, setMenuOpen] = useState(true); const [container, setContainer] = useState(null); + const openMenu = useCallback(() => setMenuOpen(true), [setMenuOpen]); + const closeMenu = useCallback(() => setMenuOpen(false), [setMenuOpen]); return (
(function ( >
{isSelected && renderMenu && container && editorElement && ( - - {renderMenu()} + + {renderMenu({ onClose: closeMenu })} )} - + {renderBlock({ isSelected })}
diff --git a/packages/slate-editor/src/components/EditorBlock/Menu.tsx b/packages/slate-editor/src/components/EditorBlock/Menu.tsx index e5e5fa670..94167548e 100644 --- a/packages/slate-editor/src/components/EditorBlock/Menu.tsx +++ b/packages/slate-editor/src/components/EditorBlock/Menu.tsx @@ -6,11 +6,14 @@ import React, { Component } from 'react'; import type { Modifier } from 'react-popper'; import { Popper } from 'react-popper'; +import { Toolbox } from '#components'; + import styles from './EditorBlock.module.scss'; interface Props { children: ReactNode; editorElement: HTMLElement; + open: boolean; reference: HTMLElement; } @@ -86,7 +89,12 @@ export class Menu extends Component { }; render() { - const { children, editorElement } = this.props; + const { children, editorElement, open } = this.props; + + if (!open) { + return null; + } + return ( { placement="right-start" > {({ ref, style, arrowProps, placement }) => ( -
+
= 0, @@ -105,7 +113,7 @@ export class Menu extends Component { {...arrowProps} /> {children} -
+
)} ); diff --git a/packages/slate-editor/src/components/EditorBlock/Overlay.tsx b/packages/slate-editor/src/components/EditorBlock/Overlay.tsx index 6484b2d93..38beeb8e5 100644 --- a/packages/slate-editor/src/components/EditorBlock/Overlay.tsx +++ b/packages/slate-editor/src/components/EditorBlock/Overlay.tsx @@ -8,9 +8,10 @@ export type OverlayMode = 'always' | 'autohide' | false; interface Props { selected: boolean; mode: OverlayMode; + onClick: () => void; } -export function Overlay({ selected, mode }: Props) { +export function Overlay({ mode, onClick, selected }: Props) { if (mode === false) { return null; } @@ -19,6 +20,7 @@ export function Overlay({ selected, mode }: Props) { className={classNames(styles.overlay, { [styles.hidden]: selected && mode === 'autohide', })} + onClick={onClick} /> ); } diff --git a/packages/slate-editor/src/components/Toggle/Toggle.stories.tsx b/packages/slate-editor/src/components/Toggle/Toggle.stories.tsx index e5bcad5a2..b67f96fd8 100644 --- a/packages/slate-editor/src/components/Toggle/Toggle.stories.tsx +++ b/packages/slate-editor/src/components/Toggle/Toggle.stories.tsx @@ -9,7 +9,7 @@ export default { export function Base() { return (
- +
); } @@ -17,7 +17,7 @@ export function Base() { export function Disabled() { return (
- +
); } diff --git a/packages/slate-editor/src/components/Toggle/Toggle.tsx b/packages/slate-editor/src/components/Toggle/Toggle.tsx index cf1a637c6..5ac92eb97 100644 --- a/packages/slate-editor/src/components/Toggle/Toggle.tsx +++ b/packages/slate-editor/src/components/Toggle/Toggle.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import styles from './Toggle.module.scss'; interface ToggleProps { + name: string; value?: boolean; onChange?: (value: boolean) => void; disabled?: boolean; @@ -14,6 +15,7 @@ export function Toggle(props: React.PropsWithChildren) { props.onChange?.(e.target.checked)} className={styles.input} disabled={props.disabled} diff --git a/packages/slate-editor/src/components/Toolbox/Header.tsx b/packages/slate-editor/src/components/Toolbox/Header.tsx index 9b31865ea..17809736d 100644 --- a/packages/slate-editor/src/components/Toolbox/Header.tsx +++ b/packages/slate-editor/src/components/Toolbox/Header.tsx @@ -17,7 +17,7 @@ export function Header(props: React.PropsWithChildren) { {props.children} {props.withCloseButton && ( -
); diff --git a/packages/slate-editor/src/components/Toolbox/Panel.tsx b/packages/slate-editor/src/components/Toolbox/Panel.tsx index 09853a0a3..82a947206 100644 --- a/packages/slate-editor/src/components/Toolbox/Panel.tsx +++ b/packages/slate-editor/src/components/Toolbox/Panel.tsx @@ -1,7 +1,24 @@ -import * as React from 'react'; +import classNames from 'classnames'; +import type { CSSProperties, ReactNode } from 'react'; +import React, { forwardRef } from 'react'; import styles from './Toolbox.module.scss'; -export function Panel(props: React.PropsWithChildren>) { - return {props.children}; +interface Props { + children: ReactNode; + className?: string; + style?: CSSProperties; } + +export const Panel = forwardRef(function ( + { children, className, style }, + ref, +) { + return ( +
+ {children} +
+ ); +}); + +Panel.displayName = 'Panel'; diff --git a/packages/slate-editor/src/components/Toolbox/Toolbox.module.scss b/packages/slate-editor/src/components/Toolbox/Toolbox.module.scss index 2852a5fad..7b3cacfc9 100644 --- a/packages/slate-editor/src/components/Toolbox/Toolbox.module.scss +++ b/packages/slate-editor/src/components/Toolbox/Toolbox.module.scss @@ -12,20 +12,18 @@ justify-content: space-between; align-items: center; overflow: hidden; - background: rgba($indigo-900, 0.96); - border-top-left-radius: $spacing-1-5; - border-top-right-radius: $spacing-1-5; padding: $spacing-2; color: $white; } .panel { backdrop-filter: blur(6px); + background: rgba($indigo-900, 0.96); + border-radius: $border-radius-base * 2; } .section { border-top: 1px solid rgba($white, 0.12); - background: rgba($indigo-900, 0.96); padding: $spacing-2; color: white; @@ -42,8 +40,5 @@ display: flex; overflow: hidden; color: $white; - background: rgba($indigo-900, 0.96); border-top: 1px solid rgba($white, 0.12); - border-bottom-left-radius: $spacing-1-5; - border-bottom-right-radius: $spacing-1-5; } diff --git a/packages/slate-editor/src/components/Toolbox/Toolbox.stories.tsx b/packages/slate-editor/src/components/Toolbox/Toolbox.stories.tsx index 5b963f136..2b23aed23 100644 --- a/packages/slate-editor/src/components/Toolbox/Toolbox.stories.tsx +++ b/packages/slate-editor/src/components/Toolbox/Toolbox.stories.tsx @@ -37,7 +37,7 @@ export function Base() { type="link" variant="clear" href="#" - Icon={ExternalLink} + icon={ExternalLink} iconPosition="right" fullWidth > @@ -46,24 +46,24 @@ export function Base() { - Show preview image + Show preview image - Open in new tab + Open in new tab - diff --git a/packages/slate-editor/src/icons/Items-Layout-Horizontal.svg b/packages/slate-editor/src/icons/Items-Layout-Horizontal.svg index e7e3b867f..e7c71df44 100644 --- a/packages/slate-editor/src/icons/Items-Layout-Horizontal.svg +++ b/packages/slate-editor/src/icons/Items-Layout-Horizontal.svg @@ -1,5 +1,5 @@ - + - \ No newline at end of file + diff --git a/packages/slate-editor/src/icons/Items-Layout-Vertical.svg b/packages/slate-editor/src/icons/Items-Layout-Vertical.svg index adbd36110..6960227e0 100644 --- a/packages/slate-editor/src/icons/Items-Layout-Vertical.svg +++ b/packages/slate-editor/src/icons/Items-Layout-Vertical.svg @@ -1,5 +1,5 @@ - + - \ No newline at end of file + diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/WebBookmarkExtension.tsx b/packages/slate-editor/src/modules/editor-v4-web-bookmark/WebBookmarkExtension.tsx index 95e75a2bd..e072424be 100644 --- a/packages/slate-editor/src/modules/editor-v4-web-bookmark/WebBookmarkExtension.tsx +++ b/packages/slate-editor/src/modules/editor-v4-web-bookmark/WebBookmarkExtension.tsx @@ -4,15 +4,11 @@ import { BOOKMARK_NODE_TYPE, isBookmarkNode } from '@prezly/slate-types'; import React from 'react'; import type { RenderElementProps } from 'slate-react'; -import { WebBookmarkElement, WebBookmarkMenu } from './components'; +import { WebBookmarkElement } from './components'; import { WEB_BOOKMARK_EXTENSION_ID } from './constants'; import { normalizeRedundantWebBookmarkAttributes, parseSerializedElement } from './lib'; -import type { WebBookmarkParameters } from './types'; -export const WebBookmarkExtension = ({ - availableWidth, - containerRef, -}: WebBookmarkParameters): Extension => ({ +export const WebBookmarkExtension = (): Extension => ({ deserialize: { element: { [BOOKMARK_NODE_TYPE]: createDeserializeElement(parseSerializedElement), @@ -24,17 +20,7 @@ export const WebBookmarkExtension = ({ if (isBookmarkNode(element)) { return ( <> - {attributes.ref.current && ( - - )} - + {children} diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkElement/WebBookmarkElement.tsx b/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkElement/WebBookmarkElement.tsx index 29915ff26..9ca59844b 100644 --- a/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkElement/WebBookmarkElement.tsx +++ b/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkElement/WebBookmarkElement.tsx @@ -10,11 +10,11 @@ import { EditorBlock } from '#components'; import { useResizeObserver } from '#lib'; import styles from './WebBookmarkElement.module.scss'; +import { WebBookmarkMenu } from './WebBookmarkMenu'; const HORIZONTAL_LAYOUT_MIN_WIDTH = 480; interface Props extends RenderElementProps { - availableWidth: number; element: BookmarkNode; } @@ -92,6 +92,7 @@ export const WebBookmarkElement: FunctionComponent = ({ attributes, child {...attributes} // contains `ref` element={element} overlay="always" + renderMenu={({ onClose }) => } renderBlock={({ isSelected }) => (
void; +} + +const LAYOUT_OPTIONS: OptionsGroupOption[] = [ + { + label: 'Vertical', + value: BookmarkCardLayout.VERTICAL, + icon: ({ isActive }) => ( + + ), + }, + { + label: 'Horizontal', + value: BookmarkCardLayout.HORIZONTAL, + icon: ({ isActive }) => ( + + ), + }, +]; + +export const WebBookmarkMenu: FunctionComponent = ({ element, onClose }) => { + const editor = useSlate(); + const isSelected = useSelected(); + + function handleRemove() { + const removedElement = removeWebBookmark(editor); + + if (removedElement) { + EventsEditor.dispatchEvent(editor, 'web-bookmark-removed', { + uuid: removedElement.uuid, + }); + } + } + + if (!isSelected) { + return null; + } + + const isLayoutChangeable = element.oembed.thumbnail_url && element.show_thumbnail; + const activeLayout = isLayoutChangeable ? element.layout : BookmarkCardLayout.VERTICAL; + + return ( + <> + + Web bookmark settings + + + + + + + + updateWebBookmark(editor, { show_thumbnail })} + > + Show preview image + + + + + + + columns={3} + disabled={!isLayoutChangeable} + name="layout" + onChange={(layout) => updateWebBookmark(editor, { layout })} + options={LAYOUT_OPTIONS} + selectedValue={activeLayout} + /> + updateWebBookmark(editor, { new_tab })} + > + Open in new tab + + + + + + + + + ); +}; diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkMenu.tsx b/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkMenu.tsx deleted file mode 100644 index 633005597..000000000 --- a/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/WebBookmarkMenu.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import type { FunctionComponent, RefObject } from 'react'; -import React from 'react'; -import { useSelected, useSlate } from 'slate-react'; - -import { Menu } from '#components'; -import { Delete } from '#icons'; - -import { EventsEditor } from '../../editor-v4-events'; -import { removeWebBookmark } from '../transforms'; - -interface Props { - containerRef: RefObject; - element: HTMLElement; -} - -export const WebBookmarkMenu: FunctionComponent = ({ containerRef, element }) => { - const editor = useSlate(); - const isSelected = useSelected(); - - function handleRemove() { - const removedElement = removeWebBookmark(editor); - - if (removedElement) { - EventsEditor.dispatchEvent(editor, 'web-bookmark-removed', { - uuid: removedElement.uuid, - }); - } - } - - if (!isSelected) { - return null; - } - - return ( - - - - - - - - ); -}; diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/index.ts b/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/index.ts index 4fc161fa7..bf4758da6 100644 --- a/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/index.ts +++ b/packages/slate-editor/src/modules/editor-v4-web-bookmark/components/index.ts @@ -1,3 +1,2 @@ export { FloatingWebBookmarkInput } from './FloatingWebBookmarkInput'; export { WebBookmarkElement } from './WebBookmarkElement'; -export { WebBookmarkMenu } from './WebBookmarkMenu'; diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/index.ts b/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/index.ts index edf88dcb9..256a4adbe 100644 --- a/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/index.ts +++ b/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/index.ts @@ -1 +1,2 @@ +export { updateWebBookmark } from './updateWebBookmark'; export { removeWebBookmark } from './removeWebBookmark'; diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/updateWebBookmark.ts b/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/updateWebBookmark.ts new file mode 100644 index 000000000..ad88a222e --- /dev/null +++ b/packages/slate-editor/src/modules/editor-v4-web-bookmark/transforms/updateWebBookmark.ts @@ -0,0 +1,11 @@ +import type { BookmarkNode } from '@prezly/slate-types'; +import { isBookmarkNode } from '@prezly/slate-types'; +import type { Editor } from 'slate'; +import { Transforms } from 'slate'; + +export function updateWebBookmark( + editor: Editor, + properties: Partial>, +): void { + Transforms.setNodes(editor, properties, { match: isBookmarkNode }); +} diff --git a/packages/slate-editor/src/modules/editor-v4-web-bookmark/types.ts b/packages/slate-editor/src/modules/editor-v4-web-bookmark/types.ts index 0951a9d09..fe1984917 100644 --- a/packages/slate-editor/src/modules/editor-v4-web-bookmark/types.ts +++ b/packages/slate-editor/src/modules/editor-v4-web-bookmark/types.ts @@ -1,11 +1,5 @@ import type { OEmbedInfo } from '@prezly/sdk'; -import type { RefObject } from 'react'; export interface WebBookmarkExtensionParameters { fetchOembed: (url: OEmbedInfo['url']) => Promise; } - -export interface WebBookmarkParameters extends WebBookmarkExtensionParameters { - availableWidth: number; - containerRef: RefObject; -} diff --git a/packages/slate-editor/src/modules/editor-v4/getEnabledExtensions.ts b/packages/slate-editor/src/modules/editor-v4/getEnabledExtensions.ts index 963b56c74..fcc4e0266 100644 --- a/packages/slate-editor/src/modules/editor-v4/getEnabledExtensions.ts +++ b/packages/slate-editor/src/modules/editor-v4/getEnabledExtensions.ts @@ -131,11 +131,7 @@ export function* getEnabledExtensions({ } if (withWebBookmarks) { - yield WebBookmarkExtension({ - ...withWebBookmarks, - availableWidth, - containerRef, - }); + yield WebBookmarkExtension(); } if (withAutoformat) {