funkwhale/front/src/composables/widths.ts

52 lines
1.6 KiB
TypeScript

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<WidthProps>
const styles : Record<Key, string> = {
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<Key>[] = [
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<WidthProps>, 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(' ')
})