@hashicorp/design-system-components
Version:
Helios Design System Components
143 lines (139 loc) • 5.81 kB
JavaScript
import Component from '@glimmer/component';
import { assert } from '@ember/debug';
import { element } from 'ember-element-helper';
import { hash } from '@ember/helper';
import style from 'ember-style-modifier';
import { HdsLayoutGridGapValues, HdsLayoutGridAlignValues } from './types.js';
import HdsLayoutGridItem from './item.js';
import { precompileTemplate } from '@ember/template-compilation';
import { setComponentTemplate } from '@ember/component';
/**
* Copyright IBM Corp. 2021, 2025
* SPDX-License-Identifier: MPL-2.0
*/
const ALIGNS = Object.values(HdsLayoutGridAlignValues);
const DEFAULT_GAP = HdsLayoutGridGapValues.Zero;
const GAPS = Object.values(HdsLayoutGridGapValues);
class HdsLayoutGrid extends Component {
get componentTag() {
return this.args.tag ?? 'div';
}
get align() {
const {
align
} = this.args;
if (align) {
assert(` for "Hds::Layout::Grid" must be one of the following: ${ALIGNS.join(', ')}; received: ${align}`, ALIGNS.includes(align));
}
return align;
}
get gap() {
const {
gap = DEFAULT_GAP
} = this.args;
if (gap) {
assert(` for "Hds::Layout::Grid" must be a single value or an array of two values of one of the following: ${GAPS.join(', ')}; received: ${gap}`, !Array.isArray(gap) && GAPS.includes(gap) || Array.isArray(gap) && gap.length === 2 && GAPS.includes(gap[0]) && GAPS.includes(gap[1]));
return Array.isArray(gap) ? gap : [gap];
} else {
return undefined;
}
}
/*
LOGIC:
Default layout behavior:
--hds-layout-grid-column-fill-type is set to auto-fit (fluid layout)
If neither columnMinWidth nor columnWidth are passed in:
- We do not set --hds-layout-grid-column-min-width (defaults to 0px)
If columnMinWidth is passed in:
- We set --hds-layout-grid-column-min-width to the passed in value
If a columnWidth value is passed in:
1) we set --hds-layout-grid-column-min-width to the passed in value for the view
2) In the CSS, we use "auto-fill" for --hds-layout-grid-column-fill-type for the view (fixed layout)
If both columnMinWidth & columnWidth are passed in:
- We throw an error, as it doesn't make sense in the context of a CSS grid layout (too complex to determine which to use & desired behavior)
*/
get inlineStyles() {
const inlineStyles = {};
// if both columnMinWidth and columnWidth are passed in, we throw an error
assert(` and for "Hds::Layout::Grid" cannot be used together`, !(this.args.columnMinWidth && this.args.columnWidth));
if (this.args.columnMinWidth) {
inlineStyles['--hds-layout-grid-column-min-width'] = this.args.columnMinWidth;
} else if (this.args.columnWidth) {
if (typeof this.args.columnWidth === 'string') {
inlineStyles['--hds-layout-grid-column-min-width'] = this.args.columnWidth;
} else if (typeof this.args.columnWidth === 'object') {
// Responsive column widths
if (this.args.columnWidth.sm) {
inlineStyles['--hds-layout-grid-column-width-sm'] = this.args.columnWidth.sm;
}
if (this.args.columnWidth.md) {
inlineStyles['--hds-layout-grid-column-width-md'] = this.args.columnWidth.md;
}
if (this.args.columnWidth.lg) {
inlineStyles['--hds-layout-grid-column-width-lg'] = this.args.columnWidth.lg;
}
if (this.args.columnWidth.xl) {
inlineStyles['--hds-layout-grid-column-width-xl'] = this.args.columnWidth.xl;
}
if (this.args.columnWidth.xxl) {
inlineStyles['--hds-layout-grid-column-width-xxl'] = this.args.columnWidth.xxl;
}
}
}
return inlineStyles;
}
get classNames() {
const classes = ['hds-layout-grid'];
// add a class based on the @align argument
if (this.align) {
classes.push(`hds-layout-grid--align-items-${this.align}`);
}
// add a class based on the @gap argument
if (this.gap) {
if (this.gap.length === 2) {
classes.push(`hds-layout-grid--row-gap-${this.gap[0]}`);
classes.push(`hds-layout-grid--column-gap-${this.gap[1]}`);
} else if (this.gap.length === 1) {
classes.push(`hds-layout-grid--row-gap-${this.gap[0]}`);
classes.push(`hds-layout-grid--column-gap-${this.gap[0]}`);
}
}
// If a single columnWidth string is passed in, set the respective CSS class (non-responsive view case)
if (typeof this.args.columnWidth === 'string') {
classes.push('hds-layout-grid--column-width-non-responsive');
}
// add classes based on responsive width arguments
// If an object is passed in for the columnWidth arg, set the respective CSS classes
if (typeof this.args.columnWidth === 'object') {
if (this.args.columnWidth.sm) {
classes.push('hds-layout-grid--column-width-sm');
}
if (this.args.columnWidth.md) {
classes.push('hds-layout-grid--column-width-md');
}
if (this.args.columnWidth.lg) {
classes.push('hds-layout-grid--column-width-lg');
}
if (this.args.columnWidth.xl) {
classes.push('hds-layout-grid--column-width-xl');
}
if (this.args.columnWidth.xxl) {
classes.push('hds-layout-grid--column-width-xxl');
}
}
return classes.join(' ');
}
static {
setComponentTemplate(precompileTemplate("{{#let (element this.componentTag) as |Tag|}}\n <Tag class={{this.classNames}} {{style this.inlineStyles}} ...attributes>{{yield (hash Item=HdsLayoutGridItem)}}</Tag>\n{{/let}}", {
strictMode: true,
scope: () => ({
element,
style,
hash,
HdsLayoutGridItem
})
}), this);
}
}
export { ALIGNS, DEFAULT_GAP, GAPS, HdsLayoutGrid as default };
//# sourceMappingURL=index.js.map