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

chore(web): MD Block #712

Merged
merged 19 commits into from
Sep 29, 2023
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
6 changes: 3 additions & 3 deletions server/e2e/gql_storytelling_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -934,8 +934,8 @@ func TestStoryPageBlocksCRUD(t *testing.T) {
res.Object().
Path("$.data.node.stories[0].pages[0].blocks").Equal([]any{})

_, _, blockID1 := createBlock(e, sID, storyID, pageID, "reearth", "storyBlock", nil)
_, _, blockID2 := createBlock(e, sID, storyID, pageID, "reearth", "storyBlock", nil)
_, _, blockID1 := createBlock(e, sID, storyID, pageID, "reearth", "textStoryBlock", nil)
_, _, blockID2 := createBlock(e, sID, storyID, pageID, "reearth", "textStoryBlock", nil)

_, res = fetchSceneForStories(e, sID)
res.Object().
Expand All @@ -947,7 +947,7 @@ func TestStoryPageBlocksCRUD(t *testing.T) {
res.Object().
Path("$.data.node.stories[0].pages[0].blocks[:].id").Equal([]string{blockID2, blockID1})

_, _, blockID3 := createBlock(e, sID, storyID, pageID, "reearth", "storyBlock", lo.ToPtr(1))
_, _, blockID3 := createBlock(e, sID, storyID, pageID, "reearth", "textStoryBlock", lo.ToPtr(1))

_, res = fetchSceneForStories(e, sID)
res.Object().
Expand Down
14 changes: 1 addition & 13 deletions server/pkg/builtin/manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2070,18 +2070,6 @@ extensions:
type: string
ui: datetime
title: Time
- id: storyBlock
name: Block
type: storyBlock
description: Storytelling Block
schema:
groups:
- id: default
title: Basic
fields:
- id: title
type: string
title: Title
- id: textStoryBlock
name: Text Block
type: storyBlock
Expand All @@ -2105,7 +2093,7 @@ extensions:
title: Content
ui: multiline
- id: mdTextStoryBlock
name: MD Test Block
name: MD Text Block
type: storyBlock
description: Storytelling MD Text Block
schema:
Expand Down
91 changes: 91 additions & 0 deletions server/pkg/builtin/manifest_ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1001,3 +1001,94 @@ extensions:
always: 常に
desktop: デスクトップのみ
mobile: モバイルのみ
story:
name: ストーリー
description: ストーリーテリングのストーリー
storyPage:
name: ストーリーページ
description: ストーリーテリングのページ
propertySchema:
panel:
title: パネル設定
fields:
padding:
title: 余白
gap:
title: 空隙
title:
title: タイトル設定
fields:
title:
title: タイトル
color:
title: 色
cameraAnimation:
title: カメラアニメーション
fields:
cameraPosition:
title: カメラ位置
cameraDuration:
title: カメラ移動時間
cameraDelay:
title: カメラ待機時間
timePoint:
title: タイムポイント
fields:
timePoint:
title: 時間
textStoryBlock:
name: テキスト
description: ストーリーテリングのテキストブロック
propertySchema:
panel:
title: パネル設定
fields:
padding:
title: 余白
default:
title: テキスト
fields:
text:
title: コンテンツ
mdTextStoryBlock:
name: マークダウン
description: ストーリーテリングのマークダウンブロック
propertySchema:
panel:
title: パネル設定
fields:
padding:
title: 余白
default:
title: マークダウン
fields:
text:
title: コンテンツ
imageStoryBlock:
name: 画像
description: ストーリーテリングの画像ブロック
propertySchema:
panel:
title: パネル設定
fields:
padding:
title: 余白
default:
title: 画像
fields:
text:
title: コンテンツ
videoStoryBlock:
name: 動画
description: ストーリーテリングの動画ブロック
propertySchema:
panel:
title: パネル設定
fields:
padding:
title: 余白
default:
title: 動画
fields:
text:
title: コンテンツ
6 changes: 5 additions & 1 deletion web/src/beta/components/ListItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ const ListItem: FC<Props> = ({
return (
<Wrapper>
<Inner border={border} isSelected={isSelected} clamp={clamp} onClick={onItemClick}>
<StyledText size="footnote">{children}</StyledText>
{typeof children === "string" ? (
<StyledText size="footnote">{children}</StyledText>
) : (
children
)}
</Inner>
{actionContent && (
<Popover.Provider
Expand Down
45 changes: 37 additions & 8 deletions web/src/beta/components/Markdown/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Meta, Story } from "@storybook/react";
import { Meta, StoryObj } from "@storybook/react";

import Component, { Props } from ".";
import { styled } from "@reearth/services/theme";

import Markdown, { Props } from ".";

const markdown = `
> A block quote with ~strikethrough~ and a URL: https://reactjs.org.
Expand All @@ -9,20 +11,47 @@ const markdown = `
* [ ] todo
* [x] done


[Link](https://reactjs.org)

### Image
![Alt text](https://images.pexels.com/photos/5656637/pexels-photo-5656637.jpeg?auto=compress&cs=tinysrgb&w=200)

A table:

| a | b |
| - | - |
`;

export default {
component: Component,
parameters: { actions: { argTypesRegex: "^on.*" } },
} as Meta;
const meta: Meta<typeof Markdown> = {
component: Markdown,
};

export default meta;

type Story = StoryObj<typeof Markdown>;

export const Default: Story<Props> = args => <Component {...args} />;
export const Default: Story = (args: Props) => {
return (
<Wrapper>
<div>
<Markdown {...args} />
</div>
</Wrapper>
);
};

const Wrapper = styled.div`
display: flex;
flex-direction: column;
gap: 10%;
margin-left: 2rem;
margin-top: 2rem;
height: 300px;
`;

Default.args = {
children: markdown,
backgroundColor: "#fff",
onClick: () => console.log("clicked"),
onDoubleClick: () => console.log("double clicked clicked"),
};
1 change: 1 addition & 0 deletions web/src/beta/components/Markdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const Wrapper = styled.div<{ styles?: Typography; dark: boolean }>`
border-bottom: none;
}

/* TODO: Fix hardcoded colors here */
code {
background-color: ${({ dark }) =>
dark ? "rgba(240, 246, 252, 0.15)" : "rgba(27, 31, 35, 0.05)"};
Expand Down
4 changes: 2 additions & 2 deletions web/src/beta/components/PopoverMenuContent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Icon, { Icons } from "@reearth/beta/components/Icon";
import Icon from "@reearth/beta/components/Icon";
import { css, styled } from "@reearth/services/theme";

export type MenuItem = {
name: string;
isSelected?: boolean;
icon?: Icons;
icon?: string;
disabled?: boolean;
onClick?: () => void;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { MouseEvent, useCallback, useState } from "react";
import TextInput from "@reearth/beta/components/fields/common/TextInput";
import ListItem from "@reearth/beta/components/ListItem";
import PopoverMenuContent from "@reearth/beta/components/PopoverMenuContent";
import Text from "@reearth/beta/components/Text";
import type { LayerNameUpdateProps } from "@reearth/beta/features/Editor/useLayers";

type LayerItemProps = {
Expand Down Expand Up @@ -90,7 +89,7 @@ const LayerItem = ({
onBlur={handleEditExit}
/>
) : (
<Text size="body">{layerTitle}</Text>
layerTitle
)}
</ListItem>
);
Expand Down
11 changes: 9 additions & 2 deletions web/src/beta/features/Editor/useStorytelling.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";

import type { FlyTo } from "@reearth/beta/lib/core/types";
import type { Camera } from "@reearth/beta/utils/value";
Expand All @@ -18,6 +18,8 @@ const getPage = (id?: string, pages?: Page[]) => {

export default function ({ sceneId, onFlyTo }: Props) {
const t = useT();
const timeoutRef = useRef<NodeJS.Timeout>();

const {
useStoriesQuery,
useCreateStoryPage,
Expand Down Expand Up @@ -66,7 +68,12 @@ export default function ({ sceneId, onFlyTo }: Props) {
if (!destination) return;

const duration = camera.fields.find(f => f.id === "cameraDuration")?.value as number;
onFlyTo({ ...destination }, { duration });
const delay = (camera.fields.find(f => f.id === "cameraDelay")?.value ?? 0) as number;

if (timeoutRef.current) clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(() => {
onFlyTo({ ...destination }, { duration });
}, delay * 1000);
}
},
[selectedStory?.pages, onFlyTo],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { debounce } from "lodash-es";
import { useContext, useCallback, useLayoutEffect, useRef, useMemo, useState } from "react";

import Markdown from "@reearth/beta/components/Markdown";
import { useT } from "@reearth/services/i18n";
import { styled } from "@reearth/services/theme";

import { BlockContext } from "../common/Wrapper";

export type Props = {
text: string;
onUpdate: (text: string) => void;
};

const MdBlockEditor: React.FC<Props> = ({ text, onUpdate }) => {
const textareaRef = useRef<HTMLTextAreaElement>(null);
const t = useT();
const context = useContext(BlockContext);

const [value, setValue] = useState(text);

const debouncedHandleTextUpdate = useMemo(() => debounce(onUpdate, 1000), [onUpdate]);

const onChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setValue(e.currentTarget.value);
debouncedHandleTextUpdate(e.currentTarget.value);
},
[debouncedHandleTextUpdate],
);

useLayoutEffect(() => {
if (!textareaRef?.current) return;
// Reset height - important to shrink on delete
textareaRef.current.style.height = "inherit";
// Set height
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
}, [value, context?.editMode]);

return context?.editMode ? (
<StyledTextArea
ref={textareaRef}
placeholder={t("Add markdown text here")}
value={value}
onChange={onChange}
/>
) : (
<StyledMarkdown empty={!value}>{value || t("Add markdown text here")}</StyledMarkdown>
);
};

const StyledTextArea = styled.textarea`
width: 100%;
resize: none;
overflow: hidden;
${({ value }) => !value && "min-height: 115px;"}
border: none;
font-size: 14px;
padding: 0px;
outline: none;
`;

const StyledMarkdown = styled(Markdown)<{ empty: boolean }>`
${({ empty }) => empty && "min-height: 115px;"}
font-size: 14px;
opacity: ${({ empty }) => (!empty ? 1 : 0.6)};
`;

export default MdBlockEditor;
Loading
Loading