@shohojdhara/atomix 0.6.4 → 0.6.6
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 +117 -38
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/atomix.umd.js +1 -1
- package/dist/atomix.umd.js.map +1 -1
- package/dist/atomix.umd.min.js +1 -1
- package/dist/charts.d.ts +30 -1
- package/dist/charts.js +625 -846
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +30 -1
- package/dist/core.js +659 -873
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +30 -1
- package/dist/forms.js +1171 -1402
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +31 -89
- package/dist/heavy.js +975 -1195
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +383 -140
- package/dist/index.esm.js +1567 -1679
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1556 -1667
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +2 -5
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +14 -16
- package/src/components/AtomixGlass/AtomixGlass.tsx +137 -364
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +32 -251
- package/src/components/AtomixGlass/GlassFilter.tsx +62 -68
- package/src/components/AtomixGlass/README.md +2 -1
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +19 -18
- package/src/components/AtomixGlass/glass-border-styles.test.ts +58 -0
- package/src/components/AtomixGlass/glass-border-styles.ts +136 -0
- package/src/components/AtomixGlass/glass-utils.ts +456 -22
- package/src/components/AtomixGlass/shader-utils.ts +19 -77
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +158 -537
- package/src/components/AtomixGlass/stories/Border.stories.tsx +149 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +229 -89
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +29 -340
- package/src/components/AtomixGlass/stories/argTypes.ts +30 -13
- package/src/components/AtomixGlass/stories/premium-presets.ts +206 -0
- package/src/components/AtomixGlass/stories/shared-components.tsx +52 -8
- package/src/components/Badge/Badge.tsx +4 -4
- package/src/components/Button/Button.tsx +2 -6
- package/src/components/Callout/Callout.test.tsx +4 -3
- package/src/components/Callout/Callout.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +3 -7
- package/src/components/Form/Checkbox.tsx +2 -8
- package/src/components/Form/Input.tsx +2 -9
- package/src/components/Form/Radio.tsx +2 -9
- package/src/components/Form/Select.test.tsx +6 -6
- package/src/components/Form/Select.tsx +2 -7
- package/src/components/Form/Textarea.stories.tsx +5 -5
- package/src/components/Form/Textarea.tsx +2 -9
- package/src/components/Messages/Messages.tsx +2 -8
- package/src/components/Modal/Modal.tsx +4 -5
- package/src/components/Navigation/Nav/Nav.tsx +2 -6
- package/src/components/Navigation/Navbar/Navbar.tsx +2 -9
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -6
- package/src/components/Pagination/Pagination.tsx +2 -10
- package/src/components/Popover/Popover.tsx +2 -9
- package/src/components/Progress/Progress.tsx +2 -7
- package/src/components/Rating/Rating.tsx +2 -10
- package/src/components/Spinner/Spinner.tsx +2 -7
- package/src/components/Steps/Steps.tsx +2 -10
- package/src/components/Tabs/Tabs.tsx +2 -9
- package/src/components/Toggle/Toggle.tsx +2 -10
- package/src/components/Tooltip/Tooltip.tsx +2 -5
- package/src/lib/composables/useAtomixGlass.ts +42 -143
- package/src/lib/composables/useAtomixGlassStyles.ts +61 -77
- package/src/lib/composables/usePerformanceMonitor.ts +5 -66
- package/src/lib/constants/components.ts +363 -46
- package/src/lib/types/components.ts +33 -1
- package/src/styles/01-settings/_settings.atomix-glass.scss +66 -28
- package/src/styles/02-tools/_tools.button.scss +51 -42
- package/src/styles/02-tools/_tools.glass.scss +45 -3
- package/src/styles/06-components/_components.atomix-glass.scss +116 -79
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +0 -171
- package/src/components/AtomixGlass/animation-system.ts +0 -578
- package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +0 -390
package/dist/forms.js
CHANGED
|
@@ -7,7 +7,65 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
9
|
* Form-specific constants
|
|
10
|
-
*/ const FORM_CLASSES_BASE = "c-form", FORM_CLASSES_DISABLED = "c-form--disabled", FORM_GROUP_CLASSES_BASE = "c-form-group", FORM_GROUP_CLASSES_SMALL = "c-form-group--sm", FORM_GROUP_CLASSES_LARGE = "c-form-group--lg", FORM_GROUP_CLASSES_INVALID = "c-form-group--invalid", FORM_GROUP_CLASSES_VALID = "c-form-group--valid", FORM_GROUP_CLASSES_DISABLED = "c-form-group--disabled", INPUT_CLASSES_BASE = "c-input", INPUT_CLASSES_SMALL = "c-input--sm", INPUT_CLASSES_LARGE = "c-input--lg", INPUT_CLASSES_INVALID = "is-invalid", INPUT_CLASSES_VALID = "is-valid", INPUT_CLASSES_DISABLED = "is-disabled", INPUT_CLASSES_FULL_WIDTH = "c-input--full-width", INPUT_CLASSES_PREFIX_ICON = "c-input--prefix-icon", INPUT_CLASSES_SUFFIX_ICON = "c-input--suffix-icon", INPUT_CLASSES_CLEARABLE = "c-input--clearable", INPUT_CLASSES_WITH_COUNTER = "c-input--with-counter", INPUT_CLASSES_PASSWORD_TOGGLE = "c-input--password-toggle", INPUT_ELEMENTS_WRAPPER = "c-input-wrapper", RADIO_CLASSES_BASE = "c-radio", RADIO_CLASSES_INVALID = "is-error", RADIO_CLASSES_VALID = "is-valid", RADIO_CLASSES_DISABLED = "is-disabled", SELECT_CLASSES_BASE = "c-select", SELECT_CLASSES_SELECTED = "c-select__selected", SELECT_CLASSES_SELECT_BODY = "c-select__body", SELECT_CLASSES_SELECT_PANEL = "c-select__panel", SELECT_CLASSES_SELECT_ITEMS = "c-select__items", SELECT_CLASSES_SELECT_ITEM = "c-select__item", SELECT_CLASSES_TOGGLE_ICON = "c-select__toggle-icon", SELECT_CLASSES_ICON_CARET = "icon-atomix-caret-down", SELECT_CLASSES_SMALL = "c-select--sm", SELECT_CLASSES_LARGE = "c-select--lg", SELECT_CLASSES_INVALID = "is-invalid", SELECT_CLASSES_VALID = "is-valid", SELECT_CLASSES_DISABLED = "is-disabled", SELECT_CLASSES_IS_OPEN = "is-open", TEXTAREA_CLASSES_BASE = "c-input c-input--textarea", TEXTAREA_CLASSES_SMALL = "c-input--sm", TEXTAREA_CLASSES_LARGE = "c-input--lg", TEXTAREA_CLASSES_INVALID = "is-invalid", TEXTAREA_CLASSES_VALID = "is-valid", TEXTAREA_CLASSES_DISABLED = "is-disabled",
|
|
10
|
+
*/ const FORM_CLASSES_BASE = "c-form", FORM_CLASSES_DISABLED = "c-form--disabled", FORM_GROUP_CLASSES_BASE = "c-form-group", FORM_GROUP_CLASSES_SMALL = "c-form-group--sm", FORM_GROUP_CLASSES_LARGE = "c-form-group--lg", FORM_GROUP_CLASSES_INVALID = "c-form-group--invalid", FORM_GROUP_CLASSES_VALID = "c-form-group--valid", FORM_GROUP_CLASSES_DISABLED = "c-form-group--disabled", INPUT_CLASSES_BASE = "c-input", INPUT_CLASSES_SMALL = "c-input--sm", INPUT_CLASSES_LARGE = "c-input--lg", INPUT_CLASSES_INVALID = "is-invalid", INPUT_CLASSES_VALID = "is-valid", INPUT_CLASSES_DISABLED = "is-disabled", INPUT_CLASSES_FULL_WIDTH = "c-input--full-width", INPUT_CLASSES_PREFIX_ICON = "c-input--prefix-icon", INPUT_CLASSES_SUFFIX_ICON = "c-input--suffix-icon", INPUT_CLASSES_CLEARABLE = "c-input--clearable", INPUT_CLASSES_WITH_COUNTER = "c-input--with-counter", INPUT_CLASSES_PASSWORD_TOGGLE = "c-input--password-toggle", INPUT_ELEMENTS_WRAPPER = "c-input-wrapper", RADIO_CLASSES_BASE = "c-radio", RADIO_CLASSES_INVALID = "is-error", RADIO_CLASSES_VALID = "is-valid", RADIO_CLASSES_DISABLED = "is-disabled", SELECT_CLASSES_BASE = "c-select", SELECT_CLASSES_SELECTED = "c-select__selected", SELECT_CLASSES_SELECT_BODY = "c-select__body", SELECT_CLASSES_SELECT_PANEL = "c-select__panel", SELECT_CLASSES_SELECT_ITEMS = "c-select__items", SELECT_CLASSES_SELECT_ITEM = "c-select__item", SELECT_CLASSES_TOGGLE_ICON = "c-select__toggle-icon", SELECT_CLASSES_ICON_CARET = "icon-atomix-caret-down", SELECT_CLASSES_SMALL = "c-select--sm", SELECT_CLASSES_LARGE = "c-select--lg", SELECT_CLASSES_INVALID = "is-invalid", SELECT_CLASSES_VALID = "is-valid", SELECT_CLASSES_DISABLED = "is-disabled", SELECT_CLASSES_IS_OPEN = "is-open", TEXTAREA_CLASSES_BASE = "c-input c-input--textarea", TEXTAREA_CLASSES_SMALL = "c-input--sm", TEXTAREA_CLASSES_LARGE = "c-input--lg", TEXTAREA_CLASSES_INVALID = "is-invalid", TEXTAREA_CLASSES_VALID = "is-valid", TEXTAREA_CLASSES_DISABLED = "is-disabled", GLASS_DEFAULTS_INPUT = {
|
|
11
|
+
displacementScale: 18,
|
|
12
|
+
borderRadius: 6,
|
|
13
|
+
elasticity: 0
|
|
14
|
+
}, GLASS_DEFAULTS_TEXTAREA = {
|
|
15
|
+
displacementScale: 18,
|
|
16
|
+
borderRadius: 6,
|
|
17
|
+
elasticity: 0
|
|
18
|
+
}, GLASS_DEFAULTS_SELECT = {
|
|
19
|
+
displacementScale: 18,
|
|
20
|
+
borderRadius: 6,
|
|
21
|
+
elasticity: 0
|
|
22
|
+
}, GLASS_DEFAULTS_CHECKBOX = {
|
|
23
|
+
displacementScale: 14,
|
|
24
|
+
borderRadius: 4,
|
|
25
|
+
elasticity: 0
|
|
26
|
+
}, GLASS_DEFAULTS_RADIO = {
|
|
27
|
+
displacementScale: 14,
|
|
28
|
+
borderRadius: 99,
|
|
29
|
+
elasticity: 0
|
|
30
|
+
}, GLASS_BORDER_GRADIENT = {
|
|
31
|
+
BASE_ANGLE: 135,
|
|
32
|
+
ANGLE_MULTIPLIER: .5,
|
|
33
|
+
VELOCITY_ANGLE_MULTIPLIER: .5,
|
|
34
|
+
CHROMATIC_OFFSET: 1.5,
|
|
35
|
+
STOP_1: {
|
|
36
|
+
MIN: 10,
|
|
37
|
+
BASE: 33,
|
|
38
|
+
get MULTIPLIER() {
|
|
39
|
+
return .009 * this.BASE;
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
STOP_2: {
|
|
43
|
+
MAX: 90,
|
|
44
|
+
BASE: 66,
|
|
45
|
+
get MULTIPLIER() {
|
|
46
|
+
return .006 * this.BASE;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
OPACITY: {
|
|
50
|
+
/** Matches $glass-border-1-opacity (0.08) */
|
|
51
|
+
BASE_1: .08,
|
|
52
|
+
get BASE_2() {
|
|
53
|
+
return 3.33 * this.BASE_1;
|
|
54
|
+
},
|
|
55
|
+
get BASE_3() {
|
|
56
|
+
return 2.66 * this.BASE_1;
|
|
57
|
+
},
|
|
58
|
+
get BASE_4() {
|
|
59
|
+
return 5 * this.BASE_1;
|
|
60
|
+
},
|
|
61
|
+
get MULTIPLIER_LOW() {
|
|
62
|
+
return .066 * this.BASE_1;
|
|
63
|
+
},
|
|
64
|
+
get MULTIPLIER_HIGH() {
|
|
65
|
+
return .1 * this.BASE_1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}, ATOMIX_GLASS = {
|
|
11
69
|
BASE_CLASS: "c-atomix-glass",
|
|
12
70
|
CONTAINER_CLASS: "c-atomix-glass__container",
|
|
13
71
|
INNER_CLASS: "c-atomix-glass__inner",
|
|
@@ -18,6 +76,22 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
18
76
|
BORDER_BACKDROP_CLASS: "c-atomix-glass__border-backdrop",
|
|
19
77
|
BORDER_1_CLASS: "c-atomix-glass__border-1",
|
|
20
78
|
BORDER_2_CLASS: "c-atomix-glass__border-2",
|
|
79
|
+
/** Centralized liquid glass rim configuration */
|
|
80
|
+
BORDER: {
|
|
81
|
+
WIDTH_CSS_VAR: "--atomix-glass-border-width",
|
|
82
|
+
DEFAULT_WIDTH: "0.5px",
|
|
83
|
+
GRADIENT_CSS_VARS: {
|
|
84
|
+
GRADIENT_1: "--atomix-glass-border-gradient-1",
|
|
85
|
+
GRADIENT_2: "--atomix-glass-border-gradient-2"
|
|
86
|
+
},
|
|
87
|
+
GRADIENT: GLASS_BORDER_GRADIENT,
|
|
88
|
+
OVER_LIGHT: {
|
|
89
|
+
opacity: .7
|
|
90
|
+
},
|
|
91
|
+
DARK: {
|
|
92
|
+
opacity: .35
|
|
93
|
+
}
|
|
94
|
+
},
|
|
21
95
|
HOVER_1_CLASS: "c-atomix-glass__hover-1",
|
|
22
96
|
HOVER_2_CLASS: "c-atomix-glass__hover-2",
|
|
23
97
|
HOVER_3_CLASS: "c-atomix-glass__hover-3",
|
|
@@ -46,25 +120,22 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
46
120
|
SHADER: "c-atomix-glass--shader"
|
|
47
121
|
},
|
|
48
122
|
DEFAULTS: {
|
|
49
|
-
|
|
123
|
+
/** Subtle refraction — Apple UI chrome avoids heavy liquid distortion */
|
|
124
|
+
DISPLACEMENT_SCALE: 28,
|
|
50
125
|
get BLUR_AMOUNT() {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// Saturate relative to intensity
|
|
57
|
-
},
|
|
126
|
+
// Apple Music sidebar / player bar: ~20–40px frost (see $glass-backdrop-filter)
|
|
127
|
+
return Math.max(20, .72 * this.DISPLACEMENT_SCALE);
|
|
128
|
+
},
|
|
129
|
+
/** Fixed 180% matches Apple's saturate(180%) backdrop recipe */
|
|
130
|
+
SATURATION: 180,
|
|
58
131
|
get ABERRATION_INTENSITY() {
|
|
59
|
-
return .
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
ELASTICITY: .15,
|
|
132
|
+
return .02 * this.DISPLACEMENT_SCALE;
|
|
133
|
+
},
|
|
134
|
+
ELASTICITY: .05,
|
|
63
135
|
get CORNER_RADIUS() {
|
|
64
136
|
return 16;
|
|
65
137
|
// Use 16 to match SCSS design system (was 20)
|
|
66
138
|
},
|
|
67
|
-
PADDING: "0",
|
|
68
139
|
MODE: "standard",
|
|
69
140
|
OVER_LIGHT: !1,
|
|
70
141
|
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
@@ -80,19 +151,29 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
80
151
|
},
|
|
81
152
|
CONSTANTS: {
|
|
82
153
|
ACTIVATION_ZONE: 200,
|
|
83
|
-
LERP_FACTOR: .
|
|
154
|
+
LERP_FACTOR: .05,
|
|
155
|
+
// Lower = more viscous, liquid-smooth tracking (Apple feel)
|
|
84
156
|
SMOOTHSTEP_POWER: 2.5,
|
|
85
157
|
MIN_BLUR: .1,
|
|
86
158
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
87
159
|
EDGE_FADE_PIXELS: 2,
|
|
88
|
-
//
|
|
89
|
-
|
|
160
|
+
// Interaction intensity multipliers shared by the hook and the imperative style updater
|
|
161
|
+
INTERACTION: {
|
|
162
|
+
HOVER_INTENSITY: 1.4,
|
|
163
|
+
ACTIVE_INTENSITY: 1.6
|
|
164
|
+
},
|
|
165
|
+
// Elasticity physics constants — Apple-tuned: soft springs, fast settling, minimal stretch
|
|
166
|
+
ELASTICITY_TRANSLATION_FACTOR: .06,
|
|
167
|
+
// Subtler elastic shift (was 0.1)
|
|
90
168
|
ELASTICITY_DISTANCE_THRESHOLD: 200,
|
|
91
169
|
ELASTICITY_COMPRESSION_FACTOR: .3,
|
|
92
|
-
ELASTICITY_STIFFNESS: .
|
|
93
|
-
|
|
170
|
+
ELASTICITY_STIFFNESS: .06,
|
|
171
|
+
// Softer springs = gentler motion (was 0.1)
|
|
172
|
+
ELASTICITY_DAMPING: .88,
|
|
173
|
+
// Fast settling, no wobble (was 0.76)
|
|
94
174
|
ELASTICITY_VELOCITY_FACTOR: .65,
|
|
95
|
-
ELASTICITY_STRETCH_RATIO: .
|
|
175
|
+
ELASTICITY_STRETCH_RATIO: .25,
|
|
176
|
+
// Less visible surface tension stretch (was 0.45)
|
|
96
177
|
ELASTICITY_MAGNIFICATION_BASE: 1.02,
|
|
97
178
|
// Note: This default must match the SCSS variable --atomix-radius-md
|
|
98
179
|
// @see src/styles/01-settings/_settings.global.scss
|
|
@@ -106,55 +187,16 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
106
187
|
},
|
|
107
188
|
// Gradient calculation constants
|
|
108
189
|
GRADIENT: {
|
|
109
|
-
BASE_ANGLE:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// Minimum percentage for border stop 1
|
|
120
|
-
BASE: 33,
|
|
121
|
-
// Base percentage for border stop 1
|
|
122
|
-
get MULTIPLIER() {
|
|
123
|
-
return .009 * this.BASE;
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
BORDER_STOP_2: {
|
|
127
|
-
MAX: 90,
|
|
128
|
-
// Maximum percentage for border stop 2
|
|
129
|
-
BASE: 66,
|
|
130
|
-
// Base percentage for border stop 2
|
|
131
|
-
get MULTIPLIER() {
|
|
132
|
-
return .006 * this.BASE;
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
BORDER_OPACITY: {
|
|
136
|
-
BASE_1: .12,
|
|
137
|
-
// Base opacity for border gradient 1
|
|
138
|
-
get BASE_2() {
|
|
139
|
-
return 3.33 * this.BASE_1;
|
|
140
|
-
},
|
|
141
|
-
// Base opacity for border gradient 2
|
|
142
|
-
get BASE_3() {
|
|
143
|
-
return 2.66 * this.BASE_1;
|
|
144
|
-
},
|
|
145
|
-
// Base opacity for border gradient 3
|
|
146
|
-
get BASE_4() {
|
|
147
|
-
return 5 * this.BASE_1;
|
|
148
|
-
},
|
|
149
|
-
// Base opacity for border gradient 4
|
|
150
|
-
get MULTIPLIER_LOW() {
|
|
151
|
-
return .066 * this.BASE_1;
|
|
152
|
-
},
|
|
153
|
-
// Low multiplier for mouse influence on opacity
|
|
154
|
-
get MULTIPLIER_HIGH() {
|
|
155
|
-
return .1 * this.BASE_1;
|
|
156
|
-
}
|
|
157
|
-
},
|
|
190
|
+
BASE_ANGLE: GLASS_BORDER_GRADIENT.BASE_ANGLE,
|
|
191
|
+
ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.ANGLE_MULTIPLIER,
|
|
192
|
+
VELOCITY_ANGLE_MULTIPLIER: GLASS_BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER,
|
|
193
|
+
CHROMATIC_OFFSET: GLASS_BORDER_GRADIENT.CHROMATIC_OFFSET,
|
|
194
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_1 */
|
|
195
|
+
BORDER_STOP_1: GLASS_BORDER_GRADIENT.STOP_1,
|
|
196
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.STOP_2 */
|
|
197
|
+
BORDER_STOP_2: GLASS_BORDER_GRADIENT.STOP_2,
|
|
198
|
+
/** @deprecated Use ATOMIX_GLASS.BORDER.GRADIENT.OPACITY */
|
|
199
|
+
BORDER_OPACITY: GLASS_BORDER_GRADIENT.OPACITY,
|
|
158
200
|
CENTER_POSITION: 50,
|
|
159
201
|
// Center position percentage (50%)
|
|
160
202
|
HOVER_POSITION: {
|
|
@@ -187,8 +229,8 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
187
229
|
return 2 * this.BLACK_STOP;
|
|
188
230
|
},
|
|
189
231
|
// End percentage for black hover 1
|
|
190
|
-
WHITE_START: .
|
|
191
|
-
//
|
|
232
|
+
WHITE_START: .35,
|
|
233
|
+
// Gentler hover flash — Apple hover is barely visible
|
|
192
234
|
get WHITE_STOP() {
|
|
193
235
|
return this.BLACK_END - 10;
|
|
194
236
|
}
|
|
@@ -206,8 +248,8 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
206
248
|
return 2 * this.BLACK_STOP;
|
|
207
249
|
},
|
|
208
250
|
// End percentage for black hover 2
|
|
209
|
-
WHITE_START:
|
|
210
|
-
//
|
|
251
|
+
WHITE_START: .7,
|
|
252
|
+
// Gentler hover flash
|
|
211
253
|
get WHITE_STOP() {
|
|
212
254
|
return this.BLACK_END;
|
|
213
255
|
}
|
|
@@ -225,8 +267,8 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
225
267
|
return 2 * this.BLACK_STOP;
|
|
226
268
|
},
|
|
227
269
|
// End percentage for black hover 3
|
|
228
|
-
WHITE_START:
|
|
229
|
-
//
|
|
270
|
+
WHITE_START: .7,
|
|
271
|
+
// Gentler hover flash
|
|
230
272
|
get WHITE_STOP() {
|
|
231
273
|
return this.BLACK_END;
|
|
232
274
|
}
|
|
@@ -236,13 +278,13 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
236
278
|
BASE_GRADIENT: {
|
|
237
279
|
ANGLE: 135,
|
|
238
280
|
// Gradient angle in degrees
|
|
239
|
-
BLACK_START_BASE: .
|
|
281
|
+
BLACK_START_BASE: .1,
|
|
240
282
|
// Base start opacity for black
|
|
241
283
|
get BLACK_START_MULTIPLIER() {
|
|
242
284
|
return .02 * this.BLACK_START_BASE;
|
|
243
285
|
},
|
|
244
286
|
// Multiplier for mouse X influence on start
|
|
245
|
-
BLACK_MID_BASE: .
|
|
287
|
+
BLACK_MID_BASE: .07,
|
|
246
288
|
// Base mid opacity for black
|
|
247
289
|
get BLACK_MID_MULTIPLIER() {
|
|
248
290
|
return .02 * this.BLACK_MID_BASE;
|
|
@@ -263,7 +305,7 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
263
305
|
}
|
|
264
306
|
},
|
|
265
307
|
OVERLAY_GRADIENT: {
|
|
266
|
-
BLACK_START_BASE: .
|
|
308
|
+
BLACK_START_BASE: .08,
|
|
267
309
|
// Base start opacity for black overlay
|
|
268
310
|
get BLACK_START_MULTIPLIER() {
|
|
269
311
|
return .025 * this.BLACK_START_BASE;
|
|
@@ -287,14 +329,14 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
287
329
|
return .416 * this.BLACK_START_BASE;
|
|
288
330
|
}
|
|
289
331
|
},
|
|
290
|
-
// Overlay highlight constants
|
|
332
|
+
// Overlay highlight constants — Apple places specular at the top-center
|
|
291
333
|
OVERLAY_HIGHLIGHT: {
|
|
292
|
-
POSITION_X:
|
|
293
|
-
//
|
|
294
|
-
POSITION_Y:
|
|
295
|
-
//
|
|
296
|
-
WHITE_OPACITY: .
|
|
297
|
-
//
|
|
334
|
+
POSITION_X: 50,
|
|
335
|
+
// Centered horizontal — Apple's top-center specular
|
|
336
|
+
POSITION_Y: 5,
|
|
337
|
+
// Very top — catches light like a curved glass surface
|
|
338
|
+
WHITE_OPACITY: .28,
|
|
339
|
+
// Softer specular — visible but not glaring
|
|
298
340
|
get STOP() {
|
|
299
341
|
return 150 * this.WHITE_OPACITY;
|
|
300
342
|
},
|
|
@@ -315,6 +357,10 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
315
357
|
SATURATION: {
|
|
316
358
|
HIGH_CONTRAST: 200
|
|
317
359
|
},
|
|
360
|
+
// Container shadows — hairline inner catch + soft floating lift (Apple player bar)
|
|
361
|
+
CONTAINER_SHADOW: {
|
|
362
|
+
LIGHT: "inset 0 0.5px 0 rgba(255, 255, 255, 0.32), inset 0 1px 2px rgba(255, 255, 255, 0.06), 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.08)"
|
|
363
|
+
},
|
|
318
364
|
// Phase 1: Animation System Constants
|
|
319
365
|
ANIMATION: {
|
|
320
366
|
// Breathing effect timing (in milliseconds)
|
|
@@ -354,267 +400,638 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
354
400
|
}
|
|
355
401
|
}
|
|
356
402
|
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
// Tighter cap to prevent blur/filter blow-out
|
|
369
|
-
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$2.MIN_BLUR : Math.max(CONSTANTS$2.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$2.MAX_SIZE && size.height <= CONSTANTS$2.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
370
|
-
if ("number" == typeof value) return Math.max(0, value);
|
|
371
|
-
if ("string" != typeof value || !value.trim()) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
372
|
-
const trimmedValue = value.trim();
|
|
373
|
-
// Handle px values
|
|
374
|
-
if (trimmedValue.endsWith("px")) {
|
|
375
|
-
const parsed = parseFloat(trimmedValue);
|
|
376
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
377
|
-
}
|
|
378
|
-
// Handle rem values (assume 16px = 1rem)
|
|
379
|
-
if (trimmedValue.endsWith("rem")) {
|
|
380
|
-
const parsed = parseFloat(trimmedValue);
|
|
381
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
382
|
-
}
|
|
383
|
-
// Handle em values (assume 16px = 1em for simplicity)
|
|
384
|
-
if (trimmedValue.endsWith("em")) {
|
|
385
|
-
const parsed = parseFloat(trimmedValue);
|
|
386
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
387
|
-
}
|
|
388
|
-
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
389
|
-
if (trimmedValue.endsWith("%")) {
|
|
390
|
-
const parsed = parseFloat(trimmedValue);
|
|
391
|
-
return isNaN(parsed) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
392
|
-
}
|
|
393
|
-
// Handle unitless numbers
|
|
394
|
-
const numValue = parseFloat(trimmedValue);
|
|
395
|
-
return isNaN(numValue) ? CONSTANTS$2.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
396
|
-
}, extractBorderRadiusFromElement = element => {
|
|
397
|
-
if (!element || !element.props) return null;
|
|
398
|
-
// Check inline styles first (highest priority)
|
|
399
|
-
if (element.props.style) {
|
|
400
|
-
const radiusFromStyle = (style => {
|
|
401
|
-
if (!style) return null;
|
|
402
|
-
// Check various border-radius properties
|
|
403
|
-
const borderRadius = style.borderRadius || style.borderTopLeftRadius || style.borderTopRightRadius || style.borderBottomLeftRadius || style.borderBottomRightRadius;
|
|
404
|
-
return void 0 !== borderRadius ? parseBorderRadiusValue(borderRadius) : null;
|
|
405
|
-
})(element.props.style);
|
|
406
|
-
if (null !== radiusFromStyle && radiusFromStyle > 0) return radiusFromStyle;
|
|
407
|
-
}
|
|
408
|
-
// If element has children, recursively check them
|
|
409
|
-
if (element.props.children) {
|
|
410
|
-
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
411
|
-
if (childRadius > 0 && childRadius !== CONSTANTS$2.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
412
|
-
}
|
|
413
|
-
return null;
|
|
414
|
-
}, extractBorderRadiusFromChildren = children => {
|
|
415
|
-
if (!children) return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Form Group-specific constants
|
|
407
|
+
*/ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
408
|
+
|
|
409
|
+
function getDefaultExportFromCjs(x) {
|
|
410
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
var fails$8 = function(exec) {
|
|
416
414
|
try {
|
|
417
|
-
|
|
418
|
-
for (let i = 0; i < childArray.length; i++) {
|
|
419
|
-
const child = childArray[i];
|
|
420
|
-
if ( React.isValidElement(child)) {
|
|
421
|
-
const radius = extractBorderRadiusFromElement(child);
|
|
422
|
-
if (null !== radius) return radius;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
415
|
+
return !!exec();
|
|
425
416
|
} catch (error) {
|
|
426
|
-
|
|
417
|
+
return !0;
|
|
427
418
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
return {
|
|
435
|
-
|
|
436
|
-
velocity: newVelocity
|
|
419
|
+
}, functionBindNative = !fails$8((function() {
|
|
420
|
+
// eslint-disable-next-line es/no-function-prototype-bind -- safe
|
|
421
|
+
var test = function() {/* empty */}.bind();
|
|
422
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
423
|
+
return "function" != typeof test || test.hasOwnProperty("prototype");
|
|
424
|
+
})), 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) {
|
|
425
|
+
return function() {
|
|
426
|
+
return call$5.apply(fn, arguments);
|
|
437
427
|
};
|
|
438
|
-
},
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
428
|
+
}, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
|
|
429
|
+
return it && it.Math === Math && it;
|
|
430
|
+
}, globalThis_1 =
|
|
431
|
+
// eslint-disable-next-line es/no-global-this -- safe
|
|
432
|
+
check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
|
|
433
|
+
// eslint-disable-next-line no-restricted-globals -- safe
|
|
434
|
+
check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
|
|
435
|
+
// eslint-disable-next-line no-new-func -- fallback
|
|
436
|
+
function() {
|
|
437
|
+
return this;
|
|
438
|
+
}() || 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() {
|
|
439
|
+
return call$4.apply(apply$1, arguments);
|
|
440
|
+
}), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
|
|
441
|
+
return stringSlice(toString$3(it), 8, -1);
|
|
442
|
+
}, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
|
|
443
|
+
// Nashorn bug:
|
|
444
|
+
// https://github.com/zloirock/core-js/issues/1128
|
|
445
|
+
// https://github.com/zloirock/core-js/issues/1130
|
|
446
|
+
if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
|
|
447
|
+
}, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
|
|
448
|
+
return "function" == typeof argument || argument === documentAll;
|
|
449
|
+
} : function(argument) {
|
|
450
|
+
return "function" == typeof argument;
|
|
451
|
+
}, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
|
|
452
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
453
|
+
return 7 !== Object.defineProperty({}, 1, {
|
|
454
|
+
get: function() {
|
|
455
|
+
return 7;
|
|
456
|
+
}
|
|
457
|
+
})[1];
|
|
458
|
+
})), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
|
|
459
|
+
return call$3.apply(call$3, arguments);
|
|
460
|
+
}, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
|
|
461
|
+
1: 2
|
|
462
|
+
}, 1);
|
|
442
463
|
|
|
443
|
-
|
|
444
|
-
|
|
464
|
+
// `Object.prototype.propertyIsEnumerable` method implementation
|
|
465
|
+
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
|
|
466
|
+
objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
|
|
467
|
+
var descriptor = getOwnPropertyDescriptor$1(this, V);
|
|
468
|
+
return !!descriptor && descriptor.enumerable;
|
|
469
|
+
} : $propertyIsEnumerable;
|
|
445
470
|
|
|
446
|
-
|
|
447
|
-
|
|
471
|
+
var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
|
|
472
|
+
return {
|
|
473
|
+
enumerable: !(1 & bitmap),
|
|
474
|
+
configurable: !(2 & bitmap),
|
|
475
|
+
writable: !(4 & bitmap),
|
|
476
|
+
value: value
|
|
477
|
+
};
|
|
478
|
+
}, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
|
|
479
|
+
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
|
480
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
481
|
+
return !$Object$3("z").propertyIsEnumerable(0);
|
|
482
|
+
})) ? function(it) {
|
|
483
|
+
return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
|
|
484
|
+
} : $Object$3, isNullOrUndefined$2 = function(it) {
|
|
485
|
+
return null == it;
|
|
486
|
+
}, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
|
|
487
|
+
if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
|
|
488
|
+
return it;
|
|
489
|
+
}, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
|
|
490
|
+
return IndexedObject(requireObjectCoercible$2(it));
|
|
491
|
+
}, isCallable$7 = isCallable$8, isObject$5 = function(it) {
|
|
492
|
+
return "object" == typeof it ? null !== it : isCallable$7(it);
|
|
493
|
+
}, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
|
|
494
|
+
return isCallable$6(variable) ? variable : void 0;
|
|
495
|
+
}, navigator$1 = globalThis_1.navigator, userAgent$1 = navigator$1 && navigator$1.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;
|
|
448
496
|
|
|
449
|
-
|
|
450
|
-
|
|
497
|
+
v8 && (
|
|
498
|
+
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
|
|
499
|
+
// but their correct versions are not interesting for us
|
|
500
|
+
version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
|
|
501
|
+
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
|
|
502
|
+
// so check `userAgent` even if `.v8` exists, but 0
|
|
503
|
+
!version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
451
504
|
|
|
452
|
-
|
|
453
|
-
|
|
505
|
+
var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
|
|
506
|
+
var symbol = Symbol("symbol detection");
|
|
507
|
+
// Chrome 38 Symbol has incorrect toString conversion
|
|
508
|
+
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
|
|
509
|
+
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
|
|
510
|
+
// of course, fail.
|
|
511
|
+
return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
|
|
512
|
+
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
|
|
513
|
+
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
|
|
514
|
+
})), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
|
|
515
|
+
return "symbol" == typeof it;
|
|
516
|
+
} : function(it) {
|
|
517
|
+
var $Symbol = function(namespace, method) {
|
|
518
|
+
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];
|
|
519
|
+
}("Symbol");
|
|
520
|
+
return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
|
|
521
|
+
}, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
|
|
522
|
+
if (isCallable$4(argument)) return argument;
|
|
523
|
+
throw new $TypeError$5(function(argument) {
|
|
524
|
+
try {
|
|
525
|
+
return $String$2(argument);
|
|
526
|
+
} catch (error) {
|
|
527
|
+
return "Object";
|
|
528
|
+
}
|
|
529
|
+
}(argument) + " is not a function");
|
|
530
|
+
}, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
|
|
531
|
+
exports: {}
|
|
532
|
+
}, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
|
|
533
|
+
try {
|
|
534
|
+
defineProperty(globalThis$6, key, {
|
|
535
|
+
value: value,
|
|
536
|
+
configurable: !0,
|
|
537
|
+
writable: !0
|
|
538
|
+
});
|
|
539
|
+
} catch (error) {
|
|
540
|
+
globalThis$6[key] = value;
|
|
454
541
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
children: [ jsxs("radialGradient", {
|
|
465
|
-
id: `${id}-edge-mask`,
|
|
466
|
-
cx: "50%",
|
|
467
|
-
cy: "50%",
|
|
468
|
-
r: "50%",
|
|
469
|
-
children: [ jsx("stop", {
|
|
470
|
-
offset: "0%",
|
|
471
|
-
stopColor: "black",
|
|
472
|
-
stopOpacity: "0"
|
|
473
|
-
}), jsx("stop", {
|
|
474
|
-
offset: `${Math.max(30, 80 - 2 * aberrationIntensity)}%`,
|
|
475
|
-
stopColor: "black",
|
|
476
|
-
stopOpacity: "0"
|
|
477
|
-
}), jsx("stop", {
|
|
478
|
-
offset: "100%",
|
|
479
|
-
stopColor: "white",
|
|
480
|
-
stopOpacity: "1"
|
|
481
|
-
}) ]
|
|
482
|
-
}), jsxs("filter", {
|
|
483
|
-
id: id,
|
|
484
|
-
x: "-35%",
|
|
485
|
-
y: "-35%",
|
|
486
|
-
width: "170%",
|
|
487
|
-
height: "170%",
|
|
488
|
-
colorInterpolationFilters: "sRGB",
|
|
489
|
-
children: [ jsx("feImage", {
|
|
490
|
-
id: `${id}-image`,
|
|
491
|
-
x: "0",
|
|
492
|
-
y: "0",
|
|
493
|
-
width: "100%",
|
|
494
|
-
height: "100%",
|
|
495
|
-
result: "DISPLACEMENT_MAP",
|
|
496
|
-
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),
|
|
497
|
-
preserveAspectRatio: "xMidYMid slice"
|
|
498
|
-
}), jsx("feColorMatrix", {
|
|
499
|
-
in: "DISPLACEMENT_MAP",
|
|
500
|
-
type: "matrix",
|
|
501
|
-
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",
|
|
502
|
-
result: "EDGE_INTENSITY"
|
|
503
|
-
}), jsx("feComponentTransfer", {
|
|
504
|
-
in: "EDGE_INTENSITY",
|
|
505
|
-
result: "EDGE_MASK",
|
|
506
|
-
children: jsx("feFuncA", {
|
|
507
|
-
type: "discrete",
|
|
508
|
-
tableValues: `0 ${.05 * aberrationIntensity} 1`
|
|
509
|
-
})
|
|
510
|
-
}), jsx("feOffset", {
|
|
511
|
-
in: "SourceGraphic",
|
|
512
|
-
dx: "0",
|
|
513
|
-
dy: "0",
|
|
514
|
-
result: "CENTER_ORIGINAL"
|
|
515
|
-
}), jsx("feDisplacementMap", {
|
|
516
|
-
in: "SourceGraphic",
|
|
517
|
-
in2: "DISPLACEMENT_MAP",
|
|
518
|
-
scale: displacementScale * ("shader" === mode ? 1 : -1),
|
|
519
|
-
xChannelSelector: "R",
|
|
520
|
-
yChannelSelector: "B",
|
|
521
|
-
result: "RED_DISPLACED"
|
|
522
|
-
}), jsx("feColorMatrix", {
|
|
523
|
-
in: "RED_DISPLACED",
|
|
524
|
-
type: "matrix",
|
|
525
|
-
values: "1 0 0 0 0\n 0 0 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
526
|
-
result: "RED_CHANNEL"
|
|
527
|
-
}), jsx("feDisplacementMap", {
|
|
528
|
-
in: "SourceGraphic",
|
|
529
|
-
in2: "DISPLACEMENT_MAP",
|
|
530
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .02 * aberrationIntensity),
|
|
531
|
-
xChannelSelector: "R",
|
|
532
|
-
yChannelSelector: "B",
|
|
533
|
-
result: "GREEN_DISPLACED"
|
|
534
|
-
}), jsx("feColorMatrix", {
|
|
535
|
-
in: "GREEN_DISPLACED",
|
|
536
|
-
type: "matrix",
|
|
537
|
-
values: "0 0 0 0 0\n 0 1 0 0 0\n 0 0 0 0 0\n 0 0 0 1 0",
|
|
538
|
-
result: "GREEN_CHANNEL"
|
|
539
|
-
}), jsx("feDisplacementMap", {
|
|
540
|
-
in: "SourceGraphic",
|
|
541
|
-
in2: "DISPLACEMENT_MAP",
|
|
542
|
-
scale: displacementScale * (("shader" === mode ? 1 : -1) - .03 * aberrationIntensity),
|
|
543
|
-
xChannelSelector: "R",
|
|
544
|
-
yChannelSelector: "B",
|
|
545
|
-
result: "BLUE_DISPLACED"
|
|
546
|
-
}), jsx("feColorMatrix", {
|
|
547
|
-
in: "BLUE_DISPLACED",
|
|
548
|
-
type: "matrix",
|
|
549
|
-
values: "0 0 0 0 0\n 0 0 0 0 0\n 0 0 1 0 0\n 0 0 0 1 0",
|
|
550
|
-
result: "BLUE_CHANNEL"
|
|
551
|
-
}), jsx("feBlend", {
|
|
552
|
-
in: "GREEN_CHANNEL",
|
|
553
|
-
in2: "BLUE_CHANNEL",
|
|
554
|
-
mode: "screen",
|
|
555
|
-
result: "GB_COMBINED"
|
|
556
|
-
}), jsx("feBlend", {
|
|
557
|
-
in: "RED_CHANNEL",
|
|
558
|
-
in2: "GB_COMBINED",
|
|
559
|
-
mode: "screen",
|
|
560
|
-
result: "RGB_COMBINED"
|
|
561
|
-
}), jsx("feGaussianBlur", {
|
|
562
|
-
in: "RGB_COMBINED",
|
|
563
|
-
result: "ABERRATED_BLURRED",
|
|
564
|
-
stdDeviation: blurAmount * aberrationIntensity * .05
|
|
565
|
-
}), jsx("feComposite", {
|
|
566
|
-
in: "ABERRATED_BLURRED",
|
|
567
|
-
in2: "EDGE_MASK",
|
|
568
|
-
operator: "in",
|
|
569
|
-
result: "EDGE_ABERRATION"
|
|
570
|
-
}), jsx("feComponentTransfer", {
|
|
571
|
-
in: "EDGE_MASK",
|
|
572
|
-
result: "INVERTED_MASK",
|
|
573
|
-
children: jsx("feFuncA", {
|
|
574
|
-
type: "table",
|
|
575
|
-
tableValues: "1 0"
|
|
576
|
-
})
|
|
577
|
-
}), jsx("feComposite", {
|
|
578
|
-
in: "CENTER_ORIGINAL",
|
|
579
|
-
in2: "INVERTED_MASK",
|
|
580
|
-
operator: "in",
|
|
581
|
-
result: "CENTER_CLEAN"
|
|
582
|
-
}), jsx("feComposite", {
|
|
583
|
-
in: "EDGE_ABERRATION",
|
|
584
|
-
in2: "CENTER_CLEAN",
|
|
585
|
-
operator: "over"
|
|
586
|
-
}) ]
|
|
587
|
-
}) ]
|
|
588
|
-
})
|
|
542
|
+
return value;
|
|
543
|
+
}("__core-js_shared__", {});
|
|
544
|
+
|
|
545
|
+
/* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
|
|
546
|
+
version: "3.43.0",
|
|
547
|
+
mode: "pure",
|
|
548
|
+
copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
|
|
549
|
+
license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
|
|
550
|
+
source: "https://github.com/zloirock/core-js"
|
|
589
551
|
});
|
|
590
552
|
|
|
553
|
+
var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
|
|
554
|
+
return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
|
|
555
|
+
}, 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) {
|
|
556
|
+
return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
|
|
557
|
+
}, wellKnownSymbol$5 = function(name) {
|
|
558
|
+
return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
|
|
559
|
+
WellKnownSymbolsStore[name];
|
|
560
|
+
}, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
|
|
561
|
+
if (!isObject$3(input) || isSymbol$1(input)) return input;
|
|
562
|
+
var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
|
|
563
|
+
if (exoticToPrim) {
|
|
564
|
+
if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
|
|
565
|
+
!isObject$3(result) || isSymbol$1(result)) return result;
|
|
566
|
+
throw new $TypeError$3("Can't convert object to primitive value");
|
|
567
|
+
}
|
|
568
|
+
return void 0 === pref && (pref = "number"), function(input, pref) {
|
|
569
|
+
var fn, val;
|
|
570
|
+
if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
571
|
+
if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
|
|
572
|
+
if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
573
|
+
throw new $TypeError$4("Can't convert object to primitive value");
|
|
574
|
+
}(input, pref);
|
|
575
|
+
}, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
|
|
576
|
+
var key = toPrimitive(argument, "string");
|
|
577
|
+
return isSymbol(key) ? key : key + "";
|
|
578
|
+
}, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
|
|
579
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
580
|
+
return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
|
|
581
|
+
get: function() {
|
|
582
|
+
return 7;
|
|
583
|
+
}
|
|
584
|
+
}).a;
|
|
585
|
+
var it;
|
|
586
|
+
})), 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;
|
|
587
|
+
|
|
588
|
+
// `Object.getOwnPropertyDescriptor` method
|
|
589
|
+
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
|
|
590
|
+
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
|
|
591
|
+
if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
|
|
592
|
+
return $getOwnPropertyDescriptor$1(O, P);
|
|
593
|
+
} catch (error) {/* empty */}
|
|
594
|
+
if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
|
|
598
|
+
var value = data[normalize(feature)];
|
|
599
|
+
return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
|
|
600
|
+
}, normalize = isForced$1.normalize = function(string) {
|
|
601
|
+
return String(string).replace(replacement, ".").toLowerCase();
|
|
602
|
+
}, 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() {
|
|
603
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
604
|
+
return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
|
|
605
|
+
value: 42,
|
|
606
|
+
writable: !1
|
|
607
|
+
}).prototype;
|
|
608
|
+
})), 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) {
|
|
609
|
+
if (isObject$1(argument)) return argument;
|
|
610
|
+
throw new $TypeError$2($String$1(argument) + " is not an object");
|
|
611
|
+
}, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
612
|
+
|
|
613
|
+
// `Object.defineProperty` method
|
|
614
|
+
// https://tc39.es/ecma262/#sec-object.defineproperty
|
|
615
|
+
objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
|
|
616
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
|
|
617
|
+
var current = $getOwnPropertyDescriptor(O, P);
|
|
618
|
+
current && current.writable && (O[P] = Attributes.value, Attributes = {
|
|
619
|
+
configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
|
|
620
|
+
enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
|
|
621
|
+
writable: !1
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
return $defineProperty(O, P, Attributes);
|
|
625
|
+
} : $defineProperty : function(O, P, Attributes) {
|
|
626
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
|
|
627
|
+
return $defineProperty(O, P, Attributes);
|
|
628
|
+
} catch (error) {/* empty */}
|
|
629
|
+
if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
|
|
630
|
+
return "value" in Attributes && (O[P] = Attributes.value), O;
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
|
|
634
|
+
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
|
|
635
|
+
} : function(object, key, value) {
|
|
636
|
+
return object[key] = value, object;
|
|
637
|
+
}, 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) {
|
|
638
|
+
return aCallable(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
|
|
639
|
+
return fn.apply(that, arguments);
|
|
640
|
+
};
|
|
641
|
+
}, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
|
|
642
|
+
var Wrapper = function(a, b, c) {
|
|
643
|
+
if (this instanceof Wrapper) {
|
|
644
|
+
switch (arguments.length) {
|
|
645
|
+
case 0:
|
|
646
|
+
return new NativeConstructor;
|
|
647
|
+
|
|
648
|
+
case 1:
|
|
649
|
+
return new NativeConstructor(a);
|
|
650
|
+
|
|
651
|
+
case 2:
|
|
652
|
+
return new NativeConstructor(a, b);
|
|
653
|
+
}
|
|
654
|
+
return new NativeConstructor(a, b, c);
|
|
655
|
+
}
|
|
656
|
+
return apply(NativeConstructor, this, arguments);
|
|
657
|
+
};
|
|
658
|
+
return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
|
|
659
|
+
}, _export = function(options, source) {
|
|
660
|
+
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;
|
|
661
|
+
for (key in source)
|
|
662
|
+
// contains in native
|
|
663
|
+
USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
|
|
664
|
+
targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
|
|
665
|
+
// export native or implementation
|
|
666
|
+
sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
|
|
667
|
+
// bind methods to global for calling from export context
|
|
668
|
+
resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
|
|
669
|
+
// add a flag to not completely full polyfills
|
|
670
|
+
(options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
|
|
671
|
+
createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
|
|
672
|
+
// export virtual prototype methods
|
|
673
|
+
createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
|
|
674
|
+
// export real prototype methods
|
|
675
|
+
options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
|
|
676
|
+
}, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
|
|
677
|
+
var n = +x;
|
|
678
|
+
return (n > 0 ? floor : ceil)(n);
|
|
679
|
+
}, toIntegerOrInfinity$2 = function(argument) {
|
|
680
|
+
var number = +argument;
|
|
681
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
682
|
+
return number != number || 0 === number ? 0 : trunc(number);
|
|
683
|
+
}, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, min$1 = Math.min, globalThis$1 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$2 = function(CONSTRUCTOR, METHOD) {
|
|
684
|
+
var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
|
|
685
|
+
if (pureMethod) return pureMethod;
|
|
686
|
+
var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
687
|
+
return NativePrototype && NativePrototype[METHOD];
|
|
688
|
+
};
|
|
689
|
+
|
|
591
690
|
/**
|
|
592
|
-
*
|
|
593
|
-
|
|
691
|
+
* Component Utilities
|
|
692
|
+
*
|
|
693
|
+
* Helper functions for component development with the new customization system
|
|
694
|
+
*/
|
|
695
|
+
/**
|
|
696
|
+
* Merge multiple class names
|
|
697
|
+
*/
|
|
698
|
+
function mergeClassNames(...classes) {
|
|
699
|
+
return classes.filter(Boolean).join(" ");
|
|
700
|
+
}
|
|
594
701
|
|
|
595
|
-
|
|
596
|
-
|
|
702
|
+
/**
|
|
703
|
+
* Utility to merge multiple React refs into one
|
|
704
|
+
*/ function setRef(ref, value) {
|
|
705
|
+
"function" == typeof ref ? ref(value) : ref && (
|
|
706
|
+
// This is safe because we're checking that ref exists first
|
|
707
|
+
ref.current = value);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Combines two React refs into a single ref function
|
|
712
|
+
* This is used when you need to use and forward a ref at the same time
|
|
713
|
+
*/ function useForkRef(refA, refB) {
|
|
714
|
+
return React.useMemo((() => null == refA && null == refB ? null : refValue => {
|
|
715
|
+
setRef(refA, refValue), setRef(refB, refValue);
|
|
716
|
+
}), [ refA, refB ]);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const {CONSTANTS: CONSTANTS$3} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
|
|
720
|
+
x: rect.left + rect.width / 2,
|
|
721
|
+
y: rect.top + rect.height / 2
|
|
722
|
+
} : {
|
|
597
723
|
x: 0,
|
|
598
724
|
y: 0
|
|
599
|
-
},
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
725
|
+
}, calculateMouseInfluence = mouseOffset => {
|
|
726
|
+
if (!mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y) return 0;
|
|
727
|
+
// Clamp influence to keep mouse response subtle and stable.
|
|
728
|
+
const influence = Math.sqrt(mouseOffset.x * mouseOffset.x + mouseOffset.y * mouseOffset.y) / CONSTANTS$3.MOUSE_INFLUENCE_DIVISOR;
|
|
729
|
+
return Math.min(.8, influence);
|
|
730
|
+
// Tighter cap to prevent blur/filter blow-out
|
|
731
|
+
}, clampBlur = value => "number" != typeof value || isNaN(value) ? CONSTANTS$3.MIN_BLUR : Math.max(CONSTANTS$3.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$3.MAX_SIZE && size.height <= CONSTANTS$3.MAX_SIZE, parseBorderRadiusValue = value => {
|
|
732
|
+
if ("number" == typeof value) return Math.max(0, value);
|
|
733
|
+
if ("string" != typeof value || !value.trim()) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
734
|
+
const trimmedValue = value.trim();
|
|
735
|
+
// Handle px values
|
|
736
|
+
if (trimmedValue.endsWith("px")) {
|
|
737
|
+
const parsed = parseFloat(trimmedValue);
|
|
738
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed);
|
|
739
|
+
}
|
|
740
|
+
// Handle rem values (assume 16px = 1rem)
|
|
741
|
+
if (trimmedValue.endsWith("rem")) {
|
|
742
|
+
const parsed = parseFloat(trimmedValue);
|
|
743
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
744
|
+
}
|
|
745
|
+
// Handle em values (assume 16px = 1em for simplicity)
|
|
746
|
+
if (trimmedValue.endsWith("em")) {
|
|
747
|
+
const parsed = parseFloat(trimmedValue);
|
|
748
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, 16 * parsed);
|
|
749
|
+
}
|
|
750
|
+
// Handle percentage (convert to approximate px value, assuming 200px container)
|
|
751
|
+
if (trimmedValue.endsWith("%")) {
|
|
752
|
+
const parsed = parseFloat(trimmedValue);
|
|
753
|
+
return isNaN(parsed) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, parsed / 100 * 200);
|
|
754
|
+
}
|
|
755
|
+
// Handle unitless numbers
|
|
756
|
+
const numValue = parseFloat(trimmedValue);
|
|
757
|
+
return isNaN(numValue) ? CONSTANTS$3.DEFAULT_CORNER_RADIUS : Math.max(0, numValue);
|
|
758
|
+
}, extractBorderRadiusFromElement = element => {
|
|
759
|
+
if (!element || !element.props) return null;
|
|
760
|
+
// Check inline styles first (highest priority)
|
|
761
|
+
if (element.props.style) {
|
|
762
|
+
const radiusFromStyle = (style => {
|
|
763
|
+
if (!style) return null;
|
|
764
|
+
// Check various border-radius properties
|
|
765
|
+
const borderRadius = style.borderRadius || style.borderTopLeftRadius || style.borderTopRightRadius || style.borderBottomLeftRadius || style.borderBottomRightRadius;
|
|
766
|
+
return void 0 !== borderRadius ? parseBorderRadiusValue(borderRadius) : null;
|
|
767
|
+
})(element.props.style);
|
|
768
|
+
if (null !== radiusFromStyle && radiusFromStyle > 0) return radiusFromStyle;
|
|
769
|
+
}
|
|
770
|
+
// If element has children, recursively check them
|
|
771
|
+
if (element.props.children) {
|
|
772
|
+
const childRadius = extractBorderRadiusFromChildren(element.props.children);
|
|
773
|
+
if (childRadius > 0 && childRadius !== CONSTANTS$3.DEFAULT_CORNER_RADIUS) return childRadius;
|
|
774
|
+
}
|
|
775
|
+
return null;
|
|
776
|
+
}, extractBorderRadiusFromChildren = children => {
|
|
777
|
+
if (!children) return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
778
|
+
try {
|
|
779
|
+
const childArray = React.Children.toArray(children);
|
|
780
|
+
for (let i = 0; i < childArray.length; i++) {
|
|
781
|
+
const child = childArray[i];
|
|
782
|
+
if ( React.isValidElement(child)) {
|
|
783
|
+
const radius = extractBorderRadiusFromElement(child);
|
|
784
|
+
if (null !== radius) return radius;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
} catch (error) {
|
|
788
|
+
// Silently handle errors
|
|
789
|
+
}
|
|
790
|
+
return CONSTANTS$3.DEFAULT_CORNER_RADIUS;
|
|
791
|
+
}, smoothstep = t => {
|
|
792
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
793
|
+
return clamped * clamped * (3 - 2 * clamped);
|
|
794
|
+
}, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), clamp = (value, min, max) => "number" != typeof value || isNaN(value) ? min : Math.max(min, Math.min(max, value)), smoothstepEdge = (edge0, edge1, x) => "number" != typeof edge0 || "number" != typeof edge1 || "number" != typeof x ? 0 : smoothstep((x - edge0) / (edge1 - edge0)), easeInOutCubic = t => {
|
|
795
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
796
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
797
|
+
return clamped < .5 ? 4 * clamped * clamped * clamped : 1 - Math.pow(-2 * clamped + 2, 3) / 2;
|
|
798
|
+
}, easeOutQuart = t => {
|
|
799
|
+
if ("number" != typeof t || isNaN(t)) return 0;
|
|
800
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
801
|
+
return 1 - Math.pow(1 - clamped, 4);
|
|
802
|
+
}, vec2Length = (x, y) => {
|
|
803
|
+
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
804
|
+
const maxComponent = Math.max(Math.abs(x), Math.abs(y));
|
|
805
|
+
if (0 === maxComponent) return 0;
|
|
806
|
+
const scaledX = x / maxComponent, scaledY = y / maxComponent;
|
|
807
|
+
return maxComponent * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
808
|
+
}, getInteractionIntensity = (isHovered, isActive) => ({
|
|
809
|
+
hoverIntensity: isHovered ? CONSTANTS$3.INTERACTION.HOVER_INTENSITY : 1,
|
|
810
|
+
activeIntensity: isActive ? CONSTANTS$3.INTERACTION.ACTIVE_INTENSITY : 1
|
|
811
|
+
})
|
|
812
|
+
/**
|
|
813
|
+
* Spring-damper integration helper
|
|
814
|
+
* Calculates the next value based on velocity, stiffness, and damping.
|
|
815
|
+
*/ , calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
|
|
816
|
+
const newVelocity = (velocity + (target - current) * stiffness) * damping;
|
|
817
|
+
return {
|
|
818
|
+
value: current + newVelocity,
|
|
819
|
+
velocity: newVelocity
|
|
820
|
+
};
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Calculate element center from bounding rect
|
|
825
|
+
*/
|
|
826
|
+
/**
|
|
827
|
+
* Normalizes a layout inset for use in CSS custom properties.
|
|
828
|
+
*
|
|
829
|
+
* @param value - Raw inset from `style` (number, px string, or `auto`).
|
|
830
|
+
* @param fallback - Value used when `value` is undefined.
|
|
831
|
+
*/
|
|
832
|
+
function formatGlassInsetValue(value, fallback = "auto") {
|
|
833
|
+
return void 0 === value ? "number" == typeof fallback ? `${fallback}px` : String(fallback) : "auto" === value ? "auto" : "number" == typeof value ? `${value}px` : value;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Determines whether the glass should use fixed/sticky layout semantics.
|
|
838
|
+
*
|
|
839
|
+
* @param explicit - Value of the `isFixedOrSticky` prop.
|
|
840
|
+
* @param position - `position` from the consumer `style` object.
|
|
841
|
+
*/
|
|
842
|
+
/** Coerces a value to a finite number, returning `fallback` when invalid. */
|
|
843
|
+
function toSafeNumber(value, fallback = 0) {
|
|
844
|
+
return "number" != typeof value || isNaN(value) ? fallback : value;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Calculates the target frame rate for shader time-animation loops.
|
|
849
|
+
*
|
|
850
|
+
* Balances visual quality against distortion complexity and `animationSpeed`.
|
|
851
|
+
*/
|
|
852
|
+
/**
|
|
853
|
+
* Computes per-channel displacement scale for the SVG chromatic-aberration filter.
|
|
854
|
+
*/
|
|
855
|
+
function getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channelFactor) {
|
|
856
|
+
return displacementScale * (("shader" === mode ? 1 : -1) - aberrationIntensity * channelFactor);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Get displacement map URL based on mode
|
|
861
|
+
*/ const getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
862
|
+
switch (mode) {
|
|
863
|
+
case "standard":
|
|
864
|
+
return displacementMap;
|
|
865
|
+
|
|
866
|
+
case "polar":
|
|
867
|
+
return polarDisplacementMap;
|
|
868
|
+
|
|
869
|
+
case "prominent":
|
|
870
|
+
return prominentDisplacementMap;
|
|
871
|
+
|
|
872
|
+
case "shader":
|
|
873
|
+
return shaderMapUrl || displacementMap;
|
|
874
|
+
|
|
875
|
+
default:
|
|
876
|
+
return console.warn("AtomixGlass: Invalid displacement mode"), displacementMap;
|
|
877
|
+
}
|
|
878
|
+
}, sharedShaderCache = new Map, CHROMATIC_CHANNELS = [ {
|
|
879
|
+
result: "RED_DISPLACED",
|
|
880
|
+
channelResult: "RED_CHANNEL",
|
|
881
|
+
aberrationFactor: 0,
|
|
882
|
+
colorMatrix: "1 0 0 0 0\n0 0 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
883
|
+
}, {
|
|
884
|
+
result: "GREEN_DISPLACED",
|
|
885
|
+
channelResult: "GREEN_CHANNEL",
|
|
886
|
+
aberrationFactor: .02,
|
|
887
|
+
colorMatrix: "0 0 0 0 0\n0 1 0 0 0\n0 0 0 0 0\n0 0 0 1 0"
|
|
888
|
+
}, {
|
|
889
|
+
result: "BLUE_DISPLACED",
|
|
890
|
+
channelResult: "BLUE_CHANNEL",
|
|
891
|
+
aberrationFactor: .03,
|
|
892
|
+
colorMatrix: "0 0 0 0 0\n0 0 0 0 0\n0 0 1 0 0\n0 0 0 1 0"
|
|
893
|
+
} ], FILTER_SVG_STYLE = {
|
|
894
|
+
position: "absolute",
|
|
895
|
+
width: "100%",
|
|
896
|
+
height: "100%",
|
|
897
|
+
inset: 0
|
|
898
|
+
}, GlassFilterComponent = ({id: id, displacementScale: displacementScale, aberrationIntensity: aberrationIntensity, mode: mode, shaderMapUrl: shaderMapUrl, blurAmount: blurAmount}) => jsx("svg", {
|
|
899
|
+
style: FILTER_SVG_STYLE,
|
|
900
|
+
"aria-hidden": "true",
|
|
901
|
+
children: jsxs("defs", {
|
|
902
|
+
children: [ jsxs("radialGradient", {
|
|
903
|
+
id: `${id}-edge-mask`,
|
|
904
|
+
cx: "50%",
|
|
905
|
+
cy: "50%",
|
|
906
|
+
r: "50%",
|
|
907
|
+
children: [ jsx("stop", {
|
|
908
|
+
offset: "0%",
|
|
909
|
+
stopColor: "black",
|
|
910
|
+
stopOpacity: "0"
|
|
911
|
+
}), jsx("stop", {
|
|
912
|
+
offset: `${Math.max(30, 80 - 2 * aberrationIntensity)}%`,
|
|
913
|
+
stopColor: "black",
|
|
914
|
+
stopOpacity: "0"
|
|
915
|
+
}), jsx("stop", {
|
|
916
|
+
offset: "100%",
|
|
917
|
+
stopColor: "white",
|
|
918
|
+
stopOpacity: "1"
|
|
919
|
+
}) ]
|
|
920
|
+
}), jsxs("filter", {
|
|
921
|
+
id: id,
|
|
922
|
+
x: "-35%",
|
|
923
|
+
y: "-35%",
|
|
924
|
+
width: "170%",
|
|
925
|
+
height: "170%",
|
|
926
|
+
colorInterpolationFilters: "sRGB",
|
|
927
|
+
children: [ jsx("feImage", {
|
|
928
|
+
id: `${id}-image`,
|
|
929
|
+
x: "0",
|
|
930
|
+
y: "0",
|
|
931
|
+
width: "100%",
|
|
932
|
+
height: "100%",
|
|
933
|
+
result: "DISPLACEMENT_MAP",
|
|
934
|
+
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),
|
|
935
|
+
preserveAspectRatio: "xMidYMid slice"
|
|
936
|
+
}), jsx("feColorMatrix", {
|
|
937
|
+
in: "DISPLACEMENT_MAP",
|
|
938
|
+
type: "matrix",
|
|
939
|
+
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",
|
|
940
|
+
result: "EDGE_INTENSITY"
|
|
941
|
+
}), jsx("feComponentTransfer", {
|
|
942
|
+
in: "EDGE_INTENSITY",
|
|
943
|
+
result: "EDGE_MASK",
|
|
944
|
+
children: jsx("feFuncA", {
|
|
945
|
+
type: "discrete",
|
|
946
|
+
tableValues: `0 ${.05 * aberrationIntensity} 1`
|
|
947
|
+
})
|
|
948
|
+
}), jsx("feOffset", {
|
|
949
|
+
in: "SourceGraphic",
|
|
950
|
+
dx: "0",
|
|
951
|
+
dy: "0",
|
|
952
|
+
result: "CENTER_ORIGINAL"
|
|
953
|
+
}), CHROMATIC_CHANNELS.map((channel => jsxs(React.Fragment, {
|
|
954
|
+
children: [ jsx("feDisplacementMap", {
|
|
955
|
+
in: "SourceGraphic",
|
|
956
|
+
in2: "DISPLACEMENT_MAP",
|
|
957
|
+
scale: getChromaticDisplacementScale(mode, displacementScale, aberrationIntensity, channel.aberrationFactor),
|
|
958
|
+
xChannelSelector: "R",
|
|
959
|
+
yChannelSelector: "B",
|
|
960
|
+
result: channel.result
|
|
961
|
+
}), jsx("feColorMatrix", {
|
|
962
|
+
in: channel.result,
|
|
963
|
+
type: "matrix",
|
|
964
|
+
values: channel.colorMatrix,
|
|
965
|
+
result: channel.channelResult
|
|
966
|
+
}) ]
|
|
967
|
+
}, channel.channelResult))), jsx("feBlend", {
|
|
968
|
+
in: "GREEN_CHANNEL",
|
|
969
|
+
in2: "BLUE_CHANNEL",
|
|
970
|
+
mode: "screen",
|
|
971
|
+
result: "GB_COMBINED"
|
|
972
|
+
}), jsx("feBlend", {
|
|
973
|
+
in: "RED_CHANNEL",
|
|
974
|
+
in2: "GB_COMBINED",
|
|
975
|
+
mode: "screen",
|
|
976
|
+
result: "RGB_COMBINED"
|
|
977
|
+
}), jsx("feGaussianBlur", {
|
|
978
|
+
in: "RGB_COMBINED",
|
|
979
|
+
result: "ABERRATED_BLURRED",
|
|
980
|
+
stdDeviation: blurAmount * aberrationIntensity * .05
|
|
981
|
+
}), jsx("feComposite", {
|
|
982
|
+
in: "ABERRATED_BLURRED",
|
|
983
|
+
in2: "EDGE_MASK",
|
|
984
|
+
operator: "in",
|
|
985
|
+
result: "EDGE_ABERRATION"
|
|
986
|
+
}), jsx("feComponentTransfer", {
|
|
987
|
+
in: "EDGE_MASK",
|
|
988
|
+
result: "INVERTED_MASK",
|
|
989
|
+
children: jsx("feFuncA", {
|
|
990
|
+
type: "table",
|
|
991
|
+
tableValues: "1 0"
|
|
992
|
+
})
|
|
993
|
+
}), jsx("feComposite", {
|
|
994
|
+
in: "CENTER_ORIGINAL",
|
|
995
|
+
in2: "INVERTED_MASK",
|
|
996
|
+
operator: "in",
|
|
997
|
+
result: "CENTER_CLEAN"
|
|
998
|
+
}), jsx("feComposite", {
|
|
999
|
+
in: "EDGE_ABERRATION",
|
|
1000
|
+
in2: "CENTER_CLEAN",
|
|
1001
|
+
operator: "over"
|
|
1002
|
+
}) ]
|
|
1003
|
+
}) ]
|
|
1004
|
+
})
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* Module-level LRU cache for shader displacement maps.
|
|
1009
|
+
*
|
|
1010
|
+
* Shared across all `AtomixGlassContainer` instances so identical size and
|
|
1011
|
+
* variant combinations are generated once.
|
|
1012
|
+
*/ GlassFilterComponent.displayName = "GlassFilter";
|
|
1013
|
+
|
|
1014
|
+
/** Shallow prop comparison to avoid redundant SVG filter regeneration. */
|
|
1015
|
+
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)), AtomixGlassContainer = forwardRef((({children: children, className: className = "", style: style, displacementScale: displacementScale = 25, blurAmount: blurAmount = .0625, saturation: saturation = 180, aberrationIntensity: aberrationIntensity = 2, mouseOffset: mouseOffset = {
|
|
1016
|
+
x: 0,
|
|
1017
|
+
y: 0
|
|
1018
|
+
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, glassSize: glassSize = {
|
|
1019
|
+
width: 0,
|
|
1020
|
+
height: 0
|
|
1021
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
1022
|
+
// React 18 useId — stable, unique, and SSR-safe (no module-level counter)
|
|
1023
|
+
const rawId = useId(), filterId = useMemo((() => `atomix-glass-filter-${rawId.replace(/:/g, "")}`), [ rawId ]), containerRef = useForkRef(ref, null), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
1024
|
+
// Lazy load shader utilities only when shader mode is needed
|
|
1025
|
+
useEffect((() => {
|
|
1026
|
+
"shader" === mode ?
|
|
1027
|
+
// Dynamic import shader utilities with animation support
|
|
1028
|
+
Promise.resolve().then((() => shaderUtils)).then((shaderUtils => {
|
|
1029
|
+
shaderUtilsRef.current = {
|
|
1030
|
+
ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
|
|
1031
|
+
fragmentShaders: shaderUtils.fragmentShaders
|
|
1032
|
+
};
|
|
1033
|
+
})).catch((error => {
|
|
1034
|
+
console.warn("AtomixGlassContainer: Error loading shader utilities", String(error).replace(/[\r\n]/g, ""));
|
|
618
1035
|
})) :
|
|
619
1036
|
// Clear shader utils when not in shader mode to free memory
|
|
620
1037
|
shaderUtilsRef.current = null;
|
|
@@ -681,15 +1098,23 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
681
1098
|
shaderGeneratorRef.current = null;
|
|
682
1099
|
}
|
|
683
1100
|
};
|
|
684
|
-
}), [ mode, glassSize, shaderVariant ]),
|
|
685
|
-
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
686
|
-
useEffect((() => {
|
|
1101
|
+
}), [ mode, glassSize, shaderVariant ]), useEffect((() => {
|
|
687
1102
|
// Only run animations in shader mode with time animation enabled
|
|
688
1103
|
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
689
1104
|
// Cancel any existing animation frame
|
|
690
1105
|
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
691
1106
|
animationFrameRef.current = null));
|
|
692
|
-
const
|
|
1107
|
+
const targetFps = function(options) {
|
|
1108
|
+
const {distortionQuality: distortionQuality, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5} = options, baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed)), complexity = withMultiLayerDistortion ? Math.max(1, distortionOctaves / 3 + .25 * Math.max(0, distortionLacunarity - 2) + Math.max(0, distortionGain - .5)) : 1;
|
|
1109
|
+
return Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
|
|
1110
|
+
}({
|
|
1111
|
+
distortionQuality: distortionQuality,
|
|
1112
|
+
animationSpeed: animationSpeed,
|
|
1113
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
1114
|
+
distortionOctaves: distortionOctaves,
|
|
1115
|
+
distortionLacunarity: distortionLacunarity,
|
|
1116
|
+
distortionGain: distortionGain
|
|
1117
|
+
}), frameInterval = 1e3 / targetFps;
|
|
693
1118
|
let lastUpdate = 0, isCancelled = !1;
|
|
694
1119
|
const animate = currentTime => {
|
|
695
1120
|
if (!isCancelled) {
|
|
@@ -713,88 +1138,21 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
713
1138
|
};
|
|
714
1139
|
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
715
1140
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
716
|
-
const
|
|
717
|
-
useEffect((() => {
|
|
718
|
-
if (!ref || "function" == typeof ref) return;
|
|
719
|
-
const element = ref.current;
|
|
720
|
-
if (element) try {
|
|
721
|
-
setRectCache(element.getBoundingClientRect());
|
|
722
|
-
} catch (error) {
|
|
723
|
-
console.warn("AtomixGlassContainer: Error getting element bounds", error), setRectCache(null);
|
|
724
|
-
}
|
|
725
|
-
}), [ ref, glassSize ]);
|
|
726
|
-
const liquidBlur = useMemo((() => {
|
|
727
|
-
const defaultBlur = {
|
|
728
|
-
baseBlur: blurAmount,
|
|
729
|
-
edgeBlur: 1.25 * blurAmount,
|
|
730
|
-
centerBlur: 1.1 * blurAmount,
|
|
731
|
-
flowBlur: 1.2 * blurAmount
|
|
732
|
-
};
|
|
733
|
-
// Enhanced validation for liquid blur
|
|
734
|
-
if (!withLiquidBlur || !rectCache || !mouseOffset || "number" != typeof mouseOffset.x || "number" != typeof mouseOffset.y || isNaN(mouseOffset.x) || isNaN(mouseOffset.y)) return defaultBlur;
|
|
735
|
-
try {
|
|
736
|
-
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = 2 * blurAmount, baseBlur = Math.min(maxBlur, blurAmount + mouseInfluence * blurAmount * .15), edgeIntensity = .15 * mouseInfluence, edgeBlur = Math.min(maxBlur, baseBlur * (.8 + .4 * edgeIntensity)), centerIntensity = .1 * mouseInfluence, centerBlur = Math.min(maxBlur, baseBlur * (.3 + .3 * centerIntensity)), flowBlur = Math.min(maxBlur, 1.2 * baseBlur);
|
|
737
|
-
// NOTE: hover/active multipliers intentionally omitted here —
|
|
738
|
-
// they belong on opacity layers, not the blur filter itself.
|
|
739
|
-
return {
|
|
740
|
-
baseBlur: clampBlur(baseBlur),
|
|
741
|
-
edgeBlur: clampBlur(edgeBlur),
|
|
742
|
-
centerBlur: clampBlur(centerBlur),
|
|
743
|
-
flowBlur: clampBlur(flowBlur)
|
|
744
|
-
};
|
|
745
|
-
} catch (error) {
|
|
746
|
-
return console.warn("AtomixGlassContainer: Error calculating liquid blur", error),
|
|
747
|
-
defaultBlur;
|
|
748
|
-
}
|
|
749
|
-
}), [ withLiquidBlur, blurAmount, mouseOffset, rectCache ]), backdropStyle = useMemo((() => {
|
|
750
|
-
try {
|
|
751
|
-
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;
|
|
752
|
-
// Validate blur values before using them
|
|
753
|
-
return !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? {
|
|
754
|
-
backdropFilter: `blur(${clampBlur(Math.max(validatedBaseBlur, .8 * validatedEdgeBlur, 1.1 * validatedCenterBlur, .9 * validatedFlowBlur))}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`
|
|
755
|
-
} : {
|
|
756
|
-
backdropFilter: `blur(${clampBlur(.4 * validatedBaseBlur + .25 * validatedEdgeBlur + .15 * validatedCenterBlur + .2 * validatedFlowBlur)}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1}) brightness(${overLightConfig?.brightness || 1})`
|
|
757
|
-
};
|
|
758
|
-
// Single-pass fallback: stronger radius to match perceived blur of multi-pass
|
|
759
|
-
} catch (error) {
|
|
760
|
-
return console.warn("AtomixGlassContainer: Error calculating backdrop style", error),
|
|
761
|
-
{
|
|
762
|
-
backdropFilter: `blur(${blurAmount}px) saturate(${saturation}%) contrast(1.05) brightness(1.05)`
|
|
763
|
-
};
|
|
764
|
-
}
|
|
765
|
-
}), [ liquidBlur, saturation, blurAmount, rectCache, effectiveReducedMotion, effectiveWithoutEffects, withLiquidBlur, overLightConfig ]), containerVars = useMemo((() => {
|
|
1141
|
+
const containerVars = useMemo((() => {
|
|
766
1142
|
try {
|
|
767
|
-
// Safe extraction of mouse offset values
|
|
768
|
-
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;
|
|
769
1143
|
return {
|
|
770
|
-
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px
|
|
771
|
-
"--atomix-glass-container-backdrop": backdropStyle?.backdropFilter || "none",
|
|
772
|
-
"--atomix-glass-container-shadow": overLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.4 + .002 * mx) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.2 + .001 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.08 + .001 * Math.abs(mx + my)) * (overLightConfig?.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.12 + .002 * Math.abs(my)) * (overLightConfig?.shadowIntensity || 1)})` ].join(", ") : "0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset",
|
|
773
|
-
"--atomix-glass-container-shadow-opacity": effectiveWithoutEffects ? 0 : 1,
|
|
774
|
-
// Background and shadow values use design token-aligned RGB values
|
|
775
|
-
"--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",
|
|
776
|
-
"--atomix-glass-container-text-shadow": overLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)",
|
|
777
|
-
"--atomix-glass-container-box-shadow": overLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)"
|
|
1144
|
+
"--atomix-glass-container-radius": `${"number" != typeof borderRadius || isNaN(borderRadius) ? 0 : borderRadius}px`
|
|
778
1145
|
};
|
|
779
1146
|
} catch (error) {
|
|
780
1147
|
return console.warn("AtomixGlassContainer: Error generating container variables", error),
|
|
781
1148
|
{
|
|
782
|
-
"--atomix-glass-container-
|
|
783
|
-
"--atomix-glass-container-radius": "0px",
|
|
784
|
-
"--atomix-glass-container-backdrop": "none",
|
|
785
|
-
"--atomix-glass-container-shadow": "none",
|
|
786
|
-
"--atomix-glass-container-shadow-opacity": 1,
|
|
787
|
-
"--atomix-glass-container-bg": "none",
|
|
788
|
-
"--atomix-glass-container-text-shadow": "none"
|
|
1149
|
+
"--atomix-glass-container-radius": "0px"
|
|
789
1150
|
};
|
|
790
1151
|
}
|
|
791
|
-
}), [ borderRadius
|
|
1152
|
+
}), [ borderRadius ]);
|
|
792
1153
|
return jsx("div", {
|
|
793
|
-
ref:
|
|
794
|
-
|
|
795
|
-
"function" == typeof ref ? ref(el) : ref && (ref.current = el);
|
|
796
|
-
},
|
|
797
|
-
className: `${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ""} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ""}`,
|
|
1154
|
+
ref: containerRef,
|
|
1155
|
+
className: mergeClassNames(ATOMIX_GLASS.CONTAINER_CLASS, className, isActive && ATOMIX_GLASS.CLASSES.ACTIVE, overLight && ATOMIX_GLASS.CLASSES.OVER_LIGHT),
|
|
798
1156
|
style: {
|
|
799
1157
|
...style,
|
|
800
1158
|
...containerVars
|
|
@@ -812,8 +1170,8 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
812
1170
|
blurAmount: blurAmount,
|
|
813
1171
|
mode: mode,
|
|
814
1172
|
id: filterId,
|
|
815
|
-
displacementScale:
|
|
816
|
-
aberrationIntensity:
|
|
1173
|
+
displacementScale: toSafeNumber(displacementScale),
|
|
1174
|
+
aberrationIntensity: toSafeNumber(aberrationIntensity),
|
|
817
1175
|
shaderMapUrl: shaderMapUrl
|
|
818
1176
|
}), jsx("div", {
|
|
819
1177
|
className: ATOMIX_GLASS.FILTER_OVERLAY_CLASS,
|
|
@@ -835,8 +1193,12 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
835
1193
|
});
|
|
836
1194
|
}));
|
|
837
1195
|
|
|
838
|
-
|
|
839
|
-
|
|
1196
|
+
/**
|
|
1197
|
+
* Internal glass surface that owns backdrop-filter, SVG distortion, and content.
|
|
1198
|
+
*
|
|
1199
|
+
* Layout and stacking styles are applied via the `style` prop from the parent.
|
|
1200
|
+
* The root wrapper supplies CSS custom properties only.
|
|
1201
|
+
*/ AtomixGlassContainer.displayName = "AtomixGlassContainer";
|
|
840
1202
|
|
|
841
1203
|
// Singleton instance
|
|
842
1204
|
const globalMouseTracker = new
|
|
@@ -951,28 +1313,32 @@ class {
|
|
|
951
1313
|
*/ getSubscriberCount() {
|
|
952
1314
|
return this.listeners.size;
|
|
953
1315
|
}
|
|
954
|
-
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
1316
|
+
}, {BORDER: BORDER, CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, BORDER_GRADIENT = BORDER.GRADIENT, WHITE = CONSTANTS$2.PALETTE.WHITE, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
955
1317
|
if (!wrapperElement && !containerElement) return;
|
|
956
1318
|
if (!validateGlassSize(params.glassSize)) return;
|
|
957
|
-
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION,
|
|
1319
|
+
const {mouseOffset: mouseOffset, globalMousePosition: globalMousePosition, glassSize: glassSize, isHovered: isHovered, isActive: isActive, isOverLight: isOverLight, baseOverLightConfig: baseOverLightConfig, effectiveBorderRadius: effectiveBorderRadius, effectiveWithoutEffects: effectiveWithoutEffects, effectiveReducedMotion: effectiveReducedMotion, elasticity: elasticity, elasticTranslation: elasticTranslation, elasticVelocity: elasticVelocity, mouseVelocity: mouseVelocity, directionalScale: directionalScale, scaleBase: scaleBase, onClick: onClick, withLiquidBlur: withLiquidBlur, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, isFixedOrSticky: isFixedOrSticky = !1, borderAnimated: borderAnimated = !0, borderOpacityMultiplier: borderOpacityMultiplier = 1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), overLightConfig = {
|
|
958
1320
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
959
1321
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
960
1322
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
961
1323
|
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
962
1324
|
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
963
1325
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
964
|
-
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`,
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
x
|
|
970
|
-
|
|
971
|
-
}
|
|
1326
|
+
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, tensionFactor =
|
|
1327
|
+
/**
|
|
1328
|
+
* Computes tension factor from elastic translation magnitude (0–1).
|
|
1329
|
+
*/
|
|
1330
|
+
function(elasticTranslation) {
|
|
1331
|
+
const magnitude = Math.hypot(elasticTranslation.x, elasticTranslation.y);
|
|
1332
|
+
return smoothstep(magnitude / 80);
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
1336
|
+
* to avoid React re-renders on mouse movement.
|
|
1337
|
+
*/ (elasticTranslation), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
|
|
972
1338
|
// Calculate mouse influence
|
|
973
1339
|
// Update Wrapper Styles (glassVars)
|
|
974
1340
|
if (wrapperElement) {
|
|
975
|
-
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT,
|
|
1341
|
+
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
976
1342
|
hover1: {
|
|
977
1343
|
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
978
1344
|
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
@@ -989,28 +1355,55 @@ class {
|
|
|
989
1355
|
x: GRADIENT.CENTER_POSITION + mx * GRADIENT.BASE_LAYER_MULTIPLIER,
|
|
990
1356
|
y: GRADIENT.CENTER_POSITION + my * GRADIENT.BASE_LAYER_MULTIPLIER
|
|
991
1357
|
}, opacityValues = {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1358
|
+
// hover-1: ambient highlight glow — present on hover and during press
|
|
1359
|
+
hover1: isHovered || isActive ? 1 : 0,
|
|
1360
|
+
// hover-2: press depth shadow — only fires on active (mousedown)
|
|
1361
|
+
hover2: isActive ? 1 : 0,
|
|
1362
|
+
// hover-3: global soft-light surface shift — half-strength on hover, full on press
|
|
1363
|
+
hover3: isActive ? 1 : isHovered ? .55 : 0,
|
|
1364
|
+
// Dark chrome: faint smoky tint; over-light keeps stronger fill
|
|
1365
|
+
base: isOverLight ? overLightConfig.opacity : .14,
|
|
1366
|
+
over: isOverLight ? 1.1 * overLightConfig.opacity : .1
|
|
997
1367
|
}, style = wrapperElement.style;
|
|
998
1368
|
style.setProperty("--atomix-glass-transform", transformStyle || "none");
|
|
999
1369
|
// Parallax for content (liquid refraction feel)
|
|
1000
1370
|
const parallaxFactor = .38 + .12 * tensionFactor;
|
|
1001
1371
|
style.setProperty("--atomix-glass-child-parallax", `translate(${elasticTranslation.x * -parallaxFactor}px, ${elasticTranslation.y * -parallaxFactor}px)`),
|
|
1002
|
-
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString())
|
|
1372
|
+
style.setProperty("--atomix-glass-contrast", lightingContrast.toString()), style.setProperty("--atomix-glass-brightness", lightingBrightness.toString());
|
|
1003
1373
|
// ── Chromatic Rim Lighting ──────────────────────────────────────
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1374
|
+
const borderVars = ATOMIX_GLASS.BORDER.GRADIENT_CSS_VARS;
|
|
1375
|
+
if (borderAnimated && !effectiveWithoutEffects) {
|
|
1376
|
+
const borderCssVars =
|
|
1377
|
+
/**
|
|
1378
|
+
* Builds animated chromatic rim CSS variables for border layers 1 and 2.
|
|
1379
|
+
* When empty, SCSS static conic/linear fallbacks apply.
|
|
1380
|
+
*/
|
|
1381
|
+
function(params) {
|
|
1382
|
+
const {mouseOffset: mouseOffset, mouseVelocity: mouseVelocity, elasticVelocity: elasticVelocity, borderOpacity: borderOpacity, opacityMultiplier: opacityMultiplier = 1, tensionFactor: tensionFactor = 0} = params, mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), velocityRotation = (mouseVelocity.x + elasticVelocity.x) * BORDER_GRADIENT.VELOCITY_ANGLE_MULTIPLIER, borderGradientAngle = BORDER_GRADIENT.BASE_ANGLE + mx * BORDER_GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = BORDER_GRADIENT.CHROMATIC_OFFSET, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, borderStop1 = Math.max(BORDER_GRADIENT.STOP_1.MIN, BORDER_GRADIENT.STOP_1.BASE + my * BORDER_GRADIENT.STOP_1.MULTIPLIER), borderStop2 = Math.min(BORDER_GRADIENT.STOP_2.MAX, BORDER_GRADIENT.STOP_2.BASE + my * BORDER_GRADIENT.STOP_2.MULTIPLIER), tensionGlow = 1 + .5 * tensionFactor, opacities = BORDER_GRADIENT.OPACITY, borderOpacities = [ (opacities.BASE_1 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_2 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow, (opacities.BASE_3 + absMx * opacities.MULTIPLIER_LOW) * tensionGlow, (opacities.BASE_4 + absMx * opacities.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = borderOpacity * opacityMultiplier, gradient1 = `linear-gradient(${angleB}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`, gradient2 = `linear-gradient(${angleR}deg, rgba(${WHITE}, 0) 0%, rgba(${WHITE}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${WHITE}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${WHITE}, 0) 100%)`;
|
|
1383
|
+
return {
|
|
1384
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_1]: gradient1,
|
|
1385
|
+
[BORDER.GRADIENT_CSS_VARS.GRADIENT_2]: gradient2
|
|
1386
|
+
};
|
|
1387
|
+
}({
|
|
1388
|
+
mouseOffset: mouseOffset,
|
|
1389
|
+
mouseVelocity: mouseVelocity,
|
|
1390
|
+
elasticVelocity: elasticVelocity,
|
|
1391
|
+
borderOpacity: overLightConfig.borderOpacity,
|
|
1392
|
+
opacityMultiplier: borderOpacityMultiplier,
|
|
1393
|
+
tensionFactor: tensionFactor
|
|
1394
|
+
});
|
|
1395
|
+
style.setProperty(borderVars.GRADIENT_1, borderCssVars[borderVars.GRADIENT_1] ?? ""),
|
|
1396
|
+
style.setProperty(borderVars.GRADIENT_2, borderCssVars[borderVars.GRADIENT_2] ?? "");
|
|
1397
|
+
} else style.removeProperty(borderVars.GRADIENT_1), style.removeProperty(borderVars.GRADIENT_2);
|
|
1398
|
+
// Hover gradients — cursor-relative radial positions for realistic light tracking.
|
|
1399
|
+
// hover-1: white overlay highlight following cursor (works on both dark + light)
|
|
1400
|
+
style.setProperty("--atomix-glass-hover-1-gradient", `radial-gradient(65% 55% at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, 0.24) 0%, rgba(${whiteColor}, 0.06) 45%, rgba(${whiteColor}, 0) 72%)`),
|
|
1401
|
+
// hover-2: press depth — darkens at cursor with multiply blend, isOverLight uses stronger black
|
|
1402
|
+
style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.22) 0%, rgba(${blackColor}, 0.06) 50%, rgba(${blackColor}, 0) 72%)` : `radial-gradient(60% 50% at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, 0.18) 0%, rgba(${blackColor}, 0.04) 50%, rgba(${blackColor}, 0) 72%)`),
|
|
1403
|
+
// hover-3: full-surface soft-light tint; linear gradient angled with cursor X
|
|
1404
|
+
style.setProperty("--atomix-glass-hover-3-gradient", `linear-gradient(${150 + .3 * mx}deg, rgba(${whiteColor}, ${isOverLight ? .08 : .12}) 0%, rgba(${whiteColor}, 0.04) 55%, rgba(${whiteColor}, 0) 100%)`),
|
|
1405
|
+
style.setProperty("--atomix-glass-base-gradient", isOverLight ? `linear-gradient(${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.ANGLE}deg, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_BASE + mx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_BASE + my * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_MULTIPLIER}) ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_BASE + absMx * ATOMIX_GLASS.CONSTANTS.BASE_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `linear-gradient(180deg, rgba(${blackColor}, 0.42) 0%, rgba(${blackColor}, 0.22) 55%, rgba(${blackColor}, 0.12) 100%)`),
|
|
1406
|
+
style.setProperty("--atomix-glass-overlay-gradient", isOverLight ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)` : `radial-gradient(120% 80% at 50% 0%, rgba(${whiteColor}, 0.14) 0%, rgba(${whiteColor}, 0) 55%)`),
|
|
1014
1407
|
// Opacities
|
|
1015
1408
|
style.setProperty("--atomix-glass-hover-1-opacity", opacityValues.hover1.toString()),
|
|
1016
1409
|
style.setProperty("--atomix-glass-hover-2-opacity", opacityValues.hover2.toString()),
|
|
@@ -1047,151 +1440,16 @@ class {
|
|
|
1047
1440
|
backdropFilterString = !withLiquidBlur || effectiveReducedMotion || effectiveWithoutEffects || area > 18e4 ? `blur(${clampBlur(Math.max(liquidBlur.baseBlur, .8 * liquidBlur.edgeBlur, 1.1 * liquidBlur.centerBlur, .9 * liquidBlur.flowBlur))}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})` : `blur(${clampBlur(.4 * liquidBlur.baseBlur + .25 * liquidBlur.edgeBlur + .15 * liquidBlur.centerBlur + .2 * liquidBlur.flowBlur)}px) saturate(${Math.min(dynamicSaturation, 250)}%) contrast(${lightingContrast}) brightness(${lightingBrightness})`;
|
|
1048
1441
|
// Container variables
|
|
1049
1442
|
const style = containerElement.style;
|
|
1050
|
-
style.setProperty("--atomix-glass-container-
|
|
1443
|
+
style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
1051
1444
|
style.setProperty("--atomix-glass-container-backdrop", backdropFilterString),
|
|
1052
1445
|
// Shadows
|
|
1053
|
-
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.
|
|
1446
|
+
style.setProperty("--atomix-glass-container-shadow", isOverLight ? [ `inset 0 1px 0 rgba(255, 255, 255, ${(.35 + .002 * mx) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 -1px 0 rgba(0, 0, 0, ${(.15 + .001 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})`, `inset 0 0 20px rgba(0, 0, 0, ${(.06 + .001 * Math.abs(mx + my)) * (overLightConfig.shadowIntensity || 1)})`, `0 2px 12px rgba(0, 0, 0, ${(.08 + .002 * Math.abs(my)) * (overLightConfig.shadowIntensity || 1)})` ].join(", ") : ATOMIX_GLASS.CONSTANTS.CONTAINER_SHADOW.LIGHT),
|
|
1054
1447
|
style.setProperty("--atomix-glass-container-shadow-opacity", effectiveWithoutEffects ? "0" : "1"),
|
|
1055
1448
|
style.setProperty("--atomix-glass-container-bg", isOverLight ? `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"),
|
|
1056
1449
|
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
1057
|
-
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "
|
|
1450
|
+
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0 4px 16px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.10)");
|
|
1058
1451
|
}
|
|
1059
|
-
};
|
|
1060
|
-
|
|
1061
|
-
/**
|
|
1062
|
-
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
1063
|
-
* to avoid React re-renders on mouse movement.
|
|
1064
|
-
*/
|
|
1065
|
-
/**
|
|
1066
|
-
* Animation System for AtomixGlass Component
|
|
1067
|
-
*
|
|
1068
|
-
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
1069
|
-
* - Feature 1.1: Time-Based Animation System
|
|
1070
|
-
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
1071
|
-
*
|
|
1072
|
-
* @packageDocumentation
|
|
1073
|
-
*/
|
|
1074
|
-
// ============================================================================
|
|
1075
|
-
// Noise Functions for FBM (Feature 1.2)
|
|
1076
|
-
// ============================================================================
|
|
1077
|
-
/**
|
|
1078
|
-
* Perlin noise implementation for smooth gradient noise
|
|
1079
|
-
*
|
|
1080
|
-
* @param x - X coordinate
|
|
1081
|
-
* @param y - Y coordinate
|
|
1082
|
-
* @returns Noise value in range [0, 1]
|
|
1083
|
-
*/
|
|
1084
|
-
function perlinNoise(x, y) {
|
|
1085
|
-
// Simplified Perlin noise using pseudo-random gradients
|
|
1086
|
-
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = fade(xf), v = fade(yf), A = p[X] + Y & 255, B = p[X + 1] + Y & 255, ga = grad(p[A], xf, yf), gb = grad(p[B], xf - 1, yf), gc = grad(p[A + 1 & 255], xf, yf - 1), gd = grad(p[B + 1 & 255], xf - 1, yf - 1), lerpX1 = lerp(ga, gb, u), lerpX2 = lerp(gc, gd, u);
|
|
1087
|
-
// Scale to [0, 1] range
|
|
1088
|
-
return (lerp(lerpX1, lerpX2, v) + 1) / 2;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// ============================================================================
|
|
1092
|
-
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
1093
|
-
// ============================================================================
|
|
1094
|
-
/**
|
|
1095
|
-
* Creates an FBM engine with configurable parameters
|
|
1096
|
-
*
|
|
1097
|
-
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
1098
|
-
* @returns Object with fbm function
|
|
1099
|
-
*
|
|
1100
|
-
* @example
|
|
1101
|
-
* ```typescript
|
|
1102
|
-
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
1103
|
-
*
|
|
1104
|
-
* // Generate noise at position (0.5, 0.5) with time animation
|
|
1105
|
-
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
1106
|
-
* ```
|
|
1107
|
-
*/ function createFBMEngine(config) {
|
|
1108
|
-
/**
|
|
1109
|
-
* Fractal Brownian Motion function
|
|
1110
|
-
* Combines multiple octaves of noise for complex, natural patterns
|
|
1111
|
-
*
|
|
1112
|
-
* @param x - X coordinate
|
|
1113
|
-
* @param y - Y coordinate
|
|
1114
|
-
* @param time - Optional time value for animation
|
|
1115
|
-
* @returns FBM noise value in range [0, 1]
|
|
1116
|
-
*/
|
|
1117
|
-
const fbm = (x, y, time = 0) => {
|
|
1118
|
-
let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
|
|
1119
|
-
// Convert to seconds for reasonable animation speed
|
|
1120
|
-
for (let i = 0; i < config.octaves; i++)
|
|
1121
|
-
// Apply time-based phase shift to all octaves
|
|
1122
|
-
value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
|
|
1123
|
-
frequency *= config.lacunarity, // Increase frequency
|
|
1124
|
-
amplitude *= config.gain;
|
|
1125
|
-
return value;
|
|
1126
|
-
};
|
|
1127
|
-
/**
|
|
1128
|
-
* Get FBM with simple time factor
|
|
1129
|
-
*/ return {
|
|
1130
|
-
fbm: fbm,
|
|
1131
|
-
fbmWithTime: (x, y, time) => fbm(x, y, time)
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
/**
|
|
1136
|
-
* Gets optimal FBM config based on quality preset
|
|
1137
|
-
*
|
|
1138
|
-
* @param quality - Quality preset level
|
|
1139
|
-
* @returns FBM configuration for the quality level
|
|
1140
|
-
*/ const fbmEngineCache = new Map;
|
|
1141
|
-
|
|
1142
|
-
// ============================================================================
|
|
1143
|
-
// Shader Utility Functions for Time-Based Effects
|
|
1144
|
-
// ============================================================================
|
|
1145
|
-
/**
|
|
1146
|
-
* Liquid glass distortion with time-based animation
|
|
1147
|
-
* Uses FBM to create organic, flowing liquid effects
|
|
1148
|
-
*
|
|
1149
|
-
* @param uv - UV coordinates (normalized 0-1)
|
|
1150
|
-
* @param time - Elapsed time in milliseconds
|
|
1151
|
-
* @param config - FBM configuration
|
|
1152
|
-
* @returns Distorted UV coordinates
|
|
1153
|
-
*/ function liquidGlassWithTime(uv, time, config) {
|
|
1154
|
-
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
1155
|
-
let fbmEngine = fbmEngineCache.get(configKey);
|
|
1156
|
-
fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
|
|
1157
|
-
// Animate noise with time
|
|
1158
|
-
const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
|
|
1159
|
-
return {
|
|
1160
|
-
x: uv.x + .04 * (animatedNoise - .5),
|
|
1161
|
-
y: uv.y + .04 * (animatedNoise - .5)
|
|
1162
|
-
};
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
// ============================================================================
|
|
1166
|
-
// Helper Functions
|
|
1167
|
-
// ============================================================================
|
|
1168
|
-
/**
|
|
1169
|
-
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
1170
|
-
*/ function fade(t) {
|
|
1171
|
-
return t * t * t * (t * (6 * t - 15) + 10);
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
/**
|
|
1175
|
-
* Linear interpolation
|
|
1176
|
-
*/ function lerp(a, b, t) {
|
|
1177
|
-
return a + t * (b - a);
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
/**
|
|
1181
|
-
* Gradient calculation for Perlin noise
|
|
1182
|
-
*/ function grad(hash, x, y) {
|
|
1183
|
-
const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
|
|
1184
|
-
return (1 & h ? -u : u) + (2 & h ? -v : v);
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
/**
|
|
1188
|
-
* Permutation table for Perlin noise
|
|
1189
|
-
*/ const p = (() => {
|
|
1190
|
-
const permutation = [];
|
|
1191
|
-
for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
|
|
1192
|
-
// Duplicate for overflow handling
|
|
1193
|
-
return [ ...permutation, ...permutation ];
|
|
1194
|
-
})(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
1452
|
+
}, {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
1195
1453
|
|
|
1196
1454
|
const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
1197
1455
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
@@ -1206,12 +1464,35 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
|
|
|
1206
1464
|
* Composable hook for AtomixGlass component logic
|
|
1207
1465
|
* Manages all state, calculations, and event handlers
|
|
1208
1466
|
*/
|
|
1209
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation,
|
|
1210
|
-
// Default priority
|
|
1211
|
-
// Phase 1: Animation System Props
|
|
1212
|
-
withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
|
|
1467
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, border: border, withBorder: withBorder = !0, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1}) {
|
|
1213
1468
|
// State
|
|
1214
|
-
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1),
|
|
1469
|
+
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), resolvedBorder = useMemo((() =>
|
|
1470
|
+
/**
|
|
1471
|
+
* Resolves `border` and legacy `withBorder` into a single configuration object.
|
|
1472
|
+
*/
|
|
1473
|
+
function(border, withBorder) {
|
|
1474
|
+
const legacyDefault = withBorder ?? !0;
|
|
1475
|
+
return void 0 === border ? {
|
|
1476
|
+
enabled: legacyDefault,
|
|
1477
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
1478
|
+
opacityMultiplier: 1,
|
|
1479
|
+
animated: !0
|
|
1480
|
+
} : "boolean" == typeof border ? {
|
|
1481
|
+
enabled: border,
|
|
1482
|
+
width: BORDER.DEFAULT_WIDTH,
|
|
1483
|
+
opacityMultiplier: 1,
|
|
1484
|
+
animated: !0
|
|
1485
|
+
} : {
|
|
1486
|
+
enabled: border.enabled ?? legacyDefault,
|
|
1487
|
+
width: (value = border.width, void 0 === value ? BORDER.DEFAULT_WIDTH : "number" == typeof value ? `${value}px` : value),
|
|
1488
|
+
opacityMultiplier: border.opacity ?? 1,
|
|
1489
|
+
animated: !1 !== border.animated
|
|
1490
|
+
};
|
|
1491
|
+
/**
|
|
1492
|
+
* Formats border width for CSS custom properties.
|
|
1493
|
+
*/
|
|
1494
|
+
var value;
|
|
1495
|
+
}(border, withBorder)), [ border, withBorder ]), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
1215
1496
|
x: 0,
|
|
1216
1497
|
y: 0
|
|
1217
1498
|
}), internalMouseOffsetRef = useRef({
|
|
@@ -1235,52 +1516,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1235
1516
|
}), scaleVelocityRef = useRef({
|
|
1236
1517
|
x: 0,
|
|
1237
1518
|
y: 0
|
|
1238
|
-
})
|
|
1239
|
-
useRef(0);
|
|
1240
|
-
const mouseVelocityRef = useRef({
|
|
1519
|
+
}), mouseVelocityRef = useRef({
|
|
1241
1520
|
x: 0,
|
|
1242
1521
|
y: 0
|
|
1243
|
-
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1),
|
|
1244
|
-
// If quality preset is provided, use it as base
|
|
1245
|
-
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
1246
|
-
// Override with custom values if provided
|
|
1247
|
-
var quality;
|
|
1248
|
-
return {
|
|
1249
|
-
octaves: distortionOctaves ?? preset.octaves,
|
|
1250
|
-
lacunarity: distortionLacunarity ?? preset.lacunarity,
|
|
1251
|
-
gain: distortionGain ?? preset.gain
|
|
1252
|
-
};
|
|
1253
|
-
}), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
|
|
1254
|
-
/**
|
|
1255
|
-
* Animation loop for time-based effects
|
|
1256
|
-
*/
|
|
1257
|
-
useEffect((() => {
|
|
1258
|
-
if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
|
|
1259
|
-
let lastFrameTime = performance.now();
|
|
1260
|
-
/**
|
|
1261
|
-
* Animation frame handler
|
|
1262
|
-
*/ const animate = currentTime => {
|
|
1263
|
-
// Calculate delta time
|
|
1264
|
-
const deltaTime = currentTime - lastFrameTime;
|
|
1265
|
-
lastFrameTime = currentTime;
|
|
1266
|
-
// Apply animation speed multiplier
|
|
1267
|
-
const scaledDelta = deltaTime * animationSpeed;
|
|
1268
|
-
elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
|
|
1269
|
-
// Continue animation loop
|
|
1270
|
-
animationFrameIdRef.current = requestAnimationFrame(animate);
|
|
1271
|
-
};
|
|
1272
|
-
// Start animation
|
|
1273
|
-
// Cleanup
|
|
1274
|
-
return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
|
|
1275
|
-
() => {
|
|
1276
|
-
null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
|
|
1277
|
-
animationFrameIdRef.current = null);
|
|
1278
|
-
};
|
|
1279
|
-
}), [ effectiveWithTimeAnimation, animationSpeed ]);
|
|
1280
|
-
/**
|
|
1281
|
-
* Get current shader time for animations
|
|
1282
|
-
*/
|
|
1283
|
-
const getShaderTime = useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
1522
|
+
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
1284
1523
|
const [glassSize, setGlassSize] = useState({
|
|
1285
1524
|
width: 270,
|
|
1286
1525
|
height: 69
|
|
@@ -1340,9 +1579,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1340
1579
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
1341
1580
|
cachedRectRef: cachedRectRef
|
|
1342
1581
|
}), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
1343
|
-
/**
|
|
1344
|
-
* Apply time-based distortion to UV coordinates
|
|
1345
|
-
*/
|
|
1346
1582
|
// Extract border-radius from children
|
|
1347
1583
|
useEffect((() => {
|
|
1348
1584
|
const extractRadius = () => {
|
|
@@ -1502,25 +1738,26 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1502
1738
|
* Get effective overLight value based on configuration
|
|
1503
1739
|
*/
|
|
1504
1740
|
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((() => {
|
|
1505
|
-
const isOverLight = getEffectiveOverLight(), hoverIntensity
|
|
1741
|
+
const isOverLight = getEffectiveOverLight(), {hoverIntensity: hoverIntensity, activeIntensity: activeIntensity} = getInteractionIntensity(isHovered, isActive), baseConfig = {
|
|
1506
1742
|
isOverLight: isOverLight,
|
|
1507
1743
|
threshold: .7,
|
|
1508
1744
|
opacity: isOverLight ? Math.min(.6, Math.max(.2, .5 * hoverIntensity * activeIntensity)) : 0,
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
shadowIntensity: .9,
|
|
1514
|
-
borderOpacity: .
|
|
1745
|
+
// Dark UI (Apple Music): neutral contrast + slight brightness lift
|
|
1746
|
+
contrast: isOverLight ? 1.4 : 1.02,
|
|
1747
|
+
brightness: isOverLight ? .9 : 1.02,
|
|
1748
|
+
saturationBoost: isOverLight ? 1.3 : 1,
|
|
1749
|
+
shadowIntensity: isOverLight ? .9 : 1,
|
|
1750
|
+
borderOpacity: isOverLight ? ATOMIX_GLASS.BORDER.OVER_LIGHT.opacity : ATOMIX_GLASS.BORDER.DARK.opacity
|
|
1515
1751
|
};
|
|
1516
1752
|
if ("object" == typeof overLight && null !== overLight) {
|
|
1517
|
-
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 = {
|
|
1753
|
+
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), validatedBorderOpacity = validateConfigValue(objConfig.borderOpacity, .1, 1, baseConfig.borderOpacity), finalConfig = {
|
|
1518
1754
|
...baseConfig,
|
|
1519
1755
|
threshold: validatedThreshold,
|
|
1520
1756
|
opacity: validatedOpacity * hoverIntensity * activeIntensity,
|
|
1521
1757
|
contrast: validatedContrast,
|
|
1522
1758
|
brightness: validatedBrightness,
|
|
1523
|
-
saturationBoost: validatedSaturationBoost
|
|
1759
|
+
saturationBoost: validatedSaturationBoost,
|
|
1760
|
+
borderOpacity: validatedBorderOpacity
|
|
1524
1761
|
};
|
|
1525
1762
|
return "undefined" == typeof process || process.env, finalConfig;
|
|
1526
1763
|
}
|
|
@@ -1545,8 +1782,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1545
1782
|
};
|
|
1546
1783
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
1547
1784
|
internalGlobalMousePositionRef.current = {
|
|
1548
|
-
x: lerp
|
|
1549
|
-
y: lerp
|
|
1785
|
+
x: lerp(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
|
|
1786
|
+
y: lerp(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
|
|
1550
1787
|
};
|
|
1551
1788
|
// ── Calculate Elastic Physics ─────────────────────────────────────
|
|
1552
1789
|
let targetElasticTranslation = {
|
|
@@ -1618,12 +1855,13 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1618
1855
|
withLiquidBlur: withLiquidBlur,
|
|
1619
1856
|
blurAmount: blurAmount,
|
|
1620
1857
|
saturation: saturation,
|
|
1621
|
-
|
|
1622
|
-
|
|
1858
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
1859
|
+
borderAnimated: resolvedBorder.animated,
|
|
1860
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
1623
1861
|
}), Math.abs(mouseVelocityRef.current.x) < .001 && Math.abs(mouseVelocityRef.current.y) < .001 && Math.abs(elasticVelocityRef.current.x) < .001 && Math.abs(elasticVelocityRef.current.y) < .001 && Math.abs(scaleVelocityRef.current.x) < .001 && Math.abs(scaleVelocityRef.current.y) < .001 && Math.abs(internalMouseOffsetRef.current.x - targetMouseOffsetRef.current.x) < .001 && Math.abs(internalMouseOffsetRef.current.y - targetMouseOffsetRef.current.y) < .001 ? stopLerpLoop() : lerpRafRef.current = requestAnimationFrame(tick);
|
|
1624
1862
|
};
|
|
1625
1863
|
lerpRafRef.current = requestAnimationFrame(tick);
|
|
1626
|
-
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation,
|
|
1864
|
+
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, isFixedOrSticky, resolvedBorder.animated, resolvedBorder.opacityMultiplier, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
1627
1865
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1628
1866
|
if (effectiveWithoutEffects) return;
|
|
1629
1867
|
const container = mouseContainer?.current || glassRef.current;
|
|
@@ -1687,9 +1925,10 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1687
1925
|
withLiquidBlur: withLiquidBlur,
|
|
1688
1926
|
blurAmount: blurAmount,
|
|
1689
1927
|
saturation: saturation,
|
|
1690
|
-
|
|
1928
|
+
borderAnimated: resolvedBorder.animated,
|
|
1929
|
+
borderOpacityMultiplier: resolvedBorder.opacityMultiplier
|
|
1691
1930
|
});
|
|
1692
|
-
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation,
|
|
1931
|
+
}), [ isHovered, isActive, glassSize, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, wrapperRef, glassRef, externalMouseOffset, externalGlobalMousePosition, withLiquidBlur, blurAmount, saturation, resolvedBorder.animated, resolvedBorder.opacityMultiplier, onClick ]);
|
|
1693
1932
|
// Event handlers
|
|
1694
1933
|
const handleMouseEnter = useCallback((() => setIsHovered(!0)), []), handleMouseLeave = useCallback((() => setIsHovered(!1)), []), handleMouseDown = useCallback((() => setIsActive(!0)), []), handleMouseUp = useCallback((() => setIsActive(!1)), []), handleKeyDown = useCallback((e => {
|
|
1695
1934
|
!onClick || "Enter" !== e.key && " " !== e.key || (e.preventDefault(), onClick());
|
|
@@ -1709,351 +1948,74 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1709
1948
|
mouseOffset: mouseOffset,
|
|
1710
1949
|
// This is now static (refs or props) unless prop changes
|
|
1711
1950
|
overLightConfig: overLightConfig,
|
|
1951
|
+
resolvedBorder: resolvedBorder,
|
|
1712
1952
|
transformStyle: transformStyle,
|
|
1713
|
-
getShaderTime: getShaderTime,
|
|
1714
|
-
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
1715
1953
|
handleMouseEnter: handleMouseEnter,
|
|
1716
1954
|
handleMouseLeave: handleMouseLeave,
|
|
1717
1955
|
handleMouseDown: handleMouseDown,
|
|
1718
1956
|
handleMouseUp: handleMouseUp,
|
|
1719
|
-
handleKeyDown: handleKeyDown
|
|
1720
|
-
};
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1723
|
-
/**
|
|
1724
|
-
* Default responsive breakpoints configuration
|
|
1725
|
-
*
|
|
1726
|
-
* These breakpoints are optimized for glass effect performance across device classes:
|
|
1727
|
-
* - Mobile: Reduced complexity for 60 FPS target
|
|
1728
|
-
* - Tablet: Balanced quality and performance
|
|
1729
|
-
* - Desktop: Full fidelity effects
|
|
1730
|
-
*/ const DEFAULT_BREAKPOINTS = {
|
|
1731
|
-
mobile: {
|
|
1732
|
-
maxWidth: 640,
|
|
1733
|
-
params: {
|
|
1734
|
-
distortionOctaves: 3,
|
|
1735
|
-
displacementScale: .7,
|
|
1736
|
-
blurAmount: .8,
|
|
1737
|
-
animationSpeed: .8,
|
|
1738
|
-
chromaticIntensity: .5
|
|
1739
|
-
}
|
|
1740
|
-
},
|
|
1741
|
-
tablet: {
|
|
1742
|
-
minWidth: 641,
|
|
1743
|
-
maxWidth: 1024,
|
|
1744
|
-
params: {
|
|
1745
|
-
distortionOctaves: 4,
|
|
1746
|
-
displacementScale: .85,
|
|
1747
|
-
blurAmount: .9,
|
|
1748
|
-
animationSpeed: .9,
|
|
1749
|
-
chromaticIntensity: .75
|
|
1750
|
-
}
|
|
1751
|
-
},
|
|
1752
|
-
desktop: {
|
|
1753
|
-
minWidth: 1025,
|
|
1754
|
-
params: {
|
|
1755
|
-
distortionOctaves: 5,
|
|
1756
|
-
displacementScale: 1,
|
|
1757
|
-
blurAmount: 1,
|
|
1758
|
-
animationSpeed: 1,
|
|
1759
|
-
chromaticIntensity: 1
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
|
|
1764
|
-
/**
|
|
1765
|
-
* Device performance tier detection
|
|
1766
|
-
*
|
|
1767
|
-
* Uses Device Memory API and Hardware Concurrency API to classify devices
|
|
1768
|
-
* into performance tiers for automatic quality adjustment.
|
|
1769
|
-
*
|
|
1770
|
-
* @returns Performance tier classification
|
|
1771
|
-
*/ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
1772
|
-
|
|
1773
|
-
function getDefaultExportFromCjs(x) {
|
|
1774
|
-
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
var fails$8 = function(exec) {
|
|
1778
|
-
try {
|
|
1779
|
-
return !!exec();
|
|
1780
|
-
} catch (error) {
|
|
1781
|
-
return !0;
|
|
1782
|
-
}
|
|
1783
|
-
}, functionBindNative = !fails$8((function() {
|
|
1784
|
-
// eslint-disable-next-line es/no-function-prototype-bind -- safe
|
|
1785
|
-
var test = function() {/* empty */}.bind();
|
|
1786
|
-
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
1787
|
-
return "function" != typeof test || test.hasOwnProperty("prototype");
|
|
1788
|
-
})), 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) {
|
|
1789
|
-
return function() {
|
|
1790
|
-
return call$5.apply(fn, arguments);
|
|
1791
|
-
};
|
|
1792
|
-
}, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
|
|
1793
|
-
return it && it.Math === Math && it;
|
|
1794
|
-
}, globalThis_1 =
|
|
1795
|
-
// eslint-disable-next-line es/no-global-this -- safe
|
|
1796
|
-
check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
|
|
1797
|
-
// eslint-disable-next-line no-restricted-globals -- safe
|
|
1798
|
-
check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
|
|
1799
|
-
// eslint-disable-next-line no-new-func -- fallback
|
|
1800
|
-
function() {
|
|
1801
|
-
return this;
|
|
1802
|
-
}() || 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() {
|
|
1803
|
-
return call$4.apply(apply$1, arguments);
|
|
1804
|
-
}), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
|
|
1805
|
-
return stringSlice(toString$3(it), 8, -1);
|
|
1806
|
-
}, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
|
|
1807
|
-
// Nashorn bug:
|
|
1808
|
-
// https://github.com/zloirock/core-js/issues/1128
|
|
1809
|
-
// https://github.com/zloirock/core-js/issues/1130
|
|
1810
|
-
if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
|
|
1811
|
-
}, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
|
|
1812
|
-
return "function" == typeof argument || argument === documentAll;
|
|
1813
|
-
} : function(argument) {
|
|
1814
|
-
return "function" == typeof argument;
|
|
1815
|
-
}, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
|
|
1816
|
-
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1817
|
-
return 7 !== Object.defineProperty({}, 1, {
|
|
1818
|
-
get: function() {
|
|
1819
|
-
return 7;
|
|
1820
|
-
}
|
|
1821
|
-
})[1];
|
|
1822
|
-
})), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
|
|
1823
|
-
return call$3.apply(call$3, arguments);
|
|
1824
|
-
}, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
|
|
1825
|
-
1: 2
|
|
1826
|
-
}, 1);
|
|
1827
|
-
|
|
1828
|
-
// `Object.prototype.propertyIsEnumerable` method implementation
|
|
1829
|
-
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
|
|
1830
|
-
objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
|
|
1831
|
-
var descriptor = getOwnPropertyDescriptor$1(this, V);
|
|
1832
|
-
return !!descriptor && descriptor.enumerable;
|
|
1833
|
-
} : $propertyIsEnumerable;
|
|
1834
|
-
|
|
1835
|
-
var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
|
|
1836
|
-
return {
|
|
1837
|
-
enumerable: !(1 & bitmap),
|
|
1838
|
-
configurable: !(2 & bitmap),
|
|
1839
|
-
writable: !(4 & bitmap),
|
|
1840
|
-
value: value
|
|
1841
|
-
};
|
|
1842
|
-
}, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
|
|
1843
|
-
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
|
1844
|
-
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
1845
|
-
return !$Object$3("z").propertyIsEnumerable(0);
|
|
1846
|
-
})) ? function(it) {
|
|
1847
|
-
return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
|
|
1848
|
-
} : $Object$3, isNullOrUndefined$2 = function(it) {
|
|
1849
|
-
return null == it;
|
|
1850
|
-
}, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
|
|
1851
|
-
if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
|
|
1852
|
-
return it;
|
|
1853
|
-
}, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
|
|
1854
|
-
return IndexedObject(requireObjectCoercible$2(it));
|
|
1855
|
-
}, isCallable$7 = isCallable$8, isObject$5 = function(it) {
|
|
1856
|
-
return "object" == typeof it ? null !== it : isCallable$7(it);
|
|
1857
|
-
}, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
|
|
1858
|
-
return isCallable$6(variable) ? variable : void 0;
|
|
1859
|
-
}, navigator$1 = globalThis_1.navigator, userAgent$1 = navigator$1 && navigator$1.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;
|
|
1860
|
-
|
|
1861
|
-
v8 && (
|
|
1862
|
-
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
|
|
1863
|
-
// but their correct versions are not interesting for us
|
|
1864
|
-
version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
|
|
1865
|
-
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
|
|
1866
|
-
// so check `userAgent` even if `.v8` exists, but 0
|
|
1867
|
-
!version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
1868
|
-
|
|
1869
|
-
var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
|
|
1870
|
-
var symbol = Symbol("symbol detection");
|
|
1871
|
-
// Chrome 38 Symbol has incorrect toString conversion
|
|
1872
|
-
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
|
|
1873
|
-
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
|
|
1874
|
-
// of course, fail.
|
|
1875
|
-
return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
|
|
1876
|
-
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
|
|
1877
|
-
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
|
|
1878
|
-
})), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
|
|
1879
|
-
return "symbol" == typeof it;
|
|
1880
|
-
} : function(it) {
|
|
1881
|
-
var $Symbol = function(namespace, method) {
|
|
1882
|
-
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];
|
|
1883
|
-
}("Symbol");
|
|
1884
|
-
return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
|
|
1885
|
-
}, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
|
|
1886
|
-
if (isCallable$4(argument)) return argument;
|
|
1887
|
-
throw new $TypeError$5(function(argument) {
|
|
1888
|
-
try {
|
|
1889
|
-
return $String$2(argument);
|
|
1890
|
-
} catch (error) {
|
|
1891
|
-
return "Object";
|
|
1892
|
-
}
|
|
1893
|
-
}(argument) + " is not a function");
|
|
1894
|
-
}, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
|
|
1895
|
-
exports: {}
|
|
1896
|
-
}, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
|
|
1897
|
-
try {
|
|
1898
|
-
defineProperty(globalThis$6, key, {
|
|
1899
|
-
value: value,
|
|
1900
|
-
configurable: !0,
|
|
1901
|
-
writable: !0
|
|
1902
|
-
});
|
|
1903
|
-
} catch (error) {
|
|
1904
|
-
globalThis$6[key] = value;
|
|
1905
|
-
}
|
|
1906
|
-
return value;
|
|
1907
|
-
}("__core-js_shared__", {});
|
|
1908
|
-
|
|
1909
|
-
/* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
|
|
1910
|
-
version: "3.43.0",
|
|
1911
|
-
mode: "pure",
|
|
1912
|
-
copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
|
|
1913
|
-
license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
|
|
1914
|
-
source: "https://github.com/zloirock/core-js"
|
|
1915
|
-
});
|
|
1916
|
-
|
|
1917
|
-
var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
|
|
1918
|
-
return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
|
|
1919
|
-
}, 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) {
|
|
1920
|
-
return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
|
|
1921
|
-
}, wellKnownSymbol$5 = function(name) {
|
|
1922
|
-
return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
|
|
1923
|
-
WellKnownSymbolsStore[name];
|
|
1924
|
-
}, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
|
|
1925
|
-
if (!isObject$3(input) || isSymbol$1(input)) return input;
|
|
1926
|
-
var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
|
|
1927
|
-
if (exoticToPrim) {
|
|
1928
|
-
if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
|
|
1929
|
-
!isObject$3(result) || isSymbol$1(result)) return result;
|
|
1930
|
-
throw new $TypeError$3("Can't convert object to primitive value");
|
|
1931
|
-
}
|
|
1932
|
-
return void 0 === pref && (pref = "number"), function(input, pref) {
|
|
1933
|
-
var fn, val;
|
|
1934
|
-
if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1935
|
-
if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1936
|
-
if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1937
|
-
throw new $TypeError$4("Can't convert object to primitive value");
|
|
1938
|
-
}(input, pref);
|
|
1939
|
-
}, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
|
|
1940
|
-
var key = toPrimitive(argument, "string");
|
|
1941
|
-
return isSymbol(key) ? key : key + "";
|
|
1942
|
-
}, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
|
|
1943
|
-
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1944
|
-
return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
|
|
1945
|
-
get: function() {
|
|
1946
|
-
return 7;
|
|
1947
|
-
}
|
|
1948
|
-
}).a;
|
|
1949
|
-
var it;
|
|
1950
|
-
})), 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;
|
|
1951
|
-
|
|
1952
|
-
// `Object.getOwnPropertyDescriptor` method
|
|
1953
|
-
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
|
|
1954
|
-
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
|
|
1955
|
-
if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
|
|
1956
|
-
return $getOwnPropertyDescriptor$1(O, P);
|
|
1957
|
-
} catch (error) {/* empty */}
|
|
1958
|
-
if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
|
|
1959
|
-
};
|
|
1960
|
-
|
|
1961
|
-
var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
|
|
1962
|
-
var value = data[normalize(feature)];
|
|
1963
|
-
return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
|
|
1964
|
-
}, normalize = isForced$1.normalize = function(string) {
|
|
1965
|
-
return String(string).replace(replacement, ".").toLowerCase();
|
|
1966
|
-
}, 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() {
|
|
1967
|
-
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1968
|
-
return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
|
|
1969
|
-
value: 42,
|
|
1970
|
-
writable: !1
|
|
1971
|
-
}).prototype;
|
|
1972
|
-
})), 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) {
|
|
1973
|
-
if (isObject$1(argument)) return argument;
|
|
1974
|
-
throw new $TypeError$2($String$1(argument) + " is not an object");
|
|
1975
|
-
}, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
1957
|
+
handleKeyDown: handleKeyDown
|
|
1958
|
+
};
|
|
1959
|
+
}
|
|
1976
1960
|
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1961
|
+
/**
|
|
1962
|
+
* Default responsive breakpoints configuration
|
|
1963
|
+
*
|
|
1964
|
+
* These breakpoints are optimized for glass effect performance across device classes:
|
|
1965
|
+
* - Mobile: Reduced complexity for 60 FPS target
|
|
1966
|
+
* - Tablet: Balanced quality and performance
|
|
1967
|
+
* - Desktop: Full fidelity effects
|
|
1968
|
+
*/ const DEFAULT_BREAKPOINTS = {
|
|
1969
|
+
mobile: {
|
|
1970
|
+
maxWidth: 640,
|
|
1971
|
+
params: {
|
|
1972
|
+
distortionOctaves: 3,
|
|
1973
|
+
displacementScale: .7,
|
|
1974
|
+
blurAmount: .8,
|
|
1975
|
+
animationSpeed: .8,
|
|
1976
|
+
chromaticIntensity: .5
|
|
1977
|
+
}
|
|
1978
|
+
},
|
|
1979
|
+
tablet: {
|
|
1980
|
+
minWidth: 641,
|
|
1981
|
+
maxWidth: 1024,
|
|
1982
|
+
params: {
|
|
1983
|
+
distortionOctaves: 4,
|
|
1984
|
+
displacementScale: .85,
|
|
1985
|
+
blurAmount: .9,
|
|
1986
|
+
animationSpeed: .9,
|
|
1987
|
+
chromaticIntensity: .75
|
|
1988
|
+
}
|
|
1989
|
+
},
|
|
1990
|
+
desktop: {
|
|
1991
|
+
minWidth: 1025,
|
|
1992
|
+
params: {
|
|
1993
|
+
distortionOctaves: 5,
|
|
1994
|
+
displacementScale: 1,
|
|
1995
|
+
blurAmount: 1,
|
|
1996
|
+
animationSpeed: 1,
|
|
1997
|
+
chromaticIntensity: 1
|
|
1998
|
+
}
|
|
1987
1999
|
}
|
|
1988
|
-
return $defineProperty(O, P, Attributes);
|
|
1989
|
-
} : $defineProperty : function(O, P, Attributes) {
|
|
1990
|
-
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
|
|
1991
|
-
return $defineProperty(O, P, Attributes);
|
|
1992
|
-
} catch (error) {/* empty */}
|
|
1993
|
-
if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
|
|
1994
|
-
return "value" in Attributes && (O[P] = Attributes.value), O;
|
|
1995
2000
|
};
|
|
1996
2001
|
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
var Wrapper = function(a, b, c) {
|
|
2007
|
-
if (this instanceof Wrapper) {
|
|
2008
|
-
switch (arguments.length) {
|
|
2009
|
-
case 0:
|
|
2010
|
-
return new NativeConstructor;
|
|
2011
|
-
|
|
2012
|
-
case 1:
|
|
2013
|
-
return new NativeConstructor(a);
|
|
2014
|
-
|
|
2015
|
-
case 2:
|
|
2016
|
-
return new NativeConstructor(a, b);
|
|
2017
|
-
}
|
|
2018
|
-
return new NativeConstructor(a, b, c);
|
|
2019
|
-
}
|
|
2020
|
-
return apply(NativeConstructor, this, arguments);
|
|
2021
|
-
};
|
|
2022
|
-
return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
|
|
2023
|
-
}, _export = function(options, source) {
|
|
2024
|
-
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;
|
|
2025
|
-
for (key in source)
|
|
2026
|
-
// contains in native
|
|
2027
|
-
USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
|
|
2028
|
-
targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
|
|
2029
|
-
// export native or implementation
|
|
2030
|
-
sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
|
|
2031
|
-
// bind methods to global for calling from export context
|
|
2032
|
-
resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
|
|
2033
|
-
// add a flag to not completely full polyfills
|
|
2034
|
-
(options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
|
|
2035
|
-
createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
|
|
2036
|
-
// export virtual prototype methods
|
|
2037
|
-
createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
|
|
2038
|
-
// export real prototype methods
|
|
2039
|
-
options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
|
|
2040
|
-
}, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
|
|
2041
|
-
var n = +x;
|
|
2042
|
-
return (n > 0 ? floor : ceil)(n);
|
|
2043
|
-
}, toIntegerOrInfinity$2 = function(argument) {
|
|
2044
|
-
var number = +argument;
|
|
2045
|
-
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2046
|
-
return number != number || 0 === number ? 0 : trunc(number);
|
|
2047
|
-
}, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
|
|
2048
|
-
return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
|
|
2002
|
+
/**
|
|
2003
|
+
* Device performance tier detection
|
|
2004
|
+
*
|
|
2005
|
+
* Uses Device Memory API and Hardware Concurrency API to classify devices
|
|
2006
|
+
* into performance tiers for automatic quality adjustment.
|
|
2007
|
+
*
|
|
2008
|
+
* @returns Performance tier classification
|
|
2009
|
+
*/ var toIntegerOrInfinity = toIntegerOrInfinity$2, max = Math.max, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
|
|
2010
|
+
return argument = obj.length, (len = toIntegerOrInfinity$1(argument)) > 0 ? min$1(len, 9007199254740991) : 0;
|
|
2049
2011
|
var argument, len;
|
|
2050
2012
|
}, createMethod = function(IS_INCLUDES) {
|
|
2051
2013
|
return function($this, el, fromIndex) {
|
|
2052
2014
|
var O = toIndexedObject($this), length = lengthOfArrayLike(O);
|
|
2053
2015
|
if (0 === length) return !IS_INCLUDES && -1;
|
|
2054
2016
|
var value, index = function(index, length) {
|
|
2055
|
-
var integer = toIntegerOrInfinity
|
|
2056
|
-
return integer < 0 ? max(integer + length, 0) : min
|
|
2017
|
+
var integer = toIntegerOrInfinity(index);
|
|
2018
|
+
return integer < 0 ? max(integer + length, 0) : min(integer, length);
|
|
2057
2019
|
}(fromIndex, length);
|
|
2058
2020
|
// Array#includes uses SameValueZero equality algorithm
|
|
2059
2021
|
// eslint-disable-next-line no-self-compare -- NaN check
|
|
@@ -2082,12 +2044,7 @@ _export({
|
|
|
2082
2044
|
}
|
|
2083
2045
|
});
|
|
2084
2046
|
|
|
2085
|
-
var
|
|
2086
|
-
var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
|
|
2087
|
-
if (pureMethod) return pureMethod;
|
|
2088
|
-
var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
2089
|
-
return NativePrototype && NativePrototype[METHOD];
|
|
2090
|
-
}, includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
|
|
2047
|
+
var includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
|
|
2091
2048
|
|
|
2092
2049
|
test[wellKnownSymbol$5("toStringTag")] = "z";
|
|
2093
2050
|
|
|
@@ -2143,148 +2100,6 @@ const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
|
2143
2100
|
/**
|
|
2144
2101
|
* Get GPU memory info if available (Chrome DevTools only)
|
|
2145
2102
|
*/
|
|
2146
|
-
/** Map an FPS value to a semantic color token string. */
|
|
2147
|
-
const getQualityColor = quality => {
|
|
2148
|
-
switch (quality) {
|
|
2149
|
-
case "high":
|
|
2150
|
-
return "var(--atomix-color-success, #4ade80)";
|
|
2151
|
-
|
|
2152
|
-
case "medium":
|
|
2153
|
-
return "var(--atomix-color-warning, #fbbf24)";
|
|
2154
|
-
|
|
2155
|
-
case "low":
|
|
2156
|
-
return "var(--atomix-color-danger, #ef4444)";
|
|
2157
|
-
|
|
2158
|
-
default:
|
|
2159
|
-
return "#9ca3af";
|
|
2160
|
-
}
|
|
2161
|
-
}, getFpsLabel = fps => fps >= 58 ? "Optimal" : fps >= 45 ? "Warning" : "Critical";
|
|
2162
|
-
|
|
2163
|
-
/** Map a quality level string to a semantic color token string. */
|
|
2164
|
-
// Inject keyframes once
|
|
2165
|
-
if ("undefined" != typeof document) {
|
|
2166
|
-
const styleId = "perf-dashboard-keyframes";
|
|
2167
|
-
if (!document.getElementById(styleId)) {
|
|
2168
|
-
const styleEl = document.createElement("style");
|
|
2169
|
-
styleEl.id = styleId, styleEl.textContent = "\n@keyframes perf-dashboard-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n",
|
|
2170
|
-
document.head.appendChild(styleEl);
|
|
2171
|
-
}
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
/**
|
|
2175
|
-
* PerformanceDashboard - Real-time performance monitoring overlay.
|
|
2176
|
-
*
|
|
2177
|
-
* Displays FPS, frame time, quality level, GPU memory, and auto-scaling status.
|
|
2178
|
-
* Rendered only when `debugPerformance={true}` on the parent `AtomixGlass`.
|
|
2179
|
-
*/ const PerformanceDashboard = memo((({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
2180
|
-
if (!isVisible) return null;
|
|
2181
|
-
const fpsColor = (fps = metrics.fps) >= 58 ? "var(--atomix-color-success, #4ade80)" : fps >= 45 ? "var(--atomix-color-warning, #fbbf24)" : "var(--atomix-color-danger, #ef4444)";
|
|
2182
|
-
var fps;
|
|
2183
|
-
const isCritical = metrics.fps < 45;
|
|
2184
|
-
return jsxs("div", {
|
|
2185
|
-
className: "c-perf-dashboard u-position-fixed u-top-4 u-end-4 u-p-3 u-px-4 u-text-xs u-font-mono u-text-white u-rounded-md u-border u-border-white-alpha-10 u-shadow-lg",
|
|
2186
|
-
style: {
|
|
2187
|
-
zIndex: 9999,
|
|
2188
|
-
minWidth: "12.5rem",
|
|
2189
|
-
// 200px
|
|
2190
|
-
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
2191
|
-
backdropFilter: "blur(8px)",
|
|
2192
|
-
transition: "opacity 0.3s ease"
|
|
2193
|
-
},
|
|
2194
|
-
children: [ jsxs("div", {
|
|
2195
|
-
className: "u-flex u-items-center u-justify-between u-mb-2 u-pb-2 u-border-b u-border-white-alpha-10",
|
|
2196
|
-
children: [ jsx("span", {
|
|
2197
|
-
className: "u-text-sm u-font-bold u-text-white",
|
|
2198
|
-
children: "Performance Monitor"
|
|
2199
|
-
}), onClose && jsx("button", {
|
|
2200
|
-
className: "u-bg-transparent u-border-none u-p-0 u-line-height-1 u-text-base u-text-gray-400 u-cursor-pointer hover:u-text-white",
|
|
2201
|
-
onClick: onClose,
|
|
2202
|
-
"aria-label": "Close performance dashboard",
|
|
2203
|
-
style: {
|
|
2204
|
-
transition: "color 0.2s ease"
|
|
2205
|
-
},
|
|
2206
|
-
children: "×"
|
|
2207
|
-
}) ]
|
|
2208
|
-
}), jsxs("div", {
|
|
2209
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2210
|
-
children: [ jsx("span", {
|
|
2211
|
-
className: "u-text-gray-400 u-me-3",
|
|
2212
|
-
children: "FPS"
|
|
2213
|
-
}), jsx("span", {
|
|
2214
|
-
className: "u-font-bold",
|
|
2215
|
-
style: {
|
|
2216
|
-
color: fpsColor
|
|
2217
|
-
},
|
|
2218
|
-
children: Math.round(metrics.fps)
|
|
2219
|
-
}) ]
|
|
2220
|
-
}), jsxs("div", {
|
|
2221
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2222
|
-
children: [ jsx("span", {
|
|
2223
|
-
className: "u-text-gray-400 u-me-3",
|
|
2224
|
-
children: "Frame Time"
|
|
2225
|
-
}), jsxs("span", {
|
|
2226
|
-
className: "u-font-bold",
|
|
2227
|
-
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
2228
|
-
}) ]
|
|
2229
|
-
}), jsxs("div", {
|
|
2230
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2231
|
-
children: [ jsx("span", {
|
|
2232
|
-
className: "u-text-gray-400 u-me-3",
|
|
2233
|
-
children: "Quality"
|
|
2234
|
-
}), jsx("span", {
|
|
2235
|
-
className: "u-font-bold u-text-uppercase",
|
|
2236
|
-
style: {
|
|
2237
|
-
fontSize: "0.6875rem",
|
|
2238
|
-
// 11px
|
|
2239
|
-
color: getQualityColor(metrics.qualityLevel)
|
|
2240
|
-
},
|
|
2241
|
-
children: metrics.qualityLevel
|
|
2242
|
-
}) ]
|
|
2243
|
-
}), metrics.gpuMemory && jsxs("div", {
|
|
2244
|
-
className: "u-flex u-items-center u-justify-between u-mb-1-5",
|
|
2245
|
-
children: [ jsx("span", {
|
|
2246
|
-
className: "u-text-gray-400 u-me-3",
|
|
2247
|
-
children: "GPU Memory"
|
|
2248
|
-
}), jsxs("span", {
|
|
2249
|
-
className: "u-font-bold",
|
|
2250
|
-
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
2251
|
-
}) ]
|
|
2252
|
-
}), metrics.isAutoScaling && jsx("div", {
|
|
2253
|
-
className: "u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10 u-text-center",
|
|
2254
|
-
style: {
|
|
2255
|
-
fontSize: "0.625rem",
|
|
2256
|
-
// 10px
|
|
2257
|
-
color: "#6b7280"
|
|
2258
|
-
},
|
|
2259
|
-
children: "Auto-scaling active"
|
|
2260
|
-
}), jsxs("div", {
|
|
2261
|
-
className: "u-flex u-items-center u-gap-2 u-mt-2 u-pt-2 u-border-t u-border-white-alpha-10",
|
|
2262
|
-
children: [ jsx("div", {
|
|
2263
|
-
className: "u-rounded-full",
|
|
2264
|
-
style: {
|
|
2265
|
-
width: "0.5rem",
|
|
2266
|
-
height: "0.5rem",
|
|
2267
|
-
flexShrink: 0,
|
|
2268
|
-
backgroundColor: fpsColor,
|
|
2269
|
-
...isCritical && {
|
|
2270
|
-
animation: "perf-dashboard-pulse 1s infinite"
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
}), jsx("span", {
|
|
2274
|
-
className: "u-text-xs",
|
|
2275
|
-
style: {
|
|
2276
|
-
fontSize: "0.625rem",
|
|
2277
|
-
// 10px
|
|
2278
|
-
color: fpsColor
|
|
2279
|
-
},
|
|
2280
|
-
children: getFpsLabel(metrics.fps)
|
|
2281
|
-
}) ]
|
|
2282
|
-
}) ]
|
|
2283
|
-
});
|
|
2284
|
-
}));
|
|
2285
|
-
|
|
2286
|
-
PerformanceDashboard.displayName = "PerformanceDashboard";
|
|
2287
|
-
|
|
2288
2103
|
/**
|
|
2289
2104
|
* Mobile optimization presets
|
|
2290
2105
|
*
|
|
@@ -2404,18 +2219,13 @@ const PERFORMANCE_PRESET = {
|
|
|
2404
2219
|
saturation: 70
|
|
2405
2220
|
}
|
|
2406
2221
|
}
|
|
2407
|
-
}, AtomixGlassInner = forwardRef((function({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, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "",
|
|
2408
|
-
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef =
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
}));
|
|
2415
|
-
};
|
|
2416
|
-
}
|
|
2417
|
-
// Internal implementation with forwardRef
|
|
2418
|
-
(ref, internalWrapperRef)), [ ref ]), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = propsIsFixedOrSticky || "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
2222
|
+
}, AtomixGlassInner = forwardRef((function({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, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", 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, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, border: border, withBorder: withBorder = !0, debugBorderRadius: debugBorderRadius = !1, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, isFixedOrSticky: propsIsFixedOrSticky, ...rest}, ref) {
|
|
2223
|
+
const glassRef = useRef(null), contentRef = useRef(null), internalWrapperRef = useRef(null), mergedRef = useForkRef(ref, internalWrapperRef), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = (explicit = propsIsFixedOrSticky,
|
|
2224
|
+
position = restStyle.position, Boolean(explicit || "fixed" === position || "sticky" === position));
|
|
2225
|
+
var explicit, position;
|
|
2226
|
+
/**
|
|
2227
|
+
* Extracts layout-related properties from a React `CSSProperties` object.
|
|
2228
|
+
*/ const {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown, resolvedBorder: resolvedBorder} = useAtomixGlass({
|
|
2419
2229
|
glassRef: glassRef,
|
|
2420
2230
|
contentRef: contentRef,
|
|
2421
2231
|
wrapperRef: internalWrapperRef,
|
|
@@ -2435,20 +2245,13 @@ const PERFORMANCE_PRESET = {
|
|
|
2435
2245
|
blurAmount: blurAmount,
|
|
2436
2246
|
saturation: saturation,
|
|
2437
2247
|
withLiquidBlur: withLiquidBlur,
|
|
2438
|
-
|
|
2248
|
+
border: border,
|
|
2249
|
+
withBorder: withBorder,
|
|
2250
|
+
debugBorderRadius: debugBorderRadius,
|
|
2439
2251
|
style: style,
|
|
2440
|
-
isFixedOrSticky: isFixedOrSticky
|
|
2441
|
-
// Phase 1: Animation System props
|
|
2442
|
-
withTimeAnimation: withTimeAnimation,
|
|
2443
|
-
animationSpeed: animationSpeed,
|
|
2444
|
-
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
2445
|
-
distortionOctaves: distortionOctaves,
|
|
2446
|
-
distortionLacunarity: distortionLacunarity,
|
|
2447
|
-
distortionGain: distortionGain,
|
|
2448
|
-
distortionQuality: distortionQuality
|
|
2252
|
+
isFixedOrSticky: isFixedOrSticky
|
|
2449
2253
|
});
|
|
2450
|
-
|
|
2451
|
-
!
|
|
2254
|
+
(
|
|
2452
2255
|
/**
|
|
2453
2256
|
* Responsive Glass Parameters Hook
|
|
2454
2257
|
*
|
|
@@ -2603,7 +2406,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2603
2406
|
}), [ enabled ]), useCallback((() => {
|
|
2604
2407
|
calculateParams();
|
|
2605
2408
|
}), [ calculateParams ]);
|
|
2606
|
-
}({
|
|
2409
|
+
})({
|
|
2607
2410
|
baseParams: {
|
|
2608
2411
|
...useMemo((() =>
|
|
2609
2412
|
/**
|
|
@@ -2637,9 +2440,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2637
2440
|
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
2638
2441
|
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
2639
2442
|
debug: !1
|
|
2640
|
-
})
|
|
2641
|
-
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
2642
|
-
const {metrics: performanceMetrics, toggleMonitoring: toggleMonitoring} =
|
|
2443
|
+
}),
|
|
2643
2444
|
/**
|
|
2644
2445
|
* Performance Monitor Hook
|
|
2645
2446
|
*
|
|
@@ -2674,7 +2475,13 @@ const PERFORMANCE_PRESET = {
|
|
|
2674
2475
|
timestamp: 0,
|
|
2675
2476
|
isAutoScaling: !0,
|
|
2676
2477
|
lowFpsCount: 0
|
|
2677
|
-
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled)
|
|
2478
|
+
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled);
|
|
2479
|
+
// Sync external `enabled` prop changes into internal state
|
|
2480
|
+
useEffect((() => {
|
|
2481
|
+
setIsEnabled(enabled ?? !0);
|
|
2482
|
+
}), [ enabled ]);
|
|
2483
|
+
// Refs for frame tracking
|
|
2484
|
+
const frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
|
|
2678
2485
|
setMetrics((prev => ({
|
|
2679
2486
|
...prev,
|
|
2680
2487
|
...newMetrics,
|
|
@@ -2794,191 +2601,214 @@ const PERFORMANCE_PRESET = {
|
|
|
2794
2601
|
/**
|
|
2795
2602
|
* Reset to auto-scaling mode
|
|
2796
2603
|
*/ var fps, currentQuality;
|
|
2797
|
-
|
|
2798
|
-
metrics: metrics,
|
|
2799
|
-
recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
|
|
2800
|
-
isUnderperforming: metrics.fps < minFps,
|
|
2801
|
-
setQualityLevel: setQualityLevel,
|
|
2802
|
-
resetAutoScaling: resetAutoScaling,
|
|
2803
|
-
toggleMonitoring: toggleMonitoring
|
|
2804
|
-
};
|
|
2604
|
+
fps = metrics.fps, currentQuality = metrics.qualityLevel, metrics.fps;
|
|
2805
2605
|
}({
|
|
2806
2606
|
enabled: debugPerformance,
|
|
2807
|
-
// Enable when debugPerformance is true
|
|
2808
2607
|
debug: !1,
|
|
2809
2608
|
showOverlay: !1
|
|
2810
2609
|
});
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
}), [ debugPerformance ]);
|
|
2816
|
-
// Re-run when debugPerformance changes
|
|
2817
|
-
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
2818
|
-
if (!isFixedOrSticky) return {};
|
|
2819
|
-
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
2820
|
-
return {
|
|
2821
|
-
...p && {
|
|
2822
|
-
position: p
|
|
2823
|
-
},
|
|
2824
|
-
...void 0 !== t && {
|
|
2825
|
-
top: t
|
|
2826
|
-
},
|
|
2827
|
-
...void 0 !== l && {
|
|
2828
|
-
left: l
|
|
2829
|
-
},
|
|
2830
|
-
...void 0 !== r && {
|
|
2831
|
-
right: r
|
|
2832
|
-
},
|
|
2833
|
-
...void 0 !== b && {
|
|
2834
|
-
bottom: b
|
|
2835
|
-
}
|
|
2836
|
-
};
|
|
2837
|
-
}), [ isFixedOrSticky, restStyle ]);
|
|
2838
|
-
// Calculate base style with transforms
|
|
2839
|
-
// When layout is hoisted to the root, strip those props from the container
|
|
2840
|
-
useMemo((() => {
|
|
2841
|
-
if (isFixedOrSticky) {
|
|
2842
|
-
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
2843
|
-
return {
|
|
2844
|
-
...visualStyle
|
|
2845
|
-
};
|
|
2610
|
+
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, containerStyle = useMemo((() => ({
|
|
2611
|
+
...restStyle,
|
|
2612
|
+
...void 0 !== customZIndex && {
|
|
2613
|
+
zIndex: customZIndex
|
|
2846
2614
|
}
|
|
2615
|
+
})), [ restStyle, customZIndex ]), componentClassName = mergeClassNames(ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className), positionStyles = useMemo((() =>
|
|
2616
|
+
/**
|
|
2617
|
+
* Returns the internal positioning context for effect layers relative to the root.
|
|
2618
|
+
*/
|
|
2619
|
+
function(isFixedOrSticky, restStyle) {
|
|
2847
2620
|
return {
|
|
2848
|
-
|
|
2621
|
+
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
2622
|
+
top: 0,
|
|
2623
|
+
left: 0,
|
|
2624
|
+
right: "auto",
|
|
2625
|
+
bottom: "auto"
|
|
2849
2626
|
};
|
|
2850
|
-
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left, restStyle.right, restStyle.bottom ]), adjustedSize = useMemo((() => {
|
|
2859
|
-
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
2860
|
-
// but sizing is driven by explicit width/height or measured size.
|
|
2861
|
-
positionStyles.position;
|
|
2862
|
-
const resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
2627
|
+
}
|
|
2628
|
+
/**
|
|
2629
|
+
* Computes `--atomix-glass-width` and `--atomix-glass-height` values.
|
|
2630
|
+
*
|
|
2631
|
+
* Fixed/sticky elements prefer explicit dimensions or measured size; in-flow
|
|
2632
|
+
* elements default to `100%`.
|
|
2633
|
+
*/ (isFixedOrSticky, restStyle)), [ isFixedOrSticky, restStyle ]), adjustedSize = useMemo((() => function(options) {
|
|
2634
|
+
const {width: width, height: height, restStyle: restStyle, glassSize: glassSize, isFixedOrSticky: isFixedOrSticky} = options, resolveLength = (value, measured) => void 0 !== value && isFixedOrSticky ? "number" == typeof value ? `${value}px` : value : measured > 0 && isFixedOrSticky ? `${measured}px` : "100%", effectiveWidth = width ?? restStyle.width, effectiveHeight = height ?? restStyle.height;
|
|
2863
2635
|
return {
|
|
2864
2636
|
width: resolveLength(effectiveWidth, glassSize.width),
|
|
2865
2637
|
height: resolveLength(effectiveHeight, glassSize.height)
|
|
2866
2638
|
};
|
|
2867
|
-
}
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2639
|
+
}
|
|
2640
|
+
/**
|
|
2641
|
+
* Builds the CSS custom properties applied to the root `.c-atomix-glass` element.
|
|
2642
|
+
*
|
|
2643
|
+
* These variables drive layer geometry, transforms, and stacking offsets. They
|
|
2644
|
+
* must not include layout properties that would interfere with backdrop-filter.
|
|
2645
|
+
*/ ({
|
|
2646
|
+
width: width,
|
|
2647
|
+
height: height,
|
|
2648
|
+
restStyle: restStyle,
|
|
2649
|
+
glassSize: glassSize,
|
|
2650
|
+
isFixedOrSticky: isFixedOrSticky
|
|
2651
|
+
})), [ width, height, restStyle, glassSize, isFixedOrSticky ]), glassVars = useMemo((() => function(input) {
|
|
2652
|
+
const {effectiveBorderRadius: effectiveBorderRadius, transformStyle: transformStyle, adjustedSize: adjustedSize, isOverLight: isOverLight, customZIndex: customZIndex, isFixedOrSticky: isFixedOrSticky, positionStyles: positionStyles, restStyle: restStyle, borderWidth: borderWidth = ATOMIX_GLASS.BORDER.DEFAULT_WIDTH} = input, layerPosition =
|
|
2653
|
+
/**
|
|
2654
|
+
* Resolves the `--atomix-glass-position` value for decorative layers.
|
|
2655
|
+
*
|
|
2656
|
+
* Fixed/sticky layers use the same positioning mode as the container; in-flow
|
|
2657
|
+
* layers default to the internal absolute positioning context.
|
|
2658
|
+
*/
|
|
2659
|
+
function(isFixedOrSticky, positionStyles, restStyle) {
|
|
2660
|
+
return isFixedOrSticky ? `${function(style) {
|
|
2661
|
+
const {position: position, top: top, left: left, right: right, bottom: bottom, inset: inset} = style;
|
|
2662
|
+
return {
|
|
2663
|
+
...null != position && {
|
|
2664
|
+
position: position
|
|
2665
|
+
},
|
|
2666
|
+
...void 0 !== top && {
|
|
2667
|
+
top: top
|
|
2668
|
+
},
|
|
2669
|
+
...void 0 !== left && {
|
|
2670
|
+
left: left
|
|
2671
|
+
},
|
|
2672
|
+
...void 0 !== right && {
|
|
2673
|
+
right: right
|
|
2674
|
+
},
|
|
2675
|
+
...void 0 !== bottom && {
|
|
2676
|
+
bottom: bottom
|
|
2677
|
+
},
|
|
2678
|
+
...void 0 !== inset && {
|
|
2679
|
+
inset: inset
|
|
2680
|
+
}
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2683
|
+
/**
|
|
2684
|
+
* Resolves inset custom properties for decorative layers (hover, borders, backgrounds).
|
|
2685
|
+
*
|
|
2686
|
+
* For fixed and sticky modes, insets mirror the container so sibling layers remain
|
|
2687
|
+
* aligned. In-flow modes, insets follow the consumer `style` when a non-default
|
|
2688
|
+
* `position` is provided.
|
|
2689
|
+
*/ (restStyle).position ?? restStyle.position ?? "fixed"}` : `${positionStyles.position}`;
|
|
2690
|
+
}(isFixedOrSticky, positionStyles, restStyle), layerInsets = function(isFixedOrSticky, restStyle) {
|
|
2691
|
+
if (isFixedOrSticky) return {
|
|
2692
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
2693
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
2694
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
2695
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
2696
|
+
};
|
|
2697
|
+
const position = restStyle.position;
|
|
2698
|
+
return null != position && "static" !== position && "relative" !== position ? {
|
|
2699
|
+
top: formatGlassInsetValue(restStyle.top, 0),
|
|
2700
|
+
left: formatGlassInsetValue(restStyle.left, 0),
|
|
2701
|
+
right: formatGlassInsetValue(restStyle.right, "auto"),
|
|
2702
|
+
bottom: formatGlassInsetValue(restStyle.bottom, "auto")
|
|
2703
|
+
} : {
|
|
2704
|
+
top: "0px",
|
|
2705
|
+
left: "0px",
|
|
2706
|
+
right: "auto",
|
|
2707
|
+
bottom: "auto"
|
|
2708
|
+
};
|
|
2709
|
+
}(isFixedOrSticky, restStyle);
|
|
2905
2710
|
return {
|
|
2906
2711
|
...void 0 !== customZIndex && {
|
|
2907
2712
|
"--atomix-glass-base-z-index": customZIndex
|
|
2908
2713
|
},
|
|
2909
2714
|
"--atomix-glass-radius": `${effectiveBorderRadius}px`,
|
|
2910
2715
|
"--atomix-glass-transform": transformStyle || "none",
|
|
2911
|
-
"--atomix-glass-container-position":
|
|
2912
|
-
"--atomix-glass-position":
|
|
2913
|
-
"--atomix-glass-top":
|
|
2914
|
-
"--atomix-glass-left":
|
|
2915
|
-
"--atomix-glass-right":
|
|
2916
|
-
"--atomix-glass-bottom":
|
|
2716
|
+
"--atomix-glass-container-position": layerPosition,
|
|
2717
|
+
"--atomix-glass-position": layerPosition,
|
|
2718
|
+
"--atomix-glass-top": layerInsets.top,
|
|
2719
|
+
"--atomix-glass-left": layerInsets.left,
|
|
2720
|
+
"--atomix-glass-right": layerInsets.right,
|
|
2721
|
+
"--atomix-glass-bottom": layerInsets.bottom,
|
|
2917
2722
|
"--atomix-glass-width": adjustedSize.width,
|
|
2918
2723
|
"--atomix-glass-height": adjustedSize.height,
|
|
2919
|
-
|
|
2920
|
-
"--atomix-glass-
|
|
2921
|
-
"--atomix-glass-
|
|
2922
|
-
|
|
2923
|
-
"--atomix-glass-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2724
|
+
// Aliases maintained for backward compatibility and consumer overrides.
|
|
2725
|
+
"--atomix-glass-container-width": adjustedSize.width,
|
|
2726
|
+
"--atomix-glass-container-height": adjustedSize.height,
|
|
2727
|
+
[ATOMIX_GLASS.BORDER.WIDTH_CSS_VAR]: borderWidth,
|
|
2728
|
+
"--atomix-glass-blend-mode": isOverLight ? "multiply" : "overlay"
|
|
2729
|
+
};
|
|
2730
|
+
}
|
|
2731
|
+
/**
|
|
2732
|
+
* Applies mode-specific multipliers and accessibility overrides to container effects.
|
|
2733
|
+
*/ ({
|
|
2734
|
+
effectiveBorderRadius: effectiveBorderRadius,
|
|
2735
|
+
transformStyle: transformStyle,
|
|
2736
|
+
adjustedSize: adjustedSize,
|
|
2737
|
+
isOverLight: isOverLight,
|
|
2738
|
+
customZIndex: customZIndex,
|
|
2739
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
2740
|
+
positionStyles: positionStyles,
|
|
2741
|
+
restStyle: restStyle,
|
|
2742
|
+
borderWidth: resolvedBorder.width
|
|
2743
|
+
})), [ effectiveBorderRadius, transformStyle, adjustedSize, isOverLight, customZIndex, isFixedOrSticky, positionStyles, restStyle, resolvedBorder.width ]), containerEffects = useMemo((() => function(options) {
|
|
2744
|
+
const {MULTIPLIERS: MULTIPLIERS, SATURATION: SATURATION} = ATOMIX_GLASS.CONSTANTS, zeroMouse = {
|
|
2745
|
+
x: 0,
|
|
2746
|
+
y: 0
|
|
2747
|
+
}, resolveSaturation = () => options.effectiveHighContrast ? SATURATION.HIGH_CONTRAST : options.isOverLight ? options.saturation * options.saturationBoost : options.saturation;
|
|
2748
|
+
if (options.effectiveWithoutEffects) return {
|
|
2749
|
+
displacementScale: 0,
|
|
2750
|
+
blurAmount: 0,
|
|
2751
|
+
saturation: resolveSaturation(),
|
|
2752
|
+
aberrationIntensity: 0,
|
|
2753
|
+
mouseOffset: zeroMouse,
|
|
2754
|
+
globalMousePosition: zeroMouse
|
|
2935
2755
|
};
|
|
2936
|
-
|
|
2937
|
-
|
|
2756
|
+
let resolvedDisplacement = options.displacementScale;
|
|
2757
|
+
"shader" === options.mode ? resolvedDisplacement *= MULTIPLIERS.SHADER_DISPLACEMENT : options.isOverLight && (resolvedDisplacement *= MULTIPLIERS.OVER_LIGHT_DISPLACEMENT);
|
|
2758
|
+
let resolvedAberration = options.aberrationIntensity;
|
|
2759
|
+
return "shader" === options.mode && (resolvedAberration *= MULTIPLIERS.SHADER_ABERRATION),
|
|
2760
|
+
{
|
|
2761
|
+
displacementScale: resolvedDisplacement,
|
|
2762
|
+
blurAmount: options.blurAmount,
|
|
2763
|
+
saturation: resolveSaturation(),
|
|
2764
|
+
aberrationIntensity: resolvedAberration,
|
|
2765
|
+
mouseOffset: options.mouseOffset,
|
|
2766
|
+
globalMousePosition: options.globalMousePosition
|
|
2767
|
+
};
|
|
2768
|
+
}({
|
|
2769
|
+
displacementScale: displacementScale,
|
|
2770
|
+
blurAmount: blurAmount,
|
|
2771
|
+
saturation: saturation,
|
|
2772
|
+
aberrationIntensity: aberrationIntensity,
|
|
2773
|
+
mode: mode,
|
|
2774
|
+
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
2775
|
+
effectiveHighContrast: effectiveHighContrast,
|
|
2776
|
+
isOverLight: isOverLight,
|
|
2777
|
+
saturationBoost: overLightConfig.saturationBoost,
|
|
2778
|
+
mouseOffset: mouseOffset,
|
|
2779
|
+
globalMousePosition: globalMousePosition
|
|
2780
|
+
})), [ displacementScale, blurAmount, saturation, aberrationIntensity, mode, effectiveWithoutEffects, effectiveHighContrast, isOverLight, overLightConfig.saturationBoost, mouseOffset, globalMousePosition ]), renderBackgroundLayer = layerType => jsx("div", {
|
|
2781
|
+
"aria-hidden": "true",
|
|
2782
|
+
className: mergeClassNames(ATOMIX_GLASS.BACKGROUND_LAYER_CLASS, "dark" === layerType ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS, isOverLight ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS)
|
|
2938
2783
|
});
|
|
2939
|
-
|
|
2940
|
-
// When root is fixed/sticky, internal layers use absolute (relative to root)
|
|
2941
|
-
return jsxs("div", {
|
|
2784
|
+
return jsxs("div", {
|
|
2942
2785
|
...rest,
|
|
2943
2786
|
ref: mergedRef,
|
|
2944
2787
|
className: componentClassName,
|
|
2945
|
-
style:
|
|
2946
|
-
...glassVars
|
|
2947
|
-
},
|
|
2788
|
+
style: glassVars,
|
|
2948
2789
|
role: role || (onClick ? "button" : void 0),
|
|
2949
2790
|
tabIndex: onClick ? tabIndex ?? 0 : tabIndex,
|
|
2950
2791
|
"aria-label": ariaLabel,
|
|
2951
2792
|
"aria-describedby": ariaDescribedBy,
|
|
2952
2793
|
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
2953
|
-
"aria-pressed": onClick ? isActive : void 0,
|
|
2954
2794
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
2955
2795
|
children: [ jsx(AtomixGlassContainer, {
|
|
2956
2796
|
ref: glassRef,
|
|
2957
2797
|
contentRef: contentRef,
|
|
2958
2798
|
className: className,
|
|
2959
|
-
style:
|
|
2960
|
-
...restStyle
|
|
2961
|
-
},
|
|
2799
|
+
style: containerStyle,
|
|
2962
2800
|
borderRadius: effectiveBorderRadius,
|
|
2963
|
-
displacementScale:
|
|
2964
|
-
blurAmount:
|
|
2965
|
-
saturation:
|
|
2966
|
-
aberrationIntensity:
|
|
2801
|
+
displacementScale: containerEffects.displacementScale,
|
|
2802
|
+
blurAmount: containerEffects.blurAmount,
|
|
2803
|
+
saturation: containerEffects.saturation,
|
|
2804
|
+
aberrationIntensity: containerEffects.aberrationIntensity,
|
|
2967
2805
|
glassSize: glassSize,
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
x: 0,
|
|
2971
|
-
y: 0
|
|
2972
|
-
} : mouseOffset,
|
|
2973
|
-
globalMousePosition: effectiveWithoutEffects ? {
|
|
2974
|
-
x: 0,
|
|
2975
|
-
y: 0
|
|
2976
|
-
} : globalMousePosition,
|
|
2806
|
+
mouseOffset: containerEffects.mouseOffset,
|
|
2807
|
+
globalMousePosition: containerEffects.globalMousePosition,
|
|
2977
2808
|
onMouseEnter: handleMouseEnter,
|
|
2978
2809
|
onMouseLeave: handleMouseLeave,
|
|
2979
2810
|
onMouseDown: handleMouseDown,
|
|
2980
2811
|
onMouseUp: handleMouseUp,
|
|
2981
|
-
isHovered: isHovered,
|
|
2982
2812
|
isActive: isActive,
|
|
2983
2813
|
overLight: isOverLight,
|
|
2984
2814
|
overLightConfig: {
|
|
@@ -2994,8 +2824,6 @@ const PERFORMANCE_PRESET = {
|
|
|
2994
2824
|
shaderVariant: shaderVariant,
|
|
2995
2825
|
withLiquidBlur: withLiquidBlur,
|
|
2996
2826
|
isFixedOrSticky: isFixedOrSticky,
|
|
2997
|
-
// Phase 1: Animation System props
|
|
2998
|
-
shaderTime: getShaderTime(),
|
|
2999
2827
|
withTimeAnimation: withTimeAnimation,
|
|
3000
2828
|
animationSpeed: animationSpeed,
|
|
3001
2829
|
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
@@ -3006,32 +2834,39 @@ const PERFORMANCE_PRESET = {
|
|
|
3006
2834
|
children: children
|
|
3007
2835
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
3008
2836
|
children: [ jsx("div", {
|
|
2837
|
+
"aria-hidden": "true",
|
|
3009
2838
|
className: ATOMIX_GLASS.HOVER_1_CLASS
|
|
3010
2839
|
}), jsx("div", {
|
|
2840
|
+
"aria-hidden": "true",
|
|
3011
2841
|
className: ATOMIX_GLASS.HOVER_2_CLASS
|
|
3012
2842
|
}), jsx("div", {
|
|
2843
|
+
"aria-hidden": "true",
|
|
3013
2844
|
className: ATOMIX_GLASS.HOVER_3_CLASS
|
|
3014
2845
|
}) ]
|
|
3015
|
-
}),
|
|
2846
|
+
}), [ "dark", "black" ].map((layerType => jsx(React.Fragment, {
|
|
2847
|
+
children: renderBackgroundLayer(layerType)
|
|
2848
|
+
}, layerType))), shouldRenderOverLightLayers && jsxs(Fragment, {
|
|
3016
2849
|
children: [ jsx("div", {
|
|
2850
|
+
"aria-hidden": "true",
|
|
3017
2851
|
className: ATOMIX_GLASS.BASE_LAYER_CLASS
|
|
3018
2852
|
}), jsx("div", {
|
|
2853
|
+
"aria-hidden": "true",
|
|
3019
2854
|
className: ATOMIX_GLASS.OVERLAY_LAYER_CLASS
|
|
3020
2855
|
}), jsx("div", {
|
|
2856
|
+
"aria-hidden": "true",
|
|
3021
2857
|
className: ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS
|
|
3022
2858
|
}) ]
|
|
3023
|
-
}),
|
|
2859
|
+
}), resolvedBorder.enabled && jsxs(Fragment, {
|
|
3024
2860
|
children: [ jsx("span", {
|
|
2861
|
+
"aria-hidden": "true",
|
|
3025
2862
|
className: ATOMIX_GLASS.BORDER_BACKDROP_CLASS
|
|
3026
2863
|
}), jsx("span", {
|
|
2864
|
+
"aria-hidden": "true",
|
|
3027
2865
|
className: ATOMIX_GLASS.BORDER_1_CLASS
|
|
3028
2866
|
}), jsx("span", {
|
|
2867
|
+
"aria-hidden": "true",
|
|
3029
2868
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
3030
2869
|
}) ]
|
|
3031
|
-
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
3032
|
-
metrics: performanceMetrics,
|
|
3033
|
-
isVisible: !0,
|
|
3034
|
-
onClose: () => {}
|
|
3035
2870
|
}) ]
|
|
3036
2871
|
});
|
|
3037
2872
|
}));
|
|
@@ -3041,10 +2876,7 @@ const PERFORMANCE_PRESET = {
|
|
|
3041
2876
|
* Default preset for most mobile devices
|
|
3042
2877
|
*/ AtomixGlassInner.displayName = "AtomixGlass";
|
|
3043
2878
|
|
|
3044
|
-
/**
|
|
3045
|
-
* AtomixGlass - wrapped with React.memo to prevent unnecessary re-renders.
|
|
3046
|
-
* Ref is forwarded to the root `<div>` element.
|
|
3047
|
-
*/
|
|
2879
|
+
/** Memoized public export. Ref targets the root `.c-atomix-glass` wrapper. */
|
|
3048
2880
|
const AtomixGlass = memo(AtomixGlassInner), Checkbox = React.memo( forwardRef((({label: label, checked: checked, onChange: onChange, className: className = "", style: style, disabled: disabled = !1, required: required = !1, id: id, name: name, value: value, invalid: invalid = !1, valid: valid = !1, indeterminate: indeterminate = !1, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, onClick: onClick, glass: glass, ...props}, ref) => {
|
|
3049
2881
|
// Local ref to handle indeterminate state
|
|
3050
2882
|
const localRef = useRef(null);
|
|
@@ -3095,14 +2927,7 @@ const AtomixGlass = memo(AtomixGlassInner), Checkbox = React.memo( forwardRef(
|
|
|
3095
2927
|
style: style,
|
|
3096
2928
|
children: inputElement
|
|
3097
2929
|
}), glass) {
|
|
3098
|
-
const defaultGlassProps = {
|
|
3099
|
-
displacementScale: 40,
|
|
3100
|
-
blurAmount: 1,
|
|
3101
|
-
saturation: 160,
|
|
3102
|
-
aberrationIntensity: .3,
|
|
3103
|
-
borderRadius: 6,
|
|
3104
|
-
mode: "shader"
|
|
3105
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
2930
|
+
const defaultGlassProps = GLASS_DEFAULTS_CHECKBOX, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3106
2931
|
...defaultGlassProps,
|
|
3107
2932
|
...glass
|
|
3108
2933
|
};
|
|
@@ -3313,15 +3138,7 @@ const Input = memo( forwardRef((({type: type = "text", value: value, defaultVal
|
|
|
3313
3138
|
} : style
|
|
3314
3139
|
});
|
|
3315
3140
|
if (glass) {
|
|
3316
|
-
|
|
3317
|
-
const defaultGlassProps = {
|
|
3318
|
-
displacementScale: 60,
|
|
3319
|
-
blurAmount: 1,
|
|
3320
|
-
saturation: 180,
|
|
3321
|
-
aberrationIntensity: .2,
|
|
3322
|
-
borderRadius: 12,
|
|
3323
|
-
mode: "shader"
|
|
3324
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3141
|
+
const defaultGlassProps = GLASS_DEFAULTS_INPUT, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3325
3142
|
...defaultGlassProps,
|
|
3326
3143
|
...glass
|
|
3327
3144
|
};
|
|
@@ -3398,15 +3215,7 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
|
|
|
3398
3215
|
}) ]
|
|
3399
3216
|
});
|
|
3400
3217
|
if (glass) {
|
|
3401
|
-
|
|
3402
|
-
const defaultGlassProps = {
|
|
3403
|
-
displacementScale: 40,
|
|
3404
|
-
blurAmount: 1,
|
|
3405
|
-
saturation: 160,
|
|
3406
|
-
aberrationIntensity: .3,
|
|
3407
|
-
borderRadius: 6,
|
|
3408
|
-
mode: "shader"
|
|
3409
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3218
|
+
const defaultGlassProps = GLASS_DEFAULTS_RADIO, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3410
3219
|
...defaultGlassProps,
|
|
3411
3220
|
...glass
|
|
3412
3221
|
};
|
|
@@ -3724,12 +3533,7 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3724
3533
|
});
|
|
3725
3534
|
// Handle item selection
|
|
3726
3535
|
if (glass) {
|
|
3727
|
-
|
|
3728
|
-
const defaultGlassProps = {
|
|
3729
|
-
displacementScale: 60,
|
|
3730
|
-
blurAmount: 10,
|
|
3731
|
-
mode: "shader"
|
|
3732
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3536
|
+
const defaultGlassProps = GLASS_DEFAULTS_SELECT, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3733
3537
|
...defaultGlassProps,
|
|
3734
3538
|
...glass
|
|
3735
3539
|
};
|
|
@@ -3809,15 +3613,7 @@ const Textarea = memo( forwardRef((({value: value, defaultValue: defaultValue,
|
|
|
3809
3613
|
} : style
|
|
3810
3614
|
});
|
|
3811
3615
|
if (glass) {
|
|
3812
|
-
|
|
3813
|
-
const defaultGlassProps = {
|
|
3814
|
-
displacementScale: 60,
|
|
3815
|
-
blurAmount: 1,
|
|
3816
|
-
saturation: 180,
|
|
3817
|
-
aberrationIntensity: 1,
|
|
3818
|
-
borderRadius: 8,
|
|
3819
|
-
mode: "shader"
|
|
3820
|
-
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3616
|
+
const defaultGlassProps = GLASS_DEFAULTS_TEXTAREA, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3821
3617
|
...defaultGlassProps,
|
|
3822
3618
|
...glass
|
|
3823
3619
|
};
|
|
@@ -3833,40 +3629,15 @@ Textarea.displayName = "Textarea";
|
|
|
3833
3629
|
|
|
3834
3630
|
// Adapted from https://github.com/shuding/liquid-glass
|
|
3835
3631
|
// Constants
|
|
3836
|
-
const
|
|
3837
|
-
// Add input validation
|
|
3838
|
-
if ("number" != typeof a || "number" != typeof b || "number" != typeof t) return 0;
|
|
3839
|
-
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a)));
|
|
3840
|
-
return clamped * clamped * (3 - 2 * clamped);
|
|
3841
|
-
}, calculateLength = (x, y) => {
|
|
3842
|
-
// Add input validation and error handling
|
|
3843
|
-
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
3844
|
-
// Prevent potential overflow
|
|
3845
|
-
const maxX = Math.max(Math.abs(x), Math.abs(y));
|
|
3846
|
-
if (0 === maxX) return 0;
|
|
3847
|
-
const scaledX = x / maxX, scaledY = y / maxX;
|
|
3848
|
-
return maxX * Math.sqrt(scaledX * scaledX + scaledY * scaledY);
|
|
3849
|
-
}, roundedRectSDF = (x, y, width, height, radius) => {
|
|
3632
|
+
const roundedRectSDF = (x, y, width, height, radius) => {
|
|
3850
3633
|
// Add input validation
|
|
3851
3634
|
if ("number" != typeof x || "number" != typeof y || "number" != typeof width || "number" != typeof height || "number" != typeof radius) return 0;
|
|
3852
3635
|
const qx = Math.abs(x) - width + radius, qy = Math.abs(y) - height + radius;
|
|
3853
|
-
return Math.min(Math.max(qx, qy), 0) +
|
|
3636
|
+
return Math.min(Math.max(qx, qy), 0) + vec2Length(Math.max(qx, 0), Math.max(qy, 0)) - radius;
|
|
3854
3637
|
}, createTexture = (x, y) => ({
|
|
3855
3638
|
x: "number" != typeof x || isNaN(x) ? .5 : Math.max(0, Math.min(1, x)),
|
|
3856
3639
|
y: "number" != typeof y || isNaN(y) ? .5 : Math.max(0, Math.min(1, y))
|
|
3857
|
-
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y),
|
|
3858
|
-
// Add input validation
|
|
3859
|
-
"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 => {
|
|
3860
|
-
// Add input validation
|
|
3861
|
-
if ("number" != typeof t || isNaN(t)) return 0;
|
|
3862
|
-
const clampedT = Math.max(0, Math.min(1, t));
|
|
3863
|
-
return clampedT < .5 ? 4 * clampedT * clampedT * clampedT : 1 - Math.pow(-2 * clampedT + 2, 3) / 2;
|
|
3864
|
-
}, easeOutQuart = t => {
|
|
3865
|
-
// Add input validation
|
|
3866
|
-
if ("number" != typeof t || isNaN(t)) return 0;
|
|
3867
|
-
const clampedT = Math.max(0, Math.min(1, t));
|
|
3868
|
-
return 1 - Math.pow(1 - clampedT, 4);
|
|
3869
|
-
}, noise2D = (x, y) => {
|
|
3640
|
+
}), validateVec2 = vec => vec && "number" == typeof vec.x && "number" == typeof vec.y && !isNaN(vec.x) && !isNaN(vec.y), noise2D = (x, y) => {
|
|
3870
3641
|
// Add input validation
|
|
3871
3642
|
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y)) return 0;
|
|
3872
3643
|
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) => {
|
|
@@ -3905,13 +3676,13 @@ const smoothStep = (a, b, t) => {
|
|
|
3905
3676
|
x: .5,
|
|
3906
3677
|
y: .5
|
|
3907
3678
|
};
|
|
3908
|
-
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 =
|
|
3679
|
+
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 = vec2Length(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 = smoothstepEdge(.8, 0, distanceToEdge - .05), radialDist = ((x, y, strength) => {
|
|
3909
3680
|
// Add input validation
|
|
3910
3681
|
if ("number" != typeof x || "number" != typeof y || isNaN(x) || isNaN(y) || isNaN(strength)) return {
|
|
3911
3682
|
x: 0,
|
|
3912
3683
|
y: 0
|
|
3913
3684
|
};
|
|
3914
|
-
const distance =
|
|
3685
|
+
const distance = vec2Length(x, y), distortion = Math.pow(Math.min(distance, 10), 2) * strength;
|
|
3915
3686
|
// Limit distance to prevent extreme values
|
|
3916
3687
|
return {
|
|
3917
3688
|
x: x * (1 + distortion),
|
|
@@ -3923,7 +3694,7 @@ const smoothStep = (a, b, t) => {
|
|
|
3923
3694
|
x: 0,
|
|
3924
3695
|
y: 0
|
|
3925
3696
|
};
|
|
3926
|
-
const distance =
|
|
3697
|
+
const distance = vec2Length(x, y);
|
|
3927
3698
|
// Prevent division by zero and extreme values
|
|
3928
3699
|
if (0 === distance) return {
|
|
3929
3700
|
x: 0,
|
|
@@ -3934,8 +3705,8 @@ const smoothStep = (a, b, t) => {
|
|
|
3934
3705
|
x: Math.cos(angle) * distance * intensity,
|
|
3935
3706
|
y: Math.sin(angle) * distance * intensity
|
|
3936
3707
|
};
|
|
3937
|
-
})(ix, iy, .015 * baseDisplacement), scaled =
|
|
3938
|
-
return createTexture(
|
|
3708
|
+
})(ix, iy, .015 * baseDisplacement), scaled = smoothstepEdge(0, 1, 1.15 * baseDisplacement), finalX = ix + totalDistortionX + .5 * chromaticOffset.x, finalY = iy + totalDistortionY + .5 * chromaticOffset.y;
|
|
3709
|
+
return createTexture(clamp(finalX * scaled + .5, 0, 1), clamp(finalY * scaled + .5, 0, 1));
|
|
3939
3710
|
},
|
|
3940
3711
|
// Premium Apple-style fluid glass with enhanced organic flow
|
|
3941
3712
|
appleFluid: (uv, mousePosition) => {
|
|
@@ -3943,8 +3714,8 @@ const smoothStep = (a, b, t) => {
|
|
|
3943
3714
|
x: .5,
|
|
3944
3715
|
y: .5
|
|
3945
3716
|
};
|
|
3946
|
-
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 =
|
|
3947
|
-
return createTexture(
|
|
3717
|
+
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 = vec2Length(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 = smoothstepEdge(.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;
|
|
3718
|
+
return createTexture(clamp(ix + (.035 * organicX + fluidVelocityX + vortexX) * mask + .5, 0, 1), clamp(totalY + .5, 0, 1));
|
|
3948
3719
|
},
|
|
3949
3720
|
// High-end glass with advanced refraction and depth
|
|
3950
3721
|
premiumGlass: (uv, mousePosition) => {
|
|
@@ -3952,7 +3723,7 @@ const smoothStep = (a, b, t) => {
|
|
|
3952
3723
|
x: .5,
|
|
3953
3724
|
y: .5
|
|
3954
3725
|
};
|
|
3955
|
-
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 =
|
|
3726
|
+
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 = vec2Length(mouseX, mouseY), centerDistance = vec2Length(ix, iy), refractionStrength = .3 * Math.pow(Math.min(centerDistance, 1), 1.5), refractionAngle = Math.atan2(iy, ix);
|
|
3956
3727
|
// Multi-layer depth effect
|
|
3957
3728
|
let depthX = 0, depthY = 0;
|
|
3958
3729
|
for (let layer = 0; layer < 3; layer++) {
|
|
@@ -3960,8 +3731,8 @@ const smoothStep = (a, b, t) => {
|
|
|
3960
3731
|
depthX += Math.sin(ix * layerScale + layerTime) * layerStrength, depthY += Math.cos(iy * layerScale - layerTime) * layerStrength;
|
|
3961
3732
|
}
|
|
3962
3733
|
// Glass refraction with mouse influence
|
|
3963
|
-
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 =
|
|
3964
|
-
return createTexture(
|
|
3734
|
+
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 = smoothstepEdge(.9, -.05, distanceToEdge), finalY = iy + (refractionY + depthY + .015 * organicNoise) * edgeMask;
|
|
3735
|
+
return createTexture(clamp(ix + (refractionX + depthX + .015 * organicNoise) * edgeMask + .5, 0, 1), clamp(finalY + .5, 0, 1));
|
|
3965
3736
|
},
|
|
3966
3737
|
// Metallic liquid effect with shimmer
|
|
3967
3738
|
liquidMetal: (uv, mousePosition) => {
|
|
@@ -3969,8 +3740,8 @@ const smoothStep = (a, b, t) => {
|
|
|
3969
3740
|
x: .5,
|
|
3970
3741
|
y: .5
|
|
3971
3742
|
};
|
|
3972
|
-
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 =
|
|
3973
|
-
return createTexture(
|
|
3743
|
+
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 = vec2Length(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 = smoothstepEdge(.88, -.08, distanceToEdge), totalX = ix + (wave1 + shimmer + Math.cos(flowAngle) * flowEffect) * mask, totalY = iy + (wave2 + .8 * shimmer + Math.sin(flowAngle) * flowEffect) * mask;
|
|
3744
|
+
return createTexture(clamp(totalX + .5, 0, 1), clamp(totalY + .5, 0, 1));
|
|
3974
3745
|
},
|
|
3975
3746
|
// basiBasi - Expert Premium Glass Shader
|
|
3976
3747
|
// The most advanced shader with caustics, spectral dispersion, parallax depth, and volumetric effects
|
|
@@ -3979,7 +3750,7 @@ const smoothStep = (a, b, t) => {
|
|
|
3979
3750
|
x: .5,
|
|
3980
3751
|
y: .5
|
|
3981
3752
|
};
|
|
3982
|
-
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 =
|
|
3753
|
+
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 = vec2Length(mouseX, mouseY), mouseFalloff = easeOutQuart(1 - Math.min(1.2 * mouseDistance, 1)), causticIntensity = ((x, y, time, intensity = 1) =>
|
|
3983
3754
|
// Add input validation
|
|
3984
3755
|
"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) => {
|
|
3985
3756
|
// Add input validation
|
|
@@ -3997,7 +3768,7 @@ const smoothStep = (a, b, t) => {
|
|
|
3997
3768
|
y: 0
|
|
3998
3769
|
}
|
|
3999
3770
|
};
|
|
4000
|
-
const distance =
|
|
3771
|
+
const distance = vec2Length(x, y), dispersionStrength = Math.min(.025 * distance, 1), redOffset = .8 * dispersionStrength, greenOffset = 1 * dispersionStrength, blueOffset = 1.2 * dispersionStrength;
|
|
4001
3772
|
return {
|
|
4002
3773
|
r: {
|
|
4003
3774
|
x: Math.cos(angle) * redOffset,
|
|
@@ -4037,8 +3808,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4037
3808
|
return turbulence;
|
|
4038
3809
|
})(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) =>
|
|
4039
3810
|
// Add input validation
|
|
4040
|
-
"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 =
|
|
4041
|
-
return createTexture(
|
|
3811
|
+
"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 = vec2Length(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 = vec2Length(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 = smoothstepEdge(.92, -.12, distanceToEdge), edgeSoftness = smoothstepEdge(.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;
|
|
3812
|
+
return createTexture(clamp(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), clamp(finalY + .5, 0, 1));
|
|
4042
3813
|
},
|
|
4043
3814
|
// Aliases for compatibility
|
|
4044
3815
|
plasma: (uv, mousePosition) => fragmentShaders.premiumGlass(uv, mousePosition),
|
|
@@ -4080,8 +3851,8 @@ const smoothStep = (a, b, t) => {
|
|
|
4080
3851
|
let dx = pos.x * w - x, dy = pos.y * h - y;
|
|
4081
3852
|
// Apply edge smoothing for Apple-like effect
|
|
4082
3853
|
const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
|
|
4083
|
-
dx *=
|
|
4084
|
-
rawValues.push(dx, dy);
|
|
3854
|
+
dx *= smoothstepEdge(0, .2, edgeFactor), dy *= smoothstepEdge(0, .2, edgeFactor),
|
|
3855
|
+
maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)), rawValues.push(dx, dy);
|
|
4085
3856
|
}
|
|
4086
3857
|
// Improved normalization to prevent artifacts while maintaining intensity
|
|
4087
3858
|
maxScale = Math.max(maxScale, 1);
|
|
@@ -4091,9 +3862,9 @@ const smoothStep = (a, b, t) => {
|
|
|
4091
3862
|
let rawIndex = 0;
|
|
4092
3863
|
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
4093
3864
|
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);
|
|
4094
|
-
data[pixelIndex] =
|
|
4095
|
-
data[pixelIndex + 1] =
|
|
4096
|
-
data[pixelIndex + 2] =
|
|
3865
|
+
data[pixelIndex] = clamp(255 * r, 0, 255), // Red channel (X displacement)
|
|
3866
|
+
data[pixelIndex + 1] = clamp(255 * g, 0, 255), // Green channel (Y displacement)
|
|
3867
|
+
data[pixelIndex + 2] = clamp(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
|
|
4097
3868
|
data[pixelIndex + 3] = 255;
|
|
4098
3869
|
}
|
|
4099
3870
|
return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
|
|
@@ -4121,9 +3892,7 @@ const smoothStep = (a, b, t) => {
|
|
|
4121
3892
|
return this.canvasDPI;
|
|
4122
3893
|
}
|
|
4123
3894
|
},
|
|
4124
|
-
|
|
4125
|
-
fragmentShaders: fragmentShaders,
|
|
4126
|
-
liquidGlassWithTime: liquidGlassWithTime
|
|
3895
|
+
fragmentShaders: fragmentShaders
|
|
4127
3896
|
}, Symbol.toStringTag, {
|
|
4128
3897
|
value: "Module"
|
|
4129
3898
|
}));
|