Skip to content

Commit 0252947

Browse files
committed
feat: create border plugin
1 parent 4de16cd commit 0252947

File tree

4 files changed

+170
-0
lines changed

4 files changed

+170
-0
lines changed

src/tokens/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
* provide*()
44
*/
55
export * from './provide-all'
6+
export * from './provide-border'
67
export * from './provide-color'
78
export * from './provide-elevation'
89
export * from './provide-motion'
910
export * from './provide-shape'
1011
export * from './provide-typography'
1112

13+
export * from './internal/border'
1214
export * from './internal/color'
1315
export * from './internal/elevation'
1416
export * from './internal/motion'

src/tokens/internal/border.ts

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import plugin from "tailwindcss/plugin"
2+
import type { IProvider } from "../../declaration/provider.interface"
3+
import { Strings } from "../../utils/strings"
4+
import { Validates } from "../../utils/validates"
5+
6+
export type TBorderProviderConstructorParams = {
7+
8+
/**
9+
* @description
10+
* For managed or public CSS variables.
11+
*
12+
* @default 'md-sys-color'
13+
*
14+
* @example If the value of prefix is 'your-prefix'.
15+
* ```css
16+
* .border-outline {
17+
* border-color: var(--your-prefix-outline, #727785);
18+
* }
19+
* ```
20+
*/
21+
readonly prefix: string
22+
23+
/**
24+
* @description
25+
* This option can customize the CSS value corresponding to certain tokens.
26+
* Note that this option ignores [hardcodeDefaultValue] and [prefix].
27+
*
28+
* @default []
29+
*
30+
* @example
31+
* ```typescript
32+
* const color = provideBorder({
33+
* customTokens: {
34+
* // .border-outline { border-color: red; }
35+
* 'outline': 'red'
36+
* },
37+
* })
38+
* ```
39+
*/
40+
readonly customTokens: IBorderTokens | Record<string, string>
41+
42+
/**
43+
* @description
44+
* When set to true, each token contains a default value.
45+
*
46+
* @default true
47+
*
48+
* @example
49+
* ```typescript
50+
* const color = provideBorder({
51+
* // .border-outline { border-color: var(--md-sys-color-outline, #727785); }
52+
* hardcodeDefaultValue: true,
53+
*
54+
* // .border-outline { border-color: var(--md-sys-color-outline, ); }
55+
* hardcodeDefaultValue: false,
56+
* })
57+
* ```
58+
*/
59+
readonly hardcodeDefaultValue: boolean
60+
61+
/**
62+
* @description
63+
* Exclude some unnecessary tokens.
64+
*
65+
* @default []
66+
*
67+
* @example
68+
* ```typescript
69+
* const color = provideBorder({
70+
* excludedTokens: [
71+
* // remove .border-outline-variant and .outline-outline-variant
72+
* 'outlineVariant',
73+
* ],
74+
* })
75+
* ```
76+
*/
77+
readonly excludedTokens: Array<(keyof IBorderTokens) | {}>
78+
79+
}
80+
81+
interface IBorderTokens {
82+
outline: string
83+
outlineVariant: string
84+
}
85+
86+
class DefaultBorderTokens implements IBorderTokens {
87+
/**
88+
* Colors
89+
*/
90+
outline = '#727785'
91+
outlineVariant = '#c2c6d6'
92+
93+
public get defaultTokenRecord() {
94+
return {
95+
outline: this.outline,
96+
outlineVariant: this.outlineVariant,
97+
}
98+
}
99+
}
100+
101+
export class BorderProvider extends DefaultBorderTokens implements IProvider {
102+
private prefix
103+
private tokens
104+
private customTokens
105+
private excludedTokens
106+
private hardcodeDefaultValue
107+
108+
constructor(params: Partial<TBorderProviderConstructorParams>) {
109+
super()
110+
this.prefix = params.prefix ?? 'md-sys-color'
111+
this.hardcodeDefaultValue = params.hardcodeDefaultValue ?? true
112+
this.customTokens = params.customTokens ?? {}
113+
this.excludedTokens = params.excludedTokens ?? []
114+
this.tokens = this.validate([this.customTokens as Record<string, string>, this.defaultTokenRecord, this.excludedTokens])
115+
}
116+
117+
private validate(params: Parameters<typeof Validates.validate>) {
118+
return Validates.validate(...params)
119+
}
120+
121+
protected transformTokensToCssRuleObject(prefix: string, tokens: Record<string, string>, hardcodeDefaultValue: boolean) {
122+
const cssPropertyComputed = (name: string, value: string) => !Object.hasOwn(this.customTokens, name) ? `var(--${prefix}-${Strings.toKebabCase(name)}, ${hardcodeDefaultValue ? value : ''})` : `${value}`
123+
124+
const borderTokens = Validates.transformTokenRecordToCssRuleObject(
125+
tokens,
126+
(name) => `.border-${Strings.toKebabCase(name)}`,
127+
(name, value) => ({
128+
'border-color': cssPropertyComputed(name, value)
129+
})
130+
)
131+
const outlineTokens = Validates.transformTokenRecordToCssRuleObject(
132+
tokens,
133+
(name) => `.outline-${Strings.toKebabCase(name)}`,
134+
(name, value) => ({
135+
'outline-color': cssPropertyComputed(name, value)
136+
})
137+
)
138+
return Object.assign({}, borderTokens, outlineTokens)
139+
}
140+
141+
getPlugin() {
142+
const tokens = this.transformTokensToCssRuleObject(this.prefix, this.tokens, this.hardcodeDefaultValue)
143+
return plugin(({ addUtilities }) => {
144+
addUtilities(tokens)
145+
})
146+
}
147+
148+
}

src/tokens/provide-all.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import type { TBorderProviderConstructorParams } from "./internal/border";
12
import type { TColorProviderConstructorParams } from "./internal/color";
23
import type { TElevationProviderConstructorParams } from "./internal/elevation";
34
import type { TMotionProviderConstructorParams } from "./internal/motion";
45
import type { TShapeProviderConstructorParams } from "./internal/shape";
56
import type { TTypographyProviderConstructorParams } from "./internal/typography";
7+
import { provideBorder } from "./provide-border";
68
import { provideColor } from "./provide-color";
79
import { provideElevation } from "./provide-elevation";
810
import { provideMotion } from "./provide-motion";
@@ -15,20 +17,23 @@ export function provideAll(params: {
1517
motion?: TMotionProviderConstructorParams,
1618
shape?: TShapeProviderConstructorParams,
1719
typography?: TTypographyProviderConstructorParams,
20+
border?: Partial<TBorderProviderConstructorParams>,
1821
}) {
1922
return ({
2023
color: provideColor(params.color),
2124
elevation: provideElevation(params.elevation),
2225
motion: provideMotion(params.motion),
2326
shape: provideShape(params.shape),
2427
typography: provideTypography(params.typography),
28+
border: provideBorder(params.border),
2529
allPlugins() {
2630
return ([
2731
this.color.getPlugin(),
2832
this.elevation.getPlugin(),
2933
this.motion.getPlugin(),
3034
this.shape.getPlugin(),
3135
this.typography.getPlugin(),
36+
this.border.getPlugin(),
3237
])
3338
}
3439
})

src/tokens/provide-border.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { BorderProvider, type TBorderProviderConstructorParams } from './internal/border'
2+
3+
/**
4+
* @example
5+
* ```typescript
6+
* const border = provideBorder()
7+
*
8+
* export default {
9+
* plugins: [
10+
* border.getPlugin()
11+
* ]
12+
* }
13+
* ```
14+
*/
15+
export const provideBorder = (param?: Partial<TBorderProviderConstructorParams>) => new BorderProvider(param ?? {})

0 commit comments

Comments
 (0)