UNPKG

@dash-ui/layout

Version:

A framework-agnostic layout library written in Dash

1,302 lines (1,203 loc) 28.1 kB
import compound from '@dash-ui/compound'; import responsive from '@dash-ui/responsive'; function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _ref8(width) { return { width }; } function _ref9(height) { return { height }; } function _ref10(maxWidth) { return { maxWidth }; } function _ref11(maxHeight) { return { maxHeight }; } function _ref12(minWidth) { return { minWidth }; } function _ref13(minHeight) { return { minHeight }; } function _ref14(size) { return { width: size, height: size }; } function _ref15(value) { return _ref => { var { pad } = _ref; return { padding: Array.isArray(value) ? value.map(k => pad[k]).join(" ") : pad[value] }; }; } function _ref16(_ref2) { var [width, borderColor] = _ref2; return _ref3 => { var { borderWidth, color } = _ref3; return { borderWidth: Array.isArray(width) ? width.map(w => borderWidth[w]).join(" ") : borderWidth[width], borderStyle: "solid", borderColor: color[borderColor] }; }; } function _ref17(value) { return _ref4 => { var { radius } = _ref4; return { borderRadius: Array.isArray(value) ? value.map(k => radius[k]).join(" ") : radius[value] }; }; } function _ref18(value) { if (Array.isArray(value)) { var _value$, _value$2, _ref5, _value$3; return { "@supports (inset: 10px)": { inset: value.map(unit).join(" ") }, "@supports not (inset: 10px)": { top: value[0], right: (_value$ = value[1]) !== null && _value$ !== void 0 ? _value$ : value[0], bottom: (_value$2 = value[2]) !== null && _value$2 !== void 0 ? _value$2 : value[0], left: (_ref5 = (_value$3 = value[3]) !== null && _value$3 !== void 0 ? _value$3 : value[1]) !== null && _ref5 !== void 0 ? _ref5 : value[0] } }; } return { "@supports (inset: 10px)": { inset: value }, "@supports not (inset: 10px)": { top: value, right: value, bottom: value, left: value } }; } function _ref19(value) { return { flexBasis: value }; } function _ref20(value) { return { flexGrow: Number(value) }; } function _ref21(value) { return { order: value }; } function _ref22(value) { return { flexShrink: Number(value) }; } function _ref23(value) { return _ref6 => { var { gap } = _ref6; return { gridGap: Array.isArray(value) ? value.map(p => gap[p]).join(" ") : gap[value] + " " + gap[value], gap: Array.isArray(value) ? value.map(p => gap[p]).join(" ") : gap[value] + " " + gap[value] }; }; } function _ref24(row) { return unit(row); } function _ref25(value) { var rows; if (Array.isArray(value)) rows = value; // ie doesn't have repeat else rows = ["repeat(" + value + ",minmax(0,1fr))"]; return { gridTemplateRows: rows.map(_ref24).join(" ") }; } function _ref26(col) { return unit(col); } function _ref27(value) { var columns; if (Array.isArray(value)) columns = value; // ie doesn't have repeat else columns = ["repeat(" + value + ",minmax(0,1fr))"]; return { gridTemplateColumns: columns.map(_ref26).join(" ") }; } function _ref28(gridColumnStart) { return { gridColumnStart }; } function _ref29(gridColumnEnd) { return { gridColumnEnd }; } function _ref30(gridRowStart) { return { gridRowStart }; } function _ref31(gridRowEnd) { return { gridRowEnd }; } function _ref32(itemWidth) { return { gridTemplateColumns: "repeat(auto-fit, minmax(" + unit(itemWidth) + ", 1fr))" }; } function _ref33(margin) { return { margin }; } function _ref34(value) { return _ref7 => { var { pad } = _ref7; return { margin: Array.isArray(value) ? value.map(k => String(k).startsWith("-") ? "" + pad[k] : "calc(-1 * " + pad[k] + ")").join(" ") + "!important" : String(value).startsWith("-") ? pad[value] + "!important" : "calc(-1 * " + pad[value] + ")!important" }; }; } /** * Creates new layout style utilities using an existing Dash `styles` instance. * * @param styles - An `styles` instance from `@dash-ui/styles` * @param mediaQueries - The media queries to use for responsive styles */ function layout(styles, mediaQueries) { var compoundStyles = compound(styles); var responsiveStyles = responsive(styles, mediaQueries || {}); var box = compoundStyles({ /** * Sets a `display` CSS property on your component */ display: responsiveStyles.variants({ flex: { display: "flex" }, inlineFlex: { display: "inline-flex" }, grid: { display: "grid" }, inlineGrid: { display: "inlineGrid" }, block: { display: "block" }, inlineBlock: { display: "inline-block" }, inline: { display: "inline" }, table: { display: "table" }, tableCell: { display: "table-cell" }, tableRowGroup: { display: "table-row-group" }, tableRow: { display: "table-row" }, tableColumn: { display: "table-column" }, tableColumnGroup: { display: "table-column-group" }, tableHeader: { display: "table-header" }, tableHeaderGroup: { display: "table-header-group" }, tableFooterGroup: { display: "table-footer-group" }, listItem: { display: "list-item" }, contents: { display: "contents" }, runIn: { display: "run-in" }, none: { display: "none" }, inherit: { display: "inherit" }, initial: { display: "initial" }, unset: { display: "unset" }, revert: { display: "revert" } }), /** * Sets a `position` CSS property on your component */ position: responsiveStyles.variants({ absolute: { position: "absolute" }, relative: { position: "relative" }, fixed: { position: "fixed" }, sticky: { position: "sticky" }, static: { position: "static" }, inherit: { position: "inherit" }, initial: { position: "initial" }, unset: { position: "unset" }, revert: { position: "revert" } }), /** * Sets a `width` CSS property on your component */ width: responsiveStyles.lazy(_ref8), /** * Sets a `height` CSS property on your component */ height: responsiveStyles.lazy(_ref9), /** * Sets a `max-width` CSS property on your component */ maxWidth: responsiveStyles.lazy(_ref10), /** * Sets a `max-height` CSS property on your component */ maxHeight: responsiveStyles.lazy(_ref11), /** * Sets a `max-width` CSS property on your component */ minWidth: responsiveStyles.lazy(_ref12), /** * Sets a `max-height` CSS property on your component */ minHeight: responsiveStyles.lazy(_ref13), /** * Sets a `width` and `height` CSS property on your component */ size: responsiveStyles.lazy(_ref14), /** * Sets a `padding` CSS property on your component using the "pad" * token in your theme */ pad: responsiveStyles.lazy(_ref15), /** * Sets a `background-color` CSS property on your component using the "color" * token in your theme */ bg: responsiveStyles.variants(reduce(styles.tokens.color, (acc, key) => { acc[key] = { backgroundColor: styles.tokens.color[key] }; return acc; }, {})), /** * Sets a `border-color` CSS property on your component using the "color" * token in your theme and a `border-width` property using the "borderWidth" * token. */ border: responsiveStyles.lazy(_ref16), /** * Sets a `box-shadow` CSS property on your component using the "shadow" * token in your theme */ shadow: responsiveStyles.variants(reduce(styles.tokens.shadow, (acc, key) => { acc[key] = { boxShadow: styles.tokens.shadow[key] }; return acc; }, {})), /** * Sets a `border-radius` CSS property on your component using the "radius" * token in your theme */ radius: responsiveStyles.lazy(_ref17), /** * Sets the top, right, bottom, left position of the element * * @see https://developer.mozilla.org/en-US/docs/Web/CSS/inset */ inset: responsiveStyles.lazy(_ref18), /** * Sets a `z-index` CSS property on your component */ z: responsiveStyles.variants(reduce(styles.tokens.zIndex, (acc, key) => { acc[key] = { zIndex: styles.tokens.zIndex[key] }; return acc; }, {})) }, { atomic: true }); var alignItems = responsiveStyles.variants({ start: { "@supports (align-items: start)": { alignItems: "start" }, "@supports not (align-items: start)": { alignItems: "flex-start" } }, end: { "@supports (align-items: end)": { alignItems: "end" }, "@supports not (align-items: end)": { alignItems: "flex-end" } }, center: { alignItems: "center" }, baseline: { alignItems: "baseline" }, stretch: { alignItems: "stretch" }, normal: { alignItems: "normal" }, inherit: { alignItems: "inherit" }, initial: { alignItems: "initial" }, unset: { alignItems: "unset" }, revert: { alignItems: "revert" } }); var justifyItems = responsiveStyles.variants({ start: { "@supports (justify-items: start)": { justifyItems: "start" }, "@supports not (justify-items: start)": { justifyItems: "flex-start" } }, end: { "@supports (justify-items: end)": { justifyItems: "end" }, "@supports not (justify-items: end)": { justifyItems: "flex-end" } }, center: { justifyItems: "center" }, baseline: { justifyItems: "baseline" }, stretch: { justifyItems: "stretch" }, normal: { justifyItems: "normal" }, inherit: { justifyItems: "inherit" }, initial: { justifyItems: "initial" }, unset: { justifyItems: "unset" }, revert: { justifyItems: "revert" } }); var justifyContent = responsiveStyles.variants({ start: { "@supports (justify-content: start)": { justifyContent: "start" }, "@supports not (justify-content: start)": { justifyContent: "flex-start" } }, end: { "@supports (justify-content: end)": { justifyContent: "end" }, "@supports not (justify-content: end)": { justifyContent: "flex-end" } }, center: { justifyContent: "center" }, around: { justifyContent: "space-around" }, between: { justifyContent: "space-between" }, evenly: { justifyContent: "space-evenly" }, baseline: { justifyContent: "baseline" }, stretch: { justifyContent: "stretch" }, normal: { justifyContent: "normal" }, inherit: { justifyContent: "inherit" }, initial: { justifyContent: "initial" }, unset: { justifyContent: "unset" }, revert: { justifyContent: "revert" } }); var alignContent = responsiveStyles.variants({ start: { "@supports (align-content: start)": { alignContent: "start" }, "@supports not (align-content: start)": { alignContent: "flex-start" } }, end: { "@supports (align-content: end)": { alignContent: "end" }, "@supports not (align-content: end)": { alignContent: "flex-end" } }, center: { alignContent: "center" }, around: { alignContent: "space-around" }, between: { alignContent: "space-between" }, evenly: { alignContent: "space-evenly" }, baseline: { alignContent: "baseline" }, stretch: { alignContent: "stretch" }, normal: { alignContent: "normal" }, inherit: { alignContent: "inherit" }, initial: { alignContent: "initial" }, unset: { alignContent: "unset" }, revert: { alignContent: "revert" } }); var alignSelf = responsiveStyles.variants({ start: { "@supports (align-self: start)": { alignSelf: "start" }, "@supports not (align-self: start)": { alignSelf: "flex-start" } }, end: { "@supports (align-self: end)": { alignSelf: "end" }, "@supports not (align-self: end)": { alignSelf: "flex-end" } }, center: { alignSelf: "center" }, baseline: { alignSelf: "baseline" }, stretch: { alignSelf: "stretch" }, auto: { alignSelf: "auto" }, normal: { alignSelf: "normal" }, inherit: { alignSelf: "inherit" }, initial: { alignSelf: "initial" }, unset: { alignSelf: "unset" }, revert: { alignSelf: "revert" } }); var justifySelf = responsiveStyles.variants({ start: { "@supports (justify-self: start)": { justifySelf: "start" }, "@supports not (justify-self: start)": { justifySelf: "flex-start" } }, end: { "@supports (justify-self: end)": { justifySelf: "end" }, "@supports not (justify-self: end)": { justifySelf: "flex-end" } }, center: { justifySelf: "center" }, around: { justifySelf: "space-around" }, between: { justifySelf: "space-between" }, evenly: { justifySelf: "space-evenly" }, baseline: { justifySelf: "baseline" }, stretch: { justifySelf: "stretch" }, auto: { justifySelf: "auto" }, normal: { justifySelf: "normal" }, inherit: { justifySelf: "inherit" }, initial: { justifySelf: "initial" }, unset: { justifySelf: "unset" }, revert: { justifySelf: "revert" } }); var flexItem = compoundStyles(_extends({ /** * Sets a `align-self` CSS property on your component */ align: alignSelf, /** * Sets a `justify-self` CSS property on your component */ basis: responsiveStyles.lazy(_ref19), /** * Sets a `justify-self` CSS property on your component */ distribute: justifySelf, /** * Sets a `flex-grow` CSS property on your component */ grow: responsiveStyles.lazy(_ref20), /** * Sets a `order` CSS property on your component */ order: responsiveStyles.lazy(_ref21), /** * Sets a `flex-shrink` CSS property on your component */ shrink: responsiveStyles.lazy(_ref22) }, box.styles), { atomic: true }); var inline = compoundStyles(_extends({ default: responsiveStyles.one({ display: "flex", flexWrap: "wrap", justifyContent: "flex-start", "& > *": { flexShrink: 0 } }), /** * Sets a vertical and horizontal gap between the child elements in the * inline using the "gap" token in your theme */ gap: responsiveStyles.variants(reduce(styles.tokens.gap, (acc, value) => { var gap = styles.tokens.gap; acc[value] = { "@supports (display: flex) and (gap: 1em)": { gap: gap[value] }, "@supports not (display: flex) and (gap: 1em)": { marginTop: "calc(-1 * " + gap[value] + ")!important", marginLeft: "calc(-1 * " + gap[value] + ")!important", "& > *": { marginTop: gap[value] + "!important", marginLeft: gap[value] + "!important" } } }; return acc; }, {})), /** * Distributed alignment properties on the x-axis using `justify-content` */ distribute: justifyContent, /** * Positional alignment for its child items on the y-axis using `align-items` */ align: alignItems }, box.styles), { atomic: true }); var sharedGrid = compoundStyles({ default: responsiveStyles.one({ display: "grid" }), /** * Makes the component display as an `inline-grid` rather than `grid` */ inline: responsiveStyles.one({ display: "inline-grid" }), /** * Sets a `justify-items` CSS property on your component */ alignX: justifyItems, /** * Sets an `align-items` CSS property on your component */ alignY: alignItems, /** * Sets a `justify-content` CSS property on your component */ distributeX: justifyContent, /** * Sets an `align-content` CSS property on your component */ distributeY: alignContent, /** * Sets a horizontal and vertical gap between the child elements in the row * using the "gap" token in your theme */ gap: responsiveStyles.lazy(_ref23), /** * Sets a `grid-template-rows` CSS property on your component */ rows: responsiveStyles.lazy(_ref25) }, { atomic: true }); var grid = compoundStyles(_extends({ /** * Sets a `grid-template-columns` CSS property on your component */ cols: responsiveStyles.lazy(_ref27) }, sharedGrid.styles, box.styles), { atomic: true }); var gridItem = compoundStyles(_extends({ /** * Sets a `justify-self` CSS property on your component */ distribute: justifySelf, /** * Sets an `align-self` CSS property on your component */ align: alignSelf, /** * Sets a `grid-column-start` CSS property on your component */ colStart: responsiveStyles.lazy(_ref28), /** * Sets a `grid-column-end` CSS property on your component */ colEnd: responsiveStyles.lazy(_ref29), /** * Sets a `grid-row-start` CSS property on your component */ rowStart: responsiveStyles.lazy(_ref30), /** * Sets a `grid-row-end` CSS property on your component */ rowEnd: responsiveStyles.lazy(_ref31) }, box.styles), { atomic: true }); var autoGrid = compoundStyles(_extends({ /** * The minimum width of a grid item */ itemWidth: responsiveStyles.lazy(_ref32) }, sharedGrid.styles), { atomic: true }); var hstack = compoundStyles(_extends({ default: responsiveStyles.one({ display: "flex", flexDirection: "row", "& > *": { flexShrink: 0 } }), /** * Reverses the order of the child elements */ reversed: responsiveStyles.one({ flexDirection: "row-reverse" }), /** * Sets a horizontal gap between the child elements in the hstack using the "gap" * token in your theme */ gap: responsiveStyles.variants(reduce(styles.tokens.gap, (acc, value) => { var gap = styles.tokens.gap; var margin = { "& > * + *": { marginLeft: gap[value] + "!important" } }; acc[value] = ("" + value).startsWith("-") ? margin : { "@supports (display: flex) and (gap: 1em)": { gap: gap[value] }, "@supports not (display: flex) and (gap: 1em)": margin }; return acc; }, {})), /** * Distributed alignment properties on the y-axis using `justify-content` */ distribute: justifyContent, /** * Positional alignment for its child items on the x-axis using `align-items` */ align: alignItems }, box.styles), { atomic: true }); var vstack = compoundStyles(_extends({ default: responsiveStyles.one({ display: "flex", flexDirection: "column", "& > *": { flexShrink: 0 } }), /** * Reverses the order of the child elements */ reversed: responsiveStyles.one({ flexDirection: "column-reverse" }), /** * Sets a vertical gap between the child elements in the vstack using the "gap" * token in your theme */ gap: responsiveStyles.variants(reduce(styles.tokens.gap, (acc, value) => { var gap = styles.tokens.gap; var margin = { "& > * + *": { marginTop: gap[value] + "!important" } }; acc[value] = (value + "").startsWith("-") ? margin : { "@supports (display: flex) and (gap: 1em)": { gap: gap[value] }, "@supports not (display: flex) and (gap: 1em)": margin }; return acc; }, {})), /** * Distributed alignment properties on the y-axis using `justify-content` */ distribute: justifyContent, /** * Positional alignment for its child items on the y-axis using `align-items` */ align: alignItems }, box.styles), { atomic: true }); var zstack = compoundStyles(_extends({ default: responsiveStyles.one({ display: "grid", "> *": { gridArea: "1/1/1/1" } }), inline: grid.styles.inline, alignX: justifyItems, alignY: alignItems, distributeX: justifyContent, distributeY: alignContent, center: responsiveStyles.one({ alignItems: "center", justifyItems: "center" }) }, box.styles), { atomic: true }); var overlay = compoundStyles(_extends({ default: responsiveStyles.one({ position: "absolute" }), /** * Sets a `margin` between the edges of the overlay item's container */ offset: responsiveStyles.lazy(_ref33), /** * Sets the placement of your overlay item relative to its container */ placement: responsiveStyles.variants({ top: { top: 0, left: "50%", transform: "translateX(-50%)" }, right: { right: 0, top: "50%", transform: "translateY(-50%)" }, bottom: { bottom: 0, left: "50%", transform: "translateX(-50%)" }, left: { left: 0, top: "50%", transform: "translateY(-50%)" }, center: { top: "50%", left: "50%", transform: "translate(-50%, -50%)" }, topRight: { top: 0, right: 0 }, topLeft: { top: 0, left: 0 }, bottomRight: { bottom: 0, right: 0 }, bottomLeft: { bottom: 0, left: 0 } }) }, box.styles), { atomic: true }); var bleed = compoundStyles(_extends({ /** * Sets a negative margin on itself using the "pad" token in your theme */ amount: responsiveStyles.lazy(_ref34) }, box.styles), { atomic: true }); return { /** * Sets a `align-items` CSS property on your component */ alignItems, /** * Sets a `justify-items` CSS property on your component */ justifyItems, /** * Sets a `justify-content` CSS property on your component */ justifyContent, /** * Sets a `align-content` CSS property on your component */ alignContent, /** * Sets a `align-self` CSS property on your component */ alignSelf, /** * Sets a `justify-self` CSS property on your component */ justifySelf, /** * A layout style for adding size, padding, position, color, and more * using tokens from your CSS variable theme. * * @example * <div className={box({size: 300, bg: {sm: 'red', md: 'blue'}})} /> */ box, /** * Arranges child nodes horizontally, wrapping to multiple lines if needed, * with equal spacing between items. * * If there is only a single child node, no space will be rendered. * * ``` * ☐☐☐☐☐ * ☐☐☐☐☐☐ * ☐☐☐☐☐ * ☐☐☐ * ``` * * Some use cases include input chips and tags. * * @example * <div className={inline({gap: 'sm})}> * <Item/> * <Item/> * </div> */ inline, /** * A layout style that can add positioning properties to itself inside * of a flex container. * * @example * <div className={flexItem({alignSelf: 'center', order: 2})}/> */ flexItem, /** * A layout style that distributes its children in a grid like so: * * ``` * ☐ ☐ ☐ * ☐ ☐ ☐ * ☐ ☐ ☐ * ``` * * @example * <div className={grid({rows: 2, cols: 2})}> * <GridItem/> * <GridItem/> * <GridItem/> * <GridItem/> * </div> */ grid, /** * A layout style that can add positioning properties to itself inside * of a `<Grid>` component. * * @example * <div className={grid({cols: 2, rows: 2})}> * // Occupies 2 columns * <div className={gridItem({colStart: 1, colEnd: 2})} /> * <div/> * <div/> * </div> */ gridItem, /** * A grid that automatically chooses a number of columns based on a preferred * minimum grid item width. The items will grow to fit snugly within the grid * container, like with flex wrapping, but no item will grow larger than the * column size, unlike flex wrapping. * * ☐ ☐ ☐ * ☐ ☐ ☐ * ☐ ☐ */ autoGrid, /** * A layout style that distributes its items in a row without wrapping * like so: * * ``` * ☐ ☐ ☐ ☐ ☐ ☐ ☐ * ``` * * @example * <div className={hstack({gap: 'sm'})}> * <Item/> * <Item/> * </div> */ hstack, /** * A layout style that distributes its items in a column without wrapping * like so: * * ``` * ☐ * ☐ * ☐ * ☐ * ``` * * @example * <div className={vstack({gap: 'sm'})}> * <Item/> * <Item/> * </div> */ vstack, /** * A layout style that stacks its items on top of one another, like so: * * ``` * _____ * | ☐ | * _____ * ``` * * @example * <div className={zstack({center: true})} /> */ zstack, /** * A layout style than positions itself absolutely inside of its * container in whichever placement you decide. * * @example * <div className={overlay({placement: 'bottomRight', offset: 24})} /> */ overlay, /** * A layout style that sets a negative left/top margin on itself using * the "pad" token in your theme. This is useful for increasing the * tap area of a component while maintaining the desired visual padding. * * @example * <div className={bleed({amount: 'sm', pad: 'lg'})}> * <Item/> * <Item/> * </div> */ bleed }; } var keys = Object.keys; function reduce(obj, fn, init) { return keys(obj).reduce(fn, init); } /** * Adds a `px` unit to numeric values and returns non-numeric values as * they are. * * @param value - The value you want to maybe add a unit to */ function unit(value) { return !isNaN(value) && value !== 0 ? value + "px" : value; } export { layout as default }; //# sourceMappingURL=index.dev.mjs.map