@hero-design/rn 8.108.1 → 8.108.3-alpha.0

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.
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  deepCompareValue,
3
+ dimHex,
3
4
  hexToRgba,
4
5
  omit,
5
6
  pick,
@@ -256,3 +257,73 @@ describe('hexToRgba', () => {
256
257
  });
257
258
  });
258
259
  });
260
+
261
+ describe('dimHex', () => {
262
+ it.each`
263
+ hex | surface | amount | expected
264
+ ${'#FF0000'} | ${'#FFFFFF'} | ${0.5} | ${'#ff8080'}
265
+ ${'#000000'} | ${'#FFFFFF'} | ${0.5} | ${'#808080'}
266
+ ${'#FF0000'} | ${'#FFFFFF'} | ${0} | ${'#ff0000'}
267
+ ${'#FF0000'} | ${'#FFFFFF'} | ${1} | ${'#ffffff'}
268
+ ${'FF0000'} | ${'FFFFFF'} | ${0.5} | ${'#ff8080'}
269
+ ${'#fff'} | ${'#000'} | ${0.5} | ${'#808080'}
270
+ ${'fff'} | ${'000'} | ${0.5} | ${'#808080'}
271
+ `(
272
+ 'should dim hex "$hex" with surface "$surface" by amount $amount to "$expected"',
273
+ ({ hex, surface, amount, expected }) => {
274
+ expect(dimHex(hex, surface, amount)).toBe(expected);
275
+ }
276
+ );
277
+
278
+ it('should use default parameters', () => {
279
+ expect(dimHex('#000000', '#ffffff')).toBe('#999999');
280
+ });
281
+
282
+ it('should throw error for invalid input types', () => {
283
+ // @ts-expect-error: Invalid param type
284
+ expect(() => dimHex(123, '#fff', 0.5)).toThrow(
285
+ 'dimHex: hex and surface must be strings and amount must be a number'
286
+ );
287
+ // @ts-expect-error: Invalid param type
288
+ expect(() => dimHex('#fff', 123, 0.5)).toThrow(
289
+ 'dimHex: hex and surface must be strings and amount must be a number'
290
+ );
291
+ // @ts-expect-error: Invalid param type
292
+ expect(() => dimHex('#fff', '#fff', '0.5')).toThrow(
293
+ 'dimHex: hex and surface must be strings and amount must be a number'
294
+ );
295
+ });
296
+
297
+ it('should throw error for amount values outside 0-1 range', () => {
298
+ expect(() => dimHex('#fff', '#fff', -0.1)).toThrow(
299
+ 'dimHex: amount must be between 0 and 1'
300
+ );
301
+ expect(() => dimHex('#fff', '#fff', 1.1)).toThrow(
302
+ 'dimHex: amount must be between 0 and 1'
303
+ );
304
+ });
305
+
306
+ it('should throw error for invalid hex formats', () => {
307
+ expect(() => dimHex('invalid', '#fff', 0.5)).toThrow(
308
+ 'dimHex: hex must be a valid 3 or 6 character hex color'
309
+ );
310
+ expect(() => dimHex('#gggggg', '#fff', 0.5)).toThrow(
311
+ 'dimHex: hex must be a valid 3 or 6 character hex color'
312
+ );
313
+ expect(() => dimHex('#ff', '#fff', 0.5)).toThrow(
314
+ 'dimHex: hex must be a valid 3 or 6 character hex color'
315
+ );
316
+ });
317
+
318
+ it('should throw error for invalid surface formats', () => {
319
+ expect(() => dimHex('#fff', 'invalid', 0.5)).toThrow(
320
+ 'dimHex: surface must be a valid 3 or 6 character hex color'
321
+ );
322
+ expect(() => dimHex('#fff', '#gggggg', 0.5)).toThrow(
323
+ 'dimHex: surface must be a valid 3 or 6 character hex color'
324
+ );
325
+ expect(() => dimHex('#fff', '#ff', 0.5)).toThrow(
326
+ 'dimHex: surface must be a valid 3 or 6 character hex color'
327
+ );
328
+ });
329
+ });
@@ -68,6 +68,85 @@ export function hexToRgba(hex: string, a: number) {
68
68
  return `rgba(${r},${g},${b},${a})`;
69
69
  }
70
70
 
71
+ /**
72
+ * Dim a hex color by blending it with a surface color
73
+ * @param hex - The hex color to dim (3 or 6 characters, with or without #)
74
+ * @param surface - The surface color to blend with.
75
+ * @param amount - The amount of dimming (0 = original color, 1 = fully surface color)
76
+ * @returns The dimmed hex color
77
+ */
78
+ const DEFAULT_DIM_AMOUNT = 0.6;
79
+ export function dimHex(
80
+ hex: string,
81
+ surface: string,
82
+ amount = DEFAULT_DIM_AMOUNT
83
+ ): string {
84
+ // Validate inputs
85
+ if (
86
+ typeof hex !== 'string' ||
87
+ typeof surface !== 'string' ||
88
+ typeof amount !== 'number'
89
+ ) {
90
+ throw new Error(
91
+ 'dimHex: hex and surface must be strings and amount must be a number'
92
+ );
93
+ }
94
+
95
+ if (amount < 0 || amount > 1) {
96
+ throw new Error('dimHex: amount must be between 0 and 1');
97
+ }
98
+
99
+ // Remove # if present and validate hex format
100
+ const cleanHex = hex.replace(/^#/, '');
101
+ const cleanSurface = surface.replace(/^#/, '');
102
+
103
+ if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanHex)) {
104
+ throw new Error('dimHex: hex must be a valid 3 or 6 character hex color');
105
+ }
106
+
107
+ if (!/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(cleanSurface)) {
108
+ throw new Error(
109
+ 'dimHex: surface must be a valid 3 or 6 character hex color'
110
+ );
111
+ }
112
+
113
+ // Handle 3-character hex codes (e.g., #fff -> #ffffff)
114
+ const normalizedHex =
115
+ cleanHex.length === 3
116
+ ? cleanHex
117
+ .split('')
118
+ .map((char) => char + char)
119
+ .join('')
120
+ : cleanHex;
121
+
122
+ const normalizedSurface =
123
+ cleanSurface.length === 3
124
+ ? cleanSurface
125
+ .split('')
126
+ .map((char) => char + char)
127
+ .join('')
128
+ : cleanSurface;
129
+
130
+ // Parse hex values
131
+ const r = parseInt(normalizedHex.substring(0, 2), 16);
132
+ const g = parseInt(normalizedHex.substring(2, 4), 16);
133
+ const b = parseInt(normalizedHex.substring(4, 6), 16);
134
+
135
+ const sr = parseInt(normalizedSurface.substring(0, 2), 16);
136
+ const sg = parseInt(normalizedSurface.substring(2, 4), 16);
137
+ const sb = parseInt(normalizedSurface.substring(4, 6), 16);
138
+
139
+ // Linear interpolation between colors
140
+ const lerp = (c: number, s: number): number =>
141
+ Math.round(c * (1 - amount) + s * amount);
142
+
143
+ const rr = lerp(r, sr).toString(16).padStart(2, '0');
144
+ const gg = lerp(g, sg).toString(16).padStart(2, '0');
145
+ const bb = lerp(b, sb).toString(16).padStart(2, '0');
146
+
147
+ return `#${rr}${gg}${bb}`;
148
+ }
149
+
71
150
  export const deepCompareValue = <V>(a: V, b: V): boolean => {
72
151
  // Handle strict equality first (handles primitives, null, undefined)
73
152
  if (a === b) return true;