feat: migrate to react-modal-sheet

This commit is contained in:
thecodrr
2022-05-31 08:58:33 +05:00
parent 94a06e829a
commit c9efde1b86
12 changed files with 247 additions and 48 deletions

View File

@@ -2,7 +2,6 @@ import { PropsWithChildren } from "react";
import { FlexProps } from "rebass";
import { MenuOptions } from "./useMenu";
import { MenuItem as MenuItemType } from "./types";
import "react-spring-bottom-sheet/dist/style.css";
declare type MenuProps = MenuContainerProps & {
items: MenuItemType[];
closeMenu: () => void;

View File

@@ -44,8 +44,7 @@ import { getPosition } from "./useMenu";
import MenuItem from "./menuitem";
// import { useMenuTrigger, useMenu, getPosition } from "../../hooks/useMenu";
import Modal from "react-modal";
import { BottomSheet } from "react-spring-bottom-sheet";
import "react-spring-bottom-sheet/dist/style.css";
import Sheet from "react-modal-sheet";
import { useIsMobile } from "../../toolbar/stores/toolbar-store";
// import { store as selectionStore } from "../../stores/selectionstore";
function useMenuFocus(items, onAction, onClose) {
@@ -272,5 +271,15 @@ export function MenuPresenter(props) {
}
export function ActionSheetPresenter(props) {
var _a = props.items, items = _a === void 0 ? [] : _a, isOpen = props.isOpen, _b = props.onClose, onClose = _b === void 0 ? function () { } : _b, children = props.children, sx = props.sx, _c = props.blocking, blocking = _c === void 0 ? true : _c, containerProps = __rest(props, ["items", "isOpen", "onClose", "children", "sx", "blocking"]);
return (_jsx(BottomSheet, __assign({ open: isOpen, onDismiss: onClose, blocking: blocking }, { children: props.children ? (props.children) : (_jsx(Menu, __assign({ items: items, closeMenu: onClose, sx: __assign({ flex: 1, boxShadow: "none", border: "none" }, sx) }, containerProps))) })));
return (_jsxs(Sheet, __assign({ isOpen: isOpen, onClose: onClose, springConfig: {
stiffness: 300,
damping: 30,
mass: 0.2,
duration: 300,
} }, { children: [_jsxs(Sheet.Container, __assign({ style: {
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
boxShadow: "none",
paddingBottom: 30,
} }, { children: [_jsx(Sheet.Header, {}), _jsx(Sheet.Content, { children: props.children ? (props.children) : (_jsx(Menu, __assign({ items: items, closeMenu: onClose, sx: __assign({ flex: 1, boxShadow: "none", border: "none" }, sx) }, containerProps))) })] })), _jsx(Sheet.Backdrop, {})] })));
}

View File

@@ -1,7 +1,8 @@
import { Node } from "@tiptap/core";
export declare type AttachmentType = "image" | "file";
export interface AttachmentOptions {
onDownloadAttachment: (attachment: Attachment) => boolean;
onOpenAttachmentPicker: () => boolean;
onOpenAttachmentPicker: (type: AttachmentType) => boolean;
}
export declare type Attachment = AttachmentProgress & {
hash: string;
@@ -17,7 +18,7 @@ export declare type AttachmentProgress = {
declare module "@tiptap/core" {
interface Commands<ReturnType> {
attachment: {
openAttachmentPicker: () => ReturnType;
openAttachmentPicker: (type: AttachmentType) => ReturnType;
insertAttachment: (attachment: Attachment) => ReturnType;
downloadAttachment: (attachment: Attachment) => ReturnType;
setProgress: (progress: AttachmentProgress) => ReturnType;

View File

@@ -68,11 +68,9 @@ export var AttachmentNode = Node.create({
return _this.options.onDownloadAttachment(attachment);
};
},
openAttachmentPicker: function () {
return function (_a) {
return _this.options.onOpenAttachmentPicker();
};
},
openAttachmentPicker: function (type) { return function () {
return _this.options.onOpenAttachmentPicker(type);
}; },
setProgress: function (options) {
return function (_a) {
var e_1, _b;

View File

@@ -124,7 +124,9 @@ var imageActionSheet = function (editor) { return ({
type: "menuitem",
title: "Upload from disk",
icon: "upload",
onClick: function () { },
onClick: function () {
return editor === null || editor === void 0 ? void 0 : editor.chain().focus().openAttachmentPicker("image").run();
},
},
{
key: "upload-from-url",
@@ -215,7 +217,7 @@ var attachment = function (editor) { return ({
title: "Attachment",
icon: "attachment",
isChecked: editor === null || editor === void 0 ? void 0 : editor.isActive("attachment"),
onClick: function () { return editor === null || editor === void 0 ? void 0 : editor.chain().focus().openAttachmentPicker().run(); },
onClick: function () { return editor === null || editor === void 0 ? void 0 : editor.chain().focus().openAttachmentPicker("file").run(); },
}); };
var tasklist = function (editor) { return ({
key: "tasklist",

View File

@@ -27,7 +27,7 @@ var __read = (this && this.__read) || function (o, n) {
};
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { ToolButton } from "../components/tool-button";
import { MenuPresenter } from "../../components/menu/menu";
import { PopupPresenter } from "../../components/menu/menu";
import { useRef, useState } from "react";
import { Flex } from "rebass";
import { Input } from "@rebass/forms";
@@ -84,7 +84,7 @@ export function Link(props) {
: editor.state.doc.textBetween(from, to);
setText(selectedText);
setIsOpen(true);
}, toggled: isOpen || !!isEditing }), _jsx(MenuPresenter, __assign({ options: {
}, toggled: isOpen || !!isEditing }), _jsx(PopupPresenter, __assign({ mobile: "sheet", desktop: "menu", options: {
type: "menu",
position: {
target: targetRef.current || buttonRef.current || undefined,
@@ -110,5 +110,5 @@ export function Link(props) {
commandChain.run();
setIsOpen(false);
},
} }, { children: _jsxs(Flex, __assign({ sx: { p: 1, width: 300, flexDirection: "column" } }, { children: [_jsx(Input, { type: "text", placeholder: "Link text", value: text, onChange: function (e) { return setText(e.target.value); } }), _jsx(Input, { type: "url", sx: { mt: 1 }, autoFocus: true, placeholder: "https://example.com/", value: href, onChange: function (e) { return setHref(e.target.value); } })] })) })) }))] }));
} }, { children: _jsxs(Flex, __assign({ sx: { p: 1, flexDirection: "column" } }, { children: [_jsx(Input, { type: "text", placeholder: "Link text", value: text, onChange: function (e) { return setText(e.target.value); } }), _jsx(Input, { type: "url", sx: { mt: 1 }, autoFocus: true, placeholder: "https://example.com/", value: href, onChange: function (e) { return setHref(e.target.value); } })] })) })) }))] }));
}

View File

@@ -47,6 +47,7 @@
"re-resizable": "^6.9.9",
"react-color": "^2.19.3",
"react-modal": "^3.14.4",
"react-modal-sheet": "file:../react-modal-sheet",
"react-spring-bottom-sheet": "^3.4.0",
"react-toggle": "^4.1.2",
"reactjs-popup": "^2.0.5",
@@ -77,6 +78,37 @@
"typescript": "^4.7.2",
"typescript-plugin-css-modules": "^3.4.0",
"web-vitals": "^2.1.4"
},
"peerDependencies": {
"framer-motion": "^4.1.17"
}
},
"../react-modal-sheet": {
"version": "1.5.1",
"license": "MIT",
"dependencies": {
"react-merge-refs": "1.1.0"
},
"devDependencies": {
"@types/react": "17.0.37",
"@types/react-dom": "17.0.11",
"@types/styled-components": "5.1.7",
"csstype": "3.0.6",
"framer-motion": "^4.1.17",
"husky": "4.2.5",
"react": "17.0.2",
"react-dom": "17.0.2",
"styled-components": "5.3.3",
"tsdx": "0.14.1",
"tslib": "2.1.0",
"typescript": "4.5.5"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"framer-motion": ">=2",
"react": ">=16"
}
},
"../themeprovider": {
@@ -11080,6 +11112,35 @@
"node": ">=0.10.0"
}
},
"node_modules/framer-motion": {
"version": "4.1.17",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-4.1.17.tgz",
"integrity": "sha512-thx1wvKzblzbs0XaK2X0G1JuwIdARcoNOW7VVwjO8BUltzXPyONGAElLu6CiCScsOQRI7FIk/45YTFtJw5Yozw==",
"peer": true,
"dependencies": {
"framesync": "5.3.0",
"hey-listen": "^1.0.8",
"popmotion": "9.3.6",
"style-value-types": "4.1.4",
"tslib": "^2.1.0"
},
"optionalDependencies": {
"@emotion/is-prop-valid": "^0.8.2"
},
"peerDependencies": {
"react": ">=16.8 || ^17.0.0",
"react-dom": ">=16.8 || ^17.0.0"
}
},
"node_modules/framesync": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/framesync/-/framesync-5.3.0.tgz",
"integrity": "sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA==",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -11699,6 +11760,12 @@
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
"dev": true
},
"node_modules/hey-listen": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
"peer": true
},
"node_modules/highlight.js": {
"version": "11.5.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.5.1.tgz",
@@ -17058,6 +17125,18 @@
"node": ">=6"
}
},
"node_modules/popmotion": {
"version": "9.3.6",
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-9.3.6.tgz",
"integrity": "sha512-ZTbXiu6zIggXzIliMi8LGxXBF5ST+wkpXGEjeTUDUOCdSQ356hij/xjeUdv0F8zCQNeqB1+PR5/BB+gC+QLAPw==",
"peer": true,
"dependencies": {
"framesync": "5.3.0",
"hey-listen": "^1.0.8",
"style-value-types": "4.1.4",
"tslib": "^2.1.0"
}
},
"node_modules/portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
@@ -19276,6 +19355,10 @@
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18"
}
},
"node_modules/react-modal-sheet": {
"resolved": "../react-modal-sheet",
"link": true
},
"node_modules/react-refresh": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
@@ -21910,6 +21993,16 @@
"webpack": "^4.0.0 || ^5.0.0"
}
},
"node_modules/style-value-types": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-4.1.4.tgz",
"integrity": "sha512-LCJL6tB+vPSUoxgUBt9juXIlNJHtBMy8jkXzUJSBzeHWdBu6lhzHqCvLVkXFGsFIlNa2ln1sQHya/gzaFmB2Lg==",
"peer": true,
"dependencies": {
"hey-listen": "^1.0.8",
"tslib": "^2.1.0"
}
},
"node_modules/styled-system": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/styled-system/-/styled-system-5.1.5.tgz",
@@ -33994,6 +34087,29 @@
"map-cache": "^0.2.2"
}
},
"framer-motion": {
"version": "4.1.17",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-4.1.17.tgz",
"integrity": "sha512-thx1wvKzblzbs0XaK2X0G1JuwIdARcoNOW7VVwjO8BUltzXPyONGAElLu6CiCScsOQRI7FIk/45YTFtJw5Yozw==",
"peer": true,
"requires": {
"@emotion/is-prop-valid": "^0.8.2",
"framesync": "5.3.0",
"hey-listen": "^1.0.8",
"popmotion": "9.3.6",
"style-value-types": "4.1.4",
"tslib": "^2.1.0"
}
},
"framesync": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/framesync/-/framesync-5.3.0.tgz",
"integrity": "sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA==",
"peer": true,
"requires": {
"tslib": "^2.1.0"
}
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -34462,6 +34578,12 @@
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
"dev": true
},
"hey-listen": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
"peer": true
},
"highlight.js": {
"version": "11.5.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.5.1.tgz",
@@ -38590,6 +38712,18 @@
"ts-pnp": "^1.1.6"
}
},
"popmotion": {
"version": "9.3.6",
"resolved": "https://registry.npmjs.org/popmotion/-/popmotion-9.3.6.tgz",
"integrity": "sha512-ZTbXiu6zIggXzIliMi8LGxXBF5ST+wkpXGEjeTUDUOCdSQ356hij/xjeUdv0F8zCQNeqB1+PR5/BB+gC+QLAPw==",
"peer": true,
"requires": {
"framesync": "5.3.0",
"hey-listen": "^1.0.8",
"style-value-types": "4.1.4",
"tslib": "^2.1.0"
}
},
"portfinder": {
"version": "1.0.28",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
@@ -40443,6 +40577,24 @@
"warning": "^4.0.3"
}
},
"react-modal-sheet": {
"version": "file:../react-modal-sheet",
"requires": {
"@types/react": "17.0.37",
"@types/react-dom": "17.0.11",
"@types/styled-components": "5.1.7",
"csstype": "3.0.6",
"framer-motion": "^4.1.17",
"husky": "4.2.5",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-merge-refs": "1.1.0",
"styled-components": "5.3.3",
"tsdx": "0.14.1",
"tslib": "2.1.0",
"typescript": "4.5.5"
}
},
"react-refresh": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
@@ -42571,6 +42723,16 @@
"schema-utils": "^2.7.0"
}
},
"style-value-types": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-4.1.4.tgz",
"integrity": "sha512-LCJL6tB+vPSUoxgUBt9juXIlNJHtBMy8jkXzUJSBzeHWdBu6lhzHqCvLVkXFGsFIlNa2ln1sQHya/gzaFmB2Lg==",
"peer": true,
"requires": {
"hey-listen": "^1.0.8",
"tslib": "^2.1.0"
}
},
"styled-system": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/styled-system/-/styled-system-5.1.5.tgz",

View File

@@ -43,6 +43,7 @@
"re-resizable": "^6.9.9",
"react-color": "^2.19.3",
"react-modal": "^3.14.4",
"react-modal-sheet": "file:../react-modal-sheet",
"react-spring-bottom-sheet": "^3.4.0",
"react-toggle": "^4.1.2",
"reactjs-popup": "^2.0.5",
@@ -74,6 +75,9 @@
"typescript-plugin-css-modules": "^3.4.0",
"web-vitals": "^2.1.4"
},
"peerDependencies": {
"framer-motion": "^4.1.17"
},
"scripts": {
"build": "./scripts/build.sh",
"watch": "./scripts/build.sh --watch"

View File

@@ -14,8 +14,7 @@ import { MenuItem as MenuItemType /*ResolvedMenuItem*/ } from "./types";
// import { useMenuTrigger, useMenu, getPosition } from "../../hooks/useMenu";
import Modal from "react-modal";
import { ThemeProvider } from "emotion-theming";
import { BottomSheet } from "react-spring-bottom-sheet";
import "react-spring-bottom-sheet/dist/style.css";
import Sheet from "react-modal-sheet";
import { useIsMobile } from "../../toolbar/stores/toolbar-store";
// import { store as selectionStore } from "../../stores/selectionstore";
@@ -424,22 +423,45 @@ export function ActionSheetPresenter(
} = props;
return (
<BottomSheet open={isOpen} onDismiss={onClose} blocking={blocking}>
{props.children ? (
props.children
) : (
<Menu
items={items}
closeMenu={onClose}
sx={{
flex: 1,
boxShadow: "none",
border: "none",
...sx,
}}
{...containerProps}
/>
)}
</BottomSheet>
<Sheet
isOpen={isOpen}
onClose={onClose}
springConfig={{
stiffness: 300,
damping: 30,
mass: 0.2,
duration: 300,
}}
>
<Sheet.Container
style={{
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
boxShadow: "none",
paddingBottom: 30,
}}
>
<Sheet.Header />
<Sheet.Content>
{props.children ? (
props.children
) : (
<Menu
items={items}
closeMenu={onClose}
sx={{
flex: 1,
boxShadow: "none",
border: "none",
...sx,
}}
{...containerProps}
/>
)}
</Sheet.Content>
</Sheet.Container>
<Sheet.Backdrop />
</Sheet>
);
}

View File

@@ -3,10 +3,11 @@ import { findChildren, ReactNodeViewRenderer } from "../react";
import { Attribute } from "@tiptap/core";
import { AttachmentComponent } from "./component";
export type AttachmentType = "image" | "file";
export interface AttachmentOptions {
// HTMLAttributes: Record<string, any>;
onDownloadAttachment: (attachment: Attachment) => boolean;
onOpenAttachmentPicker: () => boolean;
onOpenAttachmentPicker: (type: AttachmentType) => boolean;
}
export type Attachment = AttachmentProgress & {
@@ -25,7 +26,7 @@ export type AttachmentProgress = {
declare module "@tiptap/core" {
interface Commands<ReturnType> {
attachment: {
openAttachmentPicker: () => ReturnType;
openAttachmentPicker: (type: AttachmentType) => ReturnType;
insertAttachment: (attachment: Attachment) => ReturnType;
downloadAttachment: (attachment: Attachment) => ReturnType;
setProgress: (progress: AttachmentProgress) => ReturnType;
@@ -94,11 +95,9 @@ export const AttachmentNode = Node.create<AttachmentOptions>({
({}) => {
return this.options.onDownloadAttachment(attachment);
},
openAttachmentPicker:
() =>
({}) => {
return this.options.onOpenAttachmentPicker();
},
openAttachmentPicker: (type: AttachmentType) => () => {
return this.options.onOpenAttachmentPicker(type);
},
setProgress:
(options) =>
({ state, tr, dispatch }) => {

View File

@@ -156,7 +156,8 @@ const imageActionSheet = (editor: Editor | null): MenuItem => ({
type: "menuitem",
title: "Upload from disk",
icon: "upload",
onClick: () => {},
onClick: () =>
editor?.chain().focus().openAttachmentPicker("image").run(),
},
{
key: "upload-from-url",
@@ -290,7 +291,7 @@ const attachment = (editor: Editor | null): MenuItem => ({
title: "Attachment",
icon: "attachment",
isChecked: editor?.isActive("attachment"),
onClick: () => editor?.chain().focus().openAttachmentPicker().run(),
onClick: () => editor?.chain().focus().openAttachmentPicker("file").run(),
});
const tasklist = (editor: Editor | null): MenuItem => ({

View File

@@ -1,7 +1,7 @@
import { ToolProps } from "../types";
import { Editor } from "@tiptap/core";
import { ToolButton } from "../components/tool-button";
import { MenuPresenter } from "../../components/menu/menu";
import { MenuPresenter, PopupPresenter } from "../../components/menu/menu";
import { useRef, useState } from "react";
import { Flex } from "rebass";
import { Input } from "@rebass/forms";
@@ -143,7 +143,9 @@ export function Link(props: ToolProps) {
}}
toggled={isOpen || !!isEditing}
/>
<MenuPresenter
<PopupPresenter
mobile="sheet"
desktop="menu"
options={{
type: "menu",
position: {
@@ -180,7 +182,7 @@ export function Link(props: ToolProps) {
}}
// negativeButton={{ text: "Cancel", onClick: () => setIsOpen(false) }}
>
<Flex sx={{ p: 1, width: 300, flexDirection: "column" }}>
<Flex sx={{ p: 1, flexDirection: "column" }}>
<Input
type="text"
placeholder="Link text"
@@ -197,7 +199,7 @@ export function Link(props: ToolProps) {
/>
</Flex>
</Popup>
</MenuPresenter>
</PopupPresenter>
</>
);
}