@boostdev/design-system-components 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +111 -60
- package/dist/client.css +537 -537
- package/dist/client.d.cts +9 -1
- package/dist/client.d.ts +9 -1
- package/dist/client.js +111 -60
- package/dist/index.cjs +111 -60
- package/dist/index.css +537 -537
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +111 -60
- package/dist/web-components/index.d.ts +9 -0
- package/dist/web-components/index.js +58 -3
- package/package.json +1 -1
- package/src/components/layout/Grid/Grid.mdx +34 -0
- package/src/components/layout/Grid/Grid.spec.tsx +95 -0
- package/src/components/layout/Grid/Grid.stories.tsx +45 -0
- package/src/components/layout/Grid/Grid.tsx +20 -4
- package/src/components/layout/Grid/GridItem.tsx +8 -2
- package/src/components/layout/Grid/masonry.ts +91 -4
- package/src/web-components/layout/BdsGrid.mdx +34 -0
- package/src/web-components/layout/BdsGrid.stories.tsx +42 -1
- package/src/web-components/layout/bds-grid-item.spec.ts +14 -0
- package/src/web-components/layout/bds-grid-item.ts +7 -0
- package/src/web-components/layout/bds-grid.spec.ts +8 -0
- package/src/web-components/layout/bds-grid.ts +15 -1
|
@@ -9,12 +9,14 @@ function BdsGrid({
|
|
|
9
9
|
columns,
|
|
10
10
|
isCentered,
|
|
11
11
|
isMasonry,
|
|
12
|
+
masonryPreferredColumnSpan,
|
|
12
13
|
children,
|
|
13
14
|
}: {
|
|
14
15
|
variant?: GridVariant;
|
|
15
16
|
columns?: number;
|
|
16
17
|
isCentered?: boolean;
|
|
17
18
|
isMasonry?: boolean;
|
|
19
|
+
masonryPreferredColumnSpan?: number;
|
|
18
20
|
children?: React.ReactNode;
|
|
19
21
|
}) {
|
|
20
22
|
return React.createElement(
|
|
@@ -24,6 +26,7 @@ function BdsGrid({
|
|
|
24
26
|
columns,
|
|
25
27
|
'is-centered': isCentered || undefined,
|
|
26
28
|
'is-masonry': isMasonry || undefined,
|
|
29
|
+
'masonry-preferred-column-span': masonryPreferredColumnSpan,
|
|
27
30
|
},
|
|
28
31
|
children,
|
|
29
32
|
);
|
|
@@ -45,7 +48,7 @@ function Item({
|
|
|
45
48
|
return React.createElement(
|
|
46
49
|
'bds-grid-item',
|
|
47
50
|
{
|
|
48
|
-
'column-span': columnSpan
|
|
51
|
+
'column-span': columnSpan,
|
|
49
52
|
'start-column': startColumn,
|
|
50
53
|
'end-column': endColumn,
|
|
51
54
|
'row-span': rowSpan,
|
|
@@ -71,6 +74,7 @@ const meta = {
|
|
|
71
74
|
columns: { control: 'number' },
|
|
72
75
|
isCentered: { control: 'boolean' },
|
|
73
76
|
isMasonry: { control: 'boolean' },
|
|
77
|
+
masonryPreferredColumnSpan: { control: { type: 'number', min: 1, max: 4 } },
|
|
74
78
|
},
|
|
75
79
|
} satisfies Meta<typeof BdsGrid>;
|
|
76
80
|
|
|
@@ -189,6 +193,43 @@ export const MasonryWithSpans: Story = {
|
|
|
189
193
|
),
|
|
190
194
|
};
|
|
191
195
|
|
|
196
|
+
/**
|
|
197
|
+
* `masonry-preferred-column-span="2"` makes every auto-span item span 2 columns.
|
|
198
|
+
* With 7 items in a 12-column desktop grid, the 7th would normally leave a trailing
|
|
199
|
+
* gap — the polyfill **demotes** its span to fill just the remaining columns.
|
|
200
|
+
*
|
|
201
|
+
* Flip `masonryPreferredColumnSpan` between 1–4 in the Controls to see the
|
|
202
|
+
* packing re-run. Resize the viewport to watch the demotion adapt to the
|
|
203
|
+
* current column count.
|
|
204
|
+
*/
|
|
205
|
+
export const MasonryPreferredColumnSpan: Story = {
|
|
206
|
+
args: { isMasonry: true, masonryPreferredColumnSpan: 2 },
|
|
207
|
+
render: (args) => (
|
|
208
|
+
<BdsGrid {...args}>
|
|
209
|
+
{Array.from({ length: 7 }).map((_, i) => (
|
|
210
|
+
<Item key={i}><div style={masonryCellStyle(i)}>Card {i + 1}</div></Item>
|
|
211
|
+
))}
|
|
212
|
+
</BdsGrid>
|
|
213
|
+
),
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* An explicit `column-span="three-quarters"` hero alongside auto items.
|
|
218
|
+
* The hero keeps its span; its columns consume the demotion budget, so the
|
|
219
|
+
* auto items fill the remaining row consistently.
|
|
220
|
+
*/
|
|
221
|
+
export const MasonryPreferredColumnSpanWithHero: Story = {
|
|
222
|
+
args: { isMasonry: true, masonryPreferredColumnSpan: 2 },
|
|
223
|
+
render: (args) => (
|
|
224
|
+
<BdsGrid {...args}>
|
|
225
|
+
<Item columnSpan="three-quarters"><div style={masonryCellStyle(0)}>Hero (three-quarters)</div></Item>
|
|
226
|
+
{Array.from({ length: 8 }).map((_, i) => (
|
|
227
|
+
<Item key={i}><div style={masonryCellStyle(i + 1)}>Card {i + 1}</div></Item>
|
|
228
|
+
))}
|
|
229
|
+
</BdsGrid>
|
|
230
|
+
),
|
|
231
|
+
};
|
|
232
|
+
|
|
192
233
|
export const ComplexLayout: Story = {
|
|
193
234
|
args: {},
|
|
194
235
|
render: () => (
|
|
@@ -99,4 +99,18 @@ describe('bds-grid-item', () => {
|
|
|
99
99
|
expect(item.style.gridColumn).toBe('span var(--bds-grid_columns-33)');
|
|
100
100
|
cleanup(grid);
|
|
101
101
|
});
|
|
102
|
+
|
|
103
|
+
it('marks data-column-span-auto when column-span is not set', async () => {
|
|
104
|
+
const el = (await fixture('<bds-grid-item></bds-grid-item>')) as BdsGridItem;
|
|
105
|
+
expect(el.hasAttribute('data-column-span-auto')).toBe(true);
|
|
106
|
+
cleanup(el);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('clears data-column-span-auto when column-span is set', async () => {
|
|
110
|
+
const el = (await fixture(
|
|
111
|
+
'<bds-grid-item column-span="half"></bds-grid-item>',
|
|
112
|
+
)) as BdsGridItem;
|
|
113
|
+
expect(el.hasAttribute('data-column-span-auto')).toBe(false);
|
|
114
|
+
cleanup(el);
|
|
115
|
+
});
|
|
102
116
|
});
|
|
@@ -161,6 +161,13 @@ export class BdsGridItem extends LitElement {
|
|
|
161
161
|
|
|
162
162
|
this.style.gridColumn = gridColumn;
|
|
163
163
|
this.style.gridRow = this.rowSpan !== undefined ? `span ${this.rowSpan}` : '';
|
|
164
|
+
|
|
165
|
+
// Marker the masonry polyfill reads to know this item's span wasn't set by
|
|
166
|
+
// the consumer — it may override with the parent `masonry-preferred-column-span`.
|
|
167
|
+
const isColumnSpanAuto =
|
|
168
|
+
(this.columnSpan === undefined || this.columnSpan === null) && !hasExplicitRange;
|
|
169
|
+
if (isColumnSpanAuto) this.setAttribute('data-column-span-auto', '');
|
|
170
|
+
else this.removeAttribute('data-column-span-auto');
|
|
164
171
|
}
|
|
165
172
|
|
|
166
173
|
render() {
|
|
@@ -59,4 +59,12 @@ describe('bds-grid', () => {
|
|
|
59
59
|
expect(el.shadowRoot!.querySelector('.grid')!.classList.contains('--masonry')).toBe(true);
|
|
60
60
|
cleanup(el);
|
|
61
61
|
});
|
|
62
|
+
|
|
63
|
+
it('reflects masonry-preferred-column-span as a number property', async () => {
|
|
64
|
+
const el = await fixture(
|
|
65
|
+
'<bds-grid is-masonry masonry-preferred-column-span="2"></bds-grid>',
|
|
66
|
+
) as BdsGrid;
|
|
67
|
+
expect(el.masonryPreferredColumnSpan).toBe(2);
|
|
68
|
+
cleanup(el);
|
|
69
|
+
});
|
|
62
70
|
});
|
|
@@ -16,6 +16,9 @@ export type GridVariant = 'main' | 'page' | 'funnel' | 'custom';
|
|
|
16
16
|
* auto-span-media — boolean; child `<bds-grid-item>`s without a `column-span`
|
|
17
17
|
* attribute resolve their span from the intrinsic aspect
|
|
18
18
|
* ratio of their first `<img>`/`<video>` child.
|
|
19
|
+
* masonry-preferred-column-span — number; masonry only. Child items without a
|
|
20
|
+
* `column-span` attribute try to span this many columns; an
|
|
21
|
+
* item at row-end is demoted to the remaining column count.
|
|
19
22
|
*
|
|
20
23
|
* Slots:
|
|
21
24
|
* (default) — grid content; typically `<bds-grid-item>` children
|
|
@@ -76,6 +79,11 @@ export class BdsGrid extends LitElement {
|
|
|
76
79
|
isCentered: { type: Boolean, attribute: 'is-centered', reflect: true },
|
|
77
80
|
isMasonry: { type: Boolean, attribute: 'is-masonry', reflect: true },
|
|
78
81
|
autoSpanMedia: { type: Boolean, attribute: 'auto-span-media', reflect: true },
|
|
82
|
+
masonryPreferredColumnSpan: {
|
|
83
|
+
type: Number,
|
|
84
|
+
attribute: 'masonry-preferred-column-span',
|
|
85
|
+
reflect: true,
|
|
86
|
+
},
|
|
79
87
|
};
|
|
80
88
|
|
|
81
89
|
declare variant: GridVariant;
|
|
@@ -83,6 +91,7 @@ export class BdsGrid extends LitElement {
|
|
|
83
91
|
declare isCentered: boolean;
|
|
84
92
|
declare isMasonry: boolean;
|
|
85
93
|
declare autoSpanMedia: boolean;
|
|
94
|
+
declare masonryPreferredColumnSpan: number | undefined;
|
|
86
95
|
|
|
87
96
|
private _ro?: ResizeObserver;
|
|
88
97
|
private _mo?: MutationObserver;
|
|
@@ -95,6 +104,7 @@ export class BdsGrid extends LitElement {
|
|
|
95
104
|
this.isCentered = false;
|
|
96
105
|
this.isMasonry = false;
|
|
97
106
|
this.autoSpanMedia = false;
|
|
107
|
+
this.masonryPreferredColumnSpan = undefined;
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
disconnectedCallback() {
|
|
@@ -144,7 +154,11 @@ export class BdsGrid extends LitElement {
|
|
|
144
154
|
cancelAnimationFrame(this._frame);
|
|
145
155
|
this._frame = requestAnimationFrame(() => {
|
|
146
156
|
const container = this._gridEl();
|
|
147
|
-
if (container)
|
|
157
|
+
if (container) {
|
|
158
|
+
applyMasonryLayout(container, this._items(), {
|
|
159
|
+
preferredColumnSpan: this.masonryPreferredColumnSpan,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
148
162
|
});
|
|
149
163
|
}
|
|
150
164
|
|