Skip to content

Commit

Permalink
[fix] provide SidebarModalContext in RichtextToolbar to avoid studio …
Browse files Browse the repository at this point in the history
…crash

Issue: https://linear.app/plasmic/issue/PLA-10852
Change-Id: I8ef0976d7238962ae9d683b06dfa5c7e6c8a6da1
GitOrigin-RevId: ca163b71a2271861400ff1db65a14e6e2dcde2ad
  • Loading branch information
IcaroG authored and Copybara committed May 27, 2024
1 parent ebdd06f commit acd5f59
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 168 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CustomCssProps } from "@/wab/client/components/canvas/CanvasText";
import { TplTagElement } from "@/wab/client/components/canvas/slate";
import { tags } from "@/wab/client/components/canvas/subdeps";
import { SidebarModalProvider } from "@/wab/client/components/sidebar/SidebarModal";
import Button from "@/wab/client/components/widgets/Button";
import {
ColorPicker,
Expand Down Expand Up @@ -171,178 +172,183 @@ function RichTextToolbar_(
}
);
return (
<PlasmicRichTextToolbar
{...props}
root={{ ref }}
style={{
position: "absolute",
top: studioCtx.focusedMode ? 60 : 12,
}}
hideBlock={!showBlock}
block={{
props: {
"aria-label": "Block type",
children: [
...blocks.map((b) => (
<Select.Option
key={b.tag}
value={b.tag}
aria-label={b.label}
textValue={b.label}
>
<Icon icon={b.icon} style={{ marginRight: 4 }} /> {b.label}
</Select.Option>
)),
<Select.Option key={null} value={null} textValue={"Default"}>
<Icon icon={TextsvgIcon} style={{ marginRight: 4 }} />
Default
</Select.Option>,
],
onChange: (tag) => runInEditor("WRAP_BLOCK", tag),
value: block || null,
},
}}
currentColor={{
style: {
background: currentColor,
},
}}
color={{
wrap: (node) => (
<Popover
visible={colorPickerVisible}
onVisibleChange={(visible) => {
setColorPickerVisible(visible);
markCss({ color: currentColor }, false);
}}
transitionName=""
content={() =>
colorPickerVisible && (
<div style={{ width: 250 }}>
<ColorPicker
color={currentColor}
onChange={(color: string) => {
const { editor } = ctx;
const oldColor = (editor ? Editor.marks(editor) : {})
?.color;
if (oldColor !== color) {
markCss({ color }, false);
}
}}
/>
<div style={{ marginTop: 8 }}>
<Button
onClick={() => {
markCss({ color: undefined });
setColorPickerVisible(false);
<SidebarModalProvider>
<PlasmicRichTextToolbar
{...props}
root={{ ref }}
style={{
position: "absolute",
top: studioCtx.focusedMode ? 60 : 12,
}}
hideBlock={!showBlock}
block={{
props: {
"aria-label": "Block type",
children: [
...blocks.map((b) => (
<Select.Option
key={b.tag}
value={b.tag}
aria-label={b.label}
textValue={b.label}
>
<Icon icon={b.icon} style={{ marginRight: 4 }} /> {b.label}
</Select.Option>
)),
<Select.Option key={null} value={null} textValue={"Default"}>
<Icon icon={TextsvgIcon} style={{ marginRight: 4 }} />
Default
</Select.Option>,
],
onChange: (tag) => runInEditor("WRAP_BLOCK", tag),
value: block || null,
},
}}
currentColor={{
style: {
background: currentColor,
},
}}
color={{
wrap: (node) => (
<Popover
visible={colorPickerVisible}
onVisibleChange={(visible) => {
setColorPickerVisible(visible);
markCss({ color: currentColor }, false);
}}
transitionName=""
content={() =>
colorPickerVisible && (
<div style={{ width: 250 }}>
<ColorPicker
color={currentColor}
onChange={(color: string) => {
const { editor } = ctx;
const oldColor = (editor ? Editor.marks(editor) : {})
?.color;
if (oldColor !== color) {
markCss({ color }, false);
}
}}
>
Unset color
</Button>
/>
<div style={{ marginTop: 8 }}>
<Button
onClick={() => {
markCss({ color: undefined });
setColorPickerVisible(false);
}}
>
Unset color
</Button>
</div>
</div>
</div>
)
}
trigger="click"
>
{node}
</Popover>
),
}}
fontWeight={{
props: {
// TODO: Make button active if selection is bold according to marks.
"aria-label": "Bold",
onClick: () => runInEditor("BOLD"),
menu: () => (
<Menu>
{fontWeightOptions.map((option) => (
)
}
trigger="click"
>
{node}
</Popover>
),
}}
fontWeight={{
props: {
// TODO: Make button active if selection is bold according to marks.
"aria-label": "Bold",
onClick: () => runInEditor("BOLD"),
menu: () => (
<Menu>
{fontWeightOptions.map((option) => (
<Menu.Item
aria-label={option.label}
key={option.value}
onClick={() =>
markCss({ fontWeight: `${option.value}` as any })
}
>
{option.value} - {option.label}
</Menu.Item>
))}
<Menu.Item
aria-label={option.label}
key={option.value}
onClick={() =>
markCss({ fontWeight: `${option.value}` as any })
}
aria-label="Unset"
onClick={() => markCss({ fontWeight: undefined })}
>
{option.value} - {option.label}
Unset
</Menu.Item>
))}
<Menu.Item
aria-label="Unset"
onClick={() => markCss({ fontWeight: undefined })}
>
Unset
</Menu.Item>
</Menu>
),
},
}}
fontStyle={{
// TODO: Make button active if selection is italic according to marks.
props: {
onClick: () => runInEditor("ITALIC"),
},
}}
textDecoration={{
// TODO: Make button active if selection has text-decoration according
// to marks.
props: {
"aria-label": "Underline",
onClick: () => runInEditor("UNDERLINE"),
menu: () => (
<Menu>
<Menu.Item
aria-label="Underline"
onClick={() => runInEditor("UNDERLINE")}
>
<Icon icon={UnderlinesvgIcon} /> Underline
</Menu.Item>
<Menu.Item
aria-label="Strikethrough"
onClick={() => runInEditor("STRIKETHROUGH")}
>
<Icon icon={StrikeIcon} /> Strikethrough
</Menu.Item>
<Menu.Item
aria-label="Unset"
onClick={() => markCss({ textDecorationLine: undefined })}
>
Unset
</Menu.Item>
</Menu>
),
},
}}
inline={{
// TODO: Make button active if selection has link, code or span.
props: {
"aria-label": "Link",
onClick: () => runInEditor("LINK"),
menu: () => (
<Menu>
<Menu.Item aria-label="Link" onClick={() => runInEditor("LINK")}>
<Icon icon={LinksvgIcon} style={{ marginRight: 4 }} />
Link
</Menu.Item>
<Menu.Item
aria-label="Inline code"
onClick={() => runInEditor("CODE")}
>
<Icon icon={CodesvgIcon} style={{ marginRight: 4 }} />
Inline code
</Menu.Item>
<Menu.Item
aria-label="Span element"
onClick={() => runInEditor("SPAN")}
>
<Icon icon={TextsvgIcon} style={{ marginRight: 4 }} />
Span element
</Menu.Item>
</Menu>
),
},
}}
/>
</Menu>
),
},
}}
fontStyle={{
// TODO: Make button active if selection is italic according to marks.
props: {
onClick: () => runInEditor("ITALIC"),
},
}}
textDecoration={{
// TODO: Make button active if selection has text-decoration according
// to marks.
props: {
"aria-label": "Underline",
onClick: () => runInEditor("UNDERLINE"),
menu: () => (
<Menu>
<Menu.Item
aria-label="Underline"
onClick={() => runInEditor("UNDERLINE")}
>
<Icon icon={UnderlinesvgIcon} /> Underline
</Menu.Item>
<Menu.Item
aria-label="Strikethrough"
onClick={() => runInEditor("STRIKETHROUGH")}
>
<Icon icon={StrikeIcon} /> Strikethrough
</Menu.Item>
<Menu.Item
aria-label="Unset"
onClick={() => markCss({ textDecorationLine: undefined })}
>
Unset
</Menu.Item>
</Menu>
),
},
}}
inline={{
// TODO: Make button active if selection has link, code or span.
props: {
"aria-label": "Link",
onClick: () => runInEditor("LINK"),
menu: () => (
<Menu>
<Menu.Item
aria-label="Link"
onClick={() => runInEditor("LINK")}
>
<Icon icon={LinksvgIcon} style={{ marginRight: 4 }} />
Link
</Menu.Item>
<Menu.Item
aria-label="Inline code"
onClick={() => runInEditor("CODE")}
>
<Icon icon={CodesvgIcon} style={{ marginRight: 4 }} />
Inline code
</Menu.Item>
<Menu.Item
aria-label="Span element"
onClick={() => runInEditor("SPAN")}
>
<Icon icon={TextsvgIcon} style={{ marginRight: 4 }} />
Span element
</Menu.Item>
</Menu>
),
},
}}
/>
</SidebarModalProvider>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const SidebarModalContext = React.createContext<Store | undefined>(undefined);
function useSidebarModalContext() {
return ensure(
React.useContext(SidebarModalContext),
"Unexpected nulish SidebarModalContext"
"Unexpected nullish SidebarModalContext"
);
}

Expand Down

0 comments on commit acd5f59

Please sign in to comment.