-
-
Notifications
You must be signed in to change notification settings - Fork 240
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add global fontface support (#2738)
- Loading branch information
1 parent
a87ec32
commit e952f82
Showing
20 changed files
with
312 additions
and
86 deletions.
There are no files selected for viewing
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
--- | ||
'@pandacss/generator': minor | ||
'@pandacss/types': minor | ||
'@pandacss/core': minor | ||
--- | ||
|
||
Add support for defining global font face in config and preset | ||
|
||
```ts | ||
// pandacss.config.js | ||
export default defineConfig({ | ||
globalFontface: { | ||
Roboto: { | ||
src: 'url(/fonts/roboto.woff2) format("woff2")', | ||
fontWeight: '400', | ||
fontStyle: 'normal', | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
You can also add multiple font `src` for the same weight | ||
|
||
```ts | ||
// pandacss.config.js | ||
|
||
export default defineConfig({ | ||
globalFontface: { | ||
Roboto: { | ||
// multiple src | ||
src: ['url(/fonts/roboto.woff2) format("woff2")', 'url(/fonts/roboto.woff) format("woff")'], | ||
fontWeight: '400', | ||
fontStyle: 'normal', | ||
}, | ||
}, | ||
}) | ||
``` | ||
|
||
You can also define multiple font weights | ||
|
||
```ts | ||
// pandacss.config.js | ||
|
||
export default defineConfig({ | ||
globalFontface: { | ||
// multiple font weights | ||
Roboto: [ | ||
{ | ||
src: 'url(/fonts/roboto.woff2) format("woff2")', | ||
fontWeight: '400', | ||
fontStyle: 'normal', | ||
}, | ||
{ | ||
src: 'url(/fonts/roboto-bold.woff2) format("woff2")', | ||
fontWeight: '700', | ||
fontStyle: 'normal', | ||
}, | ||
], | ||
}, | ||
}) | ||
``` |
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { GlobalFontface } from '../src/global-fontface' | ||
|
||
describe('global fontface', () => { | ||
test('single src', () => { | ||
const fontface = new GlobalFontface({ | ||
globalFontface: { | ||
Inter: { | ||
src: 'url(./inter.woff2)', | ||
fontWeight: 400, | ||
fontStyle: 'normal', | ||
}, | ||
}, | ||
}) | ||
|
||
expect(fontface.toString()).toMatchInlineSnapshot(` | ||
"@font-face { | ||
font-family: Inter; | ||
src: url(./inter.woff2); | ||
font-weight: 400; | ||
font-style: normal; | ||
}" | ||
`) | ||
}) | ||
|
||
test('multiple src', () => { | ||
const fontface = new GlobalFontface({ | ||
globalFontface: { | ||
Inter: { | ||
src: ['url(./inter.woff2)', 'url(./inter.woff)'], | ||
fontWeight: 400, | ||
fontStyle: 'normal', | ||
}, | ||
}, | ||
}) | ||
|
||
expect(fontface.toString()).toMatchInlineSnapshot(` | ||
"@font-face { | ||
font-family: Inter; | ||
src: url(./inter.woff2),url(./inter.woff); | ||
font-weight: 400; | ||
font-style: normal; | ||
}" | ||
`) | ||
}) | ||
|
||
test('multiple font src', () => { | ||
const fontface = new GlobalFontface({ | ||
globalFontface: { | ||
Inter: [ | ||
{ | ||
src: ['url(./inter.woff2)', 'url(./inter.woff)'], | ||
fontWeight: 400, | ||
fontStyle: 'normal', | ||
}, | ||
{ | ||
src: ['url(./inter-bold.woff2)', 'url(./inter-bold.woff)'], | ||
fontWeight: 700, | ||
fontStyle: 'normal', | ||
}, | ||
], | ||
}, | ||
}) | ||
|
||
expect(fontface.toString()).toMatchInlineSnapshot(` | ||
"@font-face { | ||
font-family: Inter; | ||
src: url(./inter.woff2),url(./inter.woff); | ||
font-weight: 400; | ||
font-style: normal; | ||
} | ||
@font-face { | ||
font-family: Inter; | ||
src: url(./inter-bold.woff2),url(./inter-bold.woff); | ||
font-weight: 700; | ||
font-style: normal; | ||
}" | ||
`) | ||
}) | ||
}) |
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import type { FontfaceRule, GlobalFontface as GlobalFontfaceDefinition } from '@pandacss/types' | ||
import { stringify } from './stringify' | ||
|
||
interface GlobalFontfaceOptions { | ||
globalFontface?: GlobalFontfaceDefinition | ||
} | ||
|
||
export class GlobalFontface { | ||
names: string[] | ||
|
||
constructor(private options: GlobalFontfaceOptions) { | ||
const { globalFontface = {} } = options | ||
this.names = Object.keys(globalFontface) | ||
} | ||
|
||
isEmpty() { | ||
return this.names.length === 0 | ||
} | ||
|
||
toString() { | ||
const { globalFontface = {} } = this.options | ||
return stringifyGlobalFontface(globalFontface) | ||
} | ||
} | ||
|
||
const stringifyGlobalFontface = (globalFontface: GlobalFontfaceDefinition) => { | ||
if (!globalFontface) return '' | ||
|
||
const lines: string[] = [] | ||
|
||
Object.entries(globalFontface).forEach(([key, value]) => { | ||
const _value = Array.isArray(value) ? value : [value] | ||
_value.forEach((v) => { | ||
lines.push(stringifyFontface(key, v)) | ||
}) | ||
}) | ||
|
||
return lines.join('\n\n') | ||
} | ||
|
||
function stringifyFontface(fontFamily: string, config: FontfaceRule) { | ||
return `@font-face { | ||
font-family: ${fontFamily}; | ||
${stringify(config)} | ||
}` | ||
} |
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
2 changes: 1 addition & 1 deletion
2
packages/generator/src/artifacts/generated/system-types.d.ts.json
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{ | ||
"content": "import type { ConditionalValue, Nested } from './conditions'\nimport type { PropertiesFallback } from './csstype'\nimport type { SystemProperties, CssVarProperties } from './style-props'\n\ntype String = string & {}\ntype Number = number & {}\n\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n\nexport type DistributiveOmit<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never\n\nexport type DistributiveUnion<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] | T[K] : T[K]\n} & DistributiveOmit<U, keyof T>\n\nexport type Assign<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] : T[K]\n} & U\n\n/* -----------------------------------------------------------------------------\n * Native css properties\n * -----------------------------------------------------------------------------*/\n\nexport type CssProperty = keyof PropertiesFallback\n\nexport interface CssProperties extends PropertiesFallback<String | Number>, CssVarProperties {}\n\nexport interface CssKeyframes {\n [name: string]: {\n [time: string]: CssProperties\n }\n}\n\n/* -----------------------------------------------------------------------------\n * Conditional css properties\n * -----------------------------------------------------------------------------*/\n\ninterface GenericProperties {\n [key: string]: ConditionalValue<String | Number | boolean>\n}\n\n/* -----------------------------------------------------------------------------\n * Native css props\n * -----------------------------------------------------------------------------*/\n\nexport type NestedCssProperties = Nested<CssProperties>\n\nexport type SystemStyleObject = Nested<SystemProperties & CssVarProperties>\n\nexport interface GlobalStyleObject {\n [selector: string]: SystemStyleObject\n}\nexport interface ExtendableGlobalStyleObject {\n [selector: string]: SystemStyleObject | undefined\n extend?: GlobalStyleObject | undefined\n}\n\ntype FilterStyleObject<P extends string> = {\n [K in P]?: K extends keyof SystemStyleObject ? SystemStyleObject[K] : unknown\n}\n\nexport type CompositionStyleObject<Property extends string> = Nested<FilterStyleObject<Property> & CssVarProperties>\n\n/* -----------------------------------------------------------------------------\n * Jsx style props\n * -----------------------------------------------------------------------------*/\ninterface WithCss {\n css?: SystemStyleObject | SystemStyleObject[]\n}\n\nexport type JsxStyleProps = SystemStyleObject & WithCss\n\nexport interface PatchedHTMLProps {\n htmlWidth?: string | number\n htmlHeight?: string | number\n htmlTranslate?: 'yes' | 'no' | undefined\n htmlContent?: string\n}\n\nexport type OmittedHTMLProps = 'color' | 'translate' | 'transition' | 'width' | 'height' | 'content'\n\ntype WithHTMLProps<T> = DistributiveOmit<T, OmittedHTMLProps> & PatchedHTMLProps\n\nexport type JsxHTMLProps<T extends Record<string, any>, P extends Record<string, any> = {}> = Assign<\n WithHTMLProps<T>,\n P\n>\n" | ||
"content": "import type { ConditionalValue, Nested } from './conditions'\nimport type { AtRule, PropertiesFallback } from './csstype'\nimport type { SystemProperties, CssVarProperties } from './style-props'\n\ntype String = string & {}\ntype Number = number & {}\n\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n\nexport type DistributiveOmit<T, K extends keyof any> = T extends unknown ? Omit<T, K> : never\n\nexport type DistributiveUnion<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] | T[K] : T[K]\n} & DistributiveOmit<U, keyof T>\n\nexport type Assign<T, U> = {\n [K in keyof T]: K extends keyof U ? U[K] : T[K]\n} & U\n\n/* -----------------------------------------------------------------------------\n * Native css properties\n * -----------------------------------------------------------------------------*/\n\nexport type CssProperty = keyof PropertiesFallback\n\nexport interface CssProperties extends PropertiesFallback<String | Number>, CssVarProperties {}\n\nexport interface CssKeyframes {\n [name: string]: {\n [time: string]: CssProperties\n }\n}\n\n/* -----------------------------------------------------------------------------\n * Conditional css properties\n * -----------------------------------------------------------------------------*/\n\ninterface GenericProperties {\n [key: string]: ConditionalValue<String | Number | boolean>\n}\n\n/* -----------------------------------------------------------------------------\n * Native css props\n * -----------------------------------------------------------------------------*/\n\nexport type NestedCssProperties = Nested<CssProperties>\n\nexport type SystemStyleObject = Nested<SystemProperties & CssVarProperties>\n\nexport interface GlobalStyleObject {\n [selector: string]: SystemStyleObject\n}\nexport interface ExtendableGlobalStyleObject {\n [selector: string]: SystemStyleObject | undefined\n extend?: GlobalStyleObject | undefined\n}\n\n/* -----------------------------------------------------------------------------\n * Composition (text styles, layer styles)\n * -----------------------------------------------------------------------------*/\n\ntype FilterStyleObject<P extends string> = {\n [K in P]?: K extends keyof SystemStyleObject ? SystemStyleObject[K] : unknown\n}\n\nexport type CompositionStyleObject<Property extends string> = Nested<FilterStyleObject<Property> & CssVarProperties>\n\n/* -----------------------------------------------------------------------------\n * Font face\n * -----------------------------------------------------------------------------*/\n\nexport type GlobalFontfaceRule = Omit<AtRule.FontFaceFallback, 'src'> & Required<Pick<AtRule.FontFaceFallback, 'src'>>\n\nexport type FontfaceRule = Omit<GlobalFontfaceRule, 'fontFamily'>\n\nexport interface GlobalFontface {\n [name: string]: FontfaceRule | FontfaceRule[]\n}\n\nexport interface ExtendableGlobalFontface {\n [name: string]: FontfaceRule | FontfaceRule[] | GlobalFontface | undefined\n extend?: GlobalFontface | undefined\n}\n\n/* -----------------------------------------------------------------------------\n * Jsx style props\n * -----------------------------------------------------------------------------*/\ninterface WithCss {\n css?: SystemStyleObject | SystemStyleObject[]\n}\n\nexport type JsxStyleProps = SystemStyleObject & WithCss\n\nexport interface PatchedHTMLProps {\n htmlWidth?: string | number\n htmlHeight?: string | number\n htmlTranslate?: 'yes' | 'no' | undefined\n htmlContent?: string\n}\n\nexport type OmittedHTMLProps = 'color' | 'translate' | 'transition' | 'width' | 'height' | 'content'\n\ntype WithHTMLProps<T> = DistributiveOmit<T, OmittedHTMLProps> & PatchedHTMLProps\n\nexport type JsxHTMLProps<T extends Record<string, any>, P extends Record<string, any> = {}> = Assign<\n WithHTMLProps<T>,\n P\n>\n" | ||
} |
This file contains 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 characters
This file contains 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 characters
Oops, something went wrong.