mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: render footer as a component instead of render prop (#5970)
* feat: render footer as a component instead of render prop * Export FooterCenter as footer * remove useDevice export * revert some changes * remove * add spec * update specs * parse children into a dictionary * factor app footer components into a single file * Add docs * split app footer components Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
d2e371cdf0
commit
b704705ed8
17 changed files with 232 additions and 160 deletions
|
@ -13,6 +13,14 @@ Please add the latest change on the top under the correct section.
|
|||
|
||||
## Unreleased
|
||||
|
||||
### Features
|
||||
|
||||
- Render Footer as a component instead of render prop [#5970](https://github.com/excalidraw/excalidraw/pull/5970). You can read more about its usage [here](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#Footer)
|
||||
|
||||
#### BREAKING CHANGE
|
||||
|
||||
- With this change, the prop `renderFooter` is now removed.
|
||||
|
||||
### Excalidraw schema
|
||||
|
||||
- Merged `appState.currentItemStrokeSharpness` and `appState.currentItemLinearStrokeSharpness` into `appState.currentItemRoundness`. Renamed `changeSharpness` action to `changeRoundness`. Excalidraw element's `strokeSharpness` was changed to `roundness`. Check the PR for types and more details [#5553](https://github.com/excalidraw/excalidraw/pull/5553).
|
||||
|
|
|
@ -380,6 +380,31 @@ For a complete list of variables, check [theme.scss](https://github.com/excalidr
|
|||
|
||||
No, Excalidraw package doesn't come with collaboration built in, since the implementation is specific to each host app. We expose APIs which you can use to communicate with Excalidraw which you can use to implement it. You can check our own implementation [here](https://github.com/excalidraw/excalidraw/blob/master/src/excalidraw-app/index.tsx).
|
||||
|
||||
### Component API
|
||||
|
||||
#### Footer
|
||||
|
||||
Earlier we were using `renderFooter` prop to render custom footer which was removed in [#5970](https://github.com/excalidraw/excalidraw/pull/5970). Now you can pass a `Footer` component instead to render the custom UI for footer.
|
||||
|
||||
You will need to import the `Footer` component from the package and wrap your component with the Footer component. The `Footer` should a valid React Node.
|
||||
|
||||
**Usage**
|
||||
|
||||
```js
|
||||
import { Footer } from "@excalidraw/excalidraw";
|
||||
|
||||
const CustomFooter = () => <button> custom button</button>;
|
||||
const App = () => {
|
||||
return (
|
||||
<Excalidraw>
|
||||
<Footer>
|
||||
<CustomFooter />
|
||||
</Footer>
|
||||
</Excalidraw>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|
@ -392,7 +417,6 @@ No, Excalidraw package doesn't come with collaboration built in, since the imple
|
|||
| [`onPointerUpdate`](#onPointerUpdate) | Function | | Callback triggered when mouse pointer is updated. |
|
||||
| [`langCode`](#langCode) | string | `en` | Language code string |
|
||||
| [`renderTopRightUI`](#renderTopRightUI) | Function | | Function that renders custom UI in top right corner |
|
||||
| [`renderFooter `](#renderFooter) | Function | | Function that renders custom UI footer |
|
||||
| [`renderCustomStats`](#renderCustomStats) | Function | | Function that can be used to render custom stats on the stats dialog. |
|
||||
| [`renderSIdebar`](#renderSIdebar) | Function | | Render function that renders custom sidebar. |
|
||||
| [`viewModeEnabled`](#viewModeEnabled) | boolean | | This implies if the app is in view mode. |
|
||||
|
@ -613,14 +637,6 @@ import { defaultLang, languages } from "@excalidraw/excalidraw";
|
|||
|
||||
A function returning JSX to render custom UI in the top right corner of the app.
|
||||
|
||||
#### `renderFooter`
|
||||
|
||||
<pre>
|
||||
(isMobile: boolean, appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L79">AppState</a>) => JSX | null
|
||||
</pre>
|
||||
|
||||
A function returning JSX to render custom UI footer. For example, you can use this to render a language picker that was previously being rendered by Excalidraw itself (for now, you'll need to implement your own language picker).
|
||||
|
||||
#### `renderCustomStats`
|
||||
|
||||
A function that can be used to render custom stats (returns JSX) in the nerd stats dialog. For example you can use this prop to render the size of the elements in the storage.
|
||||
|
|
|
@ -68,6 +68,7 @@ const {
|
|||
viewportCoordsToSceneCoords,
|
||||
restoreElements,
|
||||
Sidebar,
|
||||
Footer,
|
||||
} = window.ExcalidrawLib;
|
||||
|
||||
const COMMENT_SVG = (
|
||||
|
@ -160,49 +161,6 @@ export default function App() {
|
|||
fetchData();
|
||||
}, [excalidrawAPI]);
|
||||
|
||||
const renderFooter = () => {
|
||||
return (
|
||||
<>
|
||||
{" "}
|
||||
<button
|
||||
className="custom-element"
|
||||
onClick={() => {
|
||||
excalidrawAPI?.setActiveTool({
|
||||
type: "custom",
|
||||
customType: "comment",
|
||||
});
|
||||
const url = `data:${MIME_TYPES.svg},${encodeURIComponent(
|
||||
`<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-message-circle"
|
||||
>
|
||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||
</svg>`,
|
||||
)}`;
|
||||
excalidrawAPI?.setCursor(`url(${url}), auto`);
|
||||
}}
|
||||
>
|
||||
{COMMENT_SVG}
|
||||
</button>
|
||||
<button
|
||||
className="custom-footer"
|
||||
onClick={() => alert("This is dummy footer")}
|
||||
>
|
||||
{" "}
|
||||
custom footer{" "}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const loadSceneOrLibrary = async () => {
|
||||
const file = await fileOpen({ description: "Excalidraw or library file" });
|
||||
const contents = await loadSceneOrLibraryFromBlob(file, null, null);
|
||||
|
@ -712,12 +670,49 @@ export default function App() {
|
|||
name="Custom name of drawing"
|
||||
UIOptions={{ canvasActions: { loadScene: false } }}
|
||||
renderTopRightUI={renderTopRightUI}
|
||||
renderFooter={renderFooter}
|
||||
onLinkOpen={onLinkOpen}
|
||||
onPointerDown={onPointerDown}
|
||||
onScrollChange={rerenderCommentIcons}
|
||||
renderSidebar={renderSidebar}
|
||||
/>
|
||||
>
|
||||
<Footer>
|
||||
<button
|
||||
className="custom-element"
|
||||
onClick={() => {
|
||||
excalidrawAPI?.setActiveTool({
|
||||
type: "custom",
|
||||
customType: "comment",
|
||||
});
|
||||
const url = `data:${MIME_TYPES.svg},${encodeURIComponent(
|
||||
`<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="feather feather-message-circle"
|
||||
>
|
||||
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
|
||||
</svg>`,
|
||||
)}`;
|
||||
excalidrawAPI?.setCursor(`url(${url}), auto`);
|
||||
}}
|
||||
>
|
||||
{COMMENT_SVG}
|
||||
</button>
|
||||
<button
|
||||
className="custom-footer"
|
||||
onClick={() => alert("This is dummy footer")}
|
||||
>
|
||||
{" "}
|
||||
custom footer{" "}
|
||||
</button>
|
||||
</Footer>
|
||||
</Excalidraw>
|
||||
{Object.keys(commentIcons || []).length > 0 && renderCommentIcons()}
|
||||
{comment && renderComment()}
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@ import { defaultLang } from "../../i18n";
|
|||
import { DEFAULT_UI_OPTIONS } from "../../constants";
|
||||
import { Provider } from "jotai";
|
||||
import { jotaiScope, jotaiStore } from "../../jotai";
|
||||
import Footer from "../../components/footer/FooterCenter";
|
||||
|
||||
const ExcalidrawBase = (props: ExcalidrawProps) => {
|
||||
const {
|
||||
|
@ -20,7 +21,6 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
|
|||
isCollaborating = false,
|
||||
onPointerUpdate,
|
||||
renderTopRightUI,
|
||||
renderFooter,
|
||||
renderSidebar,
|
||||
langCode = defaultLang.code,
|
||||
viewModeEnabled,
|
||||
|
@ -39,6 +39,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
|
|||
onLinkOpen,
|
||||
onPointerDown,
|
||||
onScrollChange,
|
||||
children,
|
||||
} = props;
|
||||
|
||||
const canvasActions = props.UIOptions?.canvasActions;
|
||||
|
@ -93,7 +94,6 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
|
|||
isCollaborating={isCollaborating}
|
||||
onPointerUpdate={onPointerUpdate}
|
||||
renderTopRightUI={renderTopRightUI}
|
||||
renderFooter={renderFooter}
|
||||
langCode={langCode}
|
||||
viewModeEnabled={viewModeEnabled}
|
||||
zenModeEnabled={zenModeEnabled}
|
||||
|
@ -113,7 +113,9 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
|
|||
onPointerDown={onPointerDown}
|
||||
onScrollChange={onScrollChange}
|
||||
renderSidebar={renderSidebar}
|
||||
/>
|
||||
>
|
||||
{children}
|
||||
</App>
|
||||
</Provider>
|
||||
</InitializeApp>
|
||||
);
|
||||
|
@ -236,3 +238,4 @@ export {
|
|||
} from "../../utils";
|
||||
|
||||
export { Sidebar } from "../../components/Sidebar/Sidebar";
|
||||
export { Footer };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue