@hero-design/rn 8.108.0 → 8.108.1
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/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +8 -0
- package/es/index.js +23 -18
- package/lib/index.js +23 -18
- package/package.json +1 -1
- package/src/components/FAB/ActionGroup/__tests__/__snapshots__/index.spec.tsx.snap +0 -1
- package/src/components/FAB/ActionGroup/index.tsx +5 -12
- package/src/components/MapPin/__tests__/__snapshots__/Focussed.spec.tsx.snap +1 -1
- package/src/utils/__tests__/helpers.spec.ts +142 -0
- package/src/utils/helpers.ts +34 -5
- package/stats/8.108.0/rn-stats.html +3 -1
- package/stats/8.108.1/rn-stats.html +4844 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(node:
|
|
1
|
+
(node:3310) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
|
|
2
2
|
(Use `node --trace-warnings ...` to show where the warning was created)
|
|
3
3
|
[36m
|
|
4
4
|
[1msrc/index.ts[22m → [1mlib/index.js, es/index.js[22m...[39m
|
|
@@ -15,9 +15,9 @@ node_modules/d3-selection/src/selection/index.js -> node_modules/d3-selection/sr
|
|
|
15
15
|
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~[0m
|
|
16
16
|
[39m
|
|
17
17
|
[1m[33m(!) [plugin node-resolve] preferring built-in module 'events' over local alternative at '/home/runner/work/hero-design/hero-design/node_modules/events/events.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning.or passing a function to 'preferBuiltins' to provide more fine-grained control over which built-in modules to prefer.[39m[22m
|
|
18
|
-
[32mcreated [1mlib/index.js, es/index.js[22m in [1m1m
|
|
18
|
+
[32mcreated [1mlib/index.js, es/index.js[22m in [1m1m 13.9s[22m[39m
|
|
19
19
|
[36m
|
|
20
20
|
[1m/home/runner/work/hero-design/hero-design/packages/rn/src/locales/en_AU.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/en_CA.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/index.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/types.ts[22m → [1m., .[22m...[39m
|
|
21
21
|
[1m[33m(!) Generated empty chunks[39m[22m
|
|
22
22
|
"locales/types" and "locales/types"
|
|
23
|
-
[32mcreated [1m., .[22m in [1m20.
|
|
23
|
+
[32mcreated [1m., .[22m in [1m20.4s[22m[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @hero-design/rn
|
|
2
2
|
|
|
3
|
+
## 8.108.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#4210](https://github.com/Thinkei/hero-design/pull/4210) [`d0856e4f74472a83c5227e88638ad9631a7fe8f5`](https://github.com/Thinkei/hero-design/commit/d0856e4f74472a83c5227e88638ad9631a7fe8f5) Thanks [@vinhphan-eh](https://github.com/vinhphan-eh)! - [FAB.ActionGroup] Fix double circle issue
|
|
8
|
+
|
|
9
|
+
- [#4211](https://github.com/Thinkei/hero-design/pull/4211) [`9af53ac4bda22015a04ca404ae2a85d9bfb11ac2`](https://github.com/Thinkei/hero-design/commit/9af53ac4bda22015a04ca404ae2a85d9bfb11ac2) Thanks [@vinhphan-eh](https://github.com/vinhphan-eh)! - [Progress] Update colors to match design
|
|
10
|
+
|
|
3
11
|
## 8.108.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/es/index.js
CHANGED
|
@@ -9430,14 +9430,26 @@ function omit(keys, obj) {
|
|
|
9430
9430
|
return result;
|
|
9431
9431
|
}
|
|
9432
9432
|
function hexToRgba(hex, a) {
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9433
|
+
// Validate inputs
|
|
9434
|
+
if (typeof hex !== 'string' || typeof a !== 'number') {
|
|
9435
|
+
throw new Error('hexToRgba: hex must be a string and alpha must be a number');
|
|
9436
|
+
}
|
|
9437
|
+
if (a < 0 || a > 1) {
|
|
9438
|
+
throw new Error('hexToRgba: alpha must be between 0 and 1');
|
|
9439
|
+
}
|
|
9440
|
+
// Remove # if present and validate hex format
|
|
9441
|
+
var cleanHex = hex.replace(/^#/, '');
|
|
9442
|
+
if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
|
|
9443
|
+
throw new Error('hexToRgba: hex must be a valid 3 or 6 character hex color');
|
|
9444
|
+
}
|
|
9445
|
+
// Handle 3-character hex codes (e.g., #fff -> #ffffff)
|
|
9446
|
+
var normalizedHex = cleanHex.length === 3 ? cleanHex.split('').map(function (_char) {
|
|
9447
|
+
return _char + _char;
|
|
9448
|
+
}).join('') : cleanHex;
|
|
9449
|
+
// Parse hex values
|
|
9450
|
+
var r = parseInt(normalizedHex.substring(0, 2), 16);
|
|
9451
|
+
var g = parseInt(normalizedHex.substring(2, 4), 16);
|
|
9452
|
+
var b = parseInt(normalizedHex.substring(4, 6), 16);
|
|
9441
9453
|
return "rgba(".concat(r, ",").concat(g, ",").concat(b, ",").concat(a, ")");
|
|
9442
9454
|
}
|
|
9443
9455
|
var _deepCompareValue = function deepCompareValue(a, b) {
|
|
@@ -9500,8 +9512,8 @@ var useKeyboard = function useKeyboard() {
|
|
|
9500
9512
|
};
|
|
9501
9513
|
};
|
|
9502
9514
|
var transformKebabCaseToCamelCase = function transformKebabCaseToCamelCase(string) {
|
|
9503
|
-
return string.replace(/-([a-z0-9])/g, function (_,
|
|
9504
|
-
return /[a-z]/.test(
|
|
9515
|
+
return string.replace(/-([a-z0-9])/g, function (_, _char2) {
|
|
9516
|
+
return /[a-z]/.test(_char2) ? _char2.toUpperCase() : _char2;
|
|
9505
9517
|
});
|
|
9506
9518
|
};
|
|
9507
9519
|
|
|
@@ -23835,7 +23847,6 @@ var ActionGroup = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
23835
23847
|
_ref$supportedOrienta = _ref.supportedOrientations,
|
|
23836
23848
|
supportedOrientations = _ref$supportedOrienta === void 0 ? ['portrait'] : _ref$supportedOrienta;
|
|
23837
23849
|
useDeprecation("FAB.ActionGroup's headerTitle prop will be removed in the next major release. Please remove it.", headerTitle !== undefined);
|
|
23838
|
-
var theme = useTheme();
|
|
23839
23850
|
var fabRef = useRef(null);
|
|
23840
23851
|
var animatedValue = useRef(new Animated.Value(active ? 1 : 0));
|
|
23841
23852
|
React__default.useImperativeHandle(ref, function () {
|
|
@@ -23914,13 +23925,7 @@ var ActionGroup = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
23914
23925
|
index: active ? index : items.length - index,
|
|
23915
23926
|
active: active
|
|
23916
23927
|
}));
|
|
23917
|
-
}))), active && /*#__PURE__*/React__default.createElement(StyledFAB$1
|
|
23918
|
-
// This FAB is moved up a bit compared to the original FAB,
|
|
23919
|
-
// set marginBottom to negative value to compensate for it
|
|
23920
|
-
, {
|
|
23921
|
-
style: {
|
|
23922
|
-
marginBottom: -theme.space.xxsmall
|
|
23923
|
-
},
|
|
23928
|
+
}))), active && /*#__PURE__*/React__default.createElement(StyledFAB$1, {
|
|
23924
23929
|
key: "fab-in-portal",
|
|
23925
23930
|
testID: "fab-in-portal",
|
|
23926
23931
|
icon: fabIcon,
|
package/lib/index.js
CHANGED
|
@@ -9459,14 +9459,26 @@ function omit(keys, obj) {
|
|
|
9459
9459
|
return result;
|
|
9460
9460
|
}
|
|
9461
9461
|
function hexToRgba(hex, a) {
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9462
|
+
// Validate inputs
|
|
9463
|
+
if (typeof hex !== 'string' || typeof a !== 'number') {
|
|
9464
|
+
throw new Error('hexToRgba: hex must be a string and alpha must be a number');
|
|
9465
|
+
}
|
|
9466
|
+
if (a < 0 || a > 1) {
|
|
9467
|
+
throw new Error('hexToRgba: alpha must be between 0 and 1');
|
|
9468
|
+
}
|
|
9469
|
+
// Remove # if present and validate hex format
|
|
9470
|
+
var cleanHex = hex.replace(/^#/, '');
|
|
9471
|
+
if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
|
|
9472
|
+
throw new Error('hexToRgba: hex must be a valid 3 or 6 character hex color');
|
|
9473
|
+
}
|
|
9474
|
+
// Handle 3-character hex codes (e.g., #fff -> #ffffff)
|
|
9475
|
+
var normalizedHex = cleanHex.length === 3 ? cleanHex.split('').map(function (_char) {
|
|
9476
|
+
return _char + _char;
|
|
9477
|
+
}).join('') : cleanHex;
|
|
9478
|
+
// Parse hex values
|
|
9479
|
+
var r = parseInt(normalizedHex.substring(0, 2), 16);
|
|
9480
|
+
var g = parseInt(normalizedHex.substring(2, 4), 16);
|
|
9481
|
+
var b = parseInt(normalizedHex.substring(4, 6), 16);
|
|
9470
9482
|
return "rgba(".concat(r, ",").concat(g, ",").concat(b, ",").concat(a, ")");
|
|
9471
9483
|
}
|
|
9472
9484
|
var _deepCompareValue = function deepCompareValue(a, b) {
|
|
@@ -9529,8 +9541,8 @@ var useKeyboard = function useKeyboard() {
|
|
|
9529
9541
|
};
|
|
9530
9542
|
};
|
|
9531
9543
|
var transformKebabCaseToCamelCase = function transformKebabCaseToCamelCase(string) {
|
|
9532
|
-
return string.replace(/-([a-z0-9])/g, function (_,
|
|
9533
|
-
return /[a-z]/.test(
|
|
9544
|
+
return string.replace(/-([a-z0-9])/g, function (_, _char2) {
|
|
9545
|
+
return /[a-z]/.test(_char2) ? _char2.toUpperCase() : _char2;
|
|
9534
9546
|
});
|
|
9535
9547
|
};
|
|
9536
9548
|
|
|
@@ -23864,7 +23876,6 @@ var ActionGroup = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
23864
23876
|
_ref$supportedOrienta = _ref.supportedOrientations,
|
|
23865
23877
|
supportedOrientations = _ref$supportedOrienta === void 0 ? ['portrait'] : _ref$supportedOrienta;
|
|
23866
23878
|
useDeprecation("FAB.ActionGroup's headerTitle prop will be removed in the next major release. Please remove it.", headerTitle !== undefined);
|
|
23867
|
-
var theme = useTheme();
|
|
23868
23879
|
var fabRef = React.useRef(null);
|
|
23869
23880
|
var animatedValue = React.useRef(new reactNative.Animated.Value(active ? 1 : 0));
|
|
23870
23881
|
React__namespace.default.useImperativeHandle(ref, function () {
|
|
@@ -23943,13 +23954,7 @@ var ActionGroup = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
|
|
|
23943
23954
|
index: active ? index : items.length - index,
|
|
23944
23955
|
active: active
|
|
23945
23956
|
}));
|
|
23946
|
-
}))), active && /*#__PURE__*/React__namespace.default.createElement(StyledFAB$1
|
|
23947
|
-
// This FAB is moved up a bit compared to the original FAB,
|
|
23948
|
-
// set marginBottom to negative value to compensate for it
|
|
23949
|
-
, {
|
|
23950
|
-
style: {
|
|
23951
|
-
marginBottom: -theme.space.xxsmall
|
|
23952
|
-
},
|
|
23957
|
+
}))), active && /*#__PURE__*/React__namespace.default.createElement(StyledFAB$1, {
|
|
23953
23958
|
key: "fab-in-portal",
|
|
23954
23959
|
testID: "fab-in-portal",
|
|
23955
23960
|
icon: fabIcon,
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React, { forwardRef, useRef } from 'react';
|
|
2
2
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
-
import { Animated,
|
|
3
|
+
import { Animated, Modal, Platform } from 'react-native';
|
|
4
|
+
import { useDeprecation } from '../../../utils/hooks';
|
|
5
|
+
import Box from '../../Box';
|
|
4
6
|
import type { IconName } from '../../Icon';
|
|
7
|
+
import Portal from '../../Portal';
|
|
8
|
+
import type { FABHandles } from '../FAB';
|
|
5
9
|
import type { ActionItemProps } from './ActionItem';
|
|
6
10
|
import ActionItem from './ActionItem';
|
|
7
11
|
import {
|
|
@@ -12,11 +16,6 @@ import {
|
|
|
12
16
|
StyledContainerInModal,
|
|
13
17
|
StyledFAB,
|
|
14
18
|
} from './StyledActionGroup';
|
|
15
|
-
import Portal from '../../Portal';
|
|
16
|
-
import Box from '../../Box';
|
|
17
|
-
import type { FABHandles } from '../FAB';
|
|
18
|
-
import { useDeprecation } from '../../../utils/hooks';
|
|
19
|
-
import { useTheme } from '../../../theme';
|
|
20
19
|
|
|
21
20
|
export type ActionGroupHandles = {
|
|
22
21
|
showFAB: () => void;
|
|
@@ -96,7 +95,6 @@ const ActionGroup = forwardRef<ActionGroupHandles, ActionGroupProps>(
|
|
|
96
95
|
headerTitle !== undefined
|
|
97
96
|
);
|
|
98
97
|
|
|
99
|
-
const theme = useTheme();
|
|
100
98
|
const fabRef = useRef<FABHandles>(null);
|
|
101
99
|
const animatedValue = useRef<Animated.Value>(
|
|
102
100
|
new Animated.Value(active ? 1 : 0)
|
|
@@ -185,11 +183,6 @@ const ActionGroup = forwardRef<ActionGroupHandles, ActionGroupProps>(
|
|
|
185
183
|
|
|
186
184
|
{active && (
|
|
187
185
|
<StyledFAB
|
|
188
|
-
// This FAB is moved up a bit compared to the original FAB,
|
|
189
|
-
// set marginBottom to negative value to compensate for it
|
|
190
|
-
style={{
|
|
191
|
-
marginBottom: -theme.space.xxsmall,
|
|
192
|
-
}}
|
|
193
186
|
key="fab-in-portal"
|
|
194
187
|
testID="fab-in-portal"
|
|
195
188
|
icon={fabIcon}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deepCompareValue,
|
|
3
|
+
hexToRgba,
|
|
3
4
|
omit,
|
|
4
5
|
pick,
|
|
5
6
|
transformKebabCaseToCamelCase,
|
|
@@ -114,3 +115,144 @@ describe('transformKebabCaseToCamelCase', () => {
|
|
|
114
115
|
}
|
|
115
116
|
);
|
|
116
117
|
});
|
|
118
|
+
|
|
119
|
+
describe('hexToRgba', () => {
|
|
120
|
+
it.each`
|
|
121
|
+
hex | alpha | expected
|
|
122
|
+
${'#FF0000'} | ${1} | ${'rgba(255,0,0,1)'}
|
|
123
|
+
${'#00FF00'} | ${0.5} | ${'rgba(0,255,0,0.5)'}
|
|
124
|
+
${'#0000FF'} | ${0} | ${'rgba(0,0,255,0)'}
|
|
125
|
+
${'#FFFFFF'} | ${0.8} | ${'rgba(255,255,255,0.8)'}
|
|
126
|
+
${'#000000'} | ${0.3} | ${'rgba(0,0,0,0.3)'}
|
|
127
|
+
${'#123456'} | ${0.7} | ${'rgba(18,52,86,0.7)'}
|
|
128
|
+
${'#ABCDEF'} | ${0.2} | ${'rgba(171,205,239,0.2)'}
|
|
129
|
+
${'#FF0000'} | ${0.25} | ${'rgba(255,0,0,0.25)'}
|
|
130
|
+
`(
|
|
131
|
+
'should convert hex "$hex" with alpha $alpha to "$expected"',
|
|
132
|
+
({ hex, alpha, expected }) => {
|
|
133
|
+
expect(hexToRgba(hex, alpha)).toBe(expected);
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
it.each`
|
|
138
|
+
hex | alpha | expected
|
|
139
|
+
${'FF0000'} | ${1} | ${'rgba(255,0,0,1)'}
|
|
140
|
+
${'00FF00'} | ${0.5} | ${'rgba(0,255,0,0.5)'}
|
|
141
|
+
${'0000FF'} | ${0} | ${'rgba(0,0,255,0)'}
|
|
142
|
+
${'FFFFFF'} | ${0.8} | ${'rgba(255,255,255,0.8)'}
|
|
143
|
+
${'000000'} | ${0.3} | ${'rgba(0,0,0,0.3)'}
|
|
144
|
+
${'123456'} | ${0.7} | ${'rgba(18,52,86,0.7)'}
|
|
145
|
+
${'ABCDEF'} | ${0.2} | ${'rgba(171,205,239,0.2)'}
|
|
146
|
+
`(
|
|
147
|
+
'should convert hex without # "$hex" with alpha $alpha to "$expected"',
|
|
148
|
+
({ hex, alpha, expected }) => {
|
|
149
|
+
expect(hexToRgba(hex, alpha)).toBe(expected);
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
it('should handle lowercase hex values', () => {
|
|
154
|
+
expect(hexToRgba('#ff0000', 1)).toBe('rgba(255,0,0,1)');
|
|
155
|
+
expect(hexToRgba('#abcdef', 0.5)).toBe('rgba(171,205,239,0.5)');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should handle mixed case hex values', () => {
|
|
159
|
+
expect(hexToRgba('#Ff0000', 1)).toBe('rgba(255,0,0,1)');
|
|
160
|
+
expect(hexToRgba('#AbCdEf', 0.5)).toBe('rgba(171,205,239,0.5)');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should handle edge case alpha values', () => {
|
|
164
|
+
expect(hexToRgba('#000000', 0)).toBe('rgba(0,0,0,0)');
|
|
165
|
+
expect(hexToRgba('#FFFFFF', 1)).toBe('rgba(255,255,255,1)');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should handle decimal alpha values', () => {
|
|
169
|
+
expect(hexToRgba('#FF0000', 0.123)).toBe('rgba(255,0,0,0.123)');
|
|
170
|
+
expect(hexToRgba('#00FF00', 0.999)).toBe('rgba(0,255,0,0.999)');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('3-character hex codes', () => {
|
|
174
|
+
it.each`
|
|
175
|
+
hex | alpha | expected
|
|
176
|
+
${'#fff'} | ${1} | ${'rgba(255,255,255,1)'}
|
|
177
|
+
${'#000'} | ${0.5} | ${'rgba(0,0,0,0.5)'}
|
|
178
|
+
${'#f00'} | ${0.8} | ${'rgba(255,0,0,0.8)'}
|
|
179
|
+
${'#0f0'} | ${0.3} | ${'rgba(0,255,0,0.3)'}
|
|
180
|
+
${'#00f'} | ${0.7} | ${'rgba(0,0,255,0.7)'}
|
|
181
|
+
${'#abc'} | ${0.2} | ${'rgba(170,187,204,0.2)'}
|
|
182
|
+
${'#123'} | ${0.25} | ${'rgba(17,34,51,0.25)'}
|
|
183
|
+
`(
|
|
184
|
+
'should convert 3-char hex "$hex" with alpha $alpha to "$expected"',
|
|
185
|
+
({ hex, alpha, expected }) => {
|
|
186
|
+
expect(hexToRgba(hex, alpha)).toBe(expected);
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
it.each`
|
|
191
|
+
hex | alpha | expected
|
|
192
|
+
${'fff'} | ${1} | ${'rgba(255,255,255,1)'}
|
|
193
|
+
${'000'} | ${0.5} | ${'rgba(0,0,0,0.5)'}
|
|
194
|
+
${'f00'} | ${0.8} | ${'rgba(255,0,0,0.8)'}
|
|
195
|
+
${'0f0'} | ${0.3} | ${'rgba(0,255,0,0.3)'}
|
|
196
|
+
${'00f'} | ${0.7} | ${'rgba(0,0,255,0.7)'}
|
|
197
|
+
${'abc'} | ${0.2} | ${'rgba(170,187,204,0.2)'}
|
|
198
|
+
`(
|
|
199
|
+
'should convert 3-char hex without # "$hex" with alpha $alpha to "$expected"',
|
|
200
|
+
({ hex, alpha, expected }) => {
|
|
201
|
+
expect(hexToRgba(hex, alpha)).toBe(expected);
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
it('should handle lowercase 3-char hex values', () => {
|
|
206
|
+
expect(hexToRgba('#fff', 1)).toBe('rgba(255,255,255,1)');
|
|
207
|
+
expect(hexToRgba('#abc', 0.5)).toBe('rgba(170,187,204,0.5)');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should handle mixed case 3-char hex values', () => {
|
|
211
|
+
expect(hexToRgba('#Ff0', 1)).toBe('rgba(255,255,0,1)');
|
|
212
|
+
expect(hexToRgba('#AbC', 0.5)).toBe('rgba(170,187,204,0.5)');
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe('validation', () => {
|
|
217
|
+
it('should throw error for invalid input types', () => {
|
|
218
|
+
expect(() => hexToRgba(123 as any, 0.5)).toThrow(
|
|
219
|
+
'hexToRgba: hex must be a string and alpha must be a number'
|
|
220
|
+
);
|
|
221
|
+
expect(() => hexToRgba('#fff', '0.5' as any)).toThrow(
|
|
222
|
+
'hexToRgba: hex must be a string and alpha must be a number'
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should throw error for alpha values outside 0-1 range', () => {
|
|
227
|
+
expect(() => hexToRgba('#fff', -0.1)).toThrow(
|
|
228
|
+
'hexToRgba: alpha must be between 0 and 1'
|
|
229
|
+
);
|
|
230
|
+
expect(() => hexToRgba('#fff', 1.1)).toThrow(
|
|
231
|
+
'hexToRgba: alpha must be between 0 and 1'
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('should throw error for invalid hex formats', () => {
|
|
236
|
+
expect(() => hexToRgba('invalid', 0.5)).toThrow(
|
|
237
|
+
'hexToRgba: hex must be a valid 3 or 6 character hex color'
|
|
238
|
+
);
|
|
239
|
+
expect(() => hexToRgba('#gggggg', 0.5)).toThrow(
|
|
240
|
+
'hexToRgba: hex must be a valid 3 or 6 character hex color'
|
|
241
|
+
);
|
|
242
|
+
expect(() => hexToRgba('#ff', 0.5)).toThrow(
|
|
243
|
+
'hexToRgba: hex must be a valid 3 or 6 character hex color'
|
|
244
|
+
);
|
|
245
|
+
expect(() => hexToRgba('#ffffff00', 0.5)).toThrow(
|
|
246
|
+
'hexToRgba: hex must be a valid 3 or 6 character hex color'
|
|
247
|
+
);
|
|
248
|
+
expect(() => hexToRgba('', 0.5)).toThrow(
|
|
249
|
+
'hexToRgba: hex must be a valid 3 or 6 character hex color'
|
|
250
|
+
);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should accept valid alpha boundary values', () => {
|
|
254
|
+
expect(() => hexToRgba('#fff', 0)).not.toThrow();
|
|
255
|
+
expect(() => hexToRgba('#fff', 1)).not.toThrow();
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
});
|
package/src/utils/helpers.ts
CHANGED
|
@@ -31,11 +31,40 @@ export function omit<O, T extends keyof O>(keys: T[], obj: O): Omit<O, T> {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function hexToRgba(hex: string, a: number) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
// Validate inputs
|
|
35
|
+
if (typeof hex !== 'string' || typeof a !== 'number') {
|
|
36
|
+
throw new Error(
|
|
37
|
+
'hexToRgba: hex must be a string and alpha must be a number'
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (a < 0 || a > 1) {
|
|
42
|
+
throw new Error('hexToRgba: alpha must be between 0 and 1');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Remove # if present and validate hex format
|
|
46
|
+
const cleanHex = hex.replace(/^#/, '');
|
|
47
|
+
|
|
48
|
+
if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
'hexToRgba: hex must be a valid 3 or 6 character hex color'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Handle 3-character hex codes (e.g., #fff -> #ffffff)
|
|
55
|
+
const normalizedHex =
|
|
56
|
+
cleanHex.length === 3
|
|
57
|
+
? cleanHex
|
|
58
|
+
.split('')
|
|
59
|
+
.map((char) => char + char)
|
|
60
|
+
.join('')
|
|
61
|
+
: cleanHex;
|
|
62
|
+
|
|
63
|
+
// Parse hex values
|
|
64
|
+
const r = parseInt(normalizedHex.substring(0, 2), 16);
|
|
65
|
+
const g = parseInt(normalizedHex.substring(2, 4), 16);
|
|
66
|
+
const b = parseInt(normalizedHex.substring(4, 6), 16);
|
|
67
|
+
|
|
39
68
|
return `rgba(${r},${g},${b},${a})`;
|
|
40
69
|
}
|
|
41
70
|
|