Example #1
0
export const insertLinkClasses = useThemeCache(() => {
    const vars = richEditorVariables();
    const style = styleFactory("insertLink");

    const root = style({
        position: "relative",
        display: "flex",
        flexWrap: "nowrap",
        alignItems: "center",
        maxWidth: unit(vars.insertLink.width),
        width: percent(100),
        paddingLeft: 0,
    });

    const input = style("input", {
        zIndex: 2,
        $nest: {
            "&, &.InputBox": {
                border: important("0"),
                marginBottom: important("0"),
                flexGrow: 1,
                maxWidth: calc(`100% - ${unit(vars.menuButton.size)}`),
            },
        },
    });

    return { root, input };
});
Example #2
0
export const nubClasses = useThemeCache(() => {
    const globalVars = globalVariables();
    const vars = richEditorVariables();
    const style = styleFactory("nub");

    const root = style({
        position: "relative",
        display: "block",
        width: unit(vars.nub.width),
        height: unit(vars.nub.width),
        borderTop: singleBorder({
            width: vars.menu.borderWidth,
        }),
        borderRight: singleBorder({
            width: vars.menu.borderWidth,
        }),
        boxShadow: globalVars.overlay.dropShadow,
        background: colorOut(vars.colors.bg),
    });

    const position = style("position", {
        position: "absolute",
        display: "flex",
        alignItems: "flex-start",
        justifyContent: "center",
        overflow: "hidden",
        width: unit(vars.nub.width * 2),
        height: unit(vars.nub.width * 2),
        ...userSelect(),
        transform: translateX("-50%"),
        pointerEvents: "none",
    });

    return { root, position };
});
Example #3
0
export const richEditorFlyoutClasses = useThemeCache(() => {
    const vars = richEditorVariables();
    const style = styleFactory("richEditorFlyout");
    const shadows = shadowHelper();
    const globalVars = globalVariables();

    const root = style({
        ...shadows.dropDown(),
        position: "absolute",
        left: 0,
        width: unit( vars.richEditorWidth + vars.emojiBody.padding.horizontal * 2),
        zIndex: 6,
        overflow: "hidden",
        backgroundColor: colorOut(vars.colors.bg),
        ...borders(),

        $nest: {
            "&& .ReactVirtualized__Grid": {
                width: important(unit(vars.richEditorWidth) as string),
            },
        },
    });

    const header = style("header", {
        position: "relative",
        borderBottom: singleBorder(),
        ...paddings(vars.emojiHeader.padding),
    });

    const title = style("title", {
        display: "flex",
        alignItems: "center",
        ...longWordEllipsis(),
        margin: 0,
        maxWidth: calc(`100% - ${unit(vars.menuButton.size)}`),
        minHeight: vars.menuButton.size - vars.emojiBody.padding.horizontal,
        fontSize: percent(100),
        lineHeight: "inherit",
        color: colorOut(globalVars.mainColors.fg),
        $nest: {
            "&:focus": {
                outline: 0,
            },
        },
    });

    const body = style("body", {
        ...paddings(vars.emojiBody.padding),
        width: unit( vars.richEditorWidth + vars.emojiBody.padding.horizontal * 2),
    });

    const footer = style("footer", {
        borderTop: singleBorder(),
    });

    return { root, header, body, footer, title };
});
Example #4
0
export const insertMediaClasses = useThemeCache(() => {
    const globalVars = globalVariables();
    const vars = richEditorVariables();
    const style = styleFactory("insertMedia");

    const root = style({
        display: "flex",
        alignItems: "center",
        justifyContent: "flex-end",
        ...paddings({
            left: vars.flyout.padding.horizontal,
            right: vars.flyout.padding.horizontal,
            bottom: vars.flyout.padding.vertical,
        }),
    });

    const help = style("help", {
        marginRight: "auto",
        fontSize: unit(globalVars.fonts.size.small),
    });

    const insert = style("insert", {
        $nest: {
            "&&": {
                // Nest deeper to override margins from the forum.
                width: percent(100),
                position: "relative",
                marginBottom: px(10),
            },
        },
    });
    const button = style("button", {
        position: "relative",
        marginLeft: "auto",
    });

    const footer = style("footer", {
        display: "flex",
        alignItems: "center",
        justifyContent: "flex-end",
        padding: 0,
    });

    return { root, help, insert, footer, button };
});
Example #5
0
export const inlineToolbarClasses = useThemeCache((legacyMode: boolean = false) => {
    const vars = richEditorVariables();
    const style = styleFactory("inlineToolbar");

    const offsetForNub = vars.menu.offset / 2;
    const root = style({
        $nest: {
            "&.isUp": {
                transform: `translateY(-12px)`,
                $nest: {
                    ".richEditor-nubPosition": {
                        bottom: 0,
                        zIndex: 10,
                    },
                    ".richEditor-nub": {
                        transform: `translateY(-50%) rotate(135deg)`,
                        marginBottom: unit(offsetForNub),
                    },
                },
            },
            "&.isDown": {
                transform: `translateY(12px)`,
                $nest: {
                    ".richEditor-nubPosition": {
                        bottom: percent(100),
                    },
                    ".richEditor-nub": {
                        transform: `translateY(50%) rotate(-45deg)`,
                        marginTop: unit(offsetForNub),
                        boxShadow: "none",
                    },
                },
            },
        },
    });
    return { root };
});
export const paragraphMenuCheckRadioClasses = useThemeCache(() => {
    const globalVars = globalVariables();
    const vars = richEditorVariables();
    const style = styleFactory("paragraphMenuCheckRadio");

    const group = style("group", {
        marginBottom: unit(9),
    });

    const checkRadio = style("checkRadio", {
        ...appearance(),
        border: 0,
        display: "flex",
        alignItems: "center",
        width: percent(100),
        minHeight: unit(30),
        userSelect: "none",
        padding: 0,
        outline: 0,
        $nest: {
            "&:hover": {
                backgroundColor: colorOut(globalVars.states.hover.color),
                zIndex: 1,
            },
            "&:active": {
                backgroundColor: colorOut(globalVars.states.active.color),
                zIndex: 1,
            },
            "&:focus": {
                backgroundColor: colorOut(globalVars.states.focus.color),
                zIndex: 1,
            },
        },
    });
    const check = style("check", {});
    const radio = style("radio", {});
    const checked = style("checked", {});
    const separator = style("separator", {});
    const icon = style("icon", {
        width: unit(vars.menuButton.size),
        flexBasis: unit(vars.menuButton.size),
    });
    const checkRadioLabel = style("checkRadioLabel", {
        flexGrow: 1,
        maxWidth: calc(`100% - ${unit(vars.menuButton.size * 2)}`),
        textAlign: "left",
    });
    const checkRadioSelected = style("checkRadioSelected", {
        width: unit(vars.menuButton.size),
        flexBasis: unit(vars.menuButton.size),
    });

    return {
        group,
        checkRadio,
        check,
        radio,
        checked,
        separator,
        icon,
        checkRadioLabel,
        checkRadioSelected,
    };
});
Example #7
0
export const insertEmojiClasses = useThemeCache(() => {
    const globalVars = globalVariables();
    const vars = richEditorVariables();
    const style = styleFactory("insertEmoji");

    const root = style({
        ...appearance(),
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        fontSize: unit(globalVars.icon.sizes.default),
        textAlign: "center",
        overflow: "hidden",
        border: 0,
        opacity: globalVars.states.text.opacity,
        cursor: "pointer",
        borderRadius: unit(3),
        $nest: {
            ...buttonStates(
                {
                    allStates: {
                        outline: 0,
                    },
                    hover: {
                        opacity: 1,
                    },
                    focus: {
                        opacity: 1,
                    },
                    active: {
                        opacity: 1,
                    },
                    accessibleFocus: {
                        backgroundColor: colorOut(globalVars.states.hover.color),
                    },
                },
                {
                    ".fallBackEmoji": {
                        display: "block",
                        margin: "auto",
                    },
                    ".safeEmoji": {
                        display: "block",
                        height: unit(globalVars.icon.sizes.default),
                        width: unit(globalVars.icon.sizes.default),
                        margin: "auto",
                    },
                },
            ),
        },
    });

    const body = style("body", {
        height: unit(vars.emojiBody.height),
        maxHeight: viewHeight(80),

    });

    const popoverDescription = style("popoverDescription", {
        marginBottom: ".5em",
    });

    return { root, body, popoverDescription };
});
Example #8
0
export const richEditorClasses = useThemeCache((legacyMode: boolean, mobile?: boolean) => {
    const globalVars = globalVariables();
    const style = styleFactory("richEditor");
    const vars = richEditorVariables();
    const formVars = formElementsVariables();

    const root = style({
        position: "relative",
        display: "block",
        $nest: {
            "&.isDisabled": {
                $nest: {
                    "&, &.richEditor-button": {
                        cursor: important("progress"),
                    },
                },
            },
            "& .richEditor-text, & .richEditor-textWrap, & .richEditor-frame": {
                display: "flex",
                flexDirection: "column",
                flexGrow: 1,
                position: "relative",
            },
            "& .ql-clipboard": {
                ...srOnly(),
                position: "fixed", // Fixed https://github.com/quilljs/quill/issues/1374#issuecomment-415333651
            },
            "& .richEditor-nextInput, .iconButton, .richEditor-button": {
                ...singleLineEllipsis(),
                ...appearance(),
                position: "relative",
                border: 0,
                padding: 0,
                background: "none",
                textAlign: "left",
            },
            "& .Close-x": {
                display: "block",
                cursor: "pointer",
            },
            "& .content-wrapper": {
                height: percent(100),
            },
            "& .embedDialogue": {
                position: "relative",
            },
        },
    });

    const iconWrap = style("iconWrap", {
        ...pointerEvents(),
        content: quote(``),
        ...absolutePosition.middleOfParent(),
        width: unit(vars.iconWrap.width),
        height: unit(vars.iconWrap.height),
        ...borders({
            radius: 3,
            color: "transparent",
        }),
    });

    const paragraphMenu = style("paragraphMenu", {
        position: "absolute",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        top: unit(vars.pilcrow.offset),
        left: 0,
        marginLeft: unit(-globalVars.gutter.quarter + (!legacyMode ? -(globalVars.gutter.size + 6) : 0)),
        transform: `translateX(-100%)`,
        height: unit(vars.paragraphMenuHandle.size),
        width: unit(globalVars.icon.sizes.default),
        animationName: vars.pilcrow.animation.name,
        animationDuration: vars.pilcrow.animation.duration,
        animationTimingFunction: vars.pilcrow.animation.timing,
        animationIterationCount: vars.pilcrow.animation.iterationCount,
        zIndex: 1,
        $nest: {
            ".richEditor-button&.isActive:hover": {
                cursor: "default",
            },
            "&.isMenuInset": {
                transform: "none",
            },
        },
    });

    const paragraphMenuMobile = style("paragraphMenu-mobile", {
        position: "relative",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        top: important(0),
    });

    const menuBar = style("menuBar", {
        position: "relative",
        width: unit(vars.menuButton.size * 4),
        overflow: "hidden",
    });

    const menuBarToggles = style("menuBarToggles", {
        position: "relative",
        display: "flex",
        justifyContent: "space-between",
        flexWrap: "nowrap",
        width: unit(vars.menuButton.size * 4),
    });

    const paragraphMenuHandle = style("paragraphMenuHandle", {
        ...appearance(),
        ...userSelect(),
        background: "transparent",
        border: 0,
        display: "block",
        cursor: "pointer",
        width: unit(formVars.sizing.height),
        height: unit(formVars.sizing.height),
        padding: 0,
        maxWidth: unit(formVars.sizing.height),
        minWidth: unit(formVars.sizing.height),
        outline: 0,
        $nest: {
            "&:focus, &:hover": {
                color: colorOut(globalVars.mainColors.primary),
            },
            [`&.isOpen .${iconWrap}`]: {
                backgroundColor: colorOut(vars.buttonContents.state.bg),
            },
        },
    });

    const paragraphMenuHandleMobile = style("paragraphMenuHandleMobile", {
        width: unit(vars.menuButton.size),
        height: unit(vars.menuButton.size),
        maxWidth: unit(vars.menuButton.size),
        minWidth: unit(vars.menuButton.size),
    });

    const text = style("text", {
        position: "relative",
        whiteSpace: important("pre-wrap"),
        outline: 0,
    });

    const menuItems = style("menuItems", {
        "-ms-overflow-style": "-ms-autohiding-scrollbar",
        display: "flex",
        alignItems: "center",
        justifyContent: "flex-start",
        flexWrap: "nowrap",
        listStyle: "none",
        padding: 0,
        margin: 0,
        zIndex: 1,
        overflow: "visible",
        $nest: {
            ".richEditor-menuItem": {
                display: "block",
                padding: 0,
                margin: 0,
                $nest: {
                    ".richEditor-button, &.richEditor-button": {
                        width: unit(vars.menuButton.size),
                        fontSize: unit((vars.menuButton.size * 24) / 39),
                        lineHeight: unit(vars.menuButton.size),
                        $nest: {
                            "&.emojiChar-🇺🇳": {
                                fontSize: unit(10),
                            },
                        },
                    },
                    "&:first-child .richEditor-embedButton": {
                        borderBottomLeftRadius: unit(globalVars.border.radius),
                    },
                    "&.isRightAligned": {
                        marginLeft: "auto",
                    },
                },
            },
        },
    });

    const button = style("button", {
        display: "block",
        ...userSelect(),
        ...appearance(),
        cursor: "pointer",
        width: unit(vars.menuButton.size),
        height: unit(vars.menuButton.size),
        border: 0,
        padding: 0,
        overflow: "hidden",
        position: "relative",
        color: colorOut(globalVars.mainColors.fg),
        outline: 0,
        $nest: {
            "&:hover": {
                color: colorOut(globalVars.mainColors.primary),
            },
            "&:focus": {
                color: colorOut(globalVars.mainColors.secondary),
            },
            "&:active": {
                color: colorOut(globalVars.mainColors.secondary),
            },
            [`&.isOpen .${iconWrap}`]: {
                backgroundColor: colorOut(vars.buttonContents.state.bg),
            },
            [`&.focus-visible .${iconWrap}`]: {
                backgroundColor: colorOut(vars.buttonContents.state.bg),
            },
            "&.richEditor-formatButton, &.richEditor-embedButton": {
                height: unit(vars.menuButton.size),
            },
            "&.emojiGroup": {
                display: "block",
                width: unit(vars.menuButton.size),
                height: unit(vars.menuButton.size),
                textAlign: "center",
            },
            "&:not(:disabled)": {
                cursor: "pointer",
            },
            [`&.isActive .${iconWrap}`]: {
                backgroundColor: colorOut(vars.buttonContents.state.bg),
            },
        },
    });

    const topLevelButtonActive = style("topLevelButtonActive", {
        color: colorOut(globalVars.mainColors.primary),
        $nest: {
            [`& .${iconWrap}`]: {
                backgroundColor: colorOut(vars.buttonContents.state.bg),
            },
        },
    });

    const menuItem = style("menuItem", {
        display: "block",
        padding: 0,
        margin: 0,
        overflow: "visible",
        $nest: {
            "& .richEditor-button, &.richEditor-button": {
                width: unit(vars.menuButton.size),
                height: unit(vars.menuButton.size),
                maxWidth: unit(vars.menuButton.size),
                fontSize: unit((vars.menuButton.size * 24) / 39),
                lineHeight: unit(vars.menuButton.size),
                $nest: {
                    "&.emojiChar-🇺🇳": {
                        fontSize: unit(14),
                    },
                },
            },
            "&.isRightAligned": {
                marginLeft: "auto",
            },
        },
    });

    const upload = style("upload", {
        display: important("none"),
    });

    const embedBar = style("embedBar", {
        display: "block",
        width: percent(100),
        padding: unit(vars.embedMenu.padding),
        background: legacyMode ? undefined : colorOut(vars.colors.bg),
    });

    const icon = style("icon", {
        display: "block",
        margin: "auto",
        height: unit(globalVars.icon.sizes.default),
        width: unit(globalVars.icon.sizes.default),
    });

    const legacyFrame = style("legacyFrame", {
        margin: "auto",
        height: "initial",
        minHeight: unit(vars.sizing.minHeight + vars.menuButton.size),
        position: "relative",
        backgroundColor: colorOut(vars.colors.bg),
        padding: 0,
        $nest: {
            "&.isMenuInset": {
                overflow: "initial",
                position: "relative",
            },
        },
    });

    const close = style("close", {
        ...absolutePosition.middleRightOfParent(6),
        ...userSelect(),
        width: unit(vars.menuButton.size),
        height: unit(vars.menuButton.size),
        lineHeight: unit(vars.menuButton.size),
        verticalAlign: "bottom",
        textAlign: "center",
        background: "transparent",
        cursor: "pointer",
    });

    const flyoutDescription = style("flyoutDescription", {
        marginBottom: ".5em",
    });

    const separator = style("separator", {
        borderTop: singleBorder(),
        marginBottom: unit(8),
    });

    const position = style("position", {
        position: "absolute",
        left: calc(`50% - ${unit(vars.spacing.paddingLeft / 2)}`),
        $nest: {
            "&.isUp": {
                bottom: calc(`50% + ${unit(vars.spacing.paddingRight / 2 - formVars.border.width)}`),
            },
            "&.isDown": {
                top: calc(`50% + ${unit(vars.spacing.paddingRight / 2 - formVars.border.width)}`),
            },
        },
    });

    const paragraphMenuPanel = style("paragraphMenuPanel", {});

    const emojiGroup = style("emojiGroup", {
        $nest: {
            [`&.isSelected .${iconWrap}`]: {
                backgroundColor: colorOut(vars.buttonContents.state.bg),
            },
        },
    });

    const flyoutOffset = style("flyoutOffset", {
        marginTop: unit((vars.menuButton.size - vars.iconWrap.width) / -2 + 1),
    });

    return {
        root,
        menuBar,
        menuBarToggles,
        paragraphMenuHandle,
        paragraphMenuHandleMobile,
        text,
        menuItems,
        upload,
        embedBar,
        menuItem,
        button,
        topLevelButtonActive,
        icon,
        close,
        flyoutDescription,
        paragraphMenu,
        paragraphMenuMobile,
        separator,
        position,
        legacyFrame,
        paragraphMenuPanel,
        iconWrap,
        flyoutOffset,
        emojiGroup,
    };
});