import { singularize } from 'inflection' import { toSlug } from '../../utils/string.js' import type * as Style from '../index.js' import * as Conventions from './conventions.js' import * as Definitions from './definitions.js' export const isRule = (style: Style.Rule): style is Style.Rule => !!style.type export const isOfType = (style: Style.Rule, type: Type): style is Style.Rule => style.type && style.type === type export function getClassName(style: Style.Rule, styles: Style.Rule[] = []) { const slug = getEffectiveSlug(style, styles) const definition = Definitions.all.find((d) => d.type == style.type && d.name == style.details.collectionId) if (definition?.isCustom === false && definition.name != 'media') { return `-${slug}` } else { return `-${style.type}--${slug}` } } export function getDefaultClassName(style: Style.Rule) { return getElementDefinition(style) ? '-' + style.details.collectionId : getClassName(style).split('--').slice(0, 2).join('--') } export function getGenericSelector(style: Style.Rule, definitions: Style.ElementDefinition[] = Definitions.all) { return Conventions.getDefinitionSelectors(getElementDefinition(style, definitions)) } export function getElementDefinition(style: Style.Rule, definitions: Style.ElementDefinition[] = Definitions.all) { return ( definitions.find((d) => d.type == style.type && d.id == style.details.collectionId) || definitions.find((d) => d.type == style.type && d.name == style.type) ) } export function getSelector(style: Style.Rule, weight = [0, 0, 0]) { switch (style.type) { case 'color': return ':root' case 'font': return null default: const customization = style.details.instanceId ? `[data-instance-id="${style.details.instanceId}"]` : '' const specificity = weight?.some((w) => w > 0) ? `:weight(${weight.join('.')})` : '' return `.${getClassName(style)}${customization}${specificity}` } } export function getCollectionSlug(style: Style.Rule) { if (style.details.slug) { return style.details.slug.split('--')[0] } return style.details.collectionId } export function getSlugPart(style: Style.Rule) { const slug = toSlug(style.details.title, true) return style.type == 'collection' ? (style.props.type in Definitions || style.props.type == 'color' ? '' : style.props.type + '--collection--') + singularize(slug) : slug } export function getSlug(style: Style.Rule, styles: Style.Rule[]): string { const collection = style.details.collectionId && (style.type == 'text' || style.type == 'block' || style.type == 'inline' || style.type == 'color') && styles.find((s) => s.type == 'collection' && s.details.id == style.details.collectionId) if (collection) { return getEffectiveSlug(collection, styles) + '--' + getSlugPart(style) } else { return getSlugPart(style) } } export function getEffectiveSlug(style: Style.Rule, styles: Style.Rule[]) { // custom rules dont have a slug, they use the id if (style.details.elementId) { return style.details.id } return style.details.slug || getSlug(style, styles) } export function findComboInTheme(theme: Style.Rule<'theme'>, comboId: string) { if (theme) { for (var prop in theme.props) { const combo = theme.props[prop as keyof Style.Theme.Props].find((c) => c.id === comboId) if (combo) return combo } } return null } export function getThemeDefaultComboForType(theme: Style.Rule<'theme'>, category: keyof Style.Theme.Props) { return theme?.props[category].find((c) => c.isDefault) } export function matchesSearchQuery(style: Style.Rule, query: string) { return style?.details.title.toLowerCase().includes(query.toLowerCase()) }