mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: select the export bcg image and bcg color from appState
This commit is contained in:
parent
f15417f864
commit
f57cd7e2d5
20 changed files with 491 additions and 97 deletions
|
@ -9,6 +9,7 @@ import {
|
|||
actionChangeExportEmbedScene,
|
||||
actionChangeExportScale,
|
||||
actionChangeProjectName,
|
||||
actionChangeExportBackgroundImage,
|
||||
} from "../actions/actionExport";
|
||||
import { probablySupportsClipboardBlob } from "../clipboard";
|
||||
import {
|
||||
|
@ -16,6 +17,8 @@ import {
|
|||
EXPORT_IMAGE_TYPES,
|
||||
isFirefox,
|
||||
EXPORT_SCALES,
|
||||
EXPORT_BACKGROUND_IMAGES,
|
||||
DEFAULT_EXPORT_BACKGROUND_IMAGE,
|
||||
} from "../constants";
|
||||
|
||||
import { canvasToBlob } from "../data/blob";
|
||||
|
@ -34,6 +37,7 @@ import { Tooltip } from "./Tooltip";
|
|||
import "./ImageExportDialog.scss";
|
||||
import { useAppProps } from "./App";
|
||||
import { FilledButton } from "./FilledButton";
|
||||
import Select from "./Select";
|
||||
|
||||
const supportsContextFilters =
|
||||
"filter" in document.createElement("canvas").getContext("2d")!;
|
||||
|
@ -74,6 +78,10 @@ const ImageExportModal = ({
|
|||
const [exportWithBackground, setExportWithBackground] = useState(
|
||||
appState.exportBackground,
|
||||
);
|
||||
const [exportBackgroundImage, setExportBackgroundImage] = useState<string>(
|
||||
DEFAULT_EXPORT_BACKGROUND_IMAGE,
|
||||
);
|
||||
|
||||
const [exportDarkMode, setExportDarkMode] = useState(
|
||||
appState.exportWithDarkMode,
|
||||
);
|
||||
|
@ -169,6 +177,20 @@ const ImageExportModal = ({
|
|||
label={t("imageExportDialog.label.withBackground")}
|
||||
name="exportBackgroundSwitch"
|
||||
>
|
||||
<Select
|
||||
items={EXPORT_BACKGROUND_IMAGES}
|
||||
ariaLabel={t("imageExportDialog.label.backgroundImage")}
|
||||
placeholder={t("imageExportDialog.label.backgroundImage")}
|
||||
value={exportBackgroundImage}
|
||||
onChange={(value) => {
|
||||
setExportBackgroundImage(value);
|
||||
actionManager.executeAction(
|
||||
actionChangeExportBackgroundImage,
|
||||
"ui",
|
||||
value,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
name="exportBackgroundSwitch"
|
||||
checked={exportWithBackground}
|
||||
|
|
69
src/components/Select.scss
Normal file
69
src/components/Select.scss
Normal file
|
@ -0,0 +1,69 @@
|
|||
.Select {
|
||||
&__trigger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 15px;
|
||||
line-height: 1;
|
||||
gap: 5px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
|
||||
&__trigger-icon {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
&__content {
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-island);
|
||||
border-radius: var(--border-radius-md);
|
||||
padding: calc(var(--padding) * var(--space-factor));
|
||||
background-color: var(--input-bg-color);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&__viewport {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
&__item {
|
||||
font-size: 0.8rem;
|
||||
line-height: 1;
|
||||
border-radius: var(--border-radius-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 1rem;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary-color);
|
||||
|
||||
&[data-highlighted] {
|
||||
outline: none;
|
||||
background-color: var(--button-hover-bg);
|
||||
}
|
||||
|
||||
&[data-state="checked"] {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--input-bg-color);
|
||||
}
|
||||
|
||||
&[data-highlighted][data-state="checked"] {
|
||||
background-color: var(--color-primary-darker);
|
||||
}
|
||||
}
|
||||
|
||||
&__scroll-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 25px;
|
||||
background-color: white;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
77
src/components/Select.tsx
Normal file
77
src/components/Select.tsx
Normal file
|
@ -0,0 +1,77 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import clxs from "clsx";
|
||||
import * as RadixSelect from "@radix-ui/react-select";
|
||||
import "./Select.scss";
|
||||
import { tablerChevronDownIcon, tablerChevronUpIcon } from "./icons";
|
||||
|
||||
type SelectItems = Record<string, string>;
|
||||
|
||||
export type SelectProps = {
|
||||
items: SelectItems;
|
||||
value: keyof SelectItems;
|
||||
onChange: (value: keyof SelectItems) => void;
|
||||
placeholder?: string;
|
||||
ariaLabel?: string;
|
||||
};
|
||||
|
||||
const Select = ({
|
||||
items,
|
||||
value,
|
||||
onChange,
|
||||
placeholder,
|
||||
ariaLabel,
|
||||
}: SelectProps) => (
|
||||
<RadixSelect.Root value={value} onValueChange={onChange}>
|
||||
<RadixSelect.Trigger
|
||||
className="Select__trigger"
|
||||
aria-label={ariaLabel ?? placeholder}
|
||||
>
|
||||
{placeholder && <RadixSelect.Value placeholder={placeholder} />}
|
||||
<RadixSelect.Icon className="Select__trigger-icon">
|
||||
{tablerChevronDownIcon}
|
||||
</RadixSelect.Icon>
|
||||
</RadixSelect.Trigger>
|
||||
<RadixSelect.Content
|
||||
className="Select__content"
|
||||
position="popper"
|
||||
align="center"
|
||||
>
|
||||
<RadixSelect.ScrollUpButton className="Select__scroll-button">
|
||||
{tablerChevronUpIcon}
|
||||
</RadixSelect.ScrollUpButton>
|
||||
|
||||
<RadixSelect.Viewport className="Select__viewport">
|
||||
{Object.entries(items).map(([itemValue, itemLabel]) => (
|
||||
<SelectItem value={itemValue} key={itemValue}>
|
||||
{itemLabel}
|
||||
</SelectItem>
|
||||
))}
|
||||
</RadixSelect.Viewport>
|
||||
|
||||
<RadixSelect.ScrollDownButton className="Select__scroll-button">
|
||||
{tablerChevronDownIcon}
|
||||
</RadixSelect.ScrollDownButton>
|
||||
</RadixSelect.Content>
|
||||
</RadixSelect.Root>
|
||||
);
|
||||
|
||||
type SelectItemProps = React.ComponentProps<typeof RadixSelect.Item>;
|
||||
|
||||
const SelectItem = forwardRef(
|
||||
(
|
||||
{ children, className, ...props }: SelectItemProps,
|
||||
forwardedRef: React.ForwardedRef<HTMLDivElement>,
|
||||
) => {
|
||||
return (
|
||||
<RadixSelect.Item
|
||||
className={clxs("Select__item", className)}
|
||||
{...props}
|
||||
ref={forwardedRef}
|
||||
>
|
||||
<RadixSelect.ItemText>{children}</RadixSelect.ItemText>
|
||||
</RadixSelect.Item>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export default Select;
|
|
@ -1655,3 +1655,19 @@ export const frameToolIcon = createIcon(
|
|||
</g>,
|
||||
tablerIconProps,
|
||||
);
|
||||
|
||||
export const tablerChevronDownIcon = createIcon(
|
||||
<>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M6 9l6 6l6 -6"></path>
|
||||
</>,
|
||||
tablerIconProps,
|
||||
);
|
||||
|
||||
export const tablerChevronUpIcon = createIcon(
|
||||
<>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M6 15l6 -6l6 6"></path>
|
||||
</>,
|
||||
tablerIconProps,
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue