@payfit/unity-themes 1.0.0 → 1.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/dist/css/unity.css +2 -2
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +10 -2
- package/dist/esm/utils/cn.d.ts +93 -0
- package/dist/esm/utils/cn.js +11 -0
- package/dist/esm/utils/merge-config.d.ts +217 -0
- package/dist/esm/utils/merge-config.js +171 -0
- package/dist/esm/utils/tailwind-merge.d.ts +66 -0
- package/dist/esm/utils/tailwind-merge.js +5 -29
- package/dist/esm/utils/tailwind-variants.d.ts +44 -0
- package/dist/esm/utils/tailwind-variants.js +9 -0
- package/package.json +9 -8
- package/src/index.ts +6 -0
- package/src/scripts/file-headers/unity.ts +1 -1
- package/src/utils/cn.ts +109 -0
- package/src/utils/merge-config.ts +193 -0
- package/src/utils/tailwind-merge.test.ts +440 -43
- package/src/utils/tailwind-merge.ts +69 -26
- package/src/utils/tailwind-variants.ts +53 -0
- package/tokens/colors.json +1 -1
- package/src/generated/tailwind-preset.js +0 -2160
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payfit/unity-themes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"main": "./dist/esm/index.js",
|
|
5
5
|
"types": "./dist/esm/index.d.ts",
|
|
6
6
|
"style": "./dist/css/unity.css",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"@payfit/hr-app-eslint": "0.0.0-use.local",
|
|
32
32
|
"@payfit/hr-apps-tsconfigs": "0.0.0-use.local",
|
|
33
33
|
"@payfit/vite-configs": "0.0.0-use.local",
|
|
34
|
-
"@storybook/addon-a11y": "9.1.
|
|
35
|
-
"@storybook/addon-docs": "9.1.
|
|
36
|
-
"@storybook/addon-links": "9.1.
|
|
37
|
-
"@storybook/addon-vitest": "9.1.
|
|
38
|
-
"@storybook/react-vite": "9.1.
|
|
34
|
+
"@storybook/addon-a11y": "9.1.5",
|
|
35
|
+
"@storybook/addon-docs": "9.1.5",
|
|
36
|
+
"@storybook/addon-links": "9.1.5",
|
|
37
|
+
"@storybook/addon-vitest": "9.1.5",
|
|
38
|
+
"@storybook/react-vite": "9.1.5",
|
|
39
39
|
"@storybook/test-runner": "0.23.0",
|
|
40
40
|
"@tailwindcss/vite": "4.1.11",
|
|
41
41
|
"@types/lodash": "4.14.202",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"prettier": "3.1.0",
|
|
52
52
|
"react": "18.3.1",
|
|
53
53
|
"react-dom": "18.3.1",
|
|
54
|
-
"storybook": "9.1.
|
|
54
|
+
"storybook": "9.1.5",
|
|
55
55
|
"tsx": "4.17.0",
|
|
56
|
-
"typescript": "5.
|
|
56
|
+
"typescript": "5.9.2",
|
|
57
57
|
"vite": "6.3.5",
|
|
58
58
|
"vitest": "3.2.4"
|
|
59
59
|
},
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"colorjs.io": "0.5.2",
|
|
69
69
|
"style-dictionary": "5.0.0",
|
|
70
70
|
"tailwind-merge": "3.3.1",
|
|
71
|
+
"tailwind-variants": "2.1.0",
|
|
71
72
|
"tailwindcss": "4.1.11"
|
|
72
73
|
}
|
|
73
74
|
}
|
package/src/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export function unityFileHeader() {
|
|
|
14
14
|
* LINKS
|
|
15
15
|
* =============================================================================
|
|
16
16
|
*
|
|
17
|
-
* GitHub Repository: https://github.com/PayFit/hr-apps/
|
|
17
|
+
* GitHub Repository: https://github.com/PayFit/hr-apps/blob/master/libs/shared/unity/themes
|
|
18
18
|
* Documentation: https://unity-theme.payfit.io/?path=/docs/1-introduction-1-welcome--docs
|
|
19
19
|
* Issues/Support: https://payfit.atlassian.net/jira/software/c/projects/CEEFRE/boards/623
|
|
20
20
|
*
|
package/src/utils/cn.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { cn as cnBase } from 'tailwind-variants'
|
|
2
|
+
|
|
3
|
+
import { twMergeConfig } from './merge-config'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Internal Unity-configured class name utility function.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
const uyCn = (...classes: string[]) =>
|
|
10
|
+
cnBase(...classes)({
|
|
11
|
+
twMerge: true,
|
|
12
|
+
twMergeConfig,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Unity-configured class name utility function for merging CSS classes.
|
|
17
|
+
*
|
|
18
|
+
* This is a pre-configured version of tailwind-variants' `cn` function that includes
|
|
19
|
+
* Unity's custom tailwind-merge configuration. It automatically handles Unity's custom
|
|
20
|
+
* class names and resolves conflicts according to Unity design system rules.
|
|
21
|
+
* @param classes - CSS class names to merge
|
|
22
|
+
* @returns Merged and deduplicated class string
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* import { cn } from '@payfit/unity-themes'
|
|
26
|
+
*
|
|
27
|
+
* // Basic usage
|
|
28
|
+
* const className = cn('uy:p-200', 'uy:bg-surface-primary-default')
|
|
29
|
+
* // → 'uy:p-200 uy:bg-surface-primary-default'
|
|
30
|
+
*
|
|
31
|
+
* // Conflict resolution - last class wins
|
|
32
|
+
* const className = cn('uy:bg-surface-primary-default', 'uy:bg-surface-danger-default')
|
|
33
|
+
* // → 'uy:bg-surface-danger-default'
|
|
34
|
+
*
|
|
35
|
+
* // Conditional classes
|
|
36
|
+
* const className = cn(
|
|
37
|
+
* 'uy:px-200 uy:py-100',
|
|
38
|
+
* isActive && 'uy:bg-surface-primary-default',
|
|
39
|
+
* isDisabled && 'uy:bg-surface-neutral-disabled'
|
|
40
|
+
* )
|
|
41
|
+
*
|
|
42
|
+
* // With component props
|
|
43
|
+
* function Button({ variant, size, className: extraClasses, ...props }) {
|
|
44
|
+
* return (
|
|
45
|
+
* <button
|
|
46
|
+
* className={cn(
|
|
47
|
+
* 'uy:px-200 uy:py-100 uy:rounded-100', // base styles
|
|
48
|
+
* variant === 'primary' && 'uy:bg-surface-primary-default',
|
|
49
|
+
* variant === 'secondary' && 'uy:bg-surface-neutral-default',
|
|
50
|
+
* size === 'large' && 'uy:px-300 uy:py-150',
|
|
51
|
+
* extraClasses // allow override
|
|
52
|
+
* )}
|
|
53
|
+
* {...props}
|
|
54
|
+
* />
|
|
55
|
+
* )
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
* @description
|
|
59
|
+
* - Automatically merges conflicting Unity classes using Unity's design system rules
|
|
60
|
+
* - Supports all Unity design tokens: semantic colors, primitive colors, spacing, typography, etc.
|
|
61
|
+
* - Handles conditional classes (falsy values are ignored)
|
|
62
|
+
* - Compatible with standard Tailwind classes alongside Unity classes
|
|
63
|
+
* - Removes duplicate classes and resolves conflicts intelligently
|
|
64
|
+
* @see {@link uyMerge} for the underlying merge function
|
|
65
|
+
* @see {@link twMergeConfig} for the Unity merge configuration details
|
|
66
|
+
*/
|
|
67
|
+
export const cn = uyCn
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Alias for {@link cn} - Unity-configured class name utility function.
|
|
71
|
+
*
|
|
72
|
+
* This function is identical to `cn` but provides a more descriptive name
|
|
73
|
+
* for developers who prefer explicit naming conventions.
|
|
74
|
+
* @param classes - CSS class names to merge
|
|
75
|
+
* @returns Merged and deduplicated class string
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* import { classNames } from '@payfit/unity-themes'
|
|
79
|
+
*
|
|
80
|
+
* const buttonClasses = classNames(
|
|
81
|
+
* 'uy:px-200 uy:py-100',
|
|
82
|
+
* 'uy:bg-surface-primary-default',
|
|
83
|
+
* 'uy:text-content-inverted-default'
|
|
84
|
+
* )
|
|
85
|
+
* ```
|
|
86
|
+
* @see {@link cn} for detailed documentation and examples
|
|
87
|
+
*/
|
|
88
|
+
export const classNames = uyCn
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Alias for {@link cn} - Unity-configured class name utility function.
|
|
92
|
+
*
|
|
93
|
+
* This function is identical to `cn` but follows the naming convention
|
|
94
|
+
* popularized by the `clsx` library for developers familiar with that API.
|
|
95
|
+
* @param classes - CSS class names to merge
|
|
96
|
+
* @returns Merged and deduplicated class string
|
|
97
|
+
* @example
|
|
98
|
+
* ```tsx
|
|
99
|
+
* import { clsx } from '@payfit/unity-themes'
|
|
100
|
+
*
|
|
101
|
+
* const cardClasses = clsx(
|
|
102
|
+
* 'uy:p-300 uy:rounded-200',
|
|
103
|
+
* 'uy:bg-surface-neutral-default',
|
|
104
|
+
* isHighlighted && 'uy:border-border-primary-default'
|
|
105
|
+
* )
|
|
106
|
+
* ```
|
|
107
|
+
* @see {@link cn} for detailed documentation and examples
|
|
108
|
+
*/
|
|
109
|
+
export const clsx = uyCn
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { validators } from 'tailwind-merge'
|
|
2
|
+
|
|
3
|
+
// Unity spacing scale values
|
|
4
|
+
const unitySpacing = [
|
|
5
|
+
'0',
|
|
6
|
+
'25',
|
|
7
|
+
'50',
|
|
8
|
+
'75',
|
|
9
|
+
'100',
|
|
10
|
+
'125',
|
|
11
|
+
'150',
|
|
12
|
+
'200',
|
|
13
|
+
'250',
|
|
14
|
+
'300',
|
|
15
|
+
'400',
|
|
16
|
+
'500',
|
|
17
|
+
'600',
|
|
18
|
+
'800',
|
|
19
|
+
'1000',
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
// Unity typography classes - actual generated class names (without -sm variants)
|
|
23
|
+
const unityTypography = [
|
|
24
|
+
'h1',
|
|
25
|
+
'h2',
|
|
26
|
+
'h3',
|
|
27
|
+
'h4',
|
|
28
|
+
'overline',
|
|
29
|
+
'subtitle',
|
|
30
|
+
'display-title',
|
|
31
|
+
'display-body',
|
|
32
|
+
'body',
|
|
33
|
+
'body-strong',
|
|
34
|
+
'body-small',
|
|
35
|
+
'body-small-strong',
|
|
36
|
+
'body-large',
|
|
37
|
+
'body-large-strong',
|
|
38
|
+
'action',
|
|
39
|
+
'action-small',
|
|
40
|
+
'action-large',
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
// Unity font sizes
|
|
44
|
+
const unityFontSizes = [
|
|
45
|
+
'50',
|
|
46
|
+
'75',
|
|
47
|
+
'100',
|
|
48
|
+
'200',
|
|
49
|
+
'300',
|
|
50
|
+
'400',
|
|
51
|
+
'500',
|
|
52
|
+
'600',
|
|
53
|
+
'800',
|
|
54
|
+
'1000',
|
|
55
|
+
'1200',
|
|
56
|
+
'1400',
|
|
57
|
+
'1600',
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
// Unity border radius values
|
|
61
|
+
const unityBorderRadius = [
|
|
62
|
+
'0',
|
|
63
|
+
'25',
|
|
64
|
+
'50',
|
|
65
|
+
'75',
|
|
66
|
+
'100',
|
|
67
|
+
'125',
|
|
68
|
+
'150',
|
|
69
|
+
'200',
|
|
70
|
+
'300',
|
|
71
|
+
'400',
|
|
72
|
+
'xs',
|
|
73
|
+
'sm',
|
|
74
|
+
'md',
|
|
75
|
+
'lg',
|
|
76
|
+
'xl',
|
|
77
|
+
'circle',
|
|
78
|
+
'pill',
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
// Unity shadow values
|
|
82
|
+
const unityShadows = ['canvas', 'raising', 'floating', 'flying', 'soaring']
|
|
83
|
+
|
|
84
|
+
// Custom validator for Unity colors
|
|
85
|
+
const isUnityColor = (value: string): boolean => {
|
|
86
|
+
// Primitive colors: {color}-l{number}
|
|
87
|
+
if (/^[a-z]+-l\d+$/.test(value)) return true
|
|
88
|
+
// Semantic colors: {category}-{type}-{variant}(-{state})?
|
|
89
|
+
if (/^(?:canvas|surface|content|border|utility)-.+$/.test(value)) return true
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const twMergeConfig = {
|
|
94
|
+
prefix: 'uy',
|
|
95
|
+
extend: {
|
|
96
|
+
classGroups: {
|
|
97
|
+
// Colors - Use pattern matching for maintainability
|
|
98
|
+
// Matches primitive colors like: grayscale-l0, red-l1, blue-l12, etc.
|
|
99
|
+
// Matches semantic colors like: surface-primary-default, content-neutral-low, border-danger-default, etc.
|
|
100
|
+
'bg-color': [{ bg: [validators.isArbitraryValue, isUnityColor] }],
|
|
101
|
+
'text-color': [{ text: [validators.isArbitraryValue, isUnityColor] }],
|
|
102
|
+
'border-color': [{ border: [validators.isArbitraryValue, isUnityColor] }],
|
|
103
|
+
'outline-color': [
|
|
104
|
+
{ outline: [validators.isArbitraryValue, isUnityColor] },
|
|
105
|
+
],
|
|
106
|
+
'ring-color': [{ ring: [validators.isArbitraryValue, isUnityColor] }],
|
|
107
|
+
'ring-offset-color': [
|
|
108
|
+
{ 'ring-offset': [validators.isArbitraryValue, isUnityColor] },
|
|
109
|
+
],
|
|
110
|
+
'divide-color': [{ divide: [validators.isArbitraryValue, isUnityColor] }],
|
|
111
|
+
'text-decoration-color': [
|
|
112
|
+
{ decoration: [validators.isArbitraryValue, isUnityColor] },
|
|
113
|
+
],
|
|
114
|
+
'gradient-color-from': [
|
|
115
|
+
{ from: [validators.isArbitraryValue, isUnityColor] },
|
|
116
|
+
],
|
|
117
|
+
'gradient-color-via': [
|
|
118
|
+
{ via: [validators.isArbitraryValue, isUnityColor] },
|
|
119
|
+
],
|
|
120
|
+
'gradient-color-to': [
|
|
121
|
+
{ to: [validators.isArbitraryValue, isUnityColor] },
|
|
122
|
+
],
|
|
123
|
+
// Spacing - Padding
|
|
124
|
+
p: [{ p: unitySpacing }],
|
|
125
|
+
px: [{ px: unitySpacing }],
|
|
126
|
+
py: [{ py: unitySpacing }],
|
|
127
|
+
ps: [{ ps: unitySpacing }],
|
|
128
|
+
pe: [{ pe: unitySpacing }],
|
|
129
|
+
pt: [{ pt: unitySpacing }],
|
|
130
|
+
pr: [{ pr: unitySpacing }],
|
|
131
|
+
pb: [{ pb: unitySpacing }],
|
|
132
|
+
pl: [{ pl: unitySpacing }],
|
|
133
|
+
// Spacing - Margin
|
|
134
|
+
m: [{ m: unitySpacing }],
|
|
135
|
+
mx: [{ mx: unitySpacing }],
|
|
136
|
+
my: [{ my: unitySpacing }],
|
|
137
|
+
ms: [{ ms: unitySpacing }],
|
|
138
|
+
me: [{ me: unitySpacing }],
|
|
139
|
+
mt: [{ mt: unitySpacing }],
|
|
140
|
+
mr: [{ mr: unitySpacing }],
|
|
141
|
+
mb: [{ mb: unitySpacing }],
|
|
142
|
+
ml: [{ ml: unitySpacing }],
|
|
143
|
+
// Spacing - Gap
|
|
144
|
+
gap: [{ gap: unitySpacing }],
|
|
145
|
+
'gap-x': [{ 'gap-x': unitySpacing }],
|
|
146
|
+
'gap-y': [{ 'gap-y': unitySpacing }],
|
|
147
|
+
// Spacing - Space between
|
|
148
|
+
'space-x': [{ 'space-x': unitySpacing }],
|
|
149
|
+
'space-y': [{ 'space-y': unitySpacing }],
|
|
150
|
+
// Spacing - Scroll padding
|
|
151
|
+
'scroll-p': [{ 'scroll-p': unitySpacing }],
|
|
152
|
+
'scroll-px': [{ 'scroll-px': unitySpacing }],
|
|
153
|
+
'scroll-py': [{ 'scroll-py': unitySpacing }],
|
|
154
|
+
'scroll-ps': [{ 'scroll-ps': unitySpacing }],
|
|
155
|
+
'scroll-pe': [{ 'scroll-pe': unitySpacing }],
|
|
156
|
+
'scroll-pt': [{ 'scroll-pt': unitySpacing }],
|
|
157
|
+
'scroll-pr': [{ 'scroll-pr': unitySpacing }],
|
|
158
|
+
'scroll-pb': [{ 'scroll-pb': unitySpacing }],
|
|
159
|
+
'scroll-pl': [{ 'scroll-pl': unitySpacing }],
|
|
160
|
+
// Spacing - Scroll margin
|
|
161
|
+
'scroll-m': [{ 'scroll-m': unitySpacing }],
|
|
162
|
+
'scroll-mx': [{ 'scroll-mx': unitySpacing }],
|
|
163
|
+
'scroll-my': [{ 'scroll-my': unitySpacing }],
|
|
164
|
+
'scroll-ms': [{ 'scroll-ms': unitySpacing }],
|
|
165
|
+
'scroll-me': [{ 'scroll-me': unitySpacing }],
|
|
166
|
+
'scroll-mt': [{ 'scroll-mt': unitySpacing }],
|
|
167
|
+
'scroll-mr': [{ 'scroll-mr': unitySpacing }],
|
|
168
|
+
'scroll-mb': [{ 'scroll-mb': unitySpacing }],
|
|
169
|
+
'scroll-ml': [{ 'scroll-ml': unitySpacing }],
|
|
170
|
+
// Typography
|
|
171
|
+
typography: [{ typography: unityTypography }],
|
|
172
|
+
'font-size': [{ text: unityFontSizes }],
|
|
173
|
+
// Border radius
|
|
174
|
+
rounded: [{ rounded: unityBorderRadius }],
|
|
175
|
+
'rounded-s': [{ 'rounded-s': unityBorderRadius }],
|
|
176
|
+
'rounded-e': [{ 'rounded-e': unityBorderRadius }],
|
|
177
|
+
'rounded-t': [{ 'rounded-t': unityBorderRadius }],
|
|
178
|
+
'rounded-r': [{ 'rounded-r': unityBorderRadius }],
|
|
179
|
+
'rounded-b': [{ 'rounded-b': unityBorderRadius }],
|
|
180
|
+
'rounded-l': [{ 'rounded-l': unityBorderRadius }],
|
|
181
|
+
'rounded-ss': [{ 'rounded-ss': unityBorderRadius }],
|
|
182
|
+
'rounded-se': [{ 'rounded-se': unityBorderRadius }],
|
|
183
|
+
'rounded-ee': [{ 'rounded-ee': unityBorderRadius }],
|
|
184
|
+
'rounded-es': [{ 'rounded-es': unityBorderRadius }],
|
|
185
|
+
'rounded-tl': [{ 'rounded-tl': unityBorderRadius }],
|
|
186
|
+
'rounded-tr': [{ 'rounded-tr': unityBorderRadius }],
|
|
187
|
+
'rounded-br': [{ 'rounded-br': unityBorderRadius }],
|
|
188
|
+
'rounded-bl': [{ 'rounded-bl': unityBorderRadius }],
|
|
189
|
+
// Shadows
|
|
190
|
+
shadow: [{ shadow: unityShadows }],
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
}
|