UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

179 lines (146 loc) • 4.78 kB
/* eslint-disable camelcase */ import {hues} from '@sanity/color' import {Box, Flex, type Theme} from '@sanity/ui' import {getTheme_v2, rgba} from '@sanity/ui/theme' import styled, {css} from 'styled-components' import {TEXT_BULLET_MARKERS, TEXT_NUMBER_FORMATS} from './constants' import {createListName} from './helpers' interface TextBlockStyleProps { $level: number } function textBlockStyle(props: TextBlockStyleProps & {theme: Theme}) { const {$level} = props const {color, font, radius, space} = getTheme_v2(props.theme) const numberMarker = TEXT_NUMBER_FORMATS[($level - 1) % TEXT_NUMBER_FORMATS.length] const bulletMarker = TEXT_BULLET_MARKERS[($level - 1) % TEXT_BULLET_MARKERS.length] return css` --marker-bg-color: transparent; mix-blend-mode: ${color._dark ? 'screen' : 'multiply'}; position: relative; & > [data-ui='TextBlock_inner'] { position: relative; flex: 1; } & > div:before { content: ''; position: absolute; top: -${space[1]}px; bottom: -${space[1]}px; left: -${space[1]}px; right: -${space[1]}px; border-radius: ${radius[2]}px; background-color: var(--marker-bg-color); // This is to make sure the marker is always behind the text z-index: -1; } &[data-markers] { --marker-bg-color: ${color._dark ? hues.purple[950].hex : hues.purple[50].hex}; } &[data-warning] { --card-border-color: ${color.button.ghost.caution.enabled.border}; --marker-bg-color: ${color.button.ghost.caution.hovered.bg}; } &[data-error] { --card-border-color: ${color.button.ghost.critical.enabled.border}; --marker-bg-color: ${color.button.ghost.critical.hovered.bg}; } & [data-list-prefix] { position: absolute; margin-left: -4.5rem; width: 3.75rem; text-align: right; box-sizing: border-box; } &[data-list-item='number'] [data-list-prefix] { font-variant-numeric: tabular-nums; & > span:before { content: counter(${createListName($level)}) '.'; content: counter(${createListName($level)}, ${numberMarker}) '.'; } } &[data-list-item='bullet'] [data-list-prefix] { & > span { position: relative; top: -0.1875em; &:before { content: '${bulletMarker}'; font-size: 0.46666em; } } } & [data-text] { overflow-wrap: anywhere; text-transform: none; white-space: pre-wrap; font-family: ${font.text.family}; flex: 1; *::selection { background-color: ${rgba(color.focusRing, 0.3)}; } } ` } export const TextRoot = styled.div<TextBlockStyleProps>(textBlockStyle) // Because of a weird bug in Google Chrome regarding the @sanity/ui Flex component and spellchecking, // this is set to be a Box with 'display: flex'. Using the Flex component here results in Chrome // using 20% CPU when idle when spellchecking is on for some reason. export const TextBlockFlexWrapper = styled(Box)` position: relative; display: flex; ` export const ListPrefixWrapper = styled.div` user-select: none; white-space: nowrap; ` export const BlockExtrasContainer = styled(Box)` user-select: none; ` export const BlockActionsOuter = styled(Box)` line-height: 0; width: 25px; position: relative; ` export const BlockActionsInner = styled(Flex)(({theme}: {theme: Theme}) => { const {fonts, space} = theme.sanity const textSize1 = fonts.text.sizes[1] const textSize2 = fonts.text.sizes[2] const capHeight1 = textSize1.lineHeight - textSize1.ascenderHeight - textSize1.descenderHeight const capHeight2 = textSize2.lineHeight - textSize2.ascenderHeight - textSize2.descenderHeight const buttonHeight = capHeight1 + space[2] + space[2] // This calculates the following: // > var buttonHeight = 25px // > var capHeight2 = 11px // > 0 - (buttonHeight - capHeight2) / 2 = -7px const negativeTop = 0 - (buttonHeight - capHeight2) / 2 return css` user-select: none; position: absolute; right: 0; top: ${negativeTop}px; ` }) export const TooltipBox = styled(Box)` max-width: 250px; ` export const TextFlex = styled(Flex)<{$level?: number}>` position: relative; padding-left: ${({$level}) => ($level ? $level * 32 : 0)}px; ` export const ChangeIndicatorWrapper = styled.div<{$hasChanges: boolean}>( ({theme, $hasChanges}: {theme: Theme; $hasChanges: boolean}) => { const {space} = theme.sanity return css` position: absolute; width: ${space[2]}px; right: 0; top: 0; bottom: 0; padding-left: ${space[1]}px; user-select: none; ${!$hasChanges && css` display: none; `} ` }, )