@shohojdhara/atomix 0.6.1 → 0.6.3
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/README.md +510 -106
- package/dist/atomix.css +30 -24
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +6 -6
- 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 +11 -2
- package/dist/charts.js +294 -139
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +14 -39
- package/dist/core.js +297 -145
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +11 -1
- package/dist/forms.js +385 -185
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +9 -0
- package/dist/heavy.js +297 -143
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +156 -164
- package/dist/index.esm.js +391 -203
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +391 -203
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +14 -6
- package/dist/theme.js +2 -9
- package/dist/theme.js.map +1 -1
- package/package.json +26 -26
- package/src/components/AtomixGlass/AtomixGlass.tsx +1 -1
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +8 -1
- package/src/components/AtomixGlass/deprecated/AtomixGlass.deprecated.tsx +390 -0
- package/src/components/AtomixGlass/glass-utils.ts +29 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +32 -1
- package/src/components/Button/Button.stories.tsx +1 -1
- package/src/components/Button/Button.tsx +6 -5
- package/src/components/Card/Card.tsx +2 -2
- package/src/components/Dropdown/Dropdown.tsx +1 -0
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Form/Select.test.tsx +75 -0
- package/src/components/Form/Select.tsx +348 -252
- package/src/components/Form/SelectOption.tsx +16 -10
- package/src/components/index.ts +1 -1
- package/src/layouts/CssGrid/index.ts +1 -0
- package/src/lib/composables/shared-mouse-tracker.ts +62 -6
- package/src/lib/composables/useAtomixGlass.ts +241 -139
- package/src/lib/composables/useAtomixGlassStyles.ts +201 -149
- package/src/lib/constants/components.ts +54 -35
- package/src/lib/theme/config/configLoader.ts +1 -1
- package/src/lib/theme/test/testTheme.ts +2 -2
- package/src/lib/theme/utils/themeUtils.ts +98 -110
- package/src/lib/types/components.ts +29 -65
- package/src/styles/01-settings/_settings.spacing.scss +6 -1
- package/src/styles/03-generic/_generic.reset.scss +1 -1
- package/src/styles/06-components/_components.atomix-glass.scss +20 -29
- package/src/styles/06-components/_components.data-table.scss +5 -4
- package/src/styles/06-components/_components.dynamic-background.scss +9 -8
- package/src/styles/06-components/_components.footer.scss +8 -7
- package/src/styles/06-components/_components.hero.scss +2 -2
- package/src/styles/06-components/_components.messages.scss +16 -16
- package/src/styles/06-components/_components.navbar.scss +2 -0
- package/src/styles/06-components/_components.select.scss +15 -2
- package/src/styles/06-components/_components.upload.scss +3 -3
- package/CHANGELOG.md +0 -165
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +0 -215
package/dist/forms.js
CHANGED
|
@@ -47,12 +47,23 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
47
47
|
},
|
|
48
48
|
DEFAULTS: {
|
|
49
49
|
DISPLACEMENT_SCALE: 70,
|
|
50
|
-
BLUR_AMOUNT
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
get BLUR_AMOUNT() {
|
|
51
|
+
return .15 * this.DISPLACEMENT_SCALE;
|
|
52
|
+
// Dynamically computed based on displacement
|
|
53
|
+
},
|
|
54
|
+
get SATURATION() {
|
|
55
|
+
return 100 + .5 * this.DISPLACEMENT_SCALE;
|
|
56
|
+
// Saturate relative to intensity
|
|
57
|
+
},
|
|
58
|
+
get ABERRATION_INTENSITY() {
|
|
59
|
+
return .03 * this.DISPLACEMENT_SCALE;
|
|
60
|
+
// Scale aberration with displacement
|
|
61
|
+
},
|
|
53
62
|
ELASTICITY: .15,
|
|
54
|
-
CORNER_RADIUS
|
|
55
|
-
|
|
63
|
+
get CORNER_RADIUS() {
|
|
64
|
+
return 16;
|
|
65
|
+
// Use 16 to match SCSS design system (was 20)
|
|
66
|
+
},
|
|
56
67
|
PADDING: "0",
|
|
57
68
|
MODE: "standard",
|
|
58
69
|
OVER_LIGHT: !1,
|
|
@@ -74,6 +85,15 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
74
85
|
MIN_BLUR: .1,
|
|
75
86
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
76
87
|
EDGE_FADE_PIXELS: 2,
|
|
88
|
+
// Elasticity physics constants
|
|
89
|
+
ELASTICITY_TRANSLATION_FACTOR: .1,
|
|
90
|
+
ELASTICITY_DISTANCE_THRESHOLD: 200,
|
|
91
|
+
ELASTICITY_COMPRESSION_FACTOR: .3,
|
|
92
|
+
ELASTICITY_STIFFNESS: .1,
|
|
93
|
+
ELASTICITY_DAMPING: .76,
|
|
94
|
+
ELASTICITY_VELOCITY_FACTOR: .65,
|
|
95
|
+
ELASTICITY_STRETCH_RATIO: .45,
|
|
96
|
+
ELASTICITY_MAGNIFICATION_BASE: 1.02,
|
|
77
97
|
// Note: This default must match the SCSS variable --atomix-radius-md
|
|
78
98
|
// @see src/styles/01-settings/_settings.global.scss
|
|
79
99
|
DEFAULT_CORNER_RADIUS: 16,
|
|
@@ -90,84 +110,126 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
90
110
|
// Base angle for border gradients (degrees)
|
|
91
111
|
ANGLE_MULTIPLIER: 1.2,
|
|
92
112
|
// Multiplier for mouse influence on angle
|
|
113
|
+
VELOCITY_ANGLE_MULTIPLIER: 2.5,
|
|
114
|
+
// How much velocity affects gradient rotation
|
|
115
|
+
CHROMATIC_OFFSET: 1.5,
|
|
116
|
+
// Degree offset for chromatic rim layers
|
|
93
117
|
BORDER_STOP_1: {
|
|
94
118
|
MIN: 10,
|
|
95
119
|
// Minimum percentage for border stop 1
|
|
96
120
|
BASE: 33,
|
|
97
121
|
// Base percentage for border stop 1
|
|
98
|
-
MULTIPLIER
|
|
122
|
+
get MULTIPLIER() {
|
|
123
|
+
return .009 * this.BASE;
|
|
124
|
+
}
|
|
99
125
|
},
|
|
100
126
|
BORDER_STOP_2: {
|
|
101
127
|
MAX: 90,
|
|
102
128
|
// Maximum percentage for border stop 2
|
|
103
129
|
BASE: 66,
|
|
104
130
|
// Base percentage for border stop 2
|
|
105
|
-
MULTIPLIER
|
|
131
|
+
get MULTIPLIER() {
|
|
132
|
+
return .006 * this.BASE;
|
|
133
|
+
}
|
|
106
134
|
},
|
|
107
135
|
BORDER_OPACITY: {
|
|
108
136
|
BASE_1: .12,
|
|
109
137
|
// Base opacity for border gradient 1
|
|
110
|
-
BASE_2
|
|
138
|
+
get BASE_2() {
|
|
139
|
+
return 3.33 * this.BASE_1;
|
|
140
|
+
},
|
|
111
141
|
// Base opacity for border gradient 2
|
|
112
|
-
BASE_3
|
|
142
|
+
get BASE_3() {
|
|
143
|
+
return 2.66 * this.BASE_1;
|
|
144
|
+
},
|
|
113
145
|
// Base opacity for border gradient 3
|
|
114
|
-
BASE_4
|
|
146
|
+
get BASE_4() {
|
|
147
|
+
return 5 * this.BASE_1;
|
|
148
|
+
},
|
|
115
149
|
// Base opacity for border gradient 4
|
|
116
|
-
MULTIPLIER_LOW
|
|
150
|
+
get MULTIPLIER_LOW() {
|
|
151
|
+
return .066 * this.BASE_1;
|
|
152
|
+
},
|
|
117
153
|
// Low multiplier for mouse influence on opacity
|
|
118
|
-
MULTIPLIER_HIGH
|
|
154
|
+
get MULTIPLIER_HIGH() {
|
|
155
|
+
return .1 * this.BASE_1;
|
|
156
|
+
}
|
|
119
157
|
},
|
|
120
158
|
CENTER_POSITION: 50,
|
|
121
159
|
// Center position percentage (50%)
|
|
122
160
|
HOVER_POSITION: {
|
|
123
161
|
DIVISOR_1: 2,
|
|
124
162
|
// Divisor for hover 1 position calculation
|
|
125
|
-
DIVISOR_2
|
|
163
|
+
get DIVISOR_2() {
|
|
164
|
+
return .75 * this.DIVISOR_1;
|
|
165
|
+
},
|
|
126
166
|
// Divisor for hover 2 position calculation
|
|
127
|
-
MULTIPLIER_3
|
|
167
|
+
get MULTIPLIER_3() {
|
|
168
|
+
return .5 * this.DIVISOR_1;
|
|
169
|
+
}
|
|
128
170
|
},
|
|
129
|
-
BASE_LAYER_MULTIPLIER
|
|
171
|
+
get BASE_LAYER_MULTIPLIER() {
|
|
172
|
+
return .5;
|
|
173
|
+
}
|
|
130
174
|
},
|
|
131
175
|
// Gradient opacity values for hover effects
|
|
132
176
|
GRADIENT_OPACITY: {
|
|
133
177
|
HOVER_1: {
|
|
134
178
|
BLACK_START: .3,
|
|
135
179
|
// Start opacity for black hover 1
|
|
136
|
-
BLACK_MID
|
|
180
|
+
get BLACK_MID() {
|
|
181
|
+
return this.BLACK_START / 3;
|
|
182
|
+
},
|
|
137
183
|
// Mid opacity for black hover 1
|
|
138
184
|
BLACK_STOP: 30,
|
|
139
185
|
// Stop percentage for black hover 1
|
|
140
|
-
BLACK_END
|
|
186
|
+
get BLACK_END() {
|
|
187
|
+
return 2 * this.BLACK_STOP;
|
|
188
|
+
},
|
|
141
189
|
// End percentage for black hover 1
|
|
142
190
|
WHITE_START: .5,
|
|
143
191
|
// Start opacity for white hover 1
|
|
144
|
-
WHITE_STOP
|
|
192
|
+
get WHITE_STOP() {
|
|
193
|
+
return this.BLACK_END - 10;
|
|
194
|
+
}
|
|
145
195
|
},
|
|
146
196
|
HOVER_2: {
|
|
147
197
|
BLACK_START: .4,
|
|
148
198
|
// Start opacity for black hover 2
|
|
149
|
-
BLACK_MID
|
|
199
|
+
get BLACK_MID() {
|
|
200
|
+
return .375 * this.BLACK_START;
|
|
201
|
+
},
|
|
150
202
|
// Mid opacity for black hover 2
|
|
151
203
|
BLACK_STOP: 40,
|
|
152
204
|
// Stop percentage for black hover 2
|
|
153
|
-
BLACK_END
|
|
205
|
+
get BLACK_END() {
|
|
206
|
+
return 2 * this.BLACK_STOP;
|
|
207
|
+
},
|
|
154
208
|
// End percentage for black hover 2
|
|
155
209
|
WHITE_START: 1,
|
|
156
210
|
// Start opacity for white hover 2
|
|
157
|
-
WHITE_STOP
|
|
211
|
+
get WHITE_STOP() {
|
|
212
|
+
return this.BLACK_END;
|
|
213
|
+
}
|
|
158
214
|
},
|
|
159
215
|
HOVER_3: {
|
|
160
216
|
BLACK_START: .5,
|
|
161
217
|
// Start opacity for black hover 3
|
|
162
|
-
BLACK_MID
|
|
218
|
+
get BLACK_MID() {
|
|
219
|
+
return .4 * this.BLACK_START;
|
|
220
|
+
},
|
|
163
221
|
// Mid opacity for black hover 3
|
|
164
222
|
BLACK_STOP: 50,
|
|
165
223
|
// Stop percentage for black hover 3
|
|
166
|
-
BLACK_END
|
|
224
|
+
get BLACK_END() {
|
|
225
|
+
return 2 * this.BLACK_STOP;
|
|
226
|
+
},
|
|
167
227
|
// End percentage for black hover 3
|
|
168
228
|
WHITE_START: 1,
|
|
169
229
|
// Start opacity for white hover 3
|
|
170
|
-
WHITE_STOP
|
|
230
|
+
get WHITE_STOP() {
|
|
231
|
+
return this.BLACK_END;
|
|
232
|
+
}
|
|
171
233
|
}
|
|
172
234
|
},
|
|
173
235
|
// Base and overlay gradient constants
|
|
@@ -176,34 +238,54 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
176
238
|
// Gradient angle in degrees
|
|
177
239
|
BLACK_START_BASE: .15,
|
|
178
240
|
// Base start opacity for black
|
|
179
|
-
BLACK_START_MULTIPLIER
|
|
241
|
+
get BLACK_START_MULTIPLIER() {
|
|
242
|
+
return .02 * this.BLACK_START_BASE;
|
|
243
|
+
},
|
|
180
244
|
// Multiplier for mouse X influence on start
|
|
181
245
|
BLACK_MID_BASE: .1,
|
|
182
246
|
// Base mid opacity for black
|
|
183
|
-
BLACK_MID_MULTIPLIER
|
|
247
|
+
get BLACK_MID_MULTIPLIER() {
|
|
248
|
+
return .02 * this.BLACK_MID_BASE;
|
|
249
|
+
},
|
|
184
250
|
// Multiplier for mouse Y influence on mid
|
|
185
251
|
BLACK_MID_STOP: 50,
|
|
186
252
|
// Mid stop percentage
|
|
187
|
-
BLACK_END_BASE
|
|
253
|
+
get BLACK_END_BASE() {
|
|
254
|
+
return 1.2 * this.BLACK_START_BASE;
|
|
255
|
+
},
|
|
188
256
|
// Base end opacity for black
|
|
189
|
-
BLACK_END_MULTIPLIER
|
|
257
|
+
get BLACK_END_MULTIPLIER() {
|
|
258
|
+
return .022 * this.BLACK_END_BASE;
|
|
259
|
+
},
|
|
190
260
|
// Multiplier for mouse X influence on end
|
|
191
|
-
WHITE_OPACITY
|
|
261
|
+
get WHITE_OPACITY() {
|
|
262
|
+
return .666 * this.BLACK_START_BASE;
|
|
263
|
+
}
|
|
192
264
|
},
|
|
193
265
|
OVERLAY_GRADIENT: {
|
|
194
266
|
BLACK_START_BASE: .12,
|
|
195
267
|
// Base start opacity for black overlay
|
|
196
|
-
BLACK_START_MULTIPLIER
|
|
268
|
+
get BLACK_START_MULTIPLIER() {
|
|
269
|
+
return .025 * this.BLACK_START_BASE;
|
|
270
|
+
},
|
|
197
271
|
// Multiplier for mouse X influence on start
|
|
198
|
-
BLACK_MID
|
|
272
|
+
get BLACK_MID() {
|
|
273
|
+
return .5 * this.BLACK_START_BASE;
|
|
274
|
+
},
|
|
199
275
|
// Mid opacity for black overlay
|
|
200
276
|
BLACK_MID_STOP: 40,
|
|
201
277
|
// Mid stop percentage
|
|
202
|
-
BLACK_END_BASE
|
|
278
|
+
get BLACK_END_BASE() {
|
|
279
|
+
return 1.25 * this.BLACK_START_BASE;
|
|
280
|
+
},
|
|
203
281
|
// Base end opacity for black overlay
|
|
204
|
-
BLACK_END_MULTIPLIER
|
|
282
|
+
get BLACK_END_MULTIPLIER() {
|
|
283
|
+
return .02 * this.BLACK_END_BASE;
|
|
284
|
+
},
|
|
205
285
|
// Multiplier for mouse Y influence on end
|
|
206
|
-
WHITE_OPACITY
|
|
286
|
+
get WHITE_OPACITY() {
|
|
287
|
+
return .416 * this.BLACK_START_BASE;
|
|
288
|
+
}
|
|
207
289
|
},
|
|
208
290
|
// Overlay highlight constants
|
|
209
291
|
OVERLAY_HIGHLIGHT: {
|
|
@@ -213,9 +295,13 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
213
295
|
// Y position percentage
|
|
214
296
|
WHITE_OPACITY: .4,
|
|
215
297
|
// White opacity in gradient
|
|
216
|
-
STOP
|
|
298
|
+
get STOP() {
|
|
299
|
+
return 150 * this.WHITE_OPACITY;
|
|
300
|
+
},
|
|
217
301
|
// Stop percentage
|
|
218
|
-
OPACITY_MULTIPLIER
|
|
302
|
+
get OPACITY_MULTIPLIER() {
|
|
303
|
+
return 1.75 * this.WHITE_OPACITY;
|
|
304
|
+
}
|
|
219
305
|
},
|
|
220
306
|
// Displacement and aberration multipliers
|
|
221
307
|
MULTIPLIERS: {
|
|
@@ -268,11 +354,7 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
268
354
|
}
|
|
269
355
|
}
|
|
270
356
|
}
|
|
271
|
-
}, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS,
|
|
272
|
-
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
273
|
-
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
274
|
-
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
275
|
-
}, calculateElementCenter = rect => rect ? {
|
|
357
|
+
}, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateElementCenter = rect => rect ? {
|
|
276
358
|
x: rect.left + rect.width / 2,
|
|
277
359
|
y: rect.top + rect.height / 2
|
|
278
360
|
} : {
|
|
@@ -344,7 +426,16 @@ import React, { memo, forwardRef, useId, useMemo, useState, useRef, useEffect, u
|
|
|
344
426
|
// Silently handle errors
|
|
345
427
|
}
|
|
346
428
|
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
347
|
-
},
|
|
429
|
+
}, smoothstep = t => {
|
|
430
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
431
|
+
return clamped * clamped * (3 - 2 * clamped);
|
|
432
|
+
}, lerp$1 = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), calculateSpring = (current, target, velocity, stiffness = .1, damping = .8) => {
|
|
433
|
+
const newVelocity = (velocity + (target - current) * stiffness) * damping;
|
|
434
|
+
return {
|
|
435
|
+
value: current + newVelocity,
|
|
436
|
+
velocity: newVelocity
|
|
437
|
+
};
|
|
438
|
+
}, getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
348
439
|
switch (mode) {
|
|
349
440
|
case "standard":
|
|
350
441
|
return displacementMap;
|
|
@@ -735,6 +826,9 @@ shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpee
|
|
|
735
826
|
}), jsx("div", {
|
|
736
827
|
ref: contentRef,
|
|
737
828
|
className: ATOMIX_GLASS.CONTENT_CLASS,
|
|
829
|
+
style: {
|
|
830
|
+
transform: "var(--atomix-glass-child-parallax, none)"
|
|
831
|
+
},
|
|
738
832
|
children: children
|
|
739
833
|
}) ]
|
|
740
834
|
})
|
|
@@ -769,9 +863,21 @@ class {
|
|
|
769
863
|
y: this.lastEvent.clientY
|
|
770
864
|
},
|
|
771
865
|
// Notify all subscribers
|
|
772
|
-
this.listeners.forEach((
|
|
866
|
+
this.listeners.forEach((listener => {
|
|
773
867
|
try {
|
|
774
|
-
|
|
868
|
+
// If the listener has an element, calculate distance-based attenuation
|
|
869
|
+
if (listener.element) {
|
|
870
|
+
const elementRect = listener.element.getBoundingClientRect(), elementCenter = {
|
|
871
|
+
x: elementRect.left + elementRect.width / 2,
|
|
872
|
+
y: elementRect.top + elementRect.height / 2
|
|
873
|
+
}, distance = this.calculateDistance(this.position, elementCenter), maxDistance = listener.maxDistance || 300, attenuation = Math.max(0, 1 - distance / maxDistance), attenuatedRelativePosition = {
|
|
874
|
+
x: (this.position.x - elementCenter.x) / elementRect.width * 100 * attenuation,
|
|
875
|
+
y: (this.position.y - elementCenter.y) / elementRect.height * 100 * attenuation
|
|
876
|
+
};
|
|
877
|
+
listener.callback(attenuatedRelativePosition);
|
|
878
|
+
} else
|
|
879
|
+
// Send original position for listeners without distance-based attenuation
|
|
880
|
+
listener.callback(this.position);
|
|
775
881
|
} catch (error) {
|
|
776
882
|
console.error("GlobalMouseTracker: Error in subscriber callback", error);
|
|
777
883
|
}
|
|
@@ -782,10 +888,17 @@ class {
|
|
|
782
888
|
/**
|
|
783
889
|
* Subscribe to mouse position updates
|
|
784
890
|
* @param callback Function to call when mouse position changes
|
|
891
|
+
* @param element Optional element for distance-based attenuation
|
|
892
|
+
* @param maxDistance Optional maximum distance for full effect
|
|
785
893
|
* @returns Unsubscribe function
|
|
786
|
-
*/ subscribe(callback) {
|
|
894
|
+
*/ subscribe(callback, element, maxDistance) {
|
|
895
|
+
const listener = {
|
|
896
|
+
callback: callback,
|
|
897
|
+
element: element,
|
|
898
|
+
maxDistance: maxDistance
|
|
899
|
+
};
|
|
787
900
|
// Return unsubscribe function
|
|
788
|
-
return this.listeners.add(
|
|
901
|
+
return this.listeners.add(listener),
|
|
789
902
|
// Start tracking if this is the first subscriber
|
|
790
903
|
1 === this.listeners.size && this.startTracking(),
|
|
791
904
|
// Immediately notify with current position
|
|
@@ -796,9 +909,13 @@ class {
|
|
|
796
909
|
/**
|
|
797
910
|
* Unsubscribe from mouse position updates
|
|
798
911
|
*/ unsubscribe(callback) {
|
|
799
|
-
|
|
912
|
+
// Find and remove the listener with the given callback
|
|
913
|
+
for (const listener of this.listeners) if (listener.callback === callback) {
|
|
914
|
+
this.listeners.delete(listener);
|
|
915
|
+
break;
|
|
916
|
+
}
|
|
800
917
|
// Stop tracking if no more subscribers
|
|
801
|
-
|
|
918
|
+
0 === this.listeners.size && this.stopTracking();
|
|
802
919
|
}
|
|
803
920
|
/**
|
|
804
921
|
* Start tracking mouse movement
|
|
@@ -817,6 +934,12 @@ class {
|
|
|
817
934
|
null !== this.rafId && (cancelAnimationFrame(this.rafId), this.rafId = null), this.lastEvent = null);
|
|
818
935
|
}
|
|
819
936
|
/**
|
|
937
|
+
* Calculate distance between two points
|
|
938
|
+
*/ calculateDistance(point1, point2) {
|
|
939
|
+
const dx = point1.x - point2.x, dy = point1.y - point2.y;
|
|
940
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
820
943
|
* Get current mouse position (synchronous)
|
|
821
944
|
*/ getPosition() {
|
|
822
945
|
return {
|
|
@@ -830,51 +953,26 @@ class {
|
|
|
830
953
|
}
|
|
831
954
|
}, updateAtomixGlassStyles = (wrapperElement, containerElement, params) => {
|
|
832
955
|
if (!wrapperElement && !containerElement) return;
|
|
833
|
-
|
|
956
|
+
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, padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, isFixedOrSticky: isFixedOrSticky = !1} = params, mouseInfluence = calculateMouseInfluence(mouseOffset), hoverIntensity = isHovered ? 1.4 : 1, activeIntensity = isActive ? 1.6 : 1, overLightConfig = {
|
|
834
958
|
opacity: baseOverLightConfig.opacity * hoverIntensity * activeIntensity,
|
|
835
959
|
contrast: Math.min(1.6, baseOverLightConfig.contrast + .1 * mouseInfluence),
|
|
836
960
|
brightness: Math.min(1.1, baseOverLightConfig.brightness + .05 * mouseInfluence),
|
|
837
961
|
shadowIntensity: Math.min(1.2, Math.max(.5, baseOverLightConfig.shadowIntensity + .2 * mouseInfluence)),
|
|
838
962
|
borderOpacity: Math.min(1, Math.max(.3, baseOverLightConfig.borderOpacity + .1 * mouseInfluence)),
|
|
839
963
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
|
|
964
|
+
}, scaleX = directionalScale.x * scaleBase, scaleY = directionalScale.y * scaleBase, transformStyle = effectiveWithoutEffects ? `scale(${scaleBase})` : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) scaleX(${scaleX}) scaleY(${scaleY})`, stretchMagnitude = ((pos1, pos2) => {
|
|
965
|
+
if (!pos1 || !pos2 || "number" != typeof pos1.x || "number" != typeof pos1.y || "number" != typeof pos2.x || "number" != typeof pos2.y) return 0;
|
|
966
|
+
const deltaX = pos1.x - pos2.x, deltaY = pos1.y - pos2.y;
|
|
967
|
+
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
968
|
+
})({
|
|
843
969
|
x: 0,
|
|
844
970
|
y: 0
|
|
845
|
-
};
|
|
846
|
-
// Calculate
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
851
|
-
const deltaX = globalMousePosition.x - center.x, deltaY = globalMousePosition.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2), edgeDistance = calculateDistance({
|
|
852
|
-
x: edgeDistanceX,
|
|
853
|
-
y: edgeDistanceY
|
|
854
|
-
}, {
|
|
855
|
-
x: 0,
|
|
856
|
-
y: 0
|
|
857
|
-
}), rawT = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE, fadeInFactor = (t => {
|
|
858
|
-
const clamped = Math.max(0, Math.min(1, t));
|
|
859
|
-
return clamped * clamped * (3 - 2 * clamped);
|
|
860
|
-
})(rawT);
|
|
861
|
-
// Directional scale
|
|
862
|
-
if (elasticTranslation = {
|
|
863
|
-
x: deltaX * elasticity * .1 * fadeInFactor,
|
|
864
|
-
y: deltaY * elasticity * .1 * fadeInFactor
|
|
865
|
-
}, !isOverLight && edgeDistance <= ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE) {
|
|
866
|
-
const centerDistance = calculateDistance(globalMousePosition, center);
|
|
867
|
-
if (centerDistance > 0) {
|
|
868
|
-
const normalizedX = deltaX / centerDistance, normalizedY = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * rawT, scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * .3 - Math.abs(normalizedY) * stretchIntensity * .15, scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * .3 - Math.abs(normalizedX) * stretchIntensity * .15, softScaleX = 1 - softClamp(Math.max(0, 1 - scaleX), .2), softScaleY = 1 - softClamp(Math.max(0, 1 - scaleY), .2);
|
|
869
|
-
computedDirectionalScale = `scaleX(${Math.max(.85, softScaleX)}) scaleY(${Math.max(.85, softScaleY)})`;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
const transformStyle = effectiveWithoutEffects ? isActive && Boolean(onClick) ? "scale(0.98)" : "scale(1)" : `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? "scale(0.96)" : computedDirectionalScale}`;
|
|
875
|
-
// Update Wrapper Styles (glassVars)
|
|
876
|
-
if (wrapperElement) {
|
|
877
|
-
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), borderOpacities = [ GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH, GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW, GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
971
|
+
}, elasticTranslation), tensionFactor = smoothstep(stretchMagnitude / 80), lightingContrast = Math.min(1.8, overLightConfig.contrast + .2 * tensionFactor), lightingBrightness = Math.min(1.2, overLightConfig.brightness + .1 * tensionFactor);
|
|
972
|
+
// Calculate mouse influence
|
|
973
|
+
// Update Wrapper Styles (glassVars)
|
|
974
|
+
if (wrapperElement) {
|
|
975
|
+
const mx = mouseOffset.x, my = mouseOffset.y, absMx = Math.abs(mx), absMy = Math.abs(my), GRADIENT = ATOMIX_GLASS.CONSTANTS.GRADIENT, velocityRotation = (mouseVelocity.x + elasticVelocity.x) * (GRADIENT.VELOCITY_ANGLE_MULTIPLIER || 2.5), borderGradientAngle = GRADIENT.BASE_ANGLE + mx * GRADIENT.ANGLE_MULTIPLIER + velocityRotation, chromaticOffset = GRADIENT.CHROMATIC_OFFSET || 1.5, angleR = borderGradientAngle - chromaticOffset, angleB = borderGradientAngle + chromaticOffset, borderStop1 = Math.max(GRADIENT.BORDER_STOP_1.MIN, GRADIENT.BORDER_STOP_1.BASE + my * GRADIENT.BORDER_STOP_1.MULTIPLIER), borderStop2 = Math.min(GRADIENT.BORDER_STOP_2.MAX, GRADIENT.BORDER_STOP_2.BASE + my * GRADIENT.BORDER_STOP_2.MULTIPLIER), tensionGlow = 1 + .5 * tensionFactor, borderOpacities = [ (GRADIENT.BORDER_OPACITY.BASE_1 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_2 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_3 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_LOW) * tensionGlow, (GRADIENT.BORDER_OPACITY.BASE_4 + absMx * GRADIENT.BORDER_OPACITY.MULTIPLIER_HIGH) * tensionGlow ], configBorderOpacity = overLightConfig.borderOpacity, whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE, blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK, hoverPositions = {
|
|
878
976
|
hover1: {
|
|
879
977
|
x: GRADIENT.CENTER_POSITION + mx / GRADIENT.HOVER_POSITION.DIVISOR_1,
|
|
880
978
|
y: GRADIENT.CENTER_POSITION + my / GRADIENT.HOVER_POSITION.DIVISOR_1
|
|
@@ -897,10 +995,16 @@ class {
|
|
|
897
995
|
base: isOverLight ? overLightConfig.opacity : 0,
|
|
898
996
|
over: isOverLight ? 1.1 * overLightConfig.opacity : 0
|
|
899
997
|
}, style = wrapperElement.style;
|
|
900
|
-
style.setProperty("--atomix-glass-transform", transformStyle || "none")
|
|
901
|
-
//
|
|
902
|
-
|
|
903
|
-
style.setProperty("--atomix-glass-
|
|
998
|
+
style.setProperty("--atomix-glass-transform", transformStyle || "none");
|
|
999
|
+
// Parallax for content (liquid refraction feel)
|
|
1000
|
+
const parallaxFactor = .38 + .12 * tensionFactor;
|
|
1001
|
+
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()),
|
|
1003
|
+
// ── Chromatic Rim Lighting ──────────────────────────────────────
|
|
1004
|
+
// Layer 1: Core White/Blue highlight
|
|
1005
|
+
style.setProperty("--atomix-glass-border-gradient-1", `linear-gradient(${angleB}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
|
|
1006
|
+
// Layer 2: Subtle Red/Warm highlight (offset angle)
|
|
1007
|
+
style.setProperty("--atomix-glass-border-gradient-2", `linear-gradient(${angleR}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`),
|
|
904
1008
|
// Hover gradients
|
|
905
1009
|
style.setProperty("--atomix-glass-hover-1-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.WHITE_STOP}%)`),
|
|
906
1010
|
style.setProperty("--atomix-glass-hover-2-gradient", isOverLight ? `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.BLACK_END}%)` : `radial-gradient(circle at ${hoverPositions.hover2.x}% ${hoverPositions.hover2.y}%, rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_START}) 0%, rgba(${whiteColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_2.WHITE_STOP}%)`),
|
|
@@ -928,7 +1032,7 @@ class {
|
|
|
928
1032
|
flowBlur: blurAmount * FLOW_BLUR_MULTIPLIER
|
|
929
1033
|
};
|
|
930
1034
|
if (withLiquidBlur && rect) {
|
|
931
|
-
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = blurAmount * MAX_BLUR_RELATIVE, baseBlur =
|
|
1035
|
+
const mouseInfluence = calculateMouseInfluence(mouseOffset), maxBlur = blurAmount * MAX_BLUR_RELATIVE, baseBlur = softClamp(blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR, maxBlur), edgeBlur = softClamp(baseBlur * (.8 + mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR * .4), maxBlur), centerBlur = softClamp(baseBlur * (.3 + mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR * .3), maxBlur), flowBlur = softClamp(baseBlur * FLOW_BLUR_MULTIPLIER, maxBlur);
|
|
932
1036
|
liquidBlur = {
|
|
933
1037
|
baseBlur: clampBlur(baseBlur),
|
|
934
1038
|
edgeBlur: clampBlur(edgeBlur),
|
|
@@ -937,9 +1041,10 @@ class {
|
|
|
937
1041
|
};
|
|
938
1042
|
}
|
|
939
1043
|
// Backdrop filter
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1044
|
+
const dynamicSaturation = saturation + 40 * tensionFactor + 15 * (liquidBlur.baseBlur || 0);
|
|
1045
|
+
let backdropFilterString = "";
|
|
1046
|
+
const area = rect ? rect.width * rect.height : 0;
|
|
1047
|
+
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})`;
|
|
943
1048
|
// Container variables
|
|
944
1049
|
const style = containerElement.style;
|
|
945
1050
|
style.setProperty("--atomix-glass-container-padding", padding), style.setProperty("--atomix-glass-container-radius", `${effectiveBorderRadius}px`),
|
|
@@ -1101,7 +1206,8 @@ const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new Weak
|
|
|
1101
1206
|
* Composable hook for AtomixGlass component logic
|
|
1102
1207
|
* Manages all state, calculations, and event handlers
|
|
1103
1208
|
*/
|
|
1104
|
-
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 = .
|
|
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, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, priority: priority = 1, withTimeAnimation:
|
|
1210
|
+
// Default priority
|
|
1105
1211
|
// Phase 1: Animation System Props
|
|
1106
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}) {
|
|
1107
1213
|
// State
|
|
@@ -1117,7 +1223,24 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1117
1223
|
}), targetGlobalMousePositionRef = useRef({
|
|
1118
1224
|
x: 0,
|
|
1119
1225
|
y: 0
|
|
1120
|
-
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS),
|
|
1226
|
+
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), elasticTranslationRef = useRef({
|
|
1227
|
+
x: 0,
|
|
1228
|
+
y: 0
|
|
1229
|
+
}), elasticVelocityRef = useRef({
|
|
1230
|
+
x: 0,
|
|
1231
|
+
y: 0
|
|
1232
|
+
}), directionalScaleRef = useRef({
|
|
1233
|
+
x: 1,
|
|
1234
|
+
y: 1
|
|
1235
|
+
}), scaleVelocityRef = useRef({
|
|
1236
|
+
x: 0,
|
|
1237
|
+
y: 0
|
|
1238
|
+
});
|
|
1239
|
+
useRef(0);
|
|
1240
|
+
const mouseVelocityRef = useRef({
|
|
1241
|
+
x: 0,
|
|
1242
|
+
y: 0
|
|
1243
|
+
}), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), animationFrameIdRef = useRef(null), animationStartTimeRef = useRef(0), elapsedTimeRef = useRef(0), shaderTimeRef = useRef(0), fbmConfig = useMemo((() => {
|
|
1121
1244
|
// If quality preset is provided, use it as base
|
|
1122
1245
|
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
1123
1246
|
// Override with custom values if provided
|
|
@@ -1402,57 +1525,85 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1402
1525
|
return "undefined" == typeof process || process.env, finalConfig;
|
|
1403
1526
|
}
|
|
1404
1527
|
return "undefined" == typeof process || process.env, baseConfig;
|
|
1405
|
-
}), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.
|
|
1528
|
+
}), [ overLight, getEffectiveOverLight, isHovered, isActive, validateConfigValue, debugOverLight ]), transformStyle = useMemo((() => effectiveWithoutEffects || isActive && Boolean(onClick) ? "scale(0.99)" : "scale(1)"), [ effectiveWithoutEffects, isActive, onClick ]), updateRectRef = useRef(null), stopLerpLoop = useCallback((() => {
|
|
1406
1529
|
lerpActiveRef.current = !1, null !== lerpRafRef.current && (cancelAnimationFrame(lerpRafRef.current),
|
|
1407
1530
|
lerpRafRef.current = null);
|
|
1408
1531
|
}), []), startLerpLoop = useCallback((() => {
|
|
1409
1532
|
if (lerpActiveRef.current) return;
|
|
1410
|
-
lerpActiveRef.current = !0;
|
|
1411
|
-
|
|
1533
|
+
lerpActiveRef.current = !0, CONSTANTS.LERP_FACTOR;
|
|
1534
|
+
// 0.08 – lower = more viscous
|
|
1535
|
+
const tick = () => {
|
|
1412
1536
|
if (!lerpActiveRef.current) return;
|
|
1413
1537
|
if (!glassRef.current) return void (lerpActiveRef.current = !1);
|
|
1414
|
-
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current,
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
},
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
// Final update and stop
|
|
1422
|
-
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1423
|
-
mouseOffset: internalMouseOffsetRef.current,
|
|
1424
|
-
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
1425
|
-
glassSize: glassSize,
|
|
1426
|
-
isHovered: isHovered,
|
|
1427
|
-
isActive: isActive,
|
|
1428
|
-
isOverLight: overLightConfig.isOverLight,
|
|
1429
|
-
baseOverLightConfig: overLightConfig,
|
|
1430
|
-
effectiveBorderRadius: effectiveBorderRadius,
|
|
1431
|
-
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1432
|
-
effectiveReducedMotion: effectiveReducedMotion,
|
|
1433
|
-
elasticity: elasticity,
|
|
1434
|
-
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1435
|
-
onClick: onClick,
|
|
1436
|
-
withLiquidBlur: withLiquidBlur,
|
|
1437
|
-
blurAmount: blurAmount,
|
|
1438
|
-
saturation: saturation,
|
|
1439
|
-
padding: padding,
|
|
1440
|
-
isFixedOrSticky: isFixedOrSticky
|
|
1441
|
-
}), void stopLerpLoop();
|
|
1442
|
-
// Smooth step
|
|
1443
|
-
internalMouseOffsetRef.current = {
|
|
1444
|
-
x: lerp$1(cur.x, tgt.x, LERP_T),
|
|
1445
|
-
y: lerp$1(cur.y, tgt.y, LERP_T)
|
|
1538
|
+
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, springX = calculateSpring(cur.x, tgt.x, mouseVelocityRef.current.x, CONSTANTS.LERP_FACTOR, CONSTANTS.ELASTICITY_DAMPING), springY = calculateSpring(cur.y, tgt.y, mouseVelocityRef.current.y, CONSTANTS.LERP_FACTOR, CONSTANTS.ELASTICITY_DAMPING);
|
|
1539
|
+
internalMouseOffsetRef.current = {
|
|
1540
|
+
x: springX.value,
|
|
1541
|
+
y: springY.value
|
|
1542
|
+
}, mouseVelocityRef.current = {
|
|
1543
|
+
x: springX.velocity,
|
|
1544
|
+
y: springY.velocity
|
|
1446
1545
|
};
|
|
1447
1546
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
1448
1547
|
internalGlobalMousePositionRef.current = {
|
|
1449
|
-
x: lerp$1(curG.x, tgtG.x,
|
|
1450
|
-
y: lerp$1(curG.y, tgtG.y,
|
|
1548
|
+
x: lerp$1(curG.x, tgtG.x, CONSTANTS.LERP_FACTOR),
|
|
1549
|
+
y: lerp$1(curG.y, tgtG.y, CONSTANTS.LERP_FACTOR)
|
|
1550
|
+
};
|
|
1551
|
+
// ── Calculate Elastic Physics ─────────────────────────────────────
|
|
1552
|
+
let targetElasticTranslation = {
|
|
1553
|
+
x: 0,
|
|
1554
|
+
y: 0
|
|
1555
|
+
}, targetScale = {
|
|
1556
|
+
x: 1,
|
|
1557
|
+
y: 1
|
|
1558
|
+
};
|
|
1559
|
+
if (!effectiveWithoutEffects && glassRef.current) {
|
|
1560
|
+
const rect = cachedRectRef.current || glassRef.current.getBoundingClientRect(), center = calculateElementCenter(rect), globalPos = internalGlobalMousePositionRef.current;
|
|
1561
|
+
if (globalPos.x && globalPos.y) {
|
|
1562
|
+
const deltaX = globalPos.x - center.x, deltaY = globalPos.y - center.y, edgeDistanceX = Math.max(0, Math.abs(deltaX) - rect.width / 2), edgeDistanceY = Math.max(0, Math.abs(deltaY) - rect.height / 2), edgeDistance = Math.sqrt(edgeDistanceX * edgeDistanceX + edgeDistanceY * edgeDistanceY), activationZone = CONSTANTS.ACTIVATION_ZONE, rawT = edgeDistance > activationZone ? 0 : 1 - edgeDistance / activationZone, fadeInFactor = smoothstep(rawT);
|
|
1563
|
+
// Scale stretch logic (liquid surface tension)
|
|
1564
|
+
if (targetElasticTranslation = {
|
|
1565
|
+
x: deltaX * elasticity * CONSTANTS.ELASTICITY_TRANSLATION_FACTOR * fadeInFactor,
|
|
1566
|
+
y: deltaY * elasticity * CONSTANTS.ELASTICITY_TRANSLATION_FACTOR * fadeInFactor
|
|
1567
|
+
}, edgeDistance <= activationZone) {
|
|
1568
|
+
const centerDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
1569
|
+
if (centerDistance > 0) {
|
|
1570
|
+
const nx = deltaX / centerDistance, ny = deltaY / centerDistance, stretchIntensity = Math.min(centerDistance / 350, 1) * elasticity * rawT, mag = 1 + .06 * stretchIntensity;
|
|
1571
|
+
targetScale = {
|
|
1572
|
+
x: mag + Math.abs(nx) * stretchIntensity * CONSTANTS.ELASTICITY_STRETCH_RATIO,
|
|
1573
|
+
y: mag + Math.abs(ny) * stretchIntensity * CONSTANTS.ELASTICITY_STRETCH_RATIO
|
|
1574
|
+
},
|
|
1575
|
+
// Maintain liquid volume by compressing the perpendicular axis
|
|
1576
|
+
targetScale.x -= Math.abs(ny) * stretchIntensity * .15, targetScale.y -= Math.abs(nx) * stretchIntensity * .15;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
// Integrate Elastic Translation Spring
|
|
1582
|
+
const springTX = calculateSpring(elasticTranslationRef.current.x, targetElasticTranslation.x, elasticVelocityRef.current.x, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING), springTY = calculateSpring(elasticTranslationRef.current.y, targetElasticTranslation.y, elasticVelocityRef.current.y, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING);
|
|
1583
|
+
elasticTranslationRef.current = {
|
|
1584
|
+
x: springTX.value,
|
|
1585
|
+
y: springTY.value
|
|
1586
|
+
}, elasticVelocityRef.current = {
|
|
1587
|
+
x: springTX.velocity,
|
|
1588
|
+
y: springTY.velocity
|
|
1589
|
+
};
|
|
1590
|
+
// Integrate Scale Spring
|
|
1591
|
+
const springSX = calculateSpring(directionalScaleRef.current.x, targetScale.x, scaleVelocityRef.current.x, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING), springSY = calculateSpring(directionalScaleRef.current.y, targetScale.y, scaleVelocityRef.current.y, CONSTANTS.ELASTICITY_STIFFNESS, CONSTANTS.ELASTICITY_DAMPING);
|
|
1592
|
+
directionalScaleRef.current = {
|
|
1593
|
+
x: springSX.value,
|
|
1594
|
+
y: springSY.value
|
|
1595
|
+
}, scaleVelocityRef.current = {
|
|
1596
|
+
x: springSX.velocity,
|
|
1597
|
+
y: springSY.velocity
|
|
1451
1598
|
},
|
|
1452
1599
|
// Imperative style update
|
|
1453
1600
|
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1454
1601
|
mouseOffset: internalMouseOffsetRef.current,
|
|
1455
1602
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
1603
|
+
elasticTranslation: elasticTranslationRef.current,
|
|
1604
|
+
elasticVelocity: elasticVelocityRef.current,
|
|
1605
|
+
mouseVelocity: mouseVelocityRef.current,
|
|
1606
|
+
directionalScale: directionalScaleRef.current,
|
|
1456
1607
|
glassSize: glassSize,
|
|
1457
1608
|
isHovered: isHovered,
|
|
1458
1609
|
isActive: isActive,
|
|
@@ -1462,17 +1613,16 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1462
1613
|
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1463
1614
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1464
1615
|
elasticity: elasticity,
|
|
1465
|
-
|
|
1616
|
+
scaleBase: isActive && Boolean(onClick) ? .99 : 1,
|
|
1466
1617
|
onClick: onClick,
|
|
1467
1618
|
withLiquidBlur: withLiquidBlur,
|
|
1468
1619
|
blurAmount: blurAmount,
|
|
1469
1620
|
saturation: saturation,
|
|
1470
1621
|
padding: padding,
|
|
1471
1622
|
isFixedOrSticky: isFixedOrSticky
|
|
1472
|
-
}), lerpRafRef.current = requestAnimationFrame(tick);
|
|
1623
|
+
}), 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);
|
|
1473
1624
|
};
|
|
1474
|
-
|
|
1475
|
-
lerpRafRef.current = requestAnimationFrame(tick);
|
|
1625
|
+
lerpRafRef.current = requestAnimationFrame(tick);
|
|
1476
1626
|
}), [ glassRef, wrapperRef, glassSize, isHovered, isActive, overLightConfig, effectiveBorderRadius, effectiveWithoutEffects, effectiveReducedMotion, elasticity, onClick, withLiquidBlur, blurAmount, saturation, padding, isFixedOrSticky, stopLerpLoop ]), handleGlobalMousePosition = useCallback((globalPos => {
|
|
1477
1627
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1478
1628
|
if (effectiveWithoutEffects) return;
|
|
@@ -1498,7 +1648,8 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1498
1648
|
useEffect((() => {
|
|
1499
1649
|
if (externalGlobalMousePosition && externalMouseOffset) return;
|
|
1500
1650
|
if (effectiveWithoutEffects) return;
|
|
1501
|
-
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition);
|
|
1651
|
+
const unsubscribe = globalMouseTracker.subscribe(handleGlobalMousePosition, glassRef.current || void 0, 300);
|
|
1652
|
+
// 300px max distance for full effect
|
|
1502
1653
|
// Initial start
|
|
1503
1654
|
startLerpLoop();
|
|
1504
1655
|
const container = mouseContainer?.current || glassRef.current;
|
|
@@ -1518,6 +1669,11 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1518
1669
|
updateAtomixGlassStyles(wrapperRef?.current || null, glassRef.current, {
|
|
1519
1670
|
mouseOffset: externalMouseOffset || internalMouseOffsetRef.current,
|
|
1520
1671
|
globalMousePosition: externalGlobalMousePosition || internalGlobalMousePositionRef.current,
|
|
1672
|
+
elasticTranslation: elasticTranslationRef.current,
|
|
1673
|
+
elasticVelocity: elasticVelocityRef.current,
|
|
1674
|
+
mouseVelocity: mouseVelocityRef.current,
|
|
1675
|
+
directionalScale: directionalScaleRef.current,
|
|
1676
|
+
scaleBase: isActive && Boolean(onClick) ? .96 : 1,
|
|
1521
1677
|
glassSize: glassSize,
|
|
1522
1678
|
isHovered: isHovered,
|
|
1523
1679
|
isActive: isActive,
|
|
@@ -1527,7 +1683,6 @@ withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: a
|
|
|
1527
1683
|
effectiveWithoutEffects: effectiveWithoutEffects,
|
|
1528
1684
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1529
1685
|
elasticity: elasticity,
|
|
1530
|
-
directionalScale: isActive && Boolean(onClick) ? "scale(0.96)" : "scale(1)",
|
|
1531
1686
|
onClick: onClick,
|
|
1532
1687
|
withLiquidBlur: withLiquidBlur,
|
|
1533
1688
|
blurAmount: blurAmount,
|
|
@@ -2795,7 +2950,7 @@ const PERFORMANCE_PRESET = {
|
|
|
2795
2950
|
"aria-label": ariaLabel,
|
|
2796
2951
|
"aria-describedby": ariaDescribedBy,
|
|
2797
2952
|
"aria-disabled": !(!onClick || !effectiveWithoutEffects) || !onClick && void 0,
|
|
2798
|
-
"aria-pressed": void 0,
|
|
2953
|
+
"aria-pressed": onClick ? isActive : void 0,
|
|
2799
2954
|
onKeyDown: onClick ? handleKeyDown : void 0,
|
|
2800
2955
|
children: [ jsx(AtomixGlassContainer, {
|
|
2801
2956
|
ref: glassRef,
|
|
@@ -3265,26 +3420,25 @@ const Radio = memo((({label: label, checked: checked = !1, onChange: onChange,
|
|
|
3265
3420
|
|
|
3266
3421
|
Radio.displayName = "Radio";
|
|
3267
3422
|
|
|
3268
|
-
const SelectContext = createContext(null), SelectOption = memo((({value: value, children: children, disabled: disabled = !1, className: className = "", style: style}) => {
|
|
3269
|
-
const context = useContext(SelectContext),
|
|
3270
|
-
|
|
3271
|
-
// For simplicity, we use children as label for registration if it's a string.
|
|
3272
|
-
if (useEffect((() => {
|
|
3423
|
+
const SelectContext = createContext(null), SelectOption = memo((({value: value, label: label, children: children, disabled: disabled = !1, className: className = "", style: style}) => {
|
|
3424
|
+
const context = useContext(SelectContext), displayLabel = label || ("string" == typeof children ? children : value);
|
|
3425
|
+
if (useEffect((() => {
|
|
3273
3426
|
if (context) return context.registerOption({
|
|
3274
3427
|
value: value,
|
|
3275
|
-
label:
|
|
3428
|
+
label: displayLabel,
|
|
3276
3429
|
disabled: disabled
|
|
3277
3430
|
}), () => {
|
|
3278
3431
|
context.unregisterOption(value);
|
|
3279
3432
|
};
|
|
3280
|
-
}), [ context, value,
|
|
3433
|
+
}), [ context, value, displayLabel, disabled ]), !context) return console.warn("SelectOption must be used within a Select component"),
|
|
3281
3434
|
null;
|
|
3282
|
-
const {selectedValue: selectedValue, onSelect: onSelect} = context, isSelected = Array.isArray(selectedValue) ? _includesInstanceProperty(selectedValue).call(selectedValue, value) : selectedValue === value;
|
|
3435
|
+
const {selectedValue: selectedValue, onSelect: onSelect, focusedValue: focusedValue, id: id} = context, isSelected = Array.isArray(selectedValue) ? _includesInstanceProperty(selectedValue).call(selectedValue, value) : selectedValue === value;
|
|
3283
3436
|
return jsx("li", {
|
|
3284
|
-
|
|
3437
|
+
id: id ? `${id}-opt-${value}` : void 0,
|
|
3438
|
+
className: `${SELECT_CLASSES_SELECT_ITEM} ${focusedValue === value ? "is-focused" : ""} ${isSelected ? "is-selected" : ""} ${className}`.trim(),
|
|
3285
3439
|
"data-value": value,
|
|
3286
3440
|
onClick: e => {
|
|
3287
|
-
e.preventDefault(), e.stopPropagation(), disabled || onSelect(value,
|
|
3441
|
+
e.preventDefault(), e.stopPropagation(), disabled || onSelect(value, displayLabel);
|
|
3288
3442
|
},
|
|
3289
3443
|
style: style,
|
|
3290
3444
|
role: "option",
|
|
@@ -3304,7 +3458,7 @@ const SelectContext = createContext(null), SelectOption = memo((({value: value
|
|
|
3304
3458
|
tabIndex: -1
|
|
3305
3459
|
}), jsx("div", {
|
|
3306
3460
|
className: "c-select__item-label",
|
|
3307
|
-
children: children
|
|
3461
|
+
children: children || displayLabel
|
|
3308
3462
|
}) ]
|
|
3309
3463
|
})
|
|
3310
3464
|
});
|
|
@@ -3360,18 +3514,18 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3360
3514
|
disabled: disabled,
|
|
3361
3515
|
invalid: invalid,
|
|
3362
3516
|
valid: valid
|
|
3363
|
-
}), [isOpen, setIsOpen] = useState(!1), [
|
|
3517
|
+
}), [isOpen, setIsOpen] = useState(!1), [focusedIndex, setFocusedIndex] = useState(-1), dropdownRef = useRef(null), panelRef = useRef(null), bodyRef = useRef(null), nativeSelectRef = useRef(null), [registeredOptions, setRegisteredOptions] = useState([]), registerOption = useCallback((option => {
|
|
3364
3518
|
setRegisteredOptions((prev => prev.some((o => o.value === option.value)) ? prev : [ ...prev, option ]));
|
|
3365
3519
|
}), []), unregisterOption = useCallback((value => {
|
|
3366
3520
|
setRegisteredOptions((prev => prev.filter((o => o.value !== value))));
|
|
3367
|
-
}), []), hasOptionsProp = options && options.length > 0, activeOptions = hasOptionsProp ? options : registeredOptions
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
if (value) {
|
|
3521
|
+
}), []), hasOptionsProp = options && options.length > 0, activeOptions = hasOptionsProp ? options : registeredOptions, selectedLabel = useMemo((() => {
|
|
3522
|
+
if (multiple && Array.isArray(value)) return 0 === value.length ? placeholder : activeOptions.filter((opt => _includesInstanceProperty(value).call(value, opt.value))).map((opt => opt.label)).join(", ");
|
|
3523
|
+
if (value && "string" == typeof value) {
|
|
3371
3524
|
const selectedOption = activeOptions.find((opt => opt.value === value));
|
|
3372
|
-
selectedOption
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3525
|
+
return selectedOption ? selectedOption.label : placeholder;
|
|
3526
|
+
}
|
|
3527
|
+
return placeholder;
|
|
3528
|
+
}), [ value, activeOptions, placeholder, multiple ]);
|
|
3375
3529
|
// Handle click outside to close dropdown
|
|
3376
3530
|
useEffect((() => {
|
|
3377
3531
|
const handleClickOutside = event => {
|
|
@@ -3384,31 +3538,54 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3384
3538
|
}), []);
|
|
3385
3539
|
// Toggle dropdown
|
|
3386
3540
|
const handleToggle = () => {
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3541
|
+
if (!disabled) {
|
|
3542
|
+
const nextOpen = !isOpen;
|
|
3543
|
+
if (nextOpen && bodyRef.current && panelRef.current)
|
|
3544
|
+
// Set focused index to current selection or first item
|
|
3545
|
+
if (bodyRef.current.style.height = `${panelRef.current.clientHeight}px`, value && !multiple && "string" == typeof value) {
|
|
3546
|
+
const index = activeOptions.findIndex((opt => opt.value === value));
|
|
3547
|
+
setFocusedIndex(index >= 0 ? index : 0);
|
|
3548
|
+
} else if (multiple && Array.isArray(value) && value.length > 0) {
|
|
3549
|
+
const index = activeOptions.findIndex((opt => _includesInstanceProperty(value).call(value, opt.value)));
|
|
3550
|
+
setFocusedIndex(index >= 0 ? index : 0);
|
|
3551
|
+
} else setFocusedIndex(0); else bodyRef.current && (bodyRef.current.style.height = "0px",
|
|
3552
|
+
setFocusedIndex(-1));
|
|
3553
|
+
setIsOpen(nextOpen);
|
|
3400
3554
|
}
|
|
3401
|
-
}
|
|
3555
|
+
}, handleItemClick = useCallback((option => {
|
|
3556
|
+
let newValue;
|
|
3557
|
+
if (multiple) {
|
|
3558
|
+
const currentValues = Array.isArray(value) ? value : value ? [ value ] : [];
|
|
3559
|
+
newValue = _includesInstanceProperty(currentValues).call(currentValues, option.value) ? currentValues.filter((v => v !== option.value)) : [ ...currentValues, option.value ];
|
|
3560
|
+
} else newValue = option.value, setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px");
|
|
3561
|
+
onChange && (
|
|
3562
|
+
// Sync native select before firing onChange
|
|
3563
|
+
nativeSelectRef.current && (multiple && Array.isArray(newValue) ? Array.from(nativeSelectRef.current.options).forEach((opt => {
|
|
3564
|
+
opt.selected = _includesInstanceProperty(newValue).call(newValue, opt.value);
|
|
3565
|
+
})) : "string" == typeof newValue && (nativeSelectRef.current.value = newValue)),
|
|
3566
|
+
onChange({
|
|
3567
|
+
target: {
|
|
3568
|
+
name: name,
|
|
3569
|
+
value: newValue
|
|
3570
|
+
}
|
|
3571
|
+
}));
|
|
3572
|
+
}), [ onChange, name, multiple, value ]), onSelect = useCallback(((val, label) => {
|
|
3402
3573
|
handleItemClick({
|
|
3403
3574
|
value: val,
|
|
3404
3575
|
label: label
|
|
3405
3576
|
});
|
|
3406
|
-
}), [ handleItemClick ]),
|
|
3577
|
+
}), [ handleItemClick ]), focusedValue = useMemo((() => {
|
|
3578
|
+
if (focusedIndex >= 0 && focusedIndex < activeOptions.length) return activeOptions[focusedIndex]?.value;
|
|
3579
|
+
}), [ focusedIndex, activeOptions ]), focusedOptionId = useMemo((() => {
|
|
3580
|
+
if (isOpen && focusedValue) return `${id || "select"}-opt-${focusedValue}`;
|
|
3581
|
+
}), [ isOpen, focusedValue, id ]), contextValue = React.useMemo((() => ({
|
|
3407
3582
|
registerOption: registerOption,
|
|
3408
3583
|
unregisterOption: unregisterOption,
|
|
3409
3584
|
selectedValue: value,
|
|
3410
|
-
onSelect: onSelect
|
|
3411
|
-
|
|
3585
|
+
onSelect: onSelect,
|
|
3586
|
+
focusedValue: focusedValue,
|
|
3587
|
+
id: id || "select"
|
|
3588
|
+
})), [ registerOption, unregisterOption, value, onSelect, focusedValue, id ]), selectContent = jsx(SelectContext.Provider, {
|
|
3412
3589
|
value: contextValue,
|
|
3413
3590
|
children: jsxs("div", {
|
|
3414
3591
|
className: `${selectClass} ${isOpen ? SELECT_CLASSES_IS_OPEN : ""}`,
|
|
@@ -3456,7 +3633,12 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3456
3633
|
if (!disabled) switch (event.key) {
|
|
3457
3634
|
case "Enter":
|
|
3458
3635
|
case " ":
|
|
3459
|
-
event.preventDefault(),
|
|
3636
|
+
if (event.preventDefault(), isOpen) {
|
|
3637
|
+
if (focusedIndex >= 0 && focusedIndex < activeOptions.length) {
|
|
3638
|
+
const option = activeOptions[focusedIndex];
|
|
3639
|
+
option && !option.disabled && handleItemClick(option);
|
|
3640
|
+
}
|
|
3641
|
+
} else handleToggle();
|
|
3460
3642
|
break;
|
|
3461
3643
|
|
|
3462
3644
|
case "Escape":
|
|
@@ -3464,8 +3646,23 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3464
3646
|
break;
|
|
3465
3647
|
|
|
3466
3648
|
case "ArrowDown":
|
|
3649
|
+
event.preventDefault(), isOpen ? setFocusedIndex((prev => prev < activeOptions.length - 1 ? prev + 1 : prev)) : handleToggle();
|
|
3650
|
+
break;
|
|
3651
|
+
|
|
3467
3652
|
case "ArrowUp":
|
|
3468
|
-
|
|
3653
|
+
event.preventDefault(), isOpen ? setFocusedIndex((prev => prev > 0 ? prev - 1 : 0)) : handleToggle();
|
|
3654
|
+
break;
|
|
3655
|
+
|
|
3656
|
+
case "Home":
|
|
3657
|
+
isOpen && (event.preventDefault(), setFocusedIndex(0));
|
|
3658
|
+
break;
|
|
3659
|
+
|
|
3660
|
+
case "End":
|
|
3661
|
+
isOpen && (event.preventDefault(), setFocusedIndex(activeOptions.length - 1));
|
|
3662
|
+
break;
|
|
3663
|
+
|
|
3664
|
+
case "Tab":
|
|
3665
|
+
isOpen && (setIsOpen(!1), bodyRef.current && (bodyRef.current.style.height = "0px"));
|
|
3469
3666
|
}
|
|
3470
3667
|
},
|
|
3471
3668
|
"aria-disabled": disabled,
|
|
@@ -3474,7 +3671,11 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3474
3671
|
"aria-haspopup": "listbox",
|
|
3475
3672
|
"aria-expanded": isOpen,
|
|
3476
3673
|
"aria-controls": id ? `${id}-listbox` : void 0,
|
|
3477
|
-
|
|
3674
|
+
"aria-activedescendant": focusedOptionId,
|
|
3675
|
+
children: jsx("div", {
|
|
3676
|
+
className: "c-select__selected-text",
|
|
3677
|
+
children: selectedLabel
|
|
3678
|
+
})
|
|
3478
3679
|
}), jsx("i", {
|
|
3479
3680
|
className: `${SELECT_CLASSES_ICON_CARET} ${SELECT_CLASSES_TOGGLE_ICON}`
|
|
3480
3681
|
}), jsx("div", {
|
|
@@ -3492,11 +3693,13 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3492
3693
|
id: id ? `${id}-listbox` : void 0,
|
|
3493
3694
|
"aria-labelledby": id,
|
|
3494
3695
|
children: hasOptionsProp ? options.map(((option, index) => jsx("li", {
|
|
3495
|
-
|
|
3696
|
+
id: `${id || "select"}-opt-${option.value}`,
|
|
3697
|
+
className: `${SELECT_CLASSES_SELECT_ITEM} ${focusedIndex === index ? "is-focused" : ""} ${multiple && Array.isArray(value) && _includesInstanceProperty(value).call(value, option.value) || value === option.value ? "is-selected" : ""}`,
|
|
3496
3698
|
"data-value": option.value,
|
|
3497
3699
|
onClick: () => !option.disabled && handleItemClick(option),
|
|
3700
|
+
onMouseEnter: () => setFocusedIndex(index),
|
|
3498
3701
|
role: "option",
|
|
3499
|
-
"aria-selected": value === option.value,
|
|
3702
|
+
"aria-selected": multiple && Array.isArray(value) && _includesInstanceProperty(value).call(value, option.value) || value === option.value,
|
|
3500
3703
|
"aria-disabled": option.disabled,
|
|
3501
3704
|
children: jsxs("label", {
|
|
3502
3705
|
htmlFor: `SelectItem${index}`,
|
|
@@ -3505,7 +3708,7 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3505
3708
|
type: "checkbox",
|
|
3506
3709
|
id: `SelectItem${index}`,
|
|
3507
3710
|
className: "c-checkbox__input c-select__item-input",
|
|
3508
|
-
checked: value === option.value,
|
|
3711
|
+
checked: multiple && Array.isArray(value) && _includesInstanceProperty(value).call(value, option.value) || value === option.value,
|
|
3509
3712
|
readOnly: !0,
|
|
3510
3713
|
disabled: option.disabled
|
|
3511
3714
|
}), jsx("div", {
|
|
@@ -3524,10 +3727,7 @@ const SelectComponentBase = ({options: options, value: value, onChange: onChange
|
|
|
3524
3727
|
// Default glass settings for select components
|
|
3525
3728
|
const defaultGlassProps = {
|
|
3526
3729
|
displacementScale: 60,
|
|
3527
|
-
blurAmount:
|
|
3528
|
-
saturation: 180,
|
|
3529
|
-
aberrationIntensity: .2,
|
|
3530
|
-
borderRadius: 12,
|
|
3730
|
+
blurAmount: 10,
|
|
3531
3731
|
mode: "shader"
|
|
3532
3732
|
}, glassProps = !0 === glass ? defaultGlassProps : {
|
|
3533
3733
|
...defaultGlassProps,
|