rsuite 6.0.0-canary-20250620 → 6.0.0-canary-20250622
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/Accordion/styles/index.css +0 -78
- package/AutoComplete/styles/index.css +1 -79
- package/Avatar/styles/index.css +0 -78
- package/AvatarGroup/styles/index.css +0 -78
- package/Badge/styles/index.css +0 -78
- package/Box/styles/index.css +0 -78
- package/Breadcrumb/styles/index.css +0 -78
- package/Button/styles/index.css +0 -78
- package/ButtonGroup/styles/index.css +0 -78
- package/ButtonToolbar/styles/index.css +0 -82
- package/Calendar/styles/index.css +0 -78
- package/Card/styles/index.css +0 -78
- package/CardGroup/styles/index.css +0 -78
- package/Carousel/styles/index.css +0 -78
- package/CascadeTree/styles/index.css +0 -78
- package/Cascader/styles/index.css +1 -79
- package/Center/styles/index.css +0 -78
- package/CheckPicker/styles/index.css +1 -79
- package/CheckTree/styles/index.css +1 -79
- package/CheckTreePicker/styles/index.css +1 -79
- package/Checkbox/styles/index.css +0 -78
- package/CheckboxGroup/styles/index.css +0 -78
- package/Container/styles/index.css +0 -78
- package/Content/styles/index.css +0 -78
- package/DateInput/styles/index.css +0 -78
- package/DatePicker/styles/index.css +1 -79
- package/DateRangeInput/styles/index.css +0 -78
- package/DateRangePicker/styles/index.css +1 -79
- package/Divider/styles/index.css +0 -78
- package/Drawer/styles/index.css +0 -78
- package/Dropdown/styles/index.css +0 -78
- package/FlexboxGrid/styles/index.css +0 -78
- package/Footer/styles/index.css +0 -78
- package/Form/styles/index.css +0 -78
- package/FormControl/styles/index.css +0 -78
- package/FormControlLabel/styles/index.css +0 -78
- package/FormErrorMessage/styles/index.css +0 -78
- package/FormGroup/styles/index.css +0 -78
- package/FormHelpText/styles/index.css +0 -78
- package/FormStack/styles/index.css +0 -78
- package/Grid/styles/index.css +0 -78
- package/Header/styles/index.css +0 -78
- package/Heading/styles/index.css +0 -78
- package/HeadingGroup/styles/index.css +0 -78
- package/Highlight/styles/index.css +0 -78
- package/IconButton/styles/index.css +0 -78
- package/Image/styles/index.css +0 -78
- package/InlineEdit/styles/index.css +0 -78
- package/Input/styles/index.css +0 -78
- package/InputGroup/styles/index.css +1 -79
- package/InputNumber/styles/index.css +1 -79
- package/InputPicker/styles/index.css +1 -79
- package/Kbd/styles/index.css +0 -78
- package/Link/styles/index.css +0 -78
- package/List/styles/index.css +0 -78
- package/Loader/styles/index.css +0 -78
- package/Menu/styles/index.css +0 -78
- package/Message/styles/index.css +0 -78
- package/Modal/styles/index.css +0 -78
- package/MultiCascadeTree/styles/index.css +1 -79
- package/MultiCascader/styles/index.css +1 -79
- package/Nav/styles/index.css +0 -78
- package/Navbar/styles/index.css +0 -78
- package/Notification/styles/index.css +0 -78
- package/NumberInput/styles/index.css +1 -79
- package/Pagination/styles/index.css +1 -79
- package/Panel/styles/index.css +0 -78
- package/PanelGroup/styles/index.css +0 -78
- package/PasswordInput/styles/index.css +1 -79
- package/PasswordStrengthMeter/styles/index.css +0 -78
- package/PinInput/styles/index.css +0 -78
- package/Placeholder/styles/index.css +0 -78
- package/Popover/styles/index.css +0 -78
- package/Progress/styles/index.css +0 -78
- package/ProgressCircle/styles/index.css +0 -78
- package/Radio/styles/index.css +0 -78
- package/RadioGroup/styles/index.css +0 -78
- package/RadioTile/styles/index.css +0 -78
- package/RangeSlider/styles/index.css +0 -78
- package/Rate/styles/index.css +0 -78
- package/SegmentedControl/package.json +7 -0
- package/SegmentedControl/styles/index.css +159 -0
- package/SelectPicker/styles/index.css +1 -79
- package/Sidebar/styles/index.css +0 -78
- package/Sidenav/styles/index.css +0 -78
- package/Slider/styles/index.css +0 -78
- package/Stack/styles/index.css +0 -78
- package/Stat/styles/index.css +0 -78
- package/StatGroup/styles/index.css +0 -78
- package/Steps/styles/index.css +0 -78
- package/Table/styles/index.css +0 -78
- package/Tabs/styles/index.css +0 -78
- package/Tag/styles/index.css +0 -78
- package/TagGroup/styles/index.css +0 -78
- package/TagInput/styles/index.css +1 -79
- package/TagPicker/styles/index.css +1 -79
- package/Text/styles/index.css +0 -78
- package/Textarea/styles/index.css +0 -78
- package/TimePicker/styles/index.css +1 -79
- package/TimeRangePicker/styles/index.css +1 -79
- package/Timeline/styles/index.css +0 -78
- package/Toggle/styles/index.css +0 -78
- package/Tooltip/styles/index.css +0 -78
- package/Tree/styles/index.css +1 -79
- package/TreePicker/styles/index.css +1 -79
- package/Uploader/styles/index.css +0 -78
- package/cjs/ButtonToolbar/ButtonToolbar.js +2 -0
- package/cjs/Grid/utils/styles.d.ts +1 -1
- package/cjs/InputPicker/utils.d.ts +1 -1
- package/cjs/Nav/Nav.d.ts +2 -3
- package/cjs/RadioGroup/RadioGroup.d.ts +4 -1
- package/cjs/SegmentedControl/Indicator.d.ts +10 -0
- package/cjs/SegmentedControl/Indicator.js +22 -0
- package/cjs/SegmentedControl/SegmentedControl.d.ts +27 -0
- package/cjs/SegmentedControl/SegmentedControl.js +87 -0
- package/cjs/SegmentedControl/SegmentedItem.d.ts +16 -0
- package/cjs/SegmentedControl/SegmentedItem.js +44 -0
- package/cjs/SegmentedControl/hooks/useIndicatorPosition.d.ts +17 -0
- package/cjs/SegmentedControl/hooks/useIndicatorPosition.js +55 -0
- package/cjs/SegmentedControl/index.d.ts +4 -0
- package/cjs/SegmentedControl/index.js +11 -0
- package/cjs/Slider/ProgressBar.js +1 -1
- package/cjs/Stack/Stack.js +20 -5
- package/cjs/Stack/utils.d.ts +9 -0
- package/cjs/Stack/utils.js +38 -0
- package/cjs/Tabs/Tabs.d.ts +4 -2
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +6 -0
- package/cjs/internals/Box/Box.d.ts +27 -27
- package/cjs/internals/Box/Box.js +13 -8
- package/cjs/internals/Box/utils.d.ts +4 -1
- package/cjs/internals/Box/utils.js +154 -13
- package/cjs/internals/Provider/types.d.ts +2 -0
- package/cjs/internals/constants/index.js +2 -2
- package/cjs/internals/hooks/useElementResize.d.ts +2 -1
- package/cjs/internals/hooks/useElementResize.js +50 -7
- package/cjs/internals/hooks/useStyled.d.ts +60 -0
- package/cjs/internals/hooks/useStyled.js +257 -0
- package/cjs/internals/utils/colours.js +1 -1
- package/cjs/internals/utils/style-sheet/css.d.ts +1 -1
- package/cjs/internals/utils/style-sheet/css.js +1 -1
- package/cjs/internals/utils/style-sheet/index.d.ts +1 -0
- package/cjs/internals/utils/style-sheet/index.js +6 -0
- package/cjs/internals/utils/style-sheet/style-manager.d.ts +50 -0
- package/cjs/internals/utils/style-sheet/style-manager.js +97 -0
- package/dist/rsuite-no-reset.css +200 -101
- package/dist/rsuite-no-reset.min.css +1 -1
- package/dist/rsuite.css +200 -101
- package/dist/rsuite.js +172 -14
- package/dist/rsuite.js.map +1 -1
- package/dist/rsuite.min.css +1 -1
- package/dist/rsuite.min.js +1 -1
- package/dist/rsuite.min.js.map +1 -1
- package/esm/ButtonToolbar/ButtonToolbar.js +2 -0
- package/esm/Grid/utils/styles.d.ts +1 -1
- package/esm/InputPicker/utils.d.ts +1 -1
- package/esm/Nav/Nav.d.ts +2 -3
- package/esm/RadioGroup/RadioGroup.d.ts +4 -1
- package/esm/SegmentedControl/Indicator.d.ts +10 -0
- package/esm/SegmentedControl/Indicator.js +17 -0
- package/esm/SegmentedControl/SegmentedControl.d.ts +27 -0
- package/esm/SegmentedControl/SegmentedControl.js +81 -0
- package/esm/SegmentedControl/SegmentedItem.d.ts +16 -0
- package/esm/SegmentedControl/SegmentedItem.js +39 -0
- package/esm/SegmentedControl/hooks/useIndicatorPosition.d.ts +17 -0
- package/esm/SegmentedControl/hooks/useIndicatorPosition.js +50 -0
- package/esm/SegmentedControl/index.d.ts +4 -0
- package/esm/SegmentedControl/index.js +8 -0
- package/esm/Slider/ProgressBar.js +1 -1
- package/esm/Stack/Stack.js +21 -6
- package/esm/Stack/utils.d.ts +9 -0
- package/esm/Stack/utils.js +35 -0
- package/esm/Tabs/Tabs.d.ts +4 -2
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/internals/Box/Box.d.ts +27 -27
- package/esm/internals/Box/Box.js +9 -4
- package/esm/internals/Box/utils.d.ts +4 -1
- package/esm/internals/Box/utils.js +153 -13
- package/esm/internals/Provider/types.d.ts +2 -0
- package/esm/internals/constants/index.js +2 -2
- package/esm/internals/hooks/useElementResize.d.ts +2 -1
- package/esm/internals/hooks/useElementResize.js +50 -7
- package/esm/internals/hooks/useStyled.d.ts +60 -0
- package/esm/internals/hooks/useStyled.js +251 -0
- package/esm/internals/utils/colours.js +1 -1
- package/esm/internals/utils/style-sheet/css.d.ts +1 -1
- package/esm/internals/utils/style-sheet/css.js +1 -1
- package/esm/internals/utils/style-sheet/index.d.ts +1 -0
- package/esm/internals/utils/style-sheet/index.js +2 -1
- package/esm/internals/utils/style-sheet/style-manager.d.ts +50 -0
- package/esm/internals/utils/style-sheet/style-manager.js +93 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { getCssValue, getSizeStyle, getColorVar } from "../utils/index.js";
|
|
3
|
-
|
|
3
|
+
import { BREAKPOINTS } from "../constants/index.js";
|
|
4
4
|
// Mapping for padding properties to their CSS style equivalents
|
|
5
5
|
const paddingStyleMap = {
|
|
6
6
|
p: 'padding',
|
|
@@ -70,6 +70,45 @@ export const omitBoxProps = props => {
|
|
|
70
70
|
return filteredProps;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Checks if a value is a responsive value object
|
|
75
|
+
* @param value - Value to check
|
|
76
|
+
* @returns True if the value is a responsive value object
|
|
77
|
+
*/
|
|
78
|
+
function isResponsiveValue(value) {
|
|
79
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).some(key => BREAKPOINTS.includes(key));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Process a value that might be a responsive value
|
|
84
|
+
* @param value - Value to process
|
|
85
|
+
* @param processor - Function to process non-responsive values
|
|
86
|
+
* @returns Processed value or responsive object with processed values
|
|
87
|
+
*/
|
|
88
|
+
function processResponsiveValue(value, processor) {
|
|
89
|
+
if (value === undefined) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
if (isResponsiveValue(value)) {
|
|
93
|
+
const result = {};
|
|
94
|
+
Object.entries(value).forEach(([breakpoint, val]) => {
|
|
95
|
+
if (val !== undefined) {
|
|
96
|
+
const processed = processor(val);
|
|
97
|
+
if (processed !== undefined) {
|
|
98
|
+
result[breakpoint] = processed;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
103
|
+
}
|
|
104
|
+
return processor(value);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Type for CSS variable values that can be string, number, or responsive values
|
|
108
|
+
|
|
109
|
+
// Silence ESLint warnings for unused parameters in forEach callbacks
|
|
110
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
111
|
+
|
|
73
112
|
/**
|
|
74
113
|
* Converts layout properties to CSS variables with abbreviated names
|
|
75
114
|
* @param props Object containing layout properties
|
|
@@ -77,42 +116,143 @@ export const omitBoxProps = props => {
|
|
|
77
116
|
*/
|
|
78
117
|
export const getBoxCSSVariables = props => {
|
|
79
118
|
const cssVars = {};
|
|
119
|
+
const prefix = `--rs-box-`;
|
|
80
120
|
|
|
81
121
|
// Process padding properties
|
|
82
122
|
Object.keys(paddingStyleMap).forEach(propKey => {
|
|
83
123
|
if (props[propKey] !== undefined) {
|
|
84
|
-
cssVars[
|
|
124
|
+
cssVars[`${prefix}${propKey}`] = processResponsiveValue(props[propKey], val => getCssValue(val));
|
|
85
125
|
}
|
|
86
126
|
});
|
|
87
127
|
|
|
88
128
|
// Process margin properties
|
|
89
129
|
Object.keys(marginStyleMap).forEach(propKey => {
|
|
90
130
|
if (props[propKey] !== undefined) {
|
|
91
|
-
cssVars[
|
|
131
|
+
cssVars[`${prefix}${propKey}`] = processResponsiveValue(props[propKey], val => getCssValue(val));
|
|
92
132
|
}
|
|
93
133
|
});
|
|
94
134
|
|
|
95
135
|
// Process size properties
|
|
96
136
|
Object.keys(sizeStyleMap).forEach(propKey => {
|
|
97
137
|
if (props[propKey] !== undefined) {
|
|
98
|
-
cssVars[
|
|
138
|
+
cssVars[`${prefix}${propKey}`] = processResponsiveValue(props[propKey], val => getCssValue(val));
|
|
99
139
|
}
|
|
100
140
|
});
|
|
101
141
|
if (props.bd !== undefined) {
|
|
102
|
-
cssVars[
|
|
142
|
+
cssVars[`${prefix}bd`] = processResponsiveValue(props.bd, val => getCssValue(val));
|
|
103
143
|
}
|
|
104
144
|
if (props.display !== undefined) {
|
|
105
|
-
cssVars[
|
|
145
|
+
cssVars[`${prefix}display`] = processResponsiveValue(props.display, val => val);
|
|
106
146
|
}
|
|
107
147
|
if (props.c !== undefined) {
|
|
108
|
-
cssVars[
|
|
148
|
+
cssVars[`${prefix}c`] = processResponsiveValue(props.c, val => getColorVar(val));
|
|
109
149
|
}
|
|
110
150
|
if (props.bg !== undefined) {
|
|
111
|
-
cssVars[
|
|
151
|
+
cssVars[`${prefix}bg`] = processResponsiveValue(props.bg, val => getColorVar(val));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Handle special cases for rounded and shadow
|
|
155
|
+
if (props.rounded !== undefined) {
|
|
156
|
+
const processRounded = val => {
|
|
157
|
+
const result = getSizeStyle(val, 'box', 'rounded');
|
|
158
|
+
return result ? result : undefined;
|
|
159
|
+
};
|
|
160
|
+
if (isResponsiveValue(props.rounded)) {
|
|
161
|
+
// Handle responsive rounded values
|
|
162
|
+
const responsiveRounded = {};
|
|
163
|
+
Object.entries(props.rounded).forEach(([breakpoint, val]) => {
|
|
164
|
+
if (val !== undefined) {
|
|
165
|
+
const styleObj = processRounded(val);
|
|
166
|
+
if (styleObj) {
|
|
167
|
+
responsiveRounded[breakpoint] = styleObj;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// For each CSS variable key in the rounded styles, create a responsive value
|
|
173
|
+
const processedKeys = new Set();
|
|
174
|
+
Object.entries(responsiveRounded).forEach(([_breakpoint, styleObj]) => {
|
|
175
|
+
if (styleObj) {
|
|
176
|
+
Object.entries(styleObj).forEach(([key, _value]) => {
|
|
177
|
+
processedKeys.add(key);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
processedKeys.forEach(key => {
|
|
182
|
+
const responsiveValue = {};
|
|
183
|
+
Object.entries(responsiveRounded).forEach(([breakpoint, styleObj]) => {
|
|
184
|
+
if (styleObj && styleObj[key] !== undefined) {
|
|
185
|
+
// Ensure we're only using string values for CSS variables
|
|
186
|
+
const value = styleObj[key];
|
|
187
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
188
|
+
responsiveValue[breakpoint] = value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
if (Object.keys(responsiveValue).length > 0) {
|
|
193
|
+
cssVars[key] = responsiveValue;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
} else {
|
|
197
|
+
// Handle non-responsive rounded value
|
|
198
|
+
const styleObj = processRounded(props.rounded);
|
|
199
|
+
if (styleObj) {
|
|
200
|
+
Object.entries(styleObj).forEach(([key, value]) => {
|
|
201
|
+
cssVars[key] = value;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (props.shadow !== undefined) {
|
|
207
|
+
const processShadow = val => {
|
|
208
|
+
const result = getSizeStyle(val, 'box', 'shadow');
|
|
209
|
+
return result ? result : undefined;
|
|
210
|
+
};
|
|
211
|
+
if (isResponsiveValue(props.shadow)) {
|
|
212
|
+
// Handle responsive shadow values
|
|
213
|
+
const responsiveShadow = {};
|
|
214
|
+
Object.entries(props.shadow).forEach(([breakpoint, val]) => {
|
|
215
|
+
if (val !== undefined) {
|
|
216
|
+
const styleObj = processShadow(val);
|
|
217
|
+
if (styleObj) {
|
|
218
|
+
responsiveShadow[breakpoint] = styleObj;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// For each CSS variable key in the shadow styles, create a responsive value
|
|
224
|
+
const processedKeys = new Set();
|
|
225
|
+
Object.entries(responsiveShadow).forEach(([_breakpoint, styleObj]) => {
|
|
226
|
+
if (styleObj) {
|
|
227
|
+
Object.entries(styleObj).forEach(([key, _value]) => {
|
|
228
|
+
processedKeys.add(key);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
processedKeys.forEach(key => {
|
|
233
|
+
const responsiveValue = {};
|
|
234
|
+
Object.entries(responsiveShadow).forEach(([breakpoint, styleObj]) => {
|
|
235
|
+
if (styleObj && styleObj[key] !== undefined) {
|
|
236
|
+
// Ensure we're only using string values for CSS variables
|
|
237
|
+
const value = styleObj[key];
|
|
238
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
239
|
+
responsiveValue[breakpoint] = value;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
if (Object.keys(responsiveValue).length > 0) {
|
|
244
|
+
cssVars[key] = responsiveValue;
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
} else {
|
|
248
|
+
// Handle non-responsive shadow value
|
|
249
|
+
const styleObj = processShadow(props.shadow);
|
|
250
|
+
if (styleObj) {
|
|
251
|
+
Object.entries(styleObj).forEach(([key, value]) => {
|
|
252
|
+
cssVars[key] = value;
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
112
256
|
}
|
|
113
|
-
return
|
|
114
|
-
...cssVars,
|
|
115
|
-
...getSizeStyle(props.rounded, 'box', 'rounded'),
|
|
116
|
-
...getSizeStyle(props.shadow, 'box', 'shadow')
|
|
117
|
-
};
|
|
257
|
+
return cssVars;
|
|
118
258
|
};
|
|
@@ -87,6 +87,7 @@ import type { RangeSliderProps } from '../../RangeSlider';
|
|
|
87
87
|
import type { RateProps } from '../../Rate';
|
|
88
88
|
import type { RowProps } from '../../Row';
|
|
89
89
|
import type { SelectPickerProps } from '../../SelectPicker';
|
|
90
|
+
import type { SegmentedControlProps } from '../../SegmentedControl';
|
|
90
91
|
import type { SidebarProps } from '../../Sidebar';
|
|
91
92
|
import type { SidenavProps } from '../../Sidenav';
|
|
92
93
|
import type { SliderProps } from '../../Slider';
|
|
@@ -209,6 +210,7 @@ export interface ReactSuiteComponents {
|
|
|
209
210
|
Rate: ComponentProps<RateProps>;
|
|
210
211
|
Row: ComponentProps<RowProps>;
|
|
211
212
|
SelectPicker: ComponentProps<SelectPickerProps>;
|
|
213
|
+
SegmentedControl: ComponentProps<SegmentedControlProps>;
|
|
212
214
|
Sidebar: ComponentProps<SidebarProps>;
|
|
213
215
|
Sidenav: ComponentProps<SidenavProps>;
|
|
214
216
|
Slider: ComponentProps<SliderProps>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export const SIZE = ['
|
|
3
|
-
export const BREAKPOINTS = ['
|
|
2
|
+
export const SIZE = ['xs', 'sm', 'md', 'lg'];
|
|
3
|
+
export const BREAKPOINTS = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
|
4
4
|
export const STATUS = ['success', 'warning', 'error', 'info'];
|
|
5
5
|
export const COLOR = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'violet'];
|
|
6
6
|
export const PLACEMENT_4 = ['top', 'bottom', 'right', 'left'];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
/**
|
|
2
3
|
* Attach the event handler directly to the specified DOM element,
|
|
3
4
|
* and it will be triggered when the size of the DOM element is changed.
|
|
@@ -5,5 +6,5 @@
|
|
|
5
6
|
* @param eventTarget The target to listen for events on
|
|
6
7
|
* @param listener An event handler
|
|
7
8
|
*/
|
|
8
|
-
export declare function useElementResize(eventTarget: Element | null | (() => Element | null)
|
|
9
|
+
export declare function useElementResize(eventTarget: Element | null | (() => Element | null) | React.RefObject<Element | null>, listener: ResizeObserverCallback): void;
|
|
9
10
|
export default useElementResize;
|
|
@@ -11,18 +11,61 @@ import { ResizeObserver } from '@juggle/resize-observer';
|
|
|
11
11
|
*/
|
|
12
12
|
export function useElementResize(eventTarget, listener) {
|
|
13
13
|
const resizeObserver = useRef(null);
|
|
14
|
+
const currentElement = useRef(null);
|
|
15
|
+
|
|
16
|
+
// Create the observer
|
|
14
17
|
useEffect(() => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// Get the target element
|
|
19
|
+
let target = null;
|
|
20
|
+
if (eventTarget) {
|
|
21
|
+
if (typeof eventTarget === 'function') {
|
|
22
|
+
target = eventTarget();
|
|
23
|
+
} else if ('current' in eventTarget) {
|
|
24
|
+
target = eventTarget.current;
|
|
25
|
+
} else {
|
|
26
|
+
target = eventTarget;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If target changed, disconnect the previous observer
|
|
31
|
+
if (currentElement.current !== target) {
|
|
32
|
+
if (resizeObserver.current) {
|
|
33
|
+
resizeObserver.current.disconnect();
|
|
34
|
+
resizeObserver.current = null;
|
|
20
35
|
}
|
|
36
|
+
currentElement.current = target;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// If we have a target and no observer, create one
|
|
40
|
+
if (target && !resizeObserver.current) {
|
|
41
|
+
const observer = new ResizeObserver(listener);
|
|
42
|
+
observer.observe(target);
|
|
43
|
+
resizeObserver.current = observer;
|
|
21
44
|
}
|
|
45
|
+
|
|
46
|
+
// Cleanup function
|
|
22
47
|
return () => {
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
if (resizeObserver.current) {
|
|
49
|
+
resizeObserver.current.disconnect();
|
|
50
|
+
resizeObserver.current = null;
|
|
51
|
+
}
|
|
52
|
+
currentElement.current = null;
|
|
25
53
|
};
|
|
26
54
|
}, [eventTarget, listener]);
|
|
55
|
+
|
|
56
|
+
// Update the current element reference if it changes
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (eventTarget) {
|
|
59
|
+
if (typeof eventTarget === 'function') {
|
|
60
|
+
currentElement.current = eventTarget();
|
|
61
|
+
} else if ('current' in eventTarget) {
|
|
62
|
+
currentElement.current = eventTarget.current;
|
|
63
|
+
} else {
|
|
64
|
+
currentElement.current = eventTarget;
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
currentElement.current = null;
|
|
68
|
+
}
|
|
69
|
+
}, [eventTarget]);
|
|
27
70
|
}
|
|
28
71
|
export default useElementResize;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import type { Breakpoints, ResponsiveValue } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Options for the useStyled hook
|
|
5
|
+
*/
|
|
6
|
+
interface UseStyledOptions {
|
|
7
|
+
/**
|
|
8
|
+
* CSS variables to apply
|
|
9
|
+
*/
|
|
10
|
+
cssVars?: Record<string, string | number | undefined | ResponsiveValue<string | number>>;
|
|
11
|
+
/**
|
|
12
|
+
* Base class name to include
|
|
13
|
+
*/
|
|
14
|
+
className?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Base style to merge with
|
|
17
|
+
*/
|
|
18
|
+
style?: CSSProperties;
|
|
19
|
+
/**
|
|
20
|
+
* Whether this element should be styled
|
|
21
|
+
* Can be a boolean or a breakpoint string
|
|
22
|
+
*/
|
|
23
|
+
enabled?: boolean | Breakpoints;
|
|
24
|
+
/**
|
|
25
|
+
* Prefix for the generated class name
|
|
26
|
+
* @default 'rs'
|
|
27
|
+
*/
|
|
28
|
+
prefix?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Result of the useStyled hook
|
|
32
|
+
*/
|
|
33
|
+
interface UseStyledResult {
|
|
34
|
+
/**
|
|
35
|
+
* Combined class name including the unique identifier
|
|
36
|
+
*/
|
|
37
|
+
className: string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Style object without CSS variables
|
|
40
|
+
*/
|
|
41
|
+
style: CSSProperties | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Unique identifier for this styled element
|
|
44
|
+
*/
|
|
45
|
+
id: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Custom hook for managing component styling with scoped CSS variables
|
|
49
|
+
*
|
|
50
|
+
* This hook handles:
|
|
51
|
+
* 1. Generating a unique class name for the component
|
|
52
|
+
* 2. Creating a scoped style rule to prevent CSS variable inheritance
|
|
53
|
+
* 3. Managing the lifecycle of style rules
|
|
54
|
+
* 4. Handling responsive values for different breakpoints
|
|
55
|
+
*
|
|
56
|
+
* @param options - Styling options
|
|
57
|
+
* @returns Styling properties to apply to the component
|
|
58
|
+
*/
|
|
59
|
+
export declare function useStyled(options: UseStyledOptions): UseStyledResult;
|
|
60
|
+
export default useStyled;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useId, useLayoutEffect, useContext } from 'react';
|
|
3
|
+
import isEmpty from 'lodash/isEmpty';
|
|
4
|
+
import { StyleManager } from "../utils/style-sheet/style-manager.js";
|
|
5
|
+
import { BREAKPOINTS } from "../constants/index.js";
|
|
6
|
+
import { CustomContext } from "../Provider/CustomContext.js";
|
|
7
|
+
// CSS Property Map
|
|
8
|
+
const propertyMap = {
|
|
9
|
+
// Padding
|
|
10
|
+
p: 'padding',
|
|
11
|
+
pt: 'padding-top',
|
|
12
|
+
pr: 'padding-right',
|
|
13
|
+
pb: 'padding-bottom',
|
|
14
|
+
pl: 'padding-left',
|
|
15
|
+
px: 'padding-inline',
|
|
16
|
+
py: 'padding-block',
|
|
17
|
+
// Margin
|
|
18
|
+
m: 'margin',
|
|
19
|
+
mt: 'margin-top',
|
|
20
|
+
mr: 'margin-right',
|
|
21
|
+
mb: 'margin-bottom',
|
|
22
|
+
ml: 'margin-left',
|
|
23
|
+
mx: 'margin-inline',
|
|
24
|
+
my: 'margin-block',
|
|
25
|
+
// Size
|
|
26
|
+
w: 'width',
|
|
27
|
+
h: 'height',
|
|
28
|
+
minw: 'min-width',
|
|
29
|
+
maxw: 'max-width',
|
|
30
|
+
minh: 'min-height',
|
|
31
|
+
maxh: 'max-height',
|
|
32
|
+
// Display
|
|
33
|
+
display: 'display',
|
|
34
|
+
// Color and Background
|
|
35
|
+
c: 'color',
|
|
36
|
+
bg: 'background',
|
|
37
|
+
// Border
|
|
38
|
+
bd: 'border',
|
|
39
|
+
rounded: 'border-radius',
|
|
40
|
+
// Shadow
|
|
41
|
+
shadow: 'box-shadow',
|
|
42
|
+
// Stack
|
|
43
|
+
spacing: 'gap',
|
|
44
|
+
align: 'align-items',
|
|
45
|
+
justify: 'justify-content'
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Breakpoint values in pixels - matching SCSS variables
|
|
49
|
+
const breakpointValues = {
|
|
50
|
+
xs: 0,
|
|
51
|
+
// Base mobile first
|
|
52
|
+
sm: 576,
|
|
53
|
+
// $screen-sm
|
|
54
|
+
md: 768,
|
|
55
|
+
// $screen-md
|
|
56
|
+
lg: 992,
|
|
57
|
+
// $screen-lg
|
|
58
|
+
xl: 1200,
|
|
59
|
+
// $screen-xl
|
|
60
|
+
xxl: 1400 // $screen-xxl
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Options for the useStyled hook
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Result of the useStyled hook
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Checks if a value is a responsive value object
|
|
73
|
+
* @param value - Value to check
|
|
74
|
+
* @returns True if the value is a responsive value object
|
|
75
|
+
*/
|
|
76
|
+
function isResponsiveValue(value) {
|
|
77
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).some(key => BREAKPOINTS.includes(key));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Custom hook for managing component styling with scoped CSS variables
|
|
82
|
+
*
|
|
83
|
+
* This hook handles:
|
|
84
|
+
* 1. Generating a unique class name for the component
|
|
85
|
+
* 2. Creating a scoped style rule to prevent CSS variable inheritance
|
|
86
|
+
* 3. Managing the lifecycle of style rules
|
|
87
|
+
* 4. Handling responsive values for different breakpoints
|
|
88
|
+
*
|
|
89
|
+
* @param options - Styling options
|
|
90
|
+
* @returns Styling properties to apply to the component
|
|
91
|
+
*/
|
|
92
|
+
export function useStyled(options) {
|
|
93
|
+
const {
|
|
94
|
+
cssVars = {},
|
|
95
|
+
className,
|
|
96
|
+
style,
|
|
97
|
+
enabled = true,
|
|
98
|
+
prefix = 'box'
|
|
99
|
+
} = options;
|
|
100
|
+
|
|
101
|
+
// CSS Variable Prefix, e.g. --rs-box-
|
|
102
|
+
const cssVarPrefix = `--rs-${prefix}-`;
|
|
103
|
+
const {
|
|
104
|
+
csp
|
|
105
|
+
} = useContext(CustomContext);
|
|
106
|
+
|
|
107
|
+
// Generate a unique ID for this component instance
|
|
108
|
+
const uniqueId = useId().replace(/:/g, '');
|
|
109
|
+
const componentId = `rs-${prefix}-${uniqueId}`;
|
|
110
|
+
|
|
111
|
+
// Only apply styling if enabled and there are CSS variables
|
|
112
|
+
const shouldApplyStyles = enabled && !isEmpty(cssVars);
|
|
113
|
+
|
|
114
|
+
// Apply CSS variables through StyleManager
|
|
115
|
+
useLayoutEffect(() => {
|
|
116
|
+
if (!shouldApplyStyles) return;
|
|
117
|
+
|
|
118
|
+
// Create base CSS rules for the variables
|
|
119
|
+
let baseVarRules = '';
|
|
120
|
+
let basePropRules = '';
|
|
121
|
+
|
|
122
|
+
// Track responsive variables to handle separately
|
|
123
|
+
const responsiveVars = {};
|
|
124
|
+
|
|
125
|
+
// Process CSS variables, separating responsive from non-responsive
|
|
126
|
+
Object.entries(cssVars).forEach(([key, value]) => {
|
|
127
|
+
if (value !== undefined) {
|
|
128
|
+
if (isResponsiveValue(value)) {
|
|
129
|
+
// Store responsive values for later processing
|
|
130
|
+
responsiveVars[key] = value;
|
|
131
|
+
|
|
132
|
+
// Add xs (mobile first) values to base styles if present
|
|
133
|
+
const xsValue = value.xs;
|
|
134
|
+
if (xsValue !== undefined) {
|
|
135
|
+
baseVarRules += `${key}: ${xsValue}; `;
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
// Add non-responsive values directly
|
|
139
|
+
baseVarRules += `${key}: ${value}; `;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Add actual style rules based on CSS variables
|
|
145
|
+
Object.keys(cssVars).forEach(varName => {
|
|
146
|
+
// Skip responsive values that don't have xs values
|
|
147
|
+
if (responsiveVars[varName] && !responsiveVars[varName].xs) return;
|
|
148
|
+
|
|
149
|
+
// Extract property name from variable name (remove prefix)
|
|
150
|
+
const propName = varName.startsWith(cssVarPrefix) ? varName.substring(cssVarPrefix.length) : varName;
|
|
151
|
+
|
|
152
|
+
// Check if the property has a corresponding CSS property mapping
|
|
153
|
+
const cssProperty = propertyMap[propName];
|
|
154
|
+
if (cssProperty) {
|
|
155
|
+
basePropRules += `${cssProperty}: var(${varName}); `;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Combine variable definitions and property assignments
|
|
160
|
+
const baseCssRules = baseVarRules + basePropRules;
|
|
161
|
+
|
|
162
|
+
// Add the base rule to the style manager
|
|
163
|
+
StyleManager.addRule(`.${componentId}`, baseCssRules, {
|
|
164
|
+
nonce: csp === null || csp === void 0 ? void 0 : csp.nonce
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Process responsive variables
|
|
168
|
+
if (!isEmpty(responsiveVars)) {
|
|
169
|
+
// Create media queries for each breakpoint
|
|
170
|
+
const breakpointVarRules = {
|
|
171
|
+
xs: '',
|
|
172
|
+
// xs rules will be merged into base styles
|
|
173
|
+
sm: '',
|
|
174
|
+
md: '',
|
|
175
|
+
lg: '',
|
|
176
|
+
xl: '',
|
|
177
|
+
xxl: ''
|
|
178
|
+
};
|
|
179
|
+
const breakpointPropRules = {
|
|
180
|
+
xs: '',
|
|
181
|
+
sm: '',
|
|
182
|
+
md: '',
|
|
183
|
+
lg: '',
|
|
184
|
+
xl: '',
|
|
185
|
+
xxl: ''
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Group styles by breakpoint
|
|
189
|
+
Object.entries(responsiveVars).forEach(([varName, responsiveValue]) => {
|
|
190
|
+
Object.entries(responsiveValue).forEach(([breakpoint, value]) => {
|
|
191
|
+
const bp = breakpoint;
|
|
192
|
+
if (value !== undefined && bp !== 'xs') {
|
|
193
|
+
// Skip xs as it's already in base styles
|
|
194
|
+
// Add the CSS variable definition for this breakpoint
|
|
195
|
+
breakpointVarRules[bp] += `${varName}: ${value}; `;
|
|
196
|
+
|
|
197
|
+
// Extract property name from variable name (remove prefix)
|
|
198
|
+
const propName = varName.startsWith(cssVarPrefix) ? varName.substring(cssVarPrefix.length) : varName;
|
|
199
|
+
|
|
200
|
+
// Check if the property has a corresponding CSS property mapping
|
|
201
|
+
const cssProperty = propertyMap[propName];
|
|
202
|
+
if (cssProperty) {
|
|
203
|
+
breakpointPropRules[bp] += `${cssProperty}: var(${varName}); `;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Combine variable definitions and property assignments for each breakpoint
|
|
210
|
+
const breakpointRules = {
|
|
211
|
+
xs: '',
|
|
212
|
+
sm: breakpointVarRules.sm + breakpointPropRules.sm,
|
|
213
|
+
md: breakpointVarRules.md + breakpointPropRules.md,
|
|
214
|
+
lg: breakpointVarRules.lg + breakpointPropRules.lg,
|
|
215
|
+
xl: breakpointVarRules.xl + breakpointPropRules.xl,
|
|
216
|
+
xxl: breakpointVarRules.xxl + breakpointPropRules.xxl
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Add media queries for each breakpoint with rules (skip xs)
|
|
220
|
+
Object.entries(breakpointRules).forEach(([breakpoint, rules]) => {
|
|
221
|
+
if (rules && breakpoint !== 'xs') {
|
|
222
|
+
const bp = breakpoint;
|
|
223
|
+
const minWidth = breakpointValues[bp];
|
|
224
|
+
StyleManager.addRule(`@media (min-width: ${minWidth}px)`, `.${componentId} { ${rules} }`, {
|
|
225
|
+
nonce: csp === null || csp === void 0 ? void 0 : csp.nonce
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return () => {
|
|
231
|
+
// Clean up rules when component unmounts
|
|
232
|
+
StyleManager.removeRule(`.${componentId}`);
|
|
233
|
+
|
|
234
|
+
// Clean up media query rules
|
|
235
|
+
Object.keys(breakpointValues).forEach(breakpoint => {
|
|
236
|
+
const bp = breakpoint;
|
|
237
|
+
const minWidth = breakpointValues[bp];
|
|
238
|
+
StyleManager.removeRule(`@media (min-width: ${minWidth}px)`);
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
}, [componentId, cssVars, shouldApplyStyles]);
|
|
242
|
+
|
|
243
|
+
// Combine class names
|
|
244
|
+
const combinedClassName = shouldApplyStyles ? `${className || ''} ${componentId}`.trim() : className;
|
|
245
|
+
return {
|
|
246
|
+
className: combinedClassName || undefined,
|
|
247
|
+
style,
|
|
248
|
+
id: componentId
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
export default useStyled;
|
|
@@ -19,7 +19,7 @@ export const getColorVar = color => {
|
|
|
19
19
|
|
|
20
20
|
// Check if color is a color with shade (e.g., 'red.50', 'gray.900')
|
|
21
21
|
const colorWithShadeRegex = /^(red|orange|yellow|green|cyan|blue|violet|gray)\.([1-9]00|50)$/;
|
|
22
|
-
const match = color.match(colorWithShadeRegex);
|
|
22
|
+
const match = color === null || color === void 0 ? void 0 : color.match(colorWithShadeRegex);
|
|
23
23
|
if (match) {
|
|
24
24
|
const [, colorName, shade] = match;
|
|
25
25
|
return `var(--rs-${colorName}-${shade})`;
|
|
@@ -3,7 +3,7 @@ import type { StyleProperties } from '../../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Processes and returns a value suitable for CSS (with a unit).
|
|
5
5
|
*/
|
|
6
|
-
export declare function getCssValue(value?: number | string | null, unit?: string): string;
|
|
6
|
+
export declare function getCssValue(value?: number | string | null, unit?: string): string | undefined;
|
|
7
7
|
/**
|
|
8
8
|
* Merge multiple style objects, filtering out undefined values
|
|
9
9
|
*/
|