@agent-facets/brand 0.1.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.
- package/package.json +27 -0
- package/src/__tests__/colors.test.ts +23 -0
- package/src/colors.ts +37 -0
- package/src/gradient.ts +48 -0
- package/src/index.ts +3 -0
- package/src/theme.ts +26 -0
- package/tsconfig.json +4 -0
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-facets/brand",
|
|
3
|
+
"repository": {
|
|
4
|
+
"type": "git",
|
|
5
|
+
"url": "https://github.com/ex-machina-co/facets",
|
|
6
|
+
"directory": "packages/brand"
|
|
7
|
+
},
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./src/index.ts"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"types": "tsc --noEmit",
|
|
15
|
+
"test": "bun test"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/bun": "1.3.10"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"typescript": "^5"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"provenance": false
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test'
|
|
2
|
+
import { BRAND, BRIGHTNESS, hexToRgb, PALETTE } from '../colors.ts'
|
|
3
|
+
|
|
4
|
+
test('hexToRgb parses brand purple', () => {
|
|
5
|
+
expect(hexToRgb(BRAND.purple)).toEqual([167, 139, 250])
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('hexToRgb parses brand green', () => {
|
|
9
|
+
expect(hexToRgb(BRAND.green)).toEqual([66, 205, 170])
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('hexToRgb parses brand coral', () => {
|
|
13
|
+
expect(hexToRgb(BRAND.coral)).toEqual([250, 139, 141])
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('PALETTE violet400 matches BRAND purple', () => {
|
|
17
|
+
expect(PALETTE.violet400).toBe(BRAND.purple)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('BRIGHTNESS has dim and dimmer values', () => {
|
|
21
|
+
expect(BRIGHTNESS.dim).toBe('#666666')
|
|
22
|
+
expect(BRIGHTNESS.dimmer).toBe('#999999')
|
|
23
|
+
})
|
package/src/colors.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core brand colors — derived from the facet.svg icon.
|
|
3
|
+
*/
|
|
4
|
+
export const BRAND = {
|
|
5
|
+
purple: '#A78BFA',
|
|
6
|
+
green: '#42CDAA',
|
|
7
|
+
coral: '#FA8B8D',
|
|
8
|
+
dark: '#1F1F28',
|
|
9
|
+
} as const
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Extended palette — includes docs/marketing variants.
|
|
13
|
+
*/
|
|
14
|
+
export const PALETTE = {
|
|
15
|
+
violet400: '#A78BFA',
|
|
16
|
+
violet700: '#6D28D9',
|
|
17
|
+
violet900: '#4C1D95',
|
|
18
|
+
green: '#42CDAA',
|
|
19
|
+
coral: '#FA8B8D',
|
|
20
|
+
dark: '#1F1F28',
|
|
21
|
+
} as const
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Text brightness scale.
|
|
25
|
+
*/
|
|
26
|
+
export const BRIGHTNESS = {
|
|
27
|
+
dim: '#666666',
|
|
28
|
+
dimmer: '#999999',
|
|
29
|
+
} as const
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parse a hex color string into an RGB tuple.
|
|
33
|
+
*/
|
|
34
|
+
export function hexToRgb(hex: string): readonly [number, number, number] {
|
|
35
|
+
const h = hex.replace('#', '')
|
|
36
|
+
return [parseInt(h.substring(0, 2), 16), parseInt(h.substring(2, 4), 16), parseInt(h.substring(4, 6), 16)] as const
|
|
37
|
+
}
|
package/src/gradient.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { THEME } from './theme.ts'
|
|
2
|
+
|
|
3
|
+
/** Fixed number of gradient stops — ensures consistent animation speed regardless of text length */
|
|
4
|
+
const GRADIENT_STOP_COUNT = 32
|
|
5
|
+
|
|
6
|
+
function toHex(r: number, g: number, b: number): string {
|
|
7
|
+
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function lerpRgb(
|
|
11
|
+
a: readonly [number, number, number],
|
|
12
|
+
b: readonly [number, number, number],
|
|
13
|
+
t: number,
|
|
14
|
+
): [number, number, number] {
|
|
15
|
+
return [
|
|
16
|
+
Math.round(a[0] + (b[0] - a[0]) * t),
|
|
17
|
+
Math.round(a[1] + (b[1] - a[1]) * t),
|
|
18
|
+
Math.round(a[2] + (b[2] - a[2]) * t),
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Pre-computed gradient loop with fixed stop count for consistent animation */
|
|
23
|
+
function generateGradientLoop(): string[] {
|
|
24
|
+
const [colorA, colorB, colorC] = THEME.gradientRGB
|
|
25
|
+
const colors: string[] = []
|
|
26
|
+
for (let i = 0; i < GRADIENT_STOP_COUNT; i++) {
|
|
27
|
+
const segment = ((i / GRADIENT_STOP_COUNT) * 3) % 3
|
|
28
|
+
let rgb: [number, number, number]
|
|
29
|
+
if (segment < 1) {
|
|
30
|
+
rgb = lerpRgb(colorA, colorB, segment)
|
|
31
|
+
} else if (segment < 2) {
|
|
32
|
+
rgb = lerpRgb(colorB, colorC, segment - 1)
|
|
33
|
+
} else {
|
|
34
|
+
rgb = lerpRgb(colorC, colorA, segment - 2)
|
|
35
|
+
}
|
|
36
|
+
colors.push(toHex(...rgb))
|
|
37
|
+
}
|
|
38
|
+
return colors
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Pre-computed stops — shared by all animated gradients */
|
|
42
|
+
export const GRADIENT_STOPS = generateGradientLoop()
|
|
43
|
+
|
|
44
|
+
/** Get the gradient colors at a given offset for animation */
|
|
45
|
+
export function getAnimatedGradient(offset: number): string[] {
|
|
46
|
+
const i = offset % GRADIENT_STOPS.length
|
|
47
|
+
return [...GRADIENT_STOPS.slice(i), ...GRADIENT_STOPS.slice(0, i)]
|
|
48
|
+
}
|
package/src/index.ts
ADDED
package/src/theme.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BRAND, BRIGHTNESS, hexToRgb } from './colors.ts'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Semantic theme — all values are references to brand constants.
|
|
5
|
+
* Consumers should use THEME, not the raw color constants.
|
|
6
|
+
*/
|
|
7
|
+
export const THEME = {
|
|
8
|
+
// Brand hierarchy
|
|
9
|
+
primary: BRAND.purple,
|
|
10
|
+
secondary: BRAND.green,
|
|
11
|
+
tertiary: BRAND.coral,
|
|
12
|
+
brand: BRAND.purple,
|
|
13
|
+
dark: BRAND.dark,
|
|
14
|
+
|
|
15
|
+
// Semantic aliases (can diverge from brand later)
|
|
16
|
+
success: BRAND.green,
|
|
17
|
+
warning: BRAND.coral,
|
|
18
|
+
|
|
19
|
+
// Text — structural
|
|
20
|
+
hint: BRIGHTNESS.dim,
|
|
21
|
+
keyword: BRIGHTNESS.dimmer,
|
|
22
|
+
|
|
23
|
+
// Three-color gradient: purple → teal → coral
|
|
24
|
+
gradient: [BRAND.purple, BRAND.green, BRAND.coral] as const,
|
|
25
|
+
gradientRGB: [hexToRgb(BRAND.purple), hexToRgb(BRAND.green), hexToRgb(BRAND.coral)] as const,
|
|
26
|
+
} as const
|
package/tsconfig.json
ADDED