Last active
January 15, 2026 17:07
-
-
Save samermurad/54ca688b977632350c75417aa80485b0 to your computer and use it in GitHub Desktop.
Revisions
-
samermurad revised this gist
Jan 15, 2026 . 1 changed file with 22 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,10 +1,4 @@ class Color implements Iterable<any>{ private _hex: string; private _rgba: RGBA; @@ -95,6 +89,7 @@ class Color { if (component <= 0) component = 0; else if (component <= 1) component = component * 255.0 else if (component > 1) component = Math.min(component, 255); component = Math.round(component); // add it to string as hex str += component.toString(16).padStart(2, '0'); } @@ -108,4 +103,24 @@ class Color { toString() { return this._hex; } [Symbol.iterator](): Iterator<number> { let currentIndex = 0; const rgba = this.rgba; const size = rgba.length; return { next(): IteratorResult<number> { if (currentIndex < size) { const nextData = currentIndex++ return { value: rgba[nextData], done: false, } } else { return { done: true, value: undefined }; } } } } } -
samermurad revised this gist
Jan 15, 2026 . 1 changed file with 19 additions and 21 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,35 +1,33 @@ try { console.log(new Color('#f')); } catch (error) { console.log(error.message); } try { console.log(new Color('#rr')); } catch (error) { console.log(error.message); } console.log(new Color('#ff')); console.log(new Color('#ffa')); console.log(new Color('#f01a')); console.log(new Color('#fd01b')); console.log(new Color('#68ff46')); console.log(new Color('#405c91a')); console.log(new Color('#405c91aa')); try { console.log(new Color('#405c91aae')); } catch (error) { console.log(error.message); } console.log(new Color('#ff00c3')); console.log(new Color('#ff00c3a')); console.log(new Color('#ff00c3a')); console.log(new Color('#ff00c3a')); console.log(new Color([1, 0, 0.7647058823529411, 0.6666666666666666])); console.log(new Color([1, 0, 0.7647058823529411])); console.log(new Color([255, 0, 255 * 0.7647058823529411, 255 * 0.6666666666666666])); console.log(new Color(0xff00c3a)); console.log(new Color(0xffaacca)); -
samermurad created this gist
Jan 15, 2026 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,111 @@ type HexString = `#${number}`; type RGB = [number, number, number]; type RGBA = [number, number, number, number]; type ColorInput = HexString | string | number | RGB | RGBA; // | {r: number, g: number; b: number, alpha?: number}; class Color { private _hex: string; private _rgba: RGBA; get hex(): string { return this._hex; } get rgba(): RGBA { return this._rgba } constructor(input: ColorInput) { if (input === undefined) throw new Error('ColorInput must be a supported type: (HexString/HexNumber/RGB/RGBA/)'); if (typeof input === 'string') { this._hex = Color.normalizeHexString(input); this._rgba = Color.hexStringToComponents(this._hex) } else if (typeof input === 'number') { this._rgba = Color.hexNumberToComponents(input); this._hex = Color.componentsToHexString(this._rgba); } else if (Array.isArray(input)) { if (!(input.length === 4 || input.length === 3)) throw new Error('must use RGB | RGBA as array input'); this._hex = Color.componentsToHexString(input); this._rgba = Color.hexStringToComponents(this._hex); } else if (typeof input === 'object') { // defaults in invalid pink color const { r = 1, g = 0, b = 0.7647058823529411, a = 1 } = input; this._hex = Color.componentsToHexString([r,g,b,a]); this._rgba = Color.hexStringToComponents(this._hex) } else { this._hex = Color.normalizeHexString('#ff00c3a'); this._rgba = Color.hexStringToComponents(this._hex); } } static normalizeHexString(hex: string): HexString { const hexNoPound = hex.replace('#', ''); if (hexNoPound.length < 2 || hexNoPound.length > 8) throw new Error('Invalid hex value: ' + hex); let fixHex = ''; switch (hexNoPound.length) { case 2: fixHex = `${hexNoPound}${hexNoPound}${hexNoPound}`; break; case 3: // 0xffff => 0xff_ff_ff case 4: // 0xffff => 0xff_ff_ff_ff fixHex = `${hexNoPound.split('').map(f => `${f}${f}`).join('')}`; break; case 5: {// 0xf_f_f_f_f const [r1, r2, g1, g2, b] = hexNoPound as any; fixHex = `${r1}${r2}${g1}${g2}${b}${b}`; break; } case 6: case 8: fixHex = hexNoPound // string is correct; /* no op*/ break; case 7: {// 0xf_f_f_f_f_f_f const [r1, r2, g1, g2, b1, b2, a] = hexNoPound as any; fixHex = `${r1}${r2}${g1}${g2}${b1}${b2}${a}${a}`; break; } } if (isNaN(parseInt(fixHex, 16))) throw new Error(fixHex + ' is not a hex number.'); return `#${fixHex}` as HexString; } static hexStringToComponents(hexStr: string) : RGBA { const normalizedHex = Color.normalizeHexString(hexStr).replace('#', ''); const hex = parseInt(normalizedHex, 16); if (isNaN(hex)) throw new Error(hex + ' is not a hex number.'); let rgba = [1, 1, 1, 1]; // r, g, b, a const size = (normalizedHex.length / 2); for (let i = size - 1; i >= 0; i--) rgba[(size - 1 - i)] = ((hex >> (i * 8)) & 0xff) / 255.0; // 24 / 16 / 8 / 0; const [r, g, b, a] = rgba; return [r, g, b, a]; } static hexNumberToComponents(hex: number): RGBA { return Color.hexStringToComponents(hex.toString(16)); } static componentsToHexString(components: RGB | RGBA): HexString { let str = ''; for (let i = 0; i < components.length; i++) { let component = components[i]; // normalize component value if (component <= 0) component = 0; else if (component <= 1) component = component * 255.0 else if (component > 1) component = Math.min(component, 255); // add it to string as hex str += component.toString(16).padStart(2, '0'); } return Color.normalizeHexString(str); } valueOf() { return this._hex; } toString() { return this._hex; } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,35 @@ try { console.log(Color.normalizeHexString('#f')); } catch (error) { console.log(error.message); } try { console.log(Color.normalizeHexString('#rr')); } catch (error) { console.log(error.message); } console.log(Color.normalizeHexString('#ff')); console.log(Color.normalizeHexString('#ffa')); console.log(Color.normalizeHexString('#f01a')); console.log(Color.normalizeHexString('#fd01b')); console.log(Color.normalizeHexString('#68ff46')); console.log(Color.normalizeHexString('#405c91a')); console.log(Color.normalizeHexString('#405c91aa')); try { console.log(Color.normalizeHexString('#405c91aae')); } catch (error) { console.log(error.message); } console.log(Color.hexStringToComponents('#ff00c3')); console.log(Color.hexStringToComponents('#ff00c3a')); console.log(Color.hexStringToComponents('#ff00c3a')); console.log(Color.normalizeHexString('#ff00c3a')); console.log(Color.componentsToHexString([1, 0, 0.7647058823529411, 0.6666666666666666])); console.log(Color.componentsToHexString([1, 0, 0.7647058823529411])); console.log(Color.componentsToHexString([255, 0, 255 * 0.7647058823529411, 255 * 0.6666666666666666])); console.log(Color.hexNumberToComponents(0xff00c3a)); console.log(Color.hexNumberToComponents(0xffaacca)); console.log(new Color('#ff'))