import type { KeysOfUnion } from "type-fest" export type WidthProps = | { minContent?: true } | { tiny?: true } | { buttonWidth?: true } | { small?: true } | { medium?: true } | { auto?: true } | { full?: true } export type Key = KeysOfUnion const styles : Record = { minContent: 'width: min-content;', tiny: "width: 124px; grid-column: span 2;", buttonWidth: "width: 136px; grid-column: span 2; flex-grow:0;", small: "width: 202px; grid-column: span 3;", medium: "width: 280px; grid-column: span 4;", auto: "width: auto;", full: "width: auto; grid-column: 1 / -1; align-self: auto; flex-grow:1;", }; // All keys are exclusive const conflicts: Set[] = [ new Set(Object.keys(styles) as Key[]) ] /** * Add a width style to your component. * Widths are designed to work both in a page-grid context and in a flex or normal context. * * (1) Add `& WidthProps` to your `Props` type * (2) Call `v-bind="propsToWidth(props)"` on your component template * (3) Now your component accepts width props such as `small`, `medium`, `stretch`. * * @param props Your component's props (or ...rest props if you have destructured them already) * @returns the corresponding `style` object */ export const width = (props: Partial, defaults: Key[] = []) => ({ style: Object.entries(props).reduce( ((acc, [key, value]) => value && key in styles ? acc.filter(accKey => !conflicts.find(set => set.has(accKey) && set.has(key as Key))) .concat([key as Key]) : acc ), defaults ).map(key => styles[key]) .join(' ') })