import { BORDER_RADIUS, COLORS } from "@heydovetail/ui-components";
import { extend, keyframes, types } from "typestyle";
import { style } from "typestyle-react";
import { CssClassName, DEFAULT_HIGHLIGHT_COLOR, PixelSize, TABLE } from "./constants";
const enum TableZindex {
DEFAULT = 0,
HOVER = 1,
SELECTED = 2
}
const tableCell: types.NestedCSSProperties = {
border: `1px solid ${TABLE.BORDER}`,
boxSizing: "border-box",
minWidth: `${PixelSize.TABLE_CELL_MIN_WIDTH}px`,
padding: `${PixelSize.TABLE_CELL_Y_PADDING}px ${PixelSize.TABLE_CELL_X_PADDING}px`,
position: "relative",
verticalAlign: "top",
$nest: {
[`& ul, & ol, & p, & .${CssClassName.ATTACHMENT}, & .${CssClassName.WEDGE_CURSOR}`]: {
margin: "0.5em 0"
}
}
};
const tableGutter: types.NestedCSSProperties = {
cursor: "pointer",
display: "block",
background: TABLE.GUTTER_BACKGROUND,
border: `1px solid ${TABLE.GUTTER_BORDER}`,
minHeight: `${PixelSize.TABLE_GUTTER}px`,
minWidth: `${PixelSize.TABLE_GUTTER}px`,
position: "absolute",
zIndex: TableZindex.DEFAULT
};
function cssSvgDataUri(svg: string): string {
return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`.replace("%20", " ");
}
const tablePimple: types.NestedCSSProperties = {
background: `transparent center center no-repeat`,
backgroundImage: cssSvgDataUri(
``
),
backgroundSize: `${PixelSize.TABLE_PIMPLE_PUPIL}px`,
backgroundPosition: "center center",
display: "block",
height: `${PixelSize.TABLE_PIMPLE}px`,
position: "absolute",
width: `${PixelSize.TABLE_PIMPLE}px`,
$nest: {
"&:hover": {
cursor: "pointer"
}
}
};
const tableInsertPimple = extend(tablePimple, {
$nest: {
"&:hover": {
backgroundImage: cssSvgDataUri(
``
),
backgroundSize: `${PixelSize.TABLE_PIMPLE_PLUS}px`
}
}
});
const tableDeletePimple = extend(tablePimple, {
$nest: {
"&:hover": {
backgroundImage: cssSvgDataUri(
``
),
backgroundSize: `${PixelSize.TABLE_PIMPLE_CROSS}px`
}
}
});
const edgeHighlight: types.NestedCSSProperties = {
zIndex: 20,
backgroundColor: TABLE.CELL_SELECTED_BORDER,
pointerEvents: "none",
position: "absolute"
};
const p = {
fontSize: "1em",
lineHeight: "1.75em",
margin: "0 0 1em"
};
export const contentClassName = style({
color: COLORS.indigo,
fontSize: "16px",
position: "relative",
$nest: {
"& h1": {
fontSize: "2em",
fontWeight: 500,
lineHeight: 1.25,
margin: "2em 0 0.5em"
},
"& h2": {
fontSize: "1.5em",
fontWeight: 500,
lineHeight: 1.25,
margin: "2em 0 0.5em"
},
"& p": p,
"& a": {
color: COLORS.purple
},
"& strong": {
fontWeight: 600
},
"& ul, & ol": {
margin: "1em 0",
padding: "0 0 0 2em"
},
[`& .${CssClassName.ATTACHMENT}`]: {
display: "flex",
marginBottom: "1em",
userSelect: "none"
},
[`& .${CssClassName.ATTACHMENT_INSERT_PREVIEW}`]: {
color: "transparent",
height: p.lineHeight,
margin: p.margin,
pointerEvents: "none",
position: "relative",
$nest: {
"&:after": {
content: '""',
display: "block",
position: "absolute",
height: "2px",
top: `calc(50% - 1px)`,
width: "100%",
background: COLORS.blue
}
}
},
"& table": {
borderCollapse: "collapse",
fontSize: "14px",
tableLayout: "fixed"
},
[`& .${CssClassName.TABLE_WRAPPER}`]: {
margin: "2em 0"
},
"& th": extend(tableCell, {
background: TABLE.HEADER_BACKGROUND,
fontWeight: 600,
textAlign: "left"
}),
"& td": tableCell,
[`& .${CssClassName.TABLE_COLUMN_EDGE_HIGHLIGHT_LEFT}`]: extend(edgeHighlight, {
left: -2,
top: -1,
bottom: -1,
width: 3
}),
[`& .${CssClassName.TABLE_COLUMN_EDGE_HIGHLIGHT_RIGHT}`]: extend(edgeHighlight, {
right: -2,
top: -1,
bottom: -1,
width: 3
}),
[`& .${CssClassName.TABLE_ROW_EDGE_HIGHLIGHT_BOTTOM}`]: extend(edgeHighlight, {
left: -1,
right: -1,
bottom: -2,
height: 3
}),
[`& .${CssClassName.TABLE_ROW_EDGE_HIGHLIGHT_TOP}`]: extend(edgeHighlight, {
top: -2,
left: -1,
right: -1,
height: 3
}),
[`& .${CssClassName.TABLE_BETA_LOZENGE}`]: {
position: "absolute",
right: "0",
top: "calc(100% + 4px)",
$nest: {
"&:after": {
background: COLORS.i08,
borderRadius: BORDER_RADIUS,
color: COLORS.i60,
display: "block",
fontSize: "8px",
fontWeight: "bold",
lineHeight: "1em",
padding: "3px 4px",
content: '"BETA"'
}
}
},
[`& .${CssClassName.TABLE_PIMPLE_ORIGIN}`]: extend(tableDeletePimple, {
bottom: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
right: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`
}),
[`& .${CssClassName.TABLE_COLUMN_PIMPLE}`]: extend(tableDeletePimple, {
bottom: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
left: `calc(50% - ${(PixelSize.TABLE_PIMPLE - PixelSize.TABLE_BORDER) >> 1}px)`
}),
[`& .${CssClassName.TABLE_COLUMN_PIMPLE_RIGHT}`]: extend(tableInsertPimple, {
bottom: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
left: `calc(100% - ${(PixelSize.TABLE_PIMPLE - PixelSize.TABLE_BORDER) >> 1}px)`
}),
[`& .${CssClassName.TABLE_COLUMN_PIMPLE_LEFT}`]: extend(tableInsertPimple, {
bottom: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
right: `calc(100% - ${(PixelSize.TABLE_PIMPLE - PixelSize.TABLE_BORDER) >> 1}px)`
}),
[`& .${CssClassName.TABLE_ROW_PIMPLE}`]: extend(tableDeletePimple, {
right: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
top: `calc(50% - ${(PixelSize.TABLE_PIMPLE - PixelSize.TABLE_BORDER) >> 1}px)`
}),
[`& .${CssClassName.TABLE_ROW_PIMPLE_BOTTOM}`]: extend(tableInsertPimple, {
right: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
top: `calc(100% - ${(PixelSize.TABLE_PIMPLE - PixelSize.TABLE_BORDER) >> 1}px)`
}),
[`& .${CssClassName.TABLE_ROW_PIMPLE_TOP}`]: extend(tableInsertPimple, {
right: `calc(100% + ${PixelSize.TABLE_GUTTER + PixelSize.TABLE_PIMPLE_MARGIN}px)`,
bottom: `calc(100% - ${(PixelSize.TABLE_PIMPLE - PixelSize.TABLE_BORDER) >> 1}px)`
}),
[`& .${CssClassName.TABLE_GUTTER_AXIS_COLUMN}`]: extend(tableGutter, {
borderLeftWidth: 0,
borderRightWidth: 0,
bottom: "100%",
left: `-${PixelSize.TABLE_BORDER}px`,
position: "absolute",
right: `-${PixelSize.TABLE_BORDER}px`,
$nest: {
[`&.${CssClassName.TABLE_GUTTER_SELECTED}`]: {
background: TABLE.GUTTER_SELECTED_BACKGROUND,
borderColor: TABLE.CELL_SELECTED_BORDER,
borderLeftWidth: `${PixelSize.TABLE_BORDER}px`,
borderRightWidth: `${PixelSize.TABLE_BORDER}px`,
zIndex: TableZindex.SELECTED
}
}
}),
[`& :last-child > .${CssClassName.TABLE_GUTTER_AXIS_COLUMN}`]: {
borderTopRightRadius: PixelSize.TABLE_BORDER_RADIUS,
borderRightWidth: `${PixelSize.TABLE_BORDER}px`
},
[`& .${CssClassName.TABLE_GUTTER_AXIS_ROW}`]: extend(tableGutter, {
borderTopWidth: 0,
borderBottomWidth: 0,
bottom: `-${PixelSize.TABLE_BORDER}px`,
right: "100%",
top: `-${PixelSize.TABLE_BORDER}px`,
$nest: {
[`&.${CssClassName.TABLE_GUTTER_SELECTED}`]: {
background: TABLE.GUTTER_SELECTED_BACKGROUND,
borderColor: TABLE.CELL_SELECTED_BORDER,
borderTopWidth: `${PixelSize.TABLE_BORDER}px`,
borderBottomWidth: `${PixelSize.TABLE_BORDER}px`,
zIndex: TableZindex.SELECTED
}
}
}),
[`& tr:last-child .${CssClassName.TABLE_GUTTER_AXIS_ROW}`]: {
borderBottomLeftRadius: PixelSize.TABLE_BORDER_RADIUS,
borderBottomWidth: `${PixelSize.TABLE_BORDER}px`
},
[`& .${CssClassName.TABLE_GUTTER_ORIGIN}`]: extend(tableGutter, {
background: "white",
borderTopLeftRadius: PixelSize.TABLE_BORDER_RADIUS,
bottom: "100%",
right: "100%",
$nest: {
"&:after": {
border: `2px solid ${TABLE.ORIGIN_ICON}`,
borderTopColor: "transparent",
borderLeftColor: "transparent",
bottom: "1px",
content: '""',
display: "block",
height: 0,
position: "absolute",
right: "1px",
width: 0
},
[`&.${CssClassName.TABLE_GUTTER_SELECTED}`]: {
borderColor: TABLE.CELL_SELECTED_BORDER,
zIndex: TableZindex.SELECTED,
$nest: {
"&:after": {
borderColor: TABLE.GUTTER_SELECTED_BACKGROUND,
borderTopColor: "transparent",
borderLeftColor: "transparent"
}
}
}
}
}),
/* Give selected cells a blue overlay */
[`& .${CssClassName.TABLE_SELECTED_CELL}:after`]: {
background: TABLE.CELL_SELECTED_BACKGROUND,
border: `${PixelSize.TABLE_BORDER}px solid ${TABLE.CELL_SELECTED_BORDER}`,
bottom: `-${PixelSize.TABLE_BORDER}px`,
content: '""',
left: `-${PixelSize.TABLE_BORDER}px`,
pointerEvents: "none",
position: "absolute",
right: `-${PixelSize.TABLE_BORDER}px`,
top: `-${PixelSize.TABLE_BORDER}px`,
zIndex: TableZindex.SELECTED
},
[`& .ProseMirror-focused .${CssClassName.WEDGE_CURSOR}`]: {
display: "block"
},
[`& .${CssClassName.WEDGE_CURSOR}`]: {
color: "transparent",
height: p.lineHeight,
margin: p.margin,
pointerEvents: "none",
position: "relative",
$nest: {
"&:after": {
content: '""',
display: "block",
position: "absolute",
height: `calc(1.2 * ${p.fontSize})`,
top: `calc(50% - (1.2 * ${p.fontSize}) / 2)`,
width: "1px",
background: "black",
animationName: keyframes({
to: {
visibility: "hidden"
}
}),
animationDuration: "1.1s",
animationIterationCount: "infinite",
animationTimingFunction: "steps(2, start)"
}
}
},
"& li p": {
marginBottom: "0.5em"
},
"& li ul, & li ol": {
margin: "0"
},
"& hr": {
border: "none",
margin: 0,
marginBottom: "1em",
padding: 0,
// Line height is 1.75em, so we want half above and half below our line.
// The line is 2px, so we take 1px off either side to stay centered.
paddingBottom: "calc((1.75em / 2) - 1px)",
paddingTop: "calc((1.75em / 2) - 1px)",
$nest: {
"&:after": {
content: "' '",
display: "block",
height: "2px",
backgroundColor: COLORS.i20
},
"&.ProseMirror-selectednode::after": {
backgroundColor: COLORS.blue
}
}
},
"& blockquote": {
borderLeft: `4px solid ${COLORS.i20}`,
color: COLORS.i60,
margin: "0 0 1em 0",
padding: "0.5em 0 0.5em 1em",
$nest: {
"& p": {
// Having the normal 1em between paragraphs felt a bit spacious.
marginBottom: "0.75em"
},
"& p:last-child": {
marginBottom: 0
}
}
},
"& .ProseMirror": {
minHeight: "72px",
outline: "none",
// This is required by Firefox to prevent spaces from disappearing from
// input when typing.
whiteSpace: "pre-wrap",
// This ensures the editor contains any bottom margin contributed by the
// last content in the document. This ensures mouse-clicks at the bottom
// of the document are captured by the editor, which allows a wedge cursor
// to be placed at the bottom.
paddingBottom: "1px",
$nest: {
[`&.${CssClassName.TABLE_RESIZE_CURSOR}`]: {
cursor: ["ew-resize", "col-resize"]
},
"&.ProseMirror-hideselection *::selection": {
$unique: true,
background: "transparent"
},
"&.ProseMirror-hideselection *::-moz-selection": {
$unique: true,
background: "transparent"
},
"&.ProseMirror-hideselection": {
caretColor: "transparent"
} as {}, // Waiting on https://github.com/typestyle/typestyle/commit/739069894ad21aaaa9ac22d6493c2fc6ffe0a092
[`&.${CssClassName.TAGGING_SELECTION_COLOR} *::-moz-selection`]: {
$unique: true,
background: DEFAULT_HIGHLIGHT_COLOR
},
[`&.${CssClassName.TAGGING_SELECTION_COLOR} *::selection`]: {
$unique: true,
background: DEFAULT_HIGHLIGHT_COLOR
}
}
}
}
});