diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json index f829c29af0bb..e10843b85524 100644 --- a/code/frameworks/nextjs/package.json +++ b/code/frameworks/nextjs/package.json @@ -59,6 +59,7 @@ "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { + "@next/font": "^13.0.7", "@storybook/builder-webpack5": "7.0.0-beta.10", "@storybook/core-common": "7.0.0-beta.10", "@storybook/node-logger": "7.0.0-beta.10", @@ -82,7 +83,6 @@ "devDependencies": { "@babel/core": "^7.20.5", "@babel/types": "^7.20.5", - "@next/font": "^13.0.6", "@storybook/addon-actions": "7.0.0-beta.10", "@types/babel__core": "^7", "next": "^13.0.5", @@ -119,7 +119,8 @@ "./src/index.ts", "./src/preset.ts", "./src/preview.tsx", - "./src/next-image-loader-stub.ts" + "./src/next-image-loader-stub.ts", + "./src/font/webpack/loader/storybook-nextjs-font-loader.ts" ], "platform": "node" }, diff --git a/code/frameworks/nextjs/src/font/babel.test.ts b/code/frameworks/nextjs/src/font/babel.test.ts deleted file mode 100644 index 460b27bfdfd9..000000000000 --- a/code/frameworks/nextjs/src/font/babel.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { transform } from '@babel/core'; -import TransformFontImports from './babel'; - -const example = ` -import { Inter, Roboto } from '@next/font/google' -import localFont from '@next/font/local' - -const myFont = localFont({ src: './my-font.woff2' }) - -const roboto = Roboto({ - weight: '400', -}) - -const inter = Inter({ - subsets: ['latin'], -}); - -const randomObj = {} -`; - -it('should transform AST properly', () => { - const { code } = transform(example, { plugins: [TransformFontImports] })!; - expect(code).toMatchInlineSnapshot(` - "import inter from \\"@next/font/google?Inter;{\\\\\\"subsets\\\\\\":[\\\\\\"latin\\\\\\"]}\\"; - import roboto from \\"@next/font/google?Roboto;{\\\\\\"weight\\\\\\":\\\\\\"400\\\\\\"}\\"; - import myFont from \\"@next/font/local?localFont;{\\\\\\"src\\\\\\":\\\\\\"./my-font.woff2\\\\\\"}\\"; - const randomObj = {};" - `); -}); diff --git a/code/frameworks/nextjs/src/font/babel.helpers.ts b/code/frameworks/nextjs/src/font/babel/helpers.ts similarity index 91% rename from code/frameworks/nextjs/src/font/babel.helpers.ts rename to code/frameworks/nextjs/src/font/babel/helpers.ts index 0e2180464c70..08e96f376c13 100644 --- a/code/frameworks/nextjs/src/font/babel.helpers.ts +++ b/code/frameworks/nextjs/src/font/babel/helpers.ts @@ -150,7 +150,7 @@ export function removeTransformedVariableDeclarations( /** * Replaces `@next/font` import with a parameterized import * @example - * // AST + * // AST of src/example.js * import { Roboto, Inter } from '@next/font/google' * const interName = Inter({ * subsets: ['latin'], @@ -160,8 +160,8 @@ export function removeTransformedVariableDeclarations( * }) * * // Result - * import interName from '@next/font/google?Inter;{"subsets":["latin"]}' - * import robotoName from '@next/font/google?Roboto;{"weight":"400"}' + * import interName from 'storybook-nextjs-font-loader?{filename: "src/example.js", source: "@next/font/google", fontFamily: "Inter", props: {"subsets":["latin"]}}!@next/font/google' + * import robotoName from 'storybook-nextjs-font-loader?{filename: "src/example.js", source: "@next/font/google", fontFamily: "Roboto", props: {"weight": "400"}}!@next/font/google' * * // Following code will be removed from removeUnusedVariableDeclarations function * const interName = Inter({ @@ -176,7 +176,8 @@ export function replaceImportWithParamterImport( path: BabelCoreNamespace.NodePath, types: BabelTypes, source: BabelCoreNamespace.types.StringLiteral, - metas: Array + metas: Array, + filename: string ) { // Add an import for each specifier with parameters path.replaceWithMultiple([ @@ -184,11 +185,12 @@ export function replaceImportWithParamterImport( return types.importDeclaration( [types.importDefaultSpecifier(types.identifier(meta.identifierName))], types.stringLiteral( - // TODO - `${source.value}?${meta.functionName};${JSON.stringify(meta.properties).replace( - '\\"', - "'" - )}` + `storybook-nextjs-font-loader?${JSON.stringify({ + source: source.value, + props: meta.properties, + fontFamily: meta.functionName, + filename, + })}!${source.value}` ) ); }), diff --git a/code/frameworks/nextjs/src/font/babel/index.test.ts b/code/frameworks/nextjs/src/font/babel/index.test.ts new file mode 100644 index 000000000000..8fd1fa37b611 --- /dev/null +++ b/code/frameworks/nextjs/src/font/babel/index.test.ts @@ -0,0 +1,30 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { transform } from '@babel/core'; +import TransformFontImports from '.'; + +const example = ` +import { Inter, Roboto } from '@next/font/google' +import localFont from '@next/font/local' + +const myFont = localFont({ src: './my-font.woff2' }) + +const roboto = Roboto({ + weight: '400', +}) + +const inter = Inter({ + subsets: ['latin'], +}); + +const randomObj = {} +`; + +it('should transform AST properly', () => { + const { code } = transform(example, { plugins: [TransformFontImports] })!; + expect(code).toMatchInlineSnapshot(` + "import inter from \\"storybook-nextjs-font-loader?{\\\\\\"source\\\\\\":\\\\\\"@next/font/google\\\\\\",\\\\\\"props\\\\\\":{\\\\\\"subsets\\\\\\":[\\\\\\"latin\\\\\\"]},\\\\\\"fontFamily\\\\\\":\\\\\\"Inter\\\\\\"}!@next/font/google\\"; + import roboto from \\"storybook-nextjs-font-loader?{\\\\\\"source\\\\\\":\\\\\\"@next/font/google\\\\\\",\\\\\\"props\\\\\\":{\\\\\\"weight\\\\\\":\\\\\\"400\\\\\\"},\\\\\\"fontFamily\\\\\\":\\\\\\"Roboto\\\\\\"}!@next/font/google\\"; + import myFont from \\"storybook-nextjs-font-loader?{\\\\\\"source\\\\\\":\\\\\\"@next/font/local\\\\\\",\\\\\\"props\\\\\\":{\\\\\\"src\\\\\\":\\\\\\"./my-font.woff2\\\\\\"},\\\\\\"fontFamily\\\\\\":\\\\\\"localFont\\\\\\"}!@next/font/local\\"; + const randomObj = {};" + `); +}); diff --git a/code/frameworks/nextjs/src/font/babel.ts b/code/frameworks/nextjs/src/font/babel/index.ts similarity index 76% rename from code/frameworks/nextjs/src/font/babel.ts rename to code/frameworks/nextjs/src/font/babel/index.ts index 4a8cae89d0be..abab8ea6e13f 100644 --- a/code/frameworks/nextjs/src/font/babel.ts +++ b/code/frameworks/nextjs/src/font/babel/index.ts @@ -5,13 +5,14 @@ import { isDefined, removeTransformedVariableDeclarations, replaceImportWithParamterImport, -} from './babel.helpers'; +} from './helpers'; type Babel = typeof BabelCoreNamespace; /** * Transforms "@next/font" imports and usages to a webpack loader friendly format with parameters * @example + * // src/example.js * // Turns this code: * import { Inter, Roboto } from '@next/font/google' * import localFont from '@next/font/local' @@ -26,9 +27,9 @@ type Babel = typeof BabelCoreNamespace; * }); * * // Into this code: - * import inter from "@next/font/google?Inter;{\"subsets\":[\"latin\"]}"; - * import roboto from "@next/font/google?Roboto;{\"weight\":\"400\"}"; - * import myFont from "@next/font/local?localFont;{\"src\":\"./my-font.woff2\"}"; + * import inter from 'storybook-nextjs-font-loader?{filename: "src/example.js", source: "@next/font/google", fontFamily: "Inter", props: {"subsets":["latin"]}}!@next/font/google' + * import roboto from 'storybook-nextjs-font-loader?{filename: "src/example.js", source: "@next/font/google", fontFamily: "Roboto", props: {"weight": "400"}}!@next/font/google' + * import myFont from 'storybook-nextjs-font-loader?{filename: "src/example.js", source: "@next/font/local", props: {"src": "./my-font.woff2"}}!@next/font/local' * * This Plugin tries to adopt the functionality which is provided by the nextjs swc plugin * https://github.com/vercel/next.js/pull/40221 @@ -37,9 +38,10 @@ export default function TransformFontImports({ types }: Babel): BabelCoreNamespa return { name: 'storybook-nextjs-font-imports', visitor: { - ImportDeclaration(path) { + ImportDeclaration(path, state) { const { node } = path; const { source } = node; + const { filename = '' } = state; if (source.value === '@next/font/local') { const { specifiers } = node; @@ -56,7 +58,7 @@ export default function TransformFontImports({ types }: Babel): BabelCoreNamespa const variableMetas = getVariableMetasBySpecifier(program, types, specifier); removeTransformedVariableDeclarations(path, types, variableMetas); - replaceImportWithParamterImport(path, types, source, variableMetas); + replaceImportWithParamterImport(path, types, source, variableMetas, filename); } if (source.value === '@next/font/google') { @@ -75,7 +77,7 @@ export default function TransformFontImports({ types }: Babel): BabelCoreNamespa .filter(isDefined); removeTransformedVariableDeclarations(path, types, variableMetas); - replaceImportWithParamterImport(path, types, source, variableMetas); + replaceImportWithParamterImport(path, types, source, variableMetas, filename); } }, }, diff --git a/code/frameworks/nextjs/src/font/webpack/configureNextFont.ts b/code/frameworks/nextjs/src/font/webpack/configureNextFont.ts new file mode 100644 index 000000000000..698bdc51bdc2 --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/configureNextFont.ts @@ -0,0 +1,15 @@ +import type { Configuration } from 'webpack'; +import VirtualLocalFontModulePlugin from './plugin/virtual-local-font-module'; + +export function configureNextFont(baseConfig: Configuration) { + baseConfig.plugins = [...(baseConfig.plugins || []), new VirtualLocalFontModulePlugin()]; + baseConfig.resolveLoader = { + ...baseConfig.resolveLoader, + alias: { + ...baseConfig.resolveLoader?.alias, + 'storybook-nextjs-font-loader': require.resolve( + './font/webpack/loader/storybook-nextjs-font-loader' + ), + }, + }; +} diff --git a/code/frameworks/nextjs/src/font/webpack/loader/google/get-font-face-declarations.ts b/code/frameworks/nextjs/src/font/webpack/loader/google/get-font-face-declarations.ts new file mode 100644 index 000000000000..8132b7de43cf --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/loader/google/get-font-face-declarations.ts @@ -0,0 +1,47 @@ +import { + fetchCSSFromGoogleFonts, + getFontAxes, + getUrl, + validateData, +} from '@next/font/dist/google/utils'; +import loaderUtils from 'next/dist/compiled/loader-utils3'; + +import type { LoaderOptions } from '../types'; + +const cssCache = new Map>(); + +export async function getFontFaceDeclarations(options: LoaderOptions) { + const { fontFamily, weights, styles, selectedVariableAxes, display, variable } = validateData( + options.fontFamily, + [options.props] + ); + + const fontAxes = getFontAxes(fontFamily, weights, styles, selectedVariableAxes); + const url = getUrl(fontFamily, fontAxes, display); + + try { + const hasCachedCSS = cssCache.has(url); + const fontFaceCSS = hasCachedCSS + ? cssCache.get(url) + : await fetchCSSFromGoogleFonts(url, fontFamily).catch(() => null); + if (!hasCachedCSS) { + cssCache.set(url, fontFaceCSS); + } else { + cssCache.delete(url); + } + if (fontFaceCSS === null) { + throw Error(`Failed to fetch \`${fontFamily}\` from Google Fonts.`); + } + + return { + id: loaderUtils.getHashDigest(url, 'md5', 'hex', 6), + fontFamily, + fontFaceCSS, + weights, + styles, + variable, + }; + } catch (error) { + throw new Error("Google Fonts couldn't be loaded."); + } +} diff --git a/code/frameworks/nextjs/src/font/webpack/loader/local/get-font-face-declarations.ts b/code/frameworks/nextjs/src/font/webpack/loader/local/get-font-face-declarations.ts new file mode 100644 index 000000000000..6abae33ce342 --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/loader/local/get-font-face-declarations.ts @@ -0,0 +1,55 @@ +import loaderUtils from 'next/dist/compiled/loader-utils3'; +import { validateData } from '@next/font/dist/local/utils'; +import path from 'path'; + +import type { LoaderOptions } from '../types'; + +type LocalFontSrc = string | Array<{ path: string; weight?: string; style?: string }>; + +export async function getFontFaceDeclarations(options: LoaderOptions, rootContext: string) { + const localFontSrc = options.props.src as LocalFontSrc; + + // Parent folder relative to the root context + const parentFolder = options.filename.split('/').slice(0, -1).join('/').replace(rootContext, ''); + + const { weight, style, variable } = validateData('', options.props); + + const id = `font-${loaderUtils.getHashDigest( + Buffer.from(JSON.stringify(localFontSrc)), + 'md5', + 'hex', + 6 + )}`; + + const getFontFaceCSS = () => { + if (typeof localFontSrc === 'string') { + const localFontPath = path.join(parentFolder, localFontSrc); + + return `@font-face { + font-family: ${id}; + src: url(${localFontPath}); + }`; + } + return localFontSrc + .map((font) => { + const localFontPath = path.join(parentFolder, font.path); + + return `@font-face { + font-family: ${id}; + src: url(${localFontPath}); + ${font.weight ? `font-weight: ${font.weight};` : ''} + ${font.style ? `font-style: ${font.style};` : ''} + }`; + }) + .join(''); + }; + + return { + id, + fontFamily: id, + fontFaceCSS: getFontFaceCSS(), + weights: weight ? [weight] : [], + styles: style ? [style] : [], + variable, + }; +} diff --git a/code/frameworks/nextjs/src/font/webpack/loader/storybook-nextjs-font-loader.ts b/code/frameworks/nextjs/src/font/webpack/loader/storybook-nextjs-font-loader.ts new file mode 100644 index 000000000000..b25f2857a75a --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/loader/storybook-nextjs-font-loader.ts @@ -0,0 +1,51 @@ +import { getFontFaceDeclarations as getGoogleFontFaceDeclarations } from './google/get-font-face-declarations'; +import { getFontFaceDeclarations as getLocalFontFaceDeclarations } from './local/get-font-face-declarations'; +import type { LoaderOptions } from './types'; +import { getCSSMeta } from './utils/get-css-meta'; +import { setFontDeclarationsInHead } from './utils/set-font-declarations-in-head'; + +type FontFaceDeclaration = { + id: string; + fontFamily: string; + fontFaceCSS: any; + weights: string[]; + styles: string[]; + variable?: string; +}; + +export default async function storybookNextjsFontLoader(this: any) { + const options = this.getOptions() as LoaderOptions; + + // get execution context + const rootCtx = this.rootContext; + + let fontFaceDeclaration: FontFaceDeclaration | undefined; + + if (options.source === '@next/font/google') { + fontFaceDeclaration = await getGoogleFontFaceDeclarations(options); + } + + if (options.source === '@next/font/local') { + fontFaceDeclaration = await getLocalFontFaceDeclarations(options, rootCtx); + } + + if (typeof fontFaceDeclaration !== 'undefined') { + const cssMeta = getCSSMeta(fontFaceDeclaration); + + return ` + ${setFontDeclarationsInHead({ + fontFaceCSS: cssMeta.fontFaceCSS, + id: fontFaceDeclaration.id, + classNamesCSS: cssMeta.classNamesCSS, + })} + + module.exports = { + className: "${cssMeta.className}", + style: ${JSON.stringify(cssMeta.style)} + ${cssMeta.variableClassName ? `, variable: "${cssMeta.variableClassName}"` : ''} + } + `; + } + + return `module.exports = {}`; +} diff --git a/code/frameworks/nextjs/src/font/webpack/loader/types.ts b/code/frameworks/nextjs/src/font/webpack/loader/types.ts new file mode 100644 index 000000000000..237e0cfb942d --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/loader/types.ts @@ -0,0 +1,18 @@ +export type LoaderOptions = { + /** + * Initial import name. Can be `@next/font/google` or `@next/font/local` + */ + source: string; + /** + * Props passed to the `@next/font` function call + */ + props: Record; + /** + * Font Family name + */ + fontFamily: string; + /** + * Filename of the issuer file, which imports `@next/font/google` or `@next/font/local + */ + filename: string; +}; diff --git a/code/frameworks/nextjs/src/font/webpack/loader/utils/get-css-meta.ts b/code/frameworks/nextjs/src/font/webpack/loader/utils/get-css-meta.ts new file mode 100644 index 000000000000..aa816e05faf4 --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/loader/utils/get-css-meta.ts @@ -0,0 +1,66 @@ +type Options = { + fontFamily: string; + styles: string[]; + weights: string[]; + fontFaceCSS: string; + variable?: string; +}; + +export function getCSSMeta(options: Options) { + const className = getClassName(options); + const style = getStylesObj(options); + const variableClassName = `__variable_${className}`; + + const classNamesCSS = ` + .${className} { + font-family: ${options.fontFamily}; + ${isNextCSSPropertyValid(options.styles) ? `font-style: ${options.styles[0]};` : ''} + ${isNextCSSPropertyValid(options.weights) ? `font-weight: ${options.weights[0]};` : ''} + } + + ${ + options.variable + ? `.${variableClassName} { ${options.variable}: '${options.fontFamily}'; }` + : '' + } + `; + + const fontFaceCSS = `${changeFontDisplayToSwap(options.fontFaceCSS)}`; + + return { + className, + fontFaceCSS, + classNamesCSS, + style, + ...(options.variable ? { variableClassName } : {}), + }; +} + +function getClassName({ styles, weights, fontFamily }: Options) { + const font = fontFamily.replace(' ', '-').toLowerCase(); + const style = isNextCSSPropertyValid(styles) ? styles[0] : null; + const weight = isNextCSSPropertyValid(weights) ? weights[0] : null; + + return `${font}${style ? `-${style}` : ''}${weight ? `-${weight}` : ''}`; +} + +function getStylesObj({ styles, weights, fontFamily }: Options) { + return { + fontFamily, + ...(isNextCSSPropertyValid(styles) ? { fontStyle: styles[0] } : {}), + ...(isNextCSSPropertyValid(weights) ? { fontWeight: weights[0] } : {}), + }; +} + +function isNextCSSPropertyValid(prop: string[]) { + return prop.length === 1 && prop[0] !== 'variable'; +} + +/** + * This step is necessary, because otherwise the font-display: optional; property + * blocks Storybook from rendering the font, because the @font-face declaration + * is not loaded in time. + */ +function changeFontDisplayToSwap(css: string) { + return css.replaceAll('font-display: optional;', 'font-display: block;'); +} diff --git a/code/frameworks/nextjs/src/font/webpack/loader/utils/set-font-declarations-in-head.ts b/code/frameworks/nextjs/src/font/webpack/loader/utils/set-font-declarations-in-head.ts new file mode 100644 index 000000000000..cccaeaf9dbf2 --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/loader/utils/set-font-declarations-in-head.ts @@ -0,0 +1,24 @@ +type Props = { + id: string; + fontFaceCSS: string; + classNamesCSS: string; +}; + +export function setFontDeclarationsInHead({ id, fontFaceCSS, classNamesCSS }: Props) { + return ` + if (!document.getElementById('id-${id}')) { + const fontDeclarations = \`${fontFaceCSS}\`; + const style = document.createElement('style'); + style.setAttribute('id', 'font-face-${id}'); + style.innerHTML = fontDeclarations; + document.head.appendChild(style); + + const classNamesCSS = \`${classNamesCSS}\`; + const classNamesStyle = document.createElement('style'); + classNamesStyle.setAttribute('id', 'classnames-${id}'); + classNamesStyle.innerHTML = classNamesCSS; + document.head.appendChild(classNamesStyle); + + } + `; +} diff --git a/code/frameworks/nextjs/src/font/webpack/plugin/virtual-local-font-module.ts b/code/frameworks/nextjs/src/font/webpack/plugin/virtual-local-font-module.ts new file mode 100644 index 000000000000..f049f5016f54 --- /dev/null +++ b/code/frameworks/nextjs/src/font/webpack/plugin/virtual-local-font-module.ts @@ -0,0 +1,18 @@ +// Write a webpack plugin that will create a virtual module for each custom font, +// which will be used by the storybook-nextjs-font-loader to generate the CSS + +import type { Compiler } from 'webpack'; + +export default class VirtualLocalFontModulePlugin { + apply(compiler: Compiler) { + // Tap into each import which starts with "storybook-nextjs-font-loader" + compiler.hooks.normalModuleFactory.tap('VirtualLocalFontModulePlugin', (nmf) => { + nmf.hooks.beforeResolve.tap('VirtualLocalFontModulePlugin', (data) => { + if (data.request.startsWith('storybook-nextjs-font-loader')) { + const { issuer } = data.contextInfo; + const fontLoaderParameters = JSON.parse(data.request.split('?')[1].split('!')[0]); + } + }); + }); + } +} diff --git a/code/frameworks/nextjs/src/preset.ts b/code/frameworks/nextjs/src/preset.ts index 8441868dc2e0..82e5b58d2bba 100644 --- a/code/frameworks/nextjs/src/preset.ts +++ b/code/frameworks/nextjs/src/preset.ts @@ -14,6 +14,7 @@ import { configureRuntimeNextjsVersionResolution } from './utils'; import type { FrameworkOptions, StorybookConfig } from './types'; import { configureNextImport } from './nextImport/webpack'; import TransformFontImports from './font/babel'; +import { configureNextFont } from './font/webpack/configureNextFont'; export const addons: PresetProperty<'addons', StorybookConfig> = [ dirname(require.resolve(join('@storybook/preset-react-webpack', 'package.json'))), @@ -127,6 +128,7 @@ export const webpackFinal: StorybookConfig['webpackFinal'] = async (baseConfig, configDir: options.configDir, }); + configureNextFont(baseConfig); configureNextImport(baseConfig); configureRuntimeNextjsVersionResolution(baseConfig); configureImports(baseConfig); diff --git a/code/frameworks/nextjs/template/stories_default-js/Font.stories.jsx b/code/frameworks/nextjs/template/stories_default-js/Font.stories.jsx index f40fe0cf26b0..117d5cb35bd4 100644 --- a/code/frameworks/nextjs/template/stories_default-js/Font.stories.jsx +++ b/code/frameworks/nextjs/template/stories_default-js/Font.stories.jsx @@ -1,12 +1,81 @@ -import { Inter } from '@next/font/google'; +/* eslint-disable react/prop-types */ +import { Rubik_Puddles } from '@next/font/google'; +import localFont from '@next/font/local'; + import React from 'react'; -const inter = Inter({ subsets: ['latin'] }); +const rubik = Rubik_Puddles({ subsets: ['latin'], variable: '--font-latin-rubik', weight: '400' }); +const localRubikStorm = localFont({ + src: '/fonts/RubikStorm-Regular.ttf', + variable: '--font-rubik-storm', +}); -const Component = () =>

Google Inter Latin

; +function Component({ variant }) { + switch (variant) { + case 'className': + return ( +
+

Google Rubik Puddles

+

Google Local Rubik Storm

+
+ ); + case 'style': + return ( +
+

Google Rubik Puddles

+

Google Local Rubik Storm

+
+ ); + case 'variable': + return ( +
+
+

+ Google Rubik Puddles +

+
+
+

+ Google Local Rubik Storm +

+
+
+ ); + default: + return null; + } +} export default { component: Component, }; -export const Default = {}; +export const WithClassName = { + args: { + variant: 'className', + }, +}; + +export const WithStyle = { + args: { + variant: 'style', + }, +}; + +export const WithVariable = { + args: { + variant: 'variable', + }, +}; diff --git a/code/frameworks/nextjs/template/stories_default-js/fonts/OFL.txt b/code/frameworks/nextjs/template/stories_default-js/fonts/OFL.txt new file mode 100644 index 000000000000..36d2f6f3febb --- /dev/null +++ b/code/frameworks/nextjs/template/stories_default-js/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Rubik Filtered Project Authors (https://https://github.com/NaN-xyz/Rubik-Filtered) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/code/frameworks/nextjs/template/stories_default-js/fonts/RubikStorm-Regular.ttf b/code/frameworks/nextjs/template/stories_default-js/fonts/RubikStorm-Regular.ttf new file mode 100644 index 000000000000..2304ee84a07b Binary files /dev/null and b/code/frameworks/nextjs/template/stories_default-js/fonts/RubikStorm-Regular.ttf differ diff --git a/code/yarn.lock b/code/yarn.lock index 332cf0bb2c16..f29a1c97da7d 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -4429,10 +4429,10 @@ __metadata: languageName: node linkType: hard -"@next/font@npm:^13.0.6": - version: 13.0.6 - resolution: "@next/font@npm:13.0.6" - checksum: 45d3722c2ae7724f74df29ba0ca59eb2766e6e68453b963f0c8b5bbb63646cf32bd1bac6ee847ac7dde3ac87b0dd3569a98e94a09778eae76c9f454df91cedad +"@next/font@npm:^13.0.7": + version: 13.0.7 + resolution: "@next/font@npm:13.0.7" + checksum: 16969448435900703df9ee9847ff26d00dd27dd26464786e291b13343cb22f11e394f0a7311ea4d3638dd14cac5ffb98a6f90aea0b75d56f5fc0b8e22c35740f languageName: node linkType: hard @@ -6774,7 +6774,7 @@ __metadata: dependencies: "@babel/core": ^7.20.5 "@babel/types": ^7.20.5 - "@next/font": ^13.0.6 + "@next/font": ^13.0.7 "@storybook/addon-actions": 7.0.0-beta.10 "@storybook/builder-webpack5": 7.0.0-beta.10 "@storybook/core-common": 7.0.0-beta.10