@shohojdhara/atomix 0.3.4 → 0.3.5
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/atomix.css +9 -10
- package/dist/atomix.css.map +1 -0
- package/dist/atomix.min.css +15108 -11
- package/dist/atomix.min.css.map +1 -0
- package/dist/charts.d.ts +1929 -0
- package/dist/charts.js +6482 -0
- package/dist/charts.js.map +1 -0
- package/dist/core.d.ts +1289 -0
- package/dist/core.js +3357 -0
- package/dist/core.js.map +1 -0
- package/dist/forms.d.ts +1085 -0
- package/dist/forms.js +2450 -0
- package/dist/forms.js.map +1 -0
- package/dist/heavy.d.ts +636 -0
- package/dist/heavy.js +4550 -0
- package/dist/heavy.js.map +1 -0
- package/dist/index.d.ts +5161 -4990
- package/dist/index.esm.js +1457 -784
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1473 -790
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.d.ts +300 -0
- package/dist/layout.js +336 -0
- package/dist/layout.js.map +1 -0
- package/dist/theme.d.ts +1992 -0
- package/dist/theme.js +5348 -0
- package/dist/theme.js.map +1 -0
- package/package.json +66 -20
- package/scripts/atomix-cli.js +544 -16
- package/scripts/cli/__tests__/cli-commands.test.js +204 -0
- package/scripts/cli/__tests__/utils.test.js +201 -0
- package/scripts/cli/__tests__/vitest.config.js +26 -0
- package/scripts/cli/interactive-init.js +1 -1
- package/scripts/cli/token-manager.js +32 -7
- package/scripts/cli/utils.js +347 -0
- package/src/components/Accordion/Accordion.tsx +5 -54
- package/src/components/Accordion/index.ts +1 -1
- package/src/components/Avatar/Avatar.tsx +3 -3
- package/src/components/Badge/Badge.tsx +3 -3
- package/src/components/Breadcrumb/Breadcrumb.tsx +3 -3
- package/src/components/Card/ElevationCard.tsx +1 -1
- package/src/components/Chart/AnimatedChart.tsx +19 -17
- package/src/components/Chart/AreaChart.tsx +5 -1
- package/src/components/Chart/BarChart.tsx +1 -0
- package/src/components/Chart/BubbleChart.tsx +6 -5
- package/src/components/Chart/ChartToolbar.tsx +1 -0
- package/src/components/Chart/FunnelChart.tsx +1 -1
- package/src/components/Chart/RadarChart.tsx +19 -12
- package/src/components/Chart/ScatterChart.tsx +3 -3
- package/src/components/Chart/TreemapChart.tsx +2 -1
- package/src/components/Chart/WaterfallChart.tsx +0 -1
- package/src/components/Chart/types.ts +12 -2
- package/src/components/Chart/utils.ts +4 -3
- package/src/components/DataTable/DataTable.tsx +3 -3
- package/src/components/Dropdown/Dropdown.tsx +12 -9
- package/src/components/Footer/FooterSection.tsx +3 -3
- package/src/components/Form/Checkbox.tsx +3 -3
- package/src/components/Form/Input.tsx +4 -2
- package/src/components/Form/Radio.tsx +3 -3
- package/src/components/Form/Select.tsx +3 -3
- package/src/components/Form/Textarea.tsx +4 -2
- package/src/components/List/List.stories.tsx +3 -3
- package/src/components/List/List.tsx +3 -3
- package/src/components/List/ListGroup.tsx +3 -1
- package/src/components/Modal/Modal.tsx +3 -3
- package/src/components/Navigation/Menu/MegaMenu.tsx +9 -3
- package/src/components/Navigation/Menu/Menu.tsx +9 -3
- package/src/components/Pagination/Pagination.tsx +6 -5
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +2 -2
- package/src/components/Popover/Popover.tsx +4 -4
- package/src/components/Progress/Progress.tsx +6 -2
- package/src/components/Rating/Rating.tsx +5 -2
- package/src/components/Slider/Slider.tsx +10 -9
- package/src/components/Spinner/Spinner.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +3 -3
- package/src/components/Tooltip/Tooltip.tsx +3 -3
- package/src/components/index.ts +5 -2
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +2 -2
- package/src/lib/composables/useChartPerformance.ts +102 -78
- package/src/lib/composables/useChartScale.ts +10 -0
- package/src/lib/composables/useHero.ts +9 -2
- package/src/lib/composables/useHeroBackgroundSlider.ts +5 -3
- package/src/lib/composables/useSideMenu.ts +1 -0
- package/src/lib/composables/useVideoPlayer.ts +3 -2
- package/src/lib/config/loader.ts +55 -13
- package/src/lib/hooks/index.ts +0 -1
- package/src/lib/hooks/useComponentCustomization.ts +10 -14
- package/src/lib/hooks/usePerformanceMonitor.ts +149 -0
- package/src/lib/patterns/index.ts +2 -2
- package/src/lib/patterns/slots.tsx +2 -2
- package/src/lib/theme/composeTheme.ts +1 -1
- package/src/lib/theme/core/ThemeEngine.ts +8 -0
- package/src/lib/theme/core/ThemeValidator.ts +5 -2
- package/src/lib/theme/devtools/Inspector.tsx +1 -1
- package/src/lib/theme/devtools/LiveEditor.tsx +11 -5
- package/src/lib/theme/generateCSSVariables.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +2 -1
- package/src/lib/theme/runtime/ThemeApplicator.ts +28 -11
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +3 -3
- package/src/lib/theme/runtime/ThemeManager.ts +4 -0
- package/src/lib/theme-tools.ts +1 -1
- package/src/lib/types/components.ts +183 -34
- package/src/lib/types/partProps.ts +0 -16
- package/src/lib/utils/fontPreloader.ts +148 -0
- package/src/lib/utils/index.ts +11 -0
- package/src/lib/utils/memoryMonitor.ts +189 -0
- package/src/styles/01-settings/_settings.fonts.scss +2 -5
- package/src/styles/03-generic/_generated-root.css +22 -1
- package/src/styles/06-components/_components.navbar.scss +0 -6
- package/src/themes/themes.config.js +37 -4
- package/scripts/build-themes.js +0 -208
- package/src/components/AtomixGlass/atomixGLass.old.tsx +0 -1263
package/dist/core.js
ADDED
|
@@ -0,0 +1,3357 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
import React, { useState, useRef, useEffect, memo, forwardRef, useId, useMemo, useCallback } from "react";
|
|
4
|
+
|
|
5
|
+
import * as PhosphorIcons from "@phosphor-icons/react";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Default theme colors for components
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Button-specific constants
|
|
12
|
+
*/ const BUTTON = {
|
|
13
|
+
BASE_CLASS: "c-btn",
|
|
14
|
+
ICON_CLASS: "c-btn__icon",
|
|
15
|
+
LABEL_CLASS: "c-btn__label",
|
|
16
|
+
SPINNER_CLASS: "c-btn__spinner",
|
|
17
|
+
VARIANT_PREFIX: "c-btn--",
|
|
18
|
+
CLASSES: {
|
|
19
|
+
BASE: "c-btn",
|
|
20
|
+
LOADING: "c-btn--loading",
|
|
21
|
+
FULL_WIDTH: "c-btn--full-width",
|
|
22
|
+
BLOCK: "c-btn--block",
|
|
23
|
+
ACTIVE: "c-btn--active",
|
|
24
|
+
SELECTED: "c-btn--selected"
|
|
25
|
+
}
|
|
26
|
+
}, ACCORDION = {
|
|
27
|
+
SELECTORS: {
|
|
28
|
+
ACCORDION: ".c-accordion",
|
|
29
|
+
HEADER: ".c-accordion__header",
|
|
30
|
+
PANEL: ".c-accordion__panel",
|
|
31
|
+
BODY: ".c-accordion__body"
|
|
32
|
+
},
|
|
33
|
+
CLASSES: {
|
|
34
|
+
IS_OPEN: "is-open",
|
|
35
|
+
IS_ANIMATING: "is-animating",
|
|
36
|
+
IS_DISABLED: "is-disabled"
|
|
37
|
+
},
|
|
38
|
+
ATTRIBUTES: {
|
|
39
|
+
ARIA_EXPANDED: "aria-expanded",
|
|
40
|
+
ARIA_CONTROLS: "aria-controls",
|
|
41
|
+
ARIA_HIDDEN: "aria-hidden",
|
|
42
|
+
ROLE: "role"
|
|
43
|
+
},
|
|
44
|
+
CSS_VARS: {
|
|
45
|
+
PANEL_HEIGHT: "--panel-height"
|
|
46
|
+
}
|
|
47
|
+
}, LIST = {
|
|
48
|
+
BASE_CLASS: "c-list",
|
|
49
|
+
ITEM_CLASS: "c-list__item",
|
|
50
|
+
VARIANT_PREFIX: "c-list--",
|
|
51
|
+
SIZE_PREFIX: "c-list--",
|
|
52
|
+
CLASSES: {
|
|
53
|
+
ORDERED: "c-list--ordered",
|
|
54
|
+
INLINE: "c-list--inline"
|
|
55
|
+
}
|
|
56
|
+
}, LIST_GROUP = {
|
|
57
|
+
BASE_CLASS: "c-list-group",
|
|
58
|
+
ITEM_CLASS: "c-list-group__item",
|
|
59
|
+
VARIANT_PREFIX: "c-list-group--",
|
|
60
|
+
SIZE_PREFIX: "c-list-group--"
|
|
61
|
+
}, BREADCRUMB = {
|
|
62
|
+
SELECTORS: {
|
|
63
|
+
BREADCRUMB: ".c-breadcrumb",
|
|
64
|
+
ITEM: ".c-breadcrumb__item",
|
|
65
|
+
LINK: ".c-breadcrumb__link"
|
|
66
|
+
},
|
|
67
|
+
CLASSES: {
|
|
68
|
+
BASE: "c-breadcrumb",
|
|
69
|
+
ITEM: "c-breadcrumb__item",
|
|
70
|
+
LINK: "c-breadcrumb__link",
|
|
71
|
+
ACTIVE: "is-active"
|
|
72
|
+
},
|
|
73
|
+
DEFAULTS: {
|
|
74
|
+
DIVIDER: "›"
|
|
75
|
+
}
|
|
76
|
+
}, CARD = {
|
|
77
|
+
SELECTORS: {
|
|
78
|
+
CARD: ".c-card",
|
|
79
|
+
HEADER: ".c-card__header",
|
|
80
|
+
BODY: ".c-card__body",
|
|
81
|
+
IMAGE: ".c-card__image",
|
|
82
|
+
TITLE: ".c-card__title",
|
|
83
|
+
TEXT: ".c-card__text",
|
|
84
|
+
ACTIONS: ".c-card__actions",
|
|
85
|
+
ICON: ".c-card__icon",
|
|
86
|
+
FOOTER: ".c-card__footer"
|
|
87
|
+
},
|
|
88
|
+
CLASSES: {
|
|
89
|
+
BASE: "c-card",
|
|
90
|
+
// Size modifiers
|
|
91
|
+
SM: "c-card--sm",
|
|
92
|
+
MD: "c-card--md",
|
|
93
|
+
LG: "c-card--lg",
|
|
94
|
+
// Layout modifiers
|
|
95
|
+
ROW: "c-card--row",
|
|
96
|
+
FLAT: "c-card--flat",
|
|
97
|
+
// Appearance modifiers
|
|
98
|
+
FILLED: "c-card--filled",
|
|
99
|
+
OUTLINED: "c-card--outlined",
|
|
100
|
+
GHOST: "c-card--ghost",
|
|
101
|
+
ELEVATED: "c-card--elevated",
|
|
102
|
+
// Elevation modifiers
|
|
103
|
+
ELEVATION_NONE: "c-card--elevation-none",
|
|
104
|
+
ELEVATION_SM: "c-card--elevation-sm",
|
|
105
|
+
ELEVATION_MD: "c-card--elevation-md",
|
|
106
|
+
ELEVATION_LG: "c-card--elevation-lg",
|
|
107
|
+
ELEVATION_XL: "c-card--elevation-xl",
|
|
108
|
+
// State modifiers
|
|
109
|
+
ACTIVE: "is-active",
|
|
110
|
+
DISABLED: "c-card--disabled",
|
|
111
|
+
LOADING: "c-card--loading",
|
|
112
|
+
SELECTED: "c-card--selected",
|
|
113
|
+
INTERACTIVE: "c-card--interactive",
|
|
114
|
+
// Other modifiers
|
|
115
|
+
FLIPPED: "is-flipped",
|
|
116
|
+
FOCUSED: "is-focused",
|
|
117
|
+
CLICKABLE: "is-clickable",
|
|
118
|
+
GLASS: "c-card--glass"
|
|
119
|
+
},
|
|
120
|
+
DEFAULTS: {
|
|
121
|
+
HOVER: !0,
|
|
122
|
+
SIZE: "md",
|
|
123
|
+
VARIANT: "primary",
|
|
124
|
+
APPEARANCE: "filled",
|
|
125
|
+
ELEVATION: "none"
|
|
126
|
+
}
|
|
127
|
+
}, BLOCK = {
|
|
128
|
+
BASE_CLASS: "o-block",
|
|
129
|
+
SPACING_PREFIX: "o-block--",
|
|
130
|
+
CLASSES: {
|
|
131
|
+
SPACING_XS: "o-block--xs",
|
|
132
|
+
SPACING_SM: "o-block--sm",
|
|
133
|
+
SPACING_MD: "o-block--md",
|
|
134
|
+
SPACING_LG: "o-block--lg",
|
|
135
|
+
SPACING_XL: "o-block--xl",
|
|
136
|
+
SPACING_NONE: "o-block--no-spacing",
|
|
137
|
+
FULL_WIDTH: "o-block--full-width",
|
|
138
|
+
BG_PRIMARY: "o-block--primary",
|
|
139
|
+
BG_SECONDARY: "o-block--secondary",
|
|
140
|
+
BG_TERTIARY: "o-block--tertiary",
|
|
141
|
+
BG_INVERT: "o-block--invert",
|
|
142
|
+
BG_BRAND: "o-block--brand",
|
|
143
|
+
BG_ERROR: "o-block--error",
|
|
144
|
+
BG_SUCCESS: "o-block--success",
|
|
145
|
+
BG_WARNING: "o-block--warning",
|
|
146
|
+
BG_INFO: "o-block--info",
|
|
147
|
+
BG_LIGHT: "o-block--light",
|
|
148
|
+
BG_DARK: "o-block--dark"
|
|
149
|
+
},
|
|
150
|
+
SPACING: {
|
|
151
|
+
SIZES: [ "xs", "sm", "md", "lg", "xl", "none" ],
|
|
152
|
+
DEFAULT: "md"
|
|
153
|
+
}
|
|
154
|
+
}, ATOMIX_GLASS = {
|
|
155
|
+
BASE_CLASS: "c-atomix-glass",
|
|
156
|
+
CONTAINER_CLASS: "c-atomix-glass__container",
|
|
157
|
+
INNER_CLASS: "c-atomix-glass__inner",
|
|
158
|
+
FILTER_CLASS: "c-atomix-glass__filter",
|
|
159
|
+
FILTER_OVERLAY_CLASS: "c-atomix-glass__filter-overlay",
|
|
160
|
+
FILTER_SHADOW_CLASS: "c-atomix-glass__filter-shadow",
|
|
161
|
+
CONTENT_CLASS: "c-atomix-glass__content",
|
|
162
|
+
BORDER_1_CLASS: "c-atomix-glass__border-1",
|
|
163
|
+
BORDER_2_CLASS: "c-atomix-glass__border-2",
|
|
164
|
+
HOVER_1_CLASS: "c-atomix-glass__hover-1",
|
|
165
|
+
HOVER_2_CLASS: "c-atomix-glass__hover-2",
|
|
166
|
+
HOVER_3_CLASS: "c-atomix-glass__hover-3",
|
|
167
|
+
BASE_LAYER_CLASS: "c-atomix-glass__base",
|
|
168
|
+
OVERLAY_LAYER_CLASS: "c-atomix-glass__overlay",
|
|
169
|
+
OVERLAY_HIGHLIGHT_CLASS: "c-atomix-glass__overlay-highlight",
|
|
170
|
+
BACKGROUND_LAYER_CLASS: "c-atomix-glass__background-layer",
|
|
171
|
+
BACKGROUND_LAYER_DARK_CLASS: "c-atomix-glass__background-layer--dark",
|
|
172
|
+
BACKGROUND_LAYER_BLACK_CLASS: "c-atomix-glass__background-layer--black",
|
|
173
|
+
BACKGROUND_LAYER_OVER_LIGHT_CLASS: "c-atomix-glass__background-layer--over-light",
|
|
174
|
+
BACKGROUND_LAYER_HIDDEN_CLASS: "c-atomix-glass__background-layer--hidden",
|
|
175
|
+
VARIANT_PREFIX: "c-atomix-glass--",
|
|
176
|
+
MODE_PREFIX: "c-atomix-glass--",
|
|
177
|
+
CLASSES: {
|
|
178
|
+
BASE: "c-atomix-glass",
|
|
179
|
+
CONTAINER: "c-atomix-glass__container",
|
|
180
|
+
INNER: "c-atomix-glass__inner",
|
|
181
|
+
FILTER: "c-atomix-glass__filter",
|
|
182
|
+
CONTENT: "c-atomix-glass__content",
|
|
183
|
+
ACTIVE: "active",
|
|
184
|
+
OVER_LIGHT: "c-atomix-glass__container--over-light",
|
|
185
|
+
// Mode variants
|
|
186
|
+
STANDARD: "c-atomix-glass--standard",
|
|
187
|
+
POLAR: "c-atomix-glass--polar",
|
|
188
|
+
PROMINENT: "c-atomix-glass--prominent",
|
|
189
|
+
SHADER: "c-atomix-glass--shader"
|
|
190
|
+
},
|
|
191
|
+
DEFAULTS: {
|
|
192
|
+
DISPLACEMENT_SCALE: 20,
|
|
193
|
+
BLUR_AMOUNT: 1,
|
|
194
|
+
SATURATION: 140,
|
|
195
|
+
ABERRATION_INTENSITY: 2.5,
|
|
196
|
+
ELASTICITY: .05,
|
|
197
|
+
CORNER_RADIUS: 16,
|
|
198
|
+
// Default border-radius matching design system
|
|
199
|
+
PADDING: "0 0",
|
|
200
|
+
MODE: "standard",
|
|
201
|
+
OVER_LIGHT: !1,
|
|
202
|
+
ENABLE_OVER_LIGHT_LAYERS: !0
|
|
203
|
+
},
|
|
204
|
+
CONSTANTS: {
|
|
205
|
+
ACTIVATION_ZONE: 200,
|
|
206
|
+
MIN_BLUR: .1,
|
|
207
|
+
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
208
|
+
EDGE_FADE_PIXELS: 2,
|
|
209
|
+
DEFAULT_CORNER_RADIUS: 16,
|
|
210
|
+
// Fallback value matching design system
|
|
211
|
+
MAX_SIZE: 4096,
|
|
212
|
+
// Maximum width/height for glass size
|
|
213
|
+
// Gradient calculation constants
|
|
214
|
+
GRADIENT: {
|
|
215
|
+
BASE_ANGLE: 135,
|
|
216
|
+
// Base angle for border gradients (degrees)
|
|
217
|
+
ANGLE_MULTIPLIER: 1.2,
|
|
218
|
+
// Multiplier for mouse influence on angle
|
|
219
|
+
BORDER_STOP_1: {
|
|
220
|
+
MIN: 10,
|
|
221
|
+
// Minimum percentage for border stop 1
|
|
222
|
+
BASE: 33,
|
|
223
|
+
// Base percentage for border stop 1
|
|
224
|
+
MULTIPLIER: .3
|
|
225
|
+
},
|
|
226
|
+
BORDER_STOP_2: {
|
|
227
|
+
MAX: 90,
|
|
228
|
+
// Maximum percentage for border stop 2
|
|
229
|
+
BASE: 66,
|
|
230
|
+
// Base percentage for border stop 2
|
|
231
|
+
MULTIPLIER: .4
|
|
232
|
+
},
|
|
233
|
+
BORDER_OPACITY: {
|
|
234
|
+
BASE_1: .12,
|
|
235
|
+
// Base opacity for border gradient 1
|
|
236
|
+
BASE_2: .4,
|
|
237
|
+
// Base opacity for border gradient 2
|
|
238
|
+
BASE_3: .32,
|
|
239
|
+
// Base opacity for border gradient 3
|
|
240
|
+
BASE_4: .6,
|
|
241
|
+
// Base opacity for border gradient 4
|
|
242
|
+
MULTIPLIER_LOW: .008,
|
|
243
|
+
// Low multiplier for mouse influence on opacity
|
|
244
|
+
MULTIPLIER_HIGH: .012
|
|
245
|
+
},
|
|
246
|
+
CENTER_POSITION: 50,
|
|
247
|
+
// Center position percentage (50%)
|
|
248
|
+
HOVER_POSITION: {
|
|
249
|
+
DIVISOR_1: 2,
|
|
250
|
+
// Divisor for hover 1 position calculation
|
|
251
|
+
DIVISOR_2: 1.5,
|
|
252
|
+
// Divisor for hover 2 position calculation
|
|
253
|
+
MULTIPLIER_3: 1
|
|
254
|
+
},
|
|
255
|
+
BASE_LAYER_MULTIPLIER: .5
|
|
256
|
+
},
|
|
257
|
+
// Gradient opacity values for hover effects
|
|
258
|
+
GRADIENT_OPACITY: {
|
|
259
|
+
HOVER_1: {
|
|
260
|
+
BLACK_START: .3,
|
|
261
|
+
// Start opacity for black hover 1
|
|
262
|
+
BLACK_MID: .1,
|
|
263
|
+
// Mid opacity for black hover 1
|
|
264
|
+
BLACK_STOP: 30,
|
|
265
|
+
// Stop percentage for black hover 1
|
|
266
|
+
BLACK_END: 60,
|
|
267
|
+
// End percentage for black hover 1
|
|
268
|
+
WHITE_START: .5,
|
|
269
|
+
// Start opacity for white hover 1
|
|
270
|
+
WHITE_STOP: 50
|
|
271
|
+
},
|
|
272
|
+
HOVER_2: {
|
|
273
|
+
BLACK_START: .4,
|
|
274
|
+
// Start opacity for black hover 2
|
|
275
|
+
BLACK_MID: .15,
|
|
276
|
+
// Mid opacity for black hover 2
|
|
277
|
+
BLACK_STOP: 40,
|
|
278
|
+
// Stop percentage for black hover 2
|
|
279
|
+
BLACK_END: 80,
|
|
280
|
+
// End percentage for black hover 2
|
|
281
|
+
WHITE_START: 1,
|
|
282
|
+
// Start opacity for white hover 2
|
|
283
|
+
WHITE_STOP: 80
|
|
284
|
+
},
|
|
285
|
+
HOVER_3: {
|
|
286
|
+
BLACK_START: .5,
|
|
287
|
+
// Start opacity for black hover 3
|
|
288
|
+
BLACK_MID: .2,
|
|
289
|
+
// Mid opacity for black hover 3
|
|
290
|
+
BLACK_STOP: 50,
|
|
291
|
+
// Stop percentage for black hover 3
|
|
292
|
+
BLACK_END: 100,
|
|
293
|
+
// End percentage for black hover 3
|
|
294
|
+
WHITE_START: 1,
|
|
295
|
+
// Start opacity for white hover 3
|
|
296
|
+
WHITE_STOP: 100
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
// Base and overlay gradient constants
|
|
300
|
+
BASE_GRADIENT: {
|
|
301
|
+
ANGLE: 135,
|
|
302
|
+
// Gradient angle in degrees
|
|
303
|
+
BLACK_START_BASE: .15,
|
|
304
|
+
// Base start opacity for black
|
|
305
|
+
BLACK_START_MULTIPLIER: .003,
|
|
306
|
+
// Multiplier for mouse X influence on start
|
|
307
|
+
BLACK_MID_BASE: .1,
|
|
308
|
+
// Base mid opacity for black
|
|
309
|
+
BLACK_MID_MULTIPLIER: .002,
|
|
310
|
+
// Multiplier for mouse Y influence on mid
|
|
311
|
+
BLACK_MID_STOP: 50,
|
|
312
|
+
// Mid stop percentage
|
|
313
|
+
BLACK_END_BASE: .18,
|
|
314
|
+
// Base end opacity for black
|
|
315
|
+
BLACK_END_MULTIPLIER: .004,
|
|
316
|
+
// Multiplier for mouse X influence on end
|
|
317
|
+
WHITE_OPACITY: .1
|
|
318
|
+
},
|
|
319
|
+
OVERLAY_GRADIENT: {
|
|
320
|
+
BLACK_START_BASE: .12,
|
|
321
|
+
// Base start opacity for black overlay
|
|
322
|
+
BLACK_START_MULTIPLIER: .003,
|
|
323
|
+
// Multiplier for mouse X influence on start
|
|
324
|
+
BLACK_MID: .06,
|
|
325
|
+
// Mid opacity for black overlay
|
|
326
|
+
BLACK_MID_STOP: 40,
|
|
327
|
+
// Mid stop percentage
|
|
328
|
+
BLACK_END_BASE: .15,
|
|
329
|
+
// Base end opacity for black overlay
|
|
330
|
+
BLACK_END_MULTIPLIER: .003,
|
|
331
|
+
// Multiplier for mouse Y influence on end
|
|
332
|
+
WHITE_OPACITY: .05
|
|
333
|
+
},
|
|
334
|
+
// Overlay highlight constants
|
|
335
|
+
OVERLAY_HIGHLIGHT: {
|
|
336
|
+
POSITION_X: 20,
|
|
337
|
+
// X position percentage
|
|
338
|
+
POSITION_Y: 20,
|
|
339
|
+
// Y position percentage
|
|
340
|
+
WHITE_OPACITY: .4,
|
|
341
|
+
// White opacity in gradient
|
|
342
|
+
STOP: 60,
|
|
343
|
+
// Stop percentage
|
|
344
|
+
OPACITY_MULTIPLIER: .7
|
|
345
|
+
},
|
|
346
|
+
// Displacement and aberration multipliers
|
|
347
|
+
MULTIPLIERS: {
|
|
348
|
+
SHADER_DISPLACEMENT: .8,
|
|
349
|
+
// Displacement scale multiplier for shader mode
|
|
350
|
+
OVER_LIGHT_DISPLACEMENT: .6,
|
|
351
|
+
// Displacement scale multiplier for over-light mode
|
|
352
|
+
SHADER_ABERRATION: .7
|
|
353
|
+
},
|
|
354
|
+
// Saturation constants
|
|
355
|
+
SATURATION: {
|
|
356
|
+
HIGH_CONTRAST: 200
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
|
|
360
|
+
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
361
|
+
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
362
|
+
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
363
|
+
}, calculateElementCenter = rect => rect ? {
|
|
364
|
+
x: rect.left + rect.width / 2,
|
|
365
|
+
y: rect.top + rect.height / 2
|
|
366
|
+
} : {
|
|
367
|
+
x: 0,
|
|
368
|
+
y: 0
|
|
369
|
+
}, calculateMouseInfluence = mouseOffset => {
|
|
370
|
+
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
371
|
+
// More responsive calculation for overlight effects
|
|
372
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$1.MOUSE_INFLUENCE_DIVISOR;
|
|
373
|
+
return Math.min(1.5, influence);
|
|
374
|
+
// Cap influence for better control
|
|
375
|
+
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$1.MIN_BLUR : Math.max(CONSTANTS$1.MIN_BLUR, Math.min(50, value)), validateGlassSize = size => size && "number" == typeof size.width && "number" == typeof size.height && size.width > 0 && size.height > 0 && size.width <= CONSTANTS$1.MAX_SIZE && size.height <= CONSTANTS$1.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
376
|
+
if ("number" == typeof value) return Math.max(0, value);
|
|
377
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
|
|
378
|
+
const trimmedValue = value.trim();
|
|
379
|
+
// Handle px values
|
|
380
|
+
if (trimmedValue.endsWith("px")) {
|
|
381
|
+
const parsed = parseFloat(trimmedValue);
|
|
382
|
+
return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
383
|
+
}
|
|
384
|
+
// Handle rem values (assume 16px = 1rem)
|
|
385
|
+
if (trimmedValue.endsWith("rem")) {
|
|
386
|
+
const parsed = parseFloat(trimmedValue);
|
|
387
|
+
return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
388
|
+
}
|
|
389
|
+
// Handle em values (assume 16px = 1em for simplicity)
|
|
390
|
+
if (trimmedValue.endsWith("em")) {
|
|
391
|
+
const parsed = parseFloat(trimmedValue);
|
|
392
|
+
return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
393
|
+
}
|
|
394
|
+
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
395
|
+
if (trimmedValue.endsWith("%")) {
|
|
396
|
+
const parsed = parseFloat(trimmedValue);
|
|
397
|
+
return isNaN(parsed) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
398
|
+
}
|
|
399
|
+
// Handle unitless numbers
|
|
400
|
+
const numValue = parseFloat(trimmedValue);
|
|
401
|
+
return isNaN(numValue) ? CONSTANTS$1.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
402
|
+
}, extractBorderRadiusFromElement = element => {
|
|
403
|
+
if (!element || !element.props) return null;
|
|
404
|
+
// Check inline styles first (highest priority)
|
|
405
|
+
if (element.props.style) {
|
|
406
|
+
const radiusFromStyle = (style => {
|
|
407
|
+
if (!style) return null;
|
|
408
|
+
// Check various border-radius properties
|
|
409
|
+
const borderRadius = style.borderRadius || style.borderTopLeftRadius || style.borderTopRightRadius || style.borderBottomLeftRadius || style.borderBottomRightRadius;
|
|
410
|
+
return void 0 !== borderRadius ? parseBorderRadiusValue(borderRadius) : null;
|
|
411
|
+
})(element.props.style);
|
|
412
|
+
if (null !== radiusFromStyle && radiusFromStyle > 0) return radiusFromStyle;
|
|
413
|
+
}
|
|
414
|
+
// If element has children, recursively check them
|
|
415
|
+
if (element.props.children) {
|
|
416
|
+
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
417
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$1.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}, extractBorderRadiusFromChildren = children => {
|
|
421
|
+
if (!children) return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
|
|
422
|
+
try {
|
|
423
|
+
const childArray = React.Children.toArray(children);
|
|
424
|
+
for (let i = 0; i < childArray.length; i++) {
|
|
425
|
+
const child = childArray[i];
|
|
426
|
+
if ( React.isValidElement(child)) {
|
|
427
|
+
const radius = extractBorderRadiusFromElement(child);
|
|
428
|
+
if (null !== radius) return radius;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
} catch (error) {
|
|
432
|
+
// Silently handle errors
|
|
433
|
+
}
|
|
434
|
+
return CONSTANTS$1.DEFAULT_CORNER_RADIUS;
|
|
435
|
+
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
436
|
+
switch (mode) {
|
|
437
|
+
case "standard":
|
|
438
|
+
return displacementMap;
|
|
439
|
+
|
|
440
|
+
case "polar":
|
|
441
|
+
return polarDisplacementMap;
|
|
442
|
+
|
|
443
|
+
case "prominent":
|
|
444
|
+
return prominentDisplacementMap;
|
|
445
|
+
|
|
446
|
+
case "shader":
|
|
447
|
+
return shaderMapUrl || displacementMap;
|
|
448
|
+
|
|
449
|
+
default:
|
|
450
|
+
return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
|
|
451
|
+
}
|
|
452
|
+
}, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
453
|
+
style: {
|
|
454
|
+
position: "absolute",
|
|
455
|
+
width: "100%",
|
|
456
|
+
height: "100%",
|
|
457
|
+
inset: 0
|
|
458
|
+
},
|
|
459
|
+
"aria-hidden": "true",
|
|
460
|
+
suppressHydrationWarning: !0,
|
|
461
|
+
children: jsxs("defs", {
|
|
462
|
+
children: [ jsxs("radialGradient", {
|
|
463
|
+
id: `${id}-edge-mask`,
|
|
464
|
+
cx: "50%",
|
|
465
|
+
cy: "50%",
|
|
466
|
+
r: "50%",
|
|
467
|
+
children: [ jsx("stop", {
|
|
468
|
+
offset: "0%",
|
|
469
|
+
stopColor: "black",
|
|
470
|
+
stopOpacity: "0"
|
|
471
|
+
}), jsx("stop", {
|
|
472
|
+
offset: `${Math.max(30, 80 - 2 * aberrationIntensity)}%`,
|
|
473
|
+
stopColor: "black",
|
|
474
|
+
stopOpacity: "0"
|
|
475
|
+
}), jsx("stop", {
|
|
476
|
+
offset: "100%",
|
|
477
|
+
stopColor: "white",
|
|
478
|
+
stopOpacity: "1"
|
|
479
|
+
}) ]
|
|
480
|
+
}), jsxs("filter", {
|
|
481
|
+
id: id,
|
|
482
|
+
x: "-35%",
|
|
483
|
+
y: "-35%",
|
|
484
|
+
width: "170%",
|
|
485
|
+
height: "170%",
|
|
486
|
+
colorInterpolationFilters: "sRGB",
|
|
487
|
+
children: [ jsx("feImage", {
|
|
488
|
+
id: "feimage",
|
|
489
|
+
x: "0",
|
|
490
|
+
y: "0",
|
|
491
|
+
width: "100%",
|
|
492
|
+
height: "100%",
|
|
493
|
+
result: "DISPLACEMENT_MAP",
|
|
494
|
+
href: getDisplacementMap(mode, "data:image/jpeg;base64,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cUAUAkEkziomgGgkoxZGgxZFQFQlYnQHRdPfj/10KCSCKESCNiVkViPSLpD0h6I0Q0I0A2IoBWBIJIBKBIJoJIJ2R2J0JWBUJ0JUB0XTv479dFZDYiglYigkhEgjZFQjRFQjRFQjQigFYigHYigmgEgmglYlYnQlQlYlQHQlQnQ9P/kf1yVkNiNCNkNiVENiNiViNEViNkVCVgKCViViViSCViSCVgdCViVCViVCdgVCVCdD1D+U/XBWQ2I0I2Q2JUQ2I0JWQ0I2JUQ2JUI2JUI2J0JWJWJWA2R0BWJ0I2JUJ2BUJUJ0P//EABkQAQEBAQEBAAAAAAAAAAAAAAECABEDEP/aAAgBAQABAgB1atWrVq1atWrVq1atWrVq1atWrVq1atWrVq+OrVq1atWrVq1atWrVq1atWrVq1atWrVq1atXxVppppppdWrVq1atWrVq1NNNNNNNNNNNPVWmmmmms6tWrVq1atWpppppppppppppp6q0000uc51atWrVq1ammmmmmmmmmmmmt1Vpppc5znVq1atWrVqaaaaaaaaaaaaaeqtNLnOc51atWrVq1ammmmmmmmmmmmmnqrS5znOc6tWrVq16222mmmmmmlVppp6tKuc5znOrVq1a9TbbbbTTTTTSq000qtLnOc5zq1atWrW0222200000qqqtKqrnOc5zq1atTbbbbbbbbTTTSqqqqqq5znOc6tTTTbbbbbbbbTTTSqqqqrlVznOctNNNtttttttttNNNNKqqqrqznKqrTTTTbbbbbbbbbTTTSqqqqrqznOc5aaaabbbbbbbbbaaaaVVVVVdWc5znVq1NNttttttttttNNKqqqqudWc5znVq16tbbbbbbbbbbTTSqqqq5XVnOc6tWrVrb1tttttttttNNKqqqqrWrK5VWmmm2230bbbbbbaaaXOc5zlVa1KuVVppptttt9G22222mmlzlVznK6tWVVWmmmm2222222222mlznOc5znLWppVVWmmm22222229bTWrOc5znOcq1qaaVpWmm222222229erVqznOc5znKtatStK0rTbTTbbbberXr1as5znOc5aVpppppWlabaabbbb1ta9WrVnOc5znU0rTTTTTTTTTbTTbbbTWvVq1as5znOdTTStNNNNNNNNNtNNtttN6tWvVq1ZznOrU00rTTTTTTTTTTTTTbTWvVq1atWrOc6tTTTStNNNNNNNNNNtNNtNa9WrVq1Z1Z1NNNNNK1q1NNNNNNNNNNNtNatWrVq1atWrU00000rWrVq1atWrVq1alaaa1atWrVq1NNNammmmla1atWrVq1aterVq16tWrVnVqa1NK1qaaaVX/xAAWEAADAAAAAAAAAAAAAAAAAAAhgJD/2gAIAQEAAz8AaExf/8QAGhEBAQEBAQEBAAAAAAAAAAAAAQISEQADEP/aAAgBAgEBAgDx48ePHjx48ePHjx48ePHjx48ePHjx48ePHj86IiIiIiInjx48ePHjx48IiIiIj0oooooooooRERER73ve60UUUUUUVrWiiiiiihERERER73ve97ooooorRWiiiiihKERERER73ve973RRRRWtFFFFFFCIiIiIiPe973ve60UUVrRRRRRRQiIlCIiI973ve973pRRWiiiiiiiiiiiiiiihEe973ve973RRWtFFFFFFFFFFFFFFFFFFa13ve973WitaKKKKKKKKKKKKKKKKKK1rWtd1rutFa1oooooooooooosssooorWta1rWta1rRRRRRRRRRRZZZZZZZZZWta1rWta1rRRRRRRRRZZZZZZZZZZZZe9a1rWta1rWitaKLLLLLLLLLLLLLLLLL3rWta1rWtFbLLLLLLLLLLLLLLLLLLLL3vWta1rWita1ssssssss+hZZZZZZZZe961rWta0Vre97LLLLLLLLLLLPoWWWWWXrWta1oorWta3ssss+hZZZZ9Cyyyyyyyyiita1orWta1ve9llllllllllllllllFFa0VorWta1ve9llllllllllllllllllFFFaK1rWta1rWiyyyyyyyyyyyyiiiiiiitFFa1rWta1oosoosssssoooosoooorRRRWta1rWta0UUUUUWUUUUUUUUUUUVoooorWta1rWtaKKKKKKmiiiiiiiiiiiiiiitd73ve61oSiiipoqaKKKKKKKKKK0UUUVrve973vREREZoSihEooooorRRRRWtd73ve9EREREREoSiiiiitFllllla73ve9ERERERESiiiiiitH0PoWWWWVrXe96IiIiMoiJRRRRRRWjwlFFllllFFd6IiIiIlCUUUUUUUUUePHjx48ePCIiIiIiIiUUUUUUUUUUUePHjx48ePHjx48ePHjx48IiUUUUUUJRRRX//xAAWEQADAAAAAAAAAAAAAAAAAAABYJD/2gAIAQIBAz8AtEV7/8QAFxEBAQEBAAAAAAAAAAAAAAAAAAECEP/aAAgBAwEBAgCtNNNNNNNNNNNNNNNNNNNNNNNNNNNNNcrTTTTTTTTTTTTTTTTTTTTTTTTTTTTTXKrTTTTTTTU000000000000000000001FVpppppqampqaaaaaaaaaaaaaaaaaaaa5Vaaaaampqampqammmmmmmmmmmlaaaaaaiq0001NTU1NTU1NTTTTTTTTTTSqqtNNNcqtNNSyzU1LNTU1NTTTTTTTTTSqqq001ytNLLLLNTU1NTU1NTbbbTTTTTSqqq001ytNLLLLLNTU1NTU3NttttNNNNNKqq001KrSyyyyyzU1NTU3Nzc02220000qqqqrSqqyyyyyzU1NTU3Nzc3NttttNNNKqqqqqqssssss1NTU3Nzc3NzbbbbTTTSqqqqqqrLLLLLNTU1Nzc3Nzc22220000qqqqqqqqssss1NTU3Nzc3NzbbbbbTTSqqqqqqqqqqzU1NTc3Nzc3Nzbc22000qqqqqqqqqqqtTU3Nzc3Nzc3NtzbTTSqqqqrKqqqqqtNNzc23Nzc3Nzc3NTU1KqqqrKqqqqqtNNNNttzc3Nzc3NzU1NLLLLLKqqqqqqqq0022223Nzc3NzU1NSyyyyyyqqqqqqqrTTbbbbc3Nzc3NTU1LLLLLLKsqqqqqqrTTTTbbbc3Nzc1NTUsssssssqqqqqqrTTTTTbbbTc3NTU1NTUsssssqqqqqqqq0000222023NTU1NTUsssssqqqqqqqq000000003NTU1NTU1LLLLLNKrTSqqqqtNNNNNNtNNTU1NSzUssss00qq0qqqqrTTTTTTTTTU1NTUs1LLLNNNKrTTTSqqq00000000001NTU1LNTU0000qtNNNKqqqtNNNNNNNNTU1NTUs1NNNNNKss1NNNK00qtK0000001NNTU0s000000qq000001NKrStNNNNK1NNNNStNNNNNKqtNNNNNNNK0000000rU0000rTTTTTSq00000rTTTTTTTTTTTTTTTTStNNNNKr/xAAUEQEAAAAAAAAAAAAAAAAAAACg/9oACAEDAQM/AAAf/9k=", "data:image/jpeg;base64,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", "data:image/png;base64,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", shaderMapUrl),
|
|
495
|
+
preserveAspectRatio: "xMidYMid slice"
|
|
496
|
+
}), jsx("feColorMatrix", {
|
|
497
|
+
in: "DISPLACEMENT_MAP",
|
|
498
|
+
type: "matrix",
|
|
499
|
+
values: "0.3 0.3 0.3 0 0\n 0.3 0.3 0.3 0 0\n 0.3 0.3 0.3 0 0\n 0 0 0 1 0",
|
|
500
|
+
result: "EDGE_INTENSITY"
|
|
501
|
+
}), jsx("feComponentTransfer", {
|
|
502
|
+
in: "EDGE_INTENSITY",
|
|
503
|
+
result: "EDGE_MASK",
|
|
504
|
+
children: jsx("feFuncA", {
|
|
505
|
+
type: "discrete",
|
|
506
|
+
tableValues: `0 ${.05 * aberrationIntensity} 1`
|
|
507
|
+
})
|
|
508
|
+
}), jsx("feOffset", {
|
|
509
|
+
in: "SourceGraphic",
|
|
510
|
+
dx: "0",
|
|
511
|
+
dy: "0",
|
|
512
|
+
result: "CENTER_ORIGINAL"
|
|
513
|
+
}), jsx("feDisplacementMap", {
|
|
514
|
+
in: "SourceGraphic",
|
|
515
|
+
in2: "DISPLACEMENT_MAP",
|
|
516
|
+
scale: displacementScale * ("shader" === mode ? 1 : -1),
|
|
517
|
+
xChannelSelector: "R",
|
|
518
|
+
yChannelSelector: "B",
|
|
519
|
+
result: "RED_DISPLACED"
|
|
520
|
+
}), jsx("feColorMatrix", {
|
|
521
|
+
in: "RED_DISPLACED",
|
|
522
|
+
type: "matrix",
|
|
523
|
+
values: "1 0 0 0 0\n 0 0 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
524
|
+
result: "RED_CHANNEL"
|
|
525
|
+
}), jsx("feDisplacementMap", {
|
|
526
|
+
in: "SourceGraphic",
|
|
527
|
+
in2: "DISPLACEMENT_MAP",
|
|
528
|
+
scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
|
|
529
|
+
xChannelSelector: "R",
|
|
530
|
+
yChannelSelector: "B",
|
|
531
|
+
result: "GREEN_DISPLACED"
|
|
532
|
+
}), jsx("feColorMatrix", {
|
|
533
|
+
in: "GREEN_DISPLACED",
|
|
534
|
+
type: "matrix",
|
|
535
|
+
values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
536
|
+
result: "GREEN_CHANNEL"
|
|
537
|
+
}), jsx("feDisplacementMap", {
|
|
538
|
+
in: "SourceGraphic",
|
|
539
|
+
in2: "DISPLACEMENT_MAP",
|
|
540
|
+
scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
|
|
541
|
+
xChannelSelector: "R",
|
|
542
|
+
yChannelSelector: "B",
|
|
543
|
+
result: "BLUE_DISPLACED"
|
|
544
|
+
}), jsx("feColorMatrix", {
|
|
545
|
+
in: "BLUE_DISPLACED",
|
|
546
|
+
type: "matrix",
|
|
547
|
+
values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
|
|
548
|
+
result: "BLUE_CHANNEL"
|
|
549
|
+
}), jsx("feBlend", {
|
|
550
|
+
in: "GREEN_CHANNEL",
|
|
551
|
+
in2: "BLUE_CHANNEL",
|
|
552
|
+
mode: "screen",
|
|
553
|
+
result: "GB_COMBINED"
|
|
554
|
+
}), jsx("feBlend", {
|
|
555
|
+
in: "RED_CHANNEL",
|
|
556
|
+
in2: "GB_COMBINED",
|
|
557
|
+
mode: "screen",
|
|
558
|
+
result: "RGB_COMBINED"
|
|
559
|
+
}), jsx("feGaussianBlur", {
|
|
560
|
+
in: "RGB_COMBINED",
|
|
561
|
+
result: "ABERRATED_BLURRED",
|
|
562
|
+
stdDeviation: blurAmount * aberrationIntensity * .05
|
|
563
|
+
}), jsx("feComposite", {
|
|
564
|
+
in: "ABERRATED_BLURRED",
|
|
565
|
+
in2: "EDGE_MASK",
|
|
566
|
+
operator: "in",
|
|
567
|
+
result: "EDGE_ABERRATION"
|
|
568
|
+
}), jsx("feComponentTransfer", {
|
|
569
|
+
in: "EDGE_MASK",
|
|
570
|
+
result: "INVERTED_MASK",
|
|
571
|
+
children: jsx("feFuncA", {
|
|
572
|
+
type: "table",
|
|
573
|
+
tableValues: "1 0"
|
|
574
|
+
})
|
|
575
|
+
}), jsx("feComposite", {
|
|
576
|
+
in: "CENTER_ORIGINAL",
|
|
577
|
+
in2: "INVERTED_MASK",
|
|
578
|
+
operator: "in",
|
|
579
|
+
result: "CENTER_CLEAN"
|
|
580
|
+
}), jsx("feComposite", {
|
|
581
|
+
in: "EDGE_ABERRATION",
|
|
582
|
+
in2: "CENTER_CLEAN",
|
|
583
|
+
operator: "over"
|
|
584
|
+
}) ]
|
|
585
|
+
}) ]
|
|
586
|
+
})
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Accordion-specific constants
|
|
591
|
+
*/ GlassFilterComponent.displayName = "GlassFilter";
|
|
592
|
+
|
|
593
|
+
// Memoize component to prevent unnecessary re-renders
|
|
594
|
+
const GlassFilter = memo(GlassFilterComponent, ((prevProps, nextProps) => prevProps.id === nextProps.id && prevProps.displacementScale === nextProps.displacementScale && prevProps.aberrationIntensity === nextProps.aberrationIntensity && prevProps.mode === nextProps.mode && prevProps.shaderMapUrl === nextProps.shaderMapUrl && prevProps.blurAmount === nextProps.blurAmount)), sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
595
|
+
x: 0,
|
|
596
|
+
y: 0
|
|
597
|
+
}, globalMousePosition: globalMousePosition = {
|
|
598
|
+
x: 0,
|
|
599
|
+
y: 0
|
|
600
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, active: active = !1, isHovered: isHovered = !1, isActive: isActive = !1, overLight: overLight = !1, cornerRadius: cornerRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
601
|
+
width: 0,
|
|
602
|
+
height: 0
|
|
603
|
+
}, onClick: onClick, mode: mode = "standard", effectiveDisableEffects: effectiveDisableEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", enableLiquidBlur: enableLiquidBlur = !1, elasticity: elasticity = 0, contentRef: contentRef}, ref) => {
|
|
604
|
+
// Use React's useId() for SSR compatibility
|
|
605
|
+
// Note: In Next.js, IDs may differ between server and client
|
|
606
|
+
// We'll suppress hydration warnings on elements that use this ID
|
|
607
|
+
const filterId = useId(), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
608
|
+
// Lazy load shader utilities only when shader mode is needed
|
|
609
|
+
useEffect((() => {
|
|
610
|
+
"shader" === mode ?
|
|
611
|
+
// Dynamic import shader utilities
|
|
612
|
+
Promise.resolve().then((() => shaderUtils)).then((shaderUtils => {
|
|
613
|
+
shaderUtilsRef.current = {
|
|
614
|
+
ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
|
|
615
|
+
fragmentShaders: shaderUtils.fragmentShaders
|
|
616
|
+
};
|
|
617
|
+
})).catch((error => {
|
|
618
|
+
console.warn("AtomixGlassContainer: Error loading shader utilities", error);
|
|
619
|
+
})) :
|
|
620
|
+
// Clear shader utils when not in shader mode to free memory
|
|
621
|
+
shaderUtilsRef.current = null;
|
|
622
|
+
}), [ mode ]),
|
|
623
|
+
// Generate shader map with debouncing and caching
|
|
624
|
+
useEffect((() => {
|
|
625
|
+
// Enhanced validation for shader mode
|
|
626
|
+
if ("shader" === mode && glassSize && validateGlassSize(glassSize) && shaderUtilsRef.current) {
|
|
627
|
+
// Create cache key from size and variant
|
|
628
|
+
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
629
|
+
const entry = sharedShaderCache.get(key);
|
|
630
|
+
return entry ? (
|
|
631
|
+
// Update access timestamp for LRU
|
|
632
|
+
entry.timestamp = Date.now(), entry.url) : null;
|
|
633
|
+
})(cacheKey);
|
|
634
|
+
// Check shared cache first
|
|
635
|
+
if (cachedUrl) return void setShaderMapUrl(cachedUrl);
|
|
636
|
+
// Clear any pending debounce
|
|
637
|
+
shaderDebounceTimeoutRef.current && clearTimeout(shaderDebounceTimeoutRef.current);
|
|
638
|
+
// Debounce shader generation to avoid blocking on rapid size changes
|
|
639
|
+
const generateShader = () => {
|
|
640
|
+
if (shaderUtilsRef.current) try {
|
|
641
|
+
const {ShaderDisplacementGenerator: ShaderDisplacementGenerator, fragmentShaders: fragmentShaders} = shaderUtilsRef.current;
|
|
642
|
+
shaderGeneratorRef.current?.destroy();
|
|
643
|
+
const selectedShader = fragmentShaders[shaderVariant] || fragmentShaders.liquidGlass;
|
|
644
|
+
shaderGeneratorRef.current = new ShaderDisplacementGenerator({
|
|
645
|
+
width: glassSize.width,
|
|
646
|
+
height: glassSize.height,
|
|
647
|
+
fragment: selectedShader
|
|
648
|
+
});
|
|
649
|
+
// Use requestIdleCallback if available for non-blocking generation
|
|
650
|
+
const generate = () => {
|
|
651
|
+
const url = shaderGeneratorRef.current?.updateShader() || "";
|
|
652
|
+
((key, url) => {
|
|
653
|
+
// Evict oldest entries if at capacity
|
|
654
|
+
if (sharedShaderCache.size >= 15) {
|
|
655
|
+
const entries = Array.from(sharedShaderCache.entries());
|
|
656
|
+
// Sort by timestamp (oldest first)
|
|
657
|
+
entries.sort(((a, b) => a[1].timestamp - b[1].timestamp));
|
|
658
|
+
// Remove oldest entry
|
|
659
|
+
const oldestEntry = entries[0];
|
|
660
|
+
oldestEntry && sharedShaderCache.delete(oldestEntry[0]);
|
|
661
|
+
}
|
|
662
|
+
sharedShaderCache.set(key, {
|
|
663
|
+
url: url,
|
|
664
|
+
timestamp: Date.now()
|
|
665
|
+
}),
|
|
666
|
+
// Development mode: log cache size
|
|
667
|
+
"production" !== process.env.NODE_ENV && sharedShaderCache.size;
|
|
668
|
+
})(cacheKey, url), setShaderMapUrl(url);
|
|
669
|
+
};
|
|
670
|
+
"undefined" != typeof requestIdleCallback ? requestIdleCallback(generate, {
|
|
671
|
+
timeout: 1e3
|
|
672
|
+
}) :
|
|
673
|
+
// Fallback to setTimeout for browsers without requestIdleCallback
|
|
674
|
+
setTimeout(generate, 0);
|
|
675
|
+
} catch (error) {
|
|
676
|
+
console.warn("AtomixGlassContainer: Error generating shader map", error), setShaderMapUrl("");
|
|
677
|
+
} else
|
|
678
|
+
// Shader utils not loaded yet, retry after a short delay
|
|
679
|
+
shaderDebounceTimeoutRef.current = setTimeout(generateShader, 100);
|
|
680
|
+
};
|
|
681
|
+
// Debounce with 300ms delay
|
|
682
|
+
shaderDebounceTimeoutRef.current = setTimeout(generateShader, 300);
|
|
683
|
+
} else
|
|
684
|
+
// Not in shader mode, clear URL
|
|
685
|
+
setShaderMapUrl("");
|
|
686
|
+
// Cleanup function with error handling
|
|
687
|
+
return () => {
|
|
688
|
+
shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
|
|
689
|
+
shaderDebounceTimeoutRef.current = null);
|
|
690
|
+
try {
|
|
691
|
+
shaderGeneratorRef.current?.destroy();
|
|
692
|
+
} catch (error) {
|
|
693
|
+
console.warn("AtomixGlassContainer: Error during shader cleanup", error);
|
|
694
|
+
} finally {
|
|
695
|
+
shaderGeneratorRef.current = null;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
}), [ mode, glassSize, shaderVariant ]);
|
|
699
|
+
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
700
|
+
const [rectCache, setRectCache] = useState(null);
|
|
701
|
+
useEffect((() => {
|
|
702
|
+
if (!ref || "function" == typeof ref) return;
|
|
703
|
+
const element = ref.current;
|
|
704
|
+
if (element) try {
|
|
705
|
+
setRectCache(element.getBoundingClientRect());
|
|
706
|
+
} catch (error) {
|
|
707
|
+
console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
|
|
708
|
+
}
|
|
709
|
+
}), [ ref, glassSize ]);
|
|
710
|
+
// Pre-calculate static multipliers outside useMemo
|
|
711
|
+
const liquidBlur = useMemo((() => {
|
|
712
|
+
const defaultBlur = {
|
|
713
|
+
baseBlur: blurAmount,
|
|
714
|
+
edgeBlur: 1.25 * blurAmount,
|
|
715
|
+
centerBlur: 1.1 * blurAmount,
|
|
716
|
+
flowBlur: 1.2 * blurAmount
|
|
717
|
+
};
|
|
718
|
+
// Enhanced validation for liquid blur
|
|
719
|
+
if (!enableLiquidBlur || !rectCache || !globalMousePosition || "number" != typeof globalMousePosition.x || "number" != typeof globalMousePosition.y || isNaN(globalMousePosition.x) || isNaN(globalMousePosition.y)) return defaultBlur;
|
|
720
|
+
try {
|
|
721
|
+
// Cache center and distance calculations
|
|
722
|
+
const center = calculateElementCenter(rectCache), distance = calculateDistance(globalMousePosition, center), maxDistance = Math.sqrt(rectCache.width * rectCache.width + rectCache.height * rectCache.height) / 2, normalizedDistance = Math.min(distance / maxDistance, 1), mouseInfluence = calculateMouseInfluence(mouseOffset), baseBlur = blurAmount + mouseInfluence * blurAmount * .4, edgeBlur = baseBlur * (.8 + .6 * (1.5 * normalizedDistance + .3 * mouseInfluence)), centerBlur = baseBlur * (.3 + .4 * (.3 * (1 - normalizedDistance) + .2 * mouseInfluence)), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, flowDirection = Math.atan2(deltaY, deltaX), flowBlur = baseBlur * (.4 + .6 * (.5 * Math.sin(flowDirection + mouseInfluence * Math.PI) + .5)), stateMultiplier = (isHovered ? 1.2 : 1) * (isActive ? 1.4 : 1);
|
|
723
|
+
return {
|
|
724
|
+
baseBlur: clampBlur(baseBlur * stateMultiplier),
|
|
725
|
+
edgeBlur: clampBlur(edgeBlur * stateMultiplier),
|
|
726
|
+
centerBlur: clampBlur(centerBlur * stateMultiplier),
|
|
727
|
+
flowBlur: clampBlur(flowBlur * stateMultiplier)
|
|
728
|
+
};
|
|
729
|
+
} catch (error) {
|
|
730
|
+
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
731
|
+
defaultBlur;
|
|
732
|
+
}
|
|
733
|
+
}), [ enableLiquidBlur, blurAmount, globalMousePosition, mouseOffset, isHovered, isActive, rectCache, style, glassSize ]), backdropStyle = useMemo((() => {
|
|
734
|
+
try {
|
|
735
|
+
const dynamicSaturation = saturation + 20 * (liquidBlur.baseBlur || 0), validatedBaseBlur = "number" != typeof liquidBlur.baseBlur || isNaN(liquidBlur.baseBlur) ? 0 : liquidBlur.baseBlur, validatedEdgeBlur = "number" != typeof liquidBlur.edgeBlur || isNaN(liquidBlur.edgeBlur) ? 0 : liquidBlur.edgeBlur, validatedCenterBlur = "number" != typeof liquidBlur.centerBlur || isNaN(liquidBlur.centerBlur) ? 0 : liquidBlur.centerBlur, validatedFlowBlur = "number" != typeof liquidBlur.flowBlur || isNaN(liquidBlur.flowBlur) ? 0 : liquidBlur.flowBlur, area = rectCache ? rectCache.width * rectCache.height : 0;
|
|
736
|
+
// Validate blur values before using them
|
|
737
|
+
return !enableLiquidBlur || effectiveReducedMotion || effectiveDisableEffects || area > 18e4 ? {
|
|
738
|
+
backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`
|
|
739
|
+
} : {
|
|
740
|
+
backdropFilter: `${[ `blur(${validatedBaseBlur}px)`, `blur(${validatedEdgeBlur}px)`, `blur(${validatedCenterBlur}px)`, `blur(${validatedFlowBlur}px)` ].join(" ")} saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`
|
|
741
|
+
};
|
|
742
|
+
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
743
|
+
} catch (error) {
|
|
744
|
+
return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
|
|
745
|
+
{
|
|
746
|
+
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
}), [ filterId, liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveDisableEffects, enableLiquidBlur ]), containerVars = useMemo((() => {
|
|
750
|
+
try {
|
|
751
|
+
// Safe extraction of mouse offset values
|
|
752
|
+
const mx = mouseOffset && "number" == typeof mouseOffset.x && !isNaN(mouseOffset.x) ? mouseOffset.x : 0, my = mouseOffset && "number" == typeof mouseOffset.y && !isNaN(mouseOffset.y) ? mouseOffset.y : 0;
|
|
753
|
+
return {
|
|
754
|
+
"--atomix-glass-container-width": `${glassSize?.width}`,
|
|
755
|
+
"--atomix-glass-container-height": `${glassSize?.height}`,
|
|
756
|
+
"--atomix-glass-container-padding": padding || "0 0",
|
|
757
|
+
"--atomix-glass-container-radius": `${"number" != typeof cornerRadius || isNaN(cornerRadius) ? 0 : cornerRadius}px`,
|
|
758
|
+
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
759
|
+
"--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${.4 + .002 * mx})`, `inset 0 -1px 0 rgba(0, 0, 0, ${.2 + .001 * Math.abs(my)})`, `inset 0 0 20px rgba(0, 0, 0, ${.08 + .001 * Math.abs(mx + my)})`, `0 2px 12px rgba(0, 0, 0, ${.12 + .002 * Math.abs(my)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
|
|
760
|
+
"--atomix-glass-container-shadow-opacity": effectiveDisableEffects ? 0 : 1,
|
|
761
|
+
// Background and shadow values use design token-aligned RGB values
|
|
762
|
+
"--atomix-glass-container-bg": overLight ? `linear-gradient(${180 + .5 * mx}deg, rgba(255, 255, 255, 0.1) 0%, transparent 20%, transparent 80%, rgba(0, 0, 0, 0.05) 100%)` : "none",
|
|
763
|
+
"--atomix-glass-container-text-shadow": overLight ? "0px 2px 12px rgba(0, 0, 0, 0)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
764
|
+
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
765
|
+
};
|
|
766
|
+
} catch (error) {
|
|
767
|
+
return console.warn("AtomixGlassContainer: Error generating container variables", error),
|
|
768
|
+
{
|
|
769
|
+
"--atomix-glass-container-padding": "0 0",
|
|
770
|
+
"--atomix-glass-container-radius": "0px",
|
|
771
|
+
"--atomix-glass-container-backdrop": "none",
|
|
772
|
+
"--atomix-glass-container-shadow": "none",
|
|
773
|
+
"--atomix-glass-container-shadow-opacity": 1,
|
|
774
|
+
"--atomix-glass-container-bg": "none",
|
|
775
|
+
"--atomix-glass-container-text-shadow": "none"
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
}), [ glassSize, padding, cornerRadius, backdropStyle, mouseOffset, overLight, effectiveDisableEffects ]);
|
|
779
|
+
return jsx("div", {
|
|
780
|
+
ref: ref,
|
|
781
|
+
className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${active ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
|
|
782
|
+
style: {
|
|
783
|
+
...style,
|
|
784
|
+
...containerVars
|
|
785
|
+
},
|
|
786
|
+
onClick: onClick,
|
|
787
|
+
children: jsxs("div", {
|
|
788
|
+
className: ATOMIX_GLASS.INNER_CLASS,
|
|
789
|
+
style: {
|
|
790
|
+
padding: "var(--atomix-glass-container-padding)",
|
|
791
|
+
boxShadow: "var(--atomix-glass-container-box-shadow)"
|
|
792
|
+
},
|
|
793
|
+
onMouseEnter: onMouseEnter,
|
|
794
|
+
onMouseLeave: onMouseLeave,
|
|
795
|
+
onMouseDown: onMouseDown,
|
|
796
|
+
onMouseUp: onMouseUp,
|
|
797
|
+
children: [ jsxs("div", {
|
|
798
|
+
className: ATOMIX_GLASS.FILTER_CLASS,
|
|
799
|
+
children: [ jsx(GlassFilter, {
|
|
800
|
+
blurAmount: blurAmount,
|
|
801
|
+
mode: mode,
|
|
802
|
+
id: filterId,
|
|
803
|
+
displacementScale: "number" != typeof displacementScale || isNaN(displacementScale) ? 0 : displacementScale,
|
|
804
|
+
aberrationIntensity: "number" != typeof aberrationIntensity || isNaN(aberrationIntensity) ? 0 : aberrationIntensity,
|
|
805
|
+
shaderMapUrl: shaderMapUrl
|
|
806
|
+
}), jsx("div", {
|
|
807
|
+
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
808
|
+
suppressHydrationWarning: !0,
|
|
809
|
+
style: {
|
|
810
|
+
filter: `url(#${filterId})`,
|
|
811
|
+
backdropFilter: "var(--atomix-glass-container-backdrop)",
|
|
812
|
+
borderRadius: "var(--atomix-glass-container-radius)"
|
|
813
|
+
}
|
|
814
|
+
}), jsx("div", {
|
|
815
|
+
className: ATOMIX_GLASS.FILTER_SHADOW_CLASS,
|
|
816
|
+
style: {
|
|
817
|
+
boxShadow: "var(--atomix-glass-container-shadow)",
|
|
818
|
+
opacity: "var(--atomix-glass-container-shadow-opacity)",
|
|
819
|
+
background: "var(--atomix-glass-container-bg)",
|
|
820
|
+
borderRadius: "var(--atomix-glass-container-radius)"
|
|
821
|
+
}
|
|
822
|
+
}) ]
|
|
823
|
+
}), jsx("div", {
|
|
824
|
+
ref: contentRef,
|
|
825
|
+
className: ATOMIX_GLASS.CONTENT_CLASS,
|
|
826
|
+
style: {
|
|
827
|
+
position: "relative",
|
|
828
|
+
textShadow: "var(--atomix-glass-container-text-shadow)",
|
|
829
|
+
...elasticity > 0 ? {
|
|
830
|
+
zIndex: 100
|
|
831
|
+
} : {}
|
|
832
|
+
},
|
|
833
|
+
children: children
|
|
834
|
+
}) ]
|
|
835
|
+
})
|
|
836
|
+
});
|
|
837
|
+
}));
|
|
838
|
+
|
|
839
|
+
// Module-level shared shader cache with LRU eviction
|
|
840
|
+
AtomixGlassContainer.displayName = "AtomixGlassContainer";
|
|
841
|
+
|
|
842
|
+
// Singleton instance
|
|
843
|
+
const globalMouseTracker = new
|
|
844
|
+
/**
|
|
845
|
+
* Global mouse tracker singleton
|
|
846
|
+
* Tracks mouse position at document level and distributes to subscribers
|
|
847
|
+
* Reduces event processing overhead when multiple AtomixGlass instances are present
|
|
848
|
+
*/
|
|
849
|
+
class {
|
|
850
|
+
constructor() {
|
|
851
|
+
this.listeners = new Set, this.position = {
|
|
852
|
+
x: 0,
|
|
853
|
+
y: 0
|
|
854
|
+
}, this.rafId = null, this.lastEvent = null, this.isTracking = !1,
|
|
855
|
+
/**
|
|
856
|
+
* Handle mouse move event
|
|
857
|
+
*/
|
|
858
|
+
this.handleMouseMove = e => {
|
|
859
|
+
this.lastEvent = e,
|
|
860
|
+
// Use requestAnimationFrame to throttle updates
|
|
861
|
+
null === this.rafId && (this.rafId = requestAnimationFrame((() => {
|
|
862
|
+
this.lastEvent && (this.position = {
|
|
863
|
+
x: this.lastEvent.clientX,
|
|
864
|
+
y: this.lastEvent.clientY
|
|
865
|
+
},
|
|
866
|
+
// Notify all subscribers
|
|
867
|
+
this.listeners.forEach((callback => {
|
|
868
|
+
try {
|
|
869
|
+
callback(this.position);
|
|
870
|
+
} catch (error) {
|
|
871
|
+
console.error("GlobalMouseTracker: Error in subscriber callback", error);
|
|
872
|
+
}
|
|
873
|
+
}))), this.rafId = null;
|
|
874
|
+
})));
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Subscribe to mouse position updates
|
|
879
|
+
* @param callback Function to call when mouse position changes
|
|
880
|
+
* @returns Unsubscribe function
|
|
881
|
+
*/ subscribe(callback) {
|
|
882
|
+
// Return unsubscribe function
|
|
883
|
+
return this.listeners.add(callback),
|
|
884
|
+
// Start tracking if this is the first subscriber
|
|
885
|
+
1 === this.listeners.size && this.startTracking(),
|
|
886
|
+
// Immediately notify with current position
|
|
887
|
+
callback(this.position), () => {
|
|
888
|
+
this.unsubscribe(callback);
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Unsubscribe from mouse position updates
|
|
893
|
+
*/ unsubscribe(callback) {
|
|
894
|
+
this.listeners.delete(callback),
|
|
895
|
+
// Stop tracking if no more subscribers
|
|
896
|
+
0 === this.listeners.size && this.stopTracking();
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Start tracking mouse movement
|
|
900
|
+
*/ startTracking() {
|
|
901
|
+
this.isTracking || (this.isTracking = !0,
|
|
902
|
+
// Use document-level listener for global tracking
|
|
903
|
+
document.addEventListener("mousemove", this.handleMouseMove, {
|
|
904
|
+
passive: !0
|
|
905
|
+
}));
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Stop tracking mouse movement
|
|
909
|
+
*/ stopTracking() {
|
|
910
|
+
this.isTracking && (this.isTracking = !1, document.removeEventListener("mousemove", this.handleMouseMove),
|
|
911
|
+
// Cancel any pending RAF
|
|
912
|
+
null !== this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.lastEvent = null);
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Get current mouse position (synchronous)
|
|
916
|
+
*/ getPosition() {
|
|
917
|
+
return {
|
|
918
|
+
...this.position
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Get number of active subscribers (for debugging)
|
|
923
|
+
*/ getSubscriberCount() {
|
|
924
|
+
return this.listeners.size;
|
|
925
|
+
}
|
|
926
|
+
}, {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
927
|
+
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
928
|
+
result: result,
|
|
929
|
+
timestamp: Date.now(),
|
|
930
|
+
config: overLightConfig,
|
|
931
|
+
threshold: threshold
|
|
932
|
+
});
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Composable hook for AtomixGlass component logic
|
|
937
|
+
* Manages all state, calculations, and event handlers
|
|
938
|
+
*/
|
|
939
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, cornerRadius: cornerRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, disableEffects: disableEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1, enablePerformanceMonitoring: enablePerformanceMonitoring = !1, children: children}) {
|
|
940
|
+
// State
|
|
941
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), [glassSize, setGlassSize] = useState({
|
|
942
|
+
width: 270,
|
|
943
|
+
height: 69
|
|
944
|
+
}), [internalGlobalMousePosition, setInternalGlobalMousePosition] = useState({
|
|
945
|
+
x: 0,
|
|
946
|
+
y: 0
|
|
947
|
+
}), [internalMouseOffset, setInternalMouseOffset] = useState({
|
|
948
|
+
x: 0,
|
|
949
|
+
y: 0
|
|
950
|
+
}), [dynamicCornerRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveCornerRadius = useMemo((() => void 0 !== cornerRadius ? Math.max(0, cornerRadius) : Math.max(0, dynamicCornerRadius)), [ cornerRadius, dynamicCornerRadius, debugCornerRadius ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveDisableEffects = useMemo((() => disableEffects || effectiveReducedMotion), [ disableEffects, effectiveReducedMotion ]), globalMousePosition = useMemo((() => externalGlobalMousePosition || internalGlobalMousePosition), [ externalGlobalMousePosition, internalGlobalMousePosition ]), mouseOffset = useMemo((() => externalMouseOffset || internalMouseOffset), [ externalMouseOffset, internalMouseOffset ]);
|
|
951
|
+
// Extract border-radius from children
|
|
952
|
+
useEffect((() => {
|
|
953
|
+
const extractRadius = () => {
|
|
954
|
+
try {
|
|
955
|
+
let extractedRadius = null, extractionSource = "default";
|
|
956
|
+
if (contentRef.current) {
|
|
957
|
+
const firstChild = contentRef.current.firstElementChild;
|
|
958
|
+
if (firstChild) {
|
|
959
|
+
const domRadius = (element => {
|
|
960
|
+
if (!element || "undefined" == typeof window) return null;
|
|
961
|
+
try {
|
|
962
|
+
const computedStyles = window.getComputedStyle(element), borderRadius = computedStyles.borderRadius || computedStyles.borderTopLeftRadius || computedStyles.borderTopRightRadius || computedStyles.borderBottomLeftRadius || computedStyles.borderBottomRightRadius;
|
|
963
|
+
if (borderRadius && "0px" !== borderRadius && "auto" !== borderRadius) {
|
|
964
|
+
const parsed = parseBorderRadiusValue(borderRadius);
|
|
965
|
+
return parsed > 0 ? parsed : null;
|
|
966
|
+
}
|
|
967
|
+
return null;
|
|
968
|
+
} catch (error) {
|
|
969
|
+
return null;
|
|
970
|
+
}
|
|
971
|
+
})(firstChild);
|
|
972
|
+
null !== domRadius && domRadius > 0 && (extractedRadius = domRadius, extractionSource = "DOM element");
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
if (null === extractedRadius) {
|
|
976
|
+
const childRadius = extractBorderRadiusFromChildren(children);
|
|
977
|
+
childRadius > 0 && childRadius !== CONSTANTS.DEFAULT_CORNER_RADIUS && (extractedRadius = childRadius,
|
|
978
|
+
extractionSource = "React children");
|
|
979
|
+
}
|
|
980
|
+
null !== extractedRadius && extractedRadius > 0 ? setDynamicCornerRadius(extractedRadius) : process.env.NODE_ENV;
|
|
981
|
+
} catch (error) {
|
|
982
|
+
"production" !== process.env.NODE_ENV && debugCornerRadius && console.error("[AtomixGlass] Error extracting corner radius:", error);
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
extractRadius();
|
|
986
|
+
const timeoutId = setTimeout(extractRadius, 100);
|
|
987
|
+
return () => clearTimeout(timeoutId);
|
|
988
|
+
}), [ children, debugCornerRadius, contentRef ]),
|
|
989
|
+
// Media query handlers and background detection
|
|
990
|
+
useEffect((() => {
|
|
991
|
+
if (("auto" === overLight || "object" == typeof overLight && null !== overLight) && glassRef.current) {
|
|
992
|
+
const element = glassRef.current, cachedResult = ((parentElement, overLightConfig) => {
|
|
993
|
+
if (!parentElement) return null;
|
|
994
|
+
const cached = backgroundDetectionCache.get(parentElement);
|
|
995
|
+
return cached && ((config1, config2) => {
|
|
996
|
+
// Primitive comparison for boolean and 'auto'
|
|
997
|
+
if ("object" != typeof config1 || null === config1) return config1 === config2;
|
|
998
|
+
// Both must be objects at this point
|
|
999
|
+
if ("object" != typeof config2 || null === config2) return !1;
|
|
1000
|
+
const obj1 = config1, obj2 = config2, props = [ "threshold", "opacity", "contrast", "brightness", "saturationBoost" ];
|
|
1001
|
+
for (const prop of props) {
|
|
1002
|
+
const val1 = obj1[prop], val2 = obj2[prop];
|
|
1003
|
+
// If both are undefined, they're equal for this property
|
|
1004
|
+
if (void 0 !== val1 || void 0 !== val2) {
|
|
1005
|
+
// If one is undefined and the other isn't, they're different
|
|
1006
|
+
if (void 0 === val1 || void 0 === val2) return !1;
|
|
1007
|
+
// Compare numeric values (handle NaN and floating point precision)
|
|
1008
|
+
if ("number" == typeof val1 && "number" == typeof val2) {
|
|
1009
|
+
// Use Number.isNaN for proper NaN comparison
|
|
1010
|
+
if (Number.isNaN(val1) && Number.isNaN(val2)) continue;
|
|
1011
|
+
if (Number.isNaN(val1) || Number.isNaN(val2)) return !1;
|
|
1012
|
+
// Compare with small epsilon for floating point numbers
|
|
1013
|
+
if (Math.abs(val1 - val2) > Number.EPSILON) return !1;
|
|
1014
|
+
} else if (val1 !== val2) return !1;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
return !0;
|
|
1018
|
+
})(cached.config, overLightConfig) ? (
|
|
1019
|
+
// Update timestamp for LRU-like behavior (though WeakMap doesn't support LRU)
|
|
1020
|
+
cached.timestamp = Date.now(), cached.result) : null;
|
|
1021
|
+
})(element.parentElement, overLight);
|
|
1022
|
+
if (null !== cachedResult) return void setDetectedOverLight(cachedResult);
|
|
1023
|
+
const timeoutId = setTimeout((() => {
|
|
1024
|
+
try {
|
|
1025
|
+
if (!element) return void setDetectedOverLight(!1);
|
|
1026
|
+
// Validate window context
|
|
1027
|
+
if ("undefined" == typeof window || "function" != typeof window.getComputedStyle) return void setDetectedOverLight(!1);
|
|
1028
|
+
let totalLuminance = 0, validSamples = 0, hasValidBackground = !1, currentElement = element.parentElement, depth = 0;
|
|
1029
|
+
const maxDepth = 20, maxSamples = 10;
|
|
1030
|
+
// Limit traversal depth to prevent infinite loops and performance issues
|
|
1031
|
+
for (;currentElement && validSamples < maxSamples && depth < maxDepth; ) {
|
|
1032
|
+
try {
|
|
1033
|
+
const computedStyle = window.getComputedStyle(currentElement);
|
|
1034
|
+
if (!computedStyle) {
|
|
1035
|
+
currentElement = currentElement.parentElement, depth++;
|
|
1036
|
+
continue;
|
|
1037
|
+
}
|
|
1038
|
+
const bgColor = computedStyle.backgroundColor, bgImage = computedStyle.backgroundImage;
|
|
1039
|
+
// Check for solid color backgrounds
|
|
1040
|
+
if (bgColor && "rgba(0, 0, 0, 0)" !== bgColor && "transparent" !== bgColor && "initial" !== bgColor && "none" !== bgColor) {
|
|
1041
|
+
const rgb = bgColor.match(/\d+/g);
|
|
1042
|
+
if (rgb && rgb.length >= 3) {
|
|
1043
|
+
const r = Number(rgb[0]), g = Number(rgb[1]), b = Number(rgb[2]);
|
|
1044
|
+
// Validate RGB values are valid numbers
|
|
1045
|
+
if (!isNaN(r) && !isNaN(g) && !isNaN(b) && isFinite(r) && isFinite(g) && isFinite(b) && r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && (r > 10 || g > 10 || b > 10)) {
|
|
1046
|
+
const luminance = (.299 * r + .587 * g + .114 * b) / 255;
|
|
1047
|
+
!isNaN(luminance) && isFinite(luminance) && (totalLuminance += luminance, validSamples++,
|
|
1048
|
+
hasValidBackground = !0);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
// Check for image backgrounds
|
|
1053
|
+
bgImage && "none" !== bgImage && "initial" !== bgImage && (
|
|
1054
|
+
// For image backgrounds, assume medium luminance
|
|
1055
|
+
totalLuminance += .5, validSamples++, hasValidBackground = !0);
|
|
1056
|
+
} catch (styleError) {
|
|
1057
|
+
process.env.NODE_ENV;
|
|
1058
|
+
}
|
|
1059
|
+
// Move to parent element for next iteration
|
|
1060
|
+
if (!currentElement) break;
|
|
1061
|
+
// Exit loop if currentElement becomes null
|
|
1062
|
+
currentElement = currentElement.parentElement, depth++;
|
|
1063
|
+
}
|
|
1064
|
+
// More conservative detection with better error handling
|
|
1065
|
+
if (hasValidBackground && validSamples > 0) {
|
|
1066
|
+
const avgLuminance = totalLuminance / validSamples;
|
|
1067
|
+
if (!isNaN(avgLuminance) && isFinite(avgLuminance)) {
|
|
1068
|
+
let threshold = .7;
|
|
1069
|
+
// Conservative threshold for overlight
|
|
1070
|
+
// If overLight is an object, use its threshold property with validation
|
|
1071
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
1072
|
+
const objConfig = overLight;
|
|
1073
|
+
if (void 0 !== objConfig.threshold) {
|
|
1074
|
+
const configThreshold = "number" == typeof objConfig.threshold && !isNaN(objConfig.threshold) && isFinite(objConfig.threshold) ? objConfig.threshold : .7;
|
|
1075
|
+
threshold = Math.min(.9, Math.max(.1, configThreshold));
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
const isOverLightDetected = avgLuminance > threshold;
|
|
1079
|
+
// Cache the result in shared cache
|
|
1080
|
+
setCachedBackgroundDetection(element.parentElement, overLight, isOverLightDetected, threshold),
|
|
1081
|
+
setDetectedOverLight(isOverLightDetected);
|
|
1082
|
+
} else {
|
|
1083
|
+
// Invalid luminance calculation, default to false
|
|
1084
|
+
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
1085
|
+
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
1086
|
+
setDetectedOverLight(result);
|
|
1087
|
+
}
|
|
1088
|
+
} else {
|
|
1089
|
+
// Default to false if no valid background found
|
|
1090
|
+
const result = !1, threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
1091
|
+
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold),
|
|
1092
|
+
setDetectedOverLight(result);
|
|
1093
|
+
}
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
// Enhanced error logging with context
|
|
1096
|
+
"development" === process.env.NODE_ENV && console.warn("AtomixGlass: Error detecting background brightness:", error);
|
|
1097
|
+
const result = !1;
|
|
1098
|
+
if (element && element.parentElement) {
|
|
1099
|
+
const threshold = "object" == typeof overLight && null !== overLight && overLight.threshold || .7;
|
|
1100
|
+
setCachedBackgroundDetection(element.parentElement, overLight, result, threshold);
|
|
1101
|
+
}
|
|
1102
|
+
setDetectedOverLight(result);
|
|
1103
|
+
}
|
|
1104
|
+
}), 150);
|
|
1105
|
+
return () => clearTimeout(timeoutId);
|
|
1106
|
+
}
|
|
1107
|
+
if ("boolean" == typeof overLight &&
|
|
1108
|
+
// For boolean values, disable auto-detection
|
|
1109
|
+
// Cache is automatically managed by WeakMap (no manual clearing needed)
|
|
1110
|
+
setDetectedOverLight(!1), "function" == typeof window.matchMedia) try {
|
|
1111
|
+
const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)"), mediaQueryHighContrast = window.matchMedia("(prefers-contrast: high)");
|
|
1112
|
+
setUserPrefersReducedMotion(mediaQueryReducedMotion.matches), setUserPrefersHighContrast(mediaQueryHighContrast.matches);
|
|
1113
|
+
const handleReducedMotionChange = e => {
|
|
1114
|
+
setUserPrefersReducedMotion(e.matches);
|
|
1115
|
+
}, handleHighContrastChange = e => {
|
|
1116
|
+
setUserPrefersHighContrast(e.matches);
|
|
1117
|
+
};
|
|
1118
|
+
return mediaQueryReducedMotion.addEventListener ? (mediaQueryReducedMotion.addEventListener("change", handleReducedMotionChange),
|
|
1119
|
+
mediaQueryHighContrast.addEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.addListener && (mediaQueryReducedMotion.addListener(handleReducedMotionChange),
|
|
1120
|
+
mediaQueryHighContrast.addListener(handleHighContrastChange)), () => {
|
|
1121
|
+
try {
|
|
1122
|
+
mediaQueryReducedMotion.removeEventListener ? (mediaQueryReducedMotion.removeEventListener("change", handleReducedMotionChange),
|
|
1123
|
+
mediaQueryHighContrast.removeEventListener("change", handleHighContrastChange)) : mediaQueryReducedMotion.removeListener && (mediaQueryReducedMotion.removeListener(handleReducedMotionChange),
|
|
1124
|
+
mediaQueryHighContrast.removeListener(handleHighContrastChange));
|
|
1125
|
+
} catch (cleanupError) {
|
|
1126
|
+
console.error("AtomixGlass: Error cleaning up media query listeners:", cleanupError);
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
} catch (error) {
|
|
1130
|
+
return void console.error("AtomixGlass: Error setting up media queries:", error);
|
|
1131
|
+
}
|
|
1132
|
+
}), [ overLight, glassRef, debugOverLight ]);
|
|
1133
|
+
// Mouse tracking using shared global tracker
|
|
1134
|
+
// Cache bounding rect to avoid repeated getBoundingClientRect calls
|
|
1135
|
+
const cachedRectRef = useRef(null), updateRectRef = useRef(null), handleGlobalMousePosition = useCallback((globalPos => {
|
|
1136
|
+
if (externalGlobalMousePosition && externalMouseOffset)
|
|
1137
|
+
// External mouse position provided, skip internal tracking
|
|
1138
|
+
return;
|
|
1139
|
+
if (effectiveDisableEffects) return;
|
|
1140
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1141
|
+
if (!container) return;
|
|
1142
|
+
enablePerformanceMonitoring && performance.now();
|
|
1143
|
+
// Use cached rect if available, otherwise get new one
|
|
1144
|
+
let rect = cachedRectRef.current;
|
|
1145
|
+
if (rect && 0 !== rect.width && 0 !== rect.height || (rect = container.getBoundingClientRect(),
|
|
1146
|
+
cachedRectRef.current = rect), 0 === rect.width || 0 === rect.height) return;
|
|
1147
|
+
const center = calculateElementCenter(rect), newOffset = {
|
|
1148
|
+
x: (globalPos.x - center.x) / rect.width * 100,
|
|
1149
|
+
y: (globalPos.y - center.y) / rect.height * 100
|
|
1150
|
+
};
|
|
1151
|
+
// Calculate offset relative to this container
|
|
1152
|
+
// React 18 automatically batches these updates
|
|
1153
|
+
setInternalMouseOffset(newOffset), setInternalGlobalMousePosition(globalPos), "production" !== process.env.NODE_ENV && enablePerformanceMonitoring && performance.now();
|
|
1154
|
+
}), [ mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects, enablePerformanceMonitoring ]);
|
|
1155
|
+
// Subscribe to shared mouse tracker
|
|
1156
|
+
useEffect((() => {
|
|
1157
|
+
if (externalGlobalMousePosition && externalMouseOffset)
|
|
1158
|
+
// External mouse position provided, don't subscribe
|
|
1159
|
+
return;
|
|
1160
|
+
if (effectiveDisableEffects)
|
|
1161
|
+
// Effects disabled, don't subscribe
|
|
1162
|
+
return;
|
|
1163
|
+
// Subscribe to shared tracker
|
|
1164
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition), container = mouseContainer?.current || glassRef.current;
|
|
1165
|
+
// Update cached rect when container size changes
|
|
1166
|
+
let resizeObserver = null;
|
|
1167
|
+
return container && "undefined" != typeof ResizeObserver && (resizeObserver = new ResizeObserver((() => {
|
|
1168
|
+
null !== updateRectRef.current && cancelAnimationFrame(updateRectRef.current), updateRectRef.current = requestAnimationFrame((() => {
|
|
1169
|
+
const container = mouseContainer?.current || glassRef.current;
|
|
1170
|
+
container && (cachedRectRef.current = container.getBoundingClientRect()), updateRectRef.current = null;
|
|
1171
|
+
}));
|
|
1172
|
+
})), resizeObserver.observe(container)), () => {
|
|
1173
|
+
unsubscribe(), null !== updateRectRef.current && (cancelAnimationFrame(updateRectRef.current),
|
|
1174
|
+
updateRectRef.current = null), resizeObserver && resizeObserver.disconnect();
|
|
1175
|
+
};
|
|
1176
|
+
}), [ handleGlobalMousePosition, mouseContainer, glassRef, externalGlobalMousePosition, externalMouseOffset, effectiveDisableEffects ]);
|
|
1177
|
+
// Transform calculations
|
|
1178
|
+
const calculateDirectionalScale = useCallback((() => {
|
|
1179
|
+
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return "scale(1)";
|
|
1180
|
+
const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
1181
|
+
x: edgeDistanceX,
|
|
1182
|
+
y: edgeDistanceY
|
|
1183
|
+
}, {
|
|
1184
|
+
x: 0,
|
|
1185
|
+
y: 0
|
|
1186
|
+
});
|
|
1187
|
+
if (edgeDistance > CONSTANTS.ACTIVATION_ZONE) return "scale(1)";
|
|
1188
|
+
const fadeInFactor = 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE, centerDistance = calculateDistance(globalMousePosition, center);
|
|
1189
|
+
if (0 === centerDistance) return "scale(1)";
|
|
1190
|
+
const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * fadeInFactor, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15;
|
|
1191
|
+
return `scaleX(${Math.max(.8, scaleX)}) scaleY(${Math.max(.8, scaleY)})`;
|
|
1192
|
+
}), [ globalMousePosition, elasticity, glassSize, glassRef ]), calculateFadeInFactor = useCallback((() => {
|
|
1193
|
+
if (!(globalMousePosition.x && globalMousePosition.y && glassRef.current && validateGlassSize(glassSize))) return 0;
|
|
1194
|
+
const rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), edgeDistanceX = Math.max(0, Math.abs(globalMousePosition.x - center.x) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(globalMousePosition.y - center.y) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
1195
|
+
x: edgeDistanceX,
|
|
1196
|
+
y: edgeDistanceY
|
|
1197
|
+
}, {
|
|
1198
|
+
x: 0,
|
|
1199
|
+
y: 0
|
|
1200
|
+
});
|
|
1201
|
+
return edgeDistance > CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / CONSTANTS.ACTIVATION_ZONE;
|
|
1202
|
+
}), [ globalMousePosition, glassSize, glassRef ]), calculateElasticTranslation = useCallback((() => {
|
|
1203
|
+
if (!glassRef.current) return {
|
|
1204
|
+
x: 0,
|
|
1205
|
+
y: 0
|
|
1206
|
+
};
|
|
1207
|
+
const fadeInFactor = calculateFadeInFactor(), rect = glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect);
|
|
1208
|
+
return {
|
|
1209
|
+
x: (globalMousePosition.x - center.x) * elasticity * .1 * fadeInFactor,
|
|
1210
|
+
y: (globalMousePosition.y - center.y) * elasticity * .1 * fadeInFactor
|
|
1211
|
+
};
|
|
1212
|
+
}), [ globalMousePosition, elasticity, calculateFadeInFactor, glassRef ]), elasticTranslation = useMemo((() => effectiveDisableEffects ? {
|
|
1213
|
+
x: 0,
|
|
1214
|
+
y: 0
|
|
1215
|
+
} : calculateElasticTranslation()), [ calculateElasticTranslation, effectiveDisableEffects ]), directionalScale = useMemo((() => effectiveDisableEffects ? "scale(1)" : calculateDirectionalScale()), [ calculateDirectionalScale, effectiveDisableEffects ]), transformStyle = useMemo((() => effectiveDisableEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : directionalScale}`), [ elasticTranslation, isActive, onClick, directionalScale, effectiveDisableEffects ]);
|
|
1216
|
+
// Size management
|
|
1217
|
+
useEffect((() => {
|
|
1218
|
+
const isValidElement = element => null !== element && element instanceof HTMLElement && element.isConnected;
|
|
1219
|
+
let rafId = null, lastSize = {
|
|
1220
|
+
width: 0,
|
|
1221
|
+
height: 0
|
|
1222
|
+
}, lastCornerRadius = effectiveCornerRadius;
|
|
1223
|
+
const updateGlassSize = (forceUpdate = !1) => {
|
|
1224
|
+
null !== rafId && cancelAnimationFrame(rafId), rafId = requestAnimationFrame((() => {
|
|
1225
|
+
if (!isValidElement(glassRef.current)) return void (rafId = null);
|
|
1226
|
+
const rect = glassRef.current.getBoundingClientRect();
|
|
1227
|
+
if (rect.width <= 0 || rect.height <= 0) return void (rafId = null);
|
|
1228
|
+
// Measure actual rendered size without artificial offsets to avoid feedback loops
|
|
1229
|
+
const newSize = {
|
|
1230
|
+
width: Math.round(rect.width),
|
|
1231
|
+
height: Math.round(rect.height)
|
|
1232
|
+
}, cornerRadiusChanged = lastCornerRadius !== effectiveCornerRadius, dimensionsChanged = Math.abs(newSize.width - lastSize.width) > 1 || Math.abs(newSize.height - lastSize.height) > 1;
|
|
1233
|
+
var size;
|
|
1234
|
+
(forceUpdate || cornerRadiusChanged || dimensionsChanged) && validateGlassSize(size = newSize) && size.width <= CONSTANTS.MAX_SIZE && size.height <= CONSTANTS.MAX_SIZE && (lastSize = newSize,
|
|
1235
|
+
lastCornerRadius = effectiveCornerRadius, setGlassSize(newSize)), rafId = null;
|
|
1236
|
+
}));
|
|
1237
|
+
};
|
|
1238
|
+
let resizeTimeoutId = null;
|
|
1239
|
+
const debouncedResizeHandler = () => {
|
|
1240
|
+
resizeTimeoutId && clearTimeout(resizeTimeoutId), resizeTimeoutId = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1241
|
+
}, initialTimeoutId = setTimeout((() => updateGlassSize(!0)), 0);
|
|
1242
|
+
let resizeObserver = null, resizeDebounceTimeout = null;
|
|
1243
|
+
// ResizeObserver has 98%+ browser support, no need for fallback
|
|
1244
|
+
if ("undefined" != typeof ResizeObserver && isValidElement(glassRef.current)) try {
|
|
1245
|
+
resizeObserver = new ResizeObserver((entries => {
|
|
1246
|
+
for (const entry of entries) if (entry.target === glassRef.current) {
|
|
1247
|
+
// Update cached rect when size changes
|
|
1248
|
+
glassRef.current && (cachedRectRef.current = glassRef.current.getBoundingClientRect()),
|
|
1249
|
+
// Debounce resize updates to match RAF timing (16ms)
|
|
1250
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), resizeDebounceTimeout = setTimeout((() => updateGlassSize(!1)), 16);
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
})), resizeObserver.observe(glassRef.current);
|
|
1254
|
+
} catch (error) {
|
|
1255
|
+
console.warn("AtomixGlass: ResizeObserver not available, using window resize only", error);
|
|
1256
|
+
}
|
|
1257
|
+
return window.addEventListener("resize", debouncedResizeHandler, {
|
|
1258
|
+
passive: !0
|
|
1259
|
+
}), () => {
|
|
1260
|
+
clearTimeout(initialTimeoutId), null !== rafId && cancelAnimationFrame(rafId), resizeTimeoutId && clearTimeout(resizeTimeoutId),
|
|
1261
|
+
resizeDebounceTimeout && clearTimeout(resizeDebounceTimeout), window.removeEventListener("resize", debouncedResizeHandler),
|
|
1262
|
+
resizeObserver?.disconnect();
|
|
1263
|
+
};
|
|
1264
|
+
}), [ effectiveCornerRadius, glassRef ]);
|
|
1265
|
+
// OverLight config
|
|
1266
|
+
/**
|
|
1267
|
+
* Get effective overLight value based on configuration
|
|
1268
|
+
* - boolean: returns the boolean value directly
|
|
1269
|
+
* - 'auto': returns detectedOverLight (auto-detected from background)
|
|
1270
|
+
* - object: returns detectedOverLight (auto-detected, but config object provides customization)
|
|
1271
|
+
*/
|
|
1272
|
+
const getEffectiveOverLight = useCallback((() => "boolean" == typeof overLight ? overLight : ("auto" === overLight || "object" == typeof overLight && null !== overLight) && detectedOverLight), [ overLight, detectedOverLight ]), validateConfigValue = useCallback(((value, min, max, defaultValue) => "number" != typeof value || isNaN(value) || !isFinite(value) ? defaultValue : Math.min(max, Math.max(min, value))), []), overLightConfig = useMemo((() => {
|
|
1273
|
+
const isOverLight = getEffectiveOverLight(), mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, baseConfig = {
|
|
1274
|
+
isOverLight: isOverLight,
|
|
1275
|
+
threshold: .7,
|
|
1276
|
+
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
1277
|
+
contrast: Math.min(1.8, Math.max(1, 1.4 + .3 * mouseInfluence)),
|
|
1278
|
+
brightness: Math.min(1.2, Math.max(.7, .85 + .15 * mouseInfluence)),
|
|
1279
|
+
saturationBoost: Math.min(2, Math.max(1, 1.3 + .4 * mouseInfluence)),
|
|
1280
|
+
shadowIntensity: Math.min(1.5, Math.max(.5, .9 + .5 * mouseInfluence)),
|
|
1281
|
+
borderOpacity: Math.min(1, Math.max(.3, .7 + .3 * mouseInfluence))
|
|
1282
|
+
};
|
|
1283
|
+
if ("object" == typeof overLight && null !== overLight) {
|
|
1284
|
+
const objConfig = overLight, validatedThreshold = validateConfigValue(objConfig.threshold, .1, 1, baseConfig.threshold), validatedOpacity = validateConfigValue(objConfig.opacity, .1, 1, baseConfig.opacity), validatedContrast = validateConfigValue(objConfig.contrast, .5, 2.5, baseConfig.contrast), validatedBrightness = validateConfigValue(objConfig.brightness, .5, 2, baseConfig.brightness), validatedSaturationBoost = validateConfigValue(objConfig.saturationBoost, .5, 3, baseConfig.saturationBoost), finalConfig = {
|
|
1285
|
+
...baseConfig,
|
|
1286
|
+
threshold: validatedThreshold,
|
|
1287
|
+
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
1288
|
+
contrast: validatedContrast + .3 * mouseInfluence,
|
|
1289
|
+
brightness: validatedBrightness + .15 * mouseInfluence,
|
|
1290
|
+
saturationBoost: validatedSaturationBoost + .4 * mouseInfluence
|
|
1291
|
+
};
|
|
1292
|
+
// Validate and apply object config values with proper clamping
|
|
1293
|
+
return process.env.NODE_ENV, finalConfig;
|
|
1294
|
+
}
|
|
1295
|
+
// Debug logging for non-object configs
|
|
1296
|
+
return process.env.NODE_ENV, baseConfig;
|
|
1297
|
+
}), [ overLight, getEffectiveOverLight, mouseOffset, isHovered, isActive, validateConfigValue, debugOverLight ]), handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
|
|
1298
|
+
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
1299
|
+
}), [ onClick ]), handleMouseMove = useCallback((_e => {}), []);
|
|
1300
|
+
/**
|
|
1301
|
+
* Validate and clamp a numeric config value
|
|
1302
|
+
* @param value - The value to validate
|
|
1303
|
+
* @param min - Minimum allowed value
|
|
1304
|
+
* @param max - Maximum allowed value
|
|
1305
|
+
* @param defaultValue - Default value if validation fails
|
|
1306
|
+
* @returns Validated and clamped value
|
|
1307
|
+
*/ return {
|
|
1308
|
+
// State
|
|
1309
|
+
isHovered: isHovered,
|
|
1310
|
+
isActive: isActive,
|
|
1311
|
+
glassSize: glassSize,
|
|
1312
|
+
dynamicCornerRadius: dynamicCornerRadius,
|
|
1313
|
+
effectiveCornerRadius: effectiveCornerRadius,
|
|
1314
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1315
|
+
effectiveHighContrast: effectiveHighContrast,
|
|
1316
|
+
effectiveDisableEffects: effectiveDisableEffects,
|
|
1317
|
+
detectedOverLight: detectedOverLight,
|
|
1318
|
+
globalMousePosition: globalMousePosition,
|
|
1319
|
+
mouseOffset: mouseOffset,
|
|
1320
|
+
// OverLight config
|
|
1321
|
+
overLightConfig: overLightConfig,
|
|
1322
|
+
// Transform calculations
|
|
1323
|
+
elasticTranslation: elasticTranslation,
|
|
1324
|
+
directionalScale: directionalScale,
|
|
1325
|
+
transformStyle: transformStyle,
|
|
1326
|
+
// Event handlers
|
|
1327
|
+
handleMouseEnter: handleMouseEnter,
|
|
1328
|
+
handleMouseLeave: handleMouseLeave,
|
|
1329
|
+
handleMouseDown: handleMouseDown,
|
|
1330
|
+
handleMouseUp: handleMouseUp,
|
|
1331
|
+
handleMouseMove: handleMouseMove,
|
|
1332
|
+
handleKeyDown: handleKeyDown
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
/**
|
|
1337
|
+
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
1338
|
+
*
|
|
1339
|
+
* Features:
|
|
1340
|
+
* - Hardware-accelerated glass effects with SVG filters
|
|
1341
|
+
* - Mouse-responsive liquid distortion
|
|
1342
|
+
* - Dynamic border-radius extraction from children CSS properties
|
|
1343
|
+
* - Automatic light/dark theme detection via overLight prop
|
|
1344
|
+
* - Accessibility and performance optimizations
|
|
1345
|
+
* - Multiple displacement modes (standard, polar, prominent, shader)
|
|
1346
|
+
* - Design token integration for consistent theming
|
|
1347
|
+
* - Focus ring support for keyboard navigation
|
|
1348
|
+
* - Responsive breakpoints for mobile optimization
|
|
1349
|
+
* - Enhanced ARIA attributes for screen readers
|
|
1350
|
+
*
|
|
1351
|
+
* Design System Compliance:
|
|
1352
|
+
* - Uses design tokens for opacity, spacing, and colors
|
|
1353
|
+
* - Follows BEM methodology for class naming
|
|
1354
|
+
* - Implements focus-ring mixin for accessibility
|
|
1355
|
+
* - Supports reduced motion and high contrast preferences
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* // Basic usage with dynamic border-radius extraction
|
|
1359
|
+
* <AtomixGlass>
|
|
1360
|
+
* <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
|
|
1361
|
+
* </AtomixGlass>
|
|
1362
|
+
*
|
|
1363
|
+
* @example
|
|
1364
|
+
* // Manual border-radius override
|
|
1365
|
+
* <AtomixGlass cornerRadius={20}>
|
|
1366
|
+
* <div>Content with 20px glass radius</div>
|
|
1367
|
+
* </AtomixGlass>
|
|
1368
|
+
*
|
|
1369
|
+
* @example
|
|
1370
|
+
* // Interactive glass with click handler
|
|
1371
|
+
* <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
|
|
1372
|
+
* <div>Clickable content</div>
|
|
1373
|
+
* </AtomixGlass>
|
|
1374
|
+
*
|
|
1375
|
+
* @example
|
|
1376
|
+
* // OverLight - Boolean mode (explicit control)
|
|
1377
|
+
* <AtomixGlass overLight={true}>
|
|
1378
|
+
* <div>Content on light background</div>
|
|
1379
|
+
* </AtomixGlass>
|
|
1380
|
+
*
|
|
1381
|
+
* @example
|
|
1382
|
+
* // OverLight - Auto-detection mode
|
|
1383
|
+
* <AtomixGlass overLight="auto">
|
|
1384
|
+
* <div>Content with auto-detected background</div>
|
|
1385
|
+
* </AtomixGlass>
|
|
1386
|
+
*
|
|
1387
|
+
* @example
|
|
1388
|
+
* // OverLight - Object config with custom settings
|
|
1389
|
+
* <AtomixGlass
|
|
1390
|
+
* overLight={{
|
|
1391
|
+
* threshold: 0.8,
|
|
1392
|
+
* opacity: 0.6,
|
|
1393
|
+
* contrast: 1.8,
|
|
1394
|
+
* brightness: 1.0,
|
|
1395
|
+
* saturationBoost: 1.5
|
|
1396
|
+
* }}
|
|
1397
|
+
* >
|
|
1398
|
+
* <div>Content with custom overLight config</div>
|
|
1399
|
+
* </AtomixGlass>
|
|
1400
|
+
*
|
|
1401
|
+
* @example
|
|
1402
|
+
* // Debug mode for overLight detection
|
|
1403
|
+
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
1404
|
+
* <div>Content with debug logging enabled</div>
|
|
1405
|
+
* </AtomixGlass>
|
|
1406
|
+
*/ function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, cornerRadius: cornerRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, disableEffects: disableEffects = !1, enableLiquidBlur: enableLiquidBlur = !1, enableBorderEffect: enableBorderEffect = !0, enableOverLightLayers: enableOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, enablePerformanceMonitoring: enablePerformanceMonitoring = !1, debugCornerRadius: debugCornerRadius = !1, debugOverLight: debugOverLight = !1}) {
|
|
1407
|
+
const glassRef = useRef(null), contentRef = useRef(null), opacityCacheRef = useRef(null), {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveCornerRadius: effectiveCornerRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveDisableEffects: effectiveDisableEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
1408
|
+
glassRef: glassRef,
|
|
1409
|
+
contentRef: contentRef,
|
|
1410
|
+
cornerRadius: cornerRadius,
|
|
1411
|
+
globalMousePosition: externalGlobalMousePosition,
|
|
1412
|
+
mouseOffset: externalMouseOffset,
|
|
1413
|
+
mouseContainer: mouseContainer,
|
|
1414
|
+
overLight: overLight,
|
|
1415
|
+
reducedMotion: reducedMotion,
|
|
1416
|
+
highContrast: highContrast,
|
|
1417
|
+
disableEffects: disableEffects,
|
|
1418
|
+
elasticity: elasticity,
|
|
1419
|
+
onClick: onClick,
|
|
1420
|
+
debugCornerRadius: debugCornerRadius,
|
|
1421
|
+
debugOverLight: debugOverLight,
|
|
1422
|
+
enablePerformanceMonitoring: enablePerformanceMonitoring,
|
|
1423
|
+
children: children
|
|
1424
|
+
}), isOverLight = overLightConfig.isOverLight, shouldRenderOverLightLayers = enableOverLightLayers && isOverLight;
|
|
1425
|
+
// Read CSS custom properties once on mount and cache them
|
|
1426
|
+
useEffect((() => {
|
|
1427
|
+
if ("undefined" != typeof window && glassRef.current && !opacityCacheRef.current) try {
|
|
1428
|
+
const computedStyle = window.getComputedStyle(glassRef.current), opacity50Value = computedStyle.getPropertyValue("--atomix-opacity-50").trim(), opacity40Value = computedStyle.getPropertyValue("--atomix-opacity-40").trim(), opacity80Value = computedStyle.getPropertyValue("--atomix-opacity-80").trim(), opacity0Value = computedStyle.getPropertyValue("--atomix-opacity-0").trim(), parseOpacity = (value, defaultValue) => {
|
|
1429
|
+
if (!value) return defaultValue;
|
|
1430
|
+
const parsed = parseFloat(value);
|
|
1431
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
1432
|
+
};
|
|
1433
|
+
opacityCacheRef.current = {
|
|
1434
|
+
opacity50: parseOpacity(opacity50Value, .5),
|
|
1435
|
+
opacity40: parseOpacity(opacity40Value, .4),
|
|
1436
|
+
opacity80: parseOpacity(opacity80Value, .8),
|
|
1437
|
+
opacity0: parseOpacity(opacity0Value, 0)
|
|
1438
|
+
};
|
|
1439
|
+
} catch (error) {
|
|
1440
|
+
// Fallback to defaults if reading fails
|
|
1441
|
+
opacityCacheRef.current = {
|
|
1442
|
+
opacity50: .5,
|
|
1443
|
+
opacity40: .4,
|
|
1444
|
+
opacity80: .8,
|
|
1445
|
+
opacity0: 0
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
}), []);
|
|
1449
|
+
// Calculate base style with transforms (only dynamic values)
|
|
1450
|
+
const baseStyle = useMemo((() => ({
|
|
1451
|
+
...style,
|
|
1452
|
+
...0 !== elasticity && !effectiveDisableEffects && {
|
|
1453
|
+
transform: transformStyle
|
|
1454
|
+
}
|
|
1455
|
+
})), [ style, transformStyle, effectiveDisableEffects, elasticity ]), componentClassName = useMemo((() => [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveDisableEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" ")), [ effectiveReducedMotion, effectiveHighContrast, effectiveDisableEffects, className ]), baseStylePosition = baseStyle.position, baseStyleTop = baseStyle.top, baseStyleLeft = baseStyle.left, positionStyles = useMemo((() => ({
|
|
1456
|
+
position: baseStylePosition || "absolute",
|
|
1457
|
+
top: baseStyleTop || 0,
|
|
1458
|
+
left: baseStyleLeft || 0
|
|
1459
|
+
})), [ baseStylePosition, baseStyleTop, baseStyleLeft ]), baseStyleWidth = baseStyle.width, baseStyleHeight = baseStyle.height, glassSizeWidth = glassSize.width, glassSizeHeight = glassSize.height, adjustedSize = useMemo((() => ({
|
|
1460
|
+
width: "fixed" !== baseStylePosition ? "100%" : baseStyleWidth || Math.max(glassSizeWidth, 0),
|
|
1461
|
+
height: "fixed" !== baseStylePosition ? "100%" : baseStyleHeight || Math.max(glassSizeHeight, 0)
|
|
1462
|
+
})), [ baseStylePosition, baseStyleWidth, baseStyleHeight, glassSizeWidth, glassSizeHeight ]), mouseOffsetX = mouseOffset.x, mouseOffsetY = mouseOffset.y, GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, gradientCalculations = useMemo((() => {
|
|
1463
|
+
const mx = mouseOffsetX, my = mouseOffsetY, borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), borderOpacity1 = GRADIENT.BORDER_OPACITY.BASE_1 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, borderOpacity2 = GRADIENT.BORDER_OPACITY.BASE_2 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, borderOpacity3 = GRADIENT.BORDER_OPACITY.BASE_3 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, borderOpacity4 = GRADIENT.BORDER_OPACITY.BASE_4 + Math.abs(mx) * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, hover1X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1, hover1Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1, hover2X = GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_2, hover2Y = GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_2, hover3X = GRADIENT.CENTER_POSITION + mx * GRADIENT.HOVER_POSITION.MULTIPLIER_3, hover3Y = GRADIENT.CENTER_POSITION + my * GRADIENT.HOVER_POSITION.MULTIPLIER_3, baseX = GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER, baseY = GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER;
|
|
1464
|
+
return {
|
|
1465
|
+
isOverLight: isOverLight,
|
|
1466
|
+
mx: mx,
|
|
1467
|
+
my: my,
|
|
1468
|
+
borderGradientAngle: borderGradientAngle,
|
|
1469
|
+
borderStop1: borderStop1,
|
|
1470
|
+
borderStop2: borderStop2,
|
|
1471
|
+
borderOpacity1: borderOpacity1,
|
|
1472
|
+
borderOpacity2: borderOpacity2,
|
|
1473
|
+
borderOpacity3: borderOpacity3,
|
|
1474
|
+
borderOpacity4: borderOpacity4,
|
|
1475
|
+
hover1X: hover1X,
|
|
1476
|
+
hover1Y: hover1Y,
|
|
1477
|
+
hover2X: hover2X,
|
|
1478
|
+
hover2Y: hover2Y,
|
|
1479
|
+
hover3X: hover3X,
|
|
1480
|
+
hover3Y: hover3Y,
|
|
1481
|
+
baseX: baseX,
|
|
1482
|
+
baseY: baseY
|
|
1483
|
+
};
|
|
1484
|
+
}), [ mouseOffsetX, mouseOffsetY, isOverLight ]), overLightOpacity = overLightConfig.opacity, opacityValues = useMemo((() => {
|
|
1485
|
+
// Use cached values if available, otherwise fallback to defaults
|
|
1486
|
+
const opacity50 = opacityCacheRef.current?.opacity50 ?? .5, opacity40 = opacityCacheRef.current?.opacity40 ?? .4, opacity80 = opacityCacheRef.current?.opacity80 ?? .8, opacity0 = opacityCacheRef.current?.opacity0 ?? 0;
|
|
1487
|
+
// Dynamic multiplier for overlay
|
|
1488
|
+
return {
|
|
1489
|
+
hover1: isHovered || isActive ? opacity50 : opacity0,
|
|
1490
|
+
hover2: isActive ? opacity50 : opacity0,
|
|
1491
|
+
hover3: isHovered ? opacity40 : isActive ? opacity80 : opacity0,
|
|
1492
|
+
base: isOverLight ? overLightOpacity || opacity40 : opacity0,
|
|
1493
|
+
over: isOverLight ? 1.1 * (overLightOpacity || opacity40) : opacity0
|
|
1494
|
+
};
|
|
1495
|
+
}), [ isHovered, isActive, isOverLight, overLightOpacity ]), gradientIsOverLight = gradientCalculations.isOverLight, gradientMx = gradientCalculations.mx, gradientMy = gradientCalculations.my, gradientBorderGradientAngle = gradientCalculations.borderGradientAngle, gradientBorderStop1 = gradientCalculations.borderStop1, gradientBorderStop2 = gradientCalculations.borderStop2, gradientBorderOpacity1 = gradientCalculations.borderOpacity1, gradientBorderOpacity2 = gradientCalculations.borderOpacity2, gradientBorderOpacity3 = gradientCalculations.borderOpacity3, gradientBorderOpacity4 = gradientCalculations.borderOpacity4, gradientHover1X = gradientCalculations.hover1X, gradientHover1Y = gradientCalculations.hover1Y, gradientHover2X = gradientCalculations.hover2X, gradientHover2Y = gradientCalculations.hover2Y, gradientHover3X = gradientCalculations.hover3X, gradientHover3Y = gradientCalculations.hover3Y, gradientBaseX = gradientCalculations.baseX, gradientBaseY = gradientCalculations.baseY, positionStylesPosition = positionStyles.position, positionStylesTop = positionStyles.top, positionStylesLeft = positionStyles.left, adjustedSizeWidth = adjustedSize.width, adjustedSizeHeight = adjustedSize.height, baseStyleTransform = baseStyle.transform, opacityValuesHover1 = opacityValues.hover1, opacityValuesHover2 = opacityValues.hover2, opacityValuesHover3 = opacityValues.hover3, opacityValuesBase = opacityValues.base, opacityValuesOver = opacityValues.over, glassVars = useMemo((() => {
|
|
1496
|
+
// RGB color values for rgba() functions
|
|
1497
|
+
// Note: CSS doesn't support rgba(var(--rgb), opacity) syntax, so we use direct values
|
|
1498
|
+
// These values align with design tokens: --atomix-white-rgb and --atomix-black-rgb
|
|
1499
|
+
// The actual RGB values are defined in SCSS and should match these fallbacks
|
|
1500
|
+
// TODO: Consider reading from CSS custom properties if browser support improves
|
|
1501
|
+
const whiteColor = "255, 255, 255";
|
|
1502
|
+
// Matches --atomix-white-rgb design token
|
|
1503
|
+
// Matches --atomix-black-rgb design token
|
|
1504
|
+
return {
|
|
1505
|
+
// Standard CSS custom properties for dynamic values
|
|
1506
|
+
"--atomix-glass-radius": `${effectiveCornerRadius}px`,
|
|
1507
|
+
"--atomix-glass-transform": baseStyleTransform || "none",
|
|
1508
|
+
"--atomix-glass-position": positionStylesPosition,
|
|
1509
|
+
"--atomix-glass-top": "fixed" !== positionStylesTop ? `${positionStylesTop}px` : "0",
|
|
1510
|
+
"--atomix-glass-left": "fixed" !== positionStylesLeft ? `${positionStylesLeft}px` : "0",
|
|
1511
|
+
"--atomix-glass-width": "fixed" !== baseStylePosition ? adjustedSizeWidth : `${adjustedSizeWidth}px`,
|
|
1512
|
+
"--atomix-glass-height": "fixed" !== baseStylePosition ? adjustedSizeHeight : `${adjustedSizeHeight}px`,
|
|
1513
|
+
// Border width: Use spacing token for consistency
|
|
1514
|
+
"--atomix-glass-border-width": "var(--atomix-spacing-0-5, 0.09375rem)",
|
|
1515
|
+
"--atomix-glass-blend-mode": gradientIsOverLight ? "multiply" : "overlay",
|
|
1516
|
+
// Dynamic gradients and backgrounds
|
|
1517
|
+
// Note: RGB values use design token-aligned constants (white: 255,255,255; black: 0,0,0)
|
|
1518
|
+
"--atomix-glass-border-gradient-1": `linear-gradient(${gradientBorderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${gradientBorderOpacity1}) ${gradientBorderStop1}%, rgba(${whiteColor}, ${gradientBorderOpacity2}) ${gradientBorderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
1519
|
+
"--atomix-glass-border-gradient-2": `linear-gradient(${gradientBorderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${gradientBorderOpacity3}) ${gradientBorderStop1}%, rgba(${whiteColor}, ${gradientBorderOpacity4}) ${gradientBorderStop2}%, rgba(${whiteColor}, 0) 100%)`,
|
|
1520
|
+
"--atomix-glass-hover-1-opacity": opacityValuesHover1,
|
|
1521
|
+
"--atomix-glass-hover-1-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientHover1X}% ${gradientHover1Y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(0, 0, 0, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${gradientHover1X}% ${gradientHover1Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`,
|
|
1522
|
+
"--atomix-glass-hover-2-opacity": opacityValuesHover2,
|
|
1523
|
+
"--atomix-glass-hover-2-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientHover2X}% ${gradientHover2Y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(0, 0, 0, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${gradientHover2X}% ${gradientHover2Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`,
|
|
1524
|
+
"--atomix-glass-hover-3-opacity": opacityValuesHover3,
|
|
1525
|
+
"--atomix-glass-hover-3-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientHover3X}% ${gradientHover3Y}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_START}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_STOP}%, rgba(0, 0, 0, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.BLACK_END}%)` : `radial-gradient(circle at ${gradientHover3X}% ${gradientHover3Y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_3.WHITE_STOP}%)`,
|
|
1526
|
+
"--atomix-glass-base-opacity": opacityValuesBase,
|
|
1527
|
+
"--atomix-glass-base-gradient": gradientIsOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + gradientMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + gradientMy * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + Math.abs(gradientMx) * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.WHITE_OPACITY})`,
|
|
1528
|
+
"--atomix-glass-overlay-opacity": opacityValuesOver,
|
|
1529
|
+
"--atomix-glass-overlay-gradient": gradientIsOverLight ? `radial-gradient(circle at ${gradientBaseX}% ${gradientBaseY}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + Math.abs(gradientMx) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(0, 0, 0, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + Math.abs(gradientMy) * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`
|
|
1530
|
+
};
|
|
1531
|
+
}), [
|
|
1532
|
+
// Position styles - only specific properties
|
|
1533
|
+
positionStylesPosition, positionStylesTop, positionStylesLeft,
|
|
1534
|
+
// Adjusted size - only specific properties
|
|
1535
|
+
adjustedSizeWidth, adjustedSizeHeight,
|
|
1536
|
+
// Base style - only transform property
|
|
1537
|
+
baseStyleTransform, baseStylePosition,
|
|
1538
|
+
// Other values
|
|
1539
|
+
effectiveCornerRadius, effectiveReducedMotion,
|
|
1540
|
+
// Gradient calculations - extracted properties
|
|
1541
|
+
gradientIsOverLight, gradientMx, gradientMy, gradientBorderGradientAngle, gradientBorderStop1, gradientBorderStop2, gradientBorderOpacity1, gradientBorderOpacity2, gradientBorderOpacity3, gradientBorderOpacity4, gradientHover1X, gradientHover1Y, gradientHover2X, gradientHover2Y, gradientHover3X, gradientHover3Y, gradientBaseX, gradientBaseY,
|
|
1542
|
+
// Opacity values - extracted properties
|
|
1543
|
+
opacityValuesHover1, opacityValuesHover2, opacityValuesHover3, opacityValuesBase, opacityValuesOver ]);
|
|
1544
|
+
// Build className with state modifiers
|
|
1545
|
+
return jsxs("div", {
|
|
1546
|
+
className: componentClassName,
|
|
1547
|
+
style: glassVars,
|
|
1548
|
+
role: role || (onClick ? "button" : void 0),
|
|
1549
|
+
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
1550
|
+
"aria-label": ariaLabel,
|
|
1551
|
+
"aria-describedby": ariaDescribedBy,
|
|
1552
|
+
"aria-disabled": !(!onClick || !effectiveDisableEffects) || !onClick && void 0,
|
|
1553
|
+
"aria-pressed": !(!onClick || !isActive) || !onClick && void 0,
|
|
1554
|
+
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
1555
|
+
children: [ jsx(AtomixGlassContainer, {
|
|
1556
|
+
ref: glassRef,
|
|
1557
|
+
contentRef: contentRef,
|
|
1558
|
+
className: className,
|
|
1559
|
+
style: baseStyle,
|
|
1560
|
+
cornerRadius: effectiveCornerRadius,
|
|
1561
|
+
displacementScale: effectiveDisableEffects ? 0 : "shader" === mode ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT : overLightConfig.isOverLight ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT : displacementScale,
|
|
1562
|
+
blurAmount: effectiveDisableEffects ? 0 : blurAmount,
|
|
1563
|
+
saturation: effectiveHighContrast ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST : overLightConfig.isOverLight ? saturation * overLightConfig.saturationBoost : saturation,
|
|
1564
|
+
aberrationIntensity: effectiveDisableEffects ? 0 : "shader" === mode ? aberrationIntensity * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_ABERRATION : aberrationIntensity,
|
|
1565
|
+
glassSize: glassSize,
|
|
1566
|
+
padding: padding,
|
|
1567
|
+
mouseOffset: effectiveDisableEffects ? {
|
|
1568
|
+
x: 0,
|
|
1569
|
+
y: 0
|
|
1570
|
+
} : mouseOffset,
|
|
1571
|
+
globalMousePosition: effectiveDisableEffects ? {
|
|
1572
|
+
x: 0,
|
|
1573
|
+
y: 0
|
|
1574
|
+
} : globalMousePosition,
|
|
1575
|
+
onMouseEnter: handleMouseEnter,
|
|
1576
|
+
onMouseLeave: handleMouseLeave,
|
|
1577
|
+
onMouseDown: handleMouseDown,
|
|
1578
|
+
onMouseUp: handleMouseUp,
|
|
1579
|
+
active: isActive,
|
|
1580
|
+
isHovered: isHovered,
|
|
1581
|
+
isActive: isActive,
|
|
1582
|
+
overLight: overLightConfig.isOverLight,
|
|
1583
|
+
onClick: onClick,
|
|
1584
|
+
mode: mode,
|
|
1585
|
+
transform: baseStyle.transform,
|
|
1586
|
+
effectiveDisableEffects: effectiveDisableEffects,
|
|
1587
|
+
effectiveReducedMotion: effectiveReducedMotion,
|
|
1588
|
+
shaderVariant: shaderVariant,
|
|
1589
|
+
elasticity: elasticity,
|
|
1590
|
+
enableLiquidBlur: enableLiquidBlur,
|
|
1591
|
+
children: children
|
|
1592
|
+
}), Boolean(onClick) && jsxs(Fragment, {
|
|
1593
|
+
children: [ jsx("div", {
|
|
1594
|
+
className: ATOMIX_GLASS.HOVER_1_CLASS
|
|
1595
|
+
}), jsx("div", {
|
|
1596
|
+
className: ATOMIX_GLASS.HOVER_2_CLASS
|
|
1597
|
+
}), jsx("div", {
|
|
1598
|
+
className: ATOMIX_GLASS.HOVER_3_CLASS
|
|
1599
|
+
}) ]
|
|
1600
|
+
}), jsx("div", {
|
|
1601
|
+
className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
|
|
1602
|
+
style: {
|
|
1603
|
+
...positionStyles,
|
|
1604
|
+
height: adjustedSize.height,
|
|
1605
|
+
width: adjustedSize.width,
|
|
1606
|
+
borderRadius: `${effectiveCornerRadius}px`,
|
|
1607
|
+
transform: baseStyle.transform
|
|
1608
|
+
}
|
|
1609
|
+
}), jsx("div", {
|
|
1610
|
+
className: [ ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS ].filter(Boolean).join(" "),
|
|
1611
|
+
style: {
|
|
1612
|
+
...positionStyles,
|
|
1613
|
+
height: adjustedSize.height,
|
|
1614
|
+
width: adjustedSize.width,
|
|
1615
|
+
borderRadius: `${effectiveCornerRadius}px`,
|
|
1616
|
+
transform: baseStyle.transform
|
|
1617
|
+
}
|
|
1618
|
+
}), shouldRenderOverLightLayers && jsxs(Fragment, {
|
|
1619
|
+
children: [ jsx("div", {
|
|
1620
|
+
className: ATOMIX_GLASS.BASE_LAYER_CLASS
|
|
1621
|
+
}), jsx("div", {
|
|
1622
|
+
className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
|
|
1623
|
+
}), jsx("div", {
|
|
1624
|
+
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS,
|
|
1625
|
+
style: {
|
|
1626
|
+
opacity: opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
|
|
1627
|
+
background: `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`
|
|
1628
|
+
}
|
|
1629
|
+
}) ]
|
|
1630
|
+
}), enableBorderEffect && jsxs(Fragment, {
|
|
1631
|
+
children: [ jsx("span", {
|
|
1632
|
+
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
1633
|
+
}), jsx("span", {
|
|
1634
|
+
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
1635
|
+
}) ]
|
|
1636
|
+
}) ]
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
const Accordion = memo((({title: title, children: children, defaultOpen: defaultOpen = !1, isOpen: controlledOpen, onOpenChange: onOpenChange, disabled: disabled = !1, iconPosition: iconPosition = "right", icon: icon, className: className = "", style: style, glass: glass}) => {
|
|
1641
|
+
// Generate unique IDs for accessibility
|
|
1642
|
+
const instanceId = useId(), buttonId = `accordion-header-${instanceId}`, panelId = `accordion-panel-${instanceId}`, {state: state, toggle: toggle, updatePanelHeight: updatePanelHeight, panelRef: panelRef, contentRef: contentRef, generateClassNames: generateClassNames, generateHeaderClassNames: generateHeaderClassNames} =
|
|
1643
|
+
/**
|
|
1644
|
+
* Accordion functionality hook
|
|
1645
|
+
* @param initialProps - Initial accordion properties
|
|
1646
|
+
* @returns Accordion state and methods
|
|
1647
|
+
*/
|
|
1648
|
+
function(initialProps) {
|
|
1649
|
+
// Default accordion properties
|
|
1650
|
+
const defaultProps = {
|
|
1651
|
+
defaultOpen: !1,
|
|
1652
|
+
disabled: !1,
|
|
1653
|
+
iconPosition: "right",
|
|
1654
|
+
...initialProps
|
|
1655
|
+
}, isControlled = "boolean" == typeof defaultProps.isOpen, [internalOpen, setInternalOpen] = useState(defaultProps.defaultOpen || !1), isOpen = isControlled ? defaultProps.isOpen : internalOpen, [panelHeight, setPanelHeight] = useState(isOpen ? "auto" : "0px"), panelRef = useRef(null), contentRef = useRef(null), updatePanelHeight = () => {
|
|
1656
|
+
if (contentRef.current && panelRef.current) {
|
|
1657
|
+
const height = isOpen ? `${contentRef.current.clientHeight}px` : "0px";
|
|
1658
|
+
panelRef.current.style.setProperty(ACCORDION.CSS_VARS.PANEL_HEIGHT, height), setPanelHeight(height);
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
// Controlled/uncontrolled open state
|
|
1662
|
+
/**
|
|
1663
|
+
* Effect to update panel height when open state changes
|
|
1664
|
+
*/
|
|
1665
|
+
return useEffect((() => {
|
|
1666
|
+
updatePanelHeight();
|
|
1667
|
+
}), [ isOpen ]),
|
|
1668
|
+
/**
|
|
1669
|
+
* Effect to handle window resize and update panel height
|
|
1670
|
+
*/
|
|
1671
|
+
useEffect((() => {
|
|
1672
|
+
const handleResize = () => {
|
|
1673
|
+
isOpen && updatePanelHeight();
|
|
1674
|
+
};
|
|
1675
|
+
return window.addEventListener("resize", handleResize), () => window.removeEventListener("resize", handleResize);
|
|
1676
|
+
}), [ isOpen ]), {
|
|
1677
|
+
state: {
|
|
1678
|
+
isOpen: isOpen,
|
|
1679
|
+
panelHeight: panelHeight
|
|
1680
|
+
},
|
|
1681
|
+
toggle: () => {
|
|
1682
|
+
defaultProps.disabled || (isControlled ? defaultProps.onOpenChange && defaultProps.onOpenChange(!isOpen) : setInternalOpen((prev => !prev)));
|
|
1683
|
+
},
|
|
1684
|
+
updatePanelHeight: updatePanelHeight,
|
|
1685
|
+
panelRef: panelRef,
|
|
1686
|
+
contentRef: contentRef,
|
|
1687
|
+
generateClassNames: (baseClassName = "") => `c-accordion ${isOpen ? ACCORDION.CLASSES.IS_OPEN : ""} ${defaultProps.disabled ? ACCORDION.CLASSES.IS_DISABLED : ""} ${baseClassName}`.trim(),
|
|
1688
|
+
generateHeaderClassNames: () => ("c-accordion__header " + ("left" === defaultProps.iconPosition ? "c-accordion__header--icon-left" : "")).trim()
|
|
1689
|
+
};
|
|
1690
|
+
}({
|
|
1691
|
+
defaultOpen: defaultOpen,
|
|
1692
|
+
disabled: disabled,
|
|
1693
|
+
iconPosition: iconPosition,
|
|
1694
|
+
isOpen: controlledOpen,
|
|
1695
|
+
onOpenChange: onOpenChange
|
|
1696
|
+
}), defaultIcon = jsx("i", {
|
|
1697
|
+
className: "c-accordion__icon",
|
|
1698
|
+
"aria-hidden": "true",
|
|
1699
|
+
children: jsx("svg", {
|
|
1700
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1701
|
+
width: "24",
|
|
1702
|
+
height: "24",
|
|
1703
|
+
viewBox: "0 0 24 24",
|
|
1704
|
+
fill: "none",
|
|
1705
|
+
stroke: "currentColor",
|
|
1706
|
+
strokeWidth: "2",
|
|
1707
|
+
strokeLinecap: "round",
|
|
1708
|
+
strokeLinejoin: "round",
|
|
1709
|
+
"aria-hidden": "true",
|
|
1710
|
+
focusable: "false",
|
|
1711
|
+
children: jsx("polyline", {
|
|
1712
|
+
points: "6 9 12 15 18 9"
|
|
1713
|
+
})
|
|
1714
|
+
})
|
|
1715
|
+
}), accordionContent = jsxs("div", {
|
|
1716
|
+
className: generateClassNames(className) + (glass ? " c-accordion--glass" : ""),
|
|
1717
|
+
style: style,
|
|
1718
|
+
children: [ jsxs("button", {
|
|
1719
|
+
id: buttonId,
|
|
1720
|
+
className: generateHeaderClassNames(),
|
|
1721
|
+
onClick: toggle,
|
|
1722
|
+
"aria-expanded": state.isOpen,
|
|
1723
|
+
"aria-controls": panelId,
|
|
1724
|
+
"aria-disabled": disabled,
|
|
1725
|
+
disabled: disabled,
|
|
1726
|
+
type: "button",
|
|
1727
|
+
children: [ jsx("span", {
|
|
1728
|
+
className: "c-accordion__title",
|
|
1729
|
+
children: title
|
|
1730
|
+
}), icon || defaultIcon ]
|
|
1731
|
+
}), jsx("div", {
|
|
1732
|
+
id: panelId,
|
|
1733
|
+
className: ACCORDION.SELECTORS.PANEL.replace(".", ""),
|
|
1734
|
+
ref: panelRef,
|
|
1735
|
+
role: "region",
|
|
1736
|
+
"aria-labelledby": buttonId,
|
|
1737
|
+
children: jsx("div", {
|
|
1738
|
+
className: ACCORDION.SELECTORS.BODY.replace(".", ""),
|
|
1739
|
+
ref: contentRef,
|
|
1740
|
+
children: children
|
|
1741
|
+
})
|
|
1742
|
+
}) ]
|
|
1743
|
+
});
|
|
1744
|
+
if (glass) {
|
|
1745
|
+
// Default glass settings for accordions
|
|
1746
|
+
const defaultGlassProps = {
|
|
1747
|
+
displacementScale: 20,
|
|
1748
|
+
elasticity: 0
|
|
1749
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
1750
|
+
...defaultGlassProps,
|
|
1751
|
+
...glass
|
|
1752
|
+
};
|
|
1753
|
+
return jsx(AtomixGlass, {
|
|
1754
|
+
...glassProps,
|
|
1755
|
+
children: accordionContent
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
return accordionContent;
|
|
1759
|
+
}));
|
|
1760
|
+
|
|
1761
|
+
// Set display name for debugging
|
|
1762
|
+
Accordion.displayName = "Accordion";
|
|
1763
|
+
|
|
1764
|
+
const Badge = memo((({label: label, variant: variant = "primary", size: size = "md", disabled: disabled = !1, icon: icon, className: className = "", glass: glass, style: style}) => {
|
|
1765
|
+
const {generateBadgeClass: generateBadgeClass} =
|
|
1766
|
+
/**
|
|
1767
|
+
* Badge state and functionality
|
|
1768
|
+
* @param initialProps - Initial badge properties
|
|
1769
|
+
* @returns Badge state and methods
|
|
1770
|
+
*/
|
|
1771
|
+
function(initialProps) {
|
|
1772
|
+
// Default badge properties
|
|
1773
|
+
const defaultProps = {
|
|
1774
|
+
variant: "primary",
|
|
1775
|
+
size: "md",
|
|
1776
|
+
disabled: !1,
|
|
1777
|
+
...initialProps
|
|
1778
|
+
};
|
|
1779
|
+
/**
|
|
1780
|
+
* Generate badge class based on properties
|
|
1781
|
+
* @param props - Badge properties
|
|
1782
|
+
* @returns Class string
|
|
1783
|
+
*/ return {
|
|
1784
|
+
defaultProps: defaultProps,
|
|
1785
|
+
generateBadgeClass: props => {
|
|
1786
|
+
const {variant: variant = defaultProps.variant, size: size = defaultProps.size, disabled: disabled = defaultProps.disabled, className: className = ""} = props;
|
|
1787
|
+
return `c-badge ${variant ? `c-badge--${variant}` : ""} ${"md" === size ? "" : `c-badge--${size}`} ${disabled ? "c-badge--disabled" : ""} ${className}`.trim();
|
|
1788
|
+
}
|
|
1789
|
+
};
|
|
1790
|
+
}({
|
|
1791
|
+
variant: variant,
|
|
1792
|
+
size: size,
|
|
1793
|
+
disabled: disabled
|
|
1794
|
+
}), ref = useRef(null), badgeClass = generateBadgeClass({
|
|
1795
|
+
variant: variant,
|
|
1796
|
+
size: size,
|
|
1797
|
+
disabled: disabled,
|
|
1798
|
+
className: `${className} ${glass ? "c-badge--glass" : ""}`.trim()
|
|
1799
|
+
}), badgeElement = jsxs("span", {
|
|
1800
|
+
className: badgeClass,
|
|
1801
|
+
"aria-disabled": disabled,
|
|
1802
|
+
ref: ref,
|
|
1803
|
+
style: style,
|
|
1804
|
+
children: [ icon && jsx("span", {
|
|
1805
|
+
className: "c-badge__icon",
|
|
1806
|
+
children: icon
|
|
1807
|
+
}), jsx("span", {
|
|
1808
|
+
children: label
|
|
1809
|
+
}) ]
|
|
1810
|
+
});
|
|
1811
|
+
if (glass) {
|
|
1812
|
+
// Default glass settings for badges
|
|
1813
|
+
const defaultGlassProps = {
|
|
1814
|
+
displacementScale: 20,
|
|
1815
|
+
cornerRadius: ref.current?.getBoundingClientRect().width ? ref.current?.getBoundingClientRect().width / 2 : 16,
|
|
1816
|
+
className: "c-badge--glass",
|
|
1817
|
+
elasticity: 0
|
|
1818
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
1819
|
+
...defaultGlassProps,
|
|
1820
|
+
...glass
|
|
1821
|
+
};
|
|
1822
|
+
return jsx(AtomixGlass, {
|
|
1823
|
+
...glassProps,
|
|
1824
|
+
children: badgeElement
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
return badgeElement;
|
|
1828
|
+
}));
|
|
1829
|
+
|
|
1830
|
+
Badge.displayName = "Badge";
|
|
1831
|
+
|
|
1832
|
+
/**
|
|
1833
|
+
* Container component for creating responsive layouts.
|
|
1834
|
+
* Uses the CSS container classes defined in _objects.container.scss.
|
|
1835
|
+
*
|
|
1836
|
+
* @example
|
|
1837
|
+
* ```tsx
|
|
1838
|
+
* <Container>
|
|
1839
|
+
* Content with responsive max-width
|
|
1840
|
+
* </Container>
|
|
1841
|
+
*
|
|
1842
|
+
* <Container type="fluid">
|
|
1843
|
+
* Full width content
|
|
1844
|
+
* </Container>
|
|
1845
|
+
*
|
|
1846
|
+
* <Container type="md">
|
|
1847
|
+
* Content with max-width at md breakpoint
|
|
1848
|
+
* </Container>
|
|
1849
|
+
* ```
|
|
1850
|
+
*/
|
|
1851
|
+
const Container = forwardRef((({children: children, className: className = "", type: type, ...props}, ref) => {
|
|
1852
|
+
let containerClass = "o-container";
|
|
1853
|
+
return type && (containerClass = `o-container-${type}`), jsx("div", {
|
|
1854
|
+
ref: ref,
|
|
1855
|
+
className: `${containerClass} ${className}`.trim(),
|
|
1856
|
+
...props,
|
|
1857
|
+
children: children
|
|
1858
|
+
});
|
|
1859
|
+
}));
|
|
1860
|
+
|
|
1861
|
+
Container.displayName = "Container";
|
|
1862
|
+
|
|
1863
|
+
/**
|
|
1864
|
+
* useBlock composable for Block component
|
|
1865
|
+
* Provides utility functions for generating consistent block styling
|
|
1866
|
+
*/
|
|
1867
|
+
const Block = forwardRef((({children: children, as: Component = "section", spacing: spacing = "md", container: container = {}, fullWidth: fullWidth = !1, className: className = "", style: style, background: background = "", ...props}, ref) => {
|
|
1868
|
+
const {generateBlockClass: generateBlockClass} = {
|
|
1869
|
+
generateBlockClass: ({spacing: spacing = BLOCK.SPACING.DEFAULT, background: background = "", fullWidth: fullWidth = !1, className: className = ""}) => {
|
|
1870
|
+
const classes = [ BLOCK.BASE_CLASS ];
|
|
1871
|
+
// Add spacing class
|
|
1872
|
+
// Add background class
|
|
1873
|
+
if (spacing && "none" !== spacing && classes.push(`${BLOCK.SPACING_PREFIX}${spacing}`),
|
|
1874
|
+
background) {
|
|
1875
|
+
const bgClass = BLOCK.CLASSES[`BG_${background.toUpperCase()}`];
|
|
1876
|
+
bgClass && classes.push(bgClass);
|
|
1877
|
+
}
|
|
1878
|
+
// Add full-width class
|
|
1879
|
+
return fullWidth && classes.push(BLOCK.CLASSES.FULL_WIDTH),
|
|
1880
|
+
// Add custom className
|
|
1881
|
+
className && classes.push(className), classes.filter(Boolean).join(" ");
|
|
1882
|
+
}
|
|
1883
|
+
}, blockClasses = generateBlockClass({
|
|
1884
|
+
spacing: spacing,
|
|
1885
|
+
background: background,
|
|
1886
|
+
fullWidth: fullWidth,
|
|
1887
|
+
className: className
|
|
1888
|
+
});
|
|
1889
|
+
return jsx(Component, {
|
|
1890
|
+
ref: ref,
|
|
1891
|
+
className: blockClasses,
|
|
1892
|
+
style: style,
|
|
1893
|
+
...props,
|
|
1894
|
+
children: fullWidth ? children : jsx(Container, {
|
|
1895
|
+
type: container.type,
|
|
1896
|
+
className: container.className,
|
|
1897
|
+
children: children
|
|
1898
|
+
})
|
|
1899
|
+
});
|
|
1900
|
+
}));
|
|
1901
|
+
|
|
1902
|
+
/**
|
|
1903
|
+
* Block component for creating structured section layouts.
|
|
1904
|
+
* Provides consistent spacing, backgrounds, and container behavior for content sections.
|
|
1905
|
+
*
|
|
1906
|
+
* @example
|
|
1907
|
+
* ```tsx
|
|
1908
|
+
* // Basic usage
|
|
1909
|
+
* <Block>
|
|
1910
|
+
* <h2>Section Title</h2>
|
|
1911
|
+
* <p>Section content goes here...</p>
|
|
1912
|
+
* </Block>
|
|
1913
|
+
*
|
|
1914
|
+
* // With custom spacing and background
|
|
1915
|
+
* <Block spacing="lg" background="subtle">
|
|
1916
|
+
* <h2>Featured Section</h2>
|
|
1917
|
+
* <p>This section has extra padding and a subtle background.</p>
|
|
1918
|
+
* </Block>
|
|
1919
|
+
*
|
|
1920
|
+
* // Full-width with custom container
|
|
1921
|
+
* <Block fullWidth background="primary">
|
|
1922
|
+
* <Container type="lg">
|
|
1923
|
+
* <h2>Hero Section</h2>
|
|
1924
|
+
* <p>Full-width section with centered content.</p>
|
|
1925
|
+
* </Container>
|
|
1926
|
+
* </Block>
|
|
1927
|
+
*
|
|
1928
|
+
* // As article element
|
|
1929
|
+
* <Block as="article" spacing="xl" background="accent">
|
|
1930
|
+
* <h1>Blog Post</h1>
|
|
1931
|
+
* <p>Article content...</p>
|
|
1932
|
+
* </Block>
|
|
1933
|
+
* ```
|
|
1934
|
+
*/ Block.displayName = "Block";
|
|
1935
|
+
|
|
1936
|
+
const Breadcrumb = memo((({items: items, divider: divider, className: className = "", ariaLabel: ariaLabel = "Breadcrumb", LinkComponent: LinkComponent, style: style}) => {
|
|
1937
|
+
const breadcrumbClasses = [ BREADCRUMB.CLASSES.BASE, className ].filter(Boolean).join(" ");
|
|
1938
|
+
return jsx("nav", {
|
|
1939
|
+
"aria-label": ariaLabel,
|
|
1940
|
+
style: style,
|
|
1941
|
+
children: jsx("ol", {
|
|
1942
|
+
className: breadcrumbClasses,
|
|
1943
|
+
children: items.map(((item, index) => {
|
|
1944
|
+
const isLast = index === items.length - 1, itemClasses = [ BREADCRUMB.CLASSES.ITEM, item.active || isLast ? BREADCRUMB.CLASSES.ACTIVE : "" ].filter(Boolean).join(" "), linkContent = jsxs(Fragment, {
|
|
1945
|
+
children: [ item.icon && jsx("span", {
|
|
1946
|
+
className: "c-breadcrumb__icon",
|
|
1947
|
+
children: item.icon
|
|
1948
|
+
}), item.label ]
|
|
1949
|
+
}), linkProps = {
|
|
1950
|
+
href: item.href,
|
|
1951
|
+
className: BREADCRUMB.CLASSES.LINK,
|
|
1952
|
+
onClick: item.onClick,
|
|
1953
|
+
style: item.style
|
|
1954
|
+
};
|
|
1955
|
+
return jsx("li", {
|
|
1956
|
+
className: itemClasses,
|
|
1957
|
+
style: item.style,
|
|
1958
|
+
children: item.href && !item.active ? jsx(LinkComponent || "a", {
|
|
1959
|
+
...linkProps,
|
|
1960
|
+
children: linkContent
|
|
1961
|
+
}) : jsx("span", {
|
|
1962
|
+
className: BREADCRUMB.CLASSES.LINK,
|
|
1963
|
+
children: linkContent
|
|
1964
|
+
})
|
|
1965
|
+
}, index);
|
|
1966
|
+
}))
|
|
1967
|
+
})
|
|
1968
|
+
});
|
|
1969
|
+
}));
|
|
1970
|
+
|
|
1971
|
+
Breadcrumb.displayName = "Breadcrumb";
|
|
1972
|
+
|
|
1973
|
+
const Spinner = memo((({size: size = "md", variant: variant = "primary", fullscreen: fullscreen = !1, className: className = "", style: style, glass: glass}) => {
|
|
1974
|
+
const {generateSpinnerClass: generateSpinnerClass} =
|
|
1975
|
+
/**
|
|
1976
|
+
* Spinner state and functionality
|
|
1977
|
+
* @param initialProps - Initial spinner properties
|
|
1978
|
+
* @returns Spinner state and methods
|
|
1979
|
+
*/
|
|
1980
|
+
function(initialProps) {
|
|
1981
|
+
// Default spinner properties
|
|
1982
|
+
const defaultProps = {
|
|
1983
|
+
variant: "primary",
|
|
1984
|
+
size: "md",
|
|
1985
|
+
fullscreen: !1,
|
|
1986
|
+
...initialProps
|
|
1987
|
+
};
|
|
1988
|
+
/**
|
|
1989
|
+
* Generate spinner class based on properties
|
|
1990
|
+
* @param props - Spinner properties
|
|
1991
|
+
* @returns Class string
|
|
1992
|
+
*/ return {
|
|
1993
|
+
defaultProps: defaultProps,
|
|
1994
|
+
generateSpinnerClass: props => {
|
|
1995
|
+
const {variant: variant = defaultProps.variant, size: size = defaultProps.size, fullscreen: fullscreen = defaultProps.fullscreen, className: className = ""} = props;
|
|
1996
|
+
return `c-spinner ${variant ? `c-spinner--${variant}` : ""} ${"md" !== size ? `c-spinner--${size}` : ""} ${fullscreen ? "c-spinner--fullscreen" : ""} ${className}`.trim();
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1999
|
+
}({
|
|
2000
|
+
size: size,
|
|
2001
|
+
variant: variant,
|
|
2002
|
+
fullscreen: fullscreen
|
|
2003
|
+
}), spinnerClass = generateSpinnerClass({
|
|
2004
|
+
size: size,
|
|
2005
|
+
variant: variant,
|
|
2006
|
+
fullscreen: fullscreen,
|
|
2007
|
+
className: `${className} ${glass ? "c-spinner--glass" : ""}`.trim()
|
|
2008
|
+
}), spinnerContent = jsx("div", {
|
|
2009
|
+
className: spinnerClass,
|
|
2010
|
+
style: style,
|
|
2011
|
+
role: "status",
|
|
2012
|
+
children: jsx("span", {
|
|
2013
|
+
className: "u-visually-hidden",
|
|
2014
|
+
children: "Loading..."
|
|
2015
|
+
})
|
|
2016
|
+
});
|
|
2017
|
+
if (glass) {
|
|
2018
|
+
const defaultGlassProps = {
|
|
2019
|
+
displacementScale: 20,
|
|
2020
|
+
blurAmount: 1,
|
|
2021
|
+
cornerRadius: 999,
|
|
2022
|
+
mode: "shader"
|
|
2023
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2024
|
+
...defaultGlassProps,
|
|
2025
|
+
...glass
|
|
2026
|
+
};
|
|
2027
|
+
return jsx(AtomixGlass, {
|
|
2028
|
+
...glassProps,
|
|
2029
|
+
children: spinnerContent
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
return spinnerContent;
|
|
2033
|
+
}));
|
|
2034
|
+
|
|
2035
|
+
Spinner.displayName = "Spinner";
|
|
2036
|
+
|
|
2037
|
+
// Map string sizes to pixel values
|
|
2038
|
+
const sizeMap = {
|
|
2039
|
+
xs: 16,
|
|
2040
|
+
sm: 20,
|
|
2041
|
+
md: 24,
|
|
2042
|
+
lg: 32,
|
|
2043
|
+
xl: 40
|
|
2044
|
+
}, Icon = ({name: name, size: size = "md", weight: weight = "regular", color: color, className: className = "", style: style, alt: alt}) => {
|
|
2045
|
+
// Get the icon component from Phosphor
|
|
2046
|
+
const IconComponent = PhosphorIcons[name];
|
|
2047
|
+
return IconComponent ? jsx("span", {
|
|
2048
|
+
className: `c-icon c-icon--${size} ${className}`,
|
|
2049
|
+
style: style,
|
|
2050
|
+
"aria-hidden": !alt,
|
|
2051
|
+
title: alt,
|
|
2052
|
+
children: jsx(IconComponent, {
|
|
2053
|
+
size: "string" == typeof size ? sizeMap[size] || 24 : size,
|
|
2054
|
+
weight: weight,
|
|
2055
|
+
color: color,
|
|
2056
|
+
"aria-label": alt
|
|
2057
|
+
})
|
|
2058
|
+
}) : (console.warn(`Icon "${name}" not found in Phosphor Icons`), null);
|
|
2059
|
+
// Convert string size to pixel value if needed
|
|
2060
|
+
};
|
|
2061
|
+
|
|
2062
|
+
/**
|
|
2063
|
+
* Icon component that displays a Phosphor icon
|
|
2064
|
+
*/ Icon.displayName = "Icon";
|
|
2065
|
+
|
|
2066
|
+
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, ariaExpanded: ariaExpanded, ariaControls: ariaControls, tabIndex: tabIndex, style: style, LinkComponent: LinkComponent, ...props}, ref) => {
|
|
2067
|
+
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href && !isDisabled), iconElement = useMemo((() => loading ? null : iconName ? jsx(Icon, {
|
|
2068
|
+
name: iconName,
|
|
2069
|
+
size: iconSize
|
|
2070
|
+
}) : icon), [ icon, iconName, iconSize, loading ]), {generateButtonClass: generateButtonClass, handleClick: handleClick} =
|
|
2071
|
+
/**
|
|
2072
|
+
* Button state and functionality
|
|
2073
|
+
* @param initialProps - Initial button properties
|
|
2074
|
+
* @returns Button state and methods
|
|
2075
|
+
*/
|
|
2076
|
+
function(initialProps) {
|
|
2077
|
+
// Default button properties
|
|
2078
|
+
const defaultProps = {
|
|
2079
|
+
variant: "primary",
|
|
2080
|
+
size: "md",
|
|
2081
|
+
disabled: !1,
|
|
2082
|
+
rounded: !1,
|
|
2083
|
+
loading: !1,
|
|
2084
|
+
fullWidth: !1,
|
|
2085
|
+
block: !1,
|
|
2086
|
+
active: !1,
|
|
2087
|
+
selected: !1,
|
|
2088
|
+
...initialProps
|
|
2089
|
+
};
|
|
2090
|
+
/**
|
|
2091
|
+
* Generate button class based on properties
|
|
2092
|
+
* @param props - Button properties
|
|
2093
|
+
* @returns Class string
|
|
2094
|
+
*/ return {
|
|
2095
|
+
defaultProps: defaultProps,
|
|
2096
|
+
generateButtonClass: props => {
|
|
2097
|
+
const {variant: variant = defaultProps.variant, size: size = defaultProps.size, disabled: disabled = defaultProps.disabled, rounded: rounded = defaultProps.rounded, iconOnly: iconOnly = !1, glass: glass = defaultProps.glass, loading: loading = defaultProps.loading, fullWidth: fullWidth = defaultProps.fullWidth, block: block = defaultProps.block, active: active = defaultProps.active, selected: selected = defaultProps.selected, className: className = ""} = props, sizeClass = "md" === size ? "" : `c-btn--${size}`, iconOnlyClass = iconOnly ? "c-btn--icon" : "", roundedClass = rounded ? "c-btn--rounded" : "", disabledClass = disabled ? "c-btn--disabled" : "", glassClass = glass ? "c-btn--glass" : "", loadingClass = loading ? BUTTON.CLASSES.LOADING : "", fullWidthClass = fullWidth ? BUTTON.CLASSES.FULL_WIDTH : "", blockClass = block ? BUTTON.CLASSES.BLOCK : "", activeClass = active ? BUTTON.CLASSES.ACTIVE : "", selectedClass = selected ? BUTTON.CLASSES.SELECTED : "";
|
|
2098
|
+
return [ BUTTON.BASE_CLASS, `c-btn--${variant}`, sizeClass, iconOnlyClass, roundedClass, disabledClass, glassClass, loadingClass, fullWidthClass, blockClass, activeClass, selectedClass, className ].filter(Boolean).join(" ");
|
|
2099
|
+
},
|
|
2100
|
+
handleClick: handler => event => {
|
|
2101
|
+
defaultProps.disabled || defaultProps.loading || !handler || handler(event);
|
|
2102
|
+
}
|
|
2103
|
+
};
|
|
2104
|
+
}({
|
|
2105
|
+
variant: variant,
|
|
2106
|
+
size: size,
|
|
2107
|
+
disabled: isDisabled,
|
|
2108
|
+
rounded: rounded,
|
|
2109
|
+
glass: glass,
|
|
2110
|
+
loading: loading,
|
|
2111
|
+
fullWidth: fullWidth,
|
|
2112
|
+
block: block,
|
|
2113
|
+
active: active,
|
|
2114
|
+
selected: selected
|
|
2115
|
+
}), buttonClass = useMemo((() => generateButtonClass({
|
|
2116
|
+
variant: variant,
|
|
2117
|
+
size: size,
|
|
2118
|
+
disabled: isDisabled,
|
|
2119
|
+
rounded: rounded,
|
|
2120
|
+
iconOnly: iconOnly,
|
|
2121
|
+
glass: glass,
|
|
2122
|
+
loading: loading,
|
|
2123
|
+
fullWidth: fullWidth,
|
|
2124
|
+
block: block,
|
|
2125
|
+
active: active,
|
|
2126
|
+
selected: selected,
|
|
2127
|
+
className: className
|
|
2128
|
+
})), [ variant, size, isDisabled, rounded, iconOnly, glass, loading, fullWidth, block, active, selected, className, generateButtonClass ]), handleClickEvent = useCallback((event => {
|
|
2129
|
+
isDisabled ? event.preventDefault() : onClick?.(event);
|
|
2130
|
+
}), [ isDisabled, onClick ]), handleMouseEnter = useCallback((event => {
|
|
2131
|
+
isDisabled || onHover?.(event);
|
|
2132
|
+
}), [ isDisabled, onHover ]), handleFocusEvent = useCallback((event => {
|
|
2133
|
+
isDisabled || onFocus?.(event);
|
|
2134
|
+
}), [ isDisabled, onFocus ]), handleBlurEvent = useCallback((event => {
|
|
2135
|
+
isDisabled || onBlur?.(event);
|
|
2136
|
+
}), [ isDisabled, onBlur ]), buttonText = useMemo((() => loading && loadingText ? loadingText : label || children), [ loading, loadingText, label, children ]), spinnerSize = useMemo((() => "sm" === size ? "sm" : "lg" === size ? "md" : "sm"), [ size ]), buttonContent = useMemo((() => {
|
|
2137
|
+
const iconSpan = iconElement && jsx("span", {
|
|
2138
|
+
className: BUTTON.ICON_CLASS,
|
|
2139
|
+
"aria-hidden": "true",
|
|
2140
|
+
children: iconElement
|
|
2141
|
+
}), spinnerElement = loading && jsx("span", {
|
|
2142
|
+
className: BUTTON.SPINNER_CLASS,
|
|
2143
|
+
"aria-hidden": "true",
|
|
2144
|
+
children: jsx(Spinner, {
|
|
2145
|
+
size: spinnerSize,
|
|
2146
|
+
variant: "link" === variant || "string" == typeof variant && variant.startsWith("outline-") ? "primary" : "danger" === variant ? "error" : variant
|
|
2147
|
+
})
|
|
2148
|
+
}), labelElement = !iconOnly && buttonText && jsx("span", {
|
|
2149
|
+
className: BUTTON.LABEL_CLASS,
|
|
2150
|
+
children: buttonText
|
|
2151
|
+
});
|
|
2152
|
+
return jsxs(Fragment, "end" === iconPosition ? {
|
|
2153
|
+
children: [ labelElement, spinnerElement, iconSpan ]
|
|
2154
|
+
} : {
|
|
2155
|
+
children: [ spinnerElement, iconSpan, labelElement ]
|
|
2156
|
+
});
|
|
2157
|
+
}), [ iconElement, iconPosition, iconOnly, buttonText, loading, spinnerSize, variant ]), buttonProps = useMemo((() => ({
|
|
2158
|
+
ref: ref,
|
|
2159
|
+
className: buttonClass,
|
|
2160
|
+
type: "button" !== Component || shouldRenderAsLink ? void 0 : type,
|
|
2161
|
+
onClick: handleClickEvent,
|
|
2162
|
+
onMouseEnter: onHover ? handleMouseEnter : void 0,
|
|
2163
|
+
onFocus: onFocus ? handleFocusEvent : void 0,
|
|
2164
|
+
onBlur: onBlur ? handleBlurEvent : void 0,
|
|
2165
|
+
disabled: isDisabled && "button" === Component && !shouldRenderAsLink,
|
|
2166
|
+
"aria-disabled": isDisabled,
|
|
2167
|
+
"aria-busy": loading,
|
|
2168
|
+
"aria-label": ariaLabel || (iconOnly ? label || children : void 0),
|
|
2169
|
+
"aria-describedby": ariaDescribedBy,
|
|
2170
|
+
"aria-expanded": ariaExpanded,
|
|
2171
|
+
"aria-controls": ariaControls,
|
|
2172
|
+
tabIndex: void 0 !== tabIndex ? tabIndex : isDisabled ? -1 : 0,
|
|
2173
|
+
style: style,
|
|
2174
|
+
...props
|
|
2175
|
+
})), [ ref, buttonClass, Component, type, handleClickEvent, handleMouseEnter, handleFocusEvent, handleBlurEvent, isDisabled, loading, ariaLabel, iconOnly, label, children, ariaDescribedBy, ariaExpanded, ariaControls, tabIndex, style, props ]);
|
|
2176
|
+
// Determine if we should render as a link
|
|
2177
|
+
// Render as anchor if href is provided
|
|
2178
|
+
if (shouldRenderAsLink) {
|
|
2179
|
+
const {ref: _, ...buttonPropsWithoutRef} = buttonProps, anchorButtonProps = {
|
|
2180
|
+
...buttonPropsWithoutRef,
|
|
2181
|
+
type: void 0,
|
|
2182
|
+
disabled: void 0
|
|
2183
|
+
};
|
|
2184
|
+
// Use custom LinkComponent if provided (e.g., Next.js Link)
|
|
2185
|
+
if (LinkComponent) {
|
|
2186
|
+
const LinkComp = LinkComponent, linkProps = {
|
|
2187
|
+
...anchorButtonProps,
|
|
2188
|
+
ref: ref,
|
|
2189
|
+
href: href,
|
|
2190
|
+
target: target,
|
|
2191
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
2192
|
+
}, linkElement = jsx(LinkComp, {
|
|
2193
|
+
...linkProps,
|
|
2194
|
+
children: buttonContent
|
|
2195
|
+
});
|
|
2196
|
+
if (glass) {
|
|
2197
|
+
const defaultGlassProps = {
|
|
2198
|
+
displacementScale: 20,
|
|
2199
|
+
blurAmount: 0,
|
|
2200
|
+
saturation: 200,
|
|
2201
|
+
elasticity: 0
|
|
2202
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2203
|
+
...defaultGlassProps,
|
|
2204
|
+
...glass
|
|
2205
|
+
};
|
|
2206
|
+
return jsx(AtomixGlass, {
|
|
2207
|
+
...glassProps,
|
|
2208
|
+
children: linkElement
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
return linkElement;
|
|
2212
|
+
}
|
|
2213
|
+
// Fallback to regular anchor tag
|
|
2214
|
+
const anchorElement = jsx("a", {
|
|
2215
|
+
...anchorButtonProps,
|
|
2216
|
+
ref: ref,
|
|
2217
|
+
href: href,
|
|
2218
|
+
target: target,
|
|
2219
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
2220
|
+
children: buttonContent
|
|
2221
|
+
});
|
|
2222
|
+
if (glass) {
|
|
2223
|
+
const defaultGlassProps = {
|
|
2224
|
+
displacementScale: 20,
|
|
2225
|
+
blurAmount: 0,
|
|
2226
|
+
saturation: 200,
|
|
2227
|
+
elasticity: 0
|
|
2228
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2229
|
+
...defaultGlassProps,
|
|
2230
|
+
...glass
|
|
2231
|
+
};
|
|
2232
|
+
return jsx(AtomixGlass, {
|
|
2233
|
+
...glassProps,
|
|
2234
|
+
children: anchorElement
|
|
2235
|
+
});
|
|
2236
|
+
}
|
|
2237
|
+
return anchorElement;
|
|
2238
|
+
}
|
|
2239
|
+
// Default button rendering
|
|
2240
|
+
if (glass) {
|
|
2241
|
+
const defaultGlassProps = {
|
|
2242
|
+
displacementScale: 20,
|
|
2243
|
+
blurAmount: 0,
|
|
2244
|
+
saturation: 200,
|
|
2245
|
+
elasticity: 0
|
|
2246
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2247
|
+
...defaultGlassProps,
|
|
2248
|
+
...glass
|
|
2249
|
+
};
|
|
2250
|
+
return jsx(AtomixGlass, {
|
|
2251
|
+
...glassProps,
|
|
2252
|
+
children: jsx(Component, {
|
|
2253
|
+
...buttonProps,
|
|
2254
|
+
children: buttonContent
|
|
2255
|
+
})
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
return jsx(Component, {
|
|
2259
|
+
...buttonProps,
|
|
2260
|
+
children: buttonContent
|
|
2261
|
+
});
|
|
2262
|
+
})));
|
|
2263
|
+
|
|
2264
|
+
Button.displayName = "Button";
|
|
2265
|
+
|
|
2266
|
+
const Card = React.memo( forwardRef((({
|
|
2267
|
+
// Variants
|
|
2268
|
+
size: size = "md", variant: variant = "", appearance: appearance = "filled", elevation: elevation = "none", hoverable: hoverable = !1, hoverElevation: hoverElevation = "md",
|
|
2269
|
+
// Layout
|
|
2270
|
+
row: row = !1, flat: flat = !1,
|
|
2271
|
+
// States
|
|
2272
|
+
active: active = !1, disabled: disabled = !1, loading: loading = !1, selected: selected = !1, interactive: interactive = !1,
|
|
2273
|
+
// Content
|
|
2274
|
+
header: header, image: image, imageAlt: imageAlt = "", title: title, text: text, actions: actions, icon: icon, footer: footer, children: children,
|
|
2275
|
+
// Interaction
|
|
2276
|
+
onClick: onClick, onHover: onHover, onFocus: onFocus, href: href, target: target,
|
|
2277
|
+
// Glass
|
|
2278
|
+
glass: glass,
|
|
2279
|
+
// Accessibility
|
|
2280
|
+
role: role, ariaLabel: ariaLabel, ariaDescribedBy: ariaDescribedBy, tabIndex: tabIndex,
|
|
2281
|
+
// Styling
|
|
2282
|
+
className: className = "", style: style, ...rest}, ref) => {
|
|
2283
|
+
// Determine if card is clickable/interactive
|
|
2284
|
+
const isClickable = Boolean(onClick || href || interactive), isDisabled = disabled || loading, cardClasses = useMemo((() => [ CARD.CLASSES.BASE,
|
|
2285
|
+
// Size modifiers
|
|
2286
|
+
"sm" === size ? CARD.CLASSES.SM : "", "md" === size ? CARD.CLASSES.MD : "", "lg" === size ? CARD.CLASSES.LG : "",
|
|
2287
|
+
// Variant modifiers (will be handled in SCSS with @each)
|
|
2288
|
+
variant ? `c-card--${variant}` : "",
|
|
2289
|
+
// Appearance modifiers
|
|
2290
|
+
"filled" === appearance ? CARD.CLASSES.FILLED : "", "outlined" === appearance ? CARD.CLASSES.OUTLINED : "", "ghost" === appearance ? CARD.CLASSES.GHOST : "", "elevated" === appearance ? CARD.CLASSES.ELEVATED : "",
|
|
2291
|
+
// Elevation modifiers
|
|
2292
|
+
"none" === elevation ? CARD.CLASSES.ELEVATION_NONE : "", "sm" === elevation ? CARD.CLASSES.ELEVATION_SM : "", "md" === elevation ? CARD.CLASSES.ELEVATION_MD : "", "lg" === elevation ? CARD.CLASSES.ELEVATION_LG : "", "xl" === elevation ? CARD.CLASSES.ELEVATION_XL : "",
|
|
2293
|
+
// Hoverable modifier
|
|
2294
|
+
hoverable ? "c-card--hoverable" : "", hoverable && hoverElevation ? `c-card--hover-elevation-${hoverElevation}` : "",
|
|
2295
|
+
// Layout modifiers
|
|
2296
|
+
row ? CARD.CLASSES.ROW : "", flat ? CARD.CLASSES.FLAT : "",
|
|
2297
|
+
// State modifiers
|
|
2298
|
+
active ? CARD.CLASSES.ACTIVE : "", disabled ? CARD.CLASSES.DISABLED : "", loading ? CARD.CLASSES.LOADING : "", selected ? CARD.CLASSES.SELECTED : "", interactive || isClickable ? CARD.CLASSES.INTERACTIVE : "", glass ? CARD.CLASSES.GLASS : "", className ].filter(Boolean).join(" ")), [ size, variant, appearance, elevation, hoverable, hoverElevation, row, flat, active, disabled, loading, selected, interactive, isClickable, glass, className ]), cardRole = useMemo((() => role || (href ? "link" : isClickable ? "button" : "article")), [ role, href, isClickable ]), handleClick = useCallback((event => {
|
|
2299
|
+
isDisabled ? event.preventDefault() : onClick?.(event);
|
|
2300
|
+
}), [ isDisabled, onClick ]), handleKeyDown = useCallback((event => {
|
|
2301
|
+
isDisabled ? event.preventDefault() :
|
|
2302
|
+
// Enter or Space activates clickable cards
|
|
2303
|
+
!isClickable || "Enter" !== event.key && " " !== event.key || (event.preventDefault(),
|
|
2304
|
+
onClick && onClick(event));
|
|
2305
|
+
}), [ isDisabled, isClickable, onClick ]), handleMouseEnter = useCallback((event => {
|
|
2306
|
+
isDisabled || onHover?.(event);
|
|
2307
|
+
}), [ isDisabled, onHover ]), handleFocusEvent = useCallback((event => {
|
|
2308
|
+
isDisabled || onFocus?.(event);
|
|
2309
|
+
}), [ isDisabled, onFocus ]), effectiveTabIndex = useMemo((() => void 0 !== tabIndex ? tabIndex : isDisabled ? -1 : isClickable ? 0 : void 0), [ tabIndex, isDisabled, isClickable ]), cardContent = useMemo((() => jsxs(Fragment, {
|
|
2310
|
+
children: [ loading && jsx("div", {
|
|
2311
|
+
className: "c-card__loading",
|
|
2312
|
+
"aria-label": "Loading",
|
|
2313
|
+
children: jsx("div", {
|
|
2314
|
+
className: "c-card__spinner"
|
|
2315
|
+
})
|
|
2316
|
+
}), (image || icon || header) && jsxs("div", {
|
|
2317
|
+
className: CARD.SELECTORS.HEADER.substring(1),
|
|
2318
|
+
children: [ header, image && jsx("img", {
|
|
2319
|
+
src: image,
|
|
2320
|
+
alt: imageAlt,
|
|
2321
|
+
className: CARD.SELECTORS.IMAGE.substring(1),
|
|
2322
|
+
loading: "lazy"
|
|
2323
|
+
}), icon && jsx("div", {
|
|
2324
|
+
className: CARD.SELECTORS.ICON.substring(1),
|
|
2325
|
+
children: icon
|
|
2326
|
+
}) ]
|
|
2327
|
+
}), jsxs("div", {
|
|
2328
|
+
className: CARD.SELECTORS.BODY.substring(1),
|
|
2329
|
+
children: [ title && jsx("h3", {
|
|
2330
|
+
className: CARD.SELECTORS.TITLE.substring(1),
|
|
2331
|
+
children: title
|
|
2332
|
+
}), text && jsx("p", {
|
|
2333
|
+
className: CARD.SELECTORS.TEXT.substring(1),
|
|
2334
|
+
children: text
|
|
2335
|
+
}), children ]
|
|
2336
|
+
}), actions && jsx("div", {
|
|
2337
|
+
className: CARD.SELECTORS.ACTIONS.substring(1),
|
|
2338
|
+
children: actions
|
|
2339
|
+
}), footer && jsx("div", {
|
|
2340
|
+
className: CARD.SELECTORS.FOOTER.substring(1),
|
|
2341
|
+
children: footer
|
|
2342
|
+
}) ]
|
|
2343
|
+
})), [ loading, image, imageAlt, icon, header, title, text, children, actions, footer ]), commonProps = {
|
|
2344
|
+
// ref is applied individually to ensure correct typing for polymorphic behavior
|
|
2345
|
+
className: cardClasses,
|
|
2346
|
+
style: style,
|
|
2347
|
+
role: cardRole,
|
|
2348
|
+
"aria-label": ariaLabel,
|
|
2349
|
+
"aria-describedby": ariaDescribedBy,
|
|
2350
|
+
"aria-disabled": !!isDisabled || void 0,
|
|
2351
|
+
tabIndex: effectiveTabIndex,
|
|
2352
|
+
onClick: isClickable ? handleClick : void 0,
|
|
2353
|
+
onKeyDown: isClickable ? handleKeyDown : void 0,
|
|
2354
|
+
onMouseEnter: onHover ? handleMouseEnter : void 0,
|
|
2355
|
+
onFocus: onFocus ? handleFocusEvent : void 0,
|
|
2356
|
+
...rest
|
|
2357
|
+
};
|
|
2358
|
+
// Render as anchor if href is provided
|
|
2359
|
+
if (href && !isDisabled) {
|
|
2360
|
+
const anchorElement = jsx("a", {
|
|
2361
|
+
...commonProps,
|
|
2362
|
+
ref: ref,
|
|
2363
|
+
href: href,
|
|
2364
|
+
target: target,
|
|
2365
|
+
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
2366
|
+
children: cardContent
|
|
2367
|
+
});
|
|
2368
|
+
return glass ? jsx(AtomixGlass, {
|
|
2369
|
+
...!0 === glass ? {} : glass,
|
|
2370
|
+
elasticity: 0,
|
|
2371
|
+
children: anchorElement
|
|
2372
|
+
}) : anchorElement;
|
|
2373
|
+
}
|
|
2374
|
+
// Render as div
|
|
2375
|
+
const divElement = jsx("div", {
|
|
2376
|
+
...commonProps,
|
|
2377
|
+
ref: ref,
|
|
2378
|
+
children: cardContent
|
|
2379
|
+
});
|
|
2380
|
+
return glass ? jsx(AtomixGlass, {
|
|
2381
|
+
...!0 === glass ? {} : glass,
|
|
2382
|
+
elasticity: 0,
|
|
2383
|
+
children: divElement
|
|
2384
|
+
}) : divElement;
|
|
2385
|
+
})));
|
|
2386
|
+
|
|
2387
|
+
Card.displayName = "Card";
|
|
2388
|
+
|
|
2389
|
+
const CardHeader = forwardRef((({title: title, subtitle: subtitle, action: action, icon: icon, children: children, className: className = "", ...props}, ref) => {
|
|
2390
|
+
const headerClasses = `${CARD.SELECTORS.HEADER.substring(1)} ${className}`.trim();
|
|
2391
|
+
return jsxs("div", {
|
|
2392
|
+
ref: ref,
|
|
2393
|
+
className: headerClasses,
|
|
2394
|
+
...props,
|
|
2395
|
+
children: [ icon && jsx("div", {
|
|
2396
|
+
className: CARD.SELECTORS.ICON.substring(1),
|
|
2397
|
+
children: icon
|
|
2398
|
+
}), (title || subtitle) && jsxs("div", {
|
|
2399
|
+
children: [ title && jsx("h3", {
|
|
2400
|
+
className: CARD.SELECTORS.TITLE.substring(1),
|
|
2401
|
+
children: title
|
|
2402
|
+
}), subtitle && jsx("p", {
|
|
2403
|
+
className: CARD.SELECTORS.TEXT.substring(1),
|
|
2404
|
+
children: subtitle
|
|
2405
|
+
}) ]
|
|
2406
|
+
}), action && jsx("div", {
|
|
2407
|
+
className: CARD.SELECTORS.ACTIONS.substring(1),
|
|
2408
|
+
children: action
|
|
2409
|
+
}), children ]
|
|
2410
|
+
});
|
|
2411
|
+
}));
|
|
2412
|
+
|
|
2413
|
+
CardHeader.displayName = "CardHeader";
|
|
2414
|
+
|
|
2415
|
+
const CardBody = forwardRef((({scrollable: scrollable = !1, maxHeight: maxHeight, children: children, className: className = "", style: style, ...props}, ref) => {
|
|
2416
|
+
const bodyClasses = `${CARD.SELECTORS.BODY.substring(1)} ${scrollable ? "c-card__body--scrollable" : ""} ${className}`.trim(), bodyStyle = {
|
|
2417
|
+
...style,
|
|
2418
|
+
...scrollable && maxHeight ? {
|
|
2419
|
+
maxHeight: "number" == typeof maxHeight ? `${maxHeight}px` : maxHeight,
|
|
2420
|
+
overflowY: "auto"
|
|
2421
|
+
} : {}
|
|
2422
|
+
};
|
|
2423
|
+
return jsx("div", {
|
|
2424
|
+
ref: ref,
|
|
2425
|
+
className: bodyClasses,
|
|
2426
|
+
style: bodyStyle,
|
|
2427
|
+
...props,
|
|
2428
|
+
children: children
|
|
2429
|
+
});
|
|
2430
|
+
}));
|
|
2431
|
+
|
|
2432
|
+
CardBody.displayName = "CardBody";
|
|
2433
|
+
|
|
2434
|
+
const CardFooter = forwardRef((({align: align, children: children, className: className = "", style: style, ...props}, ref) => {
|
|
2435
|
+
const footerClasses = `${CARD.SELECTORS.FOOTER.substring(1)} ${align ? `c-card__footer--align-${align}` : ""} ${className}`.trim();
|
|
2436
|
+
return jsx("div", {
|
|
2437
|
+
ref: ref,
|
|
2438
|
+
className: footerClasses,
|
|
2439
|
+
style: style,
|
|
2440
|
+
...props,
|
|
2441
|
+
children: children
|
|
2442
|
+
});
|
|
2443
|
+
}));
|
|
2444
|
+
|
|
2445
|
+
CardFooter.displayName = "CardFooter",
|
|
2446
|
+
// Attach subcomponents to Card
|
|
2447
|
+
Card.Header = CardHeader, Card.Body = CardBody, Card.Footer = CardFooter;
|
|
2448
|
+
|
|
2449
|
+
/**
|
|
2450
|
+
* Hook for managing Card component state and behaviors
|
|
2451
|
+
*
|
|
2452
|
+
* @param options - Configuration options for the card
|
|
2453
|
+
* @returns Card state and handlers
|
|
2454
|
+
*/
|
|
2455
|
+
const ElevationCard = ({elevationClass: elevationClass = "is-elevated", className: className = "", style: style, children: children, onClick: onClick, ...props}) => {
|
|
2456
|
+
const {getCardProps: getCardProps} = ((options = {}) => {
|
|
2457
|
+
const {elevationEffect: elevationEffect = !1, elevationClass: elevationClass = CARD.CLASSES.ACTIVE, flipEffect: flipEffect = !1, flipTrigger: flipTrigger = "click", focusEffect: focusEffect = !1, clickable: clickable = !1, onClick: onClick} = options, cardRef = useRef(null), frontRef = useRef(null), backRef = useRef(null), [isFlipped, setIsFlipped] = useState(!1), [isElevated, setIsElevated] = useState(!1), [isFocused, setIsFocused] = useState(!1), [isHovered, setIsHovered] = useState(!1), handleClick = useCallback((event => {
|
|
2458
|
+
flipEffect && "click" === flipTrigger && setIsFlipped((prev => !prev)), onClick && onClick(event);
|
|
2459
|
+
}), [ flipEffect, flipTrigger, onClick ]), handleKeyDown = useCallback((event => {
|
|
2460
|
+
"Enter" !== event.key && " " !== event.key || (event.preventDefault(), flipEffect && "click" === flipTrigger && setIsFlipped((prev => !prev)),
|
|
2461
|
+
onClick && onClick(event));
|
|
2462
|
+
}), [ flipEffect, flipTrigger, onClick ]), handleMouseEnter = useCallback((() => {
|
|
2463
|
+
setIsHovered(!0), elevationEffect && setIsElevated(!0), flipEffect && "hover" === flipTrigger && setIsFlipped(!0);
|
|
2464
|
+
}), [ elevationEffect, flipEffect, flipTrigger ]), handleMouseLeave = useCallback((() => {
|
|
2465
|
+
setIsHovered(!1), elevationEffect && setIsElevated(!1), flipEffect && "hover" === flipTrigger && setIsFlipped(!1);
|
|
2466
|
+
}), [ elevationEffect, flipEffect, flipTrigger ]), handleFocus = useCallback((() => {
|
|
2467
|
+
setIsFocused(!0);
|
|
2468
|
+
}), []), handleBlur = useCallback((() => {
|
|
2469
|
+
setIsFocused(!1);
|
|
2470
|
+
}), []), getCardProps = useCallback((() => ({
|
|
2471
|
+
className: [ CARD.CLASSES.BASE, isElevated ? elevationClass : "", isFlipped ? CARD.CLASSES.FLIPPED : "", isFocused && focusEffect ? CARD.CLASSES.FOCUSED : "", clickable ? CARD.CLASSES.CLICKABLE : "" ].filter(Boolean).join(" "),
|
|
2472
|
+
ref: cardRef,
|
|
2473
|
+
tabxwIndex: clickable || flipEffect ? 0 : -1,
|
|
2474
|
+
role: clickable ? "button" : void 0,
|
|
2475
|
+
onMouseEnter: handleMouseEnter,
|
|
2476
|
+
onMouseLeave: handleMouseLeave,
|
|
2477
|
+
onFocus: handleFocus,
|
|
2478
|
+
onBlur: handleBlur,
|
|
2479
|
+
onClick: handleClick,
|
|
2480
|
+
onKeyDown: handleKeyDown
|
|
2481
|
+
})), [ isElevated, isFlipped, isFocused, elevationClass, focusEffect, clickable, handleMouseEnter, handleMouseLeave, handleFocus, handleBlur, handleClick, handleKeyDown, flipEffect ]);
|
|
2482
|
+
return {
|
|
2483
|
+
cardRef: cardRef,
|
|
2484
|
+
frontRef: frontRef,
|
|
2485
|
+
backRef: backRef,
|
|
2486
|
+
isFlipped: isFlipped,
|
|
2487
|
+
isElevated: isElevated,
|
|
2488
|
+
isFocused: isFocused,
|
|
2489
|
+
isHovered: isHovered,
|
|
2490
|
+
handleClick: handleClick,
|
|
2491
|
+
handleKeyDown: handleKeyDown,
|
|
2492
|
+
handleMouseEnter: handleMouseEnter,
|
|
2493
|
+
handleMouseLeave: handleMouseLeave,
|
|
2494
|
+
handleFocus: handleFocus,
|
|
2495
|
+
handleBlur: handleBlur,
|
|
2496
|
+
getCardProps: getCardProps
|
|
2497
|
+
};
|
|
2498
|
+
})({
|
|
2499
|
+
elevationEffect: !0,
|
|
2500
|
+
elevationClass: elevationClass,
|
|
2501
|
+
clickable: Boolean(onClick),
|
|
2502
|
+
onClick: onClick,
|
|
2503
|
+
focusEffect: !0
|
|
2504
|
+
}), cardProps = getCardProps();
|
|
2505
|
+
return jsx("div", {
|
|
2506
|
+
className: `${className} ${cardProps.className}`,
|
|
2507
|
+
ref: cardProps.ref,
|
|
2508
|
+
style: style,
|
|
2509
|
+
tabIndex: cardProps.tabIndex,
|
|
2510
|
+
role: cardProps.role,
|
|
2511
|
+
onMouseEnter: cardProps.onMouseEnter,
|
|
2512
|
+
onMouseLeave: cardProps.onMouseLeave,
|
|
2513
|
+
onFocus: cardProps.onFocus,
|
|
2514
|
+
onBlur: cardProps.onBlur,
|
|
2515
|
+
onClick: cardProps.onClick,
|
|
2516
|
+
onKeyDown: cardProps.onKeyDown,
|
|
2517
|
+
children: jsx(Card, {
|
|
2518
|
+
...props,
|
|
2519
|
+
className: "",
|
|
2520
|
+
onClick: void 0,
|
|
2521
|
+
children: children
|
|
2522
|
+
})
|
|
2523
|
+
});
|
|
2524
|
+
};
|
|
2525
|
+
|
|
2526
|
+
ElevationCard.displayName = "ElevationCard";
|
|
2527
|
+
|
|
2528
|
+
var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
2529
|
+
|
|
2530
|
+
function getDefaultExportFromCjs(x) {
|
|
2531
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
var fails$8 = function(exec) {
|
|
2535
|
+
try {
|
|
2536
|
+
return !!exec();
|
|
2537
|
+
} catch (error) {
|
|
2538
|
+
return !0;
|
|
2539
|
+
}
|
|
2540
|
+
}, functionBindNative = !fails$8((function() {
|
|
2541
|
+
// eslint-disable-next-line es/no-function-prototype-bind -- safe
|
|
2542
|
+
var test = function() {/* empty */}.bind();
|
|
2543
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
2544
|
+
return "function" != typeof test || test.hasOwnProperty("prototype");
|
|
2545
|
+
})), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
|
|
2546
|
+
return function() {
|
|
2547
|
+
return call$5.apply(fn, arguments);
|
|
2548
|
+
};
|
|
2549
|
+
}, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
|
|
2550
|
+
return it && it.Math === Math && it;
|
|
2551
|
+
}, globalThis_1 =
|
|
2552
|
+
// eslint-disable-next-line es/no-global-this -- safe
|
|
2553
|
+
check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
|
|
2554
|
+
// eslint-disable-next-line no-restricted-globals -- safe
|
|
2555
|
+
check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
|
|
2556
|
+
// eslint-disable-next-line no-new-func -- fallback
|
|
2557
|
+
function() {
|
|
2558
|
+
return this;
|
|
2559
|
+
}() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
|
|
2560
|
+
return call$4.apply(apply$1, arguments);
|
|
2561
|
+
}), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
|
|
2562
|
+
return stringSlice(toString$3(it), 8, -1);
|
|
2563
|
+
}, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
|
|
2564
|
+
// Nashorn bug:
|
|
2565
|
+
// https://github.com/zloirock/core-js/issues/1128
|
|
2566
|
+
// https://github.com/zloirock/core-js/issues/1130
|
|
2567
|
+
if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
|
|
2568
|
+
}, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
|
|
2569
|
+
return "function" == typeof argument || argument === documentAll;
|
|
2570
|
+
} : function(argument) {
|
|
2571
|
+
return "function" == typeof argument;
|
|
2572
|
+
}, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
|
|
2573
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
2574
|
+
return 7 !== Object.defineProperty({}, 1, {
|
|
2575
|
+
get: function() {
|
|
2576
|
+
return 7;
|
|
2577
|
+
}
|
|
2578
|
+
})[1];
|
|
2579
|
+
})), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
|
|
2580
|
+
return call$3.apply(call$3, arguments);
|
|
2581
|
+
}, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
|
|
2582
|
+
1: 2
|
|
2583
|
+
}, 1);
|
|
2584
|
+
|
|
2585
|
+
// `Object.prototype.propertyIsEnumerable` method implementation
|
|
2586
|
+
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
|
|
2587
|
+
objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
|
|
2588
|
+
var descriptor = getOwnPropertyDescriptor$1(this, V);
|
|
2589
|
+
return !!descriptor && descriptor.enumerable;
|
|
2590
|
+
} : $propertyIsEnumerable;
|
|
2591
|
+
|
|
2592
|
+
var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
|
|
2593
|
+
return {
|
|
2594
|
+
enumerable: !(1 & bitmap),
|
|
2595
|
+
configurable: !(2 & bitmap),
|
|
2596
|
+
writable: !(4 & bitmap),
|
|
2597
|
+
value: value
|
|
2598
|
+
};
|
|
2599
|
+
}, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
|
|
2600
|
+
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
|
2601
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
2602
|
+
return !$Object$3("z").propertyIsEnumerable(0);
|
|
2603
|
+
})) ? function(it) {
|
|
2604
|
+
return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
|
|
2605
|
+
} : $Object$3, isNullOrUndefined$2 = function(it) {
|
|
2606
|
+
return null == it;
|
|
2607
|
+
}, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
|
|
2608
|
+
if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
|
|
2609
|
+
return it;
|
|
2610
|
+
}, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
|
|
2611
|
+
return IndexedObject(requireObjectCoercible$2(it));
|
|
2612
|
+
}, isCallable$7 = isCallable$8, isObject$5 = function(it) {
|
|
2613
|
+
return "object" == typeof it ? null !== it : isCallable$7(it);
|
|
2614
|
+
}, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
|
|
2615
|
+
return isCallable$6(variable) ? variable : void 0;
|
|
2616
|
+
}, navigator = globalThis_1.navigator, userAgent$1 = navigator && navigator.userAgent, globalThis$8 = globalThis_1, userAgent = userAgent$1 ? String(userAgent$1) : "", process$1 = globalThis$8.process, Deno = globalThis$8.Deno, versions = process$1 && process$1.versions || Deno && Deno.version, v8 = versions && versions.v8;
|
|
2617
|
+
|
|
2618
|
+
v8 && (
|
|
2619
|
+
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
|
|
2620
|
+
// but their correct versions are not interesting for us
|
|
2621
|
+
version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
|
|
2622
|
+
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
|
|
2623
|
+
// so check `userAgent` even if `.v8` exists, but 0
|
|
2624
|
+
!version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
2625
|
+
|
|
2626
|
+
var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
|
|
2627
|
+
var symbol = Symbol("symbol detection");
|
|
2628
|
+
// Chrome 38 Symbol has incorrect toString conversion
|
|
2629
|
+
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
|
|
2630
|
+
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
|
|
2631
|
+
// of course, fail.
|
|
2632
|
+
return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
|
|
2633
|
+
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
|
|
2634
|
+
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
|
|
2635
|
+
})), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
|
|
2636
|
+
return "symbol" == typeof it;
|
|
2637
|
+
} : function(it) {
|
|
2638
|
+
var $Symbol = function(namespace, method) {
|
|
2639
|
+
return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$a[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$a[namespace] && globalThis$a[namespace][method];
|
|
2640
|
+
}("Symbol");
|
|
2641
|
+
return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
|
|
2642
|
+
}, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
|
|
2643
|
+
if (isCallable$4(argument)) return argument;
|
|
2644
|
+
throw new $TypeError$5(function(argument) {
|
|
2645
|
+
try {
|
|
2646
|
+
return $String$2(argument);
|
|
2647
|
+
} catch (error) {
|
|
2648
|
+
return "Object";
|
|
2649
|
+
}
|
|
2650
|
+
}(argument) + " is not a function");
|
|
2651
|
+
}, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
|
|
2652
|
+
exports: {}
|
|
2653
|
+
}, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
|
|
2654
|
+
try {
|
|
2655
|
+
defineProperty(globalThis$6, key, {
|
|
2656
|
+
value: value,
|
|
2657
|
+
configurable: !0,
|
|
2658
|
+
writable: !0
|
|
2659
|
+
});
|
|
2660
|
+
} catch (error) {
|
|
2661
|
+
globalThis$6[key] = value;
|
|
2662
|
+
}
|
|
2663
|
+
return value;
|
|
2664
|
+
}("__core-js_shared__", {});
|
|
2665
|
+
|
|
2666
|
+
/* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
|
|
2667
|
+
version: "3.43.0",
|
|
2668
|
+
mode: "pure",
|
|
2669
|
+
copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
|
|
2670
|
+
license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
|
|
2671
|
+
source: "https://github.com/zloirock/core-js"
|
|
2672
|
+
});
|
|
2673
|
+
|
|
2674
|
+
var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
|
|
2675
|
+
return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
|
|
2676
|
+
}, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
|
|
2677
|
+
return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
|
|
2678
|
+
}, wellKnownSymbol$5 = function(name) {
|
|
2679
|
+
return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
|
|
2680
|
+
WellKnownSymbolsStore[name];
|
|
2681
|
+
}, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
|
|
2682
|
+
if (!isObject$3(input) || isSymbol$1(input)) return input;
|
|
2683
|
+
var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
|
|
2684
|
+
if (exoticToPrim) {
|
|
2685
|
+
if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
|
|
2686
|
+
!isObject$3(result) || isSymbol$1(result)) return result;
|
|
2687
|
+
throw new $TypeError$3("Can't convert object to primitive value");
|
|
2688
|
+
}
|
|
2689
|
+
return void 0 === pref && (pref = "number"), function(input, pref) {
|
|
2690
|
+
var fn, val;
|
|
2691
|
+
if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
2692
|
+
if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
|
|
2693
|
+
if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
2694
|
+
throw new $TypeError$4("Can't convert object to primitive value");
|
|
2695
|
+
}(input, pref);
|
|
2696
|
+
}, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
|
|
2697
|
+
var key = toPrimitive(argument, "string");
|
|
2698
|
+
return isSymbol(key) ? key : key + "";
|
|
2699
|
+
}, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
|
|
2700
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
2701
|
+
return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
|
|
2702
|
+
get: function() {
|
|
2703
|
+
return 7;
|
|
2704
|
+
}
|
|
2705
|
+
}).a;
|
|
2706
|
+
var it;
|
|
2707
|
+
})), DESCRIPTORS$3 = descriptors, call = functionCall, propertyIsEnumerableModule = objectPropertyIsEnumerable, createPropertyDescriptor$1 = createPropertyDescriptor$2, toIndexedObject$1 = toIndexedObject$2, toPropertyKey$1 = toPropertyKey$2, hasOwn$1 = hasOwnProperty_1, IE8_DOM_DEFINE$1 = ie8DomDefine, $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
|
|
2708
|
+
|
|
2709
|
+
// `Object.getOwnPropertyDescriptor` method
|
|
2710
|
+
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
|
|
2711
|
+
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
|
|
2712
|
+
if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
|
|
2713
|
+
return $getOwnPropertyDescriptor$1(O, P);
|
|
2714
|
+
} catch (error) {/* empty */}
|
|
2715
|
+
if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
|
|
2716
|
+
};
|
|
2717
|
+
|
|
2718
|
+
var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
|
|
2719
|
+
var value = data[normalize(feature)];
|
|
2720
|
+
return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
|
|
2721
|
+
}, normalize = isForced$1.normalize = function(string) {
|
|
2722
|
+
return String(string).replace(replacement, ".").toLowerCase();
|
|
2723
|
+
}, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable = aCallable$2, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$8((function() {
|
|
2724
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
2725
|
+
return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
|
|
2726
|
+
value: 42,
|
|
2727
|
+
writable: !1
|
|
2728
|
+
}).prototype;
|
|
2729
|
+
})), isObject$1 = isObject$5, $String$1 = String, $TypeError$2 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
|
|
2730
|
+
if (isObject$1(argument)) return argument;
|
|
2731
|
+
throw new $TypeError$2($String$1(argument) + " is not an object");
|
|
2732
|
+
}, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
2733
|
+
|
|
2734
|
+
// `Object.defineProperty` method
|
|
2735
|
+
// https://tc39.es/ecma262/#sec-object.defineproperty
|
|
2736
|
+
objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
|
|
2737
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
|
|
2738
|
+
var current = $getOwnPropertyDescriptor(O, P);
|
|
2739
|
+
current && current.writable && (O[P] = Attributes.value, Attributes = {
|
|
2740
|
+
configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
|
|
2741
|
+
enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
|
|
2742
|
+
writable: !1
|
|
2743
|
+
});
|
|
2744
|
+
}
|
|
2745
|
+
return $defineProperty(O, P, Attributes);
|
|
2746
|
+
} : $defineProperty : function(O, P, Attributes) {
|
|
2747
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
|
|
2748
|
+
return $defineProperty(O, P, Attributes);
|
|
2749
|
+
} catch (error) {/* empty */}
|
|
2750
|
+
if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
|
|
2751
|
+
return "value" in Attributes && (O[P] = Attributes.value), O;
|
|
2752
|
+
};
|
|
2753
|
+
|
|
2754
|
+
var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
|
|
2755
|
+
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
|
|
2756
|
+
} : function(object, key, value) {
|
|
2757
|
+
return object[key] = value, object;
|
|
2758
|
+
}, globalThis$2 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
|
|
2759
|
+
return aCallable(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
|
|
2760
|
+
return fn.apply(that, arguments);
|
|
2761
|
+
};
|
|
2762
|
+
}, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
|
|
2763
|
+
var Wrapper = function(a, b, c) {
|
|
2764
|
+
if (this instanceof Wrapper) {
|
|
2765
|
+
switch (arguments.length) {
|
|
2766
|
+
case 0:
|
|
2767
|
+
return new NativeConstructor;
|
|
2768
|
+
|
|
2769
|
+
case 1:
|
|
2770
|
+
return new NativeConstructor(a);
|
|
2771
|
+
|
|
2772
|
+
case 2:
|
|
2773
|
+
return new NativeConstructor(a, b);
|
|
2774
|
+
}
|
|
2775
|
+
return new NativeConstructor(a, b, c);
|
|
2776
|
+
}
|
|
2777
|
+
return apply(NativeConstructor, this, arguments);
|
|
2778
|
+
};
|
|
2779
|
+
return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
|
|
2780
|
+
}, _export = function(options, source) {
|
|
2781
|
+
var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$2 : STATIC ? globalThis$2[TARGET] : globalThis$2[TARGET] && globalThis$2[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
|
|
2782
|
+
for (key in source)
|
|
2783
|
+
// contains in native
|
|
2784
|
+
USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
|
|
2785
|
+
targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
|
|
2786
|
+
// export native or implementation
|
|
2787
|
+
sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
|
|
2788
|
+
// bind methods to global for calling from export context
|
|
2789
|
+
resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
|
|
2790
|
+
// add a flag to not completely full polyfills
|
|
2791
|
+
(options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
|
|
2792
|
+
createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
|
|
2793
|
+
// export virtual prototype methods
|
|
2794
|
+
createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
|
|
2795
|
+
// export real prototype methods
|
|
2796
|
+
options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
|
|
2797
|
+
}, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
|
|
2798
|
+
var n = +x;
|
|
2799
|
+
return (n > 0 ? floor : ceil)(n);
|
|
2800
|
+
}, toIntegerOrInfinity$2 = function(argument) {
|
|
2801
|
+
var number = +argument;
|
|
2802
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2803
|
+
return number != number || 0 === number ? 0 : trunc(number);
|
|
2804
|
+
}, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
|
|
2805
|
+
return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
|
|
2806
|
+
var argument, len;
|
|
2807
|
+
}, createMethod = function(IS_INCLUDES) {
|
|
2808
|
+
return function($this, el, fromIndex) {
|
|
2809
|
+
var O = toIndexedObject($this), length = lengthOfArrayLike(O);
|
|
2810
|
+
if (0 === length) return !IS_INCLUDES && -1;
|
|
2811
|
+
var value, index = function(index, length) {
|
|
2812
|
+
var integer = toIntegerOrInfinity$1(index);
|
|
2813
|
+
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
|
|
2814
|
+
}(fromIndex, length);
|
|
2815
|
+
// Array#includes uses SameValueZero equality algorithm
|
|
2816
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2817
|
+
if (IS_INCLUDES && el != el) {
|
|
2818
|
+
for (;length > index; )
|
|
2819
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2820
|
+
if ((value = O[index++]) != value) return !0;
|
|
2821
|
+
// Array#indexOf ignores holes, Array#includes - not
|
|
2822
|
+
} else for (;length > index; index++) if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
|
|
2823
|
+
return !IS_INCLUDES && -1;
|
|
2824
|
+
};
|
|
2825
|
+
}, $includes = [ createMethod(!0), createMethod(!1) ][0];
|
|
2826
|
+
|
|
2827
|
+
// `Array.prototype.includes` method
|
|
2828
|
+
// https://tc39.es/ecma262/#sec-array.prototype.includes
|
|
2829
|
+
_export({
|
|
2830
|
+
target: "Array",
|
|
2831
|
+
proto: !0,
|
|
2832
|
+
forced: fails$8((function() {
|
|
2833
|
+
// eslint-disable-next-line es/no-array-prototype-includes -- detection
|
|
2834
|
+
return !Array(1).includes();
|
|
2835
|
+
}))
|
|
2836
|
+
}, {
|
|
2837
|
+
includes: function(el /* , fromIndex = 0 */) {
|
|
2838
|
+
return $includes(this, el, arguments.length > 1 ? arguments[1] : void 0);
|
|
2839
|
+
}
|
|
2840
|
+
});
|
|
2841
|
+
|
|
2842
|
+
var globalThis$1 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$2 = function(CONSTRUCTOR, METHOD) {
|
|
2843
|
+
var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
|
|
2844
|
+
if (pureMethod) return pureMethod;
|
|
2845
|
+
var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
2846
|
+
return NativePrototype && NativePrototype[METHOD];
|
|
2847
|
+
}, includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
|
|
2848
|
+
|
|
2849
|
+
test[wellKnownSymbol$5("toStringTag")] = "z";
|
|
2850
|
+
|
|
2851
|
+
var TO_STRING_TAG_SUPPORT = "[object z]" === String(test), isCallable = isCallable$8, classofRaw = classofRaw$2, TO_STRING_TAG = wellKnownSymbol$5("toStringTag"), $Object = Object, CORRECT_ARGUMENTS = "Arguments" === classofRaw(function() {
|
|
2852
|
+
return arguments;
|
|
2853
|
+
}()), classof = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
|
|
2854
|
+
var O, tag, result;
|
|
2855
|
+
return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (tag = function(it, key) {
|
|
2856
|
+
try {
|
|
2857
|
+
return it[key];
|
|
2858
|
+
} catch (error) {/* empty */}
|
|
2859
|
+
}(O = $Object(it), TO_STRING_TAG)) ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : "Object" === (result = classofRaw(O)) && isCallable(O.callee) ? "Arguments" : result;
|
|
2860
|
+
}, $String = String, MATCH = wellKnownSymbol$5("match"), $ = _export, notARegExp = function(it) {
|
|
2861
|
+
if (function(it) {
|
|
2862
|
+
var isRegExp;
|
|
2863
|
+
return isObject(it) && (void 0 !== (isRegExp = it[MATCH$1]) ? !!isRegExp : "RegExp" === classof$2(it));
|
|
2864
|
+
}(it)) throw new $TypeError("The method doesn't accept regular expressions");
|
|
2865
|
+
return it;
|
|
2866
|
+
}, requireObjectCoercible = requireObjectCoercible$3, toString = function(argument) {
|
|
2867
|
+
if ("Symbol" === classof(argument)) throw new TypeError("Cannot convert a Symbol value to a string");
|
|
2868
|
+
return $String(argument);
|
|
2869
|
+
}, stringIndexOf = functionUncurryThis("".indexOf);
|
|
2870
|
+
|
|
2871
|
+
// `String.prototype.includes` method
|
|
2872
|
+
// https://tc39.es/ecma262/#sec-string.prototype.includes
|
|
2873
|
+
$({
|
|
2874
|
+
target: "String",
|
|
2875
|
+
proto: !0,
|
|
2876
|
+
forced: !function(METHOD_NAME) {
|
|
2877
|
+
var regexp = /./;
|
|
2878
|
+
try {
|
|
2879
|
+
"/./"[METHOD_NAME](regexp);
|
|
2880
|
+
} catch (error1) {
|
|
2881
|
+
try {
|
|
2882
|
+
return regexp[MATCH] = !1, "/./"[METHOD_NAME](regexp);
|
|
2883
|
+
} catch (error2) {/* empty */}
|
|
2884
|
+
}
|
|
2885
|
+
return !1;
|
|
2886
|
+
}("includes")
|
|
2887
|
+
}, {
|
|
2888
|
+
includes: function(searchString /* , position = 0 */) {
|
|
2889
|
+
return !!~stringIndexOf(toString(requireObjectCoercible(this)), toString(notARegExp(searchString)), arguments.length > 1 ? arguments[1] : void 0);
|
|
2890
|
+
}
|
|
2891
|
+
});
|
|
2892
|
+
|
|
2893
|
+
var includes$3 = getBuiltInPrototypeMethod$2("String", "includes"), isPrototypeOf = objectIsPrototypeOf, arrayMethod = includes$4, stringMethod = includes$3, ArrayPrototype = Array.prototype, StringPrototype = String.prototype;
|
|
2894
|
+
|
|
2895
|
+
const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
2896
|
+
var own = it.includes;
|
|
2897
|
+
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.includes ? arrayMethod : "string" == typeof it || it === StringPrototype || isPrototypeOf(StringPrototype, it) && own === StringPrototype.includes ? stringMethod : own;
|
|
2898
|
+
})), Callout = ({title: title, children: children, icon: icon, variant: variant = "primary", onClose: onClose, actions: actions, oneLine: oneLine = !1, toast: toast = !1, glass: glass, className: className, style: style, ...props}) => {
|
|
2899
|
+
const {generateCalloutClass: generateCalloutClass, handleClose: handleClose} =
|
|
2900
|
+
/**
|
|
2901
|
+
* Callout state and functionality
|
|
2902
|
+
* @param initialProps - Initial callout properties
|
|
2903
|
+
* @returns Callout state and methods
|
|
2904
|
+
*/
|
|
2905
|
+
function(initialProps) {
|
|
2906
|
+
// Default callout properties
|
|
2907
|
+
const defaultProps = {
|
|
2908
|
+
variant: "primary",
|
|
2909
|
+
oneLine: !1,
|
|
2910
|
+
toast: !1,
|
|
2911
|
+
glass: !1,
|
|
2912
|
+
...initialProps
|
|
2913
|
+
};
|
|
2914
|
+
/**
|
|
2915
|
+
* Generate callout class based on properties
|
|
2916
|
+
* @param props - Callout properties
|
|
2917
|
+
* @returns Class string
|
|
2918
|
+
*/ return {
|
|
2919
|
+
defaultProps: defaultProps,
|
|
2920
|
+
generateCalloutClass: props => {
|
|
2921
|
+
const {variant: variant = defaultProps.variant, oneLine: oneLine = defaultProps.oneLine, toast: toast = defaultProps.toast, glass: glass = defaultProps.glass, className: className = ""} = props;
|
|
2922
|
+
return `c-callout ${variant ? `c-callout--${variant}` : ""} ${oneLine ? "c-callout--oneline" : ""} ${toast ? "c-callout--toast" : ""} ${glass ? "c-callout--glass" : ""} ${className}`.trim();
|
|
2923
|
+
},
|
|
2924
|
+
handleClose: handler => () => {
|
|
2925
|
+
handler && handler();
|
|
2926
|
+
}
|
|
2927
|
+
};
|
|
2928
|
+
}
|
|
2929
|
+
/**
|
|
2930
|
+
* Callout component for displaying important messages, notifications, or alerts
|
|
2931
|
+
*/ ({
|
|
2932
|
+
variant: variant,
|
|
2933
|
+
oneLine: oneLine,
|
|
2934
|
+
toast: toast,
|
|
2935
|
+
glass: glass,
|
|
2936
|
+
className: className,
|
|
2937
|
+
style: style
|
|
2938
|
+
}), getAriaAttributes = () => {
|
|
2939
|
+
var _context, _context2;
|
|
2940
|
+
const baseAttributes = {
|
|
2941
|
+
role: "region"
|
|
2942
|
+
};
|
|
2943
|
+
// For toast notifications or alerts, use appropriate role and live region
|
|
2944
|
+
return toast ? (baseAttributes.role = "alert", baseAttributes["aria-live"] = "polite") : _includesInstanceProperty(_context = [ "warning", "error" ]).call(_context, variant) ? (baseAttributes.role = "alert",
|
|
2945
|
+
baseAttributes["aria-live"] = "assertive") : _includesInstanceProperty(_context2 = [ "info", "success" ]).call(_context2, variant) && (baseAttributes.role = "status",
|
|
2946
|
+
baseAttributes["aria-live"] = "polite"), baseAttributes;
|
|
2947
|
+
}, calloutContent = jsxs(Fragment, {
|
|
2948
|
+
children: [ jsxs("div", {
|
|
2949
|
+
className: "c-callout__content",
|
|
2950
|
+
children: [ icon && jsx("div", {
|
|
2951
|
+
className: "c-callout__icon",
|
|
2952
|
+
children: icon
|
|
2953
|
+
}), jsxs("div", {
|
|
2954
|
+
className: "c-callout__message",
|
|
2955
|
+
children: [ title && jsx("div", {
|
|
2956
|
+
className: "c-callout__title",
|
|
2957
|
+
children: title
|
|
2958
|
+
}), children && jsx("div", {
|
|
2959
|
+
className: "c-callout__text",
|
|
2960
|
+
children: children
|
|
2961
|
+
}) ]
|
|
2962
|
+
}) ]
|
|
2963
|
+
}), actions && jsx("div", {
|
|
2964
|
+
className: "c-callout__actions",
|
|
2965
|
+
children: actions
|
|
2966
|
+
}), onClose && jsx("button", {
|
|
2967
|
+
className: "c-callout__close-btn",
|
|
2968
|
+
onClick: handleClose(onClose),
|
|
2969
|
+
"aria-label": "Close",
|
|
2970
|
+
children: jsx(Icon, {
|
|
2971
|
+
name: "X",
|
|
2972
|
+
size: "md"
|
|
2973
|
+
})
|
|
2974
|
+
}) ]
|
|
2975
|
+
});
|
|
2976
|
+
// Determine appropriate ARIA attributes based on variant
|
|
2977
|
+
if (glass) {
|
|
2978
|
+
// Default glass settings for callouts
|
|
2979
|
+
const defaultGlassProps = {
|
|
2980
|
+
displacementScale: 30,
|
|
2981
|
+
cornerRadius: 8,
|
|
2982
|
+
elasticity: 0
|
|
2983
|
+
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2984
|
+
...defaultGlassProps,
|
|
2985
|
+
...glass
|
|
2986
|
+
};
|
|
2987
|
+
return jsx("div", {
|
|
2988
|
+
className: generateCalloutClass({
|
|
2989
|
+
variant: variant,
|
|
2990
|
+
oneLine: oneLine,
|
|
2991
|
+
toast: toast,
|
|
2992
|
+
glass: glass,
|
|
2993
|
+
className: className
|
|
2994
|
+
}),
|
|
2995
|
+
...getAriaAttributes(),
|
|
2996
|
+
...props,
|
|
2997
|
+
style: style,
|
|
2998
|
+
children: jsx(AtomixGlass, {
|
|
2999
|
+
...glassProps,
|
|
3000
|
+
children: jsx("div", {
|
|
3001
|
+
className: "c-callout__glass-content",
|
|
3002
|
+
style: {
|
|
3003
|
+
borderRadius: glassProps.cornerRadius
|
|
3004
|
+
},
|
|
3005
|
+
children: calloutContent
|
|
3006
|
+
})
|
|
3007
|
+
})
|
|
3008
|
+
});
|
|
3009
|
+
}
|
|
3010
|
+
return jsx("div", {
|
|
3011
|
+
className: generateCalloutClass({
|
|
3012
|
+
variant: variant,
|
|
3013
|
+
oneLine: oneLine,
|
|
3014
|
+
toast: toast,
|
|
3015
|
+
glass: glass,
|
|
3016
|
+
className: className
|
|
3017
|
+
}),
|
|
3018
|
+
...getAriaAttributes(),
|
|
3019
|
+
...props,
|
|
3020
|
+
style: style,
|
|
3021
|
+
children: calloutContent
|
|
3022
|
+
});
|
|
3023
|
+
};
|
|
3024
|
+
|
|
3025
|
+
Callout.displayName = "Callout";
|
|
3026
|
+
|
|
3027
|
+
const List = memo((({children: children, variant: variant = "default", className: className = "", style: style, ...props}) => {
|
|
3028
|
+
var _context;
|
|
3029
|
+
// Generate CSS classes
|
|
3030
|
+
const listClasses = [ LIST.BASE_CLASS, "default" !== variant && `c-list--${variant}`, className ].filter(Boolean).join(" "), ListElement = _includesInstanceProperty(_context = [ "number", "text" ]).call(_context, variant) ? "ol" : "ul";
|
|
3031
|
+
// Determine the HTML element based on variant
|
|
3032
|
+
return jsx(ListElement, {
|
|
3033
|
+
className: listClasses,
|
|
3034
|
+
style: style,
|
|
3035
|
+
...props,
|
|
3036
|
+
children: React.Children.map(children, (child => jsx("li", {
|
|
3037
|
+
className: "c-list__item",
|
|
3038
|
+
children: child
|
|
3039
|
+
})))
|
|
3040
|
+
});
|
|
3041
|
+
}));
|
|
3042
|
+
|
|
3043
|
+
List.displayName = "List";
|
|
3044
|
+
|
|
3045
|
+
const ListGroup = ({children: children, className: className = "", style: style, variant: variant = "default"}) => {
|
|
3046
|
+
// Generate CSS classes
|
|
3047
|
+
const listGroupClasses = [ LIST_GROUP.BASE_CLASS, className ].filter(Boolean).join(" "), validLists = React.Children.toArray(children).filter((child => React.isValidElement(child) && child.type === List));
|
|
3048
|
+
// Get valid List children
|
|
3049
|
+
return jsx("div", {
|
|
3050
|
+
className: listGroupClasses,
|
|
3051
|
+
style: style,
|
|
3052
|
+
children: validLists.map(((child, index) => {
|
|
3053
|
+
const childProps = child.props;
|
|
3054
|
+
|
|
3055
|
+
return React.cloneElement(child, {
|
|
3056
|
+
key: index,
|
|
3057
|
+
variant: childProps?.variant ?? variant
|
|
3058
|
+
});
|
|
3059
|
+
}))
|
|
3060
|
+
});
|
|
3061
|
+
};
|
|
3062
|
+
|
|
3063
|
+
ListGroup.displayName = "ListGroup";
|
|
3064
|
+
|
|
3065
|
+
// Adapted from https://github.com/shuding/liquid-glass
|
|
3066
|
+
// Constants
|
|
3067
|
+
const smoothStep = (a, b, t) => {
|
|
3068
|
+
// Add input validation
|
|
3069
|
+
if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
|
|
3070
|
+
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
|
|
3071
|
+
return clamped * clamped * (3 - 2 * clamped);
|
|
3072
|
+
}, calculateLength = (x, y) => {
|
|
3073
|
+
// Add input validation and error handling
|
|
3074
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
3075
|
+
// Prevent potential overflow
|
|
3076
|
+
const maxX = Math.max(Math.abs(x), Math.abs(y));
|
|
3077
|
+
if (0 === maxX) return 0;
|
|
3078
|
+
const scaledX = x / maxX, scaledY = y / maxX;
|
|
3079
|
+
return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
3080
|
+
}, roundedRectSDF = (x, y, width, height, radius) => {
|
|
3081
|
+
// Add input validation
|
|
3082
|
+
if ("number" != typeof x || "number" != typeof y || "number" != typeof width || "number" != typeof height || "number" != typeof radius) return 0;
|
|
3083
|
+
const qx = Math.abs(x) - width + radius, qy = Math.abs(y) - height + radius;
|
|
3084
|
+
return Math.min(Math.max(qx, qy), 0) + calculateLength(Math.max(qx, 0), Math.max(qy, 0)) - radius;
|
|
3085
|
+
}, createTexture = (x, y) => ({
|
|
3086
|
+
x: "number" != typeof x || isNaN(x) ? .5 : Math.max(0, Math.min(1, x)),
|
|
3087
|
+
y: "number" != typeof y || isNaN(y) ? .5 : Math.max(0, Math.min(1, y))
|
|
3088
|
+
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), clampValue = (value, min, max) =>
|
|
3089
|
+
// Add input validation
|
|
3090
|
+
"number" != typeof value || "number" != typeof min || "number" != typeof max || isNaN(value) ? min : isNaN(min) ? 0 : isNaN(max) ? 1 : Math.max(min, Math.min(max, value)), easeInOutCubic = t => {
|
|
3091
|
+
// Add input validation
|
|
3092
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
3093
|
+
const clampedT = Math.max(0, Math.min(1, t));
|
|
3094
|
+
return clampedT < .5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
|
|
3095
|
+
}, easeOutQuart = t => {
|
|
3096
|
+
// Add input validation
|
|
3097
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
3098
|
+
const clampedT = Math.max(0, Math.min(1, t));
|
|
3099
|
+
return 1 - Math.pow(1 - clampedT, 4);
|
|
3100
|
+
}, noise2D = (x, y) => {
|
|
3101
|
+
// Add input validation
|
|
3102
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
3103
|
+
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = easeInOutCubic(xf), v = easeInOutCubic(yf), hash = (i, j) => {
|
|
3104
|
+
// Add input validation
|
|
3105
|
+
if ("number" != typeof i || "number" != typeof j) return 0;
|
|
3106
|
+
const n = i + 57 * j, hashed = 43758.5453 * Math.sin(12.9898 * n + 78.233);
|
|
3107
|
+
// Use a more stable hash function
|
|
3108
|
+
return hashed - Math.floor(hashed);
|
|
3109
|
+
}, a = hash(X, Y), b = hash(X + 1, Y), c = hash(X, Y + 1), x1 = a + u * (b - a);
|
|
3110
|
+
return x1 + v * (c + u * (hash(X + 1, Y + 1) - c) - x1);
|
|
3111
|
+
}, fbm = (x, y, octaves = 4) => {
|
|
3112
|
+
// Add input validation
|
|
3113
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
3114
|
+
// Clamp octaves to prevent performance issues
|
|
3115
|
+
const clampedOctaves = Math.max(1, Math.min(8, Math.floor(octaves)));
|
|
3116
|
+
let value = 0, amplitude = .5, frequency = 1;
|
|
3117
|
+
for (let i = 0; i < clampedOctaves; i++) value += amplitude * noise2D(x * frequency, y * frequency),
|
|
3118
|
+
frequency *= 2, amplitude *= .5;
|
|
3119
|
+
return value;
|
|
3120
|
+
}, calculateParallaxOffset = (x, y, depth, mouseX = 0, mouseY = 0) => {
|
|
3121
|
+
// Add input validation
|
|
3122
|
+
if ("number" != typeof x || "number" != typeof y || "number" != typeof depth || "number" != typeof mouseX || "number" != typeof mouseY || isNaN(x) || isNaN(y) || isNaN(depth) || isNaN(mouseX) || isNaN(mouseY)) return {
|
|
3123
|
+
x: 0,
|
|
3124
|
+
y: 0
|
|
3125
|
+
};
|
|
3126
|
+
const parallaxStrength = Math.min(.02 * depth, .1);
|
|
3127
|
+
// Limit strength to prevent extreme values
|
|
3128
|
+
// Calculate offset based on view angle (simulated by mouse position)
|
|
3129
|
+
return {
|
|
3130
|
+
x: (x - mouseX) * parallaxStrength,
|
|
3131
|
+
y: (y - mouseY) * parallaxStrength
|
|
3132
|
+
};
|
|
3133
|
+
}, fragmentShaders = {
|
|
3134
|
+
liquidGlass: (uv, mousePosition) => {
|
|
3135
|
+
if (!validateVec2(uv)) return {
|
|
3136
|
+
x: .5,
|
|
3137
|
+
y: .5
|
|
3138
|
+
};
|
|
3139
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now(), mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(2 * mouseDistance, 1)), organicFlow = fbm(12 * (ix + .5 * mouseX) + time, 12 * (iy + .5 * mouseY) + .7 * time, 3) - .5, distanceToEdge = roundedRectSDF(ix, iy, .4, .3, .35), baseDisplacement = smoothStep(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
|
|
3140
|
+
// Add input validation
|
|
3141
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y) || isNaN(strength)) return {
|
|
3142
|
+
x: 0,
|
|
3143
|
+
y: 0
|
|
3144
|
+
};
|
|
3145
|
+
const distance = calculateLength(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
|
|
3146
|
+
// Limit distance to prevent extreme values
|
|
3147
|
+
return {
|
|
3148
|
+
x: x * (1 + distortion),
|
|
3149
|
+
y: y * (1 + distortion)
|
|
3150
|
+
};
|
|
3151
|
+
})(ix, iy, .4 * .1), refractionX = 1.2 * (radialDist.x - ix) * baseDisplacement, refractionY = 1.2 * (radialDist.y - iy) * baseDisplacement, flowX = .018 * Math.sin(8 * (ix + 2 * mouseX) + 2 * time), flowY = .018 * Math.cos(8 * (iy + 2 * mouseY) + 1.5 * time), rippleEffect = (.015 * Math.sin(12 * (ix - mouseX) + 12 * (iy - mouseY) + 3 * time) + .012 * Math.cos(10 * (ix + mouseX) - 10 * (iy - mouseY) - 2 * time)) * mouseFalloff * mouseDistance, depthEffect = (Math.sin(15 * ix + time) * Math.cos(15 * iy - time) * .008 + Math.sin(20 * ix - .5 * time) * Math.cos(20 * iy + .5 * time) * .006) * baseDisplacement, liquidFlow = .85 * (flowX + flowY + .025 * organicFlow), totalDistortionX = refractionX + liquidFlow + rippleEffect + depthEffect, totalDistortionY = refractionY + .8 * liquidFlow + .9 * rippleEffect + depthEffect, chromaticOffset = ((x, y, intensity) => {
|
|
3152
|
+
// Add input validation
|
|
3153
|
+
if ("number" != typeof x || "number" != typeof y || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(intensity)) return {
|
|
3154
|
+
x: 0,
|
|
3155
|
+
y: 0
|
|
3156
|
+
};
|
|
3157
|
+
const distance = calculateLength(x, y);
|
|
3158
|
+
// Prevent division by zero and extreme values
|
|
3159
|
+
if (0 === distance) return {
|
|
3160
|
+
x: 0,
|
|
3161
|
+
y: 0
|
|
3162
|
+
};
|
|
3163
|
+
const angle = Math.atan2(y, x);
|
|
3164
|
+
return {
|
|
3165
|
+
x: Math.cos(angle) * distance * intensity,
|
|
3166
|
+
y: Math.sin(angle) * distance * intensity
|
|
3167
|
+
};
|
|
3168
|
+
})(ix, iy, .015 * baseDisplacement), scaled = smoothStep(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
|
|
3169
|
+
return createTexture(clampValue(finalX * scaled + .5, 0, 1), clampValue(finalY * scaled + .5, 0, 1));
|
|
3170
|
+
},
|
|
3171
|
+
// Premium Apple-style fluid glass with enhanced organic flow
|
|
3172
|
+
appleFluid: (uv, mousePosition) => {
|
|
3173
|
+
if (!validateVec2(uv)) return {
|
|
3174
|
+
x: .5,
|
|
3175
|
+
y: .5
|
|
3176
|
+
};
|
|
3177
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .6, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.5 * mouseDistance, 1)), organicX = fbm(10 * (ix + .3 * mouseX) + time, 10 * (iy + .3 * mouseY), 5) - .5, organicY = fbm(10 * (ix - .3 * mouseX), 10 * (iy - .3 * mouseY) + .8 * time, 5) - .5, distanceToEdge = roundedRectSDF(ix, iy, .42, .32, .38), mask = smoothStep(.85, -.1, distanceToEdge), fluidVelocityX = Math.sin(6 * ix + 2 * time) * Math.cos(4 * iy - time) * .025, fluidVelocityY = Math.cos(4 * ix - time) * Math.sin(6 * iy + 2 * time) * .025, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexStrength = mouseFalloff * mouseDistance * .08, vortexX = Math.cos(vortexAngle + time) * vortexStrength, totalY = iy + (.035 * organicY + fluidVelocityY + Math.sin(vortexAngle + time) * vortexStrength) * mask;
|
|
3178
|
+
return createTexture(clampValue(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clampValue(totalY + .5, 0, 1));
|
|
3179
|
+
},
|
|
3180
|
+
// High-end glass with advanced refraction and depth
|
|
3181
|
+
premiumGlass: (uv, mousePosition) => {
|
|
3182
|
+
if (!validateVec2(uv)) return {
|
|
3183
|
+
x: .5,
|
|
3184
|
+
y: .5
|
|
3185
|
+
};
|
|
3186
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .4, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), centerDistance = calculateLength(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
|
|
3187
|
+
// Multi-layer depth effect
|
|
3188
|
+
let depthX = 0, depthY = 0;
|
|
3189
|
+
for (let layer = 0; layer < 3; layer++) {
|
|
3190
|
+
const layerScale = 5 * (layer + 1), layerTime = time * (1 + .3 * layer), layerStrength = .01 / (layer + 1);
|
|
3191
|
+
depthX += Math.sin(ix * layerScale + layerTime) * layerStrength, depthY += Math.cos(iy * layerScale - layerTime) * layerStrength;
|
|
3192
|
+
}
|
|
3193
|
+
// Glass refraction with mouse influence
|
|
3194
|
+
const refractionX = Math.cos(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), refractionY = Math.sin(refractionAngle) * refractionStrength * (1 + .5 * mouseDistance), organicNoise = fbm(8 * ix + time, 8 * iy - time, 2) - .5, distanceToEdge = roundedRectSDF(ix, iy, .43, .33, .36), edgeMask = smoothStep(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
|
|
3195
|
+
return createTexture(clampValue(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clampValue(finalY + .5, 0, 1));
|
|
3196
|
+
},
|
|
3197
|
+
// Metallic liquid effect with shimmer
|
|
3198
|
+
liquidMetal: (uv, mousePosition) => {
|
|
3199
|
+
if (!validateVec2(uv)) return {
|
|
3200
|
+
x: .5,
|
|
3201
|
+
y: .5
|
|
3202
|
+
};
|
|
3203
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * 1.2, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, wave1 = Math.sin(20 * ix + 4 * time) * Math.cos(15 * iy - 3 * time) * .02, wave2 = Math.cos(15 * ix - 2 * time) * Math.sin(20 * iy + 5 * time) * .015, shimmer = .025 * fbm(25 * ix + 2 * time, 25 * iy - 2 * time, 4), flowAngle = Math.atan2(iy - mouseY, ix - mouseX), flowDistance = calculateLength(ix - mouseX, iy - mouseY), flowEffect = .02 * Math.sin(15 * flowDistance - 6 * time) * easeOutQuart(1 - Math.min(2 * flowDistance, 1)), distanceToEdge = roundedRectSDF(ix, iy, .41, .31, .37), mask = smoothStep(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
|
|
3204
|
+
return createTexture(clampValue(totalX + .5, 0, 1), clampValue(totalY + .5, 0, 1));
|
|
3205
|
+
},
|
|
3206
|
+
// basiBasi - Expert Premium Glass Shader
|
|
3207
|
+
// The most advanced shader with caustics, spectral dispersion, parallax depth, and volumetric effects
|
|
3208
|
+
basiBasi: (uv, mousePosition) => {
|
|
3209
|
+
if (!validateVec2(uv)) return {
|
|
3210
|
+
x: .5,
|
|
3211
|
+
y: .5
|
|
3212
|
+
};
|
|
3213
|
+
const ix = uv.x - .5, iy = uv.y - .5, time = 8e-4 * Date.now() * .5, mouseX = mousePosition && validateVec2(mousePosition) ? mousePosition.x - .5 : 0, mouseY = mousePosition && validateVec2(mousePosition) ? mousePosition.y - .5 : 0, mouseDistance = calculateLength(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
|
|
3214
|
+
// Add input validation
|
|
3215
|
+
"number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof intensity || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(intensity) ? .5 : .5 * (Math.sin(8 * x + 2 * time) * Math.cos(8 * y - 2 * time) * .5 + Math.sin(8 * (x + .5) * 1.3 - 2 * time * .8) * Math.cos(8 * (y - .3) * 1.3 + 2 * time * .8) * .3 + Math.sin(8 * (x - .3) * .7 + 2 * time * 1.2) * Math.cos(8 * (y + .4) * .7 - 2 * time * 1.2) * .2 + 1) * intensity)(ix, iy, time, .8), causticDistortion = .02 * (causticIntensity - .5), refractionAngle = Math.atan2(iy, ix), spectralDispersion = ((x, y, angle) => {
|
|
3216
|
+
// Add input validation
|
|
3217
|
+
if ("number" != typeof x || "number" != typeof y || "number" != typeof angle || isNaN(x) || isNaN(y) || isNaN(angle) || isNaN(.025)) return {
|
|
3218
|
+
r: {
|
|
3219
|
+
x: 0,
|
|
3220
|
+
y: 0
|
|
3221
|
+
},
|
|
3222
|
+
g: {
|
|
3223
|
+
x: 0,
|
|
3224
|
+
y: 0
|
|
3225
|
+
},
|
|
3226
|
+
b: {
|
|
3227
|
+
x: 0,
|
|
3228
|
+
y: 0
|
|
3229
|
+
}
|
|
3230
|
+
};
|
|
3231
|
+
const distance = calculateLength(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
|
|
3232
|
+
return {
|
|
3233
|
+
r: {
|
|
3234
|
+
x: Math.cos(angle) * redOffset,
|
|
3235
|
+
y: Math.sin(angle) * redOffset
|
|
3236
|
+
},
|
|
3237
|
+
g: {
|
|
3238
|
+
x: Math.cos(angle) * greenOffset,
|
|
3239
|
+
y: Math.sin(angle) * greenOffset
|
|
3240
|
+
},
|
|
3241
|
+
b: {
|
|
3242
|
+
x: Math.cos(angle) * blueOffset,
|
|
3243
|
+
y: Math.sin(angle) * blueOffset
|
|
3244
|
+
}
|
|
3245
|
+
};
|
|
3246
|
+
})(ix, iy, refractionAngle), spectralX = (spectralDispersion.r.x + spectralDispersion.g.x + spectralDispersion.b.x) / 3, spectralY = (spectralDispersion.r.y + spectralDispersion.g.y + spectralDispersion.b.y) / 3;
|
|
3247
|
+
// === MULTI-LAYER PARALLAX DEPTH ===
|
|
3248
|
+
// Create depth perception with 7 layers
|
|
3249
|
+
let parallaxX = 0, parallaxY = 0;
|
|
3250
|
+
for (let layer = 0; layer < 7; layer++) {
|
|
3251
|
+
const parallaxOffset = calculateParallaxOffset(ix, iy, (layer + 1) / 7, mouseX, mouseY), layerNoise = fbm((ix + parallaxOffset.x) * (8 + 2 * layer) + time * (.5 + .1 * layer), (iy + parallaxOffset.y) * (8 + 2 * layer) - time * (.5 + .1 * layer), 3) - .5, layerWeight = 1 / (layer + 1);
|
|
3252
|
+
parallaxX += (parallaxOffset.x + .01 * layerNoise) * layerWeight, parallaxY += (parallaxOffset.y + .01 * layerNoise) * layerWeight;
|
|
3253
|
+
}
|
|
3254
|
+
// Normalize parallax effect
|
|
3255
|
+
parallaxX /= 7, parallaxY /= 7;
|
|
3256
|
+
// === VOLUMETRIC SCATTERING ===
|
|
3257
|
+
// Simulate light scattering through glass volume
|
|
3258
|
+
const volumetricDensity = ((x, y, depth, time) =>
|
|
3259
|
+
// Add input validation
|
|
3260
|
+
"number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(.5) || isNaN(time) ? .5 : fbm(5 * x + .5 * time, 5 * y - .5 * time, 3) * Math.exp(2 * -Math.max(0, .5)) * .5 + .5)(ix, iy, 0, time), scatteringX = Math.cos(refractionAngle) * volumetricDensity * .015, scatteringY = Math.sin(refractionAngle) * volumetricDensity * .015, turbulence = ((x, y, time, octaves = 5) => {
|
|
3261
|
+
// Add input validation
|
|
3262
|
+
if ("number" != typeof x || "number" != typeof y || "number" != typeof time || "number" != typeof octaves || isNaN(x) || isNaN(y) || isNaN(time) || isNaN(octaves)) return 0;
|
|
3263
|
+
// Clamp octaves to prevent performance issues
|
|
3264
|
+
const clampedOctaves = Math.max(1, Math.min(8, Math.floor(octaves)));
|
|
3265
|
+
let turbulence = 0, amplitude = 1, frequency = 1;
|
|
3266
|
+
for (let i = 0; i < clampedOctaves; i++) turbulence += Math.abs(noise2D(x * frequency + time, y * frequency - time)) * amplitude,
|
|
3267
|
+
frequency *= 2, amplitude *= .5;
|
|
3268
|
+
return turbulence;
|
|
3269
|
+
})(6 * ix, 6 * iy, time, 6), turbulenceX = .012 * Math.cos(turbulence * Math.PI * 2), turbulenceY = .012 * Math.sin(turbulence * Math.PI * 2), microSurface = ((x, y, time) =>
|
|
3270
|
+
// Add input validation
|
|
3271
|
+
"number" != typeof x || "number" != typeof y || "number" != typeof time || isNaN(x) || isNaN(y) || isNaN(time) ? .5 : .5 * (.7 * fbm(40 * x + .3 * time, 40 * y - .3 * time, 6) + .3 * fbm(80 * x, 80 * y, 4)))(ix, iy, time), microDetailX = .008 * (microSurface - .5), microDetailY = .008 * (microSurface - .5), centerDistance = calculateLength(ix, iy), dynamicRefraction = .35 * Math.pow(Math.min(centerDistance, 1), 1.8) * (1 + mouseFalloff * mouseDistance * .8), refractionX = Math.cos(refractionAngle) * dynamicRefraction, refractionY = Math.sin(refractionAngle) * dynamicRefraction, vortexAngle = Math.atan2(iy - mouseY, ix - mouseX), vortexDistance = calculateLength(ix - mouseX, iy - mouseY), vortexStrength = mouseFalloff * Math.sin(10 * vortexDistance - 3 * time) * .025, vortexX = Math.cos(vortexAngle + 2 * time) * vortexStrength, vortexY = Math.sin(vortexAngle + 2 * time) * vortexStrength, fluidX = Math.sin(10 * ix + 5 * mouseX + 2.5 * time) * Math.cos(8 * iy - 2 * time) * .018, fluidY = Math.cos(8 * ix - 2 * time) * Math.sin(10 * iy + 5 * mouseY + 2.5 * time) * .018, rippleEffect = (.012 * Math.sin(15 * Math.min(centerDistance, 10) - 4 * time) + .008 * Math.cos(20 * Math.min(centerDistance, 10) + 3 * time)) * mouseFalloff, rippleX = Math.cos(refractionAngle) * rippleEffect, rippleY = Math.sin(refractionAngle) * rippleEffect, distanceToEdge = roundedRectSDF(ix, iy, .44, .34, .39), edgeMask = smoothStep(.92, -.12, distanceToEdge), edgeSoftness = smoothStep(.85, .1, distanceToEdge), finalY = iy + (1.2 * refractionY + .8 * spectralY + 1.5 * parallaxY + .9 * scatteringY + 1 * turbulenceY + .6 * microDetailY + 1.3 * vortexY + 1.1 * fluidY + .7 * rippleY + .8 * causticDistortion) * edgeMask * edgeSoftness * .85;
|
|
3272
|
+
return createTexture(clampValue(ix + (1.2 * refractionX + .8 * spectralX + 1.5 * parallaxX + .9 * scatteringX + 1 * turbulenceX + .6 * microDetailX + 1.3 * vortexX + 1.1 * fluidX + .7 * rippleX + causticDistortion) * edgeMask * edgeSoftness * .85 + .5, 0, 1), clampValue(finalY + .5, 0, 1));
|
|
3273
|
+
}
|
|
3274
|
+
}, shaderUtils = Object.freeze( Object.defineProperty({
|
|
3275
|
+
__proto__: null,
|
|
3276
|
+
ShaderDisplacementGenerator: class {
|
|
3277
|
+
constructor(options) {
|
|
3278
|
+
if (this.options = options, this.canvasDPI = 1, !this.validateOptions(options)) throw new Error("Invalid shader options provided");
|
|
3279
|
+
this.canvas = document.createElement("canvas"),
|
|
3280
|
+
// Enhanced validation for canvas dimensions
|
|
3281
|
+
this.canvas.width = Math.max(1, Math.min(4096, Math.round(options.width * this.canvasDPI || 256))),
|
|
3282
|
+
this.canvas.height = Math.max(1, Math.min(4096, Math.round(options.height * this.canvasDPI || 256))),
|
|
3283
|
+
this.canvas.style.display = "none";
|
|
3284
|
+
const context = this.canvas.getContext("2d");
|
|
3285
|
+
if (!context) throw new Error("AtomixGlass: Could not get 2D canvas context");
|
|
3286
|
+
this.context = context;
|
|
3287
|
+
}
|
|
3288
|
+
validateOptions(options) {
|
|
3289
|
+
try {
|
|
3290
|
+
return options && "number" == typeof options.width && options.width > 0 && options.width <= 4096 && "number" == typeof options.height && options.height > 0 && options.height <= 4096 && "function" == typeof options.fragment;
|
|
3291
|
+
} catch (e) {
|
|
3292
|
+
// Graceful error handling
|
|
3293
|
+
return !1;
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
updateShader(mousePosition) {
|
|
3297
|
+
try {
|
|
3298
|
+
const w = this.options.width * this.canvasDPI, h = this.options.height * this.canvasDPI;
|
|
3299
|
+
let maxScale = 0;
|
|
3300
|
+
const rawValues = [];
|
|
3301
|
+
// Calculate displacement values with enhanced smoothing
|
|
3302
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
3303
|
+
const uv = {
|
|
3304
|
+
x: x / w,
|
|
3305
|
+
y: y / h
|
|
3306
|
+
}, pos = this.options.fragment(uv, mousePosition);
|
|
3307
|
+
let dx = pos.x * w - x, dy = pos.y * h - y;
|
|
3308
|
+
// Apply edge smoothing for Apple-like effect
|
|
3309
|
+
const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
|
|
3310
|
+
dx *= smoothStep(0, .2, edgeFactor), dy *= smoothStep(0, .2, edgeFactor), maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)),
|
|
3311
|
+
rawValues.push(dx, dy);
|
|
3312
|
+
}
|
|
3313
|
+
// Improved normalization to prevent artifacts while maintaining intensity
|
|
3314
|
+
maxScale = Math.max(maxScale, 1);
|
|
3315
|
+
// Create ImageData and fill it
|
|
3316
|
+
const imageData = this.context.createImageData(w, h), data = imageData.data;
|
|
3317
|
+
// Convert to image data with smoother normalization
|
|
3318
|
+
let rawIndex = 0;
|
|
3319
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
3320
|
+
const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
|
|
3321
|
+
data[pixelIndex] = clampValue(255 * r, 0, 255), // Red channel (X displacement)
|
|
3322
|
+
data[pixelIndex + 1] = clampValue(255 * g, 0, 255), // Green channel (Y displacement)
|
|
3323
|
+
data[pixelIndex + 2] = clampValue(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
|
|
3324
|
+
data[pixelIndex + 3] = 255;
|
|
3325
|
+
}
|
|
3326
|
+
return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
|
|
3327
|
+
} catch (error) {
|
|
3328
|
+
// Graceful fallback on error
|
|
3329
|
+
return console.warn("ShaderDisplacementGenerator: Error generating shader map, using fallback", error),
|
|
3330
|
+
"";
|
|
3331
|
+
// Return empty string as fallback
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
destroy() {
|
|
3335
|
+
try {
|
|
3336
|
+
// Clear canvas data to free memory
|
|
3337
|
+
this.context && this.context.clearRect(0, 0, this.canvas.width, this.canvas.height),
|
|
3338
|
+
// Reduce memory footprint by setting dimensions to 0
|
|
3339
|
+
this.canvas.width = 0, this.canvas.height = 0,
|
|
3340
|
+
// Remove from DOM
|
|
3341
|
+
this.canvas.remove();
|
|
3342
|
+
} catch (e) {
|
|
3343
|
+
// Silently handle cleanup errors
|
|
3344
|
+
console.warn("ShaderDisplacementGenerator: Error during cleanup", e);
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
getScale() {
|
|
3348
|
+
return this.canvasDPI;
|
|
3349
|
+
}
|
|
3350
|
+
},
|
|
3351
|
+
fragmentShaders: fragmentShaders
|
|
3352
|
+
}, Symbol.toStringTag, {
|
|
3353
|
+
value: "Module"
|
|
3354
|
+
}));
|
|
3355
|
+
|
|
3356
|
+
export { Accordion, Badge, Block, Breadcrumb, Button, Callout, Card, ElevationCard, Icon, List, ListGroup, Spinner };
|
|
3357
|
+
//# sourceMappingURL=core.js.map
|