Skip to content

Commit

Permalink
refactor builtin wrapper, etc
Browse files Browse the repository at this point in the history
  • Loading branch information
KaWaite committed Aug 10, 2023
1 parent b888bf6 commit efa2048
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 255 deletions.
1 change: 1 addition & 0 deletions web/src/beta/components/PopoverMenuContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const SRoot = styled.div<Pick<Props, "width">>`
border: 1px solid ${({ theme }) => theme.bg[3]};
background: ${({ theme }) => theme.bg[1]};
box-shadow: 4px 4px 4px 0px rgba(0, 0, 0, 0.25);
z-index: 2;
`;

const SRow = styled.button<
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useMemo } from "react";

type Props = {
title?: string;
icon?: string;
isSelected?: boolean;
editMode: boolean;
onEditModeToggle: () => void;
onSettingsToggle: () => void;
};

export default ({
title,
icon,
isSelected,
editMode,
onEditModeToggle,
onSettingsToggle,
}: Props) => {
const actionItems = useMemo(
() => [
{
blockName: title ?? "Story Block",
icon: icon ?? "plugin",
},
{
icon: editMode ? "exit" : "storyBlockEdit",
hide: !isSelected,
onClick: onEditModeToggle,
},
{
icon: "settings",
hide: !isSelected,
onClick: onSettingsToggle,
},
],
[title, icon, isSelected, editMode, onEditModeToggle, onSettingsToggle],
);
return {
actionItems,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { Dispatch, Fragment, SetStateAction } from "react";

import Icon from "@reearth/beta/components/Icon";
import * as Popover from "@reearth/beta/components/Popover";
import PopoverMenuContent from "@reearth/beta/components/PopoverMenuContent";
import Text from "@reearth/beta/components/Text";
import { useT } from "@reearth/services/i18n";
import { styled } from "@reearth/services/theme";

import useHooks from "./hooks";

type Props = {
title?: string;
icon?: string;
isSelected?: boolean;
showSettings?: boolean;
showPadding?: boolean;
editMode: boolean;
setShowPadding: Dispatch<SetStateAction<boolean>>;
onEditModeToggle: () => void;
onSettingsToggle: () => void;
onRemove?: () => void;
};

const ActionPanel: React.FC<Props> = ({
title,
icon,
isSelected,
showSettings,
showPadding,
editMode,
setShowPadding,
onEditModeToggle,
onSettingsToggle,
onRemove,
}) => {
const t = useT();
const { actionItems } = useHooks({
title,
icon,
isSelected,
editMode,
onEditModeToggle,
onSettingsToggle,
});

return (
<Wrapper isSelected={isSelected}>
<Icon icon="dndHandle" size={16} />
<Popover.Provider
open={showSettings}
onOpenChange={onSettingsToggle}
placement="bottom-start">
<BlockOptions isSelected={isSelected}>
{actionItems.map(
(a, idx) =>
!a.hide && (
<Fragment key={idx}>
<Popover.Trigger asChild>
<OptionWrapper showPointer={!isSelected || !!a.onClick} onClick={a.onClick}>
<OptionIcon icon={a.icon} size={16} />
{a.blockName && (
<OptionText size="footnote" customColor>
{a.blockName}
</OptionText>
)}
</OptionWrapper>
</Popover.Trigger>
</Fragment>
),
)}
</BlockOptions>
<Popover.Content>
{showPadding ? (
<SettingsDropdown>
<SettingsHeading>
<Text size="footnote" customColor>
Padding settings
</Text>
<CancelIcon icon="cancel" size={14} onClick={() => setShowPadding(false)} />
</SettingsHeading>
<SettingsContent>Padding</SettingsContent>
</SettingsDropdown>
) : (
<PopoverMenuContent
size="sm"
items={[
{
name: t("Padding settings"),
icon: "padding",
onClick: () => setShowPadding(true),
},
{
name: t("Remove"),
icon: "trash",
onClick: onRemove,
},
]}
/>
)}
</Popover.Content>
</Popover.Provider>
</Wrapper>
);
};

export default ActionPanel;

const Wrapper = styled.div<{ isSelected?: boolean }>`
color: ${({ theme }) => theme.select.main};
display: flex;
align-items: center;
gap: 4px;
height: 24px;
position: absolute;
right: -1px;
top: -25px;
transition: all 0.2s;
`;

const BlockOptions = styled.div<{ isSelected?: boolean }>`
background: ${({ isSelected, theme }) => (isSelected ? theme.select.main : "transparent")};
color: ${({ isSelected, theme }) => (isSelected ? theme.content.main : theme.select.main)};
display: flex;
align-items: center;
height: 24px;
transition: all 0.2s;
`;

const OptionWrapper = styled.div<{ showPointer?: boolean }>`
display: flex;
align-items: center;
${({ showPointer }) => showPointer && "cursor: pointer;"}
`;

const OptionText = styled(Text)`
padding-right: 4px;
`;

const OptionIcon = styled(Icon)`
padding: 4px;
border-left: 1px solid #f1f1f1;
`;

const SettingsDropdown = styled.div`
z-index: 999;
background: ${({ theme }) => theme.bg[1]};
border-radius: 2px;
border: 1px solid ${({ theme }) => theme.bg[3]};
`;

const SettingsHeading = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid ${({ theme }) => theme.outline.weak};
height: 28px;
padding: 0 8px;
`;

const SettingsContent = styled.div`
height: 100px;
width: 200px;
`;

const CancelIcon = styled(Icon)`
cursor: pointer;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { ReactNode } from "react";

import { styled } from "@reearth/services/theme";

import Template from "../../Template";

import ActionPanel from "./ActionPanel";
import useHooks from "./hooks";

type Spacing = {
top: number;
bottom: number;
left: number;
right: number;
};

type Props = {
title?: string;
icon?: string;
padding?: Spacing;
isSelected?: boolean;
children?: ReactNode;
onClick: (() => void) | undefined;
onRemove?: () => void;
};

const BlockWrapper: React.FC<Props> = ({
title,
icon,
padding,
isSelected,
children,
onClick,
onRemove,
}) => {
const {
isHovered,
editMode,
showSettings,
showPadding,
setShowPadding,
handleMouseEnter,
handleMouseLeave,
handleBlockClick,
handleEditModeToggle,
handleSettingsToggle,
} = useHooks({
isSelected,
onClick,
});

return (
<Wrapper
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
isSelected={isSelected}>
{(isHovered || isSelected) && (
<ActionPanel
title={title}
icon={icon}
isSelected={isSelected}
showSettings={showSettings}
showPadding={showPadding}
editMode={editMode}
setShowPadding={setShowPadding}
onEditModeToggle={handleEditModeToggle}
onSettingsToggle={handleSettingsToggle}
onRemove={onRemove}
/>
)}
<Block padding={padding} onClick={handleBlockClick}>
{children ?? <Template icon={icon} />}
</Block>
{editMode && (
<EditorPanel>
<p>Block editing</p>
</EditorPanel>
)}
</Wrapper>
);
};

export default BlockWrapper;

const Wrapper = styled.div<{ isSelected?: boolean }>`
border-width: 1px;
border-style: solid;
border-color: ${({ isSelected, theme }) => (isSelected ? theme.select.main : "transparent")};
transition: all 0.3s;
padding: 1px;
position: relative;
:hover {
border-color: ${({ isSelected, theme }) => !isSelected && theme.select.weaker};
}
`;

const Block = styled.div<{ padding?: Spacing }>`
display: flex;
min-height: 255px;
padding-top: ${({ padding }) => padding?.top + "px" ?? 0};
padding-bottom: ${({ padding }) => padding?.bottom + "px" ?? 0};
padding-left: ${({ padding }) => padding?.left + "px" ?? 0};
padding-right: ${({ padding }) => padding?.right + "px" ?? 0};
cursor: pointer;
`;

const EditorPanel = styled.div`
background: ${({ theme }) => theme.bg[1]};
color: ${({ theme }) => theme.content.main};
height: 100px;
padding: 12px;
z-index: 100;
position: absolute;
top: 100%;
left: -1px;
right: -1px;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useCallback, useState } from "react";

type Props = {
isSelected?: boolean;
onClick: (() => void) | undefined;
};

export default ({ isSelected, onClick }: Props) => {
const [isHovered, setHover] = useState(false);
const [editMode, setEditMode] = useState(false);
const [showSettings, setShowSettings] = useState(false);
const [showPadding, setShowPadding] = useState(false);

const handleEditModeToggle = useCallback(() => setEditMode(em => !em), []);

const handleSettingsToggle = useCallback(() => setShowSettings(s => !s), []);

const handleMouseEnter = useCallback(() => setHover(true), []);

const handleMouseLeave = useCallback(() => setHover(false), []);

const handleBlockClick = useCallback(() => {
if (showSettings && isSelected) return;
onClick?.();
}, [onClick, showSettings, isSelected]);

return {
isHovered,
editMode,
showSettings,
showPadding,
setShowPadding,
handleMouseEnter,
handleMouseLeave,
handleBlockClick,
handleEditModeToggle,
handleSettingsToggle,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useCallback } from "react";
import { styled } from "@reearth/services/theme";

import { CommonProps as BlockProps } from "../../types";
import BlockWrapper from "../Wrapper";
import BlockWrapper from "../Builtin/Wrapper";

export type Props = BlockProps<Property>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback } from "react";

import { CommonProps as BlockProps } from "../../types";
import BlockWrapper from "../Wrapper";
import BlockWrapper from "../Builtin/Wrapper";

export type Props = BlockProps<Property>;

Expand Down
Loading

0 comments on commit efa2048

Please sign in to comment.