rsuite 6.0.0-canary-2025062016 → 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/styles/index.css +2 -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/InputPicker/utils.d.ts +1 -1
- package/cjs/Nav/Nav.d.ts +2 -3
- 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/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/constants/index.js +2 -2
- 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/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 +3 -83
- package/dist/rsuite-no-reset.min.css +1 -1
- package/dist/rsuite.css +3 -83
- package/dist/rsuite.js +42 -9
- 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/InputPicker/utils.d.ts +1 -1
- package/esm/Nav/Nav.d.ts +2 -3
- 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/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/constants/index.js +2 -2
- 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/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
|
@@ -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})`;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StyleManager - A utility for managing CSS styles dynamically
|
|
3
|
+
*
|
|
4
|
+
* This manager creates and maintains a single style element in the document head
|
|
5
|
+
* and provides methods to add, update, and remove CSS rules.
|
|
6
|
+
* Supports CSP nonce for Content Security Policy compliance.
|
|
7
|
+
*/
|
|
8
|
+
export declare const StyleManager: {
|
|
9
|
+
styleElement: HTMLStyleElement | null;
|
|
10
|
+
styleMap: Map<string, string>;
|
|
11
|
+
nonce: string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the style element if it doesn't exist
|
|
14
|
+
* @param options - Optional configuration options
|
|
15
|
+
* @param options.nonce - CSP nonce to apply to the style element
|
|
16
|
+
* @returns The style element
|
|
17
|
+
*/
|
|
18
|
+
init(options?: {
|
|
19
|
+
nonce?: string;
|
|
20
|
+
}): HTMLStyleElement | null;
|
|
21
|
+
/**
|
|
22
|
+
* Set the CSP nonce for the style element
|
|
23
|
+
* @param nonce - CSP nonce value
|
|
24
|
+
*/
|
|
25
|
+
setNonce(nonce?: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Add a CSS rule to the style sheet
|
|
28
|
+
* @param selector - CSS selector
|
|
29
|
+
* @param cssText - CSS properties and values
|
|
30
|
+
* @param options - Optional configuration options
|
|
31
|
+
* @param options.nonce - CSP nonce to apply to the style element
|
|
32
|
+
*/
|
|
33
|
+
addRule(selector: string, cssText: string, options?: {
|
|
34
|
+
nonce?: string;
|
|
35
|
+
}): void;
|
|
36
|
+
/**
|
|
37
|
+
* Remove a CSS rule from the style sheet
|
|
38
|
+
* @param selector - CSS selector to remove
|
|
39
|
+
*/
|
|
40
|
+
removeRule(selector: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Update the style element with all current rules
|
|
43
|
+
*/
|
|
44
|
+
updateStyles(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Clear all rules from the style sheet
|
|
47
|
+
*/
|
|
48
|
+
clearRules(): void;
|
|
49
|
+
};
|
|
50
|
+
export default StyleManager;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* StyleManager - A utility for managing CSS styles dynamically
|
|
4
|
+
*
|
|
5
|
+
* This manager creates and maintains a single style element in the document head
|
|
6
|
+
* and provides methods to add, update, and remove CSS rules.
|
|
7
|
+
* Supports CSP nonce for Content Security Policy compliance.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Global style sheet manager
|
|
11
|
+
export const StyleManager = {
|
|
12
|
+
styleElement: null,
|
|
13
|
+
styleMap: new Map(),
|
|
14
|
+
nonce: undefined,
|
|
15
|
+
/**
|
|
16
|
+
* Initialize the style element if it doesn't exist
|
|
17
|
+
* @param options - Optional configuration options
|
|
18
|
+
* @param options.nonce - CSP nonce to apply to the style element
|
|
19
|
+
* @returns The style element
|
|
20
|
+
*/
|
|
21
|
+
init(options) {
|
|
22
|
+
if (!this.styleElement && typeof document !== 'undefined') {
|
|
23
|
+
this.styleElement = document.createElement('style');
|
|
24
|
+
this.styleElement.setAttribute('data-rs-style-manager', '');
|
|
25
|
+
|
|
26
|
+
// Apply CSP nonce if provided
|
|
27
|
+
const nonce = (options === null || options === void 0 ? void 0 : options.nonce) || this.nonce;
|
|
28
|
+
if (nonce) {
|
|
29
|
+
this.styleElement.setAttribute('nonce', nonce);
|
|
30
|
+
this.nonce = nonce; // Store for future use
|
|
31
|
+
}
|
|
32
|
+
document.head.appendChild(this.styleElement);
|
|
33
|
+
}
|
|
34
|
+
return this.styleElement;
|
|
35
|
+
},
|
|
36
|
+
/**
|
|
37
|
+
* Set the CSP nonce for the style element
|
|
38
|
+
* @param nonce - CSP nonce value
|
|
39
|
+
*/
|
|
40
|
+
setNonce(nonce) {
|
|
41
|
+
this.nonce = nonce;
|
|
42
|
+
|
|
43
|
+
// Apply to existing style element if it exists
|
|
44
|
+
if (this.styleElement && nonce) {
|
|
45
|
+
this.styleElement.setAttribute('nonce', nonce);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* Add a CSS rule to the style sheet
|
|
50
|
+
* @param selector - CSS selector
|
|
51
|
+
* @param cssText - CSS properties and values
|
|
52
|
+
* @param options - Optional configuration options
|
|
53
|
+
* @param options.nonce - CSP nonce to apply to the style element
|
|
54
|
+
*/
|
|
55
|
+
addRule(selector, cssText, options) {
|
|
56
|
+
this.init(options);
|
|
57
|
+
if (!this.styleMap.has(selector) || this.styleMap.get(selector) !== cssText) {
|
|
58
|
+
this.styleMap.set(selector, cssText);
|
|
59
|
+
this.updateStyles();
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
/**
|
|
63
|
+
* Remove a CSS rule from the style sheet
|
|
64
|
+
* @param selector - CSS selector to remove
|
|
65
|
+
*/
|
|
66
|
+
removeRule(selector) {
|
|
67
|
+
if (this.styleMap.has(selector)) {
|
|
68
|
+
this.styleMap.delete(selector);
|
|
69
|
+
this.updateStyles();
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Update the style element with all current rules
|
|
74
|
+
*/
|
|
75
|
+
updateStyles() {
|
|
76
|
+
if (!this.styleElement) return;
|
|
77
|
+
let cssText = '';
|
|
78
|
+
this.styleMap.forEach((rules, selector) => {
|
|
79
|
+
cssText += `${selector} { ${rules} }\n`;
|
|
80
|
+
});
|
|
81
|
+
this.styleElement.textContent = cssText;
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Clear all rules from the style sheet
|
|
85
|
+
*/
|
|
86
|
+
clearRules() {
|
|
87
|
+
this.styleMap.clear();
|
|
88
|
+
if (this.styleElement) {
|
|
89
|
+
this.styleElement.textContent = '';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
export default StyleManager;
|