@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.
@@ -0,0 +1,9 @@
1
+ import { createTV as r } from "tailwind-variants";
2
+ import { twMergeConfig as e } from "./merge-config.js";
3
+ const m = r({
4
+ twMerge: !0,
5
+ twMergeConfig: e
6
+ });
7
+ export {
8
+ m as uyTv
9
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payfit/unity-themes",
3
- "version": "1.0.0",
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.3",
35
- "@storybook/addon-docs": "9.1.3",
36
- "@storybook/addon-links": "9.1.3",
37
- "@storybook/addon-vitest": "9.1.3",
38
- "@storybook/react-vite": "9.1.3",
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.3",
54
+ "storybook": "9.1.5",
55
55
  "tsx": "4.17.0",
56
- "typescript": "5.7.3",
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
@@ -1 +1,7 @@
1
+ // Core utilities
2
+ export * from './utils/cn'
1
3
  export * from './utils/tailwind-merge'
4
+ export * from './utils/tailwind-variants'
5
+
6
+ // Configuration (for advanced users)
7
+ export { twMergeConfig } from './utils/merge-config'
@@ -14,7 +14,7 @@ export function unityFileHeader() {
14
14
  * LINKS
15
15
  * =============================================================================
16
16
  *
17
- * GitHub Repository: https://github.com/PayFit/hr-apps/tree/master/packages/unity/themes
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
  *
@@ -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
+ }