@kaizen/components 0.0.0-canary-useContainerQueries-20251121043854 → 0.0.0-canary-useContainerQueries-20251125215952
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/cjs/index.cjs +0 -2
- package/dist/cjs/src/TitleBlock/TitleBlock.module.scss.cjs +1 -0
- package/dist/cjs/src/TitleBlock/utils.cjs +1 -1
- package/dist/esm/index.mjs +0 -1
- package/dist/esm/src/TitleBlock/TitleBlock.module.scss.mjs +1 -0
- package/dist/esm/src/TitleBlock/utils.mjs +1 -1
- package/dist/styles.css +25 -5
- package/dist/types/TitleBlock/types.d.ts +1 -1
- package/dist/types/utils/index.d.ts +0 -1
- package/package.json +1 -1
- package/src/TitleBlock/TitleBlock.module.scss +29 -0
- package/src/TitleBlock/_docs/TitleBlock--usage-guidelines.mdx +4 -0
- package/src/TitleBlock/_docs/TitleBlock.stories.tsx +108 -0
- package/src/TitleBlock/_variables.scss +1 -0
- package/src/TitleBlock/types.ts +1 -1
- package/src/TitleBlock/utils.ts +1 -1
- package/src/utils/index.ts +0 -1
- package/dist/cjs/src/utils/useContainerQueries.cjs +0 -334
- package/dist/esm/src/utils/useContainerQueries.mjs +0 -326
- package/dist/types/utils/useContainerQueries.d.ts +0 -91
- package/src/utils/useContainerQueries.spec.tsx +0 -242
- package/src/utils/useContainerQueries.tsx +0 -333
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var tslib = require('tslib');
|
|
4
|
-
var React = require('react');
|
|
5
|
-
function _interopDefault(e) {
|
|
6
|
-
return e && e.__esModule ? e : {
|
|
7
|
-
default: e
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Tailwind CSS default container query breakpoints
|
|
14
|
-
* These match the default values from @tailwindcss/container-queries plugin
|
|
15
|
-
*/
|
|
16
|
-
var DEFAULT_BREAKPOINTS = {
|
|
17
|
-
'xs': '20rem',
|
|
18
|
-
// 320px
|
|
19
|
-
'sm': '24rem',
|
|
20
|
-
// 384px
|
|
21
|
-
'md': '28rem',
|
|
22
|
-
// 448px
|
|
23
|
-
'lg': '32rem',
|
|
24
|
-
// 512px
|
|
25
|
-
'xl': '36rem',
|
|
26
|
-
// 576px
|
|
27
|
-
'2xl': '42rem',
|
|
28
|
-
// 672px
|
|
29
|
-
'3xl': '48rem',
|
|
30
|
-
// 768px
|
|
31
|
-
'4xl': '56rem',
|
|
32
|
-
// 896px
|
|
33
|
-
'5xl': '64rem',
|
|
34
|
-
// 1024px
|
|
35
|
-
'6xl': '72rem',
|
|
36
|
-
// 1152px
|
|
37
|
-
'7xl': '80rem' // 1280px
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Convert rem/px values to pixels for comparison
|
|
41
|
-
*/
|
|
42
|
-
var parseBreakpointValue = function (value) {
|
|
43
|
-
if (value.endsWith('rem')) {
|
|
44
|
-
return parseFloat(value) * 16; // Assuming 1rem = 16px
|
|
45
|
-
}
|
|
46
|
-
if (value.endsWith('px')) {
|
|
47
|
-
return parseFloat(value);
|
|
48
|
-
}
|
|
49
|
-
return parseFloat(value);
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* A React hook for responding to container size changes using Tailwind CSS container query breakpoints.
|
|
53
|
-
*
|
|
54
|
-
* This hook uses ResizeObserver to detect when a container element crosses breakpoint thresholds,
|
|
55
|
-
* enabling component-level responsive behavior independent of viewport size.
|
|
56
|
-
*
|
|
57
|
-
* @param propQueries - Optional custom container size queries in the format { queryName: 'minWidth' }
|
|
58
|
-
* Example: { large: '600px', extraLarge: '48rem' }
|
|
59
|
-
*
|
|
60
|
-
* @returns An object containing:
|
|
61
|
-
* - containerRef: A ref to attach to your container element
|
|
62
|
-
* - queries: Boolean flags for each breakpoint (isXs, isSm, isMd, etc.) and custom queries
|
|
63
|
-
* - components: React components for conditional rendering (XsOnly, SmOrLarger, etc.)
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```tsx
|
|
67
|
-
* const MyComponent = () => {
|
|
68
|
-
* const { containerRef, queries, components } = useContainerQueries()
|
|
69
|
-
* const { MdOrLarger } = components
|
|
70
|
-
*
|
|
71
|
-
* return (
|
|
72
|
-
* <div ref={containerRef}>
|
|
73
|
-
* {queries.isSm && <p>Small container</p>}
|
|
74
|
-
* <MdOrLarger>
|
|
75
|
-
* <p>Medium or larger container</p>
|
|
76
|
-
* </MdOrLarger>
|
|
77
|
-
* </div>
|
|
78
|
-
* )
|
|
79
|
-
* }
|
|
80
|
-
* ```
|
|
81
|
-
*
|
|
82
|
-
* @example With custom queries
|
|
83
|
-
* ```tsx
|
|
84
|
-
* const { containerRef, queries, components } = useContainerQueries({
|
|
85
|
-
* compact: '400px',
|
|
86
|
-
* spacious: '800px',
|
|
87
|
-
* })
|
|
88
|
-
* const { Compact, Spacious } = components
|
|
89
|
-
*
|
|
90
|
-
* return (
|
|
91
|
-
* <div ref={containerRef}>
|
|
92
|
-
* <Compact><p>Compact view</p></Compact>
|
|
93
|
-
* <Spacious><p>Spacious view</p></Spacious>
|
|
94
|
-
* </div>
|
|
95
|
-
* )
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
var useContainerQueries = function (propQueries) {
|
|
99
|
-
if (propQueries === void 0) {
|
|
100
|
-
propQueries = {};
|
|
101
|
-
}
|
|
102
|
-
// SSR support - return safe defaults when window is undefined
|
|
103
|
-
if (typeof window === 'undefined') {
|
|
104
|
-
return {
|
|
105
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
106
|
-
containerRef: function () {},
|
|
107
|
-
queries: {
|
|
108
|
-
isXs: false,
|
|
109
|
-
isSm: false,
|
|
110
|
-
isMd: false,
|
|
111
|
-
isLg: false,
|
|
112
|
-
isXl: false,
|
|
113
|
-
is2xl: false,
|
|
114
|
-
is3xl: false,
|
|
115
|
-
is4xl: false,
|
|
116
|
-
is5xl: false,
|
|
117
|
-
is6xl: false,
|
|
118
|
-
is7xl: true // Default to largest for SSR
|
|
119
|
-
},
|
|
120
|
-
components: {
|
|
121
|
-
'XsOnly': function () {
|
|
122
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
123
|
-
},
|
|
124
|
-
'SmOnly': function () {
|
|
125
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
126
|
-
},
|
|
127
|
-
'MdOnly': function () {
|
|
128
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
129
|
-
},
|
|
130
|
-
'LgOnly': function () {
|
|
131
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
132
|
-
},
|
|
133
|
-
'XlOnly': function () {
|
|
134
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
135
|
-
},
|
|
136
|
-
'2xlOnly': function () {
|
|
137
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
138
|
-
},
|
|
139
|
-
'3xlOnly': function () {
|
|
140
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
141
|
-
},
|
|
142
|
-
'4xlOnly': function () {
|
|
143
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
144
|
-
},
|
|
145
|
-
'5xlOnly': function () {
|
|
146
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
147
|
-
},
|
|
148
|
-
'6xlOnly': function () {
|
|
149
|
-
return React__default.default.createElement(React__default.default.Fragment, null);
|
|
150
|
-
},
|
|
151
|
-
'7xlOnly': function (props) {
|
|
152
|
-
return React__default.default.createElement(React__default.default.Fragment, null, props.children);
|
|
153
|
-
},
|
|
154
|
-
'XsOrLarger': function (props) {
|
|
155
|
-
return React__default.default.createElement(React__default.default.Fragment, null, props.children);
|
|
156
|
-
},
|
|
157
|
-
'SmOrLarger': function (props) {
|
|
158
|
-
return React__default.default.createElement(React__default.default.Fragment, null, props.children);
|
|
159
|
-
},
|
|
160
|
-
'MdOrLarger': function (props) {
|
|
161
|
-
return React__default.default.createElement(React__default.default.Fragment, null, props.children);
|
|
162
|
-
},
|
|
163
|
-
'LgOrLarger': function (props) {
|
|
164
|
-
return React__default.default.createElement(React__default.default.Fragment, null, props.children);
|
|
165
|
-
},
|
|
166
|
-
'XlOrLarger': function (props) {
|
|
167
|
-
return React__default.default.createElement(React__default.default.Fragment, null, props.children);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
// Parse all breakpoints to pixel values for comparison
|
|
173
|
-
var breakpointsPx = React.useMemo(function () {
|
|
174
|
-
return Object.entries(DEFAULT_BREAKPOINTS).reduce(function (acc, _a) {
|
|
175
|
-
var key = _a[0],
|
|
176
|
-
value = _a[1];
|
|
177
|
-
acc[key] = parseBreakpointValue(value);
|
|
178
|
-
return acc;
|
|
179
|
-
}, {});
|
|
180
|
-
}, []);
|
|
181
|
-
// Parse custom queries
|
|
182
|
-
var customQueriesPx = React.useMemo(function () {
|
|
183
|
-
return Object.entries(propQueries).reduce(function (acc, _a) {
|
|
184
|
-
var key = _a[0],
|
|
185
|
-
value = _a[1];
|
|
186
|
-
acc[key] = parseBreakpointValue(value);
|
|
187
|
-
return acc;
|
|
188
|
-
}, {});
|
|
189
|
-
}, [propQueries]);
|
|
190
|
-
// State to track container width
|
|
191
|
-
var _a = React.useState(0),
|
|
192
|
-
containerWidth = _a[0],
|
|
193
|
-
setContainerWidth = _a[1];
|
|
194
|
-
// ResizeObserver ref
|
|
195
|
-
var resizeObserverRef = React.useRef(null);
|
|
196
|
-
// Callback ref for the container element
|
|
197
|
-
var containerRef = React.useCallback(function (node) {
|
|
198
|
-
// Cleanup previous observer
|
|
199
|
-
if (resizeObserverRef.current) {
|
|
200
|
-
resizeObserverRef.current.disconnect();
|
|
201
|
-
resizeObserverRef.current = null;
|
|
202
|
-
}
|
|
203
|
-
if (node) {
|
|
204
|
-
// Create new ResizeObserver
|
|
205
|
-
resizeObserverRef.current = new ResizeObserver(function (entries) {
|
|
206
|
-
var _a, _b, _c;
|
|
207
|
-
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
208
|
-
var entry = entries_1[_i];
|
|
209
|
-
// Use borderBoxSize for more accurate measurements
|
|
210
|
-
var width_1 = (_c = (_b = (_a = entry.borderBoxSize) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.inlineSize) !== null && _c !== void 0 ? _c : entry.contentRect.width;
|
|
211
|
-
setContainerWidth(width_1);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
resizeObserverRef.current.observe(node);
|
|
215
|
-
// Set initial width
|
|
216
|
-
var width = node.getBoundingClientRect().width;
|
|
217
|
-
setContainerWidth(width);
|
|
218
|
-
}
|
|
219
|
-
}, []);
|
|
220
|
-
// Cleanup on unmount
|
|
221
|
-
React.useEffect(function () {
|
|
222
|
-
return function () {
|
|
223
|
-
if (resizeObserverRef.current) {
|
|
224
|
-
resizeObserverRef.current.disconnect();
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
}, []);
|
|
228
|
-
// Calculate breakpoint matches based on container width
|
|
229
|
-
var breakpointMatches = React.useMemo(function () {
|
|
230
|
-
return {
|
|
231
|
-
isXs: containerWidth >= breakpointsPx.xs,
|
|
232
|
-
isSm: containerWidth >= breakpointsPx.sm,
|
|
233
|
-
isMd: containerWidth >= breakpointsPx.md,
|
|
234
|
-
isLg: containerWidth >= breakpointsPx.lg,
|
|
235
|
-
isXl: containerWidth >= breakpointsPx.xl,
|
|
236
|
-
is2xl: containerWidth >= breakpointsPx['2xl'],
|
|
237
|
-
is3xl: containerWidth >= breakpointsPx['3xl'],
|
|
238
|
-
is4xl: containerWidth >= breakpointsPx['4xl'],
|
|
239
|
-
is5xl: containerWidth >= breakpointsPx['5xl'],
|
|
240
|
-
is6xl: containerWidth >= breakpointsPx['6xl'],
|
|
241
|
-
is7xl: containerWidth >= breakpointsPx['7xl']
|
|
242
|
-
};
|
|
243
|
-
}, [containerWidth, breakpointsPx]);
|
|
244
|
-
// Calculate custom query matches
|
|
245
|
-
var customMatches = React.useMemo(function () {
|
|
246
|
-
return Object.entries(customQueriesPx).reduce(function (acc, _a) {
|
|
247
|
-
var key = _a[0],
|
|
248
|
-
value = _a[1];
|
|
249
|
-
acc[key] = containerWidth >= value;
|
|
250
|
-
return acc;
|
|
251
|
-
}, {});
|
|
252
|
-
}, [containerWidth, customQueriesPx]);
|
|
253
|
-
// Helper function to check if container is at exact breakpoint (not larger)
|
|
254
|
-
var isExactBreakpoint = React.useCallback(function (breakpoint) {
|
|
255
|
-
var sortedBreakpoints = Object.entries(breakpointsPx).sort(function (_a, _b) {
|
|
256
|
-
var a = _a[1];
|
|
257
|
-
var b = _b[1];
|
|
258
|
-
return a - b;
|
|
259
|
-
});
|
|
260
|
-
var currentIndex = sortedBreakpoints.findIndex(function (_a) {
|
|
261
|
-
var key = _a[0];
|
|
262
|
-
return key === breakpoint;
|
|
263
|
-
});
|
|
264
|
-
var nextBreakpoint = sortedBreakpoints[currentIndex + 1];
|
|
265
|
-
var minWidth = breakpointsPx[breakpoint];
|
|
266
|
-
var maxWidth = nextBreakpoint ? nextBreakpoint[1] : Infinity;
|
|
267
|
-
return containerWidth >= minWidth && containerWidth < maxWidth;
|
|
268
|
-
}, [containerWidth, breakpointsPx]);
|
|
269
|
-
// Create helper components for Tailwind breakpoints
|
|
270
|
-
var components = React.useMemo(function () {
|
|
271
|
-
return tslib.__assign({
|
|
272
|
-
'XsOnly': function (props) {
|
|
273
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('xs') && props.children);
|
|
274
|
-
},
|
|
275
|
-
'SmOnly': function (props) {
|
|
276
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('sm') && props.children);
|
|
277
|
-
},
|
|
278
|
-
'MdOnly': function (props) {
|
|
279
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('md') && props.children);
|
|
280
|
-
},
|
|
281
|
-
'LgOnly': function (props) {
|
|
282
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('lg') && props.children);
|
|
283
|
-
},
|
|
284
|
-
'XlOnly': function (props) {
|
|
285
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('xl') && props.children);
|
|
286
|
-
},
|
|
287
|
-
'2xlOnly': function (props) {
|
|
288
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('2xl') && props.children);
|
|
289
|
-
},
|
|
290
|
-
'3xlOnly': function (props) {
|
|
291
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('3xl') && props.children);
|
|
292
|
-
},
|
|
293
|
-
'4xlOnly': function (props) {
|
|
294
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('4xl') && props.children);
|
|
295
|
-
},
|
|
296
|
-
'5xlOnly': function (props) {
|
|
297
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('5xl') && props.children);
|
|
298
|
-
},
|
|
299
|
-
'6xlOnly': function (props) {
|
|
300
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('6xl') && props.children);
|
|
301
|
-
},
|
|
302
|
-
'7xlOnly': function (props) {
|
|
303
|
-
return React__default.default.createElement(React__default.default.Fragment, null, isExactBreakpoint('7xl') && props.children);
|
|
304
|
-
},
|
|
305
|
-
'XsOrLarger': function (props) {
|
|
306
|
-
return React__default.default.createElement(React__default.default.Fragment, null, breakpointMatches.isXs && props.children);
|
|
307
|
-
},
|
|
308
|
-
'SmOrLarger': function (props) {
|
|
309
|
-
return React__default.default.createElement(React__default.default.Fragment, null, breakpointMatches.isSm && props.children);
|
|
310
|
-
},
|
|
311
|
-
'MdOrLarger': function (props) {
|
|
312
|
-
return React__default.default.createElement(React__default.default.Fragment, null, breakpointMatches.isMd && props.children);
|
|
313
|
-
},
|
|
314
|
-
'LgOrLarger': function (props) {
|
|
315
|
-
return React__default.default.createElement(React__default.default.Fragment, null, breakpointMatches.isLg && props.children);
|
|
316
|
-
},
|
|
317
|
-
'XlOrLarger': function (props) {
|
|
318
|
-
return React__default.default.createElement(React__default.default.Fragment, null, breakpointMatches.isXl && props.children);
|
|
319
|
-
}
|
|
320
|
-
}, Object.keys(customQueriesPx).reduce(function (acc, key) {
|
|
321
|
-
var componentName = key.charAt(0).toUpperCase() + key.slice(1);
|
|
322
|
-
acc[componentName] = function (props) {
|
|
323
|
-
return React__default.default.createElement(React__default.default.Fragment, null, customMatches[key] && props.children);
|
|
324
|
-
};
|
|
325
|
-
return acc;
|
|
326
|
-
}, {}));
|
|
327
|
-
}, [breakpointMatches, customMatches, isExactBreakpoint, customQueriesPx]);
|
|
328
|
-
return {
|
|
329
|
-
containerRef: containerRef,
|
|
330
|
-
queries: tslib.__assign(tslib.__assign({}, breakpointMatches), customMatches),
|
|
331
|
-
components: components
|
|
332
|
-
};
|
|
333
|
-
};
|
|
334
|
-
exports.useContainerQueries = useContainerQueries;
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
import { __assign } from 'tslib';
|
|
2
|
-
import React, { useMemo, useState, useRef, useCallback, useEffect } from 'react';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Tailwind CSS default container query breakpoints
|
|
6
|
-
* These match the default values from @tailwindcss/container-queries plugin
|
|
7
|
-
*/
|
|
8
|
-
var DEFAULT_BREAKPOINTS = {
|
|
9
|
-
'xs': '20rem',
|
|
10
|
-
// 320px
|
|
11
|
-
'sm': '24rem',
|
|
12
|
-
// 384px
|
|
13
|
-
'md': '28rem',
|
|
14
|
-
// 448px
|
|
15
|
-
'lg': '32rem',
|
|
16
|
-
// 512px
|
|
17
|
-
'xl': '36rem',
|
|
18
|
-
// 576px
|
|
19
|
-
'2xl': '42rem',
|
|
20
|
-
// 672px
|
|
21
|
-
'3xl': '48rem',
|
|
22
|
-
// 768px
|
|
23
|
-
'4xl': '56rem',
|
|
24
|
-
// 896px
|
|
25
|
-
'5xl': '64rem',
|
|
26
|
-
// 1024px
|
|
27
|
-
'6xl': '72rem',
|
|
28
|
-
// 1152px
|
|
29
|
-
'7xl': '80rem' // 1280px
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Convert rem/px values to pixels for comparison
|
|
33
|
-
*/
|
|
34
|
-
var parseBreakpointValue = function (value) {
|
|
35
|
-
if (value.endsWith('rem')) {
|
|
36
|
-
return parseFloat(value) * 16; // Assuming 1rem = 16px
|
|
37
|
-
}
|
|
38
|
-
if (value.endsWith('px')) {
|
|
39
|
-
return parseFloat(value);
|
|
40
|
-
}
|
|
41
|
-
return parseFloat(value);
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* A React hook for responding to container size changes using Tailwind CSS container query breakpoints.
|
|
45
|
-
*
|
|
46
|
-
* This hook uses ResizeObserver to detect when a container element crosses breakpoint thresholds,
|
|
47
|
-
* enabling component-level responsive behavior independent of viewport size.
|
|
48
|
-
*
|
|
49
|
-
* @param propQueries - Optional custom container size queries in the format { queryName: 'minWidth' }
|
|
50
|
-
* Example: { large: '600px', extraLarge: '48rem' }
|
|
51
|
-
*
|
|
52
|
-
* @returns An object containing:
|
|
53
|
-
* - containerRef: A ref to attach to your container element
|
|
54
|
-
* - queries: Boolean flags for each breakpoint (isXs, isSm, isMd, etc.) and custom queries
|
|
55
|
-
* - components: React components for conditional rendering (XsOnly, SmOrLarger, etc.)
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```tsx
|
|
59
|
-
* const MyComponent = () => {
|
|
60
|
-
* const { containerRef, queries, components } = useContainerQueries()
|
|
61
|
-
* const { MdOrLarger } = components
|
|
62
|
-
*
|
|
63
|
-
* return (
|
|
64
|
-
* <div ref={containerRef}>
|
|
65
|
-
* {queries.isSm && <p>Small container</p>}
|
|
66
|
-
* <MdOrLarger>
|
|
67
|
-
* <p>Medium or larger container</p>
|
|
68
|
-
* </MdOrLarger>
|
|
69
|
-
* </div>
|
|
70
|
-
* )
|
|
71
|
-
* }
|
|
72
|
-
* ```
|
|
73
|
-
*
|
|
74
|
-
* @example With custom queries
|
|
75
|
-
* ```tsx
|
|
76
|
-
* const { containerRef, queries, components } = useContainerQueries({
|
|
77
|
-
* compact: '400px',
|
|
78
|
-
* spacious: '800px',
|
|
79
|
-
* })
|
|
80
|
-
* const { Compact, Spacious } = components
|
|
81
|
-
*
|
|
82
|
-
* return (
|
|
83
|
-
* <div ref={containerRef}>
|
|
84
|
-
* <Compact><p>Compact view</p></Compact>
|
|
85
|
-
* <Spacious><p>Spacious view</p></Spacious>
|
|
86
|
-
* </div>
|
|
87
|
-
* )
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
var useContainerQueries = function (propQueries) {
|
|
91
|
-
if (propQueries === void 0) {
|
|
92
|
-
propQueries = {};
|
|
93
|
-
}
|
|
94
|
-
// SSR support - return safe defaults when window is undefined
|
|
95
|
-
if (typeof window === 'undefined') {
|
|
96
|
-
return {
|
|
97
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
98
|
-
containerRef: function () {},
|
|
99
|
-
queries: {
|
|
100
|
-
isXs: false,
|
|
101
|
-
isSm: false,
|
|
102
|
-
isMd: false,
|
|
103
|
-
isLg: false,
|
|
104
|
-
isXl: false,
|
|
105
|
-
is2xl: false,
|
|
106
|
-
is3xl: false,
|
|
107
|
-
is4xl: false,
|
|
108
|
-
is5xl: false,
|
|
109
|
-
is6xl: false,
|
|
110
|
-
is7xl: true // Default to largest for SSR
|
|
111
|
-
},
|
|
112
|
-
components: {
|
|
113
|
-
'XsOnly': function () {
|
|
114
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
115
|
-
},
|
|
116
|
-
'SmOnly': function () {
|
|
117
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
118
|
-
},
|
|
119
|
-
'MdOnly': function () {
|
|
120
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
121
|
-
},
|
|
122
|
-
'LgOnly': function () {
|
|
123
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
124
|
-
},
|
|
125
|
-
'XlOnly': function () {
|
|
126
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
127
|
-
},
|
|
128
|
-
'2xlOnly': function () {
|
|
129
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
130
|
-
},
|
|
131
|
-
'3xlOnly': function () {
|
|
132
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
133
|
-
},
|
|
134
|
-
'4xlOnly': function () {
|
|
135
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
136
|
-
},
|
|
137
|
-
'5xlOnly': function () {
|
|
138
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
139
|
-
},
|
|
140
|
-
'6xlOnly': function () {
|
|
141
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null);
|
|
142
|
-
},
|
|
143
|
-
'7xlOnly': function (props) {
|
|
144
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
145
|
-
},
|
|
146
|
-
'XsOrLarger': function (props) {
|
|
147
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
148
|
-
},
|
|
149
|
-
'SmOrLarger': function (props) {
|
|
150
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
151
|
-
},
|
|
152
|
-
'MdOrLarger': function (props) {
|
|
153
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
154
|
-
},
|
|
155
|
-
'LgOrLarger': function (props) {
|
|
156
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
157
|
-
},
|
|
158
|
-
'XlOrLarger': function (props) {
|
|
159
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
// Parse all breakpoints to pixel values for comparison
|
|
165
|
-
var breakpointsPx = useMemo(function () {
|
|
166
|
-
return Object.entries(DEFAULT_BREAKPOINTS).reduce(function (acc, _a) {
|
|
167
|
-
var key = _a[0],
|
|
168
|
-
value = _a[1];
|
|
169
|
-
acc[key] = parseBreakpointValue(value);
|
|
170
|
-
return acc;
|
|
171
|
-
}, {});
|
|
172
|
-
}, []);
|
|
173
|
-
// Parse custom queries
|
|
174
|
-
var customQueriesPx = useMemo(function () {
|
|
175
|
-
return Object.entries(propQueries).reduce(function (acc, _a) {
|
|
176
|
-
var key = _a[0],
|
|
177
|
-
value = _a[1];
|
|
178
|
-
acc[key] = parseBreakpointValue(value);
|
|
179
|
-
return acc;
|
|
180
|
-
}, {});
|
|
181
|
-
}, [propQueries]);
|
|
182
|
-
// State to track container width
|
|
183
|
-
var _a = useState(0),
|
|
184
|
-
containerWidth = _a[0],
|
|
185
|
-
setContainerWidth = _a[1];
|
|
186
|
-
// ResizeObserver ref
|
|
187
|
-
var resizeObserverRef = useRef(null);
|
|
188
|
-
// Callback ref for the container element
|
|
189
|
-
var containerRef = useCallback(function (node) {
|
|
190
|
-
// Cleanup previous observer
|
|
191
|
-
if (resizeObserverRef.current) {
|
|
192
|
-
resizeObserverRef.current.disconnect();
|
|
193
|
-
resizeObserverRef.current = null;
|
|
194
|
-
}
|
|
195
|
-
if (node) {
|
|
196
|
-
// Create new ResizeObserver
|
|
197
|
-
resizeObserverRef.current = new ResizeObserver(function (entries) {
|
|
198
|
-
var _a, _b, _c;
|
|
199
|
-
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
200
|
-
var entry = entries_1[_i];
|
|
201
|
-
// Use borderBoxSize for more accurate measurements
|
|
202
|
-
var width_1 = (_c = (_b = (_a = entry.borderBoxSize) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.inlineSize) !== null && _c !== void 0 ? _c : entry.contentRect.width;
|
|
203
|
-
setContainerWidth(width_1);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
resizeObserverRef.current.observe(node);
|
|
207
|
-
// Set initial width
|
|
208
|
-
var width = node.getBoundingClientRect().width;
|
|
209
|
-
setContainerWidth(width);
|
|
210
|
-
}
|
|
211
|
-
}, []);
|
|
212
|
-
// Cleanup on unmount
|
|
213
|
-
useEffect(function () {
|
|
214
|
-
return function () {
|
|
215
|
-
if (resizeObserverRef.current) {
|
|
216
|
-
resizeObserverRef.current.disconnect();
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
}, []);
|
|
220
|
-
// Calculate breakpoint matches based on container width
|
|
221
|
-
var breakpointMatches = useMemo(function () {
|
|
222
|
-
return {
|
|
223
|
-
isXs: containerWidth >= breakpointsPx.xs,
|
|
224
|
-
isSm: containerWidth >= breakpointsPx.sm,
|
|
225
|
-
isMd: containerWidth >= breakpointsPx.md,
|
|
226
|
-
isLg: containerWidth >= breakpointsPx.lg,
|
|
227
|
-
isXl: containerWidth >= breakpointsPx.xl,
|
|
228
|
-
is2xl: containerWidth >= breakpointsPx['2xl'],
|
|
229
|
-
is3xl: containerWidth >= breakpointsPx['3xl'],
|
|
230
|
-
is4xl: containerWidth >= breakpointsPx['4xl'],
|
|
231
|
-
is5xl: containerWidth >= breakpointsPx['5xl'],
|
|
232
|
-
is6xl: containerWidth >= breakpointsPx['6xl'],
|
|
233
|
-
is7xl: containerWidth >= breakpointsPx['7xl']
|
|
234
|
-
};
|
|
235
|
-
}, [containerWidth, breakpointsPx]);
|
|
236
|
-
// Calculate custom query matches
|
|
237
|
-
var customMatches = useMemo(function () {
|
|
238
|
-
return Object.entries(customQueriesPx).reduce(function (acc, _a) {
|
|
239
|
-
var key = _a[0],
|
|
240
|
-
value = _a[1];
|
|
241
|
-
acc[key] = containerWidth >= value;
|
|
242
|
-
return acc;
|
|
243
|
-
}, {});
|
|
244
|
-
}, [containerWidth, customQueriesPx]);
|
|
245
|
-
// Helper function to check if container is at exact breakpoint (not larger)
|
|
246
|
-
var isExactBreakpoint = useCallback(function (breakpoint) {
|
|
247
|
-
var sortedBreakpoints = Object.entries(breakpointsPx).sort(function (_a, _b) {
|
|
248
|
-
var a = _a[1];
|
|
249
|
-
var b = _b[1];
|
|
250
|
-
return a - b;
|
|
251
|
-
});
|
|
252
|
-
var currentIndex = sortedBreakpoints.findIndex(function (_a) {
|
|
253
|
-
var key = _a[0];
|
|
254
|
-
return key === breakpoint;
|
|
255
|
-
});
|
|
256
|
-
var nextBreakpoint = sortedBreakpoints[currentIndex + 1];
|
|
257
|
-
var minWidth = breakpointsPx[breakpoint];
|
|
258
|
-
var maxWidth = nextBreakpoint ? nextBreakpoint[1] : Infinity;
|
|
259
|
-
return containerWidth >= minWidth && containerWidth < maxWidth;
|
|
260
|
-
}, [containerWidth, breakpointsPx]);
|
|
261
|
-
// Create helper components for Tailwind breakpoints
|
|
262
|
-
var components = useMemo(function () {
|
|
263
|
-
return __assign({
|
|
264
|
-
'XsOnly': function (props) {
|
|
265
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('xs') && props.children);
|
|
266
|
-
},
|
|
267
|
-
'SmOnly': function (props) {
|
|
268
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('sm') && props.children);
|
|
269
|
-
},
|
|
270
|
-
'MdOnly': function (props) {
|
|
271
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('md') && props.children);
|
|
272
|
-
},
|
|
273
|
-
'LgOnly': function (props) {
|
|
274
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('lg') && props.children);
|
|
275
|
-
},
|
|
276
|
-
'XlOnly': function (props) {
|
|
277
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('xl') && props.children);
|
|
278
|
-
},
|
|
279
|
-
'2xlOnly': function (props) {
|
|
280
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('2xl') && props.children);
|
|
281
|
-
},
|
|
282
|
-
'3xlOnly': function (props) {
|
|
283
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('3xl') && props.children);
|
|
284
|
-
},
|
|
285
|
-
'4xlOnly': function (props) {
|
|
286
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('4xl') && props.children);
|
|
287
|
-
},
|
|
288
|
-
'5xlOnly': function (props) {
|
|
289
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('5xl') && props.children);
|
|
290
|
-
},
|
|
291
|
-
'6xlOnly': function (props) {
|
|
292
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('6xl') && props.children);
|
|
293
|
-
},
|
|
294
|
-
'7xlOnly': function (props) {
|
|
295
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, isExactBreakpoint('7xl') && props.children);
|
|
296
|
-
},
|
|
297
|
-
'XsOrLarger': function (props) {
|
|
298
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, breakpointMatches.isXs && props.children);
|
|
299
|
-
},
|
|
300
|
-
'SmOrLarger': function (props) {
|
|
301
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, breakpointMatches.isSm && props.children);
|
|
302
|
-
},
|
|
303
|
-
'MdOrLarger': function (props) {
|
|
304
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, breakpointMatches.isMd && props.children);
|
|
305
|
-
},
|
|
306
|
-
'LgOrLarger': function (props) {
|
|
307
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, breakpointMatches.isLg && props.children);
|
|
308
|
-
},
|
|
309
|
-
'XlOrLarger': function (props) {
|
|
310
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, breakpointMatches.isXl && props.children);
|
|
311
|
-
}
|
|
312
|
-
}, Object.keys(customQueriesPx).reduce(function (acc, key) {
|
|
313
|
-
var componentName = key.charAt(0).toUpperCase() + key.slice(1);
|
|
314
|
-
acc[componentName] = function (props) {
|
|
315
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, customMatches[key] && props.children);
|
|
316
|
-
};
|
|
317
|
-
return acc;
|
|
318
|
-
}, {}));
|
|
319
|
-
}, [breakpointMatches, customMatches, isExactBreakpoint, customQueriesPx]);
|
|
320
|
-
return {
|
|
321
|
-
containerRef: containerRef,
|
|
322
|
-
queries: __assign(__assign({}, breakpointMatches), customMatches),
|
|
323
|
-
components: components
|
|
324
|
-
};
|
|
325
|
-
};
|
|
326
|
-
export { useContainerQueries };
|