mirror of
https://github.com/outline/outline.git
synced 2026-06-13 19:35:02 +03:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a97863d941 | |||
| 06b48d4276 | |||
| e3e44260de | |||
| 68fe78a20e | |||
| e978f63217 | |||
| 56ceff055e | |||
| 1cf9d4c6cb | |||
| 84bc70dfd8 |
@@ -42,9 +42,7 @@ export const changeTheme = createAction({
|
||||
isContextMenu ? t("Appearance") : t("Change theme"),
|
||||
analyticsName: "Change theme",
|
||||
placeholder: ({ t }) => t("Change theme to"),
|
||||
icon: function _Icon() {
|
||||
return stores.ui.resolvedTheme === "light" ? <SunIcon /> : <MoonIcon />;
|
||||
},
|
||||
icon: stores.ui.resolvedTheme === "light" ? <SunIcon /> : <MoonIcon />,
|
||||
keywords: "appearance display",
|
||||
section: SettingsSection,
|
||||
children: [changeToLightTheme, changeToDarkTheme, changeToSystemTheme],
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ArrowIcon, PlusIcon } from "outline-icons";
|
||||
import styled from "styled-components";
|
||||
import { stringToColor } from "@shared/utils/color";
|
||||
import RootStore from "~/stores/RootStore";
|
||||
import { LoginDialog } from "~/scenes/Login/components/LoginDialog";
|
||||
import TeamNew from "~/scenes/TeamNew";
|
||||
import TeamLogo from "~/components/TeamLogo";
|
||||
@@ -10,27 +9,25 @@ import { ActionContext } from "~/types";
|
||||
import Desktop from "~/utils/Desktop";
|
||||
import { TeamSection } from "../sections";
|
||||
|
||||
export const switchTeamsList = ({ stores }: { stores: RootStore }) =>
|
||||
export const switchTeamsList = ({ stores }: ActionContext) =>
|
||||
stores.auth.availableTeams?.map((session) => ({
|
||||
id: `switch-${session.id}`,
|
||||
name: session.name,
|
||||
analyticsName: "Switch workspace",
|
||||
section: TeamSection,
|
||||
keywords: "change switch workspace organization team",
|
||||
icon: function _Icon() {
|
||||
return (
|
||||
<StyledTeamLogo
|
||||
alt={session.name}
|
||||
model={{
|
||||
initial: session.name[0],
|
||||
avatarUrl: session.avatarUrl,
|
||||
id: session.id,
|
||||
color: stringToColor(session.id),
|
||||
}}
|
||||
size={24}
|
||||
/>
|
||||
);
|
||||
},
|
||||
icon: (
|
||||
<StyledTeamLogo
|
||||
alt={session.name}
|
||||
model={{
|
||||
initial: session.name[0],
|
||||
avatarUrl: session.avatarUrl,
|
||||
id: session.id,
|
||||
color: stringToColor(session.id),
|
||||
}}
|
||||
size={24}
|
||||
/>
|
||||
),
|
||||
visible: ({ currentTeamId }: ActionContext) => currentTeamId !== session.id,
|
||||
perform: () => (window.location.href = session.url),
|
||||
})) ?? [];
|
||||
|
||||
@@ -10,7 +10,9 @@ type Props = {
|
||||
};
|
||||
|
||||
// TODO: Refactor this component to allow injection from plugins
|
||||
const Analytics: React.FC = ({ children }: Props) => {
|
||||
const Analytics: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
// Google Analytics 3
|
||||
React.useEffect(() => {
|
||||
if (!env.GOOGLE_ANALYTICS_ID?.startsWith("UA-")) {
|
||||
|
||||
@@ -48,7 +48,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const AuthenticatedLayout: React.FC = ({ children }: Props) => {
|
||||
const AuthenticatedLayout: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const { ui, auth } = useStores();
|
||||
const location = useLocation();
|
||||
const layoutRef = React.useRef<HTMLDivElement>(null);
|
||||
@@ -111,11 +113,12 @@ const AuthenticatedLayout: React.FC = ({ children }: Props) => {
|
||||
!!team.getPreference(TeamPreference.Commenting);
|
||||
|
||||
const sidebarRight = (
|
||||
// @ts-expect-error - framer-motion v4 has TypeScript compatibility issues with React 18
|
||||
<AnimatePresence
|
||||
initial={false}
|
||||
key={ui.activeDocumentId ? "active" : "inactive"}
|
||||
>
|
||||
{(showHistory || showInsights || showComments) && (
|
||||
{showHistory || showInsights || showComments ? (
|
||||
<Route path={`/doc/${slug}`}>
|
||||
<SidebarRight>
|
||||
<React.Suspense fallback={null}>
|
||||
@@ -125,7 +128,7 @@ const AuthenticatedLayout: React.FC = ({ children }: Props) => {
|
||||
</React.Suspense>
|
||||
</SidebarRight>
|
||||
</Route>
|
||||
)}
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ const Content = styled.div<ContentProps>`
|
||||
`};
|
||||
`;
|
||||
|
||||
const CenteredContent: React.FC<Props> = ({
|
||||
const CenteredContent: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
maxWidth,
|
||||
...rest
|
||||
|
||||
@@ -132,7 +132,7 @@ function Collaborators(props: Props) {
|
||||
);
|
||||
|
||||
const renderAvatar = useCallback(
|
||||
({ model: collaborator, ...rest }) => {
|
||||
({ model: collaborator, ...rest }: any) => {
|
||||
const isPresent = presentIds.has(collaborator.id);
|
||||
const isEditing = editingIds.has(collaborator.id);
|
||||
const isObserving = observingUserId === collaborator.id;
|
||||
|
||||
@@ -11,7 +11,9 @@ type Props = {
|
||||
collection: Collection;
|
||||
};
|
||||
|
||||
export const CollectionBreadcrumb: React.FC<Props> = ({ collection }) => {
|
||||
export const CollectionBreadcrumb: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
collection,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
|
||||
@@ -52,7 +52,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const KBarPortal: React.FC = ({ children }: Props) => {
|
||||
const KBarPortal: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const { showing } = useKBar((state) => ({
|
||||
showing: state.visualState !== "hidden",
|
||||
}));
|
||||
|
||||
@@ -21,7 +21,7 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const ConfirmationDialog: React.FC<Props> = ({
|
||||
const ConfirmationDialog: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
onSubmit,
|
||||
children,
|
||||
submitText,
|
||||
|
||||
@@ -21,7 +21,7 @@ type Props = {
|
||||
to?: LocationDescriptor;
|
||||
href?: string;
|
||||
target?: "_blank";
|
||||
as?: string | React.ComponentType<any>;
|
||||
as?: string | React.ComponentType<React.PropsWithChildren<any>>;
|
||||
hide?: () => void;
|
||||
level?: number;
|
||||
icon?: React.ReactNode;
|
||||
@@ -45,7 +45,7 @@ const MenuItem = (
|
||||
ref: React.Ref<HTMLAnchorElement>
|
||||
) => {
|
||||
const content = React.useCallback(
|
||||
(props) => {
|
||||
(props: any) => {
|
||||
// Preventing default mousedown otherwise menu items do not work in Firefox,
|
||||
// which triggers the hideOnClickOutside handler first via mousedown – hiding
|
||||
// and un-rendering the menu contents.
|
||||
|
||||
@@ -56,7 +56,7 @@ type Props = MenuStateReturn & {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const ContextMenu: React.FC<Props> = ({
|
||||
const ContextMenu: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
menuRef,
|
||||
children,
|
||||
onOpen,
|
||||
|
||||
@@ -64,7 +64,7 @@ function DocumentCard(props: Props) {
|
||||
};
|
||||
|
||||
const handleUnpin = useCallback(
|
||||
async (ev) => {
|
||||
async (ev: any) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
await pin?.delete();
|
||||
|
||||
@@ -26,7 +26,7 @@ type Props = {
|
||||
to?: LocationDescriptor;
|
||||
};
|
||||
|
||||
const DocumentMeta: React.FC<Props> = ({
|
||||
const DocumentMeta: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
showPublished,
|
||||
showCollection,
|
||||
showLastViewed,
|
||||
|
||||
@@ -41,27 +41,27 @@ function EditableTitle(
|
||||
setValue(title);
|
||||
}, [title]);
|
||||
|
||||
const handleChange = React.useCallback((event) => {
|
||||
const handleChange = React.useCallback((event: any) => {
|
||||
setValue(event.target.value);
|
||||
}, []);
|
||||
|
||||
const handleDoubleClick = React.useCallback((event) => {
|
||||
const handleDoubleClick = React.useCallback((event: any) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setIsEditing(true);
|
||||
}, []);
|
||||
|
||||
const stopPropagation = React.useCallback((event) => {
|
||||
const stopPropagation = React.useCallback((event: any) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}, []);
|
||||
|
||||
const handleFocus = React.useCallback((event) => {
|
||||
const handleFocus = React.useCallback((event: any) => {
|
||||
event.target.select();
|
||||
}, []);
|
||||
|
||||
const handleSave = React.useCallback(
|
||||
async (ev) => {
|
||||
async (ev: any) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
@@ -89,7 +89,7 @@ function EditableTitle(
|
||||
);
|
||||
|
||||
const handleKeyDown = React.useCallback(
|
||||
async (ev) => {
|
||||
async (ev: any) => {
|
||||
if (ev.nativeEvent.isComposing) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
|
||||
}, [onCreateCommentMark, onDeleteCommentMark, comments.orderedData]);
|
||||
|
||||
const handleChange = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
onChange?.(event);
|
||||
updateComments();
|
||||
},
|
||||
|
||||
@@ -20,7 +20,7 @@ type Props = WithTranslation & {
|
||||
/** Whether to show a title heading. */
|
||||
showTitle?: boolean;
|
||||
/** The wrapping component to use. */
|
||||
component?: React.ComponentType | string;
|
||||
component?: React.ComponentType<React.PropsWithChildren<unknown>> | string;
|
||||
};
|
||||
|
||||
@observer
|
||||
|
||||
@@ -17,9 +17,11 @@ type Props = {
|
||||
limit?: number;
|
||||
/** A component to render the avatar, defaults to Avatar. */
|
||||
renderAvatar?: React.ComponentType<
|
||||
React.ComponentProps<typeof Avatar> & {
|
||||
model: User;
|
||||
}
|
||||
React.PropsWithChildren<
|
||||
React.ComponentProps<typeof Avatar> & {
|
||||
model: User;
|
||||
}
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ const FilterOptions = ({
|
||||
: "";
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
(option) => (
|
||||
(option: any) => (
|
||||
<MenuItem
|
||||
key={option.key}
|
||||
onClick={() => {
|
||||
|
||||
@@ -12,7 +12,7 @@ type Props = {
|
||||
onRequestClose: () => void;
|
||||
};
|
||||
|
||||
const Guide: React.FC<Props> = ({
|
||||
const Guide: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
isOpen,
|
||||
title = "Untitled",
|
||||
|
||||
@@ -27,7 +27,7 @@ const SkinTonePicker = ({
|
||||
});
|
||||
|
||||
const handleSkinClick = useCallback(
|
||||
(emojiSkin) => {
|
||||
(emojiSkin: any) => {
|
||||
menu.hide();
|
||||
onChange(emojiSkin);
|
||||
},
|
||||
|
||||
@@ -17,7 +17,11 @@ type Props = Omit<InputProps, "onChange"> & {
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
|
||||
const InputColor: React.FC<Props> = ({ value, onChange, ...rest }: Props) => {
|
||||
const InputColor: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
value,
|
||||
onChange,
|
||||
...rest
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const menu = useMenuState({
|
||||
modal: true,
|
||||
|
||||
@@ -35,4 +35,4 @@ const Select = styled(InputSelect)`
|
||||
select {
|
||||
margin: 0;
|
||||
}
|
||||
` as React.ComponentType<SelectProps>;
|
||||
` as React.ComponentType<React.PropsWithChildren<SelectProps>>;
|
||||
|
||||
@@ -29,7 +29,7 @@ function InputSearch(
|
||||
} = props;
|
||||
|
||||
const handleFocus = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
setIsFocused(true);
|
||||
onFocus?.(event);
|
||||
},
|
||||
@@ -37,7 +37,7 @@ function InputSearch(
|
||||
);
|
||||
|
||||
const handleBlur = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
setIsFocused(false);
|
||||
onBlur?.(event);
|
||||
},
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import * as React from "react";
|
||||
import lazyWithRetry from "~/utils/lazyWithRetry";
|
||||
|
||||
export interface LazyComponent<T extends React.ComponentType<any>> {
|
||||
export interface LazyComponent<
|
||||
T extends React.ComponentType<React.PropsWithChildren<any>>,
|
||||
> {
|
||||
Component: React.LazyExoticComponent<T>;
|
||||
preload: () => Promise<{ default: T }>;
|
||||
}
|
||||
@@ -34,7 +36,9 @@ interface LazyLoadOptions {
|
||||
* MyComponent.preload();
|
||||
* ```
|
||||
*/
|
||||
export function createLazyComponent<T extends React.ComponentType<any>>(
|
||||
export function createLazyComponent<
|
||||
T extends React.ComponentType<React.PropsWithChildren<any>>,
|
||||
>(
|
||||
factory: () => Promise<{ default: T }>,
|
||||
options: LazyLoadOptions = {}
|
||||
): LazyComponent<T> {
|
||||
|
||||
@@ -9,7 +9,9 @@ type Props = {
|
||||
/**
|
||||
* Asyncronously load required polyfills. Should wrap the React tree.
|
||||
*/
|
||||
export const LazyPolyfill: React.FC = ({ children }: Props) => {
|
||||
export const LazyPolyfill: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const [isLoaded, setIsLoaded] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
||||
@@ -12,7 +12,10 @@ export type Props = {
|
||||
format?: Partial<Record<keyof typeof locales, string>>;
|
||||
};
|
||||
|
||||
const LocaleTime: React.FC<Props> = ({ children, ...rest }: Props) => {
|
||||
const LocaleTime: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
...rest
|
||||
}: Props) => {
|
||||
const { tooltipContent, content } = useLocaleTime(rest);
|
||||
|
||||
return (
|
||||
|
||||
@@ -29,7 +29,7 @@ type Props = {
|
||||
onRequestClose: () => void;
|
||||
};
|
||||
|
||||
const Modal: React.FC<Props> = ({
|
||||
const Modal: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
isOpen,
|
||||
fullscreen = true,
|
||||
|
||||
@@ -10,7 +10,11 @@ type Props = {
|
||||
description?: JSX.Element;
|
||||
};
|
||||
|
||||
const Notice: React.FC<Props> = ({ children, icon, description }: Props) => (
|
||||
const Notice: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
icon,
|
||||
description,
|
||||
}: Props) => (
|
||||
<Container as="div">
|
||||
<Flex as="span" gap={8}>
|
||||
{icon}
|
||||
|
||||
@@ -12,7 +12,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const NotificationsPopover: React.FC = ({ children }: Props) => {
|
||||
const NotificationsPopover: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const scrollableRef = React.useRef<HTMLDivElement>(null);
|
||||
const closeRef = React.useRef<HTMLButtonElement>(null);
|
||||
|
||||
@@ -86,7 +86,7 @@ const useTooltipContent = ({
|
||||
}
|
||||
};
|
||||
|
||||
const Reaction: React.FC<Props> = ({
|
||||
const Reaction: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
reaction,
|
||||
reactedUsers,
|
||||
disabled,
|
||||
|
||||
@@ -22,7 +22,7 @@ type Props = {
|
||||
picker?: React.ReactElement;
|
||||
};
|
||||
|
||||
const ReactionList: React.FC<Props> = ({
|
||||
const ReactionList: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
model,
|
||||
onAddReaction,
|
||||
onRemoveReaction,
|
||||
|
||||
@@ -29,7 +29,7 @@ type Props = {
|
||||
size?: number;
|
||||
};
|
||||
|
||||
const ReactionPicker: React.FC<Props> = ({
|
||||
const ReactionPicker: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
onSelect,
|
||||
onOpen,
|
||||
onClose,
|
||||
|
||||
@@ -19,7 +19,9 @@ type Props = {
|
||||
model: Comment;
|
||||
};
|
||||
|
||||
const ViewReactionsDialog: React.FC<Props> = ({ model }) => {
|
||||
const ViewReactionsDialog: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
model,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { users } = useStores();
|
||||
const tab = useTabState();
|
||||
|
||||
@@ -23,7 +23,7 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Scene: React.FC<Props> = ({
|
||||
const Scene: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
title,
|
||||
icon,
|
||||
textTitle,
|
||||
|
||||
@@ -53,7 +53,7 @@ function SearchPopover({ shareId, className }: Props) {
|
||||
}, [searchResults, query, show]);
|
||||
|
||||
const performSearch = React.useCallback(
|
||||
async ({ query: searchQuery, ...options }) => {
|
||||
async ({ query: searchQuery, ...options }: any) => {
|
||||
if (searchQuery?.length > 0) {
|
||||
const response = await documents.search({
|
||||
query: searchQuery,
|
||||
|
||||
@@ -111,7 +111,7 @@ function SharePopover({ collection, visible, onRequestClose }: Props) {
|
||||
}, [pendingIds, prevPendingIds]);
|
||||
|
||||
const handleQuery = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
showPicker();
|
||||
setQuery(event.target.value);
|
||||
},
|
||||
|
||||
@@ -38,7 +38,7 @@ function DocumentMembersList({ document, invitedInSession }: Props) {
|
||||
const theme = useTheme();
|
||||
|
||||
const handleRemoveUser = React.useCallback(
|
||||
async (item) => {
|
||||
async (item: any) => {
|
||||
try {
|
||||
await userMemberships.delete({
|
||||
documentId: document.id,
|
||||
@@ -62,7 +62,7 @@ function DocumentMembersList({ document, invitedInSession }: Props) {
|
||||
);
|
||||
|
||||
const handleUpdateUser = React.useCallback(
|
||||
async (userToUpdate, permission) => {
|
||||
async (userToUpdate: any, permission: any) => {
|
||||
try {
|
||||
await userMemberships.create({
|
||||
documentId: document.id,
|
||||
|
||||
@@ -230,7 +230,7 @@ function SharePopover({ document, onRequestClose, visible }: Props) {
|
||||
);
|
||||
|
||||
const handleQuery = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
showPicker();
|
||||
setQuery(event.target.value);
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@ export const SearchInput = React.forwardRef(function _SearchInput(
|
||||
const isMobile = useMobile();
|
||||
|
||||
const focusInput = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
if (event.target.closest("button")) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ function AppSidebar() {
|
||||
}, [documents, collections, user.isViewer]);
|
||||
|
||||
const [dndArea, setDndArea] = useState();
|
||||
const handleSidebarRef = useCallback((node) => setDndArea(node), []);
|
||||
const handleSidebarRef = useCallback((node: any) => setDndArea(node), []);
|
||||
const html5Options = useMemo(
|
||||
() => ({
|
||||
rootElement: dndArea,
|
||||
|
||||
@@ -50,7 +50,7 @@ function Right({ children, border, className }: Props) {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleMouseDown = React.useCallback((event) => {
|
||||
const handleMouseDown = React.useCallback((event: any) => {
|
||||
event.preventDefault();
|
||||
setResizing(true);
|
||||
}, []);
|
||||
|
||||
@@ -101,7 +101,7 @@ const Sidebar = React.forwardRef<HTMLDivElement, Props>(function _Sidebar(
|
||||
}, []);
|
||||
|
||||
const handleMouseDown = React.useCallback(
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
event.preventDefault();
|
||||
if (!document.hasFocus()) {
|
||||
return;
|
||||
@@ -126,7 +126,7 @@ const Sidebar = React.forwardRef<HTMLDivElement, Props>(function _Sidebar(
|
||||
}, [ui.sidebarIsClosed]);
|
||||
|
||||
const handlePointerLeave = React.useCallback(
|
||||
(ev) => {
|
||||
(ev: any) => {
|
||||
if (hasPointerMoved) {
|
||||
// clear any previous timeout
|
||||
if (hoverTimeoutRef.current) {
|
||||
|
||||
@@ -51,7 +51,7 @@ function ArchiveLink() {
|
||||
}
|
||||
}, [expanded, request]);
|
||||
|
||||
const handleDisclosureClick = useCallback((ev) => {
|
||||
const handleDisclosureClick = useCallback((ev: any) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
setExpanded((e) => !e);
|
||||
|
||||
@@ -15,7 +15,7 @@ export function ArchivedCollectionLink({ collection, depth }: Props) {
|
||||
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
const handleDisclosureClick = useCallback((ev) => {
|
||||
const handleDisclosureClick = useCallback((ev: any) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
setExpanded((e) => !e);
|
||||
|
||||
@@ -36,7 +36,7 @@ type Props = {
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
const CollectionLink: React.FC<Props> = ({
|
||||
const CollectionLink: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
collection,
|
||||
expanded,
|
||||
onDisclosureClick,
|
||||
@@ -88,7 +88,7 @@ const CollectionLink: React.FC<Props> = ({
|
||||
useBoolean();
|
||||
|
||||
const handleNewDoc = React.useCallback(
|
||||
async (input) => {
|
||||
async (input: any) => {
|
||||
const newDocument = await documents.create(
|
||||
{
|
||||
collectionId: collection.id,
|
||||
|
||||
@@ -118,7 +118,7 @@ function InnerDocumentLink(
|
||||
}, [setCollapsed, expanded, hasChildDocuments]);
|
||||
|
||||
const handleDisclosureClick = React.useCallback(
|
||||
(ev) => {
|
||||
(ev: any) => {
|
||||
ev?.preventDefault();
|
||||
if (expanded) {
|
||||
setCollapsed();
|
||||
@@ -233,7 +233,7 @@ function InnerDocumentLink(
|
||||
useBoolean();
|
||||
|
||||
const handleNewDoc = React.useCallback(
|
||||
async (input) => {
|
||||
async (input: any) => {
|
||||
const newDocument = await documents.create(
|
||||
{
|
||||
collectionId: collection?.id,
|
||||
|
||||
@@ -93,7 +93,7 @@ function DraggableCollectionLink({
|
||||
locationSidebarContext,
|
||||
]);
|
||||
|
||||
const handleDisclosureClick = useCallback((ev) => {
|
||||
const handleDisclosureClick = useCallback((ev: any) => {
|
||||
ev?.preventDefault();
|
||||
setExpanded((e) => !e);
|
||||
}, []);
|
||||
|
||||
@@ -6,7 +6,10 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Folder: React.FC<Props> = ({ expanded, children }: Props) => {
|
||||
const Folder: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
expanded,
|
||||
children,
|
||||
}: Props) => {
|
||||
const [openedOnce, setOpenedOnce] = React.useState(expanded);
|
||||
|
||||
// allows us to avoid rendering all children when the folder hasn't been opened
|
||||
|
||||
@@ -14,14 +14,14 @@ type Props = {
|
||||
group: Group;
|
||||
};
|
||||
|
||||
const GroupLink: React.FC<Props> = ({ group }) => {
|
||||
const GroupLink: React.FC<React.PropsWithChildren<Props>> = ({ group }) => {
|
||||
const locationSidebarContext = useLocationSidebarContext();
|
||||
const sidebarContext = groupSidebarContext(group.id);
|
||||
const [expanded, setExpanded] = React.useState(
|
||||
locationSidebarContext === sidebarContext
|
||||
);
|
||||
|
||||
const handleDisclosureClick = React.useCallback((ev) => {
|
||||
const handleDisclosureClick = React.useCallback((ev: any) => {
|
||||
ev?.preventDefault();
|
||||
setExpanded((e) => !e);
|
||||
}, []);
|
||||
|
||||
@@ -19,7 +19,11 @@ export function getHeaderExpandedKey(id: string) {
|
||||
/**
|
||||
* Toggleable sidebar header
|
||||
*/
|
||||
export const Header: React.FC<Props> = ({ id, title, children }: Props) => {
|
||||
export const Header: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
id,
|
||||
title,
|
||||
children,
|
||||
}: Props) => {
|
||||
const [firstRender, setFirstRender] = React.useState(true);
|
||||
const [expanded, setExpanded] = usePersistedState<boolean>(
|
||||
getHeaderExpandedKey(id ?? ""),
|
||||
|
||||
@@ -39,7 +39,7 @@ export interface Props extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||
location?: Location;
|
||||
strict?: boolean;
|
||||
to: LocationDescriptor;
|
||||
component?: React.ComponentType;
|
||||
component?: React.ComponentType<React.PropsWithChildren<unknown>>;
|
||||
onBeforeClick?: () => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,11 @@ const Background = styled.div<{ sticky?: boolean }>`
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
const Subheading: React.FC<Props> = ({ children, sticky, ...rest }: Props) => (
|
||||
const Subheading: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
sticky,
|
||||
...rest
|
||||
}: Props) => (
|
||||
<Background sticky={sticky}>
|
||||
<H3 {...rest}>
|
||||
<Underline>{children}</Underline>
|
||||
|
||||
@@ -58,7 +58,7 @@ const transition = {
|
||||
damping: 30,
|
||||
};
|
||||
|
||||
const Tab: React.FC<Props> = ({
|
||||
const Tab: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
exact,
|
||||
exactQueryString,
|
||||
|
||||
@@ -60,7 +60,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Tabs: React.FC = ({ children }: Props) => {
|
||||
const Tabs: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const ref = React.useRef<any>();
|
||||
const [shadowVisible, setShadow] = React.useState(false);
|
||||
const { width } = useWindowSize();
|
||||
|
||||
@@ -11,7 +11,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Theme: React.FC = ({ children }: Props) => {
|
||||
const Theme: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const { auth, ui } = useStores();
|
||||
const theme = useBuildTheme(
|
||||
auth.team?.getPreference(TeamPreference.CustomTheme) ||
|
||||
|
||||
@@ -6,12 +6,14 @@ import useStores from "~/hooks/useStores";
|
||||
type StoreProps = keyof RootStore;
|
||||
|
||||
function withStores<
|
||||
P extends React.ComponentType<ResolvedProps & RootStore>,
|
||||
P extends React.ComponentType<
|
||||
React.PropsWithChildren<ResolvedProps & RootStore>
|
||||
>,
|
||||
ResolvedProps = JSX.LibraryManagedAttributes<
|
||||
P,
|
||||
Omit<React.ComponentProps<P>, StoreProps>
|
||||
>,
|
||||
>(WrappedComponent: P): React.FC<ResolvedProps> {
|
||||
>(WrappedComponent: P): React.FC<React.PropsWithChildren<ResolvedProps>> {
|
||||
const ComponentWithStore = (props: ResolvedProps) => {
|
||||
const stores = useStores();
|
||||
return <WrappedComponent {...(props as any)} {...stores} />;
|
||||
|
||||
@@ -23,7 +23,7 @@ type ComponentViewConstructor = {
|
||||
|
||||
export default class ComponentView {
|
||||
/** The React component to render. */
|
||||
component: FunctionComponent<ComponentProps>;
|
||||
component: FunctionComponent<React.PropsWithChildren<ComponentProps>>;
|
||||
/** The editor instance. */
|
||||
editor: Editor;
|
||||
/** The extension the view belongs to. */
|
||||
@@ -45,7 +45,7 @@ export default class ComponentView {
|
||||
|
||||
// See https://prosemirror.net/docs/ref/#view.NodeView
|
||||
constructor(
|
||||
component: FunctionComponent<ComponentProps>,
|
||||
component: FunctionComponent<React.PropsWithChildren<ComponentProps>>,
|
||||
{
|
||||
editor,
|
||||
extension,
|
||||
|
||||
@@ -249,7 +249,7 @@ export default function FindAndReplace({
|
||||
);
|
||||
|
||||
const handleReplace = React.useCallback(
|
||||
(ev) => {
|
||||
(ev: any) => {
|
||||
if (readOnly) {
|
||||
return;
|
||||
}
|
||||
@@ -260,7 +260,7 @@ export default function FindAndReplace({
|
||||
);
|
||||
|
||||
const handleReplaceAll = React.useCallback(
|
||||
(ev) => {
|
||||
(ev: any) => {
|
||||
if (readOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ type Props = {
|
||||
view: EditorView;
|
||||
};
|
||||
|
||||
const LinkEditor: React.FC<Props> = ({
|
||||
const LinkEditor: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
mark,
|
||||
from,
|
||||
to,
|
||||
|
||||
@@ -8,7 +8,7 @@ export class NodeViewRenderer<T extends object> {
|
||||
|
||||
public constructor(
|
||||
public element: HTMLElement,
|
||||
private Component: FunctionComponent,
|
||||
private Component: FunctionComponent<React.PropsWithChildren<unknown>>,
|
||||
props: T
|
||||
) {
|
||||
this.props = props;
|
||||
|
||||
@@ -251,7 +251,7 @@ function SuggestionsMenu<T extends MenuItem>(props: Props<T>) {
|
||||
);
|
||||
|
||||
const handleClickItem = React.useCallback(
|
||||
(item) => {
|
||||
(item: any) => {
|
||||
props.onSelect?.(item);
|
||||
|
||||
switch (item.name) {
|
||||
|
||||
@@ -36,7 +36,7 @@ function SuggestionsMenuItem({
|
||||
}: Props) {
|
||||
const portal = usePortalContext();
|
||||
const ref = React.useCallback(
|
||||
(node) => {
|
||||
(node: any) => {
|
||||
if (selected && node) {
|
||||
scrollIntoView(node, {
|
||||
scrollMode: "if-needed",
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import Tooltip, { Props } from "~/components/Tooltip";
|
||||
|
||||
const WrappedTooltip: React.FC<Props> = ({
|
||||
const WrappedTooltip: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
content,
|
||||
...rest
|
||||
|
||||
@@ -2,7 +2,7 @@ import { action } from "mobx";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import { Plugin } from "prosemirror-state";
|
||||
import { Decoration, DecorationSet } from "prosemirror-view";
|
||||
import ReactDOM from "react-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { WidgetProps } from "@shared/editor/lib/Extension";
|
||||
import { PlaceholderPlugin } from "@shared/editor/plugins/PlaceholderPlugin";
|
||||
import { findParentNode } from "@shared/editor/queries/findParentNode";
|
||||
@@ -27,7 +27,8 @@ export default class BlockMenuExtension extends Suggestion {
|
||||
const button = document.createElement("button");
|
||||
button.className = "block-menu-trigger";
|
||||
button.type = "button";
|
||||
ReactDOM.render(<PlusIcon />, button);
|
||||
const root = createRoot(button);
|
||||
root.render(<PlusIcon />);
|
||||
|
||||
return [
|
||||
...super.plugins,
|
||||
|
||||
@@ -18,7 +18,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const MenuProvider: React.FC = ({ children }: Props) => {
|
||||
export const MenuProvider: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const [isMenuOpen, setIsMenuOpen] = React.useState(false);
|
||||
|
||||
const registerMenu = React.useCallback(
|
||||
|
||||
@@ -49,8 +49,8 @@ const Templates = lazy(() => import("~/scenes/Settings/Templates"));
|
||||
export type ConfigItem = {
|
||||
name: string;
|
||||
path: string;
|
||||
icon: React.FC<ComponentProps<typeof Icon>>;
|
||||
component: React.ComponentType;
|
||||
icon: React.FC<React.PropsWithChildren<ComponentProps<typeof Icon>>>;
|
||||
component: React.ComponentType<React.PropsWithChildren<unknown>>;
|
||||
description?: string;
|
||||
preload?: () => void;
|
||||
enabled: boolean;
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@ import { LazyMotion } from "framer-motion";
|
||||
import { KBarProvider } from "kbar";
|
||||
import { Provider } from "mobx-react";
|
||||
import { StrictMode } from "react";
|
||||
import { render } from "react-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { HelmetProvider } from "react-helmet-async";
|
||||
import { Router } from "react-router-dom";
|
||||
import stores from "~/stores";
|
||||
@@ -79,7 +79,8 @@ if (element) {
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
render(<App />, element);
|
||||
const root = createRoot(element);
|
||||
root.render(<App />);
|
||||
}
|
||||
|
||||
window.addEventListener("load", async () => {
|
||||
|
||||
@@ -25,7 +25,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const AccountMenu: React.FC = ({ children }: Props) => {
|
||||
const AccountMenu: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const menu = useMenuState({
|
||||
placement: "bottom-end",
|
||||
modal: true,
|
||||
|
||||
+246
-239
@@ -98,7 +98,10 @@ type MenuTriggerProps = {
|
||||
onTrigger: () => void;
|
||||
};
|
||||
|
||||
const MenuTrigger: React.FC<MenuTriggerProps> = ({ label, onTrigger }) => {
|
||||
const MenuTrigger: React.FC<React.PropsWithChildren<MenuTriggerProps>> = ({
|
||||
label,
|
||||
onTrigger,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { subscriptions, pins } = useStores();
|
||||
@@ -162,251 +165,255 @@ type MenuContentProps = {
|
||||
showToggleEmbeds?: boolean;
|
||||
};
|
||||
|
||||
const MenuContent: React.FC<MenuContentProps> = observer(function MenuContent_({
|
||||
onOpen,
|
||||
onClose,
|
||||
onFindAndReplace,
|
||||
onSelectTemplate,
|
||||
onRename,
|
||||
showDisplayOptions,
|
||||
showToggleEmbeds,
|
||||
}) {
|
||||
const user = useCurrentUser();
|
||||
const { model: document, menuState } = useMenuContext<Document>();
|
||||
const can = usePolicy(document);
|
||||
const { t } = useTranslation();
|
||||
const { policies, collections } = useStores();
|
||||
|
||||
const collection = document.collectionId
|
||||
? collections.get(document.collectionId)
|
||||
: undefined;
|
||||
|
||||
const context = useActionContext({
|
||||
isContextMenu: true,
|
||||
activeDocumentId: document.id,
|
||||
activeCollectionId: document.collectionId ?? undefined,
|
||||
});
|
||||
|
||||
const isMobile = useMobile();
|
||||
|
||||
const handleRestore = React.useCallback(
|
||||
async (
|
||||
ev: React.SyntheticEvent,
|
||||
options?: {
|
||||
collectionId: string;
|
||||
}
|
||||
) => {
|
||||
await document.restore(options);
|
||||
toast.success(
|
||||
t("{{ documentName }} restored", {
|
||||
documentName: capitalize(document.noun),
|
||||
})
|
||||
);
|
||||
},
|
||||
[t, document]
|
||||
);
|
||||
|
||||
const restoreItems = React.useMemo(
|
||||
() => [
|
||||
...collections.orderedData.reduce<MenuItem[]>((filtered, collection) => {
|
||||
const can = policies.abilities(collection.id);
|
||||
|
||||
if (can.createDocument) {
|
||||
filtered.push({
|
||||
type: "button",
|
||||
onClick: (ev) =>
|
||||
handleRestore(ev, {
|
||||
collectionId: collection.id,
|
||||
}),
|
||||
icon: <CollectionIcon collection={collection} />,
|
||||
title: collection.name,
|
||||
});
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}, []),
|
||||
],
|
||||
[collections.orderedData, handleRestore, policies]
|
||||
);
|
||||
|
||||
const templateMenuItems = useTemplateMenuItems({
|
||||
document,
|
||||
const MenuContent: React.FC<React.PropsWithChildren<MenuContentProps>> =
|
||||
observer(function MenuContent_({
|
||||
onOpen,
|
||||
onClose,
|
||||
onFindAndReplace,
|
||||
onSelectTemplate,
|
||||
});
|
||||
onRename,
|
||||
showDisplayOptions,
|
||||
showToggleEmbeds,
|
||||
}) {
|
||||
const user = useCurrentUser();
|
||||
const { model: document, menuState } = useMenuContext<Document>();
|
||||
const can = usePolicy(document);
|
||||
const { t } = useTranslation();
|
||||
const { policies, collections } = useStores();
|
||||
|
||||
const handleEmbedsToggle = React.useCallback(
|
||||
(checked: boolean) => {
|
||||
if (checked) {
|
||||
document.enableEmbeds();
|
||||
} else {
|
||||
document.disableEmbeds();
|
||||
}
|
||||
},
|
||||
[document]
|
||||
);
|
||||
const collection = document.collectionId
|
||||
? collections.get(document.collectionId)
|
||||
: undefined;
|
||||
|
||||
const handleFullWidthToggle = React.useCallback(
|
||||
(checked: boolean) => {
|
||||
user.setPreference(UserPreference.FullWidthDocuments, checked);
|
||||
void user.save();
|
||||
document.fullWidth = checked;
|
||||
void document.save({ fullWidth: checked });
|
||||
},
|
||||
[user, document]
|
||||
);
|
||||
const context = useActionContext({
|
||||
isContextMenu: true,
|
||||
activeDocumentId: document.id,
|
||||
activeCollectionId: document.collectionId ?? undefined,
|
||||
});
|
||||
|
||||
return !isEmpty(can) ? (
|
||||
<ContextMenu
|
||||
{...menuState}
|
||||
aria-label={t("Document options")}
|
||||
onOpen={onOpen}
|
||||
onClose={onClose}
|
||||
>
|
||||
<Template
|
||||
const isMobile = useMobile();
|
||||
|
||||
const handleRestore = React.useCallback(
|
||||
async (
|
||||
ev: React.SyntheticEvent,
|
||||
options?: {
|
||||
collectionId: string;
|
||||
}
|
||||
) => {
|
||||
await document.restore(options);
|
||||
toast.success(
|
||||
t("{{ documentName }} restored", {
|
||||
documentName: capitalize(document.noun),
|
||||
})
|
||||
);
|
||||
},
|
||||
[t, document]
|
||||
);
|
||||
|
||||
const restoreItems = React.useMemo(
|
||||
() => [
|
||||
...collections.orderedData.reduce<MenuItem[]>(
|
||||
(filtered, collection) => {
|
||||
const can = policies.abilities(collection.id);
|
||||
|
||||
if (can.createDocument) {
|
||||
filtered.push({
|
||||
type: "button",
|
||||
onClick: (ev) =>
|
||||
handleRestore(ev, {
|
||||
collectionId: collection.id,
|
||||
}),
|
||||
icon: <CollectionIcon collection={collection} />,
|
||||
title: collection.name,
|
||||
});
|
||||
}
|
||||
|
||||
return filtered;
|
||||
},
|
||||
[]
|
||||
),
|
||||
],
|
||||
[collections.orderedData, handleRestore, policies]
|
||||
);
|
||||
|
||||
const templateMenuItems = useTemplateMenuItems({
|
||||
document,
|
||||
onSelectTemplate,
|
||||
});
|
||||
|
||||
const handleEmbedsToggle = React.useCallback(
|
||||
(checked: boolean) => {
|
||||
if (checked) {
|
||||
document.enableEmbeds();
|
||||
} else {
|
||||
document.disableEmbeds();
|
||||
}
|
||||
},
|
||||
[document]
|
||||
);
|
||||
|
||||
const handleFullWidthToggle = React.useCallback(
|
||||
(checked: boolean) => {
|
||||
user.setPreference(UserPreference.FullWidthDocuments, checked);
|
||||
void user.save();
|
||||
document.fullWidth = checked;
|
||||
void document.save({ fullWidth: checked });
|
||||
},
|
||||
[user, document]
|
||||
);
|
||||
|
||||
return !isEmpty(can) ? (
|
||||
<ContextMenu
|
||||
{...menuState}
|
||||
items={[
|
||||
{
|
||||
type: "button",
|
||||
title: t("Restore"),
|
||||
visible:
|
||||
!!(document.isWorkspaceTemplate || collection?.isActive) &&
|
||||
!!(can.restore || can.unarchive),
|
||||
onClick: (ev) => handleRestore(ev),
|
||||
icon: <RestoreIcon />,
|
||||
},
|
||||
{
|
||||
type: "submenu",
|
||||
title: t("Restore"),
|
||||
visible:
|
||||
!(document.isWorkspaceTemplate || collection?.isActive) &&
|
||||
!!(can.restore || can.unarchive) &&
|
||||
restoreItems.length !== 0,
|
||||
style: {
|
||||
left: -170,
|
||||
position: "relative",
|
||||
top: -40,
|
||||
aria-label={t("Document options")}
|
||||
onOpen={onOpen}
|
||||
onClose={onClose}
|
||||
>
|
||||
<Template
|
||||
{...menuState}
|
||||
items={[
|
||||
{
|
||||
type: "button",
|
||||
title: t("Restore"),
|
||||
visible:
|
||||
!!(document.isWorkspaceTemplate || collection?.isActive) &&
|
||||
!!(can.restore || can.unarchive),
|
||||
onClick: (ev) => handleRestore(ev),
|
||||
icon: <RestoreIcon />,
|
||||
},
|
||||
icon: <RestoreIcon />,
|
||||
hover: true,
|
||||
items: [
|
||||
{
|
||||
type: "heading",
|
||||
title: t("Choose a collection"),
|
||||
{
|
||||
type: "submenu",
|
||||
title: t("Restore"),
|
||||
visible:
|
||||
!(document.isWorkspaceTemplate || collection?.isActive) &&
|
||||
!!(can.restore || can.unarchive) &&
|
||||
restoreItems.length !== 0,
|
||||
style: {
|
||||
left: -170,
|
||||
position: "relative",
|
||||
top: -40,
|
||||
},
|
||||
...restoreItems,
|
||||
],
|
||||
},
|
||||
actionToMenuItem(starDocument, context),
|
||||
actionToMenuItem(unstarDocument, context),
|
||||
{
|
||||
...actionToMenuItem(subscribeDocument, context),
|
||||
disabled: collection?.isSubscribed,
|
||||
tooltip: collection?.isSubscribed
|
||||
? t("Subscription inherited from collection")
|
||||
: undefined,
|
||||
} as MenuItemButton,
|
||||
{
|
||||
...actionToMenuItem(unsubscribeDocument, context),
|
||||
disabled: collection?.isSubscribed,
|
||||
tooltip: collection?.isSubscribed
|
||||
? t("Subscription inherited from collection")
|
||||
: undefined,
|
||||
} as MenuItemButton,
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Find and replace")}…`,
|
||||
visible: !!onFindAndReplace && isMobile,
|
||||
onClick: () => onFindAndReplace?.(),
|
||||
icon: <SearchIcon />,
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
type: "route",
|
||||
title: t("Edit"),
|
||||
to: documentEditPath(document),
|
||||
visible:
|
||||
!!can.update && user.separateEditMode && !document.template,
|
||||
icon: <EditIcon />,
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Rename")}…`,
|
||||
visible: !!can.update && !user.separateEditMode && !!onRename,
|
||||
onClick: () => onRename?.(),
|
||||
icon: <InputIcon />,
|
||||
},
|
||||
actionToMenuItem(shareDocument, context),
|
||||
actionToMenuItem(createNestedDocument, context),
|
||||
actionToMenuItem(importDocument, context),
|
||||
actionToMenuItem(createTemplateFromDocument, context),
|
||||
actionToMenuItem(duplicateDocument, context),
|
||||
actionToMenuItem(publishDocument, context),
|
||||
actionToMenuItem(unpublishDocument, context),
|
||||
actionToMenuItem(archiveDocument, context),
|
||||
actionToMenuItem(moveDocument, context),
|
||||
actionToMenuItem(moveTemplate, context),
|
||||
{
|
||||
type: "submenu",
|
||||
title: t("Apply template"),
|
||||
icon: <ShapesIcon />,
|
||||
items: templateMenuItems,
|
||||
},
|
||||
actionToMenuItem(pinDocument, context),
|
||||
actionToMenuItem(createDocumentFromTemplate, context),
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
actionToMenuItem(openDocumentComments, context),
|
||||
actionToMenuItem(openDocumentHistory, context),
|
||||
actionToMenuItem(openDocumentInsights, context),
|
||||
actionToMenuItem(downloadDocument, context),
|
||||
actionToMenuItem(copyDocument, context),
|
||||
actionToMenuItem(printDocument, context),
|
||||
actionToMenuItem(searchInDocument, context),
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
actionToMenuItem(deleteDocument, context),
|
||||
actionToMenuItem(permanentlyDeleteDocument, context),
|
||||
actionToMenuItem(leaveDocument, context),
|
||||
]}
|
||||
/>
|
||||
{(showDisplayOptions || showToggleEmbeds) && can.update && (
|
||||
<>
|
||||
<Separator />
|
||||
<DisplayOptions>
|
||||
{showToggleEmbeds && (
|
||||
<Style>
|
||||
<ToggleMenuItem
|
||||
width={26}
|
||||
height={14}
|
||||
label={t("Enable embeds")}
|
||||
labelPosition="left"
|
||||
checked={!document.embedsDisabled}
|
||||
onChange={handleEmbedsToggle}
|
||||
/>
|
||||
</Style>
|
||||
)}
|
||||
{showDisplayOptions && !isMobile && (
|
||||
<Style>
|
||||
<ToggleMenuItem
|
||||
width={26}
|
||||
height={14}
|
||||
label={t("Full width")}
|
||||
labelPosition="left"
|
||||
checked={document.fullWidth}
|
||||
onChange={handleFullWidthToggle}
|
||||
/>
|
||||
</Style>
|
||||
)}
|
||||
</DisplayOptions>
|
||||
</>
|
||||
)}
|
||||
</ContextMenu>
|
||||
) : null;
|
||||
});
|
||||
icon: <RestoreIcon />,
|
||||
hover: true,
|
||||
items: [
|
||||
{
|
||||
type: "heading",
|
||||
title: t("Choose a collection"),
|
||||
},
|
||||
...restoreItems,
|
||||
],
|
||||
},
|
||||
actionToMenuItem(starDocument, context),
|
||||
actionToMenuItem(unstarDocument, context),
|
||||
{
|
||||
...actionToMenuItem(subscribeDocument, context),
|
||||
disabled: collection?.isSubscribed,
|
||||
tooltip: collection?.isSubscribed
|
||||
? t("Subscription inherited from collection")
|
||||
: undefined,
|
||||
} as MenuItemButton,
|
||||
{
|
||||
...actionToMenuItem(unsubscribeDocument, context),
|
||||
disabled: collection?.isSubscribed,
|
||||
tooltip: collection?.isSubscribed
|
||||
? t("Subscription inherited from collection")
|
||||
: undefined,
|
||||
} as MenuItemButton,
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Find and replace")}…`,
|
||||
visible: !!onFindAndReplace && isMobile,
|
||||
onClick: () => onFindAndReplace?.(),
|
||||
icon: <SearchIcon />,
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
type: "route",
|
||||
title: t("Edit"),
|
||||
to: documentEditPath(document),
|
||||
visible:
|
||||
!!can.update && user.separateEditMode && !document.template,
|
||||
icon: <EditIcon />,
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Rename")}…`,
|
||||
visible: !!can.update && !user.separateEditMode && !!onRename,
|
||||
onClick: () => onRename?.(),
|
||||
icon: <InputIcon />,
|
||||
},
|
||||
actionToMenuItem(shareDocument, context),
|
||||
actionToMenuItem(createNestedDocument, context),
|
||||
actionToMenuItem(importDocument, context),
|
||||
actionToMenuItem(createTemplateFromDocument, context),
|
||||
actionToMenuItem(duplicateDocument, context),
|
||||
actionToMenuItem(publishDocument, context),
|
||||
actionToMenuItem(unpublishDocument, context),
|
||||
actionToMenuItem(archiveDocument, context),
|
||||
actionToMenuItem(moveDocument, context),
|
||||
actionToMenuItem(moveTemplate, context),
|
||||
{
|
||||
type: "submenu",
|
||||
title: t("Apply template"),
|
||||
icon: <ShapesIcon />,
|
||||
items: templateMenuItems,
|
||||
},
|
||||
actionToMenuItem(pinDocument, context),
|
||||
actionToMenuItem(createDocumentFromTemplate, context),
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
actionToMenuItem(openDocumentComments, context),
|
||||
actionToMenuItem(openDocumentHistory, context),
|
||||
actionToMenuItem(openDocumentInsights, context),
|
||||
actionToMenuItem(downloadDocument, context),
|
||||
actionToMenuItem(copyDocument, context),
|
||||
actionToMenuItem(printDocument, context),
|
||||
actionToMenuItem(searchInDocument, context),
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
actionToMenuItem(deleteDocument, context),
|
||||
actionToMenuItem(permanentlyDeleteDocument, context),
|
||||
actionToMenuItem(leaveDocument, context),
|
||||
]}
|
||||
/>
|
||||
{(showDisplayOptions || showToggleEmbeds) && can.update && (
|
||||
<>
|
||||
<Separator />
|
||||
<DisplayOptions>
|
||||
{showToggleEmbeds && (
|
||||
<Style>
|
||||
<ToggleMenuItem
|
||||
width={26}
|
||||
height={14}
|
||||
label={t("Enable embeds")}
|
||||
labelPosition="left"
|
||||
checked={!document.embedsDisabled}
|
||||
onChange={handleEmbedsToggle}
|
||||
/>
|
||||
</Style>
|
||||
)}
|
||||
{showDisplayOptions && !isMobile && (
|
||||
<Style>
|
||||
<ToggleMenuItem
|
||||
width={26}
|
||||
height={14}
|
||||
label={t("Full width")}
|
||||
labelPosition="left"
|
||||
checked={document.fullWidth}
|
||||
onChange={handleFullWidthToggle}
|
||||
/>
|
||||
</Style>
|
||||
)}
|
||||
</DisplayOptions>
|
||||
</>
|
||||
)}
|
||||
</ContextMenu>
|
||||
) : null;
|
||||
});
|
||||
|
||||
function DocumentMenu({
|
||||
document,
|
||||
|
||||
@@ -13,7 +13,7 @@ import useActionContext from "~/hooks/useActionContext";
|
||||
import { useMenuState } from "~/hooks/useMenuState";
|
||||
import { MenuItem } from "~/types";
|
||||
|
||||
const InsightsMenu: React.FC = () => {
|
||||
const InsightsMenu: React.FC<React.PropsWithChildren<unknown>> = () => {
|
||||
const menuRef = React.useRef<HTMLDivElement>(null);
|
||||
const menu = useMenuState();
|
||||
const context = useActionContext();
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useMenuState } from "~/hooks/useMenuState";
|
||||
import useOnClickOutside from "~/hooks/useOnClickOutside";
|
||||
import { MenuItem } from "~/types";
|
||||
|
||||
const NotificationMenu: React.FC = () => {
|
||||
const NotificationMenu: React.FC<React.PropsWithChildren<unknown>> = () => {
|
||||
const menuRef = React.useRef<HTMLDivElement>(null);
|
||||
const menu = useMenuState();
|
||||
const context = useActionContext();
|
||||
|
||||
@@ -23,7 +23,9 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const TeamMenu: React.FC = ({ children }: Props) => {
|
||||
const TeamMenu: React.FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}: Props) => {
|
||||
const menu = useMenuState({
|
||||
unstable_offset: [4, -4],
|
||||
placement: "bottom-start",
|
||||
|
||||
@@ -48,11 +48,11 @@ function ApiKeyNew({ onSubmit }: Props) {
|
||||
[]
|
||||
);
|
||||
|
||||
const handleNameChange = React.useCallback((event) => {
|
||||
const handleNameChange = React.useCallback((event: any) => {
|
||||
setName(event.target.value);
|
||||
}, []);
|
||||
|
||||
const handleScopeChange = React.useCallback((event) => {
|
||||
const handleScopeChange = React.useCallback((event: any) => {
|
||||
setScope(event.target.value);
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ type Props = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const DropToImport: React.FC<Props> = ({
|
||||
const DropToImport: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
disabled,
|
||||
accept,
|
||||
|
||||
@@ -177,8 +177,9 @@ function Comments() {
|
||||
)}
|
||||
</Wrapper>
|
||||
</Scrollable>
|
||||
{/* @ts-expect-error - framer-motion v4 has TypeScript compatibility issues with React 18 */}
|
||||
<AnimatePresence initial={false}>
|
||||
{!focusedComment && can.comment && !viewingResolved && (
|
||||
{!focusedComment && can.comment && !viewingResolved ? (
|
||||
<NewCommentForm
|
||||
draft={draft}
|
||||
onSaveDraft={onSaveDraft}
|
||||
@@ -189,7 +190,7 @@ function Comments() {
|
||||
animatePresence
|
||||
standalone
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
</Sidebar>
|
||||
);
|
||||
|
||||
@@ -23,8 +23,9 @@ function ObservingBanner() {
|
||||
|
||||
return (
|
||||
<Positioner>
|
||||
{/* @ts-expect-error - framer-motion v4 has TypeScript compatibility issues with React 18 */}
|
||||
<AnimatePresence>
|
||||
{user && (
|
||||
{user ? (
|
||||
<Banner
|
||||
$color={user.color}
|
||||
transition={transition}
|
||||
@@ -34,7 +35,7 @@ function ObservingBanner() {
|
||||
>
|
||||
{t("Observing {{ userName }}", { userName: user.name })}
|
||||
</Banner>
|
||||
)}
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
</Positioner>
|
||||
);
|
||||
|
||||
@@ -41,7 +41,7 @@ function pathToDocument(
|
||||
return path;
|
||||
}
|
||||
|
||||
const PublicBreadcrumb: React.FC<Props> = ({
|
||||
const PublicBreadcrumb: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
documentId,
|
||||
shareId,
|
||||
sharedTree,
|
||||
|
||||
@@ -71,7 +71,7 @@ function Invite({ onSubmit }: Props) {
|
||||
[onSubmit, invites, role, t, users]
|
||||
);
|
||||
|
||||
const handleChange = React.useCallback((ev, index: number) => {
|
||||
const handleChange = React.useCallback((ev: any, index: number) => {
|
||||
setInvites((prevInvites) => {
|
||||
const newInvites = [...prevInvites];
|
||||
newInvites[index][ev.target.name as keyof InviteRequest] =
|
||||
|
||||
@@ -501,11 +501,11 @@ function KeyboardShortcuts() {
|
||||
);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const normalizedSearchTerm = searchTerm.toLocaleLowerCase();
|
||||
const handleChange = useCallback((event) => {
|
||||
const handleChange = useCallback((event: any) => {
|
||||
setSearchTerm(event.target.value);
|
||||
}, []);
|
||||
|
||||
const handleKeyDown = useCallback((event) => {
|
||||
const handleKeyDown = useCallback((event: any) => {
|
||||
if (event.currentTarget.value && event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
@@ -67,11 +67,11 @@ function Login({ children, onBack }: Props) {
|
||||
const handleReset = React.useCallback(() => {
|
||||
setEmailLinkSentTo("");
|
||||
}, []);
|
||||
const handleEmailSuccess = React.useCallback((email) => {
|
||||
const handleEmailSuccess = React.useCallback((email: any) => {
|
||||
setEmailLinkSentTo(email);
|
||||
}, []);
|
||||
|
||||
const handleGoSubdomain = React.useCallback(async (event) => {
|
||||
const handleGoSubdomain = React.useCallback(async (event: any) => {
|
||||
event.preventDefault();
|
||||
const data = Object.fromEntries(new FormData(event.target));
|
||||
await navigateToSubdomain(data.subdomain.toString());
|
||||
|
||||
@@ -89,7 +89,7 @@ function Groups() {
|
||||
[params, history, location.pathname]
|
||||
);
|
||||
|
||||
const handleSearch = useCallback((event) => {
|
||||
const handleSearch = useCallback((event: any) => {
|
||||
const { value } = event.target;
|
||||
setQuery(value);
|
||||
}, []);
|
||||
|
||||
@@ -89,16 +89,16 @@ function Members() {
|
||||
);
|
||||
|
||||
const handleStatusFilter = useCallback(
|
||||
(status) => updateParams("filter", status),
|
||||
(status: any) => updateParams("filter", status),
|
||||
[updateParams]
|
||||
);
|
||||
|
||||
const handleRoleFilter = useCallback(
|
||||
(role) => updateParams("role", role),
|
||||
(role: any) => updateParams("role", role),
|
||||
[updateParams]
|
||||
);
|
||||
|
||||
const handleSearch = useCallback((event) => {
|
||||
const handleSearch = useCallback((event: any) => {
|
||||
const { value } = event.target;
|
||||
setQuery(value);
|
||||
}, []);
|
||||
|
||||
@@ -103,7 +103,7 @@ function Preferences() {
|
||||
);
|
||||
|
||||
const handleThemeChange = React.useCallback(
|
||||
(theme) => {
|
||||
(theme: any) => {
|
||||
ui.setTheme(theme as Theme);
|
||||
toast.success(t("Preferences saved"));
|
||||
},
|
||||
|
||||
@@ -76,7 +76,7 @@ function Security() {
|
||||
);
|
||||
|
||||
const saveData = React.useCallback(
|
||||
async (newData) => {
|
||||
async (newData: any) => {
|
||||
try {
|
||||
setData((prev) => ({ ...prev, ...newData }));
|
||||
await team.save(newData);
|
||||
|
||||
@@ -72,7 +72,7 @@ function Shares() {
|
||||
[params, history, location.pathname]
|
||||
);
|
||||
|
||||
const handleSearch = useCallback((event) => {
|
||||
const handleSearch = useCallback((event: any) => {
|
||||
const { value } = event.target;
|
||||
setQuery(value);
|
||||
}, []);
|
||||
|
||||
@@ -10,7 +10,10 @@ type Props = {
|
||||
title: string;
|
||||
};
|
||||
|
||||
const HelpDisclosure: React.FC<Props> = ({ title, children }: Props) => {
|
||||
const HelpDisclosure: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
title,
|
||||
children,
|
||||
}: Props) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,7 +23,7 @@ export type Props = {
|
||||
borderRadius?: number;
|
||||
};
|
||||
|
||||
const ImageUpload: React.FC<Props> = ({
|
||||
const ImageUpload: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
submitText,
|
||||
@@ -127,63 +127,63 @@ type AvatarEditorDialogProps = {
|
||||
submitText: string;
|
||||
};
|
||||
|
||||
const AvatarEditorDialog: React.FC<AvatarEditorDialogProps> = observer(
|
||||
({ file, onUpload, isUploading, borderRadius, submitText }) => {
|
||||
const { ui } = useStores();
|
||||
const { t } = useTranslation();
|
||||
const [zoom, setZoom] = useState(1);
|
||||
const avatarEditorRef = useRef<AvatarEditor>(null);
|
||||
const AvatarEditorDialog: React.FC<
|
||||
React.PropsWithChildren<AvatarEditorDialogProps>
|
||||
> = observer(({ file, onUpload, isUploading, borderRadius, submitText }) => {
|
||||
const { ui } = useStores();
|
||||
const { t } = useTranslation();
|
||||
const [zoom, setZoom] = useState(1);
|
||||
const avatarEditorRef = useRef<AvatarEditor>(null);
|
||||
|
||||
const handleUpload = React.useCallback(() => {
|
||||
const canvas = avatarEditorRef.current?.getImage();
|
||||
invariant(canvas, "canvas is not defined");
|
||||
const blob = dataUrlToBlob(canvas.toDataURL());
|
||||
onUpload(blob, file);
|
||||
}, [file, onUpload]);
|
||||
const handleUpload = React.useCallback(() => {
|
||||
const canvas = avatarEditorRef.current?.getImage();
|
||||
invariant(canvas, "canvas is not defined");
|
||||
const blob = dataUrlToBlob(canvas.toDataURL());
|
||||
onUpload(blob, file);
|
||||
}, [file, onUpload]);
|
||||
|
||||
const handleZoom = React.useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const target = event.target;
|
||||
const handleZoom = React.useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const target = event.target;
|
||||
|
||||
if (target instanceof HTMLInputElement) {
|
||||
setZoom(parseFloat(target.value));
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
if (target instanceof HTMLInputElement) {
|
||||
setZoom(parseFloat(target.value));
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex auto column align="center" justify="center">
|
||||
{isUploading && <LoadingIndicator />}
|
||||
<AvatarEditorContainer>
|
||||
<AvatarEditor
|
||||
ref={avatarEditorRef}
|
||||
image={file}
|
||||
width={250}
|
||||
height={250}
|
||||
border={25}
|
||||
borderRadius={borderRadius}
|
||||
color={ui.theme === "light" ? [255, 255, 255, 0.6] : [0, 0, 0, 0.6]} // RGBA
|
||||
scale={zoom}
|
||||
rotate={0}
|
||||
/>
|
||||
</AvatarEditorContainer>
|
||||
<RangeInput
|
||||
type="range"
|
||||
min="0.1"
|
||||
max="2"
|
||||
step="0.01"
|
||||
defaultValue="1"
|
||||
onChange={handleZoom}
|
||||
return (
|
||||
<Flex auto column align="center" justify="center">
|
||||
{isUploading && <LoadingIndicator />}
|
||||
<AvatarEditorContainer>
|
||||
<AvatarEditor
|
||||
ref={avatarEditorRef}
|
||||
image={file}
|
||||
width={250}
|
||||
height={250}
|
||||
border={25}
|
||||
borderRadius={borderRadius}
|
||||
color={ui.theme === "light" ? [255, 255, 255, 0.6] : [0, 0, 0, 0.6]} // RGBA
|
||||
scale={zoom}
|
||||
rotate={0}
|
||||
/>
|
||||
<br />
|
||||
<ButtonLarge fullwidth onClick={handleUpload} disabled={isUploading}>
|
||||
{isUploading ? `${t(`Uploading`)}…` : submitText}
|
||||
</ButtonLarge>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
);
|
||||
</AvatarEditorContainer>
|
||||
<RangeInput
|
||||
type="range"
|
||||
min="0.1"
|
||||
max="2"
|
||||
step="0.01"
|
||||
defaultValue="1"
|
||||
onChange={handleZoom}
|
||||
/>
|
||||
<br />
|
||||
<ButtonLarge fullwidth onClick={handleUpload} disabled={isUploading}>
|
||||
{isUploading ? `${t(`Uploading`)}…` : submitText}
|
||||
</ButtonLarge>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
|
||||
const AvatarEditorContainer = styled(Flex)`
|
||||
margin-bottom: 30px;
|
||||
|
||||
@@ -57,7 +57,7 @@ const Label = styled(Text)`
|
||||
margin-bottom: 4px;
|
||||
`;
|
||||
|
||||
const SettingRow: React.FC<Props> = ({
|
||||
const SettingRow: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
visible,
|
||||
description,
|
||||
name,
|
||||
|
||||
@@ -29,7 +29,9 @@ type PluginValueMap = {
|
||||
/** The displayed icon of the plugin. */
|
||||
icon: React.ElementType;
|
||||
/** The lazy loaded settings screen component. */
|
||||
component: LazyComponent<React.ComponentType>;
|
||||
component: LazyComponent<
|
||||
React.ComponentType<React.PropsWithChildren<unknown>>
|
||||
>;
|
||||
/** The description that will show on the plugins card. */
|
||||
description?: string;
|
||||
/** Whether the plugin is enabled in the current context. */
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as React from "react";
|
||||
|
||||
type ComponentPromise<T extends React.ComponentType<any>> = Promise<{
|
||||
type ComponentPromise<
|
||||
T extends React.ComponentType<React.PropsWithChildren<any>>,
|
||||
> = Promise<{
|
||||
default: T;
|
||||
}>;
|
||||
|
||||
@@ -12,7 +14,9 @@ type ComponentPromise<T extends React.ComponentType<any>> = Promise<{
|
||||
* @param interval The interval between retries in milliseconds, defaults to 1000.
|
||||
* @returns A lazy component.
|
||||
*/
|
||||
export default function lazyWithRetry<T extends React.ComponentType<any>>(
|
||||
export default function lazyWithRetry<
|
||||
T extends React.ComponentType<React.PropsWithChildren<any>>,
|
||||
>(
|
||||
component: () => ComponentPromise<T>,
|
||||
retries?: number,
|
||||
interval?: number
|
||||
@@ -20,7 +24,7 @@ export default function lazyWithRetry<T extends React.ComponentType<any>>(
|
||||
return React.lazy(() => retry(component, retries, interval));
|
||||
}
|
||||
|
||||
function retry<T extends React.ComponentType<any>>(
|
||||
function retry<T extends React.ComponentType<React.PropsWithChildren<any>>>(
|
||||
fn: () => ComponentPromise<T>,
|
||||
retriesLeft = 3,
|
||||
interval = 1000
|
||||
|
||||
+5
-5
@@ -202,13 +202,13 @@
|
||||
"query-string": "^7.1.3",
|
||||
"randomstring": "1.3.1",
|
||||
"rate-limiter-flexible": "^2.4.2",
|
||||
"react": "^17.0.2",
|
||||
"react": "^18.0.0",
|
||||
"react-avatar-editor": "^13.0.2",
|
||||
"react-color": "^2.17.3",
|
||||
"react-day-picker": "^8.10.1",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-dropzone": "^11.7.1",
|
||||
"react-helmet-async": "^2.0.5",
|
||||
"react-hook-form": "^7.54.2",
|
||||
@@ -272,7 +272,7 @@
|
||||
"@babel/preset-typescript": "^7.27.1",
|
||||
"@faker-js/faker": "^8.4.1",
|
||||
"@relative-ci/agent": "^4.3.0",
|
||||
"@testing-library/react": "^12.0.0",
|
||||
"@testing-library/react": "^13.0.0",
|
||||
"@types/addressparser": "^1.0.3",
|
||||
"@types/body-scroll-lock": "^3.1.2",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
@@ -312,10 +312,10 @@
|
||||
"@types/png-chunks-extract": "^1.0.2",
|
||||
"@types/quoted-printable": "^1.0.2",
|
||||
"@types/randomstring": "^1.3.0",
|
||||
"@types/react": "^17.0.34",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-avatar-editor": "^13.0.4",
|
||||
"@types/react-color": "^3.0.13",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@types/react-helmet": "^6.1.11",
|
||||
"@types/react-portal": "^4.0.7",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Table, TBody, TR, TD } from "oy-vey";
|
||||
import * as React from "react";
|
||||
import EmptySpace from "./EmptySpace";
|
||||
|
||||
const Body: React.FC = ({ children }) => (
|
||||
const Body: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => (
|
||||
<Table width="100%">
|
||||
<TBody>
|
||||
<TR>
|
||||
|
||||
@@ -15,7 +15,7 @@ const style: React.CSSProperties = {
|
||||
cursor: "pointer",
|
||||
};
|
||||
|
||||
const Button: React.FC<Props> = (props) => (
|
||||
const Button: React.FC<React.PropsWithChildren<Props>> = (props) => (
|
||||
<a {...props} style={style}>
|
||||
{props.children}
|
||||
</a>
|
||||
|
||||
@@ -12,7 +12,7 @@ const style: React.CSSProperties = {
|
||||
letterSpacing: "0.1em",
|
||||
};
|
||||
|
||||
const CopyableCode: React.FC = (props) => (
|
||||
const CopyableCode: React.FC<React.PropsWithChildren<unknown>> = (props) => (
|
||||
<pre {...props} style={style}>
|
||||
{props.children}
|
||||
</pre>
|
||||
|
||||
@@ -2,11 +2,13 @@ import { Table, TBody, TR, TD } from "oy-vey";
|
||||
import * as React from "react";
|
||||
import theme from "@shared/styles/theme";
|
||||
|
||||
const EmailLayout: React.FC<{
|
||||
bgcolor?: string;
|
||||
previewText: string;
|
||||
goToAction?: { url: string; name: string };
|
||||
}> = ({ previewText, bgcolor = "#FFFFFF", goToAction, children }) => {
|
||||
const EmailLayout: React.FC<
|
||||
React.PropsWithChildren<{
|
||||
bgcolor?: string;
|
||||
previewText: string;
|
||||
goToAction?: { url: string; name: string };
|
||||
}>
|
||||
> = ({ previewText, bgcolor = "#FFFFFF", goToAction, children }) => {
|
||||
let markup;
|
||||
if (goToAction) {
|
||||
markup = JSON.stringify({
|
||||
|
||||
@@ -5,7 +5,7 @@ const style = {
|
||||
fontSize: "18px",
|
||||
};
|
||||
|
||||
const Heading: React.FC = ({ children }) => (
|
||||
const Heading: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => (
|
||||
<p>
|
||||
<span style={style}>{children}</span>
|
||||
</p>
|
||||
|
||||
@@ -20,7 +20,9 @@ interface Props {
|
||||
* @param props - Props object containing the content to be rendered.
|
||||
* @returns JSX.Element - The rendered component.
|
||||
*/
|
||||
export const Backticks: React.FC<Props> = ({ content }) => {
|
||||
export const Backticks: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
content,
|
||||
}) => {
|
||||
// Regex to match text between backticks
|
||||
const regex = /`([^`]+)`/g;
|
||||
const parts = content.split(regex);
|
||||
|
||||
@@ -14,7 +14,7 @@ type Props = {
|
||||
* EventBoundary is a component that prevents events from propagating to parent elements.
|
||||
* This is useful for preventing clicks or other interactions from bubbling up the DOM tree.
|
||||
*/
|
||||
const EventBoundary: React.FC<Props> = ({
|
||||
const EventBoundary: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
children,
|
||||
className,
|
||||
captureEvents = "all",
|
||||
|
||||
@@ -16,7 +16,7 @@ type Props = {
|
||||
* It's commonly used for app icons, avatars, and other UI elements where a softer
|
||||
* square shape is desired.
|
||||
*/
|
||||
const Squircle: React.FC<Props> = ({
|
||||
const Squircle: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
color,
|
||||
size = 28,
|
||||
children,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user